Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

564 lines
21 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. PCH_DeviceDriver.CPP
  5. Abstract:
  6. WBEM provider class implementation for PCH_DeviceDriver class
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 04/27/99
  9. - Created
  10. ********************************************************************/
  11. #include "pchealth.h"
  12. #include "confgmgr.h"
  13. #include "PCH_DeviceDriver.h"
  14. #include "cregcls.h"
  15. #define MAX_ARRAY 100
  16. /////////////////////////////////////////////////////////////////////////////
  17. // tracing stuff
  18. #ifdef THIS_FILE
  19. #undef THIS_FILE
  20. #endif
  21. static char __szTraceSourceFile[] = __FILE__;
  22. #define THIS_FILE __szTraceSourceFile
  23. #define TRACE_ID DCID_DEVICEDRIVER
  24. CPCH_DeviceDriver MyPCH_DeviceDriverSet (PROVIDER_NAME_PCH_DEVICEDRIVER, PCH_NAMESPACE) ;
  25. // Property names
  26. //===============
  27. const static WCHAR* pTimeStamp = L"TimeStamp" ;
  28. const static WCHAR* pChange = L"Change" ;
  29. const static WCHAR* pDate = L"Date" ;
  30. const static WCHAR* pFilename = L"Filename" ;
  31. const static WCHAR* pManufacturer = L"Manufacturer" ;
  32. const static WCHAR* pName = L"Name" ;
  33. const static WCHAR* pSize = L"Size" ;
  34. const static WCHAR* pVersion = L"Version" ;
  35. /*****************************************************************************
  36. *
  37. * FUNCTION : CPCH_DeviceDriver::EnumerateInstances
  38. *
  39. * DESCRIPTION : Returns all the instances of this class.
  40. *
  41. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  42. * A long that contains the flags described in
  43. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  44. * flags are handled by (and filtered out by) WinMgmt:
  45. * WBEM_FLAG_DEEP
  46. * WBEM_FLAG_SHALLOW
  47. * WBEM_FLAG_RETURN_IMMEDIATELY
  48. * WBEM_FLAG_FORWARD_ONLY
  49. * WBEM_FLAG_BIDIRECTIONAL
  50. *
  51. * RETURNS : WBEM_S_NO_ERROR if successful
  52. *
  53. * COMMENTS : TO DO: All instances on the machine should be returned here.
  54. * If there are no instances, return WBEM_S_NO_ERROR.
  55. * It is not an error to have no instances.
  56. *
  57. *****************************************************************************/
  58. HRESULT CPCH_DeviceDriver::EnumerateInstances(
  59. MethodContext* pMethodContext,
  60. long lFlags
  61. )
  62. {
  63. TraceFunctEnter("CPCH_DeviceDriver::EnumerateInstances");
  64. CConfigManager cfgManager;
  65. CDeviceCollection deviceList;
  66. HRESULT hRes = WBEM_S_NO_ERROR;
  67. if ( cfgManager.GetDeviceList( deviceList ) )
  68. {
  69. REFPTR_POSITION pos;
  70. if ( deviceList.BeginEnum( pos ) )
  71. {
  72. try
  73. {
  74. CConfigMgrDevice *pDevice = NULL;
  75. // Walk the list
  76. while ( (NULL != ( pDevice = deviceList.GetNext( pos ) ) ) )
  77. {
  78. try
  79. {
  80. CHString chstrVar;
  81. // Driver
  82. if (pDevice->GetDriver(chstrVar))
  83. {
  84. // Get device driver info
  85. (void)CreateDriverInstances(chstrVar, pDevice, pMethodContext);
  86. }
  87. }
  88. catch(...)
  89. {
  90. // GetNext() AddRefs
  91. pDevice->Release();
  92. throw;
  93. }
  94. // GetNext() AddRefs
  95. pDevice->Release();
  96. }
  97. }
  98. catch(...)
  99. {
  100. // Always call EndEnum(). For all Beginnings, there must be an End
  101. deviceList.EndEnum();
  102. throw;
  103. }
  104. // Always call EndEnum(). For all Beginnings, there must be an End
  105. deviceList.EndEnum();
  106. }
  107. }
  108. TraceFunctLeave();
  109. return hRes ;
  110. // pInstance->SetVariant(pTimeStamp, <Property Change>);
  111. // pInstance->SetVariant(pChange, <Property Value>);
  112. // pInstance->SetVariant(pDate, <Property Value>);
  113. // pInstance->SetVariant(pFilename, <Property Value>);
  114. // pInstance->SetVariant(pManufacturer, <Property Value>);
  115. // pInstance->SetVariant(pName, <Property Value>);
  116. // pInstance->SetVariant(pSize, <Property Value>);
  117. // pInstance->SetVariant(pVersion, <Property Value>);
  118. }
  119. //
  120. // QualifyInfFile will find where the inf file is located, in specific
  121. // sections
  122. //
  123. BOOL QualifyInfFile(CHString chstrInfFile, CHString &chstrInfFileQualified)
  124. {
  125. USES_CONVERSION;
  126. TCHAR strWinDir[MAX_PATH];
  127. if (GetWindowsDirectory(strWinDir, MAX_PATH))
  128. {
  129. // check if the file exists in %windir%\inf
  130. CHString chstrFullPath(strWinDir);
  131. chstrFullPath += "\\inf\\";
  132. chstrFullPath += chstrInfFile;
  133. // test for presence of the file
  134. HANDLE hFile = CreateFile(W2A((LPCWSTR)chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  135. // if found, then return with value
  136. if (hFile != INVALID_HANDLE_VALUE)
  137. {
  138. chstrInfFileQualified = chstrFullPath;
  139. CloseHandle(hFile);
  140. return TRUE;
  141. }
  142. // check if the file exists in %windir%\inf\other
  143. chstrFullPath = strWinDir;
  144. chstrFullPath += "\\inf\\other\\";
  145. chstrFullPath += chstrInfFile;
  146. // test for presence of the file
  147. hFile = CreateFile(W2A((LPCWSTR)chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  148. // if found, then return with value
  149. if (hFile != INVALID_HANDLE_VALUE)
  150. {
  151. chstrInfFileQualified = chstrFullPath;
  152. CloseHandle(hFile);
  153. return TRUE;
  154. }
  155. }
  156. return FALSE;
  157. }
  158. BOOL TestFile(LPCTSTR chstrPath1, LPCTSTR chstrPath2, LPCTSTR chstrPath3, CHString &chstrFullPath)
  159. {
  160. USES_CONVERSION;
  161. // concatenate all parts of the path
  162. chstrFullPath = chstrPath1;
  163. chstrFullPath += chstrPath2;
  164. chstrFullPath += chstrPath3;
  165. // test for presence of the file
  166. HANDLE hFile = CreateFile(W2A(chstrFullPath), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  167. // if found, then return with value
  168. if (hFile != INVALID_HANDLE_VALUE)
  169. {
  170. CloseHandle(hFile);
  171. return TRUE;
  172. }
  173. return FALSE;
  174. }
  175. //
  176. // QualifyDriverFile will find where the driver file is located, in specific
  177. // sections
  178. //
  179. BOOL QualifyDriverFile(CHString chstrInfFile, CHString &chstrInfFileQualified)
  180. {
  181. TCHAR strWinDir[MAX_PATH];
  182. TCHAR strSysDir[MAX_PATH];
  183. USES_CONVERSION;
  184. char * szInfFile = W2A(chstrInfFile);
  185. // Check in Windows Directory
  186. if (GetWindowsDirectory(strWinDir, MAX_PATH))
  187. {
  188. // check to see if it exists in %windir%
  189. if (TestFile(strWinDir, "\\", szInfFile, chstrInfFileQualified))
  190. return TRUE;
  191. // check to see if it exists in %windir%\system32
  192. if (TestFile(strWinDir, "\\System32\\", szInfFile, chstrInfFileQualified))
  193. return TRUE;
  194. // check if the file exists in %windir%\system32\drivers
  195. if (TestFile(strWinDir, "\\system32\\drivers\\", szInfFile, chstrInfFileQualified))
  196. return TRUE;
  197. }
  198. // check in System Directory
  199. if (GetSystemDirectory(strSysDir, MAX_PATH))
  200. {
  201. // check to see if it exists in %sysdir%
  202. if (TestFile(strSysDir, "\\", szInfFile, chstrInfFileQualified))
  203. return TRUE;
  204. // check to see if it exists in %sysdir%\iosubsys
  205. if (TestFile(strSysDir, "\\iosubsys\\", szInfFile, chstrInfFileQualified))
  206. return TRUE;
  207. // check to see if it exists in %sysdir%\vmm32
  208. if (TestFile(strSysDir, "\\vmm32\\", szInfFile, chstrInfFileQualified))
  209. return TRUE;
  210. }
  211. return FALSE;
  212. }
  213. /*****************************************************************************
  214. *
  215. * FUNCTION : CPCH_DeviceDriver::CreateDriverInstances
  216. *
  217. * DESCRIPTION : Creates all the device driver instances given the driver name
  218. *
  219. * RETURNS : WBEM_S_NO_ERROR if successful
  220. *
  221. *
  222. * How drivers are obtained from the registry and inf files :
  223. *
  224. * In the reg hive HKLM\System\CurrentControlSet\Services\Class, each device will have a subkey.
  225. * In each device subkey, there are two values InfPath and InfSection. In the specified InfPath
  226. * and InfSection, the drivers are stored in the following fashion :
  227. *
  228. * // sample.inf
  229. *
  230. * [InfSection]
  231. * CopyFiles = Subsection1, Subsection2.....
  232. *
  233. * [Subsection1]
  234. * xxx.dll
  235. * yyy.vxd
  236. * zzz.sys
  237. *
  238. * [Subsection2]
  239. * aaa.dll
  240. * bbb.vxd
  241. * zzz.sys
  242. *
  243. * Plus, there are other values for each different device which may contain driver information :
  244. *
  245. * ALL : PortDriver
  246. * Display : drv, minivdd (extra level deep : default)
  247. * Net : DeviceVxDs
  248. * Ports : PortDriver, ConfigDialog
  249. * Media : Driver
  250. *
  251. *
  252. *****************************************************************************/
  253. HRESULT CPCH_DeviceDriver::CreateDriverInstances(
  254. CHString chstrDriverName,
  255. CConfigMgrDevice* pDevice,
  256. MethodContext* pMethodContext
  257. )
  258. {
  259. TraceFunctEnter("CPCH_DeviceDriver::EnumerateInstances");
  260. HRESULT hRes = WBEM_S_NO_ERROR;
  261. CComVariant varValue;
  262. CRegistry Reg;
  263. int iDel;
  264. CHString chstrInfFileQualified;
  265. CHString chstrInfSection;
  266. TCHAR strCopyFiles[MAX_PATH];
  267. LPTSTR apstrCopyFileArray[MAX_ARRAY];
  268. LPTSTR apstrDriverArray[MAX_ARRAY];
  269. int iDriverIndex;
  270. int iCountDriver;
  271. int iCountCopyFile;
  272. int iIndex;
  273. // create the device key
  274. CHString strDeviceKey("SYSTEM\\CurrentControlSet\\SERVICES\\Class\\");
  275. strDeviceKey += chstrDriverName;
  276. // Get the date and time
  277. SYSTEMTIME stUTCTime;
  278. GetSystemTime(&stUTCTime);
  279. USES_CONVERSION;
  280. char * szInf;
  281. char * szInfFileQualified;
  282. // Get the inf filename
  283. CHString chstrInfFile;
  284. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"InfPath", chstrInfFile) != ERROR_SUCCESS)
  285. goto End;
  286. if (!QualifyInfFile(chstrInfFile, chstrInfFileQualified))
  287. goto End;
  288. // get the inf section
  289. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"InfSection", chstrInfSection) != ERROR_SUCCESS)
  290. goto End;
  291. // get the subsections to be expanded
  292. szInf = W2A(chstrInfSection);
  293. szInfFileQualified = W2A(chstrInfFileQualified);
  294. GetPrivateProfileString(szInf, "CopyFiles", "Error", strCopyFiles, MAX_PATH, szInfFileQualified);
  295. if (!_tcscmp("Error", strCopyFiles))
  296. goto End;
  297. // add the default driver to the driver array
  298. iCountDriver = DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriverName, ",", apstrDriverArray, MAX_ARRAY);
  299. // count number of files to look at
  300. iCountCopyFile = DelimitedStringToArray(strCopyFiles, ",", apstrCopyFileArray, MAX_ARRAY);
  301. // loop through all subsections
  302. for (iIndex = 0; iIndex < iCountCopyFile; iIndex++)
  303. {
  304. // get all drivers in the subsection
  305. TCHAR strDriver[MAX_PATH * MAX_ARRAY];
  306. if (0 < GetPrivateProfileSection(apstrCopyFileArray[iIndex], strDriver, MAX_PATH * MAX_ARRAY, szInfFileQualified))
  307. {
  308. // string is delimited by NULL values so in order to work with the
  309. // DelimitedStringToArray function, we'll replace it with something else
  310. int iCIndex = 0;
  311. while (!((strDriver[iCIndex] == '\0') && (strDriver[iCIndex + 1] == '\0')))
  312. {
  313. if (strDriver[iCIndex] == '\0')
  314. strDriver[iCIndex] = '%';
  315. else // do some cleanup here
  316. if (!(_istalnum(strDriver[iCIndex])) && !(strDriver[iCIndex] == '.'))
  317. strDriver[iCIndex] = '\0';
  318. iCIndex++;
  319. }
  320. iCountDriver += DelimitedStringToArray(strDriver, "%", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  321. // Scout around for more drivers in special keys
  322. CHString chstrExtraKey = strDeviceKey;
  323. chstrExtraKey += "\\default";
  324. CHString chstrDriver;
  325. // special case for display and monitor
  326. if ((!wcsncmp(chstrDriverName, L"display", wcslen(L"display"))) ||
  327. (!wcsncmp(chstrDriverName, L"monitor", wcslen(L"monitor"))))
  328. {
  329. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\####\default for Drv values
  330. if (Reg.OpenLocalMachineKeyAndReadValue(chstrExtraKey, L"Drv", chstrDriver) == ERROR_SUCCESS)
  331. {
  332. // add the list of new driver to the driver array
  333. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  334. }
  335. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\####\default for MiniVDD values
  336. if (Reg.OpenLocalMachineKeyAndReadValue(chstrExtraKey, L"MiniVDD", chstrDriver) == ERROR_SUCCESS)
  337. {
  338. // add the list of new driver to the driver array
  339. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  340. }
  341. }
  342. // special case for net, nettrans, netclient, netservice
  343. if (!wcsncmp(chstrDriverName, L"net", wcslen(L"net")))
  344. {
  345. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for DeviceVxDs values
  346. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"DeviceVxDs", chstrDriver) == ERROR_SUCCESS)
  347. {
  348. // add the list of new driver to the driver array
  349. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  350. }
  351. }
  352. // special case for ports
  353. if (!wcsncmp(chstrDriverName, L"ports", wcslen(L"ports")))
  354. {
  355. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for ConfigDialog values
  356. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"ConfigDialog", chstrDriver) == ERROR_SUCCESS)
  357. {
  358. // add the list of new driver to the driver array
  359. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  360. }
  361. }
  362. // special case for media
  363. if (!wcsncmp(chstrDriverName, L"media", wcslen(L"media")))
  364. {
  365. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for Driver values
  366. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"Driver", chstrDriver) == ERROR_SUCCESS)
  367. {
  368. // add the list of new driver to the driver array
  369. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  370. }
  371. }
  372. // HKLM\SYSTEM\CurrentControlSet\SERVICES\Class\XXXX\#### for PortDriver values
  373. if (Reg.OpenLocalMachineKeyAndReadValue(strDeviceKey, L"PortDriver", chstrDriver) == ERROR_SUCCESS)
  374. {
  375. // add the list of new driver to the driver array
  376. iCountDriver += DelimitedStringToArray((LPWSTR)(LPCWSTR)chstrDriver, ",", apstrDriverArray + iCountDriver, MAX_ARRAY - iCountDriver);
  377. }
  378. }
  379. }
  380. // Clean up
  381. for (iDel = 0; iDel < iCountCopyFile; iDel++)
  382. delete [] apstrCopyFileArray[iDel];
  383. // go through list of drivers and create the instances
  384. for (iDriverIndex = 0; iDriverIndex < iCountDriver; iDriverIndex++)
  385. {
  386. CHString chstrDriver(apstrDriverArray[iDriverIndex]);
  387. CHString chstrPath;
  388. // Check for duplicates
  389. BOOL bDup = FALSE;
  390. for (int iDup = 0; iDup < iDriverIndex; iDup++)
  391. {
  392. char * szDriver = W2A(chstrDriver);
  393. if (!_tcsicmp(szDriver, apstrDriverArray[iDup]))
  394. {
  395. bDup = TRUE;
  396. break;
  397. }
  398. }
  399. // if there exists a duplicate, skip it
  400. if (bDup)
  401. continue;
  402. // create instance
  403. CInstancePtr pInstance(CreateNewInstance(pMethodContext), false);
  404. try
  405. {
  406. // Timestamp
  407. if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)))
  408. ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
  409. // Snapshot
  410. if (!pInstance->SetCHString(pChange, L"Snapshot"))
  411. ErrorTrace(TRACE_ID, "SetCHString on Change Field failed.");
  412. // Name (key)
  413. // bug fix : should be name of device (foreign key), NOT driver name
  414. CHString chstrVar;
  415. if (pDevice->GetDeviceID(chstrVar))
  416. if (!pInstance->SetCHString(pName, chstrVar))
  417. ErrorTrace(TRACE_ID, "SetCHString on Name field failed.");
  418. // Set filename (key)
  419. if (!pInstance->SetCHString(pFilename, chstrDriver))
  420. ErrorTrace(TRACE_ID, "SetVariant on filename Field failed.");
  421. // If there exists such a driver file, get the CIM_Datafile object on it
  422. if (QualifyDriverFile(chstrDriver, chstrPath))
  423. {
  424. // get the CIMDatafile object
  425. IWbemClassObject *pFileObj;
  426. CComBSTR ccombstrPath((LPCWSTR)chstrPath);
  427. hRes = GetCIMDataFile(ccombstrPath, &pFileObj);
  428. // if succeeded in getting the CIM_Datafile object, get all file info
  429. if (SUCCEEDED(hRes))
  430. {
  431. // Get Manufacturer
  432. hRes = pFileObj->Get(CComBSTR("Manufacturer"), 0, &varValue, NULL, NULL);
  433. if (FAILED(hRes))
  434. ErrorTrace(TRACE_ID, "Get Manufacturer failed on file object");
  435. else
  436. if (!pInstance->SetVariant(pManufacturer, varValue))
  437. ErrorTrace(TRACE_ID, "SetVariant on Manufacturer Field failed.");
  438. // Get size
  439. hRes = pFileObj->Get(CComBSTR("Filesize"), 0, &varValue, NULL, NULL);
  440. if (FAILED(hRes))
  441. ErrorTrace(TRACE_ID, "Get FileSize failed on file object");
  442. else
  443. if (!pInstance->SetVariant(pSize, varValue))
  444. ErrorTrace(TRACE_ID, "SetVariant on Size Field failed.");
  445. // Get version
  446. hRes = pFileObj->Get(CComBSTR("version"), 0, &varValue, NULL, NULL);
  447. if (FAILED(hRes))
  448. ErrorTrace(TRACE_ID, "Get version failed on file object");
  449. else
  450. if (!pInstance->SetVariant(pVersion, varValue))
  451. ErrorTrace(TRACE_ID, "SetVariant on version Field failed.");
  452. // Get date
  453. hRes = pFileObj->Get(CComBSTR("LastModified"), 0, &varValue, NULL, NULL);
  454. if (FAILED(hRes))
  455. ErrorTrace(TRACE_ID, "Get LastModified failed on file object");
  456. else
  457. if (!pInstance->SetVariant(pDate, varValue))
  458. ErrorTrace(TRACE_ID, "SetVariant on Date Field failed.");
  459. }
  460. }
  461. // commit this
  462. hRes = pInstance->Commit();
  463. if (FAILED(hRes))
  464. ErrorTrace(TRACE_ID, "Commit on Instance failed.");
  465. }
  466. catch(...)
  467. {
  468. // Clean up
  469. for (iDel = 0; iDel < iCountDriver; iDel++)
  470. delete [] apstrDriverArray[iDel];
  471. throw;
  472. }
  473. }
  474. // Clean up
  475. for (iDel = 0; iDel < iCountDriver; iDel++)
  476. delete [] apstrDriverArray[iDel];
  477. End :
  478. TraceFunctLeave();
  479. return hRes;
  480. }