📄 pmutils.cpp
字号:
pIdDst->pszName = NULL;
__try {
// copy class field if present
DWORD dwNameOffset = sizeof(*pIdDst);
if(pIdSrc->pGuid != NULL) {
LPGUID pGuid = (LPGUID) ((LPBYTE) pIdDst + sizeof(*pIdDst));
*pGuid = *pIdSrc->pGuid;
pIdDst->pGuid = pGuid;
dwNameOffset += sizeof(GUID);
}
// copy name field if present
if(pIdSrc->pszName != NULL) {
LPTSTR pszName = (LPTSTR) ((LPBYTE) pIdDst + dwNameOffset);
_tcscpy(pszName, pIdSrc->pszName);
pIdDst->pszName = pszName;
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: exception during member copy\r\n"),
pszFname));
pIdDst = NULL;
}
}
return pIdDst;
}
// This routine creates a copy of a device id and returns its pointer. If
// there's a problem it returns NULL.
PDEVICEID
DeviceIdClone(PDEVICEID pId)
{
PDEVICEID pIdClone;
DWORD dwSize;
SETFNAME(_T("DeviceIdClone"));
DEBUGCHK(pId != NULL);
// calculate the amount of memory to allocate
dwSize = DeviceIdSize(pId);
if(dwSize != 0) {
pIdClone = (PDEVICEID) PmAlloc(dwSize);
} else {
pIdClone = NULL;
}
// copy data into the buffer
if(pIdClone != NULL) {
PDEVICEID pIdTmp = DeviceIdCloneIntoBuffer(pId, pIdClone, dwSize);
if(pIdTmp == NULL) {
PmFree(pIdClone);
pIdClone = NULL;
}
}
DEBUGCHK(pIdClone == NULL || pIdClone->pGuid != NULL || pIdClone->pszName != NULL);
return pIdClone;
}
// This routine parses a device name string and returns a pointer to an
// allocated device ID. The caller is responsible for freeing this pointer
// when they are done with it. If the name cannot be parsed, this routine
// returns NULL.
PDEVICEID
DeviceIdParseNameString(LPCTSTR pszDevName, DWORD dwFlags)
{
GUID idClass;
LPCTSTR pszName = pszDevName;
PDEVICEID pdi = NULL;
DEVICEID di;
SETFNAME(_T("DeviceIdParseNameString"));
// sanity check the parameters
PREFAST_DEBUGCHK(pszName != NULL);
if((dwFlags & POWER_NAME) == 0) {
PMLOGMSG(ZONE_WARN,
(_T("%s: don't know how to parse name without POWER_NAME flag\r\n"),
pszFname));
return NULL;
}
// is the name prefixed with a guid?
__try {
BOOL fOk = TRUE;
if(*pszName == '{') {
if(!ConvertStringToGuid(pszName, &idClass)) {
// indicate an error later
pszName = NULL;
} else {
// skip the guid, we are guaranteed to find the
// closing brace because the guid parsed ok.
while(*pszName != '}' && *pszName != 0) {
pszName++;
}
// skip the trailing curly-brace and backslash
if(*pszName != '}') {
fOk = FALSE;
} else {
pszName++; // go to the char after the close brace
if(*pszName != _T('\\')) {
fOk = FALSE;
} else {
pszName++;
}
}
}
} else {
// use the default device class
idClass = idGenericPMDeviceClass;
}
// do we have a name?
if(fOk && *pszName != 0) {
DWORD dwLen;
DWORD cchName;
// yes, save it and convert to lower case
di.pGuid = &idClass;
cchName = _tcslen(pszName);
dwLen = (cchName + 1) * sizeof(*pszName);
__try {
DWORD dwIndex;
LPTSTR pszTempName = (LPTSTR) _alloca(dwLen);
for(dwIndex = 0; dwIndex < cchName; dwIndex++) {
pszTempName[dwIndex] = _totlower(pszName[dwIndex]);
}
pszTempName[cchName] = 0;
di.pszName = pszTempName;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
di.pszName = NULL;
}
if(di.pszName != NULL) {
pdi = DeviceIdClone(&di);
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: exception parsing name\r\n"), pszFname));
}
PMLOGMSG(pdi == NULL && ZONE_WARN, (_T("%s: returning 0x%08x\r\n"), pszFname, pdi));
return pdi;
}
// This routine deallocates a device ID that was created with DeviceIdClone().
// Do not call this routine on a device ID that may have statically allocated
// members.
VOID
DeviceIdDestroy(PDEVICEID pId)
{
if(pId) {
PmFree(pId);
}
}
// This routine returns TRUE if two device IDs match exactly, FALSE otherwise.
// Note that exact matches are expected to be case sensitive, so "FOO1:" will
// not match "foo1:".
BOOL
DeviceIdsAreEqual(PDEVICEID pId1, PDEVICEID pId2)
{
BOOL fEqual = TRUE;
PREFAST_DEBUGCHK(pId1 != NULL);
PREFAST_DEBUGCHK(pId2 != NULL);
// check name strings first
if(pId1->pszName == NULL) {
if(pId2->pszName != NULL) {
fEqual = FALSE;
}
} else {
if(pId2->pszName == NULL || _tcscmp(pId1->pszName, pId2->pszName) != 0) {
fEqual = FALSE;
}
}
// check guid values
if(fEqual == TRUE) {
if(pId1->pGuid == NULL) {
if(pId2->pGuid != NULL) {
fEqual = FALSE;
}
} else {
if(pId2->pGuid == NULL || *pId1->pGuid != *pId2->pGuid) {
fEqual = FALSE;
}
}
}
return fEqual;
}
// ------------------------ DEVICE STATE MANAGEMENT ------------------------
// this routine creates a data structure describing a device. Its initial
// reference count is one.
PDEVICE_STATE
DeviceStateCreate(LPCTSTR pszName)
{
BOOL fOk = FALSE;
PDEVICE_STATE pds = NULL;
SETFNAME(_T("DeviceStateCreate"));
PREFAST_DEBUGCHK(pszName != NULL);
__try {
DWORD dwSize = sizeof(*pds) + ((_tcslen(pszName) + 1) * sizeof(pszName[0]));
pds = (PDEVICE_STATE) PmAlloc(dwSize);
if(pds != NULL) {
LPTSTR pszNameCopy = (LPTSTR) ((LPBYTE) pds + sizeof(*pds));
memset(pds, 0, sizeof(*pds));
_tcscpy(pszNameCopy, pszName);
pds->pszName = pszNameCopy;
pds->curDx = D0;
pds->floorDx = PwrDeviceUnspecified;
pds->ceilingDx = PwrDeviceUnspecified;
pds->setDx = PwrDeviceUnspecified;
pds->lastReqDx = D0;
pds->actualDx = D0;
pds->pendingDx = PwrDeviceUnspecified;
pds->dwNumPending = 0;
pds->pParent = NULL;
pds->dwRefCount = 1;
pds->hDevice = INVALID_HANDLE_VALUE;
pds->pListHead = NULL;
pds->pNext = NULL;
pds->pPrev = NULL;
PMLOGMSG(ZONE_REFCNT, (_T("%s: created 0x%08x (name '%s'), refcnt is %d\r\n"),
pszFname, pds, pszName, pds->dwRefCount));
fOk = TRUE;
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
PMLOGMSG(ZONE_WARN, (_T("%s: exception initializing structure\r\n"), pszFname));
}
if(!fOk) {
if(pds != NULL) {
PmFree(pds);
pds = NULL;
}
}
PMLOGMSG(pds == NULL && ZONE_WARN, (_T("%s: couldn't create structure for '%s'\r\n"),
pszFname, pszName));
return pds;
}
// this routine deallocates a device state structure. It returns TRUE if
// successful, FALSE otherwise.
BOOL
DeviceStateDestroy(PDEVICE_STATE pds)
{
BOOL fOk = TRUE;
SETFNAME(_T("DeviceStateDestroy"));
PMLOGMSG(ZONE_REFCNT, (_T("%s: deleting 0x%08x\r\n"), pszFname, pds));
if(pds != NULL) {
if(pds->pParent != NULL) DeviceStateDecRef(pds->pParent);
if(pds->hDevice != INVALID_HANDLE_VALUE) {
PREFAST_DEBUGCHK(pds->pInterface != NULL);
pds->pInterface->pfnCloseDevice(pds->hDevice);
}
PmFree(pds);
}
return fOk;
}
// this routine updates a device's reference count
VOID
DeviceStateAddRef(PDEVICE_STATE pds)
{
SETFNAME(_T("DeviceStateAddRef"));
PREFAST_DEBUGCHK(pds != NULL);
PMLOCK();
pds->dwRefCount++;
PMLOGMSG(ZONE_REFCNT, (_T("%s: refcnt for 0x%08x set to %d\r\n"), pszFname,
pds, pds->dwRefCount));
PMUNLOCK();
}
// this routine decrements a device's reference count and frees the device's
// state if the reference count goes to zero.
VOID
DeviceStateDecRef(PDEVICE_STATE pds)
{
BOOL fDestroy = FALSE;
SETFNAME(_T("DeviceStateDecRef"));
PREFAST_DEBUGCHK(pds != NULL);
PMLOCK();
DEBUGCHK(pds->dwRefCount > 0);
pds->dwRefCount--;
PMLOGMSG(ZONE_REFCNT, (_T("%s: refcnt for 0x%08x set to %d\r\n"), pszFname,
pds, pds->dwRefCount));
if(pds->dwRefCount == 0) {
DEBUGCHK(pds->pListHead == NULL && pds->pNext == NULL && pds->pPrev == NULL);
fDestroy = TRUE;
}
PMUNLOCK();
// is it time to get rid of the device?
if(fDestroy) {
DeviceStateDestroy(pds);
}
}
// this routine adds a device state structure to a list and increments its
// reference count. It returns TRUE if successful, FALSE otherwise.
BOOL
DeviceStateAddList(PDEVICE_LIST pdl, PDEVICE_STATE pdsDevice)
{
BOOL fOk = TRUE;
SETFNAME(_T("DeviceStateAddList"));
PREFAST_DEBUGCHK(pdl != NULL);
PREFAST_DEBUGCHK(pdsDevice != NULL);
DEBUGCHK(pdsDevice->pNext == NULL && pdsDevice->pPrev == NULL);
DEBUGCHK(pdsDevice->dwRefCount == 1);
DEBUGCHK(pdsDevice->pListHead == NULL);
PMLOGMSG(ZONE_REFCNT | ZONE_DEVICE,
(_T("%s: adding 0x%08x ('%s') to list 0x%08x\r\n"),
pszFname, pdsDevice, pdsDevice->pszName, pdl));
// put the new device at the head of the list
PMLOCK();
pdsDevice->pListHead = pdl;
pdsDevice->pNext = pdl->pList;
pdsDevice->pPrev = NULL;
if(pdl->pList != NULL) {
pdl->pList->pPrev = pdsDevice;
}
pdl->pList = pdsDevice;
// copy interface method pointers from the device class
DEBUGCHK(pdl->pInterface != NULL);
pdsDevice->pInterface = pdl->pInterface;
DeviceStateAddRef(pdsDevice);
PMUNLOCK();
return fOk;
}
// this routine removes a device state structure from a list and decrements
// its reference count.
BOOL
DeviceStateRemList(PDEVICE_STATE pds)
{
BOOL fOk = TRUE;
SETFNAME(_T("DeviceStateRemList"));
PREFAST_DEBUGCHK(pds != NULL);
PREFAST_DEBUGCHK(pds->pListHead != NULL);
PMLOGMSG(ZONE_REFCNT | ZONE_DEVICE,
(_T("%s: removing 0x%08x ('%s') from list 0x%08x\r\n"),
pszFname, pds, pds->pszName, pds->pListHead));
PMLOCK();
// are we at the head of the list?
if(pds->pPrev != NULL) {
pds->pPrev->pNext = pds->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(pds->pNext != NULL) {
pds->pNext->pPrev = NULL;
}
pds->pListHead->pList = pds->pNext;
}
// are we at the tail of the list?
if(pds->pNext != NULL) {
pds->pNext->pPrev = pds->pPrev;
} else {
if(pds->pPrev != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -