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