ntdll: Store all 'comClass' attributes.
[wine.git] / dlls / ntdll / actctx.c
blob1ccbf490fa389596bbd3e9e36ed21aa08706aec9
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdio.h>
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "winternl.h"
35 #include "ddk/wdm.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 /* from oaidl.h */
62 typedef enum tagLIBFLAGS {
63 LIBFLAG_FRESTRICTED = 0x1,
64 LIBFLAG_FCONTROL = 0x2,
65 LIBFLAG_FHIDDEN = 0x4,
66 LIBFLAG_FHASDISKIMAGE = 0x8
67 } LIBFLAGS;
69 /* from oleidl.idl */
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE = 0x1,
73 OLEMISC_ONLYICONIC = 0x2,
74 OLEMISC_INSERTNOTREPLACE = 0x4,
75 OLEMISC_STATIC = 0x8,
76 OLEMISC_CANTLINKINSIDE = 0x10,
77 OLEMISC_CANLINKBYOLE1 = 0x20,
78 OLEMISC_ISLINKOBJECT = 0x40,
79 OLEMISC_INSIDEOUT = 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
82 OLEMISC_INVISIBLEATRUNTIME = 0x400,
83 OLEMISC_ALWAYSRUN = 0x800,
84 OLEMISC_ACTSLIKEBUTTON = 0x1000,
85 OLEMISC_ACTSLIKELABEL = 0x2000,
86 OLEMISC_NOUIACTIVATE = 0x4000,
87 OLEMISC_ALIGNABLE = 0x8000,
88 OLEMISC_SIMPLEFRAME = 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
90 OLEMISC_IMEMODE = 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
92 OLEMISC_WANTSTOMENUMERGE = 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
94 } OLEMISC;
96 typedef struct
98 const WCHAR *ptr;
99 unsigned int len;
100 } xmlstr_t;
102 typedef struct
104 const WCHAR *ptr;
105 const WCHAR *end;
106 } xmlbuf_t;
108 struct file_info
110 ULONG type;
111 WCHAR *info;
114 struct assembly_version
116 USHORT major;
117 USHORT minor;
118 USHORT build;
119 USHORT revision;
122 struct assembly_identity
124 WCHAR *name;
125 WCHAR *arch;
126 WCHAR *public_key;
127 WCHAR *language;
128 WCHAR *type;
129 struct assembly_version version;
130 BOOL optional;
133 struct strsection_header
135 DWORD magic;
136 ULONG size;
137 DWORD unk1[3];
138 ULONG count;
139 ULONG index_offset;
140 DWORD unk2[4];
143 struct string_index
145 ULONG hash; /* key string hash */
146 ULONG name_offset;
147 ULONG name_len;
148 ULONG data_offset; /* redirect data offset */
149 ULONG data_len;
150 ULONG rosterindex;
153 struct guidsection_header
155 DWORD magic;
156 ULONG size;
157 DWORD unk[3];
158 ULONG count;
159 ULONG index_offset;
160 DWORD unk2;
161 ULONG names_offset;
162 ULONG names_len;
165 struct guid_index
167 GUID guid;
168 ULONG data_offset;
169 ULONG data_len;
170 ULONG rosterindex;
173 struct wndclass_redirect_data
175 ULONG size;
176 DWORD res;
177 ULONG name_len;
178 ULONG name_offset; /* versioned name offset */
179 ULONG module_len;
180 ULONG module_offset;/* container name offset */
183 struct dllredirect_data
185 ULONG size;
186 ULONG unk;
187 DWORD res[3];
190 struct tlibredirect_data
192 ULONG size;
193 DWORD res;
194 ULONG name_len;
195 ULONG name_offset;
196 LANGID langid;
197 WORD flags;
198 ULONG help_len;
199 ULONG help_offset;
200 WORD major_version;
201 WORD minor_version;
204 enum comclass_threadingmodel
206 ThreadingModel_Apartment = 1,
207 ThreadingModel_Free = 2,
208 ThreadingModel_No = 3,
209 ThreadingModel_Both = 4,
210 ThreadingModel_Neutral = 5
213 enum comclass_miscfields
215 MiscStatus = 1,
216 MiscStatusIcon = 2,
217 MiscStatusContent = 4,
218 MiscStatusThumbnail = 8,
219 MiscStatusDocPrint = 16
224 Sections structure.
226 Sections are accessible by string or guid key, that defines two types of sections.
227 All sections of each type have same magic value and header structure, index
228 data could be of two possible types too. So every string based section uses
229 the same index format, same applies to guid sections - they share same guid index
230 format.
232 - window class redirection section is a plain buffer with following format:
234 <section header>
235 <index[]>
236 <data[]> --- <original name>
237 <redirect data>
238 <versioned name>
239 <module name>
241 Header is fixed length structure - struct strsection_header,
242 contains redirected classes count;
244 Index is an array of fixed length index records, each record is
245 struct string_index.
247 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
249 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
250 others are relative to section itself.
252 - dll redirect section format:
254 <section header>
255 <index[]>
256 <data[]> --- <dll name>
257 <data>
259 This section doesn't seem to carry any payload data except dll names.
261 - typelib section format:
263 <section header>
264 <module names[]>
265 <index[]>
266 <data[]> --- <data>
267 <helpstring>
269 Header is fixed length, index is an array of fixed length 'struct guid_index'.
270 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
271 4-bytes aligned as a whole.
273 Module name offsets are relative to section, helpstring offset is relative to data
274 structure itself.
277 struct entity
279 DWORD kind;
280 union
282 struct
284 WCHAR *tlbid;
285 WCHAR *helpdir;
286 WORD flags;
287 WORD major;
288 WORD minor;
289 } typelib;
290 struct
292 WCHAR *clsid;
293 WCHAR *tlbid;
294 WCHAR *progid;
295 DWORD model;
296 DWORD miscstatus;
297 DWORD miscstatuscontent;
298 DWORD miscstatusthumbnail;
299 DWORD miscstatusicon;
300 DWORD miscstatusdocprint;
301 } comclass;
302 struct {
303 WCHAR *iid;
304 WCHAR *name;
305 } proxy;
306 struct
308 WCHAR *name;
309 BOOL versioned;
310 } class;
311 struct
313 WCHAR *name;
314 WCHAR *clsid;
315 } clrclass;
316 struct
318 WCHAR *name;
319 WCHAR *clsid;
320 } clrsurrogate;
321 } u;
324 struct entity_array
326 struct entity *base;
327 unsigned int num;
328 unsigned int allocated;
331 struct dll_redirect
333 WCHAR *name;
334 WCHAR *hash;
335 struct entity_array entities;
338 enum assembly_type
340 APPLICATION_MANIFEST,
341 ASSEMBLY_MANIFEST,
342 ASSEMBLY_SHARED_MANIFEST,
345 struct assembly
347 enum assembly_type type;
348 struct assembly_identity id;
349 struct file_info manifest;
350 WCHAR *directory;
351 BOOL no_inherit;
352 struct dll_redirect *dlls;
353 unsigned int num_dlls;
354 unsigned int allocated_dlls;
355 struct entity_array entities;
358 enum context_sections
360 WINDOWCLASS_SECTION = 1,
361 DLLREDIRECT_SECTION = 2,
362 TLIBREDIRECT_SECTION = 4
365 typedef struct _ACTIVATION_CONTEXT
367 ULONG magic;
368 int ref_count;
369 struct file_info config;
370 struct file_info appdir;
371 struct assembly *assemblies;
372 unsigned int num_assemblies;
373 unsigned int allocated_assemblies;
374 /* section data */
375 DWORD sections;
376 struct strsection_header *wndclass_section;
377 struct strsection_header *dllredirect_section;
378 struct guidsection_header *tlib_section;
379 } ACTIVATION_CONTEXT;
381 struct actctx_loader
383 ACTIVATION_CONTEXT *actctx;
384 struct assembly_identity *dependencies;
385 unsigned int num_dependencies;
386 unsigned int allocated_dependencies;
389 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
390 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
391 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
392 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
393 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
394 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
395 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
396 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
397 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};
398 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};
399 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
400 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
401 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
402 static const WCHAR fileW[] = {'f','i','l','e',0};
403 static const WCHAR hashW[] = {'h','a','s','h',0};
404 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
405 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
406 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
407 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
409 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
410 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
411 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
412 static const WCHAR iidW[] = {'i','i','d',0};
413 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
414 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
415 static const WCHAR nameW[] = {'n','a','m','e',0};
416 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
417 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
418 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
419 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
420 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};
421 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
422 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
423 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
424 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
425 static const WCHAR typeW[] = {'t','y','p','e',0};
426 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
427 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
428 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
429 static const WCHAR yesW[] = {'y','e','s',0};
430 static const WCHAR noW[] = {'n','o',0};
431 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
432 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
433 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
434 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
435 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
436 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
437 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
438 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
439 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
440 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
442 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
443 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
444 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
445 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
446 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
447 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
448 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
449 static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
450 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
451 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
452 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
453 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
454 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
455 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
456 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
457 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
458 static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
459 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
460 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
461 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
462 static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
463 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
465 struct olemisc_entry
467 const WCHAR *name;
468 OLEMISC value;
471 static const struct olemisc_entry olemisc_values[] =
473 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
474 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
475 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
476 { alignableW, OLEMISC_ALIGNABLE },
477 { alwaysrunW, OLEMISC_ALWAYSRUN },
478 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
479 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
480 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
481 { imemodeW, OLEMISC_IMEMODE },
482 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
483 { insideoutW, OLEMISC_INSIDEOUT },
484 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
485 { islinkobjectW, OLEMISC_ISLINKOBJECT },
486 { nouiactivateW, OLEMISC_NOUIACTIVATE },
487 { onlyiconicW, OLEMISC_ONLYICONIC },
488 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
489 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
490 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
491 { simpleframeW, OLEMISC_SIMPLEFRAME },
492 { staticW, OLEMISC_STATIC },
493 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
494 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
497 static const WCHAR xmlW[] = {'?','x','m','l',0};
498 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};
499 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};
501 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
502 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
503 static const WCHAR wildcardW[] = {'*',0};
505 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
506 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
508 static WCHAR *strdupW(const WCHAR* str)
510 WCHAR* ptr;
512 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
513 return NULL;
514 return strcpyW(ptr, str);
517 static WCHAR *xmlstrdupW(const xmlstr_t* str)
519 WCHAR *strW;
521 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
523 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
524 strW[str->len] = 0;
526 return strW;
529 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
531 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
534 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
536 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
539 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
541 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
542 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
545 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
547 UINT len = strlenW( namespace );
549 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
550 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
551 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
554 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
556 if (elem->len && elem->ptr[0] == '/')
558 xmlstr_t elem_end;
559 elem_end.ptr = elem->ptr + 1;
560 elem_end.len = elem->len - 1;
561 return xml_elem_cmp( &elem_end, str, namespace );
563 return FALSE;
566 static inline BOOL isxmlspace( WCHAR ch )
568 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
571 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
573 return debugstr_wn(str->ptr, str->len);
576 static inline const char* debugstr_version(const struct assembly_version *ver)
578 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
581 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
583 struct assembly *assembly;
585 if (actctx->num_assemblies == actctx->allocated_assemblies)
587 void *ptr;
588 unsigned int new_count;
589 if (actctx->assemblies)
591 new_count = actctx->allocated_assemblies * 2;
592 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
593 actctx->assemblies, new_count * sizeof(*assembly) );
595 else
597 new_count = 4;
598 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
600 if (!ptr) return NULL;
601 actctx->assemblies = ptr;
602 actctx->allocated_assemblies = new_count;
605 assembly = &actctx->assemblies[actctx->num_assemblies++];
606 assembly->type = at;
607 return assembly;
610 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
612 if (assembly->num_dlls == assembly->allocated_dlls)
614 void *ptr;
615 unsigned int new_count;
616 if (assembly->dlls)
618 new_count = assembly->allocated_dlls * 2;
619 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
620 assembly->dlls, new_count * sizeof(*assembly->dlls) );
622 else
624 new_count = 4;
625 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
627 if (!ptr) return NULL;
628 assembly->dlls = ptr;
629 assembly->allocated_dlls = new_count;
631 return &assembly->dlls[assembly->num_dlls++];
634 static void free_assembly_identity(struct assembly_identity *ai)
636 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
637 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
638 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
639 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
640 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
643 static struct entity* add_entity(struct entity_array *array, DWORD kind)
645 struct entity* entity;
647 if (array->num == array->allocated)
649 void *ptr;
650 unsigned int new_count;
651 if (array->base)
653 new_count = array->allocated * 2;
654 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
655 array->base, new_count * sizeof(*array->base) );
657 else
659 new_count = 4;
660 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
662 if (!ptr) return NULL;
663 array->base = ptr;
664 array->allocated = new_count;
666 entity = &array->base[array->num++];
667 entity->kind = kind;
668 return entity;
671 static void free_entity_array(struct entity_array *array)
673 unsigned int i;
674 for (i = 0; i < array->num; i++)
676 struct entity *entity = &array->base[i];
677 switch (entity->kind)
679 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
680 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
681 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
682 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
683 break;
684 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
685 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
686 RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.name);
687 break;
688 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
689 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
690 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
691 break;
692 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
693 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
694 break;
695 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
696 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.name);
697 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrclass.clsid);
698 break;
699 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
700 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
701 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
702 break;
703 default:
704 FIXME("Unknown entity kind %d\n", entity->kind);
707 RtlFreeHeap( GetProcessHeap(), 0, array->base );
710 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
712 if (!str1) return !str2;
713 return str2 && !strcmpiW( str1, str2 );
716 static BOOL is_matching_identity( const struct assembly_identity *id1,
717 const struct assembly_identity *id2 )
719 if (!is_matching_string( id1->name, id2->name )) return FALSE;
720 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
721 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
723 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
725 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
726 return FALSE;
728 if (id1->version.major != id2->version.major) return FALSE;
729 if (id1->version.minor != id2->version.minor) return FALSE;
730 if (id1->version.build > id2->version.build) return FALSE;
731 if (id1->version.build == id2->version.build &&
732 id1->version.revision > id2->version.revision) return FALSE;
733 return TRUE;
736 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
737 struct assembly_identity* ai)
739 unsigned int i;
741 /* check if we already have that assembly */
743 for (i = 0; i < acl->actctx->num_assemblies; i++)
744 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
746 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
747 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
748 ai->version.build, ai->version.revision );
749 return TRUE;
752 for (i = 0; i < acl->num_dependencies; i++)
753 if (is_matching_identity( ai, &acl->dependencies[i] ))
755 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
756 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
757 ai->version.build, ai->version.revision );
758 return TRUE;
761 if (acl->num_dependencies == acl->allocated_dependencies)
763 void *ptr;
764 unsigned int new_count;
765 if (acl->dependencies)
767 new_count = acl->allocated_dependencies * 2;
768 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
769 new_count * sizeof(acl->dependencies[0]));
771 else
773 new_count = 4;
774 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
776 if (!ptr) return FALSE;
777 acl->dependencies = ptr;
778 acl->allocated_dependencies = new_count;
780 acl->dependencies[acl->num_dependencies++] = *ai;
782 return TRUE;
785 static void free_depend_manifests(struct actctx_loader* acl)
787 unsigned int i;
788 for (i = 0; i < acl->num_dependencies; i++)
789 free_assembly_identity(&acl->dependencies[i]);
790 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
793 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
795 static const WCHAR undW[] = {'_',0};
796 static const WCHAR noneW[] = {'n','o','n','e',0};
797 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
799 const WCHAR *arch = ai->arch ? ai->arch : noneW;
800 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
801 const WCHAR *lang = ai->language ? ai->language : noneW;
802 const WCHAR *name = ai->name ? ai->name : noneW;
803 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
804 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
805 WCHAR *ret;
807 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
809 strcpyW( ret, arch );
810 strcatW( ret, undW );
811 strcatW( ret, name );
812 strcatW( ret, undW );
813 strcatW( ret, key );
814 strcatW( ret, undW );
815 sprintfW( ret + strlenW(ret), version_formatW,
816 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
817 strcatW( ret, undW );
818 strcatW( ret, lang );
819 strcatW( ret, undW );
820 strcatW( ret, mskeyW );
821 return ret;
824 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
826 WCHAR *p = buffer;
828 if (!str) return;
829 strcatW( buffer, prefix );
830 p += strlenW(p);
831 *p++ = '"';
832 strcpyW( p, str );
833 p += strlenW(p);
834 *p++ = '"';
835 *p = 0;
838 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
840 static const WCHAR archW[] =
841 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
842 static const WCHAR public_keyW[] =
843 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
844 static const WCHAR typeW[] =
845 {',','t','y','p','e','=',0};
846 static const WCHAR versionW[] =
847 {',','v','e','r','s','i','o','n','=',0};
849 WCHAR version[64], *ret;
850 SIZE_T size = 0;
852 sprintfW( version, version_formatW,
853 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
854 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
855 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
856 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
857 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
858 size += strlenW(versionW) + strlenW(version) + 2;
860 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
861 return NULL;
863 if (ai->name) strcpyW( ret, ai->name );
864 else *ret = 0;
865 append_string( ret, archW, ai->arch );
866 append_string( ret, public_keyW, ai->public_key );
867 append_string( ret, typeW, ai->type );
868 append_string( ret, versionW, version );
869 return ret;
872 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
874 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
876 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
877 __TRY
879 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
881 __EXCEPT_PAGE_FAULT
884 __ENDTRY
885 return ret;
888 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
890 interlocked_xchg_add( &actctx->ref_count, 1 );
893 static void actctx_release( ACTIVATION_CONTEXT *actctx )
895 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
897 unsigned int i, j;
899 for (i = 0; i < actctx->num_assemblies; i++)
901 struct assembly *assembly = &actctx->assemblies[i];
902 for (j = 0; j < assembly->num_dlls; j++)
904 struct dll_redirect *dll = &assembly->dlls[j];
905 free_entity_array( &dll->entities );
906 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
907 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
909 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
910 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
911 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
912 free_entity_array( &assembly->entities );
913 free_assembly_identity(&assembly->id);
915 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
916 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
917 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
918 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
919 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
920 actctx->magic = 0;
921 RtlFreeHeap( GetProcessHeap(), 0, actctx );
925 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
926 BOOL* error, BOOL* end)
928 const WCHAR* ptr;
930 *error = TRUE;
932 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
933 xmlbuf->ptr++;
935 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
937 if (*xmlbuf->ptr == '/')
939 xmlbuf->ptr++;
940 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
941 return FALSE;
943 xmlbuf->ptr++;
944 *end = TRUE;
945 *error = FALSE;
946 return FALSE;
949 if (*xmlbuf->ptr == '>')
951 xmlbuf->ptr++;
952 *error = FALSE;
953 return FALSE;
956 ptr = xmlbuf->ptr;
957 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
959 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
961 name->ptr = xmlbuf->ptr;
962 name->len = ptr-xmlbuf->ptr;
963 xmlbuf->ptr = ptr;
965 ptr++;
966 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
968 value->ptr = ++ptr;
969 if (ptr == xmlbuf->end) return FALSE;
971 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
972 if (!ptr)
974 xmlbuf->ptr = xmlbuf->end;
975 return FALSE;
978 value->len = ptr - value->ptr;
979 xmlbuf->ptr = ptr + 1;
981 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
983 *error = FALSE;
984 return TRUE;
987 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
989 const WCHAR* ptr;
991 for (;;)
993 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
994 if (!ptr)
996 xmlbuf->ptr = xmlbuf->end;
997 return FALSE;
999 ptr++;
1000 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1002 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1003 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1005 if (ptr + 3 > xmlbuf->end)
1007 xmlbuf->ptr = xmlbuf->end;
1008 return FALSE;
1010 xmlbuf->ptr = ptr + 3;
1012 else break;
1015 xmlbuf->ptr = ptr;
1016 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1017 ptr++;
1019 elem->ptr = xmlbuf->ptr;
1020 elem->len = ptr - xmlbuf->ptr;
1021 xmlbuf->ptr = ptr;
1022 return xmlbuf->ptr != xmlbuf->end;
1025 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1027 /* FIXME: parse attributes */
1028 const WCHAR *ptr;
1030 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1032 if (ptr[0] == '?' && ptr[1] == '>')
1034 xmlbuf->ptr = ptr + 2;
1035 return TRUE;
1038 return FALSE;
1041 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1043 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1045 if (!ptr) return FALSE;
1047 content->ptr = xmlbuf->ptr;
1048 content->len = ptr - xmlbuf->ptr;
1049 xmlbuf->ptr = ptr;
1051 return TRUE;
1054 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1056 unsigned int ver[4];
1057 unsigned int pos;
1058 const WCHAR *curr;
1060 /* major.minor.build.revision */
1061 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1062 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1064 if (*curr >= '0' && *curr <= '9')
1066 ver[pos] = ver[pos] * 10 + *curr - '0';
1067 if (ver[pos] >= 0x10000) goto error;
1069 else if (*curr == '.')
1071 if (++pos >= 4) goto error;
1073 else goto error;
1075 version->major = ver[0];
1076 version->minor = ver[1];
1077 version->build = ver[2];
1078 version->revision = ver[3];
1079 return TRUE;
1081 error:
1082 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1083 return FALSE;
1086 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1088 xmlstr_t elem;
1089 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1090 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1091 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1092 return FALSE;
1095 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1097 xmlstr_t attr_name, attr_value;
1098 BOOL error;
1100 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1102 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1103 debugstr_xmlstr(&attr_value));
1105 return !error;
1108 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1110 BOOL end = FALSE;
1111 return parse_expect_no_attr(xmlbuf, &end) && !end;
1114 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1116 xmlstr_t elem;
1117 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1118 if (!xml_elem_cmp_end(&elem, name, namespace))
1120 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1121 return FALSE;
1123 return parse_end_element(xmlbuf);
1126 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1128 xmlstr_t attr_name, attr_value, elem;
1129 BOOL end = FALSE, error, ret = TRUE;
1131 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1132 if(error || end) return end;
1134 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1136 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1137 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1138 break;
1139 else
1140 ret = parse_unknown_elem(xmlbuf, &elem);
1143 return ret && parse_end_element(xmlbuf);
1146 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1147 struct assembly_identity* ai)
1149 xmlstr_t attr_name, attr_value;
1150 BOOL end = FALSE, error;
1152 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1154 if (xmlstr_cmp(&attr_name, nameW))
1156 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1158 else if (xmlstr_cmp(&attr_name, typeW))
1160 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1162 else if (xmlstr_cmp(&attr_name, versionW))
1164 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1166 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1168 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1170 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1172 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1174 else if (xmlstr_cmp(&attr_name, languageW))
1176 WARN("Unsupported yet language attribute (%s)\n",
1177 debugstr_xmlstr(&attr_value));
1178 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1180 else
1182 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1183 debugstr_xmlstr(&attr_value));
1187 TRACE( "name=%s version=%s arch=%s\n",
1188 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1190 if (error || end) return end;
1191 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1194 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1196 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1197 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1198 static const WCHAR freeW[] = {'F','r','e','e',0};
1199 static const WCHAR bothW[] = {'B','o','t','h',0};
1201 if (value->len == 0) return ThreadingModel_No;
1202 if (xmlstr_cmp(value, apartW))
1203 return ThreadingModel_Apartment;
1204 else if (xmlstr_cmp(value, freeW))
1205 return ThreadingModel_Free;
1206 else if (xmlstr_cmp(value, bothW))
1207 return ThreadingModel_Both;
1208 else if (xmlstr_cmp(value, neutralW))
1209 return ThreadingModel_Neutral;
1210 else
1211 return ThreadingModel_No;
1214 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1216 int min, max;
1218 min = 0;
1219 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1221 while (min <= max)
1223 int n, c;
1225 n = (min+max)/2;
1227 c = strncmpW(olemisc_values[n].name, str, len);
1228 if (!c && !olemisc_values[n].name[len])
1229 return olemisc_values[n].value;
1231 if (c >= 0)
1232 max = n-1;
1233 else
1234 min = n+1;
1237 WARN("unknown flag %s\n", debugstr_wn(str, len));
1238 return 0;
1241 static DWORD parse_com_class_misc(const xmlstr_t *value)
1243 const WCHAR *str = value->ptr, *start;
1244 DWORD flags = 0;
1245 int i = 0;
1247 /* it's comma separated list of flags */
1248 while (i < value->len)
1250 start = str;
1251 while (*str != ',' && (i++ < value->len)) str++;
1253 flags |= get_olemisc_value(start, str-start);
1255 /* skip separator */
1256 str++;
1257 i++;
1260 return flags;
1263 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
1265 xmlstr_t elem, attr_name, attr_value;
1266 BOOL ret, end = FALSE, error;
1267 struct entity* entity;
1269 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1270 return FALSE;
1272 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1274 if (xmlstr_cmp(&attr_name, clsidW))
1276 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1278 else if (xmlstr_cmp(&attr_name, progidW))
1280 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1282 else if (xmlstr_cmp(&attr_name, tlbidW))
1284 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1286 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1288 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1290 else if (xmlstr_cmp(&attr_name, miscstatusW))
1292 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1294 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1296 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1298 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1300 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1302 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1304 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1306 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1308 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1310 else
1312 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1316 if (error || end) return end;
1318 while ((ret = next_xml_elem(xmlbuf, &elem)))
1320 if (xmlstr_cmp_end(&elem, comClassW))
1322 ret = parse_end_element(xmlbuf);
1323 break;
1325 else
1327 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1328 ret = parse_unknown_elem(xmlbuf, &elem);
1331 return ret;
1334 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
1336 xmlstr_t attr_name, attr_value;
1337 BOOL end = FALSE, error;
1338 struct entity* entity;
1340 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1341 return FALSE;
1343 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1345 if (xmlstr_cmp(&attr_name, iidW))
1347 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
1349 if (xmlstr_cmp(&attr_name, nameW))
1351 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
1353 else
1355 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1359 if (error || end) return end;
1360 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1363 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1365 WORD *flags = &entity->u.typelib.flags;
1366 const WCHAR *str = value->ptr, *start;
1367 int i = 0;
1369 *flags = 0;
1371 /* it's comma separated list of flags */
1372 while (i < value->len)
1374 start = str;
1375 while (*str != ',' && (i++ < value->len)) str++;
1377 if (!strncmpW(start, restrictedW, str-start))
1378 *flags |= LIBFLAG_FRESTRICTED;
1379 else if (!strncmpW(start, controlW, str-start))
1380 *flags |= LIBFLAG_FCONTROL;
1381 else if (!strncmpW(start, hiddenW, str-start))
1382 *flags |= LIBFLAG_FHIDDEN;
1383 else if (!strncmpW(start, hasdiskimageW, str-start))
1384 *flags |= LIBFLAG_FHASDISKIMAGE;
1385 else
1387 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1388 return FALSE;
1391 /* skip separator */
1392 str++;
1393 i++;
1396 return TRUE;
1399 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1401 unsigned int ver[2];
1402 unsigned int pos;
1403 const WCHAR *curr;
1405 /* major.minor */
1406 ver[0] = ver[1] = pos = 0;
1407 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1409 if (*curr >= '0' && *curr <= '9')
1411 ver[pos] = ver[pos] * 10 + *curr - '0';
1412 if (ver[pos] >= 0x10000) goto error;
1414 else if (*curr == '.')
1416 if (++pos >= 2) goto error;
1418 else goto error;
1420 entity->u.typelib.major = ver[0];
1421 entity->u.typelib.minor = ver[1];
1422 return TRUE;
1424 error:
1425 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1426 return FALSE;
1429 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1431 xmlstr_t attr_name, attr_value;
1432 BOOL end = FALSE, error;
1433 struct entity* entity;
1435 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1436 return FALSE;
1438 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1440 if (xmlstr_cmp(&attr_name, tlbidW))
1442 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1444 else if (xmlstr_cmp(&attr_name, versionW))
1446 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1448 else if (xmlstr_cmp(&attr_name, helpdirW))
1450 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1452 else if (xmlstr_cmp(&attr_name, flagsW))
1454 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1456 else
1458 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1462 if (error) return FALSE;
1464 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1466 if (end) return TRUE;
1468 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1471 static inline int aligned_string_len(int len)
1473 return (len + 3) & ~3;
1476 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1478 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1479 struct assembly_version *ver = &assembly->id.version;
1480 WCHAR buff[25];
1482 if (!ret) ret = buff;
1483 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1486 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1488 xmlstr_t elem, content, attr_name, attr_value;
1489 BOOL end = FALSE, ret = TRUE, error;
1490 struct entity* entity;
1492 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1493 return FALSE;
1495 entity->u.class.versioned = TRUE;
1496 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1498 if (xmlstr_cmp(&attr_name, versionedW))
1500 if (xmlstr_cmpi(&attr_value, noW))
1501 entity->u.class.versioned = FALSE;
1502 else if (!xmlstr_cmpi(&attr_value, yesW))
1503 return FALSE;
1505 else
1507 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1511 if (error || end) return end;
1513 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1515 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1517 acl->actctx->sections |= WINDOWCLASS_SECTION;
1519 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1521 if (xmlstr_cmp_end(&elem, windowClassW))
1523 ret = parse_end_element(xmlbuf);
1524 break;
1526 else
1528 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1529 ret = parse_unknown_elem(xmlbuf, &elem);
1533 return ret;
1536 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1538 xmlstr_t attr_name, attr_value;
1539 BOOL end = FALSE, error;
1541 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1543 if (xmlstr_cmp(&attr_name, oldVersionW))
1545 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1547 else if (xmlstr_cmp(&attr_name, newVersionW))
1549 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1551 else
1553 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1557 if (error || end) return end;
1558 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1561 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1563 xmlstr_t elem, content;
1564 BOOL end = FALSE, ret = TRUE;
1566 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
1567 !parse_text_content(xmlbuf, &content))
1568 return FALSE;
1570 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1572 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1574 if (xmlstr_cmp_end(&elem, descriptionW))
1576 ret = parse_end_element(xmlbuf);
1577 break;
1579 else
1581 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1582 ret = parse_unknown_elem(xmlbuf, &elem);
1586 return ret;
1589 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1590 struct assembly* assembly)
1592 xmlstr_t attr_name, attr_value;
1593 BOOL end = FALSE, error;
1594 struct entity* entity;
1596 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1597 if (!entity) return FALSE;
1599 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1601 if (xmlstr_cmp(&attr_name, iidW))
1603 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
1605 if (xmlstr_cmp(&attr_name, nameW))
1607 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
1609 else
1611 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1615 if (error || end) return end;
1616 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1619 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1621 xmlstr_t attr_name, attr_value;
1622 BOOL end = FALSE, error;
1623 struct entity* entity;
1625 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
1626 if (!entity) return FALSE;
1628 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1630 if (xmlstr_cmp(&attr_name, nameW))
1632 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
1634 else if (xmlstr_cmp(&attr_name, clsidW))
1636 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1638 else
1640 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1644 if (error || end) return end;
1645 return parse_expect_end_elem(xmlbuf, clrClassW, asmv1W);
1648 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1650 xmlstr_t attr_name, attr_value;
1651 BOOL end = FALSE, error;
1652 struct entity* entity;
1654 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1655 if (!entity) return FALSE;
1657 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1659 if (xmlstr_cmp(&attr_name, nameW))
1661 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
1663 else if (xmlstr_cmp(&attr_name, clsidW))
1665 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
1667 else
1669 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1673 if (error || end) return end;
1674 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
1677 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1679 struct assembly_identity ai;
1680 xmlstr_t elem;
1681 BOOL end = FALSE, ret = TRUE;
1683 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1685 memset(&ai, 0, sizeof(ai));
1686 ai.optional = optional;
1688 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
1689 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1690 return FALSE;
1692 TRACE( "adding name=%s version=%s arch=%s\n",
1693 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
1695 /* store the newly found identity for later loading */
1696 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1698 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1700 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
1702 ret = parse_end_element(xmlbuf);
1703 break;
1705 else if (xmlstr_cmp(&elem, bindingRedirectW))
1707 ret = parse_binding_redirect_elem(xmlbuf);
1709 else
1711 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1712 ret = parse_unknown_elem(xmlbuf, &elem);
1716 return ret;
1719 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1721 xmlstr_t attr_name, attr_value, elem;
1722 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1724 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1726 if (xmlstr_cmp(&attr_name, optionalW))
1728 optional = xmlstr_cmpi( &attr_value, yesW );
1729 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
1731 else
1733 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1737 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1739 if (xmlstr_cmp_end(&elem, dependencyW))
1741 ret = parse_end_element(xmlbuf);
1742 break;
1744 else if (xmlstr_cmp(&elem, dependentAssemblyW))
1746 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1748 else
1750 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1751 ret = parse_unknown_elem(xmlbuf, &elem);
1755 return ret;
1758 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1760 BOOL end = FALSE;
1762 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1763 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
1766 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1768 BOOL end = FALSE;
1770 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1771 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
1774 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
1776 xmlstr_t attr_name, attr_value, elem;
1777 BOOL end = FALSE, error, ret = TRUE;
1778 struct dll_redirect* dll;
1780 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1782 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1784 if (xmlstr_cmp(&attr_name, nameW))
1786 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1787 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1789 else if (xmlstr_cmp(&attr_name, hashW))
1791 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1793 else if (xmlstr_cmp(&attr_name, hashalgW))
1795 static const WCHAR sha1W[] = {'S','H','A','1',0};
1796 if (!xmlstr_cmpi(&attr_value, sha1W))
1797 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
1799 else
1801 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1805 if (error || !dll->name) return FALSE;
1807 acl->actctx->sections |= DLLREDIRECT_SECTION;
1809 if (end) return TRUE;
1811 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1813 if (xmlstr_cmp_end(&elem, fileW))
1815 ret = parse_end_element(xmlbuf);
1816 break;
1818 else if (xmlstr_cmp(&elem, comClassW))
1820 ret = parse_com_class_elem(xmlbuf, dll);
1822 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
1824 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
1826 else if (xml_elem_cmp(&elem, hashW, asmv2W))
1828 WARN("asmv2:hash (undocumented) not supported\n");
1829 ret = parse_unknown_elem(xmlbuf, &elem);
1831 else if (xmlstr_cmp(&elem, typelibW))
1833 ret = parse_typelib_elem(xmlbuf, dll, acl);
1835 else if (xmlstr_cmp(&elem, windowClassW))
1837 ret = parse_window_class_elem(xmlbuf, dll, acl);
1839 else
1841 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1842 ret = parse_unknown_elem( xmlbuf, &elem );
1846 return ret;
1849 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
1850 struct assembly* assembly,
1851 struct assembly_identity* expected_ai)
1853 xmlstr_t attr_name, attr_value, elem;
1854 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
1856 TRACE("(%p)\n", xmlbuf);
1858 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1860 if (xmlstr_cmp(&attr_name, manifestVersionW))
1862 static const WCHAR v10W[] = {'1','.','0',0};
1863 if (!xmlstr_cmp(&attr_value, v10W))
1865 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
1866 return FALSE;
1868 version = TRUE;
1870 else if (xmlstr_cmp(&attr_name, xmlnsW))
1872 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
1874 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
1875 return FALSE;
1877 xmlns = TRUE;
1879 else
1881 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1885 if (error || end || !xmlns || !version) return FALSE;
1886 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1888 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
1890 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1891 return FALSE;
1892 assembly->no_inherit = TRUE;
1895 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
1897 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
1898 return FALSE;
1900 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
1901 assembly->no_inherit)
1902 return FALSE;
1904 while (ret)
1906 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
1908 ret = parse_end_element(xmlbuf);
1909 break;
1911 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
1913 ret = parse_description_elem(xmlbuf);
1915 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
1917 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
1919 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
1921 ret = parse_dependency_elem(xmlbuf, acl);
1923 else if (xml_elem_cmp(&elem, fileW, asmv1W))
1925 ret = parse_file_elem(xmlbuf, assembly, acl);
1927 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
1929 ret = parse_clr_class_elem(xmlbuf, assembly);
1931 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
1933 ret = parse_clr_surrogate_elem(xmlbuf, assembly);
1935 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
1937 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
1939 if (expected_ai)
1941 /* FIXME: more tests */
1942 if (assembly->type == ASSEMBLY_MANIFEST &&
1943 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
1945 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
1946 expected_ai->version.major, expected_ai->version.minor,
1947 expected_ai->version.build, expected_ai->version.revision,
1948 assembly->id.version.major, assembly->id.version.minor,
1949 assembly->id.version.build, assembly->id.version.revision);
1950 ret = FALSE;
1952 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
1953 (assembly->id.version.major != expected_ai->version.major ||
1954 assembly->id.version.minor != expected_ai->version.minor ||
1955 assembly->id.version.build < expected_ai->version.build ||
1956 (assembly->id.version.build == expected_ai->version.build &&
1957 assembly->id.version.revision < expected_ai->version.revision)))
1959 FIXME("wrong version for shared assembly manifest\n");
1960 ret = FALSE;
1964 else
1966 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1967 ret = parse_unknown_elem(xmlbuf, &elem);
1969 if (ret) ret = next_xml_elem(xmlbuf, &elem);
1972 return ret;
1975 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
1976 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
1978 xmlstr_t elem;
1980 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
1982 if (xmlstr_cmp(&elem, xmlW) &&
1983 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
1984 return STATUS_SXS_CANT_GEN_ACTCTX;
1986 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
1988 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
1989 return STATUS_SXS_CANT_GEN_ACTCTX;
1992 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
1994 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
1995 return STATUS_SXS_CANT_GEN_ACTCTX;
1998 if (next_xml_elem(xmlbuf, &elem))
2000 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2001 return STATUS_SXS_CANT_GEN_ACTCTX;
2004 if (xmlbuf->ptr != xmlbuf->end)
2006 FIXME("parse error\n");
2007 return STATUS_SXS_CANT_GEN_ACTCTX;
2009 return STATUS_SUCCESS;
2012 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2013 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2014 const void *buffer, SIZE_T size )
2016 xmlbuf_t xmlbuf;
2017 NTSTATUS status;
2018 struct assembly *assembly;
2019 int unicode_tests;
2021 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2023 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2024 return STATUS_SXS_CANT_GEN_ACTCTX;
2026 if (directory && !(assembly->directory = strdupW(directory)))
2027 return STATUS_NO_MEMORY;
2029 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2030 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2031 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2033 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2034 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2036 xmlbuf.ptr = buffer;
2037 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2038 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2040 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2042 const WCHAR *buf = buffer;
2043 WCHAR *new_buff;
2044 unsigned int i;
2046 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2047 return STATUS_NO_MEMORY;
2048 for (i = 0; i < size / sizeof(WCHAR); i++)
2049 new_buff[i] = RtlUshortByteSwap( buf[i] );
2050 xmlbuf.ptr = new_buff;
2051 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2052 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2053 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2055 else
2057 /* let's assume utf-8 for now */
2058 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2059 WCHAR *new_buff;
2061 if (len == -1)
2063 FIXME( "utf-8 conversion failed\n" );
2064 return STATUS_SXS_CANT_GEN_ACTCTX;
2066 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2067 return STATUS_NO_MEMORY;
2068 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2069 xmlbuf.ptr = new_buff;
2070 xmlbuf.end = xmlbuf.ptr + len;
2071 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2072 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2074 return status;
2077 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2079 OBJECT_ATTRIBUTES attr;
2080 IO_STATUS_BLOCK io;
2082 attr.Length = sizeof(attr);
2083 attr.RootDirectory = 0;
2084 attr.Attributes = OBJ_CASE_INSENSITIVE;
2085 attr.ObjectName = name;
2086 attr.SecurityDescriptor = NULL;
2087 attr.SecurityQualityOfService = NULL;
2088 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2091 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2093 NTSTATUS status;
2094 ULONG magic;
2095 LDR_MODULE *pldr;
2097 LdrLockLoaderLock(0, NULL, &magic);
2098 status = LdrFindEntryForAddress( module, &pldr );
2099 if (status == STATUS_SUCCESS)
2101 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2102 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2104 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2105 str->Length = pldr->FullDllName.Length;
2106 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2108 else status = STATUS_NO_MEMORY;
2110 LdrUnlockLoaderLock(0, magic);
2111 return status;
2114 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2115 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2116 HANDLE hModule, LPCWSTR resname, ULONG lang )
2118 NTSTATUS status;
2119 UNICODE_STRING nameW;
2120 LDR_RESOURCE_INFO info;
2121 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2122 void *ptr;
2124 if (TRACE_ON(actctx))
2126 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2128 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2129 hModule, debugstr_w(nameW.Buffer) );
2130 RtlFreeUnicodeString( &nameW );
2132 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2133 hModule, debugstr_w(filename) );
2136 if (!resname) return STATUS_INVALID_PARAMETER;
2138 info.Type = RT_MANIFEST;
2139 info.Language = lang;
2140 if (!((ULONG_PTR)resname >> 16))
2142 info.Name = (ULONG_PTR)resname;
2143 status = LdrFindResource_U(hModule, &info, 3, &entry);
2145 else if (resname[0] == '#')
2147 ULONG value;
2148 RtlInitUnicodeString(&nameW, resname + 1);
2149 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2150 return STATUS_INVALID_PARAMETER;
2151 info.Name = value;
2152 status = LdrFindResource_U(hModule, &info, 3, &entry);
2154 else
2156 RtlCreateUnicodeString(&nameW, resname);
2157 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2158 info.Name = (ULONG_PTR)nameW.Buffer;
2159 status = LdrFindResource_U(hModule, &info, 3, &entry);
2160 RtlFreeUnicodeString(&nameW);
2162 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2164 if (status == STATUS_SUCCESS)
2165 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2167 return status;
2170 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2171 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2172 HANDLE file, LPCWSTR resname, ULONG lang )
2174 HANDLE mapping;
2175 OBJECT_ATTRIBUTES attr;
2176 LARGE_INTEGER size;
2177 LARGE_INTEGER offset;
2178 NTSTATUS status;
2179 SIZE_T count;
2180 void *base;
2182 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2184 attr.Length = sizeof(attr);
2185 attr.RootDirectory = 0;
2186 attr.ObjectName = NULL;
2187 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2188 attr.SecurityDescriptor = NULL;
2189 attr.SecurityQualityOfService = NULL;
2191 size.QuadPart = 0;
2192 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2193 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2194 if (status != STATUS_SUCCESS) return status;
2196 offset.QuadPart = 0;
2197 count = 0;
2198 base = NULL;
2199 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2200 &count, ViewShare, 0, PAGE_READONLY );
2201 NtClose( mapping );
2202 if (status != STATUS_SUCCESS) return status;
2204 if (RtlImageNtHeader(base)) /* we got a PE file */
2206 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2207 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2209 else status = STATUS_INVALID_IMAGE_FORMAT;
2211 NtUnmapViewOfSection( GetCurrentProcess(), base );
2212 return status;
2215 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2216 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2218 FILE_END_OF_FILE_INFORMATION info;
2219 IO_STATUS_BLOCK io;
2220 HANDLE mapping;
2221 OBJECT_ATTRIBUTES attr;
2222 LARGE_INTEGER size;
2223 LARGE_INTEGER offset;
2224 NTSTATUS status;
2225 SIZE_T count;
2226 void *base;
2228 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2230 attr.Length = sizeof(attr);
2231 attr.RootDirectory = 0;
2232 attr.ObjectName = NULL;
2233 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2234 attr.SecurityDescriptor = NULL;
2235 attr.SecurityQualityOfService = NULL;
2237 size.QuadPart = 0;
2238 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2239 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2240 if (status != STATUS_SUCCESS) return status;
2242 offset.QuadPart = 0;
2243 count = 0;
2244 base = NULL;
2245 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2246 &count, ViewShare, 0, PAGE_READONLY );
2247 NtClose( mapping );
2248 if (status != STATUS_SUCCESS) return status;
2250 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2251 if (status == STATUS_SUCCESS)
2252 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2254 NtUnmapViewOfSection( GetCurrentProcess(), base );
2255 return status;
2258 /* try to load the .manifest file associated to the file */
2259 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2260 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2262 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2263 WCHAR *buffer;
2264 NTSTATUS status;
2265 UNICODE_STRING nameW;
2266 HANDLE file;
2267 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2269 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2271 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2273 if (module) /* use the module filename */
2275 UNICODE_STRING name;
2277 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2279 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2280 strcatW( name.Buffer, dotManifestW );
2281 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2282 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2283 RtlFreeUnicodeString( &name );
2285 if (status) return status;
2287 else
2289 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2290 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2291 return STATUS_NO_MEMORY;
2292 strcpyW( buffer, filename );
2293 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2294 strcatW( buffer, dotManifestW );
2295 RtlInitUnicodeString( &nameW, buffer );
2298 if (!open_nt_file( &file, &nameW ))
2300 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2301 NtClose( file );
2303 else status = STATUS_RESOURCE_DATA_NOT_FOUND;
2304 RtlFreeUnicodeString( &nameW );
2305 return status;
2308 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2310 static const WCHAR lookup_fmtW[] =
2311 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2312 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2313 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2315 WCHAR *lookup, *ret = NULL;
2316 UNICODE_STRING lookup_us;
2317 IO_STATUS_BLOCK io;
2318 const WCHAR *lang = ai->language;
2319 unsigned int data_pos = 0, data_len;
2320 char buffer[8192];
2322 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2323 (strlenW(ai->arch) + strlenW(ai->name)
2324 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2325 + sizeof(lookup_fmtW) )))
2326 return NULL;
2328 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2329 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2330 ai->version.major, ai->version.minor, lang );
2331 RtlInitUnicodeString( &lookup_us, lookup );
2333 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2334 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2335 if (io.u.Status == STATUS_SUCCESS)
2337 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2338 FILE_BOTH_DIR_INFORMATION *dir_info;
2339 WCHAR *tmp;
2340 ULONG build, revision;
2342 data_len = io.Information;
2344 for (;;)
2346 if (data_pos >= data_len)
2348 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2349 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2350 if (io.u.Status != STATUS_SUCCESS) break;
2351 data_len = io.Information;
2352 data_pos = 0;
2354 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2356 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2357 else data_pos = data_len;
2359 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2360 build = atoiW(tmp);
2361 if (build < min_build) continue;
2362 tmp = strchrW(tmp, '.') + 1;
2363 revision = atoiW(tmp);
2364 if (build == min_build && revision < min_revision) continue;
2365 tmp = strchrW(tmp, '_') + 1;
2366 tmp = strchrW(tmp, '_') + 1;
2367 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2368 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2370 /* prefer a non-Wine manifest if we already have one */
2371 /* we'll still load the builtin dll if specified through DllOverrides */
2372 if (ret) continue;
2374 else
2376 min_build = build;
2377 min_revision = revision;
2379 ai->version.build = build;
2380 ai->version.revision = revision;
2381 RtlFreeHeap( GetProcessHeap(), 0, ret );
2382 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2384 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2385 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2389 else WARN("no matching file for %s\n", debugstr_w(lookup));
2390 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2391 return ret;
2394 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2396 struct assembly_identity sxs_ai;
2397 UNICODE_STRING path_us;
2398 OBJECT_ATTRIBUTES attr;
2399 IO_STATUS_BLOCK io;
2400 WCHAR *path, *file = NULL;
2401 HANDLE handle;
2403 static const WCHAR manifest_dirW[] =
2404 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2406 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2408 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2409 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2410 return STATUS_NO_MEMORY;
2412 strcpyW( path, user_shared_data->NtSystemRoot );
2413 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2415 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2417 RtlFreeHeap( GetProcessHeap(), 0, path );
2418 return STATUS_NO_SUCH_FILE;
2420 RtlFreeHeap( GetProcessHeap(), 0, path );
2422 attr.Length = sizeof(attr);
2423 attr.RootDirectory = 0;
2424 attr.Attributes = OBJ_CASE_INSENSITIVE;
2425 attr.ObjectName = &path_us;
2426 attr.SecurityDescriptor = NULL;
2427 attr.SecurityQualityOfService = NULL;
2429 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2430 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2432 sxs_ai = *ai;
2433 file = lookup_manifest_file( handle, &sxs_ai );
2434 NtClose( handle );
2436 if (!file)
2438 RtlFreeUnicodeString( &path_us );
2439 return STATUS_NO_SUCH_FILE;
2442 /* append file name to directory path */
2443 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2444 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2446 RtlFreeHeap( GetProcessHeap(), 0, file );
2447 RtlFreeUnicodeString( &path_us );
2448 return STATUS_NO_MEMORY;
2451 path[path_us.Length/sizeof(WCHAR)] = '\\';
2452 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2453 RtlInitUnicodeString( &path_us, path );
2454 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2456 if (!open_nt_file( &handle, &path_us ))
2458 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2459 NtClose( handle );
2461 else io.u.Status = STATUS_NO_SUCH_FILE;
2463 RtlFreeHeap( GetProcessHeap(), 0, file );
2464 RtlFreeUnicodeString( &path_us );
2465 return io.u.Status;
2468 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2469 struct assembly_identity* ai)
2471 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2472 unsigned int i;
2473 WCHAR *buffer, *p, *directory;
2474 NTSTATUS status;
2475 UNICODE_STRING nameW;
2476 HANDLE file;
2478 TRACE( "looking for name=%s version=%s arch=%s\n",
2479 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2481 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2483 /* FIXME: add support for language specific lookup */
2485 nameW.Buffer = NULL;
2486 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2487 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2488 return STATUS_NO_MEMORY;
2490 if (!(directory = build_assembly_dir( ai )))
2492 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2493 return STATUS_NO_MEMORY;
2496 /* lookup in appdir\name.dll
2497 * appdir\name.manifest
2498 * appdir\name\name.dll
2499 * appdir\name\name.manifest
2501 strcpyW( buffer, acl->actctx->appdir.info );
2502 p = buffer + strlenW(buffer);
2503 for (i = 0; i < 2; i++)
2505 *p++ = '\\';
2506 strcpyW( p, ai->name );
2507 p += strlenW(p);
2509 strcpyW( p, dotDllW );
2510 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2512 status = open_nt_file( &file, &nameW );
2513 if (!status)
2515 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2516 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2517 NtClose( file );
2518 break;
2520 RtlFreeUnicodeString( &nameW );
2523 strcpyW( p, dotManifestW );
2524 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2526 status = open_nt_file( &file, &nameW );
2527 if (!status)
2529 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2530 NtClose( file );
2531 break;
2533 RtlFreeUnicodeString( &nameW );
2535 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2537 RtlFreeUnicodeString( &nameW );
2538 RtlFreeHeap( GetProcessHeap(), 0, directory );
2539 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2540 return status;
2543 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2545 NTSTATUS status = STATUS_SUCCESS;
2546 unsigned int i;
2548 for (i = 0; i < acl->num_dependencies; i++)
2550 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2552 if (!acl->dependencies[i].optional)
2554 FIXME( "Could not find dependent assembly %s (%s)\n",
2555 debugstr_w(acl->dependencies[i].name),
2556 debugstr_version(&acl->dependencies[i].version) );
2557 status = STATUS_SXS_CANT_GEN_ACTCTX;
2558 break;
2562 /* FIXME should now iterate through all refs */
2563 return status;
2566 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2567 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2569 NTSTATUS status = STATUS_SUCCESS;
2571 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2573 if (*handle) return STATUS_INVALID_PARAMETER;
2575 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2576 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2578 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2580 ULONG magic;
2581 LDR_MODULE *pldr;
2583 if (!*handle) return STATUS_INVALID_PARAMETER;
2585 LdrLockLoaderLock( 0, NULL, &magic );
2586 if (!LdrFindEntryForAddress( *handle, &pldr ))
2588 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2589 status = STATUS_DLL_NOT_FOUND;
2590 else
2591 *handle = pldr->ActivationContext;
2593 else status = STATUS_DLL_NOT_FOUND;
2594 LdrUnlockLoaderLock( 0, magic );
2596 else if (!*handle && (class != ActivationContextBasicInformation))
2597 *handle = process_actctx;
2599 return status;
2602 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2604 unsigned int i, j, total_len = 0, dll_count = 0;
2605 struct strsection_header *header;
2606 struct dllredirect_data *data;
2607 struct string_index *index;
2608 ULONG name_offset;
2610 /* compute section length */
2611 for (i = 0; i < actctx->num_assemblies; i++)
2613 struct assembly *assembly = &actctx->assemblies[i];
2614 for (j = 0; j < assembly->num_dlls; j++)
2616 struct dll_redirect *dll = &assembly->dlls[j];
2618 /* each entry needs index, data and string data */
2619 total_len += sizeof(*index);
2620 total_len += sizeof(*data);
2621 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
2624 dll_count += assembly->num_dlls;
2627 total_len += sizeof(*header);
2629 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
2630 if (!header) return STATUS_NO_MEMORY;
2632 memset(header, 0, sizeof(*header));
2633 header->magic = STRSECTION_MAGIC;
2634 header->size = sizeof(*header);
2635 header->count = dll_count;
2636 header->index_offset = sizeof(*header);
2637 index = (struct string_index*)((BYTE*)header + header->index_offset);
2638 name_offset = header->index_offset + header->count*sizeof(*index);
2640 for (i = 0; i < actctx->num_assemblies; i++)
2642 struct assembly *assembly = &actctx->assemblies[i];
2643 for (j = 0; j < assembly->num_dlls; j++)
2645 struct dll_redirect *dll = &assembly->dlls[j];
2646 UNICODE_STRING str;
2647 WCHAR *ptrW;
2649 /* setup new index entry */
2650 str.Buffer = dll->name;
2651 str.Length = strlenW(dll->name)*sizeof(WCHAR);
2652 str.MaximumLength = str.Length + sizeof(WCHAR);
2653 /* hash original class name */
2654 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
2656 index->name_offset = name_offset;
2657 index->name_len = str.Length;
2658 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
2659 index->data_len = sizeof(*data);
2660 index->rosterindex = i + 1;
2662 /* setup data */
2663 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
2664 data->size = sizeof(*data);
2665 data->unk = 2; /* FIXME: seems to be constant */
2666 memset(data->res, 0, sizeof(data->res));
2668 /* dll name */
2669 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
2670 memcpy(ptrW, dll->name, index->name_len);
2671 ptrW[index->name_len/sizeof(WCHAR)] = 0;
2673 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
2675 index++;
2679 *section = header;
2681 return STATUS_SUCCESS;
2684 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
2686 struct string_index *iter, *index = NULL;
2687 ULONG hash = 0, i;
2689 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
2690 iter = (struct string_index*)((BYTE*)section + section->index_offset);
2692 for (i = 0; i < section->count; i++)
2694 if (iter->hash == hash)
2696 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
2698 if (!strcmpiW(nameW, name->Buffer))
2700 index = iter;
2701 break;
2703 else
2704 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
2706 iter++;
2709 return index;
2712 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
2714 struct guid_index *iter, *index = NULL;
2715 ULONG i;
2717 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
2719 for (i = 0; i < section->count; i++)
2721 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
2723 index = iter;
2724 break;
2726 iter++;
2729 return index;
2732 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
2734 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
2737 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
2738 PACTCTX_SECTION_KEYED_DATA data)
2740 struct dllredirect_data *dll;
2741 struct string_index *index;
2743 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
2745 if (!actctx->dllredirect_section)
2747 struct strsection_header *section;
2749 NTSTATUS status = build_dllredirect_section(actctx, &section);
2750 if (status) return status;
2752 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
2753 RtlFreeHeap(GetProcessHeap(), 0, section);
2756 index = find_string_index(actctx->dllredirect_section, name);
2757 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
2759 dll = get_dllredirect_data(actctx, index);
2761 data->ulDataFormatVersion = 1;
2762 data->lpData = dll;
2763 data->ulLength = dll->size;
2764 data->lpSectionGlobalData = NULL;
2765 data->ulSectionGlobalDataLength = 0;
2766 data->lpSectionBase = actctx->dllredirect_section;
2767 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
2768 data->hActCtx = NULL;
2770 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
2771 data->ulAssemblyRosterIndex = index->rosterindex;
2773 return STATUS_SUCCESS;
2776 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
2778 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
2781 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
2783 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
2786 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2788 unsigned int i, j, k, total_len = 0, class_count = 0;
2789 struct wndclass_redirect_data *data;
2790 struct strsection_header *header;
2791 struct string_index *index;
2792 ULONG name_offset;
2794 /* compute section length */
2795 for (i = 0; i < actctx->num_assemblies; i++)
2797 struct assembly *assembly = &actctx->assemblies[i];
2798 for (j = 0; j < assembly->num_dlls; j++)
2800 struct dll_redirect *dll = &assembly->dlls[j];
2801 for (k = 0; k < dll->entities.num; k++)
2803 struct entity *entity = &dll->entities.base[k];
2804 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
2806 int class_len = strlenW(entity->u.class.name) + 1;
2807 int len;
2809 /* each class entry needs index, data and string data */
2810 total_len += sizeof(*index);
2811 total_len += sizeof(*data);
2812 /* original name is stored separately */
2813 total_len += aligned_string_len(class_len*sizeof(WCHAR));
2814 /* versioned name and module name are stored one after another */
2815 if (entity->u.class.versioned)
2816 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
2817 else
2818 len = class_len;
2819 len += strlenW(dll->name) + 1;
2820 total_len += aligned_string_len(len*sizeof(WCHAR));
2822 class_count++;
2828 total_len += sizeof(*header);
2830 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
2831 if (!header) return STATUS_NO_MEMORY;
2833 memset(header, 0, sizeof(*header));
2834 header->magic = STRSECTION_MAGIC;
2835 header->size = sizeof(*header);
2836 header->count = class_count;
2837 header->index_offset = sizeof(*header);
2838 index = (struct string_index*)((BYTE*)header + header->index_offset);
2839 name_offset = header->index_offset + header->count*sizeof(*index);
2841 for (i = 0; i < actctx->num_assemblies; i++)
2843 struct assembly *assembly = &actctx->assemblies[i];
2844 for (j = 0; j < assembly->num_dlls; j++)
2846 struct dll_redirect *dll = &assembly->dlls[j];
2847 for (k = 0; k < dll->entities.num; k++)
2849 struct entity *entity = &dll->entities.base[k];
2850 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
2852 static const WCHAR exclW[] = {'!',0};
2853 ULONG versioned_len, module_len;
2854 UNICODE_STRING str;
2855 WCHAR *ptrW;
2857 /* setup new index entry */
2858 str.Buffer = entity->u.class.name;
2859 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
2860 str.MaximumLength = str.Length + sizeof(WCHAR);
2861 /* hash original class name */
2862 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
2864 /* include '!' separator too */
2865 if (entity->u.class.versioned)
2866 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
2867 else
2868 versioned_len = str.Length;
2869 module_len = strlenW(dll->name)*sizeof(WCHAR);
2871 index->name_offset = name_offset;
2872 index->name_len = str.Length;
2873 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
2874 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
2875 index->rosterindex = i + 1;
2877 /* setup data */
2878 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
2879 data->size = sizeof(*data);
2880 data->res = 0;
2881 data->name_len = versioned_len;
2882 data->name_offset = sizeof(*data);
2883 data->module_len = module_len;
2884 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
2886 /* original class name */
2887 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
2888 memcpy(ptrW, entity->u.class.name, index->name_len);
2889 ptrW[index->name_len/sizeof(WCHAR)] = 0;
2891 /* module name */
2892 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
2893 memcpy(ptrW, dll->name, data->module_len);
2894 ptrW[data->module_len/sizeof(WCHAR)] = 0;
2896 /* versioned name */
2897 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
2898 if (entity->u.class.versioned)
2900 get_assembly_version(assembly, ptrW);
2901 strcatW(ptrW, exclW);
2902 strcatW(ptrW, entity->u.class.name);
2904 else
2906 memcpy(ptrW, entity->u.class.name, index->name_len);
2907 ptrW[index->name_len/sizeof(WCHAR)] = 0;
2910 name_offset += sizeof(*data);
2911 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
2913 index++;
2919 *section = header;
2921 return STATUS_SUCCESS;
2924 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
2925 PACTCTX_SECTION_KEYED_DATA data)
2927 struct string_index *iter, *index = NULL;
2928 struct wndclass_redirect_data *class;
2929 ULONG hash;
2930 int i;
2932 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
2934 if (!actctx->wndclass_section)
2936 struct strsection_header *section;
2938 NTSTATUS status = build_wndclass_section(actctx, &section);
2939 if (status) return status;
2941 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
2942 RtlFreeHeap(GetProcessHeap(), 0, section);
2945 hash = 0;
2946 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
2947 iter = get_wndclass_first_index(actctx);
2949 for (i = 0; i < actctx->wndclass_section->count; i++)
2951 if (iter->hash == hash)
2953 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
2955 if (!strcmpW(nameW, name->Buffer))
2957 index = iter;
2958 break;
2960 else
2961 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
2963 iter++;
2966 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
2968 class = get_wndclass_data(actctx, index);
2970 data->ulDataFormatVersion = 1;
2971 data->lpData = class;
2972 /* full length includes string length with nulls */
2973 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
2974 data->lpSectionGlobalData = NULL;
2975 data->ulSectionGlobalDataLength = 0;
2976 data->lpSectionBase = actctx->wndclass_section;
2977 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
2978 data->hActCtx = NULL;
2980 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
2981 data->ulAssemblyRosterIndex = index->rosterindex;
2983 return STATUS_SUCCESS;
2986 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
2988 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
2989 struct guidsection_header *header;
2990 ULONG module_offset, data_offset;
2991 struct tlibredirect_data *data;
2992 struct guid_index *index;
2994 /* compute section length */
2995 for (i = 0; i < actctx->num_assemblies; i++)
2997 struct assembly *assembly = &actctx->assemblies[i];
2998 for (j = 0; j < assembly->num_dlls; j++)
3000 struct dll_redirect *dll = &assembly->dlls[j];
3001 for (k = 0; k < dll->entities.num; k++)
3003 struct entity *entity = &dll->entities.base[k];
3004 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3006 /* each entry needs index, data and string data for module name and help string */
3007 total_len += sizeof(*index);
3008 total_len += sizeof(*data);
3009 /* help string is stored separately */
3010 if (*entity->u.typelib.helpdir)
3011 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3013 /* module names are packed one after another */
3014 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3016 tlib_count++;
3022 total_len += aligned_string_len(names_len);
3023 total_len += sizeof(*header);
3025 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3026 if (!header) return STATUS_NO_MEMORY;
3028 memset(header, 0, sizeof(*header));
3029 header->magic = GUIDSECTION_MAGIC;
3030 header->size = sizeof(*header);
3031 header->count = tlib_count;
3032 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3033 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3034 module_offset = sizeof(*header);
3035 data_offset = header->index_offset + tlib_count*sizeof(*index);
3037 for (i = 0; i < actctx->num_assemblies; i++)
3039 struct assembly *assembly = &actctx->assemblies[i];
3040 for (j = 0; j < assembly->num_dlls; j++)
3042 struct dll_redirect *dll = &assembly->dlls[j];
3043 for (k = 0; k < dll->entities.num; k++)
3045 struct entity *entity = &dll->entities.base[k];
3046 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3048 ULONG module_len, help_len;
3049 UNICODE_STRING str;
3050 WCHAR *ptrW;
3052 if (*entity->u.typelib.helpdir)
3053 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3054 else
3055 help_len = 0;
3057 module_len = strlenW(dll->name)*sizeof(WCHAR);
3059 /* setup new index entry */
3060 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3061 RtlGUIDFromString(&str, &index->guid);
3062 index->data_offset = data_offset;
3063 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3064 index->rosterindex = i + 1;
3066 /* setup data */
3067 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3068 data->size = sizeof(*data);
3069 data->res = 0;
3070 data->name_len = module_len;
3071 data->name_offset = module_offset;
3072 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3073 data->langid = 0;
3074 data->flags = entity->u.typelib.flags;
3075 data->help_len = help_len;
3076 data->help_offset = sizeof(*data);
3077 data->major_version = entity->u.typelib.major;
3078 data->minor_version = entity->u.typelib.minor;
3080 /* module name */
3081 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3082 memcpy(ptrW, dll->name, data->name_len);
3083 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3085 /* help string */
3086 if (data->help_len)
3088 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3089 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3090 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3093 data_offset += sizeof(*data);
3094 if (help_len)
3095 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3097 module_offset += module_len + sizeof(WCHAR);
3099 index++;
3105 *section = header;
3107 return STATUS_SUCCESS;
3110 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3112 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3115 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3117 struct guid_index *index = NULL;
3118 struct tlibredirect_data *tlib;
3120 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3122 if (!actctx->tlib_section)
3124 struct guidsection_header *section;
3126 NTSTATUS status = build_tlib_section(actctx, &section);
3127 if (status) return status;
3129 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3130 RtlFreeHeap(GetProcessHeap(), 0, section);
3133 index = find_guid_index(actctx->tlib_section, guid);
3134 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3136 tlib = get_tlib_data(actctx, index);
3138 data->ulDataFormatVersion = 1;
3139 data->lpData = tlib;
3140 /* full length includes string length with nulls */
3141 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3142 data->lpSectionGlobalData = NULL;
3143 data->ulSectionGlobalDataLength = 0;
3144 data->lpSectionBase = actctx->tlib_section;
3145 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3146 data->hActCtx = NULL;
3148 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3149 data->ulAssemblyRosterIndex = index->rosterindex;
3151 return STATUS_SUCCESS;
3154 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
3155 const UNICODE_STRING *section_name,
3156 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
3158 NTSTATUS status;
3160 switch (section_kind)
3162 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
3163 status = find_dll_redirection(actctx, section_name, data);
3164 break;
3165 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
3166 status = find_window_class(actctx, section_name, data);
3167 break;
3168 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
3169 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
3170 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
3171 FIXME("Unsupported yet section_kind %x\n", section_kind);
3172 return STATUS_SXS_SECTION_NOT_FOUND;
3173 default:
3174 WARN("Unknown section_kind %x\n", section_kind);
3175 return STATUS_SXS_SECTION_NOT_FOUND;
3178 if (status != STATUS_SUCCESS) return status;
3180 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3182 actctx_addref(actctx);
3183 data->hActCtx = actctx;
3185 return STATUS_SUCCESS;
3188 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
3189 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
3191 NTSTATUS status;
3193 switch (section_kind)
3195 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
3196 status = find_tlib_redirection(actctx, guid, data);
3197 break;
3198 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
3199 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
3200 FIXME("Unsupported yet section_kind %x\n", section_kind);
3201 return STATUS_SXS_SECTION_NOT_FOUND;
3202 default:
3203 WARN("Unknown section_kind %x\n", section_kind);
3204 return STATUS_SXS_SECTION_NOT_FOUND;
3207 if (status != STATUS_SUCCESS) return status;
3209 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3211 actctx_addref(actctx);
3212 data->hActCtx = actctx;
3214 return STATUS_SUCCESS;
3217 /* initialize the activation context for the current process */
3218 void actctx_init(void)
3220 ACTCTXW ctx;
3221 HANDLE handle;
3223 ctx.cbSize = sizeof(ctx);
3224 ctx.lpSource = NULL;
3225 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
3226 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
3227 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
3229 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
3233 /***********************************************************************
3234 * RtlCreateActivationContext (NTDLL.@)
3236 * Create an activation context.
3238 * FIXME: function signature/prototype is wrong
3240 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
3242 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
3243 const WCHAR *directory = NULL;
3244 ACTIVATION_CONTEXT *actctx;
3245 UNICODE_STRING nameW;
3246 ULONG lang = 0;
3247 NTSTATUS status = STATUS_NO_MEMORY;
3248 HANDLE file = 0;
3249 struct actctx_loader acl;
3251 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
3253 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
3254 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
3255 return STATUS_INVALID_PARAMETER;
3257 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
3258 return STATUS_NO_MEMORY;
3260 actctx->magic = ACTCTX_MAGIC;
3261 actctx->ref_count = 1;
3262 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
3263 actctx->config.info = NULL;
3264 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
3265 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
3267 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
3269 else
3271 UNICODE_STRING dir;
3272 WCHAR *p;
3273 HMODULE module;
3275 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
3276 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
3278 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
3279 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
3280 actctx->appdir.info = dir.Buffer;
3283 nameW.Buffer = NULL;
3284 if (pActCtx->lpSource)
3286 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
3288 status = STATUS_NO_SUCH_FILE;
3289 goto error;
3291 status = open_nt_file( &file, &nameW );
3292 if (status)
3294 RtlFreeUnicodeString( &nameW );
3295 goto error;
3299 acl.actctx = actctx;
3300 acl.dependencies = NULL;
3301 acl.num_dependencies = 0;
3302 acl.allocated_dependencies = 0;
3304 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
3305 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
3307 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
3309 /* if we have a resource it's a PE file */
3310 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
3312 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
3313 pActCtx->lpResourceName, lang );
3314 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
3315 /* FIXME: what to do if pActCtx->lpSource is set */
3316 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
3317 pActCtx->hModule, pActCtx->lpResourceName );
3319 else if (pActCtx->lpSource)
3321 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
3322 file, pActCtx->lpResourceName, lang );
3323 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
3324 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
3325 NULL, pActCtx->lpResourceName );
3327 else status = STATUS_INVALID_PARAMETER;
3329 else
3331 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
3334 if (file) NtClose( file );
3335 RtlFreeUnicodeString( &nameW );
3337 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
3338 free_depend_manifests( &acl );
3340 if (status == STATUS_SUCCESS) *handle = actctx;
3341 else actctx_release( actctx );
3342 return status;
3344 error:
3345 if (file) NtClose( file );
3346 actctx_release( actctx );
3347 return status;
3351 /***********************************************************************
3352 * RtlAddRefActivationContext (NTDLL.@)
3354 void WINAPI RtlAddRefActivationContext( HANDLE handle )
3356 ACTIVATION_CONTEXT *actctx;
3358 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
3362 /******************************************************************
3363 * RtlReleaseActivationContext (NTDLL.@)
3365 void WINAPI RtlReleaseActivationContext( HANDLE handle )
3367 ACTIVATION_CONTEXT *actctx;
3369 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
3373 /******************************************************************
3374 * RtlActivateActivationContext (NTDLL.@)
3376 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
3378 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
3380 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
3381 return STATUS_NO_MEMORY;
3383 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
3384 frame->ActivationContext = handle;
3385 frame->Flags = 0;
3386 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
3387 RtlAddRefActivationContext( handle );
3389 *cookie = (ULONG_PTR)frame;
3390 TRACE( "%p cookie=%lx\n", handle, *cookie );
3391 return STATUS_SUCCESS;
3395 /***********************************************************************
3396 * RtlDeactivateActivationContext (NTDLL.@)
3398 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
3400 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
3402 TRACE( "%x cookie=%lx\n", flags, cookie );
3404 /* find the right frame */
3405 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
3406 for (frame = top; frame; frame = frame->Previous)
3407 if ((ULONG_PTR)frame == cookie) break;
3409 if (!frame)
3410 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
3412 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
3413 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
3415 /* pop everything up to and including frame */
3416 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
3418 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3420 frame = top->Previous;
3421 RtlReleaseActivationContext( top->ActivationContext );
3422 RtlFreeHeap( GetProcessHeap(), 0, top );
3423 top = frame;
3428 /******************************************************************
3429 * RtlFreeThreadActivationContextStack (NTDLL.@)
3431 void WINAPI RtlFreeThreadActivationContextStack(void)
3433 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
3435 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
3436 while (frame)
3438 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
3439 RtlReleaseActivationContext( frame->ActivationContext );
3440 RtlFreeHeap( GetProcessHeap(), 0, frame );
3441 frame = prev;
3443 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
3447 /******************************************************************
3448 * RtlGetActiveActivationContext (NTDLL.@)
3450 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
3452 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3454 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3455 RtlAddRefActivationContext( *handle );
3457 else
3458 *handle = 0;
3460 return STATUS_SUCCESS;
3464 /******************************************************************
3465 * RtlIsActivationContextActive (NTDLL.@)
3467 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
3469 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
3471 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
3472 if (frame->ActivationContext == handle) return TRUE;
3473 return FALSE;
3477 /***********************************************************************
3478 * RtlQueryInformationActivationContext (NTDLL.@)
3480 * Get information about an activation context.
3481 * FIXME: function signature/prototype may be wrong
3483 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
3484 ULONG class, PVOID buffer,
3485 SIZE_T bufsize, SIZE_T *retlen )
3487 ACTIVATION_CONTEXT *actctx;
3488 NTSTATUS status;
3490 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
3491 subinst, class, buffer, bufsize, retlen);
3493 if (retlen) *retlen = 0;
3494 if ((status = find_query_actctx( &handle, flags, class ))) return status;
3496 switch (class)
3498 case ActivationContextBasicInformation:
3500 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
3502 if (retlen) *retlen = sizeof(*info);
3503 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
3505 info->hActCtx = handle;
3506 info->dwFlags = 0; /* FIXME */
3507 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
3509 break;
3511 case ActivationContextDetailedInformation:
3513 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
3514 struct assembly *assembly = NULL;
3515 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
3516 LPWSTR ptr;
3518 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
3520 if (actctx->num_assemblies) assembly = actctx->assemblies;
3522 if (assembly && assembly->manifest.info)
3523 manifest_len = strlenW(assembly->manifest.info) + 1;
3524 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
3525 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
3526 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
3528 if (retlen) *retlen = len;
3529 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
3531 acdi->dwFlags = 0;
3532 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
3533 acdi->ulAssemblyCount = actctx->num_assemblies;
3534 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
3535 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
3536 acdi->ulRootConfigurationPathType = actctx->config.type;
3537 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
3538 acdi->ulAppDirPathType = actctx->appdir.type;
3539 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
3540 ptr = (LPWSTR)(acdi + 1);
3541 if (manifest_len)
3543 acdi->lpRootManifestPath = ptr;
3544 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
3545 ptr += manifest_len;
3547 else acdi->lpRootManifestPath = NULL;
3548 if (config_len)
3550 acdi->lpRootConfigurationPath = ptr;
3551 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
3552 ptr += config_len;
3554 else acdi->lpRootConfigurationPath = NULL;
3555 if (appdir_len)
3557 acdi->lpAppDirPath = ptr;
3558 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
3560 else acdi->lpAppDirPath = NULL;
3562 break;
3564 case AssemblyDetailedInformationInActivationContext:
3566 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
3567 struct assembly *assembly;
3568 WCHAR *assembly_id;
3569 DWORD index;
3570 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
3571 LPWSTR ptr;
3573 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
3574 if (!subinst) return STATUS_INVALID_PARAMETER;
3576 index = *(DWORD*)subinst;
3577 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
3579 assembly = &actctx->assemblies[index - 1];
3581 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
3582 id_len = strlenW(assembly_id) + 1;
3583 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
3585 if (assembly->manifest.info &&
3586 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
3587 path_len = strlenW(assembly->manifest.info) + 1;
3589 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
3591 if (retlen) *retlen = len;
3592 if (!buffer || bufsize < len)
3594 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
3595 return STATUS_BUFFER_TOO_SMALL;
3598 afdi->ulFlags = 0; /* FIXME */
3599 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
3600 afdi->ulManifestPathType = assembly->manifest.type;
3601 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
3602 /* FIXME afdi->liManifestLastWriteTime = 0; */
3603 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
3604 afdi->ulPolicyPathLength = 0;
3605 /* FIXME afdi->liPolicyLastWriteTime = 0; */
3606 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
3607 afdi->ulManifestVersionMajor = 1;
3608 afdi->ulManifestVersionMinor = 0;
3609 afdi->ulPolicyVersionMajor = 0; /* FIXME */
3610 afdi->ulPolicyVersionMinor = 0; /* FIXME */
3611 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
3612 ptr = (LPWSTR)(afdi + 1);
3613 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
3614 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
3615 ptr += id_len;
3616 if (path_len)
3618 afdi->lpAssemblyManifestPath = ptr;
3619 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
3620 ptr += path_len;
3621 } else afdi->lpAssemblyManifestPath = NULL;
3622 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
3623 if (ad_len)
3625 afdi->lpAssemblyDirectoryName = ptr;
3626 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
3628 else afdi->lpAssemblyDirectoryName = NULL;
3629 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
3631 break;
3633 case FileInformationInAssemblyOfAssemblyInActivationContext:
3635 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
3636 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
3637 struct assembly *assembly;
3638 struct dll_redirect *dll;
3639 SIZE_T len, dll_len = 0;
3640 LPWSTR ptr;
3642 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
3643 if (!acqi) return STATUS_INVALID_PARAMETER;
3645 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
3646 return STATUS_INVALID_PARAMETER;
3647 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
3649 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
3650 return STATUS_INVALID_PARAMETER;
3651 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
3653 if (dll->name) dll_len = strlenW(dll->name) + 1;
3654 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
3656 if (!buffer || bufsize < len)
3658 if (retlen) *retlen = len;
3659 return STATUS_BUFFER_TOO_SMALL;
3661 if (retlen) *retlen = 0; /* yes that's what native does !! */
3662 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
3663 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
3664 afdi->ulPathLength = 0; /* FIXME */
3665 ptr = (LPWSTR)(afdi + 1);
3666 if (dll_len)
3668 afdi->lpFileName = ptr;
3669 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
3670 } else afdi->lpFileName = NULL;
3671 afdi->lpFilePath = NULL; /* FIXME */
3673 break;
3675 default:
3676 FIXME( "class %u not implemented\n", class );
3677 return STATUS_NOT_IMPLEMENTED;
3679 return STATUS_SUCCESS;
3682 /***********************************************************************
3683 * RtlFindActivationContextSectionString (NTDLL.@)
3685 * Find information about a string in an activation context.
3686 * FIXME: function signature/prototype may be wrong
3688 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
3689 const UNICODE_STRING *section_name, PVOID ptr )
3691 PACTCTX_SECTION_KEYED_DATA data = ptr;
3692 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
3694 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
3695 debugstr_us(section_name), data);
3697 if (guid)
3699 FIXME("expected guid == NULL\n");
3700 return STATUS_INVALID_PARAMETER;
3702 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3704 FIXME("unknown flags %08x\n", flags);
3705 return STATUS_INVALID_PARAMETER;
3707 if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
3708 !section_name || !section_name->Buffer)
3710 WARN("invalid parameter\n");
3711 return STATUS_INVALID_PARAMETER;
3714 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3716 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
3717 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
3720 if (status != STATUS_SUCCESS)
3721 status = find_string( process_actctx, section_kind, section_name, flags, data );
3723 return status;
3726 /***********************************************************************
3727 * RtlFindActivationContextSectionGuid (NTDLL.@)
3729 * Find information about a GUID in an activation context.
3730 * FIXME: function signature/prototype may be wrong
3732 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
3733 const GUID *guid, void *ptr )
3735 ACTCTX_SECTION_KEYED_DATA *data = ptr;
3736 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
3738 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
3740 if (extguid)
3742 FIXME("expected extguid == NULL\n");
3743 return STATUS_INVALID_PARAMETER;
3746 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3748 FIXME("unknown flags %08x\n", flags);
3749 return STATUS_INVALID_PARAMETER;
3752 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
3753 return STATUS_INVALID_PARAMETER;
3755 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3757 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
3758 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
3761 if (status != STATUS_SUCCESS)
3762 status = find_guid( process_actctx, section_kind, guid, flags, data );
3764 return status;