ReactOS 0.4.17-dev-684-ga6524ef
NtApphelpCacheControl.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: LGPL - See COPYING.LIB in the top level directory
4 * PURPOSE: Tests for SHIM engine caching.
5 * PROGRAMMER: Mark Jansen
6 */
7
8#include "precomp.h"
9
10#include <winsvc.h>
11#include <versionhelpers.h>
12
14{
17};
18
20
22{
23 APPHELP_CACHE_SERVICE_LOOKUP CacheEntry = { {0} };
25 CacheEntry.ImageName = *PathName;
26 if (WithMapping)
27 {
28 OBJECT_ATTRIBUTES LocalObjectAttributes;
30 InitializeObjectAttributes(&LocalObjectAttributes, PathName,
32 Status = NtOpenFile(&CacheEntry.ImageHandle,
34 &LocalObjectAttributes, &IoStatusBlock,
38 }
39 else
40 {
42 }
43 Status = pNtApphelpCacheControl(Service, &CacheEntry);
44 if (CacheEntry.ImageHandle != INVALID_HANDLE_VALUE)
45 NtClose(CacheEntry.ImageHandle);
46 return Status;
47}
48
49int InitEnv(UNICODE_STRING* PathName)
50{
53 {
54 /* Windows Vista+ has a different layout for APPHELP_CACHE_SERVICE_LOOKUP */
55 return 0;
56 }
58 "Wrong value for Status, expected: SUCCESS or NOT_FOUND, got: 0x%lx\n",
59 Status);
60 return 1;
61}
62
64{
65 APPHELP_CACHE_SERVICE_LOOKUP CacheEntry = { {0} };
67
68 /* Validate the handling of a NULL pointer */
69 Status = pNtApphelpCacheControl(ApphelpCacheServiceRemove, NULL);
71 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, NULL);
73
74 /* Validate the handling of a NULL pointer inside the struct */
75 Status = pNtApphelpCacheControl(ApphelpCacheServiceRemove, &CacheEntry);
77 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, &CacheEntry);
79
80 /* Just call the dump function */
81 Status = pNtApphelpCacheControl(ApphelpCacheServiceDump, NULL);
83
84 /* Validate the handling of an invalid handle inside the struct */
85 CacheEntry.ImageName = *PathName;
86 CacheEntry.ImageHandle = (HANDLE)2;
87 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, &CacheEntry);
89
90 /* Validate the handling of an invalid service number */
91 Status = pNtApphelpCacheControl(999, NULL);
93 Status = pNtApphelpCacheControl(999, &CacheEntry);
95}
96
97static BOOLEAN RequestAddition(SC_HANDLE service_handle, BOOLEAN WithMapping)
98{
102 /* TODO: how to get a return code from the service? */
103 return TRUE;
104}
105
107{
109 UNICODE_STRING ntPath;
113
114 GetModuleFileNameW(NULL, szPath, sizeof(szPath) / sizeof(szPath[0]));
116 ok(Result == TRUE, "RtlDosPathNameToNtPathName_U\n");
117 if (!InitEnv(&ntPath))
118 {
119 skip("NtApphelpCacheControl expects a different structure layout\n");
120 if (Result)
121 {
122 RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer);
123 }
124 return;
125 }
126 /* At this point we have made sure that our binary is not present in the cache,
127 and that the NtApphelpCacheControl function expects the struct layout we use. */
128 CheckValidation(&ntPath);
129
130 /* We expect not to find it */
135
136 /* First we add our process without a file handle (so it will be registered without file info) */
138
139 /* now we try to find it without validating file info */
142 /* when validating file info the cache notices the file is wrong, so it is dropped from the cache */
145 /* making the second check without info also fail. */
148
149
150 /* Now we add the file with file info */
152
153 /* so both checks should succeed */
158
159 /* We know the file is in the cache now (assuming previous tests succeeded,
160 let's test invalid handle behavior */
161 CacheEntry.ImageName = ntPath;
162 CacheEntry.ImageHandle = 0;
163 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, &CacheEntry);
165
166 /* re-add it for the next test */
170 CacheEntry.ImageHandle = (HANDLE)1;
171 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, &CacheEntry);
173
174 /* and again */
178#ifdef _WIN64
179 CacheEntry.ImageHandle = (HANDLE)0x8000000000000000ULL;
180#else
181 CacheEntry.ImageHandle = (HANDLE)0x80000000;
182#endif
183 Status = pNtApphelpCacheControl(ApphelpCacheServiceLookup, &CacheEntry);
185
186 RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer);
187}
188
189
190/* Most service related code was taken from services_winetest:service and modified for usage here
191 The rest came from MSDN */
192
193static SERVICE_STATUS_HANDLE (WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR,LPHANDLER_FUNCTION_EX,LPVOID);
194static char service_name[100] = "apphelp_test_service";
197
199{
201 UNICODE_STRING ntPath;
204 GetModuleFileNameW(NULL, szPath, sizeof(szPath) / sizeof(szPath[0]));
206 if (!Result)
207 {
208 DbgPrint("RegisterInShimCache: RtlDosPathNameToNtPathName_U failed\n");
209 return FALSE;
210 }
211
212 Status = CallCacheControl(&ntPath, WithMapping, ApphelpCacheServiceUpdate);
213 if (!NT_SUCCESS(Status))
214 {
215 DbgPrint("RegisterInShimCache: CallCacheControl failed\n");
216 RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer);
217 return FALSE;
218 }
219 RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer);
220 return TRUE;
221}
222
223
224static DWORD WINAPI service_handler(DWORD ctrl, DWORD event_type, void *event_data, void *context)
225{
227 status.dwServiceType = SERVICE_WIN32;
228 status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
229
230 switch(ctrl)
231 {
234 status.dwCurrentState = SERVICE_STOP_PENDING;
235 status.dwControlsAccepted = 0;
238 return NO_ERROR;
241 {
242 /* TODO: how should we communicate a failure? */
243 }
244 break;
247 {
248 /* TODO: how should we communicate a failure? */
249 }
250 break;
251 default:
252 DbgPrint("Unhandled: %d\n", ctrl);
253 break;
254 }
255 status.dwCurrentState = SERVICE_RUNNING;
257 return NO_ERROR;
258}
259
260static void WINAPI service_main(DWORD argc, char **argv)
261{
263 service_status = pRegisterServiceCtrlHandlerExA(service_name, service_handler, NULL);
264 if(!service_status)
265 return;
266
267 status.dwServiceType = SERVICE_WIN32;
268 status.dwCurrentState = SERVICE_RUNNING;
271
273
274 status.dwCurrentState = SERVICE_STOPPED;
275 status.dwControlsAccepted = 0;
277}
278
279static SC_HANDLE InstallService(SC_HANDLE scm_handle)
280{
281 char service_cmd[MAX_PATH+150], *ptr;
282 SC_HANDLE service;
283
284 ptr = service_cmd + GetModuleFileNameA(NULL, service_cmd, MAX_PATH);
285 strcpy(ptr, " NtApphelpCacheControl service");
286 ptr += strlen(ptr);
287
290 service_cmd, NULL, NULL, NULL, NULL, NULL);
291 if (!service)
292 {
293 skip("Could not create helper service\n");
294 return NULL;
295 }
296 return service;
297}
298
300{
301 DWORD dwBytesNeeded;
302 DWORD dwStartTime = GetTickCount();
303 while (ssp->dwCurrentState != Status)
304 {
305 Sleep(40);
307 (LPBYTE)ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded ))
308 {
309 ok(0, "QueryServiceStatusEx failed waiting for %lu\n", Status);
310 break;
311 }
312 if ((GetTickCount() - dwStartTime) > 1000)
313 {
314 ok(0, "Timeout waiting for (%lu) from service, is: %lu.\n",
315 Status, ssp->dwCurrentState);
316 break;
317 }
318 }
319}
320
321static void RunTest()
322{
325 if (service_handle)
326 {
327 SERVICE_STATUS_PROCESS ssp = {0};
329 if (res)
330 {
335 }
336 else
337 {
338 skip("Could not start helper service\n");
339 }
341 }
343}
344
346{
347 char **argv;
348 int argc;
349
350 pRegisterServiceCtrlHandlerExA = (void*)GetProcAddress(GetModuleHandleA("advapi32.dll"), "RegisterServiceCtrlHandlerExA");
351 if (!pRegisterServiceCtrlHandlerExA)
352 {
353 win_skip("RegisterServiceCtrlHandlerExA not available, skipping tests\n");
354 return;
355 }
356
357 pNtApphelpCacheControl = (void*)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtApphelpCacheControl");
358 if (!pNtApphelpCacheControl)
359 {
360 win_skip("NtApphelpCacheControl not available, skipping tests\n");
361 return;
362 }
363
365 if(argc < 3)
366 {
367 RunTest();
368 }
369 else
370 {
371 SERVICE_TABLE_ENTRYA servtbl[] = {
373 {NULL, NULL}
374 };
377 Sleep(50);
379 }
380}
381
382
static void WINAPI service_main(DWORD argc, char **argv)
static void WaitService(SC_HANDLE service_handle, DWORD Status, SERVICE_STATUS_PROCESS *ssp)
@ RegisterShimCacheWithHandle
@ RegisterShimCacheWithoutHandle
static void RunApphelpCacheControlTests(SC_HANDLE service_handle)
static SC_HANDLE InstallService(SC_HANDLE scm_handle)
static PAPPHELP_CACHE_SERVICE_LOOKUP
static DWORD WINAPI service_handler(DWORD ctrl, DWORD event_type, void *event_data, void *context)
NTSTATUS CallCacheControl(UNICODE_STRING *PathName, BOOLEAN WithMapping, APPHELPCACHESERVICECLASS Service)
static HANDLE service_stop_event
static LPVOID
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
static void RunTest()
static BOOLEAN RequestAddition(SC_HANDLE service_handle, BOOLEAN WithMapping)
static LPHANDLER_FUNCTION_EX
static SERVICE_STATUS_HANDLE service_status
int InitEnv(UNICODE_STRING *PathName)
static BOOLEAN RegisterInShimCache(BOOLEAN WithMapping)
void CheckValidation(UNICODE_STRING *PathName)
static char service_name[100]
static SC_HANDLE scm_handle
Definition: ServiceArgs.c:20
unsigned char BOOLEAN
Definition: actypes.h:127
#define ok_ntstatus(status, expected)
Definition: atltest.h:135
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_NON_DIRECTORY_FILE
Definition: constants.h:492
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
#define NO_ERROR
Definition: dderror.h:5
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define NTSTATUS
Definition: precomp.h:19
#define CloseHandle
Definition: compat.h:739
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define FILE_SHARE_READ
Definition: compat.h:136
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1597
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
Status
Definition: gdiplustypes.h:24
GLuint res
Definition: glext.h:9613
#define DbgPrint
Definition: hal.h:12
enum _APPHELPCACHESERVICECLASS APPHELPCACHESERVICECLASS
@ ApphelpCacheServiceLookup
Definition: pstypes.h:1063
@ ApphelpCacheServiceRemove
Definition: pstypes.h:1064
@ ApphelpCacheServiceUpdate
Definition: pstypes.h:1065
@ ApphelpCacheServiceDump
Definition: pstypes.h:1067
#define win_skip
Definition: minitest.h:67
LPCWSTR szPath
Definition: env.c:37
static PVOID ptr
Definition: dispmode.c:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define ctrl
Definition: input.c:3281
#define argv
Definition: mplay32.c:18
NTSYSAPI BOOLEAN NTAPI RtlDosPathNameToNtPathName_U(_In_opt_z_ PCWSTR DosPathName, _Out_ PUNICODE_STRING NtPathName, _Out_opt_ PCWSTR *NtFileNamePart, _Out_opt_ PRTL_RELATIVE_NAME_U DirectoryInfo)
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_EXECUTE
Definition: nt_native.h:642
#define GENERIC_ALL
Definition: nt_native.h:92
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3429
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:100
NTSTATUS NTAPI NtApphelpCacheControl(_In_ APPHELPCACHESERVICECLASS Service, _In_opt_ PAPPHELP_CACHE_SERVICE_LOOKUP ServiceData)
Definition: apphelp.c:728
short WCHAR
Definition: pedump.c:58
@ Service
Definition: ntsecapi.h:292
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
@ SC_STATUS_PROCESS_INFO
Definition: winsvc.h:125
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:46
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:42
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
#define SC_MANAGER_ALL_ACCESS
Definition: winsvc.h:13
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
static SERVICE_STATUS_HANDLE service_handle
Definition: rpcss_main.c:44
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI StartServiceA(SC_HANDLE hService, DWORD dwNumServiceArgs, LPCSTR *lpServiceArgVectors)
Definition: scm.c:2981
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel, LPBYTE lpBuffer, DWORD cbBufSize, LPDWORD pcbBytesNeeded)
Definition: scm.c:2926
SC_HANDLE WINAPI CreateServiceA(SC_HANDLE hSCManager, LPCSTR lpServiceName, LPCSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName, LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies, LPCSTR lpServiceStartName, LPCSTR lpPassword)
Definition: scm.c:680
SC_HANDLE WINAPI OpenSCManagerA(LPCSTR lpMachineName, LPCSTR lpDatabaseName, DWORD dwDesiredAccess)
Definition: scm.c:2063
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
BOOL WINAPI StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
Definition: sctrl.c:1054
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:1016
strcpy
Definition: string.h:131
int winetest_get_mainargs(char ***pargv)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
UNICODE_STRING ImageName
Definition: pstypes.h:1076
Definition: http.c:7252
Definition: ps.c:97
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
const char * LPCSTR
Definition: typedefs.h:52
unsigned char * LPBYTE
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
PVOID HANDLE
Definition: typedefs.h:73
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VERSIONHELPERAPI IsWindows7OrGreater()
#define WINAPI
Definition: msvc.h:6
_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
#define SERVICE_DEMAND_START
Definition: cmtypes.h:979
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:963
#define SERVICE_ERROR_IGNORE
Definition: cmtypes.h:982
#define SERVICE_WIN32
Definition: cmtypes.h:965