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.
 
 
 
 
 
 

325 lines
9.7 KiB

#include "basesrv.h"
#include "ahcache.h"
#define SHIM_CACHE_NOT_FOUND 0x00000001
#define SHIM_CACHE_BYPASS 0x00000002 // bypass cache (either removable media or temp dir)
#define SHIM_CACHE_LAYER_ENV 0x00000004 // layer env variable set
#define SHIM_CACHE_MEDIA 0x00000008
#define SHIM_CACHE_TEMP 0x00000010
#define SHIM_CACHE_NOTAVAIL 0x00000020
#define SHIM_CACHE_UPDATE 0x00020000
#define SHIM_CACHE_ACTION 0x00010000
//
// Parameters:
// ExePath
// Environment Block (need __PROCESS_HISTORY and __COMPAT_LAYER)
// File Handle
//
BOOL
BasepSrvShimCacheUpdate(
IN PUNICODE_STRING FileName,
IN HANDLE FileHandle
)
/*++
Return: TRUE if we have a cache hit, FALSE otherwise.
Desc: Search the cache, return TRUE if we have a cache hit
pIndex will receive an index into the rgIndex array that contains
the entry which has been hit
So that if entry 5 contains the hit, and rgIndexes[3] == 5 then
*pIndex == 3
--*/
{
NTSTATUS Status;
AHCACHESERVICEDATA Data;
Data.FileName = *FileName;
Data.FileHandle = FileHandle;
Status = NtApphelpCacheControl(ApphelpCacheServiceUpdate,
&Data);
return NT_SUCCESS(Status);
}
BOOL
BasepSrvShimCacheRemoveEntry(
IN PUNICODE_STRING FileName
)
/*++
Return: TRUE.
Desc: Remove the entry from the cache.
We remove the entry by placing it as the last lru entry
and emptying the path. This routine assumes that the index
passed in is valid.
--*/
{
AHCACHESERVICEDATA Data;
NTSTATUS Status;
Data.FileName = *FileName;
Data.FileHandle = INVALID_HANDLE_VALUE;
Status = NtApphelpCacheControl(ApphelpCacheServiceRemove,
&Data);
return NT_SUCCESS(Status);
}
NTSTATUS
BasepSrvMarshallAppCompatData(
PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG pMsg,
HANDLE ClientProcessHandle,
PVOID pAppCompatData,
SIZE_T cbAppCompatData,
PVOID pSxsData,
SIZE_T cbSxsData,
SIZE_T FusionFlags
)
{
NTSTATUS Status = STATUS_SUCCESS;
SIZE_T cbData;
//
//
//
if (pAppCompatData) {
cbData = cbAppCompatData;
Status = NtAllocateVirtualMemory(ClientProcessHandle,
(PVOID*)&pMsg->pAppCompatData,
0,
&cbData,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
// we got the memory allocated, copy our data
Status = NtWriteVirtualMemory(ClientProcessHandle,
pMsg->pAppCompatData,
pAppCompatData,
cbAppCompatData,
NULL);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
pMsg->cbAppCompatData = (DWORD)cbAppCompatData;
}
if (pSxsData) {
cbData = cbSxsData;
Status = NtAllocateVirtualMemory(ClientProcessHandle,
(PVOID*)&pMsg->pSxsData,
0,
&cbData,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
// we got the memory allocated, copy our data
Status = NtWriteVirtualMemory(ClientProcessHandle,
pMsg->pSxsData,
pSxsData,
cbSxsData,
NULL);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
pMsg->cbSxsData = (DWORD)cbSxsData;
}
pMsg->FusionFlags = (DWORD)FusionFlags;
Cleanup:
if (!NT_SUCCESS(Status)) {
if (pMsg->pAppCompatData) {
NtFreeVirtualMemory(ClientProcessHandle,
(PVOID*)&pMsg->pAppCompatData,
&cbAppCompatData,
MEM_RELEASE);
pMsg->pAppCompatData = NULL;
pMsg->cbAppCompatData = 0;
}
if (pMsg->pAppCompatData) {
NtFreeVirtualMemory(ClientProcessHandle,
(PVOID*)&pMsg->pSxsData,
&cbSxsData,
MEM_RELEASE);
pMsg->pSxsData = NULL;
pMsg->cbSxsData = 0;
}
}
if (pAppCompatData) {
RtlFreeHeap(RtlProcessHeap(), 0, pAppCompatData);
}
if (pSxsData) {
RtlFreeHeap(RtlProcessHeap(), 0, pSxsData);
}
return Status;
}
NTSTATUS
BaseSrvCheckApplicationCompatibility(
IN OUT PCSR_API_MSG m,
IN OUT PCSR_REPLY_STATUS ReplyStatus
)
{
PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG pMsg = (PBASE_CHECK_APPLICATION_COMPATIBILITY_MSG)&m->u.ApiMessageData;
NTSTATUS Status;
BOOL bSuccess;
PCSR_THREAD ClientThread;
HANDLE ClientProcessHandle;
HANDLE FileHandle = INVALID_HANDLE_VALUE;
BOOL bRunApp = TRUE;
PVOID pAppCompatData = NULL;
DWORD cbAppCompatData = 0;
PVOID pSxsData = NULL;
DWORD cbSxsData = 0;
DWORD dwFusionFlags = 0;
WCHAR szEmptyEnvironment[] = { L'\0', L'\0' };
//
// first we have to check the message buffer to make sure it is good
//
if (!CsrValidateMessageBuffer(m,
&pMsg->FileName.Buffer,
pMsg->FileName.MaximumLength/sizeof(WCHAR),
sizeof(WCHAR))) {
return STATUS_INVALID_PARAMETER;
}
//
// do more validation here please
//
if (pMsg->pEnvironment != NULL) {
if (!CsrValidateMessageBuffer(m,
&pMsg->pEnvironment,
pMsg->EnvironmentSize/sizeof(WCHAR),
sizeof(WCHAR))) {
return STATUS_INVALID_PARAMETER;
}
// check that the environment ends in two 00
if (pMsg->EnvironmentSize < sizeof(szEmptyEnvironment) ||
*((PWCHAR)pMsg->pEnvironment + (pMsg->EnvironmentSize/sizeof(WCHAR) - 1)) != L'\0' ||
*((PWCHAR)pMsg->pEnvironment + (pMsg->EnvironmentSize/sizeof(WCHAR) - 2)) != L'\0') {
return STATUS_INVALID_PARAMETER;
}
}
Status = BaseSrvDelayLoadApphelp();
if (!NT_SUCCESS(Status)) {
return Status;
}
//
// check environment buffer
//
ClientThread = CSR_SERVER_QUERYCLIENTTHREAD();
ClientProcessHandle = ClientThread->Process->ProcessHandle;
//
// Calling CsrImpersonateClient before NtDuplicateObject to
// make auditing work better.
//
if (!CsrImpersonateClient(NULL)) {
//
// we could not impersonate the caller, fail this alltogether then
//
return STATUS_BAD_IMPERSONATION_LEVEL;
}
if (pMsg->FileHandle != INVALID_HANDLE_VALUE) {
Status = NtDuplicateObject(ClientProcessHandle,
pMsg->FileHandle,
NtCurrentProcess(),
&FileHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
if (!NT_SUCCESS(Status)) {
return STATUS_INVALID_PARAMETER;
}
}
//
// next - check application compatibility setting by invoking apphelp.dll
//
bRunApp = pfnCheckRunApp(FileHandle,
pMsg->FileName.Buffer,
pMsg->pEnvironment == NULL ?
(PVOID)szEmptyEnvironment : pMsg->pEnvironment,
pMsg->ExeType,
&pMsg->CacheCookie,
&pAppCompatData,
&cbAppCompatData,
&pSxsData,
&cbSxsData,
&dwFusionFlags);
//
// revert to self
//
CsrRevertToSelf();
//
// if we got compat data back -- marshal the pointers across
//
Status = BasepSrvMarshallAppCompatData(pMsg,
ClientProcessHandle,
pAppCompatData,
cbAppCompatData,
pSxsData,
cbSxsData,
dwFusionFlags);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
if (bRunApp && (pMsg->CacheCookie & SHIM_CACHE_ACTION)) {
if (pMsg->CacheCookie & SHIM_CACHE_UPDATE) {
Status = BasepSrvShimCacheUpdate(&pMsg->FileName, FileHandle);
} else {
Status = BasepSrvShimCacheRemoveEntry(&pMsg->FileName);
}
}
Cleanup:
//
// check for the handle please
//
if (FileHandle != INVALID_HANDLE_VALUE) {
NtClose(FileHandle);
}
pMsg->bRunApp = bRunApp;
return STATUS_SUCCESS;
}