kernel32: Forward ZombifyActCtx() to ntdll.
[wine.git] / dlls / ntdll / actctx.c
blobf652c18dafb76ab1e6622bb886af5ac7f7f5f3b1
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
222 struct comclassredirect_data
224 ULONG size;
225 BYTE res;
226 BYTE miscmask;
227 BYTE res1[2];
228 DWORD model;
229 GUID clsid;
230 GUID alias;
231 GUID clsid2;
232 GUID tlbid;
233 ULONG name_len;
234 ULONG name_offset;
235 ULONG progid_len;
236 ULONG progid_offset;
237 ULONG clrdata_len;
238 ULONG clrdata_offset;
239 DWORD miscstatus;
240 DWORD miscstatuscontent;
241 DWORD miscstatusthumbnail;
242 DWORD miscstatusicon;
243 DWORD miscstatusdocprint;
246 enum ifaceps_mask
248 NumMethods = 1,
249 BaseIface = 2
252 struct ifacepsredirect_data
254 ULONG size;
255 DWORD mask;
256 GUID iid;
257 ULONG nummethods;
258 GUID tlbid;
259 GUID base;
260 ULONG name_len;
261 ULONG name_offset;
264 struct clrsurrogate_data
266 ULONG size;
267 DWORD res;
268 GUID clsid;
269 ULONG version_offset;
270 ULONG version_len;
271 ULONG name_offset;
272 ULONG name_len;
277 Sections structure.
279 Sections are accessible by string or guid key, that defines two types of sections.
280 All sections of each type have same magic value and header structure, index
281 data could be of two possible types too. So every string based section uses
282 the same index format, same applies to guid sections - they share same guid index
283 format.
285 - window class redirection section is a plain buffer with following format:
287 <section header>
288 <index[]>
289 <data[]> --- <original name>
290 <redirect data>
291 <versioned name>
292 <module name>
294 Header is fixed length structure - struct strsection_header,
295 contains redirected classes count;
297 Index is an array of fixed length index records, each record is
298 struct string_index.
300 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
302 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
303 others are relative to section itself.
305 - dll redirect section format:
307 <section header>
308 <index[]>
309 <data[]> --- <dll name>
310 <data>
312 This section doesn't seem to carry any payload data except dll names.
314 - typelib section format:
316 <section header>
317 <module names[]>
318 <index[]>
319 <data[]> --- <data>
320 <helpstring>
322 Header is fixed length, index is an array of fixed length 'struct guid_index'.
323 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
324 4-bytes aligned as a whole.
326 Module name offsets are relative to section, helpstring offset is relative to data
327 structure itself.
329 - comclass section format:
331 <section header>
332 <module names[]>
333 <index[]>
334 <data[]> --- <data>
335 <progid>
337 This section uses two index records per comclass, one entry contains original guid
338 as specified by context, another one has a generated guid. Index and strings handling
339 is similar to typelib sections.
341 Module name offsets are relative to section, progid offset is relative to data
342 structure itself.
344 - COM interface section format:
346 <section header>
347 <index[]>
348 <data[]> --- <data>
349 <name>
351 Interface section contains data for proxy/stubs and external proxy/stubs. External
352 ones are defined at assembly level, so this section has no module information.
353 All records are indexed with 'iid' value from manifest. There an exception for
354 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
355 redirect data, but index is still 'iid' from manifest.
357 Interface name offset is relative to data structure itself.
359 - CLR surrogates section format:
361 <section header>
362 <index[]>
363 <data[]> --- <data>
364 <name>
365 <version>
367 There's nothing special about this section, same way to store strings is used,
368 no modules part as it belongs to assembly level, not a file.
371 struct entity
373 DWORD kind;
374 union
376 struct
378 WCHAR *tlbid;
379 WCHAR *helpdir;
380 WORD flags;
381 WORD major;
382 WORD minor;
383 } typelib;
384 struct
386 WCHAR *clsid;
387 WCHAR *tlbid;
388 WCHAR *progid;
389 WCHAR *name; /* not NULL for clrClass */
390 WCHAR *version;
391 DWORD model;
392 DWORD miscstatus;
393 DWORD miscstatuscontent;
394 DWORD miscstatusthumbnail;
395 DWORD miscstatusicon;
396 DWORD miscstatusdocprint;
397 } comclass;
398 struct {
399 WCHAR *iid;
400 WCHAR *base;
401 WCHAR *tlib;
402 WCHAR *name;
403 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
404 DWORD mask;
405 ULONG nummethods;
406 } ifaceps;
407 struct
409 WCHAR *name;
410 BOOL versioned;
411 } class;
412 struct
414 WCHAR *name;
415 WCHAR *clsid;
416 WCHAR *version;
417 } clrsurrogate;
418 } u;
421 struct entity_array
423 struct entity *base;
424 unsigned int num;
425 unsigned int allocated;
428 struct dll_redirect
430 WCHAR *name;
431 WCHAR *hash;
432 struct entity_array entities;
435 enum assembly_type
437 APPLICATION_MANIFEST,
438 ASSEMBLY_MANIFEST,
439 ASSEMBLY_SHARED_MANIFEST,
442 struct assembly
444 enum assembly_type type;
445 struct assembly_identity id;
446 struct file_info manifest;
447 WCHAR *directory;
448 BOOL no_inherit;
449 struct dll_redirect *dlls;
450 unsigned int num_dlls;
451 unsigned int allocated_dlls;
452 struct entity_array entities;
455 enum context_sections
457 WINDOWCLASS_SECTION = 1,
458 DLLREDIRECT_SECTION = 2,
459 TLIBREDIRECT_SECTION = 4,
460 SERVERREDIRECT_SECTION = 8,
461 IFACEREDIRECT_SECTION = 16,
462 CLRSURROGATES_SECTION = 32
465 typedef struct _ACTIVATION_CONTEXT
467 ULONG magic;
468 int ref_count;
469 struct file_info config;
470 struct file_info appdir;
471 struct assembly *assemblies;
472 unsigned int num_assemblies;
473 unsigned int allocated_assemblies;
474 /* section data */
475 DWORD sections;
476 struct strsection_header *wndclass_section;
477 struct strsection_header *dllredirect_section;
478 struct guidsection_header *tlib_section;
479 struct guidsection_header *comserver_section;
480 struct guidsection_header *ifaceps_section;
481 struct guidsection_header *clrsurrogate_section;
482 } ACTIVATION_CONTEXT;
484 struct actctx_loader
486 ACTIVATION_CONTEXT *actctx;
487 struct assembly_identity *dependencies;
488 unsigned int num_dependencies;
489 unsigned int allocated_dependencies;
492 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
493 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
494 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
495 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
496 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
497 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
498 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
499 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
500 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};
501 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};
502 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
503 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
504 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
505 static const WCHAR fileW[] = {'f','i','l','e',0};
506 static const WCHAR hashW[] = {'h','a','s','h',0};
507 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
508 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
509 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
510 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
512 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
513 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
514 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
515 static const WCHAR iidW[] = {'i','i','d',0};
516 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
517 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
518 static const WCHAR nameW[] = {'n','a','m','e',0};
519 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
520 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
521 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
522 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
523 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};
524 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
525 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
526 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
527 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
528 static const WCHAR typeW[] = {'t','y','p','e',0};
529 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
530 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
531 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
532 static const WCHAR yesW[] = {'y','e','s',0};
533 static const WCHAR noW[] = {'n','o',0};
534 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
535 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
536 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
537 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
538 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
539 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
540 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
541 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
542 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
543 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
544 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
545 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
546 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
547 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
549 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
550 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
551 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
552 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
553 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
554 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
555 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
556 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};
557 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
558 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
559 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
560 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
561 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
562 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
563 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
564 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
565 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};
566 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
567 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
568 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
569 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};
570 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
572 struct olemisc_entry
574 const WCHAR *name;
575 OLEMISC value;
578 static const struct olemisc_entry olemisc_values[] =
580 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
581 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
582 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
583 { alignableW, OLEMISC_ALIGNABLE },
584 { alwaysrunW, OLEMISC_ALWAYSRUN },
585 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
586 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
587 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
588 { imemodeW, OLEMISC_IMEMODE },
589 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
590 { insideoutW, OLEMISC_INSIDEOUT },
591 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
592 { islinkobjectW, OLEMISC_ISLINKOBJECT },
593 { nouiactivateW, OLEMISC_NOUIACTIVATE },
594 { onlyiconicW, OLEMISC_ONLYICONIC },
595 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
596 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
597 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
598 { simpleframeW, OLEMISC_SIMPLEFRAME },
599 { staticW, OLEMISC_STATIC },
600 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
601 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
604 static const WCHAR xmlW[] = {'?','x','m','l',0};
605 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};
606 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};
608 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
609 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
610 static const WCHAR wildcardW[] = {'*',0};
612 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
613 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
615 static WCHAR *strdupW(const WCHAR* str)
617 WCHAR* ptr;
619 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
620 return NULL;
621 return strcpyW(ptr, str);
624 static WCHAR *xmlstrdupW(const xmlstr_t* str)
626 WCHAR *strW;
628 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
630 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
631 strW[str->len] = 0;
633 return strW;
636 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
638 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
641 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
643 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
646 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
648 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
649 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
652 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
654 UINT len = strlenW( namespace );
656 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
657 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
658 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
661 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
663 if (elem->len && elem->ptr[0] == '/')
665 xmlstr_t elem_end;
666 elem_end.ptr = elem->ptr + 1;
667 elem_end.len = elem->len - 1;
668 return xml_elem_cmp( &elem_end, str, namespace );
670 return FALSE;
673 static inline BOOL isxmlspace( WCHAR ch )
675 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
678 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
680 return debugstr_wn(str->ptr, str->len);
683 static inline const char* debugstr_version(const struct assembly_version *ver)
685 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
688 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
690 struct assembly *assembly;
692 if (actctx->num_assemblies == actctx->allocated_assemblies)
694 void *ptr;
695 unsigned int new_count;
696 if (actctx->assemblies)
698 new_count = actctx->allocated_assemblies * 2;
699 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
700 actctx->assemblies, new_count * sizeof(*assembly) );
702 else
704 new_count = 4;
705 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
707 if (!ptr) return NULL;
708 actctx->assemblies = ptr;
709 actctx->allocated_assemblies = new_count;
712 assembly = &actctx->assemblies[actctx->num_assemblies++];
713 assembly->type = at;
714 return assembly;
717 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
719 if (assembly->num_dlls == assembly->allocated_dlls)
721 void *ptr;
722 unsigned int new_count;
723 if (assembly->dlls)
725 new_count = assembly->allocated_dlls * 2;
726 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
727 assembly->dlls, new_count * sizeof(*assembly->dlls) );
729 else
731 new_count = 4;
732 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
734 if (!ptr) return NULL;
735 assembly->dlls = ptr;
736 assembly->allocated_dlls = new_count;
738 return &assembly->dlls[assembly->num_dlls++];
741 static void free_assembly_identity(struct assembly_identity *ai)
743 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
744 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
745 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
746 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
747 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
750 static struct entity* add_entity(struct entity_array *array, DWORD kind)
752 struct entity* entity;
754 if (array->num == array->allocated)
756 void *ptr;
757 unsigned int new_count;
758 if (array->base)
760 new_count = array->allocated * 2;
761 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
762 array->base, new_count * sizeof(*array->base) );
764 else
766 new_count = 4;
767 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
769 if (!ptr) return NULL;
770 array->base = ptr;
771 array->allocated = new_count;
773 entity = &array->base[array->num++];
774 entity->kind = kind;
775 return entity;
778 static void free_entity_array(struct entity_array *array)
780 unsigned int i;
781 for (i = 0; i < array->num; i++)
783 struct entity *entity = &array->base[i];
784 switch (entity->kind)
786 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
787 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
788 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
789 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
790 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
791 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
792 break;
793 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
794 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
795 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
796 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
797 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
798 break;
799 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
800 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
801 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
802 break;
803 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
804 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
805 break;
806 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
807 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
808 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
809 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
810 break;
811 default:
812 FIXME("Unknown entity kind %d\n", entity->kind);
815 RtlFreeHeap( GetProcessHeap(), 0, array->base );
818 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
820 if (!str1) return !str2;
821 return str2 && !strcmpiW( str1, str2 );
824 static BOOL is_matching_identity( const struct assembly_identity *id1,
825 const struct assembly_identity *id2 )
827 if (!is_matching_string( id1->name, id2->name )) return FALSE;
828 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
829 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
831 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
833 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
834 return FALSE;
836 if (id1->version.major != id2->version.major) return FALSE;
837 if (id1->version.minor != id2->version.minor) return FALSE;
838 if (id1->version.build > id2->version.build) return FALSE;
839 if (id1->version.build == id2->version.build &&
840 id1->version.revision > id2->version.revision) return FALSE;
841 return TRUE;
844 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
845 struct assembly_identity* ai)
847 unsigned int i;
849 /* check if we already have that assembly */
851 for (i = 0; i < acl->actctx->num_assemblies; i++)
852 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
854 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
855 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
856 ai->version.build, ai->version.revision );
857 return TRUE;
860 for (i = 0; i < acl->num_dependencies; i++)
861 if (is_matching_identity( ai, &acl->dependencies[i] ))
863 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
864 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
865 ai->version.build, ai->version.revision );
866 return TRUE;
869 if (acl->num_dependencies == acl->allocated_dependencies)
871 void *ptr;
872 unsigned int new_count;
873 if (acl->dependencies)
875 new_count = acl->allocated_dependencies * 2;
876 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
877 new_count * sizeof(acl->dependencies[0]));
879 else
881 new_count = 4;
882 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
884 if (!ptr) return FALSE;
885 acl->dependencies = ptr;
886 acl->allocated_dependencies = new_count;
888 acl->dependencies[acl->num_dependencies++] = *ai;
890 return TRUE;
893 static void free_depend_manifests(struct actctx_loader* acl)
895 unsigned int i;
896 for (i = 0; i < acl->num_dependencies; i++)
897 free_assembly_identity(&acl->dependencies[i]);
898 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
901 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
903 static const WCHAR undW[] = {'_',0};
904 static const WCHAR noneW[] = {'n','o','n','e',0};
905 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
907 const WCHAR *arch = ai->arch ? ai->arch : noneW;
908 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
909 const WCHAR *lang = ai->language ? ai->language : noneW;
910 const WCHAR *name = ai->name ? ai->name : noneW;
911 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
912 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
913 WCHAR *ret;
915 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
917 strcpyW( ret, arch );
918 strcatW( ret, undW );
919 strcatW( ret, name );
920 strcatW( ret, undW );
921 strcatW( ret, key );
922 strcatW( ret, undW );
923 sprintfW( ret + strlenW(ret), version_formatW,
924 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
925 strcatW( ret, undW );
926 strcatW( ret, lang );
927 strcatW( ret, undW );
928 strcatW( ret, mskeyW );
929 return ret;
932 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
934 WCHAR *p = buffer;
936 if (!str) return;
937 strcatW( buffer, prefix );
938 p += strlenW(p);
939 *p++ = '"';
940 strcpyW( p, str );
941 p += strlenW(p);
942 *p++ = '"';
943 *p = 0;
946 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
948 static const WCHAR archW[] =
949 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
950 static const WCHAR public_keyW[] =
951 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
952 static const WCHAR typeW[] =
953 {',','t','y','p','e','=',0};
954 static const WCHAR versionW[] =
955 {',','v','e','r','s','i','o','n','=',0};
957 WCHAR version[64], *ret;
958 SIZE_T size = 0;
960 sprintfW( version, version_formatW,
961 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
962 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
963 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
964 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
965 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
966 size += strlenW(versionW) + strlenW(version) + 2;
968 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
969 return NULL;
971 if (ai->name) strcpyW( ret, ai->name );
972 else *ret = 0;
973 append_string( ret, archW, ai->arch );
974 append_string( ret, public_keyW, ai->public_key );
975 append_string( ret, typeW, ai->type );
976 append_string( ret, versionW, version );
977 return ret;
980 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
982 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
984 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
985 __TRY
987 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
989 __EXCEPT_PAGE_FAULT
992 __ENDTRY
993 return ret;
996 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
998 interlocked_xchg_add( &actctx->ref_count, 1 );
1001 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1003 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1005 unsigned int i, j;
1007 for (i = 0; i < actctx->num_assemblies; i++)
1009 struct assembly *assembly = &actctx->assemblies[i];
1010 for (j = 0; j < assembly->num_dlls; j++)
1012 struct dll_redirect *dll = &assembly->dlls[j];
1013 free_entity_array( &dll->entities );
1014 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1015 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1017 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1018 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1019 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1020 free_entity_array( &assembly->entities );
1021 free_assembly_identity(&assembly->id);
1023 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1024 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1025 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1026 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1027 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1028 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1029 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1030 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1031 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1032 actctx->magic = 0;
1033 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1037 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1038 BOOL* error, BOOL* end)
1040 const WCHAR* ptr;
1042 *error = TRUE;
1044 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1045 xmlbuf->ptr++;
1047 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1049 if (*xmlbuf->ptr == '/')
1051 xmlbuf->ptr++;
1052 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1053 return FALSE;
1055 xmlbuf->ptr++;
1056 *end = TRUE;
1057 *error = FALSE;
1058 return FALSE;
1061 if (*xmlbuf->ptr == '>')
1063 xmlbuf->ptr++;
1064 *error = FALSE;
1065 return FALSE;
1068 ptr = xmlbuf->ptr;
1069 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1071 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1073 name->ptr = xmlbuf->ptr;
1074 name->len = ptr-xmlbuf->ptr;
1075 xmlbuf->ptr = ptr;
1077 ptr++;
1078 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1080 value->ptr = ++ptr;
1081 if (ptr == xmlbuf->end) return FALSE;
1083 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1084 if (!ptr)
1086 xmlbuf->ptr = xmlbuf->end;
1087 return FALSE;
1090 value->len = ptr - value->ptr;
1091 xmlbuf->ptr = ptr + 1;
1093 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1095 *error = FALSE;
1096 return TRUE;
1099 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1101 const WCHAR* ptr;
1103 for (;;)
1105 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1106 if (!ptr)
1108 xmlbuf->ptr = xmlbuf->end;
1109 return FALSE;
1111 ptr++;
1112 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1114 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1115 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1117 if (ptr + 3 > xmlbuf->end)
1119 xmlbuf->ptr = xmlbuf->end;
1120 return FALSE;
1122 xmlbuf->ptr = ptr + 3;
1124 else break;
1127 xmlbuf->ptr = ptr;
1128 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1129 ptr++;
1131 elem->ptr = xmlbuf->ptr;
1132 elem->len = ptr - xmlbuf->ptr;
1133 xmlbuf->ptr = ptr;
1134 return xmlbuf->ptr != xmlbuf->end;
1137 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1139 /* FIXME: parse attributes */
1140 const WCHAR *ptr;
1142 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1144 if (ptr[0] == '?' && ptr[1] == '>')
1146 xmlbuf->ptr = ptr + 2;
1147 return TRUE;
1150 return FALSE;
1153 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1155 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1157 if (!ptr) return FALSE;
1159 content->ptr = xmlbuf->ptr;
1160 content->len = ptr - xmlbuf->ptr;
1161 xmlbuf->ptr = ptr;
1163 return TRUE;
1166 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1168 unsigned int ver[4];
1169 unsigned int pos;
1170 const WCHAR *curr;
1172 /* major.minor.build.revision */
1173 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1174 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1176 if (*curr >= '0' && *curr <= '9')
1178 ver[pos] = ver[pos] * 10 + *curr - '0';
1179 if (ver[pos] >= 0x10000) goto error;
1181 else if (*curr == '.')
1183 if (++pos >= 4) goto error;
1185 else goto error;
1187 version->major = ver[0];
1188 version->minor = ver[1];
1189 version->build = ver[2];
1190 version->revision = ver[3];
1191 return TRUE;
1193 error:
1194 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1195 return FALSE;
1198 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1200 xmlstr_t elem;
1201 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1202 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1203 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1204 return FALSE;
1207 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1209 xmlstr_t attr_name, attr_value;
1210 BOOL error;
1212 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1214 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1215 debugstr_xmlstr(&attr_value));
1217 return !error;
1220 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1222 BOOL end = FALSE;
1223 return parse_expect_no_attr(xmlbuf, &end) && !end;
1226 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1228 xmlstr_t elem;
1229 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1230 if (!xml_elem_cmp_end(&elem, name, namespace))
1232 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1233 return FALSE;
1235 return parse_end_element(xmlbuf);
1238 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1240 xmlstr_t attr_name, attr_value, elem;
1241 BOOL end = FALSE, error, ret = TRUE;
1243 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1244 if(error || end) return end;
1246 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1248 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1249 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1250 break;
1251 else
1252 ret = parse_unknown_elem(xmlbuf, &elem);
1255 return ret && parse_end_element(xmlbuf);
1258 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1259 struct assembly_identity* ai)
1261 xmlstr_t attr_name, attr_value;
1262 BOOL end = FALSE, error;
1264 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1266 if (xmlstr_cmp(&attr_name, nameW))
1268 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1270 else if (xmlstr_cmp(&attr_name, typeW))
1272 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1274 else if (xmlstr_cmp(&attr_name, versionW))
1276 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1278 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1280 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1282 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1284 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1286 else if (xmlstr_cmp(&attr_name, languageW))
1288 WARN("Unsupported yet language attribute (%s)\n",
1289 debugstr_xmlstr(&attr_value));
1290 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1292 else
1294 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1295 debugstr_xmlstr(&attr_value));
1299 TRACE( "name=%s version=%s arch=%s\n",
1300 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1302 if (error || end) return end;
1303 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1306 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1308 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1309 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1310 static const WCHAR freeW[] = {'F','r','e','e',0};
1311 static const WCHAR bothW[] = {'B','o','t','h',0};
1313 if (value->len == 0) return ThreadingModel_No;
1314 if (xmlstr_cmp(value, apartW))
1315 return ThreadingModel_Apartment;
1316 else if (xmlstr_cmp(value, freeW))
1317 return ThreadingModel_Free;
1318 else if (xmlstr_cmp(value, bothW))
1319 return ThreadingModel_Both;
1320 else if (xmlstr_cmp(value, neutralW))
1321 return ThreadingModel_Neutral;
1322 else
1323 return ThreadingModel_No;
1326 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1328 int min, max;
1330 min = 0;
1331 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1333 while (min <= max)
1335 int n, c;
1337 n = (min+max)/2;
1339 c = strncmpW(olemisc_values[n].name, str, len);
1340 if (!c && !olemisc_values[n].name[len])
1341 return olemisc_values[n].value;
1343 if (c >= 0)
1344 max = n-1;
1345 else
1346 min = n+1;
1349 WARN("unknown flag %s\n", debugstr_wn(str, len));
1350 return 0;
1353 static DWORD parse_com_class_misc(const xmlstr_t *value)
1355 const WCHAR *str = value->ptr, *start;
1356 DWORD flags = 0;
1357 int i = 0;
1359 /* it's comma separated list of flags */
1360 while (i < value->len)
1362 start = str;
1363 while (*str != ',' && (i++ < value->len)) str++;
1365 flags |= get_olemisc_value(start, str-start);
1367 /* skip separator */
1368 str++;
1369 i++;
1372 return flags;
1375 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1377 xmlstr_t elem, attr_name, attr_value;
1378 BOOL ret, end = FALSE, error;
1379 struct entity* entity;
1381 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1382 return FALSE;
1384 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1386 if (xmlstr_cmp(&attr_name, clsidW))
1388 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1390 else if (xmlstr_cmp(&attr_name, progidW))
1392 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1394 else if (xmlstr_cmp(&attr_name, tlbidW))
1396 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1398 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1400 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1402 else if (xmlstr_cmp(&attr_name, miscstatusW))
1404 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1406 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1408 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1410 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1412 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1414 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1416 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1418 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1420 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1422 else
1424 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1428 if (error) return FALSE;
1430 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1432 if (end) return TRUE;
1434 while ((ret = next_xml_elem(xmlbuf, &elem)))
1436 if (xmlstr_cmp_end(&elem, comClassW))
1438 ret = parse_end_element(xmlbuf);
1439 break;
1441 else
1443 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1444 ret = parse_unknown_elem(xmlbuf, &elem);
1447 return ret;
1450 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1452 const WCHAR *curr;
1453 ULONG num = 0;
1455 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1457 if (*curr >= '0' && *curr <= '9')
1458 num = num * 10 + *curr - '0';
1459 else
1461 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1462 return FALSE;
1465 entity->u.ifaceps.nummethods = num;
1467 return TRUE;
1470 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1472 xmlstr_t attr_name, attr_value;
1473 BOOL end = FALSE, error;
1474 struct entity* entity;
1476 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1477 return FALSE;
1479 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1481 if (xmlstr_cmp(&attr_name, iidW))
1483 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1485 else if (xmlstr_cmp(&attr_name, nameW))
1487 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1489 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1491 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1492 entity->u.ifaceps.mask |= BaseIface;
1494 else if (xmlstr_cmp(&attr_name, nummethodsW))
1496 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1497 entity->u.ifaceps.mask |= NumMethods;
1499 else if (xmlstr_cmp(&attr_name, tlbidW))
1501 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1503 /* not used */
1504 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1507 else
1509 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1513 if (error) return FALSE;
1514 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1515 if (end) return TRUE;
1517 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1520 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1522 WORD *flags = &entity->u.typelib.flags;
1523 const WCHAR *str = value->ptr, *start;
1524 int i = 0;
1526 *flags = 0;
1528 /* it's comma separated list of flags */
1529 while (i < value->len)
1531 start = str;
1532 while (*str != ',' && (i++ < value->len)) str++;
1534 if (!strncmpW(start, restrictedW, str-start))
1535 *flags |= LIBFLAG_FRESTRICTED;
1536 else if (!strncmpW(start, controlW, str-start))
1537 *flags |= LIBFLAG_FCONTROL;
1538 else if (!strncmpW(start, hiddenW, str-start))
1539 *flags |= LIBFLAG_FHIDDEN;
1540 else if (!strncmpW(start, hasdiskimageW, str-start))
1541 *flags |= LIBFLAG_FHASDISKIMAGE;
1542 else
1544 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1545 return FALSE;
1548 /* skip separator */
1549 str++;
1550 i++;
1553 return TRUE;
1556 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1558 unsigned int ver[2];
1559 unsigned int pos;
1560 const WCHAR *curr;
1562 /* major.minor */
1563 ver[0] = ver[1] = pos = 0;
1564 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1566 if (*curr >= '0' && *curr <= '9')
1568 ver[pos] = ver[pos] * 10 + *curr - '0';
1569 if (ver[pos] >= 0x10000) goto error;
1571 else if (*curr == '.')
1573 if (++pos >= 2) goto error;
1575 else goto error;
1577 entity->u.typelib.major = ver[0];
1578 entity->u.typelib.minor = ver[1];
1579 return TRUE;
1581 error:
1582 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1583 return FALSE;
1586 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1588 xmlstr_t attr_name, attr_value;
1589 BOOL end = FALSE, error;
1590 struct entity* entity;
1592 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1593 return FALSE;
1595 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1597 if (xmlstr_cmp(&attr_name, tlbidW))
1599 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1601 else if (xmlstr_cmp(&attr_name, versionW))
1603 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1605 else if (xmlstr_cmp(&attr_name, helpdirW))
1607 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1609 else if (xmlstr_cmp(&attr_name, flagsW))
1611 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1613 else
1615 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1619 if (error) return FALSE;
1621 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1623 if (end) return TRUE;
1625 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1628 static inline int aligned_string_len(int len)
1630 return (len + 3) & ~3;
1633 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1635 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1636 struct assembly_version *ver = &assembly->id.version;
1637 WCHAR buff[25];
1639 if (!ret) ret = buff;
1640 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1643 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1645 xmlstr_t elem, content, attr_name, attr_value;
1646 BOOL end = FALSE, ret = TRUE, error;
1647 struct entity* entity;
1649 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1650 return FALSE;
1652 entity->u.class.versioned = TRUE;
1653 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1655 if (xmlstr_cmp(&attr_name, versionedW))
1657 if (xmlstr_cmpi(&attr_value, noW))
1658 entity->u.class.versioned = FALSE;
1659 else if (!xmlstr_cmpi(&attr_value, yesW))
1660 return FALSE;
1662 else
1664 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1668 if (error || end) return end;
1670 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1672 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1674 acl->actctx->sections |= WINDOWCLASS_SECTION;
1676 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1678 if (xmlstr_cmp_end(&elem, windowClassW))
1680 ret = parse_end_element(xmlbuf);
1681 break;
1683 else
1685 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1686 ret = parse_unknown_elem(xmlbuf, &elem);
1690 return ret;
1693 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1695 xmlstr_t attr_name, attr_value;
1696 BOOL end = FALSE, error;
1698 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1700 if (xmlstr_cmp(&attr_name, oldVersionW))
1702 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1704 else if (xmlstr_cmp(&attr_name, newVersionW))
1706 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1708 else
1710 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1714 if (error || end) return end;
1715 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1718 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1720 xmlstr_t elem, content;
1721 BOOL end = FALSE, ret = TRUE;
1723 if (!parse_expect_no_attr(xmlbuf, &end) || end ||
1724 !parse_text_content(xmlbuf, &content))
1725 return FALSE;
1727 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1729 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1731 if (xmlstr_cmp_end(&elem, descriptionW))
1733 ret = parse_end_element(xmlbuf);
1734 break;
1736 else
1738 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1739 ret = parse_unknown_elem(xmlbuf, &elem);
1743 return ret;
1746 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1747 struct assembly* assembly,
1748 struct actctx_loader* acl)
1750 xmlstr_t attr_name, attr_value;
1751 BOOL end = FALSE, error;
1752 struct entity* entity;
1754 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1755 if (!entity) return FALSE;
1757 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1759 if (xmlstr_cmp(&attr_name, iidW))
1761 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1763 else if (xmlstr_cmp(&attr_name, nameW))
1765 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1767 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1769 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1770 entity->u.ifaceps.mask |= BaseIface;
1772 else if (xmlstr_cmp(&attr_name, nummethodsW))
1774 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1775 entity->u.ifaceps.mask |= NumMethods;
1777 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1779 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1781 else if (xmlstr_cmp(&attr_name, tlbidW))
1783 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1785 else
1787 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1791 if (error) return FALSE;
1792 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1793 if (end) return TRUE;
1795 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1798 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
1800 xmlstr_t attr_name, attr_value;
1801 BOOL end = FALSE, error;
1802 struct entity* entity;
1804 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1805 if (!entity) return FALSE;
1807 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1809 if (xmlstr_cmp(&attr_name, nameW))
1811 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1813 else if (xmlstr_cmp(&attr_name, clsidW))
1815 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1817 else if (xmlstr_cmp(&attr_name, progidW))
1819 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1821 else if (xmlstr_cmp(&attr_name, tlbidW))
1823 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1825 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1827 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1829 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1831 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1833 else
1835 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1839 if (error || end) return end;
1840 return parse_expect_end_elem(xmlbuf, clrClassW, asmv1W);
1843 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1845 xmlstr_t attr_name, attr_value;
1846 BOOL end = FALSE, error;
1847 struct entity* entity;
1849 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1850 if (!entity) return FALSE;
1852 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1854 if (xmlstr_cmp(&attr_name, nameW))
1856 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
1858 else if (xmlstr_cmp(&attr_name, clsidW))
1860 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
1862 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1864 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
1866 else
1868 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1872 if (error) return FALSE;
1873 acl->actctx->sections |= CLRSURROGATES_SECTION;
1874 if (end) return TRUE;
1876 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
1879 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
1881 struct assembly_identity ai;
1882 xmlstr_t elem;
1883 BOOL end = FALSE, ret = TRUE;
1885 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
1887 memset(&ai, 0, sizeof(ai));
1888 ai.optional = optional;
1890 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
1891 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
1892 return FALSE;
1894 TRACE( "adding name=%s version=%s arch=%s\n",
1895 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
1897 /* store the newly found identity for later loading */
1898 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
1900 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1902 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
1904 ret = parse_end_element(xmlbuf);
1905 break;
1907 else if (xmlstr_cmp(&elem, bindingRedirectW))
1909 ret = parse_binding_redirect_elem(xmlbuf);
1911 else
1913 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1914 ret = parse_unknown_elem(xmlbuf, &elem);
1918 return ret;
1921 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
1923 xmlstr_t attr_name, attr_value, elem;
1924 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
1926 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1928 if (xmlstr_cmp(&attr_name, optionalW))
1930 optional = xmlstr_cmpi( &attr_value, yesW );
1931 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
1933 else
1935 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1939 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1941 if (xmlstr_cmp_end(&elem, dependencyW))
1943 ret = parse_end_element(xmlbuf);
1944 break;
1946 else if (xmlstr_cmp(&elem, dependentAssemblyW))
1948 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
1950 else
1952 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
1953 ret = parse_unknown_elem(xmlbuf, &elem);
1957 return ret;
1960 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
1962 BOOL end = FALSE;
1964 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1965 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
1968 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
1970 BOOL end = FALSE;
1972 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
1973 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
1976 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
1978 xmlstr_t attr_name, attr_value, elem;
1979 BOOL end = FALSE, error, ret = TRUE;
1980 struct dll_redirect* dll;
1982 if (!(dll = add_dll_redirect(assembly))) return FALSE;
1984 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1986 if (xmlstr_cmp(&attr_name, nameW))
1988 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
1989 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
1991 else if (xmlstr_cmp(&attr_name, hashW))
1993 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
1995 else if (xmlstr_cmp(&attr_name, hashalgW))
1997 static const WCHAR sha1W[] = {'S','H','A','1',0};
1998 if (!xmlstr_cmpi(&attr_value, sha1W))
1999 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2001 else
2003 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2007 if (error || !dll->name) return FALSE;
2009 acl->actctx->sections |= DLLREDIRECT_SECTION;
2011 if (end) return TRUE;
2013 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2015 if (xmlstr_cmp_end(&elem, fileW))
2017 ret = parse_end_element(xmlbuf);
2018 break;
2020 else if (xmlstr_cmp(&elem, comClassW))
2022 ret = parse_com_class_elem(xmlbuf, dll, acl);
2024 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2026 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2028 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2030 WARN("asmv2:hash (undocumented) not supported\n");
2031 ret = parse_unknown_elem(xmlbuf, &elem);
2033 else if (xmlstr_cmp(&elem, typelibW))
2035 ret = parse_typelib_elem(xmlbuf, dll, acl);
2037 else if (xmlstr_cmp(&elem, windowClassW))
2039 ret = parse_window_class_elem(xmlbuf, dll, acl);
2041 else
2043 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2044 ret = parse_unknown_elem( xmlbuf, &elem );
2048 return ret;
2051 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2052 struct assembly* assembly,
2053 struct assembly_identity* expected_ai)
2055 xmlstr_t attr_name, attr_value, elem;
2056 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2058 TRACE("(%p)\n", xmlbuf);
2060 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2062 if (xmlstr_cmp(&attr_name, manifestVersionW))
2064 static const WCHAR v10W[] = {'1','.','0',0};
2065 if (!xmlstr_cmp(&attr_value, v10W))
2067 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2068 return FALSE;
2070 version = TRUE;
2072 else if (xmlstr_cmp(&attr_name, xmlnsW))
2074 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
2076 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2077 return FALSE;
2079 xmlns = TRUE;
2081 else
2083 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2087 if (error || end || !xmlns || !version) return FALSE;
2088 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2090 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2092 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2093 return FALSE;
2094 assembly->no_inherit = TRUE;
2097 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2099 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2100 return FALSE;
2102 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2103 assembly->no_inherit)
2104 return FALSE;
2106 while (ret)
2108 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2110 ret = parse_end_element(xmlbuf);
2111 break;
2113 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2115 ret = parse_description_elem(xmlbuf);
2117 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2119 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2121 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2123 ret = parse_dependency_elem(xmlbuf, acl);
2125 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2127 ret = parse_file_elem(xmlbuf, assembly, acl);
2129 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2131 ret = parse_clr_class_elem(xmlbuf, assembly);
2133 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2135 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2137 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2139 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2141 if (expected_ai)
2143 /* FIXME: more tests */
2144 if (assembly->type == ASSEMBLY_MANIFEST &&
2145 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2147 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2148 expected_ai->version.major, expected_ai->version.minor,
2149 expected_ai->version.build, expected_ai->version.revision,
2150 assembly->id.version.major, assembly->id.version.minor,
2151 assembly->id.version.build, assembly->id.version.revision);
2152 ret = FALSE;
2154 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2155 (assembly->id.version.major != expected_ai->version.major ||
2156 assembly->id.version.minor != expected_ai->version.minor ||
2157 assembly->id.version.build < expected_ai->version.build ||
2158 (assembly->id.version.build == expected_ai->version.build &&
2159 assembly->id.version.revision < expected_ai->version.revision)))
2161 FIXME("wrong version for shared assembly manifest\n");
2162 ret = FALSE;
2166 else
2168 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2169 ret = parse_unknown_elem(xmlbuf, &elem);
2171 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2174 return ret;
2177 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2178 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2180 xmlstr_t elem;
2182 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2184 if (xmlstr_cmp(&elem, xmlW) &&
2185 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2186 return STATUS_SXS_CANT_GEN_ACTCTX;
2188 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2190 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2191 return STATUS_SXS_CANT_GEN_ACTCTX;
2194 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2196 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2197 return STATUS_SXS_CANT_GEN_ACTCTX;
2200 if (next_xml_elem(xmlbuf, &elem))
2202 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2203 return STATUS_SXS_CANT_GEN_ACTCTX;
2206 if (xmlbuf->ptr != xmlbuf->end)
2208 FIXME("parse error\n");
2209 return STATUS_SXS_CANT_GEN_ACTCTX;
2211 return STATUS_SUCCESS;
2214 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2215 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2216 const void *buffer, SIZE_T size )
2218 xmlbuf_t xmlbuf;
2219 NTSTATUS status;
2220 struct assembly *assembly;
2221 int unicode_tests;
2223 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2225 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2226 return STATUS_SXS_CANT_GEN_ACTCTX;
2228 if (directory && !(assembly->directory = strdupW(directory)))
2229 return STATUS_NO_MEMORY;
2231 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2232 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2233 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2235 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2236 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2238 xmlbuf.ptr = buffer;
2239 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2240 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2242 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2244 const WCHAR *buf = buffer;
2245 WCHAR *new_buff;
2246 unsigned int i;
2248 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2249 return STATUS_NO_MEMORY;
2250 for (i = 0; i < size / sizeof(WCHAR); i++)
2251 new_buff[i] = RtlUshortByteSwap( buf[i] );
2252 xmlbuf.ptr = new_buff;
2253 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2254 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2255 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2257 else
2259 /* let's assume utf-8 for now */
2260 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2261 WCHAR *new_buff;
2263 if (len == -1)
2265 FIXME( "utf-8 conversion failed\n" );
2266 return STATUS_SXS_CANT_GEN_ACTCTX;
2268 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2269 return STATUS_NO_MEMORY;
2270 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2271 xmlbuf.ptr = new_buff;
2272 xmlbuf.end = xmlbuf.ptr + len;
2273 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2274 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2276 return status;
2279 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2281 OBJECT_ATTRIBUTES attr;
2282 IO_STATUS_BLOCK io;
2284 attr.Length = sizeof(attr);
2285 attr.RootDirectory = 0;
2286 attr.Attributes = OBJ_CASE_INSENSITIVE;
2287 attr.ObjectName = name;
2288 attr.SecurityDescriptor = NULL;
2289 attr.SecurityQualityOfService = NULL;
2290 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2293 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2295 NTSTATUS status;
2296 ULONG magic;
2297 LDR_MODULE *pldr;
2299 LdrLockLoaderLock(0, NULL, &magic);
2300 status = LdrFindEntryForAddress( module, &pldr );
2301 if (status == STATUS_SUCCESS)
2303 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2304 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2306 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2307 str->Length = pldr->FullDllName.Length;
2308 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2310 else status = STATUS_NO_MEMORY;
2312 LdrUnlockLoaderLock(0, magic);
2313 return status;
2316 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2317 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2318 HANDLE hModule, LPCWSTR resname, ULONG lang )
2320 NTSTATUS status;
2321 UNICODE_STRING nameW;
2322 LDR_RESOURCE_INFO info;
2323 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2324 void *ptr;
2326 if (TRACE_ON(actctx))
2328 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2330 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2331 hModule, debugstr_w(nameW.Buffer) );
2332 RtlFreeUnicodeString( &nameW );
2334 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2335 hModule, debugstr_w(filename) );
2338 if (!resname) return STATUS_INVALID_PARAMETER;
2340 info.Type = RT_MANIFEST;
2341 info.Language = lang;
2342 if (!((ULONG_PTR)resname >> 16))
2344 info.Name = (ULONG_PTR)resname;
2345 status = LdrFindResource_U(hModule, &info, 3, &entry);
2347 else if (resname[0] == '#')
2349 ULONG value;
2350 RtlInitUnicodeString(&nameW, resname + 1);
2351 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2352 return STATUS_INVALID_PARAMETER;
2353 info.Name = value;
2354 status = LdrFindResource_U(hModule, &info, 3, &entry);
2356 else
2358 RtlCreateUnicodeString(&nameW, resname);
2359 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2360 info.Name = (ULONG_PTR)nameW.Buffer;
2361 status = LdrFindResource_U(hModule, &info, 3, &entry);
2362 RtlFreeUnicodeString(&nameW);
2364 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2366 if (status == STATUS_SUCCESS)
2367 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2369 return status;
2372 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2373 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2374 HANDLE file, LPCWSTR resname, ULONG lang )
2376 HANDLE mapping;
2377 OBJECT_ATTRIBUTES attr;
2378 LARGE_INTEGER size;
2379 LARGE_INTEGER offset;
2380 NTSTATUS status;
2381 SIZE_T count;
2382 void *base;
2384 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2386 attr.Length = sizeof(attr);
2387 attr.RootDirectory = 0;
2388 attr.ObjectName = NULL;
2389 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2390 attr.SecurityDescriptor = NULL;
2391 attr.SecurityQualityOfService = NULL;
2393 size.QuadPart = 0;
2394 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2395 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2396 if (status != STATUS_SUCCESS) return status;
2398 offset.QuadPart = 0;
2399 count = 0;
2400 base = NULL;
2401 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2402 &count, ViewShare, 0, PAGE_READONLY );
2403 NtClose( mapping );
2404 if (status != STATUS_SUCCESS) return status;
2406 if (RtlImageNtHeader(base)) /* we got a PE file */
2408 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2409 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2411 else status = STATUS_INVALID_IMAGE_FORMAT;
2413 NtUnmapViewOfSection( GetCurrentProcess(), base );
2414 return status;
2417 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2418 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2420 FILE_END_OF_FILE_INFORMATION info;
2421 IO_STATUS_BLOCK io;
2422 HANDLE mapping;
2423 OBJECT_ATTRIBUTES attr;
2424 LARGE_INTEGER size;
2425 LARGE_INTEGER offset;
2426 NTSTATUS status;
2427 SIZE_T count;
2428 void *base;
2430 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2432 attr.Length = sizeof(attr);
2433 attr.RootDirectory = 0;
2434 attr.ObjectName = NULL;
2435 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2436 attr.SecurityDescriptor = NULL;
2437 attr.SecurityQualityOfService = NULL;
2439 size.QuadPart = 0;
2440 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2441 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2442 if (status != STATUS_SUCCESS) return status;
2444 offset.QuadPart = 0;
2445 count = 0;
2446 base = NULL;
2447 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2448 &count, ViewShare, 0, PAGE_READONLY );
2449 NtClose( mapping );
2450 if (status != STATUS_SUCCESS) return status;
2452 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2453 if (status == STATUS_SUCCESS)
2454 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2456 NtUnmapViewOfSection( GetCurrentProcess(), base );
2457 return status;
2460 /* try to load the .manifest file associated to the file */
2461 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2462 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2464 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2465 WCHAR *buffer;
2466 NTSTATUS status;
2467 UNICODE_STRING nameW;
2468 HANDLE file;
2469 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2471 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2473 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2475 if (module) /* use the module filename */
2477 UNICODE_STRING name;
2479 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2481 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2482 strcatW( name.Buffer, dotManifestW );
2483 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2484 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2485 RtlFreeUnicodeString( &name );
2487 if (status) return status;
2489 else
2491 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2492 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2493 return STATUS_NO_MEMORY;
2494 strcpyW( buffer, filename );
2495 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2496 strcatW( buffer, dotManifestW );
2497 RtlInitUnicodeString( &nameW, buffer );
2500 if (!open_nt_file( &file, &nameW ))
2502 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2503 NtClose( file );
2505 else status = STATUS_RESOURCE_DATA_NOT_FOUND;
2506 RtlFreeUnicodeString( &nameW );
2507 return status;
2510 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2512 static const WCHAR lookup_fmtW[] =
2513 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2514 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2515 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2517 WCHAR *lookup, *ret = NULL;
2518 UNICODE_STRING lookup_us;
2519 IO_STATUS_BLOCK io;
2520 const WCHAR *lang = ai->language;
2521 unsigned int data_pos = 0, data_len;
2522 char buffer[8192];
2524 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2525 (strlenW(ai->arch) + strlenW(ai->name)
2526 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2527 + sizeof(lookup_fmtW) )))
2528 return NULL;
2530 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2531 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2532 ai->version.major, ai->version.minor, lang );
2533 RtlInitUnicodeString( &lookup_us, lookup );
2535 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2536 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2537 if (io.u.Status == STATUS_SUCCESS)
2539 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2540 FILE_BOTH_DIR_INFORMATION *dir_info;
2541 WCHAR *tmp;
2542 ULONG build, revision;
2544 data_len = io.Information;
2546 for (;;)
2548 if (data_pos >= data_len)
2550 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2551 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2552 if (io.u.Status != STATUS_SUCCESS) break;
2553 data_len = io.Information;
2554 data_pos = 0;
2556 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2558 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2559 else data_pos = data_len;
2561 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2562 build = atoiW(tmp);
2563 if (build < min_build) continue;
2564 tmp = strchrW(tmp, '.') + 1;
2565 revision = atoiW(tmp);
2566 if (build == min_build && revision < min_revision) continue;
2567 tmp = strchrW(tmp, '_') + 1;
2568 tmp = strchrW(tmp, '_') + 1;
2569 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2570 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2572 /* prefer a non-Wine manifest if we already have one */
2573 /* we'll still load the builtin dll if specified through DllOverrides */
2574 if (ret) continue;
2576 else
2578 min_build = build;
2579 min_revision = revision;
2581 ai->version.build = build;
2582 ai->version.revision = revision;
2583 RtlFreeHeap( GetProcessHeap(), 0, ret );
2584 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2586 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2587 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2591 else WARN("no matching file for %s\n", debugstr_w(lookup));
2592 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2593 return ret;
2596 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2598 struct assembly_identity sxs_ai;
2599 UNICODE_STRING path_us;
2600 OBJECT_ATTRIBUTES attr;
2601 IO_STATUS_BLOCK io;
2602 WCHAR *path, *file = NULL;
2603 HANDLE handle;
2605 static const WCHAR manifest_dirW[] =
2606 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2608 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2610 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2611 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2612 return STATUS_NO_MEMORY;
2614 strcpyW( path, user_shared_data->NtSystemRoot );
2615 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2617 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2619 RtlFreeHeap( GetProcessHeap(), 0, path );
2620 return STATUS_NO_SUCH_FILE;
2622 RtlFreeHeap( GetProcessHeap(), 0, path );
2624 attr.Length = sizeof(attr);
2625 attr.RootDirectory = 0;
2626 attr.Attributes = OBJ_CASE_INSENSITIVE;
2627 attr.ObjectName = &path_us;
2628 attr.SecurityDescriptor = NULL;
2629 attr.SecurityQualityOfService = NULL;
2631 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2632 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2634 sxs_ai = *ai;
2635 file = lookup_manifest_file( handle, &sxs_ai );
2636 NtClose( handle );
2638 if (!file)
2640 RtlFreeUnicodeString( &path_us );
2641 return STATUS_NO_SUCH_FILE;
2644 /* append file name to directory path */
2645 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2646 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2648 RtlFreeHeap( GetProcessHeap(), 0, file );
2649 RtlFreeUnicodeString( &path_us );
2650 return STATUS_NO_MEMORY;
2653 path[path_us.Length/sizeof(WCHAR)] = '\\';
2654 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2655 RtlInitUnicodeString( &path_us, path );
2656 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2658 if (!open_nt_file( &handle, &path_us ))
2660 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2661 NtClose( handle );
2663 else io.u.Status = STATUS_NO_SUCH_FILE;
2665 RtlFreeHeap( GetProcessHeap(), 0, file );
2666 RtlFreeUnicodeString( &path_us );
2667 return io.u.Status;
2670 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2671 struct assembly_identity* ai)
2673 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2674 unsigned int i;
2675 WCHAR *buffer, *p, *directory;
2676 NTSTATUS status;
2677 UNICODE_STRING nameW;
2678 HANDLE file;
2680 TRACE( "looking for name=%s version=%s arch=%s\n",
2681 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2683 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2685 /* FIXME: add support for language specific lookup */
2687 nameW.Buffer = NULL;
2688 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2689 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2690 return STATUS_NO_MEMORY;
2692 if (!(directory = build_assembly_dir( ai )))
2694 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2695 return STATUS_NO_MEMORY;
2698 /* lookup in appdir\name.dll
2699 * appdir\name.manifest
2700 * appdir\name\name.dll
2701 * appdir\name\name.manifest
2703 strcpyW( buffer, acl->actctx->appdir.info );
2704 p = buffer + strlenW(buffer);
2705 for (i = 0; i < 2; i++)
2707 *p++ = '\\';
2708 strcpyW( p, ai->name );
2709 p += strlenW(p);
2711 strcpyW( p, dotDllW );
2712 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2714 status = open_nt_file( &file, &nameW );
2715 if (!status)
2717 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2718 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2719 NtClose( file );
2720 break;
2722 RtlFreeUnicodeString( &nameW );
2725 strcpyW( p, dotManifestW );
2726 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2728 status = open_nt_file( &file, &nameW );
2729 if (!status)
2731 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2732 NtClose( file );
2733 break;
2735 RtlFreeUnicodeString( &nameW );
2737 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2739 RtlFreeUnicodeString( &nameW );
2740 RtlFreeHeap( GetProcessHeap(), 0, directory );
2741 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2742 return status;
2745 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2747 NTSTATUS status = STATUS_SUCCESS;
2748 unsigned int i;
2750 for (i = 0; i < acl->num_dependencies; i++)
2752 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2754 if (!acl->dependencies[i].optional)
2756 FIXME( "Could not find dependent assembly %s (%s)\n",
2757 debugstr_w(acl->dependencies[i].name),
2758 debugstr_version(&acl->dependencies[i].version) );
2759 status = STATUS_SXS_CANT_GEN_ACTCTX;
2760 break;
2764 /* FIXME should now iterate through all refs */
2765 return status;
2768 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2769 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2771 NTSTATUS status = STATUS_SUCCESS;
2773 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2775 if (*handle) return STATUS_INVALID_PARAMETER;
2777 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2778 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2780 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2782 ULONG magic;
2783 LDR_MODULE *pldr;
2785 if (!*handle) return STATUS_INVALID_PARAMETER;
2787 LdrLockLoaderLock( 0, NULL, &magic );
2788 if (!LdrFindEntryForAddress( *handle, &pldr ))
2790 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2791 status = STATUS_DLL_NOT_FOUND;
2792 else
2793 *handle = pldr->ActivationContext;
2795 else status = STATUS_DLL_NOT_FOUND;
2796 LdrUnlockLoaderLock( 0, magic );
2798 else if (!*handle && (class != ActivationContextBasicInformation))
2799 *handle = process_actctx;
2801 return status;
2804 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2806 unsigned int i, j, total_len = 0, dll_count = 0;
2807 struct strsection_header *header;
2808 struct dllredirect_data *data;
2809 struct string_index *index;
2810 ULONG name_offset;
2812 /* compute section length */
2813 for (i = 0; i < actctx->num_assemblies; i++)
2815 struct assembly *assembly = &actctx->assemblies[i];
2816 for (j = 0; j < assembly->num_dlls; j++)
2818 struct dll_redirect *dll = &assembly->dlls[j];
2820 /* each entry needs index, data and string data */
2821 total_len += sizeof(*index);
2822 total_len += sizeof(*data);
2823 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
2826 dll_count += assembly->num_dlls;
2829 total_len += sizeof(*header);
2831 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
2832 if (!header) return STATUS_NO_MEMORY;
2834 memset(header, 0, sizeof(*header));
2835 header->magic = STRSECTION_MAGIC;
2836 header->size = sizeof(*header);
2837 header->count = dll_count;
2838 header->index_offset = sizeof(*header);
2839 index = (struct string_index*)((BYTE*)header + header->index_offset);
2840 name_offset = header->index_offset + header->count*sizeof(*index);
2842 for (i = 0; i < actctx->num_assemblies; i++)
2844 struct assembly *assembly = &actctx->assemblies[i];
2845 for (j = 0; j < assembly->num_dlls; j++)
2847 struct dll_redirect *dll = &assembly->dlls[j];
2848 UNICODE_STRING str;
2849 WCHAR *ptrW;
2851 /* setup new index entry */
2852 str.Buffer = dll->name;
2853 str.Length = strlenW(dll->name)*sizeof(WCHAR);
2854 str.MaximumLength = str.Length + sizeof(WCHAR);
2855 /* hash original class name */
2856 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
2858 index->name_offset = name_offset;
2859 index->name_len = str.Length;
2860 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
2861 index->data_len = sizeof(*data);
2862 index->rosterindex = i + 1;
2864 /* setup data */
2865 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
2866 data->size = sizeof(*data);
2867 data->unk = 2; /* FIXME: seems to be constant */
2868 memset(data->res, 0, sizeof(data->res));
2870 /* dll name */
2871 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
2872 memcpy(ptrW, dll->name, index->name_len);
2873 ptrW[index->name_len/sizeof(WCHAR)] = 0;
2875 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
2877 index++;
2881 *section = header;
2883 return STATUS_SUCCESS;
2886 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
2888 struct string_index *iter, *index = NULL;
2889 ULONG hash = 0, i;
2891 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
2892 iter = (struct string_index*)((BYTE*)section + section->index_offset);
2894 for (i = 0; i < section->count; i++)
2896 if (iter->hash == hash)
2898 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
2900 if (!strcmpiW(nameW, name->Buffer))
2902 index = iter;
2903 break;
2905 else
2906 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
2908 iter++;
2911 return index;
2914 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
2916 struct guid_index *iter, *index = NULL;
2917 ULONG i;
2919 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
2921 for (i = 0; i < section->count; i++)
2923 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
2925 index = iter;
2926 break;
2928 iter++;
2931 return index;
2934 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
2936 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
2939 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
2940 PACTCTX_SECTION_KEYED_DATA data)
2942 struct dllredirect_data *dll;
2943 struct string_index *index;
2945 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
2947 if (!actctx->dllredirect_section)
2949 struct strsection_header *section;
2951 NTSTATUS status = build_dllredirect_section(actctx, &section);
2952 if (status) return status;
2954 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
2955 RtlFreeHeap(GetProcessHeap(), 0, section);
2958 index = find_string_index(actctx->dllredirect_section, name);
2959 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
2961 dll = get_dllredirect_data(actctx, index);
2963 data->ulDataFormatVersion = 1;
2964 data->lpData = dll;
2965 data->ulLength = dll->size;
2966 data->lpSectionGlobalData = NULL;
2967 data->ulSectionGlobalDataLength = 0;
2968 data->lpSectionBase = actctx->dllredirect_section;
2969 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
2970 data->hActCtx = NULL;
2972 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
2973 data->ulAssemblyRosterIndex = index->rosterindex;
2975 return STATUS_SUCCESS;
2978 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
2980 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
2983 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
2985 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
2988 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2990 unsigned int i, j, k, total_len = 0, class_count = 0;
2991 struct wndclass_redirect_data *data;
2992 struct strsection_header *header;
2993 struct string_index *index;
2994 ULONG name_offset;
2996 /* compute section length */
2997 for (i = 0; i < actctx->num_assemblies; i++)
2999 struct assembly *assembly = &actctx->assemblies[i];
3000 for (j = 0; j < assembly->num_dlls; j++)
3002 struct dll_redirect *dll = &assembly->dlls[j];
3003 for (k = 0; k < dll->entities.num; k++)
3005 struct entity *entity = &dll->entities.base[k];
3006 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3008 int class_len = strlenW(entity->u.class.name) + 1;
3009 int len;
3011 /* each class entry needs index, data and string data */
3012 total_len += sizeof(*index);
3013 total_len += sizeof(*data);
3014 /* original name is stored separately */
3015 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3016 /* versioned name and module name are stored one after another */
3017 if (entity->u.class.versioned)
3018 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3019 else
3020 len = class_len;
3021 len += strlenW(dll->name) + 1;
3022 total_len += aligned_string_len(len*sizeof(WCHAR));
3024 class_count++;
3030 total_len += sizeof(*header);
3032 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3033 if (!header) return STATUS_NO_MEMORY;
3035 memset(header, 0, sizeof(*header));
3036 header->magic = STRSECTION_MAGIC;
3037 header->size = sizeof(*header);
3038 header->count = class_count;
3039 header->index_offset = sizeof(*header);
3040 index = (struct string_index*)((BYTE*)header + header->index_offset);
3041 name_offset = header->index_offset + header->count*sizeof(*index);
3043 for (i = 0; i < actctx->num_assemblies; i++)
3045 struct assembly *assembly = &actctx->assemblies[i];
3046 for (j = 0; j < assembly->num_dlls; j++)
3048 struct dll_redirect *dll = &assembly->dlls[j];
3049 for (k = 0; k < dll->entities.num; k++)
3051 struct entity *entity = &dll->entities.base[k];
3052 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3054 static const WCHAR exclW[] = {'!',0};
3055 ULONG versioned_len, module_len;
3056 UNICODE_STRING str;
3057 WCHAR *ptrW;
3059 /* setup new index entry */
3060 str.Buffer = entity->u.class.name;
3061 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3062 str.MaximumLength = str.Length + sizeof(WCHAR);
3063 /* hash original class name */
3064 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3066 /* include '!' separator too */
3067 if (entity->u.class.versioned)
3068 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3069 else
3070 versioned_len = str.Length;
3071 module_len = strlenW(dll->name)*sizeof(WCHAR);
3073 index->name_offset = name_offset;
3074 index->name_len = str.Length;
3075 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3076 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3077 index->rosterindex = i + 1;
3079 /* setup data */
3080 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3081 data->size = sizeof(*data);
3082 data->res = 0;
3083 data->name_len = versioned_len;
3084 data->name_offset = sizeof(*data);
3085 data->module_len = module_len;
3086 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3088 /* original class name */
3089 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3090 memcpy(ptrW, entity->u.class.name, index->name_len);
3091 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3093 /* module name */
3094 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3095 memcpy(ptrW, dll->name, data->module_len);
3096 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3098 /* versioned name */
3099 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3100 if (entity->u.class.versioned)
3102 get_assembly_version(assembly, ptrW);
3103 strcatW(ptrW, exclW);
3104 strcatW(ptrW, entity->u.class.name);
3106 else
3108 memcpy(ptrW, entity->u.class.name, index->name_len);
3109 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3112 name_offset += sizeof(*data);
3113 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3115 index++;
3121 *section = header;
3123 return STATUS_SUCCESS;
3126 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3127 PACTCTX_SECTION_KEYED_DATA data)
3129 struct string_index *iter, *index = NULL;
3130 struct wndclass_redirect_data *class;
3131 ULONG hash;
3132 int i;
3134 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3136 if (!actctx->wndclass_section)
3138 struct strsection_header *section;
3140 NTSTATUS status = build_wndclass_section(actctx, &section);
3141 if (status) return status;
3143 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3144 RtlFreeHeap(GetProcessHeap(), 0, section);
3147 hash = 0;
3148 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3149 iter = get_wndclass_first_index(actctx);
3151 for (i = 0; i < actctx->wndclass_section->count; i++)
3153 if (iter->hash == hash)
3155 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3157 if (!strcmpW(nameW, name->Buffer))
3159 index = iter;
3160 break;
3162 else
3163 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3165 iter++;
3168 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3170 class = get_wndclass_data(actctx, index);
3172 data->ulDataFormatVersion = 1;
3173 data->lpData = class;
3174 /* full length includes string length with nulls */
3175 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3176 data->lpSectionGlobalData = NULL;
3177 data->ulSectionGlobalDataLength = 0;
3178 data->lpSectionBase = actctx->wndclass_section;
3179 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3180 data->hActCtx = NULL;
3182 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3183 data->ulAssemblyRosterIndex = index->rosterindex;
3185 return STATUS_SUCCESS;
3188 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3190 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3191 struct guidsection_header *header;
3192 ULONG module_offset, data_offset;
3193 struct tlibredirect_data *data;
3194 struct guid_index *index;
3196 /* compute section length */
3197 for (i = 0; i < actctx->num_assemblies; i++)
3199 struct assembly *assembly = &actctx->assemblies[i];
3200 for (j = 0; j < assembly->num_dlls; j++)
3202 struct dll_redirect *dll = &assembly->dlls[j];
3203 for (k = 0; k < dll->entities.num; k++)
3205 struct entity *entity = &dll->entities.base[k];
3206 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3208 /* each entry needs index, data and string data for module name and help string */
3209 total_len += sizeof(*index);
3210 total_len += sizeof(*data);
3211 /* help string is stored separately */
3212 if (*entity->u.typelib.helpdir)
3213 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3215 /* module names are packed one after another */
3216 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3218 tlib_count++;
3224 total_len += aligned_string_len(names_len);
3225 total_len += sizeof(*header);
3227 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3228 if (!header) return STATUS_NO_MEMORY;
3230 memset(header, 0, sizeof(*header));
3231 header->magic = GUIDSECTION_MAGIC;
3232 header->size = sizeof(*header);
3233 header->count = tlib_count;
3234 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3235 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3236 module_offset = sizeof(*header);
3237 data_offset = header->index_offset + tlib_count*sizeof(*index);
3239 for (i = 0; i < actctx->num_assemblies; i++)
3241 struct assembly *assembly = &actctx->assemblies[i];
3242 for (j = 0; j < assembly->num_dlls; j++)
3244 struct dll_redirect *dll = &assembly->dlls[j];
3245 for (k = 0; k < dll->entities.num; k++)
3247 struct entity *entity = &dll->entities.base[k];
3248 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3250 ULONG module_len, help_len;
3251 UNICODE_STRING str;
3252 WCHAR *ptrW;
3254 if (*entity->u.typelib.helpdir)
3255 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3256 else
3257 help_len = 0;
3259 module_len = strlenW(dll->name)*sizeof(WCHAR);
3261 /* setup new index entry */
3262 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3263 RtlGUIDFromString(&str, &index->guid);
3264 index->data_offset = data_offset;
3265 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3266 index->rosterindex = i + 1;
3268 /* setup data */
3269 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3270 data->size = sizeof(*data);
3271 data->res = 0;
3272 data->name_len = module_len;
3273 data->name_offset = module_offset;
3274 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3275 data->langid = 0;
3276 data->flags = entity->u.typelib.flags;
3277 data->help_len = help_len;
3278 data->help_offset = sizeof(*data);
3279 data->major_version = entity->u.typelib.major;
3280 data->minor_version = entity->u.typelib.minor;
3282 /* module name */
3283 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3284 memcpy(ptrW, dll->name, data->name_len);
3285 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3287 /* help string */
3288 if (data->help_len)
3290 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3291 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3292 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3295 data_offset += sizeof(*data);
3296 if (help_len)
3297 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3299 module_offset += module_len + sizeof(WCHAR);
3301 index++;
3307 *section = header;
3309 return STATUS_SUCCESS;
3312 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3314 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3317 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3319 struct guid_index *index = NULL;
3320 struct tlibredirect_data *tlib;
3322 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3324 if (!actctx->tlib_section)
3326 struct guidsection_header *section;
3328 NTSTATUS status = build_tlib_section(actctx, &section);
3329 if (status) return status;
3331 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3332 RtlFreeHeap(GetProcessHeap(), 0, section);
3335 index = find_guid_index(actctx->tlib_section, guid);
3336 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3338 tlib = get_tlib_data(actctx, index);
3340 data->ulDataFormatVersion = 1;
3341 data->lpData = tlib;
3342 /* full length includes string length with nulls */
3343 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3344 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3345 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3346 data->lpSectionBase = actctx->tlib_section;
3347 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3348 data->hActCtx = NULL;
3350 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3351 data->ulAssemblyRosterIndex = index->rosterindex;
3353 return STATUS_SUCCESS;
3356 static void generate_uuid(ULONG *seed, GUID *guid)
3358 ULONG *ptr = (ULONG*)guid;
3359 int i;
3361 /* GUID is 16 bytes long */
3362 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3363 *ptr = RtlUniform(seed);
3365 guid->Data3 &= 0x0fff;
3366 guid->Data3 |= (4 << 12);
3367 guid->Data4[0] &= 0x3f;
3368 guid->Data4[0] |= 0x80;
3371 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3373 unsigned int i, j, k, total_len = 0, class_count = 0, names_len = 0;
3374 struct guid_index *index, *alias_index;
3375 struct comclassredirect_data *data;
3376 struct guidsection_header *header;
3377 ULONG module_offset, data_offset;
3378 ULONG seed;
3380 /* compute section length */
3381 for (i = 0; i < actctx->num_assemblies; i++)
3383 struct assembly *assembly = &actctx->assemblies[i];
3384 for (j = 0; j < assembly->num_dlls; j++)
3386 struct dll_redirect *dll = &assembly->dlls[j];
3387 for (k = 0; k < dll->entities.num; k++)
3389 struct entity *entity = &dll->entities.base[k];
3390 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3392 /* each entry needs two index entries, extra one goes for alias GUID */
3393 total_len += 2*sizeof(*index);
3394 /* to save some memory we don't allocated two data structures,
3395 instead alias index and normal index point to the same data structure */
3396 total_len += sizeof(*data);
3397 /* help string is stored separately */
3398 if (*entity->u.comclass.progid)
3399 total_len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3401 /* module names are packed one after another */
3402 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3404 class_count++;
3410 total_len += aligned_string_len(names_len);
3411 total_len += sizeof(*header);
3413 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3414 if (!header) return STATUS_NO_MEMORY;
3416 memset(header, 0, sizeof(*header));
3417 header->magic = GUIDSECTION_MAGIC;
3418 header->size = sizeof(*header);
3419 header->count = 2*class_count;
3420 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3421 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3422 module_offset = sizeof(*header);
3423 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3425 seed = NtGetTickCount();
3426 for (i = 0; i < actctx->num_assemblies; i++)
3428 struct assembly *assembly = &actctx->assemblies[i];
3429 for (j = 0; j < assembly->num_dlls; j++)
3431 struct dll_redirect *dll = &assembly->dlls[j];
3432 for (k = 0; k < dll->entities.num; k++)
3434 struct entity *entity = &dll->entities.base[k];
3435 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3437 ULONG module_len, progid_len;
3438 UNICODE_STRING str;
3439 WCHAR *ptrW;
3441 if (*entity->u.comclass.progid)
3442 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3443 else
3444 progid_len = 0;
3446 module_len = strlenW(dll->name)*sizeof(WCHAR);
3448 /* setup new index entry */
3449 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3450 RtlGUIDFromString(&str, &index->guid);
3451 index->data_offset = data_offset;
3452 index->data_len = sizeof(*data) + aligned_string_len(progid_len);
3453 index->rosterindex = i + 1;
3455 /* Setup new index entry for alias guid. Alias index records are placed after
3456 normal records, so normal guids are hit first on search */
3457 alias_index = index + class_count;
3458 generate_uuid(&seed, &alias_index->guid);
3459 alias_index->data_offset = index->data_offset;
3460 alias_index->data_len = index->data_len;
3461 alias_index->rosterindex = index->rosterindex;
3463 /* setup data */
3464 data = (struct comclassredirect_data*)((BYTE*)header + index->data_offset);
3465 data->size = sizeof(*data);
3466 data->res = 0;
3467 data->res1[0] = 0;
3468 data->res1[1] = 0;
3469 data->model = entity->u.comclass.model;
3470 data->clsid = index->guid;
3471 data->alias = alias_index->guid;
3472 data->clsid2 = data->clsid;
3473 if (entity->u.comclass.tlbid)
3475 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3476 RtlGUIDFromString(&str, &data->tlbid);
3478 else
3479 memset(&data->tlbid, 0, sizeof(data->tlbid));
3480 data->name_len = module_len;
3481 data->name_offset = module_offset;
3482 data->progid_len = progid_len;
3483 data->progid_offset = sizeof(*data);
3484 data->clrdata_len = 0;
3485 data->clrdata_offset = 0;
3486 data->miscstatus = entity->u.comclass.miscstatus;
3487 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3488 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3489 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3490 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3492 /* mask describes which misc* data is available */
3493 data->miscmask = 0;
3494 if (data->miscstatus)
3495 data->miscmask |= MiscStatus;
3496 if (data->miscstatuscontent)
3497 data->miscmask |= MiscStatusContent;
3498 if (data->miscstatusthumbnail)
3499 data->miscmask |= MiscStatusThumbnail;
3500 if (data->miscstatusicon)
3501 data->miscmask |= MiscStatusIcon;
3502 if (data->miscstatusdocprint)
3503 data->miscmask |= MiscStatusDocPrint;
3505 /* module name */
3506 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3507 memcpy(ptrW, dll->name, data->name_len);
3508 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3510 /* progid string */
3511 if (data->progid_len)
3513 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3514 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3515 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3518 data_offset += sizeof(*data);
3519 if (progid_len)
3520 data_offset += aligned_string_len(progid_len + sizeof(WCHAR));
3522 module_offset += module_len + sizeof(WCHAR);
3524 index++;
3530 *section = header;
3532 return STATUS_SUCCESS;
3535 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3537 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3540 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3542 struct comclassredirect_data *comclass;
3543 struct guid_index *index = NULL;
3545 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3547 if (!actctx->comserver_section)
3549 struct guidsection_header *section;
3551 NTSTATUS status = build_comserver_section(actctx, &section);
3552 if (status) return status;
3554 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3555 RtlFreeHeap(GetProcessHeap(), 0, section);
3558 index = find_guid_index(actctx->comserver_section, guid);
3559 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3561 comclass = get_comclass_data(actctx, index);
3563 data->ulDataFormatVersion = 1;
3564 data->lpData = comclass;
3565 /* full length includes string length with nulls */
3566 data->ulLength = comclass->size + comclass->progid_len + sizeof(WCHAR);
3567 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3568 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3569 data->lpSectionBase = actctx->comserver_section;
3570 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3571 data->hActCtx = NULL;
3573 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3574 data->ulAssemblyRosterIndex = index->rosterindex;
3576 return STATUS_SUCCESS;
3579 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3581 unsigned int i;
3583 for (i = 0; i < entities->num; i++)
3585 struct entity *entity = &entities->base[i];
3586 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3588 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3589 if (entity->u.ifaceps.name)
3590 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3591 *count += 1;
3596 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3597 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3599 unsigned int i;
3601 for (i = 0; i < entities->num; i++)
3603 struct entity *entity = &entities->base[i];
3604 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3606 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3607 UNICODE_STRING str;
3608 ULONG name_len;
3610 if (entity->u.ifaceps.name)
3611 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3612 else
3613 name_len = 0;
3615 /* setup index */
3616 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3617 RtlGUIDFromString(&str, &(*index)->guid);
3618 (*index)->data_offset = *data_offset;
3619 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3620 (*index)->rosterindex = rosterindex;
3622 /* setup data record */
3623 data->size = sizeof(*data);
3624 data->mask = entity->u.ifaceps.mask;
3626 /* proxyStubClsid32 value is only stored for external PS,
3627 if set it's used as iid, otherwise 'iid' attribute value is used */
3628 if (entity->u.ifaceps.ps32)
3630 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3631 RtlGUIDFromString(&str, &data->iid);
3633 else
3634 data->iid = (*index)->guid;
3636 data->nummethods = entity->u.ifaceps.nummethods;
3638 if (entity->u.ifaceps.tlib)
3640 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3641 RtlGUIDFromString(&str, &data->tlbid);
3643 else
3644 memset(&data->tlbid, 0, sizeof(data->tlbid));
3646 if (entity->u.ifaceps.base)
3648 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3649 RtlGUIDFromString(&str, &data->base);
3651 else
3652 memset(&data->base, 0, sizeof(data->base));
3654 data->name_len = name_len;
3655 data->name_offset = data->name_len ? sizeof(*data) : 0;
3657 /* name string */
3658 if (data->name_len)
3660 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3661 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3662 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3665 /* move to next record */
3666 (*index) += 1;
3667 *data_offset += sizeof(*data);
3668 if (data->name_len)
3669 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3674 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3676 unsigned int i, j, total_len = 0, count = 0;
3677 struct guidsection_header *header;
3678 struct guid_index *index;
3679 ULONG data_offset;
3681 /* compute section length */
3682 for (i = 0; i < actctx->num_assemblies; i++)
3684 struct assembly *assembly = &actctx->assemblies[i];
3686 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3687 for (j = 0; j < assembly->num_dlls; j++)
3689 struct dll_redirect *dll = &assembly->dlls[j];
3690 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3694 total_len += sizeof(*header);
3696 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3697 if (!header) return STATUS_NO_MEMORY;
3699 memset(header, 0, sizeof(*header));
3700 header->magic = GUIDSECTION_MAGIC;
3701 header->size = sizeof(*header);
3702 header->count = count;
3703 header->index_offset = sizeof(*header);
3704 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3705 data_offset = header->index_offset + count*sizeof(*index);
3707 for (i = 0; i < actctx->num_assemblies; i++)
3709 struct assembly *assembly = &actctx->assemblies[i];
3711 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
3712 for (j = 0; j < assembly->num_dlls; j++)
3714 struct dll_redirect *dll = &assembly->dlls[j];
3715 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
3719 *section = header;
3721 return STATUS_SUCCESS;
3724 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3726 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
3729 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3731 struct ifacepsredirect_data *iface;
3732 struct guid_index *index = NULL;
3734 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3736 if (!actctx->ifaceps_section)
3738 struct guidsection_header *section;
3740 NTSTATUS status = build_ifaceps_section(actctx, &section);
3741 if (status) return status;
3743 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
3744 RtlFreeHeap(GetProcessHeap(), 0, section);
3747 index = find_guid_index(actctx->ifaceps_section, guid);
3748 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3750 iface = get_ifaceps_data(actctx, index);
3752 data->ulDataFormatVersion = 1;
3753 data->lpData = iface;
3754 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
3755 data->lpSectionGlobalData = NULL;
3756 data->ulSectionGlobalDataLength = 0;
3757 data->lpSectionBase = actctx->ifaceps_section;
3758 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
3759 data->hActCtx = NULL;
3761 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3762 data->ulAssemblyRosterIndex = index->rosterindex;
3764 return STATUS_SUCCESS;
3767 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3769 unsigned int i, j, total_len = 0, count = 0;
3770 struct guidsection_header *header;
3771 struct clrsurrogate_data *data;
3772 struct guid_index *index;
3773 ULONG data_offset;
3775 /* compute section length */
3776 for (i = 0; i < actctx->num_assemblies; i++)
3778 struct assembly *assembly = &actctx->assemblies[i];
3779 for (j = 0; j < assembly->entities.num; j++)
3781 struct entity *entity = &assembly->entities.base[j];
3782 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
3784 ULONG len;
3786 total_len += sizeof(*index) + sizeof(*data);
3787 len = strlenW(entity->u.clrsurrogate.name) + 1;
3788 if (entity->u.clrsurrogate.version)
3789 len += strlenW(entity->u.clrsurrogate.version) + 1;
3790 total_len += aligned_string_len(len*sizeof(WCHAR));
3792 count++;
3797 total_len += sizeof(*header);
3799 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3800 if (!header) return STATUS_NO_MEMORY;
3802 memset(header, 0, sizeof(*header));
3803 header->magic = GUIDSECTION_MAGIC;
3804 header->size = sizeof(*header);
3805 header->count = count;
3806 header->index_offset = sizeof(*header);
3807 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3808 data_offset = header->index_offset + count*sizeof(*index);
3810 for (i = 0; i < actctx->num_assemblies; i++)
3812 struct assembly *assembly = &actctx->assemblies[i];
3813 for (j = 0; j < assembly->entities.num; j++)
3815 struct entity *entity = &assembly->entities.base[j];
3816 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
3818 ULONG version_len, name_len;
3819 UNICODE_STRING str;
3820 WCHAR *ptrW;
3822 if (entity->u.clrsurrogate.version)
3823 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
3824 else
3825 version_len = 0;
3826 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
3828 /* setup new index entry */
3829 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
3830 RtlGUIDFromString(&str, &index->guid);
3832 index->data_offset = data_offset;
3833 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
3834 index->rosterindex = i + 1;
3836 /* setup data */
3837 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
3838 data->size = sizeof(*data);
3839 data->res = 0;
3840 data->clsid = index->guid;
3841 data->version_offset = version_len ? data->size : 0;
3842 data->version_len = version_len;
3843 data->name_offset = data->size + version_len;
3844 if (version_len)
3845 data->name_offset += sizeof(WCHAR);
3846 data->name_len = name_len;
3848 /* surrogate name */
3849 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3850 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
3851 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3853 /* runtime version */
3854 if (data->version_len)
3856 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
3857 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
3858 ptrW[data->version_len/sizeof(WCHAR)] = 0;
3861 data_offset += index->data_offset;
3862 index++;
3867 *section = header;
3869 return STATUS_SUCCESS;
3872 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
3874 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
3877 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3879 struct clrsurrogate_data *surrogate;
3880 struct guid_index *index = NULL;
3882 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3884 if (!actctx->clrsurrogate_section)
3886 struct guidsection_header *section;
3888 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
3889 if (status) return status;
3891 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
3892 RtlFreeHeap(GetProcessHeap(), 0, section);
3895 index = find_guid_index(actctx->clrsurrogate_section, guid);
3896 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3898 surrogate = get_surrogate_data(actctx, index);
3900 data->ulDataFormatVersion = 1;
3901 data->lpData = surrogate;
3902 /* full length includes string length with nulls */
3903 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
3904 if (surrogate->version_len)
3905 data->ulLength += surrogate->version_len + sizeof(WCHAR);
3907 data->lpSectionGlobalData = NULL;
3908 data->ulSectionGlobalDataLength = 0;
3909 data->lpSectionBase = actctx->clrsurrogate_section;
3910 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
3911 data->hActCtx = NULL;
3913 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3914 data->ulAssemblyRosterIndex = index->rosterindex;
3916 return STATUS_SUCCESS;
3919 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
3920 const UNICODE_STRING *section_name,
3921 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
3923 NTSTATUS status;
3925 switch (section_kind)
3927 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
3928 status = find_dll_redirection(actctx, section_name, data);
3929 break;
3930 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
3931 status = find_window_class(actctx, section_name, data);
3932 break;
3933 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
3934 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
3935 FIXME("Unsupported yet section_kind %x\n", section_kind);
3936 return STATUS_SXS_SECTION_NOT_FOUND;
3937 default:
3938 WARN("Unknown section_kind %x\n", section_kind);
3939 return STATUS_SXS_SECTION_NOT_FOUND;
3942 if (status != STATUS_SUCCESS) return status;
3944 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3946 actctx_addref(actctx);
3947 data->hActCtx = actctx;
3949 return STATUS_SUCCESS;
3952 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
3953 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
3955 NTSTATUS status;
3957 switch (section_kind)
3959 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
3960 status = find_tlib_redirection(actctx, guid, data);
3961 break;
3962 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
3963 status = find_comserver_redirection(actctx, guid, data);
3964 break;
3965 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
3966 status = find_cominterface_redirection(actctx, guid, data);
3967 break;
3968 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
3969 status = find_clr_surrogate(actctx, guid, data);
3970 break;
3971 default:
3972 WARN("Unknown section_kind %x\n", section_kind);
3973 return STATUS_SXS_SECTION_NOT_FOUND;
3976 if (status != STATUS_SUCCESS) return status;
3978 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
3980 actctx_addref(actctx);
3981 data->hActCtx = actctx;
3983 return STATUS_SUCCESS;
3986 /* initialize the activation context for the current process */
3987 void actctx_init(void)
3989 ACTCTXW ctx;
3990 HANDLE handle;
3992 ctx.cbSize = sizeof(ctx);
3993 ctx.lpSource = NULL;
3994 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
3995 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
3996 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
3998 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4002 /***********************************************************************
4003 * RtlCreateActivationContext (NTDLL.@)
4005 * Create an activation context.
4007 * FIXME: function signature/prototype is wrong
4009 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4011 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4012 const WCHAR *directory = NULL;
4013 ACTIVATION_CONTEXT *actctx;
4014 UNICODE_STRING nameW;
4015 ULONG lang = 0;
4016 NTSTATUS status = STATUS_NO_MEMORY;
4017 HANDLE file = 0;
4018 struct actctx_loader acl;
4020 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4022 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4023 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4024 return STATUS_INVALID_PARAMETER;
4026 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4027 return STATUS_NO_MEMORY;
4029 actctx->magic = ACTCTX_MAGIC;
4030 actctx->ref_count = 1;
4031 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4032 actctx->config.info = NULL;
4033 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4034 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4036 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4038 else
4040 UNICODE_STRING dir;
4041 WCHAR *p;
4042 HMODULE module;
4044 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4045 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4047 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4048 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4049 actctx->appdir.info = dir.Buffer;
4052 nameW.Buffer = NULL;
4053 if (pActCtx->lpSource)
4055 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
4057 status = STATUS_NO_SUCH_FILE;
4058 goto error;
4060 status = open_nt_file( &file, &nameW );
4061 if (status)
4063 RtlFreeUnicodeString( &nameW );
4064 goto error;
4068 acl.actctx = actctx;
4069 acl.dependencies = NULL;
4070 acl.num_dependencies = 0;
4071 acl.allocated_dependencies = 0;
4073 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4074 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4076 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4078 /* if we have a resource it's a PE file */
4079 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4081 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4082 pActCtx->lpResourceName, lang );
4083 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4084 /* FIXME: what to do if pActCtx->lpSource is set */
4085 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4086 pActCtx->hModule, pActCtx->lpResourceName );
4088 else if (pActCtx->lpSource)
4090 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4091 file, pActCtx->lpResourceName, lang );
4092 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4093 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4094 NULL, pActCtx->lpResourceName );
4096 else status = STATUS_INVALID_PARAMETER;
4098 else
4100 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4103 if (file) NtClose( file );
4104 RtlFreeUnicodeString( &nameW );
4106 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4107 free_depend_manifests( &acl );
4109 if (status == STATUS_SUCCESS) *handle = actctx;
4110 else actctx_release( actctx );
4111 return status;
4113 error:
4114 if (file) NtClose( file );
4115 actctx_release( actctx );
4116 return status;
4120 /***********************************************************************
4121 * RtlAddRefActivationContext (NTDLL.@)
4123 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4125 ACTIVATION_CONTEXT *actctx;
4127 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4131 /******************************************************************
4132 * RtlReleaseActivationContext (NTDLL.@)
4134 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4136 ACTIVATION_CONTEXT *actctx;
4138 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4141 /******************************************************************
4142 * RtlZombifyActivationContext (NTDLL.@)
4144 * FIXME: function prototype might be wrong
4146 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4148 FIXME("%p: stub\n", handle);
4149 return STATUS_NOT_IMPLEMENTED;
4152 /******************************************************************
4153 * RtlActivateActivationContext (NTDLL.@)
4155 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4157 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4159 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4160 return STATUS_NO_MEMORY;
4162 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4163 frame->ActivationContext = handle;
4164 frame->Flags = 0;
4165 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4166 RtlAddRefActivationContext( handle );
4168 *cookie = (ULONG_PTR)frame;
4169 TRACE( "%p cookie=%lx\n", handle, *cookie );
4170 return STATUS_SUCCESS;
4174 /***********************************************************************
4175 * RtlDeactivateActivationContext (NTDLL.@)
4177 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4179 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4181 TRACE( "%x cookie=%lx\n", flags, cookie );
4183 /* find the right frame */
4184 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4185 for (frame = top; frame; frame = frame->Previous)
4186 if ((ULONG_PTR)frame == cookie) break;
4188 if (!frame)
4189 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4191 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4192 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4194 /* pop everything up to and including frame */
4195 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4197 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4199 frame = top->Previous;
4200 RtlReleaseActivationContext( top->ActivationContext );
4201 RtlFreeHeap( GetProcessHeap(), 0, top );
4202 top = frame;
4207 /******************************************************************
4208 * RtlFreeThreadActivationContextStack (NTDLL.@)
4210 void WINAPI RtlFreeThreadActivationContextStack(void)
4212 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4214 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4215 while (frame)
4217 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4218 RtlReleaseActivationContext( frame->ActivationContext );
4219 RtlFreeHeap( GetProcessHeap(), 0, frame );
4220 frame = prev;
4222 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4226 /******************************************************************
4227 * RtlGetActiveActivationContext (NTDLL.@)
4229 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4231 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4233 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4234 RtlAddRefActivationContext( *handle );
4236 else
4237 *handle = 0;
4239 return STATUS_SUCCESS;
4243 /******************************************************************
4244 * RtlIsActivationContextActive (NTDLL.@)
4246 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4248 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4250 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4251 if (frame->ActivationContext == handle) return TRUE;
4252 return FALSE;
4256 /***********************************************************************
4257 * RtlQueryInformationActivationContext (NTDLL.@)
4259 * Get information about an activation context.
4260 * FIXME: function signature/prototype may be wrong
4262 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4263 ULONG class, PVOID buffer,
4264 SIZE_T bufsize, SIZE_T *retlen )
4266 ACTIVATION_CONTEXT *actctx;
4267 NTSTATUS status;
4269 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4270 subinst, class, buffer, bufsize, retlen);
4272 if (retlen) *retlen = 0;
4273 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4275 switch (class)
4277 case ActivationContextBasicInformation:
4279 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4281 if (retlen) *retlen = sizeof(*info);
4282 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4284 info->hActCtx = handle;
4285 info->dwFlags = 0; /* FIXME */
4286 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4288 break;
4290 case ActivationContextDetailedInformation:
4292 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4293 struct assembly *assembly = NULL;
4294 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4295 LPWSTR ptr;
4297 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4299 if (actctx->num_assemblies) assembly = actctx->assemblies;
4301 if (assembly && assembly->manifest.info)
4302 manifest_len = strlenW(assembly->manifest.info) + 1;
4303 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4304 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4305 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4307 if (retlen) *retlen = len;
4308 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4310 acdi->dwFlags = 0;
4311 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4312 acdi->ulAssemblyCount = actctx->num_assemblies;
4313 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4314 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4315 acdi->ulRootConfigurationPathType = actctx->config.type;
4316 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4317 acdi->ulAppDirPathType = actctx->appdir.type;
4318 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4319 ptr = (LPWSTR)(acdi + 1);
4320 if (manifest_len)
4322 acdi->lpRootManifestPath = ptr;
4323 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4324 ptr += manifest_len;
4326 else acdi->lpRootManifestPath = NULL;
4327 if (config_len)
4329 acdi->lpRootConfigurationPath = ptr;
4330 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4331 ptr += config_len;
4333 else acdi->lpRootConfigurationPath = NULL;
4334 if (appdir_len)
4336 acdi->lpAppDirPath = ptr;
4337 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4339 else acdi->lpAppDirPath = NULL;
4341 break;
4343 case AssemblyDetailedInformationInActivationContext:
4345 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4346 struct assembly *assembly;
4347 WCHAR *assembly_id;
4348 DWORD index;
4349 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4350 LPWSTR ptr;
4352 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4353 if (!subinst) return STATUS_INVALID_PARAMETER;
4355 index = *(DWORD*)subinst;
4356 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4358 assembly = &actctx->assemblies[index - 1];
4360 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4361 id_len = strlenW(assembly_id) + 1;
4362 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4364 if (assembly->manifest.info &&
4365 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4366 path_len = strlenW(assembly->manifest.info) + 1;
4368 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4370 if (retlen) *retlen = len;
4371 if (!buffer || bufsize < len)
4373 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4374 return STATUS_BUFFER_TOO_SMALL;
4377 afdi->ulFlags = 0; /* FIXME */
4378 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4379 afdi->ulManifestPathType = assembly->manifest.type;
4380 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4381 /* FIXME afdi->liManifestLastWriteTime = 0; */
4382 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4383 afdi->ulPolicyPathLength = 0;
4384 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4385 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4386 afdi->ulManifestVersionMajor = 1;
4387 afdi->ulManifestVersionMinor = 0;
4388 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4389 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4390 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4391 ptr = (LPWSTR)(afdi + 1);
4392 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4393 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4394 ptr += id_len;
4395 if (path_len)
4397 afdi->lpAssemblyManifestPath = ptr;
4398 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4399 ptr += path_len;
4400 } else afdi->lpAssemblyManifestPath = NULL;
4401 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4402 if (ad_len)
4404 afdi->lpAssemblyDirectoryName = ptr;
4405 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4407 else afdi->lpAssemblyDirectoryName = NULL;
4408 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4410 break;
4412 case FileInformationInAssemblyOfAssemblyInActivationContext:
4414 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4415 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4416 struct assembly *assembly;
4417 struct dll_redirect *dll;
4418 SIZE_T len, dll_len = 0;
4419 LPWSTR ptr;
4421 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4422 if (!acqi) return STATUS_INVALID_PARAMETER;
4424 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4425 return STATUS_INVALID_PARAMETER;
4426 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4428 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4429 return STATUS_INVALID_PARAMETER;
4430 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4432 if (dll->name) dll_len = strlenW(dll->name) + 1;
4433 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4435 if (!buffer || bufsize < len)
4437 if (retlen) *retlen = len;
4438 return STATUS_BUFFER_TOO_SMALL;
4440 if (retlen) *retlen = 0; /* yes that's what native does !! */
4441 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4442 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4443 afdi->ulPathLength = 0; /* FIXME */
4444 ptr = (LPWSTR)(afdi + 1);
4445 if (dll_len)
4447 afdi->lpFileName = ptr;
4448 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4449 } else afdi->lpFileName = NULL;
4450 afdi->lpFilePath = NULL; /* FIXME */
4452 break;
4454 default:
4455 FIXME( "class %u not implemented\n", class );
4456 return STATUS_NOT_IMPLEMENTED;
4458 return STATUS_SUCCESS;
4461 /***********************************************************************
4462 * RtlFindActivationContextSectionString (NTDLL.@)
4464 * Find information about a string in an activation context.
4465 * FIXME: function signature/prototype may be wrong
4467 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
4468 const UNICODE_STRING *section_name, PVOID ptr )
4470 PACTCTX_SECTION_KEYED_DATA data = ptr;
4471 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4473 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
4474 debugstr_us(section_name), data);
4476 if (guid)
4478 FIXME("expected guid == NULL\n");
4479 return STATUS_INVALID_PARAMETER;
4481 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4483 FIXME("unknown flags %08x\n", flags);
4484 return STATUS_INVALID_PARAMETER;
4486 if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
4487 !section_name || !section_name->Buffer)
4489 WARN("invalid parameter\n");
4490 return STATUS_INVALID_PARAMETER;
4493 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4495 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
4496 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
4499 if (status != STATUS_SUCCESS)
4500 status = find_string( process_actctx, section_kind, section_name, flags, data );
4502 return status;
4505 /***********************************************************************
4506 * RtlFindActivationContextSectionGuid (NTDLL.@)
4508 * Find information about a GUID in an activation context.
4509 * FIXME: function signature/prototype may be wrong
4511 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
4512 const GUID *guid, void *ptr )
4514 ACTCTX_SECTION_KEYED_DATA *data = ptr;
4515 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4517 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
4519 if (extguid)
4521 FIXME("expected extguid == NULL\n");
4522 return STATUS_INVALID_PARAMETER;
4525 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4527 FIXME("unknown flags %08x\n", flags);
4528 return STATUS_INVALID_PARAMETER;
4531 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
4532 return STATUS_INVALID_PARAMETER;
4534 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4536 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
4537 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
4540 if (status != STATUS_SUCCESS)
4541 status = find_guid( process_actctx, section_kind, guid, flags, data );
4543 return status;