// note that APO_REG_PROPERTIES is a variable-sized structure so beware of slicing // also note that it's only valid for the life of the callback; // if you want to store the info for use later, make a deep copy HRESULT WINAPI myEnumerateAPOsCallback( APO_REG_PROPERTIES *pProperties, VOID *pvRefData ) { UINT32 *pnCount = reinterpret_cast<UINT32 *>(pvRefData); if (NULL == pnCount) { ERR(L"myEnumerateAPOsCallback got a NULL pvRefData"); return E_POINTER; } (*pnCount)++; return LogDetails(pProperties); // LogDetails logs its own failures }
MMRESULT EnumerateACMDrivers() { AcmDriverList list; MMRESULT mmr = acmDriverEnum( myAcmDriverEnumCallback, reinterpret_cast<DWORD_PTR>(&list), // app-specific pointer ACM_DRIVERENUMF_DISABLED // include disabled drivers ); if (MMSYSERR_NOERROR != mmr) { ERR(L"acmDriverEnum failed: mmr = 0x%08x", mmr); return mmr; } LOG(L"ACM Drivers found: %u", list.nCount); for (UINT32 i = 0; i < list.nCount; i++) { ACMDRIVERDETAILS details = {0}; details.cbStruct = sizeof(details); mmr = acmDriverDetails(list.pDrivers[i].id, &details, 0); if (MMSYSERR_NOERROR != mmr) { ERR(L"acmDriverDetails failed: mmr = 0x%08x", mmr); return mmr; } if (list.pDrivers[i].fdwSupport != details.fdwSupport) { ERR( L"Different fdwSupport values from " L"acmDriverEnum Callback (0x%08x) and acmDriverDetails (0x%08x)", list.pDrivers[i].fdwSupport, details.fdwSupport ); } LogDetails(details); LOG(L""); // blank line } return MMSYSERR_NOERROR; }
////////////////////////////////////////////////////////////////////////////////////// // Execute a single command // // Once the command is sent, wait for a response. If received and of the correct // ID, save the contents (if any) and quit. If no response, send RESYNC commands // every few seconds to get response from other end. On receipt of a RESYNC // command, resend the previous command. After no response for a minute or so, quit. ////////////////////////////////////////////////////////////////////////////////////// int CSTATEngine::SendSingleCommand(CSTATScriptCommand *pSendCommand, CSTATScriptCommand **ppRecvCommand) { int iTotalCommandTime = 0; int ret = GENERAL_FAILURE; LogDetails("Send", pSendCommand); // send the command EnterCriticalSection(&CriticalSection); ret = pComms->Send(pSendCommand->cCommandID, pSendCommand->Command(), pSendCommand->Length()); LeaveCriticalSection(&CriticalSection); if (ret != ITS_OK) { Message(pComms->Error()); return ret; } // The refresh command will not return anything due to the transport getting restarted. // So, don't wait for a response. if( (ret == ITS_OK) && (pSendCommand->cCommandID == STAT_REFRESH || pSendCommand->cCommandID == STAT_REBOOT) ) { return ret; } // wait for a response unsigned long ulLength = 0; char *pData = NULL; while(iTotalCommandTime < iMaxTimeLimit) { if (StopProcessing()) { pComms->Send(STAT_RESYNCID); ret = E_USERCANCEL; break; } EnterCriticalSection(&CriticalSection); ret = pComms->Receive(&oRecvCommand.cCommandID, &pData, &ulLength); LeaveCriticalSection(&CriticalSection); if (ret == ITS_OK) { if (oRecvCommand.SetData(pData, ulLength)) { oRecvCommand.ulLength = ulLength; *ppRecvCommand = &oRecvCommand; // invalid response received if (pSendCommand->cCommandID != oRecvCommand.cCommandID) { // need to resync back to start of this command if (oRecvCommand.cCommandID == STAT_RESYNCID) { Message("RESYNC response received - retrying command..."); ret = E_RESYNCCOMMAND; } else { if (oRecvCommand.cCommandID == STAT_FAILURE) { if (oRecvCommand.Command() && oRecvCommand.Length()) { Message("Command failed with error code %s", oRecvCommand.Command()); iDeviceCode = atoi(oRecvCommand.Command()); } } else Message("Invalid response received - expected %c received %c", pSendCommand->cCommandID, oRecvCommand.cCommandID); ret = GENERAL_FAILURE; } } else LogDetails("Receive", *ppRecvCommand); } else ret = E_OUTOFMEM; // at this point we have received something whether it's what we were expecting or not so exit loop break; } else if (ret == NO_DATA_AT_PORT) { // Message("Waiting for response"); Sleep(STAT_RETRYDELAY); iTotalCommandTime += STAT_RETRYDELAY; ret = E_TOOMUCHTIME; } else { Message(pComms->Error()); break; } } return ret; }