BOOL CNTServiceControlManager::EnumServices(DWORD dwServiceType, DWORD dwServiceState, void* pUserData, ENUM_SERVICES_PROC lpEnumServicesFunc) const { //Validate our parameters ATLASSUME(m_hSCM != NULL); DWORD dwBytesNeeded; DWORD dwServices; DWORD dwResumeHandle = 0; BOOL bSuccess = EnumServicesStatus(m_hSCM, dwServiceType, dwServiceState, NULL, 0, &dwBytesNeeded, &dwServices, &dwResumeHandle); if (!bSuccess && GetLastError() == ERROR_MORE_DATA) { //Allocate some memory for the API ATL::CHeapPtr<BYTE> lpBuffer; if (!lpBuffer.Allocate(dwBytesNeeded)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } LPENUM_SERVICE_STATUS lpServices = reinterpret_cast<LPENUM_SERVICE_STATUS>(lpBuffer.m_pData); DWORD dwSize = 0; bSuccess = EnumServicesStatus(m_hSCM, dwServiceType, dwServiceState, (LPENUM_SERVICE_STATUS) lpServices, dwBytesNeeded, &dwSize, &dwServices, &dwResumeHandle); if (bSuccess) { BOOL bContinue = TRUE; for (DWORD i=0; i<dwServices && bContinue; i++) bContinue = lpEnumServicesFunc(pUserData, lpServices[i]); } } return bSuccess; }
BOOL CNTScmService::QueryDescription(CString& sDescription) const { //Validate our parameters ASSERT(m_hService != NULL); //Check to see if the function pointer is available if (m_lpfnQueryServiceConfig2 == NULL) { TRACE(_T("CNTScmService::QueryDescription, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows 2000 to use this function\n")); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } //Call through the function pointer DWORD dwBytesNeeded = 0; BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded); if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { //Allocate some memory for the API ATL::CHeapPtr<BYTE> lpData; if (!lpData.Allocate(dwBytesNeeded)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_DESCRIPTION, lpData, dwBytesNeeded, &dwBytesNeeded); if (bSuccess) sDescription = (reinterpret_cast<LPSERVICE_DESCRIPTION>(lpData.m_pData))->lpDescription; } return bSuccess; }
BOOL CEnumerateSerial::UsingEnumPorts(CSimpleArray<UINT>& ports) #endif { //Make sure we clear out any elements which may already be in the array #if defined CENUMERATESERIAL_USE_STL ports.clear(); #else ports.RemoveAll(); #endif //Call the first time to determine the size of the buffer to allocate DWORD cbNeeded = 0; DWORD dwPorts = 0; EnumPorts(NULL, 1, NULL, 0, &cbNeeded, &dwPorts); //What will be the return value BOOL bSuccess = FALSE; //Allocate the buffer and recall ATL::CHeapPtr<BYTE> pPorts; if (pPorts.Allocate(cbNeeded)) { bSuccess = EnumPorts(NULL, 1, pPorts, cbNeeded, &cbNeeded, &dwPorts); if (bSuccess) { PORT_INFO_1* pPortInfo = reinterpret_cast<PORT_INFO_1*>(pPorts.m_pData); for (DWORD i=0; i<dwPorts; i++) { //If it looks like "COMX" then //add it to the array which will be returned size_t nLen = _tcslen(pPortInfo->pName); if (nLen > 3) { if ((_tcsnicmp(pPortInfo->pName, _T("COM"), 3) == 0) && IsNumeric(&(pPortInfo->pName[3]), TRUE)) { //Work out the port number int nPort = _ttoi(&(pPortInfo->pName[3])); #if defined CENUMERATESERIAL_USE_STL ports.push_back(nPort); #else ports.Add(nPort); #endif } } pPortInfo++; } } } else SetLastError(ERROR_OUTOFMEMORY); return bSuccess; }
BOOL CNTScmService::QueryRequiredPrivileges(CNTServiceStringArray& privileges) const { //Validate our parameters ATLASSERT(m_hService != NULL); //Empty our the array #ifdef CNTSERVICE_MFC_EXTENSIONS privileges.RemoveAll(); #else privileges.clear(); #endif //Check to see if the function pointer is available if (m_lpfnQueryServiceConfig2 == NULL) { ATLTRACE(_T("CNTScmService::QueryRequiredPrivileges, QueryServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n")); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } //Call through the function pointer DWORD dwBytesNeeded = 0; BOOL bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, NULL, 0, &dwBytesNeeded); if (!bSuccess && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { //Allocate some memory for the API ATL::CHeapPtr<BYTE> lpBuffer; if (!lpBuffer.Allocate(dwBytesNeeded)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } bSuccess = m_lpfnQueryServiceConfig2(m_hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, lpBuffer, dwBytesNeeded, &dwBytesNeeded); if (bSuccess) { LPTSTR lpszStrings = reinterpret_cast<LPTSTR>(lpBuffer.m_pData); while (lpszStrings[0] != 0) { #ifdef CNTSERVICE_MFC_EXTENSIONS privileges.Add(lpszStrings); #else privileges.push_back(lpszStrings); #endif lpszStrings += (_tcslen(lpszStrings ) + 1); } } } return bSuccess; }
BOOL CNTScmService::ChangeRequiredPrivileges(const CStringArray& privileges) { //Validate our parameters ASSERT(m_hService != NULL); //Check to see if the function pointer is available if (m_lpfnChangeServiceConfig2 == NULL) { TRACE(_T("CNTScmService::ChangeRequiredPrivileges, ChangeServiceConfig2 function is not supported on this OS. You need to be running at least Windows Vista / Windows 2008 to use this function\n")); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } //Work out the size of the buffer we will need DWORD dwSize = 0; INT_PTR nStrings = privileges.GetSize(); for (INT_PTR i=0; i<nStrings; i++) dwSize += privileges.GetAt(i).GetLength() + 1; //1 extra for each NULL terminator //Need one second NULL for the double NULL at the end dwSize++; //Allocate some memory for the API ATL::CHeapPtr<TCHAR> lpBuffer; if (!lpBuffer.Allocate(dwSize)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } //Now copy the strings into the buffer int nCurOffset = 0; LPTSTR lpszString = lpBuffer.m_pData; for (INT_PTR i=0; i<nStrings; i++) { CString sText = privileges.GetAt(i); int nCurrentStringLength = sText.GetLength(); _tcscpy_s(&lpszString[nCurOffset], nCurrentStringLength+1, sText); nCurOffset += (nCurrentStringLength + 1); } //Don't forgot to doubly NULL terminate lpszString[nCurOffset] = _T('\0'); //Call through the function pointer SERVICE_REQUIRED_PRIVILEGES_INFO srpi; srpi.pmszRequiredPrivileges = lpBuffer.m_pData; return m_lpfnChangeServiceConfig2(m_hService, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, &srpi); }
BOOL ComPortDiscovery::QueryDeviceDescription(HDEVINFO hDevInfoSet, SP_DEVINFO_DATA& devInfo, ATL::CHeapPtr<BYTE>& byFriendlyName) { DWORD dwType = 0; DWORD dwSize = 0; //Query initially to get the buffer size required if (!SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, NULL, 0, &dwSize)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; } #pragma warning(suppress: 6102) if (!byFriendlyName.Allocate(dwSize)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } return SetupDiGetDeviceRegistryProperty(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, byFriendlyName.m_pData, dwSize, &dwSize) && (dwType == REG_SZ); }
BOOL CNTServiceControlManager::EnumServices(DWORD dwServiceType, DWORD dwServiceState, LPCTSTR pszGroupName, void* pUserData, ENUM_SERVICES_PROC2 lpEnumServicesFunc) const { //Check to see if the function pointer is available if (m_lpfnEnumServicesStatusEx == NULL) { ATLTRACE(_T("CNTServiceControlManager::EnumServices, EnumServicesStatusEx function is not supported on this OS. You need to be running at least Windows 2000 to use this function\n")); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } DWORD dwBytesNeeded; DWORD dwServices; DWORD dwResumeHandle = 0; BOOL bSuccess = m_lpfnEnumServicesStatusEx(m_hSCM, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, NULL, 0, &dwBytesNeeded, &dwServices, &dwResumeHandle, pszGroupName); if (!bSuccess && GetLastError() == ERROR_MORE_DATA) { //Allocate some memory for the API ATL::CHeapPtr<BYTE> lpBuffer; if (!lpBuffer.Allocate(dwBytesNeeded)) { SetLastError(ERROR_OUTOFMEMORY); return FALSE; } LPENUM_SERVICE_STATUS_PROCESS lpServices = reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESS>(lpBuffer.m_pData); DWORD dwSize = 0; bSuccess = m_lpfnEnumServicesStatusEx(m_hSCM, SC_ENUM_PROCESS_INFO, dwServiceType, dwServiceState, reinterpret_cast<LPBYTE>(lpServices), dwBytesNeeded, &dwSize, &dwServices, &dwResumeHandle, pszGroupName); if (bSuccess) { BOOL bContinue = TRUE; for (DWORD i=0; i<dwServices && bContinue; i++) bContinue = lpEnumServicesFunc(pUserData, lpServices[i]); } } return bSuccess; }
BOOL CEnumerateSerial::UsingRegistry(CSimpleArray<CString>& ports) #endif { //Make sure we clear out any elements which may already be in the array(s) ports.RemoveAll(); //What will be the return value BOOL bSuccess = FALSE; HKEY hSERIALCOMM; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS) { //Get the max value name and max value lengths DWORD dwMaxValueNameLen; DWORD dwMaxValueLen; DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL); if (dwQueryInfo == ERROR_SUCCESS) { DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1; //Include space for the NULL terminator DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars * sizeof(TCHAR); DWORD dwMaxValueDataSizeInChars = dwMaxValueLen/sizeof(TCHAR) + 1; //Include space for the NULL terminator DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars * sizeof(TCHAR); //Allocate some space for the value name and value data ATL::CHeapPtr<TCHAR> szValueName; ATL::CHeapPtr<BYTE> byValue; if (szValueName.Allocate(dwMaxValueNameSizeInChars) && byValue.Allocate(dwMaxValueDataSizeInBytes)) { bSuccess = TRUE; //Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM DWORD dwIndex = 0; DWORD dwType; DWORD dwValueNameSize = dwMaxValueNameSizeInChars; DWORD dwDataSize = dwMaxValueDataSizeInBytes; memset(szValueName.m_pData, 0, dwMaxValueNameSizeInBytes); memset(byValue.m_pData, 0, dwMaxValueDataSizeInBytes); LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, byValue, &dwDataSize); while (nEnum == ERROR_SUCCESS) { //If the value is of the correct type, then add it to the array if (dwType == REG_SZ) { TCHAR* szPort = reinterpret_cast<TCHAR*>(byValue.m_pData); ports.Add(szPort); } //Prepare for the next time around dwValueNameSize = dwMaxValueNameSizeInChars; dwDataSize = dwMaxValueDataSizeInBytes; memset(szValueName.m_pData, 0, dwMaxValueNameSizeInBytes); memset(byValue.m_pData, 0, dwMaxValueDataSizeInBytes); ++dwIndex; nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, byValue, &dwDataSize); } } else SetLastError(ERROR_OUTOFMEMORY); } //Close the registry key now that we are finished with it RegCloseKey(hSERIALCOMM); if (dwQueryInfo != ERROR_SUCCESS) SetLastError(dwQueryInfo); } return bSuccess; }
BOOL CEnumerateSerial::UsingComDB(CSimpleArray<UINT>& ports) #endif { //Make sure we clear out any elements which may already be in the array(s) ports.RemoveAll(); //What will be the return value BOOL bSuccess = FALSE; //Used to preserve the last error value DWORD dwLastError = ERROR_SUCCESS; //Get the function pointers to "ComDBOpen", "ComDBClose" & "ComDBGetCurrentPortUsage" in msports.dll HINSTANCE hMSPorts = LoadLibrary(_T("MSPORTS.DLL")); if (hMSPorts == NULL) return FALSE; COMDBOPEN* lpfnLPCOMDBOPEN = reinterpret_cast<COMDBOPEN*>(GetProcAddress(hMSPorts, "ComDBOpen")); COMDBCLOSE* lpfnLPCOMDBCLOSE = reinterpret_cast<COMDBCLOSE*>(GetProcAddress(hMSPorts, "ComDBClose")); COMDBGETCURRENTPORTUSAGE* lpfnCOMDBGETCURRENTPORTUSAGE = reinterpret_cast<COMDBGETCURRENTPORTUSAGE*>(GetProcAddress(hMSPorts, "ComDBGetCurrentPortUsage")); if ((lpfnLPCOMDBOPEN != NULL) && (lpfnLPCOMDBCLOSE != NULL) && (lpfnCOMDBGETCURRENTPORTUSAGE != NULL)) { //First need to open up the DB HCOMDB hComDB; DWORD dwComOpen = lpfnLPCOMDBOPEN(&hComDB); if (dwComOpen == ERROR_SUCCESS) { //Work out the size of the buffer required DWORD dwMaxPortsReported = 0; DWORD dwPortUsage = lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, NULL, 0, CDB_REPORT_BYTES, &dwMaxPortsReported); if (dwPortUsage == ERROR_SUCCESS) { //Allocate some heap space and recall the function ATL::CHeapPtr<BYTE> portBytes; if (portBytes.Allocate(dwMaxPortsReported)) { bSuccess = TRUE; if (lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, portBytes, dwMaxPortsReported, CDB_REPORT_BYTES, &dwMaxPortsReported) == ERROR_SUCCESS) { //Work thro the byte bit array for ports which are in use for (DWORD i=0; i<dwMaxPortsReported; i++) { if (portBytes[i]) ports.Add(i + 1); } } } else SetLastError(ERROR_OUTOFMEMORY); } else dwLastError = dwPortUsage; //Close the DB lpfnLPCOMDBCLOSE(hComDB); } else dwLastError = dwComOpen; } else SetLastError(ERROR_CALL_NOT_IMPLEMENTED); //Unload the msports dll FreeLibrary(hMSPorts); //Reinstate the last error if (dwLastError) SetLastError(dwLastError); return bSuccess; }
BOOL CEnumerateSerial::UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& sFriendlyNames) #endif { //Make sure we clear out any elements which may already be in the array(s) ports.RemoveAll(); sFriendlyNames.RemoveAll(); //Get the function pointers to "SetupDiGetClassDevs", "SetupDiGetClassDevs", "SetupDiEnumDeviceInfo", "SetupDiOpenDevRegKey" //and "SetupDiDestroyDeviceInfoList" in setupapi.dll HINSTANCE hSetupAPI = LoadLibrary(_T("SETUPAPI.DLL")); if (hSetupAPI == NULL) return FALSE; SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(hSetupAPI, "SetupDiOpenDevRegKey")); #ifdef _UNICODE SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(hSetupAPI, "SetupDiClassGuidsFromNameW")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(hSetupAPI, "SetupDiGetClassDevsW")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyW")); #else SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(hSetupAPI, "SetupDiClassGuidsFromNameA")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(hSetupAPI, "SetupDiGetClassDevsA")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(hSetupAPI, "SetupDiGetDeviceRegistryPropertyA")); #endif SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(hSetupAPI, "SetupDiDestroyDeviceInfoList")); SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(hSetupAPI, "SetupDiEnumDeviceInfo")); if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) || (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL)) { //Unload the setup dll FreeLibrary(hSetupAPI); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName DWORD dwGuids = 0; lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids); if (dwGuids == 0) { DWORD dwLastError = GetLastError(); //Unload the setup dll FreeLibrary(hSetupAPI); SetLastError(dwLastError); return FALSE; } //Allocate the needed memory ATL::CHeapPtr<GUID> pGuids; if (!pGuids.Allocate(dwGuids)) { //Unload the setup dll FreeLibrary(hSetupAPI); SetLastError(ERROR_OUTOFMEMORY); return FALSE; } //Call the function again if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids)) { DWORD dwLastError = GetLastError(); //Unload the setup dll FreeLibrary(hSetupAPI); SetLastError(dwLastError); return FALSE; } //Now create a "device information set" which is required to enumerate all the ports HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT); if (hDevInfoSet == INVALID_HANDLE_VALUE) { DWORD dwLastError = GetLastError(); //Unload the setup dll FreeLibrary(hSetupAPI); SetLastError(dwLastError); return FALSE; } //Finally do the enumeration BOOL bMoreItems = TRUE; int nIndex = 0; SP_DEVINFO_DATA devInfo; while (bMoreItems) { //Enumerate the current device devInfo.cbSize = sizeof(SP_DEVINFO_DATA); bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo); if (bMoreItems) { //Did we find a serial port for this device BOOL bAdded = FALSE; //Get the registry key which stores the ports settings HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (hDeviceKey) { //Read in the name of the port TCHAR pszPortName[256]; DWORD dwSize = sizeof(pszPortName); DWORD dwType = 0; if ((RegQueryValueEx(hDeviceKey, _T("PortName"), NULL, &dwType, reinterpret_cast<LPBYTE>(pszPortName), &dwSize) == ERROR_SUCCESS) && (dwType == REG_SZ)) { //If it looks like "COMX" then //add it to the array which will be returned size_t nLen = _tcslen(pszPortName); if (nLen > 3) { if ((_tcsnicmp(pszPortName, _T("COM"), 3) == 0) && IsNumeric(&pszPortName[3], FALSE)) { //Work out the port number int nPort = _ttoi(&pszPortName[3]); ports.Add(nPort); bAdded = TRUE; } } } //Close the key now that we are finished with it RegCloseKey(hDeviceKey); } //If the port was a serial port, then also try to get its friendly name if (bAdded) { TCHAR pszFriendlyName[256]; DWORD dwSize = sizeof(pszFriendlyName); DWORD dwType = 0; if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(pszFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ)) sFriendlyNames.Add(pszFriendlyName); else sFriendlyNames.Add(_T("")); } } ++nIndex; } //Free up the "device information set" now that we are finished with it lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet); //Unload the setup dll FreeLibrary(hSetupAPI); //Return the success indicator return TRUE; }
BOOL CEnumerateSerial::UsingQueryDosDevice(CSimpleArray<UINT>& ports) #endif { //What will be the return value from this function (assume the worst) BOOL bSuccess = FALSE; //Make sure we clear out any elements which may already be in the array ports.RemoveAll(); //Determine what OS we are running on OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); BOOL bGetVer = GetVersionEx(&osvi); //On NT use the QueryDosDevice API if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)) { //Use QueryDosDevice to look for all devices of the form COMx. Since QueryDosDevice does //not consitently report the required size of buffer, lets start with a reasonable buffer size //of 4096 characters and go from there int nChars = 4096; BOOL bWantStop = FALSE; while (nChars && !bWantStop) { ATL::CHeapPtr<TCHAR> szDevices; if (szDevices.Allocate(nChars)) { DWORD dwChars = QueryDosDevice(NULL, szDevices, nChars); if (dwChars == 0) { DWORD dwError = GetLastError(); if (dwError == ERROR_INSUFFICIENT_BUFFER) { //Expand the buffer and loop around again nChars *= 2; } else bWantStop = TRUE; } else { bSuccess = TRUE; bWantStop = TRUE; size_t i=0; while (szDevices[i] != _T('\0')) { //Get the current device name TCHAR* pszCurrentDevice = &szDevices[i]; //If it looks like "COMX" then //add it to the array which will be returned size_t nLen = _tcslen(pszCurrentDevice); if (nLen > 3) { if ((_tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0) && IsNumeric(&pszCurrentDevice[3], FALSE)) { //Work out the port number int nPort = _ttoi(&pszCurrentDevice[3]); ports.Add(nPort); } } //Go to next device name i += (nLen + 1); } } } else { bWantStop = TRUE; SetLastError(ERROR_OUTOFMEMORY); } } } else SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return bSuccess; }
BOOL CEnumerateSerial::UsingSetupAPI2(CSimpleArray<UINT>& ports, CSimpleArray<CString>& friendlyNames) #endif { //Make sure we clear out any elements which may already be in the array(s) #if defined CENUMERATESERIAL_USE_STL ports.clear(); friendlyNames.clear(); #else ports.RemoveAll(); friendlyNames.RemoveAll(); #endif //Get the function pointers to "SetupDiGetClassDevs", "SetupDiGetClassDevs", "SetupDiEnumDeviceInfo", "SetupDiOpenDevRegKey" //and "SetupDiDestroyDeviceInfoList" in setupapi.dll CAutoHModule setupAPI(LoadLibraryFromSystem32(_T("SETUPAPI.DLL"))); if (setupAPI == NULL) return FALSE; SETUPDIOPENDEVREGKEY* lpfnLPSETUPDIOPENDEVREGKEY = reinterpret_cast<SETUPDIOPENDEVREGKEY*>(GetProcAddress(setupAPI, "SetupDiOpenDevRegKey")); #if defined _UNICODE SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameW")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsW")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyW")); #else SETUPDICLASSGUIDSFROMNAME* lpfnSETUPDICLASSGUIDSFROMNAME = reinterpret_cast<SETUPDICLASSGUIDSFROMNAME*>(GetProcAddress(setupAPI, "SetupDiClassGuidsFromNameA")); SETUPDIGETCLASSDEVS* lpfnSETUPDIGETCLASSDEVS = reinterpret_cast<SETUPDIGETCLASSDEVS*>(GetProcAddress(setupAPI, "SetupDiGetClassDevsA")); SETUPDIGETDEVICEREGISTRYPROPERTY* lpfnSETUPDIGETDEVICEREGISTRYPROPERTY = reinterpret_cast<SETUPDIGETDEVICEREGISTRYPROPERTY*>(GetProcAddress(setupAPI, "SetupDiGetDeviceRegistryPropertyA")); #endif SETUPDIDESTROYDEVICEINFOLIST* lpfnSETUPDIDESTROYDEVICEINFOLIST = reinterpret_cast<SETUPDIDESTROYDEVICEINFOLIST*>(GetProcAddress(setupAPI, "SetupDiDestroyDeviceInfoList")); SETUPDIENUMDEVICEINFO* lpfnSETUPDIENUMDEVICEINFO = reinterpret_cast<SETUPDIENUMDEVICEINFO*>(GetProcAddress(setupAPI, "SetupDiEnumDeviceInfo")); if ((lpfnLPSETUPDIOPENDEVREGKEY == NULL) || (lpfnSETUPDICLASSGUIDSFROMNAME == NULL) || (lpfnSETUPDIDESTROYDEVICEINFOLIST == NULL) || (lpfnSETUPDIENUMDEVICEINFO == NULL) || (lpfnSETUPDIGETCLASSDEVS == NULL) || (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY == NULL)) { //Set the error to report setupAPI.m_dwError = ERROR_CALL_NOT_IMPLEMENTED; return FALSE; } //First need to convert the name "Ports" to a GUID using SetupDiClassGuidsFromName DWORD dwGuids = 0; lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), NULL, 0, &dwGuids); if (dwGuids == 0) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Allocate the needed memory ATL::CHeapPtr<GUID> pGuids; if (!pGuids.Allocate(dwGuids)) { //Set the error to report setupAPI.m_dwError = ERROR_OUTOFMEMORY; return FALSE; } //Call the function again if (!lpfnSETUPDICLASSGUIDSFROMNAME(_T("Ports"), pGuids, dwGuids, &dwGuids)) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Now create a "device information set" which is required to enumerate all the ports HDEVINFO hDevInfoSet = lpfnSETUPDIGETCLASSDEVS(pGuids, NULL, NULL, DIGCF_PRESENT); if (hDevInfoSet == INVALID_HANDLE_VALUE) { //Set the error to report setupAPI.m_dwError = GetLastError(); return FALSE; } //Finally do the enumeration BOOL bMoreItems = TRUE; int nIndex = 0; SP_DEVINFO_DATA devInfo; while (bMoreItems) { //Enumerate the current device devInfo.cbSize = sizeof(SP_DEVINFO_DATA); bMoreItems = lpfnSETUPDIENUMDEVICEINFO(hDevInfoSet, nIndex, &devInfo); if (bMoreItems) { //Did we find a serial port for this device BOOL bAdded = FALSE; //Get the registry key which stores the ports settings HKEY hDeviceKey = lpfnLPSETUPDIOPENDEVREGKEY(hDevInfoSet, &devInfo, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (hDeviceKey) { int nPort = 0; if (QueryRegistryPortName(hDeviceKey, nPort)) { #if defined CENUMERATESERIAL_USE_STL ports.push_back(nPort); #else ports.Add(nPort); #endif bAdded = TRUE; } //Close the key now that we are finished with it RegCloseKey(hDeviceKey); } //If the port was a serial port, then also try to get its friendly name if (bAdded) { TCHAR szFriendlyName[1024]; szFriendlyName[0] = _T('\0'); DWORD dwSize = sizeof(szFriendlyName); DWORD dwType = 0; if (lpfnSETUPDIGETDEVICEREGISTRYPROPERTY(hDevInfoSet, &devInfo, SPDRP_DEVICEDESC, &dwType, reinterpret_cast<PBYTE>(szFriendlyName), dwSize, &dwSize) && (dwType == REG_SZ)) { #if defined CENUMERATESERIAL_USE_STL friendlyNames.push_back(szFriendlyName); #else friendlyNames.Add(szFriendlyName); #endif } else { #if defined CENUMERATESERIAL_USE_STL friendlyNames.push_back(_T("")); #else friendlyNames.Add(_T("")); #endif } } } ++nIndex; } //Free up the "device information set" now that we are finished with it lpfnSETUPDIDESTROYDEVICEINFOLIST(hDevInfoSet); //Return the success indicator return TRUE; }
BOOL CEnumerateSerial::UsingComDB(CSimpleArray<UINT>& ports) #endif { //Make sure we clear out any elements which may already be in the array(s) #if defined CENUMERATESERIAL_USE_STL ports.clear(); #else ports.RemoveAll(); #endif //What will be the return value from this function (assume the worst) BOOL bSuccess = FALSE; //Get the function pointers to "ComDBOpen", "ComDBClose" & "ComDBGetCurrentPortUsage" in msports.dll CAutoHModule msPorts(LoadLibraryFromSystem32(_T("MSPORTS.DLL"))); if (msPorts == NULL) return FALSE; COMDBOPEN* lpfnLPCOMDBOPEN = reinterpret_cast<COMDBOPEN*>(GetProcAddress(msPorts, "ComDBOpen")); COMDBCLOSE* lpfnLPCOMDBCLOSE = reinterpret_cast<COMDBCLOSE*>(GetProcAddress(msPorts, "ComDBClose")); COMDBGETCURRENTPORTUSAGE* lpfnCOMDBGETCURRENTPORTUSAGE = reinterpret_cast<COMDBGETCURRENTPORTUSAGE*>(GetProcAddress(msPorts, "ComDBGetCurrentPortUsage")); if ((lpfnLPCOMDBOPEN != NULL) && (lpfnLPCOMDBCLOSE != NULL) && (lpfnCOMDBGETCURRENTPORTUSAGE != NULL)) { //First need to open up the DB HCOMDB hComDB; DWORD dwComOpen = lpfnLPCOMDBOPEN(&hComDB); if (dwComOpen == ERROR_SUCCESS) { //Work out the size of the buffer required DWORD dwMaxPortsReported = 0; DWORD dwPortUsage = lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, NULL, 0, CDB_REPORT_BYTES, &dwMaxPortsReported); if (dwPortUsage == ERROR_SUCCESS) { //Allocate some heap space and recall the function ATL::CHeapPtr<BYTE> portBytes; if (portBytes.Allocate(dwMaxPortsReported)) { bSuccess = TRUE; if (lpfnCOMDBGETCURRENTPORTUSAGE(hComDB, portBytes, dwMaxPortsReported, CDB_REPORT_BYTES, &dwMaxPortsReported) == ERROR_SUCCESS) { //Work thro the byte bit array for ports which are in use for (DWORD i=0; i<dwMaxPortsReported; i++) { if (portBytes[i]) { #if defined CENUMERATESERIAL_USE_STL ports.push_back(i + 1); #else ports.Add(i + 1); #endif } } } } else msPorts.m_dwError = ERROR_OUTOFMEMORY; } else msPorts.m_dwError = dwPortUsage; //Close the DB lpfnLPCOMDBCLOSE(hComDB); } else msPorts.m_dwError = dwComOpen; } else msPorts.m_dwError = ERROR_CALL_NOT_IMPLEMENTED; return bSuccess; }
BOOL CNTEventLogSource::SetStringArrayIntoRegistry(ATL::CRegKey& key, LPCTSTR lpszEntry, const CNTServiceStringArray& array, DWORD* pLastError) { //Validate our input parameters ATLASSERT(lpszEntry != NULL); //Work out the size of the buffer we will need #ifdef CNTSERVICE_MFC_EXTENSIONS int nSize = 0; INT_PTR nStrings = array.GetSize(); for (INT_PTR i=0; i<nStrings; i++) nSize += array.GetAt(i).GetLength() + 1; //1 extra for each NULL terminator #else CNTServiceStringArray::size_type nSize = 0; CNTServiceStringArray::size_type nStrings = array.size(); for (CNTServiceStringArray::size_type i=0; i<nStrings; i++) nSize += array[i].length() + 1; //1 extra for each NULL terminator #endif //Need one second NULL for the double NULL at the end nSize++; //Allocate some memory for the API ATL::CHeapPtr<TCHAR> lpBuffer; if (!lpBuffer.Allocate(nSize)) { SetLastError(ERROR_OUTOFMEMORY); if (pLastError) *pLastError = ERROR_OUTOFMEMORY; return FALSE; } //Now copy the strings into the buffer LPTSTR lpszString = lpBuffer.m_pData; #ifdef CNTSERVICE_MFC_EXTENSIONS int nCurOffset = 0; for (INT_PTR i=0; i<nStrings; i++) #else CNTServiceStringArray::size_type nCurOffset = 0; for (CNTServiceStringArray::size_type i=0; i<nStrings; i++) #endif { const CNTServiceString& sText = array[i]; #ifdef CNTSERVICE_MFC_EXTENSIONS int nCurrentStringLength = sText.GetLength(); _tcscpy_s(&lpszString[nCurOffset], nCurrentStringLength+1, sText); #else CNTServiceString::size_type nCurrentStringLength = sText.length(); _tcscpy_s(&lpszString[nCurOffset], nCurrentStringLength+1, sText.c_str()); #endif nCurOffset += (nCurrentStringLength + 1); } //Don't forgot to doubly NULL terminate lpszString[nCurOffset] = _T('\0'); //Finally write it into the registry LONG lResult = key.SetMultiStringValue(lpszEntry, lpBuffer); BOOL bSuccess = (lResult == ERROR_SUCCESS); if (!bSuccess && pLastError) *pLastError = lResult; return bSuccess; }
BOOL CNTEventLogSource::GetStringArrayFromRegistry(ATL::CRegKey& key, LPCTSTR lpszEntry, CNTServiceStringArray& array, DWORD* pLastError) { //Validate our parameters ATLASSERT(lpszEntry != NULL); //What will be the return value from this function, assume the worst BOOL bSuccess = FALSE; //Empty the array before we go any further #ifdef CNTSERVICE_MFC_EXTENSIONS array.RemoveAll(); #else array.clear(); #endif DWORD dwType = 0; ULONG nBytes = 0; LONG lResult = key.QueryValue(lpszEntry, &dwType, NULL, &nBytes); if (lResult == ERROR_SUCCESS) { //Allocate some memory for the API ATL::CHeapPtr<TCHAR> lpBuffer; ULONG nChars = nBytes / sizeof(TCHAR); if (nChars < 2) //Ensure we can handle an empty MULTI_SZ string nChars = 2; if (!lpBuffer.Allocate(nChars)) { SetLastError(ERROR_OUTOFMEMORY); if (pLastError) *pLastError = ERROR_OUTOFMEMORY; return FALSE; } lResult = key.QueryMultiStringValue(lpszEntry, lpBuffer, &nChars); if (lResult == ERROR_SUCCESS) { LPTSTR lpszStrings = lpBuffer.m_pData; while (lpszStrings[0] != 0) { #ifdef CNTSERVICE_MFC_EXTENSIONS array.Add(lpszStrings); #else array.push_back(lpszStrings); #endif lpszStrings += (_tcslen(lpszStrings) + 1); } bSuccess = TRUE; } else { if (pLastError) *pLastError = lResult; } } else { if (pLastError) *pLastError = lResult; } return bSuccess; }