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