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