ReactOS 0.4.17-dev-1190-g4c812f4
apphelp.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <pshpack1.h>
#include <poppack.h>
Include dependency graph for apphelp.c:

Go to the source code of this file.

Classes

struct  SHIM_PERSISTENT_CACHE_HEADER_52
 
struct  SHIM_PERSISTENT_CACHE_ENTRY_52
 
struct  SHIM_CACHE_ENTRY
 

Macros

#define NDEBUG
 
#define EMPTY_SHIM_ENTRY   { { 0 }, { { 0 } }, 0 }
 
#define MAX_SHIM_ENTRIES   0x200
 
#define INVALID_HANDLE_VALUE   (HANDLE)(-1)
 
#define CACHE_MAGIC_NT_52   0xbadc0ffe
 
#define CACHE_HEADER_SIZE_NT_52   0x8
 
#define NT52_PERSISTENT_ENTRY_SIZE32   0x18
 
#define NT52_PERSISTENT_ENTRY_SIZE64   0x20
 
#define SHIM_CACHE_MAGIC   CACHE_MAGIC_NT_52
 
#define SHIM_CACHE_HEADER_SIZE   CACHE_HEADER_SIZE_NT_52
 
#define SHIM_PERSISTENT_CACHE_ENTRY_SIZE   NT52_PERSISTENT_ENTRY_SIZE32
 
#define SHIM_PERSISTENT_CACHE_HEADER   SHIM_PERSISTENT_CACHE_HEADER_52
 
#define PSHIM_PERSISTENT_CACHE_HEADER   PSHIM_PERSISTENT_CACHE_HEADER_52
 
#define SHIM_PERSISTENT_CACHE_ENTRY   SHIM_PERSISTENT_CACHE_ENTRY_52
 
#define PSHIM_PERSISTENT_CACHE_ENTRY   PSHIM_PERSISTENT_CACHE_ENTRY_52
 

Typedefs

typedef struct SHIM_PERSISTENT_CACHE_HEADER_52 SHIM_PERSISTENT_CACHE_HEADER_52
 
typedef struct SHIM_PERSISTENT_CACHE_HEADER_52 * PSHIM_PERSISTENT_CACHE_HEADER_52
 
typedef struct SHIM_PERSISTENT_CACHE_ENTRY_52 SHIM_PERSISTENT_CACHE_ENTRY_52
 
typedef struct SHIM_PERSISTENT_CACHE_ENTRY_52 * PSHIM_PERSISTENT_CACHE_ENTRY_52
 
typedef struct SHIM_CACHE_ENTRY SHIM_CACHE_ENTRY
 
typedef struct SHIM_CACHE_ENTRY * PSHIM_CACHE_ENTRY
 

Functions

 C_ASSERT (sizeof(SHIM_PERSISTENT_CACHE_ENTRY)==SHIM_PERSISTENT_CACHE_ENTRY_SIZE)
 
 C_ASSERT (sizeof(SHIM_PERSISTENT_CACHE_HEADER)==SHIM_CACHE_HEADER_SIZE)
 
PVOID ApphelpAlloc (_In_ ULONG ByteSize)
 
VOID ApphelpFree (_In_ PVOID Data)
 
VOID ApphelpCacheAcquireLock (VOID)
 
BOOLEAN ApphelpCacheTryAcquireLock (VOID)
 
VOID ApphelpCacheReleaseLock (VOID)
 
VOID ApphelpDuplicateUnicodeString (_Out_ PUNICODE_STRING Destination, _In_ PCUNICODE_STRING Source)
 
VOID ApphelpFreeUnicodeString (_Inout_ PUNICODE_STRING String)
 
NTSTATUS ApphelpCacheQueryInfo (_In_ HANDLE ImageHandle, _Out_ PSHIM_CACHE_ENTRY Entry)
 
RTL_GENERIC_COMPARE_RESULTS NTAPI ApphelpShimCacheCompareRoutine (_In_ struct _RTL_AVL_TABLE *Table, _In_ PVOID FirstStruct, _In_ PVOID SecondStruct)
 
PVOID NTAPI ApphelpShimCacheAllocateRoutine (_In_ struct _RTL_AVL_TABLE *Table, _In_ CLONG ByteSize)
 
VOID NTAPI ApphelpShimCacheFreeRoutine (_In_ struct _RTL_AVL_TABLE *Table, _In_ PVOID Buffer)
 
NTSTATUS ApphelpCacheParse (_In_reads_(DataLength) PUCHAR Data, _In_ ULONG DataLength)
 
BOOLEAN ApphelpCacheRead (VOID)
 
BOOLEAN ApphelpCacheWrite (VOID)
 
NTSTATUS NTAPI ApphelpCacheInitialize (VOID)
 
VOID NTAPI ApphelpCacheShutdown (VOID)
 
NTSTATUS ApphelpValidateData (_In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP ServiceData, _Out_ PUNICODE_STRING ImageName, _Out_ PHANDLE ImageHandle)
 
NTSTATUS ApphelpCacheRemoveEntryNolock (_In_ PSHIM_CACHE_ENTRY Entry)
 
NTSTATUS ApphelpCacheLookupEntry (_In_ PUNICODE_STRING ImageName, _In_ HANDLE ImageHandle)
 
NTSTATUS ApphelpCacheRemoveEntry (_In_ PUNICODE_STRING ImageName)
 
NTSTATUS ApphelpCacheAccessCheck (VOID)
 
NTSTATUS ApphelpCacheUpdateEntry (_In_ PUNICODE_STRING ImageName, _In_ HANDLE ImageHandle)
 
NTSTATUS ApphelpCacheFlush (VOID)
 
NTSTATUS ApphelpCacheDump (VOID)
 
NTSTATUS NTAPI NtApphelpCacheControl (_In_ APPHELPCACHESERVICECLASS Service, _In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP ServiceData)
 

Variables

static BOOLEAN ApphelpCacheEnabled = FALSE
 
static ERESOURCE ApphelpCacheLock
 
static RTL_AVL_TABLE ApphelpShimCache
 
static LIST_ENTRY ApphelpShimCacheAge
 
static UNICODE_STRING AppCompatCacheKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache")
 
static OBJECT_ATTRIBUTES AppCompatKeyAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&AppCompatCacheKey, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE)
 
static UNICODE_STRING AppCompatCacheValue = RTL_CONSTANT_STRING(L"AppCompatCache")
 

Macro Definition Documentation

◆ CACHE_HEADER_SIZE_NT_52

#define CACHE_HEADER_SIZE_NT_52   0x8

Definition at line 64 of file apphelp.c.

◆ CACHE_MAGIC_NT_52

#define CACHE_MAGIC_NT_52   0xbadc0ffe

Definition at line 63 of file apphelp.c.

◆ EMPTY_SHIM_ENTRY

#define EMPTY_SHIM_ENTRY   { { 0 }, { { 0 } }, 0 }

Definition at line 38 of file apphelp.c.

◆ INVALID_HANDLE_VALUE

#define INVALID_HANDLE_VALUE   (HANDLE)(-1)

Definition at line 42 of file apphelp.c.

◆ MAX_SHIM_ENTRIES

#define MAX_SHIM_ENTRIES   0x200

Definition at line 39 of file apphelp.c.

◆ NDEBUG

#define NDEBUG

Definition at line 24 of file apphelp.c.

◆ NT52_PERSISTENT_ENTRY_SIZE32

#define NT52_PERSISTENT_ENTRY_SIZE32   0x18

Definition at line 65 of file apphelp.c.

◆ NT52_PERSISTENT_ENTRY_SIZE64

#define NT52_PERSISTENT_ENTRY_SIZE64   0x20

Definition at line 66 of file apphelp.c.

◆ PSHIM_PERSISTENT_CACHE_ENTRY

#define PSHIM_PERSISTENT_CACHE_ENTRY   PSHIM_PERSISTENT_CACHE_ENTRY_52

Definition at line 83 of file apphelp.c.

◆ PSHIM_PERSISTENT_CACHE_HEADER

#define PSHIM_PERSISTENT_CACHE_HEADER   PSHIM_PERSISTENT_CACHE_HEADER_52

Definition at line 81 of file apphelp.c.

◆ SHIM_CACHE_HEADER_SIZE

#define SHIM_CACHE_HEADER_SIZE   CACHE_HEADER_SIZE_NT_52

Definition at line 74 of file apphelp.c.

◆ SHIM_CACHE_MAGIC

#define SHIM_CACHE_MAGIC   CACHE_MAGIC_NT_52

Definition at line 73 of file apphelp.c.

◆ SHIM_PERSISTENT_CACHE_ENTRY

#define SHIM_PERSISTENT_CACHE_ENTRY   SHIM_PERSISTENT_CACHE_ENTRY_52

Definition at line 82 of file apphelp.c.

◆ SHIM_PERSISTENT_CACHE_ENTRY_SIZE

#define SHIM_PERSISTENT_CACHE_ENTRY_SIZE   NT52_PERSISTENT_ENTRY_SIZE32

Definition at line 78 of file apphelp.c.

◆ SHIM_PERSISTENT_CACHE_HEADER

#define SHIM_PERSISTENT_CACHE_HEADER   SHIM_PERSISTENT_CACHE_HEADER_52

Definition at line 80 of file apphelp.c.

Typedef Documentation

◆ PSHIM_CACHE_ENTRY

◆ PSHIM_PERSISTENT_CACHE_ENTRY_52

◆ PSHIM_PERSISTENT_CACHE_HEADER_52

◆ SHIM_CACHE_ENTRY

◆ SHIM_PERSISTENT_CACHE_ENTRY_52

◆ SHIM_PERSISTENT_CACHE_HEADER_52

Function Documentation

◆ ApphelpAlloc()

PVOID ApphelpAlloc ( _In_ ULONG  ByteSize)

Definition at line 99 of file apphelp.c.

101{
103}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define TAG_SHIM
Definition: tag.h:144
_IRQL_requires_same_ _In_ CLONG ByteSize
Definition: rtltypes.h:412

Referenced by ApphelpCacheRead(), ApphelpCacheWrite(), ApphelpDuplicateUnicodeString(), and ApphelpShimCacheAllocateRoutine().

◆ ApphelpCacheAccessCheck()

NTSTATUS ApphelpCacheAccessCheck ( VOID  )

Definition at line 600 of file apphelp.c.

