GetDate/TimeFormat() patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* ole/ole2nls.c, include/winnls.h:
Chris Morgan <cmorgan@alum.wpi.edu>
GetDateFormat() and GetTimeFormat() should check the validity of the time/date 
structure it is processing.  Add comments to describe flags behavior.  Add 
support for TIME_FORCE24HOURFORMAT, TIME_NOMINUTESORSECONDS, TIME_NOSECONDS 
and TIME_NOTIMEMARKER.  Add check in GetDateFormatW() for invalid flag
combinations.  Added some missing DATE_* defines to winnls.h. Behavior
verified against NT4.0.

* dlls/kernel/tests/locale.c:
Chris Morgan <cmorgan@alum.wpi.edu>
Add additional tests for GetTimeFormat() and GetDateFormat().  Uncomment
wine_todo tests that now succeed with fixes to GetTime/DateFormat().
Index: ole/ole2nls.c
===================================================================
RCS file: /home/wine/wine/ole/ole2nls.c,v
retrieving revision 1.109
diff -u -r1.109 ole2nls.c
--- ole/ole2nls.c	12 Dec 2002 03:55:45 -0000	1.109
+++ ole/ole2nls.c	18 Dec 2002 05:03:48 -0000
@@ -1357,7 +1357,22 @@
   ''   used to quote literal characters
   ''   (within a quoted string) indicates a literal '
 
+ If TIME_NOMINUTESORSECONDS or TIME_NOSECONDS is specified, the function 
+  removes the separator(s) preceding the minutes and/or seconds element(s).
+
+ If TIME_NOTIMEMARKER is specified, the function removes the separator(s) 
+  preceding and following the time marker.
+
+ If TIME_FORCE24HOURFORMAT is specified, the function displays any existing 
+  time marker, unless the TIME_NOTIMEMARKER flag is also set.
+
  These functions REQUIRE valid locale, date,  and format.
