static int wine_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { wine_cond_detail *detail; int last_waiter; if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond); detail = ((wine_cond)cond)->cond; /* Avoid race conditions. */ RtlEnterCriticalSection (&detail->waiters_count_lock); detail->waiters_count++; RtlLeaveCriticalSection (&detail->waiters_count_lock); RtlLeaveCriticalSection ( ((wine_mutex)mutex)->critsect ); NtWaitForMultipleObjects( 1, &detail->sema, FALSE, FALSE, NULL ); /* Reacquire lock to avoid race conditions. */ RtlEnterCriticalSection (&detail->waiters_count_lock); /* We're no longer waiting... */ detail->waiters_count--; /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */ last_waiter = detail->was_broadcast && detail->waiters_count == 0; RtlLeaveCriticalSection (&detail->waiters_count_lock); /* * If we're the last waiter thread during this particular broadcast * then let all the other threads proceed. */ if (last_waiter) NtSetEvent( detail->waiters_done, NULL ); RtlEnterCriticalSection (((wine_mutex)mutex)->critsect); return 0; }
NTSTATUS __cdecl _main(int argc, char *argv[], char *envp[], ULONG DebugFlag) { NTSTATUS Status = STATUS_SUCCESS; PROCESS_BASIC_INFORMATION PBI = {0}; /* Lookup yourself */ Status = NtQueryInformationProcess (NtCurrentProcess(), ProcessBasicInformation, & PBI, sizeof PBI, NULL); if(NT_SUCCESS(Status)) { SmSsProcessId = (ULONG) PBI.UniqueProcessId; } /* Initialize the system */ Status = InitSessionManager(); /* Watch required subsystems TODO */ #if 0 if (!NT_SUCCESS(Status)) { int i; for (i=0; i < (sizeof Children / sizeof Children[0]); i++) { if (Children[i]) { NtTerminateProcess(Children[i],0); } } DPRINT1("SM: Initialization failed!\n"); goto ByeBye; } Status = NtWaitForMultipleObjects(((LONG) sizeof(Children) / sizeof(HANDLE)), Children, WaitAny, TRUE, /* alertable */ NULL); /* NULL for infinite */ if (!NT_SUCCESS(Status)) { DPRINT1("SM: NtWaitForMultipleObjects failed! (Status=0x%08lx)\n", Status); } else { DPRINT1("SM: Process terminated!\n"); } ByeBye: /* Raise a hard error (crash the system/BSOD) */ NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0,0,0,0,0); // NtTerminateProcess(NtCurrentProcess(), 0); #endif return NtTerminateThread(NtCurrentThread(), Status); }
HOOKFUNC NTSTATUS NTAPI MyNtWaitForMultipleObjects(ULONG ObjectCount, PHANDLE ObjectsArray, DWORD WaitType, BOOLEAN Alertable, PLARGE_INTEGER Timeout) { DWORD dwMilliseconds = Timeout ? Timeout->LowPart : ~0; ENTER(dwMilliseconds); { return NtWaitForMultipleObjects(ObjectCount, ObjectsArray, WaitType, Alertable, Timeout); } }
HOOKFUNC NTSTATUS NTAPI MyNtWaitForMultipleObjects(ULONG ObjectCount, PHANDLE ObjectsArray, DWORD WaitType, BOOLEAN Alertable, PLARGE_INTEGER Timeout) { DWORD dwMilliseconds = Timeout ? Timeout->LowPart : ~0; debuglog(LCF_WAIT|LCF_FREQUENT|LCF_DESYNC, __FUNCTION__ "(%d)\n", dwMilliseconds); { return NtWaitForMultipleObjects(ObjectCount, ObjectsArray, WaitType, Alertable, Timeout); } }
DWORD __stdcall MonitorThread(VOID* Parameter) { HANDLE processEvent; HANDLE d3dImageEvent; VOID *handles[2]; processEvent = OpenEvent(L"Global\\" PUSH_PROCESS_EVENT_NAME); d3dImageEvent = OpenEvent(L"Global\\" PUSH_IMAGE_EVENT_NAME); handles[0] = processEvent; handles[1] = d3dImageEvent; while (processEvent) { NTSTATUS result; HANDLE threadHandle; result = NtWaitForMultipleObjects(2, &handles[0], WaitAny, FALSE, NULL); if (processEvent && handles[result - STATUS_WAIT_0] == processEvent) { NtCreateThreadEx( &threadHandle, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), &RetrieveProcessEvent, NULL, NoThreadFlags, 0, 0, 0, NULL ); } else if (handles[result - STATUS_WAIT_0] == d3dImageEvent) { NtCreateThreadEx( &threadHandle, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), &RetrieveImageEvent, NULL, NoThreadFlags, 0, 0, 0, NULL ); } } return 0; }
static NTSTATUS PhpWfmoThreadStart( _In_ PVOID Parameter ) { HANDLE eventHandle; LARGE_INTEGER timeout; eventHandle = Parameter; timeout.QuadPart = -(LONGLONG)UInt32x32To64(5, PH_TIMEOUT_SEC); NtWaitForMultipleObjects(1, &eventHandle, WaitAll, FALSE, &timeout); return STATUS_SUCCESS; }
static int wine_pthread_cond_broadcast(pthread_cond_t *cond) { int have_waiters = 0; wine_cond_detail *detail; if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond); detail = ((wine_cond)cond)->cond; /* * This is needed to ensure that <waiters_count> and <was_broadcast> are * consistent relative to each other. */ RtlEnterCriticalSection (&detail->waiters_count_lock); if (detail->waiters_count > 0) { /* * We are broadcasting, even if there is just one waiter... * Record that we are broadcasting, which helps optimize * <pthread_cond_wait> for the non-broadcast case. */ detail->was_broadcast = 1; have_waiters = 1; } if (have_waiters) { /* Wake up all the waiters atomically. */ NtReleaseSemaphore(detail->sema, detail->waiters_count, NULL); RtlLeaveCriticalSection (&detail->waiters_count_lock); /* Wait for all the awakened threads to acquire the counting semaphore. */ NtWaitForMultipleObjects( 1, &detail->waiters_done, FALSE, FALSE, NULL ); /* * This assignment is okay, even without the <waiters_count_lock> held * because no other waiter threads can wake up to access it. */ detail->was_broadcast = 0; } else RtlLeaveCriticalSection (&detail->waiters_count_lock); return 0; }
static int wine_pthread_join(pthread_t thread, void **value_ptr) { THREAD_BASIC_INFORMATION info; CLIENT_ID cid; NTSTATUS status; HANDLE handle; cid.UniqueProcess = 0; cid.UniqueThread = (HANDLE)thread; status = NtOpenThread( &handle, THREAD_QUERY_INFORMATION|SYNCHRONIZE, NULL, &cid ); if (!status) { NtWaitForMultipleObjects( 1, &handle, FALSE, FALSE, NULL ); status = NtQueryInformationThread( handle, ThreadBasicInformation, &info, sizeof(info), NULL ); NtClose( handle ); if (!status) *value_ptr = UlongToPtr(info.ExitStatus); } if (status) return EINVAL; /* FIXME: make this more correctly match windows errors */ return 0; }
static int wine_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { LARGE_INTEGER time; int last_waiter; wine_cond_detail *detail; if ( !((wine_cond)cond)->cond ) wine_cond_real_init(cond); detail = ((wine_cond)cond)->cond; /* Avoid race conditions. */ RtlEnterCriticalSection (&detail->waiters_count_lock); detail->waiters_count++; RtlLeaveCriticalSection (&detail->waiters_count_lock); RtlLeaveCriticalSection (((wine_mutex)mutex)->critsect); time.QuadPart = (ULONGLONG)abstime->tv_sec * 10000000 + abstime->tv_nsec / 100; time.QuadPart = -time.QuadPart; NtWaitForMultipleObjects( 1, &detail->sema, FALSE, FALSE, &time ); /* Reacquire lock to avoid race conditions. */ RtlEnterCriticalSection (&detail->waiters_count_lock); /* We're no longer waiting... */ detail->waiters_count--; /* Check to see if we're the last waiter after <pthread_cond_broadcast>. */ last_waiter = detail->was_broadcast && detail->waiters_count == 0; RtlLeaveCriticalSection (&detail->waiters_count_lock); /* * If we're the last waiter thread during this particular broadcast * then let all the other threads proceed. */ if (last_waiter) NtSetEvent( detail->waiters_done, NULL ); RtlEnterCriticalSection (((wine_mutex)mutex)->critsect); return 0; }
NTSTATUS _main(IN INT argc, IN PCHAR argv[], IN PCHAR envp[], IN ULONG DebugFlag) { NTSTATUS Status; KPRIORITY SetBasePriority; ULONG_PTR Parameters[4]; HANDLE Handles[2]; PVOID State; ULONG Flags; PROCESS_BASIC_INFORMATION ProcessInfo; UNICODE_STRING DbgString, InitialCommand; /* Make us critical */ RtlSetProcessIsCritical(TRUE, NULL, FALSE); RtlSetThreadIsCritical(TRUE, NULL, FALSE); /* Raise our priority */ SetBasePriority = 11; Status = NtSetInformationProcess(NtCurrentProcess(), ProcessBasePriority, (PVOID)&SetBasePriority, sizeof(SetBasePriority)); ASSERT(NT_SUCCESS(Status)); /* Save the debug flag if it was passed */ if (DebugFlag) SmpDebug = DebugFlag != 0; /* Build the hard error parameters */ Parameters[0] = (ULONG_PTR)&DbgString; Parameters[1] = Parameters[2] = Parameters[3] = 0; /* Enter SEH so we can terminate correctly if anything goes wrong */ _SEH2_TRY { /* Initialize SMSS */ Status = SmpInit(&InitialCommand, Handles); if (!NT_SUCCESS(Status)) { DPRINT1("SMSS: SmpInit return failure - Status == %x\n", Status); RtlInitUnicodeString(&DbgString, L"Session Manager Initialization"); Parameters[1] = Status; _SEH2_LEAVE; } /* Get the global flags */ Status = NtQuerySystemInformation(SystemFlagsInformation, &Flags, sizeof(Flags), NULL); ASSERT(NT_SUCCESS(Status)); /* Before executing the initial command check if the debug flag is on */ if (Flags & (FLG_DEBUG_INITIAL_COMMAND | FLG_DEBUG_INITIAL_COMMAND_EX)) { /* SMSS should launch ntsd with a few parameters at this point */ DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n"); } /* Execute the initial command (Winlogon.exe) */ Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL); if (!NT_SUCCESS(Status)) { /* Fail and raise a hard error */ DPRINT1("SMSS: Execute Initial Command failed\n"); RtlInitUnicodeString(&DbgString, L"Session Manager ExecuteInitialCommand"); Parameters[1] = Status; _SEH2_LEAVE; } /* Check if we're already attached to a session */ Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State); if (AttachedSessionId != -1) { /* Detach from it, we should be in no session right now */ Status = NtSetSystemInformation(SystemSessionDetach, &AttachedSessionId, sizeof(AttachedSessionId)); ASSERT(NT_SUCCESS(Status)); AttachedSessionId = -1; } SmpReleasePrivilege(State); /* Wait on either CSRSS or Winlogon to die */ Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles), Handles, WaitAny, FALSE, NULL); if (Status == STATUS_WAIT_0) { /* CSRSS is dead, get exit code and prepare for the hard error */ RtlInitUnicodeString(&DbgString, L"Windows SubSystem"); Status = NtQueryInformationProcess(Handles[0], ProcessBasicInformation, &ProcessInfo, sizeof(ProcessInfo), NULL); DPRINT1("SMSS: Windows subsystem terminated when it wasn't supposed to.\n"); } else { /* The initial command is dead or we have another failure */ RtlInitUnicodeString(&DbgString, L"Windows Logon Process"); if (Status == STATUS_WAIT_1) { /* Winlogon.exe got terminated, get its exit code */ Status = NtQueryInformationProcess(Handles[1], ProcessBasicInformation, &ProcessInfo, sizeof(ProcessInfo), NULL); } else { /* Something else satisfied our wait, so set the wait status */ ProcessInfo.ExitStatus = Status; Status = STATUS_SUCCESS; } DPRINT1("SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n", &InitialCommand); } /* Check if NtQueryInformationProcess was successful */ if (NT_SUCCESS(Status)) { /* Then we must have a valid exit status in the structure, use it */ Parameters[1] = ProcessInfo.ExitStatus; } else { /* We really don't know what happened, so set a generic error */ Parameters[1] = STATUS_UNSUCCESSFUL; } } _SEH2_EXCEPT(SmpUnhandledExceptionFilter(_SEH2_GetExceptionInformation())) { /* The filter should never return here */ ASSERT(FALSE); } _SEH2_END; /* Something in the init loop failed, terminate SMSS */ return SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters)); }
/* * @implemented */ DWORD WINAPI WaitForMultipleObjectsEx(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds, IN BOOL bAlertable) { PLARGE_INTEGER TimePtr; LARGE_INTEGER Time; PHANDLE HandleBuffer; HANDLE Handle[8]; DWORD i; NTSTATUS Status; RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActCtx; /* APCs must execute with the default activation context */ if (bAlertable) { /* Setup the frame */ RtlZeroMemory(&ActCtx, sizeof(ActCtx)); ActCtx.Size = sizeof(ActCtx); ActCtx.Format = RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER; RtlActivateActivationContextUnsafeFast(&ActCtx, NULL); } /* Check if we have more handles then we locally optimize */ if (nCount > 8) { /* Allocate a buffer for them */ HandleBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HANDLE)); if (!HandleBuffer) { /* No buffer, fail the wait */ SetLastError(ERROR_NOT_ENOUGH_MEMORY); if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); return WAIT_FAILED; } } else { /* Otherwise, use our local buffer */ HandleBuffer = Handle; } /* Copy the handles into our buffer and loop them all */ RtlCopyMemory(HandleBuffer, (LPVOID)lpHandles, nCount * sizeof(HANDLE)); for (i = 0; i < nCount; i++) { /* Check what kind of handle this is */ HandleBuffer[i] = TranslateStdHandle(HandleBuffer[i]); /* Check for console handle */ if ((IsConsoleHandle(HandleBuffer[i])) && (VerifyConsoleIoHandle(HandleBuffer[i]))) { /* Get the real wait handle */ HandleBuffer[i] = GetConsoleInputWaitHandle(); } } /* Convert the timeout */ TimePtr = BaseFormatTimeOut(&Time, dwMilliseconds); /* Start wait loop */ do { /* Do the wait */ Status = NtWaitForMultipleObjects(nCount, HandleBuffer, bWaitAll ? WaitAll : WaitAny, (BOOLEAN)bAlertable, TimePtr); if (!NT_SUCCESS(Status)) { /* Wait failed */ BaseSetLastNTError(Status); Status = WAIT_FAILED; } } while ((Status == STATUS_ALERTED) && (bAlertable)); /* Check if we didn't use our local buffer */ if (HandleBuffer != Handle) { /* Free the allocated one */ RtlFreeHeap(RtlGetProcessHeap(), 0, HandleBuffer); } /* Cleanup the activation context */ if (bAlertable) RtlDeactivateActivationContextUnsafeFast(&ActCtx); /* Return wait status */ return Status; }
BOOLEAN obtest( void ) { ULONG i; HANDLE Handles[ 2 ]; NTSTATUS Status; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectTypeAName, "ObjectTypeA" ); RtlInitString( &ObjectTypeBName, "ObjectTypeB" ); RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) ); ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer ); ObjectTypeInitializer.ValidAccessMask = -1; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = TRUE; ObjectTypeInitializer.DumpProcedure = DumpAProc; ObjectTypeInitializer.OpenProcedure = OpenAProc; ObjectTypeInitializer.CloseProcedure = CloseAProc; ObjectTypeInitializer.DeleteProcedure = DeleteAProc; ObjectTypeInitializer.ParseProcedure = ParseAProc; ObCreateObjectType( &ObjectTypeAName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeA ); ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.MaintainHandleCount = FALSE; ObjectTypeInitializer.GenericMapping = MyGenericMapping; ObjectTypeInitializer.DumpProcedure = DumpBProc; ObjectTypeInitializer.OpenProcedure = NULL; ObjectTypeInitializer.CloseProcedure = NULL; ObjectTypeInitializer.DeleteProcedure = DeleteBProc; ObjectTypeInitializer.ParseProcedure = NULL; ObCreateObjectType( &ObjectTypeBName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ObjectTypeB ); ObpDumpTypes( NULL ); RtlInitString( &DirectoryName, "\\MyObjects" ); InitializeObjectAttributes( &DirectoryObjA, &DirectoryName, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL ); NtCreateDirectoryObject( &DirectoryHandle, 0, &DirectoryObjA ); NtClose( DirectoryHandle ); RtlInitString( &ObjectAName, "\\myobjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_CASE_INSENSITIVE, NULL, NULL ); RtlInitString( &ObjectBName, "\\myobjects\\ObjectB" ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA ); ObjectA = (POBJECTTYPEA)ObjectBodyA; ObjectA->TypeALength = sizeof( *ObjectA ); for (i=0; i<4; i++) { ObjectA->Stuff[i] = i+1; } KeInitializeEvent( &ObjectA->Event, NotificationEvent, TRUE ); Status = ObCreateObject( KernelMode, ObjectTypeB, &ObjectBObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEB ), 0L, 0L, (PVOID *)&ObjectBodyB ); ObjectB = (POBJECTTYPEB)ObjectBodyB; ObjectB->TypeBLength = sizeof( *ObjectB ); for (i=0; i<16; i++) { ObjectB->Stuff[i] = i+1; } KeInitializeSemaphore ( &ObjectB->Semaphore, 2L, 2L ); Status = ObInsertObject( ObjectBodyA, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA, &ObjectHandleA1 ); DbgPrint( "Status: %lx ObjectBodyA: %lx ObjectHandleA1: %lx\n", Status, ObjectBodyA, ObjectHandleA1 ); Status = ObInsertObject( ObjectBodyB, SYNCHRONIZE | 0x1, NULL, 1, &ObjectBodyB, &ObjectHandleB1 ); DbgPrint( "Status: %lx ObjectBodyB: %lx ObjectHandleB1: %lx\n", Status, ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAName, "\\MyObjects\\ObjectA" ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAName, OBJ_OPENIF, NULL, NULL ); Status = ObCreateObject( KernelMode, ObjectTypeA, &ObjectAObjA, KernelMode, NULL, (ULONG)sizeof( OBJECTTYPEA ), 0L, 0L, (PVOID *)&ObjectBodyA1 ); Status = ObInsertObject( ObjectBodyA1, SYNCHRONIZE | 0x3, NULL, 1, &ObjectBodyA2, &ObjectHandleA2 ); DbgPrint( "Status: %lx ObjectBodyA1: %lx ObjectBodyA2: %lx ObjectHandleA2: %lx\n", Status, ObjectBodyA1, ObjectBodyA2, ObjectHandleA2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA2 ); ObDereferenceObject( ObjectBodyA2 ); // ObInsertObject,ObjectPointerBias NtWaitForSingleObject( ObjectHandleB1, TRUE, NULL ); Handles[ 0 ] = ObjectHandleA1; Handles[ 1 ] = ObjectHandleB1; NtWaitForMultipleObjects( 2, Handles, WaitAny, TRUE, NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByPointer( ObjectBodyA, 0L, ObjectTypeA, KernelMode ); ObReferenceObjectByPointer( ObjectBodyB, 0L, ObjectTypeB, KernelMode ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); RtlInitString( &ObjectAPathName, "\\MyObjects\\ObjectA" ); RtlInitString( &ObjectBPathName, "\\MyObjects\\ObjectB" ); ObReferenceObjectByName( &ObjectAPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeA, KernelMode, NULL, &ObjectBodyA ); ObReferenceObjectByName( &ObjectBPathName, OBJ_CASE_INSENSITIVE, 0L, ObjectTypeB, KernelMode, NULL, &ObjectBodyB ); DbgPrint( "Reference Name %s = %lx\n", ObjectAPathName.Buffer, ObjectBodyA ); DbgPrint( "Reference Name %s = %lx\n", ObjectBPathName.Buffer, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObInsertObject,ObjectPointerBias ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByPointer ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByName ObDereferenceObject( ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); InitializeObjectAttributes( &ObjectAObjA, &ObjectAPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectAObjA, 0L, NULL, ObjectTypeA, KernelMode, NULL, &ObjectHandleA2 ); InitializeObjectAttributes( &ObjectBObjA, &ObjectBPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); ObOpenObjectByName( &ObjectBObjA, 0L, NULL, ObjectTypeB, KernelMode, NULL, &ObjectHandleB2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectAPathName.Buffer, ObjectHandleA2 ); DbgPrint( "Open Object Name %s = %lx\n", ObjectBPathName.Buffer, ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA2, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB2, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA2, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB2, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObOpenObjectByPointer( ObjectBodyA, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeA, KernelMode, &ObjectHandleA1 ); ObOpenObjectByPointer( ObjectBodyB, OBJ_CASE_INSENSITIVE, 0L, NULL, ObjectTypeB, KernelMode, &ObjectHandleB1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyA, ObjectHandleA1 ); DbgPrint( "Open Object Pointer %lx = %lx\n", ObjectBodyB, ObjectHandleB1 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObReferenceObjectByHandle( ObjectHandleA1, 0L, ObjectTypeA, KernelMode, &ObjectBodyA, NULL ); ObReferenceObjectByHandle( ObjectHandleB1, 0L, ObjectTypeB, KernelMode, &ObjectBodyB, NULL ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleA1, ObjectBodyA ); DbgPrint( "Reference Handle %lx = %lx\n", ObjectHandleB1, ObjectBodyB ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); ObDereferenceObject( ObjectBodyA ); // ObReferenceObjectByHandle ObDereferenceObject( ObjectBodyB ); NtClose( ObjectHandleA1 ); NtClose( ObjectHandleB1 ); NtClose( ObjectHandleA2 ); NtClose( ObjectHandleB2 ); ObpDumpObjectTable( ObpGetObjectTable(), NULL ); TestFunction = NULL; return( TRUE ); }
VOID NotificationThread( PVOID pJunk) { INT nEvents = ID_MEDIACHANGE; INT nMediaEvents = 0; KPRIORITY Priority; NTSTATUS Status; HANDLE hEvent[ MAXIMUM_WAIT_OBJECTS ]; try { /* * Set the priority of the RIT to 3. */ Priority = LOW_PRIORITY + 3; NtSetInformationThread(hThreadNotification, ThreadPriority, &Priority, sizeof(KPRIORITY)); /* * Setup the NLS event */ NtCreateEvent(&ghNlsEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); UserAssert( ghNlsEvent != NULL ); hEvent[ID_NLS] = ghNlsEvent; /* * Setup the MediaChangeEvent */ RtlZeroMemory(wcDriveCache, sizeof(wcDriveCache)); Status = NtUserGetMediaChangeEvents(MAXIMUM_WAIT_OBJECTS - ID_MEDIACHANGE, &hEvent[ID_MEDIACHANGE], &nMediaEvents); if (NT_SUCCESS(Status)) { nEvents += nMediaEvents; } #ifdef DEBUG else { KdPrint(("NotificationThread: NtUserGetMediaChangeEvents failed 0x08X\n", Status)); } #endif StartRegReadRead(); /* * Sit and wait forever. */ while (TRUE) { Status = NtWaitForMultipleObjects(nEvents, hEvent, WaitAny, TRUE, NULL); if (Status == ID_NLS + WAIT_OBJECT_0) { /* * Handle the NLS event */ if (gfLogon) { gfLogon = FALSE; BaseSrvNlsUpdateRegistryCache(NULL, NULL); } } else if (Status >= ID_MEDIACHANGE + WAIT_OBJECT_0 && Status < (ID_MEDIACHANGE + nMediaEvents + WAIT_OBJECT_0)) { /* * Handle the CD-ROM \Device\MediaChangeEventX event */ NtResetEvent( hEvent[Status - WAIT_OBJECT_0], NULL ); HandleMediaChangeEvent( Status - WAIT_OBJECT_0 - ID_MEDIACHANGE ); } } // While (TRUE) } except (CsrUnhandledExceptionFilter(GetExceptionInformation())) { KdPrint(("Registry notification thread is dead, sorry.\n")); } }
DWORD APIENTRY WaitForMultipleObjectsEx( DWORD nCount, CONST HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds, BOOL bAlertable ) /*++ Routine Description: A wait operation on multiple waitable objects (up to MAXIMUM_WAIT_OBJECTS) is accomplished with the WaitForMultipleObjects function. This API can be used to wait on any of the specified objects to enter the signaled state, or all of the objects to enter the signaled state. If the bAlertable parameter is FALSE, the only way the wait terminates is because the specified timeout period expires, or because the specified objects entered the signaled state. If the bAlertable parameter is TRUE, then the wait can return due to any one of the above wait termination conditions, or because an I/O completion callback terminated the wait early (return value of WAIT_IO_COMPLETION). Arguments: nCount - A count of the number of objects that are to be waited on. lpHandles - An array of object handles. Each handle must have SYNCHRONIZE access to the associated object. bWaitAll - A flag that supplies the wait type. A value of TRUE indicates a "wait all". A value of false indicates a "wait any". dwMilliseconds - A time-out value that specifies the relative time, in milliseconds, over which the wait is to be completed. A timeout value of 0 specified that the wait is to timeout immediately. This allows an application to test an object to determine if it is in the signaled state. A timeout value of 0xffffffff specifies an infinite timeout period. bAlertable - Supplies a flag that controls whether or not the wait may terminate early due to an I/O completion callback. A value of TRUE allows this API to complete early due to an I/O completion callback. A value of FALSE will not allow I/O completion callbacks to terminate this call early. Return Value: WAIT_TIME_OUT - indicates that the wait was terminated due to the TimeOut conditions. 0 to MAXIMUM_WAIT_OBJECTS-1, indicates, in the case of wait for any object, the object number which satisfied the wait. In the case of wait for all objects, the value only indicates that the wait was completed successfully. 0xffffffff - The wait terminated due to an error. GetLastError may be used to get additional error information. WAIT_ABANDONED_0 to (WAIT_ABANDONED_0)+(MAXIMUM_WAIT_OBJECTS - 1), indicates, in the case of wait for any object, the object number which satisfied the event, and that the object which satisfied the event was abandoned. In the case of wait for all objects, the value indicates that the wait was completed successfully and at least one of the objects was abandoned. WAIT_IO_COMPLETION - The wait terminated due to one or more I/O completion callbacks. --*/ { NTSTATUS Status; LARGE_INTEGER TimeOut; PLARGE_INTEGER pTimeOut; DWORD i; LPHANDLE HandleArray; HANDLE Handles[ 8 ]; PPEB Peb; if (nCount > 8) { HandleArray = (LPHANDLE) RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), nCount*sizeof(HANDLE)); if (HandleArray == NULL) { BaseSetLastNTError(STATUS_NO_MEMORY); return 0xffffffff; } } else { HandleArray = Handles; } RtlCopyMemory(HandleArray,(LPVOID)lpHandles,nCount*sizeof(HANDLE)); Peb = NtCurrentPeb(); for (i=0; i<nCount; i++) { switch( (DWORD)HandleArray[i] ) { case STD_INPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardInput; break; case STD_OUTPUT_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardOutput; break; case STD_ERROR_HANDLE: HandleArray[i] = Peb->ProcessParameters->StandardError; break; } if (CONSOLE_HANDLE(HandleArray[i]) && VerifyConsoleIoHandle(HandleArray[i])) { HandleArray[i] = GetConsoleInputWaitHandle(); } } pTimeOut = BaseFormatTimeOut(&TimeOut,dwMilliseconds); rewait: Status = NtWaitForMultipleObjects( (CHAR)nCount, HandleArray, bWaitAll ? WaitAll : WaitAny, (BOOLEAN)bAlertable, pTimeOut ); if ( !NT_SUCCESS(Status) ) { BaseSetLastNTError(Status); Status = (NTSTATUS)0xffffffff; } else { if ( bAlertable && Status == STATUS_ALERTED ) { goto rewait; } } if (HandleArray != Handles) { RtlFreeHeap(RtlProcessHeap(), 0, HandleArray); } return (DWORD)Status; }