[USB]
[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 /* let's assume utf-8 for now */
1580 size_t len;
1581 WCHAR *new_buff;
1582
1583 _SEH2_TRY
1584 {
1585 len = mbstowcs(NULL, buffer, size);
1586 }
1587 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1588 {
1589 DPRINT1("Exception accessing buffer\n");
1590 return STATUS_SXS_CANT_GEN_ACTCTX;
1591 }
1592 _SEH2_END;
1593
1594 DPRINT("len = %x\n", len);
1595
1596 if (len == -1)
1597 {
1598 DPRINT1( "utf-8 conversion failed\n" );
1599 return STATUS_SXS_CANT_GEN_ACTCTX;
1600 }
1601 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, len)))
1602 return STATUS_NO_MEMORY;
1603
1604 mbstowcs( new_buff, buffer, size);
1605 xmlbuf.ptr = new_buff;
1606
1607 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
1608 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
1609
1610 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
1611 }
1612 return status;
1613 }
1614
1615 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
1616 {
1617 OBJECT_ATTRIBUTES attr;
1618 IO_STATUS_BLOCK io;
1619
1620 attr.Length = sizeof(attr);
1621 attr.RootDirectory = 0;
1622 attr.Attributes = OBJ_CASE_INSENSITIVE;
1623 attr.ObjectName = name;
1624 attr.SecurityDescriptor = NULL;
1625 attr.SecurityQualityOfService = NULL;
1626 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
1627 }
1628
1629 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len )
1630 {
1631 NTSTATUS status;
1632 ULONG magic;
1633 LDR_DATA_TABLE_ENTRY *pldr;
1634
1635 LdrLockLoaderLock(0, NULL, &magic);
1636 status = LdrFindEntryForAddress( module, &pldr );
1637 if (status == STATUS_SUCCESS)
1638 {
1639 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1640 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
1641 {
1642 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
1643 str->Length = pldr->FullDllName.Length;
1644 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
1645 }
1646 else status = STATUS_NO_MEMORY;
1647 }
1648 LdrUnlockLoaderLock(0, magic);
1649 return status;
1650 }
1651
1652 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
1653 LPCWSTR filename, LPCWSTR directory, BOOL shared,
1654 HANDLE hModule, LPCWSTR resname, ULONG lang )
1655 {
1656 NTSTATUS status;
1657 UNICODE_STRING nameW;
1658 LDR_RESOURCE_INFO info;
1659 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
1660 void *ptr;
1661
1662 //DPRINT( "looking for res %s in module %p %s\n", resname,
1663 // hModule, filename );
1664
1665 #if 0
1666 if (TRACE_ON(actctx))
1667 {
1668 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
1669 {
1670 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
1671 hModule, debugstr_w(nameW.Buffer) );
1672 RtlFreeUnicodeString( &nameW );
1673 }
1674 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
1675 hModule, debugstr_w(filename) );
1676 }
1677 #endif
1678
1679 if (!resname) return STATUS_INVALID_PARAMETER;
1680
1681 info.Type = (ULONG_PTR)RT_MANIFEST;
1682 info.Language = lang;
1683 if (!((ULONG_PTR)resname >> 16))
1684 {
1685 info.Name = (ULONG_PTR)resname;
1686 status = LdrFindResource_U(hModule, &info, 3, &entry);
1687 }
1688 else if (resname[0] == '#')
1689 {
1690 ULONG value;
1691 RtlInitUnicodeString(&nameW, resname + 1);
1692 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
1693 return STATUS_INVALID_PARAMETER;
1694 info.Name = value;
1695 status = LdrFindResource_U(hModule, &info, 3, &entry);
1696 }
1697 else
1698 {
1699 RtlCreateUnicodeString(&nameW, resname);
1700 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
1701 info.Name = (ULONG_PTR)nameW.Buffer;
1702 status = LdrFindResource_U(hModule, &info, 3, &entry);
1703 RtlFreeUnicodeString(&nameW);
1704 }
1705 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
1706
1707 if (status == STATUS_SUCCESS)
1708 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
1709
1710 return status;
1711 }
1712
1713 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
1714 LPCWSTR filename, LPCWSTR directory, BOOL shared,
1715 HANDLE file, LPCWSTR resname, ULONG lang )
1716 {
1717 HANDLE mapping;
1718 OBJECT_ATTRIBUTES attr;
1719 LARGE_INTEGER size;
1720 LARGE_INTEGER offset;
1721 NTSTATUS status;
1722 SIZE_T count;
1723 void *base;
1724
1725 DPRINT( "looking for res %S in %S\n", resname, filename );
1726
1727 attr.Length = sizeof(attr);
1728 attr.RootDirectory = 0;
1729 attr.ObjectName = NULL;
1730 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1731 attr.SecurityDescriptor = NULL;
1732 attr.SecurityQualityOfService = NULL;
1733
1734 size.QuadPart = 0;
1735 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1736 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1737 if (status != STATUS_SUCCESS) return status;
1738
1739 offset.QuadPart = 0;
1740 count = 0;
1741 base = NULL;
1742 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
1743 &count, ViewShare, 0, PAGE_READONLY );
1744 NtClose( mapping );
1745 if (status != STATUS_SUCCESS) return status;
1746
1747 if (RtlImageNtHeader(base)) /* we got a PE file */
1748 {
1749 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
1750 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
1751 }
1752 else status = STATUS_INVALID_IMAGE_FORMAT;
1753
1754 NtUnmapViewOfSection( NtCurrentProcess(), base );
1755 return status;
1756 }
1757
1758 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
1759 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
1760 {
1761 FILE_STANDARD_INFORMATION info;
1762 IO_STATUS_BLOCK io;
1763 HANDLE mapping;
1764 OBJECT_ATTRIBUTES attr;
1765 LARGE_INTEGER size;
1766 LARGE_INTEGER offset;
1767 NTSTATUS status;
1768 SIZE_T count;
1769 void *base;
1770
1771 DPRINT( "loading manifest file %S\n", filename );
1772
1773 attr.Length = sizeof(attr);
1774 attr.RootDirectory = 0;
1775 attr.ObjectName = NULL;
1776 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
1777 attr.SecurityDescriptor = NULL;
1778 attr.SecurityQualityOfService = NULL;
1779
1780 size.QuadPart = 0;
1781 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1782 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
1783
1784 if (status != STATUS_SUCCESS) return status;
1785
1786 offset.QuadPart = 0;
1787 count = 0;
1788 base = NULL;
1789 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
1790 &count, ViewShare, 0, PAGE_READONLY );
1791
1792 if (status != STATUS_SUCCESS) return status;
1793
1794 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
1795 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
1796
1797 if (status == STATUS_SUCCESS)
1798 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart);
1799
1800 NtUnmapViewOfSection( NtCurrentProcess(), base );
1801 NtClose( mapping );
1802 return status;
1803 }
1804
1805 /* try to load the .manifest file associated to the file */
1806 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
1807 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
1808 {
1809 static const WCHAR fmtW[] = { '.','%','l','u',0 };
1810 WCHAR *buffer;
1811 NTSTATUS status;
1812 UNICODE_STRING nameW;
1813 HANDLE file;
1814 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
1815
1816 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
1817
1818 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
1819
1820 if (module) /* use the module filename */
1821 {
1822 UNICODE_STRING name;
1823
1824 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
1825 {
1826 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
1827 strcatW( name.Buffer, dotManifestW );
1828 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
1829 status = STATUS_RESOURCE_DATA_NOT_FOUND;
1830 RtlFreeUnicodeString( &name );
1831 }
1832 if (status) return status;
1833 }
1834 else
1835 {
1836 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1837 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
1838 return STATUS_NO_MEMORY;
1839 strcpyW( buffer, filename );
1840 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
1841 strcatW( buffer, dotManifestW );
1842 RtlInitUnicodeString( &nameW, buffer );
1843 }
1844
1845 if (!open_nt_file( &file, &nameW ))
1846 {
1847 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
1848 NtClose( file );
1849 }
1850 else status = STATUS_RESOURCE_DATA_NOT_FOUND;
1851 RtlFreeUnicodeString( &nameW );
1852 return status;
1853 }
1854
1855 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
1856 {
1857 static const WCHAR lookup_fmtW[] =
1858 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
1859 '*', /* FIXME */
1860 '.','m','a','n','i','f','e','s','t',0};
1861
1862 WCHAR *lookup, *ret = NULL;
1863 UNICODE_STRING lookup_us;
1864 IO_STATUS_BLOCK io;
1865 unsigned int data_pos = 0, data_len;
1866 char buffer[8192];
1867
1868 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1869 (strlenW(ai->arch) + strlenW(ai->name)
1870 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
1871 + sizeof(lookup_fmtW) )))
1872 return NULL;
1873
1874 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
1875 RtlInitUnicodeString( &lookup_us, lookup );
1876
1877 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1878 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
1879 if (io.Status == STATUS_SUCCESS)
1880 {
1881 FILE_BOTH_DIR_INFORMATION *dir_info;
1882 WCHAR *tmp;
1883 ULONG build, revision;
1884
1885 data_len = (ULONG)io.Information;
1886
1887 for (;;)
1888 {
1889 if (data_pos >= data_len)
1890 {
1891 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
1892 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
1893 if (io.Status != STATUS_SUCCESS) break;
1894 data_len = (ULONG)io.Information;
1895 data_pos = 0;
1896 }
1897 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
1898
1899 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
1900 else data_pos = data_len;
1901
1902 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
1903 build = atoiW(tmp);
1904 if (build < ai->version.build) continue;
1905 tmp = strchrW(tmp, '.') + 1;
1906 revision = atoiW(tmp);
1907 if (build == ai->version.build && revision < ai->version.revision)
1908 continue;
1909 ai->version.build = (USHORT)build;
1910 ai->version.revision = (USHORT)revision;
1911
1912 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) )))
1913 {
1914 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
1915 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
1916 }
1917 break;
1918 }
1919 }
1920 else DPRINT1("no matching file for %S\n", lookup);
1921 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
1922 return ret;
1923 }
1924
1925 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
1926 {
1927 struct assembly_identity sxs_ai;
1928 UNICODE_STRING path_us;
1929 OBJECT_ATTRIBUTES attr;
1930 IO_STATUS_BLOCK io;
1931 WCHAR *path, *file = NULL;
1932 HANDLE handle;
1933
1934 static const WCHAR manifest_dirW[] =
1935 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
1936
1937 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
1938
1939 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0,
1940 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
1941 return STATUS_NO_MEMORY;
1942
1943 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
1944 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
1945
1946 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
1947 {
1948 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
1949 return STATUS_NO_SUCH_FILE;
1950 }
1951 RtlFreeHeap( RtlGetProcessHeap(), 0, path );
1952
1953 attr.Length = sizeof(attr);
1954 attr.RootDirectory = 0;
1955 attr.Attributes = OBJ_CASE_INSENSITIVE;
1956 attr.ObjectName = &path_us;
1957 attr.SecurityDescriptor = NULL;
1958 attr.SecurityQualityOfService = NULL;
1959
1960 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
1961 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
1962 {
1963 sxs_ai = *ai;
1964 file = lookup_manifest_file( handle, &sxs_ai );
1965 NtClose( handle );
1966 }
1967 if (!file)
1968 {
1969 RtlFreeUnicodeString( &path_us );
1970 return STATUS_NO_SUCH_FILE;
1971 }
1972
1973 /* append file name to directory path */
1974 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
1975 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
1976 {
1977 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
1978 RtlFreeUnicodeString( &path_us );
1979 return STATUS_NO_MEMORY;
1980 }
1981
1982 path[path_us.Length/sizeof(WCHAR)] = '\\';
1983 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
1984 RtlInitUnicodeString( &path_us, path );
1985 *strrchrW(file, '.') = 0; /* remove .manifest extension */
1986
1987 if (!open_nt_file( &handle, &path_us ))
1988 {
1989 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
1990 NtClose( handle );
1991 }
1992 else io.Status = STATUS_NO_SUCH_FILE;
1993
1994 RtlFreeHeap( RtlGetProcessHeap(), 0, file );
1995 RtlFreeUnicodeString( &path_us );
1996 return io.Status;
1997 }
1998
1999 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2000 struct assembly_identity* ai)
2001 {
2002 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2003 unsigned int i;
2004 WCHAR *buffer, *p, *directory;
2005 NTSTATUS status;
2006 UNICODE_STRING nameW;
2007 HANDLE file;
2008
2009 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
2010 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
2011
2012 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2013
2014 /* FIXME: add support for language specific lookup */
2015
2016 nameW.Buffer = NULL;
2017 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
2018 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2019 return STATUS_NO_MEMORY;
2020
2021 if (!(directory = build_assembly_dir( ai )))
2022 {
2023 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
2024 return STATUS_NO_MEMORY;
2025 }
2026
2027 /* lookup in appdir\name.dll
2028 * appdir\name.manifest
2029 * appdir\name\name.dll
2030 * appdir\name\name.manifest
2031 */
2032 strcpyW( buffer, acl->actctx->appdir.info );
2033 p = buffer + strlenW(buffer);
2034 for (i = 0; i < 2; i++)
2035 {
2036 *p++ = '\\';
2037 strcpyW( p, ai->name );
2038 p += strlenW(p);
2039
2040 strcpyW( p, dotDllW );
2041 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2042 {
2043 status = open_nt_file( &file, &nameW );
2044 if (!status)
2045 {
2046 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2047 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2048 NtClose( file );
2049 break;
2050 }
2051 RtlFreeUnicodeString( &nameW );
2052 }
2053
2054 strcpyW( p, dotManifestW );
2055 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2056 {
2057 status = open_nt_file( &file, &nameW );
2058 if (!status)
2059 {
2060 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2061 NtClose( file );
2062 break;
2063 }
2064 RtlFreeUnicodeString( &nameW );
2065 }
2066 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2067 }
2068 RtlFreeUnicodeString( &nameW );
2069 RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
2070 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
2071 return status;
2072 }
2073
2074 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2075 {
2076 NTSTATUS status = STATUS_SUCCESS;
2077 unsigned int i;
2078
2079 for (i = 0; i < acl->num_dependencies; i++)
2080 {
2081 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2082 {
2083 if (!acl->dependencies[i].optional)
2084 {
2085 DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
2086 status = STATUS_SXS_CANT_GEN_ACTCTX;
2087 break;
2088 }
2089 }
2090 }
2091 /* FIXME should now iterate through all refs */
2092 return status;
2093 }
2094
2095 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2096 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2097 {
2098 NTSTATUS status = STATUS_SUCCESS;
2099
2100 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2101 {
2102 if (*handle) return STATUS_INVALID_PARAMETER;
2103
2104 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2105 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
2106 }
2107 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2108 {
2109 ULONG magic;
2110 LDR_DATA_TABLE_ENTRY *pldr;
2111
2112 if (!*handle) return STATUS_INVALID_PARAMETER;
2113
2114 LdrLockLoaderLock( 0, NULL, &magic );
2115 if (!LdrFindEntryForAddress( *handle, &pldr ))
2116 {
2117 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
2118 status = STATUS_DLL_NOT_FOUND;
2119 else
2120 *handle = pldr->EntryPointActivationContext;
2121 }
2122 else status = STATUS_DLL_NOT_FOUND;
2123 LdrUnlockLoaderLock( 0, magic );
2124 }
2125 else if (!*handle && (class != ActivationContextBasicInformation))
2126 *handle = process_actctx;
2127
2128 return status;
2129 }
2130
2131 static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
2132 {
2133 data->ulDataFormatVersion = 1;
2134 data->lpData = v1;
2135 data->ulLength = 20; /* FIXME */
2136 data->lpSectionGlobalData = NULL; /* FIXME */
2137 data->ulSectionGlobalDataLength = 0; /* FIXME */
2138 data->lpSectionBase = v2;
2139 data->ulSectionTotalLength = 0; /* FIXME */
2140 data->hActCtx = NULL;
2141 if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
2142 data->ulAssemblyRosterIndex = i + 1;
2143
2144 return STATUS_SUCCESS;
2145 }
2146
2147 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
2148 PACTCTX_SECTION_KEYED_DATA data)
2149 {
2150 unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
2151
2152 for (i = 0; i < actctx->num_assemblies; i++)
2153 {
2154 struct assembly *assembly = &actctx->assemblies[i];
2155 for (j = 0; j < assembly->num_dlls; j++)
2156 {
2157 struct dll_redirect *dll = &assembly->dlls[j];
2158 if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
2159 return fill_keyed_data(data, dll, assembly, i);
2160 }
2161 }
2162 return STATUS_SXS_KEY_NOT_FOUND;
2163 }
2164
2165 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
2166 PACTCTX_SECTION_KEYED_DATA data)
2167 {
2168 unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
2169
2170 for (i = 0; i < actctx->num_assemblies; i++)
2171 {
2172 struct assembly *assembly = &actctx->assemblies[i];
2173 for (j = 0; j < assembly->num_dlls; j++)
2174 {
2175 struct dll_redirect *dll = &assembly->dlls[j];
2176 for (k = 0; k < dll->entities.num; k++)
2177 {
2178 struct entity *entity = &dll->entities.base[k];
2179 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
2180 {
2181 if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
2182 return fill_keyed_data(data, entity, dll, i);
2183 }
2184 }
2185 }
2186 }
2187 return STATUS_SXS_KEY_NOT_FOUND;
2188 }
2189
2190 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
2191 const UNICODE_STRING *section_name,
2192 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
2193 {
2194 NTSTATUS status;
2195
2196 switch (section_kind)
2197 {
2198 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
2199 status = find_dll_redirection(actctx, section_name, data);
2200 break;
2201 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
2202 status = find_window_class(actctx, section_name, data);
2203 break;
2204 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
2205 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
2206 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
2207 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
2208 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
2209 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
2210 DPRINT1("Unsupported yet section_kind %x\n", section_kind);
2211 return STATUS_SXS_SECTION_NOT_FOUND;
2212 default:
2213 DPRINT1("Unknown section_kind %x\n", section_kind);
2214 return STATUS_SXS_SECTION_NOT_FOUND;
2215 }
2216
2217 if (status != STATUS_SUCCESS) return status;
2218
2219 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
2220 {
2221 actctx_addref(actctx);
2222 data->hActCtx = actctx;
2223 }
2224 return STATUS_SUCCESS;
2225 }
2226
2227 /* initialize the activation context for the current process */
2228 void actctx_init(void)
2229 {
2230 ACTCTXW ctx;
2231 HANDLE handle;
2232
2233 ctx.cbSize = sizeof(ctx);
2234 ctx.lpSource = NULL;
2235 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
2236 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
2237 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
2238
2239 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
2240 }
2241
2242 /* FUNCTIONS ***************************************************************/
2243
2244 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, void *ptr )
2245 {
2246 const ACTCTXW *pActCtx = ptr;
2247 const WCHAR *directory = NULL;
2248 ACTIVATION_CONTEXT *actctx;
2249 UNICODE_STRING nameW;
2250 ULONG lang = 0;
2251 NTSTATUS status = STATUS_NO_MEMORY;
2252 HANDLE file = 0;
2253 struct actctx_loader acl;
2254
2255 DPRINT("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
2256
2257 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
2258 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
2259 return STATUS_INVALID_PARAMETER;
2260
2261
2262 if (!(actctx = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
2263 return STATUS_NO_MEMORY;
2264
2265 actctx->magic = ACTCTX_MAGIC;
2266 actctx->ref_count = 1;
2267 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2268 actctx->config.info = NULL;
2269 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
2270 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
2271 {
2272 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
2273 }
2274 else
2275 {
2276 UNICODE_STRING dir;
2277 WCHAR *p;
2278 HMODULE module;
2279
2280 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
2281 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
2282
2283 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
2284 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
2285 actctx->appdir.info = dir.Buffer;
2286 }
2287
2288 nameW.Buffer = NULL;
2289 if (pActCtx->lpSource)
2290 {
2291 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
2292 {
2293 status = STATUS_NO_SUCH_FILE;
2294 goto error;
2295 }
2296 status = open_nt_file( &file, &nameW );
2297 if (status)
2298 {
2299 RtlFreeUnicodeString( &nameW );
2300 goto error;
2301 }
2302 }
2303
2304 acl.actctx = actctx;
2305 acl.dependencies = NULL;
2306 acl.num_dependencies = 0;
2307 acl.allocated_dependencies = 0;
2308
2309 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
2310 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
2311
2312 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
2313 {
2314 /* if we have a resource it's a PE file */
2315 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
2316 {
2317 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
2318 pActCtx->lpResourceName, lang );
2319 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
2320 /* FIXME: what to do if pActCtx->lpSource is set */
2321 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
2322 pActCtx->hModule, pActCtx->lpResourceName );
2323 }
2324 else if (pActCtx->lpSource)
2325 {
2326 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
2327 file, pActCtx->lpResourceName, lang );
2328 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
2329 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
2330 NULL, pActCtx->lpResourceName );
2331 }
2332 else status = STATUS_INVALID_PARAMETER;
2333 }
2334 else
2335 {
2336 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
2337 }
2338
2339 if (file) NtClose( file );
2340 RtlFreeUnicodeString( &nameW );
2341
2342 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
2343 free_depend_manifests( &acl );
2344
2345 if (status == STATUS_SUCCESS) *handle = actctx;
2346 else actctx_release( actctx );
2347 return status;
2348
2349 error:
2350 if (file) NtClose( file );
2351 actctx_release( actctx );
2352 return status;
2353 }
2354
2355 VOID
2356 NTAPI
2357 RtlAddRefActivationContext(HANDLE handle)
2358 {
2359 ACTIVATION_CONTEXT *actctx;
2360
2361 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
2362 }
2363
2364 VOID
2365 NTAPI
2366 RtlReleaseActivationContext( HANDLE handle )
2367 {
2368 ACTIVATION_CONTEXT *actctx;
2369
2370 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
2371 }
2372
2373 NTSTATUS
2374 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie )
2375 {
2376 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2377
2378 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
2379 return STATUS_NO_MEMORY;
2380
2381 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame;
2382 frame->ActivationContext = handle;
2383 frame->Flags = 0;
2384
2385 tebAddress->ActivationContextStackPointer->ActiveFrame = frame;
2386 RtlAddRefActivationContext( handle );
2387
2388 *cookie = (ULONG_PTR)frame;
2389 DPRINT( "%p cookie=%lx\n", handle, *cookie );
2390 return STATUS_SUCCESS;
2391 }
2392
2393
2394 NTSTATUS
2395 NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie )
2396 {
2397 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie);
2398 }
2399
2400 NTSTATUS
2401 NTAPI
2402 RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
2403 {
2404 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
2405
2406 DPRINT( "%x cookie=%lx\n", flags, cookie );
2407
2408 /* find the right frame */
2409 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2410 for (frame = top; frame; frame = frame->Previous)
2411 if ((ULONG_PTR)frame == cookie) break;
2412
2413 if (!frame)
2414 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
2415
2416 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
2417 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
2418
2419 /* pop everything up to and including frame */
2420 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
2421
2422 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2423 {
2424 frame = top->Previous;
2425 RtlReleaseActivationContext( top->ActivationContext );
2426 RtlFreeHeap( RtlGetProcessHeap(), 0, top );
2427 top = frame;
2428 }
2429
2430 return STATUS_SUCCESS;
2431 }
2432
2433 VOID
2434 NTAPI
2435 RtlFreeActivationContextStack(PACTIVATION_CONTEXT_STACK Stack)
2436 {
2437 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame;
2438
2439 /* Nothing to do if there is no stack */
2440 if (!Stack) return;
2441
2442 /* Get the current active frame */
2443 ActiveFrame = Stack->ActiveFrame;
2444
2445 /* Go through them in backwards order and release */
2446 while (ActiveFrame)
2447 {
2448 PrevFrame = ActiveFrame->Previous;
2449 RtlReleaseActivationContext(ActiveFrame->ActivationContext);
2450 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame);
2451 ActiveFrame = PrevFrame;
2452 }
2453
2454 /* Zero out the active frame */
2455 Stack->ActiveFrame = NULL;
2456
2457 /* TODO: Empty the Frame List Cache */
2458 ASSERT(IsListEmpty(&Stack->FrameListCache));
2459
2460 /* Free activation stack memory */
2461 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack);
2462 }
2463
2464 VOID
2465 NTAPI RtlFreeThreadActivationContextStack(void)
2466 {
2467 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer);
2468 NtCurrentTeb()->ActivationContextStackPointer = NULL;
2469 }
2470
2471
2472 NTSTATUS
2473 NTAPI RtlGetActiveActivationContext( HANDLE *handle )
2474 {
2475 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2476 {
2477 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
2478 RtlAddRefActivationContext( *handle );
2479 }
2480 else
2481 *handle = 0;
2482
2483 return STATUS_SUCCESS;
2484 }
2485
2486
2487 BOOLEAN
2488 NTAPI RtlIsActivationContextActive( HANDLE handle )
2489 {
2490 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2491
2492 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
2493 if (frame->ActivationContext == handle) return TRUE;
2494 return FALSE;
2495 }
2496
2497 NTSTATUS
2498 NTAPI
2499 RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
2500 ULONG class, PVOID buffer,
2501 SIZE_T bufsize, SIZE_T *retlen )
2502 {
2503 ACTIVATION_CONTEXT *actctx;
2504 NTSTATUS status;
2505
2506 DPRINT("%08x %p %p %u %p %ld %p\n", flags, handle,
2507 subinst, class, buffer, bufsize, retlen);
2508
2509 if (retlen) *retlen = 0;
2510 if ((status = find_query_actctx( &handle, flags, class ))) return status;
2511
2512 switch (class)
2513 {
2514 case ActivationContextBasicInformation:
2515 {
2516 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
2517
2518 if (retlen) *retlen = sizeof(*info);
2519 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
2520
2521 info->hActCtx = handle;
2522 info->dwFlags = 0; /* FIXME */
2523 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
2524 }
2525 break;
2526
2527 case ActivationContextDetailedInformation:
2528 {
2529 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
2530 struct assembly *assembly = NULL;
2531 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
2532 LPWSTR ptr;
2533
2534 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2535
2536 if (actctx->num_assemblies) assembly = actctx->assemblies;
2537
2538 if (assembly && assembly->manifest.info)
2539 manifest_len = strlenW(assembly->manifest.info) + 1;
2540 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
2541 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
2542 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
2543
2544 if (retlen) *retlen = len;
2545 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
2546
2547 acdi->dwFlags = 0;
2548 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
2549 acdi->ulAssemblyCount = actctx->num_assemblies;
2550 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
2551 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0;
2552 acdi->ulRootConfigurationPathType = actctx->config.type;
2553 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0;
2554 acdi->ulAppDirPathType = actctx->appdir.type;
2555 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0;
2556 ptr = (LPWSTR)(acdi + 1);
2557 if (manifest_len)
2558 {
2559 acdi->lpRootManifestPath = ptr;
2560 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
2561 ptr += manifest_len;
2562 }
2563 else acdi->lpRootManifestPath = NULL;
2564 if (config_len)
2565 {
2566 acdi->lpRootConfigurationPath = ptr;
2567 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
2568 ptr += config_len;
2569 }
2570 else acdi->lpRootConfigurationPath = NULL;
2571 if (appdir_len)
2572 {
2573 acdi->lpAppDirPath = ptr;
2574 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
2575 }
2576 else acdi->lpAppDirPath = NULL;
2577 }
2578 break;
2579
2580 case AssemblyDetailedInformationInActivationContext:
2581 {
2582 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
2583 struct assembly *assembly;
2584 WCHAR *assembly_id;
2585 DWORD index;
2586 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
2587 LPWSTR ptr;
2588
2589 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2590 if (!subinst) return STATUS_INVALID_PARAMETER;
2591
2592 index = *(DWORD*)subinst;
2593 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
2594
2595 assembly = &actctx->assemblies[index - 1];
2596
2597 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
2598 id_len = strlenW(assembly_id) + 1;
2599 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
2600
2601 if (assembly->manifest.info &&
2602 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
2603 path_len = strlenW(assembly->manifest.info) + 1;
2604
2605 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
2606
2607 if (retlen) *retlen = len;
2608 if (!buffer || bufsize < len)
2609 {
2610 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
2611 return STATUS_BUFFER_TOO_SMALL;
2612 }
2613
2614 afdi->ulFlags = 0; /* FIXME */
2615 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR);
2616 afdi->ulManifestPathType = assembly->manifest.type;
2617 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0;
2618 /* FIXME afdi->liManifestLastWriteTime = 0; */
2619 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
2620 afdi->ulPolicyPathLength = 0;
2621 /* FIXME afdi->liPolicyLastWriteTime = 0; */
2622 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
2623 afdi->ulManifestVersionMajor = 1;
2624 afdi->ulManifestVersionMinor = 0;
2625 afdi->ulPolicyVersionMajor = 0; /* FIXME */
2626 afdi->ulPolicyVersionMinor = 0; /* FIXME */
2627 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0;
2628 ptr = (LPWSTR)(afdi + 1);
2629 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
2630 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
2631 ptr += id_len;
2632 if (path_len)
2633 {
2634 afdi->lpAssemblyManifestPath = ptr;
2635 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
2636 ptr += path_len;
2637 } else afdi->lpAssemblyManifestPath = NULL;
2638 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
2639 if (ad_len)
2640 {
2641 afdi->lpAssemblyDirectoryName = ptr;
2642 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
2643 ptr += ad_len;
2644 }
2645 else afdi->lpAssemblyDirectoryName = NULL;
2646 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
2647 }
2648 break;
2649
2650 case FileInformationInAssemblyOfAssemblyInActivationContext:
2651 {
2652 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
2653 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
2654 struct assembly *assembly;
2655 struct dll_redirect *dll;
2656 SIZE_T len, dll_len = 0;
2657 LPWSTR ptr;
2658
2659 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
2660 if (!acqi) return STATUS_INVALID_PARAMETER;
2661
2662 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
2663 return STATUS_INVALID_PARAMETER;
2664 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
2665
2666 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
2667 return STATUS_INVALID_PARAMETER;
2668 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
2669
2670 if (dll->name) dll_len = strlenW(dll->name) + 1;
2671 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
2672
2673 if (!buffer || bufsize < len)
2674 {
2675 if (retlen) *retlen = len;
2676 return STATUS_BUFFER_TOO_SMALL;
2677 }
2678 if (retlen) *retlen = 0; /* yes that's what native does !! */
2679 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
2680 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0;
2681 afdi->ulPathLength = 0; /* FIXME */
2682 ptr = (LPWSTR)(afdi + 1);
2683 if (dll_len)
2684 {
2685 afdi->lpFileName = ptr;
2686 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
2687 } else afdi->lpFileName = NULL;
2688 afdi->lpFilePath = NULL; /* FIXME */
2689 }
2690 break;
2691
2692 default:
2693 DPRINT( "class %u not implemented\n", class );
2694 return STATUS_NOT_IMPLEMENTED;
2695 }
2696 return STATUS_SUCCESS;
2697 }
2698
2699 NTSTATUS
2700 NTAPI
2701 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass,
2702 PVOID pvBuffer,
2703 SIZE_T cbBuffer OPTIONAL,
2704 SIZE_T *pcbWrittenOrRequired OPTIONAL)
2705 {
2706 return RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX,
2707 NULL,
2708 NULL,
2709 ulInfoClass,
2710 pvBuffer,
2711 cbBuffer,
2712 pcbWrittenOrRequired);
2713 }
2714
2715 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002
2716 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
2717 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
2718
2719 NTSTATUS
2720 NTAPI
2721 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
2722 UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
2723 {
2724 /* Check general parameter combinations */
2725 if (!section_name ||
2726 (flags & ~FIND_ACTCTX_VALID_MASK) ||
2727 ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
2728 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
2729 {
2730 DPRINT1("invalid parameter\n");
2731 return STATUS_INVALID_PARAMETER;
2732 }
2733
2734 /* TODO */
2735 if (flags & FIND_ACTCTX_RETURN_FLAGS ||
2736 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
2737 {
2738 DPRINT1("unknown flags %08x\n", flags);
2739 return STATUS_INVALID_PARAMETER;
2740 }
2741
2742 return STATUS_SUCCESS;
2743 }
2744
2745 NTSTATUS
2746 NTAPI
2747 RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
2748 UNICODE_STRING *section_name, PVOID ptr )
2749 {
2750 PACTCTX_SECTION_KEYED_DATA data = ptr;
2751 NTSTATUS status;
2752
2753 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
2754 if (!NT_SUCCESS(status)) return status;
2755
2756 status = STATUS_SXS_KEY_NOT_FOUND;
2757
2758 /* if there is no data, but params are valid,
2759 we return that sxs key is not found to be at least somehow compatible */
2760 if (!data) return status;
2761
2762 ASSERT(NtCurrentTeb());
2763 ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
2764
2765 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
2766 {
2767 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
2768 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
2769 }
2770
2771 if (status != STATUS_SUCCESS)
2772 status = find_string( process_actctx, section_kind, section_name, flags, data );
2773
2774 return status;
2775 }
2776
2777 /* Stubs */
2778
2779 NTSTATUS
2780 NTAPI
2781 RtlAllocateActivationContextStack(IN PVOID *Context)
2782 {
2783 PACTIVATION_CONTEXT_STACK ContextStack;
2784
2785 /* Check if it's already allocated */
2786 if (*Context) return STATUS_SUCCESS;
2787
2788 /* Allocate space for the context stack */
2789 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
2790 if (!ContextStack)
2791 {
2792 return STATUS_NO_MEMORY;
2793 }
2794
2795 /* Initialize the context stack */
2796 ContextStack->Flags = 0;
2797 ContextStack->ActiveFrame = NULL;
2798 InitializeListHead(&ContextStack->FrameListCache);
2799 ContextStack->NextCookieSequenceNumber = 1;
2800 ContextStack->StackId = 1; //TODO: Timer-based
2801
2802 *Context = ContextStack;
2803
2804 return STATUS_SUCCESS;
2805 }
2806
2807 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
2808 FASTCALL
2809 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
2810 IN PVOID Context)
2811 {
2812 #if NEW_NTDLL_LOADER
2813 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
2814
2815 /* Get the curren active frame */
2816 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2817
2818 DPRINT1("ActiveFrame %p, &Frame->Frame %p, Context %p\n", ActiveFrame, &Frame->Frame, Context);
2819
2820 /* Actually activate it */
2821 Frame->Frame.Previous = ActiveFrame;
2822 Frame->Frame.ActivationContext = Context;
2823 Frame->Frame.Flags = 0;
2824
2825 /* Check if we can activate this context */
2826 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
2827 Context)
2828 {
2829 /* Set new active frame */
2830 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
2831 return &Frame->Frame;
2832 }
2833
2834 /* We can get here only one way: it was already activated */
2835 DPRINT1("Trying to activate improper activation context\n");
2836
2837 /* Activate only if we are allowing multiple activation */
2838 if (!RtlpNotAllowingMultipleActivation)
2839 {
2840 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
2841 }
2842 else
2843 {
2844 /* Set flag */
2845 Frame->Frame.Flags = 0x30;
2846 }
2847
2848 /* Return pointer to the activation frame */
2849 return &Frame->Frame;
2850 #else
2851
2852 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame;
2853
2854 frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2855 frame->ActivationContext = Context;
2856 frame->Flags = 0;
2857
2858 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
2859
2860 return STATUS_SUCCESS;
2861 #endif
2862 }
2863
2864 PRTL_ACTIVATION_CONTEXT_STACK_FRAME
2865 FASTCALL
2866 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
2867 {
2868 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
2869 //RTL_ACTIVATION_CONTEXT_STACK_FRAME *top;
2870
2871 /* find the right frame */
2872 //top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
2873 frame = &Frame->Frame;
2874
2875 if (!frame)
2876 {
2877 DPRINT1("No top frame!\n");
2878 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
2879 }
2880
2881 /* pop everything up to and including frame */
2882 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
2883
2884 return frame;
2885 }
2886
2887
2888 NTSTATUS
2889 NTAPI
2890 RtlZombifyActivationContext(PVOID Context)
2891 {
2892 UNIMPLEMENTED;
2893
2894 if (Context == ACTCTX_FAKE_HANDLE)
2895 return STATUS_SUCCESS;
2896
2897 return STATUS_NOT_IMPLEMENTED;
2898 }
2899