1 /*++ 2 3 Copyright (c) Microsoft. All rights reserved. 4 5 Module Name: 6 7 PnpStateMachine.cpp 8 9 Abstract: 10 11 This module implements the PnP state machine for the driver framework. 12 This code was split out from FxPkgPnp.cpp. 13 14 Author: 15 16 17 18 19 Environment: 20 21 Kernel mode only 22 23 Revision History: 24 25 --*/ 26 27 #include "../pnppriv.hpp" 28 #include <wdmguid.h> 29 30 #include<ntstrsafe.h> 31 32 extern "C" { 33 #if defined(EVENT_TRACING) 34 #include "PnpStateMachineKM.tmh" 35 #endif 36 } 37 38 BOOLEAN 39 FxPkgPnp::PnpCheckAndIncrementRestartCount( 40 VOID 41 ) 42 /*++ 43 44 Routine Description: 45 This is a mode-dependent wrapper for PnpIncrementRestartCountLogic, 46 which determines if this device should ask the bus driver to 47 reenumerate the device. Please refer to PnpIncrementRestartCountLogic's 48 comment block for more information. 49 50 Arguments: 51 None 52 53 Return Value: 54 TRUE if a restart should be requested. 55 56 --*/ 57 { 58 NTSTATUS status; 59 FxAutoRegKey settings, restart; 60 ULONG disposition = 0; 61 62 DECLARE_CONST_UNICODE_STRING(keyNameRestart, L"Restart"); 63 64 status = m_Device->OpenSettingsKey(&settings.m_Key); 65 if (!NT_SUCCESS(status)) { 66 return FALSE; 67 } 68 69 // 70 // We ask for a volatile key so that upon reboot, the count is purged and we 71 // start a new fresh restart count. 72 // 73 status = FxRegKey::_Create(settings.m_Key, 74 &keyNameRestart, 75 &restart.m_Key, 76 KEY_ALL_ACCESS, 77 REG_OPTION_VOLATILE, 78 &disposition); 79 if (!NT_SUCCESS(status)) { 80 return FALSE; 81 } 82 83 return PnpIncrementRestartCountLogic(restart.m_Key, 84 disposition == REG_CREATED_NEW_KEY); 85 } 86 87 BOOLEAN 88 FxPkgPnp::ShouldProcessPnpEventOnDifferentThread( 89 __in KIRQL CurrentIrql, 90 __in BOOLEAN CallerSpecifiedProcessingOnDifferentThread 91 ) 92 /*++ 93 Routine Description: 94 95 This function returns whether the PnP state machine should process the 96 current event on the same thread or on a different one. 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 Arguemnts: 128 129 CurrentIrql - The current IRQL 130 131 CallerSpecifiedProcessingOnDifferentThread - Whether or not caller of 132 PnpProcessEvent specified that the event be processed on a different 133 thread. 134 135 Returns: 136 TRUE if the PnP state machine should process the event on a different 137 thread. 138 139 FALSE if the PnP state machine should process the event on the same thread 140 141 --*/ 142 { 143 // 144 // For KMDF, we ignore what the caller of PnpProcessEvent specified (which 145 // should always be FALSE, BTW) and base our decision on the current IRQL. 146 // If we are running at PASSIVE_LEVEL, we process on the same thread else 147 // we queue a work item. 148 // 149 UNREFERENCED_PARAMETER(CallerSpecifiedProcessingOnDifferentThread); 150 151 ASSERT(FALSE == CallerSpecifiedProcessingOnDifferentThread); 152 153 return (CurrentIrql == PASSIVE_LEVEL) ? FALSE : TRUE; 154 } 155 156 _Must_inspect_result_ 157 NTSTATUS 158 FxPkgPnp::CreatePowerThreadIfNeeded( 159 VOID 160 ) 161 /*++ 162 Routine description: 163 If needed, creates a thread for processing power IRPs 164 165 Arguments: 166 None 167 168 Return value: 169 An NTSTATUS code indicating success or failure of this function 170 --*/ 171 { 172 NTSTATUS status = STATUS_SUCCESS; 173 MxDeviceObject pTopOfStack; 174 175 176 177 178 179 180 181 182 183 184 185 186 pTopOfStack.SetObject( 187 m_Device->GetAttachedDeviceReference()); 188 189 ASSERT(pTopOfStack.GetObject() != NULL); 190 191 if (pTopOfStack.GetObject() != NULL) { 192 // 193 // If the top of the stack is not power pageable, the stack needs a power 194 // thread. Query for it if we are not a PDO (and create it if the lower 195 // stack does not support it), and create it if we are a PDO. 196 // 197 // Some stacks send a usage notification when processing a start device, so 198 // a notification could have already traveled through the stack by the time 199 // the start irp has completed back up to this device. 200 // 201 if ((pTopOfStack.GetFlags() & DO_POWER_PAGABLE) == 0 && 202 HasPowerThread() == FALSE) { 203 status = QueryForPowerThread(); 204 205 if (!NT_SUCCESS(status)) { 206 SetInternalFailure(); 207 SetPendingPnpIrpStatus(status); 208 } 209 } 210 211 pTopOfStack.DereferenceObject(); 212 pTopOfStack.SetObject(NULL); 213 } 214 215 return status; 216 } 217 218 NTSTATUS 219 FxPkgPnp::PnpPrepareHardwareInternal( 220 VOID 221 ) 222 /*++ 223 Routine description: 224 This is mode-specific routine for Prepare hardware 225 226 Arguments: 227 None 228 229 Return value: 230 none. 231 --*/ 232 { 233 // 234 // nothing to do for KMDF. 235 // 236 return STATUS_SUCCESS; 237 } 238 239