📄 devcore.c
字号:
DEBUGMSG(ZONE_WARNING, (_T("I_DeregisterDevice: exception in final deinit entry point\r\n")));
}
}
DeleteDevice(lpdev);
bFreedOne = TRUE;
break;
// break out of inner loop, because after letting go of critsec &
// freeing lpdev, our loop traversal is not valid anymore. So start over
}
}
if (bFreedOne == FALSE) {
// Couldn't free anyone
LeaveCriticalSection(&g_devcs);
Sleep(5000); // snooze, and try again...
}
}
} // ProcessDyingDevs
//
// ProcessDyingOpens - called from the main thread as part of periodic clean up.
//
// Dying opens are orphaned device handles. A device open handle can be orphaned if
// CloseHandle is called by one thread while another thread using the same handle is
// blocked in a call to the device driver, for instance xxx_IoControl. When xxx_IoControl
// returns, DM_DevDeviceIoControl will access the open handle structure so it can't be freed
// yet; it is put on the g_lpDyingOpens list.
//
void ProcessDyingOpens(void)
{
fsopendev_t *fsodev;
fsopendev_t *fsodevprev;
LPEXCEPTION_POINTERS pep;
DEBUGMSG(ZONE_DYING, (L"Device:ProcessDyingOpens About to walk dying opens list\r\n"));
EnterCriticalSection(&g_devcs);
fsodevprev = fsodev = g_lpDyingOpens;
while (fsodev) {
if (fsodev->dwOpenRefCnt == 0) {
fsdev_t *lpdev = fsodev->lpDev;
if(lpdev != NULL && lpdev->fnPreClose != NULL) {
LeaveCriticalSection(&g_devcs);
__try {
lpdev->fnClose(fsodev->dwOpenData);
}
__except(pep = GetExceptionInformation(), ReportFault(pep,0), EXCEPTION_EXECUTE_HANDLER ) {
DEBUGMSG(ZONE_WARNING, (_T("ProcessDyingOpens: exception calling final close entry point\r\n")));
}
EnterCriticalSection(&g_devcs);
}
// Unlink and free unreferenced open
if (fsodev == g_lpDyingOpens) {
g_lpDyingOpens = fsodev->nextptr;
LocalFree(fsodev);
fsodev = fsodevprev = g_lpDyingOpens;
} else {
fsodevprev->nextptr = fsodev->nextptr;
LocalFree(fsodev);
fsodev = fsodevprev->nextptr;
}
} else {
fsodevprev = fsodev;
fsodev = fsodev->nextptr;
}
}
LeaveCriticalSection(&g_devcs);
} // ProcessDyingOpens
// Uses registry to call SignalStarted with the correct args. Note that ideally
// device manager should NOT know this info is in the registry!
static void SignalStartedUsingReg()
{
#define MAX_APPSTART_KEYNAME 128
HKEY hKey;
WCHAR szName[MAX_APPSTART_KEYNAME];
WCHAR szVal[MAX_APPSTART_KEYNAME];
LPWSTR lpszArg = NULL;
DWORD dwTemp, dwType, dwNameSize, dwValSize, i;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("init"), 0, NULL, 0, 0,
NULL, &hKey, &dwTemp) != ERROR_SUCCESS) {
DEBUGCHK(0);
return;
}
dwNameSize = MAX_APPSTART_KEYNAME;
dwValSize = MAX_APPSTART_KEYNAME * sizeof(WCHAR);
i = 0;
while (RegEnumValue(hKey, i, szName, &dwNameSize, 0, &dwType,
(LPBYTE)szVal, &dwValSize) == ERROR_SUCCESS) {
if ((dwType == REG_SZ) && !wcsncmp(szName, TEXT("Launch"), 6) // 6 for "launch"
&& !wcscmp(szVal, TEXT("device.exe"))) {
lpszArg = szName + 6; // 6 to go past "launch"
break;
}
dwNameSize = MAX_APPSTART_KEYNAME;
dwValSize = MAX_APPSTART_KEYNAME * sizeof(WCHAR);
i++;
}
RegCloseKey(hKey);
if (lpszArg) {
SignalStarted(_wtol(lpszArg));
} else {
// device.exe is not in the registry!
DEBUGMSG(1, (TEXT("Device manager must be listed in HKLM\\init!\r\n")));
DEBUGCHK(0);
}
}
// This routine initializes the Device Manager, Power Manager, and I/O Resource
// Manager APIs, launches device drivers, and processes device driver load/unload.
int WINAPI
StartDeviceManager(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nCmShow)
{
HINSTANCE hCeddkDll;
HANDLE hEvent;
if (IsAPIReady(SH_DEVMGR_APIS)) {
return 0;
}
DEBUGREGISTER(NULL);
DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Starting boot phase 1\n")));
// PHASE 1
g_BootPhase = 1;
InitOOMSettings();
InitializeListHead(&g_DevChain);
InitializeListHead(&g_ActivatingDevs);
InitializeListHead(&g_DyingDevs);
InitializeListHead(&g_CandidateDevs);
g_hCleanEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
g_hDevApiHandle = CreateAPISet("WFLD", NUM_FDEV_APIS, FDevApiMethods, FDevApiSigs);
g_hDevFileApiHandle = CreateAPISet("W32D", NUM_FAPIS, DevFileApiMethods, DevFileApiSigs);
RegisterAPISet(g_hDevFileApiHandle, HT_FILE | REGISTER_APISET_TYPE);
InitializePnPNotifications();
InitializeCriticalSection(&g_devcs);
ResourceInitModule();
ResourceInitFromRegistry(TEXT("Drivers\\Resources"));
SetPowerOffHandler((FARPROC) DevMgrPowerOffHandler);
RegisterAPISet(g_hDevApiHandle, SH_DEVMGR_APIS);
InitDeviceFilesystems();
// Indicate that the device manager is up and running
hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/DevMgrApiSetReady"));
DEBUGCHK(hEvent != NULL);
if (hEvent != NULL) {
SetEvent(hEvent);
CloseHandle(hEvent);
}
// Calibrate stall counter that is used for StallExecution
hCeddkDll = LoadLibrary (TEXT("ceddk.dll"));
if (NULL != hCeddkDll) {
pCalibrateStallFn fnCalibrateStall = (pCalibrateStallFn)GetProcAddress(hCeddkDll, TEXT("CalibrateStallCounter"));
if (!fnCalibrateStall) {
DEBUGMSG(ZONE_BOOTSEQ, (L"GetProcAddress failed on ceddk.dll\r\n"));
FreeLibrary(hCeddkDll);
}
else {
fnCalibrateStall();
}
}
// Call the power manager initialization entry point
PM_Init();
PM_SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
// See if we are going to have two boot phases
hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/BootPhase1"));
if (hEvent != NULL) {
// Load phase 1 drivers from the boot registry
DevloadInit();
// Signal boot phase 1 complete
SetEvent(hEvent);
CloseHandle(hEvent);
// Wait for phase 2 of the boot to begin
hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("SYSTEM/BootPhase2"));
DEBUGCHK(hEvent);
if (hEvent) {
DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Started, waiting for boot phase 2\r\n")));
WaitForSingleObject(hEvent, INFINITE);
CloseHandle(hEvent);
}
// Load any new drivers from the persistent registry. Since the
// registry may have changed, update the power state for any devices
// that need it.
DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Second-phase driver load\r\n")));
g_BootPhase = 2;
PM_SetSystemPowerState(NULL, POWER_STATE_ON, POWER_FORCE);
InitDevices(NULL);
DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: Startup sequence complete\r\n")));
SignalStartedUsingReg(); // SignalStarted call with the right args
} else {
DEBUGMSG(ZONE_BOOTSEQ, (TEXT("DEVICE: No boot registry - skipping to boot phase 2\n")));
g_BootPhase = 2;
DevloadInit();
SignalStarted(_wtol(lpCmdLine));
}
// Boot phase 3 isn't any different from phase 2; just marks that we got here.
DEBUGMSG(ZONE_BOOTSEQ,
(TEXT("DEVICE: Finished loading primary drivers - entering boot phase 3\n")));
g_BootPhase = 3;
CELOG_DeviceFinished ();
while (1) {
WaitForSingleObject(g_hCleanEvt, INFINITE);
// check for auto-deregister devs first as they may end up queuing
// themselves on the dying devs list
ProcessAutoDeregisterDevs();
ProcessDyingDevs();
ProcessDyingOpens();
}
return 1; // should not ever be reached
}
// DLL entry point.
BOOL WINAPI
DllMain(
HINSTANCE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
)
{
BOOL bRc = TRUE;
UNREFERENCED_PARAMETER(hDllHandle);
UNREFERENCED_PARAMETER(lpreserved);
switch (dwReason) {
case DLL_PROCESS_ATTACH:
{
DEBUGREGISTER(hDllHandle);
DEBUGMSG(ZONE_INIT,(_T("*** DLL_PROCESS_ATTACH - Current Process: 0x%x, ID: 0x%x ***\r\n"),
GetCurrentProcess(), GetCurrentProcessId()));
// is device manager already running?
if(IsAPIReady(SH_DEVMGR_APIS)) {
// yes -- we only allow one instance, so fail this entry point
bRc = FALSE;
} else {
DisableThreadLibraryCalls((HMODULE) hDllHandle);
}
}
break;
case DLL_PROCESS_DETACH:
{
DEBUGMSG(ZONE_INIT,(_T("*** DLL_PROCESS_DETACH - Current Process: 0x%x, ID: 0x%x ***\r\n"),
GetCurrentProcess(), GetCurrentProcessId()));
}
break;
default:
break;
}
return bRc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -