Author: ion
Date: Mon Jan 23 04:57:12 2012
New Revision: 55092
URL:
http://svn.reactos.org/svn/reactos?rev=55092&view=rev
Log:
[KERNEL32]: Changes to proc.c:
- ReadProcessMemory/WriteProcessMemory only write to *lpNumberOfBytesRead/Written if
user-mode passed in the parameter, as its an optional argument in Win32, but not in NT.
Instead, use a local variable. This means that anyone calling
ReadProcessMemory/WriteProcessMemory in ReactOS before with a NULL output argument
(totally valid) was getting an error before!
- WriteProcessMemory actually returns STATUS_ACCESS_VIOLATION in a few cases, even if
it's defined as a BOOL function. Code on Google shows major applications depending on
this, which we weren't doing.
- Rewrite InitCommandLines to be much simpler. No normalization or copying or ANSi/OEM
logic is needed.
- GetProcessAffinityMask should use the BaseStaticServerData from CSRSS instead of
querying system information each time.
- GetProcessShutdownParameters and SetProcessShutdownParameters should use the LPC status
code from CSRSS, not the LPC API status code.
- GetProcessWorkingSetSize now calls GetProcessWorkingSetSizeEx.
- Implement GetProcessWorkingSetSizeEx.
- SetProcessWorkingSetSize now calls SetProcessWorkingSetSizeEx.
- Implement SetProcessWorkingSetSizeEx.
- Acquire the required privilege in SetProcessWorkingSetSize(Ex).
- Fail with correct status code in SetProcessWorkingSetSize(Ex).
- GetExitCodeProcess should check if this is a VDM process and get the exit code that
way.
- GetStartupInfoW should not fail if the input is NULL. It should crash.
- GetStartupInfoW was not filling out the lpReserved field, which should contain the
ShellInfo buffer.
- GetStartupInfoW was always setting standard handles -- it should not do so if those are
console handles.
- GetStartupInfoA was not thread-safe.
- GetStartupInfoA was assuming all Unicode->ANSI conversions will be successful.
- GetStartupInfoA was not filling out lpReserved either.
- ExitProcess was not using SEH and was not using the PEB lock.
- TerminateProcess was not setting ERROR_INVALID_HANDLE last error code.
- FatalAppExitA was not using static TEB buffer, and was always assuming success.
- FatalAppExitW was doing some sort of bizarre hack. It now raises as a hard error as it
should.
- FatalExit now displays a debugger input interface on checked builds, just like Windows.
- SetPriorityClass now tries to acquire the real time privilege when needed, and handles
failure to do so.
- GetProcessVersion rewritten to be cleaner and simpler.
- Annotate and reformat functions where needed.
- Rename lpfnGlobalRegisterWaitForInputIdle to UserWaitForInputIdleRoutine
- GetProcessPriorityBoost is now BOOL-safe.
- IsWow64Process now sets NT error code using only one API.
- CommandLineStringA/W -> BaseAnsiCommandLine/BaseUnicodeCommandLine.
Modified:
trunk/reactos/dll/win32/kernel32/client/loader.c
trunk/reactos/dll/win32/kernel32/client/proc.c
trunk/reactos/dll/win32/kernel32/include/kernel32.h
trunk/reactos/include/ndk/extypes.h
Modified: trunk/reactos/dll/win32/kernel32/client/loader.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/loader.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/loader.c [iso-8859-1] Mon Jan 23 04:57:12
2012
@@ -1026,9 +1026,9 @@
}
/* Wait up to 30 seconds for the process to become idle */
- if (lpfnGlobalRegisterWaitForInputIdle)
- {
- lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 30000);
+ if (UserWaitForInputIdleRoutine)
+ {
+ UserWaitForInputIdleRoutine(ProcessInformation.hProcess, 30000);
}
/* Close handles */
Modified: trunk/reactos/dll/win32/kernel32/client/proc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/proc.c [iso-8859-1] Mon Jan 23 04:57:12 2012
@@ -16,39 +16,20 @@
#define NDEBUG
#include <debug.h>
-typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
-
/* GLOBALS *******************************************************************/
-static UNICODE_STRING CommandLineStringW;
-static ANSI_STRING CommandLineStringA;
+WaitForInputIdleType UserWaitForInputIdleRoutine;
+UNICODE_STRING BaseUnicodeCommandLine;
+ANSI_STRING BaseAnsiCommandLine;
UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
-
-static BOOL bCommandLineInitialized = FALSE;
-
-WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
-
-LPSTARTUPINFOA lpLocalStartupInfo = NULL;
-
-VOID WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
-
+LPSTARTUPINFOA BaseAnsiStartupInfo = NULL;
PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
-
-#define CMD_STRING L"cmd /c "
-
-extern __declspec(noreturn)
-VOID
-CALLBACK
-ConsoleControlDispatcher(DWORD CodeAndFlag);
-
BOOLEAN g_AppCertInitialized;
BOOLEAN g_HaveAppCerts;
LIST_ENTRY BasepAppCertDllsList;
RTL_CRITICAL_SECTION gcsAppCert;
PBASEP_APPCERT_EMBEDDED_FUNC fEmbeddedCertFunc;
NTSTATUS g_AppCertStatus;
-
RTL_QUERY_REGISTRY_TABLE BasepAppCertTable[2] =
{
{
@@ -64,6 +45,11 @@
PSAFER_REPLACE_PROCESS_THREAD_TOKENS g_SaferReplaceProcessThreadTokens;
HMODULE gSaferHandle = (HMODULE)-1;
+
+VOID WINAPI
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
+
+#define CMD_STRING L"cmd /c "
/* FUNCTIONS ****************************************************************/
@@ -1128,68 +1114,33 @@
WINAPI
InitCommandLines(VOID)
{
- PRTL_USER_PROCESS_PARAMETERS Params;
-
- /* get command line */
- Params = NtCurrentPeb()->ProcessParameters;
- RtlNormalizeProcessParams (Params);
-
- /* initialize command line buffers */
- CommandLineStringW.Length = Params->CommandLine.Length;
- CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR);
- CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(),
- HEAP_GENERATE_EXCEPTIONS |
HEAP_ZERO_MEMORY,
- CommandLineStringW.MaximumLength);
- if (CommandLineStringW.Buffer == NULL)
- {
- return;
- }
-
- RtlInitAnsiString(&CommandLineStringA, NULL);
-
- /* Copy command line */
- RtlCopyUnicodeString(&CommandLineStringW,
- &(Params->CommandLine));
- CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0;
-
- /* convert unicode string to ansi (or oem) */
- if (bIsFileApiAnsi)
- RtlUnicodeStringToAnsiString(&CommandLineStringA,
- &CommandLineStringW,
- TRUE);
- else
- RtlUnicodeStringToOemString(&CommandLineStringA,
- &CommandLineStringW,
- TRUE);
-
- CommandLineStringA.Buffer[CommandLineStringA.Length] = 0;
-
- bCommandLineInitialized = TRUE;
-}
+ NTSTATUS Status;
+
+ /* Read the UNICODE_STRING from the PEB */
+ BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
+
+ /* Convert to ANSI_STRING for the *A callers */
+ Status = RtlUnicodeStringToAnsiString(&BaseAnsiCommandLine,
+ &BaseUnicodeCommandLine,
+ TRUE);
+ if (!NT_SUCCESS(Status)) RtlInitEmptyAnsiString(&BaseAnsiCommandLine, 0, 0);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessAffinityMask(HANDLE hProcess,
- PDWORD_PTR lpProcessAffinityMask,
- PDWORD_PTR lpSystemAffinityMask)
+GetProcessAffinityMask(IN HANDLE hProcess,
+ OUT PDWORD_PTR lpProcessAffinityMask,
+ OUT PDWORD_PTR lpSystemAffinityMask)
{
PROCESS_BASIC_INFORMATION ProcessInfo;
- SYSTEM_BASIC_INFORMATION SystemInfo;
- NTSTATUS Status;
-
- Status = NtQuerySystemInformation(SystemBasicInformation,
- &SystemInfo,
- sizeof(SystemInfo),
- NULL);
- if (!NT_SUCCESS(Status))
- {
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
+ NTSTATUS Status;
+
+ /* Query information on the process from the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
(PVOID)&ProcessInfo,
@@ -1197,174 +1148,237 @@
NULL);
if (!NT_SUCCESS(Status))
{
+ /* Fail */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* Copy the affinity mask, and get the system one from our shared data */
*lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask;
- *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask;
-
+ *lpSystemAffinityMask =
(DWORD)BaseStaticServerData->SysInfo.ActiveProcessorsAffinityMask;
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-SetProcessAffinityMask(HANDLE hProcess,
- DWORD_PTR dwProcessAffinityMask)
-{
- NTSTATUS Status;
-
+SetProcessAffinityMask(IN HANDLE hProcess,
+ IN DWORD_PTR dwProcessAffinityMask)
+{
+ NTSTATUS Status;
+
+ /* Directly set the affinity mask */
Status = NtSetInformationProcess(hProcess,
ProcessAffinityMask,
(PVOID)&dwProcessAffinityMask,
sizeof(DWORD));
if (!NT_SUCCESS(Status))
{
+ /* Handle failure */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* Everything was ok */
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessShutdownParameters(LPDWORD lpdwLevel,
- LPDWORD lpdwFlags)
+GetProcessShutdownParameters(OUT LPDWORD lpdwLevel,
+ OUT LPDWORD lpdwFlags)
{
CSR_API_MESSAGE CsrRequest;
- ULONG Request;
- NTSTATUS Status;
-
- Request = GET_SHUTDOWN_PARAMETERS;
+ NTSTATUS Status;
+
+ /* Ask CSRSS for shutdown information */
Status = CsrClientCallServer(&CsrRequest,
NULL,
- MAKE_CSR_API(Request, CSR_NATIVE),
+ MAKE_CSR_API(GET_SHUTDOWN_PARAMETERS, CSR_NATIVE),
+ sizeof(CSR_API_MESSAGE));
+ if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(CsrRequest.Status)))
+ {
+ /* Return the failure from CSRSS */
+ BaseSetLastNTError(CsrRequest.Status);
+ return FALSE;
+ }
+
+ /* Get the data out of the LCP reply */
+ *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level;
+ *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags;
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessShutdownParameters(IN DWORD dwLevel,
+ IN DWORD dwFlags)
+{
+ CSR_API_MESSAGE CsrRequest;
+ NTSTATUS Status;
+
+ /* Write the data into the CSRSS request and send it */
+ CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
+ CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
+ Status = CsrClientCallServer(&CsrRequest,
+ NULL,
+ MAKE_CSR_API(SET_SHUTDOWN_PARAMETERS, CSR_NATIVE),
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
- BaseSetLastNTError(Status);
+ /* Return the failure from CSRSS */
+ BaseSetLastNTError(CsrRequest.Status);
return FALSE;
}
- *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level;
- *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags;
-
+ /* All went well */
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-SetProcessShutdownParameters(DWORD dwLevel,
- DWORD dwFlags)
-{
- CSR_API_MESSAGE CsrRequest;
- ULONG Request;
- NTSTATUS Status;
-
- CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
- CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
-
- Request = SET_SHUTDOWN_PARAMETERS;
- Status = CsrClientCallServer(&CsrRequest,
- NULL,
- MAKE_CSR_API(Request, CSR_NATIVE),
- sizeof(CSR_API_MESSAGE));
- if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
- {
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-GetProcessWorkingSetSize(HANDLE hProcess,
- PSIZE_T lpMinimumWorkingSetSize,
- PSIZE_T lpMaximumWorkingSetSize)
-{
- QUOTA_LIMITS QuotaLimits;
- NTSTATUS Status;
-
+GetProcessWorkingSetSizeEx(IN HANDLE hProcess,
+ OUT PSIZE_T lpMinimumWorkingSetSize,
+ OUT PSIZE_T lpMaximumWorkingSetSize,
+ OUT PDWORD Flags)
+{
+ QUOTA_LIMITS_EX QuotaLimits;
+ NTSTATUS Status;
+
+ /* Query the kernel about this */
Status = NtQueryInformationProcess(hProcess,
ProcessQuotaLimits,
&QuotaLimits,
- sizeof(QUOTA_LIMITS),
+ sizeof(QUOTA_LIMITS_EX),
NULL);
if (!NT_SUCCESS(Status))
{
+ /* Return error */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* Copy the quota information out */
*lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize;
*lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize;
-
+ *Flags = QuotaLimits.Flags;
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-SetProcessWorkingSetSize(HANDLE hProcess,
- SIZE_T dwMinimumWorkingSetSize,
- SIZE_T dwMaximumWorkingSetSize)
-{
- QUOTA_LIMITS QuotaLimits;
- NTSTATUS Status;
-
- QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
- QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
-
- Status = NtSetInformationProcess(hProcess,
- ProcessQuotaLimits,
- &QuotaLimits,
- sizeof(QUOTA_LIMITS));
- if (!NT_SUCCESS(Status))
- {
- BaseSetLastNTError(Status);
- return FALSE;
- }
-
- return TRUE;
-}
-
+GetProcessWorkingSetSize(IN HANDLE hProcess,
+ OUT PSIZE_T lpMinimumWorkingSetSize,
+ OUT PSIZE_T lpMaximumWorkingSetSize)
+{
+ DWORD Dummy;
+ return GetProcessWorkingSetSizeEx(hProcess,
+ lpMinimumWorkingSetSize,
+ lpMaximumWorkingSetSize,
+ &Dummy);
+}
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessTimes(HANDLE hProcess,
- LPFILETIME lpCreationTime,
- LPFILETIME lpExitTime,
- LPFILETIME lpKernelTime,
- LPFILETIME lpUserTime)
+SetProcessWorkingSetSizeEx(IN HANDLE hProcess,
+ IN SIZE_T dwMinimumWorkingSetSize,
+ IN SIZE_T dwMaximumWorkingSetSize,
+ IN DWORD Flags)
+{
+ QUOTA_LIMITS_EX QuotaLimits;
+ NTSTATUS Status, ReturnStatus;
+ BOOL Result;
+ PVOID State;
+ ULONG Privilege = SE_INC_BASE_PRIORITY_PRIVILEGE;
+
+ /* Zero out the input structure */
+ RtlZeroMemory(&QuotaLimits, sizeof(QuotaLimits));
+
+ /* Check if the caller sent any limits */
+ if ((dwMinimumWorkingSetSize) && (dwMaximumWorkingSetSize))
+ {
+ /* Write the quota information */
+ QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
+ QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+ QuotaLimits.Flags = Flags;
+
+ /* Acquire the required privilege */
+ Status = RtlAcquirePrivilege(&Privilege, 1, 0, &State);
+
+ /* Request the new quotas */
+ ReturnStatus = NtSetInformationProcess(hProcess,
+ ProcessQuotaLimits,
+ &QuotaLimits,
+ sizeof(QuotaLimits));
+ Result = NT_SUCCESS(ReturnStatus);
+ if (NT_SUCCESS(Status))
+ {
+ /* Release the privilege and set succes code */
+ ASSERT(State != NULL);
+ RtlReleasePrivilege(State);
+ State = NULL;
+ }
+ }
+ else
+ {
+ /* No limits, fail the call */
+ ReturnStatus = STATUS_INVALID_PARAMETER;
+ Result = FALSE;
+ }
+
+ /* Return result code, set error code if this was a failure */
+ if (!Result) BaseSetLastNTError(ReturnStatus);
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+SetProcessWorkingSetSize(IN HANDLE hProcess,
+ IN SIZE_T dwMinimumWorkingSetSize,
+ IN SIZE_T dwMaximumWorkingSetSize)
+{
+ /* Call the newer API */
+ return SetProcessWorkingSetSizeEx(hProcess,
+ dwMinimumWorkingSetSize,
+ dwMaximumWorkingSetSize,
+ 0);
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetProcessTimes(IN HANDLE hProcess,
+ IN LPFILETIME lpCreationTime,
+ IN LPFILETIME lpExitTime,
+ IN LPFILETIME lpKernelTime,
+ IN LPFILETIME lpUserTime)
{
KERNEL_USER_TIMES Kut;
NTSTATUS Status;
+ /* Query the times */
Status = NtQueryInformationProcess(hProcess,
ProcessTimes,
&Kut,
@@ -1372,26 +1386,23 @@
NULL);
if (!NT_SUCCESS(Status))
{
+ /* Handle failure */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* Copy all the times and return success */
lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart;
lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart;
-
lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart;
lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart;
-
lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart;
lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart;
-
lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart;
lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart;
-
return TRUE;
}
-
/*
* @implemented
*/
@@ -1402,7 +1413,6 @@
return (HANDLE)NtCurrentProcess();
}
-
/*
* @implemented
*/
@@ -1413,7 +1423,6 @@
return (HANDLE)NtCurrentThread();
}
-
/*
* @implemented
*/
@@ -1421,21 +1430,21 @@
WINAPI
GetCurrentProcessId(VOID)
{
- return HandleToUlong(GetTeb()->ClientId.UniqueProcess);
-}
-
+ return HandleToUlong(NtCurrentTeb()->ClientId.UniqueProcess);
+}
/*
* @implemented
*/
BOOL
WINAPI
-GetExitCodeProcess(HANDLE hProcess,
- LPDWORD lpExitCode)
+GetExitCodeProcess(IN HANDLE hProcess,
+ IN LPDWORD lpExitCode)
{
PROCESS_BASIC_INFORMATION ProcessBasic;
NTSTATUS Status;
+ /* Ask the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
&ProcessBasic,
@@ -1443,26 +1452,30 @@
NULL);
if (!NT_SUCCESS(Status))
{
+ /* We failed, was this because this is a VDM process? */
+ if (BaseCheckForVDM(hProcess, lpExitCode) == TRUE) return TRUE;
+
+ /* Not a VDM process, fail the call */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* Succes case, return the exit code */
*lpExitCode = (DWORD)ProcessBasic.ExitStatus;
-
return TRUE;
}
-
/*
* @implemented
*/
DWORD
WINAPI
-GetProcessId(HANDLE Process)
+GetProcessId(IN HANDLE Process)
{
PROCESS_BASIC_INFORMATION ProcessBasic;
NTSTATUS Status;
+ /* Query the kernel */
Status = NtQueryInformationProcess(Process,
ProcessBasicInformation,
&ProcessBasic,
@@ -1470,105 +1483,65 @@
NULL);
if (!NT_SUCCESS(Status))
{
+ /* Handle failure */
BaseSetLastNTError(Status);
return 0;
}
+ /* Return the PID */
return (DWORD)ProcessBasic.UniqueProcessId;
}
-
/*
* @implemented
*/
HANDLE
WINAPI
-OpenProcess(DWORD dwDesiredAccess,
- BOOL bInheritHandle,
- DWORD dwProcessId)
-{
- NTSTATUS errCode;
+OpenProcess(IN DWORD dwDesiredAccess,
+ IN BOOL bInheritHandle,
+ IN DWORD dwProcessId)
+{
+ NTSTATUS Status;
HANDLE ProcessHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientId;
+ /* Setup the input client ID structure */
ClientId.UniqueProcess = UlongToHandle(dwProcessId);
ClientId.UniqueThread = 0;
+ /* This is needed just to define the inheritance flags */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
(bInheritHandle ? OBJ_INHERIT : 0),
NULL,
NULL);
- errCode = NtOpenProcess(&ProcessHandle,
- dwDesiredAccess,
- &ObjectAttributes,
- &ClientId);
- if (!NT_SUCCESS(errCode))
- {
- BaseSetLastNTError(errCode);
+ /* Now try to open the process */
+ Status = NtOpenProcess(&ProcessHandle,
+ dwDesiredAccess,
+ &ObjectAttributes,
+ &ClientId);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Handle failure */
+ BaseSetLastNTError(Status);
return NULL;
}
+ /* Otherwise return a handle to the process */
return ProcessHandle;
}
-
-/*
- * @implemented
- */
-UINT
-WINAPI
-WinExec(LPCSTR lpCmdLine,
- UINT uCmdShow)
-{
- STARTUPINFOA StartupInfo;
- PROCESS_INFORMATION ProcessInformation;
- DWORD dosErr;
-
- RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
- StartupInfo.cb = sizeof(STARTUPINFOA);
- StartupInfo.wShowWindow = (WORD)uCmdShow;
- StartupInfo.dwFlags = 0;
-
- if (!CreateProcessA(NULL,
- (PVOID)lpCmdLine,
- NULL,
- NULL,
- FALSE,
- 0,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation))
- {
- dosErr = GetLastError();
- return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
- }
-
- if (NULL != lpfnGlobalRegisterWaitForInputIdle)
- {
- lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,
- 10000);
- }
-
- NtClose(ProcessInformation.hProcess);
- NtClose(ProcessInformation.hThread);
-
- return 33; /* Something bigger than 31 means success. */
-}
-
-
/*
* @implemented
*/
VOID
WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
-{
- lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
- return;
+RegisterWaitForInputIdle(IN WaitForInputIdleType lpfnRegisterWaitForInputIdle)
+{
+ /* Write the global function pointer */
+ UserWaitForInputIdleRoutine = lpfnRegisterWaitForInputIdle;
}
/*
@@ -1576,19 +1549,16 @@
*/
VOID
WINAPI
-GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
+GetStartupInfoW(IN LPSTARTUPINFOW lpStartupInfo)
{
PRTL_USER_PROCESS_PARAMETERS Params;
- if (lpStartupInfo == NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return;
- }
-
+ /* Get the process parameters */
Params = NtCurrentPeb()->ProcessParameters;
+ /* Copy the data out of there */
lpStartupInfo->cb = sizeof(STARTUPINFOW);
+ lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
lpStartupInfo->dwX = Params->StartingX;
@@ -1603,298 +1573,393 @@
lpStartupInfo->cbReserved2 = Params->RuntimeData.Length;
lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
- lpStartupInfo->hStdInput = Params->StandardInput;
- lpStartupInfo->hStdOutput = Params->StandardOutput;
- lpStartupInfo->hStdError = Params->StandardError;
-}
-
+ /* Check if the standard handles are being used for other features */
+ if (lpStartupInfo->dwFlags & (STARTF_USESTDHANDLES |
+ STARTF_USEHOTKEY |
+ STARTF_SHELLPRIVATE))
+ {
+ /* These are, so copy the standard handles too */
+ lpStartupInfo->hStdInput = Params->StandardInput;
+ lpStartupInfo->hStdOutput = Params->StandardOutput;
+ lpStartupInfo->hStdError = Params->StandardError;
+ }
+}
/*
* @implemented
*/
VOID
WINAPI
-GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
+GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo)
{
PRTL_USER_PROCESS_PARAMETERS Params;
- ANSI_STRING AnsiString;
-
- if (lpStartupInfo == NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return;
- }
-
- Params = NtCurrentPeb ()->ProcessParameters;
-
- RtlAcquirePebLock ();
-
- /* FIXME - not thread-safe */
- if (lpLocalStartupInfo == NULL)
- {
- /* create new local startup info (ansi) */
- lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(STARTUPINFOA));
- if (lpLocalStartupInfo == NULL)
- {
- RtlReleasePebLock();
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return;
- }
-
- lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
-
- /* copy window title string */
- RtlUnicodeStringToAnsiString(&AnsiString,
- &Params->WindowTitle,
- TRUE);
- lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
-
- /* copy desktop info string */
- RtlUnicodeStringToAnsiString(&AnsiString,
- &Params->DesktopInfo,
- TRUE);
- lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
-
- /* copy shell info string */
- RtlUnicodeStringToAnsiString(&AnsiString,
- &Params->ShellInfo,
- TRUE);
- lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
-
- lpLocalStartupInfo->dwX = Params->StartingX;
- lpLocalStartupInfo->dwY = Params->StartingY;
- lpLocalStartupInfo->dwXSize = Params->CountX;
- lpLocalStartupInfo->dwYSize = Params->CountY;
- lpLocalStartupInfo->dwXCountChars = Params->CountCharsX;
- lpLocalStartupInfo->dwYCountChars = Params->CountCharsY;
- lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute;
- lpLocalStartupInfo->dwFlags = Params->WindowFlags;
- lpLocalStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
- lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length;
- lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
-
- lpLocalStartupInfo->hStdInput = Params->StandardInput;
- lpLocalStartupInfo->hStdOutput = Params->StandardOutput;
- lpLocalStartupInfo->hStdError = Params->StandardError;
- }
-
- RtlReleasePebLock();
-
- /* copy local startup info data to external startup info */
- memcpy(lpStartupInfo,
- lpLocalStartupInfo,
- sizeof(STARTUPINFOA));
-}
-
+ ANSI_STRING TitleString, ShellString, DesktopString;
+ LPSTARTUPINFOA StartupInfo;
+ NTSTATUS Status;
+
+ /* Get the cached information as well as the PEB parameters */
+ StartupInfo = BaseAnsiStartupInfo;
+ Params = NtCurrentPeb()->ProcessParameters;
+
+ /* Check if this is the first time we have to get the cached version */
+ while (!StartupInfo)
+ {
+ /* Create new ANSI startup info */
+ StartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(*StartupInfo));
+ if (StartupInfo)
+ {
+ /* Zero out string pointers in case we fail to create them */
+ StartupInfo->lpReserved = 0;
+ StartupInfo->lpDesktop = 0;
+ StartupInfo->lpTitle = 0;
+
+ /* Set the size */
+ StartupInfo->cb = sizeof(*StartupInfo);
+
+ /* Copy what's already stored in the PEB */
+ StartupInfo->dwX = Params->StartingX;
+ StartupInfo->dwY = Params->StartingY;
+ StartupInfo->dwXSize = Params->CountX;
+ StartupInfo->dwYSize = Params->CountY;
+ StartupInfo->dwXCountChars = Params->CountCharsX;
+ StartupInfo->dwYCountChars = Params->CountCharsY;
+ StartupInfo->dwFillAttribute = Params->FillAttribute;
+ StartupInfo->dwFlags = Params->WindowFlags;
+ StartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
+ StartupInfo->cbReserved2 = Params->RuntimeData.Length;
+ StartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
+ StartupInfo->hStdInput = Params->StandardInput;
+ StartupInfo->hStdOutput = Params->StandardOutput;
+ StartupInfo->hStdError = Params->StandardError;
+
+ /* Copy shell info string */
+ Status = RtlUnicodeStringToAnsiString(&ShellString,
+ &Params->ShellInfo,
+ TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Save it */
+ StartupInfo->lpReserved = ShellString.Buffer;
+
+ /* Copy desktop info string */
+ Status = RtlUnicodeStringToAnsiString(&DesktopString,
+ &Params->DesktopInfo,
+ TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Save it */
+ StartupInfo->lpDesktop = DesktopString.Buffer;
+
+ /* Copy window title string */
+ Status = RtlUnicodeStringToAnsiString(&TitleString,
+ &Params->WindowTitle,
+ TRUE);
+ if (NT_SUCCESS(Status))
+ {
+ /* Save it */
+ StartupInfo->lpReserved = TitleString.Buffer;
+
+ /* We finished with the ANSI version, try to cache it */
+ if (!InterlockedCompareExchangePointer(&BaseAnsiStartupInfo,
+ StartupInfo,
+ NULL))
+ {
+ /* We were the first thread through, use the data */
+ break;
+ }
+
+ /* Someone beat us to it, use their data instead */
+ StartupInfo = BaseAnsiStartupInfo;
+ Status = STATUS_SUCCESS;
+
+ /* We're going to free our own stuff, but not raise */
+ RtlFreeAnsiString(&TitleString);
+ }
+ RtlFreeAnsiString(&DesktopString);
+ }
+ RtlFreeAnsiString(&ShellString);
+ }
+ RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo);
+ }
+ else
+ {
+ /* No memory, fail */
+ Status = STATUS_NO_MEMORY;
+ }
+
+ /* Raise an error unless we got here due to the race condition */
+ if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status);
+ }
+
+ /* Now copy from the cached ANSI version */
+ lpStartupInfo->cb = StartupInfo->cb;
+ lpStartupInfo->lpReserved = StartupInfo->lpReserved;
+ lpStartupInfo->lpDesktop = StartupInfo->lpDesktop;
+ lpStartupInfo->lpTitle = StartupInfo->lpTitle;
+ lpStartupInfo->dwX = StartupInfo->dwX;
+ lpStartupInfo->dwY = StartupInfo->dwY;
+ lpStartupInfo->dwXSize = StartupInfo->dwXSize;
+ lpStartupInfo->dwYSize = StartupInfo->dwYSize;
+ lpStartupInfo->dwXCountChars = StartupInfo->dwXCountChars;
+ lpStartupInfo->dwYCountChars = StartupInfo->dwYCountChars;
+ lpStartupInfo->dwFillAttribute = StartupInfo->dwFillAttribute;
+ lpStartupInfo->dwFlags = StartupInfo->dwFlags;
+ lpStartupInfo->wShowWindow = StartupInfo->wShowWindow;
+ lpStartupInfo->cbReserved2 = StartupInfo->cbReserved2;
+ lpStartupInfo->lpReserved2 = StartupInfo->lpReserved2;
+
+ /* Check if the shell is hijacking the handles for other features */
+ if (lpStartupInfo->dwFlags &
+ (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))
+ {
+ /* It isn't, so we can return the raw values */
+ lpStartupInfo->hStdInput = StartupInfo->hStdInput;
+ lpStartupInfo->hStdOutput = StartupInfo->hStdOutput;
+ lpStartupInfo->hStdError = StartupInfo->hStdError;
+ }
+ else
+ {
+ /* It is, so make sure nobody uses these as console handles */
+ lpStartupInfo->hStdInput = INVALID_HANDLE_VALUE;
+ lpStartupInfo->hStdOutput = INVALID_HANDLE_VALUE;
+ lpStartupInfo->hStdError = INVALID_HANDLE_VALUE;
+ }
+}
/*
* @implemented
*/
BOOL
WINAPI
-FlushInstructionCache(HANDLE hProcess,
- LPCVOID lpBaseAddress,
- SIZE_T dwSize)
-{
- NTSTATUS Status;
-
- Status = NtFlushInstructionCache(hProcess,
- (PVOID)lpBaseAddress,
- dwSize);
+FlushInstructionCache(IN HANDLE hProcess,
+ IN LPCVOID lpBaseAddress,
+ IN SIZE_T dwSize)
+{
+ NTSTATUS Status;
+
+ /* Call the native function */
+ Status = NtFlushInstructionCache(hProcess, (PVOID)lpBaseAddress, dwSize);
if (!NT_SUCCESS(Status))
{
+ /* Handle failure case */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* All good */
return TRUE;
}
-
/*
* @implemented
*/
VOID
WINAPI
-ExitProcess(UINT uExitCode)
+ExitProcess(IN UINT uExitCode)
{
CSR_API_MESSAGE CsrRequest;
- ULONG Request;
- NTSTATUS Status;
-
- /* kill sibling threads ... we want to be alone at this point */
- NtTerminateProcess(NULL, 0);
-
- /* unload all dll's */
- LdrShutdownProcess();
-
- /* notify csrss of process termination */
- Request = TERMINATE_PROCESS;
- Status = CsrClientCallServer(&CsrRequest,
- NULL,
- MAKE_CSR_API(Request, CSR_NATIVE),
- sizeof(CSR_API_MESSAGE));
- if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
- {
- DPRINT("Failed to tell csrss about terminating process\n");
- }
-
- NtTerminateProcess(NtCurrentProcess (),
- uExitCode);
+ ASSERT(!BaseRunningInServerProcess);
+
+ _SEH2_TRY
+ {
+ /* Acquire the PEB lock */
+ RtlAcquirePebLock();
+
+ /* Kill all the threads */
+ NtTerminateProcess(NULL, 0);
+
+ /* Unload all DLLs */
+ LdrShutdownProcess();
+
+ /* Notify Base Server of process termination */
+ CsrClientCallServer(&CsrRequest,
+ NULL,
+ MAKE_CSR_API(TERMINATE_PROCESS, CSR_NATIVE),
+ sizeof(CSR_API_MESSAGE));
+
+ /* Now do it again */
+ NtTerminateProcess(NtCurrentProcess(), uExitCode);
+ }
+ _SEH2_FINALLY
+ {
+ /* Release the PEB lock */
+ RtlReleasePebLock();
+ }
+ _SEH2_END;
/* should never get here */
ASSERT(0);
while(1);
}
-
/*
* @implemented
*/
BOOL
WINAPI
-TerminateProcess(HANDLE hProcess,
- UINT uExitCode)
-{
- NTSTATUS Status;
-
- if (hProcess == NULL)
- {
- return FALSE;
- }
-
- Status = NtTerminateProcess(hProcess, uExitCode);
+TerminateProcess(IN HANDLE hProcess,
+ IN UINT uExitCode)
+{
+ NTSTATUS Status;
+
+ /* Check if no handle was passed in */
+ if (!hProcess)
+ {
+ /* Set error code */
+ SetLastError(ERROR_INVALID_HANDLE);
+ }
+ else
+ {
+ /* Otherwise, try to terminate the process */
+ Status = NtTerminateProcess(hProcess, uExitCode);
+ if (NT_SUCCESS(Status)) return TRUE;
+
+ /* It failed, convert error code */
+ BaseSetLastNTError(Status);
+ }
+
+ /* This is the failure path */
+ return FALSE;
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+FatalAppExitA(UINT uAction,
+ LPCSTR lpMessageText)
+{
+ PUNICODE_STRING MessageTextU;
+ ANSI_STRING MessageText;
+ NTSTATUS Status;
+
+ /* Initialize the string using the static TEB pointer */
+ MessageTextU = &NtCurrentTeb()->StaticUnicodeString;
+ RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText);
+
+ /* Convert to unicode and just exit normally if this failed */
+ Status = RtlAnsiStringToUnicodeString(MessageTextU, &MessageText, FALSE);
+ if (!NT_SUCCESS(Status)) ExitProcess(0);
+
+ /* Call the Wide function */
+ FatalAppExitW(uAction, MessageTextU->Buffer);
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+FatalAppExitW(IN UINT uAction,
+ IN LPCWSTR lpMessageText)
+{
+ UNICODE_STRING UnicodeString;
+ ULONG Response;
+ NTSTATUS Status;
+
+ /* Setup the stirng to print out */
+ RtlInitUnicodeString(&UnicodeString, lpMessageText);
+
+ /* Display the hard error no matter what */
+ Status = NtRaiseHardError(STATUS_FATAL_APP_EXIT | HARDERROR_OVERRIDE_ERRORMODE,
+ 1,
+ 1,
+ (PULONG_PTR)&UnicodeString,
+ OptionOkCancel,
+ &Response);
+
+ /* Give the user a chance to abort */
+ if ((NT_SUCCESS(Status)) && (Response == ResponseCancel)) return;
+
+ /* Otherwise kill the process */
+ ExitProcess(0);
+}
+
+/*
+ * @implemented
+ */
+VOID
+WINAPI
+FatalExit(IN int ExitCode)
+{
+#if DBG
+ /* On Checked builds, Windows gives you a nice little debugger UI */
+ CHAR ch[2];
+ DbgPrint("FatalExit...\n");
+ DbgPrint("\n");
+
+ while (TRUE)
+ {
+ DbgPrompt( "A (Abort), B (Break), I (Ignore)? ", ch, sizeof(ch));
+ switch (ch[0])
+ {
+ case 'B': case 'b':
+ DbgBreakPoint();
+ break;
+
+ case 'A': case 'a':
+ ExitProcess(ExitCode);
+
+ case 'I': case 'i':
+ return;
+ }
+ }
+#endif
+ /* On other builds, just kill the process */
+ ExitProcess(ExitCode);
+}
+
+/*
+ * @implemented
+ */
+DWORD
+WINAPI
+GetPriorityClass(IN HANDLE hProcess)
+{
+ NTSTATUS Status;
+ PROCESS_PRIORITY_CLASS PriorityClass;
+
+ /* Query the kernel */
+ Status = NtQueryInformationProcess(hProcess,
+ ProcessPriorityClass,
+ &PriorityClass,
+ sizeof(PROCESS_PRIORITY_CLASS),
+ NULL);
if (NT_SUCCESS(Status))
{
- return TRUE;
- }
-
+ /* Handle the conversion from NT to Win32 classes */
+ switch (PriorityClass.PriorityClass)
+ {
+ case PROCESS_PRIORITY_CLASS_IDLE: return IDLE_PRIORITY_CLASS;
+ case PROCESS_PRIORITY_CLASS_BELOW_NORMAL: return
BELOW_NORMAL_PRIORITY_CLASS;
+ case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL: return
ABOVE_NORMAL_PRIORITY_CLASS;
+ case PROCESS_PRIORITY_CLASS_HIGH: return HIGH_PRIORITY_CLASS;
+ case PROCESS_PRIORITY_CLASS_REALTIME: return REALTIME_PRIORITY_CLASS;
+ case PROCESS_PRIORITY_CLASS_NORMAL: default: return NORMAL_PRIORITY_CLASS;
+ }
+ }
+
+ /* Failure path */
BaseSetLastNTError(Status);
return FALSE;
}
-
-/*
- * @unimplemented
- */
-VOID
-WINAPI
-FatalAppExitA(UINT uAction,
- LPCSTR lpMessageText)
-{
- UNICODE_STRING MessageTextU;
- ANSI_STRING MessageText;
-
- RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText);
-
- RtlAnsiStringToUnicodeString(&MessageTextU,
- &MessageText,
- TRUE);
-
- FatalAppExitW(uAction, MessageTextU.Buffer);
-
- RtlFreeUnicodeString(&MessageTextU);
-}
-
-
-/*
- * @unimplemented
- */
-VOID
-WINAPI
-FatalAppExitW(UINT uAction,
- LPCWSTR lpMessageText)
-{
- static const WCHAR szUser32[] = L"user32.dll\0";
-
- HMODULE hModule = GetModuleHandleW(szUser32);
- MessageBoxW_Proc pMessageBoxW = NULL;
-
- DPRINT1("AppExit\n");
-
- if (hModule)
- pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule,
"MessageBoxW");
-
- if (pMessageBoxW)
- pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK);
- else
- DPRINT1("%s\n", lpMessageText);
-
- ExitProcess(0);
-}
-
-
-/*
- * @implemented
- */
-VOID
-WINAPI
-FatalExit(int ExitCode)
-{
- ExitProcess(ExitCode);
-}
-
-
-/*
- * @implemented
- */
-DWORD
-WINAPI
-GetPriorityClass(HANDLE hProcess)
-{
- NTSTATUS Status;
- PROCESS_PRIORITY_CLASS PriorityClass;
-
- Status = NtQueryInformationProcess(hProcess,
- ProcessPriorityClass,
- &PriorityClass,
- sizeof(PROCESS_PRIORITY_CLASS),
- NULL);
- if(NT_SUCCESS(Status))
- {
- switch(PriorityClass.PriorityClass)
- {
- case PROCESS_PRIORITY_CLASS_IDLE:
- return IDLE_PRIORITY_CLASS;
-
- case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
- return BELOW_NORMAL_PRIORITY_CLASS;
-
- case PROCESS_PRIORITY_CLASS_NORMAL:
- return NORMAL_PRIORITY_CLASS;
-
- case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
- return ABOVE_NORMAL_PRIORITY_CLASS;
-
- case PROCESS_PRIORITY_CLASS_HIGH:
- return HIGH_PRIORITY_CLASS;
-
- case PROCESS_PRIORITY_CLASS_REALTIME:
- return REALTIME_PRIORITY_CLASS;
-
- default:
- return NORMAL_PRIORITY_CLASS;
- }
- }
-
- BaseSetLastNTError(Status);
- return FALSE;
-}
-
-
/*
* @implemented
*/
BOOL
WINAPI
-SetPriorityClass(HANDLE hProcess,
- DWORD dwPriorityClass)
-{
- NTSTATUS Status;
+SetPriorityClass(IN HANDLE hProcess,
+ IN DWORD dwPriorityClass)
+{
+ NTSTATUS Status;
+ PVOID State = NULL;
PROCESS_PRIORITY_CLASS PriorityClass;
+ /* Handle conversion from Win32 to NT priority classes */
switch (dwPriorityClass)
{
case IDLE_PRIORITY_CLASS:
@@ -1918,68 +1983,85 @@
break;
case REALTIME_PRIORITY_CLASS:
- PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
+ /* Try to acquire the privilege. If it fails, just use HIGH */
+ State = BasepIsRealtimeAllowed(TRUE);
+ PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
+ PriorityClass.PriorityClass += (State != NULL);
break;
default:
+ /* Unrecognized priority classes don't make it to the kernel */
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+ /* Send the request to the kernel, and don't touch the foreground flag */
PriorityClass.Foreground = FALSE;
-
Status = NtSetInformationProcess(hProcess,
ProcessPriorityClass,
&PriorityClass,
sizeof(PROCESS_PRIORITY_CLASS));
+
+ /* Release the privilege if we had it */
+ if (State) RtlReleasePrivilege(State);
if (!NT_SUCCESS(Status))
{
+ /* Handle error path */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* All done */
return TRUE;
}
-
/*
* @implemented
*/
DWORD
WINAPI
-GetProcessVersion(DWORD ProcessId)
+GetProcessVersion(IN DWORD ProcessId)
{
DWORD Version = 0;
- PIMAGE_NT_HEADERS NtHeader = NULL;
- IMAGE_NT_HEADERS NtHeaders;
- IMAGE_DOS_HEADER DosHeader;
+ PIMAGE_NT_HEADERS NtHeader;
+ PIMAGE_DOS_HEADER DosHeader;
+ PPEB Peb;
PROCESS_BASIC_INFORMATION ProcessBasicInfo;
- PVOID BaseAddress = NULL;
+ PVOID BaseAddress;
+ ULONG e_lfanew;
HANDLE ProcessHandle = NULL;
NTSTATUS Status;
- SIZE_T Count;
- PEB Peb;
-
+ USHORT VersionData[2];
+ BOOLEAN Result;
+
+ /* We'll be accessing stuff that can fault, so protect everything with SEH */
_SEH2_TRY
{
- if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
- {
- /* Caller's */
- BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
- NtHeader = RtlImageNtHeader(BaseAddress);
-
- Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion <<
16) |
- (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
+ /* It this an in-process or out-of-process request? */
+ if (!(ProcessId) || (GetCurrentProcessId() == ProcessId))
+ {
+ /* It's in-process, so just read our own header */
+ NtHeader = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
+ if (!NtHeader)
+ {
+ /* Unable to read the NT header, something is wrong here... */
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ goto Error;
+ }
+
+ /* Get the version straight out of the NT header */
+ Version = MAKELONG(NtHeader->OptionalHeader.MinorSubsystemVersion,
+ NtHeader->OptionalHeader.MajorSubsystemVersion);
}
else
{
- /* Other process */
+ /* Out-of-process, so open it */
ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
ProcessId);
-
if (!ProcessHandle) return 0;
+ /* Try to find out where its PEB lives */
Status = NtQueryInformationProcess(ProcessHandle,
ProcessBasicInformation,
&ProcessBasicInfo,
@@ -1987,65 +2069,64 @@
NULL);
if (!NT_SUCCESS(Status)) goto Error;
-
- Status = NtReadVirtualMemory(ProcessHandle,
- ProcessBasicInfo.PebBaseAddress,
- &Peb,
- sizeof(Peb),
- &Count);
-
- if (!NT_SUCCESS(Status) || Count != sizeof(Peb)) goto Error;
-
- memset(&DosHeader, 0, sizeof(DosHeader));
- Status = NtReadVirtualMemory(ProcessHandle,
- Peb.ImageBaseAddress,
- &DosHeader,
- sizeof(DosHeader),
- &Count);
-
- if (!NT_SUCCESS(Status) || Count != sizeof(DosHeader)) goto Error;
- if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) goto Error;
-
- memset(&NtHeaders, 0, sizeof(NtHeaders));
- Status = NtReadVirtualMemory(ProcessHandle,
- (char *)Peb.ImageBaseAddress +
DosHeader.e_lfanew,
- &NtHeaders,
- sizeof(NtHeaders),
- &Count);
-
- if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders)) goto Error;
- if (NtHeaders.Signature != IMAGE_NT_SIGNATURE) goto Error;
-
- Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
- NtHeaders.OptionalHeader.MajorSubsystemVersion);
+ Peb = ProcessBasicInfo.PebBaseAddress;
+
+ /* Now that we have the PEB, read the image base address out of it */
+ Result = ReadProcessMemory(ProcessHandle,
+ &Peb->ImageBaseAddress,
+ &BaseAddress,
+ sizeof(BaseAddress),
+ NULL);
+ if (!Result) goto Error;
+
+ /* Now read the e_lfanew (offset to NT header) from the base */
+ DosHeader = BaseAddress;
+ Result = ReadProcessMemory(ProcessHandle,
+ &DosHeader->e_lfanew,
+ &e_lfanew,
+ sizeof(e_lfanew),
+ NULL);
+ if (!Result) goto Error;
+
+ /* And finally, read the NT header itself by adding the offset */
+ NtHeader = (PVOID)((ULONG_PTR)BaseAddress + e_lfanew);
+ Result = ReadProcessMemory(ProcessHandle,
+
&NtHeader->OptionalHeader.MajorSubsystemVersion,
+ &VersionData,
+ sizeof(VersionData),
+ NULL);
+ if (!Result) goto Error;
+
+ /* Get the version straight out of the NT header */
+ Version = MAKELONG(VersionData[0], VersionData[1]);
Error:
- if (!NT_SUCCESS(Status))
- {
- BaseSetLastNTError(Status);
- }
+ /* If there was an error anywhere, set the last error */
+ if (!NT_SUCCESS(Status)) BaseSetLastNTError(Status);
}
}
_SEH2_FINALLY
{
+ /* Close the process handle */
if (ProcessHandle) CloseHandle(ProcessHandle);
}
_SEH2_END;
+ /* And return the version data */
return Version;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessIoCounters(HANDLE hProcess,
- PIO_COUNTERS lpIoCounters)
-{
- NTSTATUS Status;
-
+GetProcessIoCounters(IN HANDLE hProcess,
+ OUT PIO_COUNTERS lpIoCounters)
+{
+ NTSTATUS Status;
+
+ /* Query the kernel. Structures are identical, so let it do the copy too. */
Status = NtQueryInformationProcess(hProcess,
ProcessIoCounters,
lpIoCounters,
@@ -2053,25 +2134,27 @@
NULL);
if (!NT_SUCCESS(Status))
{
+ /* Handle error path */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* All done */
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessPriorityBoost(HANDLE hProcess,
- PBOOL pDisablePriorityBoost)
+GetProcessPriorityBoost(IN HANDLE hProcess,
+ OUT PBOOL pDisablePriorityBoost)
{
NTSTATUS Status;
ULONG PriorityBoost;
+ /* Query the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessPriorityBoost,
&PriorityBoost,
@@ -2079,78 +2162,85 @@
NULL);
if (NT_SUCCESS(Status))
{
- *pDisablePriorityBoost = PriorityBoost;
+ /* Convert from ULONG to a BOOL */
+ *pDisablePriorityBoost = PriorityBoost ? TRUE : FALSE;
return TRUE;
}
+ /* Handle error path */
BaseSetLastNTError(Status);
return FALSE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-SetProcessPriorityBoost(HANDLE hProcess,
- BOOL bDisablePriorityBoost)
-{
- NTSTATUS Status;
- ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting
values other than 1 and 0 */
-
+SetProcessPriorityBoost(IN HANDLE hProcess,
+ IN BOOL bDisablePriorityBoost)
+{
+ NTSTATUS Status;
+ ULONG PriorityBoost;
+
+ /* Enforce that this is a BOOL, and send it to the kernel as a ULONG */
+ PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE);
Status = NtSetInformationProcess(hProcess,
ProcessPriorityBoost,
&PriorityBoost,
sizeof(ULONG));
if (!NT_SUCCESS(Status))
{
+ /* Handle error path */
BaseSetLastNTError(Status);
return FALSE;
}
+ /* All done */
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessHandleCount(HANDLE hProcess,
- PDWORD pdwHandleCount)
+GetProcessHandleCount(IN HANDLE hProcess,
+ OUT PDWORD pdwHandleCount)
{
ULONG phc;
NTSTATUS Status;
+ /* Query the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessHandleCount,
&phc,
sizeof(ULONG),
NULL);
- if(NT_SUCCESS(Status))
- {
- *pdwHandleCount = phc;
- return TRUE;
- }
-
+ if (NT_SUCCESS(Status))
+ {
+ /* Copy the count and return sucecss */
+ *pdwHandleCount = phc;
+ return TRUE;
+ }
+
+ /* Handle error path */
BaseSetLastNTError(Status);
return FALSE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-IsWow64Process(HANDLE hProcess,
- PBOOL Wow64Process)
+IsWow64Process(IN HANDLE hProcess,
+ OUT PBOOL Wow64Process)
{
ULONG_PTR pbi;
NTSTATUS Status;
+ /* Query the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessWow64Information,
&pbi,
@@ -2158,12 +2248,13 @@
NULL);
if (!NT_SUCCESS(Status))
{
- SetLastError(RtlNtStatusToDosError(Status));
+ /* Handle error path */
+ BaseSetLastNTError(Status);
return FALSE;
}
+ /* Enforce this is a BOOL, and return success */
*Wow64Process = (pbi != 0);
-
return TRUE;
}
@@ -2174,10 +2265,8 @@
WINAPI
GetCommandLineA(VOID)
{
- DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer);
- return CommandLineStringA.Buffer;
-}
-
+ return BaseAnsiCommandLine.Buffer;
+}
/*
* @implemented
@@ -2186,8 +2275,7 @@
WINAPI
GetCommandLineW(VOID)
{
- DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer);
- return CommandLineStringW.Buffer;
+ return BaseUnicodeCommandLine.Buffer;
}
/*
@@ -2208,11 +2296,14 @@
(PVOID)lpBaseAddress,
lpBuffer,
nSize,
- lpNumberOfBytesRead);
+ &nSize);
+
+ /* In user-mode, this parameter is optional */
+ if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
if (!NT_SUCCESS(Status))
{
/* We failed */
- BaseSetLastNTError (Status);
+ BaseSetLastNTError(Status);
return FALSE;
}
@@ -2268,7 +2359,11 @@
lpBaseAddress,
(LPVOID)lpBuffer,
nSize,
- lpNumberOfBytesWritten);
+ &nSize);
+
+ /* In Win32, the parameter is optional, so handle this case */
+ if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
+
if (!NT_SUCCESS(Status))
{
/* We failed */
@@ -2283,7 +2378,7 @@
else
{
/* Check if we were read only */
- if ((OldValue & PAGE_NOACCESS) || (OldValue & PAGE_READONLY))
+ if (OldValue & (PAGE_NOACCESS | PAGE_READONLY))
{
/* Restore protection and fail */
NtProtectVirtualMemory(hProcess,
@@ -2292,7 +2387,9 @@
OldValue,
&OldValue);
BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
- return FALSE;
+
+ /* Note: This is what Windows returns and code depends on it */
+ return STATUS_ACCESS_VIOLATION;
}
/* Otherwise, do the write */
@@ -2300,7 +2397,10 @@
lpBaseAddress,
(LPVOID)lpBuffer,
nSize,
- lpNumberOfBytesWritten);
+ &nSize);
+
+ /* In Win32, the parameter is optional, so handle this case */
+ if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nSize;
/* And restore the protection */
NtProtectVirtualMemory(hProcess,
@@ -2312,7 +2412,9 @@
{
/* We failed */
BaseSetLastNTError(STATUS_ACCESS_VIOLATION);
- return FALSE;
+
+ /* Note: This is what Windows returns and code depends on it */
+ return STATUS_ACCESS_VIOLATION;
}
/* Flush the ITLB */
@@ -2334,7 +2436,7 @@
BOOL
WINAPI
ProcessIdToSessionId(IN DWORD dwProcessId,
- OUT DWORD *pSessionId)
+ OUT PDWORD pSessionId)
{
PROCESS_SESSION_INFORMATION SessionInformation;
OBJECT_ATTRIBUTES ObjectAttributes;
@@ -2342,61 +2444,43 @@
HANDLE ProcessHandle;
NTSTATUS Status;
+ /* Do a quick check if the pointer is not writable */
if (IsBadWritePtr(pSessionId, sizeof(DWORD)))
{
+ /* Fail fast */
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+ /* Open the process passed in by ID */
ClientId.UniqueProcess = UlongToHandle(dwProcessId);
ClientId.UniqueThread = 0;
-
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
-
Status = NtOpenProcess(&ProcessHandle,
PROCESS_QUERY_INFORMATION,
&ObjectAttributes,
&ClientId);
if (NT_SUCCESS(Status))
{
+ /* Query the session ID from the kernel */
Status = NtQueryInformationProcess(ProcessHandle,
ProcessSessionInformation,
&SessionInformation,
sizeof(SessionInformation),
NULL);
+
+ /* Close the handle and check if we suceeded */
NtClose(ProcessHandle);
-
if (NT_SUCCESS(Status))
{
+ /* Return the session ID */
*pSessionId = SessionInformation.SessionId;
return TRUE;
}
}
+ /* Set error code and fail */
BaseSetLastNTError(Status);
- return FALSE;
-}
-
-BOOL
-WINAPI
-SetProcessWorkingSetSizeEx(IN HANDLE hProcess,
- IN SIZE_T dwMinimumWorkingSetSize,
- IN SIZE_T dwMaximumWorkingSetSize,
- IN DWORD Flags)
-{
- STUB;
- return FALSE;
-}
-
-
-BOOL
-WINAPI
-GetProcessWorkingSetSizeEx(IN HANDLE hProcess,
- OUT PSIZE_T lpMinimumWorkingSetSize,
- OUT PSIZE_T lpMaximumWorkingSetSize,
- OUT PDWORD Flags)
-{
- STUB;
return FALSE;
}
@@ -3419,4 +3503,48 @@
NULL);
}
+/*
+ * @implemented
+ */
+UINT
+WINAPI
+WinExec(LPCSTR lpCmdLine,
+ UINT uCmdShow)
+{
+ STARTUPINFOA StartupInfo;
+ PROCESS_INFORMATION ProcessInformation;
+ DWORD dosErr;
+
+ RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
+ StartupInfo.cb = sizeof(STARTUPINFOA);
+ StartupInfo.wShowWindow = (WORD)uCmdShow;
+ StartupInfo.dwFlags = 0;
+
+ if (!CreateProcessA(NULL,
+ (PVOID)lpCmdLine,
+ NULL,
+ NULL,
+ FALSE,
+ 0,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation))
+ {
+ dosErr = GetLastError();
+ return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
+ }
+
+ if (NULL != UserWaitForInputIdleRoutine)
+ {
+ UserWaitForInputIdleRoutine(ProcessInformation.hProcess,
+ 10000);
+ }
+
+ NtClose(ProcessInformation.hProcess);
+ NtClose(ProcessInformation.hThread);
+
+ return 33; /* Something bigger than 31 means success. */
+}
+
/* EOF */
Modified: trunk/reactos/dll/win32/kernel32/include/kernel32.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/include…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/include/kernel32.h [iso-8859-1] Mon Jan 23 04:57:12
2012
@@ -158,7 +158,7 @@
extern BOOLEAN InWindows;
-extern WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
+extern WaitForInputIdleType UserWaitForInputIdleRoutine;
/* GLOBAL VARIABLES **********************************************************/
@@ -493,6 +493,13 @@
IN ULONG FileAttributes
);
+BOOL
+WINAPI
+BaseCheckForVDM(
+ IN HANDLE ProcessHandle,
+ OUT LPDWORD ExitCode
+);
+
/* FIXME: This is EXPORTED! It should go in an external kernel32.h header */
VOID
WINAPI
Modified: trunk/reactos/include/ndk/extypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/extypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/extypes.h [iso-8859-1] (original)
+++ trunk/reactos/include/ndk/extypes.h [iso-8859-1] Mon Jan 23 04:57:12 2012
@@ -127,9 +127,10 @@
#define PROFILE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | PROFILE_CONTROL)
//
-// Maximum Parameters for NtRaiseHardError
+// NtRaiseHardError-related parameters
//
#define MAXIMUM_HARDERROR_PARAMETERS 4
+#define HARDERROR_OVERRIDE_ERRORMODE 0x10000000
//
// Pushlock bits