ntdll: Implement ProcessPriorityClass in NtQueryInformationProcess.
[wine.git] / dlls / ntdll / actctx.c
blob27d6ad864c07755fd707565da46d7792f11dc4d8
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 } u;
470 struct entity_array
472 struct entity *base;
473 unsigned int num;
474 unsigned int allocated;
477 struct dll_redirect
479 WCHAR *name;
480 WCHAR *hash;
481 struct entity_array entities;
484 enum assembly_type
486 APPLICATION_MANIFEST,
487 ASSEMBLY_MANIFEST,
488 ASSEMBLY_SHARED_MANIFEST,
491 struct assembly
493 enum assembly_type type;
494 struct assembly_identity id;
495 struct file_info manifest;
496 WCHAR *directory;
497 BOOL no_inherit;
498 struct dll_redirect *dlls;
499 unsigned int num_dlls;
500 unsigned int allocated_dlls;
501 struct entity_array entities;
502 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts;
503 ULONG num_compat_contexts;
504 ACTCTX_REQUESTED_RUN_LEVEL run_level;
505 ULONG ui_access;
508 enum context_sections
510 WINDOWCLASS_SECTION = 1,
511 DLLREDIRECT_SECTION = 2,
512 TLIBREDIRECT_SECTION = 4,
513 SERVERREDIRECT_SECTION = 8,
514 IFACEREDIRECT_SECTION = 16,
515 CLRSURROGATES_SECTION = 32,
516 PROGIDREDIRECT_SECTION = 64
519 typedef struct _ACTIVATION_CONTEXT
521 ULONG magic;
522 int ref_count;
523 struct file_info config;
524 struct file_info appdir;
525 struct assembly *assemblies;
526 unsigned int num_assemblies;
527 unsigned int allocated_assemblies;
528 /* section data */
529 DWORD sections;
530 struct strsection_header *wndclass_section;
531 struct strsection_header *dllredirect_section;
532 struct strsection_header *progid_section;
533 struct guidsection_header *tlib_section;
534 struct guidsection_header *comserver_section;
535 struct guidsection_header *ifaceps_section;
536 struct guidsection_header *clrsurrogate_section;
537 } ACTIVATION_CONTEXT;
539 struct actctx_loader
541 ACTIVATION_CONTEXT *actctx;
542 struct assembly_identity *dependencies;
543 unsigned int num_dependencies;
544 unsigned int allocated_dependencies;
547 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
548 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
549 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
550 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
551 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
552 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
553 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
554 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
555 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};
556 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};
557 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
558 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
559 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
560 static const WCHAR fileW[] = {'f','i','l','e',0};
561 static const WCHAR hashW[] = {'h','a','s','h',0};
562 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
563 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
564 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
565 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
567 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
568 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
569 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
570 static const WCHAR iidW[] = {'i','i','d',0};
571 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
572 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
573 static const WCHAR nameW[] = {'n','a','m','e',0};
574 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
575 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
576 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
577 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
578 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};
579 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
580 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
581 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
582 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
583 static const WCHAR typeW[] = {'t','y','p','e',0};
584 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
585 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
586 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
587 static const WCHAR yesW[] = {'y','e','s',0};
588 static const WCHAR noW[] = {'n','o',0};
589 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
590 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
591 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
592 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
593 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
594 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
595 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
596 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
597 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
598 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
599 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
600 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
601 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
602 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
603 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
604 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
606 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
607 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
608 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
609 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
610 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
611 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
612 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
613 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};
614 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
615 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
616 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
617 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
618 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
619 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
620 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
621 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
622 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};
623 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
624 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
625 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
626 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};
627 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
629 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0};
630 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};
631 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0};
632 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0};
633 static const WCHAR IdW[] = {'I','d',0};
634 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};
635 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0};
636 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0};
637 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0};
639 struct olemisc_entry
641 const WCHAR *name;
642 OLEMISC value;
645 static const struct olemisc_entry olemisc_values[] =
647 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
648 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
649 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
650 { alignableW, OLEMISC_ALIGNABLE },
651 { alwaysrunW, OLEMISC_ALWAYSRUN },
652 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
653 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
654 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
655 { imemodeW, OLEMISC_IMEMODE },
656 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
657 { insideoutW, OLEMISC_INSIDEOUT },
658 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
659 { islinkobjectW, OLEMISC_ISLINKOBJECT },
660 { nouiactivateW, OLEMISC_NOUIACTIVATE },
661 { onlyiconicW, OLEMISC_ONLYICONIC },
662 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
663 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
664 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
665 { simpleframeW, OLEMISC_SIMPLEFRAME },
666 { staticW, OLEMISC_STATIC },
667 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
668 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
671 static const WCHAR xmlW[] = {'?','x','m','l',0};
672 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};
673 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};
674 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};
676 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
677 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
678 static const WCHAR wildcardW[] = {'*',0};
680 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
681 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
683 static WCHAR *strdupW(const WCHAR* str)
685 WCHAR* ptr;
687 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
688 return NULL;
689 return strcpyW(ptr, str);
692 static WCHAR *xmlstrdupW(const xmlstr_t* str)
694 WCHAR *strW;
696 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
698 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
699 strW[str->len] = 0;
701 return strW;
704 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
706 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
709 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
711 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
714 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
716 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
717 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
720 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
722 UINT len = strlenW( namespace );
724 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
725 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
726 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
729 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
731 if (elem->len && elem->ptr[0] == '/')
733 xmlstr_t elem_end;
734 elem_end.ptr = elem->ptr + 1;
735 elem_end.len = elem->len - 1;
736 return xml_elem_cmp( &elem_end, str, namespace );
738 return FALSE;
741 static inline BOOL isxmlspace( WCHAR ch )
743 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
746 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
748 return debugstr_wn(str->ptr, str->len);
751 static inline const char* debugstr_version(const struct assembly_version *ver)
753 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
756 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
758 struct assembly *assembly;
760 if (actctx->num_assemblies == actctx->allocated_assemblies)
762 void *ptr;
763 unsigned int new_count;
764 if (actctx->assemblies)
766 new_count = actctx->allocated_assemblies * 2;
767 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
768 actctx->assemblies, new_count * sizeof(*assembly) );
770 else
772 new_count = 4;
773 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
775 if (!ptr) return NULL;
776 actctx->assemblies = ptr;
777 actctx->allocated_assemblies = new_count;
780 assembly = &actctx->assemblies[actctx->num_assemblies++];
781 assembly->type = at;
782 return assembly;
785 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
787 if (assembly->num_dlls == assembly->allocated_dlls)
789 void *ptr;
790 unsigned int new_count;
791 if (assembly->dlls)
793 new_count = assembly->allocated_dlls * 2;
794 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
795 assembly->dlls, new_count * sizeof(*assembly->dlls) );
797 else
799 new_count = 4;
800 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
802 if (!ptr) return NULL;
803 assembly->dlls = ptr;
804 assembly->allocated_dlls = new_count;
806 return &assembly->dlls[assembly->num_dlls++];
809 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly)
811 void *ptr;
812 if (assembly->num_compat_contexts)
814 unsigned int new_count = assembly->num_compat_contexts + 1;
815 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
816 assembly->compat_contexts,
817 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
819 else
821 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) );
823 if (!ptr) return NULL;
824 assembly->compat_contexts = ptr;
825 return &assembly->compat_contexts[assembly->num_compat_contexts++];
828 static void free_assembly_identity(struct assembly_identity *ai)
830 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
831 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
832 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
833 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
834 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
837 static struct entity* add_entity(struct entity_array *array, DWORD kind)
839 struct entity* entity;
841 if (array->num == array->allocated)
843 void *ptr;
844 unsigned int new_count;
845 if (array->base)
847 new_count = array->allocated * 2;
848 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
849 array->base, new_count * sizeof(*array->base) );
851 else
853 new_count = 4;
854 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
856 if (!ptr) return NULL;
857 array->base = ptr;
858 array->allocated = new_count;
860 entity = &array->base[array->num++];
861 entity->kind = kind;
862 return entity;
865 static void free_entity_array(struct entity_array *array)
867 unsigned int i, j;
868 for (i = 0; i < array->num; i++)
870 struct entity *entity = &array->base[i];
871 switch (entity->kind)
873 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
874 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
875 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
876 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
877 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
878 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
879 for (j = 0; j < entity->u.comclass.progids.num; j++)
880 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
881 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
882 break;
883 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
884 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
885 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
886 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
887 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
888 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
889 break;
890 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
891 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
892 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
893 break;
894 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
895 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
896 break;
897 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
898 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
899 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
900 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
901 break;
902 default:
903 FIXME("Unknown entity kind %d\n", entity->kind);
906 RtlFreeHeap( GetProcessHeap(), 0, array->base );
909 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
911 if (!str1) return !str2;
912 return str2 && !strcmpiW( str1, str2 );
915 static BOOL is_matching_identity( const struct assembly_identity *id1,
916 const struct assembly_identity *id2 )
918 if (!is_matching_string( id1->name, id2->name )) return FALSE;
919 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
920 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
922 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
924 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
925 return FALSE;
927 if (id1->version.major != id2->version.major) return FALSE;
928 if (id1->version.minor != id2->version.minor) return FALSE;
929 if (id1->version.build > id2->version.build) return FALSE;
930 if (id1->version.build == id2->version.build &&
931 id1->version.revision > id2->version.revision) return FALSE;
932 return TRUE;
935 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
936 struct assembly_identity* ai)
938 unsigned int i;
940 /* check if we already have that assembly */
942 for (i = 0; i < acl->actctx->num_assemblies; i++)
943 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
945 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
946 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
947 ai->version.build, ai->version.revision );
948 return TRUE;
951 for (i = 0; i < acl->num_dependencies; i++)
952 if (is_matching_identity( ai, &acl->dependencies[i] ))
954 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
955 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
956 ai->version.build, ai->version.revision );
957 return TRUE;
960 if (acl->num_dependencies == acl->allocated_dependencies)
962 void *ptr;
963 unsigned int new_count;
964 if (acl->dependencies)
966 new_count = acl->allocated_dependencies * 2;
967 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
968 new_count * sizeof(acl->dependencies[0]));
970 else
972 new_count = 4;
973 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
975 if (!ptr) return FALSE;
976 acl->dependencies = ptr;
977 acl->allocated_dependencies = new_count;
979 acl->dependencies[acl->num_dependencies++] = *ai;
981 return TRUE;
984 static void free_depend_manifests(struct actctx_loader* acl)
986 unsigned int i;
987 for (i = 0; i < acl->num_dependencies; i++)
988 free_assembly_identity(&acl->dependencies[i]);
989 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
992 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
994 static const WCHAR undW[] = {'_',0};
995 static const WCHAR noneW[] = {'n','o','n','e',0};
996 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
998 const WCHAR *arch = ai->arch ? ai->arch : noneW;
999 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
1000 const WCHAR *lang = ai->language ? ai->language : noneW;
1001 const WCHAR *name = ai->name ? ai->name : noneW;
1002 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
1003 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
1004 WCHAR *ret;
1006 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
1008 strcpyW( ret, arch );
1009 strcatW( ret, undW );
1010 strcatW( ret, name );
1011 strcatW( ret, undW );
1012 strcatW( ret, key );
1013 strcatW( ret, undW );
1014 sprintfW( ret + strlenW(ret), version_formatW,
1015 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1016 strcatW( ret, undW );
1017 strcatW( ret, lang );
1018 strcatW( ret, undW );
1019 strcatW( ret, mskeyW );
1020 return ret;
1023 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
1025 WCHAR *p = buffer;
1027 if (!str) return;
1028 strcatW( buffer, prefix );
1029 p += strlenW(p);
1030 *p++ = '"';
1031 strcpyW( p, str );
1032 p += strlenW(p);
1033 *p++ = '"';
1034 *p = 0;
1037 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1039 static const WCHAR archW[] =
1040 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1041 static const WCHAR public_keyW[] =
1042 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1043 static const WCHAR typeW[] =
1044 {',','t','y','p','e','=',0};
1045 static const WCHAR versionW[] =
1046 {',','v','e','r','s','i','o','n','=',0};
1048 WCHAR version[64], *ret;
1049 SIZE_T size = 0;
1051 sprintfW( version, version_formatW,
1052 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1053 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1054 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1055 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1056 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1057 size += strlenW(versionW) + strlenW(version) + 2;
1059 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1060 return NULL;
1062 if (ai->name) strcpyW( ret, ai->name );
1063 else *ret = 0;
1064 append_string( ret, archW, ai->arch );
1065 append_string( ret, public_keyW, ai->public_key );
1066 append_string( ret, typeW, ai->type );
1067 append_string( ret, versionW, version );
1068 return ret;
1071 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1073 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1075 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1076 __TRY
1078 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1080 __EXCEPT_PAGE_FAULT
1083 __ENDTRY
1084 return ret;
1087 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1089 interlocked_xchg_add( &actctx->ref_count, 1 );
1092 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1094 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1096 unsigned int i, j;
1098 for (i = 0; i < actctx->num_assemblies; i++)
1100 struct assembly *assembly = &actctx->assemblies[i];
1101 for (j = 0; j < assembly->num_dlls; j++)
1103 struct dll_redirect *dll = &assembly->dlls[j];
1104 free_entity_array( &dll->entities );
1105 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1106 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1108 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1109 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1110 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1111 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts );
1112 free_entity_array( &assembly->entities );
1113 free_assembly_identity(&assembly->id);
1115 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1116 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1117 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1118 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1119 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1120 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1121 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1122 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1123 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1124 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1125 actctx->magic = 0;
1126 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1130 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1131 BOOL* error, BOOL* end)
1133 const WCHAR* ptr;
1135 *error = TRUE;
1137 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1138 xmlbuf->ptr++;
1140 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1142 if (*xmlbuf->ptr == '/')
1144 xmlbuf->ptr++;
1145 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1146 return FALSE;
1148 xmlbuf->ptr++;
1149 *end = TRUE;
1150 *error = FALSE;
1151 return FALSE;
1154 if (*xmlbuf->ptr == '>')
1156 xmlbuf->ptr++;
1157 *error = FALSE;
1158 return FALSE;
1161 ptr = xmlbuf->ptr;
1162 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1164 if (ptr == xmlbuf->end) return FALSE;
1166 name->ptr = xmlbuf->ptr;
1167 name->len = ptr-xmlbuf->ptr;
1168 xmlbuf->ptr = ptr;
1170 /* skip spaces before '=' */
1171 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1172 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1174 /* skip '=' itself */
1175 ptr++;
1176 if (ptr == xmlbuf->end) return FALSE;
1178 /* skip spaces after '=' */
1179 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1181 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1183 value->ptr = ++ptr;
1184 if (ptr == xmlbuf->end) return FALSE;
1186 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1187 if (!ptr)
1189 xmlbuf->ptr = xmlbuf->end;
1190 return FALSE;
1193 value->len = ptr - value->ptr;
1194 xmlbuf->ptr = ptr + 1;
1196 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1198 *error = FALSE;
1199 return TRUE;
1202 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1204 const WCHAR* ptr;
1206 for (;;)
1208 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1209 if (!ptr)
1211 xmlbuf->ptr = xmlbuf->end;
1212 return FALSE;
1214 ptr++;
1215 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1217 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1218 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1220 if (ptr + 3 > xmlbuf->end)
1222 xmlbuf->ptr = xmlbuf->end;
1223 return FALSE;
1225 xmlbuf->ptr = ptr + 3;
1227 else break;
1230 xmlbuf->ptr = ptr;
1231 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1232 ptr++;
1234 elem->ptr = xmlbuf->ptr;
1235 elem->len = ptr - xmlbuf->ptr;
1236 xmlbuf->ptr = ptr;
1237 return xmlbuf->ptr != xmlbuf->end;
1240 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1242 /* FIXME: parse attributes */
1243 const WCHAR *ptr;
1245 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1247 if (ptr[0] == '?' && ptr[1] == '>')
1249 xmlbuf->ptr = ptr + 2;
1250 return TRUE;
1253 return FALSE;
1256 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1258 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1260 if (!ptr) return FALSE;
1262 content->ptr = xmlbuf->ptr;
1263 content->len = ptr - xmlbuf->ptr;
1264 xmlbuf->ptr = ptr;
1266 return TRUE;
1269 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1271 unsigned int ver[4];
1272 unsigned int pos;
1273 const WCHAR *curr;
1275 /* major.minor.build.revision */
1276 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1277 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1279 if (*curr >= '0' && *curr <= '9')
1281 ver[pos] = ver[pos] * 10 + *curr - '0';
1282 if (ver[pos] >= 0x10000) goto error;
1284 else if (*curr == '.')
1286 if (++pos >= 4) goto error;
1288 else goto error;
1290 version->major = ver[0];
1291 version->minor = ver[1];
1292 version->build = ver[2];
1293 version->revision = ver[3];
1294 return TRUE;
1296 error:
1297 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1298 return FALSE;
1301 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1303 xmlstr_t elem;
1304 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1305 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1306 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1307 return FALSE;
1310 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1312 xmlstr_t attr_name, attr_value;
1313 BOOL error;
1315 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1317 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1318 debugstr_xmlstr(&attr_value));
1320 return !error;
1323 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1325 BOOL end = FALSE;
1326 return parse_expect_no_attr(xmlbuf, &end) && !end;
1329 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1331 xmlstr_t elem;
1332 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1333 if (!xml_elem_cmp_end(&elem, name, namespace))
1335 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1336 return FALSE;
1338 return parse_end_element(xmlbuf);
1341 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1343 xmlstr_t attr_name, attr_value, elem;
1344 BOOL end = FALSE, error, ret = TRUE;
1346 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1347 if(error || end) return end;
1349 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1351 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1352 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1353 break;
1354 else
1355 ret = parse_unknown_elem(xmlbuf, &elem);
1358 return ret && parse_end_element(xmlbuf);
1361 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1362 struct assembly_identity* ai)
1364 xmlstr_t attr_name, attr_value;
1365 BOOL end = FALSE, error;
1367 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1369 if (xmlstr_cmp(&attr_name, nameW))
1371 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1373 else if (xmlstr_cmp(&attr_name, typeW))
1375 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1377 else if (xmlstr_cmp(&attr_name, versionW))
1379 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1381 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1383 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1385 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1387 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1389 else if (xmlstr_cmp(&attr_name, languageW))
1391 WARN("Unsupported yet language attribute (%s)\n",
1392 debugstr_xmlstr(&attr_value));
1393 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1395 else
1397 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1398 debugstr_xmlstr(&attr_value));
1402 TRACE( "name=%s version=%s arch=%s\n",
1403 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1405 if (error || end) return end;
1406 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1409 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1411 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1412 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1413 static const WCHAR freeW[] = {'F','r','e','e',0};
1414 static const WCHAR bothW[] = {'B','o','t','h',0};
1416 if (value->len == 0) return ThreadingModel_No;
1417 if (xmlstr_cmp(value, apartW))
1418 return ThreadingModel_Apartment;
1419 else if (xmlstr_cmp(value, freeW))
1420 return ThreadingModel_Free;
1421 else if (xmlstr_cmp(value, bothW))
1422 return ThreadingModel_Both;
1423 else if (xmlstr_cmp(value, neutralW))
1424 return ThreadingModel_Neutral;
1425 else
1426 return ThreadingModel_No;
1429 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1431 int min, max;
1433 min = 0;
1434 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1436 while (min <= max)
1438 int n, c;
1440 n = (min+max)/2;
1442 c = strncmpW(olemisc_values[n].name, str, len);
1443 if (!c && !olemisc_values[n].name[len])
1444 return olemisc_values[n].value;
1446 if (c >= 0)
1447 max = n-1;
1448 else
1449 min = n+1;
1452 WARN("unknown flag %s\n", debugstr_wn(str, len));
1453 return 0;
1456 static DWORD parse_com_class_misc(const xmlstr_t *value)
1458 const WCHAR *str = value->ptr, *start;
1459 DWORD flags = 0;
1460 int i = 0;
1462 /* it's comma separated list of flags */
1463 while (i < value->len)
1465 start = str;
1466 while (*str != ',' && (i++ < value->len)) str++;
1468 flags |= get_olemisc_value(start, str-start);
1470 /* skip separator */
1471 str++;
1472 i++;
1475 return flags;
1478 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1480 struct progids *progids = &entity->u.comclass.progids;
1482 if (progids->allocated == 0)
1484 progids->allocated = 4;
1485 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1488 if (progids->allocated == progids->num)
1490 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids,
1491 2 * progids->allocated * sizeof(WCHAR*));
1492 if (!new_progids) return FALSE;
1493 progids->allocated *= 2;
1494 progids->progids = new_progids;
1497 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1498 progids->num++;
1500 return TRUE;
1503 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1505 xmlstr_t content;
1506 BOOL end = FALSE;
1508 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1509 return FALSE;
1511 if (!com_class_add_progid(&content, entity)) return FALSE;
1512 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1515 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1517 xmlstr_t elem, attr_name, attr_value;
1518 BOOL ret = TRUE, end = FALSE, error;
1519 struct entity* entity;
1521 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1522 return FALSE;
1524 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1526 if (xmlstr_cmp(&attr_name, clsidW))
1528 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1530 else if (xmlstr_cmp(&attr_name, progidW))
1532 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1534 else if (xmlstr_cmp(&attr_name, tlbidW))
1536 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1538 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1540 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1542 else if (xmlstr_cmp(&attr_name, miscstatusW))
1544 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1546 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1548 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1550 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1552 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1554 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1556 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1558 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1560 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1562 else if (xmlstr_cmp(&attr_name, descriptionW))
1564 /* not stored */
1566 else
1568 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1572 if (error) return FALSE;
1574 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1575 if (entity->u.comclass.progid)
1576 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1578 if (end) return TRUE;
1580 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1582 if (xmlstr_cmp_end(&elem, comClassW))
1584 ret = parse_end_element(xmlbuf);
1585 break;
1587 else if (xmlstr_cmp(&elem, progidW))
1589 ret = parse_com_class_progid(xmlbuf, entity);
1591 else
1593 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1594 ret = parse_unknown_elem(xmlbuf, &elem);
1598 if (entity->u.comclass.progids.num)
1599 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1601 return ret;
1604 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1606 const WCHAR *curr;
1607 ULONG num = 0;
1609 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1611 if (*curr >= '0' && *curr <= '9')
1612 num = num * 10 + *curr - '0';
1613 else
1615 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1616 return FALSE;
1619 entity->u.ifaceps.nummethods = num;
1621 return TRUE;
1624 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1626 xmlstr_t attr_name, attr_value;
1627 BOOL end = FALSE, error;
1628 struct entity* entity;
1630 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1631 return FALSE;
1633 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1635 if (xmlstr_cmp(&attr_name, iidW))
1637 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1639 else if (xmlstr_cmp(&attr_name, nameW))
1641 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1643 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1645 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1646 entity->u.ifaceps.mask |= BaseIface;
1648 else if (xmlstr_cmp(&attr_name, nummethodsW))
1650 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1651 entity->u.ifaceps.mask |= NumMethods;
1653 else if (xmlstr_cmp(&attr_name, tlbidW))
1655 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1657 /* not used */
1658 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1661 else
1663 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1667 if (error) return FALSE;
1668 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1669 if (end) return TRUE;
1671 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1674 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1676 WORD *flags = &entity->u.typelib.flags;
1677 const WCHAR *str = value->ptr, *start;
1678 int i = 0;
1680 *flags = 0;
1682 /* it's comma separated list of flags */
1683 while (i < value->len)
1685 start = str;
1686 while (*str != ',' && (i++ < value->len)) str++;
1688 if (!strncmpiW(start, restrictedW, str-start))
1689 *flags |= LIBFLAG_FRESTRICTED;
1690 else if (!strncmpiW(start, controlW, str-start))
1691 *flags |= LIBFLAG_FCONTROL;
1692 else if (!strncmpiW(start, hiddenW, str-start))
1693 *flags |= LIBFLAG_FHIDDEN;
1694 else if (!strncmpiW(start, hasdiskimageW, str-start))
1695 *flags |= LIBFLAG_FHASDISKIMAGE;
1696 else
1698 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1699 return FALSE;
1702 /* skip separator */
1703 str++;
1704 i++;
1707 return TRUE;
1710 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1712 unsigned int ver[2];
1713 unsigned int pos;
1714 const WCHAR *curr;
1716 /* major.minor */
1717 ver[0] = ver[1] = pos = 0;
1718 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1720 if (*curr >= '0' && *curr <= '9')
1722 ver[pos] = ver[pos] * 10 + *curr - '0';
1723 if (ver[pos] >= 0x10000) goto error;
1725 else if (*curr == '.')
1727 if (++pos >= 2) goto error;
1729 else goto error;
1731 entity->u.typelib.major = ver[0];
1732 entity->u.typelib.minor = ver[1];
1733 return TRUE;
1735 error:
1736 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1737 return FALSE;
1740 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1742 xmlstr_t attr_name, attr_value;
1743 BOOL end = FALSE, error;
1744 struct entity* entity;
1746 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1747 return FALSE;
1749 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1751 if (xmlstr_cmp(&attr_name, tlbidW))
1753 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1755 else if (xmlstr_cmp(&attr_name, versionW))
1757 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1759 else if (xmlstr_cmp(&attr_name, helpdirW))
1761 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1763 else if (xmlstr_cmp(&attr_name, flagsW))
1765 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1767 else
1769 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1773 if (error) return FALSE;
1775 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1777 if (end) return TRUE;
1779 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1782 static inline int aligned_string_len(int len)
1784 return (len + 3) & ~3;
1787 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1789 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1790 struct assembly_version *ver = &assembly->id.version;
1791 WCHAR buff[25];
1793 if (!ret) ret = buff;
1794 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1797 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1799 xmlstr_t elem, content, attr_name, attr_value;
1800 BOOL end = FALSE, ret = TRUE, error;
1801 struct entity* entity;
1803 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1804 return FALSE;
1806 entity->u.class.versioned = TRUE;
1807 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1809 if (xmlstr_cmp(&attr_name, versionedW))
1811 if (xmlstr_cmpi(&attr_value, noW))
1812 entity->u.class.versioned = FALSE;
1813 else if (!xmlstr_cmpi(&attr_value, yesW))
1814 return FALSE;
1816 else
1818 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1822 if (error || end) return end;
1824 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1826 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1828 acl->actctx->sections |= WINDOWCLASS_SECTION;
1830 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1832 if (xmlstr_cmp_end(&elem, windowClassW))
1834 ret = parse_end_element(xmlbuf);
1835 break;
1837 else
1839 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1840 ret = parse_unknown_elem(xmlbuf, &elem);
1844 return ret;
1847 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1849 xmlstr_t attr_name, attr_value;
1850 BOOL end = FALSE, error;
1852 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1854 if (xmlstr_cmp(&attr_name, oldVersionW))
1856 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1858 else if (xmlstr_cmp(&attr_name, newVersionW))
1860 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1862 else
1864 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1868 if (error || end) return end;
1869 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1872 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1874 xmlstr_t elem, content, attr_name, attr_value;
1875 BOOL end = FALSE, ret = TRUE, error = FALSE;
1877 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1878 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1880 if (error) return FALSE;
1881 if (end) return TRUE;
1883 if (!parse_text_content(xmlbuf, &content))
1884 return FALSE;
1886 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1888 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1890 if (xmlstr_cmp_end(&elem, descriptionW))
1892 ret = parse_end_element(xmlbuf);
1893 break;
1895 else
1897 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1898 ret = parse_unknown_elem(xmlbuf, &elem);
1902 return ret;
1905 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1906 struct assembly* assembly,
1907 struct actctx_loader* acl)
1909 xmlstr_t attr_name, attr_value;
1910 BOOL end = FALSE, error;
1911 struct entity* entity;
1913 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1914 if (!entity) return FALSE;
1916 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1918 if (xmlstr_cmp(&attr_name, iidW))
1920 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1922 else if (xmlstr_cmp(&attr_name, nameW))
1924 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1926 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1928 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1929 entity->u.ifaceps.mask |= BaseIface;
1931 else if (xmlstr_cmp(&attr_name, nummethodsW))
1933 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1934 entity->u.ifaceps.mask |= NumMethods;
1936 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1938 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1940 else if (xmlstr_cmp(&attr_name, tlbidW))
1942 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1944 else
1946 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1950 if (error) return FALSE;
1951 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1952 if (end) return TRUE;
1954 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1957 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1959 xmlstr_t attr_name, attr_value, elem;
1960 BOOL end = FALSE, error, ret = TRUE;
1961 struct entity* entity;
1963 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1964 if (!entity) return FALSE;
1966 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1968 if (xmlstr_cmp(&attr_name, nameW))
1970 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1972 else if (xmlstr_cmp(&attr_name, clsidW))
1974 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1976 else if (xmlstr_cmp(&attr_name, progidW))
1978 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1980 else if (xmlstr_cmp(&attr_name, tlbidW))
1982 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1984 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1986 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1988 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1990 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1992 else
1994 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1998 if (error) return FALSE;
1999 acl->actctx->sections |= SERVERREDIRECT_SECTION;
2000 if (entity->u.comclass.progid)
2001 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2002 if (end) return TRUE;
2004 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2006 if (xmlstr_cmp_end(&elem, clrClassW))
2008 ret = parse_end_element(xmlbuf);
2009 break;
2011 else if (xmlstr_cmp(&elem, progidW))
2013 ret = parse_com_class_progid(xmlbuf, entity);
2015 else
2017 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2018 ret = parse_unknown_elem(xmlbuf, &elem);
2022 if (entity->u.comclass.progids.num)
2023 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
2025 return ret;
2028 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2030 xmlstr_t attr_name, attr_value;
2031 BOOL end = FALSE, error;
2032 struct entity* entity;
2034 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
2035 if (!entity) return FALSE;
2037 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2039 if (xmlstr_cmp(&attr_name, nameW))
2041 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2043 else if (xmlstr_cmp(&attr_name, clsidW))
2045 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2047 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2049 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2051 else
2053 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2057 if (error) return FALSE;
2058 acl->actctx->sections |= CLRSURROGATES_SECTION;
2059 if (end) return TRUE;
2061 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2064 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2066 struct assembly_identity ai;
2067 xmlstr_t elem, attr_name, attr_value;
2068 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2070 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2072 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2073 static const WCHAR trueW[] = {'t','r','u','e',0};
2075 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2076 delayed = xmlstr_cmp(&attr_value, trueW);
2077 else
2078 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2081 if (error || end) return end;
2083 memset(&ai, 0, sizeof(ai));
2084 ai.optional = optional;
2085 ai.delayed = delayed;
2087 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2088 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2089 return FALSE;
2091 TRACE( "adding name=%s version=%s arch=%s\n",
2092 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2094 /* store the newly found identity for later loading */
2095 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2097 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2099 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2101 ret = parse_end_element(xmlbuf);
2102 break;
2104 else if (xmlstr_cmp(&elem, bindingRedirectW))
2106 ret = parse_binding_redirect_elem(xmlbuf);
2108 else
2110 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2111 ret = parse_unknown_elem(xmlbuf, &elem);
2115 return ret;
2118 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2120 xmlstr_t attr_name, attr_value, elem;
2121 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2123 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2125 if (xmlstr_cmp(&attr_name, optionalW))
2127 optional = xmlstr_cmpi( &attr_value, yesW );
2128 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2130 else
2132 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2136 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2138 if (xmlstr_cmp_end(&elem, dependencyW))
2140 ret = parse_end_element(xmlbuf);
2141 break;
2143 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2145 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2147 else
2149 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2150 ret = parse_unknown_elem(xmlbuf, &elem);
2154 return ret;
2157 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2159 BOOL end = FALSE;
2161 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2162 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2165 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2167 BOOL end = FALSE;
2169 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2170 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2173 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2175 xmlstr_t attr_name, attr_value, elem;
2176 BOOL end = FALSE, error, ret = TRUE;
2177 struct dll_redirect* dll;
2179 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2181 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2183 if (xmlstr_cmp(&attr_name, nameW))
2185 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2186 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2188 else if (xmlstr_cmp(&attr_name, hashW))
2190 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2192 else if (xmlstr_cmp(&attr_name, hashalgW))
2194 static const WCHAR sha1W[] = {'S','H','A','1',0};
2195 if (!xmlstr_cmpi(&attr_value, sha1W))
2196 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2198 else
2200 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2204 if (error || !dll->name) return FALSE;
2206 acl->actctx->sections |= DLLREDIRECT_SECTION;
2208 if (end) return TRUE;
2210 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2212 if (xmlstr_cmp_end(&elem, fileW))
2214 ret = parse_end_element(xmlbuf);
2215 break;
2217 else if (xmlstr_cmp(&elem, comClassW))
2219 ret = parse_com_class_elem(xmlbuf, dll, acl);
2221 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2223 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2225 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2227 WARN("asmv2:hash (undocumented) not supported\n");
2228 ret = parse_unknown_elem(xmlbuf, &elem);
2230 else if (xmlstr_cmp(&elem, typelibW))
2232 ret = parse_typelib_elem(xmlbuf, dll, acl);
2234 else if (xmlstr_cmp(&elem, windowClassW))
2236 ret = parse_window_class_elem(xmlbuf, dll, acl);
2238 else
2240 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2241 ret = parse_unknown_elem( xmlbuf, &elem );
2245 return ret;
2248 static BOOL parse_supportedos_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2250 xmlstr_t attr_name, attr_value;
2251 BOOL end = FALSE, error;
2253 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2255 if (xmlstr_cmp(&attr_name, IdW))
2257 COMPATIBILITY_CONTEXT_ELEMENT *compat;
2258 UNICODE_STRING str;
2259 GUID compat_id;
2261 str.Buffer = (PWSTR)attr_value.ptr;
2262 str.Length = str.MaximumLength = (USHORT)attr_value.len * sizeof(WCHAR);
2263 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS)
2265 if (!(compat = add_compat_context(assembly))) return FALSE;
2266 compat->Type = ACTCX_COMPATIBILITY_ELEMENT_TYPE_OS;
2267 compat->Id = compat_id;
2269 else
2271 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr_value));
2274 else
2276 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
2277 debugstr_xmlstr(&attr_value));
2281 if (error) return FALSE;
2282 if (end) return TRUE;
2284 return parse_expect_end_elem(xmlbuf, supportedOSW, asmv1W);
2287 static BOOL parse_compatibility_application_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2288 struct actctx_loader* acl)
2290 BOOL ret = TRUE;
2291 xmlstr_t elem;
2293 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2295 if (xmlstr_cmp_end(&elem, applicationW))
2297 ret = parse_end_element(xmlbuf);
2298 break;
2300 else if (xmlstr_cmp(&elem, supportedOSW))
2302 ret = parse_supportedos_elem(xmlbuf, assembly, acl);
2304 else
2306 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2307 ret = parse_unknown_elem(xmlbuf, &elem);
2311 return ret;
2314 static BOOL parse_compatibility_elem(xmlbuf_t* xmlbuf, struct assembly* assembly,
2315 struct actctx_loader* acl)
2317 xmlstr_t elem;
2318 BOOL ret = TRUE;
2320 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2322 if (xmlstr_cmp_end(&elem, compatibilityW))
2324 ret = parse_end_element(xmlbuf);
2325 break;
2327 else if (xmlstr_cmp(&elem, applicationW))
2329 ret = parse_compatibility_application_elem(xmlbuf, assembly, acl);
2331 else
2333 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2334 ret = parse_unknown_elem(xmlbuf, &elem);
2337 return ret;
2340 static BOOL parse_requested_execution_level_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
2342 static const WCHAR levelW[] = {'l','e','v','e','l',0};
2343 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0};
2344 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};
2345 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
2346 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0};
2347 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2348 static const WCHAR trueW[] = {'t','r','u','e',0};
2350 xmlstr_t attr_name, attr_value, elem;
2351 BOOL end = FALSE, ret = TRUE, error;
2353 /* Multiple requestedExecutionLevel elements are not supported. */
2354 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED)
2355 return FALSE;
2357 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2359 if (xmlstr_cmp(&attr_name, levelW))
2361 if (xmlstr_cmpi(&attr_value, asInvokerW))
2362 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER;
2363 else if (xmlstr_cmpi(&attr_value, highestAvailableW))
2364 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE;
2365 else if (xmlstr_cmpi(&attr_value, requireAdministratorW))
2366 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN;
2367 else
2368 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr_value));
2370 else if (xmlstr_cmp(&attr_name, uiAccessW))
2372 if (xmlstr_cmpi(&attr_value, falseW))
2373 assembly->ui_access = FALSE;
2374 else if (xmlstr_cmpi(&attr_value, trueW))
2375 assembly->ui_access = TRUE;
2376 else
2377 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr_value));
2379 else
2380 FIXME("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2383 if (error) return FALSE;
2384 if (end) return TRUE;
2386 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2388 if (xmlstr_cmp_end(&elem, requestedExecutionLevelW))
2390 ret = parse_end_element(xmlbuf);
2391 break;
2393 else
2395 FIXME("unknown element %s\n", debugstr_xmlstr(&elem));
2396 ret = parse_unknown_elem(xmlbuf, &elem);
2400 return ret;
2403 static BOOL parse_requested_privileges_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, 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, requestedPrivilegesW))
2412 ret = parse_end_element(xmlbuf);
2413 break;
2415 else if (xmlstr_cmp(&elem, requestedExecutionLevelW))
2416 ret = parse_requested_execution_level_elem(xmlbuf, assembly, acl);
2417 else
2419 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2420 ret = parse_unknown_elem(xmlbuf, &elem);
2424 return ret;
2427 static BOOL parse_security_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2429 xmlstr_t elem;
2430 BOOL ret = TRUE;
2432 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2434 if (xmlstr_cmp_end(&elem, securityW))
2436 ret = parse_end_element(xmlbuf);
2437 break;
2439 else if (xmlstr_cmp(&elem, requestedPrivilegesW))
2440 ret = parse_requested_privileges_elem(xmlbuf, assembly, acl);
2441 else
2443 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2444 ret = parse_unknown_elem(xmlbuf, &elem);
2448 return ret;
2451 static BOOL parse_trust_info_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl)
2453 xmlstr_t elem;
2454 BOOL ret = TRUE;
2456 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2458 if (xmlstr_cmp_end(&elem, trustInfoW))
2460 ret = parse_end_element(xmlbuf);
2461 break;
2463 else if (xmlstr_cmp(&elem, securityW))
2464 ret = parse_security_elem(xmlbuf, assembly, acl);
2465 else
2467 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2468 ret = parse_unknown_elem(xmlbuf, &elem);
2472 return ret;
2475 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2476 struct assembly* assembly,
2477 struct assembly_identity* expected_ai)
2479 xmlstr_t attr_name, attr_value, elem;
2480 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2482 TRACE("(%p)\n", xmlbuf);
2484 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2486 if (xmlstr_cmp(&attr_name, manifestVersionW))
2488 static const WCHAR v10W[] = {'1','.','0',0};
2489 if (!xmlstr_cmp(&attr_value, v10W))
2491 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2492 return FALSE;
2494 version = TRUE;
2496 else if (xmlstr_cmp(&attr_name, xmlnsW))
2498 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2499 !xmlstr_cmp(&attr_value, manifestv2W) &&
2500 !xmlstr_cmp(&attr_value, manifestv3W))
2502 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2503 return FALSE;
2505 xmlns = TRUE;
2507 else
2509 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2513 if (error || end || !xmlns || !version) return FALSE;
2514 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2516 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2518 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2519 return FALSE;
2520 assembly->no_inherit = TRUE;
2523 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2525 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2526 return FALSE;
2528 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2529 assembly->no_inherit)
2530 return FALSE;
2532 while (ret)
2534 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2536 ret = parse_end_element(xmlbuf);
2537 break;
2539 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2541 ret = parse_description_elem(xmlbuf);
2543 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2545 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2547 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2549 ret = parse_dependency_elem(xmlbuf, acl);
2551 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2553 ret = parse_file_elem(xmlbuf, assembly, acl);
2555 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2557 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2559 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2561 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2563 else if (xml_elem_cmp(&elem, trustInfoW, asmv2W) ||
2564 xml_elem_cmp(&elem, trustInfoW, asmv1W))
2566 ret = parse_trust_info_elem(xmlbuf, assembly, acl);
2568 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2570 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2572 if (expected_ai)
2574 /* FIXME: more tests */
2575 if (assembly->type == ASSEMBLY_MANIFEST &&
2576 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2578 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2579 expected_ai->version.major, expected_ai->version.minor,
2580 expected_ai->version.build, expected_ai->version.revision,
2581 assembly->id.version.major, assembly->id.version.minor,
2582 assembly->id.version.build, assembly->id.version.revision);
2583 ret = FALSE;
2585 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2586 (assembly->id.version.major != expected_ai->version.major ||
2587 assembly->id.version.minor != expected_ai->version.minor ||
2588 assembly->id.version.build < expected_ai->version.build ||
2589 (assembly->id.version.build == expected_ai->version.build &&
2590 assembly->id.version.revision < expected_ai->version.revision)))
2592 FIXME("wrong version for shared assembly manifest\n");
2593 ret = FALSE;
2597 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW))
2599 ret = parse_compatibility_elem(xmlbuf, assembly, acl);
2601 else
2603 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2604 ret = parse_unknown_elem(xmlbuf, &elem);
2606 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2609 return ret;
2612 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2613 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2615 xmlstr_t elem;
2617 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2619 if (xmlstr_cmp(&elem, xmlW) &&
2620 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2621 return STATUS_SXS_CANT_GEN_ACTCTX;
2623 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2625 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2626 return STATUS_SXS_CANT_GEN_ACTCTX;
2629 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2631 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2632 return STATUS_SXS_CANT_GEN_ACTCTX;
2635 if (next_xml_elem(xmlbuf, &elem))
2637 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2638 return STATUS_SXS_CANT_GEN_ACTCTX;
2641 if (xmlbuf->ptr != xmlbuf->end)
2643 FIXME("parse error\n");
2644 return STATUS_SXS_CANT_GEN_ACTCTX;
2646 return STATUS_SUCCESS;
2649 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2650 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2651 const void *buffer, SIZE_T size )
2653 xmlbuf_t xmlbuf;
2654 NTSTATUS status;
2655 struct assembly *assembly;
2656 int unicode_tests;
2658 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2660 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2661 return STATUS_SXS_CANT_GEN_ACTCTX;
2663 if (directory && !(assembly->directory = strdupW(directory)))
2664 return STATUS_NO_MEMORY;
2666 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2667 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2668 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2670 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2671 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2673 xmlbuf.ptr = buffer;
2674 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2675 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2677 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2679 const WCHAR *buf = buffer;
2680 WCHAR *new_buff;
2681 unsigned int i;
2683 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2684 return STATUS_NO_MEMORY;
2685 for (i = 0; i < size / sizeof(WCHAR); i++)
2686 new_buff[i] = RtlUshortByteSwap( buf[i] );
2687 xmlbuf.ptr = new_buff;
2688 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2689 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2690 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2692 else
2694 /* let's assume utf-8 for now */
2695 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2696 WCHAR *new_buff;
2698 if (len == -1)
2700 FIXME( "utf-8 conversion failed\n" );
2701 return STATUS_SXS_CANT_GEN_ACTCTX;
2703 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2704 return STATUS_NO_MEMORY;
2705 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2706 xmlbuf.ptr = new_buff;
2707 xmlbuf.end = xmlbuf.ptr + len;
2708 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2709 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2711 return status;
2714 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2716 OBJECT_ATTRIBUTES attr;
2717 IO_STATUS_BLOCK io;
2719 attr.Length = sizeof(attr);
2720 attr.RootDirectory = 0;
2721 attr.Attributes = OBJ_CASE_INSENSITIVE;
2722 attr.ObjectName = name;
2723 attr.SecurityDescriptor = NULL;
2724 attr.SecurityQualityOfService = NULL;
2725 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2728 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2730 NTSTATUS status;
2731 ULONG_PTR magic;
2732 LDR_MODULE *pldr;
2734 LdrLockLoaderLock(0, NULL, &magic);
2735 status = LdrFindEntryForAddress( module, &pldr );
2736 if (status == STATUS_SUCCESS)
2738 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2739 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2741 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2742 str->Length = pldr->FullDllName.Length;
2743 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2745 else status = STATUS_NO_MEMORY;
2747 LdrUnlockLoaderLock(0, magic);
2748 return status;
2751 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2752 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2753 HANDLE hModule, LPCWSTR resname, ULONG lang )
2755 NTSTATUS status;
2756 UNICODE_STRING nameW;
2757 LDR_RESOURCE_INFO info;
2758 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2759 void *ptr;
2761 if (TRACE_ON(actctx))
2763 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2765 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2766 hModule, debugstr_w(nameW.Buffer) );
2767 RtlFreeUnicodeString( &nameW );
2769 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2770 hModule, debugstr_w(filename) );
2773 if (!resname) return STATUS_INVALID_PARAMETER;
2775 info.Type = RT_MANIFEST;
2776 info.Language = lang;
2777 if (!((ULONG_PTR)resname >> 16))
2779 info.Name = (ULONG_PTR)resname;
2780 status = LdrFindResource_U(hModule, &info, 3, &entry);
2782 else if (resname[0] == '#')
2784 ULONG value;
2785 RtlInitUnicodeString(&nameW, resname + 1);
2786 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2787 return STATUS_INVALID_PARAMETER;
2788 info.Name = value;
2789 status = LdrFindResource_U(hModule, &info, 3, &entry);
2791 else
2793 RtlCreateUnicodeString(&nameW, resname);
2794 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2795 info.Name = (ULONG_PTR)nameW.Buffer;
2796 status = LdrFindResource_U(hModule, &info, 3, &entry);
2797 RtlFreeUnicodeString(&nameW);
2799 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2801 if (status == STATUS_SUCCESS)
2802 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2804 return status;
2807 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2808 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2809 HANDLE file, LPCWSTR resname, ULONG lang )
2811 HANDLE mapping;
2812 OBJECT_ATTRIBUTES attr;
2813 LARGE_INTEGER size;
2814 LARGE_INTEGER offset;
2815 NTSTATUS status;
2816 SIZE_T count;
2817 void *base;
2819 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2821 attr.Length = sizeof(attr);
2822 attr.RootDirectory = 0;
2823 attr.ObjectName = NULL;
2824 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2825 attr.SecurityDescriptor = NULL;
2826 attr.SecurityQualityOfService = NULL;
2828 size.QuadPart = 0;
2829 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2830 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2831 if (status != STATUS_SUCCESS) return status;
2833 offset.QuadPart = 0;
2834 count = 0;
2835 base = NULL;
2836 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2837 &count, ViewShare, 0, PAGE_READONLY );
2838 NtClose( mapping );
2839 if (status != STATUS_SUCCESS) return status;
2841 if (RtlImageNtHeader(base)) /* we got a PE file */
2843 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2844 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2846 else status = STATUS_INVALID_IMAGE_FORMAT;
2848 NtUnmapViewOfSection( GetCurrentProcess(), base );
2849 return status;
2852 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2853 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2855 FILE_END_OF_FILE_INFORMATION info;
2856 IO_STATUS_BLOCK io;
2857 HANDLE mapping;
2858 OBJECT_ATTRIBUTES attr;
2859 LARGE_INTEGER size;
2860 LARGE_INTEGER offset;
2861 NTSTATUS status;
2862 SIZE_T count;
2863 void *base;
2865 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2867 attr.Length = sizeof(attr);
2868 attr.RootDirectory = 0;
2869 attr.ObjectName = NULL;
2870 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2871 attr.SecurityDescriptor = NULL;
2872 attr.SecurityQualityOfService = NULL;
2874 size.QuadPart = 0;
2875 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2876 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2877 if (status != STATUS_SUCCESS) return status;
2879 offset.QuadPart = 0;
2880 count = 0;
2881 base = NULL;
2882 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2883 &count, ViewShare, 0, PAGE_READONLY );
2884 NtClose( mapping );
2885 if (status != STATUS_SUCCESS) return status;
2887 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2888 if (status == STATUS_SUCCESS)
2889 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2891 NtUnmapViewOfSection( GetCurrentProcess(), base );
2892 return status;
2895 /* try to load the .manifest file associated to the file */
2896 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2897 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2899 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2900 WCHAR *buffer;
2901 NTSTATUS status;
2902 UNICODE_STRING nameW;
2903 HANDLE file;
2904 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2906 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2908 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2910 if (module) /* use the module filename */
2912 UNICODE_STRING name;
2914 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2916 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2917 strcatW( name.Buffer, dotManifestW );
2918 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2919 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2920 RtlFreeUnicodeString( &name );
2922 if (status) return status;
2924 else
2926 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2927 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2928 return STATUS_NO_MEMORY;
2929 strcpyW( buffer, filename );
2930 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2931 strcatW( buffer, dotManifestW );
2932 RtlInitUnicodeString( &nameW, buffer );
2935 if (!open_nt_file( &file, &nameW ))
2937 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2938 NtClose( file );
2940 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2941 RtlFreeUnicodeString( &nameW );
2942 return status;
2945 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2947 static const WCHAR lookup_fmtW[] =
2948 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2949 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2950 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2952 WCHAR *lookup, *ret = NULL;
2953 UNICODE_STRING lookup_us;
2954 IO_STATUS_BLOCK io;
2955 const WCHAR *lang = ai->language;
2956 unsigned int data_pos = 0, data_len;
2957 char buffer[8192];
2959 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2960 (strlenW(ai->arch) + strlenW(ai->name)
2961 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2962 + sizeof(lookup_fmtW) )))
2963 return NULL;
2965 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2966 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2967 ai->version.major, ai->version.minor, lang );
2968 RtlInitUnicodeString( &lookup_us, lookup );
2970 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2971 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2973 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2974 FILE_BOTH_DIR_INFORMATION *dir_info;
2975 WCHAR *tmp;
2976 ULONG build, revision;
2978 data_len = io.Information;
2980 for (;;)
2982 if (data_pos >= data_len)
2984 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2985 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2986 break;
2987 data_len = io.Information;
2988 data_pos = 0;
2990 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2992 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2993 else data_pos = data_len;
2995 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2996 build = atoiW(tmp);
2997 if (build < min_build) continue;
2998 tmp = strchrW(tmp, '.') + 1;
2999 revision = atoiW(tmp);
3000 if (build == min_build && revision < min_revision) continue;
3001 tmp = strchrW(tmp, '_') + 1;
3002 tmp = strchrW(tmp, '_') + 1;
3003 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
3004 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
3006 /* prefer a non-Wine manifest if we already have one */
3007 /* we'll still load the builtin dll if specified through DllOverrides */
3008 if (ret) continue;
3010 else
3012 min_build = build;
3013 min_revision = revision;
3015 ai->version.build = build;
3016 ai->version.revision = revision;
3017 RtlFreeHeap( GetProcessHeap(), 0, ret );
3018 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
3020 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
3021 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
3025 else WARN("no matching file for %s\n", debugstr_w(lookup));
3026 RtlFreeHeap( GetProcessHeap(), 0, lookup );
3027 return ret;
3030 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
3032 struct assembly_identity sxs_ai;
3033 UNICODE_STRING path_us;
3034 OBJECT_ATTRIBUTES attr;
3035 IO_STATUS_BLOCK io;
3036 WCHAR *path, *file = NULL;
3037 HANDLE handle;
3039 static const WCHAR manifest_dirW[] =
3040 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
3042 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
3044 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
3045 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
3046 return STATUS_NO_MEMORY;
3048 strcpyW( path, user_shared_data->NtSystemRoot );
3049 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
3051 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
3053 RtlFreeHeap( GetProcessHeap(), 0, path );
3054 return STATUS_NO_SUCH_FILE;
3056 RtlFreeHeap( GetProcessHeap(), 0, path );
3058 attr.Length = sizeof(attr);
3059 attr.RootDirectory = 0;
3060 attr.Attributes = OBJ_CASE_INSENSITIVE;
3061 attr.ObjectName = &path_us;
3062 attr.SecurityDescriptor = NULL;
3063 attr.SecurityQualityOfService = NULL;
3065 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
3066 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
3068 sxs_ai = *ai;
3069 file = lookup_manifest_file( handle, &sxs_ai );
3070 NtClose( handle );
3072 if (!file)
3074 RtlFreeUnicodeString( &path_us );
3075 return STATUS_NO_SUCH_FILE;
3078 /* append file name to directory path */
3079 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
3080 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
3082 RtlFreeHeap( GetProcessHeap(), 0, file );
3083 RtlFreeUnicodeString( &path_us );
3084 return STATUS_NO_MEMORY;
3087 path[path_us.Length/sizeof(WCHAR)] = '\\';
3088 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
3089 RtlInitUnicodeString( &path_us, path );
3090 *strrchrW(file, '.') = 0; /* remove .manifest extension */
3092 if (!open_nt_file( &handle, &path_us ))
3094 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
3095 NtClose( handle );
3097 else io.u.Status = STATUS_NO_SUCH_FILE;
3099 RtlFreeHeap( GetProcessHeap(), 0, file );
3100 RtlFreeUnicodeString( &path_us );
3101 return io.u.Status;
3104 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
3105 struct assembly_identity* ai)
3107 static const WCHAR dotDllW[] = {'.','d','l','l',0};
3108 unsigned int i;
3109 WCHAR *buffer, *p, *directory;
3110 NTSTATUS status;
3111 UNICODE_STRING nameW;
3112 HANDLE file;
3113 DWORD len;
3115 TRACE( "looking for name=%s version=%s arch=%s\n",
3116 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
3118 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
3120 /* FIXME: add support for language specific lookup */
3122 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
3123 strlenW(acl->actctx->appdir.info));
3125 nameW.Buffer = NULL;
3126 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
3127 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
3128 return STATUS_NO_MEMORY;
3130 if (!(directory = build_assembly_dir( ai )))
3132 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3133 return STATUS_NO_MEMORY;
3136 /* Lookup in <dir>\name.dll
3137 * <dir>\name.manifest
3138 * <dir>\name\name.dll
3139 * <dir>\name\name.manifest
3141 * First 'appdir' is used as <dir>, if that failed
3142 * it tries application manifest file path.
3144 strcpyW( buffer, acl->actctx->appdir.info );
3145 p = buffer + strlenW(buffer);
3146 for (i = 0; i < 4; i++)
3148 if (i == 2)
3150 struct assembly *assembly = acl->actctx->assemblies;
3151 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
3153 else *p++ = '\\';
3155 strcpyW( p, ai->name );
3156 p += strlenW(p);
3158 strcpyW( p, dotDllW );
3159 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3161 status = open_nt_file( &file, &nameW );
3162 if (!status)
3164 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
3165 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
3166 NtClose( file );
3167 break;
3169 RtlFreeUnicodeString( &nameW );
3172 strcpyW( p, dotManifestW );
3173 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
3175 status = open_nt_file( &file, &nameW );
3176 if (!status)
3178 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
3179 NtClose( file );
3180 break;
3182 RtlFreeUnicodeString( &nameW );
3184 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
3186 RtlFreeUnicodeString( &nameW );
3187 RtlFreeHeap( GetProcessHeap(), 0, directory );
3188 RtlFreeHeap( GetProcessHeap(), 0, buffer );
3189 return status;
3192 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
3194 NTSTATUS status = STATUS_SUCCESS;
3195 unsigned int i;
3197 for (i = 0; i < acl->num_dependencies; i++)
3199 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
3201 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
3203 FIXME( "Could not find dependent assembly %s (%s)\n",
3204 debugstr_w(acl->dependencies[i].name),
3205 debugstr_version(&acl->dependencies[i].version) );
3206 status = STATUS_SXS_CANT_GEN_ACTCTX;
3207 break;
3211 /* FIXME should now iterate through all refs */
3212 return status;
3215 /* find the appropriate activation context for RtlQueryInformationActivationContext */
3216 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
3218 NTSTATUS status = STATUS_SUCCESS;
3220 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
3222 if (*handle) return STATUS_INVALID_PARAMETER;
3224 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
3225 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
3227 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
3229 ULONG_PTR magic;
3230 LDR_MODULE *pldr;
3232 if (!*handle) return STATUS_INVALID_PARAMETER;
3234 LdrLockLoaderLock( 0, NULL, &magic );
3235 if (!LdrFindEntryForAddress( *handle, &pldr ))
3237 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
3238 status = STATUS_DLL_NOT_FOUND;
3239 else
3240 *handle = pldr->ActivationContext;
3242 else status = STATUS_DLL_NOT_FOUND;
3243 LdrUnlockLoaderLock( 0, magic );
3245 else if (!*handle && (class != ActivationContextBasicInformation))
3246 *handle = process_actctx;
3248 return status;
3251 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3253 unsigned int i, j, total_len = 0, dll_count = 0;
3254 struct strsection_header *header;
3255 struct dllredirect_data *data;
3256 struct string_index *index;
3257 ULONG name_offset;
3259 /* compute section length */
3260 for (i = 0; i < actctx->num_assemblies; i++)
3262 struct assembly *assembly = &actctx->assemblies[i];
3263 for (j = 0; j < assembly->num_dlls; j++)
3265 struct dll_redirect *dll = &assembly->dlls[j];
3267 /* each entry needs index, data and string data */
3268 total_len += sizeof(*index);
3269 total_len += sizeof(*data);
3270 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3273 dll_count += assembly->num_dlls;
3276 total_len += sizeof(*header);
3278 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3279 if (!header) return STATUS_NO_MEMORY;
3281 memset(header, 0, sizeof(*header));
3282 header->magic = STRSECTION_MAGIC;
3283 header->size = sizeof(*header);
3284 header->count = dll_count;
3285 header->index_offset = sizeof(*header);
3286 index = (struct string_index*)((BYTE*)header + header->index_offset);
3287 name_offset = header->index_offset + header->count*sizeof(*index);
3289 for (i = 0; i < actctx->num_assemblies; i++)
3291 struct assembly *assembly = &actctx->assemblies[i];
3292 for (j = 0; j < assembly->num_dlls; j++)
3294 struct dll_redirect *dll = &assembly->dlls[j];
3295 UNICODE_STRING str;
3296 WCHAR *ptrW;
3298 /* setup new index entry */
3299 str.Buffer = dll->name;
3300 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3301 str.MaximumLength = str.Length + sizeof(WCHAR);
3302 /* hash original class name */
3303 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3305 index->name_offset = name_offset;
3306 index->name_len = str.Length;
3307 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3308 index->data_len = sizeof(*data);
3309 index->rosterindex = i + 1;
3311 /* setup data */
3312 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3313 data->size = sizeof(*data);
3314 data->unk = 2; /* FIXME: seems to be constant */
3315 memset(data->res, 0, sizeof(data->res));
3317 /* dll name */
3318 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3319 memcpy(ptrW, dll->name, index->name_len);
3320 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3322 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3324 index++;
3328 *section = header;
3330 return STATUS_SUCCESS;
3333 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3335 struct string_index *iter, *index = NULL;
3336 ULONG hash = 0, i;
3338 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3339 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3341 for (i = 0; i < section->count; i++)
3343 if (iter->hash == hash)
3345 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3347 if (!strcmpiW(nameW, name->Buffer))
3349 index = iter;
3350 break;
3352 else
3353 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3355 iter++;
3358 return index;
3361 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3363 struct guid_index *iter, *index = NULL;
3364 ULONG i;
3366 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3368 for (i = 0; i < section->count; i++)
3370 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3372 index = iter;
3373 break;
3375 iter++;
3378 return index;
3381 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3383 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3386 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3387 PACTCTX_SECTION_KEYED_DATA data)
3389 struct dllredirect_data *dll;
3390 struct string_index *index;
3392 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3394 if (!actctx->dllredirect_section)
3396 struct strsection_header *section;
3398 NTSTATUS status = build_dllredirect_section(actctx, &section);
3399 if (status) return status;
3401 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3402 RtlFreeHeap(GetProcessHeap(), 0, section);
3405 index = find_string_index(actctx->dllredirect_section, name);
3406 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3408 if (data)
3410 dll = get_dllredirect_data(actctx, index);
3412 data->ulDataFormatVersion = 1;
3413 data->lpData = dll;
3414 data->ulLength = dll->size;
3415 data->lpSectionGlobalData = NULL;
3416 data->ulSectionGlobalDataLength = 0;
3417 data->lpSectionBase = actctx->dllredirect_section;
3418 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3419 data->hActCtx = NULL;
3421 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3422 data->ulAssemblyRosterIndex = index->rosterindex;
3425 return STATUS_SUCCESS;
3428 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3430 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3433 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3435 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3438 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3440 unsigned int i, j, k, total_len = 0, class_count = 0;
3441 struct wndclass_redirect_data *data;
3442 struct strsection_header *header;
3443 struct string_index *index;
3444 ULONG name_offset;
3446 /* compute section length */
3447 for (i = 0; i < actctx->num_assemblies; i++)
3449 struct assembly *assembly = &actctx->assemblies[i];
3450 for (j = 0; j < assembly->num_dlls; j++)
3452 struct dll_redirect *dll = &assembly->dlls[j];
3453 for (k = 0; k < dll->entities.num; k++)
3455 struct entity *entity = &dll->entities.base[k];
3456 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3458 int class_len = strlenW(entity->u.class.name) + 1;
3459 int len;
3461 /* each class entry needs index, data and string data */
3462 total_len += sizeof(*index);
3463 total_len += sizeof(*data);
3464 /* original name is stored separately */
3465 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3466 /* versioned name and module name are stored one after another */
3467 if (entity->u.class.versioned)
3468 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3469 else
3470 len = class_len;
3471 len += strlenW(dll->name) + 1;
3472 total_len += aligned_string_len(len*sizeof(WCHAR));
3474 class_count++;
3480 total_len += sizeof(*header);
3482 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3483 if (!header) return STATUS_NO_MEMORY;
3485 memset(header, 0, sizeof(*header));
3486 header->magic = STRSECTION_MAGIC;
3487 header->size = sizeof(*header);
3488 header->count = class_count;
3489 header->index_offset = sizeof(*header);
3490 index = (struct string_index*)((BYTE*)header + header->index_offset);
3491 name_offset = header->index_offset + header->count*sizeof(*index);
3493 for (i = 0; i < actctx->num_assemblies; i++)
3495 struct assembly *assembly = &actctx->assemblies[i];
3496 for (j = 0; j < assembly->num_dlls; j++)
3498 struct dll_redirect *dll = &assembly->dlls[j];
3499 for (k = 0; k < dll->entities.num; k++)
3501 struct entity *entity = &dll->entities.base[k];
3502 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3504 static const WCHAR exclW[] = {'!',0};
3505 ULONG versioned_len, module_len;
3506 UNICODE_STRING str;
3507 WCHAR *ptrW;
3509 /* setup new index entry */
3510 str.Buffer = entity->u.class.name;
3511 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3512 str.MaximumLength = str.Length + sizeof(WCHAR);
3513 /* hash original class name */
3514 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3516 /* include '!' separator too */
3517 if (entity->u.class.versioned)
3518 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3519 else
3520 versioned_len = str.Length;
3521 module_len = strlenW(dll->name)*sizeof(WCHAR);
3523 index->name_offset = name_offset;
3524 index->name_len = str.Length;
3525 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3526 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3527 index->rosterindex = i + 1;
3529 /* setup data */
3530 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3531 data->size = sizeof(*data);
3532 data->res = 0;
3533 data->name_len = versioned_len;
3534 data->name_offset = sizeof(*data);
3535 data->module_len = module_len;
3536 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3538 /* original class name */
3539 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3540 memcpy(ptrW, entity->u.class.name, index->name_len);
3541 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3543 /* module name */
3544 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3545 memcpy(ptrW, dll->name, data->module_len);
3546 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3548 /* versioned name */
3549 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3550 if (entity->u.class.versioned)
3552 get_assembly_version(assembly, ptrW);
3553 strcatW(ptrW, exclW);
3554 strcatW(ptrW, entity->u.class.name);
3556 else
3558 memcpy(ptrW, entity->u.class.name, index->name_len);
3559 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3562 name_offset += sizeof(*data);
3563 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3565 index++;
3571 *section = header;
3573 return STATUS_SUCCESS;
3576 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3577 PACTCTX_SECTION_KEYED_DATA data)
3579 struct string_index *iter, *index = NULL;
3580 struct wndclass_redirect_data *class;
3581 ULONG hash;
3582 int i;
3584 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3586 if (!actctx->wndclass_section)
3588 struct strsection_header *section;
3590 NTSTATUS status = build_wndclass_section(actctx, &section);
3591 if (status) return status;
3593 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3594 RtlFreeHeap(GetProcessHeap(), 0, section);
3597 hash = 0;
3598 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3599 iter = get_wndclass_first_index(actctx);
3601 for (i = 0; i < actctx->wndclass_section->count; i++)
3603 if (iter->hash == hash)
3605 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3607 if (!strcmpiW(nameW, name->Buffer))
3609 index = iter;
3610 break;
3612 else
3613 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3615 iter++;
3618 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3620 if (data)
3622 class = get_wndclass_data(actctx, index);
3624 data->ulDataFormatVersion = 1;
3625 data->lpData = class;
3626 /* full length includes string length with nulls */
3627 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3628 data->lpSectionGlobalData = NULL;
3629 data->ulSectionGlobalDataLength = 0;
3630 data->lpSectionBase = actctx->wndclass_section;
3631 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3632 data->hActCtx = NULL;
3634 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3635 data->ulAssemblyRosterIndex = index->rosterindex;
3638 return STATUS_SUCCESS;
3641 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3643 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3644 struct guidsection_header *header;
3645 ULONG module_offset, data_offset;
3646 struct tlibredirect_data *data;
3647 struct guid_index *index;
3649 /* compute section length */
3650 for (i = 0; i < actctx->num_assemblies; i++)
3652 struct assembly *assembly = &actctx->assemblies[i];
3653 for (j = 0; j < assembly->num_dlls; j++)
3655 struct dll_redirect *dll = &assembly->dlls[j];
3656 for (k = 0; k < dll->entities.num; k++)
3658 struct entity *entity = &dll->entities.base[k];
3659 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3661 /* each entry needs index, data and string data for module name and help string */
3662 total_len += sizeof(*index);
3663 total_len += sizeof(*data);
3664 /* help string is stored separately */
3665 if (*entity->u.typelib.helpdir)
3666 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3668 /* module names are packed one after another */
3669 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3671 tlib_count++;
3677 total_len += aligned_string_len(names_len);
3678 total_len += sizeof(*header);
3680 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3681 if (!header) return STATUS_NO_MEMORY;
3683 memset(header, 0, sizeof(*header));
3684 header->magic = GUIDSECTION_MAGIC;
3685 header->size = sizeof(*header);
3686 header->count = tlib_count;
3687 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3688 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3689 module_offset = sizeof(*header);
3690 data_offset = header->index_offset + tlib_count*sizeof(*index);
3692 for (i = 0; i < actctx->num_assemblies; i++)
3694 struct assembly *assembly = &actctx->assemblies[i];
3695 for (j = 0; j < assembly->num_dlls; j++)
3697 struct dll_redirect *dll = &assembly->dlls[j];
3698 for (k = 0; k < dll->entities.num; k++)
3700 struct entity *entity = &dll->entities.base[k];
3701 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3703 ULONG module_len, help_len;
3704 UNICODE_STRING str;
3705 WCHAR *ptrW;
3707 if (*entity->u.typelib.helpdir)
3708 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3709 else
3710 help_len = 0;
3712 module_len = strlenW(dll->name)*sizeof(WCHAR);
3714 /* setup new index entry */
3715 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3716 RtlGUIDFromString(&str, &index->guid);
3717 index->data_offset = data_offset;
3718 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3719 index->rosterindex = i + 1;
3721 /* setup data */
3722 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3723 data->size = sizeof(*data);
3724 data->res = 0;
3725 data->name_len = module_len;
3726 data->name_offset = module_offset;
3727 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3728 data->langid = 0;
3729 data->flags = entity->u.typelib.flags;
3730 data->help_len = help_len;
3731 data->help_offset = sizeof(*data);
3732 data->major_version = entity->u.typelib.major;
3733 data->minor_version = entity->u.typelib.minor;
3735 /* module name */
3736 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3737 memcpy(ptrW, dll->name, data->name_len);
3738 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3740 /* help string */
3741 if (data->help_len)
3743 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3744 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3745 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3748 data_offset += sizeof(*data);
3749 if (help_len)
3750 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3752 module_offset += module_len + sizeof(WCHAR);
3754 index++;
3760 *section = header;
3762 return STATUS_SUCCESS;
3765 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3767 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3770 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3772 struct guid_index *index = NULL;
3773 struct tlibredirect_data *tlib;
3775 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3777 if (!actctx->tlib_section)
3779 struct guidsection_header *section;
3781 NTSTATUS status = build_tlib_section(actctx, &section);
3782 if (status) return status;
3784 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3785 RtlFreeHeap(GetProcessHeap(), 0, section);
3788 index = find_guid_index(actctx->tlib_section, guid);
3789 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3791 tlib = get_tlib_data(actctx, index);
3793 data->ulDataFormatVersion = 1;
3794 data->lpData = tlib;
3795 /* full length includes string length with nulls */
3796 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3797 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3798 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3799 data->lpSectionBase = actctx->tlib_section;
3800 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3801 data->hActCtx = NULL;
3803 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3804 data->ulAssemblyRosterIndex = index->rosterindex;
3806 return STATUS_SUCCESS;
3809 static void generate_uuid(ULONG *seed, GUID *guid)
3811 ULONG *ptr = (ULONG*)guid;
3812 int i;
3814 /* GUID is 16 bytes long */
3815 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3816 *ptr = RtlUniform(seed);
3818 guid->Data3 &= 0x0fff;
3819 guid->Data3 |= (4 << 12);
3820 guid->Data4[0] &= 0x3f;
3821 guid->Data4[0] |= 0x80;
3824 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3825 unsigned int *count, unsigned int *len, unsigned int *module_len)
3827 unsigned int i;
3829 for (i = 0; i < entities->num; i++)
3831 struct entity *entity = &entities->base[i];
3832 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3834 /* each entry needs two index entries, extra one goes for alias GUID */
3835 *len += 2*sizeof(struct guid_index);
3836 /* To save some memory we don't allocated two data structures,
3837 instead alias index and normal index point to the same data structure. */
3838 *len += sizeof(struct comclassredirect_data);
3840 /* for clrClass store some more */
3841 if (entity->u.comclass.name)
3843 unsigned int str_len;
3845 /* all string data is stored together in aligned block */
3846 str_len = strlenW(entity->u.comclass.name)+1;
3847 if (entity->u.comclass.progid)
3848 str_len += strlenW(entity->u.comclass.progid)+1;
3849 if (entity->u.comclass.version)
3850 str_len += strlenW(entity->u.comclass.version)+1;
3852 *len += sizeof(struct clrclass_data);
3853 *len += aligned_string_len(str_len*sizeof(WCHAR));
3855 /* module name is forced to mscoree.dll, and stored two times with different case */
3856 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3858 else
3860 /* progid string is stored separately */
3861 if (entity->u.comclass.progid)
3862 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3864 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3867 *count += 1;
3872 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3873 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3874 ULONG *seed, ULONG rosterindex)
3876 unsigned int i;
3878 for (i = 0; i < entities->num; i++)
3880 struct entity *entity = &entities->base[i];
3881 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3883 ULONG module_len, progid_len, str_len = 0;
3884 struct comclassredirect_data *data;
3885 struct guid_index *alias_index;
3886 struct clrclass_data *clrdata;
3887 UNICODE_STRING str;
3888 WCHAR *ptrW;
3890 if (entity->u.comclass.progid)
3891 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3892 else
3893 progid_len = 0;
3895 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3897 /* setup new index entry */
3898 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3899 RtlGUIDFromString(&str, &(*index)->guid);
3901 (*index)->data_offset = *data_offset;
3902 (*index)->data_len = sizeof(*data); /* additional length added later */
3903 (*index)->rosterindex = rosterindex;
3905 /* Setup new index entry for alias guid. Alias index records are placed after
3906 normal records, so normal guids are hit first on search. Note that class count
3907 is doubled. */
3908 alias_index = (*index) + section->count/2;
3909 generate_uuid(seed, &alias_index->guid);
3910 alias_index->data_offset = (*index)->data_offset;
3911 alias_index->data_len = 0;
3912 alias_index->rosterindex = (*index)->rosterindex;
3914 /* setup data */
3915 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3916 data->size = sizeof(*data);
3917 data->res = 0;
3918 data->res1[0] = 0;
3919 data->res1[1] = 0;
3920 data->model = entity->u.comclass.model;
3921 data->clsid = (*index)->guid;
3922 data->alias = alias_index->guid;
3923 data->clsid2 = data->clsid;
3924 if (entity->u.comclass.tlbid)
3926 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3927 RtlGUIDFromString(&str, &data->tlbid);
3929 else
3930 memset(&data->tlbid, 0, sizeof(data->tlbid));
3931 data->name_len = module_len;
3932 data->name_offset = *module_offset;
3933 data->progid_len = progid_len;
3934 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3935 data->clrdata_len = 0; /* will be set later */
3936 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3937 data->miscstatus = entity->u.comclass.miscstatus;
3938 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3939 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3940 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3941 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3943 /* mask describes which misc* data is available */
3944 data->miscmask = 0;
3945 if (data->miscstatus)
3946 data->miscmask |= MiscStatus;
3947 if (data->miscstatuscontent)
3948 data->miscmask |= MiscStatusContent;
3949 if (data->miscstatusthumbnail)
3950 data->miscmask |= MiscStatusThumbnail;
3951 if (data->miscstatusicon)
3952 data->miscmask |= MiscStatusIcon;
3953 if (data->miscstatusdocprint)
3954 data->miscmask |= MiscStatusDocPrint;
3956 if (data->clrdata_offset)
3958 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3960 clrdata->size = sizeof(*clrdata);
3961 clrdata->res[0] = 0;
3962 clrdata->res[1] = 2; /* FIXME: unknown field */
3963 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3964 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3965 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3966 clrdata->name_offset = clrdata->size;
3967 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3968 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3969 clrdata->res2[0] = 0;
3970 clrdata->res2[1] = 0;
3972 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3974 /* module name */
3975 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3976 memcpy(ptrW, mscoree2W, clrdata->module_len);
3977 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3979 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3980 memcpy(ptrW, mscoreeW, data->name_len);
3981 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3983 /* class name */
3984 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3985 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3986 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3988 /* runtime version, optional */
3989 if (clrdata->version_len)
3991 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3993 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3994 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3995 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3998 if (data->progid_len)
3999 data->progid_offset += data->clrdata_len;
4000 (*index)->data_len += sizeof(*clrdata);
4002 else
4004 clrdata = NULL;
4006 /* module name */
4007 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
4008 memcpy(ptrW, dll->name, data->name_len);
4009 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4012 /* progid string */
4013 if (data->progid_len)
4015 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
4016 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
4017 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
4020 /* string block length */
4021 str_len = 0;
4022 if (clrdata)
4024 str_len += clrdata->name_len + sizeof(WCHAR);
4025 if (clrdata->version_len)
4026 str_len += clrdata->version_len + sizeof(WCHAR);
4028 if (progid_len)
4029 str_len += progid_len + sizeof(WCHAR);
4031 (*index)->data_len += aligned_string_len(str_len);
4032 alias_index->data_len = (*index)->data_len;
4034 /* move to next data record */
4035 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
4036 (*module_offset) += module_len + sizeof(WCHAR);
4038 if (clrdata)
4040 (*data_offset) += sizeof(*clrdata);
4041 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
4043 (*index) += 1;
4048 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4050 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
4051 struct guidsection_header *header;
4052 ULONG module_offset, data_offset;
4053 struct guid_index *index;
4054 ULONG seed;
4056 /* compute section length */
4057 for (i = 0; i < actctx->num_assemblies; i++)
4059 struct assembly *assembly = &actctx->assemblies[i];
4060 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
4061 for (j = 0; j < assembly->num_dlls; j++)
4063 struct dll_redirect *dll = &assembly->dlls[j];
4064 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
4068 total_len += aligned_string_len(names_len);
4069 total_len += sizeof(*header);
4071 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4072 if (!header) return STATUS_NO_MEMORY;
4074 memset(header, 0, sizeof(*header));
4075 header->magic = GUIDSECTION_MAGIC;
4076 header->size = sizeof(*header);
4077 header->count = 2*class_count;
4078 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
4079 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4080 module_offset = sizeof(*header);
4081 data_offset = header->index_offset + 2*class_count*sizeof(*index);
4083 seed = NtGetTickCount();
4084 for (i = 0; i < actctx->num_assemblies; i++)
4086 struct assembly *assembly = &actctx->assemblies[i];
4087 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
4088 for (j = 0; j < assembly->num_dlls; j++)
4090 struct dll_redirect *dll = &assembly->dlls[j];
4091 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
4095 *section = header;
4097 return STATUS_SUCCESS;
4100 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4102 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
4105 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4107 struct comclassredirect_data *comclass;
4108 struct guid_index *index = NULL;
4110 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4112 if (!actctx->comserver_section)
4114 struct guidsection_header *section;
4116 NTSTATUS status = build_comserver_section(actctx, &section);
4117 if (status) return status;
4119 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4120 RtlFreeHeap(GetProcessHeap(), 0, section);
4123 index = find_guid_index(actctx->comserver_section, guid);
4124 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4126 comclass = get_comclass_data(actctx, index);
4128 data->ulDataFormatVersion = 1;
4129 data->lpData = comclass;
4130 /* full length includes string length with nulls */
4131 data->ulLength = comclass->size + comclass->clrdata_len;
4132 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
4133 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
4134 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
4135 data->lpSectionBase = actctx->comserver_section;
4136 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
4137 data->hActCtx = NULL;
4139 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4140 data->ulAssemblyRosterIndex = index->rosterindex;
4142 return STATUS_SUCCESS;
4145 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
4147 unsigned int i;
4149 for (i = 0; i < entities->num; i++)
4151 struct entity *entity = &entities->base[i];
4152 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4154 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
4155 if (entity->u.ifaceps.name)
4156 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
4157 *count += 1;
4162 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
4163 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
4165 unsigned int i;
4167 for (i = 0; i < entities->num; i++)
4169 struct entity *entity = &entities->base[i];
4170 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
4172 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
4173 UNICODE_STRING str;
4174 ULONG name_len;
4176 if (entity->u.ifaceps.name)
4177 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
4178 else
4179 name_len = 0;
4181 /* setup index */
4182 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
4183 RtlGUIDFromString(&str, &(*index)->guid);
4184 (*index)->data_offset = *data_offset;
4185 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
4186 (*index)->rosterindex = rosterindex;
4188 /* setup data record */
4189 data->size = sizeof(*data);
4190 data->mask = entity->u.ifaceps.mask;
4192 /* proxyStubClsid32 value is only stored for external PS,
4193 if set it's used as iid, otherwise 'iid' attribute value is used */
4194 if (entity->u.ifaceps.ps32)
4196 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
4197 RtlGUIDFromString(&str, &data->iid);
4199 else
4200 data->iid = (*index)->guid;
4202 data->nummethods = entity->u.ifaceps.nummethods;
4204 if (entity->u.ifaceps.tlib)
4206 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
4207 RtlGUIDFromString(&str, &data->tlbid);
4209 else
4210 memset(&data->tlbid, 0, sizeof(data->tlbid));
4212 if (entity->u.ifaceps.base)
4214 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
4215 RtlGUIDFromString(&str, &data->base);
4217 else
4218 memset(&data->base, 0, sizeof(data->base));
4220 data->name_len = name_len;
4221 data->name_offset = data->name_len ? sizeof(*data) : 0;
4223 /* name string */
4224 if (data->name_len)
4226 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4227 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
4228 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4231 /* move to next record */
4232 (*index) += 1;
4233 *data_offset += sizeof(*data);
4234 if (data->name_len)
4235 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
4240 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4242 unsigned int i, j, total_len = 0, count = 0;
4243 struct guidsection_header *header;
4244 struct guid_index *index;
4245 ULONG data_offset;
4247 /* compute section length */
4248 for (i = 0; i < actctx->num_assemblies; i++)
4250 struct assembly *assembly = &actctx->assemblies[i];
4252 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
4253 for (j = 0; j < assembly->num_dlls; j++)
4255 struct dll_redirect *dll = &assembly->dlls[j];
4256 get_ifaceps_datalen(&dll->entities, &count, &total_len);
4260 total_len += sizeof(*header);
4262 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4263 if (!header) return STATUS_NO_MEMORY;
4265 memset(header, 0, sizeof(*header));
4266 header->magic = GUIDSECTION_MAGIC;
4267 header->size = sizeof(*header);
4268 header->count = count;
4269 header->index_offset = sizeof(*header);
4270 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4271 data_offset = header->index_offset + count*sizeof(*index);
4273 for (i = 0; i < actctx->num_assemblies; i++)
4275 struct assembly *assembly = &actctx->assemblies[i];
4277 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4278 for (j = 0; j < assembly->num_dlls; j++)
4280 struct dll_redirect *dll = &assembly->dlls[j];
4281 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4285 *section = header;
4287 return STATUS_SUCCESS;
4290 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4292 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4295 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4297 struct ifacepsredirect_data *iface;
4298 struct guid_index *index = NULL;
4300 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4302 if (!actctx->ifaceps_section)
4304 struct guidsection_header *section;
4306 NTSTATUS status = build_ifaceps_section(actctx, &section);
4307 if (status) return status;
4309 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4310 RtlFreeHeap(GetProcessHeap(), 0, section);
4313 index = find_guid_index(actctx->ifaceps_section, guid);
4314 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4316 iface = get_ifaceps_data(actctx, index);
4318 data->ulDataFormatVersion = 1;
4319 data->lpData = iface;
4320 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4321 data->lpSectionGlobalData = NULL;
4322 data->ulSectionGlobalDataLength = 0;
4323 data->lpSectionBase = actctx->ifaceps_section;
4324 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4325 data->hActCtx = NULL;
4327 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4328 data->ulAssemblyRosterIndex = index->rosterindex;
4330 return STATUS_SUCCESS;
4333 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4335 unsigned int i, j, total_len = 0, count = 0;
4336 struct guidsection_header *header;
4337 struct clrsurrogate_data *data;
4338 struct guid_index *index;
4339 ULONG data_offset;
4341 /* compute section length */
4342 for (i = 0; i < actctx->num_assemblies; i++)
4344 struct assembly *assembly = &actctx->assemblies[i];
4345 for (j = 0; j < assembly->entities.num; j++)
4347 struct entity *entity = &assembly->entities.base[j];
4348 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4350 ULONG len;
4352 total_len += sizeof(*index) + sizeof(*data);
4353 len = strlenW(entity->u.clrsurrogate.name) + 1;
4354 if (entity->u.clrsurrogate.version)
4355 len += strlenW(entity->u.clrsurrogate.version) + 1;
4356 total_len += aligned_string_len(len*sizeof(WCHAR));
4358 count++;
4363 total_len += sizeof(*header);
4365 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4366 if (!header) return STATUS_NO_MEMORY;
4368 memset(header, 0, sizeof(*header));
4369 header->magic = GUIDSECTION_MAGIC;
4370 header->size = sizeof(*header);
4371 header->count = count;
4372 header->index_offset = sizeof(*header);
4373 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4374 data_offset = header->index_offset + count*sizeof(*index);
4376 for (i = 0; i < actctx->num_assemblies; i++)
4378 struct assembly *assembly = &actctx->assemblies[i];
4379 for (j = 0; j < assembly->entities.num; j++)
4381 struct entity *entity = &assembly->entities.base[j];
4382 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4384 ULONG version_len, name_len;
4385 UNICODE_STRING str;
4386 WCHAR *ptrW;
4388 if (entity->u.clrsurrogate.version)
4389 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4390 else
4391 version_len = 0;
4392 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4394 /* setup new index entry */
4395 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4396 RtlGUIDFromString(&str, &index->guid);
4398 index->data_offset = data_offset;
4399 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4400 index->rosterindex = i + 1;
4402 /* setup data */
4403 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4404 data->size = sizeof(*data);
4405 data->res = 0;
4406 data->clsid = index->guid;
4407 data->version_offset = version_len ? data->size : 0;
4408 data->version_len = version_len;
4409 data->name_offset = data->size + version_len;
4410 if (version_len)
4411 data->name_offset += sizeof(WCHAR);
4412 data->name_len = name_len;
4414 /* surrogate name */
4415 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4416 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4417 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4419 /* runtime version */
4420 if (data->version_len)
4422 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4423 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4424 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4427 data_offset += index->data_offset;
4428 index++;
4433 *section = header;
4435 return STATUS_SUCCESS;
4438 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4440 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4443 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4445 struct clrsurrogate_data *surrogate;
4446 struct guid_index *index = NULL;
4448 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4450 if (!actctx->clrsurrogate_section)
4452 struct guidsection_header *section;
4454 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4455 if (status) return status;
4457 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4458 RtlFreeHeap(GetProcessHeap(), 0, section);
4461 index = find_guid_index(actctx->clrsurrogate_section, guid);
4462 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4464 surrogate = get_surrogate_data(actctx, index);
4466 data->ulDataFormatVersion = 1;
4467 data->lpData = surrogate;
4468 /* full length includes string length with nulls */
4469 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4470 if (surrogate->version_len)
4471 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4473 data->lpSectionGlobalData = NULL;
4474 data->ulSectionGlobalDataLength = 0;
4475 data->lpSectionBase = actctx->clrsurrogate_section;
4476 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4477 data->hActCtx = NULL;
4479 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4480 data->ulAssemblyRosterIndex = index->rosterindex;
4482 return STATUS_SUCCESS;
4485 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4487 unsigned int i, j, single_len;
4489 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4490 for (i = 0; i < entities->num; i++)
4492 struct entity *entity = &entities->base[i];
4493 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4495 if (entity->u.comclass.progid)
4497 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4498 *count += 1;
4501 for (j = 0; j < entity->u.comclass.progids.num; j++)
4502 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4504 *total_len += single_len*entity->u.comclass.progids.num;
4505 *count += entity->u.comclass.progids.num;
4510 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4511 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4513 struct progidredirect_data *data;
4514 UNICODE_STRING str;
4515 GUID *guid_ptr;
4516 WCHAR *ptrW;
4518 /* setup new index entry */
4520 /* hash progid name */
4521 RtlInitUnicodeString(&str, progid);
4522 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4524 (*index)->name_offset = *data_offset;
4525 (*index)->name_len = str.Length;
4526 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4527 (*index)->data_len = sizeof(*data);
4528 (*index)->rosterindex = rosterindex;
4530 *data_offset += aligned_string_len(str.MaximumLength);
4532 /* setup data structure */
4533 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4534 data->size = sizeof(*data);
4535 data->reserved = 0;
4536 data->clsid_offset = *global_offset;
4538 /* write progid string */
4539 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4540 memcpy(ptrW, progid, (*index)->name_len);
4541 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4543 /* write guid to global area */
4544 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4545 *guid_ptr = *alias;
4547 /* to next entry */
4548 *global_offset += sizeof(GUID);
4549 *data_offset += data->size;
4550 (*index) += 1;
4553 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4554 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4556 unsigned int i, j;
4558 for (i = 0; i < entities->num; i++)
4560 struct entity *entity = &entities->base[i];
4561 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4563 const struct progids *progids = &entity->u.comclass.progids;
4564 struct comclassredirect_data *comclass;
4565 struct guid_index *guid_index;
4566 UNICODE_STRING str;
4567 GUID clsid;
4569 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4570 RtlGUIDFromString(&str, &clsid);
4572 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4573 comclass = get_comclass_data(actctx, guid_index);
4575 if (entity->u.comclass.progid)
4576 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4577 index, data_offset, global_offset, rosterindex);
4579 for (j = 0; j < progids->num; j++)
4580 write_progid_record(section, progids->progids[j], &comclass->alias,
4581 index, data_offset, global_offset, rosterindex);
4586 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4588 unsigned int i, j, total_len = 0, count = 0;
4589 struct strsection_header *header;
4590 ULONG data_offset, global_offset;
4591 struct string_index *index;
4593 /* compute section length */
4594 for (i = 0; i < actctx->num_assemblies; i++)
4596 struct assembly *assembly = &actctx->assemblies[i];
4598 get_progid_datalen(&assembly->entities, &count, &total_len);
4599 for (j = 0; j < assembly->num_dlls; j++)
4601 struct dll_redirect *dll = &assembly->dlls[j];
4602 get_progid_datalen(&dll->entities, &count, &total_len);
4606 total_len += sizeof(*header);
4608 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4609 if (!header) return STATUS_NO_MEMORY;
4611 memset(header, 0, sizeof(*header));
4612 header->magic = STRSECTION_MAGIC;
4613 header->size = sizeof(*header);
4614 header->count = count;
4615 header->global_offset = header->size;
4616 header->global_len = count*sizeof(GUID);
4617 header->index_offset = header->size + header->global_len;
4619 index = (struct string_index*)((BYTE*)header + header->index_offset);
4620 data_offset = header->index_offset + count*sizeof(*index);
4621 global_offset = header->global_offset;
4623 for (i = 0; i < actctx->num_assemblies; i++)
4625 struct assembly *assembly = &actctx->assemblies[i];
4627 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4628 for (j = 0; j < assembly->num_dlls; j++)
4630 struct dll_redirect *dll = &assembly->dlls[j];
4631 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4635 *section = header;
4637 return STATUS_SUCCESS;
4640 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4642 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4645 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4646 PACTCTX_SECTION_KEYED_DATA data)
4648 struct progidredirect_data *progid;
4649 struct string_index *index;
4651 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4653 if (!actctx->comserver_section)
4655 struct guidsection_header *section;
4657 NTSTATUS status = build_comserver_section(actctx, &section);
4658 if (status) return status;
4660 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4661 RtlFreeHeap(GetProcessHeap(), 0, section);
4664 if (!actctx->progid_section)
4666 struct strsection_header *section;
4668 NTSTATUS status = build_progid_section(actctx, &section);
4669 if (status) return status;
4671 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4672 RtlFreeHeap(GetProcessHeap(), 0, section);
4675 index = find_string_index(actctx->progid_section, name);
4676 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4678 if (data)
4680 progid = get_progid_data(actctx, index);
4682 data->ulDataFormatVersion = 1;
4683 data->lpData = progid;
4684 data->ulLength = progid->size;
4685 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4686 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4687 data->lpSectionBase = actctx->progid_section;
4688 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4689 data->hActCtx = NULL;
4691 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4692 data->ulAssemblyRosterIndex = index->rosterindex;
4695 return STATUS_SUCCESS;
4698 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4699 const UNICODE_STRING *section_name,
4700 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4702 NTSTATUS status;
4704 switch (section_kind)
4706 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4707 status = find_dll_redirection(actctx, section_name, data);
4708 break;
4709 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4710 status = find_window_class(actctx, section_name, data);
4711 break;
4712 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4713 status = find_progid_redirection(actctx, section_name, data);
4714 break;
4715 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4716 FIXME("Unsupported yet section_kind %x\n", section_kind);
4717 return STATUS_SXS_SECTION_NOT_FOUND;
4718 default:
4719 WARN("Unknown section_kind %x\n", section_kind);
4720 return STATUS_SXS_SECTION_NOT_FOUND;
4723 if (status != STATUS_SUCCESS) return status;
4725 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4727 actctx_addref(actctx);
4728 data->hActCtx = actctx;
4730 return STATUS_SUCCESS;
4733 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4734 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4736 NTSTATUS status;
4738 switch (section_kind)
4740 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4741 status = find_tlib_redirection(actctx, guid, data);
4742 break;
4743 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4744 status = find_comserver_redirection(actctx, guid, data);
4745 break;
4746 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4747 status = find_cominterface_redirection(actctx, guid, data);
4748 break;
4749 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4750 status = find_clr_surrogate(actctx, guid, data);
4751 break;
4752 default:
4753 WARN("Unknown section_kind %x\n", section_kind);
4754 return STATUS_SXS_SECTION_NOT_FOUND;
4757 if (status != STATUS_SUCCESS) return status;
4759 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4761 actctx_addref(actctx);
4762 data->hActCtx = actctx;
4764 return STATUS_SUCCESS;
4767 /* initialize the activation context for the current process */
4768 void actctx_init(void)
4770 ACTCTXW ctx;
4771 HANDLE handle;
4773 ctx.cbSize = sizeof(ctx);
4774 ctx.lpSource = NULL;
4775 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4776 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4777 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4779 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4783 /***********************************************************************
4784 * RtlCreateActivationContext (NTDLL.@)
4786 * Create an activation context.
4788 * FIXME: function signature/prototype is wrong
4790 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4792 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4793 const WCHAR *directory = NULL;
4794 ACTIVATION_CONTEXT *actctx;
4795 UNICODE_STRING nameW;
4796 ULONG lang = 0;
4797 NTSTATUS status = STATUS_NO_MEMORY;
4798 HANDLE file = 0;
4799 struct actctx_loader acl;
4801 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4803 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4804 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4805 return STATUS_INVALID_PARAMETER;
4807 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4808 return STATUS_NO_MEMORY;
4810 actctx->magic = ACTCTX_MAGIC;
4811 actctx->ref_count = 1;
4812 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4813 actctx->config.info = NULL;
4814 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4815 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4817 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4819 else
4821 UNICODE_STRING dir;
4822 WCHAR *p;
4823 HMODULE module;
4825 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4826 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4828 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4829 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4830 actctx->appdir.info = dir.Buffer;
4833 nameW.Buffer = NULL;
4835 /* open file only if it's going to be used */
4836 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4837 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4839 WCHAR *source = NULL;
4840 BOOLEAN ret;
4842 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4843 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4845 DWORD dir_len, source_len;
4847 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4848 source_len = strlenW(pActCtx->lpSource);
4849 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4851 status = STATUS_NO_MEMORY;
4852 goto error;
4855 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4856 source[dir_len] = '\\';
4857 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4860 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4861 RtlFreeHeap( GetProcessHeap(), 0, source );
4862 if (!ret)
4864 status = STATUS_NO_SUCH_FILE;
4865 goto error;
4867 status = open_nt_file( &file, &nameW );
4868 if (status)
4870 RtlFreeUnicodeString( &nameW );
4871 goto error;
4875 acl.actctx = actctx;
4876 acl.dependencies = NULL;
4877 acl.num_dependencies = 0;
4878 acl.allocated_dependencies = 0;
4880 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4881 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4883 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4885 /* if we have a resource it's a PE file */
4886 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4888 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4889 pActCtx->lpResourceName, lang );
4890 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4891 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4892 pActCtx->hModule, pActCtx->lpResourceName );
4894 else if (pActCtx->lpSource)
4896 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4897 file, pActCtx->lpResourceName, lang );
4898 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4899 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4900 NULL, pActCtx->lpResourceName );
4902 else status = STATUS_INVALID_PARAMETER;
4904 else
4906 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4909 if (file) NtClose( file );
4910 RtlFreeUnicodeString( &nameW );
4912 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4913 free_depend_manifests( &acl );
4915 if (status == STATUS_SUCCESS) *handle = actctx;
4916 else actctx_release( actctx );
4917 return status;
4919 error:
4920 if (file) NtClose( file );
4921 actctx_release( actctx );
4922 return status;
4926 /***********************************************************************
4927 * RtlAddRefActivationContext (NTDLL.@)
4929 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4931 ACTIVATION_CONTEXT *actctx;
4933 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4937 /******************************************************************
4938 * RtlReleaseActivationContext (NTDLL.@)
4940 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4942 ACTIVATION_CONTEXT *actctx;
4944 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4947 /******************************************************************
4948 * RtlZombifyActivationContext (NTDLL.@)
4950 * FIXME: function prototype might be wrong
4952 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4954 FIXME("%p: stub\n", handle);
4955 return STATUS_NOT_IMPLEMENTED;
4958 /******************************************************************
4959 * RtlActivateActivationContext (NTDLL.@)
4961 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4963 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4965 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4966 return STATUS_NO_MEMORY;
4968 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4969 frame->ActivationContext = handle;
4970 frame->Flags = 0;
4971 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4972 RtlAddRefActivationContext( handle );
4974 *cookie = (ULONG_PTR)frame;
4975 TRACE( "%p cookie=%lx\n", handle, *cookie );
4976 return STATUS_SUCCESS;
4980 /***********************************************************************
4981 * RtlDeactivateActivationContext (NTDLL.@)
4983 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4985 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4987 TRACE( "%x cookie=%lx\n", flags, cookie );
4989 /* find the right frame */
4990 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4991 for (frame = top; frame; frame = frame->Previous)
4992 if ((ULONG_PTR)frame == cookie) break;
4994 if (!frame)
4995 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4997 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4998 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
5000 /* pop everything up to and including frame */
5001 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
5003 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5005 frame = top->Previous;
5006 RtlReleaseActivationContext( top->ActivationContext );
5007 RtlFreeHeap( GetProcessHeap(), 0, top );
5008 top = frame;
5013 /******************************************************************
5014 * RtlFreeThreadActivationContextStack (NTDLL.@)
5016 void WINAPI RtlFreeThreadActivationContextStack(void)
5018 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5020 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
5021 while (frame)
5023 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
5024 RtlReleaseActivationContext( frame->ActivationContext );
5025 RtlFreeHeap( GetProcessHeap(), 0, frame );
5026 frame = prev;
5028 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
5032 /******************************************************************
5033 * RtlGetActiveActivationContext (NTDLL.@)
5035 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
5037 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5039 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
5040 RtlAddRefActivationContext( *handle );
5042 else
5043 *handle = 0;
5045 return STATUS_SUCCESS;
5049 /******************************************************************
5050 * RtlIsActivationContextActive (NTDLL.@)
5052 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
5054 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
5056 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
5057 if (frame->ActivationContext == handle) return TRUE;
5058 return FALSE;
5062 /***********************************************************************
5063 * RtlQueryInformationActivationContext (NTDLL.@)
5065 * Get information about an activation context.
5066 * FIXME: function signature/prototype may be wrong
5068 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
5069 ULONG class, PVOID buffer,
5070 SIZE_T bufsize, SIZE_T *retlen )
5072 ACTIVATION_CONTEXT *actctx;
5073 NTSTATUS status;
5075 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
5076 subinst, class, buffer, bufsize, retlen);
5078 if (retlen) *retlen = 0;
5079 if ((status = find_query_actctx( &handle, flags, class ))) return status;
5081 switch (class)
5083 case ActivationContextBasicInformation:
5085 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
5087 if (retlen) *retlen = sizeof(*info);
5088 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
5090 info->hActCtx = handle;
5091 info->dwFlags = 0; /* FIXME */
5092 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
5094 break;
5096 case ActivationContextDetailedInformation:
5098 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
5099 struct assembly *assembly = NULL;
5100 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
5101 LPWSTR ptr;
5103 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5105 if (actctx->num_assemblies) assembly = actctx->assemblies;
5107 if (assembly && assembly->manifest.info)
5108 manifest_len = strlenW(assembly->manifest.info) + 1;
5109 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
5110 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
5111 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
5113 if (retlen) *retlen = len;
5114 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5116 acdi->dwFlags = 0;
5117 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
5118 acdi->ulAssemblyCount = actctx->num_assemblies;
5119 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
5120 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
5121 acdi->ulRootConfigurationPathType = actctx->config.type;
5122 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
5123 acdi->ulAppDirPathType = actctx->appdir.type;
5124 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
5125 ptr = (LPWSTR)(acdi + 1);
5126 if (manifest_len)
5128 acdi->lpRootManifestPath = ptr;
5129 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
5130 ptr += manifest_len;
5132 else acdi->lpRootManifestPath = NULL;
5133 if (config_len)
5135 acdi->lpRootConfigurationPath = ptr;
5136 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
5137 ptr += config_len;
5139 else acdi->lpRootConfigurationPath = NULL;
5140 if (appdir_len)
5142 acdi->lpAppDirPath = ptr;
5143 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
5145 else acdi->lpAppDirPath = NULL;
5147 break;
5149 case AssemblyDetailedInformationInActivationContext:
5151 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
5152 struct assembly *assembly;
5153 WCHAR *assembly_id;
5154 DWORD index;
5155 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
5156 LPWSTR ptr;
5158 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5159 if (!subinst) return STATUS_INVALID_PARAMETER;
5161 index = *(DWORD*)subinst;
5162 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
5164 assembly = &actctx->assemblies[index - 1];
5166 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
5167 id_len = strlenW(assembly_id) + 1;
5168 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
5170 if (assembly->manifest.info &&
5171 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
5172 path_len = strlenW(assembly->manifest.info) + 1;
5174 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
5176 if (retlen) *retlen = len;
5177 if (!buffer || bufsize < len)
5179 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5180 return STATUS_BUFFER_TOO_SMALL;
5183 afdi->ulFlags = 0; /* FIXME */
5184 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
5185 afdi->ulManifestPathType = assembly->manifest.type;
5186 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
5187 /* FIXME afdi->liManifestLastWriteTime = 0; */
5188 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
5189 afdi->ulPolicyPathLength = 0;
5190 /* FIXME afdi->liPolicyLastWriteTime = 0; */
5191 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
5192 afdi->ulManifestVersionMajor = 1;
5193 afdi->ulManifestVersionMinor = 0;
5194 afdi->ulPolicyVersionMajor = 0; /* FIXME */
5195 afdi->ulPolicyVersionMinor = 0; /* FIXME */
5196 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
5197 ptr = (LPWSTR)(afdi + 1);
5198 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
5199 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
5200 ptr += id_len;
5201 if (path_len)
5203 afdi->lpAssemblyManifestPath = ptr;
5204 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
5205 ptr += path_len;
5206 } else afdi->lpAssemblyManifestPath = NULL;
5207 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
5208 if (ad_len)
5210 afdi->lpAssemblyDirectoryName = ptr;
5211 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
5213 else afdi->lpAssemblyDirectoryName = NULL;
5214 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
5216 break;
5218 case FileInformationInAssemblyOfAssemblyInActivationContext:
5220 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
5221 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
5222 struct assembly *assembly;
5223 struct dll_redirect *dll;
5224 SIZE_T len, dll_len = 0;
5225 LPWSTR ptr;
5227 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5228 if (!acqi) return STATUS_INVALID_PARAMETER;
5230 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
5231 return STATUS_INVALID_PARAMETER;
5232 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
5234 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
5235 return STATUS_INVALID_PARAMETER;
5236 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
5238 if (dll->name) dll_len = strlenW(dll->name) + 1;
5239 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
5241 if (!buffer || bufsize < len)
5243 if (retlen) *retlen = len;
5244 return STATUS_BUFFER_TOO_SMALL;
5246 if (retlen) *retlen = 0; /* yes that's what native does !! */
5247 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
5248 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
5249 afdi->ulPathLength = 0; /* FIXME */
5250 ptr = (LPWSTR)(afdi + 1);
5251 if (dll_len)
5253 afdi->lpFileName = ptr;
5254 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
5255 } else afdi->lpFileName = NULL;
5256 afdi->lpFilePath = NULL; /* FIXME */
5258 break;
5260 case CompatibilityInformationInActivationContext:
5262 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer;
5263 COMPATIBILITY_CONTEXT_ELEMENT *elements;
5264 struct assembly *assembly = NULL;
5265 ULONG num_compat_contexts = 0, n;
5266 SIZE_T len;
5268 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5270 if (actctx->num_assemblies) assembly = actctx->assemblies;
5272 if (assembly)
5273 num_compat_contexts = assembly->num_compat_contexts;
5274 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT);
5276 if (retlen) *retlen = len;
5277 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
5279 *acci = num_compat_contexts;
5280 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1);
5281 for (n = 0; n < num_compat_contexts; ++n)
5283 elements[n] = assembly->compat_contexts[n];
5286 break;
5288 case RunlevelInformationInActivationContext:
5290 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer;
5291 struct assembly *assembly;
5292 SIZE_T len;
5294 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
5296 len = sizeof(*acrli);
5297 if (retlen) *retlen = len;
5298 if (!buffer || bufsize < len)
5299 return STATUS_BUFFER_TOO_SMALL;
5301 assembly = actctx->assemblies;
5303 acrli->ulFlags = 0;
5304 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED;
5305 acrli->UiAccess = assembly ? assembly->ui_access : 0;
5307 break;
5309 default:
5310 FIXME( "class %u not implemented\n", class );
5311 return STATUS_NOT_IMPLEMENTED;
5313 return STATUS_SUCCESS;
5316 /***********************************************************************
5317 * RtlFindActivationContextSectionString (NTDLL.@)
5319 * Find information about a string in an activation context.
5320 * FIXME: function signature/prototype may be wrong
5322 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5323 const UNICODE_STRING *section_name, PVOID ptr )
5325 PACTCTX_SECTION_KEYED_DATA data = ptr;
5326 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5328 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5329 debugstr_us(section_name), data);
5331 if (guid)
5333 FIXME("expected guid == NULL\n");
5334 return STATUS_INVALID_PARAMETER;
5336 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5338 FIXME("unknown flags %08x\n", flags);
5339 return STATUS_INVALID_PARAMETER;
5341 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5342 !section_name || !section_name->Buffer)
5344 WARN("invalid parameter\n");
5345 return STATUS_INVALID_PARAMETER;
5348 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5350 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5351 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5354 if (status != STATUS_SUCCESS)
5355 status = find_string( process_actctx, section_kind, section_name, flags, data );
5357 return status;
5360 /***********************************************************************
5361 * RtlFindActivationContextSectionGuid (NTDLL.@)
5363 * Find information about a GUID in an activation context.
5364 * FIXME: function signature/prototype may be wrong
5366 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5367 const GUID *guid, void *ptr )
5369 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5370 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5372 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5374 if (extguid)
5376 FIXME("expected extguid == NULL\n");
5377 return STATUS_INVALID_PARAMETER;
5380 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5382 FIXME("unknown flags %08x\n", flags);
5383 return STATUS_INVALID_PARAMETER;
5386 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5387 return STATUS_INVALID_PARAMETER;
5389 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5391 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5392 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5395 if (status != STATUS_SUCCESS)
5396 status = find_guid( process_actctx, section_kind, guid, flags, data );
5398 return status;