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