601{
603 {
605 {
606 DPRINT1("SHIMS: ApphelpCacheAccessCheck failed\n");
608 }
609 }
610 return STATUS_SUCCESS;
611}
#define DPRINT1
Definition: precomp.h:8
#define ExGetPreviousMode
Definition: ex.h:143
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
const LUID SeTcbPrivilege
Definition: priv.c:26
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145

Referenced by NtApphelpCacheControl().

◆ ApphelpCacheAcquireLock()

VOID ApphelpCacheAcquireLock ( VOID  )

Definition at line 113 of file apphelp.c.

114{
117}
#define TRUE
Definition: types.h:120
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
static ERESOURCE ApphelpCacheLock
Definition: apphelp.c:30

Referenced by ApphelpCacheDump(), ApphelpCacheFlush(), ApphelpCacheRemoveEntry(), ApphelpCacheUpdateEntry(), and ApphelpCacheWrite().

◆ ApphelpCacheDump()

NTSTATUS ApphelpCacheDump ( VOID  )

Definition at line 701 of file apphelp.c.

702{
703 PLIST_ENTRY ListEntry;
705
706 DPRINT1("SHIMS: NtApphelpCacheControl( Dumping entries, newest to oldest )\n");
708 ListEntry = ApphelpShimCacheAge.Flink;
709 while (ListEntry != &ApphelpShimCacheAge)
710 {
712 DPRINT1("Entry: %wZ\n", &Entry->Persistent.ImageName);
713 DPRINT1("DateTime: 0x%I64x\n", Entry->Persistent.DateTime.QuadPart);
714 DPRINT1("FileSize: 0x%I64x\n", Entry->Persistent.FileSize.QuadPart);
715 DPRINT1("Flags: 0x%x\n", Entry->CompatFlags);
716 ListEntry = ListEntry->Flink;
717 }
719 return STATUS_SUCCESS;
720}
static LIST_ENTRY ApphelpShimCacheAge
Definition: apphelp.c:32
VOID ApphelpCacheAcquireLock(VOID)
Definition: apphelp.c:113
VOID ApphelpCacheReleaseLock(VOID)
Definition: apphelp.c:132
Entry
Definition: section.c:5216
Definition: apphelp.c:90
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550

Referenced by NtApphelpCacheControl().

◆ ApphelpCacheFlush()

NTSTATUS ApphelpCacheFlush ( VOID  )

Definition at line 686 of file apphelp.c.

687{
688 PVOID p;
689
690 DPRINT1("SHIMS: ApphelpCacheFlush\n");
693 {
695 }
697 return STATUS_SUCCESS;
698}
GLfloat GLfloat p
Definition: glext.h:8902
NTSTATUS ApphelpCacheRemoveEntryNolock(_In_ PSHIM_CACHE_ENTRY Entry)
Definition: apphelp.c:512
static RTL_AVL_TABLE ApphelpShimCache
Definition: apphelp.c:31
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlEnumerateGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ BOOLEAN Restart)

Referenced by NtApphelpCacheControl().

◆ ApphelpCacheInitialize()

NTSTATUS NTAPI ApphelpCacheInitialize ( VOID  )

Definition at line 437 of file apphelp.c.

438{
439 DPRINT("SHIMS: ApphelpCacheInitialize\n");
440 /* If we are booting in safemode we do not want to use the apphelp cache */
442 {
443 DPRINT1("SHIMS: Safe mode detected, disabling cache.\n");
445 }
446 else
447 {
453 NULL);
456 }
457 DPRINT("SHIMS: ApphelpCacheInitialize: %d\n", ApphelpCacheEnabled);
458 return STATUS_SUCCESS;
459}
VOID NTAPI RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, IN PRTL_AVL_COMPARE_ROUTINE CompareRoutine, IN PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine, IN PRTL_AVL_FREE_ROUTINE FreeRoutine, IN PVOID TableContext)
Definition: avltable.c:26
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
PULONG InitSafeBootMode
Definition: init.c:75
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
RTL_GENERIC_COMPARE_RESULTS NTAPI ApphelpShimCacheCompareRoutine(_In_ struct _RTL_AVL_TABLE *Table, _In_ PVOID FirstStruct, _In_ PVOID SecondStruct)
Definition: apphelp.c:207
static BOOLEAN ApphelpCacheEnabled
Definition: apphelp.c:29
PVOID NTAPI ApphelpShimCacheAllocateRoutine(_In_ struct _RTL_AVL_TABLE *Table, _In_ CLONG ByteSize)
Definition: apphelp.c:232
BOOLEAN ApphelpCacheRead(VOID)
Definition: apphelp.c:304
VOID NTAPI ApphelpShimCacheFreeRoutine(_In_ struct _RTL_AVL_TABLE *Table, _In_ PVOID Buffer)
Definition: apphelp.c:241
#define DPRINT
Definition: sndvol32.h:73

Referenced by IoInitSystem().

◆ ApphelpCacheLookupEntry()

NTSTATUS ApphelpCacheLookupEntry ( _In_ PUNICODE_STRING  ImageName,
_In_ HANDLE  ImageHandle 
)

Definition at line 529 of file apphelp.c.

