Files
mirror-processhacker/2.x/incomplete/hndlinfo_better_hack.patch
T
wj32 509ea2d378 imported "incomplete" code
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@3966 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2011-01-02 07:51:31 +00:00

284 lines
9.0 KiB
Diff

Index: hndlinfo.c
===================================================================
--- hndlinfo.c (revision 3919)
+++ hndlinfo.c (working copy)
@@ -23,41 +23,44 @@
#include <ph.h>
#include <kph.h>
-typedef enum _PH_QUERY_OBJECT_WORK
-{
- QueryNameHack,
- QuerySecurityHack,
- SetSecurityHack
-} PH_QUERY_OBJECT_WORK;
+#define PH_QUERY_HACK_MAX_THREADS 4
+#define PH_QUERY_HACK_THREAD_BITMAP_ALL ((1 << PH_QUERY_HACK_MAX_THREADS) - 1)
-typedef struct _PH_QUERY_OBJECT_CONTEXT
+typedef struct _PH_QUERY_HACK_THREAD
{
- LOGICAL Initialized;
- PH_QUERY_OBJECT_WORK Work;
+ SINGLE_LIST_ENTRY ListEntry;
+ HANDLE StartEventHandle;
+ HANDLE CompletedEventHandle;
+ HANDLE ThreadHandle;
+ PVOID Fiber;
+ PTHREAD_START_ROUTINE Routine;
+ PVOID Context;
+} PH_QUERY_HACK_THREAD, *PPH_QUERY_HACK_THREAD;
+
+typedef struct _QUERY_HACK_COMMON_CONTEXT
+{
HANDLE Handle;
SECURITY_INFORMATION SecurityInformation;
PVOID Buffer;
- ULONG Length;
+ ULONG BufferLength;
NTSTATUS Status;
ULONG ReturnLength;
-} PH_QUERY_OBJECT_CONTEXT, *PPH_QUERY_OBJECT_CONTEXT;
+} QUERY_HACK_COMMON_CONTEXT, *PQUERY_HACK_COMMON_CONTEXT;
-NTSTATUS PhpQueryObjectThreadStart(
+NTSTATUS PhpQueryHackThreadStart(
__in PVOID Parameter
);
-static HANDLE PhQueryObjectThreadHandle = NULL;
-static PVOID PhQueryObjectFiber = NULL;
-static PH_QUEUED_LOCK PhQueryObjectMutex;
-static HANDLE PhQueryObjectStartEvent = NULL;
-static HANDLE PhQueryObjectCompletedEvent = NULL;
-static PH_QUERY_OBJECT_CONTEXT PhQueryObjectContext;
-
static PPH_STRING PhObjectTypeNames[MAX_OBJECT_TYPE_NUMBER] = { 0 };
static PPH_GET_CLIENT_ID_NAME PhHandleGetClientIdName = NULL;
+static PH_QUERY_HACK_THREAD PhQueryHackThreads[PH_QUERY_HACK_MAX_THREADS];
+static SINGLE_LIST_ENTRY PhQueryHackThreadListHead;
+static PH_QUEUED_LOCK PhQueryHackThreadListLock = PH_QUEUED_LOCK_INIT;
+static PH_QUEUED_LOCK PhQueryHackThreadReleaseEvent = PH_QUEUED_LOCK_INIT;
+
VOID PhHandleInfoInitialization()
{
PhHandleGetClientIdName = PhStdGetClientIdName;
@@ -1145,109 +1148,71 @@
return status;
}
-BOOLEAN PhpHeadQueryObjectHack()
+PPH_QUERY_HACK_THREAD PhpAcquireQueryHackThread(
+ __in PTHREAD_START_ROUTINE Routine,
+ __in PVOID Context
+ )
{
- PhAcquireQueuedLockExclusive(&PhQueryObjectMutex);
+ PPH_QUERY_HACK_THREAD hackThread;
+ PSINGLE_LIST_ENTRY listEntry;
+ PH_QUEUED_WAIT_BLOCK waitBlock;
- // Create a query thread if we don't have one.
- if (!PhQueryObjectThreadHandle)
+ while (TRUE)
{
- PhQueryObjectThreadHandle = CreateThread(NULL, 0, PhpQueryObjectThreadStart, NULL, 0, NULL);
-
- if (!PhQueryObjectThreadHandle)
+ if (!PhQueryHackThreadListHead.Next)
{
- PhReleaseQueuedLockExclusive(&PhQueryObjectMutex);
- return FALSE;
+ if (!Try)
+ {
+ PhQueueWakeEvent(&PhQueryHackThreadReleaseEvent, &waitBlock);
+
+ if (PhQueryHackThreadListHead.Next)
+ {
+ // A new entry has just become available; cancel the wait.
+ PhSetWakeEvent(&PhQueryHackThreadReleaseEvent, &waitBlock);
+ }
+ else
+ {
+ PhWaitForWakeEvent(&PhQueryHackThreadReleaseEvent, &waitBlock, FALSE, NULL);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
}
- }
- // Create the events if they don't exist.
+ PhAcquireQueuedLockExclusive(&PhQueryHackThreadListLock);
+ listEntry = PopEntryList(&PhQueryHackThreadListHead);
+ PhReleaseQueuedLockExclusive(&PhQueryHackThreadListLock);
- if (!PhQueryObjectStartEvent)
- {
- if (!NT_SUCCESS(NtCreateEvent(
- &PhQueryObjectStartEvent,
- EVENT_ALL_ACCESS,
- NULL,
- SynchronizationEvent,
- FALSE
- )))
+ if (listEntry)
{
- PhReleaseQueuedLockExclusive(&PhQueryObjectMutex);
- return FALSE;
+ hackThread = CONTAINING_RECORD(listEntry, PH_QUERY_HACK_THREAD, ListEntry);
+ break;
}
}
- if (!PhQueryObjectCompletedEvent)
+ // Initialize the structure.
+ if (!NT_SUCCESS(NtCreateEvent(&hackThread->ThreadHandle, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE)))
{
- if (!NT_SUCCESS(NtCreateEvent(
- &PhQueryObjectCompletedEvent,
- EVENT_ALL_ACCESS,
- NULL,
- SynchronizationEvent,
- FALSE
- )))
- {
- PhReleaseQueuedLockExclusive(&PhQueryObjectMutex);
- return FALSE;
- }
- }
+ // Error; push the entry back onto the free list and return.
+ PhAcquireQueuedLockExclusive(&PhQueryHackThreadListLock);
+ PushEntryList(&PhQueryHackThreadListHead, &hackThread->ListEntry);
+ PhReleaseQueuedLockExclusive(&PhQueryHackThreadListLock);
- return TRUE;
-}
-
-NTSTATUS PhpTailQueryObjectHack(
- __out_opt PULONG ReturnLength
- )
-{
- NTSTATUS status;
- LARGE_INTEGER timeout;
-
- PhQueryObjectContext.Initialized = TRUE;
-
- // Allow the worker thread to start.
- NtSetEvent(PhQueryObjectStartEvent, NULL);
- // Wait for the work to complete, with a timeout of 1 second.
- timeout.QuadPart = -1000 * PH_TIMEOUT_MS;
- status = NtWaitForSingleObject(PhQueryObjectCompletedEvent, FALSE, &timeout);
-
- PhQueryObjectContext.Initialized = FALSE;
-
- // Return normally if the work was completed.
- if (status == STATUS_WAIT_0)
- {
- ULONG returnLength;
-
- status = PhQueryObjectContext.Status;
- returnLength = PhQueryObjectContext.ReturnLength;
-
- PhReleaseQueuedLockExclusive(&PhQueryObjectMutex);
-
- if (ReturnLength)
- *ReturnLength = returnLength;
-
- return status;
+ return NULL;
}
- // Kill the worker thread if it took too long.
- // else if (status == STATUS_TIMEOUT)
- else
- {
- // Kill the thread.
- if (NT_SUCCESS(NtTerminateThread(PhQueryObjectThreadHandle, STATUS_TIMEOUT)))
- {
- PhQueryObjectThreadHandle = NULL;
- // Delete the fiber (and free the thread stack).
- DeleteFiber(PhQueryObjectFiber);
- PhQueryObjectFiber = NULL;
- }
+ hackThread->ThreadHandle = NULL;
+ hackThread->Fiber = NULL;
+ hackThread->Routine = Routine;
+ hackThread->Context = Context;
- PhReleaseQueuedLockExclusive(&PhQueryObjectMutex);
-
- return STATUS_UNSUCCESSFUL;
- }
+ return hackThread;
}
+
+
NTSTATUS PhQueryObjectNameHack(
__in HANDLE Handle,
__out_bcount(ObjectNameInformationLength) POBJECT_NAME_INFORMATION ObjectNameInformation,
@@ -1303,54 +1268,13 @@
return PhpTailQueryObjectHack(NULL);
}
-NTSTATUS PhpQueryObjectThreadStart(
+NTSTATUS PhpQueryHackThreadStart(
__in PVOID Parameter
)
{
- PhQueryObjectFiber = ConvertThreadToFiber(Parameter);
+ PPH_QUERY_HACK_THREAD hackThread = Parameter;
- while (TRUE)
- {
- // Wait for work.
- if (NtWaitForSingleObject(PhQueryObjectStartEvent, FALSE, NULL) != STATUS_WAIT_0)
- continue;
+ hackThread->Fiber = ConvertThreadToFiber(NULL);
- // Make sure we actually have work.
- if (PhQueryObjectContext.Initialized)
- {
- switch (PhQueryObjectContext.Work)
- {
- case QueryNameHack:
- PhQueryObjectContext.Status = NtQueryObject(
- PhQueryObjectContext.Handle,
- ObjectNameInformation,
- PhQueryObjectContext.Buffer,
- PhQueryObjectContext.Length,
- &PhQueryObjectContext.ReturnLength
- );
- break;
- case QuerySecurityHack:
- PhQueryObjectContext.Status = NtQuerySecurityObject(
- PhQueryObjectContext.Handle,
- PhQueryObjectContext.SecurityInformation,
- (PSECURITY_DESCRIPTOR)PhQueryObjectContext.Buffer,
- PhQueryObjectContext.Length,
- &PhQueryObjectContext.ReturnLength
- );
- break;
- case SetSecurityHack:
- PhQueryObjectContext.Status = NtSetSecurityObject(
- PhQueryObjectContext.Handle,
- PhQueryObjectContext.SecurityInformation,
- (PSECURITY_DESCRIPTOR)PhQueryObjectContext.Buffer
- );
- break;
- }
-
- // Work done.
- NtSetEvent(PhQueryObjectCompletedEvent, NULL);
- }
- }
-
return STATUS_SUCCESS;
}