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

2394 lines
71 KiB

  1. //
  2. // Author: DebiM/UShaji
  3. // Date: Jan 97 - Apr 98
  4. //
  5. // Class Store Query and Fetch Implementation
  6. //
  7. //
  8. //---------------------------------------------------------------------
  9. //
  10. #include "cstore.hxx"
  11. //
  12. // List of Attributes for On-Demand Package Lookup Query
  13. //
  14. LPOLESTR pszInstallInfoAttrNames[] =
  15. {
  16. PKGFILEEXTNLIST, LOCALEID, ARCHLIST, PACKAGEFLAGS, SCRIPTPATH, PKGCLSIDLIST,
  17. PACKAGETYPE, PKGUSN, VERSIONHI, VERSIONLO, UPGRADESPACKAGES, UILEVEL,
  18. PACKAGENAME, HELPURL, PUBLISHER, REVISION, PRODUCTCODE, OBJECTDN,
  19. OBJECTGUID, MSIFILELIST, SECURITYDESCRIPTOR
  20. };
  21. DWORD cInstallInfoAttr = sizeof(pszInstallInfoAttrNames) / sizeof(*pszInstallInfoAttrNames);
  22. //
  23. // List of Attributes for GetPackageDetail() method
  24. //
  25. LPOLESTR pszPackageDetailAttrNames[] =
  26. {
  27. PACKAGEFLAGS, PACKAGETYPE, SCRIPTPATH, SCRIPTSIZE, SETUPCOMMAND, HELPURL, PKGUSN,
  28. VERSIONHI, VERSIONLO, UILEVEL, UPGRADESPACKAGES, ARCHLIST, LOCALEID, PKGCLSIDLIST,
  29. PKGFILEEXTNLIST,PACKAGENAME, MSIFILELIST, PKGCATEGORYLIST, MVIPC,
  30. PRODUCTCODE, REVISION, OBJECTGUID
  31. };
  32. DWORD cPackageDetailAttr = sizeof(pszPackageDetailAttrNames) / sizeof(*pszPackageDetailAttrNames);
  33. LPOLESTR pszDeleteAttrNames[] =
  34. {
  35. PACKAGEFLAGS, OBJECTDN
  36. };
  37. DWORD cDeleteAttr = 2;
  38. //
  39. // List of Attributes for App Categories
  40. //
  41. LPOLESTR pszCategoryAttrNames[] =
  42. {
  43. LOCALEDESCRIPTION, CATEGORYCATID
  44. };
  45. DWORD cCategoryAttr = 2;
  46. void GetAttributesFromPackageFlags(
  47. DWORD dwPackageFlags,
  48. UINT* pUILevel,
  49. CLASSPATHTYPE* pClassType)
  50. {
  51. *pUILevel = dwPackageFlags & ACTFLG_FullInstallUI ?
  52. INSTALLUILEVEL_BASIC :
  53. INSTALLUILEVEL_FULL;
  54. *pClassType = (CLASSPATHTYPE) (dwPackageFlags >>
  55. PATHTYPESHIFT);
  56. }
  57. BOOL MatchPlatform(
  58. CSPLATFORM *pReqPlatform,
  59. CSPLATFORM *pPkgPlatform,
  60. BOOL fExcludeX86OnWin64,
  61. BOOL fLegacy)
  62. {
  63. //
  64. // Make sure this is the correct platform
  65. //
  66. if (pReqPlatform->dwPlatformId != pPkgPlatform->dwPlatformId)
  67. {
  68. return FALSE;
  69. }
  70. //
  71. // ProcessorArch must match
  72. //
  73. if (pReqPlatform->dwProcessorArch != pPkgPlatform->dwProcessorArch)
  74. {
  75. //
  76. // Reinterpret this flag based on whether this is a legacy deployment
  77. // or not -- we have the opposite semantics for this flag for
  78. // legacy deployments
  79. //
  80. if ( fLegacy )
  81. {
  82. fExcludeX86OnWin64 = ! fExcludeX86OnWin64;
  83. }
  84. //
  85. // If the caller is requesting to ignore x86 on Win64, inequality between
  86. // architectures is automatic disqualification
  87. //
  88. if (fExcludeX86OnWin64)
  89. {
  90. return FALSE;
  91. }
  92. //
  93. // Caller specified that we should allow x86 packages on win64 --
  94. // see if we are in that situation, and only disqualify the package if not
  95. //
  96. if (!(((PROCESSOR_ARCHITECTURE_IA64 == pReqPlatform->dwProcessorArch) ||
  97. (PROCESSOR_ARCHITECTURE_AMD64 == pReqPlatform->dwProcessorArch)) &&
  98. (PROCESSOR_ARCHITECTURE_INTEL == pPkgPlatform->dwProcessorArch)) )
  99. {
  100. return FALSE;
  101. }
  102. }
  103. //
  104. // Check the OS version, hi part first -- this requested platform must be at least as
  105. // high as the package platform -- if not, it is disqualified
  106. //
  107. if (pReqPlatform->dwVersionHi < pPkgPlatform->dwVersionHi)
  108. {
  109. return FALSE;
  110. }
  111. //
  112. // If the hi version is the same, check the low part of the os version
  113. //
  114. if (pReqPlatform->dwVersionHi == pPkgPlatform->dwVersionHi)
  115. {
  116. //
  117. // If the requested platform is less than the package, it cannot
  118. // support that package, so the package is disqualified.
  119. //
  120. if (pReqPlatform->dwVersionLo < pPkgPlatform->dwVersionLo)
  121. {
  122. return FALSE;
  123. }
  124. }
  125. //
  126. // We passed all the tests -- the package matches the requested platform
  127. //
  128. return TRUE;
  129. }
  130. // this has to change if the Msi can give us a preferred list etc.
  131. DWORD PlatformWt(
  132. CSPLATFORM *pReqPlatform,
  133. CSPLATFORM *pPkgPlatform,
  134. BOOL fExcludeX86OnWin64,
  135. BOOL fLegacy)
  136. {
  137. //
  138. // See if we get an exact match
  139. //
  140. if (MatchPlatform(pReqPlatform,
  141. pPkgPlatform,
  142. TRUE,
  143. FALSE))
  144. {
  145. return PRI_ARCH_PREF1;
  146. }
  147. //
  148. // If we don't match exactly, try matching
  149. // through by taking exclusion flag into account
  150. //
  151. if (MatchPlatform(pReqPlatform,
  152. pPkgPlatform,
  153. fExcludeX86OnWin64,
  154. fLegacy))
  155. {
  156. return PRI_ARCH_PREF2;
  157. }
  158. return 0;
  159. }
  160. DWORD ClassContextWt(DWORD ClsCtx)
  161. {
  162. if (ClsCtx & CLSCTX_INPROC_SERVER)
  163. return PRI_CLSID_INPSVR;
  164. if (ClsCtx & CLSCTX_LOCAL_SERVER)
  165. return PRI_CLSID_LCLSVR;
  166. if (ClsCtx & CLSCTX_REMOTE_SERVER)
  167. return PRI_CLSID_REMSVR;
  168. return 0;
  169. }
  170. //
  171. //
  172. void GetCurrentUsn(LPOLESTR pStoreUsn)
  173. {
  174. //
  175. // Get the current time as USN for the Class Store container
  176. //
  177. SYSTEMTIME SystemTime;
  178. GetSystemTime(&SystemTime);
  179. (void) StringCchPrintf (pStoreUsn,
  180. 15,
  181. L"%04d%02d%02d%02d%02d%02d",
  182. SystemTime.wYear,
  183. SystemTime.wMonth,
  184. SystemTime.wDay,
  185. SystemTime.wHour,
  186. SystemTime.wMinute,
  187. SystemTime.wSecond);
  188. }
  189. void TimeToUsn (LPOLESTR szTimeStamp, CSUSN *pUsn)
  190. {
  191. SYSTEMTIME SystemTime;
  192. if (szTimeStamp)
  193. {
  194. UINT l = wcslen(szTimeStamp) - 1;
  195. LPOLESTR pStr = szTimeStamp;
  196. for (UINT i=0; i < l; ++i)
  197. {
  198. if (*pStr == L' ')
  199. *pStr = L'0';
  200. ++pStr;
  201. }
  202. int iStatus;
  203. iStatus = swscanf (szTimeStamp, L"%4d%2d%2d%2d%2d%2d",
  204. &SystemTime.wYear,
  205. &SystemTime.wMonth,
  206. &SystemTime.wDay,
  207. &SystemTime.wHour,
  208. &SystemTime.wMinute,
  209. &SystemTime.wSecond);
  210. if (EOF == iStatus || 0 == iStatus)
  211. {
  212. memset(pUsn, 0, sizeof(FILETIME));
  213. }
  214. else
  215. {
  216. SystemTimeToFileTime(&SystemTime, (LPFILETIME) pUsn);
  217. }
  218. }
  219. else
  220. pUsn->dwHighDateTime = pUsn->dwLowDateTime = 0;
  221. }
  222. HRESULT UsnGet(ADS_ATTR_INFO Attr, CSUSN *pUsn)
  223. {
  224. //
  225. // Read the USN for the Class Store container or Package
  226. //
  227. WCHAR *szTimeStamp=NULL;
  228. UnpackStrFrom(Attr, &szTimeStamp);
  229. TimeToUsn (szTimeStamp, pUsn);
  230. return S_OK;
  231. }
  232. // FetchInstallData
  233. //-----------------
  234. //
  235. //
  236. // Gets the result set of the ondemand lookup query to locate an install package.
  237. // Returns the properties of the most likely Package in PackageInfo structure.
  238. //
  239. // In case more than one package meets the criteria, their priorities are returned.
  240. //
  241. HRESULT FetchInstallData(HANDLE hADs,
  242. ADS_SEARCH_HANDLE hADsSearchHandle,
  243. QUERYCONTEXT *pQryContext,
  244. uCLSSPEC *pclsspec,
  245. LPOLESTR pszFileExt,
  246. ULONG cRows,
  247. ULONG *pcRowsFetched,
  248. PACKAGEDISPINFO *pPackageInfo,
  249. UINT *pdwPriority,
  250. BOOL OnDemandInstallOnly,
  251. GUID* pGpoId,
  252. WCHAR* wszGpoPath
  253. )
  254. {
  255. HRESULT hr = S_OK;
  256. LPOLESTR szUsn = NULL;
  257. ULONG cCount = 0;
  258. LPOLESTR * pszList = NULL;
  259. DWORD * pdwList = NULL;
  260. ADS_SEARCH_COLUMN column;
  261. CSPLATFORM PkgPlatform;
  262. //
  263. // Get the rows
  264. //
  265. //
  266. // Clear the caller supplied buffer in case the call to
  267. // get the first row fails
  268. //
  269. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  270. *pcRowsFetched = 0;
  271. if (*pcRowsFetched == cRows)
  272. return S_OK;
  273. for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle);
  274. ;
  275. hr = ADSIGetNextRow(hADs, hADsSearchHandle))
  276. {
  277. //
  278. // Get the data from each row
  279. //
  280. //
  281. // Clear the caller supplied buffer in case previous
  282. // trips through this loop have written data
  283. //
  284. ReleasePackageInfo(pPackageInfo);
  285. //
  286. // Stop iterating if there are no more rows
  287. //
  288. if (!((SUCCEEDED(hr)) && (hr != S_ADS_NOMORE_ROWS)))
  289. {
  290. break;
  291. }
  292. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PACKAGENAME, &column);
  293. if (SUCCEEDED(hr))
  294. {
  295. hr = UnpackStrAllocFrom(column, &(pPackageInfo->pszPackageName));
  296. ADSIFreeColumn(hADs, &column);
  297. CSDBGPrint((DM_WARNING,
  298. IDS_CSTORE_EXAMINING,
  299. pPackageInfo->pszPackageName));
  300. }
  301. else {
  302. CSDBGPrint((DM_WARNING,
  303. IDS_CSTORE_MISSING_ATTR,
  304. PACKAGENAME,
  305. hr));
  306. continue;
  307. }
  308. //
  309. // Determine the package flags -- this is used to interpret many
  310. // of the remaining attributes
  311. //
  312. if (SUCCEEDED(hr))
  313. {
  314. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, PACKAGEFLAGS, &column);
  315. }
  316. if (SUCCEEDED(hr))
  317. {
  318. UnpackDWFrom(column, &(pPackageInfo->dwActFlags));
  319. ADSIFreeColumn(hADs, &column);
  320. }
  321. else
  322. {
  323. CSDBGPrint((DM_WARNING,
  324. IDS_CSTORE_MISSING_ATTR,
  325. PACKAGEFLAGS,
  326. hr));
  327. continue;
  328. }
  329. //
  330. // Ignore the following checks when looking for a specific application
  331. // object. The caller knows what he's doing in this case and may be
  332. // searching for a removed application specifically.
  333. //
  334. if ( pclsspec->tyspec != TYSPEC_OBJECTID )
  335. {
  336. //
  337. // Does it support AutoInstall?
  338. //
  339. if ((OnDemandInstallOnly) && (!(pPackageInfo->dwActFlags & ACTFLG_OnDemandInstall)))
  340. {
  341. CSDBGPrint((DM_WARNING,
  342. IDS_CSTORE_SKIP_FLAG,
  343. pPackageInfo->pszPackageName,
  344. ACTFLG_OnDemandInstall));
  345. continue;
  346. }
  347. // If it is neither Published nor Assigned then skip it.
  348. if ((!(pPackageInfo->dwActFlags & ACTFLG_Published)) &&
  349. (!(pPackageInfo->dwActFlags & ACTFLG_Assigned)))
  350. {
  351. CSDBGPrint((DM_WARNING,
  352. IDS_CSTORE_SKIP_FLAG,
  353. pPackageInfo->pszPackageName,
  354. ACTFLG_Assigned));
  355. continue;
  356. }
  357. // If it is an Orphaned App OR Uninstalled App do not return.
  358. if ((pPackageInfo->dwActFlags & ACTFLG_Orphan) ||
  359. (pPackageInfo->dwActFlags & ACTFLG_Uninstall))
  360. {
  361. CSDBGPrint((DM_WARNING,
  362. IDS_CSTORE_SKIP_FLAG,
  363. pPackageInfo->pszPackageName,
  364. ACTFLG_Uninstall));
  365. continue;
  366. }
  367. }
  368. //
  369. // Packages using the NT 5.0 beta 3 schema are not
  370. // supported in subsequent versions of Windows
  371. //
  372. if ( ! (pPackageInfo->dwActFlags & ACTFLG_POSTBETA3) )
  373. {
  374. CSDBGPrint((DM_WARNING,
  375. IDS_CSTORE_BETA3_ERR));
  376. continue;
  377. }
  378. GetAttributesFromPackageFlags(
  379. pPackageInfo->dwActFlags,
  380. &(pPackageInfo->InstallUiLevel),
  381. &(pPackageInfo->PathType));
  382. //
  383. // If querying by file ext check match and priority
  384. //
  385. *pdwPriority = 0;
  386. if (pszFileExt)
  387. {
  388. ULONG j;
  389. //Column = fileExtension
  390. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PKGFILEEXTNLIST, &column);
  391. cCount = 0;
  392. if (SUCCEEDED(hr))
  393. {
  394. hr = UnpackStrArrFrom(column, &pszList, &cCount);
  395. }
  396. if (SUCCEEDED(hr))
  397. {
  398. UINT cLen = wcslen(pszFileExt);
  399. for (j=0; j < cCount; ++j)
  400. {
  401. LPOLESTR pStr = NULL;
  402. if (wcslen(pszList[j]) != (cLen+3))
  403. continue;
  404. if (wcsncmp(pszList[j], pszFileExt, wcslen(pszFileExt)) != 0)
  405. continue;
  406. *pdwPriority = (wcstoul(pszList[j]+(cLen+1), &pStr, 10))*PRI_EXTN_FACTOR;
  407. break;
  408. }
  409. ADSIFreeColumn(hADs, &column);
  410. }
  411. else
  412. {
  413. break;
  414. }
  415. CsMemFree(pszList); pszList = NULL;
  416. //
  417. // If none matched skip this package
  418. //
  419. if (j == cCount) {
  420. CSDBGPrint((DM_WARNING,
  421. IDS_CSTORE_SKIP_FILE,
  422. pPackageInfo->pszPackageName));
  423. continue;
  424. }
  425. }
  426. //
  427. // Now check Locale and Platform -- only do this
  428. // if a locale was specified
  429. //
  430. if (0 != pQryContext->Locale)
  431. {
  432. DWORD Wt = 0, MaxWt = 0;
  433. LANGID DesiredLang;
  434. DesiredLang = LANGIDFROMLCID(pQryContext->Locale);
  435. //Column = localeID
  436. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, LOCALEID, &column);
  437. cCount = 0;
  438. if (SUCCEEDED(hr))
  439. {
  440. DWORD dwCount;
  441. cCount = 0;
  442. dwCount = 0;
  443. //
  444. // We pass dwCount instead of cCount to avoid
  445. // type conversion problems. Note that we know the list
  446. // to always be of length 1 from the fact that
  447. // the deployment code will only use one language, so we
  448. // will not overflow this buffer
  449. //
  450. UnpackDWArrFrom(column, &pdwList, &dwCount);
  451. cCount = dwCount;
  452. ADSIFreeColumn(hADs, &column);
  453. }
  454. {
  455. //
  456. // If the caller specifies LANG_SYSTEM_DEFAULT, we interpret this
  457. // to mean that the caller wants us to choose apps according
  458. // to the language precedence in GetLanguagePriority. If some
  459. // other langid was given, we then only accept exact matches and
  460. // give those matches the highest priority, PRI_LANG_ALWAYSMATCH
  461. //
  462. if (LANG_SYSTEM_DEFAULT == DesiredLang)
  463. {
  464. Wt = GetLanguagePriority (
  465. LANGIDFROMLCID(pdwList[0]),
  466. pPackageInfo->dwActFlags);
  467. }
  468. else
  469. {
  470. Wt = (DesiredLang == LANGIDFROMLCID(pdwList[0])) ?
  471. PRI_LANG_ALWAYSMATCH :
  472. 0;
  473. }
  474. if (Wt > MaxWt)
  475. MaxWt = Wt;
  476. }
  477. //
  478. // If none matched skip this package
  479. //
  480. DWORD dwLocale;
  481. BOOL fHasLocale;
  482. fHasLocale = FALSE;
  483. if (pdwList)
  484. {
  485. dwLocale = LANGIDFROMLCID(pdwList[0]);
  486. CsMemFree(pdwList);
  487. fHasLocale = TRUE;
  488. }
  489. pdwList = NULL;
  490. // if nothing matched, quit
  491. if (MaxWt == 0)
  492. {
  493. if ( ! fHasLocale )
  494. {
  495. CSDBGPrint((DM_WARNING,
  496. IDS_CSTORE_MISSING_ATTR,
  497. LOCALEID,
  498. hr));
  499. }
  500. continue;
  501. }
  502. *pdwPriority += MaxWt;
  503. pPackageInfo->LangId = (LANGID) dwLocale;
  504. }
  505. hr = GetRsopSpecificAttributes(
  506. hADs,
  507. hADsSearchHandle,
  508. NULL,
  509. pPackageInfo,
  510. NULL);
  511. if (FAILED(hr))
  512. {
  513. CSDBGPrint((DM_WARNING,
  514. IDS_CSTORE_RSOPERROR,
  515. hr));
  516. }
  517. if (SUCCEEDED(hr))
  518. {
  519. DWORD dwCount;
  520. cCount = 0;
  521. dwCount = 0;
  522. DWORD Wt = 0, MaxWt = 0;
  523. dwCount = pPackageInfo->cArchitectures;
  524. pdwList = pPackageInfo->prgArchitectures;
  525. cCount = dwCount;
  526. pPackageInfo->MatchedArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  527. for (ULONG j=0; j < cCount; ++j)
  528. {
  529. PackPlatform (pdwList[j], &PkgPlatform);
  530. Wt = PlatformWt (&(pQryContext->Platform),
  531. &PkgPlatform,
  532. pPackageInfo->dwActFlags & ACTFLG_ExcludeX86OnWin64,
  533. SetupNamePath == pPackageInfo->PathType);
  534. if (Wt > MaxWt)
  535. {
  536. pPackageInfo->MatchedArchitecture = pdwList[j];
  537. MaxWt = Wt;
  538. }
  539. }
  540. pdwList = NULL;
  541. //
  542. // If none matched skip this package
  543. //
  544. if (MaxWt == 0)
  545. {
  546. CSDBGPrint((DM_WARNING,
  547. IDS_CSTORE_SKIP_ARCH,
  548. pPackageInfo->pszPackageName));
  549. continue;
  550. }
  551. *pdwPriority += MaxWt;
  552. }
  553. else
  554. {
  555. continue;
  556. }
  557. // passed all the filters.
  558. //Column = OBJECTGUID
  559. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_OCTET_STRING, OBJECTGUID, &column);
  560. if (SUCCEEDED(hr))
  561. {
  562. LPOLESTR pStr = NULL;
  563. UnpackGUIDFrom(column, &(pPackageInfo->PackageGuid));
  564. ADSIFreeColumn(hADs, &column);
  565. }
  566. //Column = ScriptPath
  567. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, SCRIPTPATH, &column);
  568. if (SUCCEEDED(hr))
  569. {
  570. hr = UnpackStrAllocFrom(column, &(pPackageInfo->pszScriptPath));
  571. ADSIFreeColumn(hADs, &column);
  572. if (FAILED(hr))
  573. {
  574. break;
  575. }
  576. }
  577. if (SUCCEEDED(hr) && (pclsspec->tyspec == TYSPEC_CLSID))
  578. {
  579. //Column = comClassID
  580. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PKGCLSIDLIST, &column);
  581. cCount = 0;
  582. if (SUCCEEDED(hr))
  583. {
  584. hr = UnpackStrArrFrom(column, &pszList, &cCount);
  585. if (cCount)
  586. {
  587. DWORD i=0, Ctx = 0;
  588. WCHAR szClsid[STRINGGUIDLEN], *szPtr = NULL;
  589. StringFromGUID(pclsspec->tagged_union.clsid, szClsid);
  590. for (i = 0; i < cCount; i++)
  591. if (wcsncmp(pszList[i], szClsid, STRINGGUIDLEN-1) == 0)
  592. break;
  593. //
  594. // The below assert is only hit if there is bad data -- if we find the
  595. // clsid, i will not be cCount, and cCount will never be 0. Basically,
  596. // we're asserting that the search should always succeed if the ds data
  597. // is good.
  598. //
  599. ASSERT(i != cCount);
  600. if (i == cCount)
  601. {
  602. CSDBGPrint((DM_WARNING,
  603. IDS_CSTORE_SKIP_CLSID,
  604. pPackageInfo->pszPackageName));
  605. CsMemFree(pszList);
  606. continue;
  607. }
  608. if (wcslen(pszList[i]) > (STRINGGUIDLEN-1))
  609. Ctx = wcstoul(pszList[i]+STRINGGUIDLEN, &szPtr, 16);
  610. if ( ( Ctx & pQryContext->dwContext ) == 0 )
  611. {
  612. CsMemFree(pszList);
  613. ADSIFreeColumn(hADs, &column);
  614. CSDBGPrint((DM_WARNING,
  615. IDS_CSTORE_SKIP_CLSID,
  616. pPackageInfo->pszPackageName));
  617. // none of the class context matched.
  618. continue;
  619. }
  620. else
  621. *pdwPriority += ClassContextWt((Ctx & pQryContext->dwContext));
  622. CsMemFree(pszList);
  623. }
  624. ADSIFreeColumn(hADs, &column);
  625. if (FAILED(hr))
  626. {
  627. break;
  628. }
  629. }
  630. }
  631. //Column = lastUpdateSequence
  632. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PKGUSN, &column);
  633. if (SUCCEEDED(hr))
  634. {
  635. hr = UnpackStrFrom(column, &szUsn);
  636. TimeToUsn (szUsn, (CSUSN *)(&(pPackageInfo->Usn)));
  637. ADSIFreeColumn(hADs, &column);
  638. if (FAILED(hr))
  639. {
  640. break;
  641. }
  642. }
  643. else {
  644. CSDBGPrint((DM_WARNING,
  645. IDS_CSTORE_MISSING_ATTR,
  646. PKGUSN,
  647. hr));
  648. continue;
  649. }
  650. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_OCTET_STRING, PRODUCTCODE, &column);
  651. if (SUCCEEDED(hr))
  652. {
  653. UnpackGUIDFrom(column, &(pPackageInfo->ProductCode));
  654. ADSIFreeColumn(hADs, &column);
  655. }
  656. //Column = versionNumberHi
  657. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, VERSIONHI, &column);
  658. if (SUCCEEDED(hr))
  659. {
  660. UnpackDWFrom(column, &(pPackageInfo->dwVersionHi));
  661. ADSIFreeColumn(hADs, &column);
  662. }
  663. //Column = versionNumberLo
  664. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, VERSIONLO, &column);
  665. if (SUCCEEDED(hr))
  666. {
  667. UnpackDWFrom(column, &(pPackageInfo->dwVersionLo));
  668. ADSIFreeColumn(hADs, &column);
  669. }
  670. //Column = revision
  671. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, REVISION, &column);
  672. if (SUCCEEDED(hr))
  673. {
  674. UnpackDWFrom(column, &(pPackageInfo->dwRevision));
  675. ADSIFreeColumn(hADs, &column);
  676. }
  677. // Column = url
  678. // This one is optional and will be unset in most cases.
  679. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, HELPURL, &column);
  680. if (SUCCEEDED(hr))
  681. {
  682. UnpackStrAllocFrom(column, &(pPackageInfo->pszUrl));
  683. ADSIFreeColumn(hADs, &column);
  684. }
  685. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, UPGRADESPACKAGES, &column);
  686. if (SUCCEEDED(hr))
  687. {
  688. LPOLESTR *pProp = NULL;
  689. hr = UnpackStrArrAllocFrom(column, &pProp, (DWORD *)&(pPackageInfo->cUpgrades));
  690. if (pPackageInfo->cUpgrades)
  691. pPackageInfo->prgUpgradeInfoList = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*
  692. (pPackageInfo->cUpgrades));
  693. if (pPackageInfo->prgUpgradeInfoList)
  694. {
  695. memset(pPackageInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pPackageInfo->cUpgrades));
  696. for (ULONG j=0; j < (pPackageInfo->cUpgrades); ++j)
  697. {
  698. WCHAR *pStr = NULL;
  699. LPOLESTR ptr = (pPackageInfo->prgUpgradeInfoList[j].szClassStore) = pProp[j];
  700. UINT len = wcslen (ptr);
  701. if (len <= 41)
  702. continue;
  703. *(ptr + len - 3) = NULL;
  704. (pPackageInfo->prgUpgradeInfoList[j].Flag) = wcstoul(ptr+(len-2), &pStr, 16);
  705. *(ptr + len - 3 - 36 - 2) = L'\0';
  706. /* -GUID-'::'*/
  707. GUIDFromString(ptr+len-3-36, &(pPackageInfo->prgUpgradeInfoList[j].PackageGuid));
  708. }
  709. pPackageInfo->cUpgrades = j; // we might have skipped some.
  710. }
  711. ADSIFreeColumn(hADs, &column);
  712. if (FAILED(hr))
  713. {
  714. break;
  715. }
  716. }
  717. //
  718. // Now that we know we will use this package,
  719. // copy the common gpo-related information
  720. //
  721. memcpy( &(pPackageInfo->GpoId), pGpoId, sizeof( *pGpoId ) );
  722. pPackageInfo->pszGpoPath = StringDuplicate( wszGpoPath );
  723. if ( ! pPackageInfo->pszGpoPath )
  724. {
  725. hr = E_OUTOFMEMORY;
  726. break;
  727. }
  728. ++pPackageInfo;
  729. ++pdwPriority;
  730. (*pcRowsFetched)++;
  731. if (*pcRowsFetched == cRows)
  732. break;
  733. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  734. }
  735. //
  736. // If we couldn't even retrieve the first row, return the error
  737. //
  738. if ((0 == *pcRowsFetched) && FAILED(hr))
  739. {
  740. return hr;
  741. }
  742. //
  743. // Check if we found as many as asked for
  744. //
  745. if (*pcRowsFetched != cRows)
  746. return S_FALSE;
  747. return S_OK;
  748. }
  749. // FetchPackageInfo
  750. //-----------------
  751. //
  752. // Gets the result set of the query : List of Package objects.
  753. // Returns the properties in PackageInfo structure.
  754. //
  755. HRESULT FetchPackageInfo(HANDLE hADs,
  756. ADS_SEARCH_HANDLE hADsSearchHandle,
  757. DWORD dwFlags,
  758. DWORD dwQuerySpec,
  759. CSPLATFORM *pPlatform,
  760. ULONG cRows,
  761. ULONG *pcRowsFetched,
  762. PACKAGEDISPINFO *pPackageInfo,
  763. BOOL *fFirst,
  764. GUID* pGpoId,
  765. WCHAR* wszGpoPath,
  766. PRSOPTOKEN pRsopUserToken
  767. )
  768. {
  769. HRESULT hr = S_OK;
  770. UINT i, j;
  771. ULONG cPlatforms = 0;
  772. DWORD * dwPlatformList=NULL;
  773. LCID * dwLocaleList=NULL;
  774. DWORD dwPackageFlags;
  775. ULONG cFetched = 0;
  776. ULONG cRowsLeft = 0;
  777. CSPLATFORM PkgPlatform;
  778. ADS_SEARCH_COLUMN column;
  779. LPOLESTR szUsn = NULL;
  780. BOOL fInclude;
  781. BOOL bUserHasAccess;
  782. *pcRowsFetched = 0;
  783. cRowsLeft = cRows;
  784. if (!cRowsLeft)
  785. return S_OK;
  786. //
  787. // Clear the first package
  788. //
  789. memset(pPackageInfo, 0, sizeof(PACKAGEDISPINFO));
  790. // The LDAP filter performs a part of the selection
  791. // The flag filters are interpreted on the client after obtaining the result set
  792. for (;;)
  793. {
  794. //
  795. // Leave if there are no more rows to retrieve
  796. //
  797. if (!cRowsLeft)
  798. {
  799. break;
  800. }
  801. //
  802. // Free any resources from a previous iteration
  803. //
  804. ReleasePackageInfo(pPackageInfo);
  805. memset(pPackageInfo, 0, sizeof(*pPackageInfo));
  806. if ((*fFirst) && (!(*pcRowsFetched))) {
  807. *fFirst = FALSE;
  808. hr = ADSIGetFirstRow(hADs, hADsSearchHandle);
  809. }
  810. else
  811. hr = ADSIGetNextRow(hADs, hADsSearchHandle);
  812. if ((FAILED(hr)) || (hr == S_ADS_NOMORE_ROWS))
  813. break;
  814. fInclude = dwFlags & APPFILTER_INCLUDE_ALL ? TRUE : FALSE;
  815. //Column = packageName.
  816. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PACKAGENAME, &column);
  817. if (SUCCEEDED(hr))
  818. {
  819. hr = UnpackStrAllocFrom(column, &(pPackageInfo->pszPackageName));
  820. CSDBGPrint((DM_WARNING,
  821. IDS_CSTORE_EXAMINING,
  822. pPackageInfo->pszPackageName));
  823. ADSIFreeColumn(hADs, &column);
  824. }
  825. if (FAILED(hr))
  826. {
  827. continue;
  828. }
  829. dwPackageFlags = 0;
  830. // Get the Flag Value: Column = packageFlags
  831. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, PACKAGEFLAGS, &column);
  832. if (SUCCEEDED(hr))
  833. {
  834. UnpackDWFrom(column, &dwPackageFlags);
  835. ADSIFreeColumn(hADs, &column);
  836. }
  837. else
  838. {
  839. CSDBGPrint((DM_WARNING,
  840. IDS_CSTORE_MISSING_ATTR,
  841. PACKAGEFLAGS,
  842. hr));
  843. continue;
  844. }
  845. //
  846. // Check flag values to see if this package meets the filter
  847. //
  848. //
  849. // If it is an Orphaned App, we only return it for APPINFO_ALL.
  850. //
  851. if ((dwPackageFlags & ACTFLG_Orphan) && (dwFlags & APPFILTER_REQUIRE_NON_REMOVED))
  852. {
  853. CSDBGPrint((DM_WARNING,
  854. IDS_CSTORE_SKIP_FILTER,
  855. pPackageInfo->pszPackageName,
  856. APPFILTER_REQUIRE_NON_REMOVED,
  857. ACTFLG_Orphan));
  858. continue;
  859. }
  860. // If it is an Uninstalled App return it if asked for by APPINFO_ALL
  861. if ((dwPackageFlags & ACTFLG_Uninstall) && (dwFlags & APPFILTER_REQUIRE_NON_REMOVED))
  862. {
  863. CSDBGPrint((DM_WARNING,
  864. IDS_CSTORE_SKIP_FILTER,
  865. pPackageInfo->pszPackageName,
  866. APPFILTER_REQUIRE_NON_REMOVED,
  867. ACTFLG_Uninstall));
  868. continue;
  869. }
  870. if ((dwFlags & APPFILTER_REQUIRE_PUBLISHED) && (!(dwPackageFlags & ACTFLG_Published)))
  871. {
  872. CSDBGPrint((DM_WARNING,
  873. IDS_CSTORE_SKIP_FILTER,
  874. pPackageInfo->pszPackageName,
  875. APPFILTER_REQUIRE_PUBLISHED,
  876. ACTFLG_Published));
  877. continue;
  878. }
  879. if ((dwFlags & APPFILTER_INCLUDE_ASSIGNED) && (dwPackageFlags & ACTFLG_Assigned))
  880. {
  881. fInclude = TRUE;
  882. }
  883. if ((dwFlags & APPFILTER_INCLUDE_UPGRADES) && (dwPackageFlags & ACTFLG_HasUpgrades))
  884. {
  885. fInclude = TRUE;
  886. }
  887. if ((dwFlags & APPFILTER_REQUIRE_VISIBLE) && (!(dwPackageFlags & ACTFLG_UserInstall)))
  888. {
  889. CSDBGPrint((DM_WARNING,
  890. IDS_CSTORE_SKIP_FILTER,
  891. pPackageInfo->pszPackageName,
  892. APPFILTER_REQUIRE_VISIBLE,
  893. ACTFLG_UserInstall));
  894. continue;
  895. }
  896. if ((dwFlags & APPFILTER_REQUIRE_AUTOINSTALL) && (!(dwPackageFlags & ACTFLG_OnDemandInstall)))
  897. {
  898. CSDBGPrint((DM_WARNING,
  899. IDS_CSTORE_SKIP_FILTER,
  900. pPackageInfo->pszPackageName,
  901. APPFILTER_REQUIRE_AUTOINSTALL,
  902. ACTFLG_OnDemandInstall));
  903. continue;
  904. }
  905. //
  906. // Packages using the NT 5.0 beta 3 schema are not
  907. // supported in subsequent versions of Windows
  908. //
  909. if ( ! (dwPackageFlags & ACTFLG_POSTBETA3) )
  910. {
  911. //
  912. // Only allow administrators to see beta 3 deployments for
  913. // administrative purposes (to delete the data). In NT 6.0, we
  914. // should no longer support even this
  915. //
  916. if ( APPQUERY_ADMINISTRATIVE != dwQuerySpec )
  917. {
  918. CSDBGPrint((DM_WARNING,
  919. IDS_CSTORE_BETA3_ERR));
  920. continue;
  921. }
  922. //Column = packageType
  923. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, PACKAGETYPE, &column);
  924. if (SUCCEEDED(hr))
  925. {
  926. UnpackDWFrom(column, (DWORD *)&(pPackageInfo->PathType));
  927. ADSIFreeColumn(hADs, &column);
  928. }
  929. else
  930. {
  931. continue;
  932. }
  933. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, UILEVEL, &column);
  934. if (SUCCEEDED(hr))
  935. {
  936. UnpackDWFrom(column, (DWORD *)&(pPackageInfo->InstallUiLevel));
  937. ADSIFreeColumn(hADs, &column);
  938. }
  939. else
  940. {
  941. continue;
  942. }
  943. }
  944. if ( dwPackageFlags & ACTFLG_POSTBETA3 )
  945. {
  946. GetAttributesFromPackageFlags(
  947. dwPackageFlags,
  948. &(pPackageInfo->InstallUiLevel),
  949. &(pPackageInfo->PathType));
  950. }
  951. if (( dwFlags & APPFILTER_REQUIRE_MSI) && (pPackageInfo->PathType != DrwFilePath))
  952. {
  953. CSDBGPrint((DM_WARNING,
  954. IDS_CSTORE_SKIP_MSI,
  955. pPackageInfo->pszPackageName,
  956. pPackageInfo->PathType));
  957. continue;
  958. }
  959. pPackageInfo->LangId = LANG_NEUTRAL;
  960. //
  961. // If the package flags specify that we should ignore locale, or the
  962. // caller specified that all locale's are acceptable, skip the language
  963. // checks
  964. //
  965. {
  966. LANGID PackageLangId;
  967. DWORD cLanguages;
  968. PackageLangId = LANG_NEUTRAL;
  969. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, LOCALEID, &column);
  970. dwLocaleList = NULL;
  971. if (SUCCEEDED(hr))
  972. {
  973. // type change. shouldn't affect anything.
  974. UnpackDWArrFrom(column, &dwLocaleList, &cLanguages);
  975. ADSIFreeColumn(hADs, &column);
  976. }
  977. else
  978. {
  979. CSDBGPrint((DM_WARNING,
  980. IDS_CSTORE_MISSING_ATTR,
  981. LOCALEID,
  982. hr));
  983. continue;
  984. }
  985. //
  986. // We only care about the first language returned -- originally
  987. // the packages in the ds could support multiple locales, but
  988. // we now only support one language
  989. //
  990. if (cLanguages)
  991. {
  992. PackageLangId = LANGIDFROMLCID(dwLocaleList[0]);
  993. }
  994. CsMemFree(dwLocaleList);
  995. //
  996. // If the package flags specify that we should ignore locale, or the
  997. // caller specified that all locale's are acceptable, skip the language
  998. // checks
  999. //
  1000. if ( (dwFlags & APPFILTER_REQUIRE_THIS_LANGUAGE) &&
  1001. ! ( dwPackageFlags & ACTFLG_IgnoreLanguage ) )
  1002. {
  1003. if (!cLanguages || !MatchLanguage(PackageLangId, dwPackageFlags))
  1004. {
  1005. CSDBGPrint((DM_WARNING,
  1006. IDS_CSTORE_MISSING_ATTR,
  1007. LOCALEID,
  1008. hr));
  1009. continue;
  1010. }
  1011. }
  1012. pPackageInfo->LangId = PackageLangId;
  1013. }
  1014. if (pPlatform != NULL)
  1015. {
  1016. //Column = machineArchitecture
  1017. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, ARCHLIST, &column);
  1018. cPlatforms = 0;
  1019. dwPlatformList = NULL;
  1020. if (SUCCEEDED(hr))
  1021. {
  1022. UnpackDWArrFrom(column, &dwPlatformList, &cPlatforms);
  1023. ADSIFreeColumn(hADs, &column);
  1024. }
  1025. else
  1026. {
  1027. CSDBGPrint((DM_WARNING,
  1028. IDS_CSTORE_MISSING_ATTR,
  1029. ARCHLIST,
  1030. hr));
  1031. continue;
  1032. }
  1033. DWORD MaxPlatformWeight;
  1034. MaxPlatformWeight = 0;
  1035. pPackageInfo->MatchedArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  1036. for (j=0; j < cPlatforms; ++j)
  1037. {
  1038. DWORD PlatformWeight;
  1039. PackPlatform (dwPlatformList[j], &PkgPlatform);
  1040. PlatformWeight = PlatformWt (pPlatform,
  1041. &PkgPlatform,
  1042. dwPackageFlags & ACTFLG_ExcludeX86OnWin64,
  1043. SetupNamePath == pPackageInfo->PathType);
  1044. if ( PlatformWeight > MaxPlatformWeight )
  1045. {
  1046. pPackageInfo->MatchedArchitecture = dwPlatformList[j];
  1047. MaxPlatformWeight = PlatformWeight;
  1048. }
  1049. }
  1050. if (dwPlatformList)
  1051. CsMemFree(dwPlatformList);
  1052. //
  1053. // If none matched skip this package
  1054. //
  1055. if ( 0 == MaxPlatformWeight )
  1056. {
  1057. CSDBGPrint((DM_WARNING,
  1058. IDS_CSTORE_SKIP_ARCH,
  1059. pPackageInfo->pszPackageName));
  1060. continue;
  1061. }
  1062. }
  1063. pPackageInfo->dwActFlags = dwPackageFlags;
  1064. //Column = OBJECTGUID
  1065. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_OCTET_STRING, OBJECTGUID, &column);
  1066. if (SUCCEEDED(hr))
  1067. {
  1068. UnpackGUIDFrom(column, &(pPackageInfo->PackageGuid));
  1069. ADSIFreeColumn(hADs, &column);
  1070. }
  1071. if ( ! (APPFILTER_CONTEXT_ARP & dwFlags) ||
  1072. (APPFILTER_CONTEXT_RSOP & dwFlags) )
  1073. {
  1074. //Column = ScriptPath
  1075. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, SCRIPTPATH, &column);
  1076. if (SUCCEEDED(hr))
  1077. {
  1078. UnpackStrAllocFrom(column, &(pPackageInfo->pszScriptPath));
  1079. ADSIFreeColumn(hADs, &column);
  1080. }
  1081. }
  1082. if ( ! (APPFILTER_CONTEXT_ARP & dwFlags) ||
  1083. (APPFILTER_CONTEXT_RSOP & dwFlags) )
  1084. {
  1085. //Column = lastUpdateSequence,
  1086. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, PKGUSN, &column);
  1087. if (SUCCEEDED(hr))
  1088. {
  1089. UnpackStrFrom(column, &szUsn);
  1090. TimeToUsn (szUsn, (CSUSN *)(&(pPackageInfo->Usn)));
  1091. ADSIFreeColumn(hADs, &column);
  1092. }
  1093. else {
  1094. CSDBGPrint((DM_WARNING,
  1095. IDS_CSTORE_MISSING_ATTR,
  1096. PKGUSN,
  1097. hr));
  1098. continue;
  1099. }
  1100. }
  1101. // ProductCode
  1102. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_OCTET_STRING, PRODUCTCODE, &column);
  1103. if (SUCCEEDED(hr))
  1104. {
  1105. UnpackGUIDFrom(column, &(pPackageInfo->ProductCode));
  1106. ADSIFreeColumn(hADs, &column);
  1107. }
  1108. if ( ! (APPFILTER_CONTEXT_ARP & dwQuerySpec) ||
  1109. (APPFILTER_CONTEXT_RSOP & dwFlags) )
  1110. {
  1111. //Column = revision
  1112. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_INTEGER, REVISION, &column);
  1113. if (SUCCEEDED(hr))
  1114. {
  1115. UnpackDWFrom(column, &(pPackageInfo->dwRevision));
  1116. ADSIFreeColumn(hADs, &column);
  1117. }
  1118. }
  1119. // Column = url
  1120. // This one is optional and will be unset in most cases.
  1121. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, HELPURL, &column);
  1122. if (SUCCEEDED(hr))
  1123. {
  1124. UnpackStrAllocFrom(column, &(pPackageInfo->pszUrl));
  1125. ADSIFreeColumn(hADs, &column);
  1126. }
  1127. //
  1128. // We need to grab additional attributes for rsop logging
  1129. //
  1130. if ( APPFILTER_CONTEXT_RSOP & dwFlags )
  1131. {
  1132. hr = GetRsopSpecificAttributes(
  1133. hADs,
  1134. hADsSearchHandle,
  1135. pRsopUserToken,
  1136. pPackageInfo,
  1137. &bUserHasAccess);
  1138. if (FAILED(hr))
  1139. {
  1140. CSDBGPrint((DM_WARNING,
  1141. IDS_CSTORE_RSOPERROR,
  1142. hr));
  1143. }
  1144. else
  1145. {
  1146. if ( pRsopUserToken && ( ! bUserHasAccess ) )
  1147. {
  1148. continue;
  1149. }
  1150. }
  1151. }
  1152. if ( (APPFILTER_CONTEXT_RSOP & dwFlags) ||
  1153. (APPFILTER_CONTEXT_ARP & dwFlags) )
  1154. {
  1155. hr = GetCategories(
  1156. hADs,
  1157. hADsSearchHandle,
  1158. pPackageInfo);
  1159. if ( FAILED(hr) )
  1160. {
  1161. CSDBGPrint((DM_WARNING,
  1162. IDS_CSTORE_MISSING_ATTR,
  1163. PKGCATEGORYLIST,
  1164. hr));
  1165. continue;
  1166. }
  1167. // This one is optional and will be unset in most cases.
  1168. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, HELPURL, &column);
  1169. if (SUCCEEDED(hr))
  1170. {
  1171. UnpackStrAllocFrom(column, &(pPackageInfo->pszUrl));
  1172. ADSIFreeColumn(hADs, &column);
  1173. }
  1174. hr = S_OK;
  1175. }
  1176. if ( dwPackageFlags & ACTFLG_HasUpgrades )
  1177. {
  1178. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, UPGRADESPACKAGES, &column);
  1179. if (SUCCEEDED(hr))
  1180. {
  1181. LPOLESTR *pProp = NULL;
  1182. hr = UnpackStrArrAllocFrom(column, &pProp, (DWORD *)&(pPackageInfo->cUpgrades));
  1183. ADSIFreeColumn(hADs, &column);
  1184. if (pPackageInfo->cUpgrades)
  1185. pPackageInfo->prgUpgradeInfoList = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*
  1186. (pPackageInfo->cUpgrades));
  1187. if (pPackageInfo->prgUpgradeInfoList)
  1188. {
  1189. memset(pPackageInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pPackageInfo->cUpgrades));
  1190. for (j=0; j < ( pPackageInfo->cUpgrades); ++j)
  1191. {
  1192. BOOL fGotGPO;
  1193. WCHAR *pStr = NULL;
  1194. LPOLESTR ptr = (pPackageInfo->prgUpgradeInfoList[j].szClassStore) = pProp[j];
  1195. UINT len = wcslen (ptr);
  1196. if (len <= 41)
  1197. continue;
  1198. //
  1199. // Find the GPO for this upgrade
  1200. //
  1201. fGotGPO = GetGpoIdFromClassStorePath(
  1202. pPackageInfo->prgUpgradeInfoList[j].szClassStore,
  1203. &(pPackageInfo->prgUpgradeInfoList[j].GpoId));
  1204. if (!fGotGPO)
  1205. {
  1206. continue;
  1207. }
  1208. *(ptr + len - 3) = NULL;
  1209. (pPackageInfo->prgUpgradeInfoList[j].Flag) = wcstoul(ptr+(len-2), &pStr, 16);
  1210. *(ptr + len - 3 - 36 - 2) = L'\0';
  1211. /* -GUID-'::'*/
  1212. GUIDFromString(ptr+len-3-36, &(pPackageInfo->prgUpgradeInfoList[j].PackageGuid));
  1213. }
  1214. pPackageInfo->cUpgrades = j; // we might have skipped some.
  1215. fInclude = TRUE;
  1216. }
  1217. }
  1218. }
  1219. if (!fInclude)
  1220. {
  1221. CSDBGPrint((DM_WARNING,
  1222. IDS_CSTORE_SKIP_INCLUDE,
  1223. pPackageInfo->pszPackageName));
  1224. continue;
  1225. }
  1226. //
  1227. // Now that we know we will use this package,
  1228. // copy the common gpo-related information
  1229. //
  1230. memcpy( &(pPackageInfo->GpoId), pGpoId, sizeof( *pGpoId ) );
  1231. pPackageInfo->pszGpoPath = StringDuplicate( wszGpoPath );
  1232. if ( ! pPackageInfo->pszGpoPath )
  1233. {
  1234. hr = E_OUTOFMEMORY;
  1235. break;
  1236. }
  1237. ++pPackageInfo;
  1238. cRowsLeft--;
  1239. (*pcRowsFetched)++;
  1240. if (!cRowsLeft)
  1241. {
  1242. break;
  1243. }
  1244. }
  1245. //
  1246. // If we couldn't even retrieve the first row, return the error
  1247. //
  1248. if ((0 == *pcRowsFetched) && FAILED(hr))
  1249. {
  1250. return hr;
  1251. }
  1252. if (!cRowsLeft)
  1253. return S_OK;
  1254. return S_FALSE;
  1255. }
  1256. // FetchCategory
  1257. //--------------
  1258. //
  1259. // List of columns this routine fetches.
  1260. //
  1261. HRESULT FetchCategory(HANDLE hADs,
  1262. ADS_SEARCH_HANDLE hADsSearchHandle,
  1263. APPCATEGORYINFOLIST * pCategoryInfoList,
  1264. LCID Locale
  1265. )
  1266. {
  1267. HRESULT hr = S_OK;
  1268. ADS_SEARCH_COLUMN column;
  1269. LPOLESTR * pszDesc = NULL;
  1270. DWORD cdesc = 0, i = 0;
  1271. LPOLESTR szCatid = NULL;
  1272. DWORD cMaxCategories;
  1273. DWORD cCategories;
  1274. cMaxCategories = 0;
  1275. cCategories = 0;
  1276. pCategoryInfoList->pCategoryInfo = NULL;
  1277. for (hr = ADSIGetFirstRow(hADs, hADsSearchHandle), i = 0;
  1278. ((SUCCEEDED(hr)) && ((hr) != S_ADS_NOMORE_ROWS));
  1279. hr = ADSIGetNextRow(hADs, hADsSearchHandle), i++)
  1280. {
  1281. APPCATEGORYINFO* pCurrentCategories;
  1282. cCategories++;
  1283. //
  1284. // First, verify that we have enough space to store
  1285. // the next category
  1286. //
  1287. if ( cCategories > cMaxCategories )
  1288. {
  1289. //
  1290. // Get enough space for the current categories as well
  1291. // as some extra since we still don't know how many more categories
  1292. // we have
  1293. //
  1294. cMaxCategories += CATEGORY_RETRIEVAL_ALLOC_SIZE;
  1295. pCurrentCategories = (APPCATEGORYINFO*) CsMemAlloc( cMaxCategories * sizeof(APPCATEGORYINFO) );
  1296. if ( !pCurrentCategories )
  1297. {
  1298. hr = E_OUTOFMEMORY;
  1299. break;
  1300. }
  1301. if ( pCategoryInfoList->pCategoryInfo )
  1302. {
  1303. //
  1304. // We have enough space, copy the existing entries --
  1305. // note that the list engrties are not self-referential, so we can
  1306. // blindly copy them, but the list itself contains a pointer into itself,
  1307. // so this must be adjusted after the copy
  1308. //
  1309. memcpy( pCurrentCategories, pCategoryInfoList->pCategoryInfo, i * sizeof(APPCATEGORYINFO) );
  1310. //
  1311. // Free the old list since it is no longer needed. Note that
  1312. // we do not user the ReleaseAppCategoryInfoList api to free
  1313. // the list since that would also free memory referenced by
  1314. // members of elements of the category array -- we want to preserve
  1315. // these references in the succeeding copy
  1316. //
  1317. if ( pCategoryInfoList->pCategoryInfo )
  1318. {
  1319. CsMemFree( pCategoryInfoList->pCategoryInfo );
  1320. pCategoryInfoList->pCategoryInfo = NULL;
  1321. }
  1322. }
  1323. //
  1324. // Clear the newly added entries
  1325. //
  1326. memset( &(pCurrentCategories[i]), 0, sizeof(APPCATEGORYINFO) * CATEGORY_RETRIEVAL_ALLOC_SIZE );
  1327. //
  1328. // Set the list structure to refer to the successfully
  1329. // reallocated memory
  1330. //
  1331. pCategoryInfoList->pCategoryInfo = pCurrentCategories;
  1332. }
  1333. // Get the data from each row ignoring the error returned.
  1334. //Column = description
  1335. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_CASE_IGNORE_STRING, LOCALEDESCRIPTION, &column);
  1336. cdesc = 0; pszDesc = NULL;
  1337. if (SUCCEEDED(hr))
  1338. UnpackStrArrFrom(column, &pszDesc, &cdesc);
  1339. (pCategoryInfoList->pCategoryInfo)[i].Locale = Locale;
  1340. (pCategoryInfoList->pCategoryInfo)[i].pszDescription =
  1341. (LPOLESTR)CsMemAlloc( (CAT_DESC_MAX_LEN + 1) * sizeof(WCHAR));
  1342. // The description has a maximum size.
  1343. if ((pCategoryInfoList->pCategoryInfo)[i].pszDescription)
  1344. GetCategoryLocaleDesc(pszDesc, cdesc, &((pCategoryInfoList->pCategoryInfo)[i].Locale),
  1345. (pCategoryInfoList->pCategoryInfo)[i].pszDescription, CAT_DESC_MAX_LEN + 1);
  1346. if (SUCCEEDED(hr))
  1347. ADSIFreeColumn(hADs, &column);
  1348. if (pszDesc)
  1349. CsMemFree(pszDesc);
  1350. // catid
  1351. hr = DSGetAndValidateColumn(hADs, hADsSearchHandle, ADSTYPE_OCTET_STRING, CATEGORYCATID, &column);
  1352. if (SUCCEEDED(hr))
  1353. {
  1354. UnpackGUIDFrom(column, &((pCategoryInfoList->pCategoryInfo)[i].AppCategoryId));
  1355. ADSIFreeColumn(hADs, &column);
  1356. }
  1357. }
  1358. pCategoryInfoList->cCategory = i;
  1359. //
  1360. // On failure, clean up the category list so the caller
  1361. // will not attempt to use invalid data
  1362. //
  1363. if (FAILED(hr))
  1364. {
  1365. ReleaseAppCategoryInfoList( pCategoryInfoList );
  1366. }
  1367. return hr;
  1368. }
  1369. HRESULT GetPackageDetail (HANDLE hPackageADs, WCHAR *szClassContainerPath,
  1370. PACKAGEDETAIL *pPackageDetail)
  1371. {
  1372. HRESULT hr = S_OK;
  1373. GUID PkgGuid;
  1374. DWORD *pdwArch = NULL, count = 0;
  1375. PLATFORMINFO *pPlatformInfo = NULL;
  1376. INSTALLINFO *pInstallInfo = NULL;
  1377. ACTIVATIONINFO *pActInfo = NULL;
  1378. ADS_ATTR_INFO *pAttr = NULL;
  1379. DWORD posn, cgot = 0;
  1380. DWORD cClasses = 0;
  1381. LPOLESTR *szClasses = NULL;
  1382. DWORD dwUiLevel = 0;
  1383. DWORD cProgId = 0;
  1384. LPOLESTR *pszProgId = NULL;
  1385. memset (pPackageDetail, 0, sizeof (PACKAGEDETAIL));
  1386. hr = ADSIGetObjectAttributes(hPackageADs, pszPackageDetailAttrNames, cPackageDetailAttr,
  1387. &pAttr, &cgot);
  1388. RETURN_ON_FAILURE(hr);
  1389. pInstallInfo = pPackageDetail->pInstallInfo = (INSTALLINFO *) CsMemAlloc(sizeof (INSTALLINFO));
  1390. if (!pInstallInfo)
  1391. ERROR_ON_FAILURE((hr=E_OUTOFMEMORY));
  1392. memset(pInstallInfo, NULL, sizeof(INSTALLINFO));
  1393. posn = GetPropertyFromAttr(pAttr, cgot, PACKAGEFLAGS);
  1394. if (posn < cgot)
  1395. UnpackDWFrom(pAttr[posn], (DWORD *)&(pInstallInfo->dwActFlags));
  1396. else
  1397. ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
  1398. posn = GetPropertyFromAttr(pAttr, cgot, SCRIPTPATH);
  1399. if (posn < cgot)
  1400. UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszScriptPath));
  1401. posn = GetPropertyFromAttr(pAttr, cgot, SCRIPTSIZE);
  1402. if (posn < cgot)
  1403. UnpackDWFrom(pAttr[posn], &(pInstallInfo->cScriptLen));
  1404. posn = GetPropertyFromAttr(pAttr, cgot, SETUPCOMMAND);
  1405. if (posn < cgot)
  1406. UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszSetupCommand));
  1407. posn = GetPropertyFromAttr(pAttr, cgot, HELPURL);
  1408. if (posn < cgot)
  1409. UnpackStrAllocFrom(pAttr[posn], &(pInstallInfo->pszUrl));
  1410. posn = GetPropertyFromAttr(pAttr, cgot, PKGUSN);
  1411. if (posn < cgot)
  1412. UsnGet(pAttr[posn], (CSUSN *)&(pInstallInfo->Usn));
  1413. else
  1414. ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
  1415. posn = GetPropertyFromAttr(pAttr, cgot, PRODUCTCODE);
  1416. if (posn < cgot)
  1417. UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->ProductCode));
  1418. //
  1419. // Obtain the MVIPC, which is really just an upgrade code used on the server side UI
  1420. // only to detect whether the ds contains upgrades that are mandated by a package
  1421. //
  1422. posn = GetPropertyFromAttr(pAttr, cgot, MVIPC);
  1423. if (posn < cgot)
  1424. UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->Mvipc));
  1425. // doesn't matter if the property itself is multivalued.
  1426. posn = GetPropertyFromAttr(pAttr, cgot, OBJECTGUID);
  1427. if (posn < cgot)
  1428. UnpackGUIDFrom(pAttr[posn], &(pInstallInfo->PackageGuid));
  1429. posn = GetPropertyFromAttr(pAttr, cgot, VERSIONHI);
  1430. if (posn < cgot)
  1431. UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwVersionHi));
  1432. posn = GetPropertyFromAttr(pAttr, cgot, VERSIONLO);
  1433. if (posn < cgot)
  1434. UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwVersionLo));
  1435. posn = GetPropertyFromAttr(pAttr, cgot, REVISION);
  1436. if (posn < cgot)
  1437. UnpackDWFrom(pAttr[posn], &(pInstallInfo->dwRevision));
  1438. //
  1439. // Packages deployed before NT 5.0 beta 3 are in a
  1440. // format that will not be supported for subsequent versions
  1441. // of Windows. However, we must support it for NT 5.1 at least
  1442. // from the admin UI so that the they can be un-deployed. This
  1443. // function is called in the context of the admin UI, so we
  1444. // will interpret the beta 3 schema
  1445. //
  1446. if (pInstallInfo->dwActFlags & ACTFLG_POSTBETA3)
  1447. {
  1448. GetAttributesFromPackageFlags(
  1449. pInstallInfo->dwActFlags,
  1450. (UINT*) &dwUiLevel,
  1451. &(pInstallInfo->PathType));
  1452. }
  1453. else
  1454. {
  1455. posn = GetPropertyFromAttr(pAttr, cgot, UILEVEL);
  1456. if (posn < cgot)
  1457. UnpackDWFrom(pAttr[posn], &dwUiLevel);
  1458. posn = GetPropertyFromAttr(pAttr, cgot, PACKAGETYPE);
  1459. if (posn < cgot)
  1460. UnpackDWFrom(pAttr[posn], (DWORD *)&(pInstallInfo->PathType));
  1461. else
  1462. ERROR_ON_FAILURE((hr=CS_E_OBJECT_NOTFOUND));
  1463. }
  1464. pInstallInfo->InstallUiLevel = dwUiLevel;
  1465. posn = GetPropertyFromAttr(pAttr, cgot, UPGRADESPACKAGES);
  1466. if (posn < cgot)
  1467. {
  1468. LPOLESTR *pProp = NULL;
  1469. UnpackStrArrAllocFrom(pAttr[posn], &pProp, (DWORD *)&(pInstallInfo->cUpgrades));
  1470. if (pInstallInfo->cUpgrades)
  1471. pInstallInfo->prgUpgradeInfoList = (UPGRADEINFO *)CsMemAlloc(sizeof(UPGRADEINFO)*
  1472. pInstallInfo->cUpgrades);
  1473. if (!(pInstallInfo->prgUpgradeInfoList))
  1474. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1475. memset(pInstallInfo->prgUpgradeInfoList, 0, sizeof(UPGRADEINFO)*(pInstallInfo->cUpgrades));
  1476. for (count = 0; (count < (pInstallInfo->cUpgrades)); count++)
  1477. {
  1478. WCHAR *pStr = NULL;
  1479. LPOLESTR ptr = (pInstallInfo->prgUpgradeInfoList[count].szClassStore) = pProp[count];
  1480. UINT len = wcslen (ptr);
  1481. if (len <= 41)
  1482. continue;
  1483. *(ptr + len - 3) = NULL;
  1484. pInstallInfo->prgUpgradeInfoList[count].Flag = wcstoul(ptr+(len-2), &pStr, 16);
  1485. *(ptr + len - 3 - 36 - 2) = L'\0';
  1486. /* -GUID-'::'*/
  1487. GUIDFromString(ptr+len-3-36, &(pInstallInfo->prgUpgradeInfoList[count].PackageGuid));
  1488. }
  1489. pInstallInfo->cUpgrades = count; // we might have skipped some.
  1490. }
  1491. pPlatformInfo = pPackageDetail->pPlatformInfo =
  1492. (PLATFORMINFO *) CsMemAlloc(sizeof (PLATFORMINFO));
  1493. if (!pPlatformInfo)
  1494. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1495. memset(pPlatformInfo, NULL, sizeof(PLATFORMINFO));
  1496. posn = GetPropertyFromAttr(pAttr, cgot, ARCHLIST);
  1497. if (posn < cgot)
  1498. {
  1499. DWORD dwPlatforms;
  1500. //
  1501. // Note that since the UnpackDWArrFrom takes a DWORD*, we should
  1502. // avoid passing the int directly and instead pass a DWORD
  1503. //
  1504. UnpackDWArrFrom(pAttr[posn], &pdwArch, &dwPlatforms);
  1505. pPlatformInfo->cPlatforms = dwPlatforms;
  1506. }
  1507. pPlatformInfo->prgPlatform = (CSPLATFORM *)CsMemAlloc(sizeof(CSPLATFORM)*
  1508. (pPlatformInfo->cPlatforms));
  1509. if (!(pPlatformInfo->prgPlatform))
  1510. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1511. for (count = 0; (count < (pPlatformInfo->cPlatforms)); count++)
  1512. PackPlatform (pdwArch[count], (pPlatformInfo->prgPlatform)+count);
  1513. CsMemFree(pdwArch);
  1514. posn = GetPropertyFromAttr(pAttr, cgot, LOCALEID);
  1515. if (posn < cgot)
  1516. {
  1517. DWORD dwLocales;
  1518. //
  1519. // Again, we typecast before getting the address that we
  1520. // need to pass the count to the unpack function
  1521. //
  1522. UnpackDWArrFrom(pAttr[posn], &(pPlatformInfo->prgLocale),
  1523. &dwLocales);
  1524. pPlatformInfo->cLocales = dwLocales;
  1525. }
  1526. //
  1527. // fill in ActivationInfo.
  1528. //
  1529. pActInfo = pPackageDetail->pActInfo =
  1530. (ACTIVATIONINFO *) CsMemAlloc(sizeof (ACTIVATIONINFO));
  1531. if (!pActInfo) {
  1532. hr = E_OUTOFMEMORY;
  1533. ERROR_ON_FAILURE(hr);
  1534. }
  1535. memset(pActInfo, NULL, sizeof(ACTIVATIONINFO));
  1536. //
  1537. // Do not obtain clsid's, typelibid's, iid's & progid's -- this data is never used.
  1538. // However, we do check to see if there is any clsid data so that we can set the
  1539. // member of the packagedetails which indicates that the package has com class information
  1540. //
  1541. posn = GetPropertyFromAttr(pAttr, cgot, PKGCLSIDLIST);
  1542. //
  1543. // In order to be consistent with NT5, We assume that if we do not find the classes
  1544. // attribute, that the administrator wanted the package to be deployed with classes,
  1545. // but the package had no classes.
  1546. //
  1547. pActInfo->bHasClasses = TRUE;
  1548. //
  1549. // If we searched the returned attribute list and found it before passing
  1550. // the last attribute, this package has classes
  1551. //
  1552. if ( posn < cgot )
  1553. {
  1554. //
  1555. // We have the attribute, but if it is set to an "empty" value,
  1556. // this means that an NT 5.1 or higher system deployed this package without classes
  1557. //
  1558. if ( 1 == pAttr->dwNumValues )
  1559. {
  1560. LPOLESTR* ppwszClsid;
  1561. hr = UnpackStrArrFrom(pAttr[posn], &ppwszClsid, &cClasses);
  1562. ERROR_ON_FAILURE(hr);
  1563. //
  1564. // Check for the "empty" value
  1565. //
  1566. if ( 0 == lstrcmp( *ppwszClsid, PKG_EMPTY_CLSID_VALUE ) )
  1567. {
  1568. pActInfo->bHasClasses = FALSE;
  1569. }
  1570. }
  1571. }
  1572. //
  1573. // Do obtain file extensions
  1574. //
  1575. posn = GetPropertyFromAttr(pAttr, cgot, PKGFILEEXTNLIST);
  1576. cClasses = 0;
  1577. if (posn < cgot)
  1578. UnpackStrArrAllocFrom(pAttr[posn], &(pActInfo->prgShellFileExt), &cClasses);
  1579. pActInfo->cShellFileExt = cClasses;
  1580. if (cClasses)
  1581. {
  1582. pActInfo->prgPriority = (UINT *)CsMemAlloc(cClasses * sizeof(UINT));
  1583. if (!(pActInfo->prgPriority))
  1584. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1585. for (count = 0; count < cClasses; count++)
  1586. {
  1587. LPOLESTR pStr=NULL;
  1588. UINT cLen = wcslen((pActInfo->prgShellFileExt)[count]);
  1589. *((pActInfo->prgShellFileExt)[count] + (cLen - 3)) = NULL;
  1590. (pActInfo->prgPriority)[count] =
  1591. wcstoul((pActInfo->prgShellFileExt)[count]+(cLen-2), &pStr, 10);
  1592. }
  1593. }
  1594. //
  1595. // fill in package misc info
  1596. //
  1597. posn = GetPropertyFromAttr(pAttr, cgot, PACKAGENAME);
  1598. if (posn < cgot)
  1599. UnpackStrAllocFrom(pAttr[posn], &(pPackageDetail->pszPackageName));
  1600. else
  1601. ERROR_ON_FAILURE(hr=CS_E_OBJECT_NOTFOUND);
  1602. posn = GetPropertyFromAttr(pAttr, cgot, MSIFILELIST);
  1603. if (posn < cgot) {
  1604. LPOLESTR *rpszSourceList = NULL, psz = NULL, pStr = NULL;
  1605. DWORD Loc = 0;
  1606. UnpackStrArrFrom(pAttr[posn], &(rpszSourceList),
  1607. (DWORD *)&(pPackageDetail->cSources));
  1608. // reorder and allocate spaces.
  1609. if (pPackageDetail->cSources)
  1610. {
  1611. pPackageDetail->pszSourceList = (LPOLESTR *)CsMemAlloc(sizeof(LPOLESTR)*
  1612. (pPackageDetail->cSources));
  1613. if (!(pPackageDetail->pszSourceList))
  1614. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1615. for (count = 0; count < (pPackageDetail->cSources); count++)
  1616. {
  1617. psz = wcschr(rpszSourceList[count], L':');
  1618. *psz = L'\0';
  1619. Loc = wcstoul(rpszSourceList[count], &pStr, 10);
  1620. pPackageDetail->pszSourceList[Loc] = (LPOLESTR)CsMemAlloc(sizeof(WCHAR)*(wcslen(psz+1)+1));
  1621. if (!(pPackageDetail->pszSourceList[Loc]))
  1622. ERROR_ON_FAILURE(hr=E_OUTOFMEMORY);
  1623. hr = StringCchCopy(pPackageDetail->pszSourceList[Loc],
  1624. wcslen(psz+1)+1,
  1625. psz+1);
  1626. if (FAILED(hr))
  1627. {
  1628. ERROR_ON_FAILURE(hr);
  1629. }
  1630. }
  1631. }
  1632. CsMemFree(rpszSourceList);
  1633. }
  1634. posn = GetPropertyFromAttr(pAttr, cgot, PKGCATEGORYLIST);
  1635. cClasses = 0; szClasses = NULL;
  1636. if (posn < cgot)
  1637. UnpackStrArrFrom(pAttr[posn], &szClasses, &cClasses);
  1638. if (cClasses)
  1639. {
  1640. pPackageDetail->rpCategory = (GUID *)CsMemAlloc (sizeof(GUID) * cClasses);
  1641. if (!(pPackageDetail->rpCategory))
  1642. ERROR_ON_FAILURE(hr = E_OUTOFMEMORY);
  1643. pPackageDetail->cCategories = cClasses;
  1644. for (count = 0; count < cClasses; count++)
  1645. {
  1646. GUIDFromString(szClasses[count], (pPackageDetail->rpCategory + count));
  1647. }
  1648. CsMemFree(szClasses);
  1649. }
  1650. return S_OK;
  1651. Error_Cleanup:
  1652. ReleasePackageDetail(pPackageDetail);
  1653. memset(pPackageDetail, 0, sizeof(PACKAGEDETAIL));
  1654. if (pAttr)
  1655. FreeADsMem(pAttr);
  1656. return hr;
  1657. }
  1658. // GetRsopSpecificAttributes
  1659. //--------------------------
  1660. //
  1661. // Retrieves attributes not normally gathered except for when
  1662. // diagnostic rsop logging is enabled.
  1663. HRESULT GetRsopSpecificAttributes(
  1664. HANDLE hAds,
  1665. ADS_SEARCH_HANDLE hSearchHandle,
  1666. PRSOPTOKEN pRsopUserToken,
  1667. PACKAGEDISPINFO* pPackageInfo,
  1668. BOOL* pbUserHasAccess )
  1669. {
  1670. HRESULT hr;
  1671. ADS_SEARCH_COLUMN ResultColumn;
  1672. if ( pbUserHasAccess )
  1673. {
  1674. *pbUserHasAccess = TRUE;
  1675. }
  1676. pPackageInfo->rgSecurityDescriptor = NULL;
  1677. pPackageInfo->cbSecurityDescriptor = 0;
  1678. pPackageInfo->prgTransforms = NULL;
  1679. pPackageInfo->prgArchitectures = NULL;
  1680. pPackageInfo->cTransforms = 0;
  1681. pPackageInfo->cArchitectures = 0;
  1682. hr = DSGetAndValidateColumn(
  1683. hAds,
  1684. hSearchHandle,
  1685. ADSTYPE_CASE_IGNORE_STRING,
  1686. PUBLISHER,
  1687. &ResultColumn);
  1688. if (SUCCEEDED(hr))
  1689. {
  1690. UnpackStrAllocFrom(ResultColumn, &(pPackageInfo->pszPublisher));
  1691. ADSIFreeColumn(hAds, &ResultColumn);
  1692. }
  1693. //
  1694. // Obtain the list of machine architectures
  1695. //
  1696. hr = DSGetAndValidateColumn(
  1697. hAds,
  1698. hSearchHandle,
  1699. ADSTYPE_INTEGER,
  1700. ARCHLIST,
  1701. &ResultColumn);
  1702. if (SUCCEEDED(hr))
  1703. {
  1704. DWORD dwArchitectures;
  1705. UnpackDWArrFrom(
  1706. ResultColumn,
  1707. &(pPackageInfo->prgArchitectures),
  1708. &dwArchitectures);
  1709. pPackageInfo->cArchitectures = dwArchitectures;
  1710. ADSIFreeColumn(hAds, &ResultColumn);
  1711. }
  1712. //
  1713. // Attempt to unmarshal the transform list
  1714. //
  1715. hr = DSGetAndValidateColumn(
  1716. hAds,
  1717. hSearchHandle,
  1718. ADSTYPE_CASE_IGNORE_STRING,
  1719. MSIFILELIST,
  1720. &ResultColumn);
  1721. if (SUCCEEDED(hr))
  1722. {
  1723. //
  1724. // Copy the transform list into a string -- note that this call
  1725. // also allocates the array so we must free it later.
  1726. //
  1727. DWORD cTransforms;
  1728. UnpackStrArrAllocFrom(ResultColumn,
  1729. &(pPackageInfo->prgTransforms),
  1730. &cTransforms);
  1731. pPackageInfo->cTransforms = cTransforms;
  1732. ADSIFreeColumn(hAds, &ResultColumn);
  1733. }
  1734. if ( SUCCEEDED(hr) )
  1735. {
  1736. //
  1737. // Get the app's major version number
  1738. //
  1739. hr = DSGetAndValidateColumn(
  1740. hAds,
  1741. hSearchHandle,
  1742. ADSTYPE_INTEGER,
  1743. VERSIONHI,
  1744. &ResultColumn);
  1745. if (SUCCEEDED(hr))
  1746. {
  1747. UnpackDWFrom(ResultColumn, &(pPackageInfo->dwVersionHi));
  1748. ADSIFreeColumn(hAds, &ResultColumn);
  1749. }
  1750. }
  1751. if ( SUCCEEDED(hr) )
  1752. {
  1753. //
  1754. // Get the app's minor version number
  1755. //
  1756. hr = DSGetAndValidateColumn(
  1757. hAds,
  1758. hSearchHandle,
  1759. ADSTYPE_INTEGER,
  1760. VERSIONLO,
  1761. &ResultColumn);
  1762. if (SUCCEEDED(hr))
  1763. {
  1764. UnpackDWFrom(ResultColumn, &(pPackageInfo->dwVersionLo));
  1765. ADSIFreeColumn(hAds, &ResultColumn);
  1766. }
  1767. }
  1768. if ( SUCCEEDED(hr) )
  1769. {
  1770. //
  1771. // Grab the security descriptor
  1772. //
  1773. (void) GetSecurityDescriptor(
  1774. hAds,
  1775. hSearchHandle,
  1776. pRsopUserToken,
  1777. pPackageInfo,
  1778. pbUserHasAccess);
  1779. }
  1780. return hr;
  1781. }
  1782. HRESULT GetSecurityDescriptor(
  1783. HANDLE hAds,
  1784. ADS_SEARCH_HANDLE hSearchHandle,
  1785. PRSOPTOKEN pRsopUserToken,
  1786. PACKAGEDISPINFO* pPackageInfo,
  1787. BOOL* pbUserHasAccess)
  1788. {
  1789. HRESULT hr;
  1790. ADS_SEARCH_COLUMN SecurityColumn;
  1791. BOOL bFreeSecurityColumn;
  1792. bFreeSecurityColumn = FALSE;
  1793. //
  1794. // Now unmarshal the security descriptor
  1795. //
  1796. hr = DSGetAndValidateColumn(hAds, hSearchHandle, ADSTYPE_NT_SECURITY_DESCRIPTOR, SECURITYDESCRIPTOR, &SecurityColumn);
  1797. if (SUCCEEDED(hr))
  1798. {
  1799. //
  1800. // Allocate the security descriptor
  1801. //
  1802. hr = UnpackByteAllocFrom(
  1803. SecurityColumn,
  1804. (BYTE**) &(pPackageInfo->rgSecurityDescriptor),
  1805. &(pPackageInfo->cbSecurityDescriptor));
  1806. bFreeSecurityColumn = TRUE;
  1807. }
  1808. //
  1809. // In planning mode, we must perform the access check ourselves
  1810. //
  1811. if ( SUCCEEDED(hr) && pbUserHasAccess && pRsopUserToken )
  1812. {
  1813. hr = DSAccessCheck(
  1814. pPackageInfo->rgSecurityDescriptor,
  1815. pRsopUserToken,
  1816. pbUserHasAccess);
  1817. }
  1818. if ( bFreeSecurityColumn )
  1819. {
  1820. ADSIFreeColumn(hAds, &SecurityColumn);
  1821. }
  1822. return hr;
  1823. }
  1824. // GetCategories
  1825. //--------------------------
  1826. //
  1827. // Retrieves the categories attribute for an application
  1828. // in bracketed guid string format
  1829. HRESULT GetCategories(
  1830. HANDLE hAds,
  1831. ADS_SEARCH_HANDLE hSearchHandle,
  1832. PACKAGEDISPINFO* pPackageInfo)
  1833. {
  1834. HRESULT hr;
  1835. ADS_SEARCH_COLUMN ResultColumn;
  1836. BOOL bFreeCategoriesColumn;
  1837. pPackageInfo->prgCategories = NULL;
  1838. pPackageInfo->cCategories = 0;
  1839. bFreeCategoriesColumn = FALSE;
  1840. //
  1841. // Unmarshal the category list -- this package may have no catgories,
  1842. // in which case this call will return a failure
  1843. //
  1844. hr = DSGetAndValidateColumn(
  1845. hAds,
  1846. hSearchHandle,
  1847. ADSTYPE_CASE_IGNORE_STRING,
  1848. PKGCATEGORYLIST,
  1849. &ResultColumn);
  1850. if (SUCCEEDED(hr))
  1851. {
  1852. DWORD cCategories;
  1853. //
  1854. // Convert this to an array of guids -- note that the array
  1855. // is allocated and should be freed.
  1856. //
  1857. UnpackStrArrFrom(ResultColumn,
  1858. &(pPackageInfo->prgCategories),
  1859. &cCategories);
  1860. pPackageInfo->cCategories = cCategories;
  1861. bFreeCategoriesColumn = TRUE;
  1862. }
  1863. //
  1864. // Since the category guids stored in the ds lack the begin and end
  1865. // braces, we must add them so that our callers, who expect such guids,
  1866. // will get the correct information
  1867. //
  1868. DWORD iCategoryGuid;
  1869. hr = S_OK;
  1870. for ( iCategoryGuid = 0; iCategoryGuid < pPackageInfo->cCategories; iCategoryGuid++ )
  1871. {
  1872. WCHAR* wszNewGuid;
  1873. wszNewGuid = (WCHAR*) CsMemAlloc( ( MAX_GUIDSTR_LEN + 1 ) * sizeof(WCHAR) );
  1874. if ( ! wszNewGuid )
  1875. {
  1876. hr = E_OUTOFMEMORY;
  1877. pPackageInfo->cCategories = iCategoryGuid;
  1878. break;
  1879. }
  1880. wszNewGuid[0] = L'{';
  1881. wszNewGuid++;
  1882. hr = StringCchCopy(wszNewGuid, MAX_GUIDSTR_LEN + 1, pPackageInfo->prgCategories[iCategoryGuid]);
  1883. if (FAILED(hr))
  1884. {
  1885. pPackageInfo->cCategories = iCategoryGuid;
  1886. CsMemFree(wszNewGuid);
  1887. break;
  1888. }
  1889. wszNewGuid--;
  1890. wszNewGuid[ MAX_GUIDSTR_LEN - 1 ] = L'}';
  1891. wszNewGuid[ MAX_GUIDSTR_LEN ] = L'\0';
  1892. pPackageInfo->prgCategories[iCategoryGuid] = wszNewGuid;
  1893. }
  1894. if ( bFreeCategoriesColumn )
  1895. {
  1896. ADSIFreeColumn(hAds, &ResultColumn);
  1897. }
  1898. if (FAILED(hr))
  1899. {
  1900. //
  1901. // On failure, we must free all allocated memory
  1902. //
  1903. DWORD iCategory;
  1904. for ( iCategory = 0; iCategory < pPackageInfo->cCategories; iCategory++ )
  1905. {
  1906. CsMemFree(pPackageInfo->prgCategories[iCategory]);
  1907. }
  1908. CsMemFree(pPackageInfo->prgCategories);
  1909. pPackageInfo->prgCategories = NULL;
  1910. pPackageInfo->cCategories = 0;
  1911. }
  1912. if ( E_ADS_COLUMN_NOT_SET == hr )
  1913. {
  1914. hr = S_OK;
  1915. }
  1916. return hr;
  1917. }