532{
536
538 {
539 return Status;
540 }
541
542 Lookup.Persistent.ImageName = *ImageName;
544 if (Entry == NULL)
545 {
546 DPRINT("SHIMS: ApphelpCacheLookupEntry: could not find %wZ\n", ImageName);
547 goto Cleanup;
548 }
549
550 DPRINT("SHIMS: ApphelpCacheLookupEntry: found %wZ\n", ImageName);
551 if (ImageHandle == INVALID_HANDLE_VALUE)
552 {
553 DPRINT("SHIMS: ApphelpCacheLookupEntry: ok\n");
554 /* just return if we know it, do not query file info */
556 }
557 else
558 {
559 Status = ApphelpCacheQueryInfo(ImageHandle, &Lookup);
560 if (NT_SUCCESS(Status) &&
561 Lookup.Persistent.DateTime.QuadPart == Entry->Persistent.DateTime.QuadPart &&
562 Lookup.Persistent.FileSize.QuadPart == Entry->Persistent.FileSize.QuadPart)
563 {
564 DPRINT("SHIMS: ApphelpCacheLookupEntry: found & validated\n");
566 /* move it to the front to keep it alive */
567 RemoveEntryList(&Entry->List);
569 }
570 else
571 {
572 DPRINT1("SHIMS: ApphelpCacheLookupEntry: file info mismatch (%lx)\n", Status);
574 /* Could not read file info, or it did not match, drop it from the cache */
576 }
577 }
578
579Cleanup:
581 return Status;
582}
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
static void Lookup(RTF_Info *, char *)
Definition: reader.c:2208
static const WCHAR Cleanup[]
Definition: register.c:80
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertHeadList(ListHead, Entry)
Status
Definition: gdiplustypes.h:24
NTSTATUS ApphelpCacheQueryInfo(_In_ HANDLE ImageHandle, _Out_ PSHIM_CACHE_ENTRY Entry)
Definition: apphelp.c:173
#define EMPTY_SHIM_ENTRY
Definition: apphelp.c:38
BOOLEAN ApphelpCacheTryAcquireLock(VOID)
Definition: apphelp.c:120
#define STATUS_NOT_FOUND
Definition: shellext.h:72
_Must_inspect_result_ NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)

Referenced by NtApphelpCacheControl().

◆ ApphelpCacheParse()

NTSTATUS ApphelpCacheParse ( _In_reads_(DataLength) PUCHAR  Data,
_In_ ULONG  DataLength 
)

Definition at line 249 of file apphelp.c.

252{
254 ULONG Cur;
255 ULONG NumEntries;
260
262 {
263 DPRINT1("SHIMS: ApphelpCacheParse not enough data for a minimal header (0x%x)\n", DataLength);
265 }
266
267 if (Header->Magic != SHIM_CACHE_MAGIC)
268 {
269 DPRINT1("SHIMS: ApphelpCacheParse found invalid magic (0x%x)\n", Header->Magic);
271 }
272
273 NumEntries = Header->NumEntries;
274 DPRINT("SHIMS: ApphelpCacheParse walking %d entries\n", NumEntries);
275 for (Cur = 0; Cur < NumEntries; ++Cur)
276 {
279 /* The entry in the Persistent storage is not really a UNICODE_STRING,
280 so we have to convert the offset into a real pointer before using it. */
281 String.Length = Persistent->ImageName.Length;
282 String.MaximumLength = Persistent->ImageName.MaximumLength;
283 String.Buffer = (PWCHAR)((ULONG_PTR)Persistent->ImageName.Buffer + Data);
284
285 /* Now we copy all data to a local buffer, that can be safely duplicated by RtlInsert */
286 Entry.Persistent = *Persistent;
287 ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, &String);
289 &Entry,
290 sizeof(Entry),
291 NULL);
292 if (!Result)
293 {
294 DPRINT1("SHIMS: ApphelpCacheParse insert failed\n");
295 ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
297 }
299 }
300 return STATUS_SUCCESS;
301}
Definition: Header.h:9
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG DataLength
Definition: dispmprt.h:233
#define InsertTailList(ListHead, Entry)
#define SHIM_CACHE_HEADER_SIZE
Definition: apphelp.c:74
VOID ApphelpDuplicateUnicodeString(_Out_ PUNICODE_STRING Destination, _In_ PCUNICODE_STRING Source)
Definition: apphelp.c:139
#define SHIM_CACHE_MAGIC
Definition: apphelp.c:73
VOID ApphelpFreeUnicodeString(_Inout_ PUNICODE_STRING String)
Definition: apphelp.c:159
#define PSHIM_PERSISTENT_CACHE_HEADER
Definition: apphelp.c:81
#define CACHE_HEADER_SIZE_NT_52
Definition: apphelp.c:64
#define SHIM_PERSISTENT_CACHE_ENTRY_SIZE
Definition: apphelp.c:78
#define PSHIM_PERSISTENT_CACHE_ENTRY
Definition: apphelp.c:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement)

Referenced by ApphelpCacheRead().

◆ ApphelpCacheQueryInfo()

NTSTATUS ApphelpCacheQueryInfo ( _In_ HANDLE  ImageHandle,
_Out_ PSHIM_CACHE_ENTRY  Entry 
)

Definition at line 173 of file apphelp.c.

