2 * PROJECT: shimdbg utility for WINE and ReactOS
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * PURPOSE: Test tool for SHIM engine caching.
5 * PROGRAMMER: Mark Jansen
13 void CallApphelp(APPHELPCACHESERVICECLASS Service
,
14 PAPPHELP_CACHE_SERVICE_LOOKUP CacheEntry
)
16 NTSTATUS Status
= NtApphelpCacheControl(Service
, CacheEntry
);
17 printf("NtApphelpCacheControl returned 0x%x\n", (unsigned int)Status
);
20 HANDLE
MapFile(char* filename
, UNICODE_STRING
* PathName
, int MapIt
)
22 OBJECT_ATTRIBUTES LocalObjectAttributes
;
23 IO_STATUS_BLOCK IoStatusBlock
;
25 HANDLE FileHandle
= NULL
;
26 RtlCreateUnicodeStringFromAsciiz(PathName
, filename
);
29 InitializeObjectAttributes(&LocalObjectAttributes
, PathName
,
30 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
31 Status
= NtOpenFile(&FileHandle
,
32 SYNCHRONIZE
| FILE_READ_ATTRIBUTES
| FILE_READ_DATA
| FILE_EXECUTE
,
33 &LocalObjectAttributes
, &IoStatusBlock
,
34 FILE_SHARE_READ
| FILE_SHARE_DELETE
,
35 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
36 if (!NT_SUCCESS(Status
))
38 printf("Failed opening the file, using a NULL handle\n");
45 void CallApphelpWithImage(char* filename
, int MapIt
,
46 APPHELPCACHESERVICECLASS Service
, char* ServiceName
)
48 UNICODE_STRING PathName
= {0};
49 APPHELP_CACHE_SERVICE_LOOKUP CacheEntry
;
51 HANDLE FileHandle
= MapFile(filename
, &PathName
, MapIt
);
53 printf("Calling %s %s mapping\n", ServiceName
, (MapIt
? "with" : "without"));
55 RtlInitUnicodeString(&CacheEntry
.ImageName
, PathName
.Buffer
);
56 CacheEntry
.ImageHandle
= FileHandle
? FileHandle
: (HANDLE
)-1;
57 CallApphelp(Service
, &CacheEntry
);
58 // we piggy-back on the PathName, so let the Cleanup take care of the string
59 //RtlFreeUnicodeString(&CacheEntry.ImageName);
63 RtlFreeUnicodeString(&PathName
);
66 int IsOpt(char* argv
, const char* check
)
68 if( argv
&& (argv
[0] == '-' || argv
[0] == '/') ) {
69 return !_strnicmp(argv
+ 1, check
, strlen(check
));
74 int HandleImageArg(int argc
, char* argv
[], int* pn
, char MapItChar
,
75 APPHELPCACHESERVICECLASS Service
, char* ServiceName
)
80 int MapIt
= argv
[n
][1] == MapItChar
;
81 CallApphelpWithImage(argv
[n
+1], MapIt
, Service
, ServiceName
);
85 printf("Error: no image name specified\n");
92 #define TAG_TYPE_MASK 0xF000
93 #define TAG_TYPE_DWORD 0x4000
94 #define TAG_TYPE_QWORD 0x5000
95 #define TAG_TYPE_STRINGREF 0x6000
97 #define ATTRIBUTE_AVAILABLE 0x1
98 #define ATTRIBUTE_FAILED 0x2
100 typedef struct tagATTRINFO
103 DWORD flags
; /* ATTRIBUTE_AVAILABLE, ATTRIBUTE_FAILED */
110 } ATTRINFO
, *PATTRINFO
;
113 static LPCWSTR (WINAPI
*pSdbTagToString
)(TAG
);
114 static BOOL (WINAPI
*pSdbGetFileAttributes
)(LPCWSTR
, PATTRINFO
*, LPDWORD
);
115 static BOOL (WINAPI
*pSdbFreeFileAttributes
)(PATTRINFO
);
117 static BOOL
InitApphelp()
121 static UNICODE_STRING DllName
= RTL_CONSTANT_STRING(L
"apphelp.dll");
122 static ANSI_STRING SdbTagToString
= RTL_CONSTANT_STRING("SdbTagToString");
123 static ANSI_STRING SdbGetFileAttributes
= RTL_CONSTANT_STRING("SdbGetFileAttributes");
124 static ANSI_STRING SdbFreeFileAttributes
= RTL_CONSTANT_STRING("SdbFreeFileAttributes");
125 if (!NT_SUCCESS(LdrLoadDll(NULL
, NULL
, &DllName
, &hdll
)))
127 printf("Unable to load apphelp.dll\n");
130 if (!NT_SUCCESS(LdrGetProcedureAddress(hdll
, &SdbTagToString
, 0, (PVOID
)&pSdbTagToString
)) ||
131 !NT_SUCCESS(LdrGetProcedureAddress(hdll
, &SdbGetFileAttributes
, 0, (PVOID
)&pSdbGetFileAttributes
)) ||
132 !NT_SUCCESS(LdrGetProcedureAddress(hdll
, &SdbFreeFileAttributes
, 0, (PVOID
)&pSdbFreeFileAttributes
)))
136 printf("Unable to resolve functions\n");
144 int HandleDumpAttributes(int argc
, char* argv
[], int* pn
, const char* opt
)
146 UNICODE_STRING FileName
;
155 if (strlen(argv
[argn
]) > (strlen(opt
)+1))
157 arg
= argv
[argn
] + strlen(opt
);
159 else if (argn
+1 >= argc
)
161 printf("Error: no image name specified\n");
170 RtlCreateUnicodeStringFromAsciiz(&FileName
, arg
);
172 if (pSdbGetFileAttributes(FileName
.Buffer
, &attr
, &num_attr
))
174 printf("Dumping attributes for %s\n", arg
);
175 for (n
= 0; n
< num_attr
; ++n
)
179 if (attr
[n
].flags
!= ATTRIBUTE_AVAILABLE
)
182 tagName
= pSdbTagToString(attr
[n
].type
);
184 tagType
= attr
[n
].type
& TAG_TYPE_MASK
;
188 printf("<%ls>0x%lx</%ls><!-- %ld -->\n", tagName
, attr
[n
].dwattr
, tagName
, attr
[n
].dwattr
);
190 case TAG_TYPE_STRINGREF
:
191 printf("<%ls>0x%ls</%ls>\n", tagName
, attr
[n
].lpattr
, tagName
);
194 printf("<%ls>0x%I64x</%ls><!-- %I64d -->\n", tagName
, attr
[n
].qwattr
, tagName
, attr
[n
].qwattr
);
197 printf("<!-- Unknown tag type: 0x%x (from 0x%x)\n", tagType
, attr
[n
].type
);
205 printf("Unable to get attributes from %s\n", arg
);
209 RtlFreeUnicodeString(&FileName
);
213 UNICODE_STRING AppCompatCacheKey
= RTL_CONSTANT_STRING(L
"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache");
214 OBJECT_ATTRIBUTES AppCompatKeyAttributes
= RTL_CONSTANT_OBJECT_ATTRIBUTES(&AppCompatCacheKey
, OBJ_CASE_INSENSITIVE
);
215 UNICODE_STRING AppCompatCacheValue
= RTL_CONSTANT_STRING(L
"AppCompatCache");
216 #define REG_BINARY ( 3 ) // Free form binary
219 /* produce a hex dump, stolen from rdesktop.c */
220 void hexdump(unsigned char *p
, unsigned int len
)
222 unsigned char *line
= p
;
223 unsigned int i
, thisline
, offset
= 0;
227 printf("%04x ", offset
);
228 thisline
= len
- offset
;
232 for (i
= 0; i
< thisline
; i
++)
233 printf("%02x ", line
[i
]);
238 for (i
= 0; i
< thisline
; i
++)
239 printf("%c", (line
[i
] >= 0x20 && line
[i
] < 0x7f) ? line
[i
] : '.');
247 void DumpRegistryData(int IncludeDump
)
251 KEY_VALUE_PARTIAL_INFORMATION KeyValueObject
;
252 PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation
= &KeyValueObject
;
253 ULONG KeyInfoSize
, ResultSize
;
255 printf("Dumping AppCompatCache registry key\n");
257 Status
= NtOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &AppCompatKeyAttributes
);
259 Status
= NtQueryValueKey(KeyHandle
, &AppCompatCacheValue
,
260 KeyValuePartialInformation
, KeyValueInformation
,
261 sizeof(KeyValueObject
), &ResultSize
);
263 if (Status
== STATUS_BUFFER_OVERFLOW
)
265 KeyInfoSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + KeyValueInformation
->DataLength
;
266 KeyValueInformation
= malloc(KeyInfoSize
);
267 if (KeyValueInformation
!= NULL
)
269 Status
= NtQueryValueKey(KeyHandle
, &AppCompatCacheValue
,
270 KeyValuePartialInformation
, KeyValueInformation
,
271 KeyInfoSize
, &ResultSize
);
275 if (NT_SUCCESS(Status
) && KeyValueInformation
->Type
== REG_BINARY
)
279 hexdump(KeyValueInformation
->Data
, KeyValueInformation
->DataLength
);
280 crc
= RtlComputeCrc32(0, KeyValueInformation
->Data
, KeyValueInformation
->DataLength
);
281 printf("Len: %lu, Crc: 0x%lx\n", KeyValueInformation
->DataLength
, crc
);
285 printf("Failed reading AppCompatCache from registry (0x%lx)\n", Status
);
288 if (KeyValueInformation
!= &KeyValueObject
)
289 free(KeyValueInformation
);
297 int main(int argc
, char* argv
[])
299 int n
, unhandled
= 0, keepopen
= 0;
301 for (n
= 1; n
< argc
; ++n
)
306 printf("Calling ApphelpCacheServiceDump\n");
307 CallApphelp(ApphelpCacheServiceDump
, NULL
);
310 else if (IsOpt(arg
, "h"))
312 DumpRegistryData(arg
[1] == 'h');
315 else if (IsOpt(arg
, "f"))
317 printf("Calling ApphelpCacheServiceFlush\n");
318 CallApphelp(ApphelpCacheServiceFlush
, NULL
);
321 else if (IsOpt(arg
, "z"))
323 printf("Calling ApphelpDBGReadRegistry\n");
324 CallApphelp(ApphelpDBGReadRegistry
, NULL
);
327 else if (IsOpt(arg
, "x"))
329 printf("Calling ApphelpDBGWriteRegistry\n");
330 CallApphelp(ApphelpDBGWriteRegistry
, NULL
);
333 else if (IsOpt(arg
, "l"))
335 unhandled
|= HandleImageArg(argc
, argv
, &n
, 'l',
336 ApphelpCacheServiceLookup
, "ApphelpCacheServiceLookup");
338 else if (IsOpt(arg
, "u"))
340 unhandled
|= HandleImageArg(argc
, argv
, &n
, 'u',
341 ApphelpCacheServiceUpdate
, "ApphelpCacheServiceUpdate");
343 else if (IsOpt(arg
, "r"))
345 unhandled
|= HandleImageArg(argc
, argv
, &n
, 'r',
346 ApphelpCacheServiceRemove
, "ApphelpCacheServiceRemove");
348 else if (IsOpt(arg
, "a"))
350 unhandled
|= HandleDumpAttributes(argc
, argv
, &n
, "a");
352 else if (IsOpt(arg
, "k"))
361 if (unhandled
|| argc
== 1)
363 printf("Usage: %s [-d|-z|-x|-h|-H|-f|-[l|L] <image>|-[u|U] <image>|-[r|R] <image>|-k]\n", argv
[0]);
364 printf(" -d: Dump shim cache over debug output\n");
365 printf(" -z: DEBUG Read shim cache from registry\n");
366 printf(" -x: DEBUG Write shim cache to registry\n");
367 printf(" -h: Hexdump shim registry key\n");
368 printf(" -H: Crc + Length from shim registry key only\n");
369 printf(" -f: Flush (clear) the shim cache\n");
370 printf(" -l: Lookup <image> in the shim cache\n");
371 printf(" -L: Lookup <image> in the shim cache without mapping it\n");
372 printf(" -u: Update (insert) <image> in the shim cache\n");
373 printf(" -U: Update (insert) <image> in the shim cache without mapping it\n");
374 printf(" -r: Remove <image> from the shim cache\n");
375 printf(" -R: Remove <image> from the shim cache without mapping it\n");
376 printf(" -a: Dump file attributes as used in the appcompat database\n");
377 printf(" -k: Keep the console open\n");