/******************************************************************** Copyright (c) 1999 Microsoft Corporation Module Name: PCH_DeviceDriver.CPP Abstract: WBEM provider class implementation for PCH_DeviceDriver class Revision History: Ghim-Sim Chua (gschua) 04/27/99 - Created ********************************************************************/ #include "pchealth.h" #include "confgmgr.h" #include "PCH_DeviceDriver.h" #include "cregcls.h" #define MAX_ARRAY 100 ///////////////////////////////////////////////////////////////////////////// // tracing stuff #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile #define TRACE_ID DCID_DEVICEDRIVER CPCH_DeviceDriver MyPCH_DeviceDriverSet (PROVIDER_NAME_PCH_DEVICEDRIVER, PCH_NAMESPACE) ; // Property names //=============== const static WCHAR* pTimeStamp = L"TimeStamp" ; const static WCHAR* pChange = L"Change" ; const static WCHAR* pDate = L"Date" ; const static WCHAR* pFilename = L"Filename" ; const static WCHAR* pManufacturer = L"Manufacturer" ; const static WCHAR* pName = L"Name" ; const static WCHAR* pSize = L"Size" ; const static WCHAR* pVersion = L"Version" ; /***************************************************************************** * * FUNCTION : CPCH_DeviceDriver::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * * INPUTS : A pointer to the MethodContext for communication with WinMgmt. * A long that contains the flags described in * IWbemServices::CreateInstanceEnumAsync. Note that the following * flags are handled by (and filtered out by) WinMgmt: * WBEM_FLAG_DEEP * WBEM_FLAG_SHALLOW * WBEM_FLAG_RETURN_IMMEDIATELY * WBEM_FLAG_FORWARD_ONLY * WBEM_FLAG_BIDIRECTIONAL * * RETURNS : WBEM_S_NO_ERROR if successful * * COMMENTS : TO DO: All instances on the machine should be returned here. * If there are no instances, return WBEM_S_NO_ERROR. * It is not an error to have no instances. * *****************************************************************************/ HRESULT CPCH_DeviceDriver::EnumerateInstances( MethodContext* pMethodContext, long lFlags ) { TraceFunctEnter("CPCH_DeviceDriver::EnumerateInstances"); CConfigManager cfgManager; CDeviceCollection deviceList; HRESULT hRes = WBEM_S_NO_ERROR; if ( cfgManager.GetDeviceList( deviceList ) ) { REFPTR_POSITION pos; if ( deviceList.BeginEnum( pos ) ) { try { CConfigMgrDevice *pDevice = NULL; // Walk the list while ( (NULL != ( pDevice = deviceList.GetNext( pos ) ) ) ) { try { CHString chstrVar; // Driver if (pDevice->GetDriver(chstrVar)) { // Get device driver info (void)CreateDriverInstances(chstrVar, pDevice, pMethodContext); } } catch(...) { // GetNext() AddRefs pDevice->Release(); throw; } // GetNext() AddRefs pDevice->Release(); } } catch(...) { // Always call EndEnum(). For all Beginnings, there must be an End deviceList.EndEnum(); throw; } // Always call EndEnum(). For all Beginnings, there must be an End deviceList.EndEnum(); } } TraceFunctLeave(); return hRes ; // pInstance->SetVariant(pTimeStamp, ); // pInstance->SetVariant(pChange, ); // pInstance->SetVariant(pDate, ); // pInstance->SetVariant(pFilename, ); // pInstance->SetVariant(pManufacturer, ); // pInstance->SetVariant(pName, ); // pInstance->SetVariant(pSize, ); // pInstance->SetVariant(pVersion, ); } // // QualifyInfFile will find where the inf file is located, in specific // sections // BOOL QualifyInfFile(CHString chstrInfFile, CHString &chstrInfFileQualified) { USES_CONVERSION; TCHAR strWinDir[MAX_PATH]; if (GetWindowsDirectory(strWinDir, MAX_PATH)) { // check if the file exists in %windir%\inf CHString chstrFullPath(strWinDir); chstrFullPath += "\\inf\\"; chstrFullPath += chstrInfFile; // test for presence of the file HANDLE hFile = CreateFile(W2A((LPCWSTR)chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // if found, then return with value if (hFile != INVALID_HANDLE_VALUE) { chstrInfFileQualified = chstrFullPath; CloseHandle(hFile); return TRUE; } // check if the file exists in %windir%\inf\other chstrFullPath = strWinDir; chstrFullPath += "\\inf\\other\\"; chstrFullPath += chstrInfFile; // test for presence of the file hFile = CreateFile(W2A((LPCWSTR)chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // if found, then return with value if (hFile != INVALID_HANDLE_VALUE) { chstrInfFileQualified = chstrFullPath; CloseHandle(hFile); return TRUE; } } return FALSE; } BOOL TestFile(LPCTSTR chstrPath1, LPCTSTR chstrPath2, LPCTSTR chstrPath3, CHString &chstrFullPath) { USES_CONVERSION; // concatenate all parts of the path chstrFullPath = chstrPath1; chstrFullPath += chstrPath2; chstrFullPath += chstrPath3; // test for presence of the file HANDLE hFile = CreateFile(W2A(chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // if found, then return with value if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); return TRUE; } return FALSE; } // // QualifyDriverFile will find where the driver file is located, in specific // sections // BOOL QualifyDriverFile(CHString chstrInfFile, CHString &chstrInfFileQualified) { TCHAR strWinDir[MAX_PATH]; TCHAR strSysDir[MAX_PATH]; USES_CONVERSION; char * szInfFile = W2A(chstrInfFile); // Check in Windows Directory if (GetWindowsDirectory(strWinDir, MAX_PATH)) { // check to see if it exists in %windir% if (TestFile(strWinDir, "\\", szInfFile, chstrInfFileQualified)) return TRUE; // check to see if it exists in %windir%\system32 if (TestFile(strWinDir, "\\System32\\", szInfFile, chstrInfFileQualified)) return TRUE; // check if the file exists in %windir%\system32\drivers if (TestFile(strWinDir, "\\system32\\drivers\\", szInfFile, chstrInfFileQualified)) return TRUE; } // check in System Directory if (GetSystemDirectory(strSysDir, MAX_PATH)) { // check to see if it exists in %sysdir% if (TestFile(strSysDir, "\\", szInfFile, chstrInfFileQualified)) return TRUE; // check to see if it exists in %sysdir%\iosubsys if (TestFile(strSysDir, "\\iosubsys\\", szInfFile, chstrInfFileQualified)) return TRUE; // check to see if it exists in %sysdir%\vmm32 if (TestFile(strSysDir, "\\vmm32\\", szInfFile, chstrInfFileQualified)) return TRUE; } return FALSE; } /***************************************************************************** * * FUNCTION : CPCH_DeviceDriver::CreateDriverInstances * * DESCRIPTION : Creates all the device driver instances given the driver name * * RETURNS : WBEM_S_NO_ERROR if successful * * * How drivers are obtained from the registry and inf files : * * In the reg hive HKLM\System\CurrentControlSet\Services\Class, each device will have a subkey. * In each device subkey, there are two values InfPath and InfSection. In the specified InfPath * and InfSection, the drivers are stored in the following fashion : * * // sample.inf * * [InfSection] * CopyFiles = Subsection1, Subsection2..... * * [Subsection1] * xxx.dll * yyy.vxd * zzz.sys * * [Subsection2] * aaa.dll * bbb.vxd * zzz.sys * * Plus, there are other values for each different device which may contain driver information : * * ALL : PortDriver * Display : drv, minivdd (extra level deep : default) * Net : DeviceVxDs * Ports : PortDriver, ConfigDialog * Media : Driver * * *****************************************************************************/ HRESULT CPCH_DeviceDriver::CreateDriverInstances( CHString chstrDriverName, CConfigMgrDevice* pDevice, MethodContext* pMethodContext ) { TraceFunctEnter("CPCH_DeviceDriver::EnumerateInstances"); HRESULT hRes = WBEM_S_NO_ERROR; CComVariant varValue; CRegistry Reg; int iDel; CHString chstrInfFileQualified; CHString chstrInfSection; TCHAR strCopyFiles[MAX_PATH]; LPTSTR apstrCopyFileArray[MAX_ARRAY]; LPTSTR apstrDriverArray[MAX_ARRAY]; int iDriverIndex; int iCountDriver; int iCountCopyFile; int iIndex; // create the device key CHString strDeviceKey("SYSTEM\\CurrentControlSet\\SERVICES\\Class\\"); strDeviceKey += chstrDriverName; // Get the date and time SYSTEMTIME stUTCTime; GetSystemTime(&stUTCTime); USES_CONVERSION; char * szInf; char * szInfFileQualified; // Get the inf filename CHString chstrInfFile; if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"InfPath", chstrInfFile) != ERROR_SUCCESS) goto End; if (!QualifyInfFile(chstrInfFile, chstrInfFileQualified)) goto End; // get the inf section if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"InfSection", chstrInfSection) != ERROR_SUCCESS) goto End; // get the subsections to be expanded szInf = W2A(chstrInfSection); szInfFileQualified = W2A(chstrInfFileQualified); GetPrivateProfileString(szInf, "CopyFiles", "Error", strCopyFiles, MAX_PATH, szInfFileQualified); if (!_tcscmp("Error", strCopyFiles)) goto End; // add the default driver to the driver array iCountDriver = DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriverName, ",", apstrDriverArray, MAX_ARRAY); // count number of files to look at iCountCopyFile = DelimitedStringToArray(strCopyFiles, ",", apstrCopyFileArray, MAX_ARRAY); // loop through all subsections for (iIndex = 0; iIndex < iCountCopyFile; iIndex++) { // get all drivers in the subsection TCHAR strDriver[MAX_PATH * MAX_ARRAY]; if (0 < GetPrivateProfileSection(apstrCopyFileArray[iIndex], strDriver, MAX_PATH * MAX_ARRAY, szInfFileQualified)) { // string is delimited by NULL values so in order to work with the // DelimitedStringToArray function, we'll replace it with something else int iCIndex = 0; while (!((strDriver[iCIndex] == '\0') && (strDriver[iCIndex + 1] == '\0'))) { if (strDriver[iCIndex] == '\0') strDriver[iCIndex] = '%'; else // do some cleanup here if (!(_istalnum(strDriver[iCIndex])) && !(strDriver[iCIndex] == '.')) strDriver[iCIndex] = '\0'; iCIndex++; } iCountDriver += DelimitedStringToArray(strDriver, "%", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); // Scout around for more drivers in special keys CHString chstrExtraKey = strDeviceKey; chstrExtraKey += "\\default"; CHString chstrDriver; // special case for display and monitor if ((!wcsncmp(chstrDriverName, L"display", wcslen(L"display"))) || (!wcsncmp(chstrDriverName, L"monitor", wcslen(L"monitor")))) { // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\####\default for Drv values if (Reg.OpenLocalMachineKeyAndReadValue(chstrExtraKey, L"Drv", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\####\default for MiniVDD values if (Reg.OpenLocalMachineKeyAndReadValue(chstrExtraKey, L"MiniVDD", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } } // special case for net, nettrans, netclient, netservice if (!wcsncmp(chstrDriverName, L"net", wcslen(L"net"))) { // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for DeviceVxDs values if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"DeviceVxDs", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } } // special case for ports if (!wcsncmp(chstrDriverName, L"ports", wcslen(L"ports"))) { // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for ConfigDialog values if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"ConfigDialog", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } } // special case for media if (!wcsncmp(chstrDriverName, L"media", wcslen(L"media"))) { // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for Driver values if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"Driver", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } } // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for PortDriver values if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"PortDriver", chstrDriver) == ERROR_SUCCESS) { // add the list of new driver to the driver array iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver); } } } // Clean up for (iDel = 0; iDel < iCountCopyFile; iDel++) delete [] apstrCopyFileArray[iDel]; // go through list of drivers and create the instances for (iDriverIndex = 0; iDriverIndex < iCountDriver; iDriverIndex++) { CHString chstrDriver(apstrDriverArray[iDriverIndex]); CHString chstrPath; // Check for duplicates BOOL bDup = FALSE; for (int iDup = 0; iDup < iDriverIndex; iDup++) { char * szDriver = W2A(chstrDriver); if (!_tcsicmp(szDriver, apstrDriverArray[iDup])) { bDup = TRUE; break; } } // if there exists a duplicate, skip it if (bDup) continue; // create instance CInstancePtr pInstance(CreateNewInstance(pMethodContext), false); try { // Timestamp if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime))) ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed."); // Snapshot if (!pInstance->SetCHString(pChange, L"Snapshot")) ErrorTrace(TRACE_ID, "SetCHString on Change Field failed."); // Name (key) // bug fix : should be name of device (foreign key), NOT driver name CHString chstrVar; if (pDevice->GetDeviceID(chstrVar)) if (!pInstance->SetCHString(pName, chstrVar)) ErrorTrace(TRACE_ID, "SetCHString on Name field failed."); // Set filename (key) if (!pInstance->SetCHString(pFilename, chstrDriver)) ErrorTrace(TRACE_ID, "SetVariant on filename Field failed."); // If there exists such a driver file, get the CIM_Datafile object on it if (QualifyDriverFile(chstrDriver, chstrPath)) { // get the CIMDatafile object IWbemClassObject *pFileObj; CComBSTR ccombstrPath((LPCWSTR)chstrPath); hRes = GetCIMDataFile(ccombstrPath, &pFileObj); // if succeeded in getting the CIM_Datafile object, get all file info if (SUCCEEDED(hRes)) { // Get Manufacturer hRes = pFileObj->Get(CComBSTR("Manufacturer"), 0, &varValue, NULL, NULL); if (FAILED(hRes)) ErrorTrace(TRACE_ID, "Get Manufacturer failed on file object"); else if (!pInstance->SetVariant(pManufacturer, varValue)) ErrorTrace(TRACE_ID, "SetVariant on Manufacturer Field failed."); // Get size hRes = pFileObj->Get(CComBSTR("Filesize"), 0, &varValue, NULL, NULL); if (FAILED(hRes)) ErrorTrace(TRACE_ID, "Get FileSize failed on file object"); else if (!pInstance->SetVariant(pSize, varValue)) ErrorTrace(TRACE_ID, "SetVariant on Size Field failed."); // Get version hRes = pFileObj->Get(CComBSTR("version"), 0, &varValue, NULL, NULL); if (FAILED(hRes)) ErrorTrace(TRACE_ID, "Get version failed on file object"); else if (!pInstance->SetVariant(pVersion, varValue)) ErrorTrace(TRACE_ID, "SetVariant on version Field failed."); // Get date hRes = pFileObj->Get(CComBSTR("LastModified"), 0, &varValue, NULL, NULL); if (FAILED(hRes)) ErrorTrace(TRACE_ID, "Get LastModified failed on file object"); else if (!pInstance->SetVariant(pDate, varValue)) ErrorTrace(TRACE_ID, "SetVariant on Date Field failed."); } } // commit this hRes = pInstance->Commit(); if (FAILED(hRes)) ErrorTrace(TRACE_ID, "Commit on Instance failed."); } catch(...) { // Clean up for (iDel = 0; iDel < iCountDriver; iDel++) delete [] apstrDriverArray[iDel]; throw; } } // Clean up for (iDel = 0; iDel < iCountDriver; iDel++) delete [] apstrDriverArray[iDel]; End : TraceFunctLeave(); return hRes; }