176{
178 FILE_BASIC_INFORMATION FileBasic;
179 FILE_STANDARD_INFORMATION FileStandard;
181
182 Status = ZwQueryInformationFile(ImageHandle,
184 &FileBasic,
185 sizeof(FileBasic),
187 if (!NT_SUCCESS(Status))
188 {
189 return Status;
190 }
191
192 Status = ZwQueryInformationFile(ImageHandle,
194 &FileStandard,
195 sizeof(FileStandard),
197 if (NT_SUCCESS(Status))
198 {
199 Entry->Persistent.DateTime = FileBasic.LastWriteTime;
200 Entry->Persistent.FileSize = FileStandard.EndOfFile;
201 }
202 return Status;
203}
_In_ PIO_STATUS_BLOCK IoStatusBlock
Definition: dispmprt.h:608
@ FileBasicInformation
Definition: from_kernel.h:65
#define FileStandardInformation
Definition: propsheet.cpp:61
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:944

Referenced by ApphelpCacheLookupEntry(), and ApphelpCacheUpdateEntry().

◆ ApphelpCacheRead()

BOOLEAN ApphelpCacheRead ( VOID  )

Definition at line 304 of file apphelp.c.

305{
308 KEY_VALUE_PARTIAL_INFORMATION KeyValueObject;
309 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation = &KeyValueObject;
310 ULONG KeyInfoSize, ResultSize;
311
313 if (!NT_SUCCESS(Status))
314 {
315 DPRINT1("SHIMS: ApphelpCacheRead could not even open Session Manager\\AppCompatCache (0x%x)\n", Status);
316 return FALSE;
317 }
318
319 Status = ZwQueryValueKey(KeyHandle,
322 KeyValueInformation,
323 sizeof(KeyValueObject),
324 &ResultSize);
326 {
327 KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + KeyValueInformation->DataLength;
328 KeyValueInformation = ApphelpAlloc(KeyInfoSize);
329 if (KeyValueInformation != NULL)
330 {
331 Status = ZwQueryValueKey(KeyHandle,
334 KeyValueInformation,
335 KeyInfoSize,
336 &ResultSize);
337 }
338 }
339
340 if (NT_SUCCESS(Status) && KeyValueInformation->Type == REG_BINARY)
341 {
342 Status = ApphelpCacheParse(KeyValueInformation->Data,
343 KeyValueInformation->DataLength);
344 }
345 else
346 {
347 DPRINT1("SHIMS: ApphelpCacheRead not loaded from registry (0x%x)\n", Status);
348 }
349
350 if (KeyValueInformation != &KeyValueObject && KeyValueInformation != NULL)
351 {
352 ApphelpFree(KeyValueInformation);
353 }
354
356 return NT_SUCCESS(Status);
357}
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define REG_BINARY
Definition: nt_native.h:1499
@ KeyValuePartialInformation
Definition: nt_native.h:1185
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
struct _KEY_VALUE_PARTIAL_INFORMATION KEY_VALUE_PARTIAL_INFORMATION
static UNICODE_STRING AppCompatCacheValue
Definition: apphelp.c:36
PVOID ApphelpAlloc(_In_ ULONG ByteSize)
Definition: apphelp.c:99
static OBJECT_ATTRIBUTES AppCompatKeyAttributes
Definition: apphelp.c:35
VOID ApphelpFree(_In_ PVOID Data)
Definition: apphelp.c:106
NTSTATUS ApphelpCacheParse(_In_reads_(DataLength) PUCHAR Data, _In_ ULONG DataLength)
Definition: apphelp.c:249
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66

Referenced by ApphelpCacheInitialize(), and NtApphelpCacheControl().

◆ ApphelpCacheReleaseLock()

VOID ApphelpCacheReleaseLock ( VOID  )

Definition at line 132 of file apphelp.c.

133{
136}
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822

Referenced by ApphelpCacheDump(), ApphelpCacheFlush(), ApphelpCacheLookupEntry(), ApphelpCacheRemoveEntry(), ApphelpCacheUpdateEntry(), and ApphelpCacheWrite().

◆ ApphelpCacheRemoveEntry()

NTSTATUS ApphelpCacheRemoveEntry ( _In_ PUNICODE_STRING  ImageName)

◆ ApphelpCacheRemoveEntryNolock()

NTSTATUS ApphelpCacheRemoveEntryNolock ( _In_ PSHIM_CACHE_ENTRY  Entry)

Definition at line 512 of file apphelp.c.

514{
515 if (Entry)
516 {
517 PWSTR Buffer = Entry->Persistent.ImageName.Buffer;
518 RemoveEntryList(&Entry->List);
520 {
522 }
523 return STATUS_SUCCESS;
524 }
525 return STATUS_NOT_FOUND;
526}
Definition: bufpool.h:45
uint16_t * PWSTR
Definition: typedefs.h:56
NTSYSAPI BOOLEAN NTAPI RtlDeleteElementGenericTableAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer)

Referenced by ApphelpCacheFlush(), ApphelpCacheLookupEntry(), ApphelpCacheRemoveEntry(), and ApphelpCacheUpdateEntry().

◆ ApphelpCacheShutdown()

VOID NTAPI ApphelpCacheShutdown ( VOID  )

Definition at line 463 of file apphelp.c.

464{
466 {
468 }
469}
BOOLEAN ApphelpCacheWrite(VOID)
Definition: apphelp.c:360

Referenced by PopGracefulShutdown().

◆ ApphelpCacheTryAcquireLock()

BOOLEAN ApphelpCacheTryAcquireLock ( VOID  )

Definition at line 120 of file apphelp.c.

121{
124 {
126 return FALSE;
127 }
128 return TRUE;
129}
BOOLEAN NTAPI ExTryToAcquireResourceExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:2134

Referenced by ApphelpCacheLookupEntry().

◆ ApphelpCacheUpdateEntry()

NTSTATUS ApphelpCacheUpdateEntry ( _In_ PUNICODE_STRING  ImageName,
_In_ HANDLE  ImageHandle 
)

Definition at line 614 of file apphelp.c.

617{
621 PVOID NodeOrParent;
622 TABLE_SEARCH_RESULT SearchResult;
623
625
626 /* If we got a file handle, query it for info */
627 if (ImageHandle != INVALID_HANDLE_VALUE)
628 {
629 Status = ApphelpCacheQueryInfo(ImageHandle, &Entry);
630 if (!NT_SUCCESS(Status))
631 {
632 goto Cleanup;
633 }
634 }
635
636 /* Use ImageName for the lookup, don't actually duplicate it */
637 Entry.Persistent.ImageName = *ImageName;
639 &Entry,
640 &NodeOrParent, &SearchResult);
641 if (Lookup)
642 {
643 DPRINT("SHIMS: ApphelpCacheUpdateEntry: Entry already exists, reusing it\n");
644 /* Unlink the found item, so we can put it back at the front,
645 and copy the earlier obtained file info*/
646 RemoveEntryList(&Lookup->List);
647 Lookup->Persistent.DateTime = Entry.Persistent.DateTime;
648 Lookup->Persistent.FileSize = Entry.Persistent.FileSize;
649 }
650 else
651 {
652 DPRINT("SHIMS: ApphelpCacheUpdateEntry: Inserting new Entry\n");
653 /* Insert a new entry, with its own copy of the ImageName */
654 ApphelpDuplicateUnicodeString(&Entry.Persistent.ImageName, ImageName);
656 &Entry,
657 sizeof(Entry),
658 0,
659 NodeOrParent,
660 SearchResult);
661 if (!Lookup)
662 {
663 ApphelpFreeUnicodeString(&Entry.Persistent.ImageName);
665 }
666 }
667 if (Lookup)
668 {
669 /* Either we re-used an existing item, or we inserted a new one, keep it alive */
672 {
674 DPRINT1("SHIMS: ApphelpCacheUpdateEntry: Cache growing too big, dropping oldest item\n");
677 }
678 }
679
680Cleanup:
682 return Status;
683}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define MAX_SHIM_ENTRIES
Definition: apphelp.c:39
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
_In_ BOOLEAN Remove
Definition: psfuncs.h:111
NTSYSAPI PVOID NTAPI RtlLookupElementGenericTableFullAvl(_In_ PRTL_AVL_TABLE Table, _In_ PVOID Buffer, _Out_ PVOID *NodeOrParent, _Out_ TABLE_SEARCH_RESULT *SearchResult)
NTSYSAPI PVOID NTAPI RtlInsertElementGenericTableFullAvl(_In_ PRTL_AVL_TABLE Table, _In_reads_bytes_(BufferSize) PVOID Buffer, _In_ CLONG BufferSize, _Out_opt_ PBOOLEAN NewElement, _In_ PVOID NodeOrParent, _In_ TABLE_SEARCH_RESULT SearchResult)
NTSYSAPI ULONG NTAPI RtlNumberGenericTableElementsAvl(_In_ PRTL_AVL_TABLE Table)
TABLE_SEARCH_RESULT
Definition: rtltypes.h:386

