📄 process.c
字号:
/*
* Unit test suite for CreateProcess function.
*
* Copyright 2002 Eric Pouech
*
* 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
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wincon.h"
#include "winnls.h"
static char base[MAX_PATH];
static char selfname[MAX_PATH];
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 */
static char memory[1024*32];
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;
}
#if 0
/* 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;
}
#endif
/******************************************************************
* init
*
* generates basic information like:
* base: absolute path to curr dir
* selfname: the way to reinvoke ourselves
*/
static int init(void)
{
myARGC = winetest_get_mainargs( &myARGV );
if (!GetCurrentDirectoryA(sizeof(base), base)) return 0;
strcpy(selfname, myARGV[0]);
return 1;
}
/******************************************************************
* 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;
char* ptrA;
WCHAR* ptrW;
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,
(DWORD)siA.hStdInput, (DWORD)siA.hStdOutput, (DWORD)siA.hStdError);
/* 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,
(DWORD)siW.hStdInput, (DWORD)siW.hStdOutput, (DWORD)siW.hStdError);
/* 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()));
#if 0
int argcW;
WCHAR** argvW;
/* this is part of shell32... and should be tested there */
argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
for (i = 0; i < argcW; i++)
{
childPrintf(hFile, "argvW%d=%s\n", i, encodeW(argvW[i]));
}
#endif
childPrintf(hFile, "CommandLineW=%s\n\n", encodeW(GetCommandLineW()));
/* output of environment (Ansi) */
ptrA = GetEnvironmentStringsA();
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);
}
/* output of environment (Unicode) */
ptrW = GetEnvironmentStringsW();
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);
}
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -