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.

693 lines
22 KiB

  1. #include "stdinc.h"
  2. typedef CFusionArray<BYTE> CStackBackingBuffer;
  3. #define WRITE_INTO_BUFFER(cursor, target, length, source, leftover) \
  4. (target) = (cursor); \
  5. RtlCopyMemory(cursor, source, length); \
  6. leftover -= (length); \
  7. INTERNAL_ERROR_CHECK((length % sizeof(WCHAR) == 0)); \
  8. (cursor) = (PWSTR)(((ULONG_PTR)(cursor)) + length); \
  9. *(cursor)++ = UNICODE_NULL;
  10. BOOL
  11. SxspLookupAssemblyIdentityInActCtx(
  12. HANDLE hActCtx,
  13. ULONG ulRosterIndex,
  14. CStringBuffer &TargetString
  15. )
  16. {
  17. FN_PROLOG_WIN32;
  18. SIZE_T cbRequired = 0;
  19. bool fMoreSpaceRequired = false;
  20. CStackBackingBuffer TargetRegion;
  21. PCACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION pDetailedInfo = NULL;
  22. TargetString.Clear();
  23. IFW32FALSE_EXIT_UNLESS2(
  24. QueryActCtxW(
  25. 0,
  26. hActCtx,
  27. (PVOID)&ulRosterIndex,
  28. AssemblyDetailedInformationInActivationContext,
  29. TargetRegion.GetArrayPtr(),
  30. TargetRegion.GetSize(),
  31. &cbRequired),
  32. LIST_1(ERROR_INSUFFICIENT_BUFFER),
  33. fMoreSpaceRequired);
  34. if (fMoreSpaceRequired)
  35. {
  36. IFW32FALSE_EXIT(TargetRegion.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
  37. IFW32FALSE_EXIT(
  38. QueryActCtxW(
  39. 0,
  40. hActCtx,
  41. (PVOID)&ulRosterIndex,
  42. AssemblyDetailedInformationInActivationContext,
  43. TargetRegion.GetArrayPtr(),
  44. TargetRegion.GetSize(),
  45. &cbRequired));
  46. }
  47. pDetailedInfo = (PCACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)TargetRegion.GetArrayPtr();
  48. IFW32FALSE_EXIT(TargetString.Win32Assign(
  49. pDetailedInfo->lpAssemblyEncodedAssemblyIdentity,
  50. pDetailedInfo->ulEncodedAssemblyIdentityLength / sizeof(WCHAR)));
  51. FN_EPILOG;
  52. }
  53. BOOL
  54. WINAPI
  55. SxsFindClrClassInformation(
  56. DWORD dwFlags,
  57. PVOID pvSearchData,
  58. HANDLE hActivationContext,
  59. PVOID pvDataBuffer,
  60. SIZE_T cbDataBuffer,
  61. PSIZE_T pcbDataBufferWrittenOrRequired
  62. )
  63. {
  64. FN_PROLOG_WIN32;
  65. SIZE_T cbRequired = 0;
  66. CStringBuffer AssemblyIdentity;
  67. CFusionActCtxScope ActivationScope;
  68. CFusionActCtxHandle UsedHandleDuringSearch;
  69. GUID GuidToSearch;
  70. ACTCTX_SECTION_KEYED_DATA KeyedData = {sizeof(KeyedData)};
  71. PSXS_CLR_CLASS_INFORMATION pOutputStruct = NULL;
  72. PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION pComServerRedirect = NULL;
  73. PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM pClrShim = NULL;
  74. if (pcbDataBufferWrittenOrRequired)
  75. *pcbDataBufferWrittenOrRequired = 0;
  76. PARAMETER_CHECK(pcbDataBufferWrittenOrRequired != NULL);
  77. PARAMETER_CHECK(pvSearchData != NULL);
  78. PARAMETER_CHECK(pvDataBuffer || (cbDataBuffer == 0));
  79. IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
  80. SXS_FIND_CLR_CLASS_SEARCH_PROGID |
  81. SXS_FIND_CLR_CLASS_SEARCH_GUID |
  82. SXS_FIND_CLR_CLASS_ACTIVATE_ACTCTX |
  83. SXS_FIND_CLR_CLASS_GET_IDENTITY |
  84. SXS_FIND_CLR_CLASS_GET_PROGID |
  85. SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION |
  86. SXS_FIND_CLR_CLASS_GET_TYPE_NAME);
  87. //
  88. // Can't be both... I'm sure there's a logic thing I could do smarter here, but ohwell.
  89. //
  90. if ((dwFlags & SXS_FIND_CLR_CLASS_SEARCH_PROGID) && (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_GUID))
  91. {
  92. ORIGINATE_WIN32_FAILURE_AND_EXIT(CantSearchBothProgidAndGuid, ERROR_INVALID_PARAMETER);
  93. }
  94. //
  95. // But it has to be at least one of these.
  96. //
  97. else if ((dwFlags & (SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_SEARCH_GUID)) == 0)
  98. {
  99. ORIGINATE_WIN32_FAILURE_AND_EXIT(MustHaveAtLeastOneSearchTypeSet, ERROR_INVALID_PARAMETER);
  100. }
  101. //
  102. // Activate if necessary
  103. //
  104. if (dwFlags & SXS_FIND_CLR_CLASS_ACTIVATE_ACTCTX)
  105. {
  106. IFW32FALSE_EXIT(ActivationScope.Win32Activate(hActivationContext));
  107. AddRefActCtx(hActivationContext);
  108. UsedHandleDuringSearch = hActivationContext;
  109. }
  110. else
  111. {
  112. IFW32FALSE_EXIT(GetCurrentActCtx(&UsedHandleDuringSearch));
  113. }
  114. //
  115. // Aha, they wanted a progid search
  116. //
  117. if (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_PROGID)
  118. {
  119. PCACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION pProgidFound = NULL;
  120. IFW32FALSE_EXIT(
  121. FindActCtxSectionStringW(
  122. 0,
  123. NULL,
  124. ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION,
  125. (LPCWSTR)pvSearchData,
  126. &KeyedData));
  127. pProgidFound = (PCACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION)KeyedData.lpData;
  128. GuidToSearch = *(LPGUID)(((ULONG_PTR)KeyedData.lpSectionBase) + pProgidFound->ConfiguredClsidOffset);
  129. }
  130. //
  131. // They handed us a GUID instead
  132. //
  133. else if (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_GUID)
  134. {
  135. GuidToSearch = *(LPGUID)pvSearchData;
  136. }
  137. //
  138. // Hmm.. we validated these flags above, how could we possibly get here?
  139. //
  140. else
  141. {
  142. INTERNAL_ERROR_CHECK(FALSE);
  143. }
  144. //
  145. // Now that we've got the guids, let's look in the GUID clr class table for more information
  146. //
  147. RtlZeroMemory(&KeyedData, sizeof(KeyedData));
  148. KeyedData.cbSize = sizeof(KeyedData);
  149. IFW32FALSE_EXIT(
  150. FindActCtxSectionGuid(
  151. 0,
  152. NULL,
  153. ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
  154. &GuidToSearch,
  155. &KeyedData));
  156. pComServerRedirect = (PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION)KeyedData.lpData;
  157. //
  158. // What do we want to do here if you've asked for a CLR class and yet there's no surrogate
  159. // information??
  160. //
  161. if (pComServerRedirect->ShimDataOffset == 0)
  162. {
  163. ORIGINATE_WIN32_FAILURE_AND_EXIT(ThisGuidIsNotAClrClass, ERROR_SXS_KEY_NOT_FOUND);
  164. }
  165. pClrShim = (PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM)(((ULONG_PTR)pComServerRedirect) + pComServerRedirect->ShimDataOffset);
  166. //
  167. // Now we've got all the stuff we need. Calculate the required size of things.
  168. //
  169. cbRequired = sizeof(SXS_CLR_CLASS_INFORMATION);
  170. if ((dwFlags & SXS_FIND_CLR_CLASS_GET_PROGID) && (pComServerRedirect->ProgIdLength > 0))
  171. cbRequired += pComServerRedirect->ProgIdLength + sizeof(WCHAR);
  172. if (dwFlags & SXS_FIND_CLR_CLASS_GET_IDENTITY)
  173. {
  174. IFW32FALSE_EXIT(
  175. SxspLookupAssemblyIdentityInActCtx(
  176. UsedHandleDuringSearch,
  177. KeyedData.ulAssemblyRosterIndex,
  178. AssemblyIdentity));
  179. if (AssemblyIdentity.Cch() > 0) {
  180. cbRequired += (AssemblyIdentity.Cch() + 1) * sizeof(WCHAR);
  181. }
  182. }
  183. if ((dwFlags & SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION) && (pClrShim->ShimVersionLength > 0))
  184. cbRequired += pClrShim->ShimVersionLength + sizeof(WCHAR);
  185. if ((dwFlags & SXS_FIND_CLR_CLASS_GET_TYPE_NAME) && (pClrShim->TypeLength > 0))
  186. cbRequired += pClrShim->TypeLength + sizeof(WCHAR);
  187. //
  188. // Is there enough space in the outbound buffer?
  189. //
  190. if (cbRequired <= cbDataBuffer)
  191. {
  192. PWSTR pwszCursor;
  193. SIZE_T cbRemaining = cbDataBuffer;
  194. pOutputStruct = (PSXS_CLR_CLASS_INFORMATION)pvDataBuffer;
  195. pwszCursor = (PWSTR)(pOutputStruct + 1);
  196. cbRemaining -= sizeof(SXS_CLR_CLASS_INFORMATION);
  197. pOutputStruct->ReferenceClsid = GuidToSearch;
  198. pOutputStruct->dwFlags = 0;
  199. pOutputStruct->dwSize = sizeof(*pOutputStruct);
  200. pOutputStruct->ulThreadingModel = pComServerRedirect->ThreadingModel;
  201. pOutputStruct->ulType = pClrShim->Type;
  202. if (dwFlags & SXS_FIND_CLR_CLASS_GET_IDENTITY)
  203. {
  204. SIZE_T cbWritten;
  205. pOutputStruct->pcwszImplementingAssembly = pwszCursor;
  206. IFW32FALSE_EXIT(
  207. AssemblyIdentity.Win32CopyIntoBuffer(
  208. &pwszCursor,
  209. &cbRemaining,
  210. &cbWritten,
  211. NULL,
  212. NULL,
  213. NULL));
  214. }
  215. else
  216. pOutputStruct->pcwszImplementingAssembly = NULL;
  217. if (dwFlags & SXS_FIND_CLR_CLASS_GET_PROGID)
  218. {
  219. WRITE_INTO_BUFFER(
  220. pwszCursor,
  221. pOutputStruct->pcwszProgId,
  222. pComServerRedirect->ProgIdLength,
  223. (PVOID)(((ULONG_PTR)pComServerRedirect) + pComServerRedirect->ProgIdOffset),
  224. cbRemaining);
  225. }
  226. else
  227. pOutputStruct->pcwszProgId = NULL;
  228. if (dwFlags & SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION)
  229. {
  230. WRITE_INTO_BUFFER(
  231. pwszCursor,
  232. pOutputStruct->pcwszRuntimeVersion,
  233. pClrShim->ShimVersionLength,
  234. (PVOID)(((ULONG_PTR)pClrShim) + pClrShim->ShimVersionLength),
  235. cbRemaining);
  236. }
  237. else
  238. pOutputStruct->pcwszRuntimeVersion = NULL;
  239. if (dwFlags & SXS_FIND_CLR_CLASS_GET_TYPE_NAME)
  240. {
  241. WRITE_INTO_BUFFER(
  242. pwszCursor,
  243. pOutputStruct->pcwszTypeName,
  244. pClrShim->TypeLength,
  245. (PVOID)(((ULONG_PTR)pClrShim) + pClrShim->TypeOffset),
  246. cbRemaining);
  247. }
  248. else
  249. pOutputStruct->pcwszTypeName = NULL;
  250. *pcbDataBufferWrittenOrRequired = cbRequired;
  251. }
  252. else
  253. {
  254. *pcbDataBufferWrittenOrRequired = cbRequired;
  255. ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutboundBuffer, ERROR_INSUFFICIENT_BUFFER);
  256. }
  257. FN_EPILOG;
  258. }
  259. BOOL
  260. WINAPI
  261. SxsFindClrSurrogateInformation(
  262. DWORD dwFlags,
  263. LPGUID lpGuidToFind,
  264. HANDLE hActivationContext,
  265. PVOID pvDataBuffer,
  266. SIZE_T cbDataBuffer,
  267. PSIZE_T pcbDataBufferWrittenOrRequired
  268. )
  269. {
  270. FN_PROLOG_WIN32;
  271. SIZE_T cbRequired = 0;
  272. PSXS_CLR_SURROGATE_INFORMATION pOutputStruct = NULL;
  273. PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pSurrogateInfo = NULL;
  274. ACTCTX_SECTION_KEYED_DATA KeyedData = {sizeof(KeyedData)};
  275. CFusionActCtxScope ActCtxScope;
  276. CFusionActCtxHandle UsedActivationContext;
  277. CStringBuffer AssemblyIdentity;
  278. if (pcbDataBufferWrittenOrRequired != NULL)
  279. *pcbDataBufferWrittenOrRequired = 0;
  280. //
  281. // The data buffer has to be present, or the data buffer size has to be zero,
  282. // and the written-or-required value must be present as well.
  283. //
  284. PARAMETER_CHECK(pvDataBuffer || (cbDataBuffer == 0));
  285. PARAMETER_CHECK(pcbDataBufferWrittenOrRequired != NULL);
  286. IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
  287. SXS_FIND_CLR_SURROGATE_USE_ACTCTX |
  288. SXS_FIND_CLR_SURROGATE_GET_IDENTITY |
  289. SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION |
  290. SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME);
  291. //
  292. // Steps we take here:
  293. // - Activate the actctx if required.
  294. // - Find the surrogate that corresponds to this progid
  295. // - Calculate required size of data
  296. // - If there's enough space, then start copying into the output blob
  297. // - Otherwise, set the "required" size and error out with ERROR_INSUFFICIENT_BUFFER
  298. //
  299. //
  300. // If we were told to use the actctx, then activate it over this function,
  301. // and get a reference to it into UsedActivationContext so we can query with
  302. // it later.
  303. //
  304. if (dwFlags & SXS_FIND_CLR_SURROGATE_USE_ACTCTX)
  305. {
  306. IFW32FALSE_EXIT(ActCtxScope.Win32Activate(hActivationContext));
  307. AddRefActCtx(hActivationContext);
  308. UsedActivationContext = hActivationContext;
  309. }
  310. //
  311. // Otherwise, grab the current actctx and go to town. This addrefs the activation
  312. // context, so we can let UsedActivationContext's destructor release it on the
  313. // exit path.
  314. //
  315. else
  316. {
  317. IFW32FALSE_EXIT(GetCurrentActCtx(&UsedActivationContext));
  318. }
  319. //
  320. // Initially, we require at least this amount of space.
  321. //
  322. cbRequired += sizeof(SXS_CLR_SURROGATE_INFORMATION);
  323. IFW32FALSE_EXIT(
  324. FindActCtxSectionGuid(
  325. 0,
  326. NULL,
  327. ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
  328. lpGuidToFind,
  329. &KeyedData));
  330. //
  331. // Start totalling up the size
  332. //
  333. pSurrogateInfo = (PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE)KeyedData.lpData;
  334. if ((dwFlags & SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME) && (pSurrogateInfo->TypeNameLength > 0))
  335. cbRequired += pSurrogateInfo->TypeNameLength + sizeof(WCHAR);
  336. if ((dwFlags & SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION) && (pSurrogateInfo->VersionLength > 0))
  337. cbRequired += pSurrogateInfo->VersionLength + sizeof(WCHAR);
  338. if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_IDENTITY)
  339. {
  340. IFW32FALSE_EXIT(
  341. SxspLookupAssemblyIdentityInActCtx(
  342. UsedActivationContext,
  343. KeyedData.ulAssemblyRosterIndex,
  344. AssemblyIdentity));
  345. if (AssemblyIdentity.Cch() > 0)
  346. {
  347. cbRequired += (AssemblyIdentity.Cch() + 1) * sizeof(WCHAR);
  348. }
  349. }
  350. //
  351. // Go stomp the gathered data into the right places
  352. //
  353. if (cbRequired <= cbDataBuffer)
  354. {
  355. PWSTR pwszOutputCursor;
  356. SIZE_T cbRemaining = cbDataBuffer;
  357. SIZE_T cbWritten = 0;
  358. pOutputStruct = (PSXS_CLR_SURROGATE_INFORMATION)pvDataBuffer;
  359. pwszOutputCursor = (PWSTR)(pOutputStruct + 1);
  360. pOutputStruct->cbSize = sizeof(SXS_CLR_SURROGATE_INFORMATION);
  361. pOutputStruct->dwFlags = 0;
  362. pOutputStruct->SurrogateIdent = pSurrogateInfo->SurrogateIdent;
  363. //
  364. // Write things into the output buffer
  365. //
  366. if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_IDENTITY)
  367. {
  368. pOutputStruct->pcwszImplementingAssembly = pwszOutputCursor;
  369. IFW32FALSE_EXIT(
  370. AssemblyIdentity.Win32CopyIntoBuffer(
  371. &pwszOutputCursor,
  372. &cbRemaining,
  373. &cbWritten,
  374. NULL, NULL, NULL));
  375. }
  376. else
  377. pOutputStruct->pcwszImplementingAssembly = NULL;
  378. if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME)
  379. {
  380. WRITE_INTO_BUFFER(
  381. pwszOutputCursor,
  382. pOutputStruct->pcwszSurrogateType,
  383. pSurrogateInfo->TypeNameLength,
  384. (PVOID)(((ULONG_PTR)pSurrogateInfo) + pSurrogateInfo->TypeNameOffset),
  385. cbRemaining);
  386. }
  387. else
  388. pOutputStruct->pcwszSurrogateType = NULL;
  389. if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION)
  390. {
  391. WRITE_INTO_BUFFER(
  392. pwszOutputCursor,
  393. pOutputStruct->pcwszRuntimeVersion,
  394. pSurrogateInfo->VersionLength,
  395. (PVOID)(((ULONG_PTR)pSurrogateInfo) + pSurrogateInfo->VersionOffset),
  396. cbRemaining);
  397. }
  398. else
  399. pOutputStruct->pcwszRuntimeVersion = NULL;
  400. *pcbDataBufferWrittenOrRequired = cbRequired;
  401. }
  402. else
  403. {
  404. *pcbDataBufferWrittenOrRequired = cbRequired;
  405. ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutputBuffer, ERROR_INSUFFICIENT_BUFFER);
  406. }
  407. FN_EPILOG;
  408. }
  409. BOOL
  410. WINAPI
  411. SxsLookupClrGuid(
  412. DWORD dwFlags,
  413. LPGUID pClsid,
  414. HANDLE hActCtx,
  415. PVOID pvOutputBuffer,
  416. SIZE_T cbOutputBuffer,
  417. PSIZE_T pcbOutputBuffer
  418. )
  419. {
  420. FN_PROLOG_WIN32;
  421. if (pcbOutputBuffer)
  422. *pcbOutputBuffer = 0;
  423. CStackBackingBuffer BackingBuffer;
  424. DWORD dwLastError;
  425. SIZE_T cbRequired = 0;
  426. PSXS_GUID_INFORMATION_CLR pOutputTarget = NULL;
  427. PCWSTR pcwszRuntimeVersion = NULL;
  428. PCWSTR pcwszTypeName = NULL;
  429. PCWSTR pcwszAssemblyName = NULL;
  430. SIZE_T cchRuntimeVersion = 0;
  431. SIZE_T cchTypeName = 0;
  432. SIZE_T cchAssemblyName = 0;
  433. enum {
  434. eFoundSurrogate,
  435. eFoundClrClass,
  436. eNotFound
  437. } FoundThingType = eNotFound;
  438. PARAMETER_CHECK(pcbOutputBuffer != NULL);
  439. PARAMETER_CHECK(pvOutputBuffer || (cbOutputBuffer == 0));
  440. IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
  441. SXS_LOOKUP_CLR_GUID_USE_ACTCTX |
  442. SXS_LOOKUP_CLR_GUID_FIND_SURROGATE |
  443. SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS |
  444. SXS_LOOKUP_CLR_GUID_FIND_ANY);
  445. //
  446. // Nothing found yet, let's look into the surrogate data tables first
  447. //
  448. if ((FoundThingType == eNotFound) && ((dwFlags & SXS_LOOKUP_CLR_GUID_FIND_SURROGATE) != 0))
  449. {
  450. IFW32FALSE_EXIT_UNLESS3(
  451. SxsFindClrSurrogateInformation(
  452. SXS_FIND_CLR_SURROGATE_GET_ALL | ((dwFlags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX) ? SXS_FIND_CLR_SURROGATE_USE_ACTCTX : 0),
  453. pClsid,
  454. hActCtx,
  455. BackingBuffer.GetArrayPtr(),
  456. BackingBuffer.GetSize(),
  457. &cbRequired),
  458. LIST_3(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND, ERROR_INSUFFICIENT_BUFFER),
  459. dwLastError);
  460. //
  461. // If we found the key and section, but the buffer was too small, resize and try again
  462. //
  463. if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
  464. {
  465. IFW32FALSE_EXIT(BackingBuffer.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
  466. IFW32FALSE_EXIT_UNLESS3(
  467. SxsFindClrSurrogateInformation(
  468. SXS_FIND_CLR_SURROGATE_GET_ALL | ((dwFlags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX) ? SXS_FIND_CLR_SURROGATE_USE_ACTCTX : 0),
  469. pClsid,
  470. hActCtx,
  471. BackingBuffer.GetArrayPtr(),
  472. BackingBuffer.GetSize(),
  473. &cbRequired),
  474. LIST_2(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
  475. dwLastError);
  476. }
  477. //
  478. // Great - we either succeeded during the first call, or we succeeded after
  479. // resizing our buffers. Gather information, set the type, and continue.
  480. //
  481. if (dwLastError == ERROR_SUCCESS)
  482. {
  483. //
  484. // At this point, BackingBuffer contains goop about a CLR surrogate. Ensure that
  485. // our output buffer is large enough, and then fill it out.
  486. //
  487. PCSXS_CLR_SURROGATE_INFORMATION pSurrogateInfo =
  488. (PCSXS_CLR_SURROGATE_INFORMATION)BackingBuffer.GetArrayPtr();
  489. pcwszAssemblyName = pSurrogateInfo->pcwszImplementingAssembly;
  490. pcwszTypeName = pSurrogateInfo->pcwszSurrogateType;
  491. pcwszRuntimeVersion = pSurrogateInfo->pcwszRuntimeVersion;
  492. FoundThingType = eFoundSurrogate;
  493. }
  494. }
  495. //
  496. // We've yet to find anything, and the flags say we can look up a clr class
  497. //
  498. if ((FoundThingType == eNotFound) && ((dwFlags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS) != 0))
  499. {
  500. IFW32FALSE_EXIT_UNLESS3(
  501. SxsFindClrClassInformation(
  502. SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
  503. (PVOID)pClsid,
  504. hActCtx,
  505. BackingBuffer.GetArrayPtr(),
  506. BackingBuffer.GetSize(),
  507. &cbRequired),
  508. LIST_3(ERROR_INSUFFICIENT_BUFFER, ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
  509. dwLastError);
  510. if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
  511. {
  512. IFW32FALSE_EXIT(BackingBuffer.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
  513. IFW32FALSE_EXIT_UNLESS3(
  514. SxsFindClrClassInformation(
  515. SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
  516. (PVOID)pClsid,
  517. hActCtx,
  518. BackingBuffer.GetArrayPtr(),
  519. BackingBuffer.GetSize(),
  520. &cbRequired),
  521. LIST_2(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
  522. dwLastError);
  523. }
  524. //
  525. // We succeeded, either after the first query, or after resizing.
  526. //
  527. if (dwLastError == ERROR_SUCCESS)
  528. {
  529. PCSXS_CLR_CLASS_INFORMATION pClassInfo =
  530. (PCSXS_CLR_CLASS_INFORMATION)BackingBuffer.GetArrayPtr();
  531. FoundThingType = eFoundClrClass;
  532. pcwszAssemblyName = pClassInfo->pcwszImplementingAssembly;
  533. pcwszRuntimeVersion = pClassInfo->pcwszRuntimeVersion;
  534. pcwszTypeName = pClassInfo->pcwszTypeName;
  535. }
  536. }
  537. //
  538. // If we got to this point and didn't find anything, then error out with a reasonable
  539. // error code.
  540. //
  541. if (FoundThingType == eNotFound)
  542. {
  543. ORIGINATE_WIN32_FAILURE_AND_EXIT(DidntFindObject, ERROR_NOT_FOUND);
  544. }
  545. //
  546. // Calculate some sizes - string lengths, etc.
  547. //
  548. cbRequired = sizeof(SXS_GUID_INFORMATION_CLR);
  549. cchAssemblyName = StringLength(pcwszAssemblyName);
  550. cchRuntimeVersion = StringLength(pcwszRuntimeVersion);
  551. cchTypeName = StringLength(pcwszTypeName);
  552. cbRequired += (cchAssemblyName + cchRuntimeVersion + cchTypeName + 3) * sizeof(WCHAR);
  553. //
  554. // If there was enough space, start stomping data into the output buffer
  555. //
  556. if (cbRequired <= cbOutputBuffer)
  557. {
  558. PWSTR pwszCursor;
  559. pOutputTarget = (PSXS_GUID_INFORMATION_CLR)pvOutputBuffer;
  560. pwszCursor = (PWSTR)(pOutputTarget + 1);
  561. pOutputTarget->cbSize = sizeof(*pOutputTarget);
  562. pOutputTarget->dwFlags = 0;
  563. switch (FoundThingType) {
  564. case eFoundClrClass:
  565. pOutputTarget->dwFlags |= SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS;
  566. break;
  567. case eFoundSurrogate:
  568. pOutputTarget->dwFlags |= SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE;
  569. break;
  570. default:
  571. INTERNAL_ERROR_CHECK(FALSE);
  572. break;
  573. }
  574. //
  575. // This grossness is unfortunately required.
  576. //
  577. pOutputTarget->pcwszAssemblyIdentity = pwszCursor;
  578. wcscpy(pwszCursor, pcwszAssemblyName);
  579. pwszCursor += cchAssemblyName + 1;
  580. pOutputTarget->pcwszRuntimeVersion= pwszCursor;
  581. wcscpy(pwszCursor, pcwszRuntimeVersion);
  582. pwszCursor += cchRuntimeVersion+ 1;
  583. pOutputTarget->pcwszTypeName = pwszCursor;
  584. wcscpy(pwszCursor, pcwszTypeName);
  585. pwszCursor += cchTypeName + 1;
  586. *pcbOutputBuffer = cbRequired;
  587. }
  588. else
  589. {
  590. *pcbOutputBuffer = cbRequired;
  591. ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutputBuffer, ERROR_INSUFFICIENT_BUFFER);
  592. }
  593. FN_EPILOG;
  594. }