Referenced by NtApphelpCacheControl().

◆ ApphelpCacheWrite()

BOOLEAN ApphelpCacheWrite ( VOID  )

Definition at line 360 of file apphelp.c.

361{
363 ULONG NumEntries = 0;
364 PLIST_ENTRY ListEntry;
365 PUCHAR Buffer, BufferNamePos;
370
371 /* First we have to calculate the required size. */
373 ListEntry = ApphelpShimCacheAge.Flink;
374 while (ListEntry != &ApphelpShimCacheAge)
375 {
378 Length += Entry->Persistent.ImageName.MaximumLength;
379 ++NumEntries;
380 ListEntry = ListEntry->Flink;
381 }
382 DPRINT("SHIMS: ApphelpCacheWrite, %d Entries, total size: %d\n", NumEntries, Length);
383 Length = ROUND_UP(Length, sizeof(ULONGLONG));
384 DPRINT("SHIMS: ApphelpCacheWrite, Rounded to: %d\n", Length);
385
386 /* Now we allocate and prepare some helpers */
388 BufferNamePos = Buffer + Length;
391
392 Header->Magic = SHIM_CACHE_MAGIC;
393 Header->NumEntries = NumEntries;
394
395 ListEntry = ApphelpShimCacheAge.Flink;
396 while (ListEntry != &ApphelpShimCacheAge)
397 {
399 USHORT ImageNameLen = Entry->Persistent.ImageName.MaximumLength;
400 /* Copy the Persistent structure over */
401 *WriteEntry = Entry->Persistent;
402 BufferNamePos -= ImageNameLen;
403 /* Copy the image name over */
404 RtlCopyMemory(BufferNamePos, Entry->Persistent.ImageName.Buffer, ImageNameLen);
405 /* Fix the Persistent structure, so that Buffer is once again an offset */
406 WriteEntry->ImageName.Buffer = (PWCH)(BufferNamePos - Buffer);
407
408 ++WriteEntry;
409 ListEntry = ListEntry->Flink;
410 }
412
414 if (NT_SUCCESS(Status))
415 {
416 Status = ZwSetValueKey(KeyHandle,
418 0,
420 Buffer,
421 Length);
423 }
424 else
425 {
426 DPRINT1("SHIMS: ApphelpCacheWrite could not even open Session Manager\\AppCompatCache (0x%x)\n", Status);
427 }
428
430 return NT_SUCCESS(Status);
431}
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
#define KEY_SET_VALUE
Definition: nt_native.h:1020
WCHAR * PWCH
Definition: ntbasedef.h:422
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
uint64_t ULONGLONG
Definition: typedefs.h:67
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by ApphelpCacheShutdown(), and NtApphelpCacheControl().

