Source code of Windows XP (NT5)
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.

711 lines
20 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: DrvInfo.cpp
  6. //
  7. // Owner: YanL
  8. //
  9. // Description:
  10. //
  11. // Implementation of device enumeration
  12. //
  13. //=======================================================================
  14. #include <windows.h>
  15. #include <setupapi.h>
  16. #include <shlwapi.h>
  17. #include <regstr.h>
  18. #include <devguid.h>
  19. #include <tchar.h>
  20. //#include <atlconv.h>
  21. #include <wustl.h>
  22. #include <DrvInfo.h>
  23. #define LOGGING_LEVEL 2
  24. #include <log.h>
  25. #include "cdmlibp.h"
  26. #define DEVICE_INSTANCE_SIZE 128
  27. //*********************************************************************************//
  28. // Global UNICODE<>ANSI translation helpers
  29. //*********************************************************************************//
  30. #include <malloc.h> // for _alloca
  31. #define USES_CONVERSION int _convert = 0; _convert; UINT _acp = CP_ACP; _acp; LPCWSTR _lpw = NULL; _lpw; LPCSTR _lpa = NULL; _lpa
  32. inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
  33. {
  34. //
  35. // verify that no illegal character present
  36. // since lpw was allocated based on the size of lpa
  37. // don't worry about the number of chars
  38. //
  39. lpw[0] = '\0';
  40. MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
  41. return lpw;
  42. }
  43. inline LPSTR WINAPI AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp)
  44. {
  45. //
  46. // verify that no illegal character present
  47. // since lpa was allocated based on the size of lpw
  48. // don't worry about the number of chars
  49. //
  50. lpa[0] = '\0';
  51. WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
  52. return lpa;
  53. }
  54. #define A2W(lpa) (\
  55. ((_lpa = lpa) == NULL) ? NULL : (\
  56. _convert = (lstrlenA(_lpa)+1),\
  57. AtlA2WHelper((LPWSTR)_alloca(_convert*2), _lpa, _convert, CP_ACP)))
  58. #define W2A(lpw) (\
  59. ((_lpw = lpw) == NULL) ? NULL : (\
  60. _convert = (lstrlenW(_lpw)+1)*2,\
  61. AtlW2AHelper((LPSTR)_alloca(_convert), _lpw, _convert, CP_ACP)))
  62. #define A2CW(lpa) ((LPCWSTR)A2W(lpa))
  63. #define W2CA(lpw) ((LPCSTR)W2A(lpw))
  64. #ifdef _UNICODE
  65. #define T2A W2A
  66. #define A2T A2W
  67. inline LPWSTR T2W(LPTSTR lp) { return lp; }
  68. inline LPTSTR W2T(LPWSTR lp) { return lp; }
  69. #define T2CA W2CA
  70. #define A2CT A2CW
  71. inline LPCWSTR T2CW(LPCTSTR lp) { return lp; }
  72. inline LPCTSTR W2CT(LPCWSTR lp) { return lp; }
  73. #else
  74. #define T2W A2W
  75. #define W2T W2A
  76. inline LPSTR T2A(LPTSTR lp) { return lp; }
  77. inline LPTSTR A2T(LPSTR lp) { return lp; }
  78. #define T2CW A2CW
  79. #define W2CT W2CA
  80. inline LPCSTR T2CA(LPCTSTR lp) { return lp; }
  81. inline LPCTSTR A2CT(LPCSTR lp) { return lp; }
  82. #endif
  83. #define OLE2T(p) W2T(p)
  84. #define T2OLE(p) T2W(p)
  85. #ifdef _WUV3TEST
  86. // Check the registry to see if we have been called to fake
  87. static bool FakeDetection()
  88. {
  89. auto_hkey hkey;
  90. DWORD dwFake = 0;
  91. DWORD dwSize = sizeof(dwFake);
  92. if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey)) {
  93. RegQueryValueEx(hkey, _T("UseIni"), 0, 0, (LPBYTE)&dwFake, &dwSize);
  94. }
  95. return 1 == dwFake;
  96. }
  97. #endif
  98. static bool CanOpenInf(LPCTSTR szInfFile);
  99. static bool DriverVerFromInf(LPCTSTR szInfFile, LPCTSTR szMfg, LPCTSTR szDesc, LPTSTR szValue/*size_is(256)*/);
  100. static bool IsOriginalFile(LPCTSTR szInfFile);
  101. // Implementation that gets real devices quering DevMan
  102. class CRealDrvInfo : public IDrvInfo
  103. {
  104. protected:
  105. tchar_buffer m_sDevInstID;
  106. auto_hdevinfo m_hDevInfo;
  107. SP_DEVINFO_DATA m_DevInfoData;
  108. FILETIME m_ftDriverDate;
  109. protected:
  110. bool GetPropertySetupDi(ULONG ulProperty, tchar_buffer& bufHardwareIDs);
  111. bool GetPropertyReg(LPCTSTR szProperty, tchar_buffer& bufHardwareIDs);
  112. bool LatestDriverFileTime(LPCTSTR szInfFile, LPCTSTR szMfgName, LPCTSTR szDescription,
  113. LPCTSTR szProvider, FILETIME& ftDate);
  114. virtual bool Init(LPCTSTR szDevInstID)
  115. {
  116. LOG_block("CRealDrvInfo::Init");
  117. LOG_out("[%s]", szDevInstID);
  118. m_hDevInfo = (HDEVINFO)SetupDiCreateDeviceInfoList(NULL, NULL);
  119. return_if_false(m_hDevInfo.valid()) ;
  120. ZeroMemory(&m_DevInfoData, sizeof(SP_DEVINFO_DATA));
  121. m_DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  122. return_if_false(SetupDiOpenDeviceInfo(m_hDevInfo, szDevInstID, 0, 0, &m_DevInfoData)) ;
  123. m_sDevInstID.resize(lstrlen(szDevInstID) + 1);
  124. if (!m_sDevInstID.valid()) return false;
  125. lstrcpy(m_sDevInstID, szDevInstID);
  126. m_ftDriverDate.dwHighDateTime = -1;
  127. return true;
  128. }
  129. public:
  130. virtual bool GetDeviceInstanceID(tchar_buffer& bufDeviceInstanceID)
  131. {
  132. bufDeviceInstanceID.resize(m_sDevInstID.size());
  133. if (!bufDeviceInstanceID.valid()) return false;
  134. lstrcpy(bufDeviceInstanceID, m_sDevInstID);
  135. return true;
  136. }
  137. virtual bool HasDriver()
  138. {
  139. tchar_buffer bufDriver;
  140. return GetPropertySetupDi(SPDRP_DRIVER, bufDriver);
  141. }
  142. virtual bool IsPrinter()
  143. {
  144. return IsEqualGUID(m_DevInfoData.ClassGuid, GUID_DEVCLASS_PRINTER) ? true : false;
  145. }
  146. virtual bool GetAllHardwareIDs(tchar_buffer& bufHardwareIDs);
  147. virtual bool GetHardwareIDs(tchar_buffer& bufHardwareIDs)
  148. {
  149. return GetPropertySetupDi(SPDRP_HARDWAREID, bufHardwareIDs);
  150. }
  151. virtual bool GetCompatIDs(tchar_buffer& bufHardwareIDs)
  152. {
  153. return GetPropertySetupDi(SPDRP_COMPATIBLEIDS, bufHardwareIDs);
  154. }
  155. virtual bool GetMatchingDeviceId(tchar_buffer& bufMatchingDeviceId)
  156. {
  157. return GetPropertyReg(REGSTR_VAL_MATCHINGDEVID, bufMatchingDeviceId);
  158. }
  159. virtual bool GetManufacturer(tchar_buffer& bufMfg)
  160. {
  161. return GetPropertySetupDi(SPDRP_MFG, bufMfg);
  162. }
  163. virtual bool GetProvider(tchar_buffer& bufProvider)
  164. {
  165. return GetPropertyReg(REGSTR_VAL_PROVIDER_NAME, bufProvider);
  166. }
  167. virtual bool GetDescription(tchar_buffer& bufDescription)
  168. {
  169. return GetPropertySetupDi(SPDRP_DEVICEDESC, bufDescription);
  170. }
  171. virtual bool GetDriverDate(FILETIME& ftDriverDate);
  172. };
  173. #ifdef _WUV3TEST
  174. // Implementation that gets fake devices from wuv3test.ini
  175. class CFakeDrvInfo : public IDrvInfo
  176. {
  177. protected:
  178. TCHAR m_szDevInstID[MAX_PATH];
  179. protected:
  180. bool GetString(LPCTSTR szKeyName, tchar_buffer& buf)
  181. {
  182. buf.resize(256);
  183. if (!buf.valid()) return 0;
  184. return 0 != GetPrivateProfileString(m_szDevInstID, szKeyName, _T(""), buf, 256 / sizeof(TCHAR), _T("wuv3test.ini"));
  185. }
  186. virtual bool Init(LPCTSTR szDevInstID)
  187. {
  188. lstrcpy(m_szDevInstID, szDevInstID);
  189. // Lets see if this section exists at all
  190. tchar_buffer buf;
  191. return GetString(NULL, buf);
  192. }
  193. public:
  194. virtual bool GetDeviceInstanceID(tchar_buffer& bufDeviceInstanceID)
  195. {
  196. bufDeviceInstanceID.resize(lstrlen(m_szDevInstID) + 1);
  197. if (!bufDeviceInstanceID.valid()) return false;
  198. lstrcpy(bufDeviceInstanceID, m_szDevInstID);
  199. return true;
  200. }
  201. virtual bool HasDriver()
  202. {
  203. tchar_buffer bufMfg;
  204. return GetString(_T("Manufacturer"), bufMfg);
  205. }
  206. virtual bool IsPrinter()
  207. {
  208. return false;
  209. }
  210. virtual bool GetAllHardwareIDs(tchar_buffer& bufHardwareIDs)
  211. {
  212. return GetHardwareIDs(bufHardwareIDs);
  213. }
  214. virtual bool GetHardwareIDs(tchar_buffer& bufHardwareIDs)
  215. {
  216. return GetString(_T("HardwareIDs"), bufHardwareIDs);
  217. }
  218. virtual bool GetCompatIDs(tchar_buffer& bufHardwareIDs)
  219. {
  220. return false;
  221. }
  222. virtual bool GetMatchingDeviceId(tchar_buffer& bufMatchingDeviceId)
  223. {
  224. return GetString(_T("MatchingDeviceId"), bufMatchingDeviceId);
  225. }
  226. virtual bool GetManufacturer(tchar_buffer& bufMfg)
  227. {
  228. return GetString(_T("Manufacturer"), bufMfg);
  229. }
  230. virtual bool GetProvider(tchar_buffer& bufMfg)
  231. {
  232. return GetString(_T("Provider"), bufMfg);
  233. }
  234. virtual bool GetDescription(tchar_buffer& bufDescription)
  235. {
  236. return GetString(_T("Description"), bufDescription);
  237. }
  238. virtual bool GetDriverDate(FILETIME& ftDriverDate)
  239. {
  240. tchar_buffer bufDriverDate;
  241. if (!GetString(_T("DriverDate"), bufDriverDate))
  242. return false;
  243. return DriverVer2FILETIME(bufDriverDate, ftDriverDate);
  244. }
  245. };
  246. #endif
  247. //
  248. // CDrvInfoEnum not inline implementation
  249. //
  250. bool CDrvInfoEnum::GetDrvInfo(LPCWSTR wszDevInstID, IDrvInfo** ppDrvInfo)
  251. {
  252. LOG_block("CDrvInfoEnum::GetDrvInfo");
  253. USES_CONVERSION;
  254. auto_pointer<IDrvInfo> pDrvInfo;
  255. #ifdef _WUV3TEST
  256. if ( FakeDetection())
  257. pDrvInfo = new CFakeDrvInfo;
  258. else
  259. #endif
  260. pDrvInfo = new CRealDrvInfo;
  261. return_if_false(pDrvInfo.valid());
  262. return_if_false(pDrvInfo->Init(W2T(const_cast<WCHAR*>(wszDevInstID))));
  263. *ppDrvInfo = pDrvInfo.detach();
  264. return true;
  265. }
  266. CDrvInfoEnum::CDrvInfoEnum()
  267. : m_dwDeviceIndex(0)
  268. {
  269. #ifdef _WUV3TEST
  270. if (! FakeDetection())
  271. #endif
  272. m_hDevInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
  273. }
  274. bool CDrvInfoEnum::GetNextDrvInfo(IDrvInfo** ppDrvInfo)
  275. {
  276. LOG_block("CDrvInfoEnum::GetNextDrvInfo");
  277. auto_pointer<IDrvInfo> pDrvInfo;
  278. TCHAR szDevInstID[DEVICE_INSTANCE_SIZE];
  279. if (m_hDevInfoSet.valid()) // real
  280. {
  281. SP_DEVINFO_DATA DevInfoData;
  282. memset(&DevInfoData, 0, sizeof(SP_DEVINFO_DATA));
  283. DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  284. return_if_false(SetupDiEnumDeviceInfo(m_hDevInfoSet, m_dwDeviceIndex, &DevInfoData));
  285. return_if_false(SetupDiGetDeviceInstanceId(m_hDevInfoSet, &DevInfoData, szDevInstID, sizeof(szDevInstID)/sizeof(szDevInstID[0]), NULL));
  286. pDrvInfo = new CRealDrvInfo;
  287. }
  288. #ifdef _WUV3TEST
  289. else // fake
  290. {
  291. wsprintf(szDevInstID, _T("Device%d"), (int)m_dwDeviceIndex);
  292. pDrvInfo = new CFakeDrvInfo;
  293. }
  294. #endif
  295. return_if_false(pDrvInfo.valid());
  296. return_if_false(pDrvInfo->Init(szDevInstID));
  297. m_dwDeviceIndex ++;
  298. *ppDrvInfo = pDrvInfo.detach();
  299. return true;
  300. }
  301. //
  302. // CRealDrvInfo not inline implementation
  303. //
  304. bool CRealDrvInfo::GetAllHardwareIDs(tchar_buffer& bufHardwareIDs)
  305. {
  306. if (!GetHardwareIDs(bufHardwareIDs))
  307. return false;
  308. tchar_buffer bufCompatIDs;
  309. if (!GetCompatIDs(bufCompatIDs))
  310. return true; // no campats
  311. // find \0\0 in the first buffer
  312. for (LPTSTR sz = bufHardwareIDs; *sz; sz += lstrlen(sz) + 1);
  313. int cnOldSize = sz - (LPCTSTR)bufHardwareIDs;
  314. // NTBUG9#145086 size was increased by byte rather than sizeof(TCHAR)
  315. bufHardwareIDs.resize(cnOldSize + ((bufCompatIDs.size() + 1) * sizeof(TCHAR))); // I've found a case where there are no \0\0 at the end of compat ID
  316. sz = bufHardwareIDs; sz += cnOldSize;
  317. // NTBUG9#145086 size is # chars rather than bytes
  318. memcpy(sz, bufCompatIDs, bufCompatIDs.size() * sizeof(TCHAR));
  319. sz[bufCompatIDs.size()] = 0;
  320. return true;
  321. }
  322. bool CRealDrvInfo::GetDriverDate(FILETIME& ftDriverDate)
  323. {
  324. LOG_block("CRealDrvInfo::GetDriverDate");
  325. if (-1 == m_ftDriverDate.dwHighDateTime)
  326. {
  327. OSVERSIONINFO osvi;
  328. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  329. GetVersionEx(&osvi);
  330. // Check if we are on new or old schema
  331. bool fNew = osvi.dwPlatformId == VER_PLATFORM_WIN32_NT || osvi.dwMajorVersion > 4 || osvi.dwMinorVersion >= 90;
  332. if (fNew)
  333. {
  334. // DriverVer has to be present on NT
  335. tchar_buffer bufDriverDate;
  336. return_if_false(GetPropertyReg(REGSTR_VAL_DRIVERDATE, bufDriverDate));
  337. return_if_false(DriverVer2FILETIME(bufDriverDate, m_ftDriverDate));
  338. }
  339. else
  340. {
  341. // Get INF File first
  342. tchar_buffer bufInf;
  343. return_if_false(GetPropertyReg(REGSTR_VAL_INFPATH, bufInf));
  344. if (IsOriginalFile(bufInf))
  345. {
  346. // on of the original OS drivers
  347. ZeroMemory(&m_ftDriverDate, sizeof(m_ftDriverDate));
  348. }
  349. else
  350. {
  351. tchar_buffer bufMfg;
  352. return_if_false(GetManufacturer(bufMfg));
  353. tchar_buffer bufDescription;
  354. return_if_false(GetDescription(bufDescription));
  355. TCHAR szInf[MAX_PATH]; // %systemroot%\inf\other\foo.inf or %systemroot%\inf\foo.inf
  356. GetWindowsDirectory(szInf, sizeOfArray(szInf));
  357. PathAppend(szInf, _T("inf\\other"));
  358. PathAppend(szInf, bufInf);
  359. if (!CanOpenInf(szInf))
  360. {
  361. GetWindowsDirectory(szInf, sizeOfArray(szInf));
  362. PathAppend(szInf, _T("inf"));
  363. PathAppend(szInf, bufInf);
  364. if (!CanOpenInf(szInf))
  365. {
  366. LOG_error("Cannot find %s", (LPCTSTR)bufInf);
  367. return false;
  368. }
  369. }
  370. // first try to get it from inf
  371. tchar_buffer bufDriverDate(256);
  372. if (DriverVerFromInf(szInf, bufMfg, bufDescription, bufDriverDate))
  373. {
  374. return_if_false(DriverVer2FILETIME(bufDriverDate, m_ftDriverDate))
  375. }
  376. else // enum files not
  377. {
  378. tchar_buffer bufProvider;
  379. if (!GetProvider(bufProvider))
  380. {
  381. bufProvider.resize(1);
  382. return_if_false(bufProvider.valid());
  383. lstrcpy(bufProvider, _T(""));
  384. }
  385. return_if_false(LatestDriverFileTime(szInf, bufMfg, bufDescription, bufProvider, m_ftDriverDate));
  386. }
  387. }
  388. }
  389. }
  390. ftDriverDate = m_ftDriverDate;
  391. return true;
  392. }
  393. bool CRealDrvInfo::GetPropertySetupDi(ULONG ulProperty, tchar_buffer& buf)
  394. {
  395. LOG_block("CRealDrvInfo::GetPropertySetupDi");
  396. ULONG ulSize = 0;
  397. SetupDiGetDeviceRegistryProperty(m_hDevInfo, &m_DevInfoData, ulProperty, NULL, NULL, 0, &ulSize);
  398. return_if_false(0 != ulSize);
  399. // Win98 has a bug when requesting SPDRP_HARDWAREID
  400. // NTBUG9#182680 We make this big enough to always have a Unicode double-null at the end
  401. // so that we don't fault if the reg value isn't correctly terminated
  402. ulSize += 4;
  403. buf.resize(ulSize/sizeof(TCHAR));
  404. buf.zero_buffer(); // NTBUG9#182680 zero the buffer so we don't get random garbage - REG_MULTI_SZ isn't always double-null terminated
  405. return_if_false(buf.valid());
  406. return_if_false(SetupDiGetDeviceRegistryProperty(m_hDevInfo, &m_DevInfoData, ulProperty, NULL, (LPBYTE)(LPTSTR)buf, ulSize - 4 , NULL));
  407. return true;
  408. }
  409. bool CRealDrvInfo::GetPropertyReg(LPCTSTR szProperty, tchar_buffer& buf)
  410. {
  411. LOG_block("CRealDrvInfo::GetPropertyReg");
  412. //Open the device's driver key and retrieve the INF from which the driver was installed.
  413. auto_hkeySetupDi hKey = SetupDiOpenDevRegKey(m_hDevInfo, &m_DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ);
  414. return_if_false(hKey.valid());
  415. ULONG ulSize = 0;
  416. RegQueryValueEx(hKey, szProperty, NULL, NULL, NULL, &ulSize);
  417. return_if_false(0 != ulSize);
  418. buf.resize(ulSize/sizeof(TCHAR));
  419. return_if_false(buf.valid());
  420. return_if_false( NO_ERROR == RegQueryValueEx(hKey, szProperty, NULL, NULL, (LPBYTE)(LPTSTR)buf, &ulSize));
  421. return true;
  422. }
  423. inline bool IsDriver(LPCTSTR szFile)
  424. {
  425. LPCTSTR szExt = PathFindExtension(szFile);
  426. if (NULL == szExt)
  427. {
  428. return FALSE;
  429. }
  430. static const TCHAR* aszExt[] = {
  431. _T(".sys"),
  432. _T(".dll"),
  433. _T(".drv"),
  434. _T(".vxd"),
  435. };
  436. for(int i = 0; i < sizeOfArray(aszExt); i ++)
  437. {
  438. if(0 == lstrcmpi(aszExt[i], szExt))
  439. return true;
  440. }
  441. return false;
  442. }
  443. static UINT CALLBACK FileQueueScanCallback(
  444. IN PVOID pContext, // setup api context
  445. IN UINT ulNotification, // notification message
  446. IN UINT_PTR ulParam1, // extra notification message information 1
  447. IN UINT_PTR /*Param2*/ // extra notification message information 2
  448. ) {
  449. if (SPFILENOTIFY_QUEUESCAN == ulNotification)
  450. {
  451. PFILETIME pftDateLatest = (PFILETIME)pContext;
  452. LPCTSTR szFile = (LPCTSTR)ulParam1;
  453. // Is this a binary
  454. if (IsDriver(szFile))
  455. {
  456. auto_hfile hFile = CreateFile(szFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  457. FILETIME ft;
  458. if (hFile.valid() && GetFileTime(hFile, NULL, NULL, &ft))
  459. {
  460. // #ifdef _WUV3TEST
  461. SYSTEMTIME st;
  462. FileTimeToSystemTime(&ft, &st);
  463. LOG_out1("%s : %2d/%02d/%04d", szFile, (int)st.wMonth, (int)st.wDay, (int)st.wYear);
  464. // #endif
  465. if (CompareFileTime(pftDateLatest, &ft) < 0)
  466. *pftDateLatest = ft;
  467. }
  468. }
  469. else
  470. {
  471. LOG_out1("%s : not a driver", szFile);
  472. }
  473. }
  474. return NO_ERROR;
  475. }
  476. bool CRealDrvInfo::LatestDriverFileTime(
  477. LPCTSTR szInfFile, LPCTSTR szMfgName, LPCTSTR szDescription, LPCTSTR szProvider, FILETIME& ftDate
  478. ) {
  479. LOG_block("CRealDrvInfo::LatestDriverFileTime");
  480. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  481. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  482. return_if_false(SetupDiGetDeviceInstallParams(m_hDevInfo, &m_DevInfoData, &DeviceInstallParams));
  483. lstrcpy(DeviceInstallParams.DriverPath, szInfFile);
  484. DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  485. return_if_false(SetupDiSetDeviceInstallParams(m_hDevInfo, &m_DevInfoData, &DeviceInstallParams));
  486. //Now build a class driver list from this INF.
  487. return_if_false(SetupDiBuildDriverInfoList(m_hDevInfo, &m_DevInfoData, SPDIT_CLASSDRIVER));
  488. //Prepare driver info struct
  489. SP_DRVINFO_DATA DriverInfoData;
  490. ZeroMemory(&DriverInfoData, sizeof(DriverInfoData));
  491. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA_V1); // 98
  492. DriverInfoData.DriverType = SPDIT_CLASSDRIVER;
  493. DriverInfoData.Reserved = 0;
  494. lstrcpyn(DriverInfoData.MfgName, szMfgName, LINE_LEN-1);
  495. lstrcpyn(DriverInfoData.Description, szDescription, LINE_LEN-1);
  496. lstrcpyn(DriverInfoData.ProviderName, szProvider, LINE_LEN-1);
  497. return_if_false(SetupDiSetSelectedDriver(m_hDevInfo, &m_DevInfoData, (SP_DRVINFO_DATA*)&DriverInfoData));
  498. auto_hspfileq hspfileq = SetupOpenFileQueue();
  499. return_if_false(hspfileq.valid());
  500. // Set custom queue to device installl params
  501. return_if_false(SetupDiGetDeviceInstallParams(m_hDevInfo, &m_DevInfoData, &DeviceInstallParams));
  502. DeviceInstallParams.FileQueue = hspfileq;
  503. DeviceInstallParams.Flags |= DI_NOVCP;
  504. return_if_false(SetupDiSetDeviceInstallParams(m_hDevInfo, &m_DevInfoData, &DeviceInstallParams));
  505. return_if_false(SetupDiInstallDriverFiles(m_hDevInfo, &m_DevInfoData));
  506. // Parce the queue
  507. FILETIME ftDateTmp = {0,0};
  508. DWORD dwScanResult;
  509. return_if_false(SetupScanFileQueue(hspfileq, SPQ_SCAN_USE_CALLBACK, NULL, (PSP_FILE_CALLBACK)FileQueueScanCallback, &ftDateTmp, &dwScanResult));
  510. //#ifdef _WUV3TEST
  511. SYSTEMTIME st;
  512. FileTimeToSystemTime(&ftDateTmp, &st);
  513. LOG_out("%s - %s %2d/%02d/%04d", szMfgName, szDescription, (int)st.wMonth, (int)st.wDay, (int)st.wYear);
  514. //#endif
  515. ftDate = ftDateTmp;
  516. return true;
  517. }
  518. // Date has to be in format mm-dd-yyyy or mm/dd/yyyy
  519. bool DriverVer2FILETIME(LPCTSTR szDate, FILETIME& ftDate)
  520. {
  521. LOG_block("DriverVer2FILETIME");
  522. LPCTSTR szMonth = szDate;
  523. while (*szDate && (*szDate != TEXT('-')) && (*szDate != TEXT('/')))
  524. szDate++;
  525. return_if_false(*szDate);
  526. LPCTSTR szDay = ++ szDate ;
  527. while (*szDate && (*szDate != TEXT('-')) && (*szDate != TEXT('/')))
  528. szDate++;
  529. return_if_false(*szDate);
  530. ++ szDate;
  531. SYSTEMTIME SystemTime;
  532. ZeroMemory(&SystemTime, sizeof(SYSTEMTIME));
  533. SystemTime.wMonth = (WORD)(short)StrToInt(szMonth);
  534. SystemTime.wDay = (WORD)(short)StrToInt(szDay);
  535. SystemTime.wYear = (WORD)(short)StrToInt(szDate);
  536. return_if_false(SystemTimeToFileTime(&SystemTime, &ftDate));
  537. return true;
  538. }
  539. static bool GetFirstStringField(HINF hInf, LPCTSTR szSection, LPCTSTR szKey, LPTSTR szValue/*size_is(256)*/)
  540. {
  541. LOG_block("GetFirstStringField");
  542. INFCONTEXT ctx;
  543. return_if_false(SetupFindFirstLine(hInf, szSection, szKey, &ctx));
  544. return_if_false(SetupGetStringField(&ctx, 1, szValue, 256, NULL)); //Driver section
  545. return true;
  546. }
  547. static inline bool DriverVerFromInfInstallSection(HINF hInf, LPCTSTR szMfg, LPCTSTR szDesc, LPTSTR szValue/*size_is(256)*/)
  548. {
  549. LOG_block("DriverVerFromInfInstallSection");
  550. TCHAR szDeviceSec[256];
  551. return_if_false(GetFirstStringField(hInf, _T("Manufacturer"), szMfg, szDeviceSec)); // Driver section
  552. TCHAR szInstallSec[256];
  553. return_if_false(GetFirstStringField(hInf, szDeviceSec, szDesc, szInstallSec)); // Install section
  554. return_if_false(GetFirstStringField(hInf, szInstallSec, _T("DriverVer"), szValue)); // DriverVer
  555. return true;
  556. }
  557. static bool CanOpenInf(LPCTSTR szInfFile)
  558. {
  559. auto_hinf hInf = SetupOpenInfFile(szInfFile, NULL, INF_STYLE_WIN4, NULL);
  560. return hInf.valid();
  561. }
  562. static bool DriverVerFromInf(LPCTSTR szInfFile, LPCTSTR szMfg, LPCTSTR szDesc, LPTSTR szValue/*size_is(256)*/)
  563. {
  564. LOG_block("DriverVerFromInf");
  565. auto_hinf hInf = SetupOpenInfFile(szInfFile, NULL, INF_STYLE_WIN4, NULL);
  566. return_if_false(hInf.valid());
  567. bool fFound = DriverVerFromInfInstallSection(hInf, szMfg, szDesc, szValue) ||
  568. GetFirstStringField(hInf, _T("Version"), _T("DriverVer"), szValue);
  569. //#ifdef _WUV3TEST
  570. // RAID# 146771
  571. if (fFound)
  572. LOG_out("DriverVerFromInf - %s, return true", szValue);
  573. else
  574. LOG_out("DriverVerFromInf, return false");
  575. //#endif
  576. return fFound;
  577. }
  578. static bool IsOriginalFile(LPCTSTR szInfFile)
  579. {
  580. LOG_block("IsOriginalFile");
  581. if (0 == szInfFile || 0 == lstrlen(szInfFile))
  582. {
  583. LOG_out("empty szInfFile, return false");
  584. }
  585. // construct full title
  586. LPTSTR szInfTitle = PathFindFileName(szInfFile);
  587. const static LPCTSTR aszLayoutTitle[] = {
  588. _T("layout.inf"),
  589. _T("layout1.inf"),
  590. _T("layout2.inf"),
  591. };
  592. for (int i = 0; i < sizeOfArray(aszLayoutTitle); i ++)
  593. {
  594. TCHAR szLayout[MAX_PATH];
  595. if (! GetWindowsDirectory(szLayout, sizeOfArray(szLayout)))
  596. {
  597. lstrcat(szLayout, _T("C:\\Windows"));
  598. }
  599. PathAppend(szLayout, _T("inf"));
  600. PathAppend(szLayout, aszLayoutTitle[i]);
  601. TCHAR szDummy[16];
  602. if( 0 != GetPrivateProfileString(_T("SourceDisksFiles"), szInfTitle, _T(""), szDummy, sizeOfArray(szDummy), szLayout))
  603. {
  604. LOG_out("%s found in %s, return true", szInfFile, szLayout);
  605. return true;
  606. }
  607. }
  608. LOG_out("%s in not found, return false", szInfFile);
  609. return false;
  610. }