[KERNEL32]: Reimplement BasePushProcessParameters for future extensibility, also cleanup some code paths and fix a few bugs.

[KERNEL32]: Add some more SXS and CSRSS structures.

svn path=/trunk/; revision=54986
This commit is contained in:
Alex Ionescu 2012-01-16 21:27:50 +00:00
parent e7f2a28453
commit 3b7a2e8b40
4 changed files with 278 additions and 119 deletions

View file

@ -774,57 +774,33 @@ BasepDuplicateAndWriteHandle(IN HANDLE ProcessHandle,
}
}
VOID
BOOLEAN
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
BasePushProcessParameters(IN HANDLE ProcessHandle,
IN PPEB Peb,
IN LPWSTR ApplicationPathName,
BasePushProcessParameters(IN ULONG ParameterFlags,
IN HANDLE ProcessHandle,
IN PPEB RemotePeb,
IN LPCWSTR ApplicationPathName,
IN LPWSTR lpCurrentDirectory,
IN LPWSTR lpCommandLine,
IN LPVOID lpEnvironment,
IN SIZE_T EnvSize,
IN LPSTARTUPINFOW StartupInfo,
IN DWORD CreationFlags,
IN BOOL InheritHandles)
IN BOOL InheritHandles,
IN ULONG ImageSubsystem,
IN PVOID AppCompatData,
IN ULONG AppCompatDataSize)
{
WCHAR FullPath[MAX_PATH + 5];
LPWSTR Remaining;
LPWSTR DllPathString;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PRTL_USER_PROCESS_PARAMETERS RemoteParameters = NULL;
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;
PWCHAR ScanChar;
ULONG EnviroSize;
SIZE_T Size;
UNICODE_STRING Desktop, Shell, Runtime, Title;
PPEB OurPeb = NtCurrentPeb();
LPVOID Environment = lpEnvironment;
BOOLEAN HavePebLock = FALSE, Result;
PPEB Peb = NtCurrentPeb();
DPRINT("BasePushProcessParameters\n");
/* Get the full path name */
@ -835,9 +811,14 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
if ((Size) && (Size <= (MAX_PATH + 4)))
{
/* Get the DLL Path */
DllPathString = BaseComputeProcessDllPath(ApplicationPathName,
Environment);
if (!DllPathString) return STATUS_NO_MEMORY;
DllPathString = BaseComputeProcessDllPath((LPWSTR)ApplicationPathName,
lpEnvironment);
if (!DllPathString)
{
/* Fail */
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Initialize Strings */
RtlInitUnicodeString(&DllPath, DllPathString);
@ -846,14 +827,18 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
else
{
/* Get the DLL Path */
DllPathString = BaseComputeProcessDllPath(FullPath, Environment);
if (!DllPathString) return STATUS_NO_MEMORY;
DllPathString = BaseComputeProcessDllPath(FullPath, lpEnvironment);
if (!DllPathString)
{
/* Fail */
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Initialize Strings */
RtlInitUnicodeString(&DllPath, DllPathString);
RtlInitUnicodeString(&ImageName, FullPath);
}
DPRINT("DllPath: %wZ, ImageName: %wZ\n", DllPath, ImageName);
/* Initialize Strings */
RtlInitUnicodeString(&CommandLine, lpCommandLine);
@ -889,38 +874,50 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
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))
{
DPRINT1("Failed to create process parameters!\n");
return Status;
}
if (!NT_SUCCESS(Status)) goto FailPath;
/* Clear the current directory handle if not inheriting */
if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
/* Check if the user passed in an environment */
if (lpEnvironment)
{
/* We should've made it part of the parameters block, enforce this */
ASSERT(ProcessParameters->Environment == lpEnvironment);
lpEnvironment = ProcessParameters->Environment;
}
else
{
/* The user did not, so use the one from the current PEB */
HavePebLock = TRUE;
RtlAcquirePebLock();
lpEnvironment = Peb->ProcessParameters->Environment;
}
/* Save pointer and start lookup */
Environment = ScanChar = ProcessParameters->Environment;
if (Environment)
ScanChar = lpEnvironment;
if (lpEnvironment)
{
/* Find the environment size */
while (*ScanChar) ScanChar += wcslen(ScanChar) + 1;
EnviroSize = (ULONG_PTR)ScanChar - (ULONG_PTR)Environment;
DPRINT("EnvironmentSize %ld\n", EnviroSize);
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;
@ -931,23 +928,25 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
&Size,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to allocate Environment Block\n");
return Status;
}
if (!NT_SUCCESS(Status)) goto FailPath;
/* Write the Environment Block */
Status = ZwWriteVirtualMemory(ProcessHandle,
ProcessParameters->Environment,
Environment,
lpEnvironment,
EnviroSize,
NULL);
if (!NT_SUCCESS(Status))
/* No longer need the PEB lock anymore */
if (HavePebLock)
{
DPRINT1("Failed to write Environment Block\n");
return Status;
/* Release it */
RtlReleasePebLock();
HavePebLock = FALSE;
}
/* Check if the write failed */
if (!NT_SUCCESS(Status)) goto FailPath;
}
/* Write new parameters */
@ -965,7 +964,6 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
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;
@ -987,17 +985,28 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
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)))
{
/* 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;
}
}
}
@ -1009,30 +1018,27 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
}
/* See if the first 1MB should be reserved */
if ((ULONG_PTR)ApplicationPathName & 1)
if (ParameterFlags & 1)
{
ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
}
/* See if the first 16MB should be reserved */
if ((ULONG_PTR)ApplicationPathName & 2)
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;
@ -1053,33 +1059,71 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
ProcessParameters,
ProcessParameters->Length,
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to write Parameters Block\n");
return Status;
}
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))
if (!NT_SUCCESS(Status)) goto FailPath;
/* Check if there's any app compat data to write */
RemoteAppCompatData = NULL;
if (AppCompatData)
{
DPRINT1("Failed to write Parameters Block\n");
return Status;
/* 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;
/* Write the application compatibility data */
Status = NtWriteVirtualMemory(ProcessHandle,
RemoteAppCompatData,
AppCompatData,
AppCompatDataSize,
NULL);
if (!NT_SUCCESS(Status)) goto FailPath;
}
/* 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;
/* FIXME: Write Peb->ImageSubSystem */
/* Now write Peb->ImageSubSystem */
if (ImageSubsystem)
{
NtWriteVirtualMemory(ProcessHandle,
&RemotePeb->ImageSubsystem,
&ImageSubsystem,
sizeof(ImageSubsystem),
NULL);
}
/* Success path */
Result = TRUE;
Quickie:
/* Cleanup */
if (HavePebLock) RtlReleasePebLock();
RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath.Buffer);
RtlDestroyProcessParameters(ProcessParameters);
DPRINT("Completed\n");
return STATUS_SUCCESS;
if (ProcessParameters) RtlDestroyProcessParameters(ProcessParameters);
return Result;
FailPath:
DPRINT1("Failure to create proecss parameters: %lx\n", Status);
BaseSetLastNTError(Status);
Result = FALSE;
goto Quickie;
}
VOID
@ -3058,17 +3102,21 @@ GetAppName:
/* Create Process Environment */
RemotePeb = ProcessBasicInfo.PebBaseAddress;
Status = BasePushProcessParameters(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))
@ -3076,13 +3124,6 @@ GetAppName:
RtlDestroyEnvironment(lpEnvironment);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not initialize Process Environment\n");
BaseSetLastNTError(Status);
goto Cleanup;
}
/* Close the section */
NtClose(hSection);
hSection = NULL;

