#define NDEBUG
#include <debug.h>
+/* GLOBALS *******************************************************************/
-typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
+WaitForInputIdleType UserWaitForInputIdleRoutine;
+UNICODE_STRING BaseUnicodeCommandLine;
+ANSI_STRING BaseAnsiCommandLine;
+UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
+LPSTARTUPINFOA BaseAnsiStartupInfo = NULL;
+PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
+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] =
+{
+ {
+ BasepConfigureAppCertDlls,
+ 1,
+ L"AppCertDlls",
+ &BasepAppCertDllsList,
+ 0,
+ NULL,
+ 0
+ }
+};
-/* GLOBALS *******************************************************************/
+PSAFER_REPLACE_PROCESS_THREAD_TOKENS g_SaferReplaceProcessThreadTokens;
+HMODULE gSaferHandle = (HMODULE)-1;
-static UNICODE_STRING CommandLineStringW;
-static ANSI_STRING CommandLineStringA;
+VOID WINAPI
+RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
-static BOOL bCommandLineInitialized = FALSE;
+#define CMD_STRING L"cmd /c "
-WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
+/* FUNCTIONS ****************************************************************/
-LPSTARTUPINFOA lpLocalStartupInfo = NULL;
+VOID
+WINAPI
+StuffStdHandle(IN HANDLE ProcessHandle,
+ IN HANDLE StandardHandle,
+ IN PHANDLE Address)
+{
+ NTSTATUS Status;
+ HANDLE DuplicatedHandle;
+ SIZE_T Dummy;
-VOID WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
+ /* Duplicate the handle */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ StandardHandle,
+ ProcessHandle,
+ &DuplicatedHandle,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES,
+ 0,
+ 0);
+ if (NT_SUCCESS(Status))
+ {
+ /* Write it */
+ NtWriteVirtualMemory(ProcessHandle,
+ Address,
+ &DuplicatedHandle,
+ sizeof(HANDLE),
+ &Dummy);
+ }
+}
-UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
-PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry;
+BOOLEAN
+WINAPI
+BuildSubSysCommandLine(IN LPWSTR SubsystemName,
+ IN LPWSTR ApplicationName,
+ IN LPWSTR CommandLine,
+ OUT PUNICODE_STRING SubsysCommandLine)
+{
+ UNICODE_STRING CommandLineString, ApplicationNameString;
+ PWCHAR Buffer;
+ ULONG Length;
+
+ /* Convert to unicode strings */
+ RtlInitUnicodeString(&CommandLineString, ApplicationName);
+ RtlInitUnicodeString(&ApplicationNameString, CommandLine);
+
+ /* Allocate buffer for the output string */
+ Length = CommandLineString.MaximumLength + ApplicationNameString.MaximumLength + 32;
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
+ RtlInitEmptyUnicodeString(SubsysCommandLine, Buffer, Length);
+ if (!Buffer)
+ {
+ /* Fail, no memory */
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return FALSE;
+ }
-#define CMD_STRING L"cmd /c "
+ /* Build the final subsystem command line */
+ RtlAppendUnicodeToString(SubsysCommandLine, SubsystemName);
+ RtlAppendUnicodeStringToString(SubsysCommandLine, &CommandLineString);
+ RtlAppendUnicodeToString(SubsysCommandLine, L" /C ");
+ RtlAppendUnicodeStringToString(SubsysCommandLine, &ApplicationNameString);
+ return TRUE;
+}
+
+BOOLEAN
+WINAPI
+BasepIsImageVersionOk(IN ULONG ImageMajorVersion,
+ IN ULONG ImageMinorVersion)
+{
+ /* Accept images for NT 3.1 or higher, as long as they're not newer than us */
+ return ((ImageMajorVersion >= 3) &&
+ ((ImageMajorVersion != 3) ||
+ (ImageMinorVersion >= 10)) &&
+ (ImageMajorVersion <= SharedUserData->NtMajorVersion) &&
+ ((ImageMajorVersion != SharedUserData->NtMajorVersion) ||
+ (ImageMinorVersion <= SharedUserData->NtMinorVersion)));
+}
+
+NTSTATUS
+WINAPI
+BasepCheckWebBladeHashes(IN HANDLE FileHandle)
+{
+ NTSTATUS Status;
+ CHAR Hash[16];
+
+ /* Get all the MD5 hashes */
+ Status = RtlComputeImportTableHash(FileHandle, Hash, 1);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Depending on which suite this is, run a bsearch and block the appropriate ones */
+ if (SharedUserData->SuiteMask & VER_SUITE_COMPUTE_SERVER)
+ {
+ DPRINT1("Egad! This is a ReactOS Compute Server and we should prevent you from using certain APIs...but we won't.");
+ }
+ else if (SharedUserData->SuiteMask & VER_SUITE_STORAGE_SERVER)
+ {
+ DPRINT1("Gasp! This is a ReactOS Storage Server and we should prevent you from using certain APIs...but we won't.");
+ }
+ else if (SharedUserData->SuiteMask & VER_SUITE_BLADE)
+ {
+ DPRINT1("Golly! This is a ReactOS Web Blade Server and we should prevent you from using certain APIs...but we won't.");
+ }
+
+ /* Actually, fuck it, don't block anything, we're open source */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+BasepSaveAppCertRegistryValue(IN PLIST_ENTRY List,
+ IN PWCHAR ComponentName,
+ IN PWCHAR DllName)
+{
+ /* Pretty much the only thing this key is used for, is malware */
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+BasepConfigureAppCertDlls(IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext)
+{
+ /* Add this to the certification list */
+ return BasepSaveAppCertRegistryValue(Context, ValueName, ValueData);
+}
+
+NTSTATUS
+WINAPI
+BasepIsProcessAllowed(IN PCHAR ApplicationName)
+{
+ NTSTATUS Status;
+ PWCHAR Buffer;
+ UINT Length;
+ HMODULE TrustLibrary;
+ PBASEP_APPCERT_ENTRY Entry;
+ ULONG CertFlag;
+ PLIST_ENTRY NextEntry;
+ HANDLE KeyHandle;
+ UNICODE_STRING CertKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls");
+ OBJECT_ATTRIBUTES KeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&CertKey, OBJ_CASE_INSENSITIVE);
+
+ /* Try to initialize the certification subsystem */
+ while (!g_AppCertInitialized)
+ {
+ /* Defaults */
+ Status = STATUS_SUCCESS;
+ Buffer = NULL;
+
+ /* Acquire the lock while initializing and see if we lost a race */
+ RtlEnterCriticalSection(&gcsAppCert);
+ if (g_AppCertInitialized) break;
+
+ /* On embedded, there is a special DLL */
+ if (SharedUserData->SuiteMask & VER_SUITE_EMBEDDEDNT)
+ {
+ /* Allocate a buffer for the name */
+ Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ MAX_PATH * sizeof(WCHAR) +
+ sizeof(UNICODE_NULL));
+ if (!Buffer)
+ {
+ /* Fail if no memory */
+ Status = STATUS_NO_MEMORY;
+ }
+ else
+ {
+ /* Now get the system32 directory in our buffer, make sure it fits */
+ Length = GetSystemDirectoryW(Buffer, MAX_PATH - sizeof("EmbdTrst.DLL"));
+ if ((Length) && (Length <= MAX_PATH - sizeof("EmbdTrst.DLL")))
+ {
+ /* Add a slash if needed, and add the embedded cert DLL name */
+ if (Buffer[Length - 1] != '\\') Buffer[Length++] = '\\';
+ RtlCopyMemory(&Buffer[Length],
+ L"EmbdTrst.DLL",
+ sizeof(L"EmbdTrst.DLL"));
+
+ /* Try to load it */
+ TrustLibrary = LoadLibraryW(Buffer);
+ if (TrustLibrary)
+ {
+ /* And extract the special function out of it */
+ fEmbeddedCertFunc = (PVOID)GetProcAddress(TrustLibrary,
+ "ImageOkToRunOnEmbeddedNT");
+ }
+ }
+
+ /* If we didn't get this far, set a failure code */
+ if (!fEmbeddedCertFunc) Status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else
+ {
+ /* Other systems have a registry entry for this */
+ Status = NtOpenKey(&KeyHandle, KEY_READ, &KeyAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Close it, we'll query it through Rtl */
+ NtClose(KeyHandle);
+
+ /* Do the query, which will call a special callback */
+ Status = RtlQueryRegistryValues(2,
+ L"Session Manager",
+ BasepAppCertTable,
+ 0,
+ 0);
+ if (Status == 0xC0000034) Status = STATUS_SUCCESS;
+ }
+ }
+
+ /* Free any buffer if we had one */
+ if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+
+ /* Check for errors, or a missing embedded/custom certification DLL */
+ if (!NT_SUCCESS(Status) ||
+ (!(fEmbeddedCertFunc) && (IsListEmpty(&BasepAppCertDllsList))))
+ {
+ /* The subsystem is not active on this machine, so give up */
+ g_HaveAppCerts = FALSE;
+ g_AppCertStatus = Status;
+ }
+ else
+ {
+ /* We have certification DLLs active, remember this */
+ g_HaveAppCerts = TRUE;
+ }
+
+ /* We are done the initialization phase, release the lock */
+ g_AppCertInitialized = TRUE;
+ RtlLeaveCriticalSection(&gcsAppCert);
+ }
+
+ /* If there's no certification DLLs present, return the failure code */
+ if (!g_HaveAppCerts) return g_AppCertStatus;
+
+ /* Otherwise, assume success and make sure we have *something* */
+ ASSERT(fEmbeddedCertFunc || !IsListEmpty(&BasepAppCertDllsList));
+ Status = STATUS_SUCCESS;
+
+ /* If the something is an embedded certification DLL, call it and return */
+ if (fEmbeddedCertFunc) return fEmbeddedCertFunc(ApplicationName);
+
+ /* Otherwise we have custom certification DLLs, parse them */
+ NextEntry = BasepAppCertDllsList.Flink;
+ CertFlag = 2;
+ while (NextEntry != &BasepAppCertDllsList)
+ {
+ /* Make sure the entry has a callback */
+ Entry = CONTAINING_RECORD(NextEntry, BASEP_APPCERT_ENTRY, Entry);
+ ASSERT(Entry->fPluginCertFunc != NULL);
+
+ /* Call it and check if it failed */
+ Status = Entry->fPluginCertFunc(ApplicationName, 1);
+ if (!NT_SUCCESS(Status)) CertFlag = 3;
+
+ /* Move on */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Now loop them again */
+ NextEntry = BasepAppCertDllsList.Flink;
+ while (NextEntry != &BasepAppCertDllsList)
+ {
+ /* Make sure the entry has a callback */
+ Entry = CONTAINING_RECORD(NextEntry, BASEP_APPCERT_ENTRY, Entry);
+ ASSERT(Entry->fPluginCertFunc != NULL);
+
+ /* Call it, this time with the flag from the loop above */
+ Status = Entry->fPluginCertFunc(ApplicationName, CertFlag);
+ }
+
+ /* All done, return the status */
+ return Status;
+}
+
+NTSTATUS
+WINAPI
+BasepReplaceProcessThreadTokens(IN HANDLE TokenHandle,
+ IN HANDLE ProcessHandle,
+ IN HANDLE ThreadHandle)
+{
+ NTSTATUS Status;
+ ANSI_STRING SaferiReplaceProcessThreadTokens = RTL_CONSTANT_STRING("SaferiReplaceProcessThreadTokens");
+
+ /* Enter the application certification lock */
+ RtlEnterCriticalSection(&gcsAppCert);
+
+ /* Check if we already know the function */
+ if (g_SaferReplaceProcessThreadTokens)
+ {
+ /* Call it */
+ Status = g_SaferReplaceProcessThreadTokens(TokenHandle,
+ ProcessHandle,
+ ThreadHandle) ?
+ STATUS_SUCCESS :
+ STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* Check if the app certification DLL isn't loaded */
+ if (!(gSaferHandle) ||
+ (gSaferHandle == (HMODULE)-1) ||
+ (gSaferHandle == (HMODULE)-2))
+ {
+ /* Then we can't call the function */
+ Status = STATUS_ENTRYPOINT_NOT_FOUND;
+ }
+ else
+ {
+ /* We have the DLL, find the address of the Safer function */
+ Status = LdrGetProcedureAddress(gSaferHandle,
+ &SaferiReplaceProcessThreadTokens,
+ 0,
+ (PVOID*)&g_SaferReplaceProcessThreadTokens);
+ if (NT_SUCCESS(Status))
+ {
+ /* Found it, now call it */
+ Status = g_SaferReplaceProcessThreadTokens(TokenHandle,
+ ProcessHandle,
+ ThreadHandle) ?
+ STATUS_SUCCESS :
+ STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* We couldn't find it, so this must be an unsupported DLL */
+ LdrUnloadDll(gSaferHandle);
+ gSaferHandle = NULL;
+ Status = STATUS_ENTRYPOINT_NOT_FOUND;
+ }
+ }
+ }
+
+ /* Release the lock and return the result */
+ RtlLeaveCriticalSection(&gcsAppCert);
+ return Status;
+}
-extern __declspec(noreturn)
VOID
-CALLBACK
-ConsoleControlDispatcher(DWORD CodeAndFlag);
+WINAPI
+BasepSxsCloseHandles(IN PBASE_MSG_SXS_HANDLES Handles)
+{
+ NTSTATUS Status;
-/* FUNCTIONS ****************************************************************/
+ /* Sanity checks */
+ ASSERT(Handles != NULL);
+ ASSERT(Handles->Process == NULL || Handles->Process == NtCurrentProcess());
+
+ /* Close the file handle */
+ if (Handles->File)
+ {
+ Status = NtClose(Handles->File);
+ ASSERT(NT_SUCCESS(Status));
+ }
+
+ /* Close the section handle */
+ if (Handles->Section)
+ {
+ Status = NtClose(Handles->Section);
+ ASSERT(NT_SUCCESS(Status));
+ }
+
+ /* Unmap the section view */
+ if (Handles->ViewBase.QuadPart)
+ {
+ Status = NtUnmapViewOfSection(NtCurrentProcess(),
+ (PVOID)Handles->ViewBase.LowPart);
+ ASSERT(NT_SUCCESS(Status));
+ }
+}
static
LONG BaseExceptionFilter(EXCEPTION_POINTERS *ExceptionInfo)
{
LONG ExceptionDisposition = EXCEPTION_EXECUTE_HANDLER;
+ LPTOP_LEVEL_EXCEPTION_FILTER RealFilter;
+ RealFilter = RtlDecodePointer(GlobalTopLevelExceptionFilter);
- if (GlobalTopLevelExceptionFilter != NULL)
+ if (RealFilter != NULL)
{
_SEH2_TRY
{
- ExceptionDisposition = GlobalTopLevelExceptionFilter(ExceptionInfo);
+ ExceptionDisposition = RealFilter(ExceptionInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_END;
}
if ((ExceptionDisposition == EXCEPTION_CONTINUE_SEARCH || ExceptionDisposition == EXCEPTION_EXECUTE_HANDLER) &&
- GlobalTopLevelExceptionFilter != UnhandledExceptionFilter)
+ RealFilter != UnhandledExceptionFilter)
{
ExceptionDisposition = UnhandledExceptionFilter(ExceptionInfo);
}
WINAPI
BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress)
{
- UINT uExitCode = 0;
-
DPRINT("BaseProcessStartup(..) - setting up exception frame.\n");
_SEH2_TRY
sizeof(PPROCESS_START_ROUTINE));
/* Call the Start Routine */
- uExitCode = (lpStartAddress)();
+ ExitThread(lpStartAddress());
}
_SEH2_EXCEPT(BaseExceptionFilter(_SEH2_GetExceptionInformation()))
{
- /* Get the SEH Error */
- uExitCode = _SEH2_GetExceptionCode();
+ /* Get the Exit code from the SEH Handler */
+ if (!BaseRunningInServerProcess)
+ {
+ /* Kill the whole process, usually */
+ ExitProcess(_SEH2_GetExceptionCode());
+ }
+ else
+ {
+ /* If running inside CSRSS, kill just this thread */
+ ExitThread(_SEH2_GetExceptionCode());
+ }
}
_SEH2_END;
-
- /* Exit the Process with our error */
- ExitProcess(uExitCode);
-}
-
-/*
- * Tells CSR that a new process was created
- */
-NTSTATUS
-WINAPI
-BasepNotifyCsrOfCreation(ULONG dwCreationFlags,
- IN HANDLE ProcessId,
- IN BOOL InheritHandles)
-{
- ULONG Request = CREATE_PROCESS;
- CSR_API_MESSAGE CsrRequest;
- NTSTATUS Status;
-
- DPRINT("BasepNotifyCsrOfCreation: Process: %lx, Flags %lx\n",
- ProcessId, dwCreationFlags);
-
- /* Fill out the request */
- CsrRequest.Data.CreateProcessRequest.NewProcessId = ProcessId;
- CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
- CsrRequest.Data.CreateProcessRequest.bInheritHandles = InheritHandles;
-
- /* Call CSR */
- Status = CsrClientCallServer(&CsrRequest,
- NULL,
- MAKE_CSR_API(Request, CSR_NATIVE),
- sizeof(CSR_API_MESSAGE));
- if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
- {
- DPRINT1("Failed to tell csrss about new process\n");
- return CsrRequest.Status;
- }
-
- /* Return Success */
- return STATUS_SUCCESS;
}
NTSTATUS
sizeof(CSR_API_MESSAGE));
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
- DPRINT1("Failed to tell csrss about new thread\n");
+ DPRINT1("Failed to tell csrss about new thread: %lx %lx\n", Status, CsrRequest.Status);
return CsrRequest.Status;
}
BasepCreateFirstThread(HANDLE ProcessHandle,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
PSECTION_IMAGE_INFORMATION SectionImageInfo,
- PCLIENT_ID ClientId)
+ PCLIENT_ID ClientId,
+ BOOLEAN InheritHandles,
+ DWORD dwCreationFlags)
{
OBJECT_ATTRIBUTES LocalObjectAttributes;
POBJECT_ATTRIBUTES ObjectAttributes;
INITIAL_TEB InitialTeb;
NTSTATUS Status;
HANDLE hThread;
-
+ ULONG Request = CREATE_PROCESS;
+ CSR_API_MESSAGE CsrRequest;
DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle);
/* Create the Thread's Stack */
- BasepCreateStack(ProcessHandle,
+ BaseCreateStack(ProcessHandle,
SectionImageInfo->MaximumStackSize,
SectionImageInfo->CommittedStackSize,
&InitialTeb);
/* Create the Thread's Context */
- BasepInitializeContext(&Context,
+ BaseInitializeContext(&Context,
NtCurrentPeb(),
SectionImageInfo->TransferAddress,
InitialTeb.StackBase,
0);
/* Convert the thread attributes */
- ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
+ ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
lpThreadAttributes,
NULL);
{
return NULL;
}
-
- Status = BasepNotifyCsrOfThread(hThread, ClientId);
- if (!NT_SUCCESS(Status))
+
+ /* Fill out the request to notify CSRSS */
+ CsrRequest.Data.CreateProcessRequest.ClientId = *ClientId;
+ CsrRequest.Data.CreateProcessRequest.ProcessHandle = ProcessHandle;
+ CsrRequest.Data.CreateProcessRequest.ThreadHandle = hThread;
+ CsrRequest.Data.CreateProcessRequest.CreationFlags = dwCreationFlags;
+ CsrRequest.Data.CreateProcessRequest.bInheritHandles = InheritHandles;
+
+ /* Call CSR */
+ Status = CsrClientCallServer(&CsrRequest,
+ NULL,
+ MAKE_CSR_API(Request, CSR_NATIVE),
+ sizeof(CSR_API_MESSAGE));
+ if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
{
- ASSERT(FALSE);
+ DPRINT1("Failed to tell csrss about new process: %lx %lx\n", Status, CsrRequest.Status);
+ return NULL;
}
-
+
/* Success */
return hThread;
}
else if(dwCreationFlags & REALTIME_PRIORITY_CLASS)
{
/* Check for Privilege First */
- if (BasepCheckRealTimePrivilege())
+ if (BasepIsRealtimeAllowed(TRUE))
{
ReturnClass = PROCESS_PRIORITY_CLASS_REALTIME;
}
}
}
-VOID
-NTAPI
-BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry,
- IN PVOID Context,
- OUT BOOLEAN *StopEnumeration)
-{
- /* Make sure we get Entry, Context and valid StopEnumeration pointer */
- ASSERT(Entry);
- ASSERT(Context);
- ASSERT(StopEnumeration);
-
- /* If entry is already found - signal to stop */
- if (BasepExeLdrEntry)
- {
- /* Signal to stop enumeration and return */
- *StopEnumeration = TRUE;
- return;
- }
-
- /* We don't have a exe ldr entry, so try to see if this one is ours
- by matching base address */
- if (Entry->DllBase == Context)
- {
- /* It matches, so remember the ldr entry */
- BasepExeLdrEntry = Entry;
-
- /* And stop enumeration */
- *StopEnumeration = TRUE;
- }
-}
-
-LPWSTR
+BOOLEAN
WINAPI
-BasepGetProcessPath(DWORD Reserved,
- LPWSTR FullPath,
- PVOID Environment)
+BasePushProcessParameters(IN ULONG ParameterFlags,
+ IN HANDLE ProcessHandle,
+ IN PPEB RemotePeb,
+ IN LPCWSTR ApplicationPathName,
+ IN LPWSTR lpCurrentDirectory,
+ IN LPWSTR lpCommandLine,
+ IN LPVOID lpEnvironment,
+ IN LPSTARTUPINFOW StartupInfo,
+ IN DWORD CreationFlags,
+ IN BOOL InheritHandles,
+ IN ULONG ImageSubsystem,
+ IN PVOID AppCompatData,
+ IN ULONG AppCompatDataSize)
{
+ WCHAR FullPath[MAX_PATH + 5];
+ PWCHAR Remaining, DllPathString, ScanChar;
+ PRTL_USER_PROCESS_PARAMETERS ProcessParameters, RemoteParameters;
+ PVOID RemoteAppCompatData;
+ UNICODE_STRING DllPath, ImageName, CommandLine, CurrentDirectory;
+ UNICODE_STRING Desktop, Shell, Runtime, Title;
NTSTATUS Status;
- LPWSTR AllocatedPath = NULL, ch;
- ULONG DefaultLength = BaseDefaultPath.Length;
- ULONG AppLength = 0;
- UNICODE_STRING EnvPath;
- LPWSTR NamePtr;
- LPWSTR PathBuffer;
- BOOLEAN SecondAttempt = FALSE;
+ ULONG EnviroSize;
+ SIZE_T Size;
+ BOOLEAN HavePebLock = FALSE, Result;
PPEB Peb = NtCurrentPeb();
- if (!Environment) RtlAcquirePebLock();
-
- /* Query PATH env var into append path */
- Status = RtlQueryEnvironmentVariable_U(Environment,
- &BasePathVariableName,
- &BaseDefaultPathAppend);
- if (NT_SUCCESS(Status))
- {
- /* Add up PATH environment length */
- DefaultLength += BaseDefaultPathAppend.Length;
- }
- else if (Status == STATUS_BUFFER_TOO_SMALL)
- {
- /* We have to allocate path dynamically */
- AllocatedPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, BaseDefaultPathAppend.Length + sizeof(UNICODE_NULL));
-
- if (AllocatedPath)
+ /* Get the full path name */
+ Size = GetFullPathNameW(ApplicationPathName,
+ MAX_PATH + 4,
+ FullPath,
+ &Remaining);
+ if ((Size) && (Size <= (MAX_PATH + 4)))
+ {
+ /* Get the DLL Path */
+ DllPathString = BaseComputeProcessDllPath(FullPath, lpEnvironment);
+ if (!DllPathString)
{
- /* Set up EnvPath */
- EnvPath.Buffer = AllocatedPath;
- EnvPath.Length = BaseDefaultPathAppend.Length + sizeof(UNICODE_NULL);
- EnvPath.MaximumLength = EnvPath.Length;
-
- /* Query PATH env var into newly allocated path */
- Status = RtlQueryEnvironmentVariable_U(Environment,
- &BasePathVariableName,
- &EnvPath);
-
- if (NT_SUCCESS(Status))
- {
- DefaultLength += EnvPath.Length;
- }
- else
- {
- /* Free newly allocated path, it didn't work */
- RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
- AllocatedPath = NULL;
- Status = STATUS_NO_MEMORY;
- }
+ /* Fail */
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
}
- }
-
-secondattempt:
- if (!FullPath)
- {
- /* Initialize BasepExeLdrEntry if necessary */
- if (!BasepExeLdrEntry)
- LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, Peb->ImageBaseAddress);
-
- DPRINT("Found BasepExeLdrEntry %wZ\n", &BasepExeLdrEntry->FullDllName);
- /* Set name pointer to the full dll path */
- NamePtr = BasepExeLdrEntry->FullDllName.Buffer;
+ /* Initialize Strings */
+ RtlInitUnicodeString(&DllPath, DllPathString);
+ RtlInitUnicodeString(&ImageName, FullPath);
}
else
{
- /* Set name pointer to the provided path */
- NamePtr = FullPath;
- }
-
- /* Determine application path length */
- if (NamePtr)
- {
- ch = NamePtr;
- while (*ch)
+ /* Couldn't get the path name. Just take the original path */
+ DllPathString = BaseComputeProcessDllPath((LPWSTR)ApplicationPathName,
+ lpEnvironment);
+ if (!DllPathString)
{
- /* Check if there is a slash */
- if (*ch == L'\\')
- {
- /* Update app length */
- AppLength = (ULONG_PTR)ch - (ULONG_PTR)NamePtr + sizeof(WCHAR);
- }
-
- ch++;
+ /* Fail */
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
}
- }
-
- /* Now check, if we found a valid path in the provided full path */
- if (!AppLength && FullPath && !SecondAttempt)
- {
- /* We were provided with a bad full path, retry again using just this app's path */
- FullPath = NULL;
- SecondAttempt = TRUE;
- goto secondattempt;
- }
-
- /* Allocate the path buffer */
- PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DefaultLength + AppLength + 2*sizeof(WCHAR));
- if (!PathBuffer)
- {
- /* Fail */
- if (!Environment) RtlReleasePebLock();
- if (AllocatedPath) RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
- return NULL;
- }
-
- /* Copy contents there */
- if (AppLength)
- {
- /* Remove trailing slashes if it's not root dir */
- if (AppLength != 3*sizeof(WCHAR))
- AppLength -= sizeof(WCHAR);
-
- /* Copy contents */
- RtlMoveMemory(PathBuffer, NamePtr, AppLength);
- }
-
- /* Release the lock */
- if (!Environment) RtlReleasePebLock();
-
- /* Finish preparing the path string */
- NamePtr = &PathBuffer[AppLength / sizeof(WCHAR)];
-
- /* Put a separating ";" if something was added */
- if (AppLength)
- {
- *NamePtr = L';';
- NamePtr++;
- }
-
- if (AllocatedPath)
- {
- /* Dynamically allocated env path, copy from the static buffer,
- concatenate with dynamic buffer and free it */
- RtlMoveMemory(NamePtr, BaseDefaultPath.Buffer, BaseDefaultPath.Length);
- RtlMoveMemory(&NamePtr[BaseDefaultPath.Length / sizeof(WCHAR)], AllocatedPath, EnvPath.Length);
- /* Free it */
- RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
+ /* Initialize Strings */
+ RtlInitUnicodeString(&DllPath, DllPathString);
+ RtlInitUnicodeString(&ImageName, ApplicationPathName);
}
- else
- {
- /* Static env path string, copy directly from BaseDefaultPath */
- RtlMoveMemory(NamePtr, BaseDefaultPath.Buffer, DefaultLength);
- }
-
- /* Null terminate the string */
- NamePtr[DefaultLength / sizeof(WCHAR)] = 0;
-
- return PathBuffer;
-}
-
-LPWSTR
-WINAPI
-BasepGetDllPath(LPWSTR FullPath,
- PVOID Environment)
-{
-#if 0
- LPWSTR DllPath = NULL;
-
- /* Acquire DLL directory lock */
- RtlEnterCriticalSection(&BaseDllDirectoryLock);
-
- /* Check if we have a base dll directory */
- if (BaseDllDirectory.Buffer)
- {
- /* Then get process path */
- DllPath = BasepGetProcessPath(0, FullPath, Environment);
-
- /* Release DLL directory lock */
- RtlLeaveCriticalSection(&BaseDllDirectoryLock);
-
- /* Return dll path */
- return DllPath;
- }
-
- /* Release DLL directory lock */
- RtlLeaveCriticalSection(&BaseDllDirectoryLock);
-
- /* There is no base DLL directory */
- UNIMPLEMENTED;
-
- /* Return dll path */
- return DllPath;
-#else
- return BasepGetProcessPath(0, FullPath, Environment);
-#endif
-}
-
-VOID
-WINAPI
-BasepCopyHandles(IN PRTL_USER_PROCESS_PARAMETERS Params,
- IN PRTL_USER_PROCESS_PARAMETERS PebParams,
- IN BOOL InheritHandles)
-{
- DPRINT("BasepCopyHandles %p %p, %d\n", Params, PebParams, InheritHandles);
-
- /* Copy the handle if we are inheriting or if it's a console handle */
- if (InheritHandles || IsConsoleHandle(PebParams->StandardInput))
- {
- Params->StandardInput = PebParams->StandardInput;
- }
- if (InheritHandles || IsConsoleHandle(PebParams->StandardOutput))
- {
- Params->StandardOutput = PebParams->StandardOutput;
- }
- if (InheritHandles || IsConsoleHandle(PebParams->StandardError))
- {
- Params->StandardError = PebParams->StandardError;
- }
-}
-
-NTSTATUS
-WINAPI
-BasepInitializeEnvironment(HANDLE ProcessHandle,
- PPEB Peb,
- LPWSTR ApplicationPathName,
- LPWSTR lpCurrentDirectory,
- LPWSTR lpCommandLine,
- LPVOID lpEnvironment,
- SIZE_T EnvSize,
- LPSTARTUPINFOW StartupInfo,
- DWORD CreationFlags,
- BOOL InheritHandles)
-{
- WCHAR FullPath[MAX_PATH];
- LPWSTR Remaining;
- LPWSTR DllPathString;
- PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
- PRTL_USER_PROCESS_PARAMETERS RemoteParameters = NULL;
- UNICODE_STRING DllPath, ImageName, CommandLine, CurrentDirectory;
- NTSTATUS Status;
- PWCHAR ScanChar;
- ULONG EnviroSize;
- SIZE_T Size;
- UNICODE_STRING Desktop, Shell, Runtime, Title;
- PPEB OurPeb = NtCurrentPeb();
- LPVOID Environment = lpEnvironment;
-
- DPRINT("BasepInitializeEnvironment\n");
-
- /* Get the full path name */
- GetFullPathNameW(ApplicationPathName,
- MAX_PATH,
- FullPath,
- &Remaining);
- DPRINT("ApplicationPathName: %S, FullPath: %S\n", ApplicationPathName,
- FullPath);
-
- /* Get the DLL Path */
- DllPathString = BasepGetDllPath(FullPath, Environment);
/* Initialize Strings */
- RtlInitUnicodeString(&DllPath, DllPathString);
- RtlInitUnicodeString(&ImageName, FullPath);
RtlInitUnicodeString(&CommandLine, lpCommandLine);
RtlInitUnicodeString(&CurrentDirectory, lpCurrentDirectory);
}
else
{
- RtlInitUnicodeString(&Title, L"");
+ RtlInitUnicodeString(&Title, ApplicationPathName);
}
/* This one is special because the length can differ */
Runtime.Buffer = (LPWSTR)StartupInfo->lpReserved2;
Runtime.MaximumLength = Runtime.Length = StartupInfo->cbReserved2;
+ /* Enforce no app compat data if the pointer was NULL */
+ if (!AppCompatData) AppCompatDataSize = 0;
+
/* Create the Parameter Block */
- DPRINT("Creating Process Parameters: %wZ %wZ %wZ %wZ %wZ %wZ %wZ\n",
- &ImageName, &DllPath, &CommandLine, &Desktop, &Title, &Shell,
- &Runtime);
+ ProcessParameters = NULL;
Status = RtlCreateProcessParameters(&ProcessParameters,
&ImageName,
&DllPath,
lpCurrentDirectory ?
&CurrentDirectory : NULL,
&CommandLine,
- Environment,
+ lpEnvironment,
&Title,
&Desktop,
&Shell,
&Runtime);
+ if (!NT_SUCCESS(Status)) goto FailPath;
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create process parameters!\n");
- return Status;
- }
+ /* Clear the current directory handle if not inheriting */
+ if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
- /* Check if we got an environment. If not, use ours */
- if (Environment)
+ /* Check if the user passed in an environment */
+ if (lpEnvironment)
{
- /* Save pointer and start lookup */
- Environment = ScanChar = ProcessParameters->Environment;
+ /* We should've made it part of the parameters block, enforce this */
+ ASSERT(ProcessParameters->Environment == lpEnvironment);
+ lpEnvironment = ProcessParameters->Environment;
}
else
{
- /* Save pointer and start lookup */
- Environment = ScanChar = OurPeb->ProcessParameters->Environment;
+ /* The user did not, so use the one from the current PEB */
+ HavePebLock = TRUE;
+ RtlAcquirePebLock();
+ lpEnvironment = Peb->ProcessParameters->Environment;
}
- /* Find the environment size */
- if (ScanChar)
+ /* Save pointer and start lookup */
+ ScanChar = lpEnvironment;
+ if (lpEnvironment)
{
- if (EnvSize && Environment == lpEnvironment)
- {
- /* its a converted ansi environment, bypass the length calculation */
- EnviroSize = EnvSize;
- }
- else
- {
- while (*ScanChar)
- {
- ScanChar += wcslen(ScanChar) + 1;
- }
-
- /* Calculate the size of the block */
- if (ScanChar == Environment)
- {
- EnviroSize = 2 * sizeof(WCHAR);
- }
- else
- {
- EnviroSize = (ULONG)((ULONG_PTR)ScanChar - (ULONG_PTR)Environment + sizeof(WCHAR));
- }
- }
- DPRINT("EnvironmentSize %ld\n", EnviroSize);
+ /* Find the environment size */
+ while ((ScanChar[0]) || (ScanChar[1])) ++ScanChar;
+ ScanChar += (2 * sizeof(UNICODE_NULL));
+ EnviroSize = (ULONG_PTR)ScanChar - (ULONG_PTR)lpEnvironment;
/* Allocate and Initialize new Environment Block */
Size = EnviroSize;
ProcessParameters->Environment = NULL;
- Status = ZwAllocateVirtualMemory(ProcessHandle,
+ Status = NtAllocateVirtualMemory(ProcessHandle,
(PVOID*)&ProcessParameters->Environment,
0,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status)) goto FailPath;
+
+ /* Write the Environment Block */
+ Status = NtWriteVirtualMemory(ProcessHandle,
+ ProcessParameters->Environment,
+ lpEnvironment,
+ EnviroSize,
+ NULL);
+
+ /* No longer need the PEB lock anymore */
+ if (HavePebLock)
{
- DPRINT1("Failed to allocate Environment Block\n");
- return(Status);
+ /* Release it */
+ RtlReleasePebLock();
+ HavePebLock = FALSE;
}
- /* Write the Environment Block */
- ZwWriteVirtualMemory(ProcessHandle,
- ProcessParameters->Environment,
- Environment,
- EnviroSize,
- NULL);
+ /* Check if the write failed */
+ if (!NT_SUCCESS(Status)) goto FailPath;
}
/* Write new parameters */
ProcessParameters->ShowWindowFlags = StartupInfo->wShowWindow;
/* Write the handles only if we have to */
- if (StartupInfo->dwFlags & STARTF_USESTDHANDLES)
+ if (StartupInfo->dwFlags &
+ (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))
{
- DPRINT("Using Standard Handles\n");
ProcessParameters->StandardInput = StartupInfo->hStdInput;
ProcessParameters->StandardOutput = StartupInfo->hStdOutput;
ProcessParameters->StandardError = StartupInfo->hStdError;
else
{
/* Inherit our Console Handle */
- ProcessParameters->ConsoleHandle = OurPeb->ProcessParameters->ConsoleHandle;
+ ProcessParameters->ConsoleHandle = Peb->ProcessParameters->ConsoleHandle;
- /* Is the shell trampling on our Handles? */
+ /* Make sure that the shell isn't trampling on our handles first */
if (!(StartupInfo->dwFlags &
- (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE)))
+ (STARTF_USESTDHANDLES | STARTF_USEHOTKEY | STARTF_SHELLPRIVATE)))
{
- /* Use handles from PEB, if inheriting or they are console */
- DPRINT("Copying handles from parent\n");
- BasepCopyHandles(ProcessParameters,
- OurPeb->ProcessParameters,
- InheritHandles);
+ /* Copy the handle if we are inheriting or if it's a console handle */
+ if ((InheritHandles) ||
+ (IsConsoleHandle(Peb->ProcessParameters->StandardInput)))
+ {
+ ProcessParameters->StandardInput = Peb->ProcessParameters->StandardInput;
+ }
+ if ((InheritHandles) ||
+ (IsConsoleHandle(Peb->ProcessParameters->StandardOutput)))
+ {
+ ProcessParameters->StandardOutput = Peb->ProcessParameters->StandardOutput;
+ }
+ if ((InheritHandles) ||
+ (IsConsoleHandle(Peb->ProcessParameters->StandardError)))
+ {
+ ProcessParameters->StandardError = Peb->ProcessParameters->StandardError;
+ }
}
}
/* Also set the Console Flag */
- if (CreationFlags & CREATE_NEW_PROCESS_GROUP)
+ if ((CreationFlags & CREATE_NEW_PROCESS_GROUP) &&
+ (!(CreationFlags & CREATE_NEW_CONSOLE)))
{
ProcessParameters->ConsoleFlags = 1;
}
+ /* See if the first 1MB should be reserved */
+ if (ParameterFlags & 1)
+ {
+ ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
+ }
+
+ /* See if the first 16MB should be reserved */
+ if (ParameterFlags & 2)
+ {
+ ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_16MB;
+ }
+
/* Allocate memory for the parameter block */
Size = ProcessParameters->Length;
+ RemoteParameters = NULL;
Status = NtAllocateVirtualMemory(ProcessHandle,
(PVOID*)&RemoteParameters,
0,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to allocate Parameters Block\n");
- return(Status);
- }
+ if (!NT_SUCCESS(Status)) goto FailPath;
/* Set the allocated size */
ProcessParameters->MaximumLength = Size;
/* Handle some Parameter Flags */
- ProcessParameters->ConsoleFlags = (CreationFlags & CREATE_NEW_PROCESS_GROUP);
ProcessParameters->Flags |= (CreationFlags & PROFILE_USER) ?
RTL_USER_PROCESS_PARAMETERS_PROFILE_USER : 0;
ProcessParameters->Flags |= (CreationFlags & PROFILE_KERNEL) ?
RTL_USER_PROCESS_PARAMETERS_PROFILE_KERNEL : 0;
ProcessParameters->Flags |= (CreationFlags & PROFILE_SERVER) ?
RTL_USER_PROCESS_PARAMETERS_PROFILE_SERVER : 0;
- ProcessParameters->Flags |= (NtCurrentPeb()->ProcessParameters->Flags &
+ ProcessParameters->Flags |= (Peb->ProcessParameters->Flags &
RTL_USER_PROCESS_PARAMETERS_DISABLE_HEAP_CHECKS);
/* Write the Parameter Block */
ProcessParameters,
ProcessParameters->Length,
NULL);
+ if (!NT_SUCCESS(Status)) goto FailPath;
/* Write the PEB Pointer */
Status = NtWriteVirtualMemory(ProcessHandle,
- &Peb->ProcessParameters,
+ &RemotePeb->ProcessParameters,
&RemoteParameters,
sizeof(PVOID),
NULL);
+ if (!NT_SUCCESS(Status)) goto FailPath;
- /* Cleanup */
- RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath.Buffer);
- RtlDestroyProcessParameters(ProcessParameters);
-
- DPRINT("Completed\n");
- return STATUS_SUCCESS;
-}
+ /* Check if there's any app compat data to write */
+ RemoteAppCompatData = NULL;
+ if (AppCompatData)
+ {
+ /* Allocate some space for the application compatibility data */
+ Size = AppCompatDataSize;
+ Status = NtAllocateVirtualMemory(ProcessHandle,
+ &RemoteAppCompatData,
+ 0,
+ &Size,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status)) goto FailPath;
-VOID
-WINAPI
-InitCommandLines(VOID)
-{
- PRTL_USER_PROCESS_PARAMETERS Params;
+ /* Write the application compatibility data */
+ Status = NtWriteVirtualMemory(ProcessHandle,
+ RemoteAppCompatData,
+ AppCompatData,
+ AppCompatDataSize,
+ NULL);
+ if (!NT_SUCCESS(Status)) goto FailPath;
+ }
- /* get command line */
- Params = NtCurrentPeb()->ProcessParameters;
- RtlNormalizeProcessParams (Params);
+ /* Write the PEB Pointer to the app compat data (might be NULL) */
+ Status = NtWriteVirtualMemory(ProcessHandle,
+ &RemotePeb->pShimData,
+ &RemoteAppCompatData,
+ sizeof(PVOID),
+ NULL);
+ if (!NT_SUCCESS(Status)) goto FailPath;
- /* 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)
+ /* Now write Peb->ImageSubSystem */
+ if (ImageSubsystem)
{
- return;
+ NtWriteVirtualMemory(ProcessHandle,
+ &RemotePeb->ImageSubsystem,
+ &ImageSubsystem,
+ sizeof(ImageSubsystem),
+ NULL);
}
- RtlInitAnsiString(&CommandLineStringA, NULL);
+ /* Success path */
+ Result = TRUE;
- /* Copy command line */
- RtlCopyUnicodeString(&CommandLineStringW,
- &(Params->CommandLine));
- CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0;
+Quickie:
+ /* Cleanup */
+ if (HavePebLock) RtlReleasePebLock();
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath.Buffer);
+ if (ProcessParameters) RtlDestroyProcessParameters(ProcessParameters);
+ return Result;
+FailPath:
+ DPRINT1("Failure to create proecss parameters: %lx\n", Status);
+ BaseSetLastNTError(Status);
+ Result = FALSE;
+ goto Quickie;
+}
- /* convert unicode string to ansi (or oem) */
- if (bIsFileApiAnsi)
- RtlUnicodeStringToAnsiString(&CommandLineStringA,
- &CommandLineStringW,
- TRUE);
- else
- RtlUnicodeStringToOemString(&CommandLineStringA,
- &CommandLineStringW,
- TRUE);
+VOID
+WINAPI
+InitCommandLines(VOID)
+{
+ NTSTATUS Status;
- CommandLineStringA.Buffer[CommandLineStringA.Length] = 0;
+ /* Read the UNICODE_STRING from the PEB */
+ BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
- bCommandLineInitialized = TRUE;
+ /* 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;
- }
-
+ /* Query information on the process from the kernel */
Status = NtQueryInformationProcess(hProcess,
ProcessBasicInformation,
(PVOID)&ProcessInfo,
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)
+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;
+ /* 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))
+ if (!(NT_SUCCESS(Status)) || !(NT_SUCCESS(CsrRequest.Status)))
{
- BaseSetLastNTError(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(DWORD dwLevel,
- DWORD dwFlags)
+SetProcessShutdownParameters(IN DWORD dwLevel,
+ IN DWORD dwFlags)
{
CSR_API_MESSAGE CsrRequest;
- ULONG Request;
NTSTATUS Status;
+ /* Write the data into the CSRSS request and send it */
CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
-
- Request = SET_SHUTDOWN_PARAMETERS;
Status = CsrClientCallServer(&CsrRequest,
NULL,
- MAKE_CSR_API(Request, CSR_NATIVE),
+ 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;
}
+ /* All went well */
return TRUE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-GetProcessWorkingSetSize(HANDLE hProcess,
- PSIZE_T lpMinimumWorkingSetSize,
- PSIZE_T lpMaximumWorkingSetSize)
+GetProcessWorkingSetSizeEx(IN HANDLE hProcess,
+ OUT PSIZE_T lpMinimumWorkingSetSize,
+ OUT PSIZE_T lpMaximumWorkingSetSize,
+ OUT PDWORD Flags)
{
- QUOTA_LIMITS QuotaLimits;
+ 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)
+GetProcessWorkingSetSize(IN HANDLE hProcess,
+ OUT PSIZE_T lpMinimumWorkingSetSize,
+ OUT PSIZE_T lpMaximumWorkingSetSize)
{
- QUOTA_LIMITS QuotaLimits;
- NTSTATUS Status;
-
- QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
- QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
+ DWORD Dummy;
+ return GetProcessWorkingSetSizeEx(hProcess,
+ lpMinimumWorkingSetSize,
+ lpMaximumWorkingSetSize,
+ &Dummy);
+}
- Status = NtSetInformationProcess(hProcess,
- ProcessQuotaLimits,
- &QuotaLimits,
- sizeof(QUOTA_LIMITS));
- if (!NT_SUCCESS(Status))
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+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
{
- BaseSetLastNTError(Status);
- return FALSE;
+ /* No limits, fail the call */
+ ReturnStatus = STATUS_INVALID_PARAMETER;
+ Result = FALSE;
}
- return TRUE;
+ /* 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(HANDLE hProcess,
- LPFILETIME lpCreationTime,
- LPFILETIME lpExitTime,
- LPFILETIME lpKernelTime,
- LPFILETIME lpUserTime)
+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,
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
*/
return (HANDLE)NtCurrentProcess();
}
-
/*
* @implemented
*/
return (HANDLE)NtCurrentThread();
}
-
/*
* @implemented
*/
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,
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,
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;
- HANDLE ProcessHandle;
- OBJECT_ATTRIBUTES ObjectAttributes;
- CLIENT_ID ClientId;
-
- ClientId.UniqueProcess = UlongToHandle(dwProcessId);
- ClientId.UniqueThread = 0;
-
- InitializeObjectAttributes(&ObjectAttributes,
- NULL,
- (bInheritHandle ? OBJ_INHERIT : 0),
- NULL,
- NULL);
-
- errCode = NtOpenProcess(&ProcessHandle,
- dwDesiredAccess,
- &ObjectAttributes,
- &ClientId);
- if (!NT_SUCCESS(errCode))
- {
- BaseSetLastNTError(errCode);
- return NULL;
- }
-
- return ProcessHandle;
-}
-
-
-/*
- * @implemented
- */
-UINT
-WINAPI
-WinExec(LPCSTR lpCmdLine,
- UINT uCmdShow)
+OpenProcess(IN DWORD dwDesiredAccess,
+ IN BOOL bInheritHandle,
+ IN DWORD dwProcessId)
{
- STARTUPINFOA StartupInfo;
- PROCESS_INFORMATION ProcessInformation;
- DWORD dosErr;
+ NTSTATUS Status;
+ HANDLE ProcessHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ CLIENT_ID ClientId;
- RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
- StartupInfo.cb = sizeof(STARTUPINFOA);
- StartupInfo.wShowWindow = (WORD)uCmdShow;
- StartupInfo.dwFlags = 0;
+ /* Setup the input client ID structure */
+ ClientId.UniqueProcess = UlongToHandle(dwProcessId);
+ ClientId.UniqueThread = 0;
- if (!CreateProcessA(NULL,
- (PVOID)lpCmdLine,
- NULL,
- NULL,
- FALSE,
- 0,
- NULL,
- NULL,
- &StartupInfo,
- &ProcessInformation))
- {
- dosErr = GetLastError();
- return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
- }
+ /* This is needed just to define the inheritance flags */
+ InitializeObjectAttributes(&ObjectAttributes,
+ NULL,
+ (bInheritHandle ? OBJ_INHERIT : 0),
+ NULL,
+ NULL);
- if (NULL != lpfnGlobalRegisterWaitForInputIdle)
+ /* Now try to open the process */
+ Status = NtOpenProcess(&ProcessHandle,
+ dwDesiredAccess,
+ &ObjectAttributes,
+ &ClientId);
+ if (!NT_SUCCESS(Status))
{
- lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,
- 10000);
+ /* Handle failure */
+ BaseSetLastNTError(Status);
+ return NULL;
}
- NtClose(ProcessInformation.hProcess);
- NtClose(ProcessInformation.hThread);
-
- return 33; /* Something bigger than 31 means success. */
+ /* Otherwise return a handle to the process */
+ return ProcessHandle;
}
-
/*
* @implemented
*/
VOID
WINAPI
-RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
+RegisterWaitForInputIdle(IN WaitForInputIdleType lpfnRegisterWaitForInputIdle)
{
- lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
- return;
+ /* Write the global function pointer */
+ UserWaitForInputIdleRoutine = lpfnRegisterWaitForInputIdle;
}
/*
*/
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;
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;
+ ANSI_STRING TitleString, ShellString, DesktopString;
+ LPSTARTUPINFOA StartupInfo;
+ NTSTATUS Status;
- RtlAcquirePebLock ();
+ /* Get the cached information as well as the PEB parameters */
+ StartupInfo = BaseAnsiStartupInfo;
+ Params = NtCurrentPeb()->ProcessParameters;
- /* FIXME - not thread-safe */
- if (lpLocalStartupInfo == NULL)
+ /* Check if this is the first time we have to get the cached version */
+ while (!StartupInfo)
{
- /* create new local startup info (ansi) */
- lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
- 0,
- sizeof(STARTUPINFOA));
- if (lpLocalStartupInfo == NULL)
+ /* Create new ANSI startup info */
+ StartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
+ 0,
+ sizeof(*StartupInfo));
+ if (StartupInfo)
{
- RtlReleasePebLock();
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return;
+ /* 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->lpTitle = 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;
}
- 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));
+ /* 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)
+FlushInstructionCache(IN HANDLE hProcess,
+ IN LPCVOID lpBaseAddress,
+ IN SIZE_T dwSize)
{
NTSTATUS Status;
- Status = NtFlushInstructionCache(hProcess,
- (PVOID)lpBaseAddress,
- dwSize);
+ /* 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;
+ ASSERT(!BaseRunningInServerProcess);
- /* kill sibling threads ... we want to be alone at this point */
- NtTerminateProcess(NULL, 0);
+ _SEH2_TRY
+ {
+ /* Acquire the PEB lock */
+ RtlAcquirePebLock();
- /* unload all dll's */
- LdrShutdownProcess();
+ /* Kill all the threads */
+ NtTerminateProcess(NULL, 0);
- /* 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))
+ /* Unload all DLLs */
+ LdrShutdownProcess();
+
+ /* Notify Base Server of process termination */
+ CsrRequest.Data.TerminateProcessRequest.uExitCode = uExitCode;
+ CsrClientCallServer(&CsrRequest,
+ NULL,
+ MAKE_CSR_API(TERMINATE_PROCESS, CSR_NATIVE),
+ sizeof(CSR_API_MESSAGE));
+
+ /* Now do it again */
+ NtTerminateProcess(NtCurrentProcess(), uExitCode);
+ }
+ _SEH2_FINALLY
{
- DPRINT("Failed to tell csrss about terminating process\n");
+ /* Release the PEB lock */
+ RtlReleasePebLock();
}
-
- NtTerminateProcess(NtCurrentProcess (),
- uExitCode);
+ _SEH2_END;
/* should never get here */
ASSERT(0);
while(1);
}
-
/*
* @implemented
*/
BOOL
WINAPI
-TerminateProcess(HANDLE hProcess,
- UINT uExitCode)
+TerminateProcess(IN HANDLE hProcess,
+ IN UINT uExitCode)
{
NTSTATUS Status;
- if (hProcess == NULL)
+ /* Check if no handle was passed in */
+ if (!hProcess)
{
- return FALSE;
+ /* Set error code */
+ SetLastError(ERROR_INVALID_HANDLE);
}
-
- Status = NtTerminateProcess(hProcess, uExitCode);
- if (NT_SUCCESS(Status))
+ else
{
- return TRUE;
+ /* Otherwise, try to terminate the process */
+ Status = NtTerminateProcess(hProcess, uExitCode);
+ if (NT_SUCCESS(Status)) return TRUE;
+
+ /* It failed, convert error code */
+ BaseSetLastNTError(Status);
}
- BaseSetLastNTError(Status);
+ /* This is the failure path */
return FALSE;
}
-
/*
- * @unimplemented
+ * @implemented
*/
VOID
WINAPI
FatalAppExitA(UINT uAction,
LPCSTR lpMessageText)
{
- UNICODE_STRING MessageTextU;
+ PUNICODE_STRING MessageTextU;
ANSI_STRING MessageText;
+ NTSTATUS Status;
+ /* Initialize the string using the static TEB pointer */
+ MessageTextU = &NtCurrentTeb()->StaticUnicodeString;
RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText);
- RtlAnsiStringToUnicodeString(&MessageTextU,
- &MessageText,
- TRUE);
+ /* Convert to unicode and just exit normally if this failed */
+ Status = RtlAnsiStringToUnicodeString(MessageTextU, &MessageText, FALSE);
+ if (!NT_SUCCESS(Status)) ExitProcess(0);
- FatalAppExitW(uAction, MessageTextU.Buffer);
-
- RtlFreeUnicodeString(&MessageTextU);
+ /* Call the Wide function */
+ FatalAppExitW(uAction, MessageTextU->Buffer);
}
-
/*
- * @unimplemented
+ * @implemented
*/
VOID
WINAPI
-FatalAppExitW(UINT uAction,
- LPCWSTR lpMessageText)
+FatalAppExitW(IN UINT uAction,
+ IN LPCWSTR lpMessageText)
{
- static const WCHAR szUser32[] = L"user32.dll\0";
-
- HMODULE hModule = GetModuleHandleW(szUser32);
- MessageBoxW_Proc pMessageBoxW = NULL;
+ UNICODE_STRING UnicodeString;
+ ULONG Response;
+ NTSTATUS Status;
- DPRINT1("AppExit\n");
+ /* Setup the stirng to print out */
+ RtlInitUnicodeString(&UnicodeString, lpMessageText);
- if (hModule)
- pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW");
+ /* Display the hard error no matter what */
+ Status = NtRaiseHardError(STATUS_FATAL_APP_EXIT | HARDERROR_OVERRIDE_ERRORMODE,
+ 1,
+ 1,
+ (PULONG_PTR)&UnicodeString,
+ OptionOkCancel,
+ &Response);
- if (pMessageBoxW)
- pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK);
- else
- DPRINT1("%s\n", lpMessageText);
+ /* Give the user a chance to abort */
+ if ((NT_SUCCESS(Status)) && (Response == ResponseCancel)) return;
+ /* Otherwise kill the process */
ExitProcess(0);
}
-
/*
* @implemented
*/
VOID
WINAPI
-FatalExit(int ExitCode)
+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(HANDLE hProcess)
+GetPriorityClass(IN HANDLE hProcess)
{
- NTSTATUS Status;
- PROCESS_PRIORITY_CLASS PriorityClass;
+ NTSTATUS Status;
+ PROCESS_PRIORITY_CLASS PriorityClass;
- Status = NtQueryInformationProcess(hProcess,
- ProcessPriorityClass,
- &PriorityClass,
- sizeof(PROCESS_PRIORITY_CLASS),
- NULL);
- if(NT_SUCCESS(Status))
- {
- switch(PriorityClass.PriorityClass)
+ /* Query the kernel */
+ Status = NtQueryInformationProcess(hProcess,
+ ProcessPriorityClass,
+ &PriorityClass,
+ sizeof(PROCESS_PRIORITY_CLASS),
+ NULL);
+ if (NT_SUCCESS(Status))
{
- 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;
+ /* 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;
+ }
}
- }
- BaseSetLastNTError(Status);
- return FALSE;
+ /* Failure path */
+ BaseSetLastNTError(Status);
+ return FALSE;
}
-
/*
* @implemented
*/
BOOL
WINAPI
-SetPriorityClass(HANDLE hProcess,
- DWORD dwPriorityClass)
+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:
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)
+ /* It this an in-process or out-of-process request? */
+ if (!(ProcessId) || (GetCurrentProcessId() == ProcessId))
{
- /* Caller's */
- BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
- NtHeader = RtlImageNtHeader(BaseAddress);
+ /* 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;
+ }
- Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
- (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
+ /* 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,
NULL);
if (!NT_SUCCESS(Status)) goto Error;
+ Peb = ProcessBasicInfo.PebBaseAddress;
- 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;
+ /* 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;
- Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
- NtHeaders.OptionalHeader.MajorSubsystemVersion);
+ /* 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)
+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,
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,
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)
+SetProcessPriorityBoost(IN HANDLE hProcess,
+ IN BOOL bDisablePriorityBoost)
{
NTSTATUS Status;
- ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
+ 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))
+ if (NT_SUCCESS(Status))
{
- *pdwHandleCount = phc;
- return TRUE;
+ /* 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,
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;
}
WINAPI
GetCommandLineA(VOID)
{
- DPRINT("CommandLine \'%s\'\n", CommandLineStringA.Buffer);
- return CommandLineStringA.Buffer;
+ return BaseAnsiCommandLine.Buffer;
}
-
/*
* @implemented
*/
WINAPI
GetCommandLineW(VOID)
{
- DPRINT("CommandLine \'%S\'\n", CommandLineStringW.Buffer);
- return CommandLineStringW.Buffer;
+ return BaseUnicodeCommandLine.Buffer;
}
/*
(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;
}
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 */
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,
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 */
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,
{
/* 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 */
BOOL
WINAPI
ProcessIdToSessionId(IN DWORD dwProcessId,
- OUT DWORD *pSessionId)
+ OUT PDWORD pSessionId)
{
PROCESS_SESSION_INFORMATION SessionInformation;
OBJECT_ATTRIBUTES ObjectAttributes;
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);
- NtClose(ProcessHandle);
+ /* 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;
-}
-
/*
* @implemented
*/
/* FIXME: Allow CREATE_SEPARATE only for WOW Apps, once we have that. */
/* Get some information about the executable */
- Status = ZwQuerySection(hSection,
+ Status = NtQuerySection(hSection,
SectionImageInformation,
&SectionImageInfo,
sizeof(SectionImageInfo),
}
/* Initialize the process object attributes */
- ObjectAttributes = BasepConvertObjectAttributes(&LocalObjectAttributes,
+ ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes,
lpProcessAttributes,
NULL);
/* Check if only this process will be debugged */
if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS)
{
- /* FIXME: Set process flag */
+ /* Set process flag */
+ hDebug = (HANDLE)((ULONG_PTR)hDebug | 0x1);
}
}
/* Create Process Environment */
RemotePeb = ProcessBasicInfo.PebBaseAddress;
- Status = BasepInitializeEnvironment(hProcess,
- RemotePeb,
- (LPWSTR)lpApplicationName,
- CurrentDirectory,
- (QuotesNeeded || CmdLineIsAppName || Escape) ?
- QuotedCmdLine : lpCommandLine,
- lpEnvironment,
- EnvSize,
- &StartupInfo,
- dwCreationFlags,
- bInheritHandles);
+ Ret = BasePushProcessParameters(0,
+ hProcess,
+ RemotePeb,
+ (LPWSTR)lpApplicationName,
+ CurrentDirectory,
+ (QuotesNeeded || CmdLineIsAppName || Escape) ?
+ QuotedCmdLine : lpCommandLine,
+ lpEnvironment,
+ &StartupInfo,
+ dwCreationFlags,
+ bInheritHandles,
+ 0,
+ NULL,
+ 0);
+ if (!Ret) goto Cleanup;
/* Cleanup Environment */
if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT))
RtlDestroyEnvironment(lpEnvironment);
}
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Could not initialize Process Environment\n");
- BaseSetLastNTError(Status);
- goto Cleanup;
- }
-
/* Close the section */
NtClose(hSection);
hSection = NULL;
&RemoteParameters->StandardError);
}
- /* Notify CSRSS */
- Status = BasepNotifyCsrOfCreation(dwCreationFlags,
- (HANDLE)ProcessBasicInfo.UniqueProcessId,
- bInheritHandles);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("CSR Notification Failed");
- BaseSetLastNTError(Status);
- goto Cleanup;
- }
-
/* Create the first thread */
DPRINT("Creating thread for process (EntryPoint = 0x%p)\n",
SectionImageInfo.TransferAddress);
hThread = BasepCreateFirstThread(hProcess,
lpThreadAttributes,
&SectionImageInfo,
- &ClientId);
+ &ClientId,
+ bInheritHandles,
+ dwCreationFlags);
if (hThread == NULL)
{
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 */