276 lines
8.2 KiB
C
276 lines
8.2 KiB
C
/*
|
|
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
|
|
}
|
|
|
|
|
|
|