/* 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 }