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.

1126 lines
36 KiB

  1. #include "wsdueng.h"
  2. #define IDENT_SECTION_CABPOOL "cabpools"
  3. #define IDENT_SECTION_CONTENT31 "content31"
  4. #define IDENT_KEYNAME_DEFAULT "default"
  5. #define IDENT_KEYNAME_ROOT "root"
  6. CV31Server::CV31Server(CDynamicUpdate *pDu) : m_puidConsumerCatalog(0),
  7. m_puidSetupCatalog(0),
  8. m_dwPlatformID(0),
  9. m_lcidLocaleID(0),
  10. m_dwConsumerItemCount(0),
  11. m_pConsumerCatalog(NULL),
  12. m_dwSetupItemCount(0),
  13. m_pSetupCatalog(NULL),
  14. m_dwGlobalExclusionItemCount(0),
  15. m_pDu(pDu)
  16. {
  17. // set the initial state
  18. m_dwPlatformID = (DWORD)m_pDu->m_iPlatformID;
  19. m_lcidLocaleID = m_pDu->m_lcidLocaleID;
  20. if (0 == m_pDu->m_wPlatformSKU) // Professional
  21. {
  22. m_enumPlatformSKU = enWhistlerProfessional;
  23. }
  24. else if (m_pDu->m_wPlatformSKU & VER_SUITE_DATACENTER) // DataCenter
  25. {
  26. m_enumPlatformSKU = enWhistlerDataCenter;
  27. }
  28. else if (m_pDu->m_wPlatformSKU & VER_SUITE_PERSONAL) // Personal
  29. {
  30. m_enumPlatformSKU = enWhistlerConsumer;
  31. }
  32. else if (m_pDu->m_wPlatformSKU & VER_SUITE_ENTERPRISE) // Advanced Server
  33. {
  34. m_enumPlatformSKU = enWhistlerAdvancedServer;
  35. }
  36. else if (m_pDu->m_wPlatformSKU & VER_SUITE_SMALLBUSINESS) // Server
  37. {
  38. m_enumPlatformSKU = enWhistlerServer;
  39. }
  40. // RogerJ October 25th, 2000
  41. m_pValidDependentPUIDArray = NULL;
  42. m_nNumOfValidDependentPUID = 0;
  43. m_pBitMaskAS = m_pBitMaskCDM = NULL;
  44. m_fHasDriver = FALSE;
  45. m_pszExcludedDriver = NULL;
  46. }
  47. CV31Server::~CV31Server()
  48. {
  49. FreeCatalogs(); // clears the m_pConsumerItems and m_pSetupItems Varrays.
  50. SafeGlobalFree(m_pConsumerCatalog);
  51. SafeGlobalFree(m_pSetupCatalog);
  52. // RogerJ, October 25th, 2000
  53. SafeGlobalFree(m_pValidDependentPUIDArray);
  54. SafeGlobalFree(m_pBitMaskAS);
  55. SafeGlobalFree(m_pBitMaskCDM);
  56. SafeGlobalFree(m_pszExcludedDriver);
  57. }
  58. // ----------------------------------------------------------------------------------
  59. // V3.1 Backend Server Apis
  60. //
  61. //
  62. BOOL CV31Server::ReadIdentInfo()
  63. {
  64. // ident.cab should already be downloaded at this point. Get the path to it and read the fields we care about
  65. char szIdent[MAX_PATH];
  66. char szValueName[32];
  67. int iServerNumber;
  68. char szUrl[INTERNET_MAX_URL_LENGTH + 1];
  69. PathCombine(szIdent, m_pDu->GetDuTempPath(), "ident.txt");
  70. // --------------------
  71. // Get the CABPOOL URL
  72. // --------------------
  73. iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CABPOOL, IDENT_KEYNAME_DEFAULT, 1, szIdent);
  74. wsprintf(szValueName, "Server%d", iServerNumber);
  75. GetPrivateProfileString(IDENT_SECTION_CABPOOL, szValueName, "", szUrl, sizeof(szUrl), szIdent);
  76. if ('\0' == szUrl[0])
  77. {
  78. // No Server Value was found in the ident. Cannot continue;
  79. SetLastError(ERROR_FILE_NOT_FOUND);
  80. return FALSE;
  81. }
  82. // The cabpool URL is the string in the Ident + 'cabpool'
  83. m_pDu->DuUrlCombine(m_szCabPoolUrl, szUrl, "CabPool");
  84. // --------------------
  85. // Get the CONTENT URL
  86. // --------------------
  87. iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CONTENT31, IDENT_KEYNAME_DEFAULT, 1, szIdent);
  88. wsprintf(szValueName, "Server%d", iServerNumber);
  89. GetPrivateProfileString(IDENT_SECTION_CONTENT31, szValueName, "", szUrl, sizeof(szUrl), szIdent);
  90. if ('\0' == szUrl[0])
  91. {
  92. // No Server Value
  93. SetLastError(ERROR_FILE_NOT_FOUND);
  94. return FALSE;
  95. }
  96. lstrcpy(m_szV31ContentUrl, szUrl);
  97. // -------------------------
  98. // Get the CONTENT ROOT URL
  99. // -------------------------
  100. iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CONTENT31, IDENT_KEYNAME_ROOT, 2, szIdent);
  101. wsprintf(szValueName, "Server%d", iServerNumber);
  102. GetPrivateProfileString(IDENT_SECTION_CONTENT31, szValueName, "", szUrl, sizeof(szUrl), szIdent);
  103. if ('\0' == szUrl[0])
  104. {
  105. // No Root Server Value
  106. SetLastError(ERROR_FILE_NOT_FOUND);
  107. return FALSE;
  108. }
  109. lstrcpy(m_szV31RootUrl, szUrl);
  110. return TRUE;
  111. }
  112. BOOL CV31Server::ReadCatalogINI()
  113. {
  114. LOG_block("CV31Server::ReadCatalogINI()");
  115. char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
  116. char szLocalFile[MAX_PATH];
  117. char szValue[1024];
  118. // Now read the Catalog.ini file to find out if any of these items needs to be turned off
  119. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, CATALOGINIFN);
  120. PathCombineA(szLocalFile, m_pDu->GetDuTempPath(), CATALOGINIFN);
  121. if (ERROR_SUCCESS != m_pDu->DownloadFile(szServerFile, szLocalFile, FALSE, FALSE))
  122. {
  123. LOG_out("No catalog.ini found");
  124. return TRUE;
  125. }
  126. if (0 != (GetPrivateProfileStringA("exclude", "puids", "", szValue, sizeof(szValue), szLocalFile)))
  127. {
  128. LPCSTR pszNext = szValue;
  129. char szPuid[128];
  130. while (NULL != pszNext)
  131. {
  132. pszNext = strcpystr(pszNext, ",", szPuid);
  133. if ('\0' != szPuid[0])
  134. {
  135. m_GlobalExclusionArray[m_dwGlobalExclusionItemCount] = StrToIntA(szPuid);
  136. LOG_out("Excluded puid --- %d", m_GlobalExclusionArray[m_dwGlobalExclusionItemCount]);
  137. m_dwGlobalExclusionItemCount++;
  138. }
  139. }
  140. }
  141. else
  142. LOG_out("No Excluded puid");
  143. return TRUE;
  144. }
  145. BOOL CV31Server::GetCatalogPUIDs()
  146. {
  147. LOG_block("CV31Server::GetCatalogPUIDs()");
  148. // There are two v3 catalogs that we will be looking for the PUID's for..
  149. // One is the Consumer Catalog for the target platform
  150. // The other is the Setup Catalog for the target platform
  151. char szServerFile[INTERNET_MAX_URL_LENGTH];
  152. PBYTE pCatalogList = NULL;
  153. PBYTE pInventoryList = NULL;
  154. PBYTE pWalkList = NULL;
  155. DWORD dwLength;
  156. m_puidConsumerCatalog = 0;
  157. m_puidSetupCatalog = 0;
  158. // Download the Catalog Inventory List
  159. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, "inventory.plt");
  160. m_pDu->DownloadFileToMem(szServerFile, &pInventoryList, &dwLength, TRUE, "inventory.plt", NULL);
  161. if (NULL == pInventoryList)
  162. {
  163. // error out of memory
  164. return FALSE;
  165. }
  166. // Download the CatalogList
  167. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, "inventory.cat");
  168. m_pDu->DownloadFileToMem(szServerFile, &pCatalogList, &dwLength, TRUE, "inventory.cat", NULL);
  169. if (NULL == pCatalogList)
  170. {
  171. // error out of memory
  172. SafeGlobalFree(pInventoryList);
  173. return FALSE;
  174. }
  175. // Now Parse the Inventory List to Find out how many catalogs there are.
  176. int i;
  177. WU_CATALOG_HEADER hdr;
  178. memcpy(&hdr, pInventoryList, sizeof(hdr));
  179. pWalkList = pCatalogList;
  180. CATALOGLIST catListElem;
  181. for (i = 0; i < hdr.totalItems; i++)
  182. {
  183. memcpy(&catListElem, pWalkList, sizeof(catListElem));
  184. if (catListElem.dwPlatform == m_dwPlatformID)
  185. {
  186. // standard catalog is 0, thus, standard catalog with driver will have same value as driver only
  187. if ((CATLIST_DRIVERSPRESENT == catListElem.dwFlags) || (catListElem.dwFlags == (CATLIST_DRIVERSPRESENT | CATLIST_64BIT)))
  188. {
  189. // consumer catalog for this platform
  190. m_puidConsumerCatalog = catListElem.dwCatPuid;
  191. }
  192. else if (catListElem.dwFlags & CATLIST_SETUP)
  193. {
  194. // setup catalog for this platform
  195. m_puidSetupCatalog = catListElem.dwCatPuid;
  196. if (0 == m_puidConsumerCatalog && (catListElem.dwFlags & CATLIST_DRIVERSPRESENT))
  197. m_puidConsumerCatalog = catListElem.dwCatPuid;
  198. }
  199. }
  200. pWalkList += sizeof(catListElem);
  201. }
  202. if (!m_puidConsumerCatalog && ! m_puidSetupCatalog)
  203. {
  204. SetLastError(ERROR_INTERNET_NO_CONTEXT);
  205. SafeGlobalFree(pInventoryList);
  206. SafeGlobalFree(pCatalogList);
  207. return FALSE; // this technically is an error.. wrong server was pointed to? Catalogs weren't on the server
  208. }
  209. SafeGlobalFree(pInventoryList);
  210. SafeGlobalFree(pCatalogList);
  211. LOG_out("Consumer catalog %d, Setup catalog %d", m_puidConsumerCatalog, m_puidSetupCatalog);
  212. return TRUE;
  213. }
  214. BOOL CV31Server::GetCatalogs()
  215. {
  216. // This will download the two Catalogs (Setup and Consumer) and the InventoryItem Arrays
  217. LOG_block("CV31Server::GetCatalogs()");
  218. DWORD dwRet;
  219. int i;
  220. char szServerFile[INTERNET_MAX_URL_LENGTH];
  221. char szLocalFile[MAX_PATH];
  222. char szCatalog[MAX_PATH];
  223. char szInvCRC[64];
  224. char szBmCRC[64];
  225. char szLocale[32];
  226. PBYTE pWalkCatalog = NULL;
  227. WU_CATALOG_HEADER hdr;
  228. PINVENTORY_ITEM pItem;
  229. BOOL fDriversAvailable = FALSE;
  230. DWORD dwLength;
  231. wsprintf(szLocale, "0x%8.8x", m_lcidLocaleID);
  232. FreeCatalogs(); // free any previously allocated catalog lists
  233. SafeGlobalFree(m_pValidDependentPUIDArray); // free any previously determined dependency list
  234. m_pValidDependentPUIDArray = NULL;
  235. m_nNumOfValidDependentPUID = 0;
  236. // Read the Catalog.INI to get a list of Globally Excluded Items
  237. if (0 != m_puidConsumerCatalog)
  238. {
  239. // Download the Consumer Catalog for this Platform
  240. // first we need to download the redirect file to get the CRC value of the catalog
  241. wsprintf(szCatalog, "%d/%s.as", m_puidConsumerCatalog, szLocale);
  242. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
  243. wsprintf(szCatalog, "%d_%s.as", m_puidConsumerCatalog, szLocale);
  244. PathCombine(szLocalFile, m_pDu->GetDuTempPath(), szCatalog);
  245. m_pDu->DownloadFile(szServerFile, szLocalFile, TRUE, FALSE);
  246. if (GetPrivateProfileString("redir", "invCRC", "", szInvCRC, sizeof(szInvCRC), szLocalFile) == 0)
  247. {
  248. LOG_error("Unable to Read Inventory CRC value from Consumer Catalog");
  249. return FALSE;
  250. }
  251. // does not need this for consumer catalog
  252. /*if (GetPrivateProfileString("redir", "bmCRC", "", szBmCRC, sizeof(szBmCRC), szLocalFile) == 0)
  253. {
  254. LOG_error("Unable to Read Bitmask CRC value for Consumer Catalog");
  255. return FALSE;
  256. }*/
  257. if (!GetBitMask("bitmask.cdm", m_puidConsumerCatalog, &m_pBitMaskCDM, "bitmask.cdm"))
  258. {
  259. LOG_error("Unable to get bitmask for CDM");
  260. return FALSE;
  261. }
  262. // now download the real catalog
  263. wsprintf(szCatalog, "%d/%s.inv", m_puidConsumerCatalog, szInvCRC);
  264. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
  265. SafeGlobalFree(m_pConsumerCatalog);
  266. wsprintf(szCatalog, "%s.inv", szInvCRC);
  267. m_pDu->DownloadFileToMem(szServerFile, &m_pConsumerCatalog, &dwLength, TRUE, szCatalog, "inventory.as");
  268. if (NULL == m_pConsumerCatalog)
  269. {
  270. LOG_error("Failed to download Consumer Catalog, %d", m_puidConsumerCatalog);
  271. return FALSE;
  272. }
  273. pWalkCatalog = m_pConsumerCatalog;
  274. // Read the Catalog Header
  275. ZeroMemory(&hdr, sizeof(hdr));
  276. memcpy(&hdr, pWalkCatalog, sizeof(hdr));
  277. m_pConsumerItems[hdr.totalItems] = NULL; // just to preinitialize the array.
  278. pWalkCatalog += sizeof(hdr);
  279. // walk the list and read the items.
  280. for (i = 0; i < hdr.totalItems; i++)
  281. {
  282. pItem = (PINVENTORY_ITEM) GlobalAlloc(GMEM_ZEROINIT, sizeof(INVENTORY_ITEM));
  283. if (NULL == pItem)
  284. {
  285. dwRet = GetLastError();
  286. LOG_error("Failed to Alloc Memory for Inventory Item, Error %d", dwRet);
  287. return FALSE;
  288. }
  289. pWalkCatalog = GetNextRecord(pWalkCatalog, i, pItem);
  290. if (!pWalkCatalog)
  291. {
  292. LOG_error("Failed to Alloc Memory for InventoryI Item State, Error %d", GetLastError());
  293. return FALSE;
  294. }
  295. m_pConsumerItems[i] = pItem;
  296. if ( WU_TYPE_CDM_RECORD_PLACE_HOLDER == pItem->recordType) m_fHasDriver = TRUE;
  297. m_dwConsumerItemCount++;
  298. }
  299. }
  300. if (0 != m_puidSetupCatalog)
  301. {
  302. // Download the Setup Catalog for this Platform
  303. // first we need to download the redirect file to get the CRC value of the catalog
  304. wsprintf(szCatalog, "%d/%s.as", m_puidSetupCatalog, szLocale);
  305. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
  306. wsprintf(szCatalog, "%d_%s.as", m_puidSetupCatalog, szLocale);
  307. PathCombine(szLocalFile, m_pDu->GetDuTempPath(), szCatalog);
  308. dwRet = m_pDu->DownloadFile(szServerFile, szLocalFile, TRUE, FALSE);
  309. if (ERROR_SUCCESS != dwRet)
  310. {
  311. SetLastError(dwRet);
  312. return FALSE;
  313. }
  314. if (GetPrivateProfileString("redir", "invCRC", "", szInvCRC, sizeof(szInvCRC), szLocalFile) == 0)
  315. {
  316. LOG_error("Unable to Read Inventory CRC value from Setup Catalog");
  317. return FALSE;
  318. }
  319. if (GetPrivateProfileString("redir", "bmCRC", "", szBmCRC, sizeof(szBmCRC), szLocalFile) == 0)
  320. {
  321. LOG_error("Unable to Read Bitmask CRC value for Setup Catalog");
  322. return FALSE;
  323. }
  324. char szBMCRCFileName[MAX_PATH];
  325. wsprintf(szBMCRCFileName, "%s.bm", szBmCRC);
  326. if (!GetBitMask(szBMCRCFileName, m_puidSetupCatalog, &m_pBitMaskAS, "bitmask.as"))
  327. {
  328. LOG_error("Unable to Read Bitmask File for AS");
  329. return FALSE;
  330. }
  331. // now download the real catalog
  332. wsprintf(szCatalog, "%d/%s.inv", m_puidSetupCatalog, szInvCRC);
  333. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
  334. SafeGlobalFree(m_pSetupCatalog);
  335. wsprintf(szCatalog, "%s.inv", szInvCRC);
  336. m_pDu->DownloadFileToMem(szServerFile, &m_pSetupCatalog, &dwLength, TRUE, szCatalog, "inventory.as");
  337. if (NULL == m_pSetupCatalog)
  338. {
  339. LOG_error("Failed to download Consumer Catalog, %d", m_puidSetupCatalog);
  340. return FALSE;
  341. }
  342. pWalkCatalog = m_pSetupCatalog;
  343. // Read the Catalog Header
  344. ZeroMemory(&hdr, sizeof(hdr));
  345. memcpy(&hdr, pWalkCatalog, sizeof(hdr));
  346. m_pSetupItems[hdr.totalItems] = NULL; // just to preinitialize the array.
  347. pWalkCatalog += sizeof(hdr);
  348. // walk the list and read the items.
  349. for (i = 0; i < hdr.totalItems; i++)
  350. {
  351. pItem = (PINVENTORY_ITEM) GlobalAlloc(GMEM_ZEROINIT, sizeof(INVENTORY_ITEM));
  352. if (NULL == pItem)
  353. {
  354. dwRet = GetLastError();
  355. LOG_error("Failed to Alloc Memory for Inventory Item, Error %d", dwRet);
  356. return FALSE;
  357. }
  358. pWalkCatalog = GetNextRecord(pWalkCatalog, i, pItem);
  359. if (!pWalkCatalog)
  360. {
  361. LOG_error("Failed to Alloc Memory for InventoryI Item State, Error %d", GetLastError());
  362. return FALSE;
  363. }
  364. if (!pItem->ps->bHidden && !GETBIT(m_pBitMaskAS, i))
  365. {
  366. // this item is masked out
  367. LOG_out("Item %d is masked out", i);
  368. pItem->ps->bHidden = TRUE;
  369. pItem->ps->state = WU_ITEM_STATE_PRUNED;
  370. pItem->ps->dwReason = WU_STATE_REASON_BITMASK;
  371. }
  372. m_pSetupItems[i] = pItem;
  373. m_dwSetupItemCount++;
  374. }
  375. }
  376. return TRUE;
  377. }
  378. PBYTE CV31Server::GetNextRecord(PBYTE pRecord, int iBitmaskIndex, PINVENTORY_ITEM pItem)
  379. {
  380. //first get the fixed length part of the record
  381. pItem->pf = (PWU_INV_FIXED)pRecord;
  382. //process the variable part of the record
  383. pRecord = pRecord + sizeof(WU_INV_FIXED);
  384. pItem->pv = (PWU_VARIABLE_FIELD)pRecord;
  385. //since there is no state information create an empty structure
  386. pItem->ps = (PWU_INV_STATE)GlobalAlloc(GMEM_ZEROINIT, sizeof(WU_INV_STATE));
  387. if (!pItem->ps) return NULL;
  388. //new item is unknown detection, not selected and shown to user.
  389. pItem->ps->state = WU_ITEM_STATE_UNKNOWN;
  390. pItem->ps->bChecked = FALSE;
  391. // RogerJ, to support versioning, we will use the bHidden flag
  392. pItem->ps->bHidden = pItem->pf->a.flags & WU_HIDDEN_ITEM_FLAG;
  393. if (pItem->ps->bHidden) m_nNumOfValidDependentPUID++;
  394. pItem->ps->dwReason = WU_STATE_REASON_NONE;
  395. //There is no description yet
  396. pItem->pd = (PWU_DESCRIPTION)NULL;
  397. //we need to store the bitmap index (which is the sequential record index)
  398. //since this information will be lost when we add the driver records.
  399. // YanL: is not being used
  400. // pItem->bitmaskIndex = iBitmaskIndex;
  401. //Get record type
  402. pItem->recordType = (BYTE)GetRecordType(pItem);
  403. pItem->ndxLinkInstall = (PUID) pItem->pf->a.installLink;
  404. //set record pointer to the beginning of the next record
  405. pRecord += pItem->pv->GetSize();
  406. return pRecord;
  407. }
  408. int CV31Server::GetRecordType(PINVENTORY_ITEM pItem)
  409. {
  410. GUID driverRecordId = WU_GUID_DRIVER_RECORD;
  411. int iRecordType = 0;
  412. if ( memcmp((void *)&pItem->pf->d.g, (void *)&driverRecordId, sizeof(WU_GUID_DRIVER_RECORD)) )
  413. {
  414. //if the GUID field is not 0 then we have an active setup record.
  415. iRecordType = WU_TYPE_ACTIVE_SETUP_RECORD;//active setup record type
  416. }
  417. else
  418. {
  419. //else this is either a driver record place holder or a section - sub section
  420. //record. So we need to check the type field
  421. if ( pItem->pf->d.type == SECTION_RECORD_TYPE_DEVICE_DRIVER_INSERTION )
  422. {
  423. //cdm driver place holder record
  424. iRecordType = WU_TYPE_CDM_RECORD_PLACE_HOLDER; //cdm code download manager place holder record
  425. }
  426. else if ( pItem->pf->d.type == SECTION_RECORD_TYPE_PRINTER )
  427. {
  428. //Note: We may need to use this to support printers on win 98.
  429. iRecordType = WU_TYPE_RECORD_TYPE_PRINTER; //printer record
  430. }
  431. else if ( pItem->pf->d.type == SECTION_RECORD_TYPE_DRIVER_RECORD )
  432. {
  433. iRecordType = WU_TYPE_CDM_RECORD; //Corporate catalog device driver
  434. }
  435. else if ( pItem->pf->s.type == SECTION_RECORD_TYPE_CATALOG_RECORD )
  436. {
  437. iRecordType = WU_TYPE_CATALOG_RECORD;
  438. }
  439. else
  440. {
  441. //we have either a section, sub section or sub sub section record
  442. switch ( pItem->pf->s.level )
  443. {
  444. case 0:
  445. iRecordType = WU_TYPE_SECTION_RECORD;
  446. break;
  447. case 1:
  448. iRecordType = WU_TYPE_SUBSECTION_RECORD;
  449. break;
  450. case 2:
  451. iRecordType = WU_TYPE_SUBSUBSECTION_RECORD;
  452. break;
  453. }
  454. }
  455. }
  456. return iRecordType;
  457. }
  458. // --------------------------------------------------------------------------
  459. // CV31Server::UpdateDownloadItemList()
  460. //
  461. // Parses the Catalogs and gets a list of Items in the Correct Platform SKU
  462. // section to download.
  463. //
  464. //
  465. // --------------------------------------------------------------------------
  466. BOOL CV31Server::UpdateDownloadItemList(OSVERSIONINFOEX& VersionInfo)
  467. {
  468. LOG_block("CV31Server::UpdateDownloadItemList()");
  469. ULONG ulItem = 0;
  470. int iRecordType = 0;
  471. BOOL fFound = FALSE, fRet;
  472. char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
  473. char szMapFileName[MAX_PATH];
  474. char szLocale[32];
  475. DWORD dwLength;
  476. PBYTE pMapMem = NULL;
  477. PWU_VARIABLE_FIELD pvCabs;
  478. PWU_VARIABLE_FIELD pvCRCs;
  479. int iCabNum = 0;
  480. BOOL fRetValue = TRUE;
  481. wsprintf(szLocale, "0x%8.8x", m_lcidLocaleID);
  482. wsprintf(szMapFileName, "%d_%s.des", m_dwPlatformID, szLocale);
  483. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szMapFileName);
  484. m_pDu->DownloadFileToMem(szServerFile, &pMapMem, &dwLength, TRUE, szMapFileName, NULL);
  485. if (NULL == pMapMem)
  486. {
  487. LOG_error("Failed to Download CRC Map File %s", szServerFile);
  488. return FALSE;
  489. }
  490. CCRCMapFile DescMap(pMapMem, dwLength);
  491. // Before we add any items to the download list we need to clear the download list
  492. // from any previous calls to DoDetection.
  493. m_pDu->EnterDownloadListCriticalSection(); // if we're downloading we don't want to allow the download list to change
  494. m_pDu->ClearDownloadItemList();
  495. if (0 != m_dwSetupItemCount)
  496. {
  497. // We have a valid Setup Catalog, find the Correct Section based on SKU
  498. // ROGERJ, october 24, 2000
  499. // we need to make a list of valid dependency item first
  500. if (!MakeDependentList(VersionInfo, &DescMap))
  501. {
  502. // last error will be set by MakeDependentList() function
  503. fRetValue = FALSE;
  504. goto ReturnPoint;
  505. }
  506. // We want to walk the Catalog Looking for the Section PUID that matches our requested Platform SKU
  507. for (ulItem = 0; ulItem < m_dwSetupItemCount; ulItem++)
  508. {
  509. if (WU_TYPE_SECTION_RECORD == m_pSetupItems[ulItem]->recordType)
  510. {
  511. if (m_pSetupItems[ulItem]->pf->s.puid == m_enumPlatformSKU)
  512. {
  513. // found the correct section
  514. fFound = TRUE;
  515. break;
  516. }
  517. }
  518. }
  519. if (fFound)
  520. {
  521. ulItem++; // advance to the next item
  522. // until we find the next section, or the end of the catalog
  523. while ((ulItem < m_dwSetupItemCount) && (WU_TYPE_SECTION_RECORD != GetRecordType(m_pSetupItems[ulItem])))
  524. {
  525. PINVENTORY_ITEM pItem = m_pSetupItems[ulItem];
  526. // ROGERJ, October 24th, 2000 --- determine if the item is applied to this version
  527. // skip hidden item
  528. if (pItem->ps->bHidden)
  529. {
  530. ulItem++;
  531. continue;
  532. }
  533. // determine if this item valid on this build
  534. if ( 0 != pItem->pf->a.installLink && // has dependency
  535. !IsDependencyApply(pItem->pf->a.installLink)) // dependency not apply to this version
  536. {
  537. // if the dependency item is not valid in this version, skip
  538. ulItem++;
  539. continue;
  540. }
  541. char szServerCab[128];
  542. char szLocalCab[128];
  543. // The next section record marks the end of the items valid for this SKU
  544. fRet = ReadDescription(pItem, &DescMap);
  545. if (!fRet)
  546. {
  547. // failed to read description file for this item, skip it.
  548. ulItem++;
  549. continue;
  550. }
  551. pvCabs = pItem->pd->pv->Find(WU_DESCRIPTION_CABFILENAME);
  552. pvCRCs = pItem->pd->pv->Find(WU_DESC_CRC_ARRAY);
  553. if ((NULL == pvCabs) || (NULL == pvCRCs))
  554. {
  555. // no cab list or CRC list in the description file
  556. ulItem++;
  557. continue;
  558. }
  559. DOWNLOADITEM *pDownloadItem = (DOWNLOADITEM *)GlobalAlloc(GMEM_ZEROINIT, sizeof(DOWNLOADITEM));
  560. if (NULL == pDownloadItem)
  561. {
  562. LOG_error("Error Allocating Memory for new Download Item");
  563. fRetValue = FALSE;
  564. goto ReturnPoint;
  565. }
  566. pDownloadItem->dwTotalFileSize = pItem->pd->size * 1024; // Estimated Size in Bytes
  567. pDownloadItem->puid = pItem->pf->a.puid;
  568. LPSTR pszCabName = pDownloadItem->mszFileList;
  569. iCabNum = 0;
  570. for (;;)
  571. {
  572. if (FAILED(GetCRCNameFromList(iCabNum, pvCabs->pData, pvCRCs->pData, szServerCab, sizeof(szServerCab), szLocalCab)))
  573. {
  574. break; // no more cabs
  575. }
  576. pDownloadItem->iNumberOfCabs++;
  577. lstrcpy(pszCabName, szServerCab);
  578. pszCabName += lstrlen(pszCabName) + 1;
  579. *pszCabName = '\0'; // double null terminate
  580. pszCabName++; // next cab
  581. iCabNum++;
  582. }
  583. // don't add the item unless there are cabs for it.
  584. if (pDownloadItem->iNumberOfCabs > 0 && !IsPUIDExcluded(pItem->pf->a.puid))
  585. // before adding this item to the list, check to see if it should be excluded based
  586. // on the Catalog.INI
  587. m_pDu->AddDownloadItemToList(pDownloadItem);
  588. SafeGlobalFree(pItem->pd);
  589. ulItem++;
  590. }
  591. }
  592. }
  593. ReturnPoint:
  594. m_pDu->LeaveDownloadListCriticalSection();
  595. SafeGlobalFree(pMapMem);
  596. return fRetValue;
  597. }
  598. BOOL CV31Server::ReadDescription(PINVENTORY_ITEM pItem, CCRCMapFile *pMapFile)
  599. {
  600. if ((NULL == pItem) || (NULL == pMapFile))
  601. {
  602. return FALSE;
  603. }
  604. LOG_block("CV31Server::ReadDescription()");
  605. char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
  606. char szDownloadFile[MAX_PATH];
  607. PWU_DESCRIPTION pd;
  608. DWORD dwLength;
  609. char szBase[64];
  610. char szCRCName[64];
  611. HRESULT hr = S_OK;
  612. wsprintf(szBase, "%d.des", pItem->GetPuid());
  613. hr = pMapFile->GetCRCName((DWORD)pItem->GetPuid(), szBase, szCRCName, sizeof(szCRCName));
  614. if (FAILED(hr))
  615. {
  616. LOG_error("Failed to get CRC Description Value for Item %d", pItem->GetPuid());
  617. return FALSE;
  618. }
  619. wsprintf(szDownloadFile, "CRCDesc/%s", szCRCName);
  620. m_pDu->DuUrlCombine(szServerFile, m_szV31RootUrl, szDownloadFile);
  621. m_pDu->DownloadFileToMem(szServerFile, (PBYTE *)&pd, &dwLength, TRUE, szCRCName, "desc.as");
  622. if (NULL == pd)
  623. {
  624. LOG_error("Failed to download Description File %s", szServerFile);
  625. return FALSE;
  626. }
  627. // for 64 bit, the description is off by size of DWORD
  628. //if (19 == m_pDu->m_iPlatformID)
  629. // 64 bit
  630. // pd->pv = (PWU_VARIABLE_FIELD)(((PBYTE)pd) + sizeof(WU_DESCRIPTION) + sizeof(DWORD));
  631. //else
  632. // 32 bit
  633. pd->pv = (PWU_VARIABLE_FIELD)(((PBYTE)pd) + sizeof(WU_DESCRIPTION));
  634. pItem->pd = pd;
  635. return TRUE;
  636. }
  637. void CV31Server::FreeCatalogs()
  638. {
  639. for (DWORD dwcnt = 0; dwcnt < m_dwSetupItemCount; dwcnt++)
  640. {
  641. if (m_pSetupItems[dwcnt])
  642. {
  643. SafeGlobalFree(m_pSetupItems[dwcnt]->ps);
  644. SafeGlobalFree(m_pSetupItems[dwcnt]->pd);
  645. SafeGlobalFree(m_pSetupItems[dwcnt]);
  646. }
  647. }
  648. for (dwcnt = 0; dwcnt < m_dwConsumerItemCount; dwcnt++)
  649. {
  650. if (m_pConsumerItems[dwcnt])
  651. {
  652. SafeGlobalFree(m_pConsumerItems[dwcnt]->ps);
  653. SafeGlobalFree(m_pConsumerItems[dwcnt]->pd);
  654. SafeGlobalFree(m_pConsumerItems[dwcnt]);
  655. }
  656. }
  657. m_dwSetupItemCount = 0;
  658. m_dwConsumerItemCount = 0;
  659. }
  660. BOOL CV31Server::MakeDependentList(OSVERSIONINFOEX &VersionInfo, CCRCMapFile *pMapFile)
  661. {
  662. // Log
  663. LOG_block("CV31Server::MakeDependentList()");
  664. // make sure the array is empty
  665. SafeGlobalFree(m_pValidDependentPUIDArray);
  666. // no dependency item
  667. if (!m_nNumOfValidDependentPUID) return TRUE;
  668. int nPUIDIndex = 0;
  669. // allocate the memory
  670. m_pValidDependentPUIDArray = (PUID*) GlobalAlloc(GMEM_ZEROINIT, sizeof(PUID)*m_nNumOfValidDependentPUID);
  671. if (!m_pValidDependentPUIDArray)
  672. {
  673. LOG_error("Out of memory");
  674. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  675. return FALSE;
  676. }
  677. ULONG ulItem;
  678. for (ulItem = 0; ulItem < m_dwSetupItemCount && nPUIDIndex < m_nNumOfValidDependentPUID; ulItem++)
  679. {
  680. if (WU_TYPE_ACTIVE_SETUP_RECORD != GetRecordType(m_pSetupItems[ulItem]) ||
  681. !m_pSetupItems[ulItem]->ps->bHidden || m_pSetupItems[ulItem]->ps->state == WU_ITEM_STATE_PRUNED)
  682. continue;
  683. PINVENTORY_ITEM pItem = m_pSetupItems[ulItem];
  684. // get a hidden setup dependency item record
  685. BOOL fRet = ReadDescription(pItem, pMapFile);
  686. if (!fRet)
  687. // failed to read description file for this item, assume this dependency does not apply
  688. // this way, we will not download any item not apply, but may miss some items that apply
  689. continue;
  690. // Title is composed as BuildMin.BuildMax.SPMajor.SPMinor
  691. PWU_VARIABLE_FIELD pvField = pItem->pd->pv->Find(WU_DESCRIPTION_TITLE);
  692. if (!pvField)
  693. {
  694. // title is NULL, error, ignore this item
  695. LOG_error("Title is NULL");
  696. continue;
  697. }
  698. wchar_t * pvTitle = (wchar_t*) pvField->pData;
  699. DWORD dwBuild[4];
  700. dwBuild[0]=0;
  701. dwBuild[1]=99999;
  702. dwBuild[2]=0;
  703. dwBuild[3]=0;
  704. int nBuildIndex = 0;
  705. int nTemp = 0;
  706. BOOL fBreak = FALSE;
  707. while (nBuildIndex<4 && !fBreak)
  708. {
  709. if (*pvTitle != L'.' && *pvTitle != NULL )
  710. {
  711. if (*pvTitle > L'9' || *pvTitle < '0')
  712. {
  713. // illegal use of this title
  714. LOG_error("Illegal character '%c' found in the title",(char)*pvTitle);
  715. SetLastError(ERROR_INVALID_DATA);
  716. return FALSE;
  717. }
  718. else
  719. {
  720. nTemp *=10;
  721. nTemp += (*pvTitle - L'0');
  722. }
  723. }
  724. else
  725. {
  726. if (!*pvTitle) fBreak = TRUE;
  727. dwBuild[nBuildIndex++] = nTemp;
  728. nTemp = 0;
  729. }
  730. pvTitle++;
  731. }
  732. LOG_out("Title is %d.%d.%d.%d\n", dwBuild[0], dwBuild[1], dwBuild[2], dwBuild[3]);
  733. // determine if this item apply
  734. if (dwBuild[0] <= VersionInfo.dwBuildNumber &&
  735. dwBuild[1] >= VersionInfo.dwBuildNumber &&
  736. dwBuild[2] == VersionInfo.wServicePackMajor&&
  737. dwBuild[3] == VersionInfo.wServicePackMinor)
  738. {
  739. // applys, add this to the list
  740. LOG_out("This dependency item applied");
  741. m_pValidDependentPUIDArray[nPUIDIndex++] = pItem->GetPuid();
  742. }
  743. else
  744. LOG_out("This dependency item NOT applied");
  745. }
  746. return TRUE;
  747. }
  748. BOOL CV31Server::IsDependencyApply(PUID puid)
  749. {
  750. LOG_block("CV31Server::IsDependencyApply()");
  751. LOG_out("puid(%d)", (long)puid);
  752. // handle no link
  753. if (WU_NO_LINK == puid) return TRUE;
  754. // no depend item is valid
  755. if (!m_nNumOfValidDependentPUID)
  756. {
  757. LOG_out("No dependecy item");
  758. return FALSE;
  759. }
  760. for (int nItem = 0; nItem < m_nNumOfValidDependentPUID; nItem ++)
  761. {
  762. if (m_pValidDependentPUIDArray[nItem] == puid)
  763. {
  764. LOG_out ("puid(%d) applies", (long)puid);
  765. return TRUE;
  766. }
  767. if (m_pValidDependentPUIDArray[nItem] == 0) break; // 0 mark the end of valid puid
  768. }
  769. LOG_out("puid(%d) does not apply", (long)puid);
  770. return FALSE;
  771. }
  772. BOOL CV31Server::GetBitMask(LPSTR szBitmapLocalFileName, PUID nDirectoryPuid, PBYTE* pByte, LPSTR szDecompressedName)
  773. {
  774. LOG_block("CV31Server::GetBitMask()");
  775. LOG_out("Parameters --- %s",szBitmapLocalFileName);
  776. SetLastError(0);
  777. // Parameter validation
  778. if (!szBitmapLocalFileName)
  779. {
  780. LOG_error("Invalid Parameter");
  781. SetLastError(ERROR_INVALID_PARAMETER);
  782. return FALSE;
  783. }
  784. SafeGlobalFree(*pByte);
  785. PBITMASK pBitMask = NULL;
  786. DWORD dwLength = 0;
  787. DWORD dwError = 0;
  788. BOOL fRetVal = FALSE;
  789. // log parameter
  790. LOG_out("szBitmapLocalFileName(%s)",szBitmapLocalFileName);
  791. char szBitmapServerFileName[INTERNET_MAX_URL_LENGTH];
  792. ZeroMemory(szBitmapServerFileName, INTERNET_MAX_URL_LENGTH*sizeof(char));
  793. char szBitmapFileWithDir[MAX_PATH];
  794. wsprintf(szBitmapFileWithDir, "%d/%s", nDirectoryPuid, szBitmapLocalFileName);
  795. m_pDu->DuUrlCombine(szBitmapServerFileName, m_szV31ContentUrl, szBitmapFileWithDir);
  796. dwError = m_pDu->DownloadFileToMem(szBitmapServerFileName,
  797. (PBYTE*)&pBitMask, &dwLength, TRUE, szBitmapLocalFileName, szDecompressedName);
  798. if (ERROR_SUCCESS != dwError)
  799. {
  800. LOG_error("Failed to download %s --- %d", szBitmapServerFileName, dwError);
  801. return FALSE;
  802. }
  803. int iMaskByteSize = ((pBitMask->iRecordSize+7)/8);
  804. int nIndex = 0;
  805. for (int nItem =0; nItem < pBitMask->iLocaleCount; nItem ++)
  806. {
  807. nIndex = pBitMask->iOemCount + nItem;
  808. if (pBitMask->bmID[nIndex] == m_pDu->m_lcidLocaleID) break;
  809. }
  810. if (nItem >= pBitMask->iLocaleCount)
  811. {
  812. // not found
  813. // bad locale ? or missing locale info?
  814. LOG_error("LCID %d is not found in %s", m_pDu->m_lcidLocaleID, szBitmapLocalFileName);
  815. SetLastError(ERROR_UNSUPPORTED_TYPE);
  816. goto ErrorReturn;
  817. }
  818. *pByte =(PBYTE) GlobalAlloc(GMEM_ZEROINIT, iMaskByteSize);
  819. if (!pByte)
  820. {
  821. LOG_error("Out of memory");
  822. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  823. goto ErrorReturn;
  824. }
  825. CopyMemory((PVOID)*pByte, (const PVOID) pBitMask->GetBitMaskPtr(nIndex+2), iMaskByteSize);
  826. fRetVal = TRUE;
  827. /* The next part of the code can be used to print of bitmask.as
  828. if (lstrcmp (szBitmapLocalFileName, "bitmask.cdm") == 0) goto ErrorReturn;
  829. for (nIndex = 0; nIndex < pBitMask->iLocaleCount; nIndex ++)
  830. {
  831. char szTTT [MAX_PATH];
  832. ZeroMemory(szTTT, MAX_PATH);
  833. wsprintf(szTTT, "%d --- ", pBitMask->bmID[nIndex +2 + pBitMask->iOemCount]);
  834. PBYTE pTep = (PBYTE) pBitMask->GetBitMaskPtr(nIndex +2 + pBitMask->iOemCount);
  835. for (nItem = 0; nItem < iMaskByteSize; nItem ++)
  836. {
  837. char szTTTTT [MAX_PATH];
  838. wsprintf(szTTTTT, "%d, ", pTep[nItem]);
  839. lstrcat(szTTT, szTTTTT);
  840. }
  841. LOG_out("%s", szTTT);
  842. }*/
  843. ErrorReturn:
  844. SafeGlobalFree(pBitMask);
  845. return fRetVal;
  846. }
  847. BOOL CV31Server::ReadGuidrvINF()
  848. {
  849. LOG_block("CV31Server::ReadGuidrvINF()");
  850. char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
  851. char szLocalFile[MAX_PATH];
  852. char szValue[1024];
  853. int nDefaultBufferLength = 512;
  854. SafeGlobalFree(m_pszExcludedDriver);
  855. // Now read the Catalog.ini file to find out if any of these items needs to be turned off
  856. m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, GUIDRVINF);
  857. PathCombineA(szLocalFile, m_pDu->GetDuDownloadPath(), GUIDRVINF);
  858. if (ERROR_SUCCESS!=m_pDu->DownloadFile(szServerFile, szLocalFile, FALSE, FALSE))
  859. {
  860. LOG_out("No guidrv.inf found");
  861. return TRUE;
  862. }
  863. int nReadLength;
  864. do
  865. {
  866. nDefaultBufferLength <<=1;
  867. SafeGlobalFree(m_pszExcludedDriver);
  868. m_pszExcludedDriver = (LPSTR) GlobalAlloc(GPTR, nDefaultBufferLength * sizeof(char));
  869. if (!m_pszExcludedDriver)
  870. {
  871. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  872. LOG_error("Out of memory");
  873. return FALSE;
  874. }
  875. nReadLength = GetPrivateProfileSectionA("ExcludedDrivers", m_pszExcludedDriver, nDefaultBufferLength, szLocalFile);
  876. } while ( nDefaultBufferLength-2 == nReadLength);
  877. if (!lstrlenA(m_pszExcludedDriver))
  878. {
  879. SafeGlobalFree(m_pszExcludedDriver);
  880. m_pszExcludedDriver = NULL;
  881. }
  882. return TRUE;
  883. }
  884. BOOL CV31Server::IsPUIDExcluded(PUID nPuid)
  885. {
  886. if (m_dwGlobalExclusionItemCount > 0)
  887. {
  888. for (DWORD dwCnt = 0; dwCnt < m_dwGlobalExclusionItemCount; dwCnt++)
  889. {
  890. if (nPuid == m_GlobalExclusionArray[dwCnt])
  891. return TRUE;
  892. }
  893. }
  894. return FALSE;
  895. }
  896. BOOL CV31Server::IsDriverExcluded(LPCSTR szWHQLId, LPCSTR szHardwareId)
  897. {
  898. LOG_block("CV31Server::IsDriverExcluded()");
  899. LOG_out("%s %s", szWHQLId, szHardwareId);
  900. if(m_pszExcludedDriver)
  901. {
  902. char* pTemp = m_pszExcludedDriver;
  903. while (*pTemp)
  904. {
  905. // try to find if the driver is excluded
  906. char* pCharEnd = pTemp;
  907. char* pCharBegin = pTemp;
  908. // first one is the id for the cab
  909. while (*pCharEnd != ',' && *pCharEnd != '\0') pCharEnd++;
  910. if (NULL == *pCharEnd)
  911. {
  912. LOG_error("guidrvs.inf corruption --- %s", pTemp);
  913. return TRUE; // guidrvs.inf corrupted, assume excluded
  914. }
  915. if (lstrlenA(szWHQLId) == (int)(pCharEnd - pCharBegin)
  916. && !StrCmpNI(szWHQLId, pCharBegin, (int)(pCharEnd-pCharBegin)))
  917. {
  918. // cab name matches, try to match hardware id
  919. // ignore second and third one
  920. for (int i=0; i<2; i++)
  921. {
  922. pCharBegin = pCharEnd + 1;
  923. pCharEnd = pCharBegin;
  924. while (*pCharEnd != ',' && *pCharEnd != '\0') pCharEnd++;
  925. if (NULL == *pCharEnd)
  926. {
  927. LOG_error("guidrvs.inf corruption --- %s", pTemp);
  928. return TRUE; // guidrv.inf corrupted, assume excluded
  929. }
  930. }
  931. // the forth one should be the hardware id
  932. pCharBegin = pCharEnd + 1;
  933. if (!lstrcmpi(szHardwareId, pCharBegin) || ('*' == *pCharBegin && !*(pCharBegin+1)))
  934. {
  935. LOG_out("Found match in guidrvs.inf, excluded --- %s", pTemp);
  936. return TRUE;
  937. }
  938. }
  939. // move to next string
  940. pTemp += lstrlenA(pTemp) + 1;
  941. }
  942. }
  943. return FALSE;
  944. }
  945. BOOL CV31Server::GetAltName(LPCSTR szCabName, LPSTR szAltName, int nSize)
  946. {
  947. if (!szCabName || !szAltName) return FALSE;
  948. char* pTemp = const_cast<char*>(szCabName);
  949. while (*pTemp && *pTemp != '_') pTemp++;
  950. int nTempSize = (int)(pTemp-szCabName);
  951. if (nTempSize >= nSize) return FALSE;
  952. lstrcpynA(szAltName, szCabName, nTempSize+1);
  953. return TRUE;
  954. }