Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

275 lines
8.2 KiB

/*
Cache handling functions for use in kernel32.dll
VadimB
*/
#include "basedll.h"
#include "ahcache.h"
#pragma hdrstop
BOOL
NTAPI
BaseCheckRunApp(
IN HANDLE FileHandle,
IN LPCWSTR pwszApplication,
IN PVOID pEnvironment,
IN USHORT uExeType,
IN DWORD dwReason,
OUT PVOID* ppData,
OUT PDWORD pcbData,
OUT PVOID* ppSxsData,
OUT PDWORD pcbSxsData,
OUT PDWORD pdwFusionFlags
)
{
#if defined(BUILD_WOW6432)
return NtWow64CsrBaseCheckRunApp(FileHandle,
pwszApplication,
pEnvironment,
uExeType,
dwReason,
ppData,
pcbData,
ppSxsData,
pcbSxsData,
pdwFusionFlags);
#else
BASE_API_MSG m;
PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG pMsg = &m.u.CheckApplicationCompatibility;
UNICODE_STRING EnvVar;
UNICODE_STRING EnvVarValue;
UNICODE_STRING ApplicationName;
NTSTATUS Status;
ULONG CaptureBufferSize;
ULONG CaptureEnvSize;
ULONG CountMessagePointers = 1; // at least the name of the app
PWCHAR pEnv;
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
BOOL bRunApp = TRUE;
INT i;
struct _VarDefinitions {
UNICODE_STRING Name;
UNICODE_STRING Value;
} rgImportantVariables[] = {
{ RTL_CONSTANT_STRING(L"SHIM_DEBUG_LEVEL") },
{ RTL_CONSTANT_STRING(L"SHIM_FILE_LOG") },
{ RTL_CONSTANT_STRING(L"__COMPAT_LAYER") },
{ RTL_CONSTANT_STRING(L"__PROCESS_HISTORY") }
};
pMsg->FileHandle = FileHandle;
pMsg->CacheCookie = dwReason;
pMsg->ExeType = uExeType;
pMsg->pEnvironment = NULL;
pMsg->pAppCompatData = NULL;
pMsg->cbAppCompatData = 0;
pMsg->pSxsData = NULL;
pMsg->cbSxsData = 0;
pMsg->bRunApp = TRUE; // optimistic please
pMsg->FusionFlags = 0;
RtlInitUnicodeString(&ApplicationName, pwszApplication);
pMsg->FileName.MaximumLength = ApplicationName.Length + sizeof(UNICODE_NULL);
CaptureBufferSize = 0;
CaptureEnvSize = 0;
for (i = 0; i < sizeof(rgImportantVariables)/sizeof(rgImportantVariables[0]); ++i) {
EnvVar.Buffer = NULL;
EnvVar.Length =
EnvVar.MaximumLength = 0;
Status = RtlQueryEnvironmentVariable_U(pEnvironment,
(PUNICODE_STRING)(&rgImportantVariables[i].Name),
&EnvVar);
if (Status == STATUS_BUFFER_TOO_SMALL) {
//
// variable is present, account for the buffer size
// length of the name string + length of the value string + '=' + null char
//
CaptureEnvSize += rgImportantVariables[i].Name.Length +
EnvVar.Length + sizeof(WCHAR) +
sizeof(UNICODE_NULL);
rgImportantVariables[i].Value.MaximumLength = EnvVar.Length + sizeof(UNICODE_NULL);
}
}
if (CaptureEnvSize != 0) {
CaptureEnvSize += sizeof(UNICODE_NULL);
++CountMessagePointers;
}
CaptureBufferSize = CaptureEnvSize + pMsg->FileName.MaximumLength;
//
// at this point we either have one or two parameters to place into the buffer
//
CaptureBuffer = CsrAllocateCaptureBuffer(CountMessagePointers,
CaptureBufferSize);
if (CaptureBuffer == NULL) {
DbgPrint("BaseCheckRunApp: Failed to allocate capture buffer size 0x%lx\n", CaptureBufferSize);
goto Cleanup;
}
//
// start allocating message data
//
CsrAllocateMessagePointer(CaptureBuffer,
pMsg->FileName.MaximumLength,
(PVOID)&pMsg->FileName.Buffer);
RtlCopyUnicodeString(&pMsg->FileName, &ApplicationName);
//
// now let's do our "mini-environment block"
//
if (CaptureEnvSize) {
CsrAllocateMessagePointer(CaptureBuffer,
CaptureEnvSize,
(PVOID)&pMsg->pEnvironment);
//
// loop through the vars and create mini-env
//
pEnv = pMsg->pEnvironment;
pMsg->EnvironmentSize = CaptureEnvSize;
for (i = 0; i < sizeof(rgImportantVariables)/sizeof(rgImportantVariables[0]); ++i) {
if (rgImportantVariables[i].Value.MaximumLength == 0) {
continue;
}
//
// we incorporate this variable
//
EnvVar.Buffer = pEnv;
EnvVar.Length = 0;
EnvVar.MaximumLength = (USHORT)CaptureEnvSize;
Status = RtlAppendUnicodeStringToString(&EnvVar, &rgImportantVariables[i].Name);
if (!NT_SUCCESS(Status)) {
//
// skip this one
//
continue;
}
Status = RtlAppendUnicodeToString(&EnvVar, L"=");
if (!NT_SUCCESS(Status)) {
continue;
}
//
// now query the variable
//
EnvVarValue.Buffer = pEnv + (EnvVar.Length / sizeof(WCHAR));
EnvVarValue.MaximumLength = (USHORT)(CaptureEnvSize - EnvVar.Length);
Status = RtlQueryEnvironmentVariable_U(pEnvironment,
(PUNICODE_STRING)&rgImportantVariables[i].Name,
&EnvVarValue);
if (!NT_SUCCESS(Status)) {
continue;
}
//
// make sure we're zero-terminated, adjust the size
//
CaptureEnvSize -= (EnvVar.Length + EnvVarValue.Length);
//
// zero-terminate, it may not be after an rt function call
//
if (CaptureEnvSize < sizeof(UNICODE_NULL) * 2) {
//
// can't zero-terminate
//
continue;
}
*(pEnv + (EnvVar.Length + EnvVarValue.Length) / sizeof(WCHAR)) = L'\0';
CaptureEnvSize -= sizeof(UNICODE_NULL);
pEnv += (EnvVar.Length + EnvVarValue.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
}
//
// we always slap another zero at the end please
//
if (CaptureEnvSize < sizeof(UNICODE_NULL)) {
//
// we cannot double-null terminate, forget the call then, we have failed to transport environment
// this situation however is impossible -- we will always have at least that much space left
//
goto Cleanup;
}
//
// this ensures our simple validation mechanism in server works
//
RtlZeroMemory(pEnv, CaptureEnvSize);
}
//
// we are ready to commence a csr call
//
Status = CsrClientCallServer((PCSR_API_MSG)&m,
CaptureBuffer,
CSR_MAKE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCheckApplicationCompatibility),
sizeof(*pMsg));
if (NT_SUCCESS(Status)) {
bRunApp = pMsg->bRunApp;
//
// pointers to the appcompat data
//
*ppData = pMsg->pAppCompatData;
*pcbData = pMsg->cbAppCompatData;
*ppSxsData = pMsg->pSxsData;
*pcbSxsData = pMsg->cbSxsData;
*pdwFusionFlags = pMsg->FusionFlags;
} else {
//
// dbg print here to indicate a failed csr call
//
DbgPrint("BaseCheckRunApp: failed to call csrss 0x%lx\n", Status);
}
Cleanup:
if (CaptureBuffer != NULL) {
CsrFreeCaptureBuffer(CaptureBuffer);
}
return bRunApp;
#endif
}