NTSTATUS ExDeleteResource ( IN PNTDDK_ERESOURCE Resource ) /*++ Routine Description: This routine deletes (i.e., uninitializes) the input resource variable Arguments: Resource - Supplies the resource variable being deleted Return Value: None --*/ { ASSERTMSG("Routine cannot be called at DPC ", !KeIsExecutingDpc() ); ASSERT_RESOURCE( Resource ); ASSERT( !IsExclusiveWaiting(Resource) ); if (Resource >= (PNTDDK_ERESOURCE)MM_USER_PROBE_ADDRESS) { KIRQL OldIrql; ExAcquireSpinLock( &ExpResourceSpinLock, &OldIrql ); RemoveEntryList( &Resource->SystemResourcesList ); ExReleaseSpinLock( &ExpResourceSpinLock, OldIrql ); } return STATUS_SUCCESS; }
VOID KeDumpMachineState ( IN PKPROCESSOR_STATE ProcessorState, IN PCHAR Buffer, IN PULONG BugCheckParameters, IN ULONG NumberOfParameters, IN PKE_BUGCHECK_UNICODE_TO_ANSI UnicodeToAnsiRoutine ) /*++ Routine Description: This function formats and displays the machine state at the time of the to bug check. Arguments: ProcessorState - Supplies a pointer to a processor state record. Buffer - Supplies a pointer to a buffer to be used to output machine state information. BugCheckParameters - Supplies a pointer to an array of additional bug check information. NumberOfParameters - Suppiles the size of the bug check parameters array. UnicodeToAnsiRoutine - Supplies a pointer to a routine to convert Unicode strings to Ansi strings without touching paged translation tables. Return Value: None. --*/ { PCONTEXT ContextRecord; ULONG ControlPc; PLDR_DATA_TABLE_ENTRY DataTableEntry; ULONG DisplayColumn; ULONG DisplayHeight; ULONG DisplayRow; ULONG DisplayWidth; UNICODE_STRING DllName; ULONG EstablisherFrame; PRUNTIME_FUNCTION FunctionEntry; PVOID ImageBase; ULONG Index; BOOLEAN InFunction; ULONG LastStack; PLIST_ENTRY ModuleListHead; PLIST_ENTRY NextEntry; ULONG NextPc; ULONG StackLimit; UCHAR AnsiBuffer[ 32 ]; ULONG DateStamp; // // Call the HAL to force all external interrupts to be disabled // at the interrupt controller. PowerPC optimization does not // do this when raising to high level. // for (Index = 0; Index < MAXIMUM_VECTOR; Index++) { HalDisableSystemInterrupt(Index, HIGH_LEVEL); } // // Query display parameters. // HalQueryDisplayParameters(&DisplayWidth, &DisplayHeight, &DisplayColumn, &DisplayRow); // // Display any addresses that fall within the range of any module in // the loaded module list. // for (Index = 0; Index < NumberOfParameters; Index += 1) { ImageBase = KiPcToFileHeader((PVOID)*BugCheckParameters, &ImageBase, &DataTableEntry); if (ImageBase != NULL) { sprintf(Buffer, "*** %08lX has base at %08lX - %s\n", *BugCheckParameters, ImageBase, (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); HalDisplayString(Buffer); } BugCheckParameters += 1; } // // Virtually unwind to the caller of bug check. // ContextRecord = &ProcessorState->ContextFrame; LastStack = ContextRecord->Gpr1; ControlPc = ContextRecord->Lr - 4; NextPc = ControlPc; FunctionEntry = KiLookupFunctionEntry(ControlPc); if (FunctionEntry != NULL) { NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, ContextRecord, &InFunction, &EstablisherFrame, NULL, 0, 0xffffffff); } // // At this point the context record contains the machine state at the // call to bug check. // // Put out the machine state at the time of the bugcheck. // sprintf(Buffer, "\n Machine State at Call to Bug Check IAR:%08lX MSR:%08lX\n", ContextRecord->Lr, ContextRecord->Msr); HalDisplayString(Buffer); // // Format and output the integer registers. // sprintf(Buffer, " R0:%8lX R1:%8lX R2:%8lX R3:%8lX R4:%8lX R5:%8lX\n", ContextRecord->Gpr0, ContextRecord->Gpr1, ContextRecord->Gpr2, ContextRecord->Gpr3, ContextRecord->Gpr4, ContextRecord->Gpr5); HalDisplayString(Buffer); sprintf(Buffer, " R6:%8lX R7:%8lX R8:%8lX R9:%8lX R10:%8lX R11:%8lX\n", ContextRecord->Gpr6, ContextRecord->Gpr7, ContextRecord->Gpr8, ContextRecord->Gpr9, ContextRecord->Gpr10, ContextRecord->Gpr11); HalDisplayString(Buffer); sprintf(Buffer, "R12:%8lX R13:%8lX R14:%8lX R15:%8lX R16:%8lX R17:%8lX\n", ContextRecord->Gpr12, ContextRecord->Gpr13, ContextRecord->Gpr14, ContextRecord->Gpr15, ContextRecord->Gpr16, ContextRecord->Gpr17); HalDisplayString(Buffer); sprintf(Buffer, "R18:%8lX R19:%8lX R20:%8lX R21:%8lX R22:%8lX R23:%8lX\n", ContextRecord->Gpr18, ContextRecord->Gpr19, ContextRecord->Gpr20, ContextRecord->Gpr21, ContextRecord->Gpr22, ContextRecord->Gpr23); HalDisplayString(Buffer); sprintf(Buffer, "R24:%8lX R25:%8lX R26:%8lX R27:%8lX R28:%8lX R29:%8lX\n", ContextRecord->Gpr24, ContextRecord->Gpr25, ContextRecord->Gpr26, ContextRecord->Gpr27, ContextRecord->Gpr28, ContextRecord->Gpr29); HalDisplayString(Buffer); sprintf(Buffer, "R30:%8lX R31:%8lX CR:%8lX CTR:%8lX XER:%8lX\n", ContextRecord->Gpr30, ContextRecord->Gpr31, ContextRecord->Cr, ContextRecord->Ctr, ContextRecord->Xer); HalDisplayString(Buffer); #if 0 // // I'd much rather see a longer stack trace and skip the floating // point stuff when the system crashes. plj // // // Format and output the floating registers. // DumpFloat = (PULONG)(&ContextRecord->Fpr0); sprintf(Buffer, " F0- F3:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr4); sprintf(Buffer, " F4- F7:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr8); sprintf(Buffer, " F8-F11:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr12); sprintf(Buffer, "F12-F15:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr16); sprintf(Buffer, "F16-F19:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr20); sprintf(Buffer, "F20-F23:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr24); sprintf(Buffer, "F24-F27:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr28); sprintf(Buffer, "F28-F31:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpscr); sprintf(Buffer, " FPSCR:%08lX%08lX\n", *(DumpFloat+1), *DumpFloat); HalDisplayString(Buffer); #define STAKWALK 4 #else #define STAKWALK 8 #endif // // Output short stack back trace with base address. // DllName.Length = 0; DllName.Buffer = L""; if (FunctionEntry != NULL) { StackLimit = (ULONG)KeGetCurrentThread()->KernelStack; HalDisplayString("Callee-Sp Return-Ra Dll Base - Name\n"); for (Index = 0; Index < STAKWALK; Index += 1) { ImageBase = KiPcToFileHeader((PVOID)ControlPc, &ImageBase, &DataTableEntry); sprintf(Buffer, " %08lX %08lX : %08lX - %s\n", ContextRecord->Gpr1, NextPc + 4, ImageBase, (*UnicodeToAnsiRoutine)( (ImageBase != NULL) ? &DataTableEntry->BaseDllName : &DllName, AnsiBuffer, sizeof( AnsiBuffer ))); HalDisplayString(Buffer); if ((NextPc != ControlPc) || (ContextRecord->Gpr1 != LastStack)) { ControlPc = NextPc; LastStack = ContextRecord->Gpr1; FunctionEntry = KiLookupFunctionEntry(ControlPc); if ((FunctionEntry != NULL) && (LastStack < StackLimit)) { NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, ContextRecord, &InFunction, &EstablisherFrame, NULL, 0, 0xffffffff); } else { NextPc = ContextRecord->Lr; } } else { break; } } } // // Output the build number and other useful information. // sprintf(Buffer, "\nIRQL : %d, DPC Active : %s, SYSVER 0x%08x\n", KeGetCurrentIrql(), KeIsExecutingDpc() ? "TRUE" : "FALSE", NtBuildNumber); HalDisplayString(Buffer); // // Output the processor id and the primary cache sizes. // sprintf(Buffer, "Processor Id: %d.%d, Icache: %d, Dcache: %d", PCR->ProcessorVersion, PCR->ProcessorRevision, PCR->FirstLevelIcacheSize, PCR->FirstLevelDcacheSize); HalDisplayString(Buffer); // // If the display width is greater than 80 + 24 (the size of a DLL // name and base address), then display all the modules loaded in // the system. // HalQueryDisplayParameters(&DisplayWidth, &DisplayHeight, &DisplayColumn, &DisplayRow); if (DisplayWidth > (80 + 24)) { HalDisplayString("\n"); if (KeLoaderBlock != NULL) { ModuleListHead = &KeLoaderBlock->LoadOrderListHead; } else { ModuleListHead = &PsLoadedModuleList; } // // Output display headers. // Index = 1; KiDisplayString(80, Index, "Dll Base DateStmp - Name"); NextEntry = ModuleListHead->Flink; if (NextEntry != NULL) { // // Scan the list of loaded modules and display their base // address and name. // while (NextEntry != ModuleListHead) { Index += 1; DataTableEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (MmDbgReadCheck(DataTableEntry->DllBase) != NULL) { PIMAGE_NT_HEADERS NtHeaders; NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase); DateStamp = NtHeaders->FileHeader.TimeDateStamp; } else { DateStamp = 0; } sprintf(Buffer, "%08lX %08lx - %s", DataTableEntry->DllBase, DateStamp, (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); KiDisplayString(80, Index, Buffer); NextEntry = NextEntry->Flink; if (Index > DisplayHeight) { break; } } } } // // Reset the current display position. // HalSetDisplayParameters(DisplayColumn, DisplayRow); // // The system has crashed, if we are running without the Kernel // debugger attached, attach it now. // KdInitSystem(NULL, FALSE); return; }
BOOLEAN ExAcquireResourceExclusive( IN PNTDDK_ERESOURCE Resource, IN BOOLEAN Wait ) /*++ Routine Description: The routine acquires the resource for exclusive access. Upon return from the procedure the resource is acquired for exclusive access. Arguments: Resource - Supplies the resource to acquire Wait - Indicates if the call is allowed to wait for the resource to become available for must return immediately Return Value: BOOLEAN - TRUE if the resource is acquired and FALSE otherwise --*/ { KIRQL OldIrql; ERESOURCE_THREAD OurThread; ASSERTMSG("Routine cannot be called at DPC ", !KeIsExecutingDpc() ); ASSERT((Resource->Flag & ResourceNeverExclusive) == 0); OurThread = (ULONG_PTR)ExGetCurrentResourceThread(); // // Get exclusive access to this resource structure // AcquireResourceLock( Resource, &OldIrql ); // // Loop until the resource is ours or exit if we cannot wait. // while (TRUE) { if (Resource->ActiveCount == 0) { // // Resource is un-owned, obtain it exclusive // Resource->InitialOwnerThreads[0] = OurThread; Resource->OwnerThreads[0] = OurThread; Resource->OwnerCounts[0] = 1; Resource->ActiveCount = 1; Resource->Flag |= ResourceOwnedExclusive; ReleaseResourceLock ( Resource, OldIrql ); return TRUE; } if (IsOwnedExclusive(Resource) && Resource->OwnerThreads[0] == OurThread) { // // Our thread is already the exclusive resource owner // Resource->OwnerCounts[0] += 1; ReleaseResourceLock( Resource, OldIrql ); return TRUE; } // // Check if we are allowed to wait or must return immediately, and // indicate that we didn't acquire the resource // if (!Wait) { ReleaseResourceLock( Resource, OldIrql ); return FALSE; } // // Otherwise we need to wait to acquire the resource. // WaitForResourceExclusive ( Resource, OldIrql ); } }
VOID KdpReadControlSpace ( IN PDBGKD_MANIPULATE_STATE64 m, IN PSTRING AdditionalData, IN PCONTEXT Context ) /*++ Routine Description: This function is called in response of a read control space state manipulation message. Its function is to read implementation specific system data. Arguments: m - Supplies the state manipulation message. AdditionalData - Supplies any additional data for the message. Context - Supplies the current context. Return Value: None. --*/ { PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory; ULONG Length; STRING MessageHeader; PVOID Buffer = AdditionalData->Buffer; MessageHeader.Length = sizeof(*m); MessageHeader.Buffer = (PCHAR)m; ASSERT(AdditionalData->Length == 0); if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64))) { Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64); } else { Length = a->TransferCount; } ASSERT(sizeof(PVOID) == sizeof(ULONG_PTR)); //NOTENOTE // This code will in fact only work on a uni-processor as the // m->Processor field is ignored for now // // Case on address to determine what part of Control // space is being read // switch( (ULONG_PTR)a->TargetBaseAddress ){ // // Return the pcr address for the current processor. // case DEBUG_CONTROL_SPACE_PCR: *(PKPCR *)Buffer = KdpGetPcr(); AdditionalData->Length = sizeof( PKPCR ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break; // // Return the prcb address for the current processor. // case DEBUG_CONTROL_SPACE_PRCB: *(PKPRCB *)Buffer = KdpGetCurrentPrcb(); AdditionalData->Length = sizeof( PKPRCB ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break; // // Return the pointer to the current thread address for the // current processor. // case DEBUG_CONTROL_SPACE_THREAD: *(PKTHREAD *)Buffer = KdpGetCurrentThread(); AdditionalData->Length = sizeof( PKTHREAD ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break; // // Return the current Thread Environment Block pointer for the // current thread on the current processor. // case DEBUG_CONTROL_SPACE_TEB: *(PVOID *)Buffer = (PVOID)NtCurrentTeb(); AdditionalData->Length = sizeof( struct _TEB * ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break; // // Return the dpc active flag for the current processor. // case DEBUG_CONTROL_SPACE_DPCACTIVE: *(BOOLEAN *)Buffer = KeIsExecutingDpc(); AdditionalData->Length = sizeof( ULONG ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break; // // Return the internal processor register state. // // N.B. - the kernel debugger buffer is expected to be allocated // in the 32-bit superpage // // N.B. - the size of the internal state cannot exceed the size of // the buffer allocated to the kernel debugger via // KDP_MESSAGE_BUFFER_SIZE // case DEBUG_CONTROL_SPACE_IPRSTATE: // // Guarantee that Buffer is quadword-aligned, and adjust the // size of the available buffer accordingly. // Buffer = (PVOID)( ((ULONG_PTR)Buffer + 7) & ~7); Length = (ULONG)((ULONG_PTR)&AdditionalData->Buffer[KDP_MESSAGE_BUFFER_SIZE] - (ULONG_PTR)Buffer); AdditionalData->Length = (USHORT)KdpReadInternalProcessorState( Buffer, Length ); // // Check the returned size, if greater than the buffer size than // we didn't have a sufficient buffer. If zero then the call // failed otherwise. // if( (AdditionalData->Length > KDP_MESSAGE_BUFFER_SIZE) || (AdditionalData->Length == 0) ){ AdditionalData->Length = 0; m->ReturnStatus = STATUS_UNSUCCESSFUL; a->ActualBytesRead = 0; } else { m->ReturnStatus = STATUS_SUCCESS; a->ActualBytesRead = AdditionalData->Length; } break; // // Return the internal processor counter values. // // N.B. - the kernel debugger buffer is expected to be allocated // in the 32-bit superpage // // N.B. - the size of the counters structure cannot exceed the size of // the buffer allocated to the kernel debugger via // KDP_MESSAGE_BUFFER_SIZE // case DEBUG_CONTROL_SPACE_COUNTERS: // // Guarantee that Buffer is quadword-aligned, and adjust the // size of the available buffer accordingly. // Buffer = (PVOID)( ((ULONG_PTR)Buffer + 7) & ~7); Length = (ULONG)((ULONG_PTR)&AdditionalData->Buffer[KDP_MESSAGE_BUFFER_SIZE] - (ULONG_PTR)Buffer); AdditionalData->Length = (USHORT)KdpReadInternalProcessorCounters( Buffer, Length ); // // Check the returned size, if greater than the buffer size than // we didn't have a sufficient buffer. If zero then the call // failed otherwise. // if( (AdditionalData->Length > KDP_MESSAGE_BUFFER_SIZE) || (AdditionalData->Length == 0) ){ AdditionalData->Length = 0; m->ReturnStatus = STATUS_UNSUCCESSFUL; a->ActualBytesRead = 0; } else { m->ReturnStatus = STATUS_SUCCESS; a->ActualBytesRead = AdditionalData->Length; } break; // // Uninterpreted Special Space // default: AdditionalData->Length = 0; m->ReturnStatus = STATUS_UNSUCCESSFUL; a->ActualBytesRead = 0; } KdpSendPacket( PACKET_TYPE_KD_STATE_MANIPULATE, &MessageHeader, AdditionalData ); }
VOID KeStackAttachProcess ( IN PRKPROCESS Process, OUT PRKAPC_STATE ApcState ) /*++ Routine Description: This function attaches a thread to a target process' address space and returns information about a previous attached process. Arguments: Process - Supplies a pointer to a dispatcher object of type process. Return Value: None. --*/ { KIRQL OldIrql; PRKTHREAD Thread; ASSERT_PROCESS(Process); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); // // Raise IRQL to dispatcher level and lock dispatcher database. // Thread = KeGetCurrentThread(); KiLockDispatcherDatabase(&OldIrql); // // If the current thread is executing a DPC, then bug check. // if (KeIsExecutingDpc() != FALSE) { KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT, (ULONG_PTR)Process, (ULONG_PTR)Thread->ApcState.Process, (ULONG)Thread->ApcStateIndex, (ULONG)KeIsExecutingDpc()); } // // If the target process is not the current process, then attach the target // process. Otherwise, return a distinguished process value to indicate that // an attach was not performed. // if (Thread->ApcState.Process == Process) { KiUnlockDispatcherDatabase(OldIrql); ApcState->Process = (PRKPROCESS)1; } else { // // If the current thread is attached to a process, then save the current // APC state in the callers APC state structure. Otherwise, save the // current APC state in the saved APC state structure, and return a NULL // process pointer. // if (Thread->ApcStateIndex != 0) { KiAttachProcess(Thread, Process, OldIrql, ApcState); } else { KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState); ApcState->Process = NULL; } } return; }
LOGICAL KeForceAttachProcess ( IN PRKPROCESS Process ) /*++ Routine Description: This function forces an attach of a thread to a target process' address space if the process is not current being swapped into or out of memory. N.B. This function is for use by memory management ONLY. Arguments: Process - Supplies a pointer to a dispatcher object of type process. Return Value: None. --*/ { KIRQL OldIrql; PRKTHREAD Thread; ASSERT_PROCESS(Process); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); // // Raise IRQL to dispatcher level and lock dispatcher database. // Thread = KeGetCurrentThread(); KiLockDispatcherDatabase(&OldIrql); // // Check whether there is already a process address space attached or // the thread is executing a DPC. If either condition is true, then call // bug check. // if ((Thread->ApcStateIndex != 0) || (KeIsExecutingDpc() != FALSE)) { KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT, (ULONG_PTR)Process, (ULONG_PTR)Thread->ApcState.Process, (ULONG)Thread->ApcStateIndex, (ULONG)KeIsExecutingDpc()); } // // If the target process is not the current process, then attach the target // process if the process is not currently being swapped in or out of memory. // if (Thread->ApcState.Process == Process) { KiUnlockDispatcherDatabase(OldIrql); } else { // // If the target process is currently being swapped into or out of memory, // then return a value of FALSE. Otherwise, force the process to be inswapped. // if ((Process->State == ProcessInSwap) || Process->State == ProcessOutSwap) { KiUnlockDispatcherDatabase(OldIrql); return FALSE; } else { // // If the target process is in transition, then remove it from its // transition list. // if (Process->State == ProcessInTransition) { RemoveEntryList(&Process->SwapListEntry); } // // Force the process state to in memory and attach the target process. // Process->State = ProcessInMemory; KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState); } } return TRUE; }
VOID KeAttachProcess ( IN PRKPROCESS Process ) /*++ Routine Description: This function attaches a thread to a target process' address space if, and only if, there is not already a process attached. Arguments: Process - Supplies a pointer to a dispatcher object of type process. Return Value: None. --*/ { KIRQL OldIrql; PRKTHREAD Thread; ASSERT_PROCESS(Process); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); // // Raise IRQL to dispatcher level and lock dispatcher database. // Thread = KeGetCurrentThread(); KiLockDispatcherDatabase(&OldIrql); // // If the target process is the current process, then return immediately. // Otherwise, check whether there is a process address space attached or // the thread is executing a DPC. If either condition is true, then call // bug check. Otherwise, attach the target process. // if (Thread->ApcState.Process == Process) { KiUnlockDispatcherDatabase(OldIrql); } else if ((Thread->ApcStateIndex != 0) || (KeIsExecutingDpc() != FALSE)) { KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT, (ULONG_PTR)Process, (ULONG_PTR)Thread->ApcState.Process, (ULONG)Thread->ApcStateIndex, (ULONG)KeIsExecutingDpc()); } else { KiAttachProcess(Thread, Process, OldIrql, &Thread->SavedApcState); } return; }