gdi32: Change an ERR to a WARN for fonts with too-long names.
[wine/multimedia.git] / dlls / ntdll / actctx.c
blob20a98ec76b0431624ffb430c056f4a1ffc982d98
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 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "winternl.h"
36 #include "ddk/wdm.h"
37 #include "ntdll_misc.h"
38 #include "wine/exception.h"
39 #include "wine/debug.h"
40 #include "wine/unicode.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
44 #define ACTCTX_FLAGS_ALL (\
45 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
46 ACTCTX_FLAG_LANGID_VALID |\
47 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
48 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
49 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
50 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
51 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
52 ACTCTX_FLAG_HMODULE_VALID )
54 #define ACTCTX_MAGIC 0xC07E3E11
55 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
56 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
58 /* we don't want to include winuser.h */
59 #define RT_MANIFEST ((ULONG_PTR)24)
60 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
62 /* from oaidl.h */
63 typedef enum tagLIBFLAGS {
64 LIBFLAG_FRESTRICTED = 0x1,
65 LIBFLAG_FCONTROL = 0x2,
66 LIBFLAG_FHIDDEN = 0x4,
67 LIBFLAG_FHASDISKIMAGE = 0x8
68 } LIBFLAGS;
70 /* from oleidl.idl */
71 typedef enum tagOLEMISC
73 OLEMISC_RECOMPOSEONRESIZE = 0x1,
74 OLEMISC_ONLYICONIC = 0x2,
75 OLEMISC_INSERTNOTREPLACE = 0x4,
76 OLEMISC_STATIC = 0x8,
77 OLEMISC_CANTLINKINSIDE = 0x10,
78 OLEMISC_CANLINKBYOLE1 = 0x20,
79 OLEMISC_ISLINKOBJECT = 0x40,
80 OLEMISC_INSIDEOUT = 0x80,
81 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
82 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
83 OLEMISC_INVISIBLEATRUNTIME = 0x400,
84 OLEMISC_ALWAYSRUN = 0x800,
85 OLEMISC_ACTSLIKEBUTTON = 0x1000,
86 OLEMISC_ACTSLIKELABEL = 0x2000,
87 OLEMISC_NOUIACTIVATE = 0x4000,
88 OLEMISC_ALIGNABLE = 0x8000,
89 OLEMISC_SIMPLEFRAME = 0x10000,
90 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
91 OLEMISC_IMEMODE = 0x40000,
92 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
93 OLEMISC_WANTSTOMENUMERGE = 0x100000,
94 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
95 } OLEMISC;
97 typedef struct
99 const WCHAR *ptr;
100 unsigned int len;
101 } xmlstr_t;
103 typedef struct
105 const WCHAR *ptr;
106 const WCHAR *end;
107 } xmlbuf_t;
109 struct file_info
111 ULONG type;
112 WCHAR *info;
115 struct assembly_version
117 USHORT major;
118 USHORT minor;
119 USHORT build;
120 USHORT revision;
123 struct assembly_identity
125 WCHAR *name;
126 WCHAR *arch;
127 WCHAR *public_key;
128 WCHAR *language;
129 WCHAR *type;
130 struct assembly_version version;
131 BOOL optional;
132 BOOL delayed;
135 struct strsection_header
137 DWORD magic;
138 ULONG size;
139 DWORD unk1[3];
140 ULONG count;
141 ULONG index_offset;
142 DWORD unk2[2];
143 ULONG global_offset;
144 ULONG global_len;
147 struct string_index
149 ULONG hash; /* key string hash */
150 ULONG name_offset;
151 ULONG name_len;
152 ULONG data_offset; /* redirect data offset */
153 ULONG data_len;
154 ULONG rosterindex;
157 struct guidsection_header
159 DWORD magic;
160 ULONG size;
161 DWORD unk[3];
162 ULONG count;
163 ULONG index_offset;
164 DWORD unk2;
165 ULONG names_offset;
166 ULONG names_len;
169 struct guid_index
171 GUID guid;
172 ULONG data_offset;
173 ULONG data_len;
174 ULONG rosterindex;
177 struct wndclass_redirect_data
179 ULONG size;
180 DWORD res;
181 ULONG name_len;
182 ULONG name_offset; /* versioned name offset */
183 ULONG module_len;
184 ULONG module_offset;/* container name offset */
187 struct dllredirect_data
189 ULONG size;
190 ULONG unk;
191 DWORD res[3];
194 struct tlibredirect_data
196 ULONG size;
197 DWORD res;
198 ULONG name_len;
199 ULONG name_offset;
200 LANGID langid;
201 WORD flags;
202 ULONG help_len;
203 ULONG help_offset;
204 WORD major_version;
205 WORD minor_version;
208 enum comclass_threadingmodel
210 ThreadingModel_Apartment = 1,
211 ThreadingModel_Free = 2,
212 ThreadingModel_No = 3,
213 ThreadingModel_Both = 4,
214 ThreadingModel_Neutral = 5
217 enum comclass_miscfields
219 MiscStatus = 1,
220 MiscStatusIcon = 2,
221 MiscStatusContent = 4,
222 MiscStatusThumbnail = 8,
223 MiscStatusDocPrint = 16
226 struct comclassredirect_data
228 ULONG size;
229 BYTE res;
230 BYTE miscmask;
231 BYTE res1[2];
232 DWORD model;
233 GUID clsid;
234 GUID alias;
235 GUID clsid2;
236 GUID tlbid;
237 ULONG name_len;
238 ULONG name_offset;
239 ULONG progid_len;
240 ULONG progid_offset;
241 ULONG clrdata_len;
242 ULONG clrdata_offset;
243 DWORD miscstatus;
244 DWORD miscstatuscontent;
245 DWORD miscstatusthumbnail;
246 DWORD miscstatusicon;
247 DWORD miscstatusdocprint;
250 enum ifaceps_mask
252 NumMethods = 1,
253 BaseIface = 2
256 struct ifacepsredirect_data
258 ULONG size;
259 DWORD mask;
260 GUID iid;
261 ULONG nummethods;
262 GUID tlbid;
263 GUID base;
264 ULONG name_len;
265 ULONG name_offset;
268 struct clrsurrogate_data
270 ULONG size;
271 DWORD res;
272 GUID clsid;
273 ULONG version_offset;
274 ULONG version_len;
275 ULONG name_offset;
276 ULONG name_len;
279 struct clrclass_data
281 ULONG size;
282 DWORD res[2];
283 ULONG module_len;
284 ULONG module_offset;
285 ULONG name_len;
286 ULONG name_offset;
287 ULONG version_len;
288 ULONG version_offset;
289 DWORD res2[2];
292 struct progidredirect_data
294 ULONG size;
295 DWORD reserved;
296 ULONG clsid_offset;
301 Sections structure.
303 Sections are accessible by string or guid key, that defines two types of sections.
304 All sections of each type have same magic value and header structure, index
305 data could be of two possible types too. So every string based section uses
306 the same index format, same applies to guid sections - they share same guid index
307 format.
309 - window class redirection section is a plain buffer with following format:
311 <section header>
312 <index[]>
313 <data[]> --- <original name>
314 <redirect data>
315 <versioned name>
316 <module name>
318 Header is fixed length structure - struct strsection_header,
319 contains redirected classes count;
321 Index is an array of fixed length index records, each record is
322 struct string_index.
324 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
326 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
327 others are relative to section itself.
329 - dll redirect section format:
331 <section header>
332 <index[]>
333 <data[]> --- <dll name>
334 <data>
336 This section doesn't seem to carry any payload data except dll names.
338 - typelib section format:
340 <section header>
341 <module names[]>
342 <index[]>
343 <data[]> --- <data>
344 <helpstring>
346 Header is fixed length, index is an array of fixed length 'struct guid_index'.
347 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
348 4-bytes aligned as a whole.
350 Module name offsets are relative to section, helpstring offset is relative to data
351 structure itself.
353 - comclass section format:
355 <section header>
356 <module names[]>
357 <index[]>
358 <data[]> --- <data> --- <data>
359 <progid> <clrdata>
360 <name>
361 <version>
362 <progid>
364 This section uses two index records per comclass, one entry contains original guid
365 as specified by context, another one has a generated guid. Index and strings handling
366 is similar to typelib sections.
368 For CLR classes additional data is stored after main COM class data, it contains
369 class name and runtime version string, see 'struct clrclass_data'.
371 Module name offsets are relative to section, progid offset is relative to data
372 structure itself.
374 - COM interface section format:
376 <section header>
377 <index[]>
378 <data[]> --- <data>
379 <name>
381 Interface section contains data for proxy/stubs and external proxy/stubs. External
382 ones are defined at assembly level, so this section has no module information.
383 All records are indexed with 'iid' value from manifest. There an exception for
384 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
385 redirect data, but index is still 'iid' from manifest.
387 Interface name offset is relative to data structure itself.
389 - CLR surrogates section format:
391 <section header>
392 <index[]>
393 <data[]> --- <data>
394 <name>
395 <version>
397 There's nothing special about this section, same way to store strings is used,
398 no modules part as it belongs to assembly level, not a file.
400 - ProgID section format:
402 <section header>
403 <guids[]>
404 <index[]>
405 <data[]> --- <progid>
406 <data>
408 This sections uses generated alias guids from COM server section. This way
409 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
410 is stored too, aligned.
413 struct progids
415 WCHAR **progids;
416 unsigned int num;
417 unsigned int allocated;
420 struct entity
422 DWORD kind;
423 union
425 struct
427 WCHAR *tlbid;
428 WCHAR *helpdir;
429 WORD flags;
430 WORD major;
431 WORD minor;
432 } typelib;
433 struct
435 WCHAR *clsid;
436 WCHAR *tlbid;
437 WCHAR *progid;
438 WCHAR *name; /* clrClass: class name */
439 WCHAR *version; /* clrClass: CLR runtime version */
440 DWORD model;
441 DWORD miscstatus;
442 DWORD miscstatuscontent;
443 DWORD miscstatusthumbnail;
444 DWORD miscstatusicon;
445 DWORD miscstatusdocprint;
446 struct progids progids;
447 } comclass;
448 struct {
449 WCHAR *iid;
450 WCHAR *base;
451 WCHAR *tlib;
452 WCHAR *name;
453 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
454 DWORD mask;
455 ULONG nummethods;
456 } ifaceps;
457 struct
459 WCHAR *name;
460 BOOL versioned;
461 } class;
462 struct
464 WCHAR *name;
465 WCHAR *clsid;
466 WCHAR *version;
467 } clrsurrogate;
468 } u;
471 struct entity_array
473 struct entity *base;
474 unsigned int num;
475 unsigned int allocated;
478 struct dll_redirect
480 WCHAR *name;
481 WCHAR *hash;
482 struct entity_array entities;
485 enum assembly_type
487 APPLICATION_MANIFEST,
488 ASSEMBLY_MANIFEST,
489 ASSEMBLY_SHARED_MANIFEST,
492 struct assembly
494 enum assembly_type type;
495 struct assembly_identity id;
496 struct file_info manifest;
497 WCHAR *directory;
498 BOOL no_inherit;
499 struct dll_redirect *dlls;
500 unsigned int num_dlls;
501 unsigned int allocated_dlls;
502 struct entity_array entities;
505 enum context_sections
507 WINDOWCLASS_SECTION = 1,
508 DLLREDIRECT_SECTION = 2,
509 TLIBREDIRECT_SECTION = 4,
510 SERVERREDIRECT_SECTION = 8,
511 IFACEREDIRECT_SECTION = 16,
512 CLRSURROGATES_SECTION = 32,
513 PROGIDREDIRECT_SECTION = 64
516 typedef struct _ACTIVATION_CONTEXT
518 ULONG magic;
519 int ref_count;
520 struct file_info config;
521 struct file_info appdir;
522 struct assembly *assemblies;
523 unsigned int num_assemblies;
524 unsigned int allocated_assemblies;
525 /* section data */
526 DWORD sections;
527 struct strsection_header *wndclass_section;
528 struct strsection_header *dllredirect_section;
529 struct strsection_header *progid_section;
530 struct guidsection_header *tlib_section;
531 struct guidsection_header *comserver_section;
532 struct guidsection_header *ifaceps_section;
533 struct guidsection_header *clrsurrogate_section;
534 } ACTIVATION_CONTEXT;
536 struct actctx_loader
538 ACTIVATION_CONTEXT *actctx;
539 struct assembly_identity *dependencies;
540 unsigned int num_dependencies;
541 unsigned int allocated_dependencies;
544 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
545 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
546 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
547 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
548 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
549 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
550 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
551 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
552 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};
553 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};
554 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
555 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
556 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
557 static const WCHAR fileW[] = {'f','i','l','e',0};
558 static const WCHAR hashW[] = {'h','a','s','h',0};
559 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
560 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
561 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
562 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
564 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
565 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
566 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
567 static const WCHAR iidW[] = {'i','i','d',0};
568 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
569 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
570 static const WCHAR nameW[] = {'n','a','m','e',0};
571 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
572 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
573 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
574 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
575 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};
576 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
577 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
578 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
579 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
580 static const WCHAR typeW[] = {'t','y','p','e',0};
581 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
582 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
583 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
584 static const WCHAR yesW[] = {'y','e','s',0};
585 static const WCHAR noW[] = {'n','o',0};
586 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
587 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
588 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
589 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
590 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
591 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
592 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
593 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
594 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
595 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
596 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
597 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
598 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
599 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
600 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
601 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
603 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
604 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
605 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
606 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
607 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
608 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
609 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
610 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};
611 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
612 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
613 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
614 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
615 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
616 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
617 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
618 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
619 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};
620 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
621 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
622 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
623 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};
624 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
626 struct olemisc_entry
628 const WCHAR *name;
629 OLEMISC value;
632 static const struct olemisc_entry olemisc_values[] =
634 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
635 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
636 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
637 { alignableW, OLEMISC_ALIGNABLE },
638 { alwaysrunW, OLEMISC_ALWAYSRUN },
639 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
640 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
641 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
642 { imemodeW, OLEMISC_IMEMODE },
643 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
644 { insideoutW, OLEMISC_INSIDEOUT },
645 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
646 { islinkobjectW, OLEMISC_ISLINKOBJECT },
647 { nouiactivateW, OLEMISC_NOUIACTIVATE },
648 { onlyiconicW, OLEMISC_ONLYICONIC },
649 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
650 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
651 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
652 { simpleframeW, OLEMISC_SIMPLEFRAME },
653 { staticW, OLEMISC_STATIC },
654 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
655 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
658 static const WCHAR xmlW[] = {'?','x','m','l',0};
659 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};
660 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};
661 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};
663 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
664 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
665 static const WCHAR wildcardW[] = {'*',0};
667 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
668 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
670 static WCHAR *strdupW(const WCHAR* str)
672 WCHAR* ptr;
674 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
675 return NULL;
676 return strcpyW(ptr, str);
679 static WCHAR *xmlstrdupW(const xmlstr_t* str)
681 WCHAR *strW;
683 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
685 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
686 strW[str->len] = 0;
688 return strW;
691 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
693 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
696 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
698 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
701 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
703 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
704 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
707 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
709 UINT len = strlenW( namespace );
711 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
712 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
713 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
716 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
718 if (elem->len && elem->ptr[0] == '/')
720 xmlstr_t elem_end;
721 elem_end.ptr = elem->ptr + 1;
722 elem_end.len = elem->len - 1;
723 return xml_elem_cmp( &elem_end, str, namespace );
725 return FALSE;
728 static inline BOOL isxmlspace( WCHAR ch )
730 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
733 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
735 return debugstr_wn(str->ptr, str->len);
738 static inline const char* debugstr_version(const struct assembly_version *ver)
740 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
743 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
745 struct assembly *assembly;
747 if (actctx->num_assemblies == actctx->allocated_assemblies)
749 void *ptr;
750 unsigned int new_count;
751 if (actctx->assemblies)
753 new_count = actctx->allocated_assemblies * 2;
754 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
755 actctx->assemblies, new_count * sizeof(*assembly) );
757 else
759 new_count = 4;
760 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
762 if (!ptr) return NULL;
763 actctx->assemblies = ptr;
764 actctx->allocated_assemblies = new_count;
767 assembly = &actctx->assemblies[actctx->num_assemblies++];
768 assembly->type = at;
769 return assembly;
772 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
774 if (assembly->num_dlls == assembly->allocated_dlls)
776 void *ptr;
777 unsigned int new_count;
778 if (assembly->dlls)
780 new_count = assembly->allocated_dlls * 2;
781 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
782 assembly->dlls, new_count * sizeof(*assembly->dlls) );
784 else
786 new_count = 4;
787 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
789 if (!ptr) return NULL;
790 assembly->dlls = ptr;
791 assembly->allocated_dlls = new_count;
793 return &assembly->dlls[assembly->num_dlls++];
796 static void free_assembly_identity(struct assembly_identity *ai)
798 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
799 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
800 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
801 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
802 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
805 static struct entity* add_entity(struct entity_array *array, DWORD kind)
807 struct entity* entity;
809 if (array->num == array->allocated)
811 void *ptr;
812 unsigned int new_count;
813 if (array->base)
815 new_count = array->allocated * 2;
816 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
817 array->base, new_count * sizeof(*array->base) );
819 else
821 new_count = 4;
822 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
824 if (!ptr) return NULL;
825 array->base = ptr;
826 array->allocated = new_count;
828 entity = &array->base[array->num++];
829 entity->kind = kind;
830 return entity;
833 static void free_entity_array(struct entity_array *array)
835 unsigned int i, j;
836 for (i = 0; i < array->num; i++)
838 struct entity *entity = &array->base[i];
839 switch (entity->kind)
841 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
842 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
843 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
844 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
845 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
846 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
847 for (j = 0; j < entity->u.comclass.progids.num; j++)
848 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
849 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
850 break;
851 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
852 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
853 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
854 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
855 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
856 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
857 break;
858 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
859 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
860 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
861 break;
862 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
863 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
864 break;
865 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
866 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
867 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
868 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
869 break;
870 default:
871 FIXME("Unknown entity kind %d\n", entity->kind);
874 RtlFreeHeap( GetProcessHeap(), 0, array->base );
877 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
879 if (!str1) return !str2;
880 return str2 && !strcmpiW( str1, str2 );
883 static BOOL is_matching_identity( const struct assembly_identity *id1,
884 const struct assembly_identity *id2 )
886 if (!is_matching_string( id1->name, id2->name )) return FALSE;
887 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
888 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
890 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
892 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
893 return FALSE;
895 if (id1->version.major != id2->version.major) return FALSE;
896 if (id1->version.minor != id2->version.minor) return FALSE;
897 if (id1->version.build > id2->version.build) return FALSE;
898 if (id1->version.build == id2->version.build &&
899 id1->version.revision > id2->version.revision) return FALSE;
900 return TRUE;
903 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
904 struct assembly_identity* ai)
906 unsigned int i;
908 /* check if we already have that assembly */
910 for (i = 0; i < acl->actctx->num_assemblies; i++)
911 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
913 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
914 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
915 ai->version.build, ai->version.revision );
916 return TRUE;
919 for (i = 0; i < acl->num_dependencies; i++)
920 if (is_matching_identity( ai, &acl->dependencies[i] ))
922 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
923 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
924 ai->version.build, ai->version.revision );
925 return TRUE;
928 if (acl->num_dependencies == acl->allocated_dependencies)
930 void *ptr;
931 unsigned int new_count;
932 if (acl->dependencies)
934 new_count = acl->allocated_dependencies * 2;
935 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
936 new_count * sizeof(acl->dependencies[0]));
938 else
940 new_count = 4;
941 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
943 if (!ptr) return FALSE;
944 acl->dependencies = ptr;
945 acl->allocated_dependencies = new_count;
947 acl->dependencies[acl->num_dependencies++] = *ai;
949 return TRUE;
952 static void free_depend_manifests(struct actctx_loader* acl)
954 unsigned int i;
955 for (i = 0; i < acl->num_dependencies; i++)
956 free_assembly_identity(&acl->dependencies[i]);
957 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
960 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
962 static const WCHAR undW[] = {'_',0};
963 static const WCHAR noneW[] = {'n','o','n','e',0};
964 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
966 const WCHAR *arch = ai->arch ? ai->arch : noneW;
967 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
968 const WCHAR *lang = ai->language ? ai->language : noneW;
969 const WCHAR *name = ai->name ? ai->name : noneW;
970 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
971 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
972 WCHAR *ret;
974 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
976 strcpyW( ret, arch );
977 strcatW( ret, undW );
978 strcatW( ret, name );
979 strcatW( ret, undW );
980 strcatW( ret, key );
981 strcatW( ret, undW );
982 sprintfW( ret + strlenW(ret), version_formatW,
983 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
984 strcatW( ret, undW );
985 strcatW( ret, lang );
986 strcatW( ret, undW );
987 strcatW( ret, mskeyW );
988 return ret;
991 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
993 WCHAR *p = buffer;
995 if (!str) return;
996 strcatW( buffer, prefix );
997 p += strlenW(p);
998 *p++ = '"';
999 strcpyW( p, str );
1000 p += strlenW(p);
1001 *p++ = '"';
1002 *p = 0;
1005 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1007 static const WCHAR archW[] =
1008 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1009 static const WCHAR public_keyW[] =
1010 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1011 static const WCHAR typeW[] =
1012 {',','t','y','p','e','=',0};
1013 static const WCHAR versionW[] =
1014 {',','v','e','r','s','i','o','n','=',0};
1016 WCHAR version[64], *ret;
1017 SIZE_T size = 0;
1019 sprintfW( version, version_formatW,
1020 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1021 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1022 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1023 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1024 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1025 size += strlenW(versionW) + strlenW(version) + 2;
1027 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1028 return NULL;
1030 if (ai->name) strcpyW( ret, ai->name );
1031 else *ret = 0;
1032 append_string( ret, archW, ai->arch );
1033 append_string( ret, public_keyW, ai->public_key );
1034 append_string( ret, typeW, ai->type );
1035 append_string( ret, versionW, version );
1036 return ret;
1039 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1041 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1043 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1044 __TRY
1046 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1048 __EXCEPT_PAGE_FAULT
1051 __ENDTRY
1052 return ret;
1055 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1057 interlocked_xchg_add( &actctx->ref_count, 1 );
1060 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1062 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1064 unsigned int i, j;
1066 for (i = 0; i < actctx->num_assemblies; i++)
1068 struct assembly *assembly = &actctx->assemblies[i];
1069 for (j = 0; j < assembly->num_dlls; j++)
1071 struct dll_redirect *dll = &assembly->dlls[j];
1072 free_entity_array( &dll->entities );
1073 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1074 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1077 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1078 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1079 free_entity_array( &assembly->entities );
1080 free_assembly_identity(&assembly->id);
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1091 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1092 actctx->magic = 0;
1093 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1097 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1098 BOOL* error, BOOL* end)
1100 const WCHAR* ptr;
1102 *error = TRUE;
1104 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1105 xmlbuf->ptr++;
1107 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1109 if (*xmlbuf->ptr == '/')
1111 xmlbuf->ptr++;
1112 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1113 return FALSE;
1115 xmlbuf->ptr++;
1116 *end = TRUE;
1117 *error = FALSE;
1118 return FALSE;
1121 if (*xmlbuf->ptr == '>')
1123 xmlbuf->ptr++;
1124 *error = FALSE;
1125 return FALSE;
1128 ptr = xmlbuf->ptr;
1129 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1131 if (ptr == xmlbuf->end) return FALSE;
1133 name->ptr = xmlbuf->ptr;
1134 name->len = ptr-xmlbuf->ptr;
1135 xmlbuf->ptr = ptr;
1137 /* skip spaces before '=' */
1138 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1139 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1141 /* skip '=' itself */
1142 ptr++;
1143 if (ptr == xmlbuf->end) return FALSE;
1145 /* skip spaces after '=' */
1146 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1148 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1150 value->ptr = ++ptr;
1151 if (ptr == xmlbuf->end) return FALSE;
1153 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1154 if (!ptr)
1156 xmlbuf->ptr = xmlbuf->end;
1157 return FALSE;
1160 value->len = ptr - value->ptr;
1161 xmlbuf->ptr = ptr + 1;
1163 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1165 *error = FALSE;
1166 return TRUE;
1169 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1171 const WCHAR* ptr;
1173 for (;;)
1175 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1176 if (!ptr)
1178 xmlbuf->ptr = xmlbuf->end;
1179 return FALSE;
1181 ptr++;
1182 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1184 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1185 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1187 if (ptr + 3 > xmlbuf->end)
1189 xmlbuf->ptr = xmlbuf->end;
1190 return FALSE;
1192 xmlbuf->ptr = ptr + 3;
1194 else break;
1197 xmlbuf->ptr = ptr;
1198 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1199 ptr++;
1201 elem->ptr = xmlbuf->ptr;
1202 elem->len = ptr - xmlbuf->ptr;
1203 xmlbuf->ptr = ptr;
1204 return xmlbuf->ptr != xmlbuf->end;
1207 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1209 /* FIXME: parse attributes */
1210 const WCHAR *ptr;
1212 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1214 if (ptr[0] == '?' && ptr[1] == '>')
1216 xmlbuf->ptr = ptr + 2;
1217 return TRUE;
1220 return FALSE;
1223 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1225 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1227 if (!ptr) return FALSE;
1229 content->ptr = xmlbuf->ptr;
1230 content->len = ptr - xmlbuf->ptr;
1231 xmlbuf->ptr = ptr;
1233 return TRUE;
1236 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1238 unsigned int ver[4];
1239 unsigned int pos;
1240 const WCHAR *curr;
1242 /* major.minor.build.revision */
1243 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1244 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1246 if (*curr >= '0' && *curr <= '9')
1248 ver[pos] = ver[pos] * 10 + *curr - '0';
1249 if (ver[pos] >= 0x10000) goto error;
1251 else if (*curr == '.')
1253 if (++pos >= 4) goto error;
1255 else goto error;
1257 version->major = ver[0];
1258 version->minor = ver[1];
1259 version->build = ver[2];
1260 version->revision = ver[3];
1261 return TRUE;
1263 error:
1264 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1265 return FALSE;
1268 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1270 xmlstr_t elem;
1271 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1272 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1273 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1274 return FALSE;
1277 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1279 xmlstr_t attr_name, attr_value;
1280 BOOL error;
1282 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1284 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1285 debugstr_xmlstr(&attr_value));
1287 return !error;
1290 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1292 BOOL end = FALSE;
1293 return parse_expect_no_attr(xmlbuf, &end) && !end;
1296 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1298 xmlstr_t elem;
1299 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1300 if (!xml_elem_cmp_end(&elem, name, namespace))
1302 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1303 return FALSE;
1305 return parse_end_element(xmlbuf);
1308 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1310 xmlstr_t attr_name, attr_value, elem;
1311 BOOL end = FALSE, error, ret = TRUE;
1313 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1314 if(error || end) return end;
1316 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1318 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1319 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1320 break;
1321 else
1322 ret = parse_unknown_elem(xmlbuf, &elem);
1325 return ret && parse_end_element(xmlbuf);
1328 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1329 struct assembly_identity* ai)
1331 xmlstr_t attr_name, attr_value;
1332 BOOL end = FALSE, error;
1334 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1336 if (xmlstr_cmp(&attr_name, nameW))
1338 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1340 else if (xmlstr_cmp(&attr_name, typeW))
1342 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1344 else if (xmlstr_cmp(&attr_name, versionW))
1346 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1348 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1350 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1352 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1354 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1356 else if (xmlstr_cmp(&attr_name, languageW))
1358 WARN("Unsupported yet language attribute (%s)\n",
1359 debugstr_xmlstr(&attr_value));
1360 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1362 else
1364 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1365 debugstr_xmlstr(&attr_value));
1369 TRACE( "name=%s version=%s arch=%s\n",
1370 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1372 if (error || end) return end;
1373 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1376 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1378 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1379 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1380 static const WCHAR freeW[] = {'F','r','e','e',0};
1381 static const WCHAR bothW[] = {'B','o','t','h',0};
1383 if (value->len == 0) return ThreadingModel_No;
1384 if (xmlstr_cmp(value, apartW))
1385 return ThreadingModel_Apartment;
1386 else if (xmlstr_cmp(value, freeW))
1387 return ThreadingModel_Free;
1388 else if (xmlstr_cmp(value, bothW))
1389 return ThreadingModel_Both;
1390 else if (xmlstr_cmp(value, neutralW))
1391 return ThreadingModel_Neutral;
1392 else
1393 return ThreadingModel_No;
1396 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1398 int min, max;
1400 min = 0;
1401 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1403 while (min <= max)
1405 int n, c;
1407 n = (min+max)/2;
1409 c = strncmpW(olemisc_values[n].name, str, len);
1410 if (!c && !olemisc_values[n].name[len])
1411 return olemisc_values[n].value;
1413 if (c >= 0)
1414 max = n-1;
1415 else
1416 min = n+1;
1419 WARN("unknown flag %s\n", debugstr_wn(str, len));
1420 return 0;
1423 static DWORD parse_com_class_misc(const xmlstr_t *value)
1425 const WCHAR *str = value->ptr, *start;
1426 DWORD flags = 0;
1427 int i = 0;
1429 /* it's comma separated list of flags */
1430 while (i < value->len)
1432 start = str;
1433 while (*str != ',' && (i++ < value->len)) str++;
1435 flags |= get_olemisc_value(start, str-start);
1437 /* skip separator */
1438 str++;
1439 i++;
1442 return flags;
1445 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1447 struct progids *progids = &entity->u.comclass.progids;
1449 if (progids->allocated == 0)
1451 progids->allocated = 4;
1452 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1455 if (progids->allocated == progids->num)
1457 progids->allocated *= 2;
1458 progids->progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1461 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1462 progids->num++;
1464 return TRUE;
1467 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1469 xmlstr_t content;
1470 BOOL end = FALSE;
1472 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1473 return FALSE;
1475 if (!com_class_add_progid(&content, entity)) return FALSE;
1476 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1479 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1481 xmlstr_t elem, attr_name, attr_value;
1482 BOOL ret = TRUE, end = FALSE, error;
1483 struct entity* entity;
1485 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1486 return FALSE;
1488 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1490 if (xmlstr_cmp(&attr_name, clsidW))
1492 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1494 else if (xmlstr_cmp(&attr_name, progidW))
1496 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1498 else if (xmlstr_cmp(&attr_name, tlbidW))
1500 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1502 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1504 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1506 else if (xmlstr_cmp(&attr_name, miscstatusW))
1508 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1510 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1512 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1514 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1516 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1518 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1520 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1522 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1524 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1526 else if (xmlstr_cmp(&attr_name, descriptionW))
1528 /* not stored */
1530 else
1532 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1536 if (error) return FALSE;
1538 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1539 if (entity->u.comclass.progid)
1540 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1542 if (end) return TRUE;
1544 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1546 if (xmlstr_cmp_end(&elem, comClassW))
1548 ret = parse_end_element(xmlbuf);
1549 break;
1551 else if (xmlstr_cmp(&elem, progidW))
1553 ret = parse_com_class_progid(xmlbuf, entity);
1555 else
1557 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1558 ret = parse_unknown_elem(xmlbuf, &elem);
1562 if (entity->u.comclass.progids.num)
1563 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1565 return ret;
1568 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1570 const WCHAR *curr;
1571 ULONG num = 0;
1573 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1575 if (*curr >= '0' && *curr <= '9')
1576 num = num * 10 + *curr - '0';
1577 else
1579 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1580 return FALSE;
1583 entity->u.ifaceps.nummethods = num;
1585 return TRUE;
1588 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1590 xmlstr_t attr_name, attr_value;
1591 BOOL end = FALSE, error;
1592 struct entity* entity;
1594 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1595 return FALSE;
1597 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1599 if (xmlstr_cmp(&attr_name, iidW))
1601 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1603 else if (xmlstr_cmp(&attr_name, nameW))
1605 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1607 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1609 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1610 entity->u.ifaceps.mask |= BaseIface;
1612 else if (xmlstr_cmp(&attr_name, nummethodsW))
1614 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1615 entity->u.ifaceps.mask |= NumMethods;
1617 else if (xmlstr_cmp(&attr_name, tlbidW))
1619 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1621 /* not used */
1622 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1625 else
1627 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1631 if (error) return FALSE;
1632 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1633 if (end) return TRUE;
1635 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1638 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1640 WORD *flags = &entity->u.typelib.flags;
1641 const WCHAR *str = value->ptr, *start;
1642 int i = 0;
1644 *flags = 0;
1646 /* it's comma separated list of flags */
1647 while (i < value->len)
1649 start = str;
1650 while (*str != ',' && (i++ < value->len)) str++;
1652 if (!strncmpiW(start, restrictedW, str-start))
1653 *flags |= LIBFLAG_FRESTRICTED;
1654 else if (!strncmpiW(start, controlW, str-start))
1655 *flags |= LIBFLAG_FCONTROL;
1656 else if (!strncmpiW(start, hiddenW, str-start))
1657 *flags |= LIBFLAG_FHIDDEN;
1658 else if (!strncmpiW(start, hasdiskimageW, str-start))
1659 *flags |= LIBFLAG_FHASDISKIMAGE;
1660 else
1662 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1663 return FALSE;
1666 /* skip separator */
1667 str++;
1668 i++;
1671 return TRUE;
1674 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1676 unsigned int ver[2];
1677 unsigned int pos;
1678 const WCHAR *curr;
1680 /* major.minor */
1681 ver[0] = ver[1] = pos = 0;
1682 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1684 if (*curr >= '0' && *curr <= '9')
1686 ver[pos] = ver[pos] * 10 + *curr - '0';
1687 if (ver[pos] >= 0x10000) goto error;
1689 else if (*curr == '.')
1691 if (++pos >= 2) goto error;
1693 else goto error;
1695 entity->u.typelib.major = ver[0];
1696 entity->u.typelib.minor = ver[1];
1697 return TRUE;
1699 error:
1700 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1701 return FALSE;
1704 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1706 xmlstr_t attr_name, attr_value;
1707 BOOL end = FALSE, error;
1708 struct entity* entity;
1710 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1711 return FALSE;
1713 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1715 if (xmlstr_cmp(&attr_name, tlbidW))
1717 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1719 else if (xmlstr_cmp(&attr_name, versionW))
1721 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1723 else if (xmlstr_cmp(&attr_name, helpdirW))
1725 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1727 else if (xmlstr_cmp(&attr_name, flagsW))
1729 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1731 else
1733 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1737 if (error) return FALSE;
1739 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1741 if (end) return TRUE;
1743 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1746 static inline int aligned_string_len(int len)
1748 return (len + 3) & ~3;
1751 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1753 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1754 struct assembly_version *ver = &assembly->id.version;
1755 WCHAR buff[25];
1757 if (!ret) ret = buff;
1758 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1761 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1763 xmlstr_t elem, content, attr_name, attr_value;
1764 BOOL end = FALSE, ret = TRUE, error;
1765 struct entity* entity;
1767 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1768 return FALSE;
1770 entity->u.class.versioned = TRUE;
1771 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1773 if (xmlstr_cmp(&attr_name, versionedW))
1775 if (xmlstr_cmpi(&attr_value, noW))
1776 entity->u.class.versioned = FALSE;
1777 else if (!xmlstr_cmpi(&attr_value, yesW))
1778 return FALSE;
1780 else
1782 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1786 if (error || end) return end;
1788 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1790 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1792 acl->actctx->sections |= WINDOWCLASS_SECTION;
1794 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1796 if (xmlstr_cmp_end(&elem, windowClassW))
1798 ret = parse_end_element(xmlbuf);
1799 break;
1801 else
1803 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1804 ret = parse_unknown_elem(xmlbuf, &elem);
1808 return ret;
1811 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1813 xmlstr_t attr_name, attr_value;
1814 BOOL end = FALSE, error;
1816 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1818 if (xmlstr_cmp(&attr_name, oldVersionW))
1820 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1822 else if (xmlstr_cmp(&attr_name, newVersionW))
1824 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1826 else
1828 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1832 if (error || end) return end;
1833 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1836 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1838 xmlstr_t elem, content, attr_name, attr_value;
1839 BOOL end = FALSE, ret = TRUE, error = FALSE;
1841 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1842 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1844 if (error) return FALSE;
1845 if (end) return TRUE;
1847 if (!parse_text_content(xmlbuf, &content))
1848 return FALSE;
1850 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1852 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1854 if (xmlstr_cmp_end(&elem, descriptionW))
1856 ret = parse_end_element(xmlbuf);
1857 break;
1859 else
1861 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1862 ret = parse_unknown_elem(xmlbuf, &elem);
1866 return ret;
1869 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1870 struct assembly* assembly,
1871 struct actctx_loader* acl)
1873 xmlstr_t attr_name, attr_value;
1874 BOOL end = FALSE, error;
1875 struct entity* entity;
1877 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1878 if (!entity) return FALSE;
1880 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1882 if (xmlstr_cmp(&attr_name, iidW))
1884 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1886 else if (xmlstr_cmp(&attr_name, nameW))
1888 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1890 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1892 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1893 entity->u.ifaceps.mask |= BaseIface;
1895 else if (xmlstr_cmp(&attr_name, nummethodsW))
1897 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1898 entity->u.ifaceps.mask |= NumMethods;
1900 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1902 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1904 else if (xmlstr_cmp(&attr_name, tlbidW))
1906 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1908 else
1910 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1914 if (error) return FALSE;
1915 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1916 if (end) return TRUE;
1918 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1921 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1923 xmlstr_t attr_name, attr_value, elem;
1924 BOOL end = FALSE, error, ret = TRUE;
1925 struct entity* entity;
1927 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1928 if (!entity) return FALSE;
1930 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1932 if (xmlstr_cmp(&attr_name, nameW))
1934 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1936 else if (xmlstr_cmp(&attr_name, clsidW))
1938 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1940 else if (xmlstr_cmp(&attr_name, progidW))
1942 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1944 else if (xmlstr_cmp(&attr_name, tlbidW))
1946 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1948 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1950 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1952 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1954 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1956 else
1958 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1962 if (error) return FALSE;
1963 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1964 if (entity->u.comclass.progid)
1965 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1966 if (end) return TRUE;
1968 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1970 if (xmlstr_cmp_end(&elem, clrClassW))
1972 ret = parse_end_element(xmlbuf);
1973 break;
1975 else if (xmlstr_cmp(&elem, progidW))
1977 ret = parse_com_class_progid(xmlbuf, entity);
1979 else
1981 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1982 ret = parse_unknown_elem(xmlbuf, &elem);
1986 if (entity->u.comclass.progids.num)
1987 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1989 return ret;
1992 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1994 xmlstr_t attr_name, attr_value;
1995 BOOL end = FALSE, error;
1996 struct entity* entity;
1998 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1999 if (!entity) return FALSE;
2001 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2003 if (xmlstr_cmp(&attr_name, nameW))
2005 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2007 else if (xmlstr_cmp(&attr_name, clsidW))
2009 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2011 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2013 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2015 else
2017 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2021 if (error) return FALSE;
2022 acl->actctx->sections |= CLRSURROGATES_SECTION;
2023 if (end) return TRUE;
2025 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2028 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2030 struct assembly_identity ai;
2031 xmlstr_t elem, attr_name, attr_value;
2032 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2034 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2036 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2037 static const WCHAR trueW[] = {'t','r','u','e',0};
2039 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2040 delayed = xmlstr_cmp(&attr_value, trueW);
2041 else
2042 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2045 if (error || end) return end;
2047 memset(&ai, 0, sizeof(ai));
2048 ai.optional = optional;
2049 ai.delayed = delayed;
2051 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2052 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2053 return FALSE;
2055 TRACE( "adding name=%s version=%s arch=%s\n",
2056 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2058 /* store the newly found identity for later loading */
2059 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2061 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2063 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2065 ret = parse_end_element(xmlbuf);
2066 break;
2068 else if (xmlstr_cmp(&elem, bindingRedirectW))
2070 ret = parse_binding_redirect_elem(xmlbuf);
2072 else
2074 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2075 ret = parse_unknown_elem(xmlbuf, &elem);
2079 return ret;
2082 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2084 xmlstr_t attr_name, attr_value, elem;
2085 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2087 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2089 if (xmlstr_cmp(&attr_name, optionalW))
2091 optional = xmlstr_cmpi( &attr_value, yesW );
2092 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2094 else
2096 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2100 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2102 if (xmlstr_cmp_end(&elem, dependencyW))
2104 ret = parse_end_element(xmlbuf);
2105 break;
2107 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2109 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2111 else
2113 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2114 ret = parse_unknown_elem(xmlbuf, &elem);
2118 return ret;
2121 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2123 BOOL end = FALSE;
2125 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2126 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2129 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2131 BOOL end = FALSE;
2133 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2134 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2137 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2139 xmlstr_t attr_name, attr_value, elem;
2140 BOOL end = FALSE, error, ret = TRUE;
2141 struct dll_redirect* dll;
2143 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2145 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2147 if (xmlstr_cmp(&attr_name, nameW))
2149 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2150 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2152 else if (xmlstr_cmp(&attr_name, hashW))
2154 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2156 else if (xmlstr_cmp(&attr_name, hashalgW))
2158 static const WCHAR sha1W[] = {'S','H','A','1',0};
2159 if (!xmlstr_cmpi(&attr_value, sha1W))
2160 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2162 else
2164 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2168 if (error || !dll->name) return FALSE;
2170 acl->actctx->sections |= DLLREDIRECT_SECTION;
2172 if (end) return TRUE;
2174 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2176 if (xmlstr_cmp_end(&elem, fileW))
2178 ret = parse_end_element(xmlbuf);
2179 break;
2181 else if (xmlstr_cmp(&elem, comClassW))
2183 ret = parse_com_class_elem(xmlbuf, dll, acl);
2185 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2187 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2189 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2191 WARN("asmv2:hash (undocumented) not supported\n");
2192 ret = parse_unknown_elem(xmlbuf, &elem);
2194 else if (xmlstr_cmp(&elem, typelibW))
2196 ret = parse_typelib_elem(xmlbuf, dll, acl);
2198 else if (xmlstr_cmp(&elem, windowClassW))
2200 ret = parse_window_class_elem(xmlbuf, dll, acl);
2202 else
2204 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2205 ret = parse_unknown_elem( xmlbuf, &elem );
2209 return ret;
2212 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2213 struct assembly* assembly,
2214 struct assembly_identity* expected_ai)
2216 xmlstr_t attr_name, attr_value, elem;
2217 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2219 TRACE("(%p)\n", xmlbuf);
2221 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2223 if (xmlstr_cmp(&attr_name, manifestVersionW))
2225 static const WCHAR v10W[] = {'1','.','0',0};
2226 if (!xmlstr_cmp(&attr_value, v10W))
2228 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2229 return FALSE;
2231 version = TRUE;
2233 else if (xmlstr_cmp(&attr_name, xmlnsW))
2235 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2236 !xmlstr_cmp(&attr_value, manifestv2W) &&
2237 !xmlstr_cmp(&attr_value, manifestv3W))
2239 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2240 return FALSE;
2242 xmlns = TRUE;
2244 else
2246 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2250 if (error || end || !xmlns || !version) return FALSE;
2251 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2253 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2255 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2256 return FALSE;
2257 assembly->no_inherit = TRUE;
2260 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2262 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2263 return FALSE;
2265 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2266 assembly->no_inherit)
2267 return FALSE;
2269 while (ret)
2271 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2273 ret = parse_end_element(xmlbuf);
2274 break;
2276 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2278 ret = parse_description_elem(xmlbuf);
2280 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2282 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2284 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2286 ret = parse_dependency_elem(xmlbuf, acl);
2288 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2290 ret = parse_file_elem(xmlbuf, assembly, acl);
2292 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2294 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2296 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2298 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2300 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2302 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2304 if (expected_ai)
2306 /* FIXME: more tests */
2307 if (assembly->type == ASSEMBLY_MANIFEST &&
2308 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2310 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2311 expected_ai->version.major, expected_ai->version.minor,
2312 expected_ai->version.build, expected_ai->version.revision,
2313 assembly->id.version.major, assembly->id.version.minor,
2314 assembly->id.version.build, assembly->id.version.revision);
2315 ret = FALSE;
2317 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2318 (assembly->id.version.major != expected_ai->version.major ||
2319 assembly->id.version.minor != expected_ai->version.minor ||
2320 assembly->id.version.build < expected_ai->version.build ||
2321 (assembly->id.version.build == expected_ai->version.build &&
2322 assembly->id.version.revision < expected_ai->version.revision)))
2324 FIXME("wrong version for shared assembly manifest\n");
2325 ret = FALSE;
2329 else
2331 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2332 ret = parse_unknown_elem(xmlbuf, &elem);
2334 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2337 return ret;
2340 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2341 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2343 xmlstr_t elem;
2345 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2347 if (xmlstr_cmp(&elem, xmlW) &&
2348 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2349 return STATUS_SXS_CANT_GEN_ACTCTX;
2351 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2353 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2354 return STATUS_SXS_CANT_GEN_ACTCTX;
2357 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2359 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2360 return STATUS_SXS_CANT_GEN_ACTCTX;
2363 if (next_xml_elem(xmlbuf, &elem))
2365 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2366 return STATUS_SXS_CANT_GEN_ACTCTX;
2369 if (xmlbuf->ptr != xmlbuf->end)
2371 FIXME("parse error\n");
2372 return STATUS_SXS_CANT_GEN_ACTCTX;
2374 return STATUS_SUCCESS;
2377 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2378 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2379 const void *buffer, SIZE_T size )
2381 xmlbuf_t xmlbuf;
2382 NTSTATUS status;
2383 struct assembly *assembly;
2384 int unicode_tests;
2386 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2388 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2389 return STATUS_SXS_CANT_GEN_ACTCTX;
2391 if (directory && !(assembly->directory = strdupW(directory)))
2392 return STATUS_NO_MEMORY;
2394 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2395 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2396 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2398 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2399 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2401 xmlbuf.ptr = buffer;
2402 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2403 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2405 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2407 const WCHAR *buf = buffer;
2408 WCHAR *new_buff;
2409 unsigned int i;
2411 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2412 return STATUS_NO_MEMORY;
2413 for (i = 0; i < size / sizeof(WCHAR); i++)
2414 new_buff[i] = RtlUshortByteSwap( buf[i] );
2415 xmlbuf.ptr = new_buff;
2416 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2417 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2418 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2420 else
2422 /* let's assume utf-8 for now */
2423 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2424 WCHAR *new_buff;
2426 if (len == -1)
2428 FIXME( "utf-8 conversion failed\n" );
2429 return STATUS_SXS_CANT_GEN_ACTCTX;
2431 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2432 return STATUS_NO_MEMORY;
2433 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2434 xmlbuf.ptr = new_buff;
2435 xmlbuf.end = xmlbuf.ptr + len;
2436 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2437 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2439 return status;
2442 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2444 OBJECT_ATTRIBUTES attr;
2445 IO_STATUS_BLOCK io;
2447 attr.Length = sizeof(attr);
2448 attr.RootDirectory = 0;
2449 attr.Attributes = OBJ_CASE_INSENSITIVE;
2450 attr.ObjectName = name;
2451 attr.SecurityDescriptor = NULL;
2452 attr.SecurityQualityOfService = NULL;
2453 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2456 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2458 NTSTATUS status;
2459 ULONG_PTR magic;
2460 LDR_MODULE *pldr;
2462 LdrLockLoaderLock(0, NULL, &magic);
2463 status = LdrFindEntryForAddress( module, &pldr );
2464 if (status == STATUS_SUCCESS)
2466 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2467 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2469 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2470 str->Length = pldr->FullDllName.Length;
2471 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2473 else status = STATUS_NO_MEMORY;
2475 LdrUnlockLoaderLock(0, magic);
2476 return status;
2479 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2480 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2481 HANDLE hModule, LPCWSTR resname, ULONG lang )
2483 NTSTATUS status;
2484 UNICODE_STRING nameW;
2485 LDR_RESOURCE_INFO info;
2486 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2487 void *ptr;
2489 if (TRACE_ON(actctx))
2491 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2493 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2494 hModule, debugstr_w(nameW.Buffer) );
2495 RtlFreeUnicodeString( &nameW );
2497 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2498 hModule, debugstr_w(filename) );
2501 if (!resname) return STATUS_INVALID_PARAMETER;
2503 info.Type = RT_MANIFEST;
2504 info.Language = lang;
2505 if (!((ULONG_PTR)resname >> 16))
2507 info.Name = (ULONG_PTR)resname;
2508 status = LdrFindResource_U(hModule, &info, 3, &entry);
2510 else if (resname[0] == '#')
2512 ULONG value;
2513 RtlInitUnicodeString(&nameW, resname + 1);
2514 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2515 return STATUS_INVALID_PARAMETER;
2516 info.Name = value;
2517 status = LdrFindResource_U(hModule, &info, 3, &entry);
2519 else
2521 RtlCreateUnicodeString(&nameW, resname);
2522 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2523 info.Name = (ULONG_PTR)nameW.Buffer;
2524 status = LdrFindResource_U(hModule, &info, 3, &entry);
2525 RtlFreeUnicodeString(&nameW);
2527 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2529 if (status == STATUS_SUCCESS)
2530 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2532 return status;
2535 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2536 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2537 HANDLE file, LPCWSTR resname, ULONG lang )
2539 HANDLE mapping;
2540 OBJECT_ATTRIBUTES attr;
2541 LARGE_INTEGER size;
2542 LARGE_INTEGER offset;
2543 NTSTATUS status;
2544 SIZE_T count;
2545 void *base;
2547 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2549 attr.Length = sizeof(attr);
2550 attr.RootDirectory = 0;
2551 attr.ObjectName = NULL;
2552 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2553 attr.SecurityDescriptor = NULL;
2554 attr.SecurityQualityOfService = NULL;
2556 size.QuadPart = 0;
2557 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2558 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2559 if (status != STATUS_SUCCESS) return status;
2561 offset.QuadPart = 0;
2562 count = 0;
2563 base = NULL;
2564 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2565 &count, ViewShare, 0, PAGE_READONLY );
2566 NtClose( mapping );
2567 if (status != STATUS_SUCCESS) return status;
2569 if (RtlImageNtHeader(base)) /* we got a PE file */
2571 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2572 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2574 else status = STATUS_INVALID_IMAGE_FORMAT;
2576 NtUnmapViewOfSection( GetCurrentProcess(), base );
2577 return status;
2580 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2581 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2583 FILE_END_OF_FILE_INFORMATION info;
2584 IO_STATUS_BLOCK io;
2585 HANDLE mapping;
2586 OBJECT_ATTRIBUTES attr;
2587 LARGE_INTEGER size;
2588 LARGE_INTEGER offset;
2589 NTSTATUS status;
2590 SIZE_T count;
2591 void *base;
2593 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2595 attr.Length = sizeof(attr);
2596 attr.RootDirectory = 0;
2597 attr.ObjectName = NULL;
2598 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2599 attr.SecurityDescriptor = NULL;
2600 attr.SecurityQualityOfService = NULL;
2602 size.QuadPart = 0;
2603 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2604 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2605 if (status != STATUS_SUCCESS) return status;
2607 offset.QuadPart = 0;
2608 count = 0;
2609 base = NULL;
2610 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2611 &count, ViewShare, 0, PAGE_READONLY );
2612 NtClose( mapping );
2613 if (status != STATUS_SUCCESS) return status;
2615 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2616 if (status == STATUS_SUCCESS)
2617 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2619 NtUnmapViewOfSection( GetCurrentProcess(), base );
2620 return status;
2623 /* try to load the .manifest file associated to the file */
2624 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2625 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2627 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2628 WCHAR *buffer;
2629 NTSTATUS status;
2630 UNICODE_STRING nameW;
2631 HANDLE file;
2632 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2634 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2636 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2638 if (module) /* use the module filename */
2640 UNICODE_STRING name;
2642 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2644 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2645 strcatW( name.Buffer, dotManifestW );
2646 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2647 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2648 RtlFreeUnicodeString( &name );
2650 if (status) return status;
2652 else
2654 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2655 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2656 return STATUS_NO_MEMORY;
2657 strcpyW( buffer, filename );
2658 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2659 strcatW( buffer, dotManifestW );
2660 RtlInitUnicodeString( &nameW, buffer );
2663 if (!open_nt_file( &file, &nameW ))
2665 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2666 NtClose( file );
2668 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2669 RtlFreeUnicodeString( &nameW );
2670 return status;
2673 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2675 static const WCHAR lookup_fmtW[] =
2676 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2677 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2678 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2680 WCHAR *lookup, *ret = NULL;
2681 UNICODE_STRING lookup_us;
2682 IO_STATUS_BLOCK io;
2683 const WCHAR *lang = ai->language;
2684 unsigned int data_pos = 0, data_len;
2685 char buffer[8192];
2687 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2688 (strlenW(ai->arch) + strlenW(ai->name)
2689 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2690 + sizeof(lookup_fmtW) )))
2691 return NULL;
2693 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2694 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2695 ai->version.major, ai->version.minor, lang );
2696 RtlInitUnicodeString( &lookup_us, lookup );
2698 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2699 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
2700 if (io.u.Status == STATUS_SUCCESS)
2702 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2703 FILE_BOTH_DIR_INFORMATION *dir_info;
2704 WCHAR *tmp;
2705 ULONG build, revision;
2707 data_len = io.Information;
2709 for (;;)
2711 if (data_pos >= data_len)
2713 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2714 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
2715 if (io.u.Status != STATUS_SUCCESS) break;
2716 data_len = io.Information;
2717 data_pos = 0;
2719 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2721 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2722 else data_pos = data_len;
2724 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2725 build = atoiW(tmp);
2726 if (build < min_build) continue;
2727 tmp = strchrW(tmp, '.') + 1;
2728 revision = atoiW(tmp);
2729 if (build == min_build && revision < min_revision) continue;
2730 tmp = strchrW(tmp, '_') + 1;
2731 tmp = strchrW(tmp, '_') + 1;
2732 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2733 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2735 /* prefer a non-Wine manifest if we already have one */
2736 /* we'll still load the builtin dll if specified through DllOverrides */
2737 if (ret) continue;
2739 else
2741 min_build = build;
2742 min_revision = revision;
2744 ai->version.build = build;
2745 ai->version.revision = revision;
2746 RtlFreeHeap( GetProcessHeap(), 0, ret );
2747 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2749 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2750 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2754 else WARN("no matching file for %s\n", debugstr_w(lookup));
2755 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2756 return ret;
2759 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2761 struct assembly_identity sxs_ai;
2762 UNICODE_STRING path_us;
2763 OBJECT_ATTRIBUTES attr;
2764 IO_STATUS_BLOCK io;
2765 WCHAR *path, *file = NULL;
2766 HANDLE handle;
2768 static const WCHAR manifest_dirW[] =
2769 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2771 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2773 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2774 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2775 return STATUS_NO_MEMORY;
2777 strcpyW( path, user_shared_data->NtSystemRoot );
2778 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2780 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2782 RtlFreeHeap( GetProcessHeap(), 0, path );
2783 return STATUS_NO_SUCH_FILE;
2785 RtlFreeHeap( GetProcessHeap(), 0, path );
2787 attr.Length = sizeof(attr);
2788 attr.RootDirectory = 0;
2789 attr.Attributes = OBJ_CASE_INSENSITIVE;
2790 attr.ObjectName = &path_us;
2791 attr.SecurityDescriptor = NULL;
2792 attr.SecurityQualityOfService = NULL;
2794 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2795 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2797 sxs_ai = *ai;
2798 file = lookup_manifest_file( handle, &sxs_ai );
2799 NtClose( handle );
2801 if (!file)
2803 RtlFreeUnicodeString( &path_us );
2804 return STATUS_NO_SUCH_FILE;
2807 /* append file name to directory path */
2808 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2809 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2811 RtlFreeHeap( GetProcessHeap(), 0, file );
2812 RtlFreeUnicodeString( &path_us );
2813 return STATUS_NO_MEMORY;
2816 path[path_us.Length/sizeof(WCHAR)] = '\\';
2817 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2818 RtlInitUnicodeString( &path_us, path );
2819 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2821 if (!open_nt_file( &handle, &path_us ))
2823 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2824 NtClose( handle );
2826 else io.u.Status = STATUS_NO_SUCH_FILE;
2828 RtlFreeHeap( GetProcessHeap(), 0, file );
2829 RtlFreeUnicodeString( &path_us );
2830 return io.u.Status;
2833 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2834 struct assembly_identity* ai)
2836 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2837 unsigned int i;
2838 WCHAR *buffer, *p, *directory;
2839 NTSTATUS status;
2840 UNICODE_STRING nameW;
2841 HANDLE file;
2842 DWORD len;
2844 TRACE( "looking for name=%s version=%s arch=%s\n",
2845 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2847 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2849 /* FIXME: add support for language specific lookup */
2851 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2852 strlenW(acl->actctx->appdir.info));
2854 nameW.Buffer = NULL;
2855 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2856 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2857 return STATUS_NO_MEMORY;
2859 if (!(directory = build_assembly_dir( ai )))
2861 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2862 return STATUS_NO_MEMORY;
2865 /* Lookup in <dir>\name.dll
2866 * <dir>\name.manifest
2867 * <dir>\name\name.dll
2868 * <dir>\name\name.manifest
2870 * First 'appdir' is used as <dir>, if that failed
2871 * it tries application manifest file path.
2873 strcpyW( buffer, acl->actctx->appdir.info );
2874 p = buffer + strlenW(buffer);
2875 for (i = 0; i < 4; i++)
2877 if (i == 2)
2879 struct assembly *assembly = acl->actctx->assemblies;
2880 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
2882 else *p++ = '\\';
2884 strcpyW( p, ai->name );
2885 p += strlenW(p);
2887 strcpyW( p, dotDllW );
2888 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2890 status = open_nt_file( &file, &nameW );
2891 if (!status)
2893 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2894 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2895 NtClose( file );
2896 break;
2898 RtlFreeUnicodeString( &nameW );
2901 strcpyW( p, dotManifestW );
2902 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2904 status = open_nt_file( &file, &nameW );
2905 if (!status)
2907 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2908 NtClose( file );
2909 break;
2911 RtlFreeUnicodeString( &nameW );
2913 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2915 RtlFreeUnicodeString( &nameW );
2916 RtlFreeHeap( GetProcessHeap(), 0, directory );
2917 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2918 return status;
2921 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2923 NTSTATUS status = STATUS_SUCCESS;
2924 unsigned int i;
2926 for (i = 0; i < acl->num_dependencies; i++)
2928 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2930 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
2932 FIXME( "Could not find dependent assembly %s (%s)\n",
2933 debugstr_w(acl->dependencies[i].name),
2934 debugstr_version(&acl->dependencies[i].version) );
2935 status = STATUS_SXS_CANT_GEN_ACTCTX;
2936 break;
2940 /* FIXME should now iterate through all refs */
2941 return status;
2944 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2945 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2947 NTSTATUS status = STATUS_SUCCESS;
2949 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2951 if (*handle) return STATUS_INVALID_PARAMETER;
2953 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2954 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2956 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2958 ULONG_PTR magic;
2959 LDR_MODULE *pldr;
2961 if (!*handle) return STATUS_INVALID_PARAMETER;
2963 LdrLockLoaderLock( 0, NULL, &magic );
2964 if (!LdrFindEntryForAddress( *handle, &pldr ))
2966 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2967 status = STATUS_DLL_NOT_FOUND;
2968 else
2969 *handle = pldr->ActivationContext;
2971 else status = STATUS_DLL_NOT_FOUND;
2972 LdrUnlockLoaderLock( 0, magic );
2974 else if (!*handle && (class != ActivationContextBasicInformation))
2975 *handle = process_actctx;
2977 return status;
2980 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2982 unsigned int i, j, total_len = 0, dll_count = 0;
2983 struct strsection_header *header;
2984 struct dllredirect_data *data;
2985 struct string_index *index;
2986 ULONG name_offset;
2988 /* compute section length */
2989 for (i = 0; i < actctx->num_assemblies; i++)
2991 struct assembly *assembly = &actctx->assemblies[i];
2992 for (j = 0; j < assembly->num_dlls; j++)
2994 struct dll_redirect *dll = &assembly->dlls[j];
2996 /* each entry needs index, data and string data */
2997 total_len += sizeof(*index);
2998 total_len += sizeof(*data);
2999 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3002 dll_count += assembly->num_dlls;
3005 total_len += sizeof(*header);
3007 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3008 if (!header) return STATUS_NO_MEMORY;
3010 memset(header, 0, sizeof(*header));
3011 header->magic = STRSECTION_MAGIC;
3012 header->size = sizeof(*header);
3013 header->count = dll_count;
3014 header->index_offset = sizeof(*header);
3015 index = (struct string_index*)((BYTE*)header + header->index_offset);
3016 name_offset = header->index_offset + header->count*sizeof(*index);
3018 for (i = 0; i < actctx->num_assemblies; i++)
3020 struct assembly *assembly = &actctx->assemblies[i];
3021 for (j = 0; j < assembly->num_dlls; j++)
3023 struct dll_redirect *dll = &assembly->dlls[j];
3024 UNICODE_STRING str;
3025 WCHAR *ptrW;
3027 /* setup new index entry */
3028 str.Buffer = dll->name;
3029 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3030 str.MaximumLength = str.Length + sizeof(WCHAR);
3031 /* hash original class name */
3032 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3034 index->name_offset = name_offset;
3035 index->name_len = str.Length;
3036 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3037 index->data_len = sizeof(*data);
3038 index->rosterindex = i + 1;
3040 /* setup data */
3041 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3042 data->size = sizeof(*data);
3043 data->unk = 2; /* FIXME: seems to be constant */
3044 memset(data->res, 0, sizeof(data->res));
3046 /* dll name */
3047 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3048 memcpy(ptrW, dll->name, index->name_len);
3049 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3051 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3053 index++;
3057 *section = header;
3059 return STATUS_SUCCESS;
3062 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3064 struct string_index *iter, *index = NULL;
3065 ULONG hash = 0, i;
3067 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3068 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3070 for (i = 0; i < section->count; i++)
3072 if (iter->hash == hash)
3074 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3076 if (!strcmpiW(nameW, name->Buffer))
3078 index = iter;
3079 break;
3081 else
3082 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3084 iter++;
3087 return index;
3090 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3092 struct guid_index *iter, *index = NULL;
3093 ULONG i;
3095 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3097 for (i = 0; i < section->count; i++)
3099 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3101 index = iter;
3102 break;
3104 iter++;
3107 return index;
3110 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3112 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3115 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3116 PACTCTX_SECTION_KEYED_DATA data)
3118 struct dllredirect_data *dll;
3119 struct string_index *index;
3121 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3123 if (!actctx->dllredirect_section)
3125 struct strsection_header *section;
3127 NTSTATUS status = build_dllredirect_section(actctx, &section);
3128 if (status) return status;
3130 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3131 RtlFreeHeap(GetProcessHeap(), 0, section);
3134 index = find_string_index(actctx->dllredirect_section, name);
3135 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3137 dll = get_dllredirect_data(actctx, index);
3139 data->ulDataFormatVersion = 1;
3140 data->lpData = dll;
3141 data->ulLength = dll->size;
3142 data->lpSectionGlobalData = NULL;
3143 data->ulSectionGlobalDataLength = 0;
3144 data->lpSectionBase = actctx->dllredirect_section;
3145 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
3146 data->hActCtx = NULL;
3148 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3149 data->ulAssemblyRosterIndex = index->rosterindex;
3151 return STATUS_SUCCESS;
3154 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3156 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3159 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3161 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3164 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3166 unsigned int i, j, k, total_len = 0, class_count = 0;
3167 struct wndclass_redirect_data *data;
3168 struct strsection_header *header;
3169 struct string_index *index;
3170 ULONG name_offset;
3172 /* compute section length */
3173 for (i = 0; i < actctx->num_assemblies; i++)
3175 struct assembly *assembly = &actctx->assemblies[i];
3176 for (j = 0; j < assembly->num_dlls; j++)
3178 struct dll_redirect *dll = &assembly->dlls[j];
3179 for (k = 0; k < dll->entities.num; k++)
3181 struct entity *entity = &dll->entities.base[k];
3182 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3184 int class_len = strlenW(entity->u.class.name) + 1;
3185 int len;
3187 /* each class entry needs index, data and string data */
3188 total_len += sizeof(*index);
3189 total_len += sizeof(*data);
3190 /* original name is stored separately */
3191 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3192 /* versioned name and module name are stored one after another */
3193 if (entity->u.class.versioned)
3194 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3195 else
3196 len = class_len;
3197 len += strlenW(dll->name) + 1;
3198 total_len += aligned_string_len(len*sizeof(WCHAR));
3200 class_count++;
3206 total_len += sizeof(*header);
3208 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3209 if (!header) return STATUS_NO_MEMORY;
3211 memset(header, 0, sizeof(*header));
3212 header->magic = STRSECTION_MAGIC;
3213 header->size = sizeof(*header);
3214 header->count = class_count;
3215 header->index_offset = sizeof(*header);
3216 index = (struct string_index*)((BYTE*)header + header->index_offset);
3217 name_offset = header->index_offset + header->count*sizeof(*index);
3219 for (i = 0; i < actctx->num_assemblies; i++)
3221 struct assembly *assembly = &actctx->assemblies[i];
3222 for (j = 0; j < assembly->num_dlls; j++)
3224 struct dll_redirect *dll = &assembly->dlls[j];
3225 for (k = 0; k < dll->entities.num; k++)
3227 struct entity *entity = &dll->entities.base[k];
3228 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3230 static const WCHAR exclW[] = {'!',0};
3231 ULONG versioned_len, module_len;
3232 UNICODE_STRING str;
3233 WCHAR *ptrW;
3235 /* setup new index entry */
3236 str.Buffer = entity->u.class.name;
3237 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3238 str.MaximumLength = str.Length + sizeof(WCHAR);
3239 /* hash original class name */
3240 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3242 /* include '!' separator too */
3243 if (entity->u.class.versioned)
3244 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3245 else
3246 versioned_len = str.Length;
3247 module_len = strlenW(dll->name)*sizeof(WCHAR);
3249 index->name_offset = name_offset;
3250 index->name_len = str.Length;
3251 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3252 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3253 index->rosterindex = i + 1;
3255 /* setup data */
3256 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3257 data->size = sizeof(*data);
3258 data->res = 0;
3259 data->name_len = versioned_len;
3260 data->name_offset = sizeof(*data);
3261 data->module_len = module_len;
3262 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3264 /* original class name */
3265 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3266 memcpy(ptrW, entity->u.class.name, index->name_len);
3267 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3269 /* module name */
3270 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3271 memcpy(ptrW, dll->name, data->module_len);
3272 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3274 /* versioned name */
3275 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3276 if (entity->u.class.versioned)
3278 get_assembly_version(assembly, ptrW);
3279 strcatW(ptrW, exclW);
3280 strcatW(ptrW, entity->u.class.name);
3282 else
3284 memcpy(ptrW, entity->u.class.name, index->name_len);
3285 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3288 name_offset += sizeof(*data);
3289 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3291 index++;
3297 *section = header;
3299 return STATUS_SUCCESS;
3302 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3303 PACTCTX_SECTION_KEYED_DATA data)
3305 struct string_index *iter, *index = NULL;
3306 struct wndclass_redirect_data *class;
3307 ULONG hash;
3308 int i;
3310 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3312 if (!actctx->wndclass_section)
3314 struct strsection_header *section;
3316 NTSTATUS status = build_wndclass_section(actctx, &section);
3317 if (status) return status;
3319 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3320 RtlFreeHeap(GetProcessHeap(), 0, section);
3323 hash = 0;
3324 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3325 iter = get_wndclass_first_index(actctx);
3327 for (i = 0; i < actctx->wndclass_section->count; i++)
3329 if (iter->hash == hash)
3331 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3333 if (!strcmpW(nameW, name->Buffer))
3335 index = iter;
3336 break;
3338 else
3339 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3341 iter++;
3344 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3346 class = get_wndclass_data(actctx, index);
3348 data->ulDataFormatVersion = 1;
3349 data->lpData = class;
3350 /* full length includes string length with nulls */
3351 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3352 data->lpSectionGlobalData = NULL;
3353 data->ulSectionGlobalDataLength = 0;
3354 data->lpSectionBase = actctx->wndclass_section;
3355 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3356 data->hActCtx = NULL;
3358 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3359 data->ulAssemblyRosterIndex = index->rosterindex;
3361 return STATUS_SUCCESS;
3364 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3366 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3367 struct guidsection_header *header;
3368 ULONG module_offset, data_offset;
3369 struct tlibredirect_data *data;
3370 struct guid_index *index;
3372 /* compute section length */
3373 for (i = 0; i < actctx->num_assemblies; i++)
3375 struct assembly *assembly = &actctx->assemblies[i];
3376 for (j = 0; j < assembly->num_dlls; j++)
3378 struct dll_redirect *dll = &assembly->dlls[j];
3379 for (k = 0; k < dll->entities.num; k++)
3381 struct entity *entity = &dll->entities.base[k];
3382 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3384 /* each entry needs index, data and string data for module name and help string */
3385 total_len += sizeof(*index);
3386 total_len += sizeof(*data);
3387 /* help string is stored separately */
3388 if (*entity->u.typelib.helpdir)
3389 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3391 /* module names are packed one after another */
3392 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3394 tlib_count++;
3400 total_len += aligned_string_len(names_len);
3401 total_len += sizeof(*header);
3403 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3404 if (!header) return STATUS_NO_MEMORY;
3406 memset(header, 0, sizeof(*header));
3407 header->magic = GUIDSECTION_MAGIC;
3408 header->size = sizeof(*header);
3409 header->count = tlib_count;
3410 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3411 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3412 module_offset = sizeof(*header);
3413 data_offset = header->index_offset + tlib_count*sizeof(*index);
3415 for (i = 0; i < actctx->num_assemblies; i++)
3417 struct assembly *assembly = &actctx->assemblies[i];
3418 for (j = 0; j < assembly->num_dlls; j++)
3420 struct dll_redirect *dll = &assembly->dlls[j];
3421 for (k = 0; k < dll->entities.num; k++)
3423 struct entity *entity = &dll->entities.base[k];
3424 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3426 ULONG module_len, help_len;
3427 UNICODE_STRING str;
3428 WCHAR *ptrW;
3430 if (*entity->u.typelib.helpdir)
3431 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3432 else
3433 help_len = 0;
3435 module_len = strlenW(dll->name)*sizeof(WCHAR);
3437 /* setup new index entry */
3438 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3439 RtlGUIDFromString(&str, &index->guid);
3440 index->data_offset = data_offset;
3441 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3442 index->rosterindex = i + 1;
3444 /* setup data */
3445 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3446 data->size = sizeof(*data);
3447 data->res = 0;
3448 data->name_len = module_len;
3449 data->name_offset = module_offset;
3450 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3451 data->langid = 0;
3452 data->flags = entity->u.typelib.flags;
3453 data->help_len = help_len;
3454 data->help_offset = sizeof(*data);
3455 data->major_version = entity->u.typelib.major;
3456 data->minor_version = entity->u.typelib.minor;
3458 /* module name */
3459 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3460 memcpy(ptrW, dll->name, data->name_len);
3461 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3463 /* help string */
3464 if (data->help_len)
3466 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3467 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3468 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3471 data_offset += sizeof(*data);
3472 if (help_len)
3473 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3475 module_offset += module_len + sizeof(WCHAR);
3477 index++;
3483 *section = header;
3485 return STATUS_SUCCESS;
3488 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3490 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3493 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3495 struct guid_index *index = NULL;
3496 struct tlibredirect_data *tlib;
3498 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3500 if (!actctx->tlib_section)
3502 struct guidsection_header *section;
3504 NTSTATUS status = build_tlib_section(actctx, &section);
3505 if (status) return status;
3507 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3508 RtlFreeHeap(GetProcessHeap(), 0, section);
3511 index = find_guid_index(actctx->tlib_section, guid);
3512 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3514 tlib = get_tlib_data(actctx, index);
3516 data->ulDataFormatVersion = 1;
3517 data->lpData = tlib;
3518 /* full length includes string length with nulls */
3519 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3520 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3521 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3522 data->lpSectionBase = actctx->tlib_section;
3523 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3524 data->hActCtx = NULL;
3526 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3527 data->ulAssemblyRosterIndex = index->rosterindex;
3529 return STATUS_SUCCESS;
3532 static void generate_uuid(ULONG *seed, GUID *guid)
3534 ULONG *ptr = (ULONG*)guid;
3535 int i;
3537 /* GUID is 16 bytes long */
3538 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3539 *ptr = RtlUniform(seed);
3541 guid->Data3 &= 0x0fff;
3542 guid->Data3 |= (4 << 12);
3543 guid->Data4[0] &= 0x3f;
3544 guid->Data4[0] |= 0x80;
3547 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3548 unsigned int *count, unsigned int *len, unsigned int *module_len)
3550 unsigned int i;
3552 for (i = 0; i < entities->num; i++)
3554 struct entity *entity = &entities->base[i];
3555 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3557 /* each entry needs two index entries, extra one goes for alias GUID */
3558 *len += 2*sizeof(struct guid_index);
3559 /* To save some memory we don't allocated two data structures,
3560 instead alias index and normal index point to the same data structure. */
3561 *len += sizeof(struct comclassredirect_data);
3563 /* for clrClass store some more */
3564 if (entity->u.comclass.name)
3566 unsigned int str_len;
3568 /* all string data is stored together in aligned block */
3569 str_len = strlenW(entity->u.comclass.name)+1;
3570 if (entity->u.comclass.progid)
3571 str_len += strlenW(entity->u.comclass.progid)+1;
3572 if (entity->u.comclass.version)
3573 str_len += strlenW(entity->u.comclass.version)+1;
3575 *len += sizeof(struct clrclass_data);
3576 *len += aligned_string_len(str_len*sizeof(WCHAR));
3578 /* module name is forced to mscoree.dll, and stored two times with different case */
3579 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3581 else
3583 /* progid string is stored separately */
3584 if (entity->u.comclass.progid)
3585 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3587 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3590 *count += 1;
3595 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3596 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3597 ULONG *seed, ULONG rosterindex)
3599 unsigned int i;
3601 for (i = 0; i < entities->num; i++)
3603 struct entity *entity = &entities->base[i];
3604 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3606 ULONG module_len, progid_len, str_len = 0;
3607 struct comclassredirect_data *data;
3608 struct guid_index *alias_index;
3609 struct clrclass_data *clrdata;
3610 UNICODE_STRING str;
3611 WCHAR *ptrW;
3613 if (entity->u.comclass.progid)
3614 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3615 else
3616 progid_len = 0;
3618 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3620 /* setup new index entry */
3621 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3622 RtlGUIDFromString(&str, &(*index)->guid);
3624 (*index)->data_offset = *data_offset;
3625 (*index)->data_len = sizeof(*data); /* additional length added later */
3626 (*index)->rosterindex = rosterindex;
3628 /* Setup new index entry for alias guid. Alias index records are placed after
3629 normal records, so normal guids are hit first on search. Note that class count
3630 is doubled. */
3631 alias_index = (*index) + section->count/2;
3632 generate_uuid(seed, &alias_index->guid);
3633 alias_index->data_offset = (*index)->data_offset;
3634 alias_index->data_len = 0;
3635 alias_index->rosterindex = (*index)->rosterindex;
3637 /* setup data */
3638 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3639 data->size = sizeof(*data);
3640 data->res = 0;
3641 data->res1[0] = 0;
3642 data->res1[1] = 0;
3643 data->model = entity->u.comclass.model;
3644 data->clsid = (*index)->guid;
3645 data->alias = alias_index->guid;
3646 data->clsid2 = data->clsid;
3647 if (entity->u.comclass.tlbid)
3649 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3650 RtlGUIDFromString(&str, &data->tlbid);
3652 else
3653 memset(&data->tlbid, 0, sizeof(data->tlbid));
3654 data->name_len = module_len;
3655 data->name_offset = *module_offset;
3656 data->progid_len = progid_len;
3657 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3658 data->clrdata_len = 0; /* will be set later */
3659 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3660 data->miscstatus = entity->u.comclass.miscstatus;
3661 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3662 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3663 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3664 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3666 /* mask describes which misc* data is available */
3667 data->miscmask = 0;
3668 if (data->miscstatus)
3669 data->miscmask |= MiscStatus;
3670 if (data->miscstatuscontent)
3671 data->miscmask |= MiscStatusContent;
3672 if (data->miscstatusthumbnail)
3673 data->miscmask |= MiscStatusThumbnail;
3674 if (data->miscstatusicon)
3675 data->miscmask |= MiscStatusIcon;
3676 if (data->miscstatusdocprint)
3677 data->miscmask |= MiscStatusDocPrint;
3679 if (data->clrdata_offset)
3681 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3683 clrdata->size = sizeof(*clrdata);
3684 clrdata->res[0] = 0;
3685 clrdata->res[1] = 2; /* FIXME: unknown field */
3686 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3687 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3688 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3689 clrdata->name_offset = clrdata->size;
3690 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3691 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3692 clrdata->res2[0] = 0;
3693 clrdata->res2[1] = 0;
3695 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3697 /* module name */
3698 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3699 memcpy(ptrW, mscoree2W, clrdata->module_len);
3700 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3702 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3703 memcpy(ptrW, mscoreeW, data->name_len);
3704 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3706 /* class name */
3707 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3708 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3709 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3711 /* runtime version, optional */
3712 if (clrdata->version_len)
3714 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3716 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3717 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3718 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3721 if (data->progid_len)
3722 data->progid_offset += data->clrdata_len;
3723 (*index)->data_len += sizeof(*clrdata);
3725 else
3727 clrdata = NULL;
3729 /* module name */
3730 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3731 memcpy(ptrW, dll->name, data->name_len);
3732 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3735 /* progid string */
3736 if (data->progid_len)
3738 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3739 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3740 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3743 /* string block length */
3744 str_len = 0;
3745 if (clrdata)
3747 str_len += clrdata->name_len + sizeof(WCHAR);
3748 if (clrdata->version_len)
3749 str_len += clrdata->version_len + sizeof(WCHAR);
3751 if (progid_len)
3752 str_len += progid_len + sizeof(WCHAR);
3754 (*index)->data_len += aligned_string_len(str_len);
3755 alias_index->data_len = (*index)->data_len;
3757 /* move to next data record */
3758 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3759 (*module_offset) += module_len + sizeof(WCHAR);
3761 if (clrdata)
3763 (*data_offset) += sizeof(*clrdata);
3764 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3766 (*index) += 1;
3771 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3773 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3774 struct guidsection_header *header;
3775 ULONG module_offset, data_offset;
3776 struct guid_index *index;
3777 ULONG seed;
3779 /* compute section length */
3780 for (i = 0; i < actctx->num_assemblies; i++)
3782 struct assembly *assembly = &actctx->assemblies[i];
3783 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3784 for (j = 0; j < assembly->num_dlls; j++)
3786 struct dll_redirect *dll = &assembly->dlls[j];
3787 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3791 total_len += aligned_string_len(names_len);
3792 total_len += sizeof(*header);
3794 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3795 if (!header) return STATUS_NO_MEMORY;
3797 memset(header, 0, sizeof(*header));
3798 header->magic = GUIDSECTION_MAGIC;
3799 header->size = sizeof(*header);
3800 header->count = 2*class_count;
3801 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3802 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3803 module_offset = sizeof(*header);
3804 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3806 seed = NtGetTickCount();
3807 for (i = 0; i < actctx->num_assemblies; i++)
3809 struct assembly *assembly = &actctx->assemblies[i];
3810 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3811 for (j = 0; j < assembly->num_dlls; j++)
3813 struct dll_redirect *dll = &assembly->dlls[j];
3814 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3818 *section = header;
3820 return STATUS_SUCCESS;
3823 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3825 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3828 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3830 struct comclassredirect_data *comclass;
3831 struct guid_index *index = NULL;
3833 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3835 if (!actctx->comserver_section)
3837 struct guidsection_header *section;
3839 NTSTATUS status = build_comserver_section(actctx, &section);
3840 if (status) return status;
3842 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3843 RtlFreeHeap(GetProcessHeap(), 0, section);
3846 index = find_guid_index(actctx->comserver_section, guid);
3847 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3849 comclass = get_comclass_data(actctx, index);
3851 data->ulDataFormatVersion = 1;
3852 data->lpData = comclass;
3853 /* full length includes string length with nulls */
3854 data->ulLength = comclass->size + comclass->clrdata_len;
3855 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
3856 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3857 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3858 data->lpSectionBase = actctx->comserver_section;
3859 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3860 data->hActCtx = NULL;
3862 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3863 data->ulAssemblyRosterIndex = index->rosterindex;
3865 return STATUS_SUCCESS;
3868 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3870 unsigned int i;
3872 for (i = 0; i < entities->num; i++)
3874 struct entity *entity = &entities->base[i];
3875 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3877 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3878 if (entity->u.ifaceps.name)
3879 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3880 *count += 1;
3885 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3886 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3888 unsigned int i;
3890 for (i = 0; i < entities->num; i++)
3892 struct entity *entity = &entities->base[i];
3893 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3895 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3896 UNICODE_STRING str;
3897 ULONG name_len;
3899 if (entity->u.ifaceps.name)
3900 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3901 else
3902 name_len = 0;
3904 /* setup index */
3905 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3906 RtlGUIDFromString(&str, &(*index)->guid);
3907 (*index)->data_offset = *data_offset;
3908 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3909 (*index)->rosterindex = rosterindex;
3911 /* setup data record */
3912 data->size = sizeof(*data);
3913 data->mask = entity->u.ifaceps.mask;
3915 /* proxyStubClsid32 value is only stored for external PS,
3916 if set it's used as iid, otherwise 'iid' attribute value is used */
3917 if (entity->u.ifaceps.ps32)
3919 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3920 RtlGUIDFromString(&str, &data->iid);
3922 else
3923 data->iid = (*index)->guid;
3925 data->nummethods = entity->u.ifaceps.nummethods;
3927 if (entity->u.ifaceps.tlib)
3929 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3930 RtlGUIDFromString(&str, &data->tlbid);
3932 else
3933 memset(&data->tlbid, 0, sizeof(data->tlbid));
3935 if (entity->u.ifaceps.base)
3937 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3938 RtlGUIDFromString(&str, &data->base);
3940 else
3941 memset(&data->base, 0, sizeof(data->base));
3943 data->name_len = name_len;
3944 data->name_offset = data->name_len ? sizeof(*data) : 0;
3946 /* name string */
3947 if (data->name_len)
3949 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3950 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3951 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3954 /* move to next record */
3955 (*index) += 1;
3956 *data_offset += sizeof(*data);
3957 if (data->name_len)
3958 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3963 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3965 unsigned int i, j, total_len = 0, count = 0;
3966 struct guidsection_header *header;
3967 struct guid_index *index;
3968 ULONG data_offset;
3970 /* compute section length */
3971 for (i = 0; i < actctx->num_assemblies; i++)
3973 struct assembly *assembly = &actctx->assemblies[i];
3975 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3976 for (j = 0; j < assembly->num_dlls; j++)
3978 struct dll_redirect *dll = &assembly->dlls[j];
3979 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3983 total_len += sizeof(*header);
3985 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3986 if (!header) return STATUS_NO_MEMORY;
3988 memset(header, 0, sizeof(*header));
3989 header->magic = GUIDSECTION_MAGIC;
3990 header->size = sizeof(*header);
3991 header->count = count;
3992 header->index_offset = sizeof(*header);
3993 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3994 data_offset = header->index_offset + count*sizeof(*index);
3996 for (i = 0; i < actctx->num_assemblies; i++)
3998 struct assembly *assembly = &actctx->assemblies[i];
4000 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4001 for (j = 0; j < assembly->num_dlls; j++)
4003 struct dll_redirect *dll = &assembly->dlls[j];
4004 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4008 *section = header;
4010 return STATUS_SUCCESS;
4013 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4015 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4018 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4020 struct ifacepsredirect_data *iface;
4021 struct guid_index *index = NULL;
4023 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4025 if (!actctx->ifaceps_section)
4027 struct guidsection_header *section;
4029 NTSTATUS status = build_ifaceps_section(actctx, &section);
4030 if (status) return status;
4032 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4033 RtlFreeHeap(GetProcessHeap(), 0, section);
4036 index = find_guid_index(actctx->ifaceps_section, guid);
4037 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4039 iface = get_ifaceps_data(actctx, index);
4041 data->ulDataFormatVersion = 1;
4042 data->lpData = iface;
4043 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4044 data->lpSectionGlobalData = NULL;
4045 data->ulSectionGlobalDataLength = 0;
4046 data->lpSectionBase = actctx->ifaceps_section;
4047 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4048 data->hActCtx = NULL;
4050 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4051 data->ulAssemblyRosterIndex = index->rosterindex;
4053 return STATUS_SUCCESS;
4056 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4058 unsigned int i, j, total_len = 0, count = 0;
4059 struct guidsection_header *header;
4060 struct clrsurrogate_data *data;
4061 struct guid_index *index;
4062 ULONG data_offset;
4064 /* compute section length */
4065 for (i = 0; i < actctx->num_assemblies; i++)
4067 struct assembly *assembly = &actctx->assemblies[i];
4068 for (j = 0; j < assembly->entities.num; j++)
4070 struct entity *entity = &assembly->entities.base[j];
4071 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4073 ULONG len;
4075 total_len += sizeof(*index) + sizeof(*data);
4076 len = strlenW(entity->u.clrsurrogate.name) + 1;
4077 if (entity->u.clrsurrogate.version)
4078 len += strlenW(entity->u.clrsurrogate.version) + 1;
4079 total_len += aligned_string_len(len*sizeof(WCHAR));
4081 count++;
4086 total_len += sizeof(*header);
4088 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4089 if (!header) return STATUS_NO_MEMORY;
4091 memset(header, 0, sizeof(*header));
4092 header->magic = GUIDSECTION_MAGIC;
4093 header->size = sizeof(*header);
4094 header->count = count;
4095 header->index_offset = sizeof(*header);
4096 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4097 data_offset = header->index_offset + count*sizeof(*index);
4099 for (i = 0; i < actctx->num_assemblies; i++)
4101 struct assembly *assembly = &actctx->assemblies[i];
4102 for (j = 0; j < assembly->entities.num; j++)
4104 struct entity *entity = &assembly->entities.base[j];
4105 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4107 ULONG version_len, name_len;
4108 UNICODE_STRING str;
4109 WCHAR *ptrW;
4111 if (entity->u.clrsurrogate.version)
4112 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4113 else
4114 version_len = 0;
4115 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4117 /* setup new index entry */
4118 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4119 RtlGUIDFromString(&str, &index->guid);
4121 index->data_offset = data_offset;
4122 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4123 index->rosterindex = i + 1;
4125 /* setup data */
4126 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4127 data->size = sizeof(*data);
4128 data->res = 0;
4129 data->clsid = index->guid;
4130 data->version_offset = version_len ? data->size : 0;
4131 data->version_len = version_len;
4132 data->name_offset = data->size + version_len;
4133 if (version_len)
4134 data->name_offset += sizeof(WCHAR);
4135 data->name_len = name_len;
4137 /* surrogate name */
4138 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4139 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4140 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4142 /* runtime version */
4143 if (data->version_len)
4145 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4146 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4147 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4150 data_offset += index->data_offset;
4151 index++;
4156 *section = header;
4158 return STATUS_SUCCESS;
4161 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4163 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4166 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4168 struct clrsurrogate_data *surrogate;
4169 struct guid_index *index = NULL;
4171 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4173 if (!actctx->clrsurrogate_section)
4175 struct guidsection_header *section;
4177 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4178 if (status) return status;
4180 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4181 RtlFreeHeap(GetProcessHeap(), 0, section);
4184 index = find_guid_index(actctx->clrsurrogate_section, guid);
4185 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4187 surrogate = get_surrogate_data(actctx, index);
4189 data->ulDataFormatVersion = 1;
4190 data->lpData = surrogate;
4191 /* full length includes string length with nulls */
4192 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4193 if (surrogate->version_len)
4194 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4196 data->lpSectionGlobalData = NULL;
4197 data->ulSectionGlobalDataLength = 0;
4198 data->lpSectionBase = actctx->clrsurrogate_section;
4199 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4200 data->hActCtx = NULL;
4202 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4203 data->ulAssemblyRosterIndex = index->rosterindex;
4205 return STATUS_SUCCESS;
4208 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4210 unsigned int i, j, single_len;
4212 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4213 for (i = 0; i < entities->num; i++)
4215 struct entity *entity = &entities->base[i];
4216 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4218 if (entity->u.comclass.progid)
4220 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4221 *count += 1;
4224 for (j = 0; j < entity->u.comclass.progids.num; j++)
4225 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4227 *total_len += single_len*entity->u.comclass.progids.num;
4228 *count += entity->u.comclass.progids.num;
4233 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4234 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4236 struct progidredirect_data *data;
4237 UNICODE_STRING str;
4238 GUID *guid_ptr;
4239 WCHAR *ptrW;
4241 /* setup new index entry */
4243 /* hash progid name */
4244 RtlInitUnicodeString(&str, progid);
4245 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4247 (*index)->name_offset = *data_offset;
4248 (*index)->name_len = str.Length;
4249 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4250 (*index)->data_len = sizeof(*data);
4251 (*index)->rosterindex = rosterindex;
4253 *data_offset += aligned_string_len(str.MaximumLength);
4255 /* setup data structure */
4256 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4257 data->size = sizeof(*data);
4258 data->reserved = 0;
4259 data->clsid_offset = *global_offset;
4261 /* write progid string */
4262 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4263 memcpy(ptrW, progid, (*index)->name_len);
4264 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4266 /* write guid to global area */
4267 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4268 *guid_ptr = *alias;
4270 /* to next entry */
4271 *global_offset += sizeof(GUID);
4272 *data_offset += data->size;
4273 (*index) += 1;
4276 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4277 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4279 unsigned int i, j;
4281 for (i = 0; i < entities->num; i++)
4283 struct entity *entity = &entities->base[i];
4284 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4286 const struct progids *progids = &entity->u.comclass.progids;
4287 struct comclassredirect_data *comclass;
4288 struct guid_index *guid_index;
4289 UNICODE_STRING str;
4290 GUID clsid;
4292 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4293 RtlGUIDFromString(&str, &clsid);
4295 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4296 comclass = get_comclass_data(actctx, guid_index);
4298 if (entity->u.comclass.progid)
4299 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4300 index, data_offset, global_offset, rosterindex);
4302 for (j = 0; j < progids->num; j++)
4303 write_progid_record(section, progids->progids[j], &comclass->alias,
4304 index, data_offset, global_offset, rosterindex);
4309 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4311 unsigned int i, j, total_len = 0, count = 0;
4312 struct strsection_header *header;
4313 ULONG data_offset, global_offset;
4314 struct string_index *index;
4316 /* compute section length */
4317 for (i = 0; i < actctx->num_assemblies; i++)
4319 struct assembly *assembly = &actctx->assemblies[i];
4321 get_progid_datalen(&assembly->entities, &count, &total_len);
4322 for (j = 0; j < assembly->num_dlls; j++)
4324 struct dll_redirect *dll = &assembly->dlls[j];
4325 get_progid_datalen(&dll->entities, &count, &total_len);
4329 total_len += sizeof(*header);
4331 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4332 if (!header) return STATUS_NO_MEMORY;
4334 memset(header, 0, sizeof(*header));
4335 header->magic = STRSECTION_MAGIC;
4336 header->size = sizeof(*header);
4337 header->count = count;
4338 header->global_offset = header->size;
4339 header->global_len = count*sizeof(GUID);
4340 header->index_offset = header->size + header->global_len;
4342 index = (struct string_index*)((BYTE*)header + header->index_offset);
4343 data_offset = header->index_offset + count*sizeof(*index);
4344 global_offset = header->global_offset;
4346 for (i = 0; i < actctx->num_assemblies; i++)
4348 struct assembly *assembly = &actctx->assemblies[i];
4350 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4351 for (j = 0; j < assembly->num_dlls; j++)
4353 struct dll_redirect *dll = &assembly->dlls[j];
4354 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4358 *section = header;
4360 return STATUS_SUCCESS;
4363 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4365 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4368 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4369 PACTCTX_SECTION_KEYED_DATA data)
4371 struct progidredirect_data *progid;
4372 struct string_index *index;
4374 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4376 if (!actctx->comserver_section)
4378 struct guidsection_header *section;
4380 NTSTATUS status = build_comserver_section(actctx, &section);
4381 if (status) return status;
4383 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4384 RtlFreeHeap(GetProcessHeap(), 0, section);
4387 if (!actctx->progid_section)
4389 struct strsection_header *section;
4391 NTSTATUS status = build_progid_section(actctx, &section);
4392 if (status) return status;
4394 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4395 RtlFreeHeap(GetProcessHeap(), 0, section);
4398 index = find_string_index(actctx->progid_section, name);
4399 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4401 progid = get_progid_data(actctx, index);
4403 data->ulDataFormatVersion = 1;
4404 data->lpData = progid;
4405 data->ulLength = progid->size;
4406 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4407 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4408 data->lpSectionBase = actctx->progid_section;
4409 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4410 data->hActCtx = NULL;
4412 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4413 data->ulAssemblyRosterIndex = index->rosterindex;
4415 return STATUS_SUCCESS;
4418 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4419 const UNICODE_STRING *section_name,
4420 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4422 NTSTATUS status;
4424 switch (section_kind)
4426 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4427 status = find_dll_redirection(actctx, section_name, data);
4428 break;
4429 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4430 status = find_window_class(actctx, section_name, data);
4431 break;
4432 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4433 status = find_progid_redirection(actctx, section_name, data);
4434 break;
4435 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4436 FIXME("Unsupported yet section_kind %x\n", section_kind);
4437 return STATUS_SXS_SECTION_NOT_FOUND;
4438 default:
4439 WARN("Unknown section_kind %x\n", section_kind);
4440 return STATUS_SXS_SECTION_NOT_FOUND;
4443 if (status != STATUS_SUCCESS) return status;
4445 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4447 actctx_addref(actctx);
4448 data->hActCtx = actctx;
4450 return STATUS_SUCCESS;
4453 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4454 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4456 NTSTATUS status;
4458 switch (section_kind)
4460 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4461 status = find_tlib_redirection(actctx, guid, data);
4462 break;
4463 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4464 status = find_comserver_redirection(actctx, guid, data);
4465 break;
4466 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4467 status = find_cominterface_redirection(actctx, guid, data);
4468 break;
4469 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4470 status = find_clr_surrogate(actctx, guid, data);
4471 break;
4472 default:
4473 WARN("Unknown section_kind %x\n", section_kind);
4474 return STATUS_SXS_SECTION_NOT_FOUND;
4477 if (status != STATUS_SUCCESS) return status;
4479 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4481 actctx_addref(actctx);
4482 data->hActCtx = actctx;
4484 return STATUS_SUCCESS;
4487 /* initialize the activation context for the current process */
4488 void actctx_init(void)
4490 ACTCTXW ctx;
4491 HANDLE handle;
4493 ctx.cbSize = sizeof(ctx);
4494 ctx.lpSource = NULL;
4495 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4496 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4497 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4499 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4503 /***********************************************************************
4504 * RtlCreateActivationContext (NTDLL.@)
4506 * Create an activation context.
4508 * FIXME: function signature/prototype is wrong
4510 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4512 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4513 const WCHAR *directory = NULL;
4514 ACTIVATION_CONTEXT *actctx;
4515 UNICODE_STRING nameW;
4516 ULONG lang = 0;
4517 NTSTATUS status = STATUS_NO_MEMORY;
4518 HANDLE file = 0;
4519 struct actctx_loader acl;
4521 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4523 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4524 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4525 return STATUS_INVALID_PARAMETER;
4527 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4528 return STATUS_NO_MEMORY;
4530 actctx->magic = ACTCTX_MAGIC;
4531 actctx->ref_count = 1;
4532 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4533 actctx->config.info = NULL;
4534 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4535 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4537 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4539 else
4541 UNICODE_STRING dir;
4542 WCHAR *p;
4543 HMODULE module;
4545 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4546 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4548 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4549 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4550 actctx->appdir.info = dir.Buffer;
4553 nameW.Buffer = NULL;
4555 /* open file only if it's going to be used */
4556 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4557 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4559 WCHAR *source = NULL;
4560 BOOLEAN ret;
4562 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4563 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4565 DWORD dir_len, source_len;
4567 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4568 source_len = strlenW(pActCtx->lpSource);
4569 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4571 status = STATUS_NO_MEMORY;
4572 goto error;
4575 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4576 source[dir_len] = '\\';
4577 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4580 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4581 if (source) RtlFreeHeap( GetProcessHeap(), 0, source );
4582 if (!ret)
4584 status = STATUS_NO_SUCH_FILE;
4585 goto error;
4587 status = open_nt_file( &file, &nameW );
4588 if (status)
4590 RtlFreeUnicodeString( &nameW );
4591 goto error;
4595 acl.actctx = actctx;
4596 acl.dependencies = NULL;
4597 acl.num_dependencies = 0;
4598 acl.allocated_dependencies = 0;
4600 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4601 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4603 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4605 /* if we have a resource it's a PE file */
4606 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4608 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4609 pActCtx->lpResourceName, lang );
4610 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4611 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4612 pActCtx->hModule, pActCtx->lpResourceName );
4614 else if (pActCtx->lpSource)
4616 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4617 file, pActCtx->lpResourceName, lang );
4618 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4619 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4620 NULL, pActCtx->lpResourceName );
4622 else status = STATUS_INVALID_PARAMETER;
4624 else
4626 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4629 if (file) NtClose( file );
4630 RtlFreeUnicodeString( &nameW );
4632 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4633 free_depend_manifests( &acl );
4635 if (status == STATUS_SUCCESS) *handle = actctx;
4636 else actctx_release( actctx );
4637 return status;
4639 error:
4640 if (file) NtClose( file );
4641 actctx_release( actctx );
4642 return status;
4646 /***********************************************************************
4647 * RtlAddRefActivationContext (NTDLL.@)
4649 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4651 ACTIVATION_CONTEXT *actctx;
4653 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4657 /******************************************************************
4658 * RtlReleaseActivationContext (NTDLL.@)
4660 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4662 ACTIVATION_CONTEXT *actctx;
4664 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4667 /******************************************************************
4668 * RtlZombifyActivationContext (NTDLL.@)
4670 * FIXME: function prototype might be wrong
4672 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4674 FIXME("%p: stub\n", handle);
4675 return STATUS_NOT_IMPLEMENTED;
4678 /******************************************************************
4679 * RtlActivateActivationContext (NTDLL.@)
4681 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4683 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4685 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4686 return STATUS_NO_MEMORY;
4688 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4689 frame->ActivationContext = handle;
4690 frame->Flags = 0;
4691 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4692 RtlAddRefActivationContext( handle );
4694 *cookie = (ULONG_PTR)frame;
4695 TRACE( "%p cookie=%lx\n", handle, *cookie );
4696 return STATUS_SUCCESS;
4700 /***********************************************************************
4701 * RtlDeactivateActivationContext (NTDLL.@)
4703 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4705 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4707 TRACE( "%x cookie=%lx\n", flags, cookie );
4709 /* find the right frame */
4710 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4711 for (frame = top; frame; frame = frame->Previous)
4712 if ((ULONG_PTR)frame == cookie) break;
4714 if (!frame)
4715 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4717 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4718 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4720 /* pop everything up to and including frame */
4721 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4723 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4725 frame = top->Previous;
4726 RtlReleaseActivationContext( top->ActivationContext );
4727 RtlFreeHeap( GetProcessHeap(), 0, top );
4728 top = frame;
4733 /******************************************************************
4734 * RtlFreeThreadActivationContextStack (NTDLL.@)
4736 void WINAPI RtlFreeThreadActivationContextStack(void)
4738 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4740 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4741 while (frame)
4743 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4744 RtlReleaseActivationContext( frame->ActivationContext );
4745 RtlFreeHeap( GetProcessHeap(), 0, frame );
4746 frame = prev;
4748 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4752 /******************************************************************
4753 * RtlGetActiveActivationContext (NTDLL.@)
4755 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4757 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4759 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4760 RtlAddRefActivationContext( *handle );
4762 else
4763 *handle = 0;
4765 return STATUS_SUCCESS;
4769 /******************************************************************
4770 * RtlIsActivationContextActive (NTDLL.@)
4772 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4774 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4776 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4777 if (frame->ActivationContext == handle) return TRUE;
4778 return FALSE;
4782 /***********************************************************************
4783 * RtlQueryInformationActivationContext (NTDLL.@)
4785 * Get information about an activation context.
4786 * FIXME: function signature/prototype may be wrong
4788 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4789 ULONG class, PVOID buffer,
4790 SIZE_T bufsize, SIZE_T *retlen )
4792 ACTIVATION_CONTEXT *actctx;
4793 NTSTATUS status;
4795 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4796 subinst, class, buffer, bufsize, retlen);
4798 if (retlen) *retlen = 0;
4799 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4801 switch (class)
4803 case ActivationContextBasicInformation:
4805 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4807 if (retlen) *retlen = sizeof(*info);
4808 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4810 info->hActCtx = handle;
4811 info->dwFlags = 0; /* FIXME */
4812 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4814 break;
4816 case ActivationContextDetailedInformation:
4818 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4819 struct assembly *assembly = NULL;
4820 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4821 LPWSTR ptr;
4823 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4825 if (actctx->num_assemblies) assembly = actctx->assemblies;
4827 if (assembly && assembly->manifest.info)
4828 manifest_len = strlenW(assembly->manifest.info) + 1;
4829 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4830 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4831 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4833 if (retlen) *retlen = len;
4834 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4836 acdi->dwFlags = 0;
4837 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4838 acdi->ulAssemblyCount = actctx->num_assemblies;
4839 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4840 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4841 acdi->ulRootConfigurationPathType = actctx->config.type;
4842 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4843 acdi->ulAppDirPathType = actctx->appdir.type;
4844 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4845 ptr = (LPWSTR)(acdi + 1);
4846 if (manifest_len)
4848 acdi->lpRootManifestPath = ptr;
4849 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4850 ptr += manifest_len;
4852 else acdi->lpRootManifestPath = NULL;
4853 if (config_len)
4855 acdi->lpRootConfigurationPath = ptr;
4856 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4857 ptr += config_len;
4859 else acdi->lpRootConfigurationPath = NULL;
4860 if (appdir_len)
4862 acdi->lpAppDirPath = ptr;
4863 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4865 else acdi->lpAppDirPath = NULL;
4867 break;
4869 case AssemblyDetailedInformationInActivationContext:
4871 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4872 struct assembly *assembly;
4873 WCHAR *assembly_id;
4874 DWORD index;
4875 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4876 LPWSTR ptr;
4878 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4879 if (!subinst) return STATUS_INVALID_PARAMETER;
4881 index = *(DWORD*)subinst;
4882 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4884 assembly = &actctx->assemblies[index - 1];
4886 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4887 id_len = strlenW(assembly_id) + 1;
4888 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4890 if (assembly->manifest.info &&
4891 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4892 path_len = strlenW(assembly->manifest.info) + 1;
4894 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4896 if (retlen) *retlen = len;
4897 if (!buffer || bufsize < len)
4899 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4900 return STATUS_BUFFER_TOO_SMALL;
4903 afdi->ulFlags = 0; /* FIXME */
4904 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4905 afdi->ulManifestPathType = assembly->manifest.type;
4906 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4907 /* FIXME afdi->liManifestLastWriteTime = 0; */
4908 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4909 afdi->ulPolicyPathLength = 0;
4910 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4911 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4912 afdi->ulManifestVersionMajor = 1;
4913 afdi->ulManifestVersionMinor = 0;
4914 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4915 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4916 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4917 ptr = (LPWSTR)(afdi + 1);
4918 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4919 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4920 ptr += id_len;
4921 if (path_len)
4923 afdi->lpAssemblyManifestPath = ptr;
4924 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4925 ptr += path_len;
4926 } else afdi->lpAssemblyManifestPath = NULL;
4927 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4928 if (ad_len)
4930 afdi->lpAssemblyDirectoryName = ptr;
4931 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4933 else afdi->lpAssemblyDirectoryName = NULL;
4934 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4936 break;
4938 case FileInformationInAssemblyOfAssemblyInActivationContext:
4940 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4941 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4942 struct assembly *assembly;
4943 struct dll_redirect *dll;
4944 SIZE_T len, dll_len = 0;
4945 LPWSTR ptr;
4947 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4948 if (!acqi) return STATUS_INVALID_PARAMETER;
4950 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4951 return STATUS_INVALID_PARAMETER;
4952 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4954 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4955 return STATUS_INVALID_PARAMETER;
4956 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4958 if (dll->name) dll_len = strlenW(dll->name) + 1;
4959 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4961 if (!buffer || bufsize < len)
4963 if (retlen) *retlen = len;
4964 return STATUS_BUFFER_TOO_SMALL;
4966 if (retlen) *retlen = 0; /* yes that's what native does !! */
4967 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4968 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4969 afdi->ulPathLength = 0; /* FIXME */
4970 ptr = (LPWSTR)(afdi + 1);
4971 if (dll_len)
4973 afdi->lpFileName = ptr;
4974 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4975 } else afdi->lpFileName = NULL;
4976 afdi->lpFilePath = NULL; /* FIXME */
4978 break;
4980 default:
4981 FIXME( "class %u not implemented\n", class );
4982 return STATUS_NOT_IMPLEMENTED;
4984 return STATUS_SUCCESS;
4987 /***********************************************************************
4988 * RtlFindActivationContextSectionString (NTDLL.@)
4990 * Find information about a string in an activation context.
4991 * FIXME: function signature/prototype may be wrong
4993 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
4994 const UNICODE_STRING *section_name, PVOID ptr )
4996 PACTCTX_SECTION_KEYED_DATA data = ptr;
4997 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
4999 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5000 debugstr_us(section_name), data);
5002 if (guid)
5004 FIXME("expected guid == NULL\n");
5005 return STATUS_INVALID_PARAMETER;
5007 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5009 FIXME("unknown flags %08x\n", flags);
5010 return STATUS_INVALID_PARAMETER;
5012 if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
5013 !section_name || !section_name->Buffer)
5015 WARN("invalid parameter\n");
5016 return STATUS_INVALID_PARAMETER;
5019 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5021 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5022 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5025 if (status != STATUS_SUCCESS)
5026 status = find_string( process_actctx, section_kind, section_name, flags, data );
5028 return status;
5031 /***********************************************************************
5032 * RtlFindActivationContextSectionGuid (NTDLL.@)
5034 * Find information about a GUID in an activation context.
5035 * FIXME: function signature/prototype may be wrong
5037 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5038 const GUID *guid, void *ptr )
5040 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5041 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5043 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5045 if (extguid)
5047 FIXME("expected extguid == NULL\n");
5048 return STATUS_INVALID_PARAMETER;
5051 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5053 FIXME("unknown flags %08x\n", flags);
5054 return STATUS_INVALID_PARAMETER;
5057 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5058 return STATUS_INVALID_PARAMETER;
5060 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5062 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5063 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5066 if (status != STATUS_SUCCESS)
5067 status = find_guid( process_actctx, section_kind, guid, flags, data );
5069 return status;