/*++ Copyright (c) 1989 Microsoft Corporation Module Name: thread.c Abstract: This module implements verification functions for thread interfaces. Author: Silviu Calinoiu (SilviuC) 22-Feb-2001 Revision History: --*/ #include "pch.h" #include "verifier.h" #include "support.h" //WINBASEAPI DECLSPEC_NORETURN VOID WINAPI AVrfpExitThread( IN DWORD dwExitCode ) { typedef VOID (WINAPI * FUNCTION_TYPE) (DWORD); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_EXITTHREAD); // // Checking for orphaned locks is a no op if lock verifier // is not enabled. // RtlCheckForOrphanedCriticalSections(NtCurrentThread()); // // Perform all typical checks for a thread that will exit. // AVrfpCheckThreadTermination (); // // Call the real thing. // (* Function)(dwExitCode); } //WINBASEAPI BOOL WINAPI AVrfpTerminateThread( IN OUT HANDLE hThread, IN DWORD dwExitCode ) { typedef BOOL (WINAPI * FUNCTION_TYPE) (HANDLE, DWORD); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_TERMINATETHREAD); // // Checking for orphaned locks is a no op if lock verifier // is not enabled. // RtlCheckForOrphanedCriticalSections(hThread); // // This API should not be called. We need to report this. // This is useful if we did not detect any orphans but we still want // to complain. // VERIFIER_STOP (APPLICATION_VERIFIER_TERMINATE_THREAD_CALL, "TerminateThread() called. This function should not be used.", NtCurrentTeb()->ClientId.UniqueProcess, "Caller thread ID", 0, NULL, 0, NULL, 0, NULL); return (* Function)(hThread, dwExitCode); } //WINBASEAPI DWORD WINAPI AVrfpSuspendThread( IN HANDLE hThread ) { typedef DWORD (WINAPI * FUNCTION_TYPE) (HANDLE); FUNCTION_TYPE Function; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_SUSPENDTHREAD); // // Checking for orphaned locks is a no op if lock verifier // is not enabled. // // SilviuC: disabled this check for now because java VM and others // might do this in valid conditions. // // RtlCheckForOrphanedCriticalSections(hThread); // return (* Function)(hThread); } //WINBASEAPI HANDLE WINAPI AVrfpCreateThread( IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN SIZE_T dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId ) { typedef HANDLE (WINAPI * FUNCTION_TYPE) (LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD); FUNCTION_TYPE Function; HANDLE Result; DWORD ThreadId; PAVRF_THREAD_INFO Info; Function = AVRFP_GET_ORIGINAL_EXPORT (AVrfpKernel32Thunks, AVRF_INDEX_KERNEL32_CREATETHREAD); Info = RtlAllocateHeap (RtlProcessHeap(), 0, sizeof *Info); if (Info == NULL) { NtCurrentTeb()->LastErrorValue = ERROR_OUTOFMEMORY; return NULL; } Info->Parameter = lpParameter; Info->Function = lpStartAddress; Result = (* Function) (lpThreadAttributes, dwStackSize, AVrfpStandardThreadFunction, (PVOID)Info, dwCreationFlags, lpThreadId); return Result; } ///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////// Thread pool hooks ///////////////////////////////////////////////////////////////////// typedef struct _AVRF_WORKER_INFO { WORKERCALLBACKFUNC Function; PVOID Context; } AVRF_WORKER_INFO, * PAVRF_WORKER_INFO; typedef struct _AVRF_WAIT_INFO { WAITORTIMERCALLBACKFUNC Function; PVOID Context; } AVRF_WAIT_INFO, * PAVRF_WAIT_INFO; ULONG AVrfpWorkerFunctionExceptionFilter ( ULONG ExceptionCode, PVOID ExceptionRecord ) { VERIFIER_STOP (APPLICATION_VERIFIER_UNEXPECTED_EXCEPTION, "unexpected exception raised in worker thread", ExceptionCode, "Exception code", ExceptionRecord, "Exception record (.exr on 1st word, .cxr on 2nd word)", 0, "", 0, ""); return EXCEPTION_EXECUTE_HANDLER; } VOID NTAPI AVrfpStandardWorkerCallback ( PVOID Context ) { PAVRF_WORKER_INFO Info = (PAVRF_WORKER_INFO)Context; try { // // Call the real thing. // (Info->Function)(Info->Context); } except (AVrfpWorkerFunctionExceptionFilter (_exception_code(), _exception_info())) { // // Nothing. // } RtlCheckForOrphanedCriticalSections (NtCurrentThread()); RtlFreeHeap (RtlProcessHeap(), 0, Info); } VOID NTAPI AVrfpStandardWaitCallback ( PVOID Context, BOOLEAN Value ) { PAVRF_WAIT_INFO Info = (PAVRF_WAIT_INFO)Context; try { // // Call the real thing. // (Info->Function)(Info->Context, Value); } except (AVrfpWorkerFunctionExceptionFilter (_exception_code(), _exception_info())) { // // Nothing. // } RtlCheckForOrphanedCriticalSections (NtCurrentThread()); RtlFreeHeap (RtlProcessHeap(), 0, Info); } //NTSYSAPI NTSTATUS NTAPI AVrfpRtlQueueWorkItem( IN WORKERCALLBACKFUNC Function, IN PVOID Context, IN ULONG Flags ) { NTSTATUS Status; PAVRF_WORKER_INFO Info; Info = RtlAllocateHeap (RtlProcessHeap(), 0, sizeof *Info); if (Info == NULL) { return STATUS_NO_MEMORY; } Info->Context = Context; Info->Function = Function; Status = RtlQueueWorkItem (AVrfpStandardWorkerCallback, (PVOID)Info, Flags); return Status; } //NTSYSAPI NTSTATUS NTAPI AVrfpRtlRegisterWait ( OUT PHANDLE WaitHandle, IN HANDLE Handle, IN WAITORTIMERCALLBACKFUNC Function, IN PVOID Context, IN ULONG Milliseconds, IN ULONG Flags ) { NTSTATUS Status; PAVRF_WAIT_INFO Info; Info = RtlAllocateHeap (RtlProcessHeap(), 0, sizeof *Info); if (Info == NULL) { return STATUS_NO_MEMORY; } Info->Context = Context; Info->Function = Function; Status = RtlRegisterWait (WaitHandle, Handle, AVrfpStandardWaitCallback, (PVOID)Info, Milliseconds, Flags); return Status; } //NTSYSAPI NTSTATUS NTAPI AVrfpRtlCreateTimer ( IN HANDLE TimerQueueHandle, OUT HANDLE *Handle, IN WAITORTIMERCALLBACKFUNC Function, IN PVOID Context, IN ULONG DueTime, IN ULONG Period, IN ULONG Flags ) { NTSTATUS Status; PAVRF_WAIT_INFO Info; Info = RtlAllocateHeap (RtlProcessHeap(), 0, sizeof *Info); if (Info == NULL) { return STATUS_NO_MEMORY; } Info->Context = Context; Info->Function = Function; Status = RtlCreateTimer (TimerQueueHandle, Handle, AVrfpStandardWaitCallback, (PVOID)Info, DueTime, Period, Flags); return Status; }