[PATCH] Implement SHFormatDateTimeA/SHFormatDateTimeW with tests

Nikolay Sivov nsivov at codeweavers.com
Sun Feb 28 16:10:24 CST 2010


---
 dlls/shlwapi/ordinal.c       |   75 +++++++++--
 dlls/shlwapi/tests/ordinal.c |  307 +++++++++++++++++++++++++++++++++++++++++-
 include/shlwapi.h            |   11 ++
 3 files changed, 381 insertions(+), 12 deletions(-)

diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 99de394..375ddaf 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -4661,7 +4661,7 @@ HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
  *  fileTime   [I] Pointer to FILETIME structure specifying the time
  *  flags      [I] Flags specifying the desired output
  *  buf        [O] Pointer to buffer for output
- *  bufSize    [I] Number of characters that can be contained in buffer
+ *  size       [I] Number of characters that can be contained in buffer
  *
  * RETURNS
  *  success: number of characters written to the buffer
@@ -4669,10 +4669,65 @@ HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
  *
  */
 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
-    LPWSTR buf, UINT bufSize)
+    LPWSTR buf, UINT size)
 {
-    FIXME("%p %p %s %d STUB\n", fileTime, flags, debugstr_w(buf), bufSize);
-    return 0;
+#define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
+    DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
+    SYSTEMTIME st;
+    FILETIME ft;
+    INT ret = 0;
+
+    TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
+
+    if (!buf || !size)
+        return 0;
+
+    if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
+        FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
+
+    FileTimeToLocalFileTime(fileTime, &ft);
+    FileTimeToSystemTime(&ft, &st);
+
+    /* first of all date */
+    if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
+    {
+        static const WCHAR sep1[] = {',',' ',0};
+        static const WCHAR sep2[] = {' ',0};
+
+        DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
+        ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
+        if (ret >= size) return ret;
+
+        /* add separator */
+        if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
+        {
+            if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
+            {
+                if (ret < size + 2)
+                {
+                   lstrcatW(&buf[ret-1], sep1);
+                   ret += 2;
+                }
+            }
+            else
+            {
+                lstrcatW(&buf[ret-1], sep2);
+                ret++;
+            }
+        }
+    }
+    /* time part */
+    if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
+    {
+        DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
+
+        if (ret) ret--;
+        ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
+    }
+
+    return ret;
+
+#undef SHFORMATDT_UNSUPPORTED_FLAGS
 }
 
 /***********************************************************************
@@ -4682,21 +4737,19 @@ INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
  *
  */
 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
