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.

319 lines
11 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. query.cpp
  5. Abstract:
  6. Information querying functions for sxs.dll
  7. Author:
  8. Michael J. Grier (MGrier) 22-May-2001
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include <windows.h>
  13. #include "sxsp.h"
  14. BOOL
  15. SxspQueryManifestInformationBasic(
  16. IN DWORD dwFlags,
  17. IN PCWSTR pszSource,
  18. IN DWORD dwInfoClassSpecificFlags,
  19. IN SIZE_T cbBuffer,
  20. OUT PVOID lpBuffer,
  21. OUT PSIZE_T cbWrittenOrRequired OPTIONAL
  22. );
  23. BOOL
  24. SxsQueryManifestInformation(
  25. IN DWORD dwFlags,
  26. IN PCWSTR pszSource,
  27. IN ULONG ulInfoClass,
  28. IN DWORD dwInfoClassSpecificFlags,
  29. IN SIZE_T cbBuffer,
  30. OUT PVOID lpBuffer,
  31. OUT PSIZE_T pcbWrittenOrRequired OPTIONAL
  32. )
  33. {
  34. FN_PROLOG_WIN32;
  35. if (pcbWrittenOrRequired != NULL)
  36. *pcbWrittenOrRequired = 0;
  37. PARAMETER_CHECK((dwFlags & ~SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL) == 0);
  38. PARAMETER_CHECK(pszSource != NULL);
  39. PARAMETER_CHECK(ulInfoClass == SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC);
  40. // ignore infoclass specific flags
  41. PARAMETER_CHECK((cbBuffer == 0) || (lpBuffer != NULL)); // can't have a nonzero-sized buffer with a NULL pointer to it
  42. PARAMETER_CHECK((cbBuffer != 0) || (pcbWrittenOrRequired != NULL));
  43. switch (ulInfoClass)
  44. {
  45. default:
  46. INTERNAL_ERROR_CHECK(
  47. (ulInfoClass == SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC)
  48. );
  49. ORIGINATE_WIN32_FAILURE_AND_EXIT(InternalErrorNoCaseForInfoClass, ERROR_INTERNAL_ERROR);
  50. break;
  51. case SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC:
  52. IFW32FALSE_EXIT(
  53. ::SxspQueryManifestInformationBasic(
  54. dwFlags,
  55. pszSource,
  56. dwInfoClassSpecificFlags,
  57. cbBuffer,
  58. lpBuffer,
  59. pcbWrittenOrRequired));
  60. break;
  61. }
  62. FN_EPILOG;
  63. }
  64. BOOL
  65. SxspQueryManifestInformationBasic(
  66. IN DWORD dwFlags,
  67. IN PCWSTR pszSource,
  68. IN DWORD dwInfoClassSpecificFlags,
  69. IN SIZE_T cbBuffer,
  70. OUT PVOID lpBuffer,
  71. OUT PSIZE_T pcbWrittenOrRequired OPTIONAL
  72. )
  73. {
  74. FN_PROLOG_WIN32;
  75. ACTCTXGENCTX ActCtxGenCtx;
  76. ULONG ManifestFlags;
  77. CImpersonationData ImpersonationData;
  78. PCWSTR Slash = NULL;
  79. CSmartRef<ASSEMBLY> Asm;
  80. CStringBuffer buffManifestPath;
  81. USHORT ProcessorArchitecture = ::SxspGetSystemProcessorArchitecture();
  82. LANGID LangId = ::GetUserDefaultUILanguage();
  83. CStringBufferAccessor acc;
  84. SIZE_T cch, cchRequired;
  85. SIZE_T cbRequired, cbLeft, cbWritten;
  86. PCASSEMBLY_IDENTITY AssemblyIdentity = NULL;
  87. CStringBuffer buffShortName;
  88. PWSTR Cursor;
  89. PSXS_MANIFEST_INFORMATION_BASIC psmib;
  90. CResourceStream DllStream;
  91. CFileStream FileStream;
  92. IStream* pStream = NULL;
  93. CProbedAssemblyInformation AssemblyInformation;
  94. if (pcbWrittenOrRequired != NULL)
  95. *pcbWrittenOrRequired = 0;
  96. // We'll assume that SxsQueryManifestInformation checked everything
  97. // except dwInfoClassSpecificFlags.
  98. PARAMETER_CHECK((dwInfoClassSpecificFlags & ~(
  99. SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY |
  100. SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME)) == 0);
  101. //
  102. // If this is a DLL source, then ensure that the size is at least big enough for our basic
  103. // data, and ensure that the flags are zero (in this rev, that's all that's allowed.
  104. //
  105. if (dwFlags & SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL)
  106. {
  107. PCSXS_MANIFEST_INFORMATION_SOURCE_DLL pDllSource = (PCSXS_MANIFEST_INFORMATION_SOURCE_DLL)pszSource;
  108. const DWORD dwValidFlags =
  109. SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID |
  110. SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID |
  111. SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID;
  112. PARAMETER_CHECK(pDllSource->dwSize >= sizeof(SXS_MANIFEST_INFORMATION_SOURCE_DLL));
  113. PARAMETER_CHECK((pDllSource->dwFlags & ~dwValidFlags) == 0);
  114. PARAMETER_CHECK(pDllSource->pcwszDllPath!= NULL);
  115. PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID) == 0) || (pDllSource->Language != 0));
  116. PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID) == 0) || (pDllSource->pcwszResourceType != NULL));
  117. PARAMETER_CHECK(((pDllSource->dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID) == 0) || (pDllSource->pcwszResourceName != NULL));
  118. }
  119. IFW32FALSE_EXIT(
  120. ::SxspInitActCtxGenCtx(
  121. &ActCtxGenCtx, // context out
  122. MANIFEST_OPERATION_VALIDATE_SYNTAX,
  123. 0,
  124. 0,
  125. ImpersonationData,
  126. ProcessorArchitecture,
  127. LangId,
  128. ACTIVATION_CONTEXT_PATH_TYPE_NONE,
  129. 0,
  130. NULL));
  131. IFALLOCFAILED_EXIT(Asm = new ASSEMBLY);
  132. //
  133. // For DLL sources, tease apart the version and whatnot from the
  134. // structure passed in.
  135. //
  136. if (dwFlags & SXS_QUERY_MANIFEST_INFORMATION_FLAG_SOURCE_IS_DLL)
  137. {
  138. PCSXS_MANIFEST_INFORMATION_SOURCE_DLL pcSourceInfo = (PCSXS_MANIFEST_INFORMATION_SOURCE_DLL)pszSource;
  139. IFW32FALSE_EXIT(SxspGetFullPathName(pcSourceInfo->pcwszDllPath, buffManifestPath, NULL));
  140. //
  141. // Default action... just go use the normal "find the first in the dll" thing
  142. //
  143. if (pcSourceInfo->dwFlags == 0)
  144. {
  145. IFW32FALSE_EXIT(DllStream.Initialize(buffManifestPath, (PCWSTR)RT_MANIFEST));
  146. }
  147. else
  148. {
  149. const DWORD dwFlags = pcSourceInfo->dwFlags;
  150. IFW32FALSE_EXIT(
  151. DllStream.Initialize(
  152. buffManifestPath,
  153. ((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_TYPE_VALID) ? pcSourceInfo->pcwszResourceType : (PCWSTR)RT_MANIFEST),
  154. ((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_ID_VALID) ? pcSourceInfo->pcwszResourceName : NULL),
  155. ((dwFlags & SXS_QUERY_MANIFEST_INFORMATION_DLL_SOURCE_FLAG_RESOURCE_LANGUAGE_VALID) ? (WORD)pcSourceInfo->Language : (WORD)MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL))));
  156. }
  157. pStream = &DllStream;
  158. }
  159. //
  160. // Otherwise, dumb file.
  161. //
  162. else
  163. {
  164. IFW32FALSE_EXIT(SxspGetFullPathName(pszSource, buffManifestPath, NULL));
  165. IFW32FALSE_EXIT(
  166. FileStream.OpenForRead(
  167. buffManifestPath,
  168. CImpersonationData(),
  169. FILE_SHARE_READ,
  170. OPEN_EXISTING,
  171. FILE_ATTRIBUTE_NORMAL));
  172. pStream = &FileStream;
  173. }
  174. ManifestFlags = ASSEMBLY_MANIFEST_FILETYPE_STREAM;
  175. IFW32FALSE_EXIT(AssemblyInformation.Initialize());
  176. IFW32FALSE_EXIT(AssemblyInformation.SetManifestFlags(ManifestFlags));
  177. IFW32FALSE_EXIT(AssemblyInformation.SetManifestStream(pStream));
  178. IFW32FALSE_EXIT(AssemblyInformation.SetManifestPath(ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, buffManifestPath));
  179. IFW32FALSE_EXIT(AssemblyInformation.SetManifestLastWriteTime(&ActCtxGenCtx));
  180. IFW32FALSE_EXIT(::SxspInitAssembly(Asm, AssemblyInformation));
  181. Asm->m_AssemblyRosterIndex = 1; // set it to be the root...
  182. IFW32FALSE_EXIT(::SxspIncorporateAssembly(&ActCtxGenCtx, Asm));
  183. IFW32FALSE_EXIT(::SxspFireActCtxGenEnding(&ActCtxGenCtx));
  184. pStream->Release();
  185. AssemblyIdentity = Asm->m_Information.GetAssemblyIdentity();
  186. cchRequired = 0;
  187. if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY) == 0)
  188. {
  189. SIZE_T TextuallyEncodedIdentityBufferBytes = 0;
  190. IFW32FALSE_EXIT(
  191. ::SxsComputeAssemblyIdentityEncodedSize(
  192. 0,
  193. AssemblyIdentity,
  194. NULL,
  195. SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL,
  196. &TextuallyEncodedIdentityBufferBytes));
  197. INTERNAL_ERROR_CHECK((TextuallyEncodedIdentityBufferBytes % sizeof(WCHAR)) == 0);
  198. cchRequired += ((TextuallyEncodedIdentityBufferBytes / sizeof(WCHAR)) + 1);
  199. }
  200. if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME) == 0)
  201. {
  202. IFW32FALSE_EXIT(
  203. ::SxspGenerateSxsPath(
  204. SXSP_GENERATE_SXS_PATH_FLAG_OMIT_ROOT,
  205. SXSP_GENERATE_SXS_PATH_PATHTYPE_ASSEMBLY,
  206. NULL, 0,
  207. AssemblyIdentity,
  208. buffShortName));
  209. cchRequired += (buffShortName.Cch() + 1);
  210. }
  211. cbRequired = sizeof(SXS_MANIFEST_INFORMATION_BASIC) + (cchRequired * sizeof(WCHAR));
  212. if (cbRequired > cbBuffer)
  213. {
  214. *pcbWrittenOrRequired = cbRequired;
  215. ORIGINATE_WIN32_FAILURE_AND_EXIT(BufferTooSmall, ERROR_INSUFFICIENT_BUFFER);
  216. }
  217. psmib = (PSXS_MANIFEST_INFORMATION_BASIC) lpBuffer;
  218. psmib->lpIdentity = NULL;
  219. psmib->lpShortName = NULL;
  220. psmib->ulFileCount = ActCtxGenCtx.m_ulFileCount;
  221. Cursor = (PWSTR) (psmib + 1);
  222. cbLeft = (cbBuffer - sizeof(SXS_MANIFEST_INFORMATION_BASIC));
  223. cbWritten = sizeof(SXS_MANIFEST_INFORMATION_BASIC);
  224. if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_IDENTITY) == 0)
  225. {
  226. SIZE_T cbActual;
  227. IFW32FALSE_EXIT(
  228. ::SxsEncodeAssemblyIdentity(
  229. 0,
  230. AssemblyIdentity,
  231. NULL,
  232. SXS_ASSEMBLY_IDENTITY_ENCODING_DEFAULTGROUP_TEXTUAL,
  233. cbLeft,
  234. Cursor,
  235. &cbActual));
  236. INTERNAL_ERROR_CHECK((cbActual % sizeof(WCHAR)) == 0);
  237. INTERNAL_ERROR_CHECK(cbLeft >= cbActual);
  238. psmib->lpIdentity = Cursor;
  239. cbLeft -= cbActual;
  240. cbWritten += cbActual;
  241. Cursor = (PWSTR) (((ULONG_PTR) Cursor) + cbActual);
  242. INTERNAL_ERROR_CHECK(cbLeft >= sizeof(WCHAR));
  243. *Cursor++ = L'\0';
  244. cbLeft -= sizeof(WCHAR);
  245. cbWritten += sizeof(WCHAR);
  246. }
  247. if ((dwInfoClassSpecificFlags & SXS_QUERY_MANIFEST_INFORMATION_INFOCLASS_BASIC_FLAG_OMIT_SHORTNAME) == 0)
  248. {
  249. cch = buffShortName.Cch();
  250. INTERNAL_ERROR_CHECK(cbLeft >= ((cch + 1) * sizeof(WCHAR)));
  251. memcpy(Cursor, static_cast<PCWSTR>(buffShortName), (cch + 1) * sizeof(WCHAR));
  252. psmib->lpShortName = Cursor;
  253. cbLeft -= ((cch + 1) * sizeof(WCHAR));
  254. cbWritten += ((cch + 1) * sizeof(WCHAR));
  255. Cursor += (cch + 1);
  256. }
  257. if (pcbWrittenOrRequired != NULL)
  258. *pcbWrittenOrRequired = cbWritten;
  259. FN_EPILOG;
  260. }