📄 pmutils.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// This modules contains various utility routines for creating, deleting
// and accessing power manager data.
//
#include <pmimpl.h>
#include <msgqueue.h>
#include <nkintr.h>
#ifdef DEBUG
// turns on some memory garbling code -- adds overhead but hopefully helps catch bugs
#define DEBUGALLOC
#endif // DEBUG
// ------------------------ REGISTRY FUNCTIONS ------------------------
// This routine reads data from the registry and verifies that it's
// of the proper type. It returns ERROR_SUCCESS if the data can be
// read and is the right type or a registry error if it can't be
// read. If the data is the wrong type, this routine returns
// ERROR_INVALID_DATA.
DWORD
RegQueryTypedValue(HKEY hk, LPCWSTR pszValue, PVOID pvData,
LPDWORD pdwSize, DWORD dwType)
{
DWORD dwActualType;
SETFNAME(_T("RegQueryTypedValue"));
DWORD dwStatus = RegQueryValueEx(hk, pszValue, NULL, &dwActualType,
(PBYTE) pvData, pdwSize);
if(dwStatus == ERROR_SUCCESS && dwActualType != dwType) {
PMLOGMSG(ZONE_WARN, (_T("%s: wrong type for '%s'\r\n"),
pszFname, pszValue));
dwStatus = ERROR_INVALID_DATA;
}
return dwStatus;
}
BOOL
GetPMThreadPriority(LPCTSTR pszValue, LPINT piThreadPriority)
{
BOOL fOk = FALSE;
HKEY hkPm = NULL;
DWORD dwStatus;
SETFNAME(_T("GetPMThreadPriority"));
// open the PM key
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PWRMGR_REG_KEY, 0, 0, &hkPm);
if(dwStatus == ERROR_SUCCESS) {
DWORD dwValue;
DWORD dwSize = sizeof(dwValue);
// read the requested value
dwStatus = RegQueryTypedValue(hkPm, pszValue, &dwValue, &dwSize, REG_DWORD);
if(dwStatus == ERROR_SUCCESS) {
*piThreadPriority = (INT) dwValue;
PMLOGMSG(ZONE_REGISTRY, (_T("%s: priority for '%s' is %d\r\n"),
pszFname, pszValue, dwValue));
fOk = TRUE;
}
// close the key
RegCloseKey(hkPm);
}
PMLOGMSG(!fOk && ZONE_REGISTRY, (_T("%s: no setting for '%s'\r\n"),
pszFname, pszValue));
return fOk;
}
// ------------------------ SERIALIZATION ------------------------
// serialize access to PM list variables and structure members
VOID
PmLock(VOID)
{
EnterCriticalSection(&gcsPowerManager);
}
// release synchronization objects obtained with PmLock()
VOID
PmUnlock(VOID)
{
LeaveCriticalSection(&gcsPowerManager);
}
// serialize access to appliation APIs that cause device updates
VOID
PmEnterUpdate(VOID)
{
EnterCriticalSection(&gcsDeviceUpdateAPIs);
}
// release synchronization objects obtained with PmEnterUpdate()
VOID
PmLeaveUpdate(VOID)
{
LeaveCriticalSection(&gcsDeviceUpdateAPIs);
}
// ------------------------ MEMORY STATE MANAGEMENT ------------------------
#define HEAPSIGNATURE 0xFA124301 // randomly chosen number
#define HEAPHEADERSIZE (4 * sizeof(DWORD))
#ifdef DEBUG
// debug globals
LONG glTotalObjects = 0;
#endif // DEBUG
// this routine allocates memory and returns a pointer to it, or returns
// NULL.
PVOID
PmAlloc(DWORD dwSize)
{
SETFNAME(_T("PmAlloc"));
DEBUGCHK(dwSize != 0);
#ifdef DEBUGALLOC
// prepend a header so we can track post-free accesses of the memory
dwSize += HEAPHEADERSIZE;
#endif // DEBUGALLOC
PVOID pvRet = HeapAlloc(ghPmHeap, 0, dwSize);
if(pvRet == NULL) {
PMLOGMSG(ZONE_WARN, (_T("%s: HeapAlloc(%d) failed %d\r\n"), pszFname,
dwSize, GetLastError()));
}
#ifdef DEBUG
else {
InterlockedIncrement(&glTotalObjects);
}
#endif // DEBUG
#ifdef DEBUGALLOC
// fill memory with a diagnostic pattern for debugging
if(pvRet != NULL) {
memset(pvRet, 0xAA, dwSize);
PDWORD pdwRet = (PDWORD) pvRet;
pdwRet[0] = HEAPSIGNATURE; // record a signature
pdwRet[1] = dwSize; // and the real size of the buffer
pvRet = &pdwRet[HEAPHEADERSIZE / sizeof(DWORD)]; // return a pointer to a buffer of the requested size
}
#endif // DEBUGALLOC
#ifdef DEBUG
PMLOGMSG(ZONE_ALLOC, (_T("%s: alloc %d bytes returned 0x%08x (%d total objects allocated)\r\n"),
pszFname, dwSize, pvRet, glTotalObjects));
#else // DEBUG
PMLOGMSG(ZONE_ALLOC, (_T("%s: alloc %d bytes returned 0x%08x\r\n"),
pszFname, dwSize, pvRet));
#endif // DEBUG
return pvRet;
}
// this routine frees memory allocated with PmAlloc()
BOOL
PmFree(PVOID pvMemory)
{
SETFNAME(_T("PmFree"));
PMLOGMSG(ZONE_ALLOC, (_T("%s: freeing 0x%08x\r\n"), pszFname, pvMemory));
DEBUGCHK(pvMemory != NULL);
#ifdef DEBUGALLOC
// fill
if(pvMemory != NULL) {
PDWORD pdwMemory = (PDWORD) ((DWORD) pvMemory - HEAPHEADERSIZE);
DEBUGCHK(pdwMemory[0] == HEAPSIGNATURE && pdwMemory[1] > HEAPHEADERSIZE);
memset(pdwMemory, 0xDD, pdwMemory[1]);
pvMemory = pdwMemory;
}
#endif // DEBUGALLOC
BOOL fOk = HeapFree(ghPmHeap, 0, pvMemory);
if(!fOk) {
PMLOGMSG(ZONE_WARN, (_T("%s: HeapFree(0x%08x) failed %d\r\n"), pszFname,
pvMemory, GetLastError()));
}
#ifdef DEBUG
else {
InterlockedDecrement(&glTotalObjects);
DEBUGCHK(glTotalObjects >= 0);
}
#endif // DEBUG
return fOk;
}
// ------------------------ DEVICE ID MANAGEMENT ------------------------
static BOOL
HexStringToDword(LPCWSTR FAR& lpsz, DWORD FAR& Value,
int cDigits, WCHAR chDelim)
{
int Count;
Value = 0;
for (Count = 0; Count < cDigits; Count++, lpsz++)
{
if (*lpsz >= '0' && *lpsz <= '9')
Value = (Value << 4) + *lpsz - '0';
else if (*lpsz >= 'A' && *lpsz <= 'F')
Value = (Value << 4) + *lpsz - 'A' + 10;
else if (*lpsz >= 'a' && *lpsz <= 'f')
Value = (Value << 4) + *lpsz - 'a' + 10;
else
return(FALSE);
}
if (chDelim != 0)
return *lpsz++ == chDelim;
else
return TRUE;
}
static BOOL
wUUIDFromString(LPCWSTR lpsz, LPGUID pguid)
{
DWORD dw;
if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
return FALSE;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
return FALSE;
pguid->Data2 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
return FALSE;
pguid->Data3 = (WORD)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[0] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
return FALSE;
pguid->Data4[1] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[2] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[3] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[4] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[5] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[6] = (BYTE)dw;
if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
return FALSE;
pguid->Data4[7] = (BYTE)dw;
return TRUE;
}
static BOOL
GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
{
if (*lpsz++ != '{' )
return FALSE;
if(wUUIDFromString(lpsz, pguid) != TRUE)
return FALSE;
lpsz +=36;
if (*lpsz++ != '}' )
return FALSE;
return TRUE;
}
// this routine converts a text string to a GUID if possible.
BOOL
ConvertStringToGuid (LPCTSTR pszGuid, GUID *pGuid)
{
BOOL fOk = FALSE;
SETFNAME(_T("ConvertStringToGuid"));
DEBUGCHK(pGuid != NULL && pszGuid != NULL);
__try {
if (! GUIDFromString(pszGuid, pGuid)) {
PMLOGMSG(ZONE_WARN, (_T("%s: couldn't parse '%s'\r\n"), pszFname,
pszGuid));
}
fOk = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: error parsing guid\r\n"), pszFname));
}
return fOk;
}
// This routine returns the number of bytes that would need to be allocated to hold
// a copy of the device ID being passed in as a parameter. It returns zero if there
// is an error OR if the device id pointer is NULL.
DWORD
DeviceIdSize(PDEVICEID pId)
{
DWORD dwSize;
SETFNAME(_T("DeviceIdSize"));
if(pId != NULL) {
// calculate the amount of memory to allocate
__try {
dwSize = sizeof(*pId);
if(pId->pszName != NULL) {
dwSize += (_tcslen(pId->pszName) + 1) * sizeof(pId->pszName[0]);
}
if(pId->pGuid != NULL) {
dwSize += sizeof(GUID);
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: exception calculating size\r\n"), pszFname));
dwSize = 0;;
}
} else {
dwSize = 0;
}
return dwSize;
}
// This routine clones a source device ID into a pre-allocated buffer. The
// pre-allocation enables callers to reduce the number of heap allocations
// they need to make when embedding device IDs into larger structures.
// This routine returns pIdDst, or NULL in case of error. Errors include
// insufficient buffer size or exceptions while copying.
PDEVICEID
DeviceIdCloneIntoBuffer(PDEVICEID pIdSrc, PDEVICEID pIdDst, DWORD cbDst)
{
DWORD dwSize;
SETFNAME(_T("DeviceIdCloneIntoBuffer"));
PREFAST_DEBUGCHK(pIdSrc != NULL);
DEBUGCHK(pIdSrc->pGuid != NULL || pIdSrc->pszName != NULL);
PREFAST_DEBUGCHK(pIdDst != NULL);
DEBUGCHK(cbDst >= sizeof(DEVICEID));
// make sure we have enough room
dwSize = DeviceIdSize(pIdSrc);
if(cbDst < dwSize) {
PMLOGMSG(ZONE_WARN,
(_T("%s: destination buffer size %d too small, %d bytes needed\r\n"),
pszFname, cbDst, dwSize));
pIdDst = NULL;
} else {
memset(pIdDst, 0, dwSize);
pIdDst->pGuid = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -