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.

462 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. comprogid.cpp
  5. Abstract:
  6. Activation context section contributor for COM progid mapping.
  7. Author:
  8. Michael J. Grier (MGrier) 23-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include <windows.h>
  13. #include "sxsp.h"
  14. DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(clsid);
  15. DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(progid);
  16. DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(id);
  17. #define STRING_AND_LENGTH(x) x, NUMBER_OF(x)-1
  18. BOOL
  19. SxspComProgIdRedirectionStringSectionGenerationCallback(
  20. PVOID Context,
  21. ULONG Reason,
  22. PVOID CallbackData
  23. );
  24. typedef struct _COM_PROGID_GLOBAL_CONTEXT *PCOM_PROGID_GLOBAL_CONTEXT;
  25. typedef struct _COM_PROGID_SERVER_CONTEXT *PCOM_PROGID_SERVER_CONTEXT;
  26. typedef struct _COM_PROGID_GLOBAL_CONTEXT
  27. {
  28. // Temporary holding buffer for the configured CLSID until the first COM progid entry is
  29. // found, at which time a COM_PROGID_SERVER_CONTEXT is allocated and the filename moved to it.
  30. GUID m_ConfiguredClsid;
  31. PCOM_PROGID_SERVER_CONTEXT m_ServerContextListHead;
  32. ULONG m_ServerContextListCount;
  33. } COM_PROGID_GLOBAL_CONTEXT;
  34. typedef struct _COM_PROGID_SERVER_CONTEXT
  35. {
  36. PCOM_PROGID_SERVER_CONTEXT m_Next;
  37. GUID m_ConfiguredClsid;
  38. LONG m_Offset; // populated during section generation
  39. } COM_PROGID_SERVER_CONTEXT;
  40. VOID
  41. SxspComProgIdRedirectionContributorCallback(
  42. PACTCTXCTB_CALLBACK_DATA Data
  43. )
  44. {
  45. FN_TRACE();
  46. PSTRING_SECTION_GENERATION_CONTEXT SSGenContext = (PSTRING_SECTION_GENERATION_CONTEXT) Data->Header.ActCtxGenContext;
  47. PCOM_PROGID_GLOBAL_CONTEXT ComGlobalContext = NULL;
  48. if (SSGenContext != NULL)
  49. ComGlobalContext = (PCOM_PROGID_GLOBAL_CONTEXT) ::SxsGetStringSectionGenerationContextCallbackContext(SSGenContext);
  50. switch (Data->Header.Reason)
  51. {
  52. case ACTCTXCTB_CBREASON_ACTCTXGENBEGINNING:
  53. Data->GenBeginning.Success = FALSE;
  54. INTERNAL_ERROR_CHECK(ComGlobalContext == NULL);
  55. INTERNAL_ERROR_CHECK(SSGenContext == NULL);
  56. IFALLOCFAILED_EXIT(ComGlobalContext = new COM_PROGID_GLOBAL_CONTEXT);
  57. ComGlobalContext->m_ConfiguredClsid = GUID_NULL;
  58. ComGlobalContext->m_ServerContextListHead = NULL;
  59. ComGlobalContext->m_ServerContextListCount = 0;
  60. if (!::SxsInitStringSectionGenerationContext(
  61. &SSGenContext,
  62. ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION_FORMAT_WHISTLER,
  63. TRUE,
  64. &::SxspComProgIdRedirectionStringSectionGenerationCallback,
  65. ComGlobalContext))
  66. {
  67. FUSION_DELETE_SINGLETON(ComGlobalContext);
  68. goto Exit;
  69. }
  70. Data->Header.ActCtxGenContext = SSGenContext;
  71. Data->GenBeginning.Success = TRUE;
  72. break;
  73. case ACTCTXCTB_CBREASON_ACTCTXGENENDED:
  74. {
  75. PCOM_PROGID_SERVER_CONTEXT ServerContext;
  76. ULONG ContextCount;
  77. if (ComGlobalContext != NULL)
  78. {
  79. if (SSGenContext != NULL)
  80. ::SxsDestroyStringSectionGenerationContext(SSGenContext);
  81. ServerContext = ComGlobalContext->m_ServerContextListHead;
  82. ContextCount = 0;
  83. while (ServerContext != NULL)
  84. {
  85. PCOM_PROGID_SERVER_CONTEXT NextServerContext = ServerContext->m_Next;
  86. FUSION_DELETE_SINGLETON(ServerContext);
  87. ServerContext = NextServerContext;
  88. if (ContextCount++ > ComGlobalContext->m_ServerContextListCount)
  89. break;
  90. }
  91. // If this assert fires, we ran out of entries in the list before we hit as many
  92. // server contexts as the list thinks there are.
  93. ASSERT(ContextCount == ComGlobalContext->m_ServerContextListCount);
  94. // If this assert fires, we seem to have more entries in the list than the
  95. // list count indicates.
  96. ASSERT(ServerContext == NULL);
  97. FUSION_DELETE_SINGLETON(ComGlobalContext);
  98. }
  99. break;
  100. }
  101. case ACTCTXCTB_CBREASON_ALLPARSINGDONE:
  102. Data->AllParsingDone.Success = FALSE;
  103. if (SSGenContext != NULL)
  104. IFW32FALSE_EXIT(::SxsDoneModifyingStringSectionGenerationContext(SSGenContext));
  105. Data->AllParsingDone.Success = TRUE;
  106. break;
  107. case ACTCTXCTB_CBREASON_PCDATAPARSED:
  108. {
  109. Data->PCDATAParsed.Success = FALSE;
  110. ULONG MappedValue = 0;
  111. bool fFound = false;
  112. enum MappedValues
  113. {
  114. eAssemblyFileComclassProgid = 1
  115. };
  116. static const ELEMENT_PATH_MAP_ENTRY s_rgEntries[] =
  117. {
  118. { 4, STRING_AND_LENGTH(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^comClass!urn:schemas-microsoft-com:asm.v1^progid"), eAssemblyFileComclassProgid },
  119. { 3, STRING_AND_LENGTH(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^clrClass!urn:schemas-microsoft-com:asm.v1^progid"), eAssemblyFileComclassProgid }
  120. };
  121. IFW32FALSE_EXIT(
  122. ::SxspProcessElementPathMap(
  123. Data->PCDATAParsed.ParseContext,
  124. s_rgEntries,
  125. NUMBER_OF(s_rgEntries),
  126. MappedValue,
  127. fFound));;
  128. if (fFound)
  129. {
  130. switch (MappedValue)
  131. {
  132. default:
  133. INTERNAL_ERROR2_ACTION(MappedValue, "Invalid mapped value returned from SxspProcessElementPathMap()");
  134. case eAssemblyFileComclassProgid:
  135. {
  136. if (Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
  137. {
  138. PCOM_PROGID_SERVER_CONTEXT ServerContext = NULL;
  139. INTERNAL_ERROR_CHECK(ComGlobalContext != NULL);
  140. ServerContext = ComGlobalContext->m_ServerContextListHead;
  141. INTERNAL_ERROR_CHECK(ServerContext != NULL);
  142. IFW32FALSE_EXIT(
  143. ::SxsAddStringToStringSectionGenerationContext(
  144. (PSTRING_SECTION_GENERATION_CONTEXT) Data->PCDATAParsed.Header.ActCtxGenContext,
  145. Data->PCDATAParsed.Text,
  146. Data->PCDATAParsed.TextCch,
  147. ServerContext,
  148. Data->PCDATAParsed.AssemblyContext->AssemblyRosterIndex,
  149. ERROR_SXS_DUPLICATE_PROGID));
  150. }
  151. break;
  152. }
  153. }
  154. }
  155. Data->PCDATAParsed.Success = TRUE;
  156. break;
  157. }
  158. case ACTCTXCTB_CBREASON_ELEMENTPARSED:
  159. {
  160. Data->ElementParsed.Success = FALSE;
  161. ULONG MappedValue = 0;
  162. bool fFound = false;
  163. enum MappedValues
  164. {
  165. eAssemblyFileComclass = 1
  166. };
  167. static const ELEMENT_PATH_MAP_ENTRY s_rgEntries[] =
  168. {
  169. { 3, STRING_AND_LENGTH(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^comClass"), eAssemblyFileComclass },
  170. { 2, STRING_AND_LENGTH(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^clrClass"), eAssemblyFileComclass }
  171. };
  172. IFW32FALSE_EXIT(
  173. ::SxspProcessElementPathMap(
  174. Data->ElementParsed.ParseContext,
  175. s_rgEntries,
  176. NUMBER_OF(s_rgEntries),
  177. MappedValue,
  178. fFound));
  179. if (fFound)
  180. {
  181. switch (MappedValue)
  182. {
  183. default:
  184. INTERNAL_ERROR2_ACTION(MappedValue, "Invalid mapped value returned from SxspProcessElementPathMap()");
  185. case eAssemblyFileComclass:
  186. {
  187. bool fProgIdFound = false;
  188. bool fFound = false;
  189. SIZE_T cb;
  190. CSmallStringBuffer VersionIndependentComClassIdBuffer;
  191. PCOM_PROGID_SERVER_CONTEXT ServerContext = NULL;
  192. CSmallStringBuffer ProgIdBuffer;
  193. GUID ReferenceClsid, ConfiguredClsid, ImplementedClsid;
  194. INTERNAL_ERROR_CHECK2(
  195. ComGlobalContext != NULL,
  196. "COM progid global context NULL while processing comClass tag");
  197. IFW32FALSE_EXIT(
  198. ::SxspGetAttributeValue(
  199. SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
  200. &s_AttributeName_clsid,
  201. &Data->ElementParsed,
  202. fFound,
  203. sizeof(VersionIndependentComClassIdBuffer),
  204. &VersionIndependentComClassIdBuffer,
  205. cb,
  206. NULL,
  207. 0));
  208. INTERNAL_ERROR_CHECK(fFound);
  209. IFW32FALSE_EXIT(
  210. ::SxspParseGUID(
  211. VersionIndependentComClassIdBuffer,
  212. VersionIndependentComClassIdBuffer.Cch(),
  213. ReferenceClsid));
  214. IFW32FALSE_EXIT(
  215. ::SxspGetAttributeValue(
  216. 0,
  217. &s_AttributeName_progid,
  218. &Data->ElementParsed,
  219. fProgIdFound,
  220. sizeof(ProgIdBuffer),
  221. &ProgIdBuffer,
  222. cb,
  223. NULL,
  224. 0));
  225. // That was sufficient we are not generating an activation context,
  226. // or if there's no progid= attribute on the element.
  227. if (fProgIdFound && (Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT))
  228. {
  229. IFW32FALSE_EXIT(Data->Header.ClsidMappingContext->Map->MapReferenceClsidToConfiguredClsid(
  230. &ReferenceClsid,
  231. Data->ElementParsed.AssemblyContext,
  232. &ConfiguredClsid,
  233. &ImplementedClsid));
  234. IFALLOCFAILED_EXIT(ServerContext = new COM_PROGID_SERVER_CONTEXT);
  235. ServerContext->m_ConfiguredClsid = ConfiguredClsid;
  236. ServerContext->m_Offset = 0;
  237. ServerContext->m_Next = ComGlobalContext->m_ServerContextListHead;
  238. ComGlobalContext->m_ServerContextListHead = ServerContext;
  239. ComGlobalContext->m_ServerContextListCount++;
  240. IFW32FALSE_EXIT(::SxsAddStringToStringSectionGenerationContext(
  241. (PSTRING_SECTION_GENERATION_CONTEXT) Data->ElementParsed.Header.ActCtxGenContext,
  242. ProgIdBuffer,
  243. ProgIdBuffer.Cch(),
  244. ServerContext,
  245. Data->ElementParsed.AssemblyContext->AssemblyRosterIndex,
  246. ERROR_SXS_DUPLICATE_PROGID));
  247. }
  248. break;
  249. }
  250. }
  251. }
  252. Data->ElementParsed.Success = TRUE;
  253. break;
  254. }
  255. case ACTCTXCTB_CBREASON_GETSECTIONSIZE:
  256. Data->GetSectionSize.Success = FALSE;
  257. // Someone shouldn't be asking for the section size if we
  258. // are generating an activation context.
  259. // These two asserts should be equivalent...
  260. INTERNAL_ERROR_CHECK(Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
  261. INTERNAL_ERROR_CHECK(SSGenContext != NULL);
  262. IFW32FALSE_EXIT(
  263. ::SxsGetStringSectionGenerationContextSectionSize(
  264. SSGenContext,
  265. &Data->GetSectionSize.SectionSize));
  266. Data->GetSectionSize.Success = TRUE;
  267. break;
  268. case ACTCTXCTB_CBREASON_GETSECTIONDATA:
  269. Data->GetSectionData.Success = FALSE;
  270. INTERNAL_ERROR_CHECK(SSGenContext != NULL);
  271. INTERNAL_ERROR_CHECK(Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
  272. IFW32FALSE_EXIT(
  273. ::SxsGetStringSectionGenerationContextSectionData(
  274. SSGenContext,
  275. Data->GetSectionData.SectionSize,
  276. Data->GetSectionData.SectionDataStart,
  277. NULL));
  278. Data->GetSectionData.Success = TRUE;
  279. break;
  280. }
  281. Exit:
  282. ;
  283. }
  284. BOOL
  285. SxspComProgIdRedirectionStringSectionGenerationCallback(
  286. PVOID Context,
  287. ULONG Reason,
  288. PVOID CallbackData
  289. )
  290. {
  291. BOOL fSuccess = FALSE;
  292. FN_TRACE_WIN32(fSuccess);
  293. PCOM_PROGID_GLOBAL_CONTEXT GlobalContext = (PCOM_PROGID_GLOBAL_CONTEXT) Context;
  294. switch (Reason)
  295. {
  296. default:
  297. INTERNAL_ERROR_CHECK(FALSE);
  298. goto Exit; // never hit this line, INTERNAL_ERROR_CHECK would "goto Exit"
  299. case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_ENTRYDELETED:
  300. // do nothing;
  301. break;
  302. case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETUSERDATASIZE:
  303. {
  304. PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETUSERDATASIZE CBData = (PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETUSERDATASIZE) CallbackData;
  305. CBData->DataSize = sizeof(GUID) * GlobalContext->m_ServerContextListCount;
  306. break;
  307. }
  308. case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETUSERDATA:
  309. {
  310. PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETUSERDATA CBData = (PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETUSERDATA) CallbackData;
  311. SIZE_T BytesWritten = 0;
  312. SIZE_T BytesLeft = CBData->BufferSize;
  313. GUID *Cursor = (GUID *) CBData->Buffer;
  314. PCOM_PROGID_SERVER_CONTEXT ServerContext = GlobalContext->m_ServerContextListHead;
  315. INTERNAL_ERROR_CHECK2(
  316. BytesLeft >= (sizeof(GUID) * GlobalContext->m_ServerContextListCount),
  317. "progid section generation ran out of buffer storing configured clsids");
  318. BytesWritten += (sizeof(GUID) * GlobalContext->m_ServerContextListCount);
  319. BytesLeft -= (sizeof(GUID) * GlobalContext->m_ServerContextListCount);
  320. while (ServerContext != NULL)
  321. {
  322. ServerContext->m_Offset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) CBData->SectionHeader));
  323. *Cursor++ = ServerContext->m_ConfiguredClsid;
  324. ServerContext = ServerContext->m_Next;
  325. }
  326. CBData->BytesWritten = BytesWritten;
  327. break;
  328. }
  329. case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATASIZE:
  330. {
  331. PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE CBData = (PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE) CallbackData;
  332. CBData->DataSize = sizeof(ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION);
  333. break;
  334. }
  335. case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATA:
  336. {
  337. PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA CBData = (PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA) CallbackData;
  338. PACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION Info;
  339. PCOM_PROGID_SERVER_CONTEXT ServerContext = (PCOM_PROGID_SERVER_CONTEXT) CBData->DataContext;
  340. SIZE_T BytesLeft = CBData->BufferSize;
  341. SIZE_T BytesWritten = 0;
  342. Info = (PACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION) CBData->Buffer;
  343. if (BytesLeft < sizeof(ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION))
  344. {
  345. ::FusionpSetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
  346. goto Exit;
  347. }
  348. BytesWritten += sizeof(ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION);
  349. BytesLeft -= sizeof(ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION);
  350. Info->Size = sizeof(ACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION);
  351. Info->Flags = 0;
  352. Info->ConfiguredClsidOffset = ServerContext->m_Offset;
  353. CBData->BytesWritten = BytesWritten;
  354. break;
  355. }
  356. }
  357. fSuccess = TRUE;
  358. Exit:
  359. return fSuccess;
  360. }