[NTOS:APPHELP]

- Avoid excessive indentation
- Minor changes to conform better to kernel style

svn path=/trunk/; revision=69534
This commit is contained in:
Thomas Faber 2015-10-15 07:44:25 +00:00
parent 62ffa081a9
commit 027ae80ad0

View file

@ -182,17 +182,25 @@ ApphelpCacheQueryInfo(
FILE_STANDARD_INFORMATION FileStandard; FILE_STANDARD_INFORMATION FileStandard;
NTSTATUS Status; NTSTATUS Status;
Status = ZwQueryInformationFile(ImageHandle, &IoStatusBlock, Status = ZwQueryInformationFile(ImageHandle,
&FileBasic, sizeof(FileBasic), FileBasicInformation); &IoStatusBlock,
&FileBasic,
sizeof(FileBasic),
FileBasicInformation);
if (!NT_SUCCESS(Status))
{
return Status;
}
Status = ZwQueryInformationFile(ImageHandle,
&IoStatusBlock,
&FileStandard,
sizeof(FileStandard),
FileStandardInformation);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = ZwQueryInformationFile(ImageHandle, &IoStatusBlock, Entry->Persistent.DateTime = FileBasic.LastWriteTime;
&FileStandard, sizeof(FileStandard), FileStandardInformation); Entry->Persistent.FileSize = FileStandard.EndOfFile;
if (NT_SUCCESS(Status))
{
Entry->Persistent.DateTime = FileBasic.LastWriteTime;
Entry->Persistent.FileSize = FileStandard.EndOfFile;
}
} }
return Status; return Status;
} }
@ -204,14 +212,21 @@ ApphelpShimCacheCompareRoutine(
_In_ PVOID FirstStruct, _In_ PVOID FirstStruct,
_In_ PVOID SecondStruct) _In_ PVOID SecondStruct)
{ {
LONG lResult = RtlCompareUnicodeString( PSHIM_CACHE_ENTRY FirstEntry = FirstStruct;
&((PSHIM_CACHE_ENTRY)FirstStruct)->Persistent.ImageName, PSHIM_CACHE_ENTRY SecondEntry = SecondStruct;
&((PSHIM_CACHE_ENTRY)SecondStruct)->Persistent.ImageName, TRUE); LONG Result;
if (lResult < 0) Result = RtlCompareUnicodeString(&FirstEntry->Persistent.ImageName,
&SecondEntry->Persistent.ImageName,
TRUE);
if (Result < 0)
{
return GenericLessThan; return GenericLessThan;
else if (lResult == 0) }
else if (Result == 0)
{
return GenericEqual; return GenericEqual;
}
return GenericGreaterThan; return GenericGreaterThan;
} }
@ -239,47 +254,53 @@ ApphelpCacheParse(
_In_ ULONG DataLength) _In_ ULONG DataLength)
{ {
PSHIM_PERSISTENT_CACHE_HEADER Header = (PSHIM_PERSISTENT_CACHE_HEADER)Data; PSHIM_PERSISTENT_CACHE_HEADER Header = (PSHIM_PERSISTENT_CACHE_HEADER)Data;
ULONG Cur;
ULONG NumEntries;
UNICODE_STRING String;
SHIM_CACHE_ENTRY Entry = EMPTY_SHIM_ENTRY;
PSHIM_CACHE_ENTRY Result;
PSHIM_PERSISTENT_CACHE_ENTRY Persistent;
if (DataLength < CACHE_HEADER_SIZE_NT_52) if (DataLength < CACHE_HEADER_SIZE_NT_52)
{ {
DPRINT1("SHIMS: ApphelpCacheParse not enough data for a minimal header (0x%x)\n", DataLength); DPRINT1("SHIMS: ApphelpCacheParse not enough data for a minimal header (0x%x)\n", DataLength);
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
if (Header->Magic == SHIM_CACHE_MAGIC)
{
ULONG Cur;
ULONG NumEntries = Header->NumEntries;
DPRINT1("SHIMS: ApphelpCacheParse walking %d entries\n", NumEntries);
for (Cur = 0; Cur < NumEntries; ++Cur)
{
UNICODE_STRING String;
SHIM_CACHE_ENTRY Entry = EMPTY_SHIM_ENTRY;
PSHIM_CACHE_ENTRY Result;
PSHIM_PERSISTENT_CACHE_ENTRY pPersistent =
(PSHIM_PERSISTENT_CACHE_ENTRY)(Data + SHIM_CACHE_HEADER_SIZE +
(Cur * SHIM_PERSISTENT_CACHE_ENTRY_SIZE));
/* The entry in the Persitent storage is not really a UNICODE_STRING,
so we have to convert the offset into a real pointer before using it. */
String.Length = pPersistent->ImageName.Length;
String.MaximumLength = pPersistent->ImageName.MaximumLength;
String.Buffer = (PWCHAR)((ULONG_PTR)pPersistent->ImageName.Buffer + Data);
/* Now we copy all data to a local buffer, that can be safely duplicated by RtlInsert */ if (Header->Magic != SHIM_CACHE_MAGIC)
Entry.Persistent = *pPersistent; {
ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, &String); DPRINT1("SHIMS: ApphelpCacheParse found invalid magic (0x%x)\n", Header->Magic);
Result = RtlInsertElementGenericTableAvl(&ApphelpShimCache, &Entry, sizeof(Entry), NULL); return STATUS_INVALID_PARAMETER;
if (!Result)
{
DPRINT1("SHIMS: ApphelpCacheParse insert failed\n");
ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
return STATUS_INVALID_PARAMETER;
}
InsertTailList(&ApphelpShimCacheAge, &Result->List);
}
return STATUS_SUCCESS;
} }
DPRINT1("SHIMS: ApphelpCacheParse found invalid magic (0x%x)\n", Header->Magic);
return STATUS_INVALID_PARAMETER; NumEntries = Header->NumEntries;
DPRINT1("SHIMS: ApphelpCacheParse walking %d entries\n", NumEntries);
for (Cur = 0; Cur < NumEntries; ++Cur)
{
Persistent = (PSHIM_PERSISTENT_CACHE_ENTRY)(Data + SHIM_CACHE_HEADER_SIZE +
(Cur * SHIM_PERSISTENT_CACHE_ENTRY_SIZE));
/* The entry in the Persistent storage is not really a UNICODE_STRING,
so we have to convert the offset into a real pointer before using it. */
String.Length = Persistent->ImageName.Length;
String.MaximumLength = Persistent->ImageName.MaximumLength;
String.Buffer = (PWCHAR)((ULONG_PTR)Persistent->ImageName.Buffer + Data);
/* Now we copy all data to a local buffer, that can be safely duplicated by RtlInsert */
Entry.Persistent = *Persistent;
ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, &String);
Result = RtlInsertElementGenericTableAvl(&ApphelpShimCache,
&Entry,
sizeof(Entry),
NULL);
if (!Result)
{
DPRINT1("SHIMS: ApphelpCacheParse insert failed\n");
ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
return STATUS_INVALID_PARAMETER;
}
InsertTailList(&ApphelpShimCacheAge, &Result->List);
}
return STATUS_SUCCESS;
} }
BOOLEAN BOOLEAN
@ -292,33 +313,37 @@ ApphelpCacheRead(VOID)
ULONG KeyInfoSize, ResultSize; ULONG KeyInfoSize, ResultSize;
Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &AppCompatKeyAttributes); Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &AppCompatKeyAttributes);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("SHIMS: ApphelpCacheRead could not even open Session Manager\\AppCompatCache (0x%x)\n", Status); DPRINT1("SHIMS: ApphelpCacheRead could not even open Session Manager\\AppCompatCache (0x%x)\n", Status);
return FALSE; return FALSE;
} }
Status = ZwQueryValueKey(KeyHandle, &AppCompatCacheValue, Status = ZwQueryValueKey(KeyHandle,
KeyValuePartialInformation, KeyValueInformation, &AppCompatCacheValue,
sizeof(KeyValueObject), &ResultSize); KeyValuePartialInformation,
KeyValueInformation,
sizeof(KeyValueObject),
&ResultSize);
if (Status == STATUS_BUFFER_OVERFLOW) if (Status == STATUS_BUFFER_OVERFLOW)
{ {
KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation->DataLength; KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation->DataLength;
KeyValueInformation = ApphelpAlloc(KeyInfoSize); KeyValueInformation = ApphelpAlloc(KeyInfoSize);
if (KeyValueInformation != NULL) if (KeyValueInformation != NULL)
{ {
Status = ZwQueryValueKey(KeyHandle, &AppCompatCacheValue, Status = ZwQueryValueKey(KeyHandle,
KeyValuePartialInformation, KeyValueInformation, &AppCompatCacheValue,
KeyInfoSize, &ResultSize); KeyValuePartialInformation,
KeyValueInformation,
KeyInfoSize,
&ResultSize);
} }
} }
if (NT_SUCCESS(Status) && KeyValueInformation->Type == REG_BINARY) if (NT_SUCCESS(Status) && KeyValueInformation->Type == REG_BINARY)
{ {
Status = ApphelpCacheParse(KeyValueInformation->Data, Status = ApphelpCacheParse(KeyValueInformation->Data,
KeyValueInformation->DataLength); KeyValueInformation->DataLength);
} }
else else
{ {
@ -326,7 +351,9 @@ ApphelpCacheRead(VOID)
} }
if (KeyValueInformation != &KeyValueObject && KeyValueInformation != NULL) if (KeyValueInformation != &KeyValueObject && KeyValueInformation != NULL)
{
ApphelpFree(KeyValueInformation); ApphelpFree(KeyValueInformation);
}
ZwClose(KeyHandle); ZwClose(KeyHandle);
return NT_SUCCESS(Status); return NT_SUCCESS(Status);
@ -389,7 +416,12 @@ ApphelpCacheWrite(VOID)
Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &AppCompatKeyAttributes); Status = ZwOpenKey(&KeyHandle, KEY_SET_VALUE, &AppCompatKeyAttributes);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = ZwSetValueKey(KeyHandle, &AppCompatCacheValue, 0, REG_BINARY, Buffer, Length); Status = ZwSetValueKey(KeyHandle,
&AppCompatCacheValue,
0,
REG_BINARY,
Buffer,
Length);
ZwClose(KeyHandle); ZwClose(KeyHandle);
} }
else else
@ -418,10 +450,10 @@ ApphelpCacheInitialize(VOID)
{ {
ExInitializeResourceLite(&ApphelpCacheLock); ExInitializeResourceLite(&ApphelpCacheLock);
RtlInitializeGenericTableAvl(&ApphelpShimCache, RtlInitializeGenericTableAvl(&ApphelpShimCache,
ApphelpShimCacheCompareRoutine, ApphelpShimCacheCompareRoutine,
ApphelpShimCacheAllocateRoutine, ApphelpShimCacheAllocateRoutine,
ApphelpShimCacheFreeRoutine, ApphelpShimCacheFreeRoutine,
NULL); NULL);
InitializeListHead(&ApphelpShimCacheAge); InitializeListHead(&ApphelpShimCacheAge);
ApphelpCacheEnabled = ApphelpCacheRead(); ApphelpCacheEnabled = ApphelpCacheRead();
} }
@ -452,12 +484,16 @@ ApphelpValidateData(
UNICODE_STRING LocalImageName; UNICODE_STRING LocalImageName;
_SEH2_TRY _SEH2_TRY
{ {
ProbeForRead(ServiceData, sizeof(APPHELP_CACHE_SERVICE_LOOKUP), sizeof(ULONG)); ProbeForRead(ServiceData,
sizeof(APPHELP_CACHE_SERVICE_LOOKUP),
sizeof(ULONG));
LocalImageName = ServiceData->ImageName; LocalImageName = ServiceData->ImageName;
*ImageHandle = ServiceData->ImageHandle; *ImageHandle = ServiceData->ImageHandle;
if (LocalImageName.Length && LocalImageName.Buffer) if (LocalImageName.Length && LocalImageName.Buffer)
{ {
ProbeForRead(LocalImageName.Buffer, LocalImageName.Length * sizeof(WCHAR), 1); ProbeForRead(LocalImageName.Buffer,
LocalImageName.Length * sizeof(WCHAR),
1);
ApphelpDuplicateUnicodeString(ImageName, &LocalImageName); ApphelpDuplicateUnicodeString(ImageName, &LocalImageName);
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
} }
@ -484,7 +520,9 @@ ApphelpCacheRemoveEntryNolock(
PWSTR Buffer = Entry->Persistent.ImageName.Buffer; PWSTR Buffer = Entry->Persistent.ImageName.Buffer;
RemoveEntryList(&Entry->List); RemoveEntryList(&Entry->List);
if (RtlDeleteElementGenericTableAvl(&ApphelpShimCache, Entry)) if (RtlDeleteElementGenericTableAvl(&ApphelpShimCache, Entry))
{
ApphelpFree(Buffer); ApphelpFree(Buffer);
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
return STATUS_NOT_FOUND; return STATUS_NOT_FOUND;
@ -496,45 +534,52 @@ ApphelpCacheLookupEntry(
_In_ HANDLE ImageHandle) _In_ HANDLE ImageHandle)
{ {
NTSTATUS Status = STATUS_NOT_FOUND; NTSTATUS Status = STATUS_NOT_FOUND;
SHIM_CACHE_ENTRY Lookup = EMPTY_SHIM_ENTRY;
PSHIM_CACHE_ENTRY Entry;
if (ApphelpCacheTryAcquireLock()) if (!ApphelpCacheTryAcquireLock())
{ {
SHIM_CACHE_ENTRY Lookup = EMPTY_SHIM_ENTRY; return Status;
PSHIM_CACHE_ENTRY Entry; }
Lookup.Persistent.ImageName = *ImageName;
Entry = RtlLookupElementGenericTableAvl(&ApphelpShimCache, &Lookup); Lookup.Persistent.ImageName = *ImageName;
if (Entry) Entry = RtlLookupElementGenericTableAvl(&ApphelpShimCache, &Lookup);
if (Entry == NULL)
{
DPRINT1("SHIMS: ApphelpCacheLookupEntry: could not find %wZ\n", ImageName);
goto Cleanup;
}
DPRINT1("SHIMS: ApphelpCacheLookupEntry: found %wZ\n", ImageName);
if (ImageHandle == INVALID_HANDLE_VALUE)
{
DPRINT1("SHIMS: ApphelpCacheLookupEntry: ok\n");
/* just return if we know it, do not query file info */
Status = STATUS_SUCCESS;
}
else
{
Status = ApphelpCacheQueryInfo(ImageHandle, &Lookup);
if (NT_SUCCESS(Status) &&
Lookup.Persistent.DateTime.QuadPart == Entry->Persistent.DateTime.QuadPart &&
Lookup.Persistent.FileSize.QuadPart == Entry->Persistent.FileSize.QuadPart)
{ {
DPRINT1("SHIMS: ApphelpCacheLookupEntry: found %wZ\n", ImageName); DPRINT1("SHIMS: ApphelpCacheLookupEntry: found & validated\n");
if (ImageHandle == INVALID_HANDLE_VALUE) Status = STATUS_SUCCESS;
{ /* move it to the front to keep it alive */
DPRINT1("SHIMS: ApphelpCacheLookupEntry: ok\n"); RemoveEntryList(&Entry->List);
/* just return if we know it, do not query file info */ InsertHeadList(&ApphelpShimCacheAge, &Entry->List);
Status = STATUS_SUCCESS;
}
else if (NT_SUCCESS(ApphelpCacheQueryInfo(ImageHandle, &Lookup)) &&
Lookup.Persistent.DateTime.QuadPart == Entry->Persistent.DateTime.QuadPart &&
Lookup.Persistent.FileSize.QuadPart == Entry->Persistent.FileSize.QuadPart)
{
DPRINT1("SHIMS: ApphelpCacheLookupEntry: found & validated\n");
Status = STATUS_SUCCESS;
/* move it to the front to keep it alive */
RemoveEntryList(&Entry->List);
InsertHeadList(&ApphelpShimCacheAge, &Entry->List);
}
else
{
DPRINT1("SHIMS: ApphelpCacheLookupEntry: file info mismatch\n");
/* Could not read file info, or it did not match, drop it from the cache */
ApphelpCacheRemoveEntryNolock(Entry);
}
} }
else else
{ {
DPRINT1("SHIMS: ApphelpCacheLookupEntry: could not find %wZ\n", ImageName); DPRINT1("SHIMS: ApphelpCacheLookupEntry: file info mismatch\n");
/* Could not read file info, or it did not match, drop it from the cache */
ApphelpCacheRemoveEntryNolock(Entry);
} }
ApphelpCacheReleaseLock();
} }
Cleanup:
ApphelpCacheReleaseLock();
return Status; return Status;
} }
@ -584,49 +629,57 @@ ApphelpCacheUpdateEntry(
if (ImageHandle != INVALID_HANDLE_VALUE) if (ImageHandle != INVALID_HANDLE_VALUE)
{ {
Status = ApphelpCacheQueryInfo(ImageHandle, &Entry); Status = ApphelpCacheQueryInfo(ImageHandle, &Entry);
if (!NT_SUCCESS(Status))
{
goto Cleanup;
}
} }
if (NT_SUCCESS(Status)) /* Use ImageName for the lookup, don't actually duplicate it */
Entry.Persistent.ImageName = *ImageName;
Lookup = RtlLookupElementGenericTableFullAvl(&ApphelpShimCache,
&Entry,
&NodeOrParent, &SearchResult);
if (Lookup)
{ {
/* Use ImageName for the lookup, don't actually duplicate it */ DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Entry already exists, reusing it\n");
Entry.Persistent.ImageName = *ImageName; /* Unlink the found item, so we can put it back at the front,
Lookup = RtlLookupElementGenericTableFullAvl(&ApphelpShimCache, &Entry, and copy the earlier obtained file info*/
&NodeOrParent, &SearchResult); RemoveEntryList(&Lookup->List);
if (Lookup) Lookup->Persistent.DateTime = Entry.Persistent.DateTime;
Lookup->Persistent.FileSize = Entry.Persistent.FileSize;
}
else
{
DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Inserting new Entry\n");
/* Insert a new entry, with its own copy of the ImageName */
ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, ImageName);
Lookup = RtlInsertElementGenericTableFullAvl(&ApphelpShimCache,
&Entry,
sizeof(Entry),
0,
NodeOrParent,
SearchResult);
if (!Lookup)
{ {
DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Entry already exists, reusing it\n"); ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
/* Unlink the found item, so we can put it back at the front, Status = STATUS_NO_MEMORY;
and copy the earlier obtained file info*/
RemoveEntryList(&Lookup->List);
Lookup->Persistent.DateTime = Entry.Persistent.DateTime;
Lookup->Persistent.FileSize = Entry.Persistent.FileSize;
}
else
{
DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Inserting new Entry\n");
/* Insert a new entry, with its own copy of the ImageName */
ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, ImageName);
Lookup = RtlInsertElementGenericTableFullAvl(&ApphelpShimCache,
&Entry, sizeof(Entry), 0, NodeOrParent, SearchResult);
if (!Lookup)
{
ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
Status = STATUS_NO_MEMORY;
}
}
if (Lookup)
{
/* Either we re-used an existing item, or we inserted a new one, keep it alive */
InsertHeadList(&ApphelpShimCacheAge, &Lookup->List);
if (RtlNumberGenericTableElementsAvl(&ApphelpShimCache) > MAX_SHIM_ENTRIES)
{
PSHIM_CACHE_ENTRY Remove;
DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Cache growing too big, dropping oldest item\n");
Remove = CONTAINING_RECORD(ApphelpShimCacheAge.Blink, SHIM_CACHE_ENTRY, List);
Status = ApphelpCacheRemoveEntryNolock(Remove);
}
} }
} }
if (Lookup)
{
/* Either we re-used an existing item, or we inserted a new one, keep it alive */
InsertHeadList(&ApphelpShimCacheAge, &Lookup->List);
if (RtlNumberGenericTableElementsAvl(&ApphelpShimCache) > MAX_SHIM_ENTRIES)
{
PSHIM_CACHE_ENTRY Remove;
DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Cache growing too big, dropping oldest item\n");
Remove = CONTAINING_RECORD(ApphelpShimCacheAge.Blink, SHIM_CACHE_ENTRY, List);
Status = ApphelpCacheRemoveEntryNolock(Remove);
}
}
Cleanup:
ApphelpCacheReleaseLock(); ApphelpCacheReleaseLock();
return Status; return Status;
} }
@ -650,18 +703,17 @@ NTSTATUS
ApphelpCacheDump(VOID) ApphelpCacheDump(VOID)
{ {
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
PSHIM_CACHE_ENTRY Entry;
DPRINT1("SHIMS: NtApphelpCacheControl( Dumping entries, newset to oldest )\n"); DPRINT1("SHIMS: NtApphelpCacheControl( Dumping entries, newset to oldest )\n");
ApphelpCacheAcquireLock(); ApphelpCacheAcquireLock();
ListEntry = ApphelpShimCacheAge.Flink; ListEntry = ApphelpShimCacheAge.Flink;
while (ListEntry != &ApphelpShimCacheAge) while (ListEntry != &ApphelpShimCacheAge)
{ {
PSHIM_CACHE_ENTRY Entry = CONTAINING_RECORD(ListEntry, SHIM_CACHE_ENTRY, List); Entry = CONTAINING_RECORD(ListEntry, SHIM_CACHE_ENTRY, List);
DPRINT1("Entry: %S\n", Entry->Persistent.ImageName.Buffer); DPRINT1("Entry: %wZ\n", &Entry->Persistent.ImageName);
DPRINT1("DateTime High: 0x%x, Low: 0x%x\n", DPRINT1("DateTime: 0x%I64x\n", Entry->Persistent.DateTime.QuadPart);
Entry->Persistent.DateTime.HighPart, Entry->Persistent.DateTime.LowPart); DPRINT1("FileSize: 0x%I64x\n", Entry->Persistent.FileSize.QuadPart);
DPRINT1("FileSize High: 0x%x, Low: 0x%x\n",
Entry->Persistent.FileSize.HighPart, Entry->Persistent.FileSize.LowPart);
DPRINT1("Flags: 0x%x\n", Entry->CompatFlags); DPRINT1("Flags: 0x%x\n", Entry->CompatFlags);
ListEntry = ListEntry->Flink; ListEntry = ListEntry->Flink;
} }