~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/kernel32/tests/locale.c

Version: ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Unit tests for locale functions
  3  *
  4  * Copyright 2002 YASAR Mehmet
  5  * Copyright 2003 Dmitry Timoshkov
  6  * Copyright 2003 Jon Griffiths
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  *
 22  * NOTES
 23  *  We must pass LOCALE_NOUSEROVERRIDE (NUO) to formatting functions so that
 24  *  even when the user has overridden their default i8n settings (e.g. in
 25  *  the control panel i8n page), we will still get the expected results.
 26  */
 27 
 28 #include <assert.h>
 29 #include <stdlib.h>
 30 #include <stdarg.h>
 31 
 32 #include "wine/test.h"
 33 #include "windef.h"
 34 #include "winbase.h"
 35 #include "winerror.h"
 36 #include "winnls.h"
 37 
 38 static inline unsigned int strlenW( const WCHAR *str )
 39 {
 40     const WCHAR *s = str;
 41     while (*s) s++;
 42     return s - str;
 43 }
 44 
 45 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
 46 {
 47     if (n <= 0) return 0;
 48     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
 49     return *str1 - *str2;
 50 }
 51 
 52 static inline WCHAR *strchrW( const WCHAR *str, WCHAR ch )
 53 {
 54     do { if (*str == ch) return (WCHAR *)str; } while (*str++);
 55     return NULL;
 56 }
 57 
 58 static inline int isdigitW( WCHAR wc )
 59 {
 60     WORD type;
 61     GetStringTypeW( CT_CTYPE1, &wc, 1, &type );
 62     return type & C1_DIGIT;
 63 }
 64 
 65 /* Some functions are only in later versions of kernel32.dll */
 66 static HMODULE hKernel32;
 67 static WORD enumCount;
 68 
 69 typedef BOOL (WINAPI *EnumSystemLanguageGroupsAFn)(LANGUAGEGROUP_ENUMPROC,
 70                                                    DWORD, LONG_PTR);
 71 static EnumSystemLanguageGroupsAFn pEnumSystemLanguageGroupsA;
 72 typedef BOOL (WINAPI *EnumLanguageGroupLocalesAFn)(LANGGROUPLOCALE_ENUMPROC,
 73                                                    LGRPID, DWORD, LONG_PTR);
 74 static EnumLanguageGroupLocalesAFn pEnumLanguageGroupLocalesA;
 75 typedef BOOL (WINAPI *EnumUILanguagesAFn)(UILANGUAGE_ENUMPROC,
 76                                                    DWORD, LONG_PTR);
 77 static EnumUILanguagesAFn pEnumUILanguagesA;
 78 
 79 typedef INT (WINAPI *FoldStringAFn)(DWORD, LPCSTR, INT, LPSTR, INT);
 80 static FoldStringAFn pFoldStringA;
 81 typedef INT (WINAPI *FoldStringWFn)(DWORD, LPCWSTR, INT, LPWSTR, INT);
 82 static FoldStringWFn pFoldStringW;
 83 
 84 typedef BOOL (WINAPI *IsValidLanguageGroupFn)(LGRPID, DWORD);
 85 static IsValidLanguageGroupFn pIsValidLanguageGroup;
 86 
 87 static void InitFunctionPointers(void)
 88 {
 89   hKernel32 = GetModuleHandleA("kernel32");
 90   pEnumSystemLanguageGroupsA = (void*)GetProcAddress(hKernel32, "EnumSystemLanguageGroupsA");
 91   pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
 92   pFoldStringA = (void*)GetProcAddress(hKernel32, "FoldStringA");
 93   pFoldStringW = (void*)GetProcAddress(hKernel32, "FoldStringW");
 94   pIsValidLanguageGroup = (void*)GetProcAddress(hKernel32, "IsValidLanguageGroup");
 95   pEnumUILanguagesA = (void*)GetProcAddress(hKernel32, "EnumUILanguagesA");
 96 }
 97 
 98 #define eq(received, expected, label, type) \
 99         ok((received) == (expected), "%s: got " type " instead of " type "\n", \
100            (label), (received), (expected))
101 
102 #define BUFFER_SIZE    128
103 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
104 
105 #define EXPECT_LEN(len) ok(ret == (len), "Expected Len %d, got %d\n", (int)(len), ret)
106 #define EXPECT_INVALID  ok(GetLastError() == ERROR_INVALID_PARAMETER, \
107  "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError())
108 #define EXPECT_BUFFER  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, \
109  "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError())
110 #define EXPECT_FLAGS  ok(GetLastError() == ERROR_INVALID_FLAGS, \
111  "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
112 #define EXPECT_INVALIDFLAGS ok(GetLastError() == ERROR_INVALID_FLAGS || \
113   GetLastError() == ERROR_INVALID_PARAMETER, \
114  "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError())
115 #define EXPECT_LASTERROR_0 ok(GetLastError() == 0, \
116  "Expected GetLastError() == 0, got %d\n", GetLastError())
117 #define EXPECT_VALID ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError())
118 
119 #define STRINGSA(x,y) strcpy(input, x); strcpy(Expected, y); SetLastError(0); buffer[0] = '\0'
120 #define EXPECT_LENA EXPECT_LEN((int)strlen(Expected)+1)
121 #define EXPECT_EQA ok(strncmp(buffer, Expected, strlen(Expected)) == 0, \
122   "Expected '%s', got '%s'\n", Expected, buffer)
123 
124 #define STRINGSW(x,y) MultiByteToWideChar(CP_ACP,0,x,-1,input,COUNTOF(input)); \
125    MultiByteToWideChar(CP_ACP,0,y,-1,Expected,COUNTOF(Expected)); \
126    SetLastError(0); buffer[0] = '\0'
127 #define EXPECT_LENW EXPECT_LEN((int)strlenW(Expected)+1)
128 #define EXPECT_EQW  ok(strncmpW(buffer, Expected, strlenW(Expected)) == 0, "Bad conversion\n")
129 #define EXPECT_FALSE ok(FALSE == ret, "Expected return value FALSE, got TRUE\n")
130 #define EXPECT_TRUE  ok(FALSE != ret, "Expected return value TRUE, got FALSE\n")
131 
132 #define NUO LOCALE_NOUSEROVERRIDE
133 
134 static void test_GetLocaleInfoA(void)
135 {
136   int ret;
137   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
138   char buffer[BUFFER_SIZE];
139 
140   ok(lcid == 0x409, "wrong LCID calculated - %d\n", lcid);
141 
142   /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
143    * partially fill the buffer even if it is too short. See bug 637.
144    */
145   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
146   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 0);
147   ok(ret == 7 && !buffer[0], "Expected len=7, got %d\n", ret);
148 
149   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
150   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 3);
151   EXPECT_BUFFER; EXPECT_LEN(0);
152   ok(!strcmp(buffer, "Mon"), "Expected 'Mon', got '%s'\n", buffer);
153 
154   SetLastError(0); memset(buffer, 0, COUNTOF(buffer));
155   ret = GetLocaleInfoA(lcid, NUO|LOCALE_SDAYNAME1, buffer, 10);
156   EXPECT_VALID; EXPECT_LEN(7);
157   ok(!strcmp(buffer, "Monday"), "Expected 'Monday', got '%s'\n", buffer);
158 }
159 
160 static void test_GetTimeFormatA(void)
161 {
162   int ret;
163   SYSTEMTIME  curtime;
164   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
165   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
166 
167   memset(&curtime, 2, sizeof(SYSTEMTIME));
168   STRINGSA("tt HH':'mm'@'ss", ""); /* Invalid time */
169   SetLastError(0xdeadbeef);
170   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
171   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
172 
173   curtime.wHour = 8;
174   curtime.wMinute = 56;
175   curtime.wSecond = 13;
176   curtime.wMilliseconds = 22;
177   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Valid time */
178   SetLastError(0xdeadbeef);
179   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
180   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
181 
182   /* MSDN: LOCALE_NOUSEROVERRIDE can't be specified with a format string */
183   SetLastError(0xdeadbeef);
184   ret = GetTimeFormatA(lcid, NUO|TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
185   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
186 
187   STRINGSA("tt HH':'mm'@'ss", "A"); /* Insufficient buffer */
188   SetLastError(0xdeadbeef);
189   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, 2);
190   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
191 
192   STRINGSA("tt HH':'mm'@'ss", "AM 08:56@13"); /* Calculate length only */
193   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, NULL, 0);
194   EXPECT_VALID; EXPECT_LENA;
195 
196   STRINGSA("", "8 AM"); /* TIME_NOMINUTESORSECONDS, default format */
197   ret = GetTimeFormatA(lcid, NUO|TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
198   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
199 
200   STRINGSA("m1s2m3s4", ""); /* TIME_NOMINUTESORSECONDS/complex format */
201   ret = GetTimeFormatA(lcid, TIME_NOMINUTESORSECONDS, &curtime, input, buffer, COUNTOF(buffer));
202   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
203 
204   STRINGSA("", "8:56 AM"); /* TIME_NOSECONDS/Default format */
205   ret = GetTimeFormatA(lcid, NUO|TIME_NOSECONDS, &curtime, NULL, buffer, COUNTOF(buffer));
206   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
207 
208   STRINGSA("h:m:s tt", "8:56 AM"); /* TIME_NOSECONDS */
209   strcpy(Expected, "8:56 AM");
210   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
211   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
212 
213   STRINGSA("h.@:m.@:s.@:tt", "8.@:56AM"); /* Multiple delimiters */
214   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
215   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
216 
217   STRINGSA("s1s2s3", ""); /* Duplicate tokens */
218   ret = GetTimeFormatA(lcid, TIME_NOSECONDS, &curtime, input, buffer, COUNTOF(buffer));
219   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
220 
221   STRINGSA("t/tt", "A/AM"); /* AM time marker */
222   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
223   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
224 
225   curtime.wHour = 13;
226   STRINGSA("t/tt", "P/PM"); /* PM time marker */
227   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
228   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
229 
230   STRINGSA("h1t2tt3m", "156"); /* TIME_NOTIMEMARKER: removes text around time marker token */
231   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
232   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
233 
234   STRINGSA("h:m:s tt", "13:56:13 PM"); /* TIME_FORCE24HOURFORMAT */
235   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
236   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
237 
238   STRINGSA("h:m:s", "13:56:13"); /* TIME_FORCE24HOURFORMAT doesn't add time marker */
239   ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, input, buffer, COUNTOF(buffer));
240   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
241 
242   curtime.wHour = 14; /* change this to 14 or 2pm */
243   curtime.wMinute = 5;
244   curtime.wSecond = 3;
245   STRINGSA("h hh H HH m mm s ss t tt", "2 02 14 14 5 05 3 03 P PM"); /* 24 hrs, leading 0 */
246   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
247   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
248 
249   curtime.wHour = 0;
250   STRINGSA("h/H/hh/HH", "12/0/12/00"); /* "hh" and "HH" */
251   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
252   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
253 
254   STRINGSA("h:m:s tt", "12:5:3 AM"); /* non-zero flags should fail with format, doesn't */
255   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
256   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
257 
258   /* try to convert formatting strings with more than two letters
259    * "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS"
260    * NOTE: We expect any letter for which there is an upper case value
261    *       we should see a replacement.  For letters that DO NOT have
262    *       upper case values we should see NO REPLACEMENT.
263    */
264   curtime.wHour = 8;
265   curtime.wMinute = 56;
266   curtime.wSecond = 13;
267   curtime.wMilliseconds = 22;
268   STRINGSA("h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS",
269            "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
270   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
271   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
272 
273   STRINGSA("h", "text"); /* Don't write to buffer if len is 0 */
274   strcpy(buffer, "text");
275   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, 0);
276   EXPECT_VALID; EXPECT_LEN(2); EXPECT_EQA;
277 
278   STRINGSA("h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'",
279            "8 h 8 H 08 HH 56 m 13 s A t AM tt"); /* "'" preserves tokens */
280   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
281   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
282 
283   STRINGSA("'''", "'"); /* invalid quoted string */
284   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
285   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
286 
287   /* test that msdn suggested single quotation usage works as expected */
288   STRINGSA("''''", "'"); /* single quote mark */
289   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
290   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
291 
292   STRINGSA("''HHHHHH", "08"); /* Normal use */
293   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
294   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
295 
296   /* and test for normal use of the single quotation mark */
297   STRINGSA("'''HHHHHH'", "'HHHHHH"); /* Normal use */
298   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
299   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
300 
301   STRINGSA("'''HHHHHH", "'HHHHHH"); /* Odd use */
302   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
303   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
304 
305   STRINGSA("'123'tt", ""); /* TIME_NOTIMEMARKER drops literals too */
306   ret = GetTimeFormatA(lcid, TIME_NOTIMEMARKER, &curtime, input, buffer, COUNTOF(buffer));
307   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
308 
309   curtime.wHour = 25;
310   STRINGSA("'123'tt", ""); /* Invalid time */
311   SetLastError(0xdeadbeef);
312   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
313   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
314 
315   curtime.wHour = 12;
316   curtime.wMonth = 60; /* Invalid */
317   STRINGSA("h:m:s", "12:56:13"); /* Invalid date */
318   ret = GetTimeFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
319   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
320 }
321 
322 static void test_GetDateFormatA(void)
323 {
324   int ret;
325   SYSTEMTIME  curtime;
326   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
327   char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
328 
329   memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
330   STRINGSA("ddd',' MMM dd yy","");
331   SetLastError(0xdeadbeef);
332   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
333   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
334 
335   curtime.wYear = 2002;
336   curtime.wMonth = 5;
337   curtime.wDay = 4;
338   curtime.wDayOfWeek = 3;
339   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Simple case */
340   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
341   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
342 
343   /* Same as above but with LOCALE_NOUSEROVERRIDE */
344   STRINGSA("ddd',' MMM dd yy",""); /* Simple case */
345   SetLastError(0xdeadbeef);
346   ret = GetDateFormatA(lcid, NUO, &curtime, input, buffer, COUNTOF(buffer));
347   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
348 
349   STRINGSA("ddd',' MMM dd yy","Sat, May 04 02"); /* Format containing "'" */
350   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
351   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
352 
353   curtime.wHour = 36; /* Invalid */
354   STRINGSA("ddd',' MMM dd ''''yy","Sat, May 04 '02"); /* Invalid time */
355   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
356   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
357 
358   STRINGSA("ddd',' MMM dd ''''yy",""); /* Get size only */
359   ret = GetDateFormatA(lcid, 0, &curtime, input, NULL, 0);
360   EXPECT_VALID; EXPECT_LEN(16); EXPECT_EQA;
361 
362   STRINGSA("ddd',' MMM dd ''''yy",""); /* Buffer too small */
363   SetLastError(0xdeadbeef);
364   ret = GetDateFormatA(lcid, 0, &curtime, input, buffer, 2);
365   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
366 
367   STRINGSA("ddd',' MMM dd ''''yy","5/4/2002"); /* Default to DATE_SHORTDATE */
368   ret = GetDateFormat(lcid, NUO, &curtime, NULL, buffer, COUNTOF(buffer));
369   EXPECT_VALID; EXPECT_LENA;
370   if (strncmp(buffer, Expected, strlen(Expected)) && strncmp(buffer, "5/4/02", strlen(Expected)) != 0)
371           ok (0, "Expected '%s' or '5/4/02', got '%s'\n", Expected, buffer);
372 
373   STRINGSA("ddd',' MMM dd ''''yy", "Saturday, May 04, 2002"); /* DATE_LONGDATE */
374   ret = GetDateFormat(lcid, NUO|DATE_LONGDATE, &curtime, NULL, buffer, COUNTOF(buffer));
375   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
376 
377   /* test for expected DATE_YEARMONTH behavior with null format */
378   /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
379   STRINGSA("ddd',' MMM dd ''''yy", ""); /* DATE_YEARMONTH */
380   SetLastError(0xdeadbeef);
381   ret = GetDateFormat(lcid, NUO|DATE_YEARMONTH, &curtime, input, buffer, COUNTOF(buffer));
382   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
383 
384   /* Test that using invalid DATE_* flags results in the correct error */
385   /* and return values */
386   STRINGSA("m/d/y", ""); /* Invalid flags */
387   SetLastError(0xdeadbeef);
388   ret = GetDateFormat(lcid, DATE_YEARMONTH|DATE_SHORTDATE|DATE_LONGDATE,
389                       &curtime, input, buffer, COUNTOF(buffer));
390   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQA;
391 }
392 
393 static void test_GetDateFormatW(void)
394 {
395   int ret;
396   SYSTEMTIME  curtime;
397   WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
398   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
399 
400   STRINGSW("",""); /* If flags is not zero then format must be NULL */
401   ret = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, DATE_LONGDATE, NULL,
402                        input, buffer, COUNTOF(buffer));
403   if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
404       return;
405   EXPECT_FLAGS; EXPECT_LEN(0); EXPECT_EQW;
406 
407   STRINGSW("",""); /* NULL buffer, len > 0 */
408   SetLastError(0xdeadbeef);
409   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, COUNTOF(buffer));
410   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQW;
411 
412   STRINGSW("",""); /* NULL buffer, len == 0 */
413   ret = GetDateFormatW (lcid, 0, NULL, input, NULL, 0);
414   EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
415 
416   curtime.wYear = 2002;
417   curtime.wMonth = 10;
418   curtime.wDay = 23;
419   curtime.wDayOfWeek = 45612; /* Should be 3 - Wednesday */
420   curtime.wHour = 65432; /* Invalid */
421   curtime.wMinute = 34512; /* Invalid */
422   curtime.wSecond = 65535; /* Invalid */
423   curtime.wMilliseconds = 12345;
424   STRINGSW("dddd d MMMM yyyy","Wednesday 23 October 2002"); /* Incorrect DOW and time */
425   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
426   EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
427 
428   /* Limit tests */
429 
430   curtime.wYear = 1601;
431   curtime.wMonth = 1;
432   curtime.wDay = 1;
433   curtime.wDayOfWeek = 0; /* Irrelevant */
434   curtime.wHour = 0;
435   curtime.wMinute = 0;
436   curtime.wSecond = 0;
437   curtime.wMilliseconds = 0;
438   STRINGSW("dddd d MMMM yyyy","Monday 1 January 1601");
439   SetLastError(0xdeadbeef);
440   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
441   EXPECT_VALID; EXPECT_LENW; EXPECT_EQW;
442 
443   curtime.wYear = 1600;
444   curtime.wMonth = 12;
445   curtime.wDay = 31;
446   curtime.wDayOfWeek = 0; /* Irrelevant */
447   curtime.wHour = 23;
448   curtime.wMinute = 59;
449   curtime.wSecond = 59;
450   curtime.wMilliseconds = 999;
451   STRINGSW("dddd d MMMM yyyy","Friday 31 December 1600");
452   SetLastError(0xdeadbeef);
453   ret = GetDateFormatW (lcid, 0, &curtime, input, buffer, COUNTOF(buffer));
454   EXPECT_INVALID;
455 }
456 
457 
458 #define CY_POS_LEFT  0
459 #define CY_POS_RIGHT 1
460 #define CY_POS_LEFT_SPACE  2
461 #define CY_POS_RIGHT_SPACE 3
462 
463 static void test_GetCurrencyFormatA(void)
464 {
465   static char szDot[] = { '.', '\0' };
466   static char szComma[] = { ',', '\0' };
467   static char szDollar[] = { '$', '\0' };
468   int ret;
469   LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
470   char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE], input[BUFFER_SIZE];
471   CURRENCYFMTA format;
472 
473   memset(&format, 0, sizeof(format));
474 
475   STRINGSA("23",""); /* NULL output, length > 0 --> Error */
476   SetLastError(0xdeadbeef);
477   ret = GetCurrencyFormatA(lcid, 0, input, NULL, NULL, COUNTOF(buffer));
478   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
479 
480   STRINGSA("23,53",""); /* Invalid character --> Error */
481   SetLastError(0xdeadbeef);
482   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
483   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
484 
485   STRINGSA("--",""); /* Double '-' --> Error */
486   SetLastError(0xdeadbeef);
487   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
488   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
489 
490   STRINGSA("0-",""); /* Trailing '-' --> Error */
491   SetLastError(0xdeadbeef);
492   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
493   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
494 
495   STRINGSA("0..",""); /* Double '.' --> Error */
496   SetLastError(0xdeadbeef);
497   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
498   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
499 
500   STRINGSA(" 0.1",""); /* Leading space --> Error */
501   SetLastError(0xdeadbeef);
502   ret = GetCurrencyFormatA(lcid, 0, input, NULL, buffer, COUNTOF(buffer));
503   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
504 
505   STRINGSA("1234","$"); /* Length too small --> Write up to length chars */
506   SetLastError(0xdeadbeef);
507   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, 2);
508   EXPECT_BUFFER; EXPECT_LEN(0); EXPECT_EQA;
509 
510   STRINGSA("2353",""); /* Format and flags given --> Error */
511   SetLastError(0xdeadbeef);
512   ret = GetCurrencyFormatA(lcid, NUO, input, &format, buffer, COUNTOF(buffer));
513   EXPECT_INVALIDFLAGS; EXPECT_LEN(0); EXPECT_EQA;
514 
515   STRINGSA("2353",""); /* Invalid format --> Error */
516   SetLastError(0xdeadbeef);
517   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
518   EXPECT_INVALID; EXPECT_LEN(0); EXPECT_EQA;
519 
520   STRINGSA("2353","$2,353.00"); /* Valid number */
521   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
522   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
523 
524   STRINGSA("-2353","($2,353.00)"); /* Valid negative number */
525   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
526   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
527 
528   STRINGSA("2353.1","$2,353.10"); /* Valid real number */
529   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
530   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
531 
532   STRINGSA("2353.111","$2,353.11"); /* Too many DP --> Truncated */
533   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
534   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
535 
536   STRINGSA("2353.119","$2,353.12");  /* Too many DP --> Rounded */
537   ret = GetCurrencyFormatA(lcid, NUO, input, NULL, buffer, COUNTOF(buffer));
538   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
539 
540   format.NumDigits = 0; /* No decimal separator */
541   format.LeadingZero = 0;
542   format.Grouping = 0;  /* No grouping char */
543   format.NegativeOrder = 0;
544   format.PositiveOrder = CY_POS_LEFT;
545   format.lpDecimalSep = szDot;
546   format.lpThousandSep = szComma;
547   format.lpCurrencySymbol = szDollar;
548 
549   STRINGSA("2353","$2353"); /* No decimal or grouping chars expected */
550   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
551   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
552 
553   format.NumDigits = 1; /* 1 DP --> Expect decimal separator */
554   STRINGSA("2353","$2353.0");
555   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
556   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
557 
558   format.Grouping = 2; /* Group by 100's */
559   STRINGSA("2353","$23,53.0");
560   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
561   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
562 
563   format.LeadingZero = 1; /* Always provide leading zero */
564   STRINGSA(".5","$0.5");
565   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
566   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
567 
568   format.PositiveOrder = CY_POS_RIGHT;
569   STRINGSA("1","1.0$");
570   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
571   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
572 
573   format.PositiveOrder = CY_POS_LEFT_SPACE;
574   STRINGSA("1","$ 1.0");
575   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
576   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
577 
578   format.PositiveOrder = CY_POS_RIGHT_SPACE;
579   STRINGSA("1","1.0 $");
580   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
581   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
582 
583   format.NegativeOrder = 0;
584   STRINGSA("-1","($1.0)");
585   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
586   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
587 
588   format.NegativeOrder = 1;
589   STRINGSA("-1","-$1.0");
590   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
591   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
592 
593   format.NegativeOrder = 2;
594   STRINGSA("-1","$-1.0");
595   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
596   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
597 
598   format.NegativeOrder = 3;
599   STRINGSA("-1","$1.0-");
600   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
601   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
602 
603   format.NegativeOrder = 4;
604   STRINGSA("-1","(1.0$)");
605   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
606   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
607 
608   format.NegativeOrder = 5;
609   STRINGSA("-1","-1.0$");
610   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
611   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
612 
613   format.NegativeOrder = 6;
614   STRINGSA("-1","1.0-$");
615   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
616   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
617 
618   format.NegativeOrder = 7;
619   STRINGSA("-1","1.0$-");
620   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
621   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
622 
623   format.NegativeOrder = 8;
624   STRINGSA("-1","-1.0 $");
625   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
626   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
627 
628   format.NegativeOrder = 9;
629   STRINGSA("-1","-$ 1.0");
630   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
631   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
632 
633   format.NegativeOrder = 10;
634   STRINGSA("-1","1.0 $-");
635   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
636   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
637 
638   format.NegativeOrder = 11;
639   STRINGSA("-1","$ 1.0-");
640   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
641   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
642 
643   format.NegativeOrder = 12;
644   STRINGSA("-1","$ -1.0");
645   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
646   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
647 
648   format.NegativeOrder = 13;
649   STRINGSA("-1","1.0- $");
650   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
651   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
652 
653   format.NegativeOrder = 14;
654   STRINGSA("-1","($ 1.0)");
655   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
656   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
657 
658   format.NegativeOrder = 15;
659   STRINGSA("-1","(1.0 $)");
660   ret = GetCurrencyFormatA(lcid, 0, input, &format, buffer, COUNTOF(buffer));
661   EXPECT_VALID; EXPECT_LENA; EXPECT_EQA;
662 }
663 
664 #define NEG_PARENS      0 /* "(1.1)" */
665 #define NEG_LEFT        1 /* "-1.1"  */
666 #define NEG_LEFT_SPACE  2 /* "- 1.1" */
667 #define NEG_RIGHT       3 /* "1.1-"  */