2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/client/actctx.c
5 * PURPOSE: Activation contexts - NT-compatible helpers
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
8 * NOTE: See also kernel32/wine/actctx.c
11 /* INCLUDES ******************************************************************/
17 #define QUERY_ACTCTX_FLAG_VALID (QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX | \
18 QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE | \
19 QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS | \
20 QUERY_ACTCTX_FLAG_NO_ADDREF)
22 /* PRIVATE FUNCTIONS *********************************************************/
26 BasepFreeActivationContextActivationBlock(IN PBASEP_ACTCTX_BLOCK ActivationBlock
)
28 /* Exit if there was nothing passed in */
29 if (!ActivationBlock
) return;
31 /* Do we have a context? */
32 if (ActivationBlock
->ActivationContext
)
34 /* Release and clear it */
35 RtlReleaseActivationContext(ActivationBlock
->ActivationContext
);
36 ActivationBlock
->ActivationContext
= NULL
;
40 RtlFreeHeap(RtlGetProcessHeap(), 0, ActivationBlock
);
45 BasepAllocateActivationContextActivationBlock(IN DWORD Flags
,
46 IN PVOID CompletionRoutine
,
47 IN PVOID CompletionContext
,
48 OUT PBASEP_ACTCTX_BLOCK
*ActivationBlock
)
51 ACTIVATION_CONTEXT_BASIC_INFORMATION ContextInfo
;
53 /* Clear the info structure */
54 ContextInfo
.dwFlags
= 0;
55 ContextInfo
.hActCtx
= NULL
;
58 if (ActivationBlock
) *ActivationBlock
= NULL
;
60 /* Only support valid flags */
61 if (Flags
& ~(1 | 2)) // FIXME: What are they? 2 looks like BASEP_ACTCTX_FORCE_BLOCK
63 /* Fail if unknown flags are passed in */
64 Status
= STATUS_INVALID_PARAMETER_1
;
68 /* Caller should have passed in an activation block */
72 Status
= STATUS_INVALID_PARAMETER_4
;
76 /* Query RTL for information on the current activation context */
77 Status
= RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
,
80 ActivationContextBasicInformation
,
84 if (!NT_SUCCESS(Status
))
86 /* Failed -- bail out */
87 DPRINT1("SXS: %s - Failure getting active activation context; ntstatus %08lx\n",
88 __FUNCTION__
, Status
);
92 /* Check if the current one should be freed */
93 if (ContextInfo
.dwFlags
& 1)
95 /* Release and clear it */
96 RtlReleaseActivationContext(ContextInfo
.hActCtx
);
97 ContextInfo
.hActCtx
= NULL
;
100 /* Check if there's an active context, or if the caller is forcing one */
101 if (!(Flags
& 2) || (ContextInfo
.hActCtx
))
103 /* Allocate the block */
104 *ActivationBlock
= RtlAllocateHeap(RtlGetProcessHeap(),
106 sizeof(BASEP_ACTCTX_BLOCK
));
107 if (!(*ActivationBlock
))
109 /* Ran out of memory, fail */
110 Status
= STATUS_NO_MEMORY
;
115 (*ActivationBlock
)->ActivationContext
= ContextInfo
.hActCtx
;
116 (*ActivationBlock
)->Flags
= 0;
117 if (Flags
& 1) (*ActivationBlock
)->Flags
|= 1; // Not sure about this flag
118 (*ActivationBlock
)->CompletionRoutine
= CompletionRoutine
;
119 (*ActivationBlock
)->CompletionContext
= CompletionContext
;
121 /* Tell Quickie below not to free anything, since this is success */
122 ContextInfo
.hActCtx
= NULL
;
125 /* Set success status */
126 Status
= STATUS_SUCCESS
;
129 /* Failure or success path, return to caller and free on failure */
130 if (ContextInfo
.hActCtx
) RtlReleaseActivationContext(ContextInfo
.hActCtx
);
136 BasepProbeForDllManifest(IN PVOID DllHandle
,
137 IN PCWSTR FullDllName
,
140 NTSTATUS Status
= STATUS_SUCCESS
;
141 LDR_RESOURCE_INFO Info
;
142 IMAGE_RESOURCE_DATA_ENTRY
*Entry
;
146 /* Check if activation context parameter is provided */
150 return STATUS_INVALID_PARAMETER
;
156 /* Check whether the image has manifest resource associated with it */
157 Info
.Type
= (ULONG
)RT_MANIFEST
;
158 Info
.Name
= (ULONG
)ISOLATIONAWARE_MANIFEST_RESOURCE_ID
;
160 if (!(Status
= LdrFindResource_U(DllHandle
, &Info
, 3, &Entry
)))
162 /* Create the activation context */
163 Context
.cbSize
= sizeof(Context
);
164 Context
.lpSource
= FullDllName
;
165 Context
.dwFlags
= ACTCTX_FLAG_RESOURCE_NAME_VALID
| ACTCTX_FLAG_HMODULE_VALID
;
166 Context
.hModule
= DllHandle
;
167 Context
.lpResourceName
= (LPCWSTR
)ISOLATIONAWARE_MANIFEST_RESOURCE_ID
;
169 Status
= RtlCreateActivationContext(0, (PVOID
)&Context
, 0, NULL
, NULL
, &Result
);
171 /* Store activation context pointer if it was created successfully */
172 if (NT_SUCCESS(Status
)) *ActCtx
= Result
;
174 /* CORE-10843: Windows always returns this since we pass the wrong struct */
175 if (Status
== STATUS_SXS_INVALID_ACTCTXDATA_FORMAT
)
177 /* Fake "Manifest not found" so the load doesn't fail */
181 DPRINT1("HACK: Passed invalid ACTIVATION_CONTEXT_DATA!\n");
183 Status
= STATUS_RESOURCE_DATA_NOT_FOUND
;
190 /* PUBLIC FUNCTIONS **********************************************************/
197 AddRefActCtx(IN HANDLE hActCtx
)
199 /* Call the native API */
200 RtlAddRefActivationContext(hActCtx
);
208 ReleaseActCtx(IN HANDLE hActCtx
)
210 /* Call the native API */
211 RtlReleaseActivationContext(hActCtx
);
219 ZombifyActCtx(HANDLE hActCtx
)
223 /* Call the native API */
224 Status
= RtlZombifyActivationContext(hActCtx
);
225 if (NT_SUCCESS(Status
)) return TRUE
;
227 /* Set last error if we failed */
228 BaseSetLastNTError(Status
);
237 ActivateActCtx(IN HANDLE hActCtx
,
238 OUT PULONG_PTR ulCookie
)
242 /* Check if the handle was invalid */
243 if (hActCtx
== INVALID_HANDLE_VALUE
)
245 /* Set error and bail out */
246 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
250 /* Call the native API */
251 Status
= RtlActivateActivationContext(0, hActCtx
, ulCookie
);
252 if (!NT_SUCCESS(Status
))
254 /* Set error and bail out */
255 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
268 DeactivateActCtx(IN DWORD dwFlags
,
269 IN ULONG_PTR ulCookie
)
273 /* Check if the flags are invalid */
274 if ((dwFlags
& ~DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
) != 0)
276 /* Set error and bail out */
277 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
283 if (dwFlags
& DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION
)
285 NativeFlags
= RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION
;
288 /* Call the native API -- it can never fail */
289 RtlDeactivateActivationContext(NativeFlags
, ulCookie
);
298 GetCurrentActCtx(OUT PHANDLE phActCtx
)
302 /* Check if the output handle pointer was invalid */
303 if (phActCtx
== NULL
)
305 /* Set error and bail out */
306 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
310 /* Call the native API */
311 Status
= RtlGetActiveActivationContext(phActCtx
);
312 if (!NT_SUCCESS(Status
))
314 /* Set error and bail out */
315 BaseSetLastNTError(STATUS_INVALID_PARAMETER
);
328 QueryActCtxW(IN DWORD dwFlags
,
330 IN PVOID pvSubInstance
,
331 IN ULONG ulInfoClass
,
334 IN OUT SIZE_T
*pcbWrittenOrRequired OPTIONAL
)
336 ULONG NativeFlags
= 0;
340 if (pcbWrittenOrRequired
) *pcbWrittenOrRequired
= 0;
342 /* Check if native flags were passed in to the Win32 function */
345 case RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
:
346 dwFlags
|= QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
;
348 case RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
:
349 dwFlags
|= QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
;
351 case (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
- 1): // Yep, not sure why
352 dwFlags
|= QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
;
356 /* Now mask out the native flags */
359 /* Check if any invalid flags are left */
360 if (dwFlags
& ~QUERY_ACTCTX_FLAG_VALID
)
363 DPRINT1("SXS: %s() bad flags(passed: 0x%lx, allowed: 0x%lx, bad: 0x%lx)\n",
366 QUERY_ACTCTX_FLAG_VALID
,
367 dwFlags
& ~QUERY_ACTCTX_FLAG_VALID
);
368 BaseSetLastNTError(STATUS_INVALID_PARAMETER_1
);
372 /* See if additional parameters are required */
375 case ActivationContextBasicInformation
:
376 case ActivationContextDetailedInformation
:
378 /* Nothing to check */
381 case AssemblyDetailedInformationInActivationContext
:
382 case FileInformationInAssemblyOfAssemblyInActivationContext
:
384 /* We need a subinstance for these queries*/
387 /* None present, bail out */
388 DPRINT1("SXS: %s() InfoClass 0x%lx requires SubInstance != NULL\n",
391 BaseSetLastNTError(STATUS_INVALID_PARAMETER_3
);
398 /* Invalid class, bail out */
399 DPRINT1("SXS: %s() bad InfoClass(0x%lx)\n",
402 BaseSetLastNTError(STATUS_INVALID_PARAMETER_2
);
406 /* Check if no buffer was passed in*/
409 /* But a non-zero length was? */
412 /* This is bogus... */
413 DPRINT1("SXS: %s() (pvBuffer == NULL) && ((cbBuffer=0x%lu) != 0)\n",
416 BaseSetLastNTError(STATUS_INVALID_PARAMETER_4
);
420 /* But the caller doesn't want to know how big to make it? */
421 if (!pcbWrittenOrRequired
)
424 DPRINT1("SXS: %s() (pvBuffer == NULL) && (pcbWrittenOrRequired == NULL)\n",
426 BaseSetLastNTError(STATUS_INVALID_PARAMETER_5
);
431 /* These 3 flags are mutually exclusive -- only one should be present */
432 switch (dwFlags
& (QUERY_ACTCTX_FLAG_VALID
& ~QUERY_ACTCTX_FLAG_NO_ADDREF
))
434 /* Convert into native format */
435 case QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX
:
436 NativeFlags
= RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT
;
438 case QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE
:
439 NativeFlags
= RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE
;
441 case QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS
:
442 NativeFlags
= RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS
;
447 /* More than one flag is set... */
450 DPRINT1("SXS: %s(dwFlags=0x%lx) more than one flag in 0x%lx was passed\n",
454 BaseSetLastNTError(STATUS_INVALID_PARAMETER_1
);
458 /* Convert this last flag */
459 if (dwFlags
& QUERY_ACTCTX_FLAG_NO_ADDREF
)
461 NativeFlags
|= RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF
;
464 /* Now call the native API */
465 DPRINT("SXS: %s() Calling Native API with Native Flags %lx for Win32 Flags %lx\n",
469 Status
= RtlQueryInformationActivationContext(NativeFlags
,
475 pcbWrittenOrRequired
);
476 if (NT_SUCCESS(Status
)) return TRUE
;
478 /* Failed, set error and return */
479 BaseSetLastNTError(Status
);