📄 stubutils.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) {
DEBUGMSG(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;
DEBUGMSG(ZONE_REGISTRY, (_T("%s: priority for '%s' is %d\r\n"),
pszFname, pszValue, dwValue));
fOk = TRUE;
}
// close the key
RegCloseKey(hkPm);
}
DEBUGMSG(!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) {
DEBUGMSG(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
DEBUGMSG(ZONE_ALLOC, (_T("%s: alloc %d bytes returned 0x%08x (%d total objects allocated)\r\n"),
pszFname, dwSize, pvRet, glTotalObjects));
return pvRet;
}
// this routine frees memory allocated with PmAlloc()
BOOL
PmFree(PVOID pvMemory)
{
SETFNAME(_T("PmFree"));
DEBUGMSG(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) {
DEBUGMSG(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;
}
// ------------------------ POWER NOTIFICATION MANAGEMENT ----------
// This routine creates a data structure describing a power notification.
// It returns a pointer to the structure, or NULL if there's an
// error.
PPOWER_NOTIFICATION
PowerNotificationCreate(HANDLE hMsgQ, HANDLE hOwner)
{
SETFNAME(_T("PowerNotificationCreate"));
// allocate resources
PPOWER_NOTIFICATION ppn = (PPOWER_NOTIFICATION) PmAlloc(sizeof(*ppn));
if(ppn != NULL ) {
// initialize the structure
memset(ppn, 0, sizeof(*ppn));
ppn->hOwner = hOwner;
ppn->pNext = NULL;
ppn->pPrev = NULL;
// now try to open the message queue
MSGQUEUEOPTIONS msgopts;
memset(&msgopts, 0, sizeof(msgopts));
msgopts.dwSize = sizeof(MSGQUEUEOPTIONS);
msgopts.bReadAccess = FALSE;
ppn->hMsgQ = OpenMsgQueue(hOwner, hMsgQ, &msgopts);
if(ppn->hMsgQ == NULL) {
DEBUGMSG(ZONE_WARN,
(_T("%s: OpenMsgQueue() failed %d (owner 0x%08x, source q 0x%08x)\r\n"),
pszFname, GetLastError(), hOwner, hMsgQ));
PmFree(ppn);
ppn = NULL;
}
}
DEBUGMSG(ppn == NULL && ZONE_WARN, (_T("%s: couldn't create structure\r\n"), pszFname));
return ppn;
}
// this routine deallocates a device state structure. It returns TRUE if
// successful, FALSE otherwise.
BOOL
PowerNotificationDestroy(PPOWER_NOTIFICATION ppn)
{
BOOL fOk = TRUE;
if(ppn != NULL) {
if(ppn->hMsgQ != NULL) CloseMsgQueue(ppn->hMsgQ);
PmFree(ppn);
}
return fOk;
}
// This routine adds a power notification to a list.
BOOL
PowerNotificationAddList(PPPOWER_NOTIFICATION ppListHead, PPOWER_NOTIFICATION ppn)
{
BOOL fOk = TRUE;
PREFAST_DEBUGCHK(ppListHead != NULL);
PREFAST_DEBUGCHK(ppn != NULL);
DEBUGCHK(ppn->pNext == NULL && ppn->pPrev == NULL);
DEBUGCHK(ppListHead != NULL);
// put the new device at the head of the list
PMLOCK();
ppn->pNext = *ppListHead;
ppn->pPrev = NULL;
if(*ppListHead != NULL) {
(*ppListHead)->pPrev = ppn;
}
*ppListHead = ppn;
PMUNLOCK();
return fOk;
}
// this routine removes a power notification from a list and deletes it.
BOOL
PowerNotificationRemList(PPPOWER_NOTIFICATION ppListHead, PPOWER_NOTIFICATION ppn)
{
BOOL fOk = TRUE;
PREFAST_DEBUGCHK(ppListHead != NULL);
PMLOCK();
// are we at the head of the list?
if(ppn->pPrev != NULL) {
ppn->pPrev->pNext = ppn->pNext;
} else {
// not that if pNext == NULL && pPrev == NULL we are the only list
// member and the assignment to the list head will set it to NULL (meaning
// empty).
if(ppn->pNext != NULL) {
ppn->pNext->pPrev = NULL;
}
*ppListHead = ppn->pNext;
}
// are we at the tail of the list?
if(ppn->pNext != NULL) {
ppn->pNext->pPrev = ppn->pPrev;
} else {
if(ppn->pPrev != NULL) {
ppn->pPrev->pNext = NULL;
}
}
// clear list pointers
ppn->pNext = NULL;
ppn->pPrev = NULL;
// delete the structure and its members
PowerNotificationDestroy(ppn);
PMUNLOCK();
return fOk;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -