[KERNEL32_WINETEST]
[reactos.git] / rostests / winetests / kernel32 / process.c
index 7b5ac75..8aadf2a 100755 (executable)
     } while (0)
 
 static HINSTANCE hkernel32;
+static void   (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
+static BOOL   (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
+static BOOL   (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
 static BOOL   (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
 static BOOL   (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
 static BOOL   (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
+static DWORD  (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
 
 /* ############################### */
 static char     base[MAX_PATH];
@@ -194,10 +198,14 @@ static int     init(void)
     if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
 
     hkernel32 = GetModuleHandleA("kernel32");
+    pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
+    pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
+    pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
     pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
     pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
     pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
     pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
+    pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
     return 1;
 }
 
@@ -243,8 +251,8 @@ static void     doChild(const char* file, const char* option)
     STARTUPINFOA        siA;
     STARTUPINFOW        siW;
     int                 i;
-    char*               ptrA;
-    WCHAR*              ptrW;
+    char                *ptrA, *ptrA_save;
+    WCHAR               *ptrW, *ptrW_save;
     char                bufA[MAX_PATH];
     WCHAR               bufW[MAX_PATH];
     HANDLE              hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
@@ -305,7 +313,7 @@ static void     doChild(const char* file, const char* option)
     childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
 
     /* output of environment (Ansi) */
-    ptrA = GetEnvironmentStringsA();
+    ptrA_save = ptrA = GetEnvironmentStringsA();
     if (ptrA)
     {
         char    env_var[MAX_LISTED_ENV_VAR];
@@ -320,10 +328,11 @@ static void     doChild(const char* file, const char* option)
             ptrA += strlen(ptrA) + 1;
         }
         childPrintf(hFile, "len=%d\n\n", i);
+        FreeEnvironmentStringsA(ptrA_save);
     }
 
     /* output of environment (Unicode) */
-    ptrW = GetEnvironmentStringsW();
+    ptrW_save = ptrW = GetEnvironmentStringsW();
     if (ptrW)
     {
         WCHAR   env_var[MAX_LISTED_ENV_VAR];
@@ -339,6 +348,7 @@ static void     doChild(const char* file, const char* option)
             ptrW += lstrlenW(ptrW) + 1;
         }
         childPrintf(hFile, "len=%d\n\n", i);
+        FreeEnvironmentStringsW(ptrW_save);
     }
 
     childPrintf(hFile, "[Misc]\n");
@@ -523,6 +533,7 @@ static void test_Startup(void)
     char                buffer[MAX_PATH];
     PROCESS_INFORMATION        info;
     STARTUPINFOA       startup,si;
+    char *result;
     static CHAR title[]   = "I'm the title string",
                 desktop[] = "winsta0\\default",
                 empty[]   = "";
@@ -534,7 +545,7 @@ static void test_Startup(void)
     startup.wShowWindow = SW_SHOWNORMAL;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -572,7 +583,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -610,7 +621,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -648,7 +659,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -656,7 +667,7 @@ static void test_Startup(void)
     WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
 
     okChildInt("StartupInfoA", "cb", startup.cb);
-    todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
+    okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
     okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
@@ -686,7 +697,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -695,8 +706,9 @@ static void test_Startup(void)
 
     okChildInt("StartupInfoA", "cb", startup.cb);
     okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
-    ok (startup.lpTitle == NULL || !strcmp(startup.lpTitle, selfname),
-        "StartupInfoA:lpTitle expected '%s' or null, got '%s'\n", selfname, startup.lpTitle);
+    result = getChildString( "StartupInfoA", "lpTitle" );
+    ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
+        "expected '%s' or null, got '%s'\n", selfname, result );
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -725,7 +737,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -734,7 +746,7 @@ static void test_Startup(void)
 
     okChildInt("StartupInfoA", "cb", startup.cb);
     okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
-    todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
+    okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -763,7 +775,7 @@ static void test_Startup(void)
     startup.dwFillAttribute = 0xA55A;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -771,8 +783,8 @@ static void test_Startup(void)
     WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
 
     okChildInt("StartupInfoA", "cb", startup.cb);
-    todo_wine okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
-    todo_wine okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
+    okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
+    okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -794,7 +806,6 @@ static void test_CommandLine(void)
     char                buffer2[MAX_PATH];
     PROCESS_INFORMATION        info;
     STARTUPINFOA       startup;
-    DWORD               len;
     BOOL                ret;
 
     memset(&startup, 0, sizeof(startup));
@@ -804,7 +815,7 @@ static void test_CommandLine(void)
 
     /* the basics */
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -823,9 +834,9 @@ static void test_CommandLine(void)
     startup.dwFlags = STARTF_USESHOWWINDOW;
     startup.wShowWindow = SW_SHOWNORMAL;
 
-    /* from Frangois */
+    /* from Franรงois */
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
@@ -844,7 +855,7 @@ static void test_CommandLine(void)
     /* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
     get_file_name(resfile);
     /* Use exename to avoid buffer containing things like 'C:' */
-    sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+    sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
     SetLastError(0xdeadbeef);
     ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
     ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
@@ -859,7 +870,7 @@ static void test_CommandLine(void)
 
     get_file_name(resfile);
     /* Use exename to avoid buffer containing things like 'C:' */
-    sprintf(buffer, ".\\%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+    sprintf(buffer, ".\\%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
     SetLastError(0xdeadbeef);
     ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
     ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
@@ -873,13 +884,13 @@ static void test_CommandLine(void)
     assert(DeleteFileA(resfile) != 0);
     
     get_file_name(resfile);
-    len = GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
+    GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
     assert ( lpFilePart != 0);
     *(lpFilePart -1 ) = 0;
     p = strrchr(fullpath, '\\');
     /* Use exename to avoid buffer containing things like 'C:' */
-    if (p) sprintf(buffer, "..%s/%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
-    else sprintf(buffer, "./%s tests/process.c %s \"a\\\"b\\\\\" c\\\" d", exename, resfile);
+    if (p) sprintf(buffer, "..%s/%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", p, exename, resfile);
+    else sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
     SetLastError(0xdeadbeef);
     ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
     ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
@@ -895,14 +906,14 @@ static void test_CommandLine(void)
 
     /* Using AppName */
     get_file_name(resfile);
-    len = GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
+    GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
     assert ( lpFilePart != 0);
     *(lpFilePart -1 ) = 0;
     p = strrchr(fullpath, '\\');
     /* Use exename to avoid buffer containing things like 'C:' */
     if (p) sprintf(buffer, "..%s/%s", p, exename);
     else sprintf(buffer, "./%s", exename);
-    sprintf(buffer2, "dummy tests/process.c %s \"a\\\"b\\\\\" c\\\" d", resfile);
+    sprintf(buffer2, "dummy tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
     SetLastError(0xdeadbeef);
     ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
     ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
@@ -1000,7 +1011,7 @@ static void test_Directory(void)
 
     /* the basics */
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     GetWindowsDirectoryA( windir, sizeof(windir) );
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
@@ -1093,10 +1104,11 @@ static void test_Environment(void)
     char                buffer[MAX_PATH];
     PROCESS_INFORMATION        info;
     STARTUPINFOA       startup;
-    char*               child_env;
+    char                *child_env;
     int                 child_env_len;
-    char*               ptr;
-    char*               env;
+    char                *ptr;
+    char                *ptr2;
+    char                *env;
     int                 slen;
 
     memset(&startup, 0, sizeof(startup));
@@ -1106,14 +1118,15 @@ static void test_Environment(void)
 
     /* the basics */
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
     /* wait for child to terminate */
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
     /* child process has changed result file, so let profile functions know about it */
     WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
-    
-    cmpEnvironment(GetEnvironmentStringsA());
+
+    env = GetEnvironmentStringsA();
+    cmpEnvironment(env);
     release_memory();
     assert(DeleteFileA(resfile) != 0);
 
@@ -1124,10 +1137,10 @@ static void test_Environment(void)
 
     /* the basics */
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
-    
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
+
     child_env_len = 0;
-    ptr = GetEnvironmentStringsA();
+    ptr = env;
     while(*ptr)
     {
         slen = strlen(ptr)+1;
@@ -1137,7 +1150,7 @@ static void test_Environment(void)
     /* Add space for additional environment variables */
     child_env_len += 256;
     child_env = HeapAlloc(GetProcessHeap(), 0, child_env_len);
-    
+
     ptr = child_env;
     sprintf(ptr, "=%c:=%s", 'C', "C:\\FOO\\BAR");
     ptr += strlen(ptr) + 1;
@@ -1152,13 +1165,13 @@ static void test_Environment(void)
      * - PATH (already set above)
      * - the directory definitions (=[A-Z]:=)
      */
-    for (env = GetEnvironmentStringsA(); *env; env += strlen(env) + 1)
+    for (ptr2 = env; *ptr2; ptr2 += strlen(ptr2) + 1)
     {
-        if (strncmp(env, "PATH=", 5) != 0 &&
-            strncmp(env, "WINELOADER=", 11) != 0 &&
-            !is_str_env_drive_dir(env))
+        if (strncmp(ptr2, "PATH=", 5) != 0 &&
+            strncmp(ptr2, "WINELOADER=", 11) != 0 &&
+            !is_str_env_drive_dir(ptr2))
         {
-            strcpy(ptr, env);
+            strcpy(ptr, ptr2);
             ptr += strlen(ptr) + 1;
         }
     }
@@ -1168,10 +1181,11 @@ static void test_Environment(void)
     ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n");
     /* child process has changed result file, so let profile functions know about it */
     WritePrivateProfileStringA(NULL, NULL, NULL, resfile);
-    
+
     cmpEnvironment(child_env);
 
     HeapFree(GetProcessHeap(), 0, child_env);
+    FreeEnvironmentStringsA(env);
     release_memory();
     assert(DeleteFileA(resfile) != 0);
 }
@@ -1182,6 +1196,7 @@ static  void    test_SuspendFlag(void)
     PROCESS_INFORMATION        info;
     STARTUPINFOA       startup, us;
     DWORD               exit_status;
+    char *result;
 
     /* let's start simplistic */
     memset(&startup, 0, sizeof(startup));
@@ -1190,7 +1205,7 @@ static  void    test_SuspendFlag(void)
     startup.wShowWindow = SW_SHOWNORMAL;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startup, &info), "CreateProcess\n");
 
     ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
@@ -1207,8 +1222,9 @@ static  void    test_SuspendFlag(void)
 
     okChildInt("StartupInfoA", "cb", startup.cb);
     okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
-    ok (startup.lpTitle == NULL || !strcmp(startup.lpTitle, selfname),
-        "StartupInfoA:lpTitle expected '%s' or null, got '%s'\n", selfname, startup.lpTitle);
+    result = getChildString( "StartupInfoA", "lpTitle" );
+    ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
+        "expected '%s' or null, got '%s'\n", selfname, result );
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -1230,6 +1246,7 @@ static  void    test_DebuggingFlag(void)
     STARTUPINFOA       startup, us;
     DEBUG_EVENT         de;
     unsigned            dbg = 0;
+    char *result;
 
     /* let's start simplistic */
     memset(&startup, 0, sizeof(startup));
@@ -1238,7 +1255,7 @@ static  void    test_DebuggingFlag(void)
     startup.wShowWindow = SW_SHOWNORMAL;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, DEBUG_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
 
     /* get all startup events up to the entry point break exception */
@@ -1267,8 +1284,9 @@ static  void    test_DebuggingFlag(void)
 
     okChildInt("StartupInfoA", "cb", startup.cb);
     okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
-    ok (startup.lpTitle == NULL || !strcmp(startup.lpTitle, selfname),
-        "StartupInfoA:lpTitle expected '%s' or null, got '%s'\n", selfname, startup.lpTitle);
+    result = getChildString( "StartupInfoA", "lpTitle" );
+    ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
+        "expected '%s' or null, got '%s'\n", selfname, result );
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -1301,6 +1319,7 @@ static void test_Console(void)
     const char*         msg = "This is a std-handle inheritance test.";
     unsigned            msg_len;
     BOOL                run_tests = TRUE;
+    char *result;
 
     memset(&startup, 0, sizeof(startup));
     startup.cb = sizeof(startup);
@@ -1334,7 +1353,7 @@ static void test_Console(void)
     cpOut = GetConsoleOutputCP();
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s console", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\" console", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
 
     /* wait for child to terminate */
@@ -1378,8 +1397,9 @@ static void test_Console(void)
 
     okChildInt("StartupInfoA", "cb", startup.cb);
     okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
-    ok (startup.lpTitle == NULL || !strcmp(startup.lpTitle, selfname),
-        "StartupInfoA:lpTitle expected '%s' or null, got '%s'\n", selfname, startup.lpTitle);
+    result = getChildString( "StartupInfoA", "lpTitle" );
+    ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
+        "expected '%s' or null, got '%s'\n", selfname, result );
     okChildInt("StartupInfoA", "dwX", startup.dwX);
     okChildInt("StartupInfoA", "dwY", startup.dwY);
     okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
@@ -1447,7 +1467,7 @@ static void test_Console(void)
     startup.hStdError = hChildOutInh;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s stdhandle", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\" stdhandle", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &startup, &info), "CreateProcess\n");
     ok(CloseHandle(hChildInInh), "Closing handle\n");
     ok(CloseHandle(hChildOutInh), "Closing handle\n");
@@ -1484,7 +1504,7 @@ static  void    test_ExitCode(void)
     startup.wShowWindow = SW_SHOWNORMAL;
 
     get_file_name(resfile);
-    sprintf(buffer, "%s tests/process.c %s exit_code", selfname, resfile);
+    sprintf(buffer, "\"%s\" tests/process.c \"%s\" exit_code", selfname, resfile);
     ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info), "CreateProcess\n");
 
     /* wait for child to terminate */
@@ -1505,6 +1525,7 @@ static void test_OpenProcess(void)
     void *addr1;
     MEMORY_BASIC_INFORMATION info;
     SIZE_T dummy, read_bytes;
+    BOOL ret;
 
     /* not exported in all windows versions */
     if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
@@ -1529,8 +1550,8 @@ static void test_OpenProcess(void)
 
     read_bytes = 0xdeadbeef;
     SetLastError(0xdeadbeef);
-    ok(ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes),
-       "ReadProcessMemory error %d\n", GetLastError());
+    ret = ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes);
+    ok(ret, "ReadProcessMemory error %d\n", GetLastError());
     ok(read_bytes == sizeof(dummy), "wrong read bytes %ld\n", read_bytes);
 
     CloseHandle(hproc);
@@ -1560,8 +1581,8 @@ static void test_OpenProcess(void)
     hproc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
 
     memset(&info, 0xcc, sizeof(info));
