2007-03-06 11:59:18 +00:00
|
|
|
|
/*
|
2010-03-05 19:01:21 +00:00
|
|
|
|
* Unit test suite for process functions
|
2007-03-06 11:59:18 +00:00
|
|
|
|
*
|
|
|
|
|
* Copyright 2002 Eric Pouech
|
2008-05-09 17:35:45 +00:00
|
|
|
|
* Copyright 2006 Dmitry Timoshkov
|
2007-03-06 11:59:18 +00:00
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2008-05-09 17:35:45 +00:00
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2007-03-06 11:59:18 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
#include "ntstatus.h"
|
|
|
|
|
#define WIN32_NO_STATUS
|
2007-03-06 11:59:18 +00:00
|
|
|
|
#include "windef.h"
|
|
|
|
|
#include "winbase.h"
|
|
|
|
|
#include "winuser.h"
|
|
|
|
|
#include "wincon.h"
|
|
|
|
|
#include "winnls.h"
|
2008-12-23 20:02:47 +00:00
|
|
|
|
#include "winternl.h"
|
|
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
2014-04-18 22:50:27 +00:00
|
|
|
|
/* PROCESS_ALL_ACCESS in Vista+ PSDKs is incompatible with older Windows versions */
|
|
|
|
|
#define PROCESS_ALL_ACCESS_NT4 (PROCESS_ALL_ACCESS & ~0xf000)
|
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
|
#define expect_eq_d(expected, actual) \
|
|
|
|
|
do { \
|
|
|
|
|
int value = (actual); \
|
|
|
|
|
ok((expected) == value, "Expected " #actual " to be %d (" #expected ") is %d\n", \
|
|
|
|
|
(expected), value); \
|
|
|
|
|
} while (0)
|
2009-06-23 11:44:23 +00:00
|
|
|
|
#define expect_eq_s(expected, actual) \
|
|
|
|
|
do { \
|
|
|
|
|
LPCSTR value = (actual); \
|
|
|
|
|
ok(lstrcmpA((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
|
|
|
|
|
expected, value); \
|
|
|
|
|
} while (0)
|
2009-05-17 07:05:22 +00:00
|
|
|
|
#define expect_eq_ws_i(expected, actual) \
|
|
|
|
|
do { \
|
|
|
|
|
LPCWSTR value = (actual); \
|
|
|
|
|
ok(lstrcmpiW((expected), value) == 0, "Expected " #actual " to be L\"%s\" (" #expected ") is L\"%s\"\n", \
|
|
|
|
|
wine_dbgstr_w(expected), wine_dbgstr_w(value)); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static HINSTANCE hkernel32;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
static BOOL (WINAPI *pGetSystemRegistryQuota)(PDWORD, PDWORD);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
|
|
|
|
|
static BOOL (WINAPI *pVirtualFreeEx)(HANDLE, LPVOID, SIZE_T, DWORD);
|
2009-06-23 11:44:23 +00:00
|
|
|
|
static BOOL (WINAPI *pQueryFullProcessImageNameA)(HANDLE hProcess, DWORD dwFlags, LPSTR lpExeName, PDWORD lpdwSize);
|
2009-05-17 07:05:22 +00:00
|
|
|
|
static BOOL (WINAPI *pQueryFullProcessImageNameW)(HANDLE hProcess, DWORD dwFlags, LPWSTR lpExeName, PDWORD lpdwSize);
|
2012-05-12 19:33:11 +00:00
|
|
|
|
static DWORD (WINAPI *pK32GetProcessImageFileNameA)(HANDLE,LPSTR,DWORD);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
/* ############################### */
|
2007-03-06 11:59:18 +00:00
|
|
|
|
static char base[MAX_PATH];
|
|
|
|
|
static char selfname[MAX_PATH];
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static char* exename;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
static char resfile[MAX_PATH];
|
|
|
|
|
|
|
|
|
|
static int myARGC;
|
|
|
|
|
static char** myARGV;
|
|
|
|
|
|
|
|
|
|
/* As some environment variables get very long on Unix, we only test for
|
|
|
|
|
* the first 127 bytes.
|
|
|
|
|
* Note that increasing this value past 256 may exceed the buffer size
|
|
|
|
|
* limitations of the *Profile functions (at least on Wine).
|
|
|
|
|
*/
|
|
|
|
|
#define MAX_LISTED_ENV_VAR 128
|
|
|
|
|
|
|
|
|
|
/* ---------------- portable memory allocation thingie */
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static char memory[1024*256];
|
2007-03-06 11:59:18 +00:00
|
|
|
|
static char* memory_index = memory;
|
|
|
|
|
|
|
|
|
|
static char* grab_memory(size_t len)
|
|
|
|
|
{
|
|
|
|
|
char* ret = memory_index;
|
|
|
|
|
/* align on dword */
|
|
|
|
|
len = (len + 3) & ~3;
|
|
|
|
|
memory_index += len;
|
|
|
|
|
assert(memory_index <= memory + sizeof(memory));
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void release_memory(void)
|
|
|
|
|
{
|
|
|
|
|
memory_index = memory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------- simplistic tool to encode/decode strings (to hide \ " ' and such) */
|
|
|
|
|
|
|
|
|
|
static const char* encodeA(const char* str)
|
|
|
|
|
{
|
|
|
|
|
char* ptr;
|
|
|
|
|
size_t len,i;
|
|
|
|
|
|
|
|
|
|
if (!str) return "";
|
|
|
|
|
len = strlen(str) + 1;
|
|
|
|
|
ptr = grab_memory(len * 2 + 1);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
|
|
|
|
|
ptr[2 * len] = '\0';
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char* encodeW(const WCHAR* str)
|
|
|
|
|
{
|
|
|
|
|
char* ptr;
|
|
|
|
|
size_t len,i;
|
|
|
|
|
|
|
|
|
|
if (!str) return "";
|
|
|
|
|
len = lstrlenW(str) + 1;
|
|
|
|
|
ptr = grab_memory(len * 4 + 1);
|
|
|
|
|
assert(ptr);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
sprintf(&ptr[i * 4], "%04x", (unsigned int)(unsigned short)str[i]);
|
|
|
|
|
ptr[4 * len] = '\0';
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static unsigned decode_char(char c)
|
|
|
|
|
{
|
|
|
|
|
if (c >= '0' && c <= '9') return c - '0';
|
|
|
|
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
|
|
|
assert(c >= 'A' && c <= 'F');
|
|
|
|
|
return c - 'A' + 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char* decodeA(const char* str)
|
|
|
|
|
{
|
|
|
|
|
char* ptr;
|
|
|
|
|
size_t len,i;
|
|
|
|
|
|
|
|
|
|
len = strlen(str) / 2;
|
|
|
|
|
if (!len--) return NULL;
|
|
|
|
|
ptr = grab_memory(len + 1);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
|
|
|
|
|
ptr[len] = '\0';
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This will be needed to decode Unicode strings saved by the child process
|
|
|
|
|
* when we test Unicode functions.
|
|
|
|
|
*/
|
|
|
|
|
static WCHAR* decodeW(const char* str)
|
|
|
|
|
{
|
|
|
|
|
size_t len;
|
|
|
|
|
WCHAR* ptr;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
len = strlen(str) / 4;
|
|
|
|
|
if (!len--) return NULL;
|
|
|
|
|
ptr = (WCHAR*)grab_memory(len * 2 + 1);
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
ptr[i] = (decode_char(str[4 * i]) << 12) |
|
|
|
|
|
(decode_char(str[4 * i + 1]) << 8) |
|
|
|
|
|
(decode_char(str[4 * i + 2]) << 4) |
|
|
|
|
|
(decode_char(str[4 * i + 3]) << 0);
|
|
|
|
|
ptr[len] = '\0';
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
|
* init
|
|
|
|
|
*
|
|
|
|
|
* generates basic information like:
|
|
|
|
|
* base: absolute path to curr dir
|
|
|
|
|
* selfname: the way to reinvoke ourselves
|
2008-05-09 17:35:45 +00:00
|
|
|
|
* exename: executable without the path
|
|
|
|
|
* function-pointers, which are not implemented in all windows versions
|
2007-03-06 11:59:18 +00:00
|
|
|
|
*/
|
2014-04-18 22:50:27 +00:00
|
|
|
|
static BOOL init(void)
|
2007-03-06 11:59:18 +00:00
|
|
|
|
{
|
2008-05-09 17:35:45 +00:00
|
|
|
|
char *p;
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
myARGC = winetest_get_mainargs( &myARGV );
|
2014-04-18 22:50:27 +00:00
|
|
|
|
if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
strcpy(selfname, myARGV[0]);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
/* Strip the path of selfname */
|
|
|
|
|
if ((p = strrchr(selfname, '\\')) != NULL) exename = p + 1;
|
|
|
|
|
else exename = selfname;
|
|
|
|
|
|
|
|
|
|
if ((p = strrchr(exename, '/')) != NULL) exename = p + 1;
|
|
|
|
|
|
|
|
|
|
hkernel32 = GetModuleHandleA("kernel32");
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
pGetNativeSystemInfo = (void *) GetProcAddress(hkernel32, "GetNativeSystemInfo");
|
2011-10-03 17:58:01 +00:00
|
|
|
|
pGetSystemRegistryQuota = (void *) GetProcAddress(hkernel32, "GetSystemRegistryQuota");
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
pIsWow64Process = (void *) GetProcAddress(hkernel32, "IsWow64Process");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
pVirtualAllocEx = (void *) GetProcAddress(hkernel32, "VirtualAllocEx");
|
|
|
|
|
pVirtualFreeEx = (void *) GetProcAddress(hkernel32, "VirtualFreeEx");
|
2009-06-23 11:44:23 +00:00
|
|
|
|
pQueryFullProcessImageNameA = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameA");
|
2009-05-17 07:05:22 +00:00
|
|
|
|
pQueryFullProcessImageNameW = (void *) GetProcAddress(hkernel32, "QueryFullProcessImageNameW");
|
2012-05-12 19:33:11 +00:00
|
|
|
|
pK32GetProcessImageFileNameA = (void *) GetProcAddress(hkernel32, "K32GetProcessImageFileNameA");
|
2014-04-18 22:50:27 +00:00
|
|
|
|
return TRUE;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
|
* get_file_name
|
|
|
|
|
*
|
|
|
|
|
* generates an absolute file_name for temporary file
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void get_file_name(char* buf)
|
|
|
|
|
{
|
|
|
|
|
char path[MAX_PATH];
|
|
|
|
|
|
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
GetTempPathA(sizeof(path), path);
|
|
|
|
|
GetTempFileNameA(path, "wt", 0, buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
|
* static void childPrintf
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
static void childPrintf(HANDLE h, const char* fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list valist;
|
|
|
|
|
char buffer[1024+4*MAX_LISTED_ENV_VAR];
|
|
|
|
|
DWORD w;
|
|
|
|
|
|
|
|
|
|
va_start(valist, fmt);
|
|
|
|
|
vsprintf(buffer, fmt, valist);
|
|
|
|
|
va_end(valist);
|
|
|
|
|
WriteFile(h, buffer, strlen(buffer), &w, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************
|
|
|
|
|
* doChild
|
|
|
|
|
*
|
|
|
|
|
* output most of the information in the child process
|
|
|
|
|
*/
|
|
|
|
|
static void doChild(const char* file, const char* option)
|
|
|
|
|
{
|
|
|
|
|
STARTUPINFOA siA;
|
|
|
|
|
STARTUPINFOW siW;
|
|
|
|
|
int i;
|
2011-10-03 17:58:01 +00:00
|
|
|
|
char *ptrA, *ptrA_save;
|
|
|
|
|
WCHAR *ptrW, *ptrW_save;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
char bufA[MAX_PATH];
|
|
|
|
|
WCHAR bufW[MAX_PATH];
|
|
|
|
|
HANDLE hFile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) return;
|
|
|
|
|
|
|
|
|
|
/* output of startup info (Ansi) */
|
|
|
|
|
GetStartupInfoA(&siA);
|
|
|
|
|
childPrintf(hFile,
|
|
|
|
|
"[StartupInfoA]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
|
|
|
|
|
"dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
|
|
|
|
|
"dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
|
|
|
|
|
"dwFlags=%lu\nwShowWindow=%u\n"
|
|
|
|
|
"hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
|
|
|
|
|
siA.cb, encodeA(siA.lpDesktop), encodeA(siA.lpTitle),
|
|
|
|
|
siA.dwX, siA.dwY, siA.dwXSize, siA.dwYSize,
|
|
|
|
|
siA.dwXCountChars, siA.dwYCountChars, siA.dwFillAttribute,
|
|
|
|
|
siA.dwFlags, siA.wShowWindow,
|
2009-05-17 07:05:22 +00:00
|
|
|
|
(DWORD_PTR)siA.hStdInput, (DWORD_PTR)siA.hStdOutput, (DWORD_PTR)siA.hStdError);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* since GetStartupInfoW is only implemented in win2k,
|
|
|
|
|
* zero out before calling so we can notice the difference
|
|
|
|
|
*/
|
|
|
|
|
memset(&siW, 0, sizeof(siW));
|
|
|
|
|
GetStartupInfoW(&siW);
|
|
|
|
|
childPrintf(hFile,
|
|
|
|
|
"[StartupInfoW]\ncb=%08ld\nlpDesktop=%s\nlpTitle=%s\n"
|
|
|
|
|
"dwX=%lu\ndwY=%lu\ndwXSize=%lu\ndwYSize=%lu\n"
|
|
|
|
|
"dwXCountChars=%lu\ndwYCountChars=%lu\ndwFillAttribute=%lu\n"
|
|
|
|
|
"dwFlags=%lu\nwShowWindow=%u\n"
|
|
|
|
|
"hStdInput=%lu\nhStdOutput=%lu\nhStdError=%lu\n\n",
|
|
|
|
|
siW.cb, encodeW(siW.lpDesktop), encodeW(siW.lpTitle),
|
|
|
|
|
siW.dwX, siW.dwY, siW.dwXSize, siW.dwYSize,
|
|
|
|
|
siW.dwXCountChars, siW.dwYCountChars, siW.dwFillAttribute,
|
|
|
|
|
siW.dwFlags, siW.wShowWindow,
|
2009-05-17 07:05:22 +00:00
|
|
|
|
(DWORD_PTR)siW.hStdInput, (DWORD_PTR)siW.hStdOutput, (DWORD_PTR)siW.hStdError);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* Arguments */
|
|
|
|
|
childPrintf(hFile, "[Arguments]\nargcA=%d\n", myARGC);
|
|
|
|
|
for (i = 0; i < myARGC; i++)
|
|
|
|
|
{
|
|
|
|
|
childPrintf(hFile, "argvA%d=%s\n", i, encodeA(myARGV[i]));
|
|
|
|
|
}
|
|
|
|
|
childPrintf(hFile, "CommandLineA=%s\n", encodeA(GetCommandLineA()));
|
|
|
|
|
childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
|
|
|
|
|
|
|
|
|
|
/* output of environment (Ansi) */
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ptrA_save = ptrA = GetEnvironmentStringsA();
|
2007-03-06 11:59:18 +00:00
|
|
|
|
if (ptrA)
|
|
|
|
|
{
|
|
|
|
|
char env_var[MAX_LISTED_ENV_VAR];
|
|
|
|
|
|
|
|
|
|
childPrintf(hFile, "[EnvironmentA]\n");
|
|
|
|
|
i = 0;
|
|
|
|
|
while (*ptrA)
|
|
|
|
|
{
|
|
|
|
|
lstrcpynA(env_var, ptrA, MAX_LISTED_ENV_VAR);
|
|
|
|
|
childPrintf(hFile, "env%d=%s\n", i, encodeA(env_var));
|
|
|
|
|
i++;
|
|
|
|
|
ptrA += strlen(ptrA) + 1;
|
|
|
|
|
}
|
|
|
|
|
childPrintf(hFile, "len=%d\n\n", i);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
FreeEnvironmentStringsA(ptrA_save);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* output of environment (Unicode) */
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ptrW_save = ptrW = GetEnvironmentStringsW();
|
2007-03-06 11:59:18 +00:00
|
|
|
|
if (ptrW)
|
|
|
|
|
{
|
|
|
|
|
WCHAR env_var[MAX_LISTED_ENV_VAR];
|
|
|
|
|
|
|
|
|
|
childPrintf(hFile, "[EnvironmentW]\n");
|
|
|
|
|
i = 0;
|
|
|
|
|
while (*ptrW)
|
|
|
|
|
{
|
|
|
|
|
lstrcpynW(env_var, ptrW, MAX_LISTED_ENV_VAR - 1);
|
|
|
|
|
env_var[MAX_LISTED_ENV_VAR - 1] = '\0';
|
|
|
|
|
childPrintf(hFile, "env%d=%s\n", i, encodeW(env_var));
|
|
|
|
|
i++;
|
|
|
|
|
ptrW += lstrlenW(ptrW) + 1;
|
|
|
|
|
}
|
|
|
|
|
childPrintf(hFile, "len=%d\n\n", i);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
FreeEnvironmentStringsW(ptrW_save);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
childPrintf(hFile, "[Misc]\n");
|
|
|
|
|
if (GetCurrentDirectoryA(sizeof(bufA), bufA))
|
|
|
|
|
childPrintf(hFile, "CurrDirA=%s\n", encodeA(bufA));
|
|
|
|
|
if (GetCurrentDirectoryW(sizeof(bufW) / sizeof(bufW[0]), bufW))
|
|
|
|
|
childPrintf(hFile, "CurrDirW=%s\n", encodeW(bufW));
|
|
|
|
|
childPrintf(hFile, "\n");
|
|
|
|
|
|
|
|
|
|
if (option && strcmp(option, "console") == 0)
|
|
|
|
|
{
|
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
|
|
|
|
HANDLE hConIn = GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
|
HANDLE hConOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
DWORD modeIn, modeOut;
|
|
|
|
|
|
|
|
|
|
childPrintf(hFile, "[Console]\n");
|
|
|
|
|
if (GetConsoleScreenBufferInfo(hConOut, &sbi))
|
|
|
|
|
{
|
|
|
|
|
childPrintf(hFile, "SizeX=%d\nSizeY=%d\nCursorX=%d\nCursorY=%d\nAttributes=%d\n",
|
|
|
|
|
sbi.dwSize.X, sbi.dwSize.Y, sbi.dwCursorPosition.X, sbi.dwCursorPosition.Y, sbi.wAttributes);
|
|
|
|
|
childPrintf(hFile, "winLeft=%d\nwinTop=%d\nwinRight=%d\nwinBottom=%d\n",
|
|
|
|
|
sbi.srWindow.Left, sbi.srWindow.Top, sbi.srWindow.Right, sbi.srWindow.Bottom);
|
|
|
|
|
childPrintf(hFile, "maxWinWidth=%d\nmaxWinHeight=%d\n",
|
|
|
|
|
sbi.dwMaximumWindowSize.X, sbi.dwMaximumWindowSize.Y);
|
|
|
|
|
}
|
|
|
|
|
childPrintf(hFile, "InputCP=%d\nOutputCP=%d\n",
|
|
|
|
|
GetConsoleCP(), GetConsoleOutputCP());
|
|
|
|
|
if (GetConsoleMode(hConIn, &modeIn))
|
|
|
|
|
childPrintf(hFile, "InputMode=%ld\n", modeIn);
|
|
|
|
|
if (GetConsoleMode(hConOut, &modeOut))
|
|
|
|
|
childPrintf(hFile, "OutputMode=%ld\n", modeOut);
|
|
|
|
|
|
|
|
|
|
/* now that we have written all relevant information, let's change it */
|
2008-12-23 20:02:47 +00:00
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = SetConsoleCP(1252);
|
|
|
|
|
if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
|
|
|
{
|
2009-06-06 16:10:47 +00:00
|
|
|
|
win_skip("Setting the codepage is not implemented\n");
|
2008-12-23 20:02:47 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ok(ret, "Setting CP\n");
|
|
|
|
|
ok(SetConsoleOutputCP(1252), "Setting SB CP\n");
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ret = SetConsoleMode(hConIn, modeIn ^ 1);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok( ret, "Setting mode (%d)\n", GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ret = SetConsoleMode(hConOut, modeOut ^ 1);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok( ret, "Setting mode (%d)\n", GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
sbi.dwCursorPosition.X ^= 1;
|
|
|
|
|
sbi.dwCursorPosition.Y ^= 1;
|
|
|
|
|
ret = SetConsoleCursorPosition(hConOut, sbi.dwCursorPosition);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok( ret, "Setting cursor position (%d)\n", GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
if (option && strcmp(option, "stdhandle") == 0)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
|
|
|
|
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
|
|
|
|
|
|
if (hStdIn != INVALID_HANDLE_VALUE || hStdOut != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
char buf[1024];
|
|
|
|
|
DWORD r, w;
|
|
|
|
|
|
|
|
|
|
ok(ReadFile(hStdIn, buf, sizeof(buf), &r, NULL) && r > 0, "Reading message from input pipe\n");
|
|
|
|
|
childPrintf(hFile, "[StdHandle]\nmsg=%s\n\n", encodeA(buf));
|
|
|
|
|
ok(WriteFile(hStdOut, buf, r, &w, NULL) && w == r, "Writing message to output pipe\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (option && strcmp(option, "exit_code") == 0)
|
|
|
|
|
{
|
|
|
|
|
childPrintf(hFile, "[ExitCode]\nvalue=%d\n\n", 123);
|
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
ExitProcess(123);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static char* getChildString(const char* sect, const char* key)
|
|
|
|
|
{
|
|
|
|
|
char buf[1024+4*MAX_LISTED_ENV_VAR];
|
|
|
|
|
char* ret;
|
|
|
|
|
|
|
|
|
|
GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
|
|
|
|
|
if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
|
|
|
|
|
assert(!(strlen(buf) & 1));
|
|
|
|
|
ret = decodeA(buf);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
static WCHAR* getChildStringW(const char* sect, const char* key)
|
|
|
|
|
{
|
|
|
|
|
char buf[1024+4*MAX_LISTED_ENV_VAR];
|
|
|
|
|
WCHAR* ret;
|
|
|
|
|
|
|
|
|
|
GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), resfile);
|
|
|
|
|
if (buf[0] == '\0' || (buf[0] == '-' && buf[1] == '\0')) return NULL;
|
|
|
|
|
assert(!(strlen(buf) & 1));
|
|
|
|
|
ret = decodeW(buf);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* FIXME: this may be moved to the wtmain.c file, because it may be needed by
|
|
|
|
|
* others... (windows uses stricmp while Un*x uses strcasecmp...)
|
|
|
|
|
*/
|
|
|
|
|
static int wtstrcasecmp(const char* p1, const char* p2)
|
|
|
|
|
{
|
|
|
|
|
char c1, c2;
|
|
|
|
|
|
|
|
|
|
c1 = c2 = '@';
|
|
|
|
|
while (c1 == c2 && c1)
|
|
|
|
|
{
|
|
|
|
|
c1 = *p1++; c2 = *p2++;
|
|
|
|
|
if (c1 != c2)
|
|
|
|
|
{
|
|
|
|
|
c1 = toupper(c1); c2 = toupper(c2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return c1 - c2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int strCmp(const char* s1, const char* s2, BOOL sensitive)
|
|
|
|
|
{
|
|
|
|
|
if (!s1 && !s2) return 0;
|
|
|
|
|
if (!s2) return -1;
|
|
|
|
|
if (!s1) return 1;
|
|
|
|
|
return (sensitive) ? strcmp(s1, s2) : wtstrcasecmp(s1, s2);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static void ok_child_string( int line, const char *sect, const char *key,
|
|
|
|
|
const char *expect, int sensitive )
|
|
|
|
|
{
|
|
|
|
|
char* result = getChildString( sect, key );
|
|
|
|
|
ok_(__FILE__, line)( strCmp(result, expect, sensitive) == 0, "%s:%s expected '%s', got '%s'\n",
|
|
|
|
|
sect, key, expect ? expect : "(null)", result );
|
|
|
|
|
}
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
static void ok_child_stringWA( int line, const char *sect, const char *key,
|
|
|
|
|
const char *expect, int sensitive )
|
|
|
|
|
{
|
|
|
|
|
WCHAR* expectW;
|
|
|
|
|
CHAR* resultA;
|
|
|
|
|
DWORD len;
|
|
|
|
|
WCHAR* result = getChildStringW( sect, key );
|
|
|
|
|
|
|
|
|
|
len = MultiByteToWideChar( CP_ACP, 0, expect, -1, NULL, 0);
|
|
|
|
|
expectW = HeapAlloc(GetProcessHeap(),0,len*sizeof(WCHAR));
|
|
|
|
|
MultiByteToWideChar( CP_ACP, 0, expect, -1, expectW, len);
|
|
|
|
|
|
|
|
|
|
len = WideCharToMultiByte( CP_ACP, 0, result, -1, NULL, 0, NULL, NULL);
|
|
|
|
|
resultA = HeapAlloc(GetProcessHeap(),0,len*sizeof(CHAR));
|
|
|
|
|
WideCharToMultiByte( CP_ACP, 0, result, -1, resultA, len, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (sensitive)
|
|
|
|
|
ok_(__FILE__, line)( lstrcmpW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
|
|
|
|
|
sect, key, expect ? expect : "(null)", resultA );
|
|
|
|
|
else
|
|
|
|
|
ok_(__FILE__, line)( lstrcmpiW(result, expectW) == 0, "%s:%s expected '%s', got '%s'\n",
|
|
|
|
|
sect, key, expect ? expect : "(null)", resultA );
|
|
|
|
|
HeapFree(GetProcessHeap(),0,expectW);
|
|
|
|
|
HeapFree(GetProcessHeap(),0,resultA);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
#define okChildString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 1 )
|
|
|
|
|
#define okChildIString(sect, key, expect) ok_child_string(__LINE__, (sect), (key), (expect), 0 )
|
2008-12-23 20:02:47 +00:00
|
|
|
|
#define okChildStringWA(sect, key, expect) ok_child_stringWA(__LINE__, (sect), (key), (expect), 1 )
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* using !expect ensures that the test will fail if the sect/key isn't present
|
|
|
|
|
* in result file
|
|
|
|
|
*/
|
|
|
|
|
#define okChildInt(sect, key, expect) \
|
|
|
|
|
do { \
|
|
|
|
|
UINT result = GetPrivateProfileIntA((sect), (key), !(expect), resfile); \
|
2009-05-17 07:05:22 +00:00
|
|
|
|
ok(result == expect, "%s:%s expected %u, but got %u\n", (sect), (key), (UINT)(expect), result); \
|
2007-03-06 11:59:18 +00:00
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
static void test_Startup(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup,si;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
char *result;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static CHAR title[] = "I'm the title string",
|
2008-12-23 20:02:47 +00:00
|
|
|
|
desktop[] = "winsta0\\default",
|
2008-05-09 17:35:45 +00:00
|
|
|
|
empty[] = "";
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* let's start simplistic */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
GetStartupInfoA(&si);
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
|
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpTitle = title;
|
|
|
|
|
startup.lpDesktop = desktop;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
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);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpTitle = title;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.lpDesktop = NULL;
|
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", si.lpDesktop);
|
|
|
|
|
okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
|
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpTitle = title;
|
|
|
|
|
startup.lpDesktop = empty;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
|
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
startup.lpTitle = NULL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpDesktop = desktop;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
result = getChildString( "StartupInfoA", "lpTitle" );
|
|
|
|
|
ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
|
|
|
|
|
"expected '%s' or null, got '%s'\n", selfname, result );
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpTitle = empty;
|
|
|
|
|
startup.lpDesktop = desktop;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* not so simplistic now */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
startup.lpTitle = empty;
|
|
|
|
|
startup.lpDesktop = empty;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
startup.dwXCountChars = 0x12121212;
|
|
|
|
|
startup.dwYCountChars = 0x23232323;
|
|
|
|
|
startup.dwX = 0x34343434;
|
|
|
|
|
startup.dwY = 0x45454545;
|
|
|
|
|
startup.dwXSize = 0x56565656;
|
|
|
|
|
startup.dwYSize = 0x67676767;
|
|
|
|
|
startup.dwFillAttribute = 0xA55A;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", startup.lpDesktop);
|
|
|
|
|
okChildString("StartupInfoA", "lpTitle", startup.lpTitle);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* TODO: test for A/W and W/A and W/W */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_CommandLine(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH], fullpath[MAX_PATH], *lpFilePart, *p;
|
2008-12-23 20:02:47 +00:00
|
|
|
|
char buffer2[MAX_PATH];
|
2007-03-06 11:59:18 +00:00
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
BOOL ret;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
/* the basics */
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"C:\\Program Files\\my nice app.exe\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("Arguments", "argcA", 4);
|
|
|
|
|
okChildString("Arguments", "argvA3", "C:\\Program Files\\my nice app.exe");
|
|
|
|
|
okChildString("Arguments", "argvA4", NULL);
|
|
|
|
|
okChildString("Arguments", "CommandLineA", buffer);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
2011-10-03 17:58:01 +00:00
|
|
|
|
/* from Fran<61>ois */
|
2007-03-06 11:59:18 +00:00
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
okChildInt("Arguments", "argcA", 6);
|
|
|
|
|
okChildString("Arguments", "argvA3", "a\"b\\");
|
|
|
|
|
okChildString("Arguments", "argvA4", "c\"");
|
|
|
|
|
okChildString("Arguments", "argvA5", "d");
|
|
|
|
|
okChildString("Arguments", "argvA6", NULL);
|
|
|
|
|
okChildString("Arguments", "CommandLineA", buffer);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
/* Test for Bug1330 to show that XP doesn't change '/' to '\\' in argv[0]*/
|
|
|
|
|
get_file_name(resfile);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
/* Use exename to avoid buffer containing things like 'C:' */
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "./%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* 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);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
sprintf(buffer, "./%s", exename);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildString("Arguments", "argvA0", buffer);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
/* Use exename to avoid buffer containing things like 'C:' */
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, ".\\%s tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", exename, resfile);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* 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);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
sprintf(buffer, ".\\%s", exename);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildString("Arguments", "argvA0", buffer);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
get_file_name(resfile);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
assert ( lpFilePart != 0);
|
|
|
|
|
*(lpFilePart -1 ) = 0;
|
|
|
|
|
p = strrchr(fullpath, '\\');
|
2008-05-09 17:35:45 +00:00
|
|
|
|
/* Use exename to avoid buffer containing things like 'C:' */
|
2011-10-03 17:58:01 +00:00
|
|
|
|
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);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* 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);
|
2008-12-23 20:02:47 +00:00
|
|
|
|
if (p) sprintf(buffer, "..%s/%s", p, exename);
|
|
|
|
|
else sprintf(buffer, "./%s", exename);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildString("Arguments", "argvA0", buffer);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
2008-12-23 20:02:47 +00:00
|
|
|
|
|
|
|
|
|
/* Using AppName */
|
|
|
|
|
get_file_name(resfile);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
GetFullPathNameA(selfname, MAX_PATH, fullpath, &lpFilePart);
|
2008-12-23 20:02:47 +00:00
|
|
|
|
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);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer2, "dummy tests/process.c \"%s\" \"a\\\"b\\\\\" c\\\" d", resfile);
|
2008-12-23 20:02:47 +00:00
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(ret, "CreateProcess (%s) failed : %d\n", buffer, GetLastError());
|
|
|
|
|
/* 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);
|
|
|
|
|
sprintf(buffer, "tests/process.c %s", resfile);
|
|
|
|
|
okChildString("Arguments", "argvA0", "dummy");
|
|
|
|
|
okChildString("Arguments", "CommandLineA", buffer2);
|
|
|
|
|
okChildStringWA("Arguments", "CommandLineW", buffer2);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
2009-06-06 16:10:47 +00:00
|
|
|
|
|
|
|
|
|
if (0) /* Test crashes on NT-based Windows. */
|
|
|
|
|
{
|
|
|
|
|
/* Test NULL application name and command line parameters. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
|
|
|
|
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buffer[0] = '\0';
|
|
|
|
|
|
|
|
|
|
/* Test empty application name parameter. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(buffer, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_PATH_NOT_FOUND ||
|
|
|
|
|
broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
|
|
|
|
|
broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
|
|
|
|
|
"Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
buffer2[0] = '\0';
|
|
|
|
|
|
|
|
|
|
/* Test empty application name and command line parameters. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(buffer, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_PATH_NOT_FOUND ||
|
|
|
|
|
broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* Win9x/WinME */ ||
|
|
|
|
|
broken(GetLastError() == ERROR_ACCESS_DENIED) /* Win98 */,
|
|
|
|
|
"Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* Test empty command line parameter. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
|
|
|
|
|
GetLastError() == ERROR_PATH_NOT_FOUND /* NT4 */ ||
|
2009-10-25 16:21:40 +00:00
|
|
|
|
GetLastError() == ERROR_BAD_PATHNAME /* Win98 */ ||
|
|
|
|
|
GetLastError() == ERROR_INVALID_PARAMETER /* Win7 */,
|
2009-06-06 16:10:47 +00:00
|
|
|
|
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
strcpy(buffer, "doesnotexist.exe");
|
|
|
|
|
strcpy(buffer2, "does not exist.exe");
|
|
|
|
|
|
|
|
|
|
/* Test nonexistent application name. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(buffer, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(buffer2, NULL, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* Test nonexistent command line parameter. */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = CreateProcessA(NULL, buffer2, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info);
|
|
|
|
|
ok(!ret, "CreateProcessA unexpectedly succeeded\n");
|
|
|
|
|
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_Directory(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup;
|
|
|
|
|
char windir[MAX_PATH];
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static CHAR cmdline[] = "winver.exe";
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
/* the basics */
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
GetWindowsDirectoryA( windir, sizeof(windir) );
|
|
|
|
|
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, windir, &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);
|
|
|
|
|
|
|
|
|
|
okChildIString("Misc", "CurrDirA", windir);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
/* search PATH for the exe if directory is NULL */
|
|
|
|
|
ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n");
|
|
|
|
|
ok(TerminateProcess(info.hProcess, 0), "Child process termination\n");
|
|
|
|
|
|
|
|
|
|
/* if any directory is provided, don't search PATH, error on bad directory */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
|
ok(!CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L,
|
|
|
|
|
NULL, "non\\existent\\directory", &startup, &info), "CreateProcess\n");
|
|
|
|
|
ok(GetLastError() == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", GetLastError());
|
|
|
|
|
ok(!TerminateProcess(info.hProcess, 0), "Child process should not exist\n");
|
2007-03-06 11:59:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL is_str_env_drive_dir(const char* str)
|
|
|
|
|
{
|
|
|
|
|
return str[0] == '=' && str[1] >= 'A' && str[1] <= 'Z' && str[2] == ':' &&
|
|
|
|
|
str[3] == '=' && str[4] == str[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* compared expected child's environment (in gesA) from actual
|
|
|
|
|
* environment our child got
|
|
|
|
|
*/
|
|
|
|
|
static void cmpEnvironment(const char* gesA)
|
|
|
|
|
{
|
|
|
|
|
int i, clen;
|
|
|
|
|
const char* ptrA;
|
|
|
|
|
char* res;
|
|
|
|
|
char key[32];
|
|
|
|
|
BOOL found;
|
|
|
|
|
|
|
|
|
|
clen = GetPrivateProfileIntA("EnvironmentA", "len", 0, resfile);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* now look each parent env in child */
|
|
|
|
|
if ((ptrA = gesA) != NULL)
|
|
|
|
|
{
|
|
|
|
|
while (*ptrA)
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < clen; i++)
|
|
|
|
|
{
|
|
|
|
|
sprintf(key, "env%d", i);
|
|
|
|
|
res = getChildString("EnvironmentA", key);
|
|
|
|
|
if (strncmp(ptrA, res, MAX_LISTED_ENV_VAR - 1) == 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
found = i < clen;
|
|
|
|
|
ok(found, "Parent-env string %s isn't in child process\n", ptrA);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ptrA += strlen(ptrA) + 1;
|
|
|
|
|
release_memory();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* and each child env in parent */
|
|
|
|
|
for (i = 0; i < clen; i++)
|
|
|
|
|
{
|
|
|
|
|
sprintf(key, "env%d", i);
|
|
|
|
|
res = getChildString("EnvironmentA", key);
|
|
|
|
|
if ((ptrA = gesA) != NULL)
|
|
|
|
|
{
|
|
|
|
|
while (*ptrA)
|
|
|
|
|
{
|
|
|
|
|
if (strncmp(res, ptrA, MAX_LISTED_ENV_VAR - 1) == 0)
|
|
|
|
|
break;
|
|
|
|
|
ptrA += strlen(ptrA) + 1;
|
|
|
|
|
}
|
|
|
|
|
if (!*ptrA) ptrA = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_str_env_drive_dir(res))
|
|
|
|
|
{
|
|
|
|
|
found = ptrA != NULL;
|
|
|
|
|
ok(found, "Child-env string %s isn't in parent process\n", res);
|
|
|
|
|
}
|
|
|
|
|
/* else => should also test we get the right per drive default directory here... */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_Environment(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup;
|
2011-10-03 17:58:01 +00:00
|
|
|
|
char *child_env;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
int child_env_len;
|
2011-10-03 17:58:01 +00:00
|
|
|
|
char *ptr;
|
|
|
|
|
char *ptr2;
|
|
|
|
|
char *env;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
int slen;
|
|
|
|
|
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
/* the basics */
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
|
|
|
|
|
env = GetEnvironmentStringsA();
|
|
|
|
|
cmpEnvironment(env);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
/* the basics */
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
child_env_len = 0;
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ptr = env;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
while(*ptr)
|
|
|
|
|
{
|
|
|
|
|
slen = strlen(ptr)+1;
|
|
|
|
|
child_env_len += slen;
|
|
|
|
|
ptr += slen;
|
|
|
|
|
}
|
|
|
|
|
/* Add space for additional environment variables */
|
|
|
|
|
child_env_len += 256;
|
|
|
|
|
child_env = HeapAlloc(GetProcessHeap(), 0, child_env_len);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ptr = child_env;
|
|
|
|
|
sprintf(ptr, "=%c:=%s", 'C', "C:\\FOO\\BAR");
|
|
|
|
|
ptr += strlen(ptr) + 1;
|
|
|
|
|
strcpy(ptr, "PATH=C:\\WINDOWS;C:\\WINDOWS\\SYSTEM;C:\\MY\\OWN\\DIR");
|
|
|
|
|
ptr += strlen(ptr) + 1;
|
|
|
|
|
strcpy(ptr, "FOO=BAR");
|
|
|
|
|
ptr += strlen(ptr) + 1;
|
|
|
|
|
strcpy(ptr, "BAR=FOOBAR");
|
|
|
|
|
ptr += strlen(ptr) + 1;
|
|
|
|
|
/* copy all existing variables except:
|
|
|
|
|
* - WINELOADER
|
|
|
|
|
* - PATH (already set above)
|
|
|
|
|
* - the directory definitions (=[A-Z]:=)
|
|
|
|
|
*/
|
2011-10-03 17:58:01 +00:00
|
|
|
|
for (ptr2 = env; *ptr2; ptr2 += strlen(ptr2) + 1)
|
2007-03-06 11:59:18 +00:00
|
|
|
|
{
|
2011-10-03 17:58:01 +00:00
|
|
|
|
if (strncmp(ptr2, "PATH=", 5) != 0 &&
|
|
|
|
|
strncmp(ptr2, "WINELOADER=", 11) != 0 &&
|
|
|
|
|
!is_str_env_drive_dir(ptr2))
|
2007-03-06 11:59:18 +00:00
|
|
|
|
{
|
2011-10-03 17:58:01 +00:00
|
|
|
|
strcpy(ptr, ptr2);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ptr += strlen(ptr) + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, child_env, 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);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
cmpEnvironment(child_env);
|
|
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, child_env);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
FreeEnvironmentStringsA(env);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_SuspendFlag(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup, us;
|
|
|
|
|
DWORD exit_status;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
char *result;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* let's start simplistic */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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");
|
|
|
|
|
Sleep(8000);
|
|
|
|
|
ok(GetExitCodeThread(info.hThread, &exit_status) && exit_status == STILL_ACTIVE, "thread still running\n");
|
|
|
|
|
ok(ResumeThread(info.hThread) == 1, "Resuming thread\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);
|
|
|
|
|
|
|
|
|
|
GetStartupInfoA(&us);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
result = getChildString( "StartupInfoA", "lpTitle" );
|
|
|
|
|
ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
|
|
|
|
|
"expected '%s' or null, got '%s'\n", selfname, result );
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_DebuggingFlag(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
2009-08-22 16:42:11 +00:00
|
|
|
|
void *processbase = NULL;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup, us;
|
|
|
|
|
DEBUG_EVENT de;
|
|
|
|
|
unsigned dbg = 0;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
char *result;
|
2007-03-06 11:59:18 +00:00
|
|
|
|
|
|
|
|
|
/* let's start simplistic */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\"", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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 */
|
2008-05-09 17:35:45 +00:00
|
|
|
|
do
|
2007-03-06 11:59:18 +00:00
|
|
|
|
{
|
|
|
|
|
ok(WaitForDebugEvent(&de, INFINITE), "reading debug event\n");
|
|
|
|
|
ContinueDebugEvent(de.dwProcessId, de.dwThreadId, DBG_CONTINUE);
|
2009-08-22 16:42:11 +00:00
|
|
|
|
if (!dbg)
|
|
|
|
|
{
|
|
|
|
|
ok(de.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT,
|
|
|
|
|
"first event: %d\n", de.dwDebugEventCode);
|
|
|
|
|
processbase = de.u.CreateProcessInfo.lpBaseOfImage;
|
|
|
|
|
}
|
2007-03-06 11:59:18 +00:00
|
|
|
|
if (de.dwDebugEventCode != EXCEPTION_DEBUG_EVENT) dbg++;
|
2009-08-22 16:42:11 +00:00
|
|
|
|
ok(de.dwDebugEventCode != LOAD_DLL_DEBUG_EVENT ||
|
|
|
|
|
de.u.LoadDll.lpBaseOfDll != processbase, "got LOAD_DLL for main module\n");
|
2007-03-06 11:59:18 +00:00
|
|
|
|
} while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
|
|
|
|
|
|
|
|
|
|
ok(dbg, "I have seen a debug event\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);
|
|
|
|
|
|
|
|
|
|
GetStartupInfoA(&us);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
result = getChildString( "StartupInfoA", "lpTitle" );
|
|
|
|
|
ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
|
|
|
|
|
"expected '%s' or null, got '%s'\n", selfname, result );
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL is_console(HANDLE h)
|
|
|
|
|
{
|
|
|
|
|
return h != INVALID_HANDLE_VALUE && ((ULONG_PTR)h & 3) == 3;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_Console(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup, us;
|
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFO sbi, sbiC;
|
|
|
|
|
DWORD modeIn, modeOut, modeInC, modeOutC;
|
|
|
|
|
DWORD cpIn, cpOut, cpInC, cpOutC;
|
|
|
|
|
DWORD w;
|
|
|
|
|
HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
|
|
|
|
|
const char* msg = "This is a std-handle inheritance test.";
|
|
|
|
|
unsigned msg_len;
|
2008-12-23 20:02:47 +00:00
|
|
|
|
BOOL run_tests = TRUE;
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
char *result;
|
2009-01-12 12:29:53 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
sa.nLength = sizeof(sa);
|
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
|
|
|
|
|
|
startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
|
|
|
|
|
startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
|
|
|
|
|
|
|
|
|
|
/* first, we need to be sure we're attached to a console */
|
|
|
|
|
if (!is_console(startup.hStdInput) || !is_console(startup.hStdOutput))
|
|
|
|
|
{
|
|
|
|
|
/* we're not attached to a console, let's do it */
|
|
|
|
|
AllocConsole();
|
|
|
|
|
startup.hStdInput = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
|
|
|
|
|
startup.hStdOutput = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
/* now verify everything's ok */
|
|
|
|
|
ok(startup.hStdInput != INVALID_HANDLE_VALUE, "Opening ConIn\n");
|
|
|
|
|
ok(startup.hStdOutput != INVALID_HANDLE_VALUE, "Opening ConOut\n");
|
|
|
|
|
startup.hStdError = startup.hStdOutput;
|
|
|
|
|
|
|
|
|
|
ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbi), "Getting sb info\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(GetConsoleMode(startup.hStdInput, &modeIn) &&
|
2007-03-06 11:59:18 +00:00
|
|
|
|
GetConsoleMode(startup.hStdOutput, &modeOut), "Getting console modes\n");
|
|
|
|
|
cpIn = GetConsoleCP();
|
|
|
|
|
cpOut = GetConsoleOutputCP();
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\" console", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(CreateProcessA(NULL, buffer, NULL, NULL, TRUE, 0, 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);
|
|
|
|
|
|
|
|
|
|
/* now get the modification the child has made, and resets parents expected values */
|
|
|
|
|
ok(GetConsoleScreenBufferInfo(startup.hStdOutput, &sbiC), "Getting sb info\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(GetConsoleMode(startup.hStdInput, &modeInC) &&
|
2007-03-06 11:59:18 +00:00
|
|
|
|
GetConsoleMode(startup.hStdOutput, &modeOutC), "Getting console modes\n");
|
|
|
|
|
|
|
|
|
|
SetConsoleMode(startup.hStdInput, modeIn);
|
|
|
|
|
SetConsoleMode(startup.hStdOutput, modeOut);
|
|
|
|
|
|
|
|
|
|
cpInC = GetConsoleCP();
|
|
|
|
|
cpOutC = GetConsoleOutputCP();
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
/* Try to set invalid CP */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ok(!SetConsoleCP(0), "Shouldn't succeed\n");
|
2008-12-23 20:02:47 +00:00
|
|
|
|
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
|
|
|
|
|
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
|
2008-05-09 17:35:45 +00:00
|
|
|
|
"GetLastError: expecting %u got %u\n",
|
|
|
|
|
ERROR_INVALID_PARAMETER, GetLastError());
|
2008-12-23 20:02:47 +00:00
|
|
|
|
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
|
|
|
run_tests = FALSE;
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ok(!SetConsoleOutputCP(0), "Shouldn't succeed\n");
|
2008-12-23 20:02:47 +00:00
|
|
|
|
ok(GetLastError()==ERROR_INVALID_PARAMETER ||
|
|
|
|
|
broken(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), /* win9x */
|
2008-05-09 17:35:45 +00:00
|
|
|
|
"GetLastError: expecting %u got %u\n",
|
|
|
|
|
ERROR_INVALID_PARAMETER, GetLastError());
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
SetConsoleCP(cpIn);
|
|
|
|
|
SetConsoleOutputCP(cpOut);
|
|
|
|
|
|
|
|
|
|
GetStartupInfoA(&us);
|
|
|
|
|
|
|
|
|
|
okChildInt("StartupInfoA", "cb", startup.cb);
|
|
|
|
|
okChildString("StartupInfoA", "lpDesktop", us.lpDesktop);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
result = getChildString( "StartupInfoA", "lpTitle" );
|
|
|
|
|
ok( broken(!result) || (result && !strCmp( result, selfname, 0 )),
|
|
|
|
|
"expected '%s' or null, got '%s'\n", selfname, result );
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("StartupInfoA", "dwX", startup.dwX);
|
|
|
|
|
okChildInt("StartupInfoA", "dwY", startup.dwY);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXSize", startup.dwXSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYSize", startup.dwYSize);
|
|
|
|
|
okChildInt("StartupInfoA", "dwXCountChars", startup.dwXCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwYCountChars", startup.dwYCountChars);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFillAttribute", startup.dwFillAttribute);
|
|
|
|
|
okChildInt("StartupInfoA", "dwFlags", startup.dwFlags);
|
|
|
|
|
okChildInt("StartupInfoA", "wShowWindow", startup.wShowWindow);
|
|
|
|
|
|
|
|
|
|
/* check child correctly inherited the console */
|
2009-05-17 07:05:22 +00:00
|
|
|
|
okChildInt("StartupInfoA", "hStdInput", (DWORD_PTR)startup.hStdInput);
|
|
|
|
|
okChildInt("StartupInfoA", "hStdOutput", (DWORD_PTR)startup.hStdOutput);
|
|
|
|
|
okChildInt("StartupInfoA", "hStdError", (DWORD_PTR)startup.hStdError);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
okChildInt("Console", "SizeX", (DWORD)sbi.dwSize.X);
|
|
|
|
|
okChildInt("Console", "SizeY", (DWORD)sbi.dwSize.Y);
|
|
|
|
|
okChildInt("Console", "CursorX", (DWORD)sbi.dwCursorPosition.X);
|
|
|
|
|
okChildInt("Console", "CursorY", (DWORD)sbi.dwCursorPosition.Y);
|
|
|
|
|
okChildInt("Console", "Attributes", sbi.wAttributes);
|
|
|
|
|
okChildInt("Console", "winLeft", (DWORD)sbi.srWindow.Left);
|
|
|
|
|
okChildInt("Console", "winTop", (DWORD)sbi.srWindow.Top);
|
|
|
|
|
okChildInt("Console", "winRight", (DWORD)sbi.srWindow.Right);
|
|
|
|
|
okChildInt("Console", "winBottom", (DWORD)sbi.srWindow.Bottom);
|
|
|
|
|
okChildInt("Console", "maxWinWidth", (DWORD)sbi.dwMaximumWindowSize.X);
|
|
|
|
|
okChildInt("Console", "maxWinHeight", (DWORD)sbi.dwMaximumWindowSize.Y);
|
|
|
|
|
okChildInt("Console", "InputCP", cpIn);
|
|
|
|
|
okChildInt("Console", "OutputCP", cpOut);
|
|
|
|
|
okChildInt("Console", "InputMode", modeIn);
|
|
|
|
|
okChildInt("Console", "OutputMode", modeOut);
|
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
if (run_tests)
|
|
|
|
|
{
|
|
|
|
|
ok(cpInC == 1252, "Wrong console CP (expected 1252 got %d/%d)\n", cpInC, cpIn);
|
|
|
|
|
ok(cpOutC == 1252, "Wrong console-SB CP (expected 1252 got %d/%d)\n", cpOutC, cpOut);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
win_skip("Setting the codepage is not implemented\n");
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(modeInC == (modeIn ^ 1), "Wrong console mode\n");
|
|
|
|
|
ok(modeOutC == (modeOut ^ 1), "Wrong console-SB mode\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
trace("cursor position(X): %d/%d\n",sbi.dwCursorPosition.X, sbiC.dwCursorPosition.X);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(sbiC.dwCursorPosition.Y == (sbi.dwCursorPosition.Y ^ 1), "Wrong cursor position\n");
|
|
|
|
|
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
|
|
|
|
|
ok(CreatePipe(&hParentIn, &hChildOut, NULL, 0), "Creating parent-input pipe\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(DuplicateHandle(GetCurrentProcess(), hChildOut, GetCurrentProcess(),
|
2007-03-06 11:59:18 +00:00
|
|
|
|
&hChildOutInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
|
|
|
|
|
"Duplicating as inheritable child-output pipe\n");
|
|
|
|
|
CloseHandle(hChildOut);
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(CreatePipe(&hChildIn, &hParentOut, NULL, 0), "Creating parent-output pipe\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(DuplicateHandle(GetCurrentProcess(), hChildIn, GetCurrentProcess(),
|
2007-03-06 11:59:18 +00:00
|
|
|
|
&hChildInInh, 0, TRUE, DUPLICATE_SAME_ACCESS),
|
|
|
|
|
"Duplicating as inheritable child-input pipe\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
CloseHandle(hChildIn);
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
startup.hStdInput = hChildInInh;
|
|
|
|
|
startup.hStdOutput = hChildOutInh;
|
|
|
|
|
startup.hStdError = hChildOutInh;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\" stdhandle", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
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");
|
|
|
|
|
|
|
|
|
|
msg_len = strlen(msg) + 1;
|
|
|
|
|
ok(WriteFile(hParentOut, msg, msg_len, &w, NULL), "Writing to child\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(w == msg_len, "Should have written %u bytes, actually wrote %u\n", msg_len, w);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
|
ok(ReadFile(hParentIn, buffer, sizeof(buffer), &w, NULL), "Reading from child\n");
|
|
|
|
|
ok(strcmp(buffer, msg) == 0, "Should have received '%s'\n", msg);
|
|
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
|
okChildString("StdHandle", "msg", msg);
|
|
|
|
|
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_ExitCode(void)
|
|
|
|
|
{
|
|
|
|
|
char buffer[MAX_PATH];
|
|
|
|
|
PROCESS_INFORMATION info;
|
|
|
|
|
STARTUPINFOA startup;
|
|
|
|
|
DWORD code;
|
|
|
|
|
|
|
|
|
|
/* let's start simplistic */
|
|
|
|
|
memset(&startup, 0, sizeof(startup));
|
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
|
|
|
|
|
|
get_file_name(resfile);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
sprintf(buffer, "\"%s\" tests/process.c \"%s\" exit_code", selfname, resfile);
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, 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);
|
|
|
|
|
|
|
|
|
|
ok(GetExitCodeProcess(info.hProcess, &code), "Getting exit code\n");
|
|
|
|
|
okChildInt("ExitCode", "value", code);
|
|
|
|
|
|
|
|
|
|
release_memory();
|
|
|
|
|
assert(DeleteFileA(resfile) != 0);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-09 17:35:45 +00:00
|
|
|
|
static void test_OpenProcess(void)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hproc;
|
|
|
|
|
void *addr1;
|
|
|
|
|
MEMORY_BASIC_INFORMATION info;
|
|
|
|
|
SIZE_T dummy, read_bytes;
|
2011-10-03 17:58:01 +00:00
|
|
|
|
BOOL ret;
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
/* not exported in all windows versions */
|
|
|
|
|
if ((!pVirtualAllocEx) || (!pVirtualFreeEx)) {
|
2009-05-17 07:05:22 +00:00
|
|
|
|
win_skip("VirtualAllocEx not found\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* without PROCESS_VM_OPERATION */
|
2014-04-18 22:50:27 +00:00
|
|
|
|
hproc = OpenProcess(PROCESS_ALL_ACCESS_NT4 & ~PROCESS_VM_OPERATION, FALSE, GetCurrentProcessId());
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
|
|
|
|
|
ok(!addr1, "VirtualAllocEx should fail\n");
|
|
|
|
|
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
|
|
|
{ /* Win9x */
|
|
|
|
|
CloseHandle(hproc);
|
2009-05-17 07:05:22 +00:00
|
|
|
|
win_skip("VirtualAllocEx not implemented\n");
|
2008-05-09 17:35:45 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
read_bytes = 0xdeadbeef;
|
|
|
|
|
SetLastError(0xdeadbeef);
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ret = ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes);
|
|
|
|
|
ok(ret, "ReadProcessMemory error %d\n", GetLastError());
|
2008-05-09 17:35:45 +00:00
|
|
|
|
ok(read_bytes == sizeof(dummy), "wrong read bytes %ld\n", read_bytes);
|
|
|
|
|
|
|
|
|
|
CloseHandle(hproc);
|
|
|
|
|
|
|
|
|
|
hproc = OpenProcess(PROCESS_VM_OPERATION, FALSE, GetCurrentProcessId());
|
|
|
|
|
ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
|
|
|
|
|
ok(addr1 != NULL, "VirtualAllocEx error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* without PROCESS_QUERY_INFORMATION */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ok(!VirtualQueryEx(hproc, addr1, &info, sizeof(info)),
|
|
|
|
|
"VirtualQueryEx without PROCESS_QUERY_INFORMATION rights should fail\n");
|
|
|
|
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* without PROCESS_VM_READ */
|
|
|
|
|
read_bytes = 0xdeadbeef;
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ok(!ReadProcessMemory(hproc, addr1, &dummy, sizeof(dummy), &read_bytes),
|
|
|
|
|
"ReadProcessMemory without PROCESS_VM_READ rights should fail\n");
|
|
|
|
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
|
|
|
|
|
ok(read_bytes == 0, "wrong read bytes %ld\n", read_bytes);
|
|
|
|
|
|
|
|
|
|
CloseHandle(hproc);
|
|
|
|
|
|
|
|
|
|
hproc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
|
|
|
|
|
|
|
|
|
|
memset(&info, 0xcc, sizeof(info));
|
2011-10-03 17:58:01 +00:00
|
|
|
|
read_bytes = VirtualQueryEx(hproc, addr1, &info, sizeof(info));
|
|
|
|
|
ok(read_bytes == sizeof(info), "VirtualQueryEx error %d\n", GetLastError());
|
2008-05-09 17:35:45 +00:00
|
|
|
|
|
|
|
|
|
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
|
|
|
|
|
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
|
|
|
|
|
ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
|
|
|
|
|
ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
|
|
|
|
|
ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
|
|
|
|
|
/* NT reports Protect == 0 for a not committed memory block */
|
|
|
|
|
ok(info.Protect == 0 /* NT */ ||
|
|
|
|
|
info.Protect == PAGE_NOACCESS, /* Win9x */
|
|
|
|
|
"%x != PAGE_NOACCESS\n", info.Protect);
|
|
|
|
|
ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ok(!pVirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
|
|
|
|
|
"VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
|
|
|
|
|
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
CloseHandle(hproc);
|
|
|
|
|
|
|
|
|
|
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
static void test_GetProcessVersion(void)
|
|
|
|
|
{
|
|
|
|
|
static char cmdline[] = "winver.exe";
|
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
|
STARTUPINFOA si;
|
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = GetProcessVersion(0);
|
|
|
|
|
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = GetProcessVersion(GetCurrentProcessId());
|
|
|
|
|
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
|
si.wShowWindow = SW_HIDE;
|
|
|
|
|
SetLastError(0xdeadbeef);
|
2013-09-11 11:32:57 +00:00
|
|
|
|
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
2008-12-23 20:02:47 +00:00
|
|
|
|
ok(ret, "CreateProcess error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = GetProcessVersion(pi.dwProcessId);
|
|
|
|
|
ok(ret, "GetProcessVersion error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = TerminateProcess(pi.hProcess, 0);
|
|
|
|
|
ok(ret, "TerminateProcess error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-12 19:33:11 +00:00
|
|
|
|
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));
|
2014-04-18 22:50:27 +00:00
|
|
|
|
ok(lstrcmpiA(process, image) == 0, "expected '%s' to be equal to '%s'\n", process, image);
|
2012-05-12 19:33:11 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_QueryFullProcessImageNameA(void)
|
2009-06-23 11:44:23 +00:00
|
|
|
|
{
|
|
|
|
|
#define INIT_STR "Just some words"
|
|
|
|
|
DWORD length, size;
|
2012-05-12 19:33:11 +00:00
|
|
|
|
CHAR buf[MAX_PATH], module[MAX_PATH];
|
2009-06-23 11:44:23 +00:00
|
|
|
|
|
|
|
|
|
if (!pQueryFullProcessImageNameA)
|
|
|
|
|
{
|
|
|
|
|
win_skip("QueryFullProcessImageNameA unavailable (added in Windows Vista)\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-05-12 19:33:11 +00:00
|
|
|
|
|
|
|
|
|
*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());
|
|
|
|
|
|
2009-06-23 11:44:23 +00:00
|
|
|
|
/* get the buffer length without \0 terminator */
|
2012-05-12 19:33:11 +00:00
|
|
|
|
length = sizeof(buf);
|
2009-06-23 11:44:23 +00:00
|
|
|
|
expect_eq_d(TRUE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &length));
|
|
|
|
|
expect_eq_d(length, lstrlenA(buf));
|
2012-05-12 19:33:11 +00:00
|
|
|
|
ok((buf[0] == '\\' && buf[1] == '\\') ||
|
2014-04-18 22:50:27 +00:00
|
|
|
|
lstrcmpiA(buf, module) == 0, "expected %s to match %s\n", buf, module);
|
2009-06-23 11:44:23 +00:00
|
|
|
|
|
|
|
|
|
/* when the buffer is too small
|
|
|
|
|
* - function fail with error ERROR_INSUFFICIENT_BUFFER
|
|
|
|
|
* - the size variable is not modified
|
|
|
|
|
* tested with the biggest too small size
|
|
|
|
|
*/
|
|
|
|
|
size = length;
|
|
|
|
|
sprintf(buf,INIT_STR);
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
expect_eq_d(length, size);
|
|
|
|
|
expect_eq_s(INIT_STR, buf);
|
|
|
|
|
|
|
|
|
|
/* retest with smaller buffer size
|
|
|
|
|
*/
|
|
|
|
|
size = 4;
|
|
|
|
|
sprintf(buf,INIT_STR);
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, buf, &size));
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
expect_eq_d(4, size);
|
|
|
|
|
expect_eq_s(INIT_STR, buf);
|
|
|
|
|
|
|
|
|
|
/* this is a difference between the ascii and the unicode version
|
2012-05-12 19:33:11 +00:00
|
|
|
|
* the unicode version crashes when the size is big enough to hold
|
|
|
|
|
* the result while the ascii version throws an error
|
2009-06-23 11:44:23 +00:00
|
|
|
|
*/
|
|
|
|
|
size = 1024;
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameA(GetCurrentProcess(), 0, NULL, &size));
|
|
|
|
|
expect_eq_d(1024, size);
|
|
|
|
|
expect_eq_d(ERROR_INVALID_PARAMETER, GetLastError());
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-12 19:33:11 +00:00
|
|
|
|
static void test_QueryFullProcessImageNameW(void)
|
2009-05-17 07:05:22 +00:00
|
|
|
|
{
|
|
|
|
|
HANDLE hSelf;
|
2012-05-12 19:33:11 +00:00
|
|
|
|
WCHAR module_name[1024], device[1024];
|
2009-05-17 07:05:22 +00:00
|
|
|
|
WCHAR deviceW[] = {'\\','D', 'e','v','i','c','e',0};
|
|
|
|
|
WCHAR buf[1024];
|
2012-05-12 19:33:11 +00:00
|
|
|
|
DWORD size, len;
|
2009-05-17 07:05:22 +00:00
|
|
|
|
|
|
|
|
|
if (!pQueryFullProcessImageNameW)
|
|
|
|
|
{
|
|
|
|
|
win_skip("QueryFullProcessImageNameW unavailable (added in Windows Vista)\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ok(GetModuleFileNameW(NULL, module_name, 1024), "GetModuleFileNameW(NULL, ...) failed\n");
|
|
|
|
|
|
|
|
|
|
/* GetCurrentProcess pseudo-handle */
|
|
|
|
|
size = sizeof(buf) / sizeof(buf[0]);
|
|
|
|
|
expect_eq_d(TRUE, pQueryFullProcessImageNameW(GetCurrentProcess(), 0, buf, &size));
|
|
|
|
|
expect_eq_d(lstrlenW(buf), size);
|
|
|
|
|
expect_eq_ws_i(buf, module_name);
|
|
|
|
|
|
|
|
|
|
hSelf = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
|
|
|
|
|
/* Real handle */
|
|
|
|
|
size = sizeof(buf) / sizeof(buf[0]);
|
|
|
|
|
expect_eq_d(TRUE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
|
|
|
|
expect_eq_d(lstrlenW(buf), size);
|
|
|
|
|
expect_eq_ws_i(buf, module_name);
|
|
|
|
|
|
|
|
|
|
/* Buffer too small */
|
|
|
|
|
size = lstrlenW(module_name)/2;
|
|
|
|
|
lstrcpyW(buf, deviceW);
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
|
|
|
|
expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
expect_eq_ws_i(deviceW, buf); /* buffer not changed */
|
|
|
|
|
|
|
|
|
|
/* Too small - not space for NUL terminator */
|
|
|
|
|
size = lstrlenW(module_name);
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
|
|
|
|
expect_eq_d(lstrlenW(module_name), size); /* size not changed(!) */
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
|
|
|
|
|
/* NULL buffer */
|
|
|
|
|
size = 0;
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, NULL, &size));
|
|
|
|
|
expect_eq_d(0, size);
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
|
|
|
|
|
/* Buffer too small */
|
|
|
|
|
size = lstrlenW(module_name)/2;
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
lstrcpyW(buf, module_name);
|
|
|
|
|
expect_eq_d(FALSE, pQueryFullProcessImageNameW(hSelf, 0, buf, &size));
|
|
|
|
|
expect_eq_d(lstrlenW(module_name)/2, size); /* size not changed(!) */
|
|
|
|
|
expect_eq_d(ERROR_INSUFFICIENT_BUFFER, GetLastError());
|
|
|
|
|
expect_eq_ws_i(module_name, buf); /* buffer not changed */
|
|
|
|
|
|
2012-05-12 19:33:11 +00:00
|
|
|
|
|
|
|
|
|
/* 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));
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-17 07:05:22 +00:00
|
|
|
|
CloseHandle(hSelf);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-23 20:02:47 +00:00
|
|
|
|
static void test_Handles(void)
|
|
|
|
|
{
|
|
|
|
|
HANDLE handle = GetCurrentProcess();
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
HANDLE h2, h3;
|
2008-12-23 20:02:47 +00:00
|
|
|
|
BOOL ret;
|
|
|
|
|
DWORD code;
|
|
|
|
|
|
|
|
|
|
ok( handle == (HANDLE)~(ULONG_PTR)0 ||
|
|
|
|
|
handle == (HANDLE)(ULONG_PTR)0x7fffffff /* win9x */,
|
|
|
|
|
"invalid current process handle %p\n", handle );
|
|
|
|
|
ret = GetExitCodeProcess( handle, &code );
|
|
|
|
|
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
|
|
|
|
|
#ifdef _WIN64
|
|
|
|
|
/* truncated handle */
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
|
handle = (HANDLE)((ULONG_PTR)handle & ~0u);
|
|
|
|
|
ret = GetExitCodeProcess( handle, &code );
|
|
|
|
|
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
|
|
|
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
|
|
|
|
/* sign-extended handle */
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
|
handle = (HANDLE)((LONG_PTR)(int)(ULONG_PTR)handle);
|
|
|
|
|
ret = GetExitCodeProcess( handle, &code );
|
|
|
|
|
ok( ret, "GetExitCodeProcess failed err %u\n", GetLastError() );
|
|
|
|
|
/* invalid high-word */
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
|
handle = (HANDLE)(((ULONG_PTR)handle & ~0u) + ((ULONG_PTR)1 << 32));
|
|
|
|
|
ret = GetExitCodeProcess( handle, &code );
|
|
|
|
|
ok( !ret, "GetExitCodeProcess succeeded for %p\n", handle );
|
|
|
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
|
|
|
|
|
#endif
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2011-10-03 17:58:01 +00:00
|
|
|
|
if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
{
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ok(S(U(nsi)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64,
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
"Expected PROCESSOR_ARCHITECTURE_AMD64, got %d\n",
|
2011-10-03 17:58:01 +00:00
|
|
|
|
S(U(nsi)).wProcessorArchitecture);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
ok(nsi.dwProcessorType == PROCESSOR_AMD_X8664,
|
|
|
|
|
"Expected PROCESSOR_AMD_X8664, got %d\n",
|
|
|
|
|
nsi.dwProcessorType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2011-10-03 17:58:01 +00:00
|
|
|
|
ok(S(U(si)).wProcessorArchitecture == S(U(nsi)).wProcessorArchitecture,
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
"Expected no difference for wProcessorArchitecture, got %d and %d\n",
|
2011-10-03 17:58:01 +00:00
|
|
|
|
S(U(si)).wProcessorArchitecture, S(U(nsi)).wProcessorArchitecture);
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
ok(si.dwProcessorType == nsi.dwProcessorType,
|
|
|
|
|
"Expected no difference for dwProcessorType, got %d and %d\n",
|
|
|
|
|
si.dwProcessorType, nsi.dwProcessorType);
|
|
|
|
|
}
|
2008-12-23 20:02:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-10-03 17:58:01 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-11 11:32:57 +00:00
|
|
|
|
static void test_TerminateProcess(void)
|
|
|
|
|
{
|
|
|
|
|
static char cmdline[] = "winver.exe";
|
|
|
|
|
PROCESS_INFORMATION pi;
|
2014-04-18 22:50:27 +00:00
|
|
|
|
STARTUPINFOA si;
|
2013-09-11 11:32:57 +00:00
|
|
|
|
DWORD ret;
|
|
|
|
|
HANDLE dummy, thread;
|
|
|
|
|
|
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
|
SetLastError(0xdeadbeef);
|
2014-04-18 22:50:27 +00:00
|
|
|
|
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
|
2013-09-11 11:32:57 +00:00
|
|
|
|
ok(ret, "CreateProcess error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
thread = CreateRemoteThread(pi.hProcess, NULL, 0, (void *)0xdeadbeef, NULL, CREATE_SUSPENDED, &ret);
|
|
|
|
|
ok(thread != 0, "CreateRemoteThread error %d\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* create a not closed thread handle duplicate in the target process */
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = DuplicateHandle(GetCurrentProcess(), thread, pi.hProcess, &dummy,
|
|
|
|
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
|
|
|
ok(ret, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = TerminateThread(thread, 0);
|
|
|
|
|
ok(ret, "TerminateThread error %u\n", GetLastError());
|
|
|
|
|
CloseHandle(thread);
|
|
|
|
|
|
|
|
|
|
SetLastError(0xdeadbeef);
|
|
|
|
|
ret = TerminateProcess(pi.hProcess, 0);
|
|
|
|
|
ok(ret, "TerminateProcess error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void test_DuplicateHandle(void)
|
|
|
|
|
{
|
|
|
|
|
char path[MAX_PATH], file_name[MAX_PATH];
|
|
|
|
|
HANDLE f, fmin, out;
|
|
|
|
|
DWORD info;
|
|
|
|
|
BOOL r;
|
|
|
|
|
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
|
|
|
|
|
GetCurrentProcess(), &out, 0, FALSE,
|
|
|
|
|
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
r = GetHandleInformation(out, &info);
|
|
|
|
|
ok(r, "GetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
ok(info == 0, "info = %x\n", info);
|
|
|
|
|
ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
|
|
|
|
|
CloseHandle(out);
|
|
|
|
|
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
|
|
|
|
|
GetCurrentProcess(), &out, 0, TRUE,
|
|
|
|
|
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
r = GetHandleInformation(out, &info);
|
|
|
|
|
ok(r, "GetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
|
|
|
|
|
ok(out != GetCurrentProcess(), "out = GetCurrentProcess()\n");
|
|
|
|
|
CloseHandle(out);
|
|
|
|
|
|
2014-04-18 22:50:27 +00:00
|
|
|
|
GetTempPathA(MAX_PATH, path);
|
|
|
|
|
GetTempFileNameA(path, "wt", 0, file_name);
|
|
|
|
|
f = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
2013-09-11 11:32:57 +00:00
|
|
|
|
if (f == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
ok(0, "could not create %s\n", file_name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out,
|
|
|
|
|
0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
ok(f == out, "f != out\n");
|
|
|
|
|
r = GetHandleInformation(out, &info);
|
|
|
|
|
ok(r, "GetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
ok(info == 0, "info = %x\n", info);
|
|
|
|
|
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out,
|
|
|
|
|
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
ok(f == out, "f != out\n");
|
|
|
|
|
r = GetHandleInformation(out, &info);
|
|
|
|
|
ok(r, "GetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
|
|
|
|
|
|
|
|
|
|
r = SetHandleInformation(f, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE);
|
|
|
|
|
ok(r, "SetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out,
|
|
|
|
|
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
ok(f != out, "f == out\n");
|
|
|
|
|
r = GetHandleInformation(out, &info);
|
|
|
|
|
ok(r, "GetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
ok(info == HANDLE_FLAG_INHERIT, "info = %x\n", info);
|
|
|
|
|
r = SetHandleInformation(f, HANDLE_FLAG_PROTECT_FROM_CLOSE, 0);
|
|
|
|
|
ok(r, "SetHandleInformation error %u\n", GetLastError());
|
|
|
|
|
|
|
|
|
|
/* Test if DuplicateHandle allocates first free handle */
|
|
|
|
|
if (f > out)
|
|
|
|
|
{
|
|
|
|
|
fmin = out;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fmin = f;
|
|
|
|
|
f = out;
|
|
|
|
|
}
|
|
|
|
|
CloseHandle(fmin);
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out,
|
|
|
|
|
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
ok(f == out, "f != out\n");
|
|
|
|
|
CloseHandle(out);
|
2014-04-18 22:50:27 +00:00
|
|
|
|
DeleteFileA(file_name);
|
2013-09-11 11:32:57 +00:00
|
|
|
|
|
2014-04-18 22:50:27 +00:00
|
|
|
|
f = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
|
2013-09-11 11:32:57 +00:00
|
|
|
|
if (!is_console(f))
|
|
|
|
|
{
|
|
|
|
|
skip("DuplicateHandle on console handle\n");
|
|
|
|
|
CloseHandle(f);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
r = DuplicateHandle(GetCurrentProcess(), f, GetCurrentProcess(), &out,
|
|
|
|
|
0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
|
|
|
|
|
ok(r, "DuplicateHandle error %u\n", GetLastError());
|
|
|
|
|
todo_wine ok(f != out, "f == out\n");
|
|
|
|
|
CloseHandle(out);
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-06 11:59:18 +00:00
|
|
|
|
START_TEST(process)
|
|
|
|
|
{
|
2014-04-18 22:50:27 +00:00
|
|
|
|
BOOL b = init();
|
2007-03-06 11:59:18 +00:00
|
|
|
|
ok(b, "Basic init of CreateProcess test\n");
|
|
|
|
|
if (!b) return;
|
|
|
|
|
|
|
|
|
|
if (myARGC >= 3)
|
|
|
|
|
{
|
|
|
|
|
doChild(myARGV[2], (myARGC == 3) ? NULL : myARGV[3]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-09-11 11:32:57 +00:00
|
|
|
|
test_TerminateProcess();
|
2007-03-06 11:59:18 +00:00
|
|
|
|
test_Startup();
|
|
|
|
|
test_CommandLine();
|
|
|
|
|
test_Directory();
|
|
|
|
|
test_Environment();
|
|
|
|
|
test_SuspendFlag();
|
|
|
|
|
test_DebuggingFlag();
|
|
|
|
|
test_Console();
|
|
|
|
|
test_ExitCode();
|
2008-05-09 17:35:45 +00:00
|
|
|
|
test_OpenProcess();
|
2008-12-23 20:02:47 +00:00
|
|
|
|
test_GetProcessVersion();
|
2012-05-12 19:33:11 +00:00
|
|
|
|
test_GetProcessImageFileNameA();
|
|
|
|
|
test_QueryFullProcessImageNameA();
|
|
|
|
|
test_QueryFullProcessImageNameW();
|
2008-12-23 20:02:47 +00:00
|
|
|
|
test_Handles();
|
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
|
|
|
|
test_SystemInfo();
|
2011-10-03 17:58:01 +00:00
|
|
|
|
test_RegistryQuota();
|
2013-09-11 11:32:57 +00:00
|
|
|
|
test_DuplicateHandle();
|
2007-03-06 11:59:18 +00:00
|
|
|
|
/* things that can be tested:
|
|
|
|
|
* lookup: check the way program to be executed is searched
|
|
|
|
|
* handles: check the handle inheritance stuff (+sec options)
|
|
|
|
|
* console: check if console creation parameters work
|
|
|
|
|
*/
|
|
|
|
|
}
|