◆ ApphelpDuplicateUnicodeString()

VOID ApphelpDuplicateUnicodeString ( _Out_ PUNICODE_STRING  Destination,
_In_ PCUNICODE_STRING  Source 
)

Definition at line 139 of file apphelp.c.

142{
143 Destination->Length = Source->Length;
144 if (Destination->Length)
145 {
150 }
151 else
152 {
155 }
156}
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3051
#define UNICODE_NULL
short WCHAR
Definition: pedump.c:58
USHORT MaximumLength
Definition: env_spec_w32.h:370

Referenced by ApphelpCacheParse(), ApphelpCacheUpdateEntry(), and ApphelpValidateData().

◆ ApphelpFree()

VOID ApphelpFree ( _In_ PVOID  Data)

◆ ApphelpFreeUnicodeString()

VOID ApphelpFreeUnicodeString ( _Inout_ PUNICODE_STRING  String)

Definition at line 159 of file apphelp.c.

161{
162 if (String->Buffer)
163 {
164 ApphelpFree(String->Buffer);
165 }
166 String->Length = 0;
167 String->MaximumLength = 0;
168 String->Buffer = NULL;
169}

Referenced by ApphelpCacheParse(), ApphelpCacheUpdateEntry(), and NtApphelpCacheControl().

◆ ApphelpShimCacheAllocateRoutine()

PVOID NTAPI ApphelpShimCacheAllocateRoutine ( _In_ struct _RTL_AVL_TABLE *  Table,
_In_ CLONG  ByteSize 
)

Definition at line 232 of file apphelp.c.

235{
236 return ApphelpAlloc(ByteSize);
237}

Referenced by ApphelpCacheInitialize().

◆ ApphelpShimCacheCompareRoutine()

RTL_GENERIC_COMPARE_RESULTS NTAPI ApphelpShimCacheCompareRoutine ( _In_ struct _RTL_AVL_TABLE *  Table,
_In_ PVOID  FirstStruct,
_In_ PVOID  SecondStruct 
)

Definition at line 207 of file apphelp.c.

211{
212 PSHIM_CACHE_ENTRY FirstEntry = FirstStruct;
213 PSHIM_CACHE_ENTRY SecondEntry = SecondStruct;
214 LONG Result;
215
216 Result = RtlCompareUnicodeString(&FirstEntry->Persistent.ImageName,
217 &SecondEntry->Persistent.ImageName,
218 TRUE);
219 if (Result < 0)
220 {
221 return GenericLessThan;
222 }
223 else if (Result == 0)
224 {
225 return GenericEqual;
226 }
227 return GenericGreaterThan;
228}
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
long LONG
Definition: pedump.c:60
SHIM_PERSISTENT_CACHE_ENTRY Persistent
Definition: apphelp.c:92
_IRQL_requires_same_ _In_ PVOID _In_ PVOID SecondStruct
Definition: rtltypes.h:403
_IRQL_requires_same_ _In_ PVOID FirstStruct
Definition: rtltypes.h:402
@ GenericLessThan
Definition: rtltypes.h:389
@ GenericEqual
Definition: rtltypes.h:391
@ GenericGreaterThan
Definition: rtltypes.h:390

Referenced by ApphelpCacheInitialize().

◆ ApphelpShimCacheFreeRoutine()

VOID NTAPI ApphelpShimCacheFreeRoutine ( _In_ struct _RTL_AVL_TABLE *  Table,
_In_ PVOID  Buffer 
)

Definition at line 241 of file apphelp.c.

244{
246}

Referenced by ApphelpCacheInitialize().

◆ ApphelpValidateData()

NTSTATUS ApphelpValidateData ( _In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP  ServiceData,
_Out_ PUNICODE_STRING  ImageName,
_Out_ PHANDLE  ImageHandle 
)

Definition at line 472 of file apphelp.c.

476{
478
479 if (ServiceData)
480 {
481 UNICODE_STRING LocalImageName;
483 {
484 ProbeForRead(ServiceData,
486 sizeof(ULONG));
487 LocalImageName = ServiceData->ImageName;
488 *ImageHandle = ServiceData->ImageHandle;
489 if (LocalImageName.Length && LocalImageName.Buffer)
490 {
491 ProbeForRead(LocalImageName.Buffer,
492 LocalImageName.Length * sizeof(WCHAR),
493 1);
494 ApphelpDuplicateUnicodeString(ImageName, &LocalImageName);
496 }
497 }
499 {
501 }
502 _SEH2_END;
503 }
504 if (!NT_SUCCESS(Status))
505 {
506 DPRINT1("SHIMS: ApphelpValidateData: invalid data passed\n");
507 }
508 return Status;
509}
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207

