Merge 16553 / 16555 (weiden) from trunk:
handle memory allocation errors in GetEnvironmentVariable() and ensure the string is always null-terminated
Modified: branches/ros-branch-0_2_7/reactos/lib/kernel32/misc/env.c

Modified: branches/ros-branch-0_2_7/reactos/lib/kernel32/misc/env.c
--- branches/ros-branch-0_2_7/reactos/lib/kernel32/misc/env.c	2005-08-03 15:05:54 UTC (rev 17004)
+++ branches/ros-branch-0_2_7/reactos/lib/kernel32/misc/env.c	2005-08-03 16:10:03 UTC (rev 17005)
@@ -48,17 +48,33 @@
 
 	/* initialize unicode variable value string and allocate buffer */
 	VarValueU.Length = 0;
-	VarValueU.MaximumLength = nSize * sizeof(WCHAR);
-	VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
-	                                    0,
-	                                    VarValueU.MaximumLength);
+	if (nSize != 0)
+	{
+	    VarValueU.MaximumLength = (nSize - 1) * sizeof(WCHAR);
+	    VarValueU.Buffer = RtlAllocateHeap (RtlGetProcessHeap (),
+	                                        0,
+	                                        nSize * sizeof(WCHAR));
+            if (VarValueU.Buffer != NULL)
+            {
+                /* NULL-terminate the buffer in any case! RtlQueryEnvironmentVariable_U
+                   only terminates it if MaximumLength < Length! */
+                VarValueU.Buffer[nSize - 1] = L'\0';
+            }
+        }
+	else
+	{
+            VarValueU.MaximumLength = 0;
+            VarValueU.Buffer = NULL;
+	}
 
-	/* get unicode environment variable */
-	Status = RtlQueryEnvironmentVariable_U (NULL,
-	                                        &VarNameU,
-	                                        &VarValueU);
-	if (!NT_SUCCESS(Status))
-	{
+        if (VarValueU.Buffer != NULL || nSize == 0)
+        {
+            /* get unicode environment variable */
+	    Status = RtlQueryEnvironmentVariable_U (NULL,
+	                                            &VarNameU,
+	                                            &VarValueU);
+	    if (!NT_SUCCESS(Status))
+	    {
 		/* free unicode buffer */
 		RtlFreeHeap (RtlGetProcessHeap (),
 		             0,
@@ -70,28 +86,37 @@
 		SetLastErrorByStatus (Status);
 		if (Status == STATUS_BUFFER_TOO_SMALL)
 		{
-			return VarValueU.Length / sizeof(WCHAR) + 1;
+			return (VarValueU.Length / sizeof(WCHAR)) + 1;
 		}
 		else
 		{
 			return 0;
 		}
-	}
+	    }
 
-	/* convert unicode value string to ansi */
-	RtlUnicodeStringToAnsiString (&VarValue,
-	                              &VarValueU,
-	                              FALSE);
+	    /* convert unicode value string to ansi */
+	    RtlUnicodeStringToAnsiString (&VarValue,
+	                                  &VarValueU,
+	                                  FALSE);
 
-	/* free unicode buffer */
-	RtlFreeHeap (RtlGetProcessHeap (),
-	             0,
-	             VarValueU.Buffer);
+            if (VarValueU.Buffer != NULL)
+            {
+                /* free unicode buffer */
+	        RtlFreeHeap (RtlGetProcessHeap (),
+	                     0,
+	                     VarValueU.Buffer);
+            }
 
-	/* free unicode variable name string */
-	RtlFreeUnicodeString (&VarNameU);
+	    /* free unicode variable name string */
+	    RtlFreeUnicodeString (&VarNameU);
 
-	return (VarValueU.Length / sizeof(WCHAR));
+	    return (VarValueU.Length / sizeof(WCHAR));
+        }
+        else
+        {
+            SetLastError (ERROR_NOT_ENOUGH_MEMORY);
+            return 0;
+        }
 }
 
 
@@ -114,7 +139,7 @@
 	                      lpName);
 
 	VarValue.Length = 0;
-	VarValue.MaximumLength = nSize * sizeof(WCHAR);
+	VarValue.MaximumLength = (nSize != 0 ? (nSize - 1) * sizeof(WCHAR) : 0);
 	VarValue.Buffer = lpBuffer;
 
 	Status = RtlQueryEnvironmentVariable_U (NULL,
@@ -125,13 +150,20 @@
 		SetLastErrorByStatus (Status);
 		if (Status == STATUS_BUFFER_TOO_SMALL)
 		{
-			return (VarValue.Length / sizeof(WCHAR)) +  1;
+			return (VarValue.Length / sizeof(WCHAR)) + 1;
 		}
 		else
 		{
 			return 0;
 		}
 	}
+	
+        if (nSize != 0)
+        {
+            /* make sure the string is NULL-terminated! RtlQueryEnvironmentVariable_U
+               only terminates it if MaximumLength < Length */
+	    VarValue.Buffer[VarValue.Length / sizeof(WCHAR)] = L'\0';
+	}
 
 	return (VarValue.Length / sizeof(WCHAR));
 }