View file

@ -450,6 +450,19 @@ typedef struct _BASE_MSG_SXS_HANDLES
LARGE_INTEGER ViewBase;
} BASE_MSG_SXS_HANDLES, *PBASE_MSG_SXS_HANDLES;
typedef struct _SXS_WIN32_NT_PATH_PAIR
{
PUNICODE_STRING Win32;
PUNICODE_STRING Nt;
} SXS_WIN32_NT_PATH_PAIR, *PSXS_WIN32_NT_PATH_PAIR;
typedef struct _SXS_OVERRIDE_MANIFEST
{
PCWCH Name;
PVOID Address;
ULONG Size;
} SXS_OVERRIDE_MANIFEST, *PSXS_OVERRIDE_MANIFEST;
NTSTATUS
NTAPI
BasepConfigureAppCertDlls(
@ -464,6 +477,15 @@ BasepConfigureAppCertDlls(
extern LIST_ENTRY BasepAppCertDllsList;
extern RTL_CRITICAL_SECTION gcsAppCert;
BOOL
WINAPI
BaseUpdateVDMEntry(
IN ULONG UpdateIndex,
IN OUT PHANDLE WaitHandle,
IN ULONG IndexInfo,
IN ULONG BinaryType
);
VOID
WINAPI
BaseMarkFileForDelete(
@ -471,3 +493,10 @@ BaseMarkFileForDelete(
IN ULONG FileAttributes
);
/* FIXME: This is EXPORTED! It should go in an external kernel32.h header */
VOID
WINAPI
BasepFreeAppCompatData(
IN PVOID AppCompatData,
IN PVOID AppCompatSxsData
);

View file

@ -1380,6 +1380,26 @@ typedef struct _RTL_TRACE_BLOCK
PVOID *Trace;
} RTL_TRACE_BLOCK, *PRTL_TRACE_BLOCK;
//
// Auto-Managed Rtl* String Buffer
//
typedef struct _RTL_BUFFER
{
PUCHAR Buffer;
PUCHAR StaticBuffer;
SIZE_T Size;
SIZE_T StaticSize;
SIZE_T ReservedForAllocatedSize;
PVOID ReservedForIMalloc;
} RTL_BUFFER, *PRTL_BUFFER;
typedef struct _RTL_UNICODE_STRING_BUFFER
{
UNICODE_STRING String;
RTL_BUFFER ByteBuffer;
WCHAR MinimumStaticBufferForTerminalNul;
} RTL_UNICODE_STRING_BUFFER, *PRTL_UNICODE_STRING_BUFFER;
#ifndef NTOS_MODE_USER
//

View file

@ -31,11 +31,46 @@ typedef struct
ULONG Dummy;
} CSRSS_CONNECT_PROCESS, *PCSRSS_CONNECT_PROCESS;
typedef struct _BASE_SXS_CREATEPROCESS_MSG
{
ULONG Flags;
ULONG ProcessParameterFlags;
HANDLE FileHandle;
UNICODE_STRING SxsWin32ExePath;
UNICODE_STRING SxsNtExePath;
SIZE_T OverrideManifestOffset;
ULONG OverrideManifestSize;
SIZE_T OverridePolicyOffset;
ULONG OverridePolicySize;
PVOID PEManifestAddress;
ULONG PEManifestSize;
UNICODE_STRING CultureFallbacks;
ULONG Unknown[7];
UNICODE_STRING AssemblyName;
} BASE_SXS_CREATEPROCESS_MSG, *PBASE_SXS_CREATEPROCESS_MSG;
typedef struct
{
HANDLE NewProcessId;
ULONG Flags;
BOOL bInheritHandles;
//
// NT-type structure (BASE_CREATEPROCESS_MSG)
//
HANDLE ProcessHandle;
HANDLE ThreadHandle;
CLIENT_ID ClientId;
ULONG CreationFlags;
ULONG VdmBinaryType;
ULONG VdmTask;
HANDLE hVDM;
BASE_SXS_CREATEPROCESS_MSG Sxs;
PVOID PebAddressNative;
ULONG PebAddressWow64;
USHORT ProcessorArchitecture;
//
// ReactOS Data
//
HANDLE NewProcessId;
ULONG Flags;
BOOL bInheritHandles;
} CSRSS_CREATE_PROCESS, *PCSRSS_CREATE_PROCESS;
typedef struct
@ -548,6 +583,38 @@ typedef struct
ULONG ExitCode;
} CSRSS_GET_VDM_EXIT_CODE, *PCSRSS_GET_VDM_EXIT_CODE;
typedef struct
{
ULONG iTask;
HANDLE ConsoleHandle;
ULONG BinaryType;
HANDLE WaitObjectForParent;
HANDLE StdIn;
HANDLE StdOut;
HANDLE StdErr;
ULONG CodePage;
ULONG dwCreationFlags;
PCHAR CmdLine;
PCHAR appName;
PCHAR PifFile;
PCHAR CurDirectory;
PCHAR Env;
ULONG EnvLen;
PVOID StartupInfo;
PCHAR Desktop;
ULONG DesktopLen;
PCHAR Title;
ULONG TitleLen;
PCHAR Reserved;
ULONG ReservedLen;
USHORT CmdLen;
USHORT AppLen;
USHORT PifLen;
USHORT CurDirectoryLen;
USHORT CurDrive;
USHORT VDMState;
} CSRSS_CHECK_VDM, *PCSRSS_CHECK_VDM;
#define CSR_API_MESSAGE_HEADER_SIZE(Type) (FIELD_OFFSET(CSR_API_MESSAGE, Data) + sizeof(Type))
#define CSRSS_MAX_WRITE_CONSOLE (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE))
#define CSRSS_MAX_WRITE_CONSOLE_OUTPUT_CHAR (LPC_MAX_DATA_LENGTH - CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR))
@ -632,6 +699,7 @@ typedef struct
#define SOUND_SENTRY (0x50)
#define UPDATE_VDM_ENTRY (0x51)
#define GET_VDM_EXIT_CODE (0x52)
#define CHECK_VDM (0x53)
/* Keep in sync with definition below. */
#define CSRSS_HEADER_SIZE (sizeof(PORT_MESSAGE) + sizeof(ULONG) + sizeof(NTSTATUS))
@ -718,6 +786,7 @@ typedef struct _CSR_API_MESSAGE
CSRSS_SOUND_SENTRY SoundSentryRequest;
CSRSS_UPDATE_VDM_ENTRY UpdateVdmEntry;
CSRSS_GET_VDM_EXIT_CODE GetVdmExitCode;
CSRSS_CHECK_VDM CheckVdm;
} Data;
} CSR_API_MESSAGE, *PCSR_API_MESSAGE;