Referenced by NtApphelpCacheControl().

◆ C_ASSERT() [1/2]

◆ C_ASSERT() [2/2]

◆ NtApphelpCacheControl()

NTSTATUS NTAPI NtApphelpCacheControl ( _In_ APPHELPCACHESERVICECLASS  Service,
_In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP  ServiceData 
)

Definition at line 726 of file apphelp.c.

729{
731 UNICODE_STRING ImageName = { 0 };
733
735 {
736 DPRINT1("NtApphelpCacheControl: ApphelpCacheEnabled == 0\n");
737 return Status;
738 }
739 switch (Service)
740 {
742 DPRINT("SHIMS: NtApphelpCacheControl( ApphelpCacheServiceLookup )\n");
743 Status = ApphelpValidateData(ServiceData, &ImageName, &Handle);
744 if (NT_SUCCESS(Status))
746 break;
748 DPRINT("SHIMS: NtApphelpCacheControl( ApphelpCacheServiceRemove )\n");
749 Status = ApphelpValidateData(ServiceData, &ImageName, &Handle);
750 if (NT_SUCCESS(Status))
751 Status = ApphelpCacheRemoveEntry(&ImageName);
752 break;
754 DPRINT("SHIMS: NtApphelpCacheControl( ApphelpCacheServiceUpdate )\n");
756 if (NT_SUCCESS(Status))
757 {
758 Status = ApphelpValidateData(ServiceData, &ImageName, &Handle);
759 if (NT_SUCCESS(Status))
761 }
762 break;
764 /* FIXME: Check for admin or system here. */
766 break;
769 break;
771 DPRINT1("SHIMS: NtApphelpCacheControl( ApphelpDBGReadRegistry ): flushing cache.\n");
773 DPRINT1("SHIMS: NtApphelpCacheControl( ApphelpDBGReadRegistry ): reading cache.\n");
775 break;
777 DPRINT1("SHIMS: NtApphelpCacheControl( ApphelpDBGWriteRegistry ): writing cache.\n");
779 break;
780 default:
781 DPRINT1("SHIMS: NtApphelpCacheControl( Invalid service requested )\n");
782 break;
783 }
784 if (ImageName.Buffer)
785 {
786 ApphelpFreeUnicodeString(&ImageName);
787 }
788 return Status;
789}
ULONG Handle
Definition: gdb_input.c:15
@ ApphelpDBGReadRegistry
Definition: pstypes.h:1099
@ ApphelpCacheServiceLookup
Definition: pstypes.h:1093
@ ApphelpCacheServiceRemove
Definition: pstypes.h:1094
@ ApphelpCacheServiceUpdate
Definition: pstypes.h:1095
@ ApphelpCacheServiceDump
Definition: pstypes.h:1097
@ ApphelpDBGWriteRegistry
Definition: pstypes.h:1100
@ ApphelpCacheServiceFlush
Definition: pstypes.h:1096
NTSTATUS ApphelpCacheDump(VOID)
Definition: apphelp.c:701
NTSTATUS ApphelpCacheFlush(VOID)
Definition: apphelp.c:686
NTSTATUS ApphelpCacheRemoveEntry(_In_ PUNICODE_STRING ImageName)
Definition: apphelp.c:585
NTSTATUS ApphelpCacheUpdateEntry(_In_ PUNICODE_STRING ImageName, _In_ HANDLE ImageHandle)
Definition: apphelp.c:614
NTSTATUS ApphelpValidateData(_In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP ServiceData, _Out_ PUNICODE_STRING ImageName, _Out_ PHANDLE ImageHandle)
Definition: apphelp.c:472
NTSTATUS ApphelpCacheAccessCheck(VOID)
Definition: apphelp.c:600
NTSTATUS ApphelpCacheLookupEntry(_In_ PUNICODE_STRING ImageName, _In_ HANDLE ImageHandle)
Definition: apphelp.c:529
@ Service
Definition: ntsecapi.h:292

Referenced by BaseDumpAppcompatCache(), BaseFlushAppcompatCache(), BasepShimCacheRemoveEntry(), BasepShimCacheSearch(), and CallApphelp().

Variable Documentation

◆ AppCompatCacheKey

UNICODE_STRING AppCompatCacheKey = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache")
static

Definition at line 34 of file apphelp.c.

◆ AppCompatCacheValue

UNICODE_STRING AppCompatCacheValue = RTL_CONSTANT_STRING(L"AppCompatCache")
static

Definition at line 36 of file apphelp.c.

Referenced by ApphelpCacheRead(), and ApphelpCacheWrite().

◆ AppCompatKeyAttributes

◆ ApphelpCacheEnabled

BOOLEAN ApphelpCacheEnabled = FALSE
static

Definition at line 29 of file apphelp.c.

Referenced by ApphelpCacheInitialize(), ApphelpCacheShutdown(), and NtApphelpCacheControl().

◆ ApphelpCacheLock

ERESOURCE ApphelpCacheLock
static

◆ ApphelpShimCache

◆ ApphelpShimCacheAge