-    LPCSTR buf, UINT bufSize)
+    LPSTR buf, UINT size)
 {
     WCHAR *bufW;
-    DWORD buflenW, convlen;
     INT retval;
 
-    if (!buf || !bufSize)
+    if (!buf || !size)
         return 0;
 
-    buflenW = bufSize;
-    bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
-    retval = SHFormatDateTimeW(fileTime, flags, bufW, buflenW);
+    bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
+    retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
 
     if (retval != 0)
-        convlen = WideCharToMultiByte(CP_ACP, 0, bufW, -1, (LPSTR) buf, bufSize, NULL, NULL);
+        WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
 
     HeapFree(GetProcessHeap(), 0, bufW);
     return retval;
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c
index b53d81c..dd046aa 100644
--- a/dlls/shlwapi/tests/ordinal.c
+++ b/dlls/shlwapi/tests/ordinal.c
@@ -28,6 +28,7 @@
 #include "oaidl.h"
 #include "ocidl.h"
 #include "mlang.h"
+#include "shlwapi.h"
 
 /* Function ptrs for ordinal calls */
 static HMODULE hShlwapi;
@@ -43,7 +44,9 @@ static HRESULT(WINAPI *pIConnectionPoint_SimpleInvoke)(IConnectionPoint*,DISPID,
 static HRESULT(WINAPI *pIConnectionPoint_InvokeWithCancel)(IConnectionPoint*,DISPID,DISPPARAMS*,DWORD,DWORD);
 static HRESULT(WINAPI *pConnectToConnectionPoint)(IUnknown*,REFIID,BOOL,IUnknown*, LPDWORD,IConnectionPoint **);
 static HRESULT(WINAPI *pSHPropertyBag_ReadLONG)(IPropertyBag *,LPCWSTR,LPLONG);
-static LONG   (WINAPI *pSHSetWindowBits)(HWND hwnd, INT offset, UINT wMask, UINT wFlags);
+static LONG   (WINAPI *pSHSetWindowBits)(HWND, INT, UINT, UINT);
+static INT    (WINAPI *pSHFormatDateTimeA)(const FILETIME UNALIGNED*, DWORD*, LPSTR, UINT);
+static INT    (WINAPI *pSHFormatDateTimeW)(const FILETIME UNALIGNED*, DWORD*, LPWSTR, UINT);
 
 static HMODULE hmlang;
 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
@@ -1474,6 +1477,304 @@ static void test_SHSetWindowBits(void)
     UnregisterClassA("Shlwapi test class", GetModuleHandleA(NULL));
 }
 
+static void test_SHFormatDateTimeA(void)
+{
+    FILETIME UNALIGNED filetime;
+    CHAR buff[100], buff2[100], buff3[100];
+    SYSTEMTIME st;
+    DWORD flags;
+    INT ret;
+
+    if(!pSHFormatDateTimeA)
+    {
+        win_skip("pSHFormatDateTimeA isn't available\n");
+        return;
+    }
+
+if (0)
+{
+    /* crashes on native */
+    ret = pSHFormatDateTimeA(NULL, NULL, NULL, 0);
+}
+
+    GetLocalTime(&st);
+    SystemTimeToFileTime(&st, &filetime);
+    /* SHFormatDateTime expects input as utc */
+    LocalFileTimeToFileTime(&filetime, &filetime);
+
+    /* no way to get required buffer length here */
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeA(&filetime, NULL, NULL, 0);
+    ok(ret == 0, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    buff[0] = 'a'; buff[1] = 0;
+    ret = pSHFormatDateTimeA(&filetime, NULL, buff, 0);
+    ok(ret == 0, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+    ok(buff[0] == 'a', "expected same string, got %s\n", buff);
+
+    /* all combinations documented as invalid succeeded */
+    flags = FDTF_SHORTTIME | FDTF_LONGTIME;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    flags = FDTF_SHORTDATE | FDTF_LONGDATE;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    /* now check returned strings */
+    flags = FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_LONGTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    /* both time flags */
+    flags = FDTF_LONGTIME | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_SHORTDATE;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_LONGDATE;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    /* both date flags */
+    flags = FDTF_LONGDATE | FDTF_SHORTDATE;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    /* various combinations of date/time flags */
+    flags = FDTF_LONGDATE | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d, length %d\n", ret, lstrlenA(buff)+1);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    strcat(buff2, ", ");
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
+    ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
+    strcat(buff2, buff3);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_LONGDATE | FDTF_LONGTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    strcat(buff2, ", ");
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
+    ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
+    strcat(buff2, buff3);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    strcat(buff2, " ");
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3));
+    ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
+    strcat(buff2, buff3);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+
+    flags = FDTF_SHORTDATE | FDTF_LONGTIME;
+    ret = pSHFormatDateTimeA(&filetime, &flags, buff, sizeof(buff));
+    ok(ret == lstrlenA(buff)+1, "got %d\n", ret);
+    ret = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2));
+    ok(ret == lstrlenA(buff2)+1, "got %d\n", ret);
+    strcat(buff2, " ");
+    ret = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3));
+    ok(ret == lstrlenA(buff3)+1, "got %d\n", ret);
+    strcat(buff2, buff3);
+    ok(lstrcmpA(buff, buff2) == 0, "expected (%s), got (%s)\n", buff2, buff);
+}
+
+static void test_SHFormatDateTimeW(void)
+{
+    FILETIME UNALIGNED filetime;
+    WCHAR buff[100], buff2[100], buff3[100];
+    SYSTEMTIME st;
+    DWORD flags;
+    INT ret;
+    static const WCHAR spaceW[] = {' ',0};
+    static const WCHAR commaW[] = {',',' ',0};
+
+    if(!pSHFormatDateTimeW)
+    {
+        win_skip("pSHFormatDateTimeW isn't available\n");
+        return;
+    }
+
+if (0)
+{
+    /* crashes on native */
+    ret = pSHFormatDateTimeW(NULL, NULL, NULL, 0);
+}
+
+    GetLocalTime(&st);
+    SystemTimeToFileTime(&st, &filetime);
+    /* SHFormatDateTime expects input as utc */
+    LocalFileTimeToFileTime(&filetime, &filetime);
+
+    /* no way to get required buffer length here */
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeW(&filetime, NULL, NULL, 0);
+    ok(ret == 0, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    buff[0] = 'a'; buff[1] = 0;
+    ret = pSHFormatDateTimeW(&filetime, NULL, buff, 0);
+    ok(ret == 0, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+    ok(buff[0] == 'a', "expected same string\n");
+
+    /* all combinations documented as invalid succeeded */
+    flags = FDTF_SHORTTIME | FDTF_LONGTIME;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    flags = FDTF_SHORTDATE | FDTF_LONGDATE;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    flags = FDTF_SHORTDATE | FDTF_LTRDATE | FDTF_RTLDATE;
+    SetLastError(0xdeadbeef);
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ok(GetLastError() == 0xdeadbeef, "expected 0xdeadbeef, got %d\n", GetLastError());
+
+    /* now check returned strings */
+    flags = FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    flags = FDTF_LONGTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    /* both time flags */
+    flags = FDTF_LONGTIME | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal string\n");
+
+    flags = FDTF_SHORTDATE;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    flags = FDTF_LONGDATE;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    /* both date flags */
+    flags = FDTF_LONGDATE | FDTF_SHORTDATE;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    /* various combinations of date/time flags */
+    flags = FDTF_LONGDATE | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d, length %d\n", ret, lstrlenW(buff)+1);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    lstrcatW(buff2, commaW);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+    lstrcatW(buff2, buff3);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    flags = FDTF_LONGDATE | FDTF_LONGTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    lstrcatW(buff2, commaW);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+    lstrcatW(buff2, buff3);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    flags = FDTF_SHORTDATE | FDTF_SHORTTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    lstrcatW(buff2, spaceW);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+    lstrcatW(buff2, buff3);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+
+    flags = FDTF_SHORTDATE | FDTF_LONGTIME;
+    ret = pSHFormatDateTimeW(&filetime, &flags, buff, sizeof(buff)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff)+1, "got %d\n", ret);
+    ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, buff2, sizeof(buff2)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff2)+1, "got %d\n", ret);
+    lstrcatW(buff2, spaceW);
+    ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buff3, sizeof(buff3)/sizeof(WCHAR));
+    ok(ret == lstrlenW(buff3)+1, "got %d\n", ret);
+    lstrcatW(buff2, buff3);
+    ok(lstrcmpW(buff, buff2) == 0, "expected equal strings\n");
+}
+
 static void init_pointers(void)
 {
 #define MAKEFUNC(f, ord) (p##f = (void*)GetProcAddress(hShlwapi, (LPSTR)(ord)))
@@ -1488,6 +1789,8 @@ static void init_pointers(void)
     MAKEFUNC(SHPackDispParams, 282);
     MAKEFUNC(IConnectionPoint_InvokeWithCancel, 283);
     MAKEFUNC(IConnectionPoint_SimpleInvoke, 284);
+    MAKEFUNC(SHFormatDateTimeA, 353);
+    MAKEFUNC(SHFormatDateTimeW, 354);
     MAKEFUNC(SHPropertyBag_ReadLONG, 496);
 #undef MAKEFUNC
 }
@@ -1510,4 +1813,6 @@ START_TEST(ordinal)
     test_IConnectionPoint();
     test_SHPropertyBag_ReadLONG();
     test_SHSetWindowBits();
+    test_SHFormatDateTimeA();
+    test_SHFormatDateTimeW();
 }
diff --git a/include/shlwapi.h b/include/shlwapi.h
index fe33a17..b449cfa 100644
--- a/include/shlwapi.h
+++ b/include/shlwapi.h
@@ -1074,6 +1074,17 @@ BOOL WINAPI IsOS(DWORD);
 #define TPS_EXECUTEIO    0x00000001
 #define TPS_LONGEXECTIME 0x00000008
 
+/* SHFormatDateTimeA/SHFormatDateTimeW flags */
+#define FDTF_SHORTTIME          0x00000001
+#define FDTF_SHORTDATE          0x00000002
+#define FDTF_DEFAULT            (FDTF_SHORTDATE | FDTF_SHORTTIME)
+#define FDTF_LONGDATE           0x00000004
+#define FDTF_LONGTIME           0x00000008
+#define FDTF_RELATIVE           0x00000010
+#define FDTF_LTRDATE            0x00000100
+#define FDTF_RTLDATE            0x00000200
+#define FDTF_NOAUTOREADINGORDER 0x00000400
+
 #include <poppack.h> 
 
 #ifdef __cplusplus
-- 
1.5.6.5


--=-daTYCYb3/EgeNIHG2kRo--




More information about the wine-patches mailing list