/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: hooks.c Abstract: This module implements verifier hooks for various APIs that do not fall in any specific category. Author: Silviu Calinoiu (SilviuC) 3-Dec-2001 Revision History: 3-Dec-2001 (SilviuC): initial version. --*/ #include "pch.h" #include "verifier.h" #include "support.h" #include "faults.h" ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// Wait APIs ///////////////////////////////////////////////////////////////////// //WINBASEAPI DWORD WINAPI AVrfpWaitForSingleObject( IN HANDLE hHandle, IN DWORD dwMilliseconds ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (HANDLE, DWORD); FUNCTION_TYPE Function; DWORD Result; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_WAITFORSINGLEOBJECT); BUMP_COUNTER (CNT_WAIT_SINGLE_CALLS); if (dwMilliseconds != INFINITE && dwMilliseconds != 0) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_CALLS); if (SHOULD_FAULT_INJECT(CLS_WAIT_APIS)) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_FAILS); CHECK_BREAK (BRK_WAIT_WITH_TIMEOUT_FAIL); return WAIT_TIMEOUT; } } Result = (* Function) (hHandle, dwMilliseconds); // // No matter if it fails or not we will introduce a random delay // in order to randomize the timings in the process. // if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } return Result; } //WINBASEAPI DWORD WINAPI AVrfpWaitForMultipleObjects( IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (DWORD, CONST HANDLE *, BOOL, DWORD); FUNCTION_TYPE Function; DWORD Result; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_WAITFORMULTIPLEOBJECTS); BUMP_COUNTER (CNT_WAIT_MULTIPLE_CALLS); if (dwMilliseconds != INFINITE && dwMilliseconds != 0) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_CALLS); if (SHOULD_FAULT_INJECT(CLS_WAIT_APIS)) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_FAILS); CHECK_BREAK (BRK_WAIT_WITH_TIMEOUT_FAIL); return WAIT_TIMEOUT; } } Result = (* Function) (nCount, lpHandles, bWaitAll, dwMilliseconds); // // No matter if it fails or not we will introduce a random delay // in order to randomize the timings in the process. // if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } return Result; } //WINBASEAPI DWORD WINAPI AVrfpWaitForSingleObjectEx( IN HANDLE hHandle, IN DWORD dwMilliseconds, IN BOOL bAlertable ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (HANDLE, DWORD, BOOL); FUNCTION_TYPE Function; DWORD Result; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_WAITFORSINGLEOBJECTEX); BUMP_COUNTER (CNT_WAIT_SINGLEEX_CALLS); if (dwMilliseconds != INFINITE && dwMilliseconds != 0) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_CALLS); if (SHOULD_FAULT_INJECT(CLS_WAIT_APIS)) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_FAILS); CHECK_BREAK (BRK_WAIT_WITH_TIMEOUT_FAIL); return WAIT_TIMEOUT; } } Result = (* Function) (hHandle, dwMilliseconds, bAlertable); // // No matter if it fails or not we will introduce a random delay // in order to randomize the timings in the process. // if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } return Result; } //WINBASEAPI DWORD WINAPI AVrfpWaitForMultipleObjectsEx( IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds, IN BOOL bAlertable ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (DWORD, CONST HANDLE *, BOOL, DWORD, BOOL); FUNCTION_TYPE Function; DWORD Result; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_WAITFORMULTIPLEOBJECTSEX); BUMP_COUNTER (CNT_WAIT_MULTIPLEEX_CALLS); if (dwMilliseconds != INFINITE && dwMilliseconds != 0) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_CALLS); if (SHOULD_FAULT_INJECT(CLS_WAIT_APIS)) { BUMP_COUNTER (CNT_WAIT_WITH_TIMEOUT_FAILS); CHECK_BREAK (BRK_WAIT_WITH_TIMEOUT_FAIL); return WAIT_TIMEOUT; } } Result = (* Function) (nCount, lpHandles, bWaitAll, dwMilliseconds, bAlertable); // // No matter if it fails or not we will introduce a random delay // in order to randomize the timings in the process. // if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } return Result; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtWaitForSingleObject( IN HANDLE Handle, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ) { NTSTATUS Status; // // Verify that it is legal to wait for this object // in the current state. One example of illegal wait // is waiting for a thread object while holding the // loader lock. That thread will need the loader lock // when calling ExitThread so it will most likely // deadlock with the current thread. // AVrfpVerifyLegalWait (&Handle, 1, TRUE); // // Call the original function. // Status = NtWaitForSingleObject (Handle, Alertable, Timeout); return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtWaitForMultipleObjects( IN ULONG Count, IN HANDLE Handles[], IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL ) { NTSTATUS Status; // // Verify that it is legal to wait for these objects // in the current state. One example of illegal wait // is waiting for a thread object while holding the // loader lock. That thread will need the loader lock // when calling ExitThread so it will most likely // deadlock with the current thread. // AVrfpVerifyLegalWait (Handles, Count, (WaitType == WaitAll)); // // Call the original function. // Status = NtWaitForMultipleObjects (Count, Handles, WaitType, Alertable, Timeout); return Status; } ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// File APIs ///////////////////////////////////////////////////////////////////// //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtCreateFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PLARGE_INTEGER AllocationSize OPTIONAL, IN ULONG FileAttributes, IN ULONG ShareAccess, IN ULONG CreateDisposition, IN ULONG CreateOptions, IN PVOID EaBuffer OPTIONAL, IN ULONG EaLength ) { NTSTATUS Status; if (SHOULD_FAULT_INJECT(CLS_FILE_APIS)) { CHECK_BREAK (BRK_CREATE_FILE_FAIL); return STATUS_NO_MEMORY; } Status = NtCreateFile (FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, EaBuffer, EaLength); return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtOpenFile( OUT PHANDLE FileHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions ) { NTSTATUS Status; if (SHOULD_FAULT_INJECT(CLS_FILE_APIS)) { CHECK_BREAK (BRK_CREATE_FILE_FAIL); return STATUS_NO_MEMORY; } Status = NtOpenFile (FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, ShareAccess, OpenOptions); return Status; } //WINBASEAPI HANDLE WINAPI AVrfpCreateFileA( IN LPCSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile ) { typedef HANDLE (WINAPI * FUNCTION_TYPE) (LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_CREATEFILEA); if (SHOULD_FAULT_INJECT(CLS_FILE_APIS)) { CHECK_BREAK (BRK_CREATE_FILE_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return INVALID_HANDLE_VALUE; } return (* Function) (lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } //WINBASEAPI HANDLE WINAPI AVrfpCreateFileW( IN LPCWSTR lpFileName, IN DWORD dwDesiredAccess, IN DWORD dwShareMode, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, IN DWORD dwCreationDisposition, IN DWORD dwFlagsAndAttributes, IN HANDLE hTemplateFile ) { typedef HANDLE (WINAPI * FUNCTION_TYPE) (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_CREATEFILEW); if (SHOULD_FAULT_INJECT(CLS_FILE_APIS)) { CHECK_BREAK (BRK_CREATE_FILE_FAIL); NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return INVALID_HANDLE_VALUE; } return (* Function) (lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////// Registry APIs ///////////////////////////////////////////////////////////////////// //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtCreateKey( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL ) { NTSTATUS Status; if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return STATUS_NO_MEMORY; } Status = NtCreateKey (KeyHandle, DesiredAccess, ObjectAttributes, TitleIndex, Class, CreateOptions, Disposition); return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtOpenKey( OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes ) { NTSTATUS Status; if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return STATUS_NO_MEMORY; } Status = NtOpenKey (KeyHandle, DesiredAccess, ObjectAttributes); return Status; } //WINADVAPI LONG APIENTRY AVrfpRegCreateKeyA ( IN HKEY hKey, IN LPCSTR lpSubKey, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCSTR, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGCREATEKEYA); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, phkResult); } //WINADVAPI LONG APIENTRY AVrfpRegCreateKeyW ( IN HKEY hKey, IN LPCWSTR lpSubKey, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCWSTR, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGCREATEKEYW); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, phkResult); } //WINADVAPI LONG APIENTRY AVrfpRegCreateKeyExA ( IN HKEY hKey, IN LPCSTR lpSubKey, IN DWORD Reserved, IN LPSTR lpClass, IN DWORD dwOptions, IN REGSAM samDesired, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, OUT PHKEY phkResult, OUT LPDWORD lpdwDisposition ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCSTR, DWORD, LPSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGCREATEKEYEXA); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } //WINADVAPI LONG APIENTRY AVrfpRegCreateKeyExW ( IN HKEY hKey, IN LPCWSTR lpSubKey, IN DWORD Reserved, IN LPWSTR lpClass, IN DWORD dwOptions, IN REGSAM samDesired, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, OUT PHKEY phkResult, OUT LPDWORD lpdwDisposition ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGCREATEKEYEXW); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition); } //WINADVAPI LONG APIENTRY AVrfpRegOpenKeyA ( IN HKEY hKey, IN LPCSTR lpSubKey, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCSTR, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGOPENKEYA); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function)(hKey, lpSubKey, phkResult); } //WINADVAPI LONG APIENTRY AVrfpRegOpenKeyW ( IN HKEY hKey, IN LPCWSTR lpSubKey, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCWSTR, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGOPENKEYW); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function)(hKey, lpSubKey, phkResult); } //WINADVAPI LONG APIENTRY AVrfpRegOpenKeyExA ( IN HKEY hKey, IN LPCSTR lpSubKey, IN DWORD ulOptions, IN REGSAM samDesired, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCSTR, DWORD, REGSAM, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGOPENKEYEXA); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, ulOptions, samDesired, phkResult); } //WINADVAPI LONG APIENTRY AVrfpRegOpenKeyExW ( IN HKEY hKey, IN LPCWSTR lpSubKey, IN DWORD ulOptions, IN REGSAM samDesired, OUT PHKEY phkResult ) { typedef LONG (APIENTRY * FUNCTION_TYPE) (HKEY, LPCWSTR, DWORD, REGSAM, PHKEY); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpAdvapi32Thunks, AVRF_INDEX_ADVAPI32_REGOPENKEYEXW); if (SHOULD_FAULT_INJECT(CLS_REGISTRY_APIS)) { CHECK_BREAK (BRK_CREATE_KEY_FAIL); return ERROR_OUTOFMEMORY; } return (* Function) (hKey, lpSubKey, ulOptions, samDesired, phkResult); } ///////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// Read/Write File I/O ///////////////////////////////////////////////////////////////////// //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtReadFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ) { NTSTATUS Status; // // Fill the I/O buffer with garbage. // // silviuc: should we link this fill to some feature? // In principle the operation of filling memory is peanuts // compared with the time taken by the i/o operation. // RtlFillMemory (Buffer, Length, 0xFA); // // Call original API. // Status = NtReadFile (FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); // // Asynchronous operations are delayed a bit. This conceivably // has good chances to randomize timings in the process. // if (Status == STATUS_PENDING) { if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } } return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtReadFileScatter( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PFILE_SEGMENT_ELEMENT SegmentArray, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ) { NTSTATUS Status; // // silviuc: we should fill these buffers with garbage too. // // // Call original API. // Status = NtReadFileScatter (FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, SegmentArray, Length, ByteOffset, Key); // // Asynchronous operations are delayed a bit. This conceivably // has good chances to randomize timings in the process. // if (Status == STATUS_PENDING) { if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } } return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtWriteFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ) { NTSTATUS Status; // // Call original API. // Status = NtWriteFile (FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset, Key); // // Asynchronous operations are delayed a bit. This conceivably // has good chances to randomize timings in the process. // if (Status == STATUS_PENDING) { if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } } return Status; } //NTSYSCALLAPI NTSTATUS NTAPI AVrfpNtWriteFileGather( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PFILE_SEGMENT_ELEMENT SegmentArray, IN ULONG Length, IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL ) { NTSTATUS Status; // // Call original API. // Status = NtWriteFileGather (FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, SegmentArray, Length, ByteOffset, Key); // // Asynchronous operations are delayed a bit. This conceivably // has good chances to randomize timings in the process. // if (Status == STATUS_PENDING) { if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_RACE_CHECKS)) { AVrfpCreateRandomDelay (); } } return Status; } ///////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////// Tick count overlap ///////////////////////////////////////////////////////////////////// // // Special value so that the counter will overlap in 5 mins. // DWORD AVrfpTickCountOffset = 0xFFFFFFFF - 5 * 60 * 1000; //WINBASEAPI DWORD WINAPI AVrfpGetTickCount( VOID ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (VOID); FUNCTION_TYPE Function; DWORD Result; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_GETTICKCOUNT); Result = (* Function) (); if ((AVrfpProvider.VerifierFlags & RTL_VRF_FLG_MISCELLANEOUS_CHECKS)) { return Result + AVrfpTickCountOffset; } else { return Result; } }