[KERNEL32/NTDLL]: Fix definition of RtlCreateActivationContext (although the code...
[reactos.git] / reactos / lib / rtl / actctx.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Runtime Library
4 * PURPOSE: Activation Context Support
5 * FILE: lib/rtl/actctx.c
6 * PROGRAMERS:
7 * Jon Griffiths
8 * Eric Pouech
9 * Jacek Caban for CodeWeavers
10 * Alexandre Julliard
11 * Stefan Ginsberg (stefan__100__@hotmail.com)
12 * Samuel SerapiĆ³n
13 */
14
15 /* Based on Wine 1.1.26 */
16
17 /* INCLUDES *****************************************************************/
18 #include <rtl.h>
19
20 #define NDEBUG
21 #include <debug.h>
22
23 #include <wine/unicode.h>
24
25 BOOLEAN RtlpNotAllowingMultipleActivation;
26
27 #define ACTCTX_FLAGS_ALL (\
28 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
29 ACTCTX_FLAG_LANGID_VALID |\
30 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
31 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
32 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
33 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
34 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
35 ACTCTX_FLAG_HMODULE_VALID )
36
37 #define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
38
39 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
40 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
41
42
43
44 typedef struct
45 {
46 const WCHAR *ptr;
47 unsigned int len;
48 } xmlstr_t;
49
50 typedef struct
51 {
52 const WCHAR *ptr;
53 const WCHAR *end;
54 } xmlbuf_t;
55
56 struct file_info
57 {
58 ULONG type;
59 WCHAR *info;
60 };
61
62 struct assembly_version
63 {
64 USHORT major;
65 USHORT minor;
66 USHORT build;
67 USHORT revision;
68 };
69
70 struct assembly_identity
71 {
72 WCHAR *name;
73 WCHAR *arch;
74 WCHAR *public_key;
75 WCHAR *language;
76 WCHAR *type;
77 struct assembly_version version;
78 BOOL optional;
79 };
80
81 struct entity
82 {
83 DWORD kind;
84 union
85 {
86 struct
87 {
88 WCHAR *tlbid;
89 WCHAR *version;
90 WCHAR *helpdir;
91 } typelib;
92 struct
93 {
94 WCHAR *clsid;
95 } comclass;
96 struct {
97 WCHAR *iid;
98 WCHAR *name;
99 } proxy;
100 struct
101 {
102 WCHAR *name;
103 } class;
104 struct
105 {
106 WCHAR *name;
107 WCHAR *clsid;
108 } clrclass;
109 struct
110 {
111 WCHAR *name;
112 WCHAR *clsid;
113 } clrsurrogate;
114 } u;
115 };
116
117 struct entity_array
118 {
119 struct entity *base;
120 unsigned int num;
121 unsigned int allocated;
122 };
123
124 struct dll_redirect
125 {
126 WCHAR *name;
127 WCHAR *hash;
128 struct entity_array entities;
129 };
130
131 enum assembly_type
132 {
133 APPLICATION_MANIFEST,
134 ASSEMBLY_MANIFEST,
135 ASSEMBLY_SHARED_MANIFEST,
136 };
137
138 struct assembly
139 {
140 enum assembly_type type;
141 struct assembly_identity id;
142 struct file_info manifest;
143 WCHAR *directory;
144 BOOL no_inherit;
145 struct dll_redirect *dlls;
146 unsigned int num_dlls;
147 unsigned int allocated_dlls;
148 struct entity_array entities;
149 };
150
151 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
152 {
153 ULONG Flags;
154 UNICODE_STRING DosPath;
155 HANDLE Handle;
156 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY;
157
158 typedef struct _ASSEMBLY_STORAGE_MAP
159 {
160 ULONG Flags;
161 ULONG AssemblyCount;
162 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray;
163 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP;
164
165 typedef struct _ACTIVATION_CONTEXT
166 {
167 LONG RefCount;
168 ULONG Flags;
169 LIST_ENTRY Links;
170 PACTIVATION_CONTEXT_DATA ActivationContextData;
171 PVOID NotificationRoutine;
172 PVOID NotificationContext;
173 ULONG SentNotifications[8];
174 ULONG DisabledNotifications[8];
175 ASSEMBLY_STORAGE_MAP StorageMap;
176 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries;
177 ULONG StackTraceIndex;
178 PVOID StackTraces[4][4];
179 struct file_info config;
180 struct file_info appdir;
181 struct assembly *assemblies;
182 unsigned int num_assemblies;
183 unsigned int allocated_assemblies;
184 } ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
185
186 struct actctx_loader
187 {
188 ACTIVATION_CONTEXT *actctx;
189 struct assembly_identity *dependencies;
190 unsigned int num_dependencies;
191 unsigned int allocated_dependencies;
192 };
193
194 typedef struct _ACTIVATION_CONTEXT_WRAPPED
195 {
196 PVOID MagicMarker;
197 ACTIVATION_CONTEXT ActivationContext;
198 } ACTIVATION_CONTEXT_WRAPPED, *PACTIVATION_CONTEXT_WRAPPED;
199
200 VOID
201 NTAPI
202 RtlpSxsBreakOnInvalidMarker(IN PACTIVATION_CONTEXT ActCtx,
203 IN ULONG FailureCode)
204 {
205 EXCEPTION_RECORD ExceptionRecord;
206
207 /* Fatal SxS exception header */
208 ExceptionRecord.ExceptionRecord = NULL;
209 ExceptionRecord.ExceptionCode = STATUS_SXS_CORRUPTION;
210 ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
211
212 /* With SxS-specific information plus the context itself */
213 ExceptionRecord.ExceptionInformation[0] = 1;
214 ExceptionRecord.ExceptionInformation[1] = FailureCode;
215 ExceptionRecord.ExceptionInformation[2] = (ULONG_PTR)ActCtx;
216 ExceptionRecord.NumberParameters = 3;
217
218 /* Raise it */
219 RtlRaiseException(&ExceptionRecord);
220 }
221
222 FORCEINLINE
223 VOID
224 RtlpValidateActCtx(IN PACTIVATION_CONTEXT ActCtx)
225 {
226 PACTIVATION_CONTEXT_WRAPPED pActual;
227
228 /* Get the caller-opaque header */
229 pActual = CONTAINING_RECORD(ActCtx,
230 ACTIVATION_CONTEXT_WRAPPED,
231 ActivationContext);
232
233 /* Check if the header matches as expected */
234 if (pActual->MagicMarker != ACTCTX_MAGIC_MARKER)
235 {
236 /* Nope, print out a warning, assert, and then throw an exception */
237 DbgPrint("%s : Invalid activation context marker %p found in activation context %p\n"
238 " This means someone stepped on the allocation, or someone is using a\n"
239 " deallocated activation context\n",
240 __FUNCTION__,
241 pActual->MagicMarker,
242 ActCtx);
243 ASSERT(pActual->MagicMarker == ACTCTX_MAGIC_MARKER);
244 RtlpSxsBreakOnInvalidMarker(ActCtx, 1);
245 }
246 }
247
248 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
249 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
250 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
251 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
252 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
253 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
254 static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
255 static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
256 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
257 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
258 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
259 static const WCHAR fileW[] = {'f','i','l','e',0};
260 static const WCHAR asmv2hashW[] = {'a','s','m','v','2',':','h','a','s','h',0};
261 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
262 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
263 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
264 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
265
266 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
267 static const WCHAR hashW[] = {'h','a','s','h',0};
268 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
269 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
270 static const WCHAR iidW[] = {'i','i','d',0};
271 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
272 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
273 static const WCHAR g_nameW[] = {'n','a','m','e',0};
274 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
275 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
276 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
277 static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
278 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
279 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
280 static const WCHAR typeW[] = {'t','y','p','e',0};
281 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
282 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
283
284 static const WCHAR g_xmlW[] = {'?','x','m','l',0};
285 static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
286 static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
287
288 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
289 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
290
291 static ACTIVATION_CONTEXT_WRAPPED system_actctx = { ACTCTX_MAGIC_MARKER, { 1 } };
292 static ACTIVATION_CONTEXT *process_actctx = &system_actctx.ActivationContext;
293
294 static WCHAR *strdupW(const WCHAR* str)
295 {
296 WCHAR* ptr;
297
298 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
299 return NULL;
300 return strcpyW(ptr, str);
301 }
302
303 static WCHAR *xmlstrdupW(const xmlstr_t* str)
304 {
305 WCHAR *strW;
306
307 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
308 {
309 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
310 strW[str->len] = 0;
311 }
312 return strW;
313 }
314
315 static UNICODE_STRING xmlstr2unicode(const xmlstr_t *xmlstr)
316 {
317 UNICODE_STRING res;
318
319 res.Buffer = (PWSTR)xmlstr->ptr;
320 res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR);
321
322 return res;
323 }
324
325 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
326 {
327 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
328 }
329
330 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
331 {
332 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
333 }
334
335 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
336 {
337 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
338 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
339 }
340
341 static inline BOOL isxmlspace( WCHAR ch )
342 {
343 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
344 }
345
346 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
347 {
348 struct assembly *assembly;
349
350 if (actctx->num_assemblies == actctx->allocated_assemblies)
351 {
352 void *ptr;
353 unsigned int new_count;
354 if (actctx->assemblies)
355 {
356 new_count = actctx->allocated_assemblies * 2;
357 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
358 actctx->assemblies, new_count * sizeof(*assembly) );
359 }
360 else
361 {
362 new_count = 4;
363 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
364 }
365 if (!ptr) return NULL;
366 actctx->assemblies = ptr;
367 actctx->allocated_assemblies = new_count;
368 }
369
370 assembly = &actctx->assemblies[actctx->num_assemblies++];
371 assembly->type = at;
372 return assembly;
373 }
374
375 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
376 {
377 if (assembly->num_dlls == assembly->allocated_dlls)
378 {
379 void *ptr;
380 unsigned int new_count;
381 if (assembly->dlls)
382 {
383 new_count = assembly->allocated_dlls * 2;
384 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
385 assembly->dlls, new_count * sizeof(*assembly->dlls) );
386 }
387 else
388 {
389 new_count = 4;
390 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
391 }
392 if (!ptr) return NULL;
393 assembly->dlls = ptr;
394 assembly->allocated_dlls = new_count;
395 }
396 return &assembly->dlls[assembly->num_dlls++];
397 }
398
399 static void free_assembly_identity(struct assembly_identity *ai)
400 {
401 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
402 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
403 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
404 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
405 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
406 }
407
408 static struct entity* add_entity(struct entity_array *array, DWORD kind)
409 {
410 struct entity* entity;
411
412 if (array->num == array->allocated)
413 {
414 void *ptr;
415 unsigned int new_count;
416 if (array->base)
417 {
418 new_count = array->allocated * 2;
419 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
420 array->base, new_count * sizeof(*array->base) );
421 }
422 else
423 {
424 new_count = 4;
425 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
426 }
427 if (!ptr) return NULL;
428 array->base = ptr;
429 array->allocated = new_count;
430 }
431 entity = &array->base[array->num++];
432 entity->kind = kind;
433 return entity;
434 }
435
436 static void free_entity_array(struct entity_array *array)
437 {
438 unsigned int i;
439 for (i = 0; i < array->num; i++)
440 {
441 struct entity *entity = &array->base[i];
442 switch (entity->kind)
443 {
444 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
445 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
446 break;
447 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
448 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid);
449 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name);
450 break;
451 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
452 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
453 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version);
454 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
455 break;
456 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
457 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
458 break;
459 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
460 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name);
461 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid);
462 break;
463 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
464 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
465 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
466 break;
467 default:
468 DPRINT1("Unknown entity kind %u\n", entity->kind);
469 }
470 }
471 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
472 }
473
474 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
475 {
476 if (!str1) return !str2;
477 return str2 && !strcmpiW( str1, str2 );
478 }
479
480 static BOOL is_matching_identity( const struct assembly_identity *id1,
481 const struct assembly_identity *id2 )
482 {
483 if (!is_matching_string( id1->name, id2->name )) return FALSE;
484 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
485 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
486
487 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
488 {
489 static const WCHAR wildcardW[] = {'*',0};
490 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
491 return FALSE;
492 }
493 if (id1->version.major != id2->version.major) return FALSE;
494 if (id1->version.minor != id2->version.minor) return FALSE;
495 if (id1->version.build > id2->version.build) return FALSE;
496 if (id1->version.build == id2->version.build &&
497 id1->version.revision > id2->version.revision) return FALSE;
498 return TRUE;
499 }
500
501 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
502 struct assembly_identity* ai)
503 {
504 unsigned int i;
505
506 /* check if we already have that assembly */
507
508 for (i = 0; i < acl->actctx->num_assemblies; i++)
509 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
510 {
511 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
512 ai->name, ai->arch, ai->version.major, ai->version.minor,
513 ai->version.build, ai->version.revision );
514 return TRUE;
515 }
516
517 for (i = 0; i < acl->num_dependencies; i++)
518 if (is_matching_identity( ai, &acl->dependencies[i] ))
519 {
520 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
521 ai->name, ai->arch, ai->version.major, ai->version.minor,
522 ai->version.build, ai->version.revision );
523 return TRUE;
524 }
525
526 if (acl->num_dependencies == acl->allocated_dependencies)
527 {
528 void *ptr;
529 unsigned int new_count;
530 if (acl->dependencies)
531 {
532 new_count = acl->allocated_dependencies * 2;
533 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
534 new_count * sizeof(acl->dependencies[0]));
535 }
536 else
537 {
538 new_count = 4;
539 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
540 }
541 if (!ptr) return FALSE;
542 acl->dependencies = ptr;
543 acl->allocated_dependencies = new_count;
544 }
545 acl->dependencies[acl->num_dependencies++] = *ai;
546
547 return TRUE;
548 }
549
550 static void free_depend_manifests(struct actctx_loader* acl)
551 {
552 unsigned int i;
553 for (i = 0; i < acl->num_dependencies; i++)
554 free_assembly_identity(&acl->dependencies[i]);
555 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
556 }
557
558 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
559 {
560 static const WCHAR undW[] = {'_',0};
561 static const WCHAR noneW[] = {'n','o','n','e',0};
562 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
563
564 const WCHAR *arch = ai->arch ? ai->arch : noneW;
565 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
566 const WCHAR *lang = ai->language ? ai->language : noneW;
567 const WCHAR *name = ai->name ? ai->name : noneW;
568 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
569 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
570 WCHAR *ret;
571
572 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
573
574 strcpyW( ret, arch );
575 strcatW( ret, undW );
576 strcatW( ret, name );
577 strcatW( ret, undW );
578 strcatW( ret, key );
579 strcatW( ret, undW );
580 sprintfW( ret + strlenW(ret), version_formatW,
581 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
582 strcatW( ret, undW );
583 strcatW( ret, lang );
584 strcatW( ret, undW );
585 strcatW( ret, mskeyW );
586 return ret;
587 }
588
589 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
590 {
591 WCHAR *p = buffer;
592
593 if (!str) return;
594 strcatW( buffer, prefix );
595 p += strlenW(p);
596 *p++ = '"';
597 strcpyW( p, str );
598 p += strlenW(p);
599 *p++ = '"';
600 *p = 0;
601 }
602
603 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
604 {
605 static const WCHAR archW[] =
606 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
607 static const WCHAR public_keyW[] =
608 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
609
610 WCHAR version[64], *ret;
611 SIZE_T size = 0;
612
613 sprintfW( version, version_formatW,
614 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
615 if (ai->name) size += strlenW(ai->name);
616 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
617 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
618 if (ai->type) size += 1 + strlenW(typeW) + 1 + strlenW(ai->type) + 2;
619 size += 1+ strlenW(versionW) + 1 + strlenW(version) + 2;
620
621 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
622 return NULL;
623
624 if (ai->name) strcpyW( ret, ai->name );
625 else *ret = 0;
626 append_string( ret, archW, ai->arch );
627 append_string( ret, public_keyW, ai->public_key );
628 append_string( ret, typeW, ai->type );
629 append_string( ret, versionW, version );
630 return ret;
631 }
632 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
633 {
634 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
635 PACTIVATION_CONTEXT_WRAPPED pActual;
636
637 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
638 _SEH2_TRY
639 {
640 if (actctx)
641 {
642 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
643 if (pActual->MagicMarker == ACTCTX_MAGIC_MARKER) ret = &pActual->ActivationContext;
644 }
645 }
646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
647 {
648 DPRINT1("Invalid activation context handle!\n");
649 }
650 _SEH2_END;
651 return ret;
652 }
653
654 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
655 {
656 InterlockedExchangeAdd( &actctx->RefCount, 1 );
657 }
658
659 static void actctx_release( ACTIVATION_CONTEXT *actctx )
660 {
661 PACTIVATION_CONTEXT_WRAPPED pActual;
662
663 if (InterlockedExchangeAdd(&actctx->RefCount, -1) == 1)
664 {
665 unsigned int i, j;
666
667 for (i = 0; i < actctx->num_assemblies; i++)
668 {
669 struct assembly *assembly = &actctx->assemblies[i];
670 for (j = 0; j < assembly->num_dlls; j++)
671 {
672 struct dll_redirect *dll = &assembly->dlls[j];
673 free_entity_array( &dll->entities );
674 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
675 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
676 }
677 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
678 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
679 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
680 free_entity_array( &assembly->entities );
681 free_assembly_identity(&assembly->id);
682 }
683 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
684 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
685 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
686 pActual = CONTAINING_RECORD(actctx, ACTIVATION_CONTEXT_WRAPPED, ActivationContext);
687 pActual->MagicMarker = 0;
688 RtlFreeHeap(RtlGetProcessHeap(), 0, pActual);
689 }
690 }
691
692 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
693 BOOL* error, BOOL* end)
694 {
695 const WCHAR* ptr;
696
697 *error = TRUE;
698
699 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
700 xmlbuf->ptr++;
701
702 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
703
704 if (*xmlbuf->ptr == '/')
705 {
706 xmlbuf->ptr++;
707 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
708 return FALSE;
709
710 xmlbuf->ptr++;
711 *end = TRUE;
712 *error = FALSE;
713 return FALSE;
714 }
715
716 if (*xmlbuf->ptr == '>')
717 {
718 xmlbuf->ptr++;
719 *error = FALSE;
720 return FALSE;
721 }
722
723 ptr = xmlbuf->ptr;
724 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
725
726 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
727
728 name->ptr = xmlbuf->ptr;
729 name->len = (ULONG)(ptr - xmlbuf->ptr);
730 xmlbuf->ptr = ptr;
731
732 ptr++;
733 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
734
735 value->ptr = ++ptr;
736 if (ptr == xmlbuf->end) return FALSE;
737
738 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
739 if (!ptr)
740 {
741 xmlbuf->ptr = xmlbuf->end;
742 return FALSE;
743 }
744
745 value->len = (ULONG)(ptr - value->ptr);
746 xmlbuf->ptr = ptr + 1;
747
748 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
749
750 *error = FALSE;
751 return TRUE;
752 }
753
754 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
755 {
756 const WCHAR* ptr;
757
758 for (;;)
759 {
760 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
761 if (!ptr)
762 {
763 xmlbuf->ptr = xmlbuf->end;
764 return FALSE;
765 }
766 ptr++;
767 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
768 {
769 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
770 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
771
772 if (ptr + 3 > xmlbuf->end)
773 {
774 xmlbuf->ptr = xmlbuf->end;
775 return FALSE;
776 }
777 xmlbuf->ptr = ptr + 3;
778 }
779 else break;
780 }
781
782 xmlbuf->ptr = ptr;
783 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
784 ptr++;
785
786 elem->ptr = xmlbuf->ptr;
787 elem->len = (ULONG)(ptr - xmlbuf->ptr);
788 xmlbuf->ptr = ptr;
789 return xmlbuf->ptr != xmlbuf->end;
790 }
791
792 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
793 {
794 /* FIXME: parse attributes */
795 const WCHAR *ptr;
796
797 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
798 {
799 if (ptr[0] == '?' && ptr[1] == '>')
800 {
801 xmlbuf->ptr = ptr + 2;
802 return TRUE;
803 }
804 }
805 return FALSE;
806 }
807
808 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
809 {
810 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
811
812 if (!ptr) return FALSE;
813
814 content->ptr = xmlbuf->ptr;
815 content->len = (ULONG)(ptr - xmlbuf->ptr);
816 xmlbuf->ptr = ptr;
817
818 return TRUE;
819 }
820
821 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
822 {
823 unsigned int ver[4];
824 unsigned int pos;
825 const WCHAR *curr;
826 UNICODE_STRING strU;
827
828 /* major.minor.build.revision */
829 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
830 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
831 {
832 if (*curr >= '0' && *curr <= '9')
833 {
834 ver[pos] = ver[pos] * 10 + *curr - '0';
835 if (ver[pos] >= 0x10000) goto error;
836 }
837 else if (*curr == '.')
838 {
839 if (++pos >= 4) goto error;
840 }
841 else goto error;
842 }
843 version->major = ver[0];
844 version->minor = ver[1];
845 version->build = ver[2];
846 version->revision = ver[3];
847 return TRUE;
848
849 error:
850 strU = xmlstr2unicode(str);
851 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU );
852 return FALSE;
853 }
854
855 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name)
856 {
857 xmlstr_t elem;
858 UNICODE_STRING elemU;
859 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
860 if (xmlstr_cmp(&elem, name)) return TRUE;
861 elemU = xmlstr2unicode(&elem);
862 DPRINT1( "unexpected element %wZ\n", &elemU );
863 return FALSE;
864 }
865
866 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
867 {
868 xmlstr_t attr_name, attr_value;
869 UNICODE_STRING attr_nameU, attr_valueU;
870 BOOL error;
871
872 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
873 {
874 attr_nameU = xmlstr2unicode(&attr_name);
875 attr_valueU = xmlstr2unicode(&attr_value);
876 DPRINT1( "unexpected attr %wZ=%wZ\n", &attr_nameU,
877 &attr_valueU);
878 }
879 return !error;
880 }
881
882 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
883 {
884 BOOL end = FALSE;
885 return parse_expect_no_attr(xmlbuf, &end) && !end;
886 }
887
888 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name)
889 {
890 xmlstr_t elem;
891 UNICODE_STRING elemU;
892 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
893 if (!xmlstr_cmp_end(&elem, name))
894 {
895 elemU = xmlstr2unicode(&elem);
896 DPRINT1( "unexpected element %wZ\n", &elemU );
897 return FALSE;
898 }
899 return parse_end_element(xmlbuf);
900 }
901
902 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
903 {
904 xmlstr_t attr_name, attr_value, elem;
905 BOOL end = FALSE, error, ret = TRUE;
906
907 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
908 if(error || end) return end;
909
910 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
911 {
912 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
913 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
914 break;
915 else
916 ret = parse_unknown_elem(xmlbuf, &elem);
917 }
918
919 return ret && parse_end_element(xmlbuf);
920 }
921
922 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
923 struct assembly_identity* ai)
924 {
925 xmlstr_t attr_name, attr_value;
926 BOOL end = FALSE, error;
927 UNICODE_STRING attr_valueU, attr_nameU;
928
929 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
930 {
931 if (xmlstr_cmp(&attr_name, g_nameW))
932 {
933 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
934 }
935 else if (xmlstr_cmp(&attr_name, typeW))
936 {
937 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
938 }
939 else if (xmlstr_cmp(&attr_name, versionW))
940 {
941 if (!parse_version(&attr_value, &ai->version)) return FALSE;
942 }
943 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
944 {
945 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
946 }
947 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
948 {
949 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
950 }
951 else if (xmlstr_cmp(&attr_name, languageW))
952 {
953 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
954 DPRINT1("Unsupported yet language attribute (%S)\n",
955 ai->language);
956 }
957 else
958 {
959 attr_nameU = xmlstr2unicode(&attr_name);
960 attr_valueU = xmlstr2unicode(&attr_value);
961 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
962 }
963 }
964
965 if (error || end) return end;
966 return parse_expect_end_elem(xmlbuf, assemblyIdentityW);
967 }
968
969 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
970 {
971 xmlstr_t elem, attr_name, attr_value;
972 BOOL ret, end = FALSE, error;
973 struct entity* entity;
974 UNICODE_STRING attr_valueU, attr_nameU;
975
976 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
977 return FALSE;
978
979 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
980 {
981 if (xmlstr_cmp(&attr_name, clsidW))
982 {
983 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
984 }
985 else
986 {
987 attr_nameU = xmlstr2unicode(&attr_name);
988 attr_valueU = xmlstr2unicode(&attr_value);
989 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
990 }
991 }
992
993 if (error || end) return end;
994
995 while ((ret = next_xml_elem(xmlbuf, &elem)))
996 {
997 if (xmlstr_cmp_end(&elem, comClassW))
998 {
999 ret = parse_end_element(xmlbuf);
1000 break;
1001 }
1002 else
1003 {
1004 attr_nameU = xmlstr2unicode(&elem);
1005 DPRINT1("unknown elem %wZ\n", &attr_nameU);
1006 ret = parse_unknown_elem(xmlbuf, &elem);
1007 }
1008 }
1009 return ret;
1010 }
1011
1012 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
1013 {
1014 xmlstr_t attr_name, attr_value;
1015 BOOL end = FALSE, error;
1016 struct entity* entity;
1017 UNICODE_STRING attr_valueU, attr_nameU;
1018
1019 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1020 return FALSE;
1021
1022 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1023 {
1024 if (xmlstr_cmp(&attr_name, iidW))
1025 {
1026 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
1027 }
1028 if (xmlstr_cmp(&attr_name, g_nameW))
1029 {
1030 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
1031 }
1032 else
1033 {
1034 attr_nameU = xmlstr2unicode(&attr_name);
1035 attr_valueU = xmlstr2unicode(&attr_value);
1036 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1037 }
1038 }
1039
1040 if (error || end) return end;
1041 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW);
1042 }
1043
1044 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
1045 {
1046 xmlstr_t attr_name, attr_value;
1047 BOOL end = FALSE, error;
1048 struct entity* entity;
1049 UNICODE_STRING attr_valueU, attr_nameU;
1050
1051 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1052 return FALSE;
1053
1054 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1055 {
1056 if (xmlstr_cmp(&attr_name, tlbidW))
1057 {
1058 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1059 }
1060 if (xmlstr_cmp(&attr_name, versionW))
1061 {
1062 if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
1063 }
1064 if (xmlstr_cmp(&attr_name, helpdirW))
1065 {
1066 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1067 }
1068 else
1069 {
1070 attr_nameU = xmlstr2unicode(&attr_name);
1071 attr_valueU = xmlstr2unicode(&attr_value);
1072 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1073 }
1074 }
1075
1076 if (error || end) return end;
1077 return parse_expect_end_elem(xmlbuf, typelibW);
1078 }
1079
1080 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
1081 {
1082 xmlstr_t elem, content;
1083 BOOL end = FALSE, ret = TRUE;
1084 struct entity* entity;
1085 UNICODE_STRING elemU;
1086
1087 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1088 return FALSE;
1089
1090 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1091 if (end) return FALSE;
1092
1093 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1094
1095 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1096
1097 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1098 {
1099 if (xmlstr_cmp_end(&elem, windowClassW))
1100 {
1101 ret = parse_end_element(xmlbuf);
1102 break;
1103 }
1104 else
1105 {
1106 elemU = xmlstr2unicode(&elem);
1107 DPRINT1("unknown elem %wZ\n", &elemU);
1108 ret = parse_unknown_elem(xmlbuf, &elem);
1109 }
1110 }
1111
1112 return ret;
1113 }
1114
1115 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1116 {
1117 xmlstr_t attr_name, attr_value;
1118 UNICODE_STRING attr_valueU, attr_nameU;
1119 BOOL end = FALSE, error;
1120
1121 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1122 {
1123 attr_nameU = xmlstr2unicode(&attr_name);
1124 attr_valueU = xmlstr2unicode(&attr_value);
1125
1126 if (xmlstr_cmp(&attr_name, oldVersionW))
1127 {
1128 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
1129 }
1130 else if (xmlstr_cmp(&attr_name, newVersionW))
1131 {
1132 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
1133 }
1134 else
1135 {
1136 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1137 }
1138 }
1139
1140 if (error || end) return end;
1141 return parse_expect_end_elem(xmlbuf, bindingRedirectW);
1142 }
1143
1144 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1145 {
1146 xmlstr_t elem, content;
1147 UNICODE_STRING elemU;
1148 BOOL end = FALSE, ret = TRUE;
1149
1150 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
1151 !parse_text_content(xmlbuf, &content))
1152 return FALSE;
1153
1154 elemU = xmlstr2unicode(&content);
1155 DPRINT("Got description %wZ\n", &elemU);
1156
1157 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1158 {
1159 if (xmlstr_cmp_end(&elem, descriptionW))
1160 {
1161 ret = parse_end_element(xmlbuf);
1162 break;
1163 }
1164 else
1165 {
1166 elemU = xmlstr2unicode(&elem);
1167 DPRINT1("unknown elem %wZ\n", &elemU);
1168 ret = parse_unknown_elem(xmlbuf, &elem);
1169 }
1170 }
1171
1172 return ret;
1173 }
1174
1175 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1176 struct assembly* assembly)
1177 {
1178 xmlstr_t attr_name, attr_value;
1179 BOOL end = FALSE, error;
1180 struct entity* entity;
1181
1182 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1183 if (!entity) return FALSE;
1184
1185 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1186 {
1187 if (xmlstr_cmp(&attr_name, iidW))
1188 {
1189 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
1190 }
1191 if (xmlstr_cmp(&attr_name, g_nameW))
1192 {
1193 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
1194 }
1195 else
1196 {
1197 DPRINT1("unknown attr %S=%S\n", attr_name.ptr, attr_value.ptr);
1198 }
1199 }
1200
1201 if (error || end) return end;
1202 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW);
1203 }
1204
1205 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1206 {
1207 xmlstr_t attr_name, attr_value;
1208 UNICODE_STRING attr_nameU, attr_valueU;
1209 BOOL end = FALSE, error;
1210 struct entity* entity;
1211
1212 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
1213 if (!entity) return FALSE;
1214
1215 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1216 {
1217 if (xmlstr_cmp(&attr_name, g_nameW))
1218 {
1219 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
1220 }
1221 else if (xmlstr_cmp(&attr_name, clsidW))
1222 {
1223 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1224 }
1225 else
1226 {
1227 attr_nameU = xmlstr2unicode(&attr_name);
1228 attr_valueU = xmlstr2unicode(&attr_value);
1229 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1230 }
1231 }
1232
1233 if (error || end) return end;
1234 return parse_expect_end_elem(xmlbuf, clrClassW);
1235 }
1236
1237 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1238 {
1239 xmlstr_t attr_name, attr_value;
1240 UNICODE_STRING attr_nameU, attr_valueU;
1241 BOOL end = FALSE, error;
1242 struct entity* entity;
1243
1244 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1245 if (!entity) return FALSE;
1246
1247 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1248 {
1249 if (xmlstr_cmp(&attr_name, g_nameW))
1250 {
1251 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
1252 }
1253 else if (xmlstr_cmp(&attr_name, clsidW))
1254 {
1255 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
1256 }
1257 else
1258 {
1259 attr_nameU = xmlstr2unicode(&attr_name);
1260 attr_valueU = xmlstr2unicode(&attr_value);
1261 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1262 }
1263 }
1264
1265 if (error || end) return end;
1266 return parse_expect_end_elem(xmlbuf, clrSurrogateW);
1267 }
1268
1269 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1270 {
1271 struct assembly_identity ai;
1272 xmlstr_t elem;
1273 BOOL end = FALSE, ret = TRUE;
1274
1275 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1276
1277 memset(&ai, 0, sizeof(ai));
1278 ai.optional = optional;
1279
1280 if (!parse_expect_elem(xmlbuf, assemblyIdentityW) ||
1281 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1282 return FALSE;
1283
1284 /* store the newly found identity for later loading */
1285 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1286
1287 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1288 {
1289 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
1290 {
1291 ret = parse_end_element(xmlbuf);
1292 break;
1293 }
1294 else if (xmlstr_cmp(&elem, bindingRedirectW))
1295 {
1296 ret = parse_binding_redirect_elem(xmlbuf);
1297 }
1298 else
1299 {
1300 DPRINT1("unknown elem %S\n", elem.ptr);
1301 ret = parse_unknown_elem(xmlbuf, &elem);
1302 }
1303 }
1304
1305 return ret;
1306 }
1307
1308 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1309 {
1310 xmlstr_t attr_name, attr_value, elem;
1311 UNICODE_STRING attr_nameU, attr_valueU;
1312 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1313
1314 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1315 {
1316 attr_nameU = xmlstr2unicode(&attr_name);
1317 attr_valueU = xmlstr2unicode(&attr_value);
1318
1319 if (xmlstr_cmp(&attr_name, optionalW))
1320 {
1321 static const WCHAR yesW[] = {'y','e','s',0};
1322 optional = xmlstr_cmpi( &attr_value, yesW );
1323 DPRINT1("optional=%wZ\n", &attr_valueU);
1324 }
1325 else
1326 {
1327 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1328 }
1329 }
1330
1331 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1332 {
1333 if (xmlstr_cmp_end(&elem, dependencyW))
1334 {
1335 ret = parse_end_element(xmlbuf);
1336 break;
1337 }
1338 else if (xmlstr_cmp(&elem, dependentAssemblyW))
1339 {
1340 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1341 }
1342 else
1343 {
1344 attr_nameU = xmlstr2unicode(&elem);
1345 DPRINT1("unknown element %wZ\n", &attr_nameU);
1346 ret = parse_unknown_elem(xmlbuf, &elem);
1347 }
1348 }
1349
1350 return ret;
1351 }
1352
1353 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1354 {
1355 BOOL end = FALSE;
1356
1357 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1358 return end || parse_expect_end_elem(xmlbuf, noInheritW);
1359 }
1360
1361 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1362 {
1363 BOOL end = FALSE;
1364
1365 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1366 return end || parse_expect_end_elem(xmlbuf, noInheritableW);
1367 }
1368
1369 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1370 {
1371 xmlstr_t attr_name, attr_value, elem;
1372 UNICODE_STRING attr_nameU, attr_valueU;
1373 BOOL end = FALSE, error, ret = TRUE;
1374 struct dll_redirect* dll;
1375
1376 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1377
1378 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1379 {
1380 attr_nameU = xmlstr2unicode(&attr_name);
1381 attr_valueU = xmlstr2unicode(&attr_value);
1382
1383 if (xmlstr_cmp(&attr_name, g_nameW))
1384 {
1385 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1386 DPRINT("name=%wZ\n", &attr_valueU);
1387 }
1388 else if (xmlstr_cmp(&attr_name, hashW))
1389 {
1390 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1391 }
1392 else if (xmlstr_cmp(&attr_name, hashalgW))
1393 {
1394 static const WCHAR sha1W[] = {'S','H','A','1',0};
1395 if (!xmlstr_cmpi(&attr_value, sha1W))
1396 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
1397 }
1398 else
1399 {
1400 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1401 }
1402 }
1403
1404 if (error || !dll->name) return FALSE;
1405 if (end) return TRUE;
1406
1407 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1408 {
1409 if (xmlstr_cmp_end(&elem, fileW))
1410 {
1411 ret = parse_end_element(xmlbuf);
1412 break;
1413 }
1414 else if (xmlstr_cmp(&elem, comClassW))
1415 {
1416 ret = parse_com_class_elem(xmlbuf, dll);
1417 }
1418 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
1419 {
1420 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1421 }
1422 else if (xmlstr_cmp(&elem, asmv2hashW))
1423 {
1424 DPRINT1("asmv2hash (undocumented) not supported\n");
1425 ret = parse_unknown_elem(xmlbuf, &elem);
1426 }
1427 else if (xmlstr_cmp(&elem, typelibW))
1428 {
1429 ret = parse_typelib_elem(xmlbuf, dll);
1430 }
1431 else if (xmlstr_cmp(&elem, windowClassW))
1432 {
1433 ret = parse_window_class_elem(xmlbuf, dll);
1434 }
1435 else
1436 {
1437 attr_nameU = xmlstr2unicode(&elem);
1438 DPRINT1("unknown elem %wZ\n", &attr_nameU);
1439 ret = parse_unknown_elem( xmlbuf, &elem );
1440 }
1441 }
1442
1443 return ret;
1444 }
1445
1446 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1447 struct assembly* assembly,
1448 struct assembly_identity* expected_ai)
1449 {
1450 xmlstr_t attr_name, attr_value, elem;
1451 UNICODE_STRING attr_nameU, attr_valueU;
1452 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1453
1454 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1455 {
1456 attr_nameU = xmlstr2unicode(&attr_name);
1457 attr_valueU = xmlstr2unicode(&attr_value);
1458
1459 if (xmlstr_cmp(&attr_name, manifestVersionW))
1460 {
1461 static const WCHAR v10W[] = {'1','.','0',0};
1462 if (!xmlstr_cmp(&attr_value, v10W))
1463 {
1464 DPRINT1("wrong version %wZ\n", &attr_valueU);
1465 return FALSE;
1466 }
1467 version = TRUE;
1468 }
1469 else if (xmlstr_cmp(&attr_name, xmlnsW))
1470 {
1471 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
1472 {
1473 DPRINT1("wrong namespace %wZ\n", &attr_valueU);
1474 return FALSE;
1475 }
1476 xmlns = TRUE;
1477 }
1478 else
1479 {
1480 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
1481 }
1482 }
1483
1484 if (error || end || !xmlns || !version) return FALSE;
1485 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1486
1487 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
1488 {
1489 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1490 return FALSE;
1491 assembly->no_inherit = TRUE;
1492 }
1493
1494 if (xmlstr_cmp(&elem, noInheritableW))
1495 {
1496 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1497 return FALSE;
1498 }
1499 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
1500 assembly->no_inherit)
1501 return FALSE;
1502
1503 while (ret)
1504 {
1505 if (xmlstr_cmp_end(&elem, assemblyW))
1506 {
1507 ret = parse_end_element(xmlbuf);
1508 break;
1509 }
1510 else if (xmlstr_cmp(&elem, descriptionW))
1511 {
1512 ret = parse_description_elem(xmlbuf);
1513 }
1514 else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW))
1515 {
1516 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1517 }
1518 else if (xmlstr_cmp(&elem, dependencyW))
1519 {
1520 ret = parse_dependency_elem(xmlbuf, acl);
1521 }
1522 else if (xmlstr_cmp(&elem, fileW))
1523 {
1524 ret = parse_file_elem(xmlbuf, assembly);
1525 }
1526 else if (xmlstr_cmp(&elem, clrClassW))
1527 {
1528 ret = parse_clr_class_elem(xmlbuf, assembly);
1529 }
1530 else if (xmlstr_cmp(&elem, clrSurrogateW))
1531 {
1532 ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1533 }
1534 else if (xmlstr_cmp(&elem, assemblyIdentityW))
1535 {
1536 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
1537
1538 if (expected_ai)
1539 {
1540 /* FIXME: more tests */
1541 if (assembly->type == ASSEMBLY_MANIFEST &&
1542 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
1543 {
1544 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
1545 expected_ai->version.major, expected_ai->version.minor,
1546 expected_ai->version.build, expected_ai->version.revision,
1547 assembly->id.version.major, assembly->id.version.minor,
1548 assembly->id.version.build, assembly->id.version.revision);
1549 ret = FALSE;
1550 }
1551 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
1552 (assembly->id.version.major != expected_ai->version.major ||
1553 assembly->id.version.minor != expected_ai->version.minor ||
1554 assembly->id.version.build < expected_ai->version.build ||
1555 (assembly->id.version.build == expected_ai->version.build &&
1556 assembly->id.version.revision < expected_ai->version.revision)))
1557 {
1558 DPRINT1("wrong version for shared assembly manifest\n");
1559 ret = FALSE;
1560 }
1561 }
1562 }
1563 else
1564 {
1565 attr_nameU = xmlstr2unicode(&elem);
1566 DPRINT1("unknown element %wZ\n", &attr_nameU);
1567 ret = parse_unknown_elem(xmlbuf, &elem);
1568 }
1569 if (ret) ret = next_xml_elem(xmlbuf, &elem);
1570 }
1571
1572 return ret;
1573 }
1574
1575 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
1576 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
1577 {
1578 xmlstr_t elem;
1579 UNICODE_STRING elemU;
1580
1581 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1582
1583 if (xmlstr_cmp(&elem, g_xmlW) &&
1584 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1585 return STATUS_SXS_CANT_GEN_ACTCTX;
1586
1587 if (!xmlstr_cmp(&elem, assemblyW))
1588 {
1589 elemU = xmlstr2unicode(&elem);
1590 DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
1591 return STATUS_SXS_CANT_GEN_ACTCTX;
1592 }
1593
1594 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1595 {
1596 DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
1597 return STATUS_SXS_CANT_GEN_ACTCTX;
1598 }
1599
1600 if (next_xml_elem(xmlbuf, &elem))
1601 {
1602 elemU = xmlstr2unicode(&elem);
1603 DPRINT1("unexpected element %wZ\n", &elemU);
1604 return STATUS_SXS_CANT_GEN_ACTCTX;
1605 }
1606
1607 if (xmlbuf->ptr != xmlbuf->end)
1608 {
1609 DPRINT1("parse error\n");
1610 return STATUS_SXS_CANT_GEN_ACTCTX;
1611 }
1612 return STATUS_SUCCESS;
1613 }
1614
1615 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1616 LPCWSTR filename, LPCWSTR directory, BOOL shared,
1617 const void *buffer, SIZE_T size )
1618 {
1619 xmlbuf_t xmlbuf;
1620 NTSTATUS status;
1621 struct assembly *assembly;
1622 int unicode_tests;
1623
1624 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
1625
1626 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
1627 return STATUS_SXS_CANT_GEN_ACTCTX;
1628
1629 if (directory && !(assembly->directory = strdupW(directory)))
1630 return STATUS_NO_MEMORY;
1631
1632 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
1633 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
1634 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
1635
1636 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
1637 if (RtlIsTextUnicode((PVOID)buffer, (ULONG)size, &unicode_tests ))
1638 {
1639 xmlbuf.ptr = buffer;
1640 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
1641 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
1642 }
1643 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
1644 {
1645 const WCHAR *buf = buffer;
1646 WCHAR *new_buff;
1647 unsigned int i;
1648
1649 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
1650 return STATUS_NO_MEMORY;
1651 for (i = 0; i < size / sizeof(WCHAR); i++)
1652 new_buff[i] = RtlUshortByteSwap( buf[i] );
1653 xmlbuf.ptr = new_buff;
1654 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
1655 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
1656 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
1657 }
1658 else
1659 {
1660 /* TODO: this doesn't handle arbitrary encodings */
1661 ANSI_STRING xmlA;
1662 UNICODE_STRING xmlW;
1663
1664 ASSERT(size < MAXUSHORT);
1665 xmlA.Buffer = (PCHAR)buffer;
1666 xmlA.Length = xmlA.MaximumLength = (USHORT)size;
1667
1668 _SEH2_TRY
1669 {
1670 status = RtlAnsiStringToUnicodeString(&xmlW, &xmlA, TRUE);
1671 }
1672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1673 {
1674 DPRINT1("Exception accessing buffer\n");
1675 _SEH2_YIELD(return STATUS_SXS_CANT_GEN_ACTCTX);
1676 }
1677 _SEH2_END;
1678
1679 if (!NT_SUCCESS(status))
1680 {
1681 DPRINT1("RtlAnsiStringToUnicodeString failed with %lx\n", status);
1682 return STATUS_SXS_CANT_GEN_ACTCTX;
1683 }
1684 ASSERT(xmlW.Buffer != NULL);
1685
1686 xmlbuf.ptr = xmlW.Buffer;
1687 xmlbuf.end = xmlbuf.ptr + xmlW.Length / sizeof(WCHAR);
1688 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
1689
1690 RtlFreeUnicodeString(&xmlW);
1691 }
1692 return status;
1693 }
1694
1695 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
1696 {
1697 OBJECT_ATTRIBUTES attr;
1698 IO_STATUS_BLOCK io;
1699
1700 attr.Length = sizeof(attr);
1701 attr.RootDirectory = 0;
1702 attr.Attributes = OBJ_CASE_INSENSITIVE;
1703 attr.ObjectName = name;
1704 attr.SecurityDescriptor = NULL;
1705 attr.SecurityQualityOfService = NULL;
1706 return NtOpenFile(handle,
1707 GENERIC_READ | SYNCHRONIZE,
1708 &attr, &io,
1709 FILE_SHARE_READ,
1710 FILE_SYNCHRONOUS_IO_ALERT);
1711 }
1712
1713 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
1714 {
1715 NTSTATUS status;
1716 ULONG magic;
1717 LDR_DATA_TABLE_ENTRY *pldr;
1718
1719 LdrLockLoaderLock(0, NULL, &magic);
1720 status = LdrFindEntryForAddress( module, &pldr );
1721 if (status == STATUS_SUCCESS)
1722 {
1723 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1724 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1725 {
1726 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1727 str->Length = pldr->FullDllName.Length;
1728 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1729 }
1730 else status = STATUS_NO_MEMORY;
1731 }
1732 LdrUnlockLoaderLock(0, magic);
1733 return status;
1734 }
1735
1736 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1737 LPCWSTR filename, LPCWSTR directory, BOOL shared,
1738 HANDLE hModule, LPCWSTR resname, ULONG lang )
1739 {
1740 NTSTATUS status;
1741 UNICODE_STRING nameW;
1742 LDR_RESOURCE_INFO info;
1743 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1744 void *ptr;
1745
1746 //DPRINT( "looking for res %s in module %p %s\n", resname,
1747 // hModule, filename );
1748
1749 #if 0
1750 if (TRACE_ON(actctx))
1751 {
1752 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
1753 {
1754 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
1755 hModule, debugstr_w(nameW.Buffer) );
1756 RtlFreeUnicodeString( &nameW );
1757 }
1758 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
1759 hModule, debugstr_w(filename) );
1760 }
1761 #endif
1762
1763 if (!resname) return STATUS_INVALID_PARAMETER;
1764
1765 info.Type = (ULONG_PTR)RT_MANIFEST;
1766 info.Language = lang;
1767 if (!((ULONG_PTR)resname >> 16))
1768 {
1769 info.Name = (ULONG_PTR)resname;
1770 status = LdrFindResource_U(hModule, &info, 3, &entry);
1771 }
1772 else if (resname[0] == '#')
1773 {
1774 ULONG value;
1775 RtlInitUnicodeString(&nameW, resname + 1);
1776 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1777 return STATUS_INVALID_PARAMETER;
1778 info.Name = value;
1779 status = LdrFindResource_U(hModule, &info, 3, &entry);
1780 }
1781 else
1782 {
1783 RtlCreateUnicodeString(&nameW, resname);
1784 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1785 info.Name = (ULONG_PTR)nameW.Buffer;
1786 status = LdrFindResource_U(hModule, &info, 3, &entry);
1787 RtlFreeUnicodeString(&nameW);
1788 }
1789 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1790
1791 if (status == STATUS_SUCCESS)
1792 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
1793
1794 return status;
1795 }
1796
1797 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1798 LPCWSTR filename, LPCWSTR directory, BOOL shared,
1799 HANDLE file, LPCWSTR resname, ULONG lang )
1800 {
1801 HANDLE mapping;
1802 OBJECT_ATTRIBUTES attr;
1803 LARGE_INTEGER size;
1804 LARGE_INTEGER offset;
1805 NTSTATUS status;
1806 SIZE_T count;
1807 void *base;
1808
1809 DPRINT( "looking for res %S in %S\n", resname, filename );
1810
1811 attr.Length = sizeof(attr);
1812 attr.RootDirectory = 0;
1813 attr.ObjectName = NULL;
1814 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1815 attr.SecurityDescriptor = NULL;
1816 attr.SecurityQualityOfService = NULL;
1817
1818 size.QuadPart = 0;
1819 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1820 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1821 if (status != STATUS_SUCCESS) return status;
1822
1823 offset.QuadPart = 0;
1824 count = 0;
1825 base = NULL;
1826 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
1827 &count, ViewShare, 0, PAGE_READONLY );
1828 NtClose( mapping );
1829 if (status != STATUS_SUCCESS) return status;
1830
1831 if (RtlImageNtHeader(base)) /* we got a PE file */
1832 {
1833 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1834 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
1835 }
1836 else status = STATUS_INVALID_IMAGE_FORMAT;
1837
1838 NtUnmapViewOfSection( NtCurrentProcess(), base );
1839 return status;
1840 }
1841
1842 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1843 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
1844 {
1845 FILE_STANDARD_INFORMATION info;
1846 IO_STATUS_BLOCK io;
1847 HANDLE mapping;
1848 OBJECT_ATTRIBUTES attr;
1849 LARGE_INTEGER size;
1850 LARGE_INTEGER offset;
1851 NTSTATUS status;
1852 SIZE_T count;
1853 void *base;
1854
1855 DPRINT( "loading manifest file %S\n", filename );
1856
1857 attr.Length = sizeof(attr);
1858 attr.RootDirectory = 0;
1859 attr.ObjectName = NULL;
1860 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1861 attr.SecurityDescriptor = NULL;
1862 attr.SecurityQualityOfService = NULL;
1863
1864 size.QuadPart = 0;
1865 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1866 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1867
1868 if (status != STATUS_SUCCESS) return status;
1869
1870 offset.QuadPart = 0;
1871 count = 0;
1872 base = NULL;
1873 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
1874 &count, ViewShare, 0, PAGE_READONLY );
1875
1876 if (status != STATUS_SUCCESS) return status;
1877
1878 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
1879 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
1880
1881 if (status == STATUS_SUCCESS)
1882 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
1883
1884 NtUnmapViewOfSection( NtCurrentProcess(), base );
1885 NtClose( mapping );
1886 return status;
1887 }
1888
1889 /* try to load the .manifest file associated to the file */
1890 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1891 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
1892 {
1893 static const WCHAR fmtW[] = { '.','%','l','u',0 };
1894 WCHAR *buffer;
1895 NTSTATUS status;
1896 UNICODE_STRING nameW;
1897 HANDLE file;
1898 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
1899
1900 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1901
1902 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
1903
1904 if (module) /* use the module filename */
1905 {
1906 UNICODE_STRING name;
1907
1908 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1909 {
1910 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1911 strcatW( name.Buffer, dotManifestW );
1912 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1913 status = STATUS_RESOURCE_DATA_NOT_FOUND;
1914 RtlFreeUnicodeString( &name );
1915 }
1916 if (status) return status;
1917 }
1918 else
1919 {
1920 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1921 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1922 return STATUS_NO_MEMORY;
1923 strcpyW( buffer, filename );
1924 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1925 strcatW( buffer, dotManifestW );
1926 RtlInitUnicodeString( &nameW, buffer );
1927 }
1928
1929 if (!open_nt_file( &file, &nameW ))
1930 {
1931 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
1932 NtClose( file );
1933 }
1934 else status = STATUS_RESOURCE_DATA_NOT_FOUND;
1935 RtlFreeUnicodeString( &nameW );
1936 return status;
1937 }
1938
1939 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
1940 {
1941 static const WCHAR lookup_fmtW[] =
1942 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1943 '*', /* FIXME */
1944 '.','m','a','n','i','f','e','s','t',0};
1945
1946 WCHAR *lookup, *ret = NULL;
1947 UNICODE_STRING lookup_us;
1948 IO_STATUS_BLOCK io;
1949 unsigned int data_pos = 0, data_len;
1950 char buffer[8192];
1951
1952 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1953 (strlenW(ai->arch) + strlenW(ai->name)
1954 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
1955 + sizeof(lookup_fmtW) )))
1956 return NULL;
1957
1958 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
1959 RtlInitUnicodeString( &lookup_us, lookup );
1960
1961 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1962 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
1963 if (io.Status == STATUS_SUCCESS)
1964 {
1965 FILE_BOTH_DIR_INFORMATION *dir_info;
1966 WCHAR *tmp;
1967 ULONG build, revision;
1968
1969 data_len = (ULONG)io.Information;
1970
1971 for (;;)
1972 {
1973 if (data_pos >= data_len)
1974 {
1975 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1976 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
1977 if (io.Status != STATUS_SUCCESS) break;
1978 data_len = (ULONG)io.Information;
1979 data_pos = 0;
1980 }
1981 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
1982
1983 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
1984 else data_pos = data_len;
1985
1986 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
1987 build = atoiW(tmp);
1988 if (build < ai->version.build) continue;
1989 tmp = strchrW(tmp, '.') + 1;
1990 revision = atoiW(tmp);
1991 if (build == ai->version.build && revision < ai->version.revision)
1992 continue;
1993 ai->version.build = (USHORT)build;
1994 ai->version.revision = (USHORT)revision;
1995
1996 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) )))
1997 {
1998 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
1999 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2000 }
2001 break;
2002 }
2003 }
2004 else DPRINT1("no matching file for %S\n", lookup);
2005 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
2006 return ret;
2007 }
2008
2009 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2010 {
2011 struct assembly_identity sxs_ai;
2012 UNICODE_STRING path_us;
2013 OBJECT_ATTRIBUTES attr;
2014 IO_STATUS_BLOCK io;
2015 WCHAR *path, *file = NULL;
2016 HANDLE handle;
2017
2018 static const WCHAR manifest_dirW[] =
2019 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2020
2021 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2022
2023 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2024 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
2025 return STATUS_NO_MEMORY;
2026
2027 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
2028 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
2029
2030 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2031 {
2032 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2033 return STATUS_NO_SUCH_FILE;
2034 }
2035 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
2036
2037 attr.Length = sizeof(attr);
2038 attr.RootDirectory = 0;
2039 attr.Attributes = OBJ_CASE_INSENSITIVE;
2040 attr.ObjectName = &path_us;
2041 attr.SecurityDescriptor = NULL;
2042 attr.SecurityQualityOfService = NULL;
2043
2044 if (!NtOpenFile(&handle,
2045 GENERIC_READ | SYNCHRONIZE,
2046 &attr, &io,
2047 FILE_SHARE_READ | FILE_SHARE_WRITE,
2048 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT))
2049 {
2050 sxs_ai = *ai;
2051 file = lookup_manifest_file( handle, &sxs_ai );
2052 NtClose( handle );
2053 }
2054 if (!file)
2055 {
2056 RtlFreeUnicodeString( &path_us );
2057 return STATUS_NO_SUCH_FILE;
2058 }
2059
2060 /* append file name to directory path */
2061 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
2062 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2063 {
2064 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2065 RtlFreeUnicodeString( &path_us );
2066 return STATUS_NO_MEMORY;
2067 }
2068
2069 path[path_us.Length/sizeof(WCHAR)] = '\\';
2070 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2071 RtlInitUnicodeString( &path_us, path );
2072 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2073
2074 if (!open_nt_file( &handle, &path_us ))
2075 {
2076 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2077 NtClose( handle );
2078 }
2079 else io.Status = STATUS_NO_SUCH_FILE;
2080
2081 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
2082 RtlFreeUnicodeString( &path_us );
2083 return io.Status;
2084 }
2085
2086 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2087 struct assembly_identity* ai)
2088 {
2089 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2090 unsigned int i;
2091 WCHAR *buffer, *p, *directory;
2092 NTSTATUS status;
2093 UNICODE_STRING nameW;
2094 HANDLE file;
2095
2096 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2097 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
2098
2099 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2100
2101 /* FIXME: add support for language specific lookup */
2102
2103 nameW.Buffer = NULL;
2104 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2105 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2106 return STATUS_NO_MEMORY;
2107
2108 if (!(directory = build_assembly_dir( ai )))
2109 {
2110 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
2111 return STATUS_NO_MEMORY;
2112 }
2113
2114 /* lookup in appdir\name.dll
2115 * appdir\name.manifest
2116 * appdir\name\name.dll
2117 * appdir\name\name.manifest
2118 */
2119 strcpyW( buffer, acl->actctx->appdir.info );
2120 p = buffer + strlenW(buffer);
2121 for (i = 0; i < 2; i++)
2122 {
2123 *p++ = '\\';
2124 strcpyW( p, ai->name );
2125 p += strlenW(p);
2126
2127 strcpyW( p, dotDllW );
2128 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2129 {
2130 status = open_nt_file( &file, &nameW );
2131 if (!status)
2132 {
2133 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2134 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2135 NtClose( file );
2136 break;
2137 }
2138 RtlFreeUnicodeString( &nameW );
2139 }
2140
2141 strcpyW( p, dotManifestW );
2142 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2143 {
2144 status = open_nt_file( &file, &nameW );
2145 if (!status)
2146 {
2147 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2148 NtClose( file );
2149 break;
2150 }
2151 RtlFreeUnicodeString( &nameW );
2152 }
2153 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2154 }
2155 RtlFreeUnicodeString( &nameW );
2156 RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
2157 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
2158 return status;
2159 }
2160
2161 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2162 {
2163 NTSTATUS status = STATUS_SUCCESS;
2164 unsigned int i;
2165
2166 for (i = 0; i < acl->num_dependencies; i++)
2167 {
2168 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2169 {
2170 if (!acl->dependencies[i].optional)
2171 {
2172 DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
2173 status = STATUS_SXS_CANT_GEN_ACTCTX;
2174 break;
2175 }
2176 }
2177 }
2178 /* FIXME should now iterate through all refs */
2179 return status;
2180 }
2181
2182 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2183 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2184 {
2185 NTSTATUS status = STATUS_SUCCESS;
2186
2187 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT)
2188 {
2189 if (*handle) return STATUS_INVALID_PARAMETER;
2190
2191 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2192 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
2193 }
2194 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE))
2195 {
2196 ULONG magic;
2197 LDR_DATA_TABLE_ENTRY *pldr;
2198
2199 if (!*handle) return STATUS_INVALID_PARAMETER;
2200
2201 LdrLockLoaderLock( 0, NULL, &magic );
2202 if (!LdrFindEntryForAddress( *handle, &pldr ))
2203 {
2204 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase)
2205 status = STATUS_DLL_NOT_FOUND;
2206 else
2207 *handle = pldr->EntryPointActivationContext;
2208 }
2209 else status = STATUS_DLL_NOT_FOUND;
2210 LdrUnlockLoaderLock( 0, magic );
2211 }
2212 else if (!*handle && (class != ActivationContextBasicInformation))
2213 *handle = process_actctx;
2214
2215 return status;
2216 }
2217
2218 static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
2219 {
2220 data->ulDataFormatVersion = 1;
2221 data->lpData = v1;
2222 data->ulLength = 20; /* FIXME */
2223 data->lpSectionGlobalData = NULL; /* FIXME */
2224 data->ulSectionGlobalDataLength = 0; /* FIXME */
2225 data->lpSectionBase = v2;
2226 data->ulSectionTotalLength = 0; /* FIXME */
2227 data->hActCtx = NULL;
2228 if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
2229 data->ulAssemblyRosterIndex = i + 1;
2230
2231 return STATUS_SUCCESS;
2232 }
2233
2234 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
2235 PACTCTX_SECTION_KEYED_DATA data)
2236 {
2237 unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
2238
2239 for (i = 0; i < actctx->num_assemblies; i++)
2240 {
2241 struct assembly *assembly = &actctx->assemblies[i];
2242 for (j = 0; j < assembly->num_dlls; j++)
2243 {
2244 struct dll_redirect *dll = &assembly->dlls[j];
2245 if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
2246 return fill_keyed_data(data, dll, assembly, i);
2247 }
2248 }
2249 return STATUS_SXS_KEY_NOT_FOUND;
2250 }
2251
2252 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
2253 PACTCTX_SECTION_KEYED_DATA data)
2254 {
2255 unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
2256
2257 for (i = 0; i < actctx->num_assemblies; i++)
2258 {
2259 struct assembly *assembly = &actctx->assemblies[i];
2260 for (j = 0; j < assembly->num_dlls; j++)
2261 {
2262 struct dll_redirect *dll = &assembly->dlls[j];
2263 for (k = 0; k < dll->entities.num; k++)
2264 {
2265 struct entity *entity = &dll->entities.base[k];
2266 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
2267 {
2268 if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
2269 return fill_keyed_data(data, entity, dll, i);
2270 }
2271 }
2272 }
2273 }
2274 return STATUS_SXS_KEY_NOT_FOUND;
2275 }
2276
2277 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
2278 const UNICODE_STRING *section_name,
2279 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
2280 {
2281 NTSTATUS status;
2282
2283 switch (section_kind)
2284 {
2285 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
2286 status = find_dll_redirection(actctx, section_name, data);
2287 break;
2288 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
2289 status = find_window_class(actctx, section_name, data);
2290 break;
2291 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
2292 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
2293 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
2294 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
2295 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
2296 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
2297 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
2298 return STATUS_SXS_SECTION_NOT_FOUND;
2299 default:
2300 DPRINT1("Unknown section_kind %x\n", section_kind);
2301 return STATUS_SXS_SECTION_NOT_FOUND;
2302 }
2303
2304 if (status != STATUS_SUCCESS) return status;
2305
2306 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
2307 {
2308 actctx_addref(actctx);
2309 data->hActCtx = actctx;
2310 }
2311 return STATUS_SUCCESS;
2312 }
2313
2314 /* initialize the activation context for the current process */
2315 void actctx_init(void)
2316 {
2317 ACTCTXW ctx;
2318 HANDLE handle;
2319
2320 ctx.cbSize = sizeof(ctx);
2321 ctx.lpSource = NULL;
2322 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
2323 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
2324 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
2325
2326 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle)))
2327 {
2328 process_actctx = check_actctx(handle);
2329 }
2330 }
2331
2332 /* FUNCTIONS ***************************************************************/
2333
2334 NTSTATUS
2335 NTAPI
2336 RtlCreateActivationContext(IN ULONG Flags,
2337 IN PACTIVATION_CONTEXT_DATA ActivationContextData,
2338 IN ULONG ExtraBytes,
2339 IN PVOID NotificationRoutine,
2340 IN PVOID NotificationContext,
2341 OUT PACTIVATION_CONTEXT *ActCtx)
2342 {
2343 const ACTCTXW *pActCtx = (PVOID)ActivationContextData;
2344 const WCHAR *directory = NULL;
2345 PACTIVATION_CONTEXT_WRAPPED ActualActCtx;
2346 ACTIVATION_CONTEXT *actctx;
2347 UNICODE_STRING nameW;
2348 ULONG lang = 0;
2349 NTSTATUS status = STATUS_NO_MEMORY;
2350 HANDLE file = 0;
2351 struct actctx_loader acl;
2352
2353 DPRINT("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
2354
2355 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
2356 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
2357 return STATUS_INVALID_PARAMETER;
2358
2359
2360 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx))))
2361 return STATUS_NO_MEMORY;
2362
2363 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER;
2364
2365 actctx = &ActualActCtx->ActivationContext;
2366 actctx->RefCount = 1;
2367 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2368 actctx->config.info = NULL;
2369 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
2370 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
2371 {
2372 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
2373 }
2374 else
2375 {
2376 UNICODE_STRING dir;
2377 WCHAR *p;
2378 HMODULE module;
2379
2380 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
2381 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
2382
2383 status = get_module_filename(module, &dir, 0);
2384 if (!NT_SUCCESS(status)) goto error;
2385 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
2386 actctx->appdir.info = dir.Buffer;
2387 }
2388
2389 nameW.Buffer = NULL;
2390 if (pActCtx->lpSource)
2391 {
2392 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
2393 {
2394 status = STATUS_NO_SUCH_FILE;
2395 goto error;
2396 }
2397 status = open_nt_file( &file, &nameW );
2398 if (!NT_SUCCESS(status))
2399 {
2400 RtlFreeUnicodeString( &nameW );
2401 goto error;
2402 }
2403 }
2404
2405 acl.actctx = actctx;
2406 acl.dependencies = NULL;
2407 acl.num_dependencies = 0;
2408 acl.allocated_dependencies = 0;
2409
2410 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
2411 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
2412
2413 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
2414 {
2415 /* if we have a resource it's a PE file */
2416 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
2417 {
2418 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
2419 pActCtx->lpResourceName, lang );
2420 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
2421 /* FIXME: what to do if pActCtx->lpSource is set */
2422 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
2423 pActCtx->hModule, pActCtx->lpResourceName );
2424 }
2425 else if (pActCtx->lpSource)
2426 {
2427 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
2428 file, pActCtx->lpResourceName, lang );
2429 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
2430 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
2431 NULL, pActCtx->lpResourceName );
2432 }
2433 else status = STATUS_INVALID_PARAMETER;
2434 }
2435 else
2436 {
2437 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
2438 }
2439
2440 if (file) NtClose( file );
2441 RtlFreeUnicodeString( &nameW );
2442
2443 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl);
2444 free_depend_manifests( &acl );
2445
2446 if (NT_SUCCESS(status))
2447 *ActCtx = actctx;
2448 else actctx_release( actctx );
2449 return status;
2450
2451 error:
2452 if (file) NtClose( file );
2453 actctx_release( actctx );
2454 return status;
2455 }
2456
2457 #if 0
2458 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1)
2459
2460 VOID
2461 NTAPI
2462 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle)
2463 {
2464 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle;
2465 LONG OldRefCount, NewRefCount;
2466
2467 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
2468 {
2469 RtlpValidateActCtx(ActCtx);
2470
2471 while (TRUE)
2472 {
2473 OldRefCount = ActCtx->RefCount;
2474 ASSERT(OldRefCount > 0);
2475
2476 if (OldRefCount == LONG_MAX) break;
2477
2478 NewRefCount = OldRefCount + 1;
2479 if (InterlockedCompareExchange(&ActCtx->RefCount,
2480 NewRefCount,
2481 OldRefCount) == OldRefCount)
2482 {
2483 break;
2484 }
2485 }
2486
2487 NewRefCount = LONG_MAX;
2488 ASSERT(NewRefCount > 0);
2489 }
2490 }
2491
2492 VOID
2493 NTAPI
2494 RtlReleaseActivationContext( HANDLE handle )
2495 {
2496 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle;
2497
2498 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX))
2499 {
2500 RtlpValidateActCtx(ActCtx);
2501
2502 actctx_release(ActCtx);
2503 }
2504 }
2505 #else
2506 VOID
2507 NTAPI
2508 RtlAddRefActivationContext( HANDLE handle )
2509 {
2510 ACTIVATION_CONTEXT *actctx;
2511
2512 if ((actctx = check_actctx(handle))) actctx_addref(actctx);
2513 }
2514
2515 VOID
2516 NTAPI
2517 RtlReleaseActivationContext( HANDLE handle )
2518 {
2519 ACTIVATION_CONTEXT *actctx;
2520
2521 if ((actctx = check_actctx(handle))) actctx_release(actctx);
2522 }
2523 #endif
2524
2525 NTSTATUS
2526 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
2527 {
2528 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2529
2530 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
2531 return STATUS_NO_MEMORY;
2532
2533 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
2534 frame->ActivationContext = handle;
2535 frame->Flags = 0;
2536
2537 tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
2538 RtlAddRefActivationContext( handle );
2539
2540 *cookie = (ULONG_PTR)frame;
2541 DPRINT( "%p cookie=%lx\n", handle, *cookie );
2542 return STATUS_SUCCESS;
2543 }
2544
2545
2546 NTSTATUS
2547 NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
2548 {
2549 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
2550 }
2551
2552 NTSTATUS
2553 NTAPI
2554 RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
2555 {
2556 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
2557
2558 DPRINT( "%x cookie=%lx\n", flags, cookie );
2559
2560 /* find the right frame */
2561 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2562 for (frame = top; frame; frame = frame->Previous)
2563 if ((ULONG_PTR)frame == cookie) break;
2564
2565 if (!frame)
2566 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
2567
2568 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION))
2569 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
2570
2571 /* pop everything up to and including frame */
2572 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
2573
2574 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2575 {
2576 frame = top->Previous;
2577 RtlReleaseActivationContext( top->ActivationContext );
2578 RtlFreeHeap( RtlGetProcessHeap(), 0, top );
2579 top = frame;
2580 }
2581
2582 return STATUS_SUCCESS;
2583 }
2584
2585 VOID
2586 NTAPI
2587 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack)
2588 {
2589 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
2590
2591 /* Nothing to do if there is no stack */
2592 if (!Stack) return;
2593
2594 /* Get the current active frame */
2595 ActiveFrame = Stack->ActiveFrame;
2596
2597 /* Go through them in backwards order and release */
2598 while (ActiveFrame)
2599 {
2600 PrevFrame = ActiveFrame->Previous;
2601 RtlReleaseActivationContext(ActiveFrame->ActivationContext);
2602 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
2603 ActiveFrame = PrevFrame;
2604 }
2605
2606 /* Zero out the active frame */
2607 Stack->ActiveFrame = NULL;
2608
2609 /* TODO: Empty the Frame List Cache */
2610 ASSERT(IsListEmpty(&Stack->FrameListCache));
2611
2612 /* Free activation stack memory */
2613 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
2614 }
2615
2616 VOID
2617 NTAPI RtlFreeThreadActivationContextStack(VOID)
2618 {
2619 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
2620 NtCurrentTeb()->ActivationContextStackPointer = NULL;
2621 }
2622
2623
2624 NTSTATUS
2625 NTAPI RtlGetActiveActivationContext( HANDLE *handle )
2626 {
2627 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2628 {
2629 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
2630 RtlAddRefActivationContext( *handle );
2631 }
2632 else
2633 *handle = 0;
2634
2635 return STATUS_SUCCESS;
2636 }
2637
2638
2639 BOOLEAN
2640 NTAPI RtlIsActivationContextActive( HANDLE handle )
2641 {
2642 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2643
2644 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
2645 if (frame->ActivationContext == handle) return TRUE;
2646 return FALSE;
2647 }
2648
2649 NTSTATUS
2650 NTAPI
2651 RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
2652 ULONG class, PVOID buffer,
2653 SIZE_T bufsize, SIZE_T *retlen )
2654 {
2655 ACTIVATION_CONTEXT *actctx;
2656 NTSTATUS status;
2657
2658 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle,
2659 subinst, class, buffer, bufsize, retlen);
2660
2661 if (retlen) *retlen = 0;
2662 if ((status = find_query_actctx( &handle, flags, class ))) return status;
2663
2664 switch (class)
2665 {
2666 case ActivationContextBasicInformation:
2667 {
2668 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
2669
2670 if (retlen) *retlen = sizeof(*info);
2671 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
2672
2673 info->hActCtx = handle;
2674 info->dwFlags = 0; /* FIXME */
2675 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle);
2676 }
2677 break;
2678
2679 case ActivationContextDetailedInformation:
2680 {
2681 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
2682 struct assembly *assembly = NULL;
2683 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
2684 LPWSTR ptr;
2685
2686 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2687
2688 if (actctx->num_assemblies) assembly = actctx->assemblies;
2689
2690 if (assembly && assembly->manifest.info)
2691 manifest_len = strlenW(assembly->manifest.info) + 1;
2692 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
2693 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
2694 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
2695
2696 if (retlen) *retlen = len;
2697 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
2698
2699 acdi->dwFlags = 0;
2700 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
2701 acdi->ulAssemblyCount = actctx->num_assemblies;
2702 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
2703 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
2704 acdi->ulRootConfigurationPathType = actctx->config.type;
2705 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
2706 acdi->ulAppDirPathType = actctx->appdir.type;
2707 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
2708 ptr = (LPWSTR)(acdi + 1);
2709 if (manifest_len)
2710 {
2711 acdi->lpRootManifestPath = ptr;
2712 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
2713 ptr += manifest_len;
2714 }
2715 else acdi->lpRootManifestPath = NULL;
2716 if (config_len)
2717 {
2718 acdi->lpRootConfigurationPath = ptr;
2719 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
2720 ptr += config_len;
2721 }
2722 else acdi->lpRootConfigurationPath = NULL;
2723 if (appdir_len)
2724 {
2725 acdi->lpAppDirPath = ptr;
2726 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
2727 }
2728 else acdi->lpAppDirPath = NULL;
2729 }
2730 break;
2731
2732 case AssemblyDetailedInformationInActivationContext:
2733 {
2734 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
2735 struct assembly *assembly;
2736 WCHAR *assembly_id;
2737 DWORD index;
2738 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
2739 LPWSTR ptr;
2740
2741 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2742 if (!subinst) return STATUS_INVALID_PARAMETER;
2743
2744 index = *(DWORD*)subinst;
2745 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
2746
2747 assembly = &actctx->assemblies[index - 1];
2748
2749 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
2750 id_len = strlenW(assembly_id) + 1;
2751 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
2752
2753 if (assembly->manifest.info &&
2754 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
2755 path_len = strlenW(assembly->manifest.info) + 1;
2756
2757 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
2758
2759 if (retlen) *retlen = len;
2760 if (!buffer || bufsize < len)
2761 {
2762 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
2763 return STATUS_BUFFER_TOO_SMALL;
2764 }
2765
2766 afdi->ulFlags = 0; /* FIXME */
2767 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
2768 afdi->ulManifestPathType = assembly->manifest.type;
2769 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
2770 /* FIXME afdi->liManifestLastWriteTime = 0; */
2771 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
2772 afdi->ulPolicyPathLength = 0;
2773 /* FIXME afdi->liPolicyLastWriteTime = 0; */
2774 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
2775 afdi->ulManifestVersionMajor = 1;
2776 afdi->ulManifestVersionMinor = 0;
2777 afdi->ulPolicyVersionMajor = 0; /* FIXME */
2778 afdi->ulPolicyVersionMinor = 0; /* FIXME */
2779 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
2780 ptr = (LPWSTR)(afdi + 1);
2781 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
2782 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
2783 ptr += id_len;
2784 if (path_len)
2785 {
2786 afdi->lpAssemblyManifestPath = ptr;
2787 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
2788 ptr += path_len;
2789 } else afdi->lpAssemblyManifestPath = NULL;
2790 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
2791 if (ad_len)
2792 {
2793 afdi->lpAssemblyDirectoryName = ptr;
2794 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
2795 ptr += ad_len;
2796 }
2797 else afdi->lpAssemblyDirectoryName = NULL;
2798 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
2799 }
2800 break;
2801
2802 case FileInformationInAssemblyOfAssemblyInActivationContext:
2803 {
2804 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
2805 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
2806 struct assembly *assembly;
2807 struct dll_redirect *dll;
2808 SIZE_T len, dll_len = 0;
2809 LPWSTR ptr;
2810
2811 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2812 if (!acqi) return STATUS_INVALID_PARAMETER;
2813
2814 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
2815 return STATUS_INVALID_PARAMETER;
2816 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
2817
2818 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
2819 return STATUS_INVALID_PARAMETER;
2820 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
2821
2822 if (dll->name) dll_len = strlenW(dll->name) + 1;
2823 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
2824
2825 if (!buffer || bufsize < len)
2826 {
2827 if (retlen) *retlen = len;
2828 return STATUS_BUFFER_TOO_SMALL;
2829 }
2830 if (retlen) *retlen = 0; /* yes that's what native does !! */
2831 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
2832 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
2833 afdi->ulPathLength = 0; /* FIXME */
2834 ptr = (LPWSTR)(afdi + 1);
2835 if (dll_len)
2836 {
2837 afdi->lpFileName = ptr;
2838 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
2839 } else afdi->lpFileName = NULL;
2840 afdi->lpFilePath = NULL; /* FIXME */
2841 }
2842 break;
2843
2844 default:
2845 DPRINT( "class %u not implemented\n", class );
2846 return STATUS_NOT_IMPLEMENTED;
2847 }
2848 return STATUS_SUCCESS;
2849 }
2850
2851 NTSTATUS
2852 NTAPI
2853 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
2854 PVOID pvBuffer,
2855 SIZE_T cbBuffer OPTIONAL,
2856 SIZE_T *pcbWrittenOrRequired OPTIONAL)
2857 {
2858 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT,
2859 NULL,
2860 NULL,
2861 ulInfoClass,
2862 pvBuffer,
2863 cbBuffer,
2864 pcbWrittenOrRequired);
2865 }
2866
2867 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
2868 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
2869 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
2870
2871 NTSTATUS
2872 NTAPI
2873 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
2874 UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
2875 {
2876 /* Check general parameter combinations */
2877 if (!section_name ||
2878 (flags & ~FIND_ACTCTX_VALID_MASK) ||
2879 ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
2880 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
2881 {
2882 DPRINT1("invalid parameter\n");
2883 return STATUS_INVALID_PARAMETER;
2884 }
2885
2886 /* TODO */
2887 if (flags & FIND_ACTCTX_RETURN_FLAGS ||
2888 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
2889 {
2890 DPRINT1("unknown flags %08x\n", flags);
2891 return STATUS_INVALID_PARAMETER;
2892 }
2893
2894 return STATUS_SUCCESS;
2895 }
2896
2897 NTSTATUS
2898 NTAPI
2899 RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
2900 UNICODE_STRING *section_name, PVOID ptr )
2901 {
2902 PACTCTX_SECTION_KEYED_DATA data = ptr;
2903 NTSTATUS status;
2904
2905 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
2906 if (!NT_SUCCESS(status)) return status;
2907
2908 status = STATUS_SXS_KEY_NOT_FOUND;
2909
2910 /* if there is no data, but params are valid,
2911 we return that sxs key is not found to be at least somehow compatible */
2912 if (!data) return status;
2913
2914 ASSERT(NtCurrentTeb());
2915 ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
2916
2917 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2918 {
2919 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
2920 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
2921 }
2922
2923 if (status != STATUS_SUCCESS)
2924 status = find_string( process_actctx, section_kind, section_name, flags, data );
2925
2926 return status;
2927 }
2928
2929 NTSTATUS
2930 NTAPI
2931 RtlFindActivationContextSectionGuid(ULONG flags, const GUID *guid, ULONG section_kind, UNICODE_STRING *section_name, PVOID ptr)
2932 {
2933 UNIMPLEMENTED;
2934 return STATUS_NOT_IMPLEMENTED;
2935 }
2936
2937 /* Stubs */
2938
2939 NTSTATUS
2940 NTAPI
2941 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack)
2942 {
2943 PACTIVATION_CONTEXT_STACK ContextStack;
2944
2945 /* Check if it's already allocated */
2946 if (*Stack) return STATUS_SUCCESS;
2947
2948 /* Allocate space for the context stack */
2949 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK));
2950 if (!ContextStack)
2951 {
2952 return STATUS_NO_MEMORY;
2953 }
2954
2955 /* Initialize the context stack */
2956 ContextStack->Flags = 0;
2957 ContextStack->ActiveFrame = NULL;
2958 InitializeListHead(&ContextStack->FrameListCache);
2959 ContextStack->NextCookieSequenceNumber = 1;
2960 ContextStack->StackId = 1; //TODO: Timer-based
2961
2962 *Stack = ContextStack;
2963
2964 return STATUS_SUCCESS;
2965 }
2966
2967 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
2968 FASTCALL
2969 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
2970 IN PVOID Context)
2971 {
2972 #if NEW_NTDLL_LOADER
2973 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
2974
2975 /* Get the curren active frame */
2976 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2977
2978 DPRINT1("ActiveFrame %p, &Frame->Frame %p, Context %p\n", ActiveFrame, &Frame->Frame, Context);
2979
2980 /* Actually activate it */
2981 Frame->Frame.Previous = ActiveFrame;
2982 Frame->Frame.ActivationContext = Context;
2983 Frame->Frame.Flags = 0;
2984
2985 /* Check if we can activate this context */
2986 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
2987 Context)
2988 {
2989 /* Set new active frame */
2990 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
2991 return &Frame->Frame;
2992 }
2993
2994 /* We can get here only one way: it was already activated */
2995 DPRINT1("Trying to activate improper activation context\n");
2996
2997 /* Activate only if we are allowing multiple activation */
2998 if (!RtlpNotAllowingMultipleActivation)
2999 {
3000 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
3001 }
3002 else
3003 {
3004 /* Set flag */
3005 Frame->Frame.Flags = 0x30;
3006 }
3007
3008 /* Return pointer to the activation frame */
3009 return &Frame->Frame;
3010 #else
3011
3012 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame;
3013
3014 frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
3015 frame->ActivationContext = Context;
3016 frame->Flags = 0;
3017
3018 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
3019
3020 return STATUS_SUCCESS;
3021 #endif
3022 }
3023
3024 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
3025 FASTCALL
3026 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
3027 {
3028 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
3029 //RTL_ACTIVATION_CONTEXT_STACK_FRAME *top;
3030
3031 /* find the right frame */
3032 //top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
3033 frame = &Frame->Frame;
3034
3035 if (!frame)
3036 {
3037 DPRINT1("No top frame!\n");
3038 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
3039 }
3040
3041 /* pop everything up to and including frame */
3042 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
3043
3044 return frame;
3045 }
3046
3047
3048 NTSTATUS
3049 NTAPI
3050 RtlZombifyActivationContext(PVOID Context)
3051 {
3052 UNIMPLEMENTED;
3053
3054 if (Context == ACTCTX_FAKE_HANDLE)
3055 return STATUS_SUCCESS;
3056
3057 return STATUS_NOT_IMPLEMENTED;
3058 }
3059