ntdll: Add support for parsing application settings in manifests.
[wine.git] / dlls / ntdll / actctx.c
blobf8dd3fc3c6890d69bdb8c78f134309a3c7d9d413
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
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
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;
131 BOOL delayed;
134 struct strsection_header
136 DWORD magic;
137 ULONG size;
138 DWORD unk1[3];
139 ULONG count;
140 ULONG index_offset;
141 DWORD unk2[2];
142 ULONG global_offset;
143 ULONG global_len;
146 struct string_index
148 ULONG hash; /* key string hash */
149 ULONG name_offset;
150 ULONG name_len;
151 ULONG data_offset; /* redirect data offset */
152 ULONG data_len;
153 ULONG rosterindex;
156 struct guidsection_header
158 DWORD magic;
159 ULONG size;
160 DWORD unk[3];
161 ULONG count;
162 ULONG index_offset;
163 DWORD unk2;
164 ULONG names_offset;
165 ULONG names_len;
168 struct guid_index
170 GUID guid;
171 ULONG data_offset;
172 ULONG data_len;
173 ULONG rosterindex;
176 struct wndclass_redirect_data
178 ULONG size;
179 DWORD res;
180 ULONG name_len;
181 ULONG name_offset; /* versioned name offset */
182 ULONG module_len;
183 ULONG module_offset;/* container name offset */
186 struct dllredirect_data
188 ULONG size;
189 ULONG unk;
190 DWORD res[3];
193 struct tlibredirect_data
195 ULONG size;
196 DWORD res;
197 ULONG name_len;
198 ULONG name_offset;
199 LANGID langid;
200 WORD flags;
201 ULONG help_len;
202 ULONG help_offset;
203 WORD major_version;
204 WORD minor_version;
207 enum comclass_threadingmodel
209 ThreadingModel_Apartment = 1,
210 ThreadingModel_Free = 2,
211 ThreadingModel_No = 3,
212 ThreadingModel_Both = 4,
213 ThreadingModel_Neutral = 5
216 enum comclass_miscfields
218 MiscStatus = 1,
219 MiscStatusIcon = 2,
220 MiscStatusContent = 4,
221 MiscStatusThumbnail = 8,
222 MiscStatusDocPrint = 16
225 struct comclassredirect_data
227 ULONG size;
228 BYTE res;
229 BYTE miscmask;
230 BYTE res1[2];
231 DWORD model;
232 GUID clsid;
233 GUID alias;
234 GUID clsid2;
235 GUID tlbid;
236 ULONG name_len;
237 ULONG name_offset;
238 ULONG progid_len;
239 ULONG progid_offset;
240 ULONG clrdata_len;
241 ULONG clrdata_offset;
242 DWORD miscstatus;
243 DWORD miscstatuscontent;
244 DWORD miscstatusthumbnail;
245 DWORD miscstatusicon;
246 DWORD miscstatusdocprint;
249 enum ifaceps_mask
251 NumMethods = 1,
252 BaseIface = 2
255 struct ifacepsredirect_data
257 ULONG size;
258 DWORD mask;
259 GUID iid;
260 ULONG nummethods;
261 GUID tlbid;
262 GUID base;
263 ULONG name_len;
264 ULONG name_offset;
267 struct clrsurrogate_data
269 ULONG size;
270 DWORD res;
271 GUID clsid;
272 ULONG version_offset;
273 ULONG version_len;
274 ULONG name_offset;
275 ULONG name_len;
278 struct clrclass_data
280 ULONG size;
281 DWORD res[2];
282 ULONG module_len;
283 ULONG module_offset;
284 ULONG name_len;
285 ULONG name_offset;
286 ULONG version_len;
287 ULONG version_offset;
288 DWORD res2[2];
291 struct progidredirect_data
293 ULONG size;
294 DWORD reserved;
295 ULONG clsid_offset;
300 Sections structure.
302 Sections are accessible by string or guid key, that defines two types of sections.
303 All sections of each type have same magic value and header structure, index
304 data could be of two possible types too. So every string based section uses
305 the same index format, same applies to guid sections - they share same guid index
306 format.
308 - window class redirection section is a plain buffer with following format:
310 <section header>
311 <index[]>
312 <data[]> --- <original name>
313 <redirect data>
314 <versioned name>
315 <module name>
317 Header is fixed length structure - struct strsection_header,
318 contains redirected classes count;
320 Index is an array of fixed length index records, each record is
321 struct string_index.
323 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
325 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
326 others are relative to section itself.
328 - dll redirect section format:
330 <section header>
331 <index[]>
332 <data[]> --- <dll name>
333 <data>
335 This section doesn't seem to carry any payload data except dll names.
337 - typelib section format:
339 <section header>
340 <module names[]>
341 <index[]>
342 <data[]> --- <data>
343 <helpstring>
345 Header is fixed length, index is an array of fixed length 'struct guid_index'.
346 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
347 4-bytes aligned as a whole.
349 Module name offsets are relative to section, helpstring offset is relative to data
350 structure itself.
352 - comclass section format:
354 <section header>
355 <module names[]>
356 <index[]>
357 <data[]> --- <data> --- <data>
358 <progid> <clrdata>
359 <name>
360 <version>
361 <progid>
363 This section uses two index records per comclass, one entry contains original guid
364 as specified by context, another one has a generated guid. Index and strings handling
365 is similar to typelib sections.
367 For CLR classes additional data is stored after main COM class data, it contains
368 class name and runtime version string, see 'struct clrclass_data'.
370 Module name offsets are relative to section, progid offset is relative to data
371 structure itself.
373 - COM interface section format:
375 <section header>
376 <index[]>
377 <data[]> --- <data>
378 <name>
380 Interface section contains data for proxy/stubs and external proxy/stubs. External
381 ones are defined at assembly level, so this section has no module information.
382 All records are indexed with 'iid' value from manifest. There an exception for
383 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
384 redirect data, but index is still 'iid' from manifest.
386 Interface name offset is relative to data structure itself.
388 - CLR surrogates section format:
390 <section header>
391 <index[]>
392 <data[]> --- <data>
393 <name>
394 <version>
396 There's nothing special about this section, same way to store strings is used,
397 no modules part as it belongs to assembly level, not a file.
399 - ProgID section format:
401 <section header>
402 <guids[]>
403 <index[]>
404 <data[]> --- <progid>
405 <data>
407 This sections uses generated alias guids from COM server section. This way
408 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
409 is stored too, aligned.
412 struct progids
414 WCHAR **progids;
415 unsigned int num;
416 unsigned int allocated;
419 struct entity
421 DWORD kind;
422 union
424 struct
426 WCHAR *tlbid;
427 WCHAR *helpdir;
428 WORD flags;
429 WORD major;
430 WORD minor;
431 } typelib;
432 struct
434 WCHAR *clsid;
435 WCHAR *tlbid;
436 WCHAR *progid;
437 WCHAR *name; /* clrClass: class name */
438 WCHAR *version; /* clrClass: CLR runtime version */
439 DWORD model;
440 DWORD miscstatus;
441 DWORD miscstatuscontent;
442 DWORD miscstatusthumbnail;
443 DWORD miscstatusicon;
444 DWORD miscstatusdocprint;
445 struct progids progids;
446 } comclass;
447 struct {
448 WCHAR *iid;
449 WCHAR *base;
450 WCHAR *tlib;
451 WCHAR *name;
452 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
453 DWORD mask;
454 ULONG nummethods;
455 } ifaceps;
456 struct
458 WCHAR *name;
459 BOOL versioned;
460 } class;
461 struct
463 WCHAR *name;
464 WCHAR *clsid;
465 WCHAR *version;
466 } clrsurrogate;
467 struct
469 WCHAR *name;
470 WCHAR *value;
471 } settings;
472 } u;
475 struct entity_array
477 struct entity *base;
478 unsigned int num;
479 unsigned int allocated;
482 struct dll_redirect
484 WCHAR *name;
485 WCHAR *hash;
486 struct entity_array entities;
489 enum assembly_type
491 APPLICATION_MANIFEST,
492 ASSEMBLY_MANIFEST,
493 ASSEMBLY_SHARED_MANIFEST,
496 struct assembly
498 enum assembly_type type;
499 struct assembly_identity id;
500 struct file_info manifest;
501 WCHAR *directory;
502 BOOL no_inherit;
503 struct dll_redirect *dlls;
504 unsigned int num_dlls;
505 unsigned int allocated_dlls;
506 struct entity_array entities;
507 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
508 ULONG num_compat_contexts;
509 ACTCTX_REQUESTED_RUN_LEVEL run_level;
510 ULONG ui_access;
513 enum context_sections
515 WINDOWCLASS_SECTION = 1,
516 DLLREDIRECT_SECTION = 2,
517 TLIBREDIRECT_SECTION = 4,
518 SERVERREDIRECT_SECTION = 8,
519 IFACEREDIRECT_SECTION = 16,
520 CLRSURROGATES_SECTION = 32,
521 PROGIDREDIRECT_SECTION = 64
524 typedef struct _ACTIVATION_CONTEXT
526 ULONG magic;
527 int ref_count;
528 struct file_info config;
529 struct file_info appdir;
530 struct assembly *assemblies;
531 unsigned int num_assemblies;
532 unsigned int allocated_assemblies;
533 /* section data */
534 DWORD sections;
535 struct strsection_header *wndclass_section;
536 struct strsection_header *dllredirect_section;
537 struct strsection_header *progid_section;
538 struct guidsection_header *tlib_section;
539 struct guidsection_header *comserver_section;
540 struct guidsection_header *ifaceps_section;
541 struct guidsection_header *clrsurrogate_section;
542 } ACTIVATION_CONTEXT;
544 struct actctx_loader
546 ACTIVATION_CONTEXT *actctx;
547 struct assembly_identity *dependencies;
548 unsigned int num_dependencies;
549 unsigned int allocated_dependencies;
552 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
553 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
554 static const WCHAR asmv3W[] = {'a','s','m','v','3',':',0};
555 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
556 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
557 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
558 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
559 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
560 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
561 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};
562 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};
563 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
564 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
565 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
566 static const WCHAR fileW[] = {'f','i','l','e',0};
567 static const WCHAR hashW[] = {'h','a','s','h',0};
568 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
569 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
570 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
571 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
573 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
574 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
575 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
576 static const WCHAR iidW[] = {'i','i','d',0};
577 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
578 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
579 static const WCHAR nameW[] = {'n','a','m','e',0};
580 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
581 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
582 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
583 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
584 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};
585 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
586 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
587 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
588 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
589 static const WCHAR typeW[] = {'t','y','p','e',0};
590 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
591 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
592 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
593 static const WCHAR yesW[] = {'y','e','s',0};
594 static const WCHAR noW[] = {'n','o',0};
595 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
596 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
597 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
598 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
599 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
600 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
601 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
602 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
603 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
604 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
605 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
606 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
607 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
608 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
609 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
610 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
612 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
613 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
614 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
615 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
616 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
617 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
618 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
619 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};
620 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
621 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
622 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
623 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
624 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
625 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
626 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
627 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
628 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};
629 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
630 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
631 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
632 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};
633 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
635 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
636 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0};
637 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
638 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
639 static const WCHAR IdW[] = {'I','d',0};
640 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0};
641 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
642 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
643 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
644 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0};
645 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0};
646 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0};
647 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0};
648 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0};
649 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0};
650 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0};
651 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
652 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0};
653 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0};
654 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0};
655 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0};
657 struct olemisc_entry
659 const WCHAR *name;
660 OLEMISC value;
663 static const struct olemisc_entry olemisc_values[] =
665 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
666 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
667 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
668 { alignableW, OLEMISC_ALIGNABLE },
669 { alwaysrunW, OLEMISC_ALWAYSRUN },
670 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
671 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
672 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
673 { imemodeW, OLEMISC_IMEMODE },
674 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
675 { insideoutW, OLEMISC_INSIDEOUT },
676 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
677 { islinkobjectW, OLEMISC_ISLINKOBJECT },
678 { nouiactivateW, OLEMISC_NOUIACTIVATE },
679 { onlyiconicW, OLEMISC_ONLYICONIC },
680 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
681 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
682 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
683 { simpleframeW, OLEMISC_SIMPLEFRAME },
684 { staticW, OLEMISC_STATIC },
685 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
686 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
689 static const WCHAR xmlW[] = {'?','x','m','l',0};
690 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};
691 static const WCHAR manifestv2W[] = {'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','2',0};
692 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};
694 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
695 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
696 static const WCHAR wildcardW[] = {'*',0};
698 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
699 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
701 static WCHAR *strdupW(const WCHAR* str)
703 WCHAR* ptr;
705 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
706 return NULL;
707 return strcpyW(ptr, str);
710 static WCHAR *xmlstrdupW(const xmlstr_t* str)
712 WCHAR *strW;
714 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
716 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
717 strW[str->len] = 0;
719 return strW;
722 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
724 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
727 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
729 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
732 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
734 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
735 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
738 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
740 UINT len = strlenW( namespace );
742 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
743 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
744 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
747 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
749 if (elem->len && elem->ptr[0] == '/')
751 xmlstr_t elem_end;
752 elem_end.ptr = elem->ptr + 1;
753 elem_end.len = elem->len - 1;
754 return xml_elem_cmp( &elem_end, str, namespace );
756 return FALSE;
759 static inline BOOL isxmlspace( WCHAR ch )
761 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
764 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
766 return debugstr_wn(str->ptr, str->len);
769 static inline const char* debugstr_version(const struct assembly_version *ver)
771 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
774 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
776 struct assembly *assembly;
778 if (actctx->num_assemblies == actctx->allocated_assemblies)
780 void *ptr;
781 unsigned int new_count;
782 if (actctx->assemblies)
784 new_count = actctx->allocated_assemblies * 2;
785 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
786 actctx->assemblies, new_count * sizeof(*assembly) );
788 else
790 new_count = 4;
791 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
793 if (!ptr) return NULL;
794 actctx->assemblies = ptr;
795 actctx->allocated_assemblies = new_count;
798 assembly = &actctx->assemblies[actctx->num_assemblies++];
799 assembly->type = at;
800 return assembly;
803 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
805 if (assembly->num_dlls == assembly->allocated_dlls)
807 void *ptr;
808 unsigned int new_count;
809 if (assembly->dlls)
811 new_count = assembly->allocated_dlls * 2;
812 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
813 assembly->dlls, new_count * sizeof(*assembly->dlls) );
815 else
817 new_count = 4;
818 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
820 if (!ptr) return NULL;
821 assembly->dlls = ptr;
822 assembly->allocated_dlls = new_count;
824 return &assembly->dlls[assembly->num_dlls++];
827 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
829 void *ptr;
830 if (assembly->num_compat_contexts)
832 unsigned int new_count = assembly->num_compat_contexts + 1;
833 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
834 assembly->compat_contexts,
835 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
837 else
839 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
841 if (!ptr) return NULL;
842 assembly->compat_contexts = ptr;
843 return &assembly->compat_contexts[assembly->num_compat_contexts++];
846 static void free_assembly_identity(struct assembly_identity *ai)
848 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
849 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
850 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
851 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
852 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
855 static struct entity* add_entity(struct entity_array *array, DWORD kind)
857 struct entity* entity;
859 if (array->num == array->allocated)
861 void *ptr;
862 unsigned int new_count;
863 if (array->base)
865 new_count = array->allocated * 2;
866 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
867 array->base, new_count * sizeof(*array->base) );
869 else
871 new_count = 4;
872 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
874 if (!ptr) return NULL;
875 array->base = ptr;
876 array->allocated = new_count;
878 entity = &array->base[array->num++];
879 entity->kind = kind;
880 return entity;
883 static void free_entity_array(struct entity_array *array)
885 unsigned int i, j;
886 for (i = 0; i < array->num; i++)
888 struct entity *entity = &array->base[i];
889 switch (entity->kind)
891 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
892 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
893 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
894 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
895 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
896 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
897 for (j = 0; j < entity->u.comclass.progids.num; j++)
898 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
899 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
900 break;
901 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
902 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
903 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
904 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
905 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
906 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
907 break;
908 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
909 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
910 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
911 break;
912 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
913 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
914 break;
915 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
916 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
917 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
918 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
919 break;
920 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS:
921 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name);
922 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value);
923 break;
924 default:
925 FIXME("Unknown entity kind %d\n", entity->kind);
928 RtlFreeHeap( GetProcessHeap(), 0, array->base );
931 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
933 if (!str1) return !str2;
934 return str2 && !strcmpiW( str1, str2 );
937 static BOOL is_matching_identity( const struct assembly_identity *id1,
938 const struct assembly_identity *id2 )
940 if (!is_matching_string( id1->name, id2->name )) return FALSE;
941 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
942 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
944 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
946 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
947 return FALSE;
949 if (id1->version.major != id2->version.major) return FALSE;
950 if (id1->version.minor != id2->version.minor) return FALSE;
951 if (id1->version.build > id2->version.build) return FALSE;
952 if (id1->version.build == id2->version.build &&
953 id1->version.revision > id2->version.revision) return FALSE;
954 return TRUE;
957 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
958 struct assembly_identity* ai)
960 unsigned int i;
962 /* check if we already have that assembly */
964 for (i = 0; i < acl->actctx->num_assemblies; i++)
965 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
967 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
968 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
969 ai->version.build, ai->version.revision );
970 return TRUE;
973 for (i = 0; i < acl->num_dependencies; i++)
974 if (is_matching_identity( ai, &acl->dependencies[i] ))
976 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
977 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
978 ai->version.build, ai->version.revision );
979 return TRUE;
982 if (acl->num_dependencies == acl->allocated_dependencies)
984 void *ptr;
985 unsigned int new_count;
986 if (acl->dependencies)
988 new_count = acl->allocated_dependencies * 2;
989 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
990 new_count * sizeof(acl->dependencies[0]));
992 else
994 new_count = 4;
995 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
997 if (!ptr) return FALSE;
998 acl->dependencies = ptr;
999 acl->allocated_dependencies = new_count;
1001 acl->dependencies[acl->num_dependencies++] = *ai;
1003 return TRUE;
1006 static void free_depend_manifests(struct actctx_loader* acl)
1008 unsigned int i;
1009 for (i = 0; i < acl->num_dependencies; i++)
1010 free_assembly_identity(&acl->dependencies[i]);
1011 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
1014 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
1016 static const WCHAR undW[] = {'_',0};
1017 static const WCHAR noneW[] = {'n','o','n','e',0};
1018 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
1020 const WCHAR *arch = ai->arch ? ai->arch : noneW;
1021 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1022 const WCHAR *lang = ai->language ? ai->language : noneW;
1023 const WCHAR *name = ai->name ? ai->name : noneW;
1024 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1025 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1026 WCHAR *ret;
1028 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1030 strcpyW( ret, arch );
1031 strcatW( ret, undW );
1032 strcatW( ret, name );
1033 strcatW( ret, undW );
1034 strcatW( ret, key );
1035 strcatW( ret, undW );
1036 sprintfW( ret + strlenW(ret), version_formatW,
1037 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1038 strcatW( ret, undW );
1039 strcatW( ret, lang );
1040 strcatW( ret, undW );
1041 strcatW( ret, mskeyW );
1042 return ret;
1045 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1047 WCHAR *p = buffer;
1049 if (!str) return;
1050 strcatW( buffer, prefix );
1051 p += strlenW(p);
1052 *p++ = '"';
1053 strcpyW( p, str );
1054 p += strlenW(p);
1055 *p++ = '"';
1056 *p = 0;
1059 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1061 static const WCHAR archW[] =
1062 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1063 static const WCHAR public_keyW[] =
1064 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1065 static const WCHAR typeW[] =
1066 {',','t','y','p','e','=',0};
1067 static const WCHAR versionW[] =
1068 {',','v','e','r','s','i','o','n','=',0};
1070 WCHAR version[64], *ret;
1071 SIZE_T size = 0;
1073 sprintfW( version, version_formatW,
1074 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1075 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1076 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1077 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1078 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1079 size += strlenW(versionW) + strlenW(version) + 2;
1081 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1082 return NULL;
1084 if (ai->name) strcpyW( ret, ai->name );
1085 else *ret = 0;
1086 append_string( ret, archW, ai->arch );
1087 append_string( ret, public_keyW, ai->public_key );
1088 append_string( ret, typeW, ai->type );
1089 append_string( ret, versionW, version );
1090 return ret;
1093 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1095 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1097 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1098 __TRY
1100 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1102 __EXCEPT_PAGE_FAULT
1105 __ENDTRY
1106 return ret;
1109 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1111 interlocked_xchg_add( &actctx->ref_count, 1 );
1114 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1116 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1118 unsigned int i, j;
1120 for (i = 0; i < actctx->num_assemblies; i++)
1122 struct assembly *assembly = &actctx->assemblies[i];
1123 for (j = 0; j < assembly->num_dlls; j++)
1125 struct dll_redirect *dll = &assembly->dlls[j];
1126 free_entity_array( &dll->entities );
1127 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1128 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1130 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1131 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1132 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1133 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1134 free_entity_array( &assembly->entities );
1135 free_assembly_identity(&assembly->id);
1137 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1138 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1139 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1140 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1141 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1142 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1143 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1144 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1145 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1146 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1147 actctx->magic = 0;
1148 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1152 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1153 BOOL* error, BOOL* end)
1155 const WCHAR* ptr;
1157 *error = TRUE;
1159 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1160 xmlbuf->ptr++;
1162 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1164 if (*xmlbuf->ptr == '/')
1166 xmlbuf->ptr++;
1167 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1168 return FALSE;
1170 xmlbuf->ptr++;
1171 *end = TRUE;
1172 *error = FALSE;
1173 return FALSE;
1176 if (*xmlbuf->ptr == '>')
1178 xmlbuf->ptr++;
1179 *error = FALSE;
1180 return FALSE;
1183 ptr = xmlbuf->ptr;
1184 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1186 if (ptr == xmlbuf->end) return FALSE;
1188 name->ptr = xmlbuf->ptr;
1189 name->len = ptr-xmlbuf->ptr;
1190 xmlbuf->ptr = ptr;
1192 /* skip spaces before '=' */
1193 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1194 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1196 /* skip '=' itself */
1197 ptr++;
1198 if (ptr == xmlbuf->end) return FALSE;
1200 /* skip spaces after '=' */
1201 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1203 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1205 value->ptr = ++ptr;
1206 if (ptr == xmlbuf->end) return FALSE;
1208 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1209 if (!ptr)
1211 xmlbuf->ptr = xmlbuf->end;
1212 return FALSE;
1215 value->len = ptr - value->ptr;
1216 xmlbuf->ptr = ptr + 1;
1218 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1220 *error = FALSE;
1221 return TRUE;
1224 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1226 const WCHAR* ptr;
1228 for (;;)
1230 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1231 if (!ptr)
1233 xmlbuf->ptr = xmlbuf->end;
1234 return FALSE;
1236 ptr++;
1237 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1239 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1240 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1242 if (ptr + 3 > xmlbuf->end)
1244 xmlbuf->ptr = xmlbuf->end;
1245 return FALSE;
1247 xmlbuf->ptr = ptr + 3;
1249 else break;
1252 xmlbuf->ptr = ptr;
1253 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1254 ptr++;
1256 elem->ptr = xmlbuf->ptr;
1257 elem->len = ptr - xmlbuf->ptr;
1258 xmlbuf->ptr = ptr;
1259 return xmlbuf->ptr != xmlbuf->end;
1262 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1264 /* FIXME: parse attributes */
1265 const WCHAR *ptr;
1267 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1269 if (ptr[0] == '?' && ptr[1] == '>')
1271 xmlbuf->ptr = ptr + 2;
1272 return TRUE;
1275 return FALSE;
1278 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1280 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1282 if (!ptr) return FALSE;
1284 content->ptr = xmlbuf->ptr;
1285 content->len = ptr - xmlbuf->ptr;
1286 xmlbuf->ptr = ptr;
1288 return TRUE;
1291 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1293 unsigned int ver[4];
1294 unsigned int pos;
1295 const WCHAR *curr;
1297 /* major.minor.build.revision */
1298 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1299 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1301 if (*curr >= '0' && *curr <= '9')
1303 ver[pos] = ver[pos] * 10 + *curr - '0';
1304 if (ver[pos] >= 0x10000) goto error;
1306 else if (*curr == '.')
1308 if (++pos >= 4) goto error;
1310 else goto error;
1312 version->major = ver[0];
1313 version->minor = ver[1];
1314 version->build = ver[2];
1315 version->revision = ver[3];
1316 return TRUE;
1318 error:
1319 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1320 return FALSE;
1323 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1325 xmlstr_t elem;
1326 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1327 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1328 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1329 return FALSE;
1332 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1334 xmlstr_t attr_name, attr_value;
1335 BOOL error;
1337 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1339 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1340 debugstr_xmlstr(&attr_value));
1342 return !error;
1345 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1347 BOOL end = FALSE;
1348 return parse_expect_no_attr(xmlbuf, &end) && !end;
1351 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1353 xmlstr_t elem;
1354 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1355 if (!xml_elem_cmp_end(&elem, name, namespace))
1357 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1358 return FALSE;
1360 return parse_end_element(xmlbuf);
1363 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1365 xmlstr_t attr_name, attr_value, elem;
1366 BOOL end = FALSE, error, ret = TRUE;
1368 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1369 if(error || end) return end;
1371 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1373 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1374 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1375 break;
1376 else
1377 ret = parse_unknown_elem(xmlbuf, &elem);
1380 return ret && parse_end_element(xmlbuf);
1383 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1384 struct assembly_identity* ai)
1386 xmlstr_t attr_name, attr_value;
1387 BOOL end = FALSE, error;
1389 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1391 if (xmlstr_cmp(&attr_name, nameW))
1393 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1395 else if (xmlstr_cmp(&attr_name, typeW))
1397 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1399 else if (xmlstr_cmp(&attr_name, versionW))
1401 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1403 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1405 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1407 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1409 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1411 else if (xmlstr_cmp(&attr_name, languageW))
1413 WARN("Unsupported yet language attribute (%s)\n",
1414 debugstr_xmlstr(&attr_value));
1415 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1417 else
1419 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1420 debugstr_xmlstr(&attr_value));
1424 TRACE( "name=%s version=%s arch=%s\n",
1425 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1427 if (error || end) return end;
1428 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1431 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1433 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1434 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1435 static const WCHAR freeW[] = {'F','r','e','e',0};
1436 static const WCHAR bothW[] = {'B','o','t','h',0};
1438 if (value->len == 0) return ThreadingModel_No;
1439 if (xmlstr_cmp(value, apartW))
1440 return ThreadingModel_Apartment;
1441 else if (xmlstr_cmp(value, freeW))
1442 return ThreadingModel_Free;
1443 else if (xmlstr_cmp(value, bothW))
1444 return ThreadingModel_Both;
1445 else if (xmlstr_cmp(value, neutralW))
1446 return ThreadingModel_Neutral;
1447 else
1448 return ThreadingModel_No;
1451 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1453 int min, max;
1455 min = 0;
1456 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1458 while (min <= max)
1460 int n, c;
1462 n = (min+max)/2;
1464 c = strncmpW(olemisc_values[n].name, str, len);
1465 if (!c && !olemisc_values[n].name[len])
1466 return olemisc_values[n].value;
1468 if (c >= 0)
1469 max = n-1;
1470 else
1471 min = n+1;
1474 WARN("unknown flag %s\n", debugstr_wn(str, len));
1475 return 0;
1478 static DWORD parse_com_class_misc(const xmlstr_t *value)
1480 const WCHAR *str = value->ptr, *start;
1481 DWORD flags = 0;
1482 int i = 0;
1484 /* it's comma separated list of flags */
1485 while (i < value->len)
1487 start = str;
1488 while (*str != ',' && (i++ < value->len)) str++;
1490 flags |= get_olemisc_value(start, str-start);
1492 /* skip separator */
1493 str++;
1494 i++;
1497 return flags;
1500 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1502 struct progids *progids = &entity->u.comclass.progids;
1504 if (progids->allocated == 0)
1506 progids->allocated = 4;
1507 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1510 if (progids->allocated == progids->num)
1512 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1513 2 * progids->allocated * sizeof(WCHAR*));
1514 if (!new_progids) return FALSE;
1515 progids->allocated *= 2;
1516 progids->progids = new_progids;
1519 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1520 progids->num++;
1522 return TRUE;
1525 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1527 xmlstr_t content;
1528 BOOL end = FALSE;
1530 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1531 return FALSE;
1533 if (!com_class_add_progid(&content, entity)) return FALSE;
1534 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1537 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1539 xmlstr_t elem, attr_name, attr_value;
1540 BOOL ret = TRUE, end = FALSE, error;
1541 struct entity* entity;
1543 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1544 return FALSE;
1546 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1548 if (xmlstr_cmp(&attr_name, clsidW))
1550 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1552 else if (xmlstr_cmp(&attr_name, progidW))
1554 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1556 else if (xmlstr_cmp(&attr_name, tlbidW))
1558 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1560 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1562 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1564 else if (xmlstr_cmp(&attr_name, miscstatusW))
1566 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1568 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1570 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1572 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1574 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1576 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1578 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1580 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1582 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1584 else if (xmlstr_cmp(&attr_name, descriptionW))
1586 /* not stored */
1588 else
1590 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1594 if (error) return FALSE;
1596 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1597 if (entity->u.comclass.progid)
1598 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1600 if (end) return TRUE;
1602 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1604 if (xmlstr_cmp_end(&elem, comClassW))
1606 ret = parse_end_element(xmlbuf);
1607 break;
1609 else if (xmlstr_cmp(&elem, progidW))
1611 ret = parse_com_class_progid(xmlbuf, entity);
1613 else
1615 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1616 ret = parse_unknown_elem(xmlbuf, &elem);
1620 if (entity->u.comclass.progids.num)
1621 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1623 return ret;
1626 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1628 const WCHAR *curr;
1629 ULONG num = 0;
1631 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1633 if (*curr >= '0' && *curr <= '9')
1634 num = num * 10 + *curr - '0';
1635 else
1637 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1638 return FALSE;
1641 entity->u.ifaceps.nummethods = num;
1643 return TRUE;
1646 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1648 xmlstr_t attr_name, attr_value;
1649 BOOL end = FALSE, error;
1650 struct entity* entity;
1652 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1653 return FALSE;
1655 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1657 if (xmlstr_cmp(&attr_name, iidW))
1659 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1661 else if (xmlstr_cmp(&attr_name, nameW))
1663 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1665 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1667 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1668 entity->u.ifaceps.mask |= BaseIface;
1670 else if (xmlstr_cmp(&attr_name, nummethodsW))
1672 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1673 entity->u.ifaceps.mask |= NumMethods;
1675 else if (xmlstr_cmp(&attr_name, tlbidW))
1677 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1679 /* not used */
1680 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1683 else
1685 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1689 if (error) return FALSE;
1690 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1691 if (end) return TRUE;
1693 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1696 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1698 WORD *flags = &entity->u.typelib.flags;
1699 const WCHAR *str = value->ptr, *start;
1700 int i = 0;
1702 *flags = 0;
1704 /* it's comma separated list of flags */
1705 while (i < value->len)
1707 start = str;
1708 while (*str != ',' && (i++ < value->len)) str++;
1710 if (!strncmpiW(start, restrictedW, str-start))
1711 *flags |= LIBFLAG_FRESTRICTED;
1712 else if (!strncmpiW(start, controlW, str-start))
1713 *flags |= LIBFLAG_FCONTROL;
1714 else if (!strncmpiW(start, hiddenW, str-start))
1715 *flags |= LIBFLAG_FHIDDEN;
1716 else if (!strncmpiW(start, hasdiskimageW, str-start))
1717 *flags |= LIBFLAG_FHASDISKIMAGE;
1718 else
1720 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1721 return FALSE;
1724 /* skip separator */
1725 str++;
1726 i++;
1729 return TRUE;
1732 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1734 unsigned int ver[2];
1735 unsigned int pos;
1736 const WCHAR *curr;
1738 /* major.minor */
1739 ver[0] = ver[1] = pos = 0;
1740 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1742 if (*curr >= '0' && *curr <= '9')
1744 ver[pos] = ver[pos] * 10 + *curr - '0';
1745 if (ver[pos] >= 0x10000) goto error;
1747 else if (*curr == '.')
1749 if (++pos >= 2) goto error;
1751 else goto error;
1753 entity->u.typelib.major = ver[0];
1754 entity->u.typelib.minor = ver[1];
1755 return TRUE;
1757 error:
1758 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1759 return FALSE;
1762 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1764 xmlstr_t attr_name, attr_value;
1765 BOOL end = FALSE, error;
1766 struct entity* entity;
1768 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1769 return FALSE;
1771 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1773 if (xmlstr_cmp(&attr_name, tlbidW))
1775 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1777 else if (xmlstr_cmp(&attr_name, versionW))
1779 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1781 else if (xmlstr_cmp(&attr_name, helpdirW))
1783 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1785 else if (xmlstr_cmp(&attr_name, flagsW))
1787 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1789 else
1791 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1795 if (error) return FALSE;
1797 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1799 if (end) return TRUE;
1801 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1804 static inline int aligned_string_len(int len)
1806 return (len + 3) & ~3;
1809 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1811 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1812 struct assembly_version *ver = &assembly->id.version;
1813 WCHAR buff[25];
1815 if (!ret) ret = buff;
1816 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1819 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1821 xmlstr_t elem, content, attr_name, attr_value;
1822 BOOL end = FALSE, ret = TRUE, error;
1823 struct entity* entity;
1825 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1826 return FALSE;
1828 entity->u.class.versioned = TRUE;
1829 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1831 if (xmlstr_cmp(&attr_name, versionedW))
1833 if (xmlstr_cmpi(&attr_value, noW))
1834 entity->u.class.versioned = FALSE;
1835 else if (!xmlstr_cmpi(&attr_value, yesW))
1836 return FALSE;
1838 else
1840 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1844 if (error || end) return end;
1846 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1848 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1850 acl->actctx->sections |= WINDOWCLASS_SECTION;
1852 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1854 if (xmlstr_cmp_end(&elem, windowClassW))
1856 ret = parse_end_element(xmlbuf);
1857 break;
1859 else
1861 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1862 ret = parse_unknown_elem(xmlbuf, &elem);
1866 return ret;
1869 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1871 xmlstr_t attr_name, attr_value;
1872 BOOL end = FALSE, error;
1874 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1876 if (xmlstr_cmp(&attr_name, oldVersionW))
1878 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1880 else if (xmlstr_cmp(&attr_name, newVersionW))
1882 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1884 else
1886 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1890 if (error || end) return end;
1891 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1894 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1896 xmlstr_t elem, content, attr_name, attr_value;
1897 BOOL end = FALSE, ret = TRUE, error = FALSE;
1899 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1900 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1902 if (error) return FALSE;
1903 if (end) return TRUE;
1905 if (!parse_text_content(xmlbuf, &content))
1906 return FALSE;
1908 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1910 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1912 if (xmlstr_cmp_end(&elem, descriptionW))
1914 ret = parse_end_element(xmlbuf);
1915 break;
1917 else
1919 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1920 ret = parse_unknown_elem(xmlbuf, &elem);
1924 return ret;
1927 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1928 struct assembly* assembly,
1929 struct actctx_loader* acl)
1931 xmlstr_t attr_name, attr_value;
1932 BOOL end = FALSE, error;
1933 struct entity* entity;
1935 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1936 if (!entity) return FALSE;
1938 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1940 if (xmlstr_cmp(&attr_name, iidW))
1942 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1944 else if (xmlstr_cmp(&attr_name, nameW))
1946 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1948 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1950 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1951 entity->u.ifaceps.mask |= BaseIface;
1953 else if (xmlstr_cmp(&attr_name, nummethodsW))
1955 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1956 entity->u.ifaceps.mask |= NumMethods;
1958 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1960 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1962 else if (xmlstr_cmp(&attr_name, tlbidW))
1964 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1966 else
1968 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1972 if (error) return FALSE;
1973 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1974 if (end) return TRUE;
1976 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1979 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1981 xmlstr_t attr_name, attr_value, elem;
1982 BOOL end = FALSE, error, ret = TRUE;
1983 struct entity* entity;
1985 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1986 if (!entity) return FALSE;
1988 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1990 if (xmlstr_cmp(&attr_name, nameW))
1992 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1994 else if (xmlstr_cmp(&attr_name, clsidW))
1996 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1998 else if (xmlstr_cmp(&attr_name, progidW))
2000 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
2002 else if (xmlstr_cmp(&attr_name, tlbidW))
2004 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
2006 else if (xmlstr_cmp(&attr_name, threadingmodelW))
2008 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
2010 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2012 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
2014 else
2016 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2020 if (error) return FALSE;
2021 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2022 if (entity->u.comclass.progid)
2023 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2024 if (end) return TRUE;
2026 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2028 if (xmlstr_cmp_end(&elem, clrClassW))
2030 ret = parse_end_element(xmlbuf);
2031 break;
2033 else if (xmlstr_cmp(&elem, progidW))
2035 ret = parse_com_class_progid(xmlbuf, entity);
2037 else
2039 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2040 ret = parse_unknown_elem(xmlbuf, &elem);
2044 if (entity->u.comclass.progids.num)
2045 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2047 return ret;
2050 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2052 xmlstr_t attr_name, attr_value;
2053 BOOL end = FALSE, error;
2054 struct entity* entity;
2056 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2057 if (!entity) return FALSE;
2059 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2061 if (xmlstr_cmp(&attr_name, nameW))
2063 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2065 else if (xmlstr_cmp(&attr_name, clsidW))
2067 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2069 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2071 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2073 else
2075 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2079 if (error) return FALSE;
2080 acl->actctx->sections |= CLRSURROGATES_SECTION;
2081 if (end) return TRUE;
2083 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2086 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2088 struct assembly_identity ai;
2089 xmlstr_t elem, attr_name, attr_value;
2090 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2092 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2094 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2095 static const WCHAR trueW[] = {'t','r','u','e',0};
2097 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2098 delayed = xmlstr_cmp(&attr_value, trueW);
2099 else
2100 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2103 if (error || end) return end;
2105 memset(&ai, 0, sizeof(ai));
2106 ai.optional = optional;
2107 ai.delayed = delayed;
2109 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2110 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2111 return FALSE;
2113 TRACE( "adding name=%s version=%s arch=%s\n",
2114 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2116 /* store the newly found identity for later loading */
2117 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2119 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2121 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2123 ret = parse_end_element(xmlbuf);
2124 break;
2126 else if (xmlstr_cmp(&elem, bindingRedirectW))
2128 ret = parse_binding_redirect_elem(xmlbuf);
2130 else
2132 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2133 ret = parse_unknown_elem(xmlbuf, &elem);
2137 return ret;
2140 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2142 xmlstr_t attr_name, attr_value, elem;
2143 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2145 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2147 if (xmlstr_cmp(&attr_name, optionalW))
2149 optional = xmlstr_cmpi( &attr_value, yesW );
2150 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2152 else
2154 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2158 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2160 if (xmlstr_cmp_end(&elem, dependencyW))
2162 ret = parse_end_element(xmlbuf);
2163 break;
2165 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2167 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2169 else
2171 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2172 ret = parse_unknown_elem(xmlbuf, &elem);
2176 return ret;
2179 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2181 BOOL end = FALSE;
2183 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2184 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2187 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2189 BOOL end = FALSE;
2191 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2192 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2195 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2197 xmlstr_t attr_name, attr_value, elem;
2198 BOOL end = FALSE, error, ret = TRUE;
2199 struct dll_redirect* dll;
2201 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2203 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2205 if (xmlstr_cmp(&attr_name, nameW))
2207 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2208 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2210 else if (xmlstr_cmp(&attr_name, hashW))
2212 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2214 else if (xmlstr_cmp(&attr_name, hashalgW))
2216 static const WCHAR sha1W[] = {'S','H','A','1',0};
2217 if (!xmlstr_cmpi(&attr_value, sha1W))
2218 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2220 else
2222 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2226 if (error || !dll->name) return FALSE;
2228 acl->actctx->sections |= DLLREDIRECT_SECTION;
2230 if (end) return TRUE;
2232 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2234 if (xmlstr_cmp_end(&elem, fileW))
2236 ret = parse_end_element(xmlbuf);
2237 break;
2239 else if (xmlstr_cmp(&elem, comClassW))
2241 ret = parse_com_class_elem(xmlbuf, dll, acl);
2243 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2245 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2247 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2249 WARN("asmv2:hash (undocumented) not supported\n");
2250 ret = parse_unknown_elem(xmlbuf, &elem);
2252 else if (xmlstr_cmp(&elem, typelibW))
2254 ret = parse_typelib_elem(xmlbuf, dll, acl);
2256 else if (xmlstr_cmp(&elem, windowClassW))
2258 ret = parse_window_class_elem(xmlbuf, dll, acl);
2260 else
2262 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2263 ret = parse_unknown_elem( xmlbuf, &elem );
2267 return ret;
2270 static BOOL parse_supportedos_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2272 xmlstr_t attr_name, attr_value;
2273 BOOL end = FALSE, error;
2275 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2277 if (xmlstr_cmp(&attr_name, IdW))
2279 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2280 UNICODE_STRING str;
2281 GUID compat_id;
2283 str.Buffer = (PWSTR)attr_value.ptr;
2284 str.Length = str.MaximumLength = (USHORT)attr_value.len * sizeof(WCHAR);
2285 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2287 if (!(compat = add_compat_context(assembly))) return FALSE;
2288 compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2289 compat->Id = compat_id;
2291 else
2293 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value));
2296 else
2298 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
2299 debugstr_xmlstr(&attr_value));
2303 if (error) return FALSE;
2304 if (end) return TRUE;
2306 return parse_expect_end_elem(xmlbuf, supportedOSW, asmv1W);
2309 static BOOL parse_compatibility_application_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2310 struct actctx_loader* acl)
2312 BOOL ret = TRUE;
2313 xmlstr_t elem;
2315 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2317 if (xmlstr_cmp_end(&elem, applicationW))
2319 ret = parse_end_element(xmlbuf);
2320 break;
2322 else if (xmlstr_cmp(&elem, supportedOSW))
2324 ret = parse_supportedos_elem(xmlbuf, assembly, acl);
2326 else
2328 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2329 ret = parse_unknown_elem(xmlbuf, &elem);
2333 return ret;
2336 static BOOL parse_compatibility_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2337 struct actctx_loader* acl)
2339 xmlstr_t elem;
2340 BOOL ret = TRUE;
2342 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2344 if (xmlstr_cmp_end(&elem, compatibilityW))
2346 ret = parse_end_element(xmlbuf);
2347 break;
2349 else if (xmlstr_cmp(&elem, applicationW))
2351 ret = parse_compatibility_application_elem(xmlbuf, assembly, acl);
2353 else
2355 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2356 ret = parse_unknown_elem(xmlbuf, &elem);
2359 return ret;
2362 static BOOL parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl,
2363 xmlstr_t *parent )
2365 xmlstr_t elem, content, attr_name, attr_value;
2366 BOOL end = FALSE, ret = TRUE, error = FALSE;
2367 struct entity *entity;
2369 while (next_xml_attr( xmlbuf, &attr_name, &attr_value, &error, &end ))
2371 if (xmlstr_cmp( &attr_name, xmlnsW )) continue;
2372 WARN( "unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value) );
2375 if (error) return FALSE;
2376 if (end) return TRUE;
2378 if (!parse_text_content( xmlbuf, &content )) return FALSE;
2379 TRACE( "got %s %s\n", debugstr_xmlstr(parent), debugstr_xmlstr(&content) );
2381 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS );
2382 if (!entity) return FALSE;
2383 entity->u.settings.name = xmlstrdupW( parent );
2384 entity->u.settings.value = xmlstrdupW( &content );
2386 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2388 if (xmlstr_cmp_end( &elem, entity->u.settings.name ))
2390 ret = parse_end_element( xmlbuf );
2391 break;
2393 else
2395 WARN( "unknown elem %s\n", debugstr_xmlstr(&elem) );
2396 ret = parse_unknown_elem( xmlbuf, &elem );
2399 return ret;
2402 static BOOL parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly,
2403 struct actctx_loader *acl )
2405 xmlstr_t elem;
2406 BOOL ret = TRUE;
2408 while (ret && (ret = next_xml_elem( xmlbuf, &elem )))
2410 if (xmlstr_cmp_end( &elem, windowsSettingsW ))
2412 ret = parse_end_element( xmlbuf );
2413 break;
2415 else if (xmlstr_cmp( &elem, autoElevateW ) ||
2416 xmlstr_cmp( &elem, disableThemingW ) ||
2417 xmlstr_cmp( &elem, disableWindowFilteringW ) ||
2418 xmlstr_cmp( &elem, dpiAwareW ) ||
2419 xmlstr_cmp( &elem, dpiAwarenessW ) ||
2420 xmlstr_cmp( &elem, gdiScalingW ) ||
2421 xmlstr_cmp( &elem, highResolutionScrollingAwareW ) ||
2422 xmlstr_cmp( &elem, longPathAwareW ) ||
2423 xmlstr_cmp( &elem, magicFutureSettingW ) ||
2424 xmlstr_cmp( &elem, printerDriverIsolationW ) ||
2425 xmlstr_cmp( &elem, ultraHighResolutionScrollingAwareW ))
2427 ret = parse_settings_elem( xmlbuf, assembly, acl, &elem );
2429 else
2431 WARN( "unknown elem %s\n", debugstr_xmlstr(&elem) );
2432 ret = parse_unknown_elem( xmlbuf, &elem );
2435 return ret;
2438 static BOOL parse_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2440 xmlstr_t elem;
2441 BOOL ret = TRUE;
2443 while (ret && (ret = next_xml_elem( xmlbuf, &elem )))
2445 if (xmlstr_cmp_end( &elem, applicationW ))
2447 ret = parse_end_element( xmlbuf );
2448 break;
2450 else if (xmlstr_cmp( &elem, windowsSettingsW ))
2452 ret = parse_windows_settings_elem( xmlbuf, assembly, acl );
2454 else
2456 WARN( "unknown elem %s\n", debugstr_xmlstr(&elem) );
2457 ret = parse_unknown_elem( xmlbuf, &elem );
2460 return ret;
2463 static BOOL parse_requested_execution_level_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2465 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2466 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2467 static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0};
2468 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2469 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2470 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2471 static const WCHAR trueW[] = {'t','r','u','e',0};
2473 xmlstr_t attr_name, attr_value, elem;
2474 BOOL end = FALSE, ret = TRUE, error;
2476 /* Multiple requestedExecutionLevel elements are not supported. */
2477 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED)
2478 return FALSE;
2480 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2482 if (xmlstr_cmp(&attr_name, levelW))
2484 if (xmlstr_cmpi(&attr_value, asInvokerW))
2485 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2486 else if (xmlstr_cmpi(&attr_value, highestAvailableW))
2487 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2488 else if (xmlstr_cmpi(&attr_value, requireAdministratorW))
2489 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2490 else
2491 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr_value));
2493 else if (xmlstr_cmp(&attr_name, uiAccessW))
2495 if (xmlstr_cmpi(&attr_value, falseW))
2496 assembly->ui_access = FALSE;
2497 else if (xmlstr_cmpi(&attr_value, trueW))
2498 assembly->ui_access = TRUE;
2499 else
2500 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr_value));
2502 else
2503 FIXME("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2506 if (error) return FALSE;
2507 if (end) return TRUE;
2509 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2511 if (xml_elem_cmp_end(&elem, requestedExecutionLevelW, asmv2W))
2513 ret = parse_end_element(xmlbuf);
2514 break;
2516 else
2518 FIXME("unknown element %s\n", debugstr_xmlstr(&elem));
2519 ret = parse_unknown_elem(xmlbuf, &elem);
2523 return ret;
2526 static BOOL parse_requested_privileges_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2528 xmlstr_t elem;
2529 BOOL ret = TRUE;
2531 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2533 if (xml_elem_cmp_end(&elem, requestedPrivilegesW, asmv2W))
2535 ret = parse_end_element(xmlbuf);
2536 break;
2538 else if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv2W))
2539 ret = parse_requested_execution_level_elem(xmlbuf, assembly, acl);
2540 else
2542 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2543 ret = parse_unknown_elem(xmlbuf, &elem);
2547 return ret;
2550 static BOOL parse_security_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2552 xmlstr_t elem;
2553 BOOL ret = TRUE;
2555 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2557 if (xml_elem_cmp_end(&elem, securityW, asmv2W))
2559 ret = parse_end_element(xmlbuf);
2560 break;
2562 else if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv2W))
2563 ret = parse_requested_privileges_elem(xmlbuf, assembly, acl);
2564 else
2566 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2567 ret = parse_unknown_elem(xmlbuf, &elem);
2571 return ret;
2574 static BOOL parse_trust_info_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2576 xmlstr_t elem;
2577 BOOL ret = TRUE;
2579 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2581 if (xml_elem_cmp_end(&elem, trustInfoW, asmv2W))
2583 ret = parse_end_element(xmlbuf);
2584 break;
2586 else if (xml_elem_cmp(&elem, securityW, asmv2W))
2587 ret = parse_security_elem(xmlbuf, assembly, acl);
2588 else
2590 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2591 ret = parse_unknown_elem(xmlbuf, &elem);
2595 return ret;
2598 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2599 struct assembly* assembly,
2600 struct assembly_identity* expected_ai)
2602 xmlstr_t attr_name, attr_value, elem;
2603 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2605 TRACE("(%p)\n", xmlbuf);
2607 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2609 if (xmlstr_cmp(&attr_name, manifestVersionW))
2611 static const WCHAR v10W[] = {'1','.','0',0};
2612 if (!xmlstr_cmp(&attr_value, v10W))
2614 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2615 return FALSE;
2617 version = TRUE;
2619 else if (xmlstr_cmp(&attr_name, xmlnsW))
2621 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2622 !xmlstr_cmp(&attr_value, manifestv2W) &&
2623 !xmlstr_cmp(&attr_value, manifestv3W))
2625 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2626 return FALSE;
2628 xmlns = TRUE;
2630 else
2632 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2636 if (error || end || !xmlns || !version) return FALSE;
2637 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2639 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2641 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2642 return FALSE;
2643 assembly->no_inherit = TRUE;
2646 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2648 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2649 return FALSE;
2651 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2652 assembly->no_inherit)
2653 return FALSE;
2655 while (ret)
2657 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2659 ret = parse_end_element(xmlbuf);
2660 break;
2662 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2664 ret = parse_description_elem(xmlbuf);
2666 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2668 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2670 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2672 ret = parse_dependency_elem(xmlbuf, acl);
2674 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2676 ret = parse_file_elem(xmlbuf, assembly, acl);
2678 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2680 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2682 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2684 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2686 else if (xml_elem_cmp(&elem, trustInfoW, asmv2W) ||
2687 xml_elem_cmp(&elem, trustInfoW, asmv1W))
2689 ret = parse_trust_info_elem(xmlbuf, assembly, acl);
2691 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2693 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2695 if (expected_ai)
2697 /* FIXME: more tests */
2698 if (assembly->type == ASSEMBLY_MANIFEST &&
2699 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2701 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2702 expected_ai->version.major, expected_ai->version.minor,
2703 expected_ai->version.build, expected_ai->version.revision,
2704 assembly->id.version.major, assembly->id.version.minor,
2705 assembly->id.version.build, assembly->id.version.revision);
2706 ret = FALSE;
2708 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2709 (assembly->id.version.major != expected_ai->version.major ||
2710 assembly->id.version.minor != expected_ai->version.minor ||
2711 assembly->id.version.build < expected_ai->version.build ||
2712 (assembly->id.version.build == expected_ai->version.build &&
2713 assembly->id.version.revision < expected_ai->version.revision)))
2715 FIXME("wrong version for shared assembly manifest\n");
2716 ret = FALSE;
2720 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2722 ret = parse_compatibility_elem(xmlbuf, assembly, acl);
2724 else if (xml_elem_cmp(&elem, applicationW, asmv3W))
2726 ret = parse_application_elem(xmlbuf, assembly, acl);
2728 else
2730 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2731 ret = parse_unknown_elem(xmlbuf, &elem);
2733 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2736 return ret;
2739 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2740 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2742 xmlstr_t elem;
2744 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2746 if (xmlstr_cmp(&elem, xmlW) &&
2747 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2748 return STATUS_SXS_CANT_GEN_ACTCTX;
2750 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2752 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2753 return STATUS_SXS_CANT_GEN_ACTCTX;
2756 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2758 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2759 return STATUS_SXS_CANT_GEN_ACTCTX;
2762 if (next_xml_elem(xmlbuf, &elem))
2764 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2765 return STATUS_SXS_CANT_GEN_ACTCTX;
2768 if (xmlbuf->ptr != xmlbuf->end)
2770 FIXME("parse error\n");
2771 return STATUS_SXS_CANT_GEN_ACTCTX;
2773 return STATUS_SUCCESS;
2776 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2777 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2778 const void *buffer, SIZE_T size )
2780 xmlbuf_t xmlbuf;
2781 NTSTATUS status;
2782 struct assembly *assembly;
2783 int unicode_tests;
2785 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2787 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2788 return STATUS_SXS_CANT_GEN_ACTCTX;
2790 if (directory && !(assembly->directory = strdupW(directory)))
2791 return STATUS_NO_MEMORY;
2793 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2794 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2795 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2797 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2798 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2800 xmlbuf.ptr = buffer;
2801 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2802 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2804 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2806 const WCHAR *buf = buffer;
2807 WCHAR *new_buff;
2808 unsigned int i;
2810 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2811 return STATUS_NO_MEMORY;
2812 for (i = 0; i < size / sizeof(WCHAR); i++)
2813 new_buff[i] = RtlUshortByteSwap( buf[i] );
2814 xmlbuf.ptr = new_buff;
2815 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2816 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2817 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2819 else
2821 /* let's assume utf-8 for now */
2822 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2823 WCHAR *new_buff;
2825 if (len == -1)
2827 FIXME( "utf-8 conversion failed\n" );
2828 return STATUS_SXS_CANT_GEN_ACTCTX;
2830 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2831 return STATUS_NO_MEMORY;
2832 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2833 xmlbuf.ptr = new_buff;
2834 xmlbuf.end = xmlbuf.ptr + len;
2835 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2836 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2838 return status;
2841 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2843 OBJECT_ATTRIBUTES attr;
2844 IO_STATUS_BLOCK io;
2846 attr.Length = sizeof(attr);
2847 attr.RootDirectory = 0;
2848 attr.Attributes = OBJ_CASE_INSENSITIVE;
2849 attr.ObjectName = name;
2850 attr.SecurityDescriptor = NULL;
2851 attr.SecurityQualityOfService = NULL;
2852 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2855 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2857 NTSTATUS status;
2858 ULONG_PTR magic;
2859 LDR_MODULE *pldr;
2861 LdrLockLoaderLock(0, NULL, &magic);
2862 status = LdrFindEntryForAddress( module, &pldr );
2863 if (status == STATUS_SUCCESS)
2865 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2866 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2868 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2869 str->Length = pldr->FullDllName.Length;
2870 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2872 else status = STATUS_NO_MEMORY;
2874 LdrUnlockLoaderLock(0, magic);
2875 return status;
2878 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2879 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2880 HANDLE hModule, LPCWSTR resname, ULONG lang )
2882 NTSTATUS status;
2883 UNICODE_STRING nameW;
2884 LDR_RESOURCE_INFO info;
2885 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2886 void *ptr;
2888 if (TRACE_ON(actctx))
2890 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2892 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2893 hModule, debugstr_w(nameW.Buffer) );
2894 RtlFreeUnicodeString( &nameW );
2896 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2897 hModule, debugstr_w(filename) );
2900 if (!resname) return STATUS_INVALID_PARAMETER;
2902 info.Type = RT_MANIFEST;
2903 info.Language = lang;
2904 if (!((ULONG_PTR)resname >> 16))
2906 info.Name = (ULONG_PTR)resname;
2907 status = LdrFindResource_U(hModule, &info, 3, &entry);
2909 else if (resname[0] == '#')
2911 ULONG value;
2912 RtlInitUnicodeString(&nameW, resname + 1);
2913 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2914 return STATUS_INVALID_PARAMETER;
2915 info.Name = value;
2916 status = LdrFindResource_U(hModule, &info, 3, &entry);
2918 else
2920 RtlCreateUnicodeString(&nameW, resname);
2921 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2922 info.Name = (ULONG_PTR)nameW.Buffer;
2923 status = LdrFindResource_U(hModule, &info, 3, &entry);
2924 RtlFreeUnicodeString(&nameW);
2926 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2928 if (status == STATUS_SUCCESS)
2929 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2931 return status;
2934 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2935 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2936 HANDLE file, LPCWSTR resname, ULONG lang )
2938 HANDLE mapping;
2939 OBJECT_ATTRIBUTES attr;
2940 LARGE_INTEGER size;
2941 LARGE_INTEGER offset;
2942 NTSTATUS status;
2943 SIZE_T count;
2944 void *base;
2946 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2948 attr.Length = sizeof(attr);
2949 attr.RootDirectory = 0;
2950 attr.ObjectName = NULL;
2951 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2952 attr.SecurityDescriptor = NULL;
2953 attr.SecurityQualityOfService = NULL;
2955 size.QuadPart = 0;
2956 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2957 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2958 if (status != STATUS_SUCCESS) return status;
2960 offset.QuadPart = 0;
2961 count = 0;
2962 base = NULL;
2963 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2964 &count, ViewShare, 0, PAGE_READONLY );
2965 NtClose( mapping );
2966 if (status != STATUS_SUCCESS) return status;
2968 if (RtlImageNtHeader(base)) /* we got a PE file */
2970 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2971 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2973 else status = STATUS_INVALID_IMAGE_FORMAT;
2975 NtUnmapViewOfSection( GetCurrentProcess(), base );
2976 return status;
2979 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2980 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2982 FILE_END_OF_FILE_INFORMATION info;
2983 IO_STATUS_BLOCK io;
2984 HANDLE mapping;
2985 OBJECT_ATTRIBUTES attr;
2986 LARGE_INTEGER size;
2987 LARGE_INTEGER offset;
2988 NTSTATUS status;
2989 SIZE_T count;
2990 void *base;
2992 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2994 attr.Length = sizeof(attr);
2995 attr.RootDirectory = 0;
2996 attr.ObjectName = NULL;
2997 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2998 attr.SecurityDescriptor = NULL;
2999 attr.SecurityQualityOfService = NULL;
3001 size.QuadPart = 0;
3002 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
3003 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
3004 if (status != STATUS_SUCCESS) return status;
3006 offset.QuadPart = 0;
3007 count = 0;
3008 base = NULL;
3009 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
3010 &count, ViewShare, 0, PAGE_READONLY );
3011 NtClose( mapping );
3012 if (status != STATUS_SUCCESS) return status;
3014 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
3015 if (status == STATUS_SUCCESS)
3016 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
3018 NtUnmapViewOfSection( GetCurrentProcess(), base );
3019 return status;
3022 /* try to load the .manifest file associated to the file */
3023 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
3024 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
3026 static const WCHAR fmtW[] = { '.','%','l','u',0 };
3027 WCHAR *buffer;
3028 NTSTATUS status;
3029 UNICODE_STRING nameW;
3030 HANDLE file;
3031 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
3033 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
3035 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
3037 if (module) /* use the module filename */
3039 UNICODE_STRING name;
3041 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
3043 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
3044 strcatW( name.Buffer, dotManifestW );
3045 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
3046 status = STATUS_RESOURCE_DATA_NOT_FOUND;
3047 RtlFreeUnicodeString( &name );
3049 if (status) return status;
3051 else
3053 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3054 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3055 return STATUS_NO_MEMORY;
3056 strcpyW( buffer, filename );
3057 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
3058 strcatW( buffer, dotManifestW );
3059 RtlInitUnicodeString( &nameW, buffer );
3062 if (!open_nt_file( &file, &nameW ))
3064 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3065 NtClose( file );
3067 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
3068 RtlFreeUnicodeString( &nameW );
3069 return status;
3072 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
3074 static const WCHAR lookup_fmtW[] =
3075 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
3076 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
3077 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
3079 WCHAR *lookup, *ret = NULL;
3080 UNICODE_STRING lookup_us;
3081 IO_STATUS_BLOCK io;
3082 const WCHAR *lang = ai->language;
3083 unsigned int data_pos = 0, data_len;
3084 char buffer[8192];
3086 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
3087 (strlenW(ai->arch) + strlenW(ai->name)
3088 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
3089 + sizeof(lookup_fmtW) )))
3090 return NULL;
3092 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
3093 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
3094 ai->version.major, ai->version.minor, lang );
3095 RtlInitUnicodeString( &lookup_us, lookup );
3097 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3098 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
3100 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
3101 FILE_BOTH_DIR_INFORMATION *dir_info;
3102 WCHAR *tmp;
3103 ULONG build, revision;
3105 data_len = io.Information;
3107 for (;;)
3109 if (data_pos >= data_len)
3111 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
3112 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
3113 break;
3114 data_len = io.Information;
3115 data_pos = 0;
3117 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
3119 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
3120 else data_pos = data_len;
3122 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
3123 build = atoiW(tmp);
3124 if (build < min_build) continue;
3125 tmp = strchrW(tmp, '.') + 1;
3126 revision = atoiW(tmp);
3127 if (build == min_build && revision < min_revision) continue;
3128 tmp = strchrW(tmp, '_') + 1;
3129 tmp = strchrW(tmp, '_') + 1;
3130 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3131 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3133 /* prefer a non-Wine manifest if we already have one */
3134 /* we'll still load the builtin dll if specified through DllOverrides */
3135 if (ret) continue;
3137 else
3139 min_build = build;
3140 min_revision = revision;
3142 ai->version.build = build;
3143 ai->version.revision = revision;
3144 RtlFreeHeap( GetProcessHeap(), 0, ret );
3145 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3147 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3148 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3152 else WARN("no matching file for %s\n", debugstr_w(lookup));
3153 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3154 return ret;
3157 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3159 struct assembly_identity sxs_ai;
3160 UNICODE_STRING path_us;
3161 OBJECT_ATTRIBUTES attr;
3162 IO_STATUS_BLOCK io;
3163 WCHAR *path, *file = NULL;
3164 HANDLE handle;
3166 static const WCHAR manifest_dirW[] =
3167 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3169 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3171 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3172 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3173 return STATUS_NO_MEMORY;
3175 strcpyW( path, user_shared_data->NtSystemRoot );
3176 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3178 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3180 RtlFreeHeap( GetProcessHeap(), 0, path );
3181 return STATUS_NO_SUCH_FILE;
3183 RtlFreeHeap( GetProcessHeap(), 0, path );
3185 attr.Length = sizeof(attr);
3186 attr.RootDirectory = 0;
3187 attr.Attributes = OBJ_CASE_INSENSITIVE;
3188 attr.ObjectName = &path_us;
3189 attr.SecurityDescriptor = NULL;
3190 attr.SecurityQualityOfService = NULL;
3192 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3193 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3195 sxs_ai = *ai;
3196 file = lookup_manifest_file( handle, &sxs_ai );
3197 NtClose( handle );
3199 if (!file)
3201 RtlFreeUnicodeString( &path_us );
3202 return STATUS_NO_SUCH_FILE;
3205 /* append file name to directory path */
3206 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3207 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3209 RtlFreeHeap( GetProcessHeap(), 0, file );
3210 RtlFreeUnicodeString( &path_us );
3211 return STATUS_NO_MEMORY;
3214 path[path_us.Length/sizeof(WCHAR)] = '\\';
3215 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3216 RtlInitUnicodeString( &path_us, path );
3217 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3219 if (!open_nt_file( &handle, &path_us ))
3221 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3222 NtClose( handle );
3224 else io.u.Status = STATUS_NO_SUCH_FILE;
3226 RtlFreeHeap( GetProcessHeap(), 0, file );
3227 RtlFreeUnicodeString( &path_us );
3228 return io.u.Status;
3231 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3232 struct assembly_identity* ai)
3234 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3235 unsigned int i;
3236 WCHAR *buffer, *p, *directory;
3237 NTSTATUS status;
3238 UNICODE_STRING nameW;
3239 HANDLE file;
3240 DWORD len;
3242 TRACE( "looking for name=%s version=%s arch=%s\n",
3243 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3245 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3247 /* FIXME: add support for language specific lookup */
3249 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3250 strlenW(acl->actctx->appdir.info));
3252 nameW.Buffer = NULL;
3253 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3254 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3255 return STATUS_NO_MEMORY;
3257 if (!(directory = build_assembly_dir( ai )))
3259 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3260 return STATUS_NO_MEMORY;
3263 /* Lookup in <dir>\name.dll
3264 * <dir>\name.manifest
3265 * <dir>\name\name.dll
3266 * <dir>\name\name.manifest
3268 * First 'appdir' is used as <dir>, if that failed
3269 * it tries application manifest file path.
3271 strcpyW( buffer, acl->actctx->appdir.info );
3272 p = buffer + strlenW(buffer);
3273 for (i = 0; i < 4; i++)
3275 if (i == 2)
3277 struct assembly *assembly = acl->actctx->assemblies;
3278 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3280 else *p++ = '\\';
3282 strcpyW( p, ai->name );
3283 p += strlenW(p);
3285 strcpyW( p, dotDllW );
3286 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3288 status = open_nt_file( &file, &nameW );
3289 if (!status)
3291 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3292 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3293 NtClose( file );
3294 break;
3296 RtlFreeUnicodeString( &nameW );
3299 strcpyW( p, dotManifestW );
3300 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3302 status = open_nt_file( &file, &nameW );
3303 if (!status)
3305 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3306 NtClose( file );
3307 break;
3309 RtlFreeUnicodeString( &nameW );
3311 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3313 RtlFreeUnicodeString( &nameW );
3314 RtlFreeHeap( GetProcessHeap(), 0, directory );
3315 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3316 return status;
3319 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3321 NTSTATUS status = STATUS_SUCCESS;
3322 unsigned int i;
3324 for (i = 0; i < acl->num_dependencies; i++)
3326 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3328 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3330 FIXME( "Could not find dependent assembly %s (%s)\n",
3331 debugstr_w(acl->dependencies[i].name),
3332 debugstr_version(&acl->dependencies[i].version) );
3333 status = STATUS_SXS_CANT_GEN_ACTCTX;
3334 break;
3338 /* FIXME should now iterate through all refs */
3339 return status;
3342 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3343 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3345 NTSTATUS status = STATUS_SUCCESS;
3347 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3349 if (*handle) return STATUS_INVALID_PARAMETER;
3351 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3352 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3354 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3356 ULONG_PTR magic;
3357 LDR_MODULE *pldr;
3359 if (!*handle) return STATUS_INVALID_PARAMETER;
3361 LdrLockLoaderLock( 0, NULL, &magic );
3362 if (!LdrFindEntryForAddress( *handle, &pldr ))
3364 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3365 status = STATUS_DLL_NOT_FOUND;
3366 else
3367 *handle = pldr->ActivationContext;
3369 else status = STATUS_DLL_NOT_FOUND;
3370 LdrUnlockLoaderLock( 0, magic );
3372 else if (!*handle && (class != ActivationContextBasicInformation))
3373 *handle = process_actctx;
3375 return status;
3378 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3380 unsigned int i, j, total_len = 0, dll_count = 0;
3381 struct strsection_header *header;
3382 struct dllredirect_data *data;
3383 struct string_index *index;
3384 ULONG name_offset;
3386 /* compute section length */
3387 for (i = 0; i < actctx->num_assemblies; i++)
3389 struct assembly *assembly = &actctx->assemblies[i];
3390 for (j = 0; j < assembly->num_dlls; j++)
3392 struct dll_redirect *dll = &assembly->dlls[j];
3394 /* each entry needs index, data and string data */
3395 total_len += sizeof(*index);
3396 total_len += sizeof(*data);
3397 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3400 dll_count += assembly->num_dlls;
3403 total_len += sizeof(*header);
3405 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3406 if (!header) return STATUS_NO_MEMORY;
3408 memset(header, 0, sizeof(*header));
3409 header->magic = STRSECTION_MAGIC;
3410 header->size = sizeof(*header);
3411 header->count = dll_count;
3412 header->index_offset = sizeof(*header);
3413 index = (struct string_index*)((BYTE*)header + header->index_offset);
3414 name_offset = header->index_offset + header->count*sizeof(*index);
3416 for (i = 0; i < actctx->num_assemblies; i++)
3418 struct assembly *assembly = &actctx->assemblies[i];
3419 for (j = 0; j < assembly->num_dlls; j++)
3421 struct dll_redirect *dll = &assembly->dlls[j];
3422 UNICODE_STRING str;
3423 WCHAR *ptrW;
3425 /* setup new index entry */
3426 str.Buffer = dll->name;
3427 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3428 str.MaximumLength = str.Length + sizeof(WCHAR);
3429 /* hash original class name */
3430 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3432 index->name_offset = name_offset;
3433 index->name_len = str.Length;
3434 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3435 index->data_len = sizeof(*data);
3436 index->rosterindex = i + 1;
3438 /* setup data */
3439 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3440 data->size = sizeof(*data);
3441 data->unk = 2; /* FIXME: seems to be constant */
3442 memset(data->res, 0, sizeof(data->res));
3444 /* dll name */
3445 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3446 memcpy(ptrW, dll->name, index->name_len);
3447 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3449 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3451 index++;
3455 *section = header;
3457 return STATUS_SUCCESS;
3460 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3462 struct string_index *iter, *index = NULL;
3463 ULONG hash = 0, i;
3465 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3466 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3468 for (i = 0; i < section->count; i++)
3470 if (iter->hash == hash)
3472 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3474 if (!strcmpiW(nameW, name->Buffer))
3476 index = iter;
3477 break;
3479 else
3480 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3482 iter++;
3485 return index;
3488 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3490 struct guid_index *iter, *index = NULL;
3491 ULONG i;
3493 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3495 for (i = 0; i < section->count; i++)
3497 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3499 index = iter;
3500 break;
3502 iter++;
3505 return index;
3508 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3510 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3513 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3514 PACTCTX_SECTION_KEYED_DATA data)
3516 struct dllredirect_data *dll;
3517 struct string_index *index;
3519 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3521 if (!actctx->dllredirect_section)
3523 struct strsection_header *section;
3525 NTSTATUS status = build_dllredirect_section(actctx, &section);
3526 if (status) return status;
3528 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3529 RtlFreeHeap(GetProcessHeap(), 0, section);
3532 index = find_string_index(actctx->dllredirect_section, name);
3533 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3535 if (data)
3537 dll = get_dllredirect_data(actctx, index);
3539 data->ulDataFormatVersion = 1;
3540 data->lpData = dll;
3541 data->ulLength = dll->size;
3542 data->lpSectionGlobalData = NULL;
3543 data->ulSectionGlobalDataLength = 0;
3544 data->lpSectionBase = actctx->dllredirect_section;
3545 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3546 data->hActCtx = NULL;
3548 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3549 data->ulAssemblyRosterIndex = index->rosterindex;
3552 return STATUS_SUCCESS;
3555 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3557 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3560 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3562 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3565 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3567 unsigned int i, j, k, total_len = 0, class_count = 0;
3568 struct wndclass_redirect_data *data;
3569 struct strsection_header *header;
3570 struct string_index *index;
3571 ULONG name_offset;
3573 /* compute section length */
3574 for (i = 0; i < actctx->num_assemblies; i++)
3576 struct assembly *assembly = &actctx->assemblies[i];
3577 for (j = 0; j < assembly->num_dlls; j++)
3579 struct dll_redirect *dll = &assembly->dlls[j];
3580 for (k = 0; k < dll->entities.num; k++)
3582 struct entity *entity = &dll->entities.base[k];
3583 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3585 int class_len = strlenW(entity->u.class.name) + 1;
3586 int len;
3588 /* each class entry needs index, data and string data */
3589 total_len += sizeof(*index);
3590 total_len += sizeof(*data);
3591 /* original name is stored separately */
3592 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3593 /* versioned name and module name are stored one after another */
3594 if (entity->u.class.versioned)
3595 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3596 else
3597 len = class_len;
3598 len += strlenW(dll->name) + 1;
3599 total_len += aligned_string_len(len*sizeof(WCHAR));
3601 class_count++;
3607 total_len += sizeof(*header);
3609 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3610 if (!header) return STATUS_NO_MEMORY;
3612 memset(header, 0, sizeof(*header));
3613 header->magic = STRSECTION_MAGIC;
3614 header->size = sizeof(*header);
3615 header->count = class_count;
3616 header->index_offset = sizeof(*header);
3617 index = (struct string_index*)((BYTE*)header + header->index_offset);
3618 name_offset = header->index_offset + header->count*sizeof(*index);
3620 for (i = 0; i < actctx->num_assemblies; i++)
3622 struct assembly *assembly = &actctx->assemblies[i];
3623 for (j = 0; j < assembly->num_dlls; j++)
3625 struct dll_redirect *dll = &assembly->dlls[j];
3626 for (k = 0; k < dll->entities.num; k++)
3628 struct entity *entity = &dll->entities.base[k];
3629 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3631 static const WCHAR exclW[] = {'!',0};
3632 ULONG versioned_len, module_len;
3633 UNICODE_STRING str;
3634 WCHAR *ptrW;
3636 /* setup new index entry */
3637 str.Buffer = entity->u.class.name;
3638 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3639 str.MaximumLength = str.Length + sizeof(WCHAR);
3640 /* hash original class name */
3641 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3643 /* include '!' separator too */
3644 if (entity->u.class.versioned)
3645 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3646 else
3647 versioned_len = str.Length;
3648 module_len = strlenW(dll->name)*sizeof(WCHAR);
3650 index->name_offset = name_offset;
3651 index->name_len = str.Length;
3652 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3653 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3654 index->rosterindex = i + 1;
3656 /* setup data */
3657 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3658 data->size = sizeof(*data);
3659 data->res = 0;
3660 data->name_len = versioned_len;
3661 data->name_offset = sizeof(*data);
3662 data->module_len = module_len;
3663 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3665 /* original class name */
3666 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3667 memcpy(ptrW, entity->u.class.name, index->name_len);
3668 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3670 /* module name */
3671 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3672 memcpy(ptrW, dll->name, data->module_len);
3673 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3675 /* versioned name */
3676 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3677 if (entity->u.class.versioned)
3679 get_assembly_version(assembly, ptrW);
3680 strcatW(ptrW, exclW);
3681 strcatW(ptrW, entity->u.class.name);
3683 else
3685 memcpy(ptrW, entity->u.class.name, index->name_len);
3686 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3689 name_offset += sizeof(*data);
3690 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3692 index++;
3698 *section = header;
3700 return STATUS_SUCCESS;
3703 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3704 PACTCTX_SECTION_KEYED_DATA data)
3706 struct string_index *iter, *index = NULL;
3707 struct wndclass_redirect_data *class;
3708 ULONG hash;
3709 int i;
3711 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3713 if (!actctx->wndclass_section)
3715 struct strsection_header *section;
3717 NTSTATUS status = build_wndclass_section(actctx, &section);
3718 if (status) return status;
3720 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3721 RtlFreeHeap(GetProcessHeap(), 0, section);
3724 hash = 0;
3725 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3726 iter = get_wndclass_first_index(actctx);
3728 for (i = 0; i < actctx->wndclass_section->count; i++)
3730 if (iter->hash == hash)
3732 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3734 if (!strcmpiW(nameW, name->Buffer))
3736 index = iter;
3737 break;
3739 else
3740 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3742 iter++;
3745 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3747 if (data)
3749 class = get_wndclass_data(actctx, index);
3751 data->ulDataFormatVersion = 1;
3752 data->lpData = class;
3753 /* full length includes string length with nulls */
3754 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3755 data->lpSectionGlobalData = NULL;
3756 data->ulSectionGlobalDataLength = 0;
3757 data->lpSectionBase = actctx->wndclass_section;
3758 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3759 data->hActCtx = NULL;
3761 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3762 data->ulAssemblyRosterIndex = index->rosterindex;
3765 return STATUS_SUCCESS;
3768 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3770 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3771 struct guidsection_header *header;
3772 ULONG module_offset, data_offset;
3773 struct tlibredirect_data *data;
3774 struct guid_index *index;
3776 /* compute section length */
3777 for (i = 0; i < actctx->num_assemblies; i++)
3779 struct assembly *assembly = &actctx->assemblies[i];
3780 for (j = 0; j < assembly->num_dlls; j++)
3782 struct dll_redirect *dll = &assembly->dlls[j];
3783 for (k = 0; k < dll->entities.num; k++)
3785 struct entity *entity = &dll->entities.base[k];
3786 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3788 /* each entry needs index, data and string data for module name and help string */
3789 total_len += sizeof(*index);
3790 total_len += sizeof(*data);
3791 /* help string is stored separately */
3792 if (*entity->u.typelib.helpdir)
3793 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3795 /* module names are packed one after another */
3796 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3798 tlib_count++;
3804 total_len += aligned_string_len(names_len);
3805 total_len += sizeof(*header);
3807 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3808 if (!header) return STATUS_NO_MEMORY;
3810 memset(header, 0, sizeof(*header));
3811 header->magic = GUIDSECTION_MAGIC;
3812 header->size = sizeof(*header);
3813 header->count = tlib_count;
3814 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3815 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3816 module_offset = sizeof(*header);
3817 data_offset = header->index_offset + tlib_count*sizeof(*index);
3819 for (i = 0; i < actctx->num_assemblies; i++)
3821 struct assembly *assembly = &actctx->assemblies[i];
3822 for (j = 0; j < assembly->num_dlls; j++)
3824 struct dll_redirect *dll = &assembly->dlls[j];
3825 for (k = 0; k < dll->entities.num; k++)
3827 struct entity *entity = &dll->entities.base[k];
3828 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3830 ULONG module_len, help_len;
3831 UNICODE_STRING str;
3832 WCHAR *ptrW;
3834 if (*entity->u.typelib.helpdir)
3835 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3836 else
3837 help_len = 0;
3839 module_len = strlenW(dll->name)*sizeof(WCHAR);
3841 /* setup new index entry */
3842 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3843 RtlGUIDFromString(&str, &index->guid);
3844 index->data_offset = data_offset;
3845 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3846 index->rosterindex = i + 1;
3848 /* setup data */
3849 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3850 data->size = sizeof(*data);
3851 data->res = 0;
3852 data->name_len = module_len;
3853 data->name_offset = module_offset;
3854 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3855 data->langid = 0;
3856 data->flags = entity->u.typelib.flags;
3857 data->help_len = help_len;
3858 data->help_offset = sizeof(*data);
3859 data->major_version = entity->u.typelib.major;
3860 data->minor_version = entity->u.typelib.minor;
3862 /* module name */
3863 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3864 memcpy(ptrW, dll->name, data->name_len);
3865 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3867 /* help string */
3868 if (data->help_len)
3870 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3871 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3872 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3875 data_offset += sizeof(*data);
3876 if (help_len)
3877 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3879 module_offset += module_len + sizeof(WCHAR);
3881 index++;
3887 *section = header;
3889 return STATUS_SUCCESS;
3892 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3894 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3897 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3899 struct guid_index *index = NULL;
3900 struct tlibredirect_data *tlib;
3902 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3904 if (!actctx->tlib_section)
3906 struct guidsection_header *section;
3908 NTSTATUS status = build_tlib_section(actctx, &section);
3909 if (status) return status;
3911 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3912 RtlFreeHeap(GetProcessHeap(), 0, section);
3915 index = find_guid_index(actctx->tlib_section, guid);
3916 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3918 tlib = get_tlib_data(actctx, index);
3920 data->ulDataFormatVersion = 1;
3921 data->lpData = tlib;
3922 /* full length includes string length with nulls */
3923 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3924 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3925 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3926 data->lpSectionBase = actctx->tlib_section;
3927 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3928 data->hActCtx = NULL;
3930 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3931 data->ulAssemblyRosterIndex = index->rosterindex;
3933 return STATUS_SUCCESS;
3936 static void generate_uuid(ULONG *seed, GUID *guid)
3938 ULONG *ptr = (ULONG*)guid;
3939 int i;
3941 /* GUID is 16 bytes long */
3942 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3943 *ptr = RtlUniform(seed);
3945 guid->Data3 &= 0x0fff;
3946 guid->Data3 |= (4 << 12);
3947 guid->Data4[0] &= 0x3f;
3948 guid->Data4[0] |= 0x80;
3951 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3952 unsigned int *count, unsigned int *len, unsigned int *module_len)
3954 unsigned int i;
3956 for (i = 0; i < entities->num; i++)
3958 struct entity *entity = &entities->base[i];
3959 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3961 /* each entry needs two index entries, extra one goes for alias GUID */
3962 *len += 2*sizeof(struct guid_index);
3963 /* To save some memory we don't allocated two data structures,
3964 instead alias index and normal index point to the same data structure. */
3965 *len += sizeof(struct comclassredirect_data);
3967 /* for clrClass store some more */
3968 if (entity->u.comclass.name)
3970 unsigned int str_len;
3972 /* all string data is stored together in aligned block */
3973 str_len = strlenW(entity->u.comclass.name)+1;
3974 if (entity->u.comclass.progid)
3975 str_len += strlenW(entity->u.comclass.progid)+1;
3976 if (entity->u.comclass.version)
3977 str_len += strlenW(entity->u.comclass.version)+1;
3979 *len += sizeof(struct clrclass_data);
3980 *len += aligned_string_len(str_len*sizeof(WCHAR));
3982 /* module name is forced to mscoree.dll, and stored two times with different case */
3983 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3985 else
3987 /* progid string is stored separately */
3988 if (entity->u.comclass.progid)
3989 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3991 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3994 *count += 1;
3999 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
4000 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
4001 ULONG *seed, ULONG rosterindex)
4003 unsigned int i;
4005 for (i = 0; i < entities->num; i++)
4007 struct entity *entity = &entities->base[i];
4008 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4010 ULONG module_len, progid_len, str_len = 0;
4011 struct comclassredirect_data *data;
4012 struct guid_index *alias_index;
4013 struct clrclass_data *clrdata;
4014 UNICODE_STRING str;
4015 WCHAR *ptrW;
4017 if (entity->u.comclass.progid)
4018 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
4019 else
4020 progid_len = 0;
4022 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
4024 /* setup new index entry */
4025 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4026 RtlGUIDFromString(&str, &(*index)->guid);
4028 (*index)->data_offset = *data_offset;
4029 (*index)->data_len = sizeof(*data); /* additional length added later */
4030 (*index)->rosterindex = rosterindex;
4032 /* Setup new index entry for alias guid. Alias index records are placed after
4033 normal records, so normal guids are hit first on search. Note that class count
4034 is doubled. */
4035 alias_index = (*index) + section->count/2;
4036 generate_uuid(seed, &alias_index->guid);
4037 alias_index->data_offset = (*index)->data_offset;
4038 alias_index->data_len = 0;
4039 alias_index->rosterindex = (*index)->rosterindex;
4041 /* setup data */
4042 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
4043 data->size = sizeof(*data);
4044 data->res = 0;
4045 data->res1[0] = 0;
4046 data->res1[1] = 0;
4047 data->model = entity->u.comclass.model;
4048 data->clsid = (*index)->guid;
4049 data->alias = alias_index->guid;
4050 data->clsid2 = data->clsid;
4051 if (entity->u.comclass.tlbid)
4053 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
4054 RtlGUIDFromString(&str, &data->tlbid);
4056 else
4057 memset(&data->tlbid, 0, sizeof(data->tlbid));
4058 data->name_len = module_len;
4059 data->name_offset = *module_offset;
4060 data->progid_len = progid_len;
4061 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
4062 data->clrdata_len = 0; /* will be set later */
4063 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
4064 data->miscstatus = entity->u.comclass.miscstatus;
4065 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
4066 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
4067 data->miscstatusicon = entity->u.comclass.miscstatusicon;
4068 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
4070 /* mask describes which misc* data is available */
4071 data->miscmask = 0;
4072 if (data->miscstatus)
4073 data->miscmask |= MiscStatus;
4074 if (data->miscstatuscontent)
4075 data->miscmask |= MiscStatusContent;
4076 if (data->miscstatusthumbnail)
4077 data->miscmask |= MiscStatusThumbnail;
4078 if (data->miscstatusicon)
4079 data->miscmask |= MiscStatusIcon;
4080 if (data->miscstatusdocprint)
4081 data->miscmask |= MiscStatusDocPrint;
4083 if (data->clrdata_offset)
4085 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
4087 clrdata->size = sizeof(*clrdata);
4088 clrdata->res[0] = 0;
4089 clrdata->res[1] = 2; /* FIXME: unknown field */
4090 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
4091 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
4092 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
4093 clrdata->name_offset = clrdata->size;
4094 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
4095 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
4096 clrdata->res2[0] = 0;
4097 clrdata->res2[1] = 0;
4099 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
4101 /* module name */
4102 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
4103 memcpy(ptrW, mscoree2W, clrdata->module_len);
4104 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
4106 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4107 memcpy(ptrW, mscoreeW, data->name_len);
4108 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4110 /* class name */
4111 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
4112 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
4113 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
4115 /* runtime version, optional */
4116 if (clrdata->version_len)
4118 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
4120 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
4121 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
4122 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
4125 if (data->progid_len)
4126 data->progid_offset += data->clrdata_len;
4127 (*index)->data_len += sizeof(*clrdata);
4129 else
4131 clrdata = NULL;
4133 /* module name */
4134 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4135 memcpy(ptrW, dll->name, data->name_len);
4136 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4139 /* progid string */
4140 if (data->progid_len)
4142 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4143 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4144 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4147 /* string block length */
4148 str_len = 0;
4149 if (clrdata)
4151 str_len += clrdata->name_len + sizeof(WCHAR);
4152 if (clrdata->version_len)
4153 str_len += clrdata->version_len + sizeof(WCHAR);
4155 if (progid_len)
4156 str_len += progid_len + sizeof(WCHAR);
4158 (*index)->data_len += aligned_string_len(str_len);
4159 alias_index->data_len = (*index)->data_len;
4161 /* move to next data record */
4162 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4163 (*module_offset) += module_len + sizeof(WCHAR);
4165 if (clrdata)
4167 (*data_offset) += sizeof(*clrdata);
4168 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4170 (*index) += 1;
4175 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4177 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4178 struct guidsection_header *header;
4179 ULONG module_offset, data_offset;
4180 struct guid_index *index;
4181 ULONG seed;
4183 /* compute section length */
4184 for (i = 0; i < actctx->num_assemblies; i++)
4186 struct assembly *assembly = &actctx->assemblies[i];
4187 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4188 for (j = 0; j < assembly->num_dlls; j++)
4190 struct dll_redirect *dll = &assembly->dlls[j];
4191 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4195 total_len += aligned_string_len(names_len);
4196 total_len += sizeof(*header);
4198 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4199 if (!header) return STATUS_NO_MEMORY;
4201 memset(header, 0, sizeof(*header));
4202 header->magic = GUIDSECTION_MAGIC;
4203 header->size = sizeof(*header);
4204 header->count = 2*class_count;
4205 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4206 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4207 module_offset = sizeof(*header);
4208 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4210 seed = NtGetTickCount();
4211 for (i = 0; i < actctx->num_assemblies; i++)
4213 struct assembly *assembly = &actctx->assemblies[i];
4214 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4215 for (j = 0; j < assembly->num_dlls; j++)
4217 struct dll_redirect *dll = &assembly->dlls[j];
4218 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4222 *section = header;
4224 return STATUS_SUCCESS;
4227 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4229 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4232 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4234 struct comclassredirect_data *comclass;
4235 struct guid_index *index = NULL;
4237 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4239 if (!actctx->comserver_section)
4241 struct guidsection_header *section;
4243 NTSTATUS status = build_comserver_section(actctx, &section);
4244 if (status) return status;
4246 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4247 RtlFreeHeap(GetProcessHeap(), 0, section);
4250 index = find_guid_index(actctx->comserver_section, guid);
4251 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4253 comclass = get_comclass_data(actctx, index);
4255 data->ulDataFormatVersion = 1;
4256 data->lpData = comclass;
4257 /* full length includes string length with nulls */
4258 data->ulLength = comclass->size + comclass->clrdata_len;
4259 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4260 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4261 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4262 data->lpSectionBase = actctx->comserver_section;
4263 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4264 data->hActCtx = NULL;
4266 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4267 data->ulAssemblyRosterIndex = index->rosterindex;
4269 return STATUS_SUCCESS;
4272 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4274 unsigned int i;
4276 for (i = 0; i < entities->num; i++)
4278 struct entity *entity = &entities->base[i];
4279 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4281 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4282 if (entity->u.ifaceps.name)
4283 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4284 *count += 1;
4289 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4290 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4292 unsigned int i;
4294 for (i = 0; i < entities->num; i++)
4296 struct entity *entity = &entities->base[i];
4297 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4299 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4300 UNICODE_STRING str;
4301 ULONG name_len;
4303 if (entity->u.ifaceps.name)
4304 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4305 else
4306 name_len = 0;
4308 /* setup index */
4309 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4310 RtlGUIDFromString(&str, &(*index)->guid);
4311 (*index)->data_offset = *data_offset;
4312 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4313 (*index)->rosterindex = rosterindex;
4315 /* setup data record */
4316 data->size = sizeof(*data);
4317 data->mask = entity->u.ifaceps.mask;
4319 /* proxyStubClsid32 value is only stored for external PS,
4320 if set it's used as iid, otherwise 'iid' attribute value is used */
4321 if (entity->u.ifaceps.ps32)
4323 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4324 RtlGUIDFromString(&str, &data->iid);
4326 else
4327 data->iid = (*index)->guid;
4329 data->nummethods = entity->u.ifaceps.nummethods;
4331 if (entity->u.ifaceps.tlib)
4333 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4334 RtlGUIDFromString(&str, &data->tlbid);
4336 else
4337 memset(&data->tlbid, 0, sizeof(data->tlbid));
4339 if (entity->u.ifaceps.base)
4341 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4342 RtlGUIDFromString(&str, &data->base);
4344 else
4345 memset(&data->base, 0, sizeof(data->base));
4347 data->name_len = name_len;
4348 data->name_offset = data->name_len ? sizeof(*data) : 0;
4350 /* name string */
4351 if (data->name_len)
4353 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4354 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4355 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4358 /* move to next record */
4359 (*index) += 1;
4360 *data_offset += sizeof(*data);
4361 if (data->name_len)
4362 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4367 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4369 unsigned int i, j, total_len = 0, count = 0;
4370 struct guidsection_header *header;
4371 struct guid_index *index;
4372 ULONG data_offset;
4374 /* compute section length */
4375 for (i = 0; i < actctx->num_assemblies; i++)
4377 struct assembly *assembly = &actctx->assemblies[i];
4379 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4380 for (j = 0; j < assembly->num_dlls; j++)
4382 struct dll_redirect *dll = &assembly->dlls[j];
4383 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4387 total_len += sizeof(*header);
4389 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4390 if (!header) return STATUS_NO_MEMORY;
4392 memset(header, 0, sizeof(*header));
4393 header->magic = GUIDSECTION_MAGIC;
4394 header->size = sizeof(*header);
4395 header->count = count;
4396 header->index_offset = sizeof(*header);
4397 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4398 data_offset = header->index_offset + count*sizeof(*index);
4400 for (i = 0; i < actctx->num_assemblies; i++)
4402 struct assembly *assembly = &actctx->assemblies[i];
4404 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4405 for (j = 0; j < assembly->num_dlls; j++)
4407 struct dll_redirect *dll = &assembly->dlls[j];
4408 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4412 *section = header;
4414 return STATUS_SUCCESS;
4417 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4419 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4422 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4424 struct ifacepsredirect_data *iface;
4425 struct guid_index *index = NULL;
4427 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4429 if (!actctx->ifaceps_section)
4431 struct guidsection_header *section;
4433 NTSTATUS status = build_ifaceps_section(actctx, &section);
4434 if (status) return status;
4436 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4437 RtlFreeHeap(GetProcessHeap(), 0, section);
4440 index = find_guid_index(actctx->ifaceps_section, guid);
4441 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4443 iface = get_ifaceps_data(actctx, index);
4445 data->ulDataFormatVersion = 1;
4446 data->lpData = iface;
4447 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4448 data->lpSectionGlobalData = NULL;
4449 data->ulSectionGlobalDataLength = 0;
4450 data->lpSectionBase = actctx->ifaceps_section;
4451 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4452 data->hActCtx = NULL;
4454 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4455 data->ulAssemblyRosterIndex = index->rosterindex;
4457 return STATUS_SUCCESS;
4460 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4462 unsigned int i, j, total_len = 0, count = 0;
4463 struct guidsection_header *header;
4464 struct clrsurrogate_data *data;
4465 struct guid_index *index;
4466 ULONG data_offset;
4468 /* compute section length */
4469 for (i = 0; i < actctx->num_assemblies; i++)
4471 struct assembly *assembly = &actctx->assemblies[i];
4472 for (j = 0; j < assembly->entities.num; j++)
4474 struct entity *entity = &assembly->entities.base[j];
4475 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4477 ULONG len;
4479 total_len += sizeof(*index) + sizeof(*data);
4480 len = strlenW(entity->u.clrsurrogate.name) + 1;
4481 if (entity->u.clrsurrogate.version)
4482 len += strlenW(entity->u.clrsurrogate.version) + 1;
4483 total_len += aligned_string_len(len*sizeof(WCHAR));
4485 count++;
4490 total_len += sizeof(*header);
4492 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4493 if (!header) return STATUS_NO_MEMORY;
4495 memset(header, 0, sizeof(*header));
4496 header->magic = GUIDSECTION_MAGIC;
4497 header->size = sizeof(*header);
4498 header->count = count;
4499 header->index_offset = sizeof(*header);
4500 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4501 data_offset = header->index_offset + count*sizeof(*index);
4503 for (i = 0; i < actctx->num_assemblies; i++)
4505 struct assembly *assembly = &actctx->assemblies[i];
4506 for (j = 0; j < assembly->entities.num; j++)
4508 struct entity *entity = &assembly->entities.base[j];
4509 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4511 ULONG version_len, name_len;
4512 UNICODE_STRING str;
4513 WCHAR *ptrW;
4515 if (entity->u.clrsurrogate.version)
4516 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4517 else
4518 version_len = 0;
4519 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4521 /* setup new index entry */
4522 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4523 RtlGUIDFromString(&str, &index->guid);
4525 index->data_offset = data_offset;
4526 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4527 index->rosterindex = i + 1;
4529 /* setup data */
4530 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4531 data->size = sizeof(*data);
4532 data->res = 0;
4533 data->clsid = index->guid;
4534 data->version_offset = version_len ? data->size : 0;
4535 data->version_len = version_len;
4536 data->name_offset = data->size + version_len;
4537 if (version_len)
4538 data->name_offset += sizeof(WCHAR);
4539 data->name_len = name_len;
4541 /* surrogate name */
4542 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4543 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4544 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4546 /* runtime version */
4547 if (data->version_len)
4549 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4550 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4551 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4554 data_offset += index->data_offset;
4555 index++;
4560 *section = header;
4562 return STATUS_SUCCESS;
4565 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4567 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4570 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4572 struct clrsurrogate_data *surrogate;
4573 struct guid_index *index = NULL;
4575 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4577 if (!actctx->clrsurrogate_section)
4579 struct guidsection_header *section;
4581 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4582 if (status) return status;
4584 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4585 RtlFreeHeap(GetProcessHeap(), 0, section);
4588 index = find_guid_index(actctx->clrsurrogate_section, guid);
4589 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4591 surrogate = get_surrogate_data(actctx, index);
4593 data->ulDataFormatVersion = 1;
4594 data->lpData = surrogate;
4595 /* full length includes string length with nulls */
4596 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4597 if (surrogate->version_len)
4598 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4600 data->lpSectionGlobalData = NULL;
4601 data->ulSectionGlobalDataLength = 0;
4602 data->lpSectionBase = actctx->clrsurrogate_section;
4603 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4604 data->hActCtx = NULL;
4606 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4607 data->ulAssemblyRosterIndex = index->rosterindex;
4609 return STATUS_SUCCESS;
4612 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4614 unsigned int i, j, single_len;
4616 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4617 for (i = 0; i < entities->num; i++)
4619 struct entity *entity = &entities->base[i];
4620 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4622 if (entity->u.comclass.progid)
4624 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4625 *count += 1;
4628 for (j = 0; j < entity->u.comclass.progids.num; j++)
4629 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4631 *total_len += single_len*entity->u.comclass.progids.num;
4632 *count += entity->u.comclass.progids.num;
4637 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4638 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4640 struct progidredirect_data *data;
4641 UNICODE_STRING str;
4642 GUID *guid_ptr;
4643 WCHAR *ptrW;
4645 /* setup new index entry */
4647 /* hash progid name */
4648 RtlInitUnicodeString(&str, progid);
4649 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4651 (*index)->name_offset = *data_offset;
4652 (*index)->name_len = str.Length;
4653 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4654 (*index)->data_len = sizeof(*data);
4655 (*index)->rosterindex = rosterindex;
4657 *data_offset += aligned_string_len(str.MaximumLength);
4659 /* setup data structure */
4660 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4661 data->size = sizeof(*data);
4662 data->reserved = 0;
4663 data->clsid_offset = *global_offset;
4665 /* write progid string */
4666 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4667 memcpy(ptrW, progid, (*index)->name_len);
4668 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4670 /* write guid to global area */
4671 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4672 *guid_ptr = *alias;
4674 /* to next entry */
4675 *global_offset += sizeof(GUID);
4676 *data_offset += data->size;
4677 (*index) += 1;
4680 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4681 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4683 unsigned int i, j;
4685 for (i = 0; i < entities->num; i++)
4687 struct entity *entity = &entities->base[i];
4688 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4690 const struct progids *progids = &entity->u.comclass.progids;
4691 struct comclassredirect_data *comclass;
4692 struct guid_index *guid_index;
4693 UNICODE_STRING str;
4694 GUID clsid;
4696 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4697 RtlGUIDFromString(&str, &clsid);
4699 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4700 comclass = get_comclass_data(actctx, guid_index);
4702 if (entity->u.comclass.progid)
4703 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4704 index, data_offset, global_offset, rosterindex);
4706 for (j = 0; j < progids->num; j++)
4707 write_progid_record(section, progids->progids[j], &comclass->alias,
4708 index, data_offset, global_offset, rosterindex);
4713 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4715 unsigned int i, j, total_len = 0, count = 0;
4716 struct strsection_header *header;
4717 ULONG data_offset, global_offset;
4718 struct string_index *index;
4720 /* compute section length */
4721 for (i = 0; i < actctx->num_assemblies; i++)
4723 struct assembly *assembly = &actctx->assemblies[i];
4725 get_progid_datalen(&assembly->entities, &count, &total_len);
4726 for (j = 0; j < assembly->num_dlls; j++)
4728 struct dll_redirect *dll = &assembly->dlls[j];
4729 get_progid_datalen(&dll->entities, &count, &total_len);
4733 total_len += sizeof(*header);
4735 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4736 if (!header) return STATUS_NO_MEMORY;
4738 memset(header, 0, sizeof(*header));
4739 header->magic = STRSECTION_MAGIC;
4740 header->size = sizeof(*header);
4741 header->count = count;
4742 header->global_offset = header->size;
4743 header->global_len = count*sizeof(GUID);
4744 header->index_offset = header->size + header->global_len;
4746 index = (struct string_index*)((BYTE*)header + header->index_offset);
4747 data_offset = header->index_offset + count*sizeof(*index);
4748 global_offset = header->global_offset;
4750 for (i = 0; i < actctx->num_assemblies; i++)
4752 struct assembly *assembly = &actctx->assemblies[i];
4754 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4755 for (j = 0; j < assembly->num_dlls; j++)
4757 struct dll_redirect *dll = &assembly->dlls[j];
4758 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4762 *section = header;
4764 return STATUS_SUCCESS;
4767 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4769 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4772 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4773 PACTCTX_SECTION_KEYED_DATA data)
4775 struct progidredirect_data *progid;
4776 struct string_index *index;
4778 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4780 if (!actctx->comserver_section)
4782 struct guidsection_header *section;
4784 NTSTATUS status = build_comserver_section(actctx, &section);
4785 if (status) return status;
4787 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4788 RtlFreeHeap(GetProcessHeap(), 0, section);
4791 if (!actctx->progid_section)
4793 struct strsection_header *section;
4795 NTSTATUS status = build_progid_section(actctx, &section);
4796 if (status) return status;
4798 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4799 RtlFreeHeap(GetProcessHeap(), 0, section);
4802 index = find_string_index(actctx->progid_section, name);
4803 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4805 if (data)
4807 progid = get_progid_data(actctx, index);
4809 data->ulDataFormatVersion = 1;
4810 data->lpData = progid;
4811 data->ulLength = progid->size;
4812 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4813 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4814 data->lpSectionBase = actctx->progid_section;
4815 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4816 data->hActCtx = NULL;
4818 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4819 data->ulAssemblyRosterIndex = index->rosterindex;
4822 return STATUS_SUCCESS;
4825 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4826 const UNICODE_STRING *section_name,
4827 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4829 NTSTATUS status;
4831 switch (section_kind)
4833 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4834 status = find_dll_redirection(actctx, section_name, data);
4835 break;
4836 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4837 status = find_window_class(actctx, section_name, data);
4838 break;
4839 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4840 status = find_progid_redirection(actctx, section_name, data);
4841 break;
4842 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4843 FIXME("Unsupported yet section_kind %x\n", section_kind);
4844 return STATUS_SXS_SECTION_NOT_FOUND;
4845 default:
4846 WARN("Unknown section_kind %x\n", section_kind);
4847 return STATUS_SXS_SECTION_NOT_FOUND;
4850 if (status != STATUS_SUCCESS) return status;
4852 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4854 actctx_addref(actctx);
4855 data->hActCtx = actctx;
4857 return STATUS_SUCCESS;
4860 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4861 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4863 NTSTATUS status;
4865 switch (section_kind)
4867 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4868 status = find_tlib_redirection(actctx, guid, data);
4869 break;
4870 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4871 status = find_comserver_redirection(actctx, guid, data);
4872 break;
4873 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4874 status = find_cominterface_redirection(actctx, guid, data);
4875 break;
4876 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4877 status = find_clr_surrogate(actctx, guid, data);
4878 break;
4879 default:
4880 WARN("Unknown section_kind %x\n", section_kind);
4881 return STATUS_SXS_SECTION_NOT_FOUND;
4884 if (status != STATUS_SUCCESS) return status;
4886 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4888 actctx_addref(actctx);
4889 data->hActCtx = actctx;
4891 return STATUS_SUCCESS;
4894 /* initialize the activation context for the current process */
4895 void actctx_init(void)
4897 ACTCTXW ctx;
4898 HANDLE handle;
4900 ctx.cbSize = sizeof(ctx);
4901 ctx.lpSource = NULL;
4902 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4903 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4904 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4906 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4910 /***********************************************************************
4911 * RtlCreateActivationContext (NTDLL.@)
4913 * Create an activation context.
4915 * FIXME: function signature/prototype is wrong
4917 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4919 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4920 const WCHAR *directory = NULL;
4921 ACTIVATION_CONTEXT *actctx;
4922 UNICODE_STRING nameW;
4923 ULONG lang = 0;
4924 NTSTATUS status = STATUS_NO_MEMORY;
4925 HANDLE file = 0;
4926 struct actctx_loader acl;
4928 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4930 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4931 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4932 return STATUS_INVALID_PARAMETER;
4934 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4935 return STATUS_NO_MEMORY;
4937 actctx->magic = ACTCTX_MAGIC;
4938 actctx->ref_count = 1;
4939 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4940 actctx->config.info = NULL;
4941 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4942 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4944 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4946 else
4948 UNICODE_STRING dir;
4949 WCHAR *p;
4950 HMODULE module;
4952 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4953 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4955 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4956 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4957 actctx->appdir.info = dir.Buffer;
4960 nameW.Buffer = NULL;
4962 /* open file only if it's going to be used */
4963 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4964 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4966 WCHAR *source = NULL;
4967 BOOLEAN ret;
4969 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4970 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4972 DWORD dir_len, source_len;
4974 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4975 source_len = strlenW(pActCtx->lpSource);
4976 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4978 status = STATUS_NO_MEMORY;
4979 goto error;
4982 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4983 source[dir_len] = '\\';
4984 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4987 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4988 RtlFreeHeap( GetProcessHeap(), 0, source );
4989 if (!ret)
4991 status = STATUS_NO_SUCH_FILE;
4992 goto error;
4994 status = open_nt_file( &file, &nameW );
4995 if (status)
4997 RtlFreeUnicodeString( &nameW );
4998 goto error;
5002 acl.actctx = actctx;
5003 acl.dependencies = NULL;
5004 acl.num_dependencies = 0;
5005 acl.allocated_dependencies = 0;
5007 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
5008 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
5010 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
5012 /* if we have a resource it's a PE file */
5013 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
5015 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
5016 pActCtx->lpResourceName, lang );
5017 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5018 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
5019 pActCtx->hModule, pActCtx->lpResourceName );
5021 else if (pActCtx->lpSource)
5023 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
5024 file, pActCtx->lpResourceName, lang );
5025 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
5026 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
5027 NULL, pActCtx->lpResourceName );
5029 else status = STATUS_INVALID_PARAMETER;
5031 else
5033 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
5036 if (file) NtClose( file );
5037 RtlFreeUnicodeString( &nameW );
5039 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
5040 free_depend_manifests( &acl );
5042 if (status == STATUS_SUCCESS) *handle = actctx;
5043 else actctx_release( actctx );
5044 return status;
5046 error:
5047 if (file) NtClose( file );
5048 actctx_release( actctx );
5049 return status;
5053 /***********************************************************************
5054 * RtlAddRefActivationContext (NTDLL.@)
5056 void WINAPI RtlAddRefActivationContext( HANDLE handle )
5058 ACTIVATION_CONTEXT *actctx;
5060 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
5064 /******************************************************************
5065 * RtlReleaseActivationContext (NTDLL.@)
5067 void WINAPI RtlReleaseActivationContext( HANDLE handle )
5069 ACTIVATION_CONTEXT *actctx;
5071 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
5074 /******************************************************************
5075 * RtlZombifyActivationContext (NTDLL.@)
5077 * FIXME: function prototype might be wrong
5079 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
5081 FIXME("%p: stub\n", handle);
5082 return STATUS_NOT_IMPLEMENTED;
5085 /******************************************************************
5086 * RtlActivateActivationContext (NTDLL.@)
5088 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
5090 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5092 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
5093 return STATUS_NO_MEMORY;
5095 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5096 frame->ActivationContext = handle;
5097 frame->Flags = 0;
5098 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
5099 RtlAddRefActivationContext( handle );
5101 *cookie = (ULONG_PTR)frame;
5102 TRACE( "%p cookie=%lx\n", handle, *cookie );
5103 return STATUS_SUCCESS;
5107 /***********************************************************************
5108 * RtlDeactivateActivationContext (NTDLL.@)
5110 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
5112 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
5114 TRACE( "%x cookie=%lx\n", flags, cookie );
5116 /* find the right frame */
5117 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5118 for (frame = top; frame; frame = frame->Previous)
5119 if ((ULONG_PTR)frame == cookie) break;
5121 if (!frame)
5122 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
5124 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
5125 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5127 /* pop everything up to and including frame */
5128 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5130 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5132 frame = top->Previous;
5133 RtlReleaseActivationContext( top->ActivationContext );
5134 RtlFreeHeap( GetProcessHeap(), 0, top );
5135 top = frame;
5140 /******************************************************************
5141 * RtlFreeThreadActivationContextStack (NTDLL.@)
5143 void WINAPI RtlFreeThreadActivationContextStack(void)
5145 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5147 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5148 while (frame)
5150 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5151 RtlReleaseActivationContext( frame->ActivationContext );
5152 RtlFreeHeap( GetProcessHeap(), 0, frame );
5153 frame = prev;
5155 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5159 /******************************************************************
5160 * RtlGetActiveActivationContext (NTDLL.@)
5162 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5164 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5166 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5167 RtlAddRefActivationContext( *handle );
5169 else
5170 *handle = 0;
5172 return STATUS_SUCCESS;
5176 /******************************************************************
5177 * RtlIsActivationContextActive (NTDLL.@)
5179 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5181 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5183 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5184 if (frame->ActivationContext == handle) return TRUE;
5185 return FALSE;
5189 /***********************************************************************
5190 * RtlQueryInformationActivationContext (NTDLL.@)
5192 * Get information about an activation context.
5193 * FIXME: function signature/prototype may be wrong
5195 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5196 ULONG class, PVOID buffer,
5197 SIZE_T bufsize, SIZE_T *retlen )
5199 ACTIVATION_CONTEXT *actctx;
5200 NTSTATUS status;
5202 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5203 subinst, class, buffer, bufsize, retlen);
5205 if (retlen) *retlen = 0;
5206 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5208 switch (class)
5210 case ActivationContextBasicInformation:
5212 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5214 if (retlen) *retlen = sizeof(*info);
5215 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5217 info->hActCtx = handle;
5218 info->dwFlags = 0; /* FIXME */
5219 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5221 break;
5223 case ActivationContextDetailedInformation:
5225 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5226 struct assembly *assembly = NULL;
5227 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5228 LPWSTR ptr;
5230 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5232 if (actctx->num_assemblies) assembly = actctx->assemblies;
5234 if (assembly && assembly->manifest.info)
5235 manifest_len = strlenW(assembly->manifest.info) + 1;
5236 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5237 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5238 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5240 if (retlen) *retlen = len;
5241 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5243 acdi->dwFlags = 0;
5244 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5245 acdi->ulAssemblyCount = actctx->num_assemblies;
5246 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5247 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5248 acdi->ulRootConfigurationPathType = actctx->config.type;
5249 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5250 acdi->ulAppDirPathType = actctx->appdir.type;
5251 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5252 ptr = (LPWSTR)(acdi + 1);
5253 if (manifest_len)
5255 acdi->lpRootManifestPath = ptr;
5256 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5257 ptr += manifest_len;
5259 else acdi->lpRootManifestPath = NULL;
5260 if (config_len)
5262 acdi->lpRootConfigurationPath = ptr;
5263 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5264 ptr += config_len;
5266 else acdi->lpRootConfigurationPath = NULL;
5267 if (appdir_len)
5269 acdi->lpAppDirPath = ptr;
5270 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5272 else acdi->lpAppDirPath = NULL;
5274 break;
5276 case AssemblyDetailedInformationInActivationContext:
5278 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5279 struct assembly *assembly;
5280 WCHAR *assembly_id;
5281 DWORD index;
5282 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5283 LPWSTR ptr;
5285 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5286 if (!subinst) return STATUS_INVALID_PARAMETER;
5288 index = *(DWORD*)subinst;
5289 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5291 assembly = &actctx->assemblies[index - 1];
5293 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5294 id_len = strlenW(assembly_id) + 1;
5295 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5297 if (assembly->manifest.info &&
5298 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5299 path_len = strlenW(assembly->manifest.info) + 1;
5301 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5303 if (retlen) *retlen = len;
5304 if (!buffer || bufsize < len)
5306 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5307 return STATUS_BUFFER_TOO_SMALL;
5310 afdi->ulFlags = 0; /* FIXME */
5311 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5312 afdi->ulManifestPathType = assembly->manifest.type;
5313 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5314 /* FIXME afdi->liManifestLastWriteTime = 0; */
5315 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5316 afdi->ulPolicyPathLength = 0;
5317 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5318 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5319 afdi->ulManifestVersionMajor = 1;
5320 afdi->ulManifestVersionMinor = 0;
5321 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5322 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5323 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5324 ptr = (LPWSTR)(afdi + 1);
5325 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5326 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5327 ptr += id_len;
5328 if (path_len)
5330 afdi->lpAssemblyManifestPath = ptr;
5331 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5332 ptr += path_len;
5333 } else afdi->lpAssemblyManifestPath = NULL;
5334 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5335 if (ad_len)
5337 afdi->lpAssemblyDirectoryName = ptr;
5338 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5340 else afdi->lpAssemblyDirectoryName = NULL;
5341 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5343 break;
5345 case FileInformationInAssemblyOfAssemblyInActivationContext:
5347 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5348 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5349 struct assembly *assembly;
5350 struct dll_redirect *dll;
5351 SIZE_T len, dll_len = 0;
5352 LPWSTR ptr;
5354 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5355 if (!acqi) return STATUS_INVALID_PARAMETER;
5357 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5358 return STATUS_INVALID_PARAMETER;
5359 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5361 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5362 return STATUS_INVALID_PARAMETER;
5363 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5365 if (dll->name) dll_len = strlenW(dll->name) + 1;
5366 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5368 if (!buffer || bufsize < len)
5370 if (retlen) *retlen = len;
5371 return STATUS_BUFFER_TOO_SMALL;
5373 if (retlen) *retlen = 0; /* yes that's what native does !! */
5374 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5375 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5376 afdi->ulPathLength = 0; /* FIXME */
5377 ptr = (LPWSTR)(afdi + 1);
5378 if (dll_len)
5380 afdi->lpFileName = ptr;
5381 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5382 } else afdi->lpFileName = NULL;
5383 afdi->lpFilePath = NULL; /* FIXME */
5385 break;
5387 case CompatibilityInformationInActivationContext:
5389 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5390 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5391 struct assembly *assembly = NULL;
5392 ULONG num_compat_contexts = 0, n;
5393 SIZE_T len;
5395 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5397 if (actctx->num_assemblies) assembly = actctx->assemblies;
5399 if (assembly)
5400 num_compat_contexts = assembly->num_compat_contexts;
5401 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5403 if (retlen) *retlen = len;
5404 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5406 *acci = num_compat_contexts;
5407 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5408 for (n = 0; n < num_compat_contexts; ++n)
5410 elements[n] = assembly->compat_contexts[n];
5413 break;
5415 case RunlevelInformationInActivationContext:
5417 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5418 struct assembly *assembly;
5419 SIZE_T len;
5421 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5423 len = sizeof(*acrli);
5424 if (retlen) *retlen = len;
5425 if (!buffer || bufsize < len)
5426 return STATUS_BUFFER_TOO_SMALL;
5428 assembly = actctx->assemblies;
5430 acrli->ulFlags = 0;
5431 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5432 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5434 break;
5436 default:
5437 FIXME( "class %u not implemented\n", class );
5438 return STATUS_NOT_IMPLEMENTED;
5440 return STATUS_SUCCESS;
5443 /***********************************************************************
5444 * RtlFindActivationContextSectionString (NTDLL.@)
5446 * Find information about a string in an activation context.
5447 * FIXME: function signature/prototype may be wrong
5449 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5450 const UNICODE_STRING *section_name, PVOID ptr )
5452 PACTCTX_SECTION_KEYED_DATA data = ptr;
5453 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5455 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5456 debugstr_us(section_name), data);
5458 if (guid)
5460 FIXME("expected guid == NULL\n");
5461 return STATUS_INVALID_PARAMETER;
5463 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5465 FIXME("unknown flags %08x\n", flags);
5466 return STATUS_INVALID_PARAMETER;
5468 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5469 !section_name || !section_name->Buffer)
5471 WARN("invalid parameter\n");
5472 return STATUS_INVALID_PARAMETER;
5475 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5477 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5478 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5481 if (status != STATUS_SUCCESS)
5482 status = find_string( process_actctx, section_kind, section_name, flags, data );
5484 return status;
5487 /***********************************************************************
5488 * RtlFindActivationContextSectionGuid (NTDLL.@)
5490 * Find information about a GUID in an activation context.
5491 * FIXME: function signature/prototype may be wrong
5493 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5494 const GUID *guid, void *ptr )
5496 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5497 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5499 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5501 if (extguid)
5503 FIXME("expected extguid == NULL\n");
5504 return STATUS_INVALID_PARAMETER;
5507 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5509 FIXME("unknown flags %08x\n", flags);
5510 return STATUS_INVALID_PARAMETER;
5513 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5514 return STATUS_INVALID_PARAMETER;
5516 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5518 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5519 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5522 if (status != STATUS_SUCCESS)
5523 status = find_guid( process_actctx, section_kind, guid, flags, data );
5525 return status;