-    ok(VirtualQueryEx(hproc, addr1, &info, sizeof(info)) == sizeof(info),
-       "VirtualQueryEx error %d\n", GetLastError());
+    read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
+    ok(read_bytes == sizeof(info), "VirtualQueryEx error %d\n", GetLastError());
 
     ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
     ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
@@ -1619,21 +1640,70 @@ static void test_GetProcessVersion(void)
     CloseHandle(pi.hThread);
 }
 
-static void test_ProcessNameA(void)
+static void test_GetProcessImageFileNameA(void)
+{
+    DWORD rc;
+    CHAR process[MAX_PATH];
+    static const char harddisk[] = "\\Device\\HarddiskVolume";
+
+    if (!pK32GetProcessImageFileNameA)
+    {
+        win_skip("K32GetProcessImageFileNameA is unavailable\n");
+        return;
+    }
+
+    /* callers must guess the buffer size */
+    SetLastError(0xdeadbeef);
+    rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), NULL, 0);
+    ok(!rc && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "K32GetProcessImageFileNameA(no buffer): returned %u, le=%u\n", rc, GetLastError());
+
+    *process = '\0';
+    rc = pK32GetProcessImageFileNameA(GetCurrentProcess(), process, sizeof(process));
+    expect_eq_d(rc, lstrlenA(process));
+    if (strncmp(process, harddisk, lstrlenA(harddisk)))
+    {
+        todo_wine win_skip("%s is probably on a network share, skipping tests\n", process);
+        return;
+    }
+
+    if (!pQueryFullProcessImageNameA)
+        win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
+    else
+    {
+        CHAR image[MAX_PATH];
+        DWORD length;
+
+        length = sizeof(image);
+        expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), PROCESS_NAME_NATIVE, image, &length));
+        expect_eq_d(length, lstrlenA(image));
+        ok(lstrcmpi(process, image) == 0, "expected '%s' to be equal to '%s'\n", process, image);
+    }
+}
+
+static void test_QueryFullProcessImageNameA(void)
 {
 #define INIT_STR "Just some words"
     DWORD length, size;
-    CHAR buf[1024];
+    CHAR buf[MAX_PATH], module[MAX_PATH];
 
     if (!pQueryFullProcessImageNameA)
     {
         win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
         return;
     }
+
+    *module = '\0';
+    SetLastError(0); /* old Windows don't reset it on success */
+    size = GetModuleFileNameA(NULL, module, sizeof(module));
+    ok(size && GetLastError() != ERROR_INSUFFICIENT_BUFFER, "GetModuleFileName failed: %u le=%u\n", size, GetLastError());
+
     /* get the buffer length without \0 terminator */
-    length = 1024;
+    length = sizeof(buf);
     expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &length));
     expect_eq_d(length, lstrlenA(buf));
+    ok((buf[0] == '\\' && buf[1] == '\\') ||
+       lstrcmpi(buf, module) == 0, "expected %s to match %s\n", buf, module);
 
     /*  when the buffer is too small
      *  - function fail with error ERROR_INSUFFICIENT_BUFFER
@@ -1657,8 +1727,8 @@ static void test_ProcessNameA(void)
     expect_eq_s(INIT_STR, buf);
 
     /* this is a difference between the ascii and the unicode version
-     * the unicode version crashes when the size is big enough to hold the result
-     * ascii version throughs an error
+     * the unicode version crashes when the size is big enough to hold
+     * the result while the ascii version throws an error
      */
     size = 1024;
     expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
@@ -1666,13 +1736,13 @@ static void test_ProcessNameA(void)
     expect_eq_d(ERROR_INVALID_PARAMETER, GetLastError());
 }
 
-static void test_ProcessName(void)
+static void test_QueryFullProcessImageNameW(void)
 {
     HANDLE hSelf;
-    WCHAR module_name[1024];
+    WCHAR module_name[1024], device[1024];
     WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
     WCHAR buf[1024];
-    DWORD size;
+    DWORD size, len;
 
     if (!pQueryFullProcessImageNameW)
     {
@@ -1717,13 +1787,6 @@ static void test_ProcessName(void)
     expect_eq_d(0, size);
     expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
 
-    /* native path */
-    size = sizeof(buf) / sizeof(buf[0]);
-    expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
-    expect_eq_d(lstrlenW(buf), size);
-    ok(buf[0] == '\\', "NT path should begin with '\\'\n");
-    todo_wine ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
-
     /* Buffer too small */
     size = lstrlenW(module_name)/2;
     SetLastError(0xdeadbeef);
@@ -1733,12 +1796,40 @@ static void test_ProcessName(void)
     expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
     expect_eq_ws_i(module_name, buf);  /* buffer not changed */
 
+
+    /* native path */
+    size = sizeof(buf) / sizeof(buf[0]);
+    expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, PROCESS_NAME_NATIVE, buf, &size));
+    expect_eq_d(lstrlenW(buf), size);
+    ok(buf[0] == '\\', "NT path should begin with '\\'\n");
+    ok(memcmp(buf, deviceW, sizeof(WCHAR)*lstrlenW(deviceW)) == 0, "NT path should begin with \\Device\n");
+
+    module_name[2] = '\0';
+    *device = '\0';
+    size = QueryDosDeviceW(module_name, device, sizeof(device)/sizeof(device[0]));
+    ok(size, "QueryDosDeviceW failed: le=%u\n", GetLastError());
+    len = lstrlenW(device);
+    ok(size >= len+2, "expected %d to be greater than %d+2 = strlen(%s)\n", size, len, wine_dbgstr_w(device));
+
+    if (size >= lstrlenW(buf))
+    {
+        ok(0, "expected %s\\ to match the start of %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
+    }
+    else
+    {
+        ok(buf[len] == '\\', "expected '%c' to be a '\\' in %s\n", buf[len], wine_dbgstr_w(module_name));
+        buf[len] = '\0';
+        ok(lstrcmpiW(device, buf) == 0, "expected %s to match %s\n", wine_dbgstr_w(device), wine_dbgstr_w(buf));
+        ok(lstrcmpiW(module_name+3, buf+len+1) == 0, "expected '%s' to match '%s'\n", wine_dbgstr_w(module_name+3), wine_dbgstr_w(buf+len+1));
+    }
+
     CloseHandle(hSelf);
 }
 
 static void test_Handles(void)
 {
     HANDLE handle = GetCurrentProcess();
+    HANDLE h2, h3;
     BOOL ret;
     DWORD code;
 
@@ -1766,6 +1857,85 @@ static void test_Handles(void)
     ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
     ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
 #endif
+
+    handle = GetStdHandle( STD_ERROR_HANDLE );
+    ok( handle != 0, "handle %p\n", handle );
+    DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &h3,
+                     0, TRUE, DUPLICATE_SAME_ACCESS );
+    SetStdHandle( STD_ERROR_HANDLE, h3 );
+    CloseHandle( (HANDLE)STD_ERROR_HANDLE );
+    h2 = GetStdHandle( STD_ERROR_HANDLE );
+    ok( h2 == 0 ||
+        broken( h2 == h3) || /* nt4, w2k */
+        broken( h2 == INVALID_HANDLE_VALUE),  /* win9x */
+        "wrong handle %p/%p\n", h2, h3 );
+    SetStdHandle( STD_ERROR_HANDLE, handle );
+}
+
+static void test_SystemInfo(void)
+{
+    SYSTEM_INFO si, nsi;
+    BOOL is_wow64;
+
+    if (!pGetNativeSystemInfo)
+    {
+        win_skip("GetNativeSystemInfo is not available\n");
+        return;
+    }
+
+    if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
+
+    GetSystemInfo(&si);
+    pGetNativeSystemInfo(&nsi);
+    if (is_wow64)
+    {
+        if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+        {
+            ok(S(U(nsi)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
+               "Expected PROCESSOR_ARCHITECTURE_AMD64, got %d\n",
+               S(U(nsi)).wProcessorArchitecture);
+            ok(nsi.dwProcessorType == PROCESSOR_AMD_X8664,
+               "Expected PROCESSOR_AMD_X8664, got %d\n",
+               nsi.dwProcessorType);
+        }
+    }
+    else
+    {
+        ok(S(U(si)).wProcessorArchitecture == S(U(nsi)).wProcessorArchitecture,
+           "Expected no difference for wProcessorArchitecture, got %d and %d\n",
+           S(U(si)).wProcessorArchitecture, S(U(nsi)).wProcessorArchitecture);
+        ok(si.dwProcessorType == nsi.dwProcessorType,
+           "Expected no difference for dwProcessorType, got %d and %d\n",
+           si.dwProcessorType, nsi.dwProcessorType);
+    }
+}
+
+static void test_RegistryQuota(void)
+{
+    BOOL ret;
+    DWORD max_quota, used_quota;
+
+    if (!pGetSystemRegistryQuota)
+    {
+        win_skip("GetSystemRegistryQuota is not available\n");
+        return;
+    }
+
+    ret = pGetSystemRegistryQuota(NULL, NULL);
+    ok(ret == TRUE,
+       "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+    ret = pGetSystemRegistryQuota(&max_quota, NULL);
+    ok(ret == TRUE,
+       "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+    ret = pGetSystemRegistryQuota(NULL, &used_quota);
+    ok(ret == TRUE,
+       "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
+
+    ret = pGetSystemRegistryQuota(&max_quota, &used_quota);
+    ok(ret == TRUE,
+       "Expected GetSystemRegistryQuota to return TRUE, got %d\n", ret);
 }
 
 START_TEST(process)
@@ -1789,9 +1959,12 @@ START_TEST(process)
     test_ExitCode();
     test_OpenProcess();
     test_GetProcessVersion();
-    test_ProcessNameA();
-    test_ProcessName();
+    test_GetProcessImageFileNameA();
+    test_QueryFullProcessImageNameA();
+    test_QueryFullProcessImageNameW();
     test_Handles();
+    test_SystemInfo();
+    test_RegistryQuota();
     /* things that can be tested:
      *  lookup:         check the way program to be executed is searched
      *  handles:        check the handle inheritance stuff (+sec options)