+
+ If the time or date is invalid, return 0 and set ERROR_INVALID_PARAMETER
+
+ Return value is the number of characters written, or if outlen is zero
+	it is the number of characters required for the output including
+	the terminating null.
  */
 static INT OLE_GetFormatW(LCID locale, DWORD flags, DWORD tflags,
 			    const SYSTEMTIME* xtime,
@@ -1365,6 +1380,12 @@
 			    LPWSTR output, INT outlen, int dateformat)
 {
    INT     outpos;
+   INT	   lastFormatPos; /* the position in the output buffer of */
+			  /* the end of the output from the last formatting */
+			  /* character */
+   BOOL	   dropUntilNextFormattingChar = FALSE; /* TIME_NOTIMEMARKER drops 
+				all of the text around the dropped marker,
+				eg. "h@!t@!m" becomes "hm" */
 
    /* make a debug report */
    TRACE("args: 0x%lx, 0x%lx, 0x%lx, time(d=%d,h=%d,m=%d,s=%d), fmt:%s (at %p), "
@@ -1375,25 +1396,49 @@
 
    /* initialize state variables */
    outpos = 0;
+   lastFormatPos = 0;
 
    while (*format) {
       /* Literal string: Maybe terminated early by a \0 */
-      if (*format == (WCHAR) '\'') {
+      if (*format == (WCHAR) '\'')
+      {
          format++;
-         while (*format) {
-            if (*format == (WCHAR) '\'') {
+
+	 /* We loop while we haven't reached the end of the format string */
+	 /* and until we haven't found another "'" character */
+	 while (*format)
+         {
+	    /* we found what might be the close single quote mark */
+	    /* we need to make sure there isn't another single quote */
+	    /* after it, if there is we need to skip over this quote mark */
+	    /* as the user is trying to put a single quote mark in their output */
+            if (*format == (WCHAR) '\'')
+            {
                format++;
-               if (*format != '\'') {
+               if (*format != '\'')
+               {
                   break; /* It was a terminating quote */
                }
             }
+
+	    /* if outlen is zero then we are couting the number of */
+	    /* characters of space we need to output this text, don't */
+	    /* modify the output buffer */
             if (!outlen)
-               /* We are counting */;
-            else if (outpos >= outlen)
+            {
+               outpos++;   /* We are counting */;
+            }  else if (outpos >= outlen)
+            {
                goto too_short;
-            else
-               output[outpos] = *format;
-            outpos++;
+            } else 
+            {
+               /* even drop literal strings */
+	       if(!dropUntilNextFormattingChar)
+               {
+                 output[outpos] = *format;
+                 outpos++;
+               }
+            }
             format++;
          }
       } else if ( (dateformat &&  (*format=='d' ||
@@ -1404,15 +1449,28 @@
 				   *format=='h' ||
 				   *format=='m' ||
 				   *format=='s' ||
-				   *format=='t') )    ) {
+				   *format=='t') )    ) 
+     /* if processing a date and we have a date formatting character, OR */
+     /* if we are processing a time and we have a time formatting character */
+     {
          int type, count;
          char    tmp[16];
          WCHAR   buf[40];
          int     buflen=0;
          type = *format;
          format++;
+
+	 /* clear out the drop text flag if we are in here */
+	 dropUntilNextFormattingChar = FALSE;
+
+         /* count up the number of the same letter values in a row that */
+	 /* we get, this lets us distinguish between "s" and "ss" and it */
+	 /* eliminates the duplicate to simplify the below case statement */
          for (count = 1; *format == type; format++)
             count++;
+
+	 buf[0] = 0; /* always null terminate the buffer */
+
          switch(type)
          {
           case 'd':
@@ -1466,38 +1524,72 @@
             break;
 
           case 'h':
-              /* hours 1:00-12:00 --- is this right? */
-              sprintf( tmp, "%.*d", count > 2 ? 2 : count, (xtime->wHour-1)%12 +1);
-              MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
-              break;
-
+	      /* fallthrough if we are forced to output in 24 hour format */
+	      if(!(tflags & TIME_FORCE24HOURFORMAT))
+              {
+                /* hours 1:00-12:00 --- is this right? */
+		/* NOTE: 0000 hours is also 12 midnight */
+                sprintf( tmp, "%.*d", count > 2 ? 2 : count, 
+			xtime->wHour == 0 ? 12 : (xtime->wHour-1)%12 +1);
+                MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
+                break;
+              }
           case 'H':
               sprintf( tmp, "%.*d", count > 2 ? 2 : count, xtime->wHour );
               MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
               break;
 
           case 'm':
-              sprintf( tmp, "%.*d", count > 2 ? 2 : count, xtime->wMinute );
-              MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
+	      /* if TIME_NOMINUTESORSECONDS don't display minutes */
+	      if(!(tflags & TIME_NOMINUTESORSECONDS))
+              {
+                sprintf( tmp, "%.*d", count > 2 ? 2 : count, xtime->wMinute );
+                MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
+	      } else
+	      {
+		outpos = lastFormatPos;
+	      }
               break;
 
           case 's':
-              sprintf( tmp, "%.*d", count > 2 ? 2 : count, xtime->wSecond );
-              MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
+	      /* if we have a TIME_NOSECONDS or TIME_NOMINUTESORSECONDS 
+			flag then don't display seconds */
+	      if(!(tflags & TIME_NOSECONDS) && !(tflags & 
+			TIME_NOMINUTESORSECONDS))
+              {
+                sprintf( tmp, "%.*d", count > 2 ? 2 : count, xtime->wSecond );
+                MultiByteToWideChar( CP_ACP, 0, tmp, -1, buf, sizeof(buf)/sizeof(WCHAR) );
+	      } else
+	      {
+		outpos = lastFormatPos;
+	      }
               break;
 
           case 't':
-	    GetLocaleInfoW(locale, (xtime->wHour < 12) ?
+	    if(!(tflags & TIME_NOTIMEMARKER))
+	    {
+  	      GetLocaleInfoW(locale, (xtime->wHour < 12) ?
 			     LOCALE_S1159 : LOCALE_S2359,
 			     buf, sizeof(buf) );
-	    if        (count == 1) {
-	       buf[1] = 0;
+  	      if (count == 1)
+	      {
+	         buf[1] = 0;
+	      }
+            } else
+	    {
+		outpos = lastFormatPos; /* remove any prior text up until 
+			the output due to formatting characters */
+ 		dropUntilNextFormattingChar = TRUE; /* drop everything 
+			until we hit the next formatting character */
 	    }
             break;
          }
 
 	 /* cat buf onto the output */
 	 buflen = strlenW(buf);
+
+	 /* we are counting how many characters we need for output */
+	 /* don't modify the output buffer... */
          if (!outlen)
             /* We are counting */;
          else if (outpos + buflen < outlen) {
@@ -1508,15 +1600,27 @@
             goto too_short;
 	 }
 	 outpos += buflen;
-      } else {
+	 lastFormatPos = outpos; /* record the end of the formatting text we just output */
+      } else /* we are processing a NON formatting character */
+      {
          /* a literal character */
          if (!outlen)
-            /* We are counting */;
+         {
+            outpos++;   /* We are counting */;
+         }
          else if (outpos >= outlen)
+         {
             goto too_short;
-         else
-            output[outpos] = *format;
-         outpos++;
+         }
+         else /* just copy the character into the output buffer */
+         {
+	    /* unless we are dropping characters */
+	    if(!dropUntilNextFormattingChar)
+	    {
+	       output[outpos] = *format;
+               outpos++;
+            }
+         }
          format++;
       }
    }
@@ -1528,7 +1632,8 @@
       goto too_short;
    else
       output[outpos] = '\0';
-   outpos++;
+
+   outpos++; /* add one for the terminating null character */
 
    TRACE(" returning %d %s\n", outpos, debugstr_w(output));
    return outpos;
@@ -1624,9 +1729,9 @@
     TRACE("(0x%04lx,0x%08lx,%p,%s,%p,%d)\n",
 	  locale,flags,xtime,debugstr_w(format),date,datelen);
     
-    /* Tests (could be left until OLE_GetFormatW) */
-    if (flags && format)
-    {
+    /* Tests */
+    if (flags && format) /* if lpFormat is non-null then flags must be zero */
+    {			 
         SetLastError (ERROR_INVALID_FLAGS);
 	return 0;
     }
@@ -1635,26 +1740,62 @@
         SetLastError (ERROR_INVALID_PARAMETER);
 	return 0;
     }
-    if (!locale) {
+    if (!locale)
+    {
 	locale = LOCALE_SYSTEM_DEFAULT;
     };
     
-    if (locale == LOCALE_SYSTEM_DEFAULT) {
+    if (locale == LOCALE_SYSTEM_DEFAULT)
+    {
 	thislocale = GetSystemDefaultLCID();
-    } else if (locale == LOCALE_USER_DEFAULT) {
+    } else if (locale == LOCALE_USER_DEFAULT)
+    {
 	thislocale = GetUserDefaultLCID();
-    } else {
+    } else
+    {
 	thislocale = locale;
     };
-    
-    if (xtime == NULL) {
+
+    /* check for invalid flag combinations */
+    if((flags & DATE_LTRREADING) && (flags & DATE_RTLREADING))
+    {
+        SetLastError (ERROR_INVALID_FLAGS);
+	return 0;
+    }
+
+    /* DATE_SHORTDATE, DATE_LONGDATE and DATE_YEARMONTH are mutually */
+    /* exclusive */    
+    if((flags & (DATE_SHORTDATE|DATE_LONGDATE|DATE_YEARMONTH))
+	 && !((flags & DATE_SHORTDATE) ^ (flags & 
+        DATE_LONGDATE) ^ (flags & DATE_YEARMONTH)))
+    {
+        SetLastError (ERROR_INVALID_FLAGS);
+	return 0;
+    }
+
+    /* if the user didn't pass in a pointer to the current time we read it */    
+    /* here */
+    if (xtime == NULL)
+    {
 	GetSystemTime(&t);
-    } else {
+    } else
+    {
+        /* NOTE: check here before we perform the SystemTimeToFileTime conversion */
+        /*  because this conversion will fix invalid time values */
+        /* check to see if the time/date is valid */
+        /* set ERROR_INVALID_PARAMETER and return 0 if invalid */
+        if((xtime->wDay > 31) || (xtime->wDayOfWeek > 6) || (xtime->wMonth > 12))
+        {
+          SetLastError(ERROR_INVALID_PARAMETER);
+          return 0;
+        }
+
 	/* Silently correct wDayOfWeek by transforming to FileTime and back again */
 	res=SystemTimeToFileTime(xtime,&ft);
+
 	/* Check year(?)/month and date for range and set ERROR_INVALID_PARAMETER  on error */
-	/*FIXME: SystemTimeToFileTime doesn't yet do that check */
-	if(!res) {
+	if(!res)
+	{
 	    SetLastError(ERROR_INVALID_PARAMETER);
 	    return 0;
 	}
@@ -1663,13 +1804,15 @@
     };
     thistime = &t;
     
-    if (format == NULL) {
+    if (format == NULL)
+    {
 	GetLocaleInfoW(thislocale, ((flags&DATE_LONGDATE)
 				    ? LOCALE_SLONGDATE
 				    : LOCALE_SSHORTDATE),
 		       format_buf, sizeof(format_buf)/sizeof(*format_buf));
 	thisformat = format_buf;
-    } else {
+    } else
+    {
 	thisformat = format;
     };
     
@@ -2758,6 +2901,8 @@
 /******************************************************************************
  *		GetTimeFormatW	[KERNEL32.@]
  * Makes a Unicode string of the time
+ *
+ * NOTE: See OLE_GetFormatW() for further documentation
  */
 INT WINAPI
 GetTimeFormatW(LCID locale,        /* [in]  */
@@ -2779,15 +2924,29 @@
 
 	thislocale = OLE2NLS_CheckLocale ( locale );
 
+	/* if the user didn't specify a format we use the default */
+        /* format for this locale */
 	if (format == NULL)
-	{ if (flags & LOCALE_NOUSEROVERRIDE)  /* use system default */
-	  { thislocale = GetSystemDefaultLCID();
+	{
+	  if (flags & LOCALE_NOUSEROVERRIDE)  /* use system default */
+	  { 
+            thislocale = GetSystemDefaultLCID();
 	  }
 	  GetLocaleInfoW(thislocale, thisflags, format_buf, 40);
 	  thisformat = format_buf;
 	}
 	else
-	{ thisformat = format;
+	{
+	  /* if non-null format and LOCALE_NOUSEROVERRIDE then fail */ 
+	  /* NOTE: this could be either invalid flags or invalid parameter */
+	  /*  windows sets it to invalid flags */
+	  if (flags & LOCALE_NOUSEROVERRIDE)
+          {
+	    SetLastError(ERROR_INVALID_FLAGS);
+	    return 0;
+          }
+
+          thisformat = format;
 	}
 
 	if (xtime == NULL) /* NULL means use the current local time */
@@ -2795,7 +2954,15 @@
 	  thistime = &t;
 	}
 	else
-	{ thistime = xtime;
+	{
+          /* check time values */
+          if((xtime->wHour > 24) || (xtime->wMinute >= 60) || (xtime->wSecond >= 60))
+          {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return 0;
+          }
+
+          thistime = xtime;
 	}
 
 	ret = OLE_GetFormatW(thislocale, thisflags, flags, thistime, thisformat,
Index: include/winnls.h
===================================================================
RCS file: /home/wine/wine/include/winnls.h,v
retrieving revision 1.37
diff -u -r1.37 winnls.h
--- include/winnls.h	4 Nov 2002 22:39:45 -0000	1.37
+++ include/winnls.h	18 Dec 2002 05:03:48 -0000
@@ -196,6 +196,10 @@
 #define DATE_USE_ALT_CALENDAR  0x00000004  /* use alternate calendar */
                           /* alt. calendar support is broken anyway */
 
+#define DATE_YEARMONTH         0x00000008  /* use year/month */
+#define DATE_LTRREADING        0x00000010  /* left to right reading order */
+#define DATE_RTLREADING        0x00000020  /* right to left reading order */
+
 #define TIME_FORCE24HOURFORMAT 0x00000008  /* force 24 hour format*/
 #define TIME_NOTIMEMARKER      0x00000004  /* show no AM/PM */
 #define TIME_NOSECONDS         0x00000002  /* show no seconds */
Index: dlls/kernel/tests/locale.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/tests/locale.c,v
retrieving revision 1.9
diff -u -r1.9 locale.c
--- dlls/kernel/tests/locale.c	12 Dec 2002 22:25:23 -0000	1.9
+++ dlls/kernel/tests/locale.c	18 Dec 2002 05:01:51 -0000
@@ -27,7 +27,7 @@
 #define eq(received, expected, label, type) \
         ok((received) == (expected), "%s: got " type " instead of " type, (label),(received),(expected))
 
-#define BUFFER_SIZE		50
+#define BUFFER_SIZE		128
 /* Buffer used by callback function */
 char GlobalBuffer[BUFFER_SIZE];
 #define COUNTOF(x) (sizeof(x)/sizeof(x)[0])
@@ -43,17 +43,17 @@
 
 void TestGetLocaleInfoA()
 {
-int ret, cmp;
-LCID lcid;
-char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE];
+	int ret, cmp;
+  	LCID lcid;
+  	char buffer[BUFFER_SIZE], Expected[BUFFER_SIZE];
 
 	strcpy(Expected, "Monday");
 	lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
 	ok (lcid == 0x409, "wrong LCID calculated");
 
-        /* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
-         * partially fill the buffer even if it is too short. See bug 637.
-         */
+	/* HTMLKit and "Font xplorer lite" expect GetLocaleInfoA to
+	* partially fill the buffer even if it is too short. See bug 637.
+	*/
 	strcpy(Expected, "xxxxx");
 	memset( buffer, 'x', sizeof(buffer) );
 	ret = GetLocaleInfoA(lcid, LOCALE_SDAYNAME1, buffer, 0);
@@ -90,103 +90,425 @@
 
 void TestGetTimeFormatA()
 {
-int ret, error, cmp;
-SYSTEMTIME  curtime;
-char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
-LCID lcid;
+  int ret, error, cmp;
+  SYSTEMTIME  curtime;
+  char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
+  LCID lcid;
+
+  lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
+  strcpy(format, "tt HH':'mm'@'ss");
+
+  /* fill curtime with dummy data */
+  memset(&curtime, 2, sizeof(SYSTEMTIME));
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
+  error = GetLastError ();
+  ok (ret == 0, "GetTimeFormat should fail on dummy data");
+  eq (error, ERROR_INVALID_PARAMETER, "GetTimeFormat GetLastError()", "%d");
+  SetLastError(NO_ERROR);   /* clear out the last error */
+
+  /* test that we can correctly produce the expected output, not a very */
+  /* demanding test ;-) */
+  strcpy(Expected, "AM 08:56@13");
+  curtime.wHour = 8;  curtime.wMinute = 56;
+  curtime.wSecond = 13; curtime.wMilliseconds = 22;
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
+  cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+  ok (cmp == 0, "GetTimeFormat got %s instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* check that the size reported by the above call is accuate */
+  memset(buffer, 'x', sizeof(buffer));
+  ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, ret);
+  ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
+           "GetTimeFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
+  ok(buffer[0] != 'x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
 
-	lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
-	strcpy(format, "tt HH':'mm'@'ss");
+  /* test failure due to insufficent buffer */
+  ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, 2);
+  ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
+           "GetTimeFormat(len=2): ret=%d error=%ld", ret, GetLastError());
 
-        todo_wine {
-            /* fill curtime with dummy data */
-            memset(&curtime, 2, sizeof(SYSTEMTIME));
-            ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
-            error = GetLastError ();
-            ok (ret == 0, "GetTimeFormat should fail on dummy data");
-            eq (error, ERROR_INVALID_PARAMETER, "GetTimeFormat GetLastError()", "%d");
-        }
-
-	strcpy(Expected, "AM 08:56@13");
-	curtime.wHour = 8;  curtime.wMinute = 56;
-	curtime.wSecond = 13; curtime.wMilliseconds = 22;
-	ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, COUNTOF(buffer));
-	cmp = strncmp (Expected, buffer, strlen(Expected)+1);
-	ok (cmp == 0, "GetTimeFormat got %s instead of %s", buffer, Expected);
-	eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
-
-	/* test with too small buffers */
-        SetLastError(0);
-	ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, NULL, 0);
-        ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
+  /* test with too small buffers */
+  SetLastError(0);
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, NULL, 0);
+  ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
            "GetTimeFormat(len=0): ret=%d error=%ld\n",ret,GetLastError());
 
-	memset(buffer, 'x', sizeof(buffer));
-        ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, ret);
-        ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
-           "GetTimeFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
-	ok(buffer[0]!='x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
-
-	ret = GetTimeFormatA(lcid, TIME_FORCE24HOURFORMAT, &curtime, format, buffer, 2);
-	ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
-           "GetTimeFormat(len=2): ret=%d error=%ld", ret, GetLastError());
+  /************************************/
+  /* test out TIME_NOMINUTESORSECONDS */
+  strcpy(Expected, "8 AM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOMINUTESORSECONDS, &curtime, NULL, buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test out TIME_NOMINUTESORSECONDS with complex format strings */
+  strcpy(Expected, "4");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOMINUTESORSECONDS, &curtime, "m1s2m3s4", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+
+  /************************************/
+  /* test out TIME_NOSECONDS */
+  strcpy(Expected, "8:56 AM");
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &curtime, NULL, buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test out TIME_NOSECONDS with a format string of "h:m:s tt" */
+  strcpy(Expected, "8:56 AM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &curtime, "h:m:s tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test out TIME_NOSECONDS a strange format string of multiple delimiters "h@:m@:s tt" */
+  /* expected behavior is to turn "hD1D2...mD3D4...sD5D6...tt" and turn this into */
+  /* "hD1D2...mD3D4...tt" */
+  strcpy(Expected, "8.@:56.@:AM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &curtime, "h.@:m.@:s.@:tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test out TIME_NOSECONDS with an string of "1s2s3s4" */
+  /* expect to see only "3" */
+  strcpy(Expected, "3");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOSECONDS, &curtime, "s1s2s3", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /************************/
+  /* Test out time marker */
+  /* test out time marker(AM/PM) behavior */
+  strcpy(Expected, "A/AM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "t/tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* time marker testing part 2 */
+  curtime.wHour = 13;
+  strcpy(Expected, "P/PM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "t/tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /******************************/
+  /* test out TIME_NOTIMEMARKER */
+  /* NOTE: TIME_NOTIMEMARKER elminates all text around any time marker */
+  /*      formatting character until the previous or next formatting character */
+  strcpy(Expected, "156");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOTIMEMARKER, &curtime, "h1t2tt3m", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /***********************************/
+  /* test out TIME_FORCE24HOURFORMAT */
+  strcpy(Expected, "13:56:13 PM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_FORCE24HOURFORMAT, &curtime, "h:m:s tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* check to confirm that unlike what msdn documentation suggests, the time marker */
+  /* is not added under TIME_FORCE24HOURFORMAT */
+  strcpy(Expected, "13:56:13");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_FORCE24HOURFORMAT, &curtime, "h:m:s", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of %s", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+
+  /*********************************************/
+  /* test advanced formatting of GetTimeFormat */
+
+  /* test for 24 hour conversion and for leading zero */
+  /* NOTE: we do not test the "hh or HH" case since hours is two digits */
+  /* "h hh H HH m mm s ss t tt" */
+  curtime.wHour = 14; /* change this to 14 or 2pm */
+  curtime.wMinute = 5;
+  curtime.wSecond = 3;
+  strcpy(Expected, "2 02 14 14 5 05 3 03 P PM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h hh H HH m mm s ss t tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* complete testing on the advanced formatting by testing "hh" and "HH" */
+  /* 0 hour is 12 o'clock or 00 hundred hours */
+  curtime.wHour = 0;
+  strcpy(Expected, "12/0/12/00");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h/H/hh/HH", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test for LOCALE_NOUSEROVERRIDE set, lpFormat must be NULL */
+  strcpy(Expected, "0:5:3 AM");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &curtime, "h:m:s tt", buffer, sizeof(buffer));
+  /* NOTE: we expect this to FAIL */
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (ret == 0, "GetTimeFormat succeeded instead of failing for LOCALE_NOUSEROVERRIDE and a non-null lpFormat\n");
+
+  /* try to convert formatting strings with more than two letters */
+  /* "h:hh:hhh:H:HH:HHH:m:mm:mmm:M:MM:MMM:s:ss:sss:S:SS:SSS" */
+  /* NOTE: we expect any letter for which there is an upper case value */
+  /*    we should expect to see a replacement.  For letters that DO NOT */
+  /*    have upper case values we expect to see NO REPLACEMENT */
+  curtime.wHour = 8;  curtime.wMinute = 56;
+  curtime.wSecond = 13; curtime.wMilliseconds = 22;
+  strcpy(Expected, "8:08:08 8:08:08 56:56:56 M:MM:MMM 13:13:13 S:SS:SSS");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h:hh:hhh H:HH:HHH m:mm:mmm M:MM:MMM s:ss:sss S:SS:SSS", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test that if the size of the buffer is zero that the buffer is not modified */
+  /* and that the number of necessary characters is returned */
+  /* NOTE: The count includes the terminating null. */
+  strcpy(buffer, "THIS SHOULD NOT BE MODIFIED");
+  strcpy(Expected, "THIS SHOULD NOT BE MODIFIED");
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h", buffer, 0);
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, 2, "GetTimeFormat", "%d"); /* we expect to require two characters of space from "h" */
+
+  /* test that characters in single quotation marks are ignored and left in */
+  /* the same location in the output string */
+  strcpy(Expected, "8 h 8 H 08 HH 56 m 13 s A t AM tt");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h 'h' H 'H' HH 'HH' m 'm' s 's' t 't' tt 'tt'", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test the printing of the single quotation marks when */
+  /* we use an invalid formatting string of "'''" instead of "''''" */
+  strcpy(Expected, "'");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "'''", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test that msdn suggested single quotation usage works as expected */
+  strcpy(Expected, "'");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "''''", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test for more normal use of single quotation mark */
+  strcpy(Expected, "08");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "''HHHHHH", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* and test for normal use of the single quotation mark */
+  strcpy(Expected, "'HHHHHH");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "'''HHHHHH'", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test for more odd use of the single quotation mark */
+  strcpy(Expected, "'HHHHHH");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "'''HHHHHH", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test that with TIME_NOTIMEMARKER that even if something is defined */
+  /* as a literal we drop it before and after the markers until the next */
+  /* formatting character */
+  strcpy(Expected, "");
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, TIME_NOTIMEMARKER, &curtime, "'123'tt", buffer, sizeof(buffer));
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok (cmp == 0, "GetTimeFormat got '%s' instead of '%s'", buffer, Expected);
+  eq (ret, lstrlenA(Expected)+1, "GetTimeFormat", "%d");
+
+  /* test for expected return and error value when we have a */
+  /* non-null format and LOCALE_NOUSEROVERRIDE for flags */
+  SetLastError(NO_ERROR); /* reset last error value */
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &curtime, "'123'tt", buffer, sizeof(buffer));
+  error = GetLastError();
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok ((ret == 0) && (error == ERROR_INVALID_FLAGS), "GetTimeFormat got ret of '%d' and error of '%d'", ret, error);
+
+  /* test that invalid time values result in ERROR_INVALID_PARAMETER */
+  /* and a return value of 0 */
+  curtime.wHour = 25;
+  SetLastError(NO_ERROR); /* reset last error value */
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "'123'tt", buffer, sizeof(buffer));
+  error = GetLastError();
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok ((ret == 0) && (error == ERROR_INVALID_PARAMETER), "GetTimeFormat got ret of '%d' and error of '%d'", ret, error);
+
+  /* test that invalid information in the date section of the current time */
+  /* doesn't result in an error since GetTimeFormat() should ignore this information */
+  curtime.wHour = 12; /* valid wHour */
+  curtime.wMonth = 60; /* very invalid wMonth */
+  strcpy(Expected, "12:56:13");
+  SetLastError(NO_ERROR); /* reset last error value */
+  ret = GetTimeFormatA(LOCALE_SYSTEM_DEFAULT, 0, &curtime, "h:m:s", buffer, sizeof(buffer));
+  error = GetLastError();
+  cmp = strncmp(buffer, Expected, BUFFER_SIZE);
+  ok ((ret == lstrlenA(Expected)+1) && (error == NO_ERROR), "GetTimeFormat got ret of '%d' and error of '%d' and a buffer of '%s'", ret, error, buffer);
 }
 
 void TestGetDateFormatA()
 {
-int ret, error, cmp;
-SYSTEMTIME  curtime;
-char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
-LCID lcid;
-
-	lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
-	strcpy(format, "ddd',' MMM dd yy");
-
-        todo_wine {
-            /* fill curtime with dummy data */
-            memset(&curtime, 2, sizeof(SYSTEMTIME));
-            memset(buffer, 'x', sizeof(buffer));
-            ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
-            error = GetLastError ();
-            ok (ret== 0, "GetDateFormat should fail on dummy data");
-            eq (error, ERROR_INVALID_PARAMETER, "GetDateFormat", "%d");
-        }
-
-	strcpy(Expected, "Sat, May 04 02");
-	memset(buffer, 'x', sizeof(buffer));
-	curtime.wYear = 2002;
-	curtime.wMonth = 5;
-	curtime.wDay = 4;
-	curtime.wDayOfWeek = 3;
-	ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
-	cmp = strncmp (Expected, buffer, strlen(Expected)+1);
-	todo_wine { ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected); }
-	eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
-
-	/* test format with "'" */
-	memset(buffer, 'x', sizeof(buffer));
-	strcpy(format, "ddd',' MMM dd ''''yy");
-	strcpy(Expected, "Sat, May 04 '02");
-	ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
-	cmp = strncmp (Expected, buffer, strlen(Expected)+1);
-	todo_wine { ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected); }
-	eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
-
-	/* test with too small buffers */
-        SetLastError(0);
-	ret = GetDateFormatA(lcid, 0, &curtime, format, NULL, 0);
-	ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
-           "GetDateFormat(len=0): ret=%d error=%ld\n",ret,GetLastError());
-
-	memset(buffer, 'x', sizeof(buffer));
-        ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, ret);
-	ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
-           "GetDateFormat(right size): ret=%d error=%ld\n",ret,GetLastError());
-	ok(buffer[0]!='x',"GetTimeFormat(right size): buffer=[%s]\n",buffer);
-
-	ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, 2);
-	ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
+  int ret, error, cmp;
+  SYSTEMTIME  curtime;
+  char buffer[BUFFER_SIZE], format[BUFFER_SIZE], Expected[BUFFER_SIZE];
+  LCID lcid;
+
+  lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
+  strcpy(format, "ddd',' MMM dd yy");
+
+  /* test for failure on dummy data */
+  memset(&curtime, 2, sizeof(SYSTEMTIME));
+  memset(buffer, '0', sizeof(buffer));
+  SetLastError(NO_ERROR);
+  ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
+  error = GetLastError ();
+  ok(ret == 0, "GetDateFormat should fail on dummy data");
+  eq(error, ERROR_INVALID_PARAMETER, "GetDateFormat", "%d");
+
+  /* test for a simple case of date conversion */
+  todo_wine {
+    strcpy(Expected, "Sat, May 04 02");
+    curtime.wYear = 2002;
+    curtime.wMonth = 5;
+    curtime.wDay = 4;
+    curtime.wDayOfWeek = 3;
+    memset(buffer, 0, sizeof(buffer));
+    ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
+/* Uncomment the below when todo_wine is removed */
+/*    eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d"); */
+  }
+
+  /* test format with "'" */
+  todo_wine {
+    strcpy(format, "ddd',' MMM dd ''''yy");
+    strcpy(Expected, "Sat, May 04 '02");
+    memset(buffer, 0, sizeof(buffer));
+    ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
+/* Uncomment the below when todo_wine is removed */
+/*    eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d"); */
+  }
+
+  /* test for success with dummy time data */
+  todo_wine {
+    curtime.wHour = 36;
+    memset(buffer, 0, sizeof(buffer));
+    ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, COUNTOF(buffer));
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (cmp == 0, "GetDateFormat got %s instead of %s", buffer, Expected);
+/* Uncomment the below when the todo_wine is removed */
+/*    eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d"); */
+  }
+
+  /* test that we retrieve the expected size for the necessary output of this string */
+  SetLastError(NO_ERROR);
+  memset(buffer, 0, sizeof(buffer));
+  ret = GetDateFormatA(lcid, 0, &curtime, format, NULL, 0);
+  ok(ret==lstrlenA(Expected)+1 && GetLastError() == 0,
+          "GetDateFormat(len=0): ret=%d error=%ld buffer='%s', expected NO_ERROR(0)\n",ret,GetLastError(), buffer);
+
+  /* test that the expected size matches the actual required size by passing */
+  /* in the expected size */
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, ret);
+  ok(ret==lstrlenA(Expected)+1 && GetLastError()==0,
+           "GetDateFormat(right size): ret=%d error=%ld, buffer = '%s'\n",ret,GetLastError(), buffer);
+  ok(buffer[0]!='x',"GetDateFormat(right size): buffer=[%s]\n",buffer);
+
+  /* test that a buffer shorter than the necessary size results in ERROR_INSUFFICIENT_BUFFER */
+  ret = GetDateFormatA(lcid, 0, &curtime, format, buffer, 2);
+  ok(ret==0 && GetLastError()==ERROR_INSUFFICIENT_BUFFER,
            "GetDateFormat(len=2): ret=%d error=%ld", ret, GetLastError());
+
+  /* test for default behavior being DATE_SHORTDATE */
+  todo_wine {
+    strcpy(Expected, "5/4/02");
+    memset(buffer, '0', sizeof(buffer));
+    ret = GetDateFormat(lcid, 0, &curtime, NULL, buffer, sizeof(buffer));
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (cmp == 0, "GetDateFormat got '%s' instead of '%s'", buffer, Expected);
+    eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
+  }
+
+
+  todo_wine {
+    /* test for expected DATE_LONGDATE behavior with null format */
+    strcpy(Expected, "Saturday, May 04, 2002");
+    memset(buffer, '0', sizeof(buffer));
+    ret = GetDateFormat(lcid, DATE_LONGDATE, &curtime, NULL, buffer, sizeof(buffer));
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (cmp == 0, "GetDateFormat got '%s' instead of '%s'", buffer, Expected);
+    eq (ret, lstrlenA(Expected)+1, "GetDateFormat", "%d");
+  }
+
+  /* test for expected DATE_YEARMONTH behavior with null format */
+  /* NT4 returns ERROR_INVALID_FLAGS for DATE_YEARMONTH */
+  todo_wine {
+    strcpy(Expected, "");
+    buffer[0] = 0;
+    SetLastError(NO_ERROR);
+    memset(buffer, '0', sizeof(buffer));
+    ret = GetDateFormat(lcid, DATE_YEARMONTH, &curtime, NULL, buffer, sizeof(buffer));
+    error = GetLastError();
+    cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+    ok (ret == 0 && (error == ERROR_INVALID_FLAGS), "GetDateFormat check DATE_YEARMONTH with null format expected ERROR_INVALID_FLAGS got return of '%d' and error of '%d'", ret, error);
+  }
+
+  /* Test that using invalid DATE_* flags results in the correct error */
+  /* and return values */
+  strcpy(format, "m/d/y");
+  strcpy(Expected, "Saturday May 2002");
+  SetLastError(NO_ERROR);
+  memset(buffer, '0', sizeof(buffer));
+  ret = GetDateFormat(lcid, DATE_YEARMONTH | DATE_SHORTDATE | DATE_LONGDATE, &curtime, format, buffer, sizeof(buffer));
+  error = GetLastError();
+  cmp = strncmp (Expected, buffer, strlen(Expected)+1);
+  ok ((ret == 0) && (error == ERROR_INVALID_FLAGS), "GetDateFormat checking for mutually exclusive flags got '%s' instead of '%s', got error of %d, expected ERROR_INVALID_FLAGS", buffer, Expected, error);
 }
 
 void TestGetDateFormatW()
@@ -231,16 +553,6 @@
     MultiByteToWideChar (CP_ACP, 0, "Wednesday 23 October 2002", -1, Expected, COUNTOF(Expected));
     cmp = ret ? lstrcmpW (buffer, Expected) : 2;
     ok (ret == lstrlenW(Expected)+1 && error == 0 && cmp == 0, "Day of week correction failed\n");
-
-    /* 1d Invalid year, month or day results in error */
-
-    /* 1e Insufficient space results in error */
-
-    /* 2. Standard behaviour */
-    /* 1c is a reasonable test */
-
-    /* 3. Replicated undocumented behaviour */
-    /* e.g. unexepected characters are retained. */
 }
 
 

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux