+ PLIST_ENTRY ListEntry;
+ NTSTATUS Status;
+ PKTHREAD Thread = KeGetCurrentThread();
+
+ KeAcquireDispatcherDatabaseLock(FALSE);
+
+ //assiciate new thread with queue?
+ if (Thread->Queue != Queue)
+ {
+ //remove association from other queue
+ if (!IsListEmpty(&Thread->QueueListEntry))
+ {
+ RemoveEntryList(&Thread->QueueListEntry);
+ }
+
+ //associate with this queue
+ InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
+ Queue->RunningThreads++;
+ Thread->Queue = Queue;
+ }
+
+ if (Queue->RunningThreads <= Queue->MaximumThreads && !IsListEmpty(&Queue->EntryListHead))
+ {
+ ListEntry = RemoveHeadList(&Queue->EntryListHead);
+ Queue->Header.SignalState--;
+ KeReleaseDispatcherDatabaseLock(FALSE);
+ return ListEntry;
+ }
+
+ //need to wait for it...
+ KeReleaseDispatcherDatabaseLock(FALSE);
+
+ Status = KeWaitForSingleObject(Queue,
+ WrQueue,
+ WaitMode,
+ TRUE,//Alertable,
+ Timeout);
+
+ if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+ {
+ return (PVOID)Status;
+ }
+ else
+ {
+ KeAcquireDispatcherDatabaseLock(FALSE);
+ ListEntry = RemoveHeadList(&Queue->EntryListHead);
+ KeReleaseDispatcherDatabaseLock(FALSE);
+ return ListEntry;
+ }
+