App and driver 电源管理器注册

2019-07-13 23:10发布

data/attach/1907/djta9bgvhukegnodiaw278khh5q82mz5.jpg  电源注册过程:
1、DevicePowerNotify      Sends a request to the Power Manager about changing a power state
of a peripheral device. 2、RequestPowerNotifications (注册电源管理器)       Registers a message queue to receive power change notifications .
3、StopPowerNotifications      Stops receiving power change notifications .
4、SetPowerRequirement     Informs the Power Manager about power requirements of a given peripheral device . 5、ReleasePowerRequirement      Informs Power Manager that it can release previously set power re- quirements of a given peripheral device .
6. SetSystemPowerState A request sent to the Power Manager about changing a power state of the system as a whole .
IOCTL:
PM Example:
// // Copyright (c) Microsoft Corporation. All rights reserved. // // // Use of this source code is subject to the terms of the Microsoft // premium shared source license agreement under which you licensed // this source code. If you did not accept the terms of the license // agreement, you are not authorized to use this source code. // For the terms of the license, please see the license agreement // signed by you and Microsoft. // THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES. // /*++ Module Name: api.c Abstract: Power Manager API runthrough test (defunct). Notes: Revision History: --*/ #include #include #include extern int CreateArgvArgc(TCHAR *pProgName, TCHAR *argv[20], TCHAR *pCmdLine); typedef enum _Cmd { TEST_INFINITE = 'i', TEST_ONCE = 'o', PREMATURE_RELEASE = 'p', } CMD; #define QUEUE_ENTRIES 3 #define MAX_NAMELEN 200 #define QUEUE_SIZE (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + MAX_NAMELEN)) HANDLE hMsgQ; DWORD WINAPI PowerNotifyThread( LPVOID Context ); #ifdef DEBUG DBGPARAM dpCurSettings = { TEXT("PMAPI"), { TEXT("Error"), TEXT("Warn"), TEXT("Thread"), TEXT("Trace") TEXT("5"), TEXT("6"), TEXT("7"), TEXT("8") TEXT("9"), TEXT("10"), TEXT("11"), TEXT("12") TEXT("13"), TEXT("14"), TEXT("15"), TEXT("16") }, 0x0007 // ZONE_WRN|ZONE_ERR|ZONE_THREAD }; #define ZONE_ERR DEBUGZONE(0) #define ZONE_WRN DEBUGZONE(1) #define ZONE_THREAD DEBUGZONE(2) #define ZONE_TRACE DEBUGZONE(3) #endif // DEBUG DWORD MyEnumRegValues( HKEY hKey, LPCWSTR pState, DWORD Len ) { WCHAR wsValBuff[MAX_PATH]; BYTE bData[MAX_PATH]; DWORD iValue, dwValBuffLen, dwType, dwDataLen; DWORD dwErr = ERROR_SUCCESS; for (iValue = 0; ERROR_SUCCESS == dwErr; iValue++) { memset(&wsValBuff, 0, MAX_PATH); dwValBuffLen = MAX_PATH; dwType = 0; memset(&bData, 0, MAX_PATH); dwDataLen = MAX_PATH; dwErr = RegEnumValue(hKey, iValue, &wsValBuff[0], &dwValBuffLen, NULL, &dwType, &bData[0], &dwDataLen); if (ERROR_SUCCESS == dwErr) { if (pState && dwType == REG_DWORD && sizeof(DWORD) == dwDataLen && 0 == wcsncmp(PM_FLAGS_SZ, wsValBuff, dwValBuffLen)) { DWORD Flags = *(PDWORD)bData; switch (POWER_STATE(Flags)) { case POWER_STATE_OFF: DEBUGMSG(ZONE_TRACE, (TEXT("'%s' is a POWER_STATE_OFF "), pState)); continue; case POWER_STATE_SUSPEND: DEBUGMSG(ZONE_TRACE, (TEXT("'%s' is a POWER_STATE_SUSPEND "), pState)); continue; } } } else if (ERROR_NO_MORE_ITEMS != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI! RegEnumValue ERROR:%d dwType:%d "), dwErr, dwType)); } } return (dwErr == ERROR_NO_MORE_ITEMS ? ERROR_SUCCESS : dwErr); } /*++ System power state processing sample. --*/ DWORD MyProcessSystemPowerStates( VOID ) { WCHAR wsKeyBuff[MAX_PATH]; DWORD dwKeyBuffLen; DWORD dwSubErr; DWORD dwErr; int iKey; HKEY hKey; // open the power manager's state keys // _stprintf(wsKeyBuff, _T("%s\State"), PWRMGR_REG_KEY); dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wsKeyBuff, 0, 0, &hKey); // enumerate the subkeys // for (iKey = 0; ERROR_SUCCESS == dwErr; iKey++) { memset(&wsKeyBuff, 0, MAX_PATH); dwKeyBuffLen = MAX_PATH; dwErr = RegEnumKeyEx(hKey, iKey, &wsKeyBuff[0], &dwKeyBuffLen, NULL, NULL, NULL, NULL); if (ERROR_SUCCESS == dwErr) { HKEY hSubKey; // open the subkey // dwSubErr = RegOpenKeyEx(hKey, &wsKeyBuff[0], 0, 0, &hSubKey); if (ERROR_SUCCESS != dwSubErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!RegOpenKeyEx ERROR:%d "), dwSubErr)); break; } // enumerate the values // dwSubErr = MyEnumRegValues(hSubKey, wsKeyBuff, dwKeyBuffLen); if (hSubKey) RegCloseKey(hSubKey); // subkeys name the system states, so set them... // DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetSystemPowerState:%s "), wsKeyBuff)); dwErr = SetSystemPowerState(wsKeyBuff, 0, 0); if (ERROR_SUCCESS != dwErr && ERROR_CANCELLED != dwErr && ERROR_SET_POWER_STATE_VETOED != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetSystemPowerState ERROR:%d *** "), dwErr)); RegCloseKey(hSubKey); break; } DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetSystemPowerState:%s, POWER_FORCE "), wsKeyBuff)); dwErr = SetSystemPowerState(wsKeyBuff, 0, POWER_FORCE); if (ERROR_SUCCESS != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetSystemPowerState ERROR:%d *** "), dwErr)); RegCloseKey(hSubKey); break; } } else if (ERROR_NO_MORE_ITEMS != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!RegEnumKeyEx ERROR: %d "), dwErr)); } } if (hKey) RegCloseKey(hKey); return (dwErr == ERROR_NO_MORE_ITEMS ? ERROR_SUCCESS : dwErr); } // Simple test app // int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nCmShow) { TCHAR *argv[20]; int argc; CMD cCmd = 0; MSGQUEUEOPTIONS msgOptions = {0}; MEMORYSTATUS m1 = {0}, m2 = {0}; DWORD dwErr; HANDLE hReq = NULL; HANDLE hNotifications; CEDEVICE_POWER_STATE Dx; HANDLE hPrev; HANDLE hThread; DWORD dwTest = 1; BOOL bDone = FALSE; WIN32_FIND_DATA fd; DWORD device; UNREFERENCED_PARAMETER(hInst); UNREFERENCED_PARAMETER(hPrevInst); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmShow); DEBUGREGISTER(NULL); // // parse command line // argc = CreateArgvArgc(TEXT( "PMAPI" ), argv, lpCmdLine); if (argc >= 2) { if (!swscanf(argv[1], TEXT("%c"), &cCmd )) cCmd = 0; } switch (cCmd) { case TEST_ONCE: case TEST_INFINITE: case PREMATURE_RELEASE: break; default: { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI "))); DEBUGMSG(ZONE_ERR, (TEXT(" where is one of "))); DEBUGMSG(ZONE_ERR, (TEXT(" %c : Infinite test pass "), TEST_INFINITE)); DEBUGMSG(ZONE_ERR, (TEXT(" %c : One-shot test pass "), TEST_ONCE)); DEBUGMSG(ZONE_ERR, (TEXT(" %c : Premature exit test pass "), PREMATURE_RELEASE)); } return 0; } // snap mem // GlobalMemoryStatus(&m1); DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!Before PM API Tests: Virtual Memory = %ld "), m1.dwAvailVirtual)); // // create a message queue for device notifications // msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS); msgOptions.dwFlags = 0; msgOptions.cbMaxMessage = QUEUE_SIZE; msgOptions.bReadAccess = TRUE; hMsgQ = CreateMsgQueue(NULL, &msgOptions); if (!hMsgQ) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!CreateMessageQueue ERROR:%d "), dwErr)); return dwErr; } // request Power notifications // hNotifications = RequestPowerNotifications(hMsgQ, POWER_NOTIFY_ALL); if (!hNotifications) { CloseMsgQueue(hMsgQ); dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!RequestPowerNotifications ERROR:%d "), dwErr)); return dwErr; } // start the notify thread // hThread = CreateThread(NULL, 0, PowerNotifyThread, NULL, 0, NULL ); if ( !hThread ) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!CreateThread ERROR:%d "), dwErr )); return -1; } do { DEBUGMSG(ZONE_ERR, (TEXT(" PMAPI!************************ BEGIN PM API Test[%d]************************ "), dwTest)); ///////////////////////////////////////////// // // Test : set every *named* system power state // dwErr = MyProcessSystemPowerStates( ); if (ERROR_SUCCESS != dwErr && ERROR_CANCELLED != dwErr && // cancelled by user dialog ERROR_SET_POWER_STATE_VETOED != dwErr ) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!MyProcessSystemPowerStates ERROR.1:%d "), dwErr)); break; } ///////////////////////////////////////////// // // Test: SetSystemPowerState: by flags // DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetSystemPowerState:POWER_STATE_SUSPEND, POWER_FORCE "))); dwErr = SetSystemPowerState(NULL, POWER_STATE_SUSPEND, POWER_FORCE); if (ERROR_SUCCESS != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!SetSystemPowerState ERROR.1:%d "), dwErr)); break; } ///////////////////////////////////////////// // // Test: SetSystemPowerState: invalid states // DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetSystemPowerState:abcde "))); dwErr = SetSystemPowerState(L"abcde", 0, 0); if (ERROR_SUCCESS == dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetSystemPowerState ERROR.2:%d **** "), dwErr)); break; } DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetSystemPowerState: 123 "))); dwErr = SetSystemPowerState(L" 123 ", 0, 0); if (ERROR_SUCCESS == dwErr) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetSystemPowerState ERROR.2:%d **** "), dwErr)); break; } ///////////////////////////////////////////// // // Test: SetPowerRequirement: invalid parameters // dwErr = ERROR_SUCCESS; for (Dx = PwrDeviceUnspecified; Dx <= PwrDeviceMaximum; Dx++) { HANDLE h; // *INVALID* parameter DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetPowerRequirement:#$%#$ "))); h = SetPowerRequirement(L"#$%#$", // *INVALID* DeviceName Dx, // DeviceState, POWER_NAME, // DeviceFlags NULL, 0); if (h) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetPowerRequirement ERROR.3.1:%d **** "), dwErr)); break; } // *INVALID* parameter DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetPowerRequirement:PwrDeviceMaximum "))); h = SetPowerRequirement(L"DSK1:", // DeviceName Dx, // DeviceState, 0, // *INVALID* Flags NULL, 0); if (h) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetPowerRequirement ERROR.3.2:%d **** "), dwErr)); break; } } if (ERROR_SUCCESS != dwErr) break; ///////////////////////////////////////////// // // Test: SetPowerRequirement: make sure we always get the same handle in this process // hPrev = hReq = NULL; for ( Dx = D0; Dx < PwrDeviceMaximum; Dx++) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetPowerRequirement:DSK1: "))); hReq = SetPowerRequirement(L"DSK1:", // DeviceName Dx, // DeviceState, POWER_NAME, // Flags NULL, 0); if (!hReq) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetPowerRequirement ERROR.3.3:%d, Dx:%d**** "), dwErr, Dx)); break; } if (hPrev && (hPrev != hReq)) { dwErr = ERROR_GEN_FAILURE; DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!*** SetPowerRequirement ERROR.3.4:%d, hPrev:0x%x, hReq:0x%x **** "), dwErr, hPrev, hReq)); break; } hPrev = hReq; } if (ERROR_SUCCESS != dwErr) break; DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!ReleasePowerRequirement "))); dwErr = ReleasePowerRequirement(hReq); if (ERROR_SUCCESS != dwErr) break; ///////////////////////////////////////////// // // Test: SetPowerRequirement: on *all devices* // for (device = 0; ; device++) { memset(&fd, 0, sizeof(fd)); if ( !GetDeviceByIndex(device, &fd) ) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!GetDeviceByIndex: no more devices:%d "), device)); break; } for (Dx = D0; Dx < PwrDeviceMaximum; Dx++) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetPowerRequirement:'%s', D%d "), fd.cFileName, Dx)); hReq = SetPowerRequirement(fd.cFileName, // DeviceName Dx, // DeviceState, POWER_NAME, // Flags NULL, 0); if ( !hReq ) { dwErr = GetLastError(); DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!*** SetPowerRequirement Device:'%s', Dx:%d, ERROR.4:%d **** "), fd.cFileName, Dx, dwErr)); if (fd.cFileName[0] != 0) // NULL name? break; else dwErr = ERROR_SUCCESS; } } if (ERROR_SUCCESS != dwErr) break; DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!ReleasePowerRequirement "))); dwErr = ReleasePowerRequirement(hReq); if (ERROR_SUCCESS != dwErr) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!ReleasePowerRequirement ERROR:%d "), dwErr)); if (hReq) break; else dwErr = ERROR_SUCCESS; } } if (ERROR_SUCCESS != dwErr) break; ///////////////////////////////////////////// // // Test : simulate DevicePowerNotify on all devices // for (device = 0; ; device++) { memset(&fd, 0, sizeof(fd)); if ( !GetDeviceByIndex(device, &fd) ) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!GetDeviceByIndex: no more devices:%d "), device)); break; } for (Dx = D0; Dx < PwrDeviceMaximum; Dx++) { dwErr = DevicePowerNotify(fd.cFileName, // DeviceName Dx, // DeviceState, POWER_NAME // Flags ); if ( ERROR_SUCCESS != dwErr ) { // this error code was propogated from the named device, so don't abort DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!*** DevicePowerNotify Device:'%s', Dx:%d, ERROR:%d **** "), fd.cFileName, Dx, dwErr)); } } } dwErr = ERROR_SUCCESS; ///////////////////////////////////////////// // // Test: set device requirement on *all devices*, then adjust the system power level // // .... ///////////////////////////////////////////// // // Test: set device requirement on *all* devices, then exit prematurely // for (device = 0; ;device++) { memset(&fd, 0, sizeof(fd)); if ( !GetDeviceByIndex(device, &fd) ) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!GetDeviceByIndex: no more devices:%d "), device)); break; } for (Dx = D0; Dx < PwrDeviceMaximum; Dx++) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!SetPowerRequirement:'%s' "), fd.cFileName)); hReq = SetPowerRequirement(fd.cFileName, // DeviceName Dx, // DeviceState, POWER_NAME, // Flags 0, 0); if ( !hReq ) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!*** SetPowerRequirement on Device:'%s', Dx:%d, ERROR.0:%d **** "), fd.cFileName, Dx, GetLastError())); if (fd.cFileName[0] != 0) // NULL name? break; else dwErr = ERROR_SUCCESS; } // drop them all on the floor to see if PM will clean it up } } switch(cCmd) { case PREMATURE_RELEASE: exit(0); case TEST_INFINITE: Sleep(500); break; default: bDone = TRUE; break; } DEBUGMSG(ZONE_ERR, (TEXT(" PMAPI!************************ END PM API Test[%d] ************************ "), dwTest++)); } while (!bDone); DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!StopPowerNotifications "))); if ( !StopPowerNotifications(hNotifications) ) { DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!StopNotifications ERROR:%d "), GetLastError())); } CloseMsgQueue(hMsgQ); // snap mem // GlobalMemoryStatus(&m2); DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI!After PM API Tests: Virtual Memory = %ld "), m2.dwAvailVirtual)); if ((m2.dwAvailVirtual < m1.dwAvailVirtual)) { DEBUGMSG(ZONE_TRACE, (TEXT("PMAPI! *** PM API Leaked: Physical Memory = %ld, Virtual Memory = %ld *** "), (m1.dwAvailPhys - m2.dwAvailPhys), (m1.dwAvailVirtual - m2.dwAvailVirtual))); } if (ERROR_SUCCESS != dwErr) { DEBUGMSG(ZONE_ERR, (TEXT(" *** PMAPI TEST FAILED:%d **** "), dwErr)); } else { DEBUGMSG(ZONE_ERR, (TEXT(" *** PMAPI TEST PASSED **** "))); } return 1; } int GetPriority( VOID ) { return 251; // THREAD_PRIORITY_NORMAL } DWORD WINAPI PowerNotifyThread( LPVOID Context ) { DWORD dwErr, dwFlags = 0, dwCount = 0; DWORD dwPri = 0; UCHAR buf[QUEUE_SIZE]; int iBytesInQueue; const int ci = sizeof(POWER_BROADCAST); dwPri = GetPriority(); if ( !CeSetThreadPriority(GetCurrentThread(), dwPri)) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!CeSetThreadPriority ERROR:%d "), dwErr)); ExitThread(dwErr); return dwErr; } do { iBytesInQueue = 0; memset(&buf, 0, QUEUE_SIZE); // Block on our message queue. // This thread runs when the power manager writes a notification into the queue. if ( !ReadMsgQueue(hMsgQ, &buf, QUEUE_SIZE, &iBytesInQueue, INFINITE, // Timeout &dwFlags)) { dwErr = GetLastError(); DEBUGMSG(ZONE_ERR, (TEXT("PMAPI!ReadMsgQueue: ERROR:%d "), dwErr)); break; } else { // // process power notifications // PPOWER_BROADCAST pB = (PPOWER_BROADCAST)&buf; while (iBytesInQueue > 0 && iBytesInQueue > ci) { DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI!*** Power Notification @ Tick:%u, Count:%d, Pri:%d*** "), GetTickCount(), dwCount++, CeGetThreadPriority(GetCurrentThread()))); DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! Message: 0x%x "), pB->Message)); DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! Flags: 0x%x "), pB->Flags)); DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! dwLen: %d "), pB->Length)); DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! SystemPowerState: '%s' "), pB->SystemPowerState)); switch (pB->Message) { case PBT_TRANSITION: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! PBT_TRANSITION "))); switch (POWER_STATE(pB->Flags)) { case POWER_STATE_ON: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_ON "))); break; case POWER_STATE_OFF: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_OFF "))); break; case POWER_STATE_CRITICAL: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_CRITICAL "))); break; case POWER_STATE_BOOT: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_BOOT "))); break; case POWER_STATE_IDLE: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_IDLE "))); break; case POWER_STATE_SUSPEND: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_SUSPEND "))); break; case POWER_STATE_RESET: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! POWER_STATE_RESET "))); break; default: DEBUGMSG(ZONE_THREAD,(TEXT("PMAPI! Unknown Power State:0x%x "),pB->Flags)); ASSERT(0); break; } break; case PBT_RESUME: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! PBT_RESUME "))); break; case PBT_POWERSTATUSCHANGE: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! PBT_POWERSTATUSCHANGE "))); break; default: DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI! Invalid Message:%d "), pB->Message)); ASSERT(0); break; } DEBUGMSG(ZONE_THREAD, (TEXT("PMAPI!*********************** "))); iBytesInQueue -= ci + pB->Length; pB += ci + pB->Length; } } } while (1); ExitThread(ERROR_SUCCESS); return ERROR_SUCCESS; } // EOF