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.

1012 lines
32 KiB

  1. // ----------------------------------------------------------------------------------
  2. //
  3. // Created By RogerJ, October 3rd, 2000
  4. // This CPP file has all the functions that related to driver detection (on W2K) and
  5. // driver downloading. The setup item download part is in Wsdueng.cpp
  6. //
  7. // ----------------------------------------------------------------------------------
  8. #include "Wsdueng.h"
  9. #include <winspool.h>
  10. // DuDriver.h includes definition of structures used in driver bitmap and bucket file, it is a
  11. // cut and paste version of "bucket.h" (minus some unused function declaration)
  12. #include "DuDriver.h"
  13. #include "..\wsdu\Dynamic.h"
  14. extern CDynamicUpdate* g_pDynamicUpdate;
  15. // --------------------------------------------------------------------------------------------
  16. // DLL Exposed function starts here
  17. // --------------------------------------------------------------------------------------------
  18. // --------------------------------------------------------------------------------------------
  19. // Function Name: DuQueryUnsupportedDriversA()
  20. // Function Description: This function is the entry point function of Win9x. It will construct
  21. // the list of PnPId for searching of the web site and call DuDoSetUpItemDetection to get
  22. // other item information
  23. // Return Code: BOOL
  24. // TRUE --- if succeed
  25. // FALSE --- if failed, call GetLastError() to get the extensive error information
  26. //
  27. BOOL DuQueryUnsupportedDriversA (IN HANDLE hConnection, // connection handle
  28. IN PCSTR *ListOfDriversNotOnCD, // multi-sz string array
  29. OUT PDWORD pdwEstimatedTime,
  30. OUT PDWORD pdwEstimatedSize)
  31. {
  32. LOG_block("CDynamicUpdate::DuQueryUnsupportedDriversA");
  33. // parameter validation
  34. if (INVALID_HANDLE_VALUE == hConnection ||
  35. NULL == pdwEstimatedTime ||
  36. NULL == pdwEstimatedSize )
  37. {
  38. LOG_error("Invalid Parameter");
  39. SetLastError(ERROR_INVALID_PARAMETER);
  40. return FALSE;
  41. }
  42. // do setup item detection first
  43. if (NULL == g_pDynamicUpdate)
  44. return FALSE;
  45. DWORD dwRetSetup, dwRetDriver;
  46. dwRetSetup = dwRetDriver = 0;
  47. g_pDynamicUpdate->ClearDownloadItemList();
  48. dwRetSetup = g_pDynamicUpdate->DoSetupUpdateDetection();
  49. if (ERROR_SUCCESS != dwRetSetup)
  50. {
  51. LOG_error("Setup item detection failed --- %d", dwRetSetup);
  52. }
  53. // do driver detection next
  54. // clean up the hardware id list first
  55. g_pDynamicUpdate->m_arrayHardwareId.RemoveAll();
  56. // determine if there are drivers need download
  57. if (ListOfDriversNotOnCD)
  58. {
  59. // iternate the PnPId list and construct the m_arrayHardwareId
  60. PSTR* ListIternator = const_cast<PSTR*>(ListOfDriversNotOnCD);
  61. while (*ListIternator)
  62. {
  63. g_pDynamicUpdate->m_arrayHardwareId.Add(*ListIternator);
  64. ListIternator++;
  65. }
  66. if (!g_pDynamicUpdate->DoWindowsUpdateDriverDetection())
  67. {
  68. dwRetDriver = GetLastError();
  69. LOG_error("Driver detection failed");
  70. }
  71. }
  72. if (dwRetSetup && dwRetDriver)
  73. {
  74. LOG_error("Both Setup item and Driver detection failed");
  75. return FALSE;
  76. }
  77. // determine the download time and download size
  78. if (g_pDynamicUpdate->m_dwDownloadItemCount > 0)
  79. {
  80. g_pDynamicUpdate->UpdateDownloadItemSize();
  81. *pdwEstimatedSize = g_pDynamicUpdate->m_dwTotalDownloadSize; // size in bytes
  82. // Time Estimate is based on roughly how long it took us to download the data files.
  83. if (0 == g_pDynamicUpdate->m_dwDownloadSpeedInBytesPerSecond)
  84. g_pDynamicUpdate->m_dwDownloadSpeedInBytesPerSecond = 2048; // default to 120k per minute, (2048 bytes per second).
  85. *pdwEstimatedTime = g_pDynamicUpdate->m_dwTotalDownloadSize / g_pDynamicUpdate->m_dwDownloadSpeedInBytesPerSecond; // number of seconds
  86. if (*pdwEstimatedTime == 0)
  87. *pdwEstimatedTime = 1; // at least one second
  88. if (dwRetSetup)
  89. SetLastError(dwRetSetup);
  90. if (dwRetDriver)
  91. SetLastError(dwRetDriver);
  92. return TRUE;
  93. }
  94. else
  95. {
  96. // At this point there was no error, but we have no items to download,
  97. SetLastError(ERROR_NO_MORE_ITEMS);
  98. return TRUE;
  99. }
  100. }
  101. // ----------------------------------------------------------------------------------
  102. // member function of CDynamicUpdate starts from here
  103. // ----------------------------------------------------------------------------------
  104. // ----------------------------------------------------------------------------------
  105. // Function Name: DoDriverDetection
  106. // Function Description: This function will detect all the device currently installed
  107. // in the machine and return (via member parameter) a multi-sz string array
  108. // of all the hardware ids and the compatible ids. The array will be NULL
  109. // terminated
  110. // Return Value: BOOL
  111. // TRUE for success
  112. // FALSE for failure, use GetLastError() to retrieve error code
  113. //
  114. BOOL CDynamicUpdate::DoDriverDetection (void) // connection handle
  115. {
  116. // log
  117. LOG_block("DuDoDriverDetection");
  118. // Clean up and previous error code might exist
  119. SetLastError(0);
  120. BOOL fIsPrinterInfo6Supported = FALSE;
  121. // this function will call some setup API which is only supported on a certain
  122. // platform. We will do a platform detection here. If the current platform
  123. // does not support all the setup API we need, bail out.
  124. {
  125. OSVERSIONINFO OsInfo;
  126. ZeroMemory( (PVOID) &OsInfo, sizeof (OsInfo) );
  127. OsInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  128. if (!GetVersionEx( &OsInfo ))
  129. // Function call failed, last error is set by GetVersionEx()
  130. return FALSE;
  131. if ( VER_PLATFORM_WIN32_NT == OsInfo.dwPlatformId )
  132. {
  133. // WinNT, DU driver is supported only from W2K and up
  134. if ( 4 >= OsInfo.dwMajorVersion )
  135. {
  136. // NT 3.51 or NT 4.0
  137. LOG_error("DU driver is not supported on NT 3.51 or NT 4.0");
  138. SetLastError(ERROR_OLD_WIN_VERSION);
  139. return TRUE; // no detection to do, succeed
  140. }
  141. else
  142. // Win2K and beyond
  143. fIsPrinterInfo6Supported = TRUE;
  144. }
  145. else if ( VER_PLATFORM_WIN32_WINDOWS == OsInfo.dwPlatformId )
  146. {
  147. // Win9x, DU driver detection is supported only from Win98 and up
  148. // for Win9x, we should call DuQueryUnsupportedDrivers() instead
  149. // Since this function should also work for Win98 and up, we will
  150. // allow this call
  151. // ROGERJ, october 31th, 2000, remove driver support for win9x platform
  152. //if ( 0 == OsInfo.dwMinorVersion )
  153. //{
  154. // // Win95
  155. // LOG_error("DU driver is not supported on Win95");
  156. // SetLastError(ERROR_OLD_WIN_VERSION);
  157. // return FALSE;
  158. //}
  159. //if (90 <= OsInfo.dwMinorVersion)
  160. // // WinME
  161. // fIsPrinterInfo6Supported = TRUE;
  162. LOG_error("DU driver is not supported on Win9x");
  163. SetLastError(ERROR_OLD_WIN_VERSION);
  164. return TRUE; // no detection to do, succeed
  165. }
  166. else
  167. {
  168. // Win 3.x and below, not supported
  169. LOG_error("DU driver is not supported on Win 3.x");
  170. SetLastError(ERROR_OLD_WIN_VERSION);
  171. return FALSE;
  172. }
  173. }
  174. // Do the driver detection
  175. BOOL fRetValue = TRUE;
  176. // clean up the hardware id list first
  177. m_arrayHardwareId.RemoveAll();
  178. // Get all the device class installed in the machine
  179. HDEVINFO hDeviceInfoSet = INVALID_HANDLE_VALUE;
  180. int nIndex = 0;
  181. SP_DEVINFO_DATA DeviceInfoData;
  182. if ( INVALID_HANDLE_VALUE ==
  183. (hDeviceInfoSet = SetupDiGetClassDevs ( NULL, // class guid
  184. NULL, // enumerator
  185. NULL, // parent window handler
  186. DIGCF_PRESENT|DIGCF_ALLCLASSES))) // all class, device presented
  187. {
  188. // function call failed, error will be set by Setup API
  189. LOG_error("SetupDiGetClassDevs failed --- %d", GetLastError());
  190. return FALSE;
  191. }
  192. // initialize SP_DEVINFO_DATA structure
  193. ZeroMemory((PVOID)&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  194. DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  195. while ( SetupDiEnumDeviceInfo( hDeviceInfoSet, // handle of device info set
  196. nIndex++, // 0 based index
  197. &DeviceInfoData)) // retrieved device info data
  198. {
  199. ULONG uHwidSize, uCompatidSize;
  200. uHwidSize = uCompatidSize = 0;
  201. unsigned char *pszBuffer = NULL;
  202. DWORD dwError = 0;
  203. // get the size needed for hard ware id
  204. if (!SetupDiGetDeviceRegistryProperty( hDeviceInfoSet, // handle of device info set
  205. &DeviceInfoData, // device info data
  206. SPDRP_HARDWAREID, // hardware id
  207. NULL, // reg data type
  208. NULL, // buffer
  209. 0, // buffer size
  210. &uHwidSize)) // out buffer size
  211. {
  212. if (!uHwidSize)
  213. {
  214. // missing a HWID is not catastrophic, we just need to skip this device node
  215. continue;
  216. }
  217. dwError = GetLastError();
  218. if (ERROR_INSUFFICIENT_BUFFER != dwError)
  219. {
  220. LOG_error("SetupDiGetDeviceRegistryProperty 1st call --- %d, skipping device", dwError);
  221. continue;
  222. }
  223. }
  224. if (!SetupDiGetDeviceRegistryProperty( hDeviceInfoSet, // handle of device info set
  225. &DeviceInfoData, // device info data
  226. SPDRP_COMPATIBLEIDS , // compatible ids
  227. NULL, // reg data type
  228. NULL, // buffer
  229. 0, // buffer size
  230. &uCompatidSize) && uCompatidSize) // out buffer size
  231. {
  232. dwError = GetLastError();
  233. if (ERROR_INSUFFICIENT_BUFFER != dwError)
  234. {
  235. LOG_error("SetupDiGetDeviceRegistryProperty 2nd call --- %d, skipping device", dwError);
  236. continue;
  237. }
  238. }
  239. // allocate memory for the multi-sz buffer
  240. pszBuffer = new unsigned char [uHwidSize + uCompatidSize + 2];
  241. if (!pszBuffer)
  242. {
  243. // out of memory
  244. LOG_error("Out of memory");
  245. fRetValue = FALSE;
  246. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  247. goto ErrorReturn;
  248. }
  249. // initiliaze the buffer
  250. ZeroMemory(pszBuffer, sizeof(char)*(uHwidSize + uCompatidSize + 2));
  251. // get the hardware id and compatible id
  252. if (uHwidSize && !SetupDiGetDeviceRegistryProperty( hDeviceInfoSet, // handle of device info set
  253. &DeviceInfoData, // device info data
  254. SPDRP_HARDWAREID, // hardware id
  255. NULL, // reg data type
  256. pszBuffer, // buffer
  257. uHwidSize, // buffer size
  258. NULL)) // out buffer size
  259. {
  260. dwError = GetLastError();
  261. LOG_error("SetupDiGetDeviceRegistryProperty 3rd call --- %d, skipping device", dwError);
  262. if (pszBuffer) delete [] pszBuffer;
  263. pszBuffer = NULL;
  264. continue;
  265. }
  266. if (uCompatidSize)
  267. {
  268. if (!SetupDiGetDeviceRegistryProperty( hDeviceInfoSet, // handle of device info set
  269. &DeviceInfoData, // device info data
  270. SPDRP_COMPATIBLEIDS , // compatible ids
  271. NULL, // reg data type
  272. pszBuffer + uHwidSize -1 , // buffer
  273. uCompatidSize, // buffer size
  274. NULL)) // out buffer size
  275. {
  276. dwError = GetLastError();
  277. LOG_error("SetupDiGetDeviceRegistryProperty 4th call --- %d, skipping device", dwError);
  278. if (pszBuffer) delete [] pszBuffer;
  279. pszBuffer = NULL;
  280. continue;
  281. }
  282. }
  283. // output first hardware id to log file
  284. LOG_out("HardwareID detected --- \"%s\"", pszBuffer);
  285. // Test if the hardwareid we got is on the setup CD or not
  286. if (!IsHardwareIdHasDriversOnCD((char*)pszBuffer))
  287. {
  288. // not on CD
  289. // Add this multi-sz list to our hardware id list
  290. LOG_out("HardwareID added --- \"%s\"", pszBuffer);
  291. m_arrayHardwareId.Add((char*)pszBuffer);
  292. }
  293. else
  294. LOG_out("HardwareID ignored --- \"%s\"", pszBuffer);
  295. // re-initialize SP_DEVINFO_DATA structure
  296. ZeroMemory((PVOID)&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
  297. DeviceInfoData.cbSize = sizeof (SP_DEVINFO_DATA);
  298. if (pszBuffer) delete [] pszBuffer;
  299. pszBuffer = NULL;
  300. } // end of while
  301. if (ERROR_NO_MORE_ITEMS != GetLastError())
  302. {
  303. // Failed other than reach the end of the list
  304. LOG_error("SetupDiEnumDeviceInfo failed --- %d", GetLastError());
  305. fRetValue = FALSE;
  306. }
  307. ErrorReturn:
  308. if ( INVALID_HANDLE_VALUE != hDeviceInfoSet)
  309. SetupDiDestroyDeviceInfoList(hDeviceInfoSet);
  310. if (fIsPrinterInfo6Supported)
  311. DoPrinterDriverDetection();
  312. return fRetValue;
  313. }
  314. // --------------------------------------------------------------------------------------------
  315. // Function Name: IsHardwareIdHasDriversOnCD()
  316. // Function Description: This function take a multi-sz list and determins if any of the hardware
  317. // id in the list is on setup CD.
  318. // Return Code: BOOL
  319. // TRUE --- if any one hardware id is on CD
  320. // FALSE --- if all hardware id is not on CD
  321. //
  322. BOOL CDynamicUpdate::IsHardwareIdHasDriversOnCD(LPCSTR pszHardwareIdList)
  323. {
  324. LOG_block("FilterDriverListFromCD");
  325. // parameter validation
  326. if (NULL == pszHardwareIdList)
  327. {
  328. LOG_error("NULL parameter");
  329. // since the pszHardwareIdList is NULL, which means all the hardwareid (zero) contained in the
  330. // string is on CD, we will return TRUE here
  331. return TRUE;
  332. }
  333. // call the callback function provided by setup to find out if there is a driver for this
  334. // hardware id on CD
  335. PNPID_INFO PnPInfo;
  336. // initialize default state --- device supported, but driver not found
  337. PnPInfo.fHandled = FALSE;
  338. PnPInfo.fUnSupported = FALSE;
  339. DWORD dwSizePnPInfo = (DWORD) sizeof(PNPID_INFO);
  340. if (!(*m_pfnWinNT32Query) ( SETUPQUERYID_PNPID, // query flag
  341. (PVOID)pszHardwareIdList, // multi-SZ list of HardwareId
  342. 0, // sizeof pszHardwarIdList, not used
  343. (PVOID)&PnPInfo,
  344. &dwSizePnPInfo))
  345. {
  346. LOG_error("Callback Function Failed --- %d", GetLastError());
  347. return TRUE; // assume found
  348. }
  349. if (PnPInfo.fUnSupported)
  350. LOG_out("HardwareID unsupported --- \"%s\"", pszHardwareIdList);
  351. if (PnPInfo.fUnSupported || PnPInfo.fHandled)
  352. return TRUE; // device is not supported or driver is found in CD
  353. else
  354. return FALSE; // device is supported and driver is not on CD
  355. }
  356. // ------------------------------------------------------------------------------------------------
  357. // Function Name: DoWindowsUpdateDriverDetection
  358. // Function Description: This function will take the member variable (multi-sz list) for hardware id
  359. // not found in the CD and search for the driver on the site. If found, the function will add
  360. // the file needed to be downloaded into the download list
  361. // Return Code: BOOL
  362. // TRUE --- if successful
  363. // FALSE --- if failed, call GetLastError() to get extensive error information
  364. //
  365. BOOL CDynamicUpdate::DoWindowsUpdateDriverDetection()
  366. {
  367. LOG_block("CDynamicUpdate::DoWindowsUpdateDriverDetection");
  368. BOOL fRetVal = TRUE;
  369. if (!m_pV3->ReadGuidrvINF()) return FALSE;
  370. // no driver presents on the catalog
  371. if (!m_pV3->m_fHasDriver)
  372. {
  373. // need to ping back the drivers
  374. m_arrayHardwareId.ResetIndex();
  375. CMultiSZString* pSZTemp = NULL;
  376. while ( NULL != (pSZTemp = m_arrayHardwareId.GetNextMultiSZString()))
  377. {
  378. if (pSZTemp->IsFound()) continue; // driver found for this device
  379. pSZTemp->ResetIndex();
  380. PingBack(DU_PINGBACK_DRIVERNOTFOUND, 0, pSZTemp->GetNextString(), FALSE);
  381. }
  382. return TRUE;
  383. }
  384. int nNumOfDevNeedDriver = m_arrayHardwareId.GetCount();
  385. int nNumOfTotalPnPIds = m_arrayHardwareId.GetTotalStringCount();
  386. // no driver is needed
  387. if (!nNumOfDevNeedDriver || !nNumOfTotalPnPIds) return TRUE;
  388. // download the bitmap file to memory
  389. PCDM_HASHTABLE pBitMap = NULL;
  390. DWORD dwLength = 0;
  391. DWORD dwError = 0;
  392. UINT *pnHashList = NULL;
  393. int nIdCount = 0;
  394. int nCount = 0;
  395. CMultiSZString* pTemp = NULL;
  396. PDRIVER_DOWNLOAD_INFO* pPlaceHolder = NULL;
  397. int nPlaceHolderIndex = 0;
  398. int nTempHolderIndex = 0;
  399. char szBmpRelativeName[MAX_PATH];
  400. ZeroMemory(szBmpRelativeName, MAX_PATH*sizeof(char));
  401. wsprintfA(szBmpRelativeName, "%d/inventory.cdm", m_pV3->m_puidConsumerCatalog);
  402. // get the bitmap file name on server
  403. char szServerBitMapFileName [INTERNET_MAX_URL_LENGTH];
  404. ZeroMemory(szServerBitMapFileName, INTERNET_MAX_URL_LENGTH*sizeof(char));
  405. DuUrlCombine(szServerBitMapFileName, m_pV3->m_szV31ContentUrl, szBmpRelativeName);
  406. // down load bitmap file to pBitMap
  407. dwError = DownloadFileToMem( szServerBitMapFileName, // server file name
  408. (PBYTE*) &pBitMap, // buffer, OUT
  409. & dwLength, // buffer length, OUT
  410. TRUE, // try to decompress
  411. "inventory.cdm",
  412. NULL);
  413. if (ERROR_SUCCESS != dwError)
  414. {
  415. // download failed
  416. LOG_error("Download bitmask.cdm failed --- %d", dwError);
  417. fRetVal = FALSE;
  418. goto CleanUp;
  419. }
  420. // allocate memory for hash list
  421. pnHashList = new UINT [nNumOfTotalPnPIds];
  422. if (!pnHashList)
  423. {
  424. LOG_error("Out of memory");
  425. SetLastError(ERROR_OUTOFMEMORY);
  426. fRetVal = FALSE;
  427. goto CleanUp;
  428. }
  429. ZeroMemory(pnHashList, nNumOfTotalPnPIds*sizeof(UINT));
  430. // allocate memory for place holder list
  431. pPlaceHolder = (PDRIVER_DOWNLOAD_INFO*) GlobalAlloc(GMEM_ZEROINIT, nNumOfDevNeedDriver * sizeof (PDRIVER_DOWNLOAD_INFO));
  432. if (!pPlaceHolder)
  433. {
  434. LOG_error("Out of memory");
  435. SetLastError(ERROR_OUTOFMEMORY);
  436. fRetVal = FALSE;
  437. goto CleanUp;
  438. }
  439. m_arrayHardwareId.ResetIndex();
  440. // go through every device that has no driver on the CD
  441. for (nCount = 0; nCount<nNumOfDevNeedDriver; nCount++)
  442. {
  443. pTemp = m_arrayHardwareId.GetNextMultiSZString();
  444. // error!
  445. if (!pTemp) break;
  446. // get each string from the multi-sz string
  447. pTemp->ResetIndex();
  448. LPCTSTR pTempId = pTemp->GetNextString();
  449. while (*pTempId)
  450. {
  451. // Log
  452. LOG_out("Searching driver for HardwareID --- %s", pTempId);
  453. // get the hashed id list
  454. UINT uHashValue = CDM_HwID2Hash(pTempId, pBitMap->hdr.iTableSize);
  455. if (!uHashValue)
  456. {
  457. // uHashValue is 0, could be an error condition, need to call GetLastError() to determine
  458. dwError = GetLastError();
  459. if (ERROR_SUCCESS != dwError)
  460. {
  461. // Error happened
  462. LOG_error("Invalid Hash Value --- %d", dwError);
  463. // try next hardware id
  464. pTempId = pTemp->GetNextString();
  465. continue;
  466. }
  467. }
  468. // find out if a hash value exists in the bitmap
  469. if (0 != ((pBitMap->pData)[(uHashValue/8)] & (0x80 >> (uHashValue%8))))
  470. {
  471. // Log
  472. LOG_out ("Bucket file %d", uHashValue);
  473. // match found, add to pnHashList
  474. // check see if the same hash already in the list, if not, add it to the list
  475. int k;
  476. for (k = 0; k<nIdCount; k++)
  477. if (uHashValue == pnHashList[k]) break;
  478. if (k >= nIdCount)
  479. pnHashList[nIdCount++] = uHashValue;
  480. }
  481. pTempId = pTemp->GetNextString();
  482. }
  483. }
  484. // now we got all the bucket file number we need to download
  485. for (nCount = 0; nCount < nIdCount; nCount++)
  486. {
  487. // read bucket file
  488. char szBucketFileName[MAX_PATH];
  489. ZeroMemory(szBucketFileName, MAX_PATH*sizeof(char));
  490. char szServerBKFFullName [INTERNET_MAX_URL_LENGTH];
  491. ZeroMemory(szServerBKFFullName, INTERNET_MAX_URL_LENGTH*sizeof(char));
  492. // get bucket file name without the URL
  493. wsprintfA(szBucketFileName, "%d/%d.bkf", m_pV3->m_puidConsumerCatalog, pnHashList[nCount]);
  494. // get bucket file name with URL
  495. DuUrlCombine(szServerBKFFullName, m_pV3->m_szV31ContentUrl, szBucketFileName);
  496. // reset szBucketFileName to local bucket file name
  497. wsprintfA(szBucketFileName,"%d.bkf", pnHashList[nCount]);
  498. // download bucket file to memory
  499. LOG_out("Download bucket file %s", szBucketFileName);
  500. PBYTE pBKFFile = NULL;
  501. dwError = DownloadFileToMem(szServerBKFFullName, // server file name
  502. &pBKFFile, // buffer
  503. &dwLength, // buffer length
  504. TRUE, // try to decompress
  505. szBucketFileName,
  506. NULL);
  507. if (ERROR_SUCCESS != dwError)
  508. {
  509. LOG_error("Failed to download %s --- %d", szBucketFileName, dwError);
  510. if (pBKFFile) GlobalFree(pBKFFile);
  511. fRetVal = FALSE;
  512. goto CleanUp;
  513. }
  514. // download each bucket file and parse the bucket file to get the correct cabinet file
  515. UINT uBKFIndex = 0;
  516. while ( uBKFIndex < dwLength )
  517. {
  518. PCDM_RECORD_HEADER pCdmHeader = (PCDM_RECORD_HEADER) (pBKFFile + uBKFIndex);
  519. if (!m_pV3->IsPUIDExcluded(pCdmHeader->puid))
  520. {
  521. LPCSTR pTempHardwareid = (LPCSTR) ((PBYTE)pCdmHeader + sizeof(CDM_RECORD_HEADER));
  522. LPCSTR pRememberedHWID = pTempHardwareid;
  523. // parse the bucket file to find a PnPId match
  524. // only get the hardware id, we don't care about any other information for DU, thus, we
  525. // don't need to parse them
  526. PosIndex PI;
  527. if (m_arrayHardwareId.PositionIndex (pTempHardwareid, &PI))
  528. {
  529. LOG_out("HardwareID '%s' found in bucket file '%s'", pTempHardwareid, szBucketFileName);
  530. // prune by locale
  531. if (!GETBIT(m_pV3->m_pBitMaskCDM, pCdmHeader->nBitmaskIdx))
  532. {
  533. // masked out
  534. LOG_out("HardwareID %s is masked out.", pTempHardwareid);
  535. }
  536. else
  537. {
  538. // match found
  539. // first get necessary infomation
  540. // get DriverVer
  541. for (int t=0; t<4; t++)
  542. {
  543. pTempHardwareid += (lstrlenA(pTempHardwareid) + 1);
  544. }
  545. // now pTempHardwareid points to szDriverVer
  546. // DriverVer is of format mm/dd/yyyy, change it into a number
  547. // we set every month to 31 day, every year to 31 *12 days are construct
  548. // a number start for 01/01/1998
  549. int nTempYear = (pTempHardwareid[6]-'0')*1000 +(pTempHardwareid[7]-'0')*100 +
  550. (pTempHardwareid[8]-'0')*10 +(pTempHardwareid[9]-'0');
  551. int nTempMonth = (pTempHardwareid[0]-'0')*10+pTempHardwareid[1]-'0';
  552. int nTempDay = (pTempHardwareid[3]-'0')*10+pTempHardwareid[4]-'0';
  553. // no driver in windows update database has a date earlier than 1999.
  554. // set to 1998 as the earliest date.
  555. // NOTE: this will still work for drivers before 1998
  556. int nTempDriverVer = (nTempYear - 1998)*31*12 + (nTempMonth-1)*31 +(nTempDay-1);
  557. // get the cabinet file name
  558. // now pTempHardwareid points to pszCabFileTitle
  559. pTempHardwareid += (lstrlenA(pTempHardwareid) + 1);
  560. char szAltName[MAX_PATH];
  561. ZeroMemory(szAltName, MAX_PATH*sizeof(char));
  562. // third see if the driver is excluded by guidrvs.inf
  563. if (m_pV3->GetAltName(pTempHardwareid, szAltName, MAX_PATH)
  564. && !m_pV3->IsDriverExcluded(szAltName, pRememberedHWID))
  565. {
  566. // third, determine if a better match is already in the place holder
  567. BOOL fFound = FALSE;
  568. for (nTempHolderIndex = 0; nTempHolderIndex < nPlaceHolderIndex; nTempHolderIndex++)
  569. {
  570. if ((pPlaceHolder[nTempHolderIndex]->Position.x == PI.x))
  571. {
  572. // Driver for same device is found
  573. fFound = TRUE;
  574. if (pPlaceHolder[nTempHolderIndex]->Position.y < PI.y)
  575. {
  576. // a better matched driver is already in the place holder list
  577. // do nothing
  578. LOG_out("A better matched is already found");
  579. }
  580. else if (pPlaceHolder[nTempHolderIndex]->Position.y > PI.y)
  581. {
  582. // a worse matched driver is already in the place holder list
  583. // replace it
  584. pPlaceHolder[nTempHolderIndex]->Position.x = PI.x;
  585. pPlaceHolder[nTempHolderIndex]->Position.y = PI.y;
  586. pPlaceHolder[nTempHolderIndex]->nDriverVer = nTempDriverVer;
  587. pPlaceHolder[nTempHolderIndex]->puid = pCdmHeader->puid;
  588. lstrcpy(pPlaceHolder[nTempHolderIndex]->szCabFile, pTempHardwareid);
  589. LOG_out("Replaced an old match");
  590. }
  591. else
  592. {
  593. LOG_out("Same match found, need to compare DriverVer");
  594. // need to compare DriverVer for the same match
  595. if (nTempDriverVer > pPlaceHolder[nTempHolderIndex]->nDriverVer)
  596. {
  597. // older driver in the list
  598. // replace it
  599. pPlaceHolder[nTempHolderIndex]->Position.x = PI.x;
  600. pPlaceHolder[nTempHolderIndex]->Position.y = PI.y;
  601. pPlaceHolder[nTempHolderIndex]->nDriverVer = nTempDriverVer;
  602. pPlaceHolder[nTempHolderIndex]->puid = pCdmHeader->puid;
  603. lstrcpy(pPlaceHolder[nTempHolderIndex]->szCabFile, pTempHardwareid);
  604. LOG_out("Replaced an old match");
  605. }
  606. else
  607. LOG_out("A better matched is already found");
  608. }
  609. break;
  610. }
  611. }
  612. if (!fFound)
  613. {
  614. m_arrayHardwareId.CheckFound(PI.x); // mark as found
  615. // not found, new entry
  616. PDRIVER_DOWNLOAD_INFO pNewHolder = new DRIVER_DOWNLOAD_INFO;
  617. if (!pNewHolder)
  618. {
  619. LOG_error("Out of memory");
  620. SetLastError(ERROR_OUTOFMEMORY);
  621. fRetVal = FALSE;
  622. goto CleanUp;
  623. }
  624. pNewHolder->Position.x = PI.x;
  625. pNewHolder->Position.y = PI.y;
  626. pNewHolder->nDriverVer = nTempDriverVer;
  627. pNewHolder->puid = pCdmHeader->puid;
  628. lstrcpy(pNewHolder->szCabFile, pTempHardwareid);
  629. // add to list
  630. pPlaceHolder[nPlaceHolderIndex++] = pNewHolder;
  631. LOG_out("New match found, add to download list");
  632. }
  633. }
  634. }
  635. }
  636. }
  637. uBKFIndex += pCdmHeader->cnRecordLength; // move to next record
  638. }
  639. // free bucket file memory
  640. SafeGlobalFree(pBKFFile);
  641. pBKFFile = NULL;
  642. }
  643. // now we have a list of driver in pPlaceHolder that are best for this machine
  644. // add all to download list
  645. for (nTempHolderIndex=0; nTempHolderIndex<nPlaceHolderIndex; nTempHolderIndex++)
  646. {
  647. // fill in the download item structure
  648. DOWNLOADITEM* pDownloadDriver = (DOWNLOADITEM*) GlobalAlloc(GMEM_ZEROINIT, sizeof(DOWNLOADITEM));
  649. if (!pDownloadDriver)
  650. {
  651. LOG_error("Out of memory");
  652. SetLastError(ERROR_OUTOFMEMORY);
  653. fRetVal = FALSE;
  654. goto CleanUp;
  655. }
  656. lstrcpyA(pDownloadDriver->mszFileList, pPlaceHolder[nTempHolderIndex]->szCabFile);
  657. pDownloadDriver->iNumberOfCabs = 1; // always 1 cab 1 driver
  658. pDownloadDriver->puid = pPlaceHolder[nTempHolderIndex]->puid;
  659. char pszDownloadUrl [INTERNET_MAX_URL_LENGTH];
  660. ZeroMemory(pszDownloadUrl, INTERNET_MAX_URL_LENGTH*sizeof(char));
  661. DuUrlCombine(pszDownloadUrl, m_pV3->m_szCabPoolUrl, pPlaceHolder[nTempHolderIndex]->szCabFile);
  662. dwError = OpenHttpConnection(pszDownloadUrl, FALSE);
  663. if (ERROR_SUCCESS != dwError)
  664. {
  665. // Log error
  666. LOG_error("Failed to open internet connection --- %d", dwError);
  667. pDownloadDriver->dwTotalFileSize = 102400; // default to 100k
  668. continue;
  669. }
  670. // get file size from HTTP header
  671. DWORD dwQueryLength = sizeof(DWORD);
  672. if (! HttpQueryInfoA(m_hOpenRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
  673. (LPVOID)&pDownloadDriver->dwTotalFileSize , &dwQueryLength, NULL) )
  674. {
  675. dwError = GetLastError();
  676. LOG_error("HttpQueryInfo Failed on File %s, Error %d", pszDownloadUrl, dwError);
  677. pDownloadDriver->dwTotalFileSize = 102400; // default to 100k
  678. }
  679. SafeInternetCloseHandle(m_hOpenRequest);
  680. // Add the new item into download item list
  681. EnterDownloadListCriticalSection();
  682. AddDownloadItemToList(pDownloadDriver);
  683. LeaveDownloadListCriticalSection();
  684. }
  685. // we need to ping the pnpid back for all the devices what does not has a driver found
  686. m_arrayHardwareId.ResetIndex();
  687. CMultiSZString* pSZTemp = NULL;
  688. while ( NULL != (pSZTemp = m_arrayHardwareId.GetNextMultiSZString()))
  689. {
  690. if (pSZTemp->IsFound()) continue; // driver found for this device
  691. pSZTemp->ResetIndex();
  692. PingBack(DU_PINGBACK_DRIVERNOTFOUND, 0, pSZTemp->GetNextString(), FALSE);
  693. }
  694. CleanUp:
  695. PlaceHolderCleanUp(pPlaceHolder, nNumOfDevNeedDriver);
  696. SafeGlobalFree(pPlaceHolder);
  697. SafeGlobalFree(pBitMap);
  698. if (pnHashList) delete [] pnHashList;
  699. return fRetVal;
  700. }
  701. // Utility function starts here
  702. //These functions form a hash lookup for hwIDs.
  703. static ULONG HashFunction(
  704. IN ULONG seed //Seed value to use for hashing hwid.
  705. ) {
  706. ULONG q;
  707. ULONG r;
  708. ULONG a;
  709. ULONG m;
  710. ULONG val;
  711. q = 127773L;
  712. r = 2836L;
  713. a = 16807L;
  714. m = 2147483647;
  715. val = ((seed % q) * a) - (seed / q) * r;
  716. if(((long)val) <= 0)
  717. val = val + m;
  718. return val;
  719. }
  720. //These functions form a hash lookup for hwIDs.
  721. ULONG CDM_HwID2Hash(
  722. IN LPCSTR szHwID, //Hardware id being hashed.
  723. IN ULONG iTableSize //Size of downloaded hash table.
  724. ) {
  725. SetLastError(0);
  726. if (0 == iTableSize)
  727. {
  728. SetLastError(ERROR_INVALID_DATA);
  729. return 0; // error
  730. }
  731. ULONG ulHashIndex = 1;
  732. while(*szHwID)
  733. {
  734. if (*szHwID > 127 || *szHwID < 0)
  735. {
  736. // an extended ANSCII value, not valid
  737. SetLastError(ERROR_INVALID_DATA);
  738. return 0;
  739. }
  740. ulHashIndex = ulHashIndex + HashFunction(ulHashIndex + (ULONG)(INT_PTR)CharUpper((LPSTR)*szHwID));
  741. szHwID++;
  742. }
  743. return (ulHashIndex % iTableSize);
  744. }
  745. // ------------------------------------------------------------------------------------
  746. // Function Name: DoPrinterDriverDetection
  747. // Function Description: This function will detect all locally installed printer and add
  748. // the printer Hwid into out device list
  749. // Return Value: BOOL
  750. // TRUE for succeed
  751. // FALSE for failure
  752. BOOL CDynamicUpdate::DoPrinterDriverDetection()
  753. {
  754. LOG_block("CDynamicUpdate::DoPrinterDriverDetection()");
  755. // Get Printers' Hwid
  756. // Note: This method only worked on Win2K / WinME. If we are at other 9x, printer will not be supported
  757. // by this function
  758. DWORD nBytesNeeded;
  759. DWORD nDriverRetrieved;
  760. DWORD dwError;
  761. nBytesNeeded = nDriverRetrieved = dwError = 0;
  762. BYTE *pBuffer = NULL;
  763. BOOL fRetValue = FALSE;
  764. DRIVER_INFO_6 * pPrinterInfo = NULL;
  765. if (!EnumPrinterDriversA(NULL, // only enum local drivers
  766. NULL, // use default enviroment
  767. 6, // use DRIVER_INFO_6
  768. NULL, // no out information
  769. 0, // out buffer is zero
  770. &nBytesNeeded,
  771. &nDriverRetrieved ))
  772. {
  773. if (ERROR_INSUFFICIENT_BUFFER != (dwError = GetLastError()))
  774. {
  775. // Failed
  776. LOG_error("EnumPrinterDrivers 1st call failed --- %d",dwError);
  777. goto ErrorReturn;
  778. }
  779. }
  780. if (!nBytesNeeded)
  781. LOG_out("No local printers for this machine");
  782. else
  783. {
  784. pBuffer = new BYTE [nBytesNeeded];
  785. int nCount = 0;
  786. if (!pBuffer)
  787. {
  788. LOG_error("Insufficient memory when locating printer string");
  789. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  790. goto ErrorReturn;
  791. }
  792. // get printer driver information;
  793. if (!EnumPrinterDriversA( NULL, // only enum local drivers
  794. NULL, // use default enviroment
  795. 6, // use DRIVER_INFO_6
  796. pBuffer, // no out information
  797. nBytesNeeded, // out buffer is zero
  798. &nBytesNeeded,
  799. &nDriverRetrieved ))
  800. {
  801. if (ERROR_INSUFFICIENT_BUFFER != (dwError = GetLastError()))
  802. {
  803. // Failed
  804. LOG_error("EnumPrinterDrivers 1st call failed --- %d",dwError);
  805. goto ErrorReturn;
  806. }
  807. }
  808. // get individual hwid
  809. for (nCount=0; nCount<(int)nDriverRetrieved; nCount++)
  810. {
  811. pPrinterInfo = &((DRIVER_INFO_6*)pBuffer)[nCount];
  812. // record printer driver information
  813. // output printer hardware id to log file
  814. LOG_out("HardwareID detected --- \"%s\"", pPrinterInfo->pszHardwareID);
  815. // Test if the hardwareid we got is on the setup CD or not
  816. if (!IsHardwareIdHasDriversOnCD((char*)pPrinterInfo->pszHardwareID))
  817. {
  818. // not on CD
  819. // Add this multi-sz list to our hardware id list
  820. LOG_out("HardwareID added --- \"%s\"", pPrinterInfo->pszHardwareID);
  821. // for Windows Update, we need fake the printer id as
  822. // orignial_id&manufacteur&name&provider to distinguish between monolithic and unidriver
  823. int nSizeOfFakeId = lstrlenA(pPrinterInfo->pszHardwareID) +
  824. lstrlenA(pPrinterInfo->pszMfgName) +
  825. lstrlenA(pPrinterInfo->pName) +
  826. lstrlenA(pPrinterInfo->pszProvider) + 3 + 2; // 3 for 3 & sign, 2 for double NULL termination
  827. char* szFakeId = new char [nSizeOfFakeId];
  828. if (!szFakeId)
  829. {
  830. LOG_error("Out of memory");
  831. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  832. goto ErrorReturn;
  833. }
  834. ZeroMemory(szFakeId, nSizeOfFakeId * sizeof(char));
  835. lstrcpyA(szFakeId,pPrinterInfo->pszHardwareID);
  836. lstrcatA(szFakeId,"&");
  837. lstrcatA(szFakeId,pPrinterInfo->pszMfgName);
  838. lstrcatA(szFakeId,"&");
  839. lstrcatA(szFakeId,pPrinterInfo->pName);
  840. lstrcatA(szFakeId,"&");
  841. lstrcatA(szFakeId,pPrinterInfo->pszProvider);
  842. // Add to hardware id list
  843. m_arrayHardwareId.Add(szFakeId);
  844. delete [] szFakeId;
  845. }
  846. }
  847. }
  848. fRetValue = TRUE;
  849. ErrorReturn:
  850. if (pBuffer) delete [] pBuffer;
  851. return fRetValue;
  852. }
  853. void PlaceHolderCleanUp(PDRIVER_DOWNLOAD_INFO* pTemp, int nTotal)
  854. {
  855. if (NULL == pTemp)
  856. return;
  857. for (int i=0; i<nTotal; i++)
  858. {
  859. if (pTemp[i])
  860. {
  861. PDRIVER_DOWNLOAD_INFO pDelete = pTemp[i];
  862. delete pDelete;
  863. }
  864. else
  865. break;
  866. }
  867. }