Author: ion
Date: Thu Jul 20 04:13:09 2006
New Revision: 23175
URL:
http://svn.reactos.org/svn/reactos?rev=23175&view=rev
Log:
- Major formatting cleanup and optimizations to NtQueryInformationProcess so that it does
not burn the eyes of anyone that might attempt to read it.
Modified:
trunk/reactos/ntoskrnl/ps/query.c
Modified: trunk/reactos/ntoskrnl/ps/query.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/query.c?rev=23…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/query.c (original)
+++ trunk/reactos/ntoskrnl/ps/query.c Thu Jul 20 04:13:09 2006
@@ -16,10 +16,65 @@
/* Include Information Class Tables */
#include "internal/ps_i.h"
-/* FUNCTIONS *****************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/* FIXME:
+ * This entire API is messed up because:
+ * 1) Directly pokes SECTION_OBJECT/FILE_OBJECT without special reffing.
+ * 2) Ignores SeAuditProcessImageFileName stuff added in XP (and ROS).
+ * 3) Doesn't use ObQueryNameString.
+ */
+NTSTATUS
+NTAPI
+PspGetImagePath(IN PEPROCESS Process,
+ OUT PUNICODE_STRING DstPath,
+ IN ULONG ProcessInformationLength)
+{
+ NTSTATUS Status;
+ ULONG ImagePathLen = 0;
+ PROS_SECTION_OBJECT Section;
+ PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
+
+ Section = (PROS_SECTION_OBJECT)Process->SectionObject;
+ if ((Section)&& (Section->FileObject))
+ {
+ /* FIXME - check for SEC_IMAGE and/or SEC_FILE instead
+ of relying on FileObject being != NULL? */
+ SrcBuffer = Section->FileObject->FileName.Buffer;
+ if (SrcBuffer) ImagePathLen = Section->FileObject->FileName.Length;
+ }
+
+ if (ProcessInformationLength < (sizeof(UNICODE_STRING) +
+ ImagePathLen +
+ sizeof(WCHAR)))
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ Status = STATUS_SUCCESS;
+ _SEH_TRY
+ {
+ /* copy the string manually, don't use RtlCopyUnicodeString with DstPath! */
+ DstPath->Length = ImagePathLen;
+ DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
+ DstPath->Buffer = DstBuffer;
+ if (ImagePathLen) RtlCopyMemory(DstBuffer, SrcBuffer, ImagePathLen);
+ DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* Return status */
+ return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
@@ -27,11 +82,21 @@
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
- OUT PULONG ReturnLength OPTIONAL)
+ OUT PULONG ReturnLength OPTIONAL)
{
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
+ ULONG Length = 0;
+ PPROCESS_BASIC_INFORMATION ProcessBasicInfo =
+ (PPROCESS_BASIC_INFORMATION)ProcessInformation;
+ PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation;
+ ULONG HandleCount;
+ PPROCESS_SESSION_INFORMATION SessionInfo =
+ (PPROCESS_SESSION_INFORMATION)ProcessInformation;
+ PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation;
+ PROCESS_DEVICEMAP_INFORMATION DeviceMap;
+ ULONG Cookie;
PAGED_CODE();
/* Check validity of Information Class */
@@ -42,108 +107,113 @@
ProcessInformationLength,
ReturnLength,
PreviousMode);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtQueryInformationProcess() failed, Status: 0x%x\n", Status);
- return Status;
- }
-
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check if this isn't the cookie class */
if(ProcessInformationClass != ProcessCookie)
{
+ /* Reference the process */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_QUERY_INFORMATION,
PsProcessType,
PreviousMode,
(PVOID*)&Process,
NULL);
- if (!NT_SUCCESS(Status)) return(Status);
+ if (!NT_SUCCESS(Status)) return Status;
}
else if(ProcessHandle != NtCurrentProcess())
{
- /* retreiving the process cookie is only allowed for the calling process
- itself! XP only allowes NtCurrentProcess() as process handles even if a
- real handle actually represents the current process. */
+ /*
+ * Retreiving the process cookie is only allowed for the calling process
+ * itself! XP only allowes NtCurrentProcess() as process handles even if
+ * a real handle actually represents the current process.
+ */
return STATUS_INVALID_PARAMETER;
}
+ /* Check the information class */
switch (ProcessInformationClass)
{
+ /* Basic process information */
case ProcessBasicInformation:
- {
- PPROCESS_BASIC_INFORMATION ProcessBasicInformationP =
- (PPROCESS_BASIC_INFORMATION)ProcessInformation;
-
- _SEH_TRY
- {
- ProcessBasicInformationP->ExitStatus = Process->ExitStatus;
- ProcessBasicInformationP->PebBaseAddress = Process->Peb;
- ProcessBasicInformationP->AffinityMask =
Process->Pcb.Affinity;
- ProcessBasicInformationP->UniqueProcessId =
- (ULONG)Process->UniqueProcessId;
- ProcessBasicInformationP->InheritedFromUniqueProcessId =
- (ULONG)Process->InheritedFromUniqueProcessId;
- ProcessBasicInformationP->BasePriority =
- Process->Pcb.BasePriority;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_BASIC_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Protect writes with SEH */
+ _SEH_TRY
+ {
+ /* Write all the information from the EPROCESS/KPROCESS */
+ ProcessBasicInfo->ExitStatus = Process->ExitStatus;
+ ProcessBasicInfo->PebBaseAddress = Process->Peb;
+ ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity;
+ ProcessBasicInfo->UniqueProcessId = (ULONG)Process->
+ UniqueProcessId;
+ ProcessBasicInfo->InheritedFromUniqueProcessId =
+ (ULONG)Process->InheritedFromUniqueProcessId;
+ ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority;
+
+ /* Set return length */
+ Length = sizeof(PROCESS_BASIC_INFORMATION);
+ }
+ _SEH_HANDLE
+ {
+ /* Get exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Quote limits and I/O Counters: not implemented */
case ProcessQuotaLimits:
case ProcessIoCounters:
Status = STATUS_NOT_IMPLEMENTED;
break;
+ /* Timing */
case ProcessTimes:
- {
- PKERNEL_USER_TIMES ProcessTimeP =
(PKERNEL_USER_TIMES)ProcessInformation;
- _SEH_TRY
- {
- ProcessTimeP->CreateTime = Process->CreateTime;
- ProcessTimeP->UserTime.QuadPart = Process->Pcb.UserTime *
100000LL;
- ProcessTimeP->KernelTime.QuadPart = Process->Pcb.KernelTime *
100000LL;
- ProcessTimeP->ExitTime = Process->ExitTime;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(KERNEL_USER_TIMES);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Protect writes with SEH */
+ _SEH_TRY
+ {
+ /* Copy time information from EPROCESS/KPROCESS */
+ ProcessTime->CreateTime = Process->CreateTime;
+ ProcessTime->UserTime.QuadPart = Process->Pcb.UserTime *
+ 100000LL;
+ ProcessTime->KernelTime.QuadPart = Process->Pcb.KernelTime *
+ 100000LL;
+ ProcessTime->ExitTime = Process->ExitTime;
+
+ /* Set the return length */
+ Length = sizeof(KERNEL_USER_TIMES);
+ }
+ _SEH_HANDLE
+ {
+ /* Get exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Process Debug Port */
case ProcessDebugPort:
- {
- _SEH_TRY
- {
- *(PHANDLE)ProcessInformation = (Process->DebugPort != NULL ?
(HANDLE)-1 : NULL);
- if (ReturnLength)
- {
- *ReturnLength = sizeof(HANDLE);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Protect write with SEH */
+ _SEH_TRY
+ {
+ /* Return whether or not we have a debug port */
+ *(PHANDLE)ProcessInformation = (Process->DebugPort ?
+ (HANDLE)-1 : NULL);
+
+ /* Set the return length*/
+ Length = sizeof(HANDLE);
+ }
+ _SEH_HANDLE
+ {
+ /* Get exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* LDT, WS and VDM Information: not implemented */
case ProcessLdtInformation:
case ProcessWorkingSetWatch:
case ProcessWx86Information:
@@ -151,278 +221,217 @@
break;
case ProcessHandleCount:
- {
- ULONG HandleCount =
ObpGetHandleCountByHandleTable(Process->ObjectTable);
-
- _SEH_TRY
- {
- *(PULONG)ProcessInformation = HandleCount;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Count the number of handles this process has */
+ HandleCount = ObpGetHandleCountByHandleTable(Process->ObjectTable);
+
+ /* Protect write in SEH */
+ _SEH_TRY
+ {
+ /* Return the count of handles */
+ *(PULONG)ProcessInformation = HandleCount;
+
+ /* Set the return length*/
+ Length = sizeof(ULONG);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Session ID for the process */
case ProcessSessionInformation:
- {
- PPROCESS_SESSION_INFORMATION SessionInfo =
(PPROCESS_SESSION_INFORMATION)ProcessInformation;
-
- _SEH_TRY
- {
- SessionInfo->SessionId = Process->Session;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_SESSION_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Enter SEH for write safety */
+ _SEH_TRY
+ {
+ /* Write back the Session ID */
+ SessionInfo->SessionId = Process->Session;
+
+ /* Set the return length */
+ Length = sizeof(PROCESS_SESSION_INFORMATION);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* WOW64: Not implemented */
case ProcessWow64Information:
- DPRINT1("We currently don't support the ProcessWow64Information
information class!\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
+ /* Virtual Memory Statistics */
case ProcessVmCounters:
- {
- PVM_COUNTERS pOut = (PVM_COUNTERS)ProcessInformation;
-
- _SEH_TRY
- {
- pOut->PeakVirtualSize = Process->PeakVirtualSize;
- /*
- * Here we should probably use VirtualSize.LowPart, but due to
- * incompatibilities in current headers (no unnamed union),
- * I opted for cast.
- */
- pOut->VirtualSize =
(ULONG)Process->VirtualSize;
- pOut->PageFaultCount = Process->Vm.PageFaultCount;
- pOut->PeakWorkingSetSize =
Process->Vm.PeakWorkingSetSize;
- pOut->WorkingSetSize = Process->Vm.WorkingSetSize;
- pOut->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0]; //
TODO: Verify!
- pOut->QuotaPagedPoolUsage = Process->QuotaUsage[0];
// TODO: Verify!
- pOut->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1]; //
TODO: Verify!
- pOut->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
// TODO: Verify!
- pOut->PagefileUsage = Process->QuotaUsage[2];
- pOut->PeakPagefileUsage = Process->QuotaPeak[2];
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(VM_COUNTERS);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Enter SEH for write safety */
+ _SEH_TRY
+ {
+ /* Return data from EPROCESS */
+ VmCounters->PeakVirtualSize = Process->PeakVirtualSize;
+ VmCounters->VirtualSize = Process->VirtualSize;
+ VmCounters->PageFaultCount = Process->Vm.PageFaultCount;
+ VmCounters->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize;
+ VmCounters->WorkingSetSize = Process->Vm.WorkingSetSize;
+ VmCounters->QuotaPeakPagedPoolUsage = Process->QuotaPeak[0];
+ VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[0];
+ VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[1];
+ VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[1];
+ VmCounters->PagefileUsage = Process->QuotaUsage[2];
+ VmCounters->PeakPagefileUsage = Process->QuotaPeak[2];
+
+ /* Set the return length */
+ *ReturnLength = sizeof(VM_COUNTERS);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Hard Error Processing Mode */
case ProcessDefaultHardErrorMode:
- {
- PULONG HardErrMode = (PULONG)ProcessInformation;
- _SEH_TRY
- {
- *HardErrMode = Process->DefaultHardErrorProcessing;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Enter SEH for writing back data */
+ _SEH_TRY
+ {
+ /* Write the current processing mode */
+ *(PULONG)ProcessInformation = Process->
+ DefaultHardErrorProcessing;
+
+ /* Set the return length */
+ Length = sizeof(ULONG);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Priority Boosting status */
case ProcessPriorityBoost:
- {
- PULONG BoostEnabled = (PULONG)ProcessInformation;
-
- _SEH_TRY
- {
- *BoostEnabled = Process->Pcb.DisableBoost ? FALSE : TRUE;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Enter SEH for writing back data */
+ _SEH_TRY
+ {
+ /* Return boost status */
+ *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ?
+ FALSE : TRUE;
+
+ /* Set the return length */
+ Length = sizeof(ULONG);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* DOS Device Map */
case ProcessDeviceMap:
- {
- PROCESS_DEVICEMAP_INFORMATION DeviceMap;
-
- ObQueryDeviceMapInformation(Process, &DeviceMap);
-
- _SEH_TRY
- {
- *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(PROCESS_DEVICEMAP_INFORMATION);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
-
+
+ /* Query the device map information */
+ ObQueryDeviceMapInformation(Process, &DeviceMap);
+
+ /* Enter SEH for writing back data */
+ _SEH_TRY
+ {
+ *(PPROCESS_DEVICEMAP_INFORMATION)ProcessInformation = DeviceMap;
+
+ /* Set the return length */
+ Length = sizeof(PROCESS_DEVICEMAP_INFORMATION);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Priority class */
case ProcessPriorityClass:
- {
- PUSHORT Priority = (PUSHORT)ProcessInformation;
-
- _SEH_TRY
- {
- *Priority = Process->PriorityClass;
-
- if (ReturnLength)
- {
- *ReturnLength = sizeof(USHORT);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- break;
- }
+
+ /* Enter SEH for writing back data */
+ _SEH_TRY
+ {
+ /* Return current priority class */
+ *(PUSHORT)ProcessInformation = Process->PriorityClass;
+
+ /* Set the return length */
+ Length = sizeof(USHORT);
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
case ProcessImageFileName:
- {
- ULONG ImagePathLen = 0;
- PROS_SECTION_OBJECT Section;
- PUNICODE_STRING DstPath = (PUNICODE_STRING)ProcessInformation;
- PWSTR SrcBuffer = NULL, DstBuffer = (PWSTR)(DstPath + 1);
-
- Section = (PROS_SECTION_OBJECT)Process->SectionObject;
-
- if (Section != NULL && Section->FileObject != NULL)
- {
- /* FIXME - check for SEC_IMAGE and/or SEC_FILE instead
- of relying on FileObject being != NULL? */
- SrcBuffer = Section->FileObject->FileName.Buffer;
- if (SrcBuffer != NULL)
- {
- ImagePathLen = Section->FileObject->FileName.Length;
- }
- }
-
- if(ProcessInformationLength < sizeof(UNICODE_STRING) + ImagePathLen +
sizeof(WCHAR))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- _SEH_TRY
- {
- /* copy the string manually, don't use RtlCopyUnicodeString
with DstPath! */
- DstPath->Length = ImagePathLen;
- DstPath->MaximumLength = ImagePathLen + sizeof(WCHAR);
- DstPath->Buffer = DstBuffer;
- if (ImagePathLen != 0)
- {
- RtlCopyMemory(DstBuffer,
- SrcBuffer,
- ImagePathLen);
- }
- DstBuffer[ImagePathLen / sizeof(WCHAR)] = L'\0';
-
- Status = STATUS_SUCCESS;
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
- }
- break;
- }
-
+
+ /* Get the image path */
+ Status = PspGetImagePath(Process,
+ (PUNICODE_STRING)ProcessInformation,
+ ProcessInformationLength);
+ break;
+
+ /* Per-process security cookie */
case ProcessCookie:
- {
- ULONG Cookie;
-
- /* receive the process cookie, this is only allowed for the current
- process! */
-
- Process = PsGetCurrentProcess();
-
- Cookie = Process->Cookie;
- if(Cookie == 0)
- {
- LARGE_INTEGER SystemTime;
- ULONG NewCookie;
- PKPRCB Prcb;
-
- /* generate a new cookie */
-
- KeQuerySystemTime(&SystemTime);
-
- Prcb = KeGetCurrentPrcb();
-
- NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
- SystemTime.u.LowPart ^ SystemTime.u.HighPart;
-
- /* try to set the new cookie, return the current one if another
thread
- set it in the meanwhile */
- Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
- NewCookie,
- Cookie);
- if(Cookie == 0)
- {
- /* successfully set the cookie */
- Cookie = NewCookie;
- }
- }
-
- _SEH_TRY
- {
- *(PULONG)ProcessInformation = Cookie;
- if (ReturnLength)
- {
- *ReturnLength = sizeof(ULONG);
- }
- }
- _SEH_HANDLE
- {
- Status = _SEH_GetExceptionCode();
- }
- _SEH_END;
-
- break;
- }
-
- /*
- * Note: The following 10 information classes are verified to not be
- * implemented on NT, and do indeed return STATUS_INVALID_INFO_CLASS;
- */
+
+ /* Get the current process and cookie */
+ Process = PsGetCurrentProcess();
+ Cookie = Process->Cookie;
+ if(!Cookie)
+ {
+ LARGE_INTEGER SystemTime;
+ ULONG NewCookie;
+ PKPRCB Prcb;
+
+ /* Generate a new cookie */
+ KeQuerySystemTime(&SystemTime);
+ Prcb = KeGetCurrentPrcb();
+ NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^
+ SystemTime.u.LowPart ^ SystemTime.u.HighPart;
+
+ /* Set the new cookie or return the current one */
+ Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie,
+ NewCookie,
+ Cookie);
+ if(!Cookie) Cookie = NewCookie;
+
+ /* Set return length */
+ Length = sizeof(ULONG);
+ }
+
+ /* Enter SEH to protect write */
+ _SEH_TRY
+ {
+ /* Write back the cookie */
+ *(PULONG)ProcessInformation = Cookie;
+ }
+ _SEH_HANDLE
+ {
+ /* Get the exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ break;
+
+ /* Not yet implemented, or unknown */
case ProcessBasePriority:
case ProcessRaisePriority:
case ProcessExceptionPort:
@@ -437,6 +446,20 @@
Status = STATUS_INVALID_INFO_CLASS;
}
+ /* Protect write with SEH */
+ _SEH_TRY
+ {
+ /* Check if caller wanted return length */
+ if (ReturnLength) *ReturnLength = Length;
+ }
+ _SEH_HANDLE
+ {
+ /* Get exception code */
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* If we referenced the process, dereference it */
if(ProcessInformationClass != ProcessCookie) ObDereferenceObject(Process);
return Status;
}