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.

512 lines
17 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. sxsactctx.cpp
  5. Abstract:
  6. Implement SxsGenerateActivationContext, called from csrss.exe.
  7. Author:
  8. Michael J. Grier (MGrier)
  9. Revision History:
  10. Jay Krell (a-JayK, JayKrell) June 2000
  11. moved file opening from here (sxs.dll) to csrss.exe client process,
  12. pass ISequentialStreams to sxs.dll.
  13. Xiaoyu Wu (xiaoyuw) Nov 2001
  14. enable logfile for actctx gen
  15. --*/
  16. #include "stdinc.h"
  17. #include <windows.h>
  18. #include "sxsapi.h"
  19. #include "sxsp.h"
  20. #include "fusioneventlog.h"
  21. #include "filestream.h"
  22. #include "fusionprintf.h"
  23. // temporary dbprint reduction until we fix setup/comctl
  24. ULONG DbgPrintReduceLevel(ULONG FilterLevel)
  25. {
  26. if (FilterLevel != FUSION_DBG_LEVEL_ERROR)
  27. return FilterLevel;
  28. LONG Error = ::FusionpGetLastWin32Error();
  29. if (Error == ERROR_FILE_NOT_FOUND || Error == ERROR_PATH_NOT_FOUND)
  30. return FUSION_DBG_LEVEL_ENTEREXIT;
  31. return FilterLevel;
  32. }
  33. VOID
  34. DbgPrintSxsGenerateActivationContextParameters(
  35. ULONG FilterLevel,
  36. PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters,
  37. PCSTR Function
  38. )
  39. {
  40. FilterLevel = DbgPrintReduceLevel(FilterLevel);
  41. #if !DBG
  42. if (FilterLevel != FUSION_DBG_LEVEL_ERROR)
  43. return;
  44. #endif
  45. //
  46. // AssemblyDirectory deliberately not being printed
  47. // because it's garbage sometimes.
  48. //
  49. FusionpDbgPrintEx(
  50. FilterLevel,
  51. "SXS: %s() Input Parameters %p{\n"
  52. "SXS: Flags: 0x%lx\n"
  53. "SXS: ProcessorArchitecture: 0x%lx\n"
  54. "SXS: LangId: 0x%lx\n"
  55. "SXS: TextualIdentity: %ls\n"
  56. "SXS: Manifest: { %p, %ls }\n"
  57. "SXS: Policy: { %p, %ls }\n"
  58. "SXS: }\n",
  59. Function,
  60. Parameters,
  61. (Parameters != NULL) ? ULONG(Parameters->Flags) : 0,
  62. (Parameters != NULL) ? ULONG(Parameters->ProcessorArchitecture) : NULL,
  63. (Parameters != NULL) ? ULONG(Parameters->LangId) : NULL,
  64. (Parameters != NULL) ? Parameters->TextualAssemblyIdentity : NULL,
  65. (Parameters != NULL) ? Parameters->Manifest.Stream : NULL,
  66. (Parameters != NULL) ? Parameters->Manifest.Path : NULL,
  67. (Parameters != NULL) ? Parameters->Policy.Stream : NULL,
  68. (Parameters != NULL) ? Parameters->Policy.Path : NULL);
  69. }
  70. #define IF_FUSION_LOG_ACTCTX 0 && defined(_X86_)
  71. #if IF_FUSION_LOG_ACTCTX_ACTION
  72. extern HANDLE g_hActCtxLog;
  73. __inline
  74. ULONGLONG
  75. GetCycleCount(void)
  76. {
  77. __asm
  78. {
  79. RDTSC
  80. }
  81. }
  82. BOOL
  83. SxspWriteUnicodeStringToFileAsAnsi(
  84. HANDLE hFile, // handle to file
  85. PCWSTR pszBuffer, // data buffer
  86. DWORD dwCchBuffer, // number of unicode characters to write
  87. LPDWORD pdwWritten // number of bytes written
  88. )
  89. {
  90. BOOL bRet = FALSE;
  91. PSTR pszAnsiStr = NULL;
  92. int nErr = 0;
  93. if (pdwWritten == NULL)
  94. {
  95. ::SetLastError(ERROR_INVALID_PARAMETER); // should never happen
  96. return FALSE;
  97. }
  98. if (dwCchBuffer == 0)
  99. return TRUE;
  100. pszAnsiStr = reinterpret_cast<PSTR>(malloc(dwCchBuffer * 2 + 1));
  101. if (pszAnsiStr == NULL)
  102. {
  103. FusionpSetLastWin32Error(FUSION_WIN32_ALLOCFAILED_ERROR);
  104. goto Exit;
  105. }
  106. nErr = WideCharToMultiByte(CP_ACP,
  107. WC_COMPOSITECHECK,
  108. pszBuffer,
  109. dwCchBuffer,
  110. pszAnsiStr,
  111. dwCchBuffer,
  112. NULL,
  113. NULL );
  114. if (nErr == 0)
  115. goto Exit;
  116. bRet = WriteFile( hFile,
  117. pszAnsiStr,
  118. dwCchBuffer,
  119. pdwWritten,
  120. NULL);
  121. if (!bRet)
  122. {
  123. goto Exit;
  124. }
  125. bRet = TRUE;
  126. Exit:
  127. if (pszAnsiStr != NULL)
  128. {
  129. CSxsPreserveLastError ple;
  130. free(pszAnsiStr);
  131. ple.Restore();
  132. }
  133. return bRet;
  134. }
  135. VOID
  136. SxspLogActCtxAction(ULONGLONG & ts, PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters)
  137. {
  138. if ((g_hActCtxLog == INVALID_HANDLE_VALUE) || (!::FusionpDbgWouldPrintAtFilterLevel(FUSION_DBG_LEVEL_LOG_ACTCTX)))
  139. {
  140. ts = 0;
  141. return;
  142. }
  143. ULONGLONG cts = GetCycleCount() - ts;
  144. CStringBuffer sbLogText;
  145. SYSTEMTIME st;
  146. GetSystemTime(&st);
  147. if (!sbLogText.Win32Format(L"%4d.%02d.%02d-%#08x%08x, ",
  148. st.wYear, st.wMonth, st.wDay,
  149. (ULONG)(ts >> 32), (ULONG)(ts & 0x00000000FFFFFFFF)))
  150. {
  151. goto Exit;
  152. }
  153. #define SB_APPEND(sb, x) do \
  154. { if ((x) != NULL && (x)[0] != L'\0') \
  155. { \
  156. if (sb.Win32Append(x, wcslen(x)) == FALSE) \
  157. goto Exit; \
  158. } \
  159. } while (0)
  160. SB_APPEND(sbLogText, (Parameters != NULL) ? Parameters->AssemblyDirectory : L"NULL");
  161. SB_APPEND(sbLogText, L", ");
  162. SB_APPEND(sbLogText, (Parameters != NULL) ? Parameters->Manifest.Path) : L"NULL");
  163. SB_APPEND(sbLogText, L", ");
  164. SB_APPEND(sbLogText, (Parameters != NULL) ? Parameters->TextualAssemblyIdentity : L"NULL");
  165. SB_APPEND(sbLogText, L", ");
  166. SB_APPEND(sbLogText, (Parameters != NULL) ? Parameters->Policy.Path : L"NULL");
  167. SB_APPEND(sbLogText, L", ");
  168. HANDLE ActCtxSection = (HANDLE)(Parameters->SectionObjectHandle);
  169. if (ActCtxSection == NULL || ActCtxSection == INVALID_HANDLE_VALUE)
  170. {
  171. SB_APPEND(sbLogText, L"FAILED, ");
  172. WCHAR buf[sizeof(ULONG) * 8 + 1];
  173. FusionpFormatStringW(buf, NUMBER_OF(buf), L"%#08x", ::GetLastError());
  174. SB_APPEND(sbLogText, buf);
  175. }
  176. else
  177. {
  178. //
  179. // set status
  180. //
  181. SB_APPEND(sbLogText, L"SUCCESS, ");
  182. //
  183. // set ActCtx Size
  184. //
  185. PACTIVATION_CONTEXT_DATA ActCtxData = (PACTIVATION_CONTEXT_DATA )MapViewOfFile(ActCtxSection, FILE_MAP_READ, 0, 0, 0);
  186. WCHAR buf[sizeof(ULONG) * 8 + 1];
  187. FusionpFormatStringW(buf, NUMBER_OF(buf), L"%#08x, ", ActCtxData->TotalSize);
  188. SB_APPEND(sbLogText, buf);
  189. //
  190. // set time cost
  191. //
  192. FusionpFormatStringW(buf, NUMBER_OF(buf), L"%#08x, ", (ULONG)(cts & 0x00000000FFFFFFFF));
  193. SB_APPEND(sbLogText, buf);
  194. //
  195. // set gen rate
  196. //
  197. FusionpFormatStringW(buf, NUMBER_OF(buf), L"%#08x", cts / ActCtxData->TotalSize);
  198. SB_APPEND(sbLogText, buf);
  199. UnmapViewOfFile((LPVOID)ActCtxData);
  200. }
  201. SB_APPEND(sbLogText, L";\n");
  202. DWORD dwBytesWritten;
  203. if (!SxspWriteUnicodeStringToFileAsAnsi(g_hActCtxLog, sbLogText, sbLogText.GetCchAsDWORD(), &dwBytesWritten))
  204. {
  205. ::FusionpDbgPrintEx(
  206. FUSION_DBG_LEVEL_ERROR,
  207. "SXS: Logging actctx failed. Data string: %S\n",
  208. sbLogText);
  209. }
  210. Exit:
  211. #undef SB_APPEND
  212. return;
  213. }
  214. #endif /* IF_FUSION_LOG_ACTCTX_ACTION */
  215. extern "C"
  216. BOOL
  217. WINAPI
  218. SxsGenerateActivationContext(
  219. PSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters
  220. )
  221. {
  222. #if IF_FUSION_LOG_ACTCTX_ACTION
  223. ULONGLONG ts = GetCycleCount();
  224. #endif
  225. BOOL fSuccess = FALSE;
  226. FN_TRACE_WIN32(fSuccess);
  227. RTL_PATH_TYPE PathType = static_cast<RTL_PATH_TYPE>(0);
  228. BOOL fSxspCloseManifestGraph = FALSE;
  229. CSmartPtr<CFileStream> SystemDefaultManifestFileStream;
  230. ACTCTXGENCTX *pActCtxGenCtx = NULL;
  231. DWORD dwWin32Error = 0;
  232. #define IS_NT_DOS_PATH(_x) (((_x)[0] == L'\\') && ((_x)[1] == L'?') && ((_x)[2] == L'?') && ((_x)[3] == L'\\'))
  233. ::DbgPrintSxsGenerateActivationContextParameters(
  234. FUSION_DBG_LEVEL_ENTEREXIT,
  235. Parameters,
  236. __FUNCTION__);
  237. if (Parameters != NULL)
  238. {
  239. Parameters->SystemDefaultActCxtGenerationResult = NO_ERROR;
  240. Parameters->SectionObjectHandle = NULL;
  241. }
  242. PARAMETER_CHECK(Parameters != NULL);
  243. IFINVALID_FLAGS_EXIT_WIN32(Parameters->Flags,
  244. SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY |
  245. SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY |
  246. SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_APP_RUNNING_IN_SAFEMODE);
  247. PARAMETER_CHECK(Parameters->AssemblyDirectory != NULL);
  248. if (Parameters->Flags &
  249. (SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY
  250. | SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY))
  251. {
  252. PARAMETER_CHECK(Parameters->TextualAssemblyIdentity != NULL);
  253. PARAMETER_CHECK(Parameters->Manifest.Stream == NULL);
  254. PARAMETER_CHECK(Parameters->Policy.Stream == NULL);
  255. }
  256. else
  257. {
  258. PARAMETER_CHECK(Parameters->Manifest.Stream != NULL);
  259. }
  260. ASSERT(!IS_NT_DOS_PATH(Parameters->AssemblyDirectory));
  261. if (Parameters->Manifest.Path != NULL)
  262. ASSERT(!IS_NT_DOS_PATH(Parameters->Manifest.Path));
  263. if (Parameters->Policy.Path != NULL)
  264. ASSERT(!IS_NT_DOS_PATH(Parameters->Policy.Path));
  265. PathType = ::SxspDetermineDosPathNameType(Parameters->AssemblyDirectory);
  266. PARAMETER_CHECK((PathType == RtlPathTypeUncAbsolute) ||
  267. (PathType == RtlPathTypeLocalDevice) ||
  268. (PathType == RtlPathTypeDriveAbsolute) ||
  269. (PathType == RtlPathTypeDriveRelative));
  270. // Fast out if there was not actually any manifest.
  271. if ((Parameters->Flags &
  272. (SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY |
  273. SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY)) == 0)
  274. {
  275. if (Parameters->Manifest.Stream == NULL)
  276. {
  277. // No stream means no activation context.
  278. FN_SUCCESSFUL_EXIT();
  279. }
  280. else
  281. {
  282. STATSTG statstg;
  283. IFCOMFAILED_EXIT(Parameters->Manifest.Stream->Stat(&statstg, STATFLAG_NONAME));
  284. if (statstg.cbSize.QuadPart <= 4)
  285. {
  286. FN_SUCCESSFUL_EXIT();
  287. }
  288. }
  289. }
  290. IFALLOCFAILED_EXIT(pActCtxGenCtx = new ACTCTXGENCTX);
  291. CStringBuffer &sbAssemblyDirectory = pActCtxGenCtx->SxsGenerateActivationContextLocals.sbAssemblyDirectory;
  292. // rarely used, mainly for system compatible assembly
  293. CSmallStringBuffer &sbManifestFileName = pActCtxGenCtx->SxsGenerateActivationContextLocals.sbManifestFileName;
  294. {
  295. CImpersonationData ImpersonationData(Parameters->ImpersonationCallback, Parameters->ImpersonationContext);
  296. Parameters->SectionObjectHandle = NULL;
  297. if (Parameters->Flags &
  298. (SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_TEXTUAL_ASSEMBLY_IDENTITY
  299. | SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY))
  300. {
  301. //
  302. // If basesrv passes in a textual assembly identity, we have to create stream for manifest from here !
  303. //
  304. BOOL fOpenManifestFailed = FALSE;
  305. IFW32FALSE_EXIT(sbAssemblyDirectory.Win32Assign(Parameters->AssemblyDirectory, ::wcslen(Parameters->AssemblyDirectory)));
  306. IFW32FALSE_EXIT(::SxspCreateManifestFileNameFromTextualString(
  307. 0,
  308. SXSP_GENERATE_SXS_PATH_PATHTYPE_MANIFEST,
  309. sbAssemblyDirectory,
  310. Parameters->TextualAssemblyIdentity,
  311. sbManifestFileName));
  312. IFW32FALSE_EXIT(SystemDefaultManifestFileStream.Win32Allocate(__FILE__, __LINE__));
  313. IFW32FALSE_EXIT(SystemDefaultManifestFileStream->OpenForRead(
  314. sbManifestFileName,
  315. CImpersonationData(),FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, // default value for parameters
  316. dwWin32Error,
  317. 4,
  318. ERROR_FILE_NOT_FOUND,
  319. ERROR_PATH_NOT_FOUND,
  320. ERROR_BAD_NETPATH,
  321. ERROR_BAD_NET_NAME));
  322. if (dwWin32Error != ERROR_SUCCESS)
  323. {
  324. Parameters->SystemDefaultActCxtGenerationResult = BASESRV_SXS_RETURN_RESULT_SYSTEM_DEFAULT_NOT_FOUND;
  325. FN_SUCCESSFUL_EXIT();
  326. }
  327. if (Parameters->Manifest.Path == NULL)
  328. Parameters->Manifest.Path = sbManifestFileName;
  329. Parameters->Manifest.Stream = SystemDefaultManifestFileStream;
  330. }
  331. // Ensure that there's a trailing slash...
  332. IFW32FALSE_EXIT(sbAssemblyDirectory.Win32Assign(Parameters->AssemblyDirectory, ::wcslen(Parameters->AssemblyDirectory)));
  333. IFW32FALSE_EXIT(sbAssemblyDirectory.Win32EnsureTrailingPathSeparator());
  334. Parameters->AssemblyDirectory = sbAssemblyDirectory;
  335. DWORD dwFlags = 0;
  336. if (Parameters->Flags & SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY)
  337. dwFlags |= SXS_GENERATE_ACTCTX_SYSTEM_DEFAULT;
  338. if(Parameters->Flags & SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_APP_RUNNING_IN_SAFEMODE)
  339. {
  340. ASSERT(dwFlags == 0);
  341. dwFlags |= SXS_GENERATE_ACTCTX_APP_RUNNING_IN_SAFEMODE;
  342. }
  343. // Allocate and initialize the activation context generation context
  344. IFW32FALSE_EXIT(
  345. ::SxspInitActCtxGenCtx(
  346. pActCtxGenCtx, // context out
  347. MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT,
  348. dwFlags,
  349. 0, // operation-specific flags
  350. ImpersonationData,
  351. Parameters->ProcessorArchitecture,
  352. Parameters->LangId,
  353. ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE,
  354. ::wcslen(Parameters->AssemblyDirectory),
  355. Parameters->AssemblyDirectory));
  356. if (Parameters->Policy.Stream != NULL)
  357. {
  358. SIZE_T cchPolicyPath = (Parameters->Policy.Path != NULL) ? ::wcslen(Parameters->Policy.Path): 0;
  359. // Do the policy thing...
  360. IFW32FALSE_EXIT(
  361. ::SxspParseApplicationPolicy(
  362. 0,
  363. pActCtxGenCtx,
  364. ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE,
  365. Parameters->Policy.Path,
  366. cchPolicyPath,
  367. Parameters->Policy.Stream));
  368. }
  369. // Add this manifest (and its policy file) to the context
  370. IFW32FALSE_EXIT(
  371. ::SxspAddRootManifestToActCtxGenCtx(
  372. pActCtxGenCtx,
  373. Parameters));
  374. // Add its dependencies, and their dependencies, etc. until there's nothing more to add
  375. IFW32FALSE_EXIT_UNLESS(
  376. ::SxspCloseManifestGraph(pActCtxGenCtx),
  377. ((Parameters->Flags & SXS_GENERATE_ACTIVATION_CONTEXT_FLAG_SYSTEM_DEFAULT_TEXTUAL_ASSEMBLY_IDENTITY) && (::FusionpGetLastWin32Error() == ERROR_SXS_ROOT_MANIFEST_DEPENDENCY_NOT_INSTALLED)),
  378. fSxspCloseManifestGraph);
  379. if (fSxspCloseManifestGraph)
  380. {
  381. Parameters->SystemDefaultActCxtGenerationResult |= BASESRV_SXS_RETURN_RESULT_SYSTEM_DEFAULT_DEPENDENCY_ASSEMBLY_NOT_FOUND;
  382. fSuccess = TRUE;
  383. goto Exit;
  384. }
  385. // Build the activation context data blob.
  386. IFW32FALSE_EXIT(::SxspBuildActCtxData(pActCtxGenCtx, &Parameters->SectionObjectHandle));
  387. fSuccess = TRUE;
  388. }
  389. Exit:
  390. #if IF_FUSION_LOG_ACTCTX_ACTION
  391. SxspLogActCtxAction(ts, Parameters);
  392. #endif // defined(_X86_)
  393. #undef IS_NT_DOS_PATH
  394. // for system default stream,
  395. if (Parameters->Manifest.Stream == SystemDefaultManifestFileStream)
  396. Parameters->Manifest.Stream = NULL;
  397. if (pActCtxGenCtx)
  398. FUSION_DELETE_SINGLETON(pActCtxGenCtx);
  399. if (!fSuccess) // put a win32-error-message into eventlog
  400. {
  401. CSxsPreserveLastError ple;
  402. #if !DBG
  403. BOOL fAreWeInOSSetupMode = FALSE;
  404. //
  405. // If we can't determine this, then let the first error through.
  406. //
  407. if (!::FusionpAreWeInOSSetupMode(&fAreWeInOSSetupMode) || !fAreWeInOSSetupMode)
  408. #endif
  409. {
  410. ::FusionpLogError(
  411. MSG_SXS_FUNCTION_CALL_FAIL,
  412. CEventLogString(L"Generate Activation Context"),
  413. (Parameters->Manifest.Path != NULL) ? CEventLogString(static_cast<PCWSTR>(Parameters->Manifest.Path)) : CEventLogString(L"Manifest Filename Unknown"),
  414. CEventLogLastError(ple.LastError()));
  415. #if DBG
  416. ::DbgPrintSxsGenerateActivationContextParameters(
  417. FUSION_DBG_LEVEL_ERROR,
  418. Parameters,
  419. __FUNCTION__);
  420. #endif
  421. }
  422. ple.Restore();
  423. }
  424. return fSuccess;
  425. }