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.

1464 lines
39 KiB

  1. #include "dsbase.hxx"
  2. //
  3. // List of columns this routine fetches.
  4. //
  5. LPOLESTR szInstallInfoColumns =
  6. L"msiScriptPath,packageFlags,comClassID,packageType,lastUpdateSequence,versionNumberHi,versionNumberLo,localeID,machineArchitecture,oSVersion,fileExtPriority,canUpgradeScript,installUiLevel,executionContext,url,setupCommand";
  7. //
  8. // List of columns this routine fetches.
  9. //
  10. LPOLESTR szPackageInfoColumns =
  11. L"packageName,packageFlags,packageType,msiScriptPath,msiScriptSize,lastUpdateSequence,versionNumberHi,versionNumberLo,localeID,machineArchitecture,oSVersion,canUpgradeScript";
  12. //
  13. // MatchLocale : Compares the packages locale to the client locale.
  14. // Prescribed order is :
  15. //
  16. BOOL MatchLocale(DWORD dwReqLocale, DWORD dwPkgLocale)
  17. {
  18. return ((dwReqLocale == dwPkgLocale) || // locale is matching
  19. (dwPkgLocale == GetUserDefaultLCID()) || // pkg locale is user default
  20. (dwPkgLocale == GetSystemDefaultLCID()) || // pkg locale is system default
  21. (dwPkgLocale == LOCALE_NEUTRAL) // pkg is locale neutral
  22. );
  23. }
  24. BOOL MatchPlatform(CSPLATFORM *pReqPlatform, CSPLATFORM *pPkgPlatform)
  25. {
  26. //
  27. // ProcessorArch must match
  28. // AND OS must match
  29. // AND the OS version reqd by the package MUST be less or equal
  30. // to the client's OS version
  31. //
  32. return (
  33. (pReqPlatform->dwPlatformId == pPkgPlatform->dwPlatformId) &&
  34. (pReqPlatform->dwProcessorArch == pPkgPlatform->dwProcessorArch) &&
  35. ((pReqPlatform->dwVersionHi < pPkgPlatform->dwVersionHi) ||
  36. ((pReqPlatform->dwVersionHi == pPkgPlatform->dwVersionHi) &&
  37. (pReqPlatform->dwVersionLo <= pPkgPlatform->dwVersionLo))
  38. )
  39. );
  40. }
  41. //---------------------------------------------------------------
  42. // Query
  43. //----------------------------------------------------------------
  44. HRESULT
  45. StartQuery(IDBCreateCommand ** ppIDBCreateCommand)
  46. {
  47. HRESULT hr;
  48. IDBCreateSession * pIDBCS = NULL;
  49. IDBInitialize * pIDBInit = NULL;
  50. //
  51. // Instantiate a data source object for LDAP provider
  52. //
  53. hr = CoCreateInstance(
  54. CLSID_ADsDSOObject,
  55. 0,
  56. CLSCTX_INPROC_SERVER,
  57. IID_IDBInitialize,
  58. (void **)&pIDBInit
  59. );
  60. if(FAILED(hr))
  61. {
  62. printf("CoCreateInstance failed \n");
  63. goto error;
  64. }
  65. hr = pIDBInit->Initialize();
  66. if(FAILED(hr))
  67. {
  68. printf("IDBIntialize::Initialize failed \n");
  69. goto error;
  70. }
  71. //
  72. // Request the IDBCreateSession interface
  73. //
  74. pIDBInit->QueryInterface(
  75. IID_IDBCreateSession,
  76. (void**) &pIDBCS);
  77. if(FAILED(hr))
  78. {
  79. printf("QueryInterface for IDBCreateSession failed \n");
  80. goto error;
  81. }
  82. pIDBInit->Release();
  83. pIDBInit = NULL;
  84. //
  85. // Create a session returning a pointer to its CreateCommand interface
  86. //
  87. hr = pIDBCS->CreateSession(
  88. NULL,
  89. IID_IDBCreateCommand,
  90. (LPUNKNOWN*) ppIDBCreateCommand
  91. );
  92. if(FAILED(hr))
  93. {
  94. printf("IDBCreateSession::CreateSession failed \n");
  95. goto error;
  96. }
  97. pIDBCS->Release();
  98. pIDBCS = NULL;
  99. return S_OK;
  100. error:
  101. if(pIDBInit)
  102. pIDBInit->Release();
  103. if(pIDBCS)
  104. pIDBCS->Release();
  105. return -1;
  106. }
  107. HRESULT
  108. EndQuery(IDBCreateCommand * pIDBCreateCommand)
  109. {
  110. pIDBCreateCommand->Release();
  111. return S_OK;
  112. }
  113. HRESULT
  114. CreateBindingHelper(
  115. IRowset *pIRowset,
  116. ULONG cColumns,
  117. DBBINDING **pprgBindings
  118. );
  119. // ExecuteQuery
  120. // --------------
  121. //
  122. // This is a generic routine.
  123. // It hides a lot of nuisances with regards to setting up a OLEDB
  124. // query session, specifying a query command and executing it,
  125. // associating a provided binding with it and getting an
  126. // Accessor and Rowset out of all these.
  127. //
  128. // The inputs are
  129. // A IDBCreateCommand object to provide for reuse
  130. // The Query Command Text
  131. // Number of Columns in the query
  132. // Binding Association for Data Access
  133. // The Returned Set is:
  134. // Rowset Object
  135. // Accessor Object
  136. // Accessor Handle
  137. HRESULT ExecuteQuery (IDBCreateCommand * pIDBCreateCommand,
  138. LPWSTR pszCommandText,
  139. UINT nColumns,
  140. DBBINDING * pBinding,
  141. HACCESSOR * phAccessor,
  142. IAccessor ** ppIAccessor,
  143. IRowset ** ppIRowset
  144. )
  145. {
  146. HRESULT hr;
  147. ICommand * pICommand = NULL;
  148. ICommandText * pICommandText = NULL;
  149. IAccessor * pAccessor = NULL;
  150. DBBINDING * prgBindings = NULL;
  151. //
  152. // Create a command from the session object
  153. //
  154. hr = pIDBCreateCommand->CreateCommand(
  155. NULL,
  156. IID_ICommandText,
  157. (LPUNKNOWN*) &pICommandText);
  158. if(FAILED(hr))
  159. {
  160. printf(" IDBCreateCommand::CreateCommand failed, hr = 0x%x\n", hr);
  161. return hr;
  162. }
  163. hr = pICommandText->SetCommandText(
  164. DBGUID_LDAPDialect,
  165. pszCommandText
  166. );
  167. CSDbgPrint(("CS: Query: %S\n", pszCommandText));
  168. if(FAILED(hr))
  169. {
  170. printf("ICommandText::CommandText failed \n");
  171. return hr;
  172. }
  173. hr = pICommandText->QueryInterface(
  174. IID_ICommand,
  175. (void**) &pICommand);
  176. if(FAILED(hr))
  177. {
  178. printf("QueryInterface for ICommand failed \n");
  179. return hr;
  180. }
  181. hr = pICommandText->Release();
  182. //
  183. // Do the search and get back a rowset
  184. //
  185. hr = pICommand->Execute(
  186. NULL,
  187. IID_IRowset,
  188. NULL,
  189. NULL,
  190. (LPUNKNOWN *)ppIRowset);
  191. if (FAILED(hr))
  192. {
  193. printf("ICommand::Execute failed \n");
  194. return hr;
  195. }
  196. pICommand->Release();
  197. hr= (*ppIRowset)->QueryInterface(
  198. IID_IAccessor,
  199. (void**) ppIAccessor);
  200. if(FAILED(hr))
  201. {
  202. printf("QueryInterface for IAccessor failed \n");
  203. return hr;
  204. }
  205. //
  206. // With the bindings create the accessor
  207. //
  208. if (!pBinding)
  209. {
  210. //
  211. // Create a binding from data type
  212. //
  213. hr = CreateBindingHelper(
  214. *ppIRowset,
  215. nColumns,
  216. &prgBindings);
  217. }
  218. hr = (*ppIAccessor)->CreateAccessor(
  219. DBACCESSOR_ROWDATA,
  220. nColumns,
  221. (pBinding?pBinding:prgBindings),
  222. 0,
  223. phAccessor,
  224. NULL);
  225. //
  226. // If a binding was created automatically, free it
  227. //
  228. if (prgBindings)
  229. {
  230. CoTaskMemFree(prgBindings);
  231. }
  232. return hr;
  233. }
  234. // FetchInstallData
  235. //-----------------
  236. //
  237. // This routine performs actual data access after a query execution.
  238. //
  239. // It is not generic. It is query specific.
  240. //
  241. // This routine fetches data for the most common package query.
  242. HRESULT FetchInstallData(
  243. IRowset *pIRowset,
  244. HACCESSOR hAccessor,
  245. QUERYCONTEXT *pQryContext,
  246. LPOLESTR pszFileExt,
  247. ULONG cRows,
  248. ULONG *pcRowsFetched,
  249. INSTALLINFO *pInstallInfo,
  250. UINT *pdwPriority
  251. )
  252. {
  253. HROW * phRows = NULL;
  254. HRESULT hr;
  255. UINT i, j;
  256. Data pData[20];
  257. VARIANT *pVariant;
  258. ULONG cRowsGot;
  259. ULONG cPlatforms = 0;
  260. DWORD dwPlatformList[20];
  261. ULONG cLocale = 0;
  262. LCID dwLocaleList[20];
  263. CSPLATFORM PkgPlatform;
  264. *pcRowsFetched = 0;
  265. //
  266. // Get the rows
  267. //
  268. phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
  269. if(!phRows)
  270. {
  271. return E_OUTOFMEMORY;
  272. }
  273. hr = pIRowset->GetNextRows(NULL, 0, cRows, &cRowsGot, &phRows);
  274. if(FAILED(hr))
  275. {
  276. printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
  277. return hr;
  278. }
  279. for (i = 0; i < cRowsGot; i++)
  280. {
  281. //
  282. // Get the data from each row
  283. //
  284. memset(pData, 0, sizeof(Data) * 20);
  285. hr = pIRowset->GetData(phRows[i],
  286. hAccessor,
  287. (void*)&pData[0]
  288. );
  289. if (FAILED(hr))
  290. {
  291. //
  292. // BUGBUG. Missing cleanup.
  293. //
  294. printf("IRowset::GetData failed \n");
  295. return hr;
  296. }
  297. //
  298. // If querying by file ext check match and priority
  299. // .
  300. if (pszFileExt)
  301. {
  302. //Column = fileExtension
  303. ULONG cFileExt = 20;
  304. LPOLESTR szFileExt[20], pStr;
  305. if (pData[10].status != DBSTATUS_S_ISNULL)
  306. {
  307. cFileExt = 20;
  308. pVariant = (VARIANT*) pData[10].obValue;
  309. hr = GetFromVariant(pVariant, &cFileExt, (LPOLESTR *)&szFileExt[0]);
  310. }
  311. UINT cLen = wcslen(pszFileExt);
  312. for (j=0; j < cFileExt; ++j)
  313. {
  314. if (wcslen(szFileExt[j]) != (cLen+3))
  315. continue;
  316. if (wcsncmp(szFileExt[j], pszFileExt, wcslen(pszFileExt)) != 0)
  317. continue;
  318. *pdwPriority = wcstoul(szFileExt[j]+(cLen+1), &pStr, 10);
  319. break;
  320. }
  321. //
  322. // If none matched skip this package
  323. //
  324. if (j == cFileExt)
  325. continue;
  326. }
  327. //
  328. // Now check Locale and Platform
  329. // .
  330. if (pQryContext->Locale != LOCALE_NEUTRAL)
  331. {
  332. //Column = localeID
  333. if (pData[7].status != DBSTATUS_S_ISNULL)
  334. {
  335. cLocale = 20;
  336. pVariant = (VARIANT*) pData[7].obValue;
  337. hr = GetFromVariant(pVariant, &cLocale, (LPOLESTR *)&dwLocaleList[0]);
  338. }
  339. for (j=0; j < cLocale; ++j)
  340. {
  341. if (MatchLocale (dwLocaleList[j], pQryContext->Locale))
  342. break;
  343. }
  344. //
  345. // If none matched skip this package
  346. //
  347. if (j == cLocale)
  348. continue;
  349. }
  350. //Column = machineArchitecture
  351. if (pData[8].status != DBSTATUS_S_ISNULL)
  352. {
  353. cPlatforms = 20;
  354. pVariant = (VARIANT*) pData[8].obValue;
  355. hr = GetFromVariant(pVariant, &cPlatforms, (LPOLESTR *)&dwPlatformList[0]);
  356. }
  357. for (j=0; j < cPlatforms; ++j)
  358. {
  359. PackPlatform (dwPlatformList[j], &PkgPlatform);
  360. if (MatchPlatform (&(pQryContext->Platform), &PkgPlatform))
  361. break;
  362. }
  363. //
  364. // If none matched skip this package
  365. //
  366. if (j == cPlatforms)
  367. continue;
  368. //
  369. // Move the data into InstallInfo structure
  370. //
  371. memset(pInstallInfo, 0, sizeof(INSTALLINFO));
  372. //Column = packageFlags
  373. if (pData[1].status != DBSTATUS_S_ISNULL)
  374. {
  375. pInstallInfo->dwActFlags = (ULONG) (pData[1].obValue);
  376. }
  377. //
  378. // Does it support AutoInstall?
  379. //
  380. if (!(pInstallInfo->dwActFlags & ACTFLG_OnDemandInstall))
  381. continue;
  382. //Column = codePackage
  383. if (pData[0].status != DBSTATUS_S_ISNULL)
  384. {
  385. pInstallInfo->pszScriptPath = (LPWSTR) CoTaskMemAlloc
  386. (sizeof(WCHAR) * (wcslen ((WCHAR *)pData[0].obValue)+1));
  387. wcscpy (pInstallInfo->pszScriptPath, (WCHAR *) pData[0].obValue);
  388. }
  389. //Column = comClassID
  390. if (pData[2].status != DBSTATUS_S_ISNULL)
  391. {
  392. ULONG cCount = 1;
  393. LPOLESTR pList = NULL;
  394. pVariant = (VARIANT*) pData[2].obValue;
  395. // Only access the first entry
  396. hr = GetFromVariant(pVariant, &cCount, &pList);
  397. pInstallInfo->pClsid = (GUID *) CoTaskMemAlloc (sizeof (GUID));
  398. GUIDFromString(pList, pInstallInfo->pClsid);
  399. CoTaskMemFree (pList);
  400. }
  401. //Column = packageType
  402. if (pData[3].status != DBSTATUS_S_ISNULL)
  403. {
  404. pInstallInfo->PathType = (CLASSPATHTYPE) (ULONG) (pData[3].obValue);
  405. }
  406. //Column = lastUpdateSequence,
  407. if (pData[4].status != DBSTATUS_S_ISNULL)
  408. {
  409. swscanf ((LPOLESTR)(pData[4].obValue),
  410. L"%d %d",
  411. &(((CSUSN *)&(pInstallInfo->Usn))->dwHighDateTime),
  412. &(((CSUSN *)&(pInstallInfo->Usn))->dwLowDateTime));
  413. }
  414. //Column = versionNumberHi
  415. if (pData[5].status != DBSTATUS_S_ISNULL)
  416. {
  417. pInstallInfo->dwVersionHi = (ULONG) (pData[5].obValue);
  418. }
  419. //Column = versionNumberLo
  420. if (pData[6].status != DBSTATUS_S_ISNULL)
  421. {
  422. pInstallInfo->dwVersionLo = (ULONG) (pData[6].obValue);
  423. }
  424. if (pData[11].status != DBSTATUS_S_ISNULL)
  425. {
  426. ULONG cUp = 20;
  427. pVariant = (VARIANT*) pData[11].obValue;
  428. pInstallInfo->prgUpgradeScript =
  429. (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR) * cUp);
  430. hr = GetFromVariant(pVariant, &cUp, pInstallInfo->prgUpgradeScript);
  431. pInstallInfo->cUpgrades = cUp;
  432. pInstallInfo->prgUpgradeFlag =
  433. (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * cUp);
  434. for (j=0; j < cUp; ++j)
  435. {
  436. LPOLESTR pStr;
  437. LPOLESTR ptr = (pInstallInfo->prgUpgradeScript)[j];
  438. UINT l = wcslen (ptr);
  439. *(ptr+l-2) = NULL;
  440. (pInstallInfo->prgUpgradeFlag)[j] = wcstoul(ptr+(l-1), &pStr, 10);
  441. }
  442. }
  443. //Column = installUiLevel
  444. if (pData[12].status != DBSTATUS_S_ISNULL)
  445. {
  446. pInstallInfo->InstallUiLevel = (UINT) (pData[12].obValue);
  447. }
  448. //Column = ComClassContext
  449. if (pData[13].status != DBSTATUS_S_ISNULL)
  450. {
  451. pInstallInfo->dwComClassContext = (UINT) (pData[13].obValue);
  452. }
  453. //Column = HelpUrl
  454. if (pData[14].status != DBSTATUS_S_ISNULL)
  455. {
  456. ULONG cCount = 1;
  457. pVariant = (VARIANT*) pData[14].obValue;
  458. // access only the first entry, allocated.
  459. hr = GetFromVariant(pVariant, &cCount, &(pInstallInfo->pszUrl));
  460. }
  461. //Column = setupCommand
  462. if (pData[15].status != DBSTATUS_S_ISNULL)
  463. {
  464. pInstallInfo->pszSetupCommand = (LPWSTR) CoTaskMemAlloc
  465. (sizeof(WCHAR) * (wcslen ((WCHAR *)pData[15].obValue)+1));
  466. wcscpy (pInstallInfo->pszSetupCommand, (WCHAR *) pData[15].obValue);
  467. }
  468. //
  469. // Check what memory needs to be freed
  470. //
  471. ++pInstallInfo;
  472. ++pdwPriority;
  473. ++(*pcRowsFetched);
  474. }
  475. if (cRowsGot)
  476. {
  477. //
  478. // Free the Row Handles
  479. //
  480. hr = pIRowset->ReleaseRows(cRowsGot, phRows, NULL, NULL, NULL);
  481. }
  482. if (phRows)
  483. {
  484. //
  485. // Free the Row Handle Pointer
  486. //
  487. CoTaskMemFree (phRows);
  488. }
  489. return S_OK;
  490. }
  491. // FetchPackageInfo
  492. //-----------------
  493. //
  494. // This routine performs actual data access after a query execution.
  495. //
  496. // It is not generic. It is query specific.
  497. //
  498. // This routine fetches data for the most common package query.
  499. HRESULT FetchPackageInfo(IRowset *pIRowset,
  500. HACCESSOR hAccessor,
  501. DWORD dwFlags,
  502. DWORD *pdwLocale,
  503. CSPLATFORM *pPlatform,
  504. ULONG cRows,
  505. ULONG *pcRowsFetched,
  506. PACKAGEDISPINFO *pPackageInfo
  507. )
  508. {
  509. HROW * phRows = NULL;
  510. HRESULT hr;
  511. UINT i, j;
  512. Data pData[20];
  513. VARIANT *pVariant;
  514. ULONG cPlatforms = 0;
  515. DWORD dwPlatformList[20];
  516. ULONG cOs = 0;
  517. DWORD dwOsList[20];
  518. ULONG cLocale = 0;
  519. LCID dwLocaleList[20];
  520. DWORD dwPackageFlags;
  521. ULONG cFetched;
  522. ULONG cRowsLeft;
  523. CSPLATFORM PkgPlatform;
  524. //
  525. // Get the rows
  526. //
  527. phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
  528. if(!phRows)
  529. {
  530. return E_OUTOFMEMORY;
  531. }
  532. //
  533. // The LDAP filter performs a part of the selection
  534. // The flag filters are interpreted on the client after obtaining the result set
  535. // That requires us to repeat the fetch a number of times so as to
  536. // make sure that all requested items are obtained.
  537. //
  538. *pcRowsFetched = 0;
  539. cRowsLeft = cRows;
  540. while (TRUE)
  541. {
  542. hr = pIRowset->GetNextRows(NULL, 0, cRowsLeft, &cFetched, &phRows);
  543. if(FAILED(hr))
  544. {
  545. printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
  546. return hr;
  547. }
  548. for (i = 0; i < cFetched; i++)
  549. {
  550. //
  551. // Get the data from each row
  552. //
  553. memset(pData, 0, sizeof(Data) * 20);
  554. hr = pIRowset->GetData(phRows[i],
  555. hAccessor,
  556. (void*)&pData[0]
  557. );
  558. if(FAILED(hr))
  559. {
  560. //
  561. // BUGBUG. Missing cleanup.
  562. //
  563. printf("IRowset::GetData failed \n");
  564. return hr;
  565. }
  566. //
  567. // Check flag values to see if this package meets the filter
  568. //
  569. //Get the Flag Value: Column = packageFlags
  570. dwPackageFlags = 0;
  571. if (pData[1].status != DBSTATUS_S_ISNULL)
  572. {
  573. dwPackageFlags = (ULONG) (pData[1].obValue);
  574. }
  575. if ((dwFlags & APPINFO_PUBLISHED) && (!(dwPackageFlags & ACTFLG_Published)))
  576. {
  577. continue;
  578. }
  579. if ((dwFlags & APPINFO_ASSIGNED) && (!(dwPackageFlags & ACTFLG_Assigned)))
  580. {
  581. continue;
  582. }
  583. if ((dwFlags & APPINFO_VISIBLE) && (!(dwPackageFlags & ACTFLG_UserInstall)))
  584. {
  585. continue;
  586. }
  587. if ((dwFlags & APPINFO_AUTOINSTALL) && (!(dwPackageFlags & ACTFLG_OnDemandInstall)))
  588. {
  589. continue;
  590. }
  591. //
  592. // Move the data into PackageInfo structure
  593. //
  594. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  595. //Column = packageType
  596. if (pData[2].status != DBSTATUS_S_ISNULL)
  597. {
  598. pPackageInfo->PathType = (CLASSPATHTYPE) (ULONG) (pData[2].obValue);
  599. }
  600. //
  601. // Now check PathType
  602. //
  603. if ((dwFlags & APPINFO_MSI) && (pPackageInfo->PathType != DrwFilePath))
  604. {
  605. continue;
  606. }
  607. //
  608. // Now check Locale and Platform
  609. // BUGBUG. Missing.
  610. if (pdwLocale)
  611. {
  612. //Column = localeID
  613. if (pData[8].status != DBSTATUS_S_ISNULL)
  614. {
  615. cLocale = 20;
  616. pVariant = (VARIANT*) pData[8].obValue;
  617. hr = GetFromVariant(pVariant, &cLocale, (LPOLESTR *)&dwLocaleList[0]);
  618. }
  619. for (j=0; j < cLocale; ++j)
  620. {
  621. if (MatchLocale (dwLocaleList[j], *pdwLocale))
  622. break;
  623. }
  624. //
  625. // If none matched skip this package
  626. //
  627. if (j == cLocale)
  628. continue;
  629. }
  630. if (pPlatform != NULL)
  631. {
  632. //Column = machineArchitecture
  633. if (pData[9].status != DBSTATUS_S_ISNULL)
  634. {
  635. cPlatforms = 20;
  636. pVariant = (VARIANT*) pData[9].obValue;
  637. hr = GetFromVariant(pVariant, &cPlatforms, (LPOLESTR *)&dwPlatformList[0]);
  638. }
  639. //Column = oSVersion. BUGBUG - unused now
  640. if (pData[10].status != DBSTATUS_S_ISNULL)
  641. {
  642. cOs = 20;
  643. pVariant = (VARIANT*) pData[10].obValue;
  644. hr = GetFromVariant(pVariant, &cOs, (LPOLESTR *)&dwOsList[0]);
  645. }
  646. for (j=0; j < cPlatforms; ++j)
  647. {
  648. PackPlatform (dwPlatformList[j], &PkgPlatform);
  649. if (MatchPlatform (pPlatform, &PkgPlatform))
  650. break;
  651. }
  652. //
  653. // If none matched skip this package.
  654. //
  655. if (j == cPlatforms)
  656. continue;
  657. }
  658. pPackageInfo->dwActFlags = dwPackageFlags;
  659. //Column = packageName
  660. if (pData[0].status != DBSTATUS_S_ISNULL)
  661. {
  662. pPackageInfo->pszPackageName = (LPWSTR) CoTaskMemAlloc
  663. (sizeof(WCHAR) * (wcslen ((WCHAR *)pData[0].obValue)+1));
  664. wcscpy (pPackageInfo->pszPackageName, (WCHAR *) pData[0].obValue);
  665. }
  666. //Column = codePackage
  667. if (pData[3].status != DBSTATUS_S_ISNULL)
  668. {
  669. pPackageInfo->pszScriptPath = (LPWSTR) CoTaskMemAlloc
  670. (sizeof(WCHAR) * (wcslen ((WCHAR *)pData[3].obValue)+1));
  671. wcscpy (pPackageInfo->pszScriptPath, (WCHAR *) pData[3].obValue);
  672. }
  673. //Column = cScriptLen
  674. // BUGBUG. Wait for pScript.
  675. if (pData[4].status != DBSTATUS_S_ISNULL)
  676. {
  677. pPackageInfo->cScriptLen = 0; //(ULONG) (pData[4].obValue);
  678. }
  679. //Column = lastUpdateSequence,
  680. if (pData[5].status != DBSTATUS_S_ISNULL)
  681. {
  682. swscanf ((LPOLESTR)(pData[5].obValue),
  683. L"%d %d",
  684. &(((CSUSN *)&(pPackageInfo->Usn))->dwHighDateTime),
  685. &(((CSUSN *)&(pPackageInfo->Usn))->dwLowDateTime));
  686. }
  687. //Column = versionNumberHi
  688. if (pData[6].status != DBSTATUS_S_ISNULL)
  689. {
  690. pPackageInfo->dwVersionHi = (ULONG) (pData[6].obValue);
  691. }
  692. //Column = versionNumberLo
  693. if (pData[7].status != DBSTATUS_S_ISNULL)
  694. {
  695. pPackageInfo->dwVersionLo = (ULONG) (pData[7].obValue);
  696. }
  697. if (pData[11].status != DBSTATUS_S_ISNULL)
  698. {
  699. ULONG cUp = 20;
  700. pVariant = (VARIANT*) pData[11].obValue;
  701. pPackageInfo->prgUpgradeScript =
  702. (LPOLESTR *)CoTaskMemAlloc(sizeof(LPOLESTR) * cUp);
  703. hr = GetFromVariant(pVariant, &cUp, pPackageInfo->prgUpgradeScript);
  704. pPackageInfo->cUpgrades = cUp;
  705. pPackageInfo->prgUpgradeFlag =
  706. (DWORD *) CoTaskMemAlloc(sizeof(DWORD) * cUp);
  707. for (j=0; j < cUp; ++j)
  708. {
  709. LPOLESTR pStr;
  710. LPOLESTR ptr = (pPackageInfo->prgUpgradeScript)[j];
  711. UINT l = wcslen (ptr);
  712. *(ptr+l-2) = NULL;
  713. (pPackageInfo->prgUpgradeFlag)[j] =
  714. wcstoul(ptr+(l-1), &pStr, 10);
  715. }
  716. }
  717. //
  718. // Now process inline filters to decide if this package
  719. // meets the filter requirements
  720. // BUGBUG. Not implemented.
  721. if (0)
  722. {
  723. PackPlatform (dwPlatformList[0], NULL);
  724. }
  725. ++pPackageInfo;
  726. (*pcRowsFetched)++;
  727. //
  728. // Release memory
  729. //
  730. }
  731. if (cFetched)
  732. {
  733. //
  734. // Free the Row Handles
  735. //
  736. hr = pIRowset->ReleaseRows(cFetched, phRows, NULL, NULL, NULL);
  737. }
  738. if (cRowsLeft > cFetched)
  739. {
  740. hr = S_FALSE;
  741. break;
  742. }
  743. cRowsLeft = cRows - *pcRowsFetched;
  744. if (cRowsLeft == 0)
  745. {
  746. hr = S_OK;
  747. break;
  748. }
  749. }
  750. if (phRows)
  751. {
  752. //
  753. // Free the Row Handle Pointer
  754. //
  755. CoTaskMemFree (phRows);
  756. }
  757. //
  758. // Check if we found as many as asked for
  759. //
  760. //if (*pcRowsFetched != cRows)
  761. // return S_FALSE;
  762. return hr;
  763. }
  764. // FetchCategory
  765. //--------------
  766. //
  767. // List of columns this routine fetches.
  768. //
  769. LPOLESTR szAppCategoryColumns =
  770. L"extensionName, categoryId";
  771. HRESULT FetchCategory(IRowset * pIRowset,
  772. HACCESSOR hAccessor,
  773. ULONG cRows,
  774. ULONG * pcRowsFetched,
  775. APPCATEGORYINFO ** ppCategory,
  776. LCID Locale
  777. )
  778. {
  779. HROW * phRows = NULL;
  780. HRESULT hr = S_OK;
  781. UINT i;
  782. Data pData[20];
  783. VARIANT * pVariant = NULL;
  784. //
  785. // Get the rows
  786. //
  787. // phRows = (HROW *) CoTaskMemAlloc (sizeof (HROW) * cRows);
  788. // if(!phRows)
  789. // {
  790. // return E_OUTOFMEMORY;
  791. // }
  792. //
  793. // hr = pIRowset->GetNextRows(NULL, 0, cRows, pcRowsFetched, &phRows);
  794. phRows = NULL;
  795. hr = pIRowset->GetNextRows(NULL, 0, cRows, pcRowsFetched, &phRows);
  796. if(FAILED(hr))
  797. {
  798. printf("IRowset::GetNextRows failed hr = 0x%x\n", hr);
  799. return hr;
  800. }
  801. if (*pcRowsFetched)
  802. *ppCategory = (APPCATEGORYINFO *)CoTaskMemAlloc(sizeof(APPCATEGORYINFO)*
  803. (*pcRowsFetched));
  804. for (i = 0; i < *pcRowsFetched; i++)
  805. {
  806. //
  807. // Get the data from each row
  808. //
  809. memset(pData, 0, sizeof(Data));
  810. hr = pIRowset->GetData(phRows[i],
  811. hAccessor,
  812. (void*)&pData[0]
  813. );
  814. if(FAILED(hr))
  815. {
  816. //
  817. // BUGBUG. Missing cleanup.
  818. //
  819. printf("IRowset::GetData failed \n");
  820. return hr;
  821. }
  822. //Column = description
  823. if (pData[0].status != DBSTATUS_S_ISNULL)
  824. {
  825. ULONG cCount = 20;
  826. LPOLESTR pszDesc[20];
  827. pVariant = (VARIANT*) pData[0].obValue;
  828. hr = GetFromVariant(pVariant, &cCount, (LPOLESTR *)&pszDesc[0]);
  829. (*ppCategory)[i].Locale = Locale;
  830. (*ppCategory)[i].pszDescription = (LPOLESTR)CoTaskMemAlloc(sizeof(WCHAR)*128);
  831. // BUGBUG:: same as comcat size. an arbitrary restriction.
  832. hr = GetCategoryLocaleDesc(pszDesc, cCount, &((*ppCategory)[i].Locale),
  833. (*ppCategory)[i].pszDescription);
  834. }
  835. // column catid
  836. if (pData[1].status != DBSTATUS_S_ISNULL)
  837. {
  838. GUIDFromString((LPOLESTR)pData[1].obValue, &((*ppCategory)[i].AppCategoryId));
  839. }
  840. }
  841. if (*pcRowsFetched)
  842. {
  843. //
  844. // Free the Row Handles
  845. //
  846. hr = pIRowset->ReleaseRows(*pcRowsFetched, phRows, NULL, NULL, NULL);
  847. }
  848. if (*pcRowsFetched)
  849. {
  850. //
  851. // Free the Row Handle Pointer
  852. //
  853. CoTaskMemFree (phRows);
  854. }
  855. //
  856. // Check if we found as many as asked for
  857. //
  858. if (*pcRowsFetched != cRows)
  859. return S_FALSE;
  860. return S_OK;
  861. }
  862. HRESULT CloseQuery(IAccessor *pAccessor,
  863. HACCESSOR hAccessor,
  864. IRowset *pIRowset)
  865. {
  866. ULONG cRef;
  867. if (pAccessor)
  868. {
  869. pAccessor->ReleaseAccessor(hAccessor, &cRef);
  870. pAccessor->Release();
  871. }
  872. if (pIRowset)
  873. {
  874. pIRowset->Release();
  875. }
  876. return S_OK;
  877. }
  878. //---------------------------------------------------------------
  879. // End of Query
  880. //----------------------------------------------------------------
  881. //
  882. // Form the bindings array to specify the way the provider has to put the
  883. // data in buffer.
  884. //
  885. UINT i;
  886. HRESULT
  887. CreateBindingHelper(
  888. IRowset *pIRowset,
  889. ULONG cColumns,
  890. DBBINDING **pprgBind
  891. )
  892. {
  893. HRESULT hr;
  894. ULONG cCols;
  895. DBCOLUMNINFO *prgColInfo = NULL;
  896. IColumnsInfo *pIColsInfo = NULL;
  897. LPOLESTR szColNames = NULL;
  898. DBBINDING *prgBindings = NULL;
  899. if(!pIRowset)
  900. return(E_INVALIDARG);
  901. hr = pIRowset->QueryInterface(
  902. IID_IColumnsInfo,
  903. (void**) &pIColsInfo
  904. );
  905. if(FAILED(hr))
  906. {
  907. printf("QueryInterface for IColumnsInfo failed \n");
  908. return hr;
  909. }
  910. hr = pIColsInfo->GetColumnInfo(
  911. &cCols,
  912. &prgColInfo,
  913. &szColNames
  914. );
  915. if(FAILED(hr))
  916. {
  917. printf("IColumnsInfo::GetColumnInfo failed \n");
  918. return hr;
  919. }
  920. //
  921. // Verify that the number of columns match
  922. //
  923. if (cColumns != (cCols - 1))
  924. {
  925. return E_FAIL;
  926. }
  927. prgBindings = (DBBINDING *) CoTaskMemAlloc(sizeof(DBBINDING) * cColumns);
  928. //
  929. // Set up rest of the attributes
  930. //
  931. for (i=0; i < cColumns; i++)
  932. {
  933. memset (prgBindings+i, 0, sizeof(DBBINDING));
  934. prgBindings[i].iOrdinal = i+1;
  935. prgBindings[i].wType= prgColInfo[i+1].wType;
  936. if ((prgBindings[i].wType == DBTYPE_DATE) || (prgBindings[i].wType == DBTYPE_I8))
  937. prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue2);
  938. else
  939. prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue);
  940. prgBindings[i].obLength= sizeof(Data)*i + offsetof(Data, obLength);
  941. prgBindings[i].obStatus= sizeof(Data)*i + offsetof(Data, status);
  942. prgBindings[i].dwPart= DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;
  943. if(prgBindings[i].wType & DBTYPE_BYREF)
  944. prgBindings[i].dwMemOwner= DBMEMOWNER_PROVIDEROWNED;
  945. else
  946. prgBindings[i].dwMemOwner= DBMEMOWNER_CLIENTOWNED;
  947. prgBindings[i].dwFlags= 0;
  948. }
  949. *pprgBind = prgBindings;
  950. pIColsInfo->Release();
  951. CoTaskMemFree(szColNames);
  952. CoTaskMemFree(prgColInfo);
  953. return(hr);
  954. }
  955. //
  956. //
  957. void GetCurrentUsn(LPOLESTR pStoreUsn)
  958. {
  959. //
  960. // Get the current time as USN for the Class Store container
  961. //
  962. SYSTEMTIME SystemTime;
  963. GetSystemTime(&SystemTime);
  964. wsprintf (pStoreUsn, L"%4d%2d%2d%2d%2d%2d",
  965. SystemTime.wYear,
  966. SystemTime.wMonth,
  967. SystemTime.wDay,
  968. SystemTime.wHour,
  969. SystemTime.wMinute,
  970. SystemTime.wSecond);
  971. }
  972. //
  973. HRESULT UsnUpd (IADs *pADs, LPWSTR szProp, LPOLESTR pUsn)
  974. {
  975. //
  976. // Store the current USN
  977. //
  978. HRESULT hr = SetProperty (pADs,
  979. szProp,
  980. pUsn);
  981. return S_OK;
  982. }
  983. HRESULT UsnGet(IADs *pADs, LPWSTR szProp, CSUSN *pUsn)
  984. {
  985. //
  986. // Read the USN for the Class Store container or Package
  987. //
  988. WCHAR szTimeStamp [20];
  989. SYSTEMTIME SystemTime;
  990. GetProperty (pADs,
  991. szProp,
  992. szTimeStamp);
  993. swscanf (szTimeStamp, L"%4d%2d%2d%2d%2d%2d",
  994. &SystemTime.wYear,
  995. &SystemTime.wMonth,
  996. &SystemTime.wDay,
  997. &SystemTime.wHour,
  998. &SystemTime.wMinute,
  999. &SystemTime.wSecond);
  1000. SystemTimeToFileTime(&SystemTime,
  1001. (LPFILETIME) pUsn);
  1002. return S_OK;
  1003. }
  1004. HRESULT GetPackageDetail (IADs *pPackageADs,
  1005. PACKAGEDETAIL *pPackageDetail)
  1006. {
  1007. HRESULT hr = S_OK;
  1008. GUID PkgGuid;
  1009. LPOLESTR *pszString = NULL;
  1010. DWORD *pdwArch = NULL, count;
  1011. PLATFORMINFO *pPlatformInfo;
  1012. INSTALLINFO *pInstallInfo;
  1013. ACTIVATIONINFO *pActInfo;
  1014. DWORD cClasses;
  1015. LPOLESTR *szClasses;
  1016. DWORD dwUiLevel;
  1017. memset (pPackageDetail, 0, sizeof (PACKAGEDETAIL));
  1018. pInstallInfo = pPackageDetail->pInstallInfo = (INSTALLINFO *) CoTaskMemAlloc(sizeof (INSTALLINFO));
  1019. if (pInstallInfo)
  1020. {
  1021. memset(pInstallInfo, NULL, sizeof(INSTALLINFO));
  1022. hr = GetPropertyDW (pPackageADs, PACKAGEFLAGS,
  1023. &(pInstallInfo->dwActFlags));
  1024. ERROR_ON_FAILURE(hr);
  1025. hr = GetPropertyDW (pPackageADs, PACKAGETYPE,
  1026. (DWORD *)&(pInstallInfo->PathType));
  1027. ERROR_ON_FAILURE(hr);
  1028. hr = GetPropertyAlloc(pPackageADs, SCRIPTPATH,
  1029. &(pInstallInfo->pszScriptPath));
  1030. ERROR_ON_FAILURE(hr);
  1031. // BUGBUG. Wait for pScript
  1032. //hr = GetPropertyDW (pPackageADs, SCRIPTSIZE,
  1033. // &(pInstallInfo->cScriptLen));
  1034. //ERROR_ON_FAILURE(hr);
  1035. hr = GetPropertyAlloc(pPackageADs, SETUPCOMMAND,
  1036. &(pInstallInfo->pszSetupCommand));
  1037. ERROR_ON_FAILURE(hr);
  1038. hr = GetPropertyAlloc(pPackageADs, HELPURL,
  1039. &(pInstallInfo->pszUrl));
  1040. ERROR_ON_FAILURE(hr);
  1041. hr = UsnGet(pPackageADs,
  1042. PKGUSN,
  1043. (CSUSN *)&(pInstallInfo->Usn));
  1044. ERROR_ON_FAILURE(hr);
  1045. hr = GetPropertyDW (pPackageADs, CLASSCTX,
  1046. &(pInstallInfo->dwComClassContext));
  1047. ERROR_ON_FAILURE(hr);
  1048. // BUGBUG::***ProductCode
  1049. hr = GetPropertyDW (pPackageADs, VERSIONHI,
  1050. &(pInstallInfo->dwVersionHi));
  1051. ERROR_ON_FAILURE(hr);
  1052. hr = GetPropertyDW (pPackageADs, VERSIONLO,
  1053. &(pInstallInfo->dwVersionLo));
  1054. ERROR_ON_FAILURE(hr);
  1055. hr = GetPropertyDW (pPackageADs, UILEVEL,
  1056. &dwUiLevel);
  1057. pInstallInfo->InstallUiLevel = dwUiLevel;
  1058. ERROR_ON_FAILURE(hr);
  1059. hr = GetPropertyListAlloc(pPackageADs,
  1060. UPGRADESCRIPTNAMES,
  1061. &count,
  1062. &(pInstallInfo->prgUpgradeScript));
  1063. pInstallInfo->prgUpgradeFlag = (DWORD *)CoTaskMemAlloc(count*sizeof(DWORD));
  1064. pInstallInfo->cUpgrades = count;
  1065. for (count = 0; (count < (pInstallInfo->cUpgrades)); count++)
  1066. {
  1067. LPOLESTR pStr = NULL;
  1068. LPOLESTR ptr = (pInstallInfo->prgUpgradeScript)[count];
  1069. UINT l = wcslen (ptr);
  1070. *(ptr + l - 2) = NULL;
  1071. (pInstallInfo->prgUpgradeFlag)[count] = wcstoul(ptr+(l-1), &pStr, 10);
  1072. }
  1073. }
  1074. pPlatformInfo = pPackageDetail->pPlatformInfo =
  1075. (PLATFORMINFO *) CoTaskMemAlloc(sizeof (PLATFORMINFO));
  1076. if (pPlatformInfo)
  1077. {
  1078. memset(pPlatformInfo, NULL, sizeof(PLATFORMINFO));
  1079. hr = GetPropertyListAllocDW(pPackageADs, ARCHLIST,
  1080. (DWORD *)&(pPlatformInfo->cPlatforms), &pdwArch);
  1081. ERROR_ON_FAILURE(hr);
  1082. pPlatformInfo->prgPlatform = (CSPLATFORM *)CoTaskMemAlloc(sizeof(CSPLATFORM)*
  1083. (pPlatformInfo->cPlatforms));
  1084. for (count = 0; (count < (pPlatformInfo->cPlatforms)); count++)
  1085. PackPlatform (pdwArch[count], (pPlatformInfo->prgPlatform)+count);
  1086. CoTaskMemFree(pdwArch);
  1087. hr = GetPropertyListAllocDW (pPackageADs, LOCALEID,
  1088. (DWORD *)&(pPlatformInfo->cLocales),
  1089. &(pPlatformInfo->prgLocale));
  1090. ERROR_ON_FAILURE(hr);
  1091. }
  1092. //
  1093. // fill in ActivationInfo.
  1094. //
  1095. pActInfo = pPackageDetail->pActInfo =
  1096. (ACTIVATIONINFO *) CoTaskMemAlloc(sizeof (ACTIVATIONINFO));
  1097. if (pActInfo)
  1098. {
  1099. memset(pActInfo, NULL, sizeof(ACTIVATIONINFO));
  1100. hr = GetPropertyListAlloc(pPackageADs, PKGCLSIDLIST, &cClasses, &szClasses);
  1101. pActInfo->cClasses = cClasses;
  1102. if (cClasses)
  1103. {
  1104. pActInfo->pClasses = (CLASSDETAIL *) CoTaskMemAlloc (cClasses * sizeof(CLASSDETAIL));
  1105. memset (pActInfo->pClasses, NULL, cClasses * sizeof(CLASSDETAIL));
  1106. for (count = 0; count < cClasses; count++)
  1107. {
  1108. GUIDFromString(szClasses[count], &((pActInfo->pClasses[count]).Clsid));
  1109. }
  1110. }
  1111. for (count = 0; count < cClasses; count++)
  1112. CoTaskMemFree(szClasses[count]);
  1113. CoTaskMemFree(szClasses);
  1114. hr = GetPropertyListAlloc(pPackageADs, PKGIIDLIST, &cClasses, &szClasses);
  1115. pActInfo->cInterfaces = cClasses;
  1116. if (cClasses)
  1117. {
  1118. pActInfo->prgInterfaceId = (IID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
  1119. for (count = 0; count < cClasses; count++)
  1120. {
  1121. GUIDFromString(szClasses[count], (pActInfo->prgInterfaceId + count));
  1122. }
  1123. }
  1124. for (count = 0; count < cClasses; count++)
  1125. CoTaskMemFree(szClasses[count]);
  1126. CoTaskMemFree(szClasses);
  1127. hr = GetPropertyListAlloc(pPackageADs, PKGTLBIDLIST, &cClasses, &szClasses);
  1128. pActInfo->cTypeLib = cClasses;
  1129. if (cClasses)
  1130. {
  1131. pActInfo->prgTlbId = (GUID *) CoTaskMemAlloc (cClasses * sizeof(GUID));
  1132. for (count = 0; count < cClasses; count++)
  1133. {
  1134. GUIDFromString(szClasses[count], (pActInfo->prgTlbId + count));
  1135. }
  1136. }
  1137. for (count = 0; count < cClasses; count++)
  1138. CoTaskMemFree(szClasses[count]);
  1139. CoTaskMemFree(szClasses);
  1140. hr = GetPropertyListAlloc(pPackageADs, PKGFILEEXTNLIST, &cClasses,
  1141. &(pActInfo->prgShellFileExt));
  1142. pActInfo->cShellFileExt = cClasses;
  1143. if (cClasses)
  1144. {
  1145. pActInfo->prgPriority = (UINT *)CoTaskMemAlloc(cClasses * sizeof(UINT));
  1146. for (count = 0; count < cClasses; count++)
  1147. {
  1148. LPOLESTR pStr;
  1149. UINT cLen = wcslen((pActInfo->prgShellFileExt)[count]);
  1150. *((pActInfo->prgShellFileExt)[count] + (cLen - 3)) = NULL;
  1151. (pActInfo->prgPriority)[count] =
  1152. wcstoul((pActInfo->prgShellFileExt)[count]+(cLen-2), &pStr, 10);
  1153. }
  1154. }
  1155. }
  1156. //
  1157. // fill in package misc info
  1158. //
  1159. hr = GetPropertyAlloc(pPackageADs, PACKAGENAME,
  1160. &(pPackageDetail->pszPackageName));
  1161. ERROR_ON_FAILURE(hr);
  1162. hr = GetPropertyListAlloc(pPackageADs, MSIFILELIST, &cClasses,
  1163. &(pPackageDetail->pszSourceList));
  1164. pPackageDetail->cSources = cClasses;
  1165. ERROR_ON_FAILURE(hr);
  1166. hr = GetPropertyListAlloc(pPackageADs, PKGCATEGORYLIST,
  1167. &cClasses, &szClasses);
  1168. ERROR_ON_FAILURE(hr);
  1169. if (cClasses)
  1170. {
  1171. pPackageDetail->rpCategory = (GUID *)CoTaskMemAlloc (sizeof(GUID) * cClasses);
  1172. pPackageDetail->cCategories = cClasses;
  1173. for (count = 0; count < cClasses; count++)
  1174. {
  1175. GUIDFromString(szClasses[count], (pPackageDetail->rpCategory + count));
  1176. CoTaskMemFree(szClasses[count]);
  1177. }
  1178. CoTaskMemFree(szClasses);
  1179. }
  1180. Error_Cleanup:
  1181. // BUGBUG:: free each of the strings.
  1182. if (pszString)
  1183. CoTaskMemFree(pszString);
  1184. pPackageADs->Release();
  1185. return hr;
  1186. }
  1187.