ddraw/tests: Add another invalid arguments test for surface QI.
[wine.git] / dlls / ntdll / actctx.c
blob323ee68fc09bfb298e10af55134f6847340e6786
1 /*
2 * Activation contexts
4 * Copyright 2004 Jon Griffiths
5 * Copyright 2007 Eric Pouech
6 * Copyright 2007 Jacek Caban for CodeWeavers
7 * Copyright 2007 Alexandre Julliard
8 * Copyright 2013 Nikolay Sivov
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #define NONAMELESSUNION
34 #include "winternl.h"
35 #include "ddk/wdm.h"
36 #include "ntdll_misc.h"
37 #include "wine/exception.h"
38 #include "wine/debug.h"
39 #include "wine/unicode.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(actctx);
43 #define ACTCTX_FLAGS_ALL (\
44 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
45 ACTCTX_FLAG_LANGID_VALID |\
46 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
47 ACTCTX_FLAG_RESOURCE_NAME_VALID |\
48 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
49 ACTCTX_FLAG_APPLICATION_NAME_VALID |\
50 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
51 ACTCTX_FLAG_HMODULE_VALID )
53 #define ACTCTX_MAGIC 0xC07E3E11
54 #define STRSECTION_MAGIC 0x64487353 /* dHsS */
55 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
57 /* we don't want to include winuser.h */
58 #define RT_MANIFEST ((ULONG_PTR)24)
59 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1)
61 /* from oaidl.h */
62 typedef enum tagLIBFLAGS {
63 LIBFLAG_FRESTRICTED = 0x1,
64 LIBFLAG_FCONTROL = 0x2,
65 LIBFLAG_FHIDDEN = 0x4,
66 LIBFLAG_FHASDISKIMAGE = 0x8
67 } LIBFLAGS;
69 /* from oleidl.idl */
70 typedef enum tagOLEMISC
72 OLEMISC_RECOMPOSEONRESIZE = 0x1,
73 OLEMISC_ONLYICONIC = 0x2,
74 OLEMISC_INSERTNOTREPLACE = 0x4,
75 OLEMISC_STATIC = 0x8,
76 OLEMISC_CANTLINKINSIDE = 0x10,
77 OLEMISC_CANLINKBYOLE1 = 0x20,
78 OLEMISC_ISLINKOBJECT = 0x40,
79 OLEMISC_INSIDEOUT = 0x80,
80 OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
81 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
82 OLEMISC_INVISIBLEATRUNTIME = 0x400,
83 OLEMISC_ALWAYSRUN = 0x800,
84 OLEMISC_ACTSLIKEBUTTON = 0x1000,
85 OLEMISC_ACTSLIKELABEL = 0x2000,
86 OLEMISC_NOUIACTIVATE = 0x4000,
87 OLEMISC_ALIGNABLE = 0x8000,
88 OLEMISC_SIMPLEFRAME = 0x10000,
89 OLEMISC_SETCLIENTSITEFIRST = 0x20000,
90 OLEMISC_IMEMODE = 0x40000,
91 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
92 OLEMISC_WANTSTOMENUMERGE = 0x100000,
93 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
94 } OLEMISC;
96 typedef struct
98 const WCHAR *ptr;
99 unsigned int len;
100 } xmlstr_t;
102 typedef struct
104 const WCHAR *ptr;
105 const WCHAR *end;
106 } xmlbuf_t;
108 struct file_info
110 ULONG type;
111 WCHAR *info;
114 struct assembly_version
116 USHORT major;
117 USHORT minor;
118 USHORT build;
119 USHORT revision;
122 struct assembly_identity
124 WCHAR *name;
125 WCHAR *arch;
126 WCHAR *public_key;
127 WCHAR *language;
128 WCHAR *type;
129 struct assembly_version version;
130 BOOL optional;
131 BOOL delayed;
134 struct strsection_header
136 DWORD magic;
137 ULONG size;
138 DWORD unk1[3];
139 ULONG count;
140 ULONG index_offset;
141 DWORD unk2[2];
142 ULONG global_offset;
143 ULONG global_len;
146 struct string_index
148 ULONG hash; /* key string hash */
149 ULONG name_offset;
150 ULONG name_len;
151 ULONG data_offset; /* redirect data offset */
152 ULONG data_len;
153 ULONG rosterindex;
156 struct guidsection_header
158 DWORD magic;
159 ULONG size;
160 DWORD unk[3];
161 ULONG count;
162 ULONG index_offset;
163 DWORD unk2;
164 ULONG names_offset;
165 ULONG names_len;
168 struct guid_index
170 GUID guid;
171 ULONG data_offset;
172 ULONG data_len;
173 ULONG rosterindex;
176 struct wndclass_redirect_data
178 ULONG size;
179 DWORD res;
180 ULONG name_len;
181 ULONG name_offset; /* versioned name offset */
182 ULONG module_len;
183 ULONG module_offset;/* container name offset */
186 struct dllredirect_data
188 ULONG size;
189 ULONG unk;
190 DWORD res[3];
193 struct tlibredirect_data
195 ULONG size;
196 DWORD res;
197 ULONG name_len;
198 ULONG name_offset;
199 LANGID langid;
200 WORD flags;
201 ULONG help_len;
202 ULONG help_offset;
203 WORD major_version;
204 WORD minor_version;
207 enum comclass_threadingmodel
209 ThreadingModel_Apartment = 1,
210 ThreadingModel_Free = 2,
211 ThreadingModel_No = 3,
212 ThreadingModel_Both = 4,
213 ThreadingModel_Neutral = 5
216 enum comclass_miscfields
218 MiscStatus = 1,
219 MiscStatusIcon = 2,
220 MiscStatusContent = 4,
221 MiscStatusThumbnail = 8,
222 MiscStatusDocPrint = 16
225 struct comclassredirect_data
227 ULONG size;
228 BYTE res;
229 BYTE miscmask;
230 BYTE res1[2];
231 DWORD model;
232 GUID clsid;
233 GUID alias;
234 GUID clsid2;
235 GUID tlbid;
236 ULONG name_len;
237 ULONG name_offset;
238 ULONG progid_len;
239 ULONG progid_offset;
240 ULONG clrdata_len;
241 ULONG clrdata_offset;
242 DWORD miscstatus;
243 DWORD miscstatuscontent;
244 DWORD miscstatusthumbnail;
245 DWORD miscstatusicon;
246 DWORD miscstatusdocprint;
249 enum ifaceps_mask
251 NumMethods = 1,
252 BaseIface = 2
255 struct ifacepsredirect_data
257 ULONG size;
258 DWORD mask;
259 GUID iid;
260 ULONG nummethods;
261 GUID tlbid;
262 GUID base;
263 ULONG name_len;
264 ULONG name_offset;
267 struct clrsurrogate_data
269 ULONG size;
270 DWORD res;
271 GUID clsid;
272 ULONG version_offset;
273 ULONG version_len;
274 ULONG name_offset;
275 ULONG name_len;
278 struct clrclass_data
280 ULONG size;
281 DWORD res[2];
282 ULONG module_len;
283 ULONG module_offset;
284 ULONG name_len;
285 ULONG name_offset;
286 ULONG version_len;
287 ULONG version_offset;
288 DWORD res2[2];
291 struct progidredirect_data
293 ULONG size;
294 DWORD reserved;
295 ULONG clsid_offset;
300 Sections structure.
302 Sections are accessible by string or guid key, that defines two types of sections.
303 All sections of each type have same magic value and header structure, index
304 data could be of two possible types too. So every string based section uses
305 the same index format, same applies to guid sections - they share same guid index
306 format.
308 - window class redirection section is a plain buffer with following format:
310 <section header>
311 <index[]>
312 <data[]> --- <original name>
313 <redirect data>
314 <versioned name>
315 <module name>
317 Header is fixed length structure - struct strsection_header,
318 contains redirected classes count;
320 Index is an array of fixed length index records, each record is
321 struct string_index.
323 All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
325 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
326 others are relative to section itself.
328 - dll redirect section format:
330 <section header>
331 <index[]>
332 <data[]> --- <dll name>
333 <data>
335 This section doesn't seem to carry any payload data except dll names.
337 - typelib section format:
339 <section header>
340 <module names[]>
341 <index[]>
342 <data[]> --- <data>
343 <helpstring>
345 Header is fixed length, index is an array of fixed length 'struct guid_index'.
346 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
347 4-bytes aligned as a whole.
349 Module name offsets are relative to section, helpstring offset is relative to data
350 structure itself.
352 - comclass section format:
354 <section header>
355 <module names[]>
356 <index[]>
357 <data[]> --- <data> --- <data>
358 <progid> <clrdata>
359 <name>
360 <version>
361 <progid>
363 This section uses two index records per comclass, one entry contains original guid
364 as specified by context, another one has a generated guid. Index and strings handling
365 is similar to typelib sections.
367 For CLR classes additional data is stored after main COM class data, it contains
368 class name and runtime version string, see 'struct clrclass_data'.
370 Module name offsets are relative to section, progid offset is relative to data
371 structure itself.
373 - COM interface section format:
375 <section header>
376 <index[]>
377 <data[]> --- <data>
378 <name>
380 Interface section contains data for proxy/stubs and external proxy/stubs. External
381 ones are defined at assembly level, so this section has no module information.
382 All records are indexed with 'iid' value from manifest. There an exception for
383 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
384 redirect data, but index is still 'iid' from manifest.
386 Interface name offset is relative to data structure itself.
388 - CLR surrogates section format:
390 <section header>
391 <index[]>
392 <data[]> --- <data>
393 <name>
394 <version>
396 There's nothing special about this section, same way to store strings is used,
397 no modules part as it belongs to assembly level, not a file.
399 - ProgID section format:
401 <section header>
402 <guids[]>
403 <index[]>
404 <data[]> --- <progid>
405 <data>
407 This sections uses generated alias guids from COM server section. This way
408 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
409 is stored too, aligned.
412 struct progids
414 WCHAR **progids;
415 unsigned int num;
416 unsigned int allocated;
419 struct entity
421 DWORD kind;
422 union
424 struct
426 WCHAR *tlbid;
427 WCHAR *helpdir;
428 WORD flags;
429 WORD major;
430 WORD minor;
431 } typelib;
432 struct
434 WCHAR *clsid;
435 WCHAR *tlbid;
436 WCHAR *progid;
437 WCHAR *name; /* clrClass: class name */
438 WCHAR *version; /* clrClass: CLR runtime version */
439 DWORD model;
440 DWORD miscstatus;
441 DWORD miscstatuscontent;
442 DWORD miscstatusthumbnail;
443 DWORD miscstatusicon;
444 DWORD miscstatusdocprint;
445 struct progids progids;
446 } comclass;
447 struct {
448 WCHAR *iid;
449 WCHAR *base;
450 WCHAR *tlib;
451 WCHAR *name;
452 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
453 DWORD mask;
454 ULONG nummethods;
455 } ifaceps;
456 struct
458 WCHAR *name;
459 BOOL versioned;
460 } class;
461 struct
463 WCHAR *name;
464 WCHAR *clsid;
465 WCHAR *version;
466 } clrsurrogate;
467 } u;
470 struct entity_array
472 struct entity *base;
473 unsigned int num;
474 unsigned int allocated;
477 struct dll_redirect
479 WCHAR *name;
480 WCHAR *hash;
481 struct entity_array entities;
484 enum assembly_type
486 APPLICATION_MANIFEST,
487 ASSEMBLY_MANIFEST,
488 ASSEMBLY_SHARED_MANIFEST,
491 struct assembly
493 enum assembly_type type;
494 struct assembly_identity id;
495 struct file_info manifest;
496 WCHAR *directory;
497 BOOL no_inherit;
498 struct dll_redirect *dlls;
499 unsigned int num_dlls;
500 unsigned int allocated_dlls;
501 struct entity_array entities;
504 enum context_sections
506 WINDOWCLASS_SECTION = 1,
507 DLLREDIRECT_SECTION = 2,
508 TLIBREDIRECT_SECTION = 4,
509 SERVERREDIRECT_SECTION = 8,
510 IFACEREDIRECT_SECTION = 16,
511 CLRSURROGATES_SECTION = 32,
512 PROGIDREDIRECT_SECTION = 64
515 typedef struct _ACTIVATION_CONTEXT
517 ULONG magic;
518 int ref_count;
519 struct file_info config;
520 struct file_info appdir;
521 struct assembly *assemblies;
522 unsigned int num_assemblies;
523 unsigned int allocated_assemblies;
524 /* section data */
525 DWORD sections;
526 struct strsection_header *wndclass_section;
527 struct strsection_header *dllredirect_section;
528 struct strsection_header *progid_section;
529 struct guidsection_header *tlib_section;
530 struct guidsection_header *comserver_section;
531 struct guidsection_header *ifaceps_section;
532 struct guidsection_header *clrsurrogate_section;
533 } ACTIVATION_CONTEXT;
535 struct actctx_loader
537 ACTIVATION_CONTEXT *actctx;
538 struct assembly_identity *dependencies;
539 unsigned int num_dependencies;
540 unsigned int allocated_dependencies;
543 static const WCHAR asmv1W[] = {'a','s','m','v','1',':',0};
544 static const WCHAR asmv2W[] = {'a','s','m','v','2',':',0};
545 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
546 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
547 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
548 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
549 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
550 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
551 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};
552 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};
553 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
554 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
555 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
556 static const WCHAR fileW[] = {'f','i','l','e',0};
557 static const WCHAR hashW[] = {'h','a','s','h',0};
558 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
559 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
560 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
561 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
563 static const WCHAR clsidW[] = {'c','l','s','i','d',0};
564 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
565 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
566 static const WCHAR iidW[] = {'i','i','d',0};
567 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
568 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
569 static const WCHAR nameW[] = {'n','a','m','e',0};
570 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0};
571 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
572 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
573 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
574 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};
575 static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
576 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
577 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
578 static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
579 static const WCHAR typeW[] = {'t','y','p','e',0};
580 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
581 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
582 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
583 static const WCHAR yesW[] = {'y','e','s',0};
584 static const WCHAR noW[] = {'n','o',0};
585 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
586 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
587 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
588 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
589 static const WCHAR flagsW[] = {'f','l','a','g','s',0};
590 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
591 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
592 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
593 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
594 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
595 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
596 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
597 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
598 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
599 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
600 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
602 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
603 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
604 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
605 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
606 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
607 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
608 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
609 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};
610 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
611 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
612 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
613 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
614 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
615 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
616 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
617 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
618 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};
619 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
620 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
621 static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
622 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};
623 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
625 struct olemisc_entry
627 const WCHAR *name;
628 OLEMISC value;
631 static const struct olemisc_entry olemisc_values[] =
633 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
634 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
635 { actslikelabelW, OLEMISC_ACTSLIKELABEL },
636 { alignableW, OLEMISC_ALIGNABLE },
637 { alwaysrunW, OLEMISC_ALWAYSRUN },
638 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
639 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
640 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
641 { imemodeW, OLEMISC_IMEMODE },
642 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
643 { insideoutW, OLEMISC_INSIDEOUT },
644 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
645 { islinkobjectW, OLEMISC_ISLINKOBJECT },
646 { nouiactivateW, OLEMISC_NOUIACTIVATE },
647 { onlyiconicW, OLEMISC_ONLYICONIC },
648 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
649 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
650 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
651 { simpleframeW, OLEMISC_SIMPLEFRAME },
652 { staticW, OLEMISC_STATIC },
653 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
654 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
657 static const WCHAR xmlW[] = {'?','x','m','l',0};
658 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};
659 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};
660 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};
662 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
663 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
664 static const WCHAR wildcardW[] = {'*',0};
666 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
667 static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
669 static WCHAR *strdupW(const WCHAR* str)
671 WCHAR* ptr;
673 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
674 return NULL;
675 return strcpyW(ptr, str);
678 static WCHAR *xmlstrdupW(const xmlstr_t* str)
680 WCHAR *strW;
682 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
684 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
685 strW[str->len] = 0;
687 return strW;
690 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
692 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
695 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
697 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
700 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
702 return (xmlstr->len && xmlstr->ptr[0] == '/' &&
703 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
706 static inline BOOL xml_elem_cmp(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
708 UINT len = strlenW( namespace );
710 if (!strncmpW(elem->ptr, str, elem->len) && !str[elem->len]) return TRUE;
711 return (elem->len > len && !strncmpW(elem->ptr, namespace, len) &&
712 !strncmpW(elem->ptr + len, str, elem->len - len) && !str[elem->len - len]);
715 static inline BOOL xml_elem_cmp_end(const xmlstr_t *elem, const WCHAR *str, const WCHAR *namespace)
717 if (elem->len && elem->ptr[0] == '/')
719 xmlstr_t elem_end;
720 elem_end.ptr = elem->ptr + 1;
721 elem_end.len = elem->len - 1;
722 return xml_elem_cmp( &elem_end, str, namespace );
724 return FALSE;
727 static inline BOOL isxmlspace( WCHAR ch )
729 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
732 static inline const char* debugstr_xmlstr(const xmlstr_t* str)
734 return debugstr_wn(str->ptr, str->len);
737 static inline const char* debugstr_version(const struct assembly_version *ver)
739 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision);
742 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
744 struct assembly *assembly;
746 if (actctx->num_assemblies == actctx->allocated_assemblies)
748 void *ptr;
749 unsigned int new_count;
750 if (actctx->assemblies)
752 new_count = actctx->allocated_assemblies * 2;
753 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
754 actctx->assemblies, new_count * sizeof(*assembly) );
756 else
758 new_count = 4;
759 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
761 if (!ptr) return NULL;
762 actctx->assemblies = ptr;
763 actctx->allocated_assemblies = new_count;
766 assembly = &actctx->assemblies[actctx->num_assemblies++];
767 assembly->type = at;
768 return assembly;
771 static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
773 if (assembly->num_dlls == assembly->allocated_dlls)
775 void *ptr;
776 unsigned int new_count;
777 if (assembly->dlls)
779 new_count = assembly->allocated_dlls * 2;
780 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
781 assembly->dlls, new_count * sizeof(*assembly->dlls) );
783 else
785 new_count = 4;
786 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
788 if (!ptr) return NULL;
789 assembly->dlls = ptr;
790 assembly->allocated_dlls = new_count;
792 return &assembly->dlls[assembly->num_dlls++];
795 static void free_assembly_identity(struct assembly_identity *ai)
797 RtlFreeHeap( GetProcessHeap(), 0, ai->name );
798 RtlFreeHeap( GetProcessHeap(), 0, ai->arch );
799 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key );
800 RtlFreeHeap( GetProcessHeap(), 0, ai->language );
801 RtlFreeHeap( GetProcessHeap(), 0, ai->type );
804 static struct entity* add_entity(struct entity_array *array, DWORD kind)
806 struct entity* entity;
808 if (array->num == array->allocated)
810 void *ptr;
811 unsigned int new_count;
812 if (array->base)
814 new_count = array->allocated * 2;
815 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY,
816 array->base, new_count * sizeof(*array->base) );
818 else
820 new_count = 4;
821 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
823 if (!ptr) return NULL;
824 array->base = ptr;
825 array->allocated = new_count;
827 entity = &array->base[array->num++];
828 entity->kind = kind;
829 return entity;
832 static void free_entity_array(struct entity_array *array)
834 unsigned int i, j;
835 for (i = 0; i < array->num; i++)
837 struct entity *entity = &array->base[i];
838 switch (entity->kind)
840 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
841 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
842 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
843 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
844 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name);
845 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version);
846 for (j = 0; j < entity->u.comclass.progids.num; j++)
847 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
848 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids);
849 break;
850 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
851 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid);
852 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base);
853 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32);
854 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name);
855 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib);
856 break;
857 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
858 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid);
859 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir);
860 break;
861 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
862 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name);
863 break;
864 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
865 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name);
866 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
867 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version);
868 break;
869 default:
870 FIXME("Unknown entity kind %d\n", entity->kind);
873 RtlFreeHeap( GetProcessHeap(), 0, array->base );
876 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
878 if (!str1) return !str2;
879 return str2 && !strcmpiW( str1, str2 );
882 static BOOL is_matching_identity( const struct assembly_identity *id1,
883 const struct assembly_identity *id2 )
885 if (!is_matching_string( id1->name, id2->name )) return FALSE;
886 if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
887 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
889 if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
891 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
892 return FALSE;
894 if (id1->version.major != id2->version.major) return FALSE;
895 if (id1->version.minor != id2->version.minor) return FALSE;
896 if (id1->version.build > id2->version.build) return FALSE;
897 if (id1->version.build == id2->version.build &&
898 id1->version.revision > id2->version.revision) return FALSE;
899 return TRUE;
902 static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
903 struct assembly_identity* ai)
905 unsigned int i;
907 /* check if we already have that assembly */
909 for (i = 0; i < acl->actctx->num_assemblies; i++)
910 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
912 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n",
913 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
914 ai->version.build, ai->version.revision );
915 return TRUE;
918 for (i = 0; i < acl->num_dependencies; i++)
919 if (is_matching_identity( ai, &acl->dependencies[i] ))
921 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n",
922 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor,
923 ai->version.build, ai->version.revision );
924 return TRUE;
927 if (acl->num_dependencies == acl->allocated_dependencies)
929 void *ptr;
930 unsigned int new_count;
931 if (acl->dependencies)
933 new_count = acl->allocated_dependencies * 2;
934 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies,
935 new_count * sizeof(acl->dependencies[0]));
937 else
939 new_count = 4;
940 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
942 if (!ptr) return FALSE;
943 acl->dependencies = ptr;
944 acl->allocated_dependencies = new_count;
946 acl->dependencies[acl->num_dependencies++] = *ai;
948 return TRUE;
951 static void free_depend_manifests(struct actctx_loader* acl)
953 unsigned int i;
954 for (i = 0; i < acl->num_dependencies; i++)
955 free_assembly_identity(&acl->dependencies[i]);
956 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies);
959 static WCHAR *build_assembly_dir(struct assembly_identity* ai)
961 static const WCHAR undW[] = {'_',0};
962 static const WCHAR noneW[] = {'n','o','n','e',0};
963 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
965 const WCHAR *arch = ai->arch ? ai->arch : noneW;
966 const WCHAR *key = ai->public_key ? ai->public_key : noneW;
967 const WCHAR *lang = ai->language ? ai->language : noneW;
968 const WCHAR *name = ai->name ? ai->name : noneW;
969 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
970 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
971 WCHAR *ret;
973 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL;
975 strcpyW( ret, arch );
976 strcatW( ret, undW );
977 strcatW( ret, name );
978 strcatW( ret, undW );
979 strcatW( ret, key );
980 strcatW( ret, undW );
981 sprintfW( ret + strlenW(ret), version_formatW,
982 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
983 strcatW( ret, undW );
984 strcatW( ret, lang );
985 strcatW( ret, undW );
986 strcatW( ret, mskeyW );
987 return ret;
990 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
992 WCHAR *p = buffer;
994 if (!str) return;
995 strcatW( buffer, prefix );
996 p += strlenW(p);
997 *p++ = '"';
998 strcpyW( p, str );
999 p += strlenW(p);
1000 *p++ = '"';
1001 *p = 0;
1004 static WCHAR *build_assembly_id( const struct assembly_identity *ai )
1006 static const WCHAR archW[] =
1007 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
1008 static const WCHAR public_keyW[] =
1009 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
1010 static const WCHAR typeW[] =
1011 {',','t','y','p','e','=',0};
1012 static const WCHAR versionW[] =
1013 {',','v','e','r','s','i','o','n','=',0};
1015 WCHAR version[64], *ret;
1016 SIZE_T size = 0;
1018 sprintfW( version, version_formatW,
1019 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
1020 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
1021 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
1022 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
1023 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
1024 size += strlenW(versionW) + strlenW(version) + 2;
1026 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
1027 return NULL;
1029 if (ai->name) strcpyW( ret, ai->name );
1030 else *ret = 0;
1031 append_string( ret, archW, ai->arch );
1032 append_string( ret, public_keyW, ai->public_key );
1033 append_string( ret, typeW, ai->type );
1034 append_string( ret, versionW, version );
1035 return ret;
1038 static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
1040 ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
1042 if (!h || h == INVALID_HANDLE_VALUE) return NULL;
1043 __TRY
1045 if (actctx->magic == ACTCTX_MAGIC) ret = actctx;
1047 __EXCEPT_PAGE_FAULT
1050 __ENDTRY
1051 return ret;
1054 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
1056 interlocked_xchg_add( &actctx->ref_count, 1 );
1059 static void actctx_release( ACTIVATION_CONTEXT *actctx )
1061 if (interlocked_xchg_add( &actctx->ref_count, -1 ) == 1)
1063 unsigned int i, j;
1065 for (i = 0; i < actctx->num_assemblies; i++)
1067 struct assembly *assembly = &actctx->assemblies[i];
1068 for (j = 0; j < assembly->num_dlls; j++)
1070 struct dll_redirect *dll = &assembly->dlls[j];
1071 free_entity_array( &dll->entities );
1072 RtlFreeHeap( GetProcessHeap(), 0, dll->name );
1073 RtlFreeHeap( GetProcessHeap(), 0, dll->hash );
1075 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls );
1076 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info );
1077 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory );
1078 free_entity_array( &assembly->entities );
1079 free_assembly_identity(&assembly->id);
1081 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info );
1082 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info );
1083 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies );
1084 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section );
1085 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
1086 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section );
1087 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section );
1088 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
1089 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
1090 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section );
1091 actctx->magic = 0;
1092 RtlFreeHeap( GetProcessHeap(), 0, actctx );
1096 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
1097 BOOL* error, BOOL* end)
1099 const WCHAR* ptr;
1101 *error = TRUE;
1103 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
1104 xmlbuf->ptr++;
1106 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1108 if (*xmlbuf->ptr == '/')
1110 xmlbuf->ptr++;
1111 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
1112 return FALSE;
1114 xmlbuf->ptr++;
1115 *end = TRUE;
1116 *error = FALSE;
1117 return FALSE;
1120 if (*xmlbuf->ptr == '>')
1122 xmlbuf->ptr++;
1123 *error = FALSE;
1124 return FALSE;
1127 ptr = xmlbuf->ptr;
1128 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
1130 if (ptr == xmlbuf->end) return FALSE;
1132 name->ptr = xmlbuf->ptr;
1133 name->len = ptr-xmlbuf->ptr;
1134 xmlbuf->ptr = ptr;
1136 /* skip spaces before '=' */
1137 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++;
1138 if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
1140 /* skip '=' itself */
1141 ptr++;
1142 if (ptr == xmlbuf->end) return FALSE;
1144 /* skip spaces after '=' */
1145 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++;
1147 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
1149 value->ptr = ++ptr;
1150 if (ptr == xmlbuf->end) return FALSE;
1152 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
1153 if (!ptr)
1155 xmlbuf->ptr = xmlbuf->end;
1156 return FALSE;
1159 value->len = ptr - value->ptr;
1160 xmlbuf->ptr = ptr + 1;
1162 if (xmlbuf->ptr == xmlbuf->end) return FALSE;
1164 *error = FALSE;
1165 return TRUE;
1168 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
1170 const WCHAR* ptr;
1172 for (;;)
1174 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1175 if (!ptr)
1177 xmlbuf->ptr = xmlbuf->end;
1178 return FALSE;
1180 ptr++;
1181 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
1183 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
1184 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
1186 if (ptr + 3 > xmlbuf->end)
1188 xmlbuf->ptr = xmlbuf->end;
1189 return FALSE;
1191 xmlbuf->ptr = ptr + 3;
1193 else break;
1196 xmlbuf->ptr = ptr;
1197 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
1198 ptr++;
1200 elem->ptr = xmlbuf->ptr;
1201 elem->len = ptr - xmlbuf->ptr;
1202 xmlbuf->ptr = ptr;
1203 return xmlbuf->ptr != xmlbuf->end;
1206 static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
1208 /* FIXME: parse attributes */
1209 const WCHAR *ptr;
1211 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
1213 if (ptr[0] == '?' && ptr[1] == '>')
1215 xmlbuf->ptr = ptr + 2;
1216 return TRUE;
1219 return FALSE;
1222 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
1224 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
1226 if (!ptr) return FALSE;
1228 content->ptr = xmlbuf->ptr;
1229 content->len = ptr - xmlbuf->ptr;
1230 xmlbuf->ptr = ptr;
1232 return TRUE;
1235 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
1237 unsigned int ver[4];
1238 unsigned int pos;
1239 const WCHAR *curr;
1241 /* major.minor.build.revision */
1242 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
1243 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1245 if (*curr >= '0' && *curr <= '9')
1247 ver[pos] = ver[pos] * 10 + *curr - '0';
1248 if (ver[pos] >= 0x10000) goto error;
1250 else if (*curr == '.')
1252 if (++pos >= 4) goto error;
1254 else goto error;
1256 version->major = ver[0];
1257 version->minor = ver[1];
1258 version->build = ver[2];
1259 version->revision = ver[3];
1260 return TRUE;
1262 error:
1263 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) );
1264 return FALSE;
1267 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name, const WCHAR *namespace)
1269 xmlstr_t elem;
1270 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1271 if (xml_elem_cmp(&elem, name, namespace)) return TRUE;
1272 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1273 return FALSE;
1276 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
1278 xmlstr_t attr_name, attr_value;
1279 BOOL error;
1281 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
1283 WARN("unexpected attr %s=%s\n", debugstr_xmlstr(&attr_name),
1284 debugstr_xmlstr(&attr_value));
1286 return !error;
1289 static BOOL parse_end_element(xmlbuf_t *xmlbuf)
1291 BOOL end = FALSE;
1292 return parse_expect_no_attr(xmlbuf, &end) && !end;
1295 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name, const WCHAR *namespace)
1297 xmlstr_t elem;
1298 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
1299 if (!xml_elem_cmp_end(&elem, name, namespace))
1301 FIXME( "unexpected element %s\n", debugstr_xmlstr(&elem) );
1302 return FALSE;
1304 return parse_end_element(xmlbuf);
1307 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
1309 xmlstr_t attr_name, attr_value, elem;
1310 BOOL end = FALSE, error, ret = TRUE;
1312 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
1313 if(error || end) return end;
1315 while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
1317 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
1318 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
1319 break;
1320 else
1321 ret = parse_unknown_elem(xmlbuf, &elem);
1324 return ret && parse_end_element(xmlbuf);
1327 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
1328 struct assembly_identity* ai)
1330 xmlstr_t attr_name, attr_value;
1331 BOOL end = FALSE, error;
1333 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1335 if (xmlstr_cmp(&attr_name, nameW))
1337 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
1339 else if (xmlstr_cmp(&attr_name, typeW))
1341 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
1343 else if (xmlstr_cmp(&attr_name, versionW))
1345 if (!parse_version(&attr_value, &ai->version)) return FALSE;
1347 else if (xmlstr_cmp(&attr_name, processorArchitectureW))
1349 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
1351 else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
1353 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
1355 else if (xmlstr_cmp(&attr_name, languageW))
1357 WARN("Unsupported yet language attribute (%s)\n",
1358 debugstr_xmlstr(&attr_value));
1359 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
1361 else
1363 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name),
1364 debugstr_xmlstr(&attr_value));
1368 TRACE( "name=%s version=%s arch=%s\n",
1369 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
1371 if (error || end) return end;
1372 return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
1375 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
1377 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
1378 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
1379 static const WCHAR freeW[] = {'F','r','e','e',0};
1380 static const WCHAR bothW[] = {'B','o','t','h',0};
1382 if (value->len == 0) return ThreadingModel_No;
1383 if (xmlstr_cmp(value, apartW))
1384 return ThreadingModel_Apartment;
1385 else if (xmlstr_cmp(value, freeW))
1386 return ThreadingModel_Free;
1387 else if (xmlstr_cmp(value, bothW))
1388 return ThreadingModel_Both;
1389 else if (xmlstr_cmp(value, neutralW))
1390 return ThreadingModel_Neutral;
1391 else
1392 return ThreadingModel_No;
1395 static OLEMISC get_olemisc_value(const WCHAR *str, int len)
1397 int min, max;
1399 min = 0;
1400 max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
1402 while (min <= max)
1404 int n, c;
1406 n = (min+max)/2;
1408 c = strncmpW(olemisc_values[n].name, str, len);
1409 if (!c && !olemisc_values[n].name[len])
1410 return olemisc_values[n].value;
1412 if (c >= 0)
1413 max = n-1;
1414 else
1415 min = n+1;
1418 WARN("unknown flag %s\n", debugstr_wn(str, len));
1419 return 0;
1422 static DWORD parse_com_class_misc(const xmlstr_t *value)
1424 const WCHAR *str = value->ptr, *start;
1425 DWORD flags = 0;
1426 int i = 0;
1428 /* it's comma separated list of flags */
1429 while (i < value->len)
1431 start = str;
1432 while (*str != ',' && (i++ < value->len)) str++;
1434 flags |= get_olemisc_value(start, str-start);
1436 /* skip separator */
1437 str++;
1438 i++;
1441 return flags;
1444 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
1446 struct progids *progids = &entity->u.comclass.progids;
1448 if (progids->allocated == 0)
1450 progids->allocated = 4;
1451 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
1454 if (progids->allocated == progids->num)
1456 progids->allocated *= 2;
1457 progids->progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
1460 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
1461 progids->num++;
1463 return TRUE;
1466 static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
1468 xmlstr_t content;
1469 BOOL end = FALSE;
1471 if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
1472 return FALSE;
1474 if (!com_class_add_progid(&content, entity)) return FALSE;
1475 return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
1478 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
1480 xmlstr_t elem, attr_name, attr_value;
1481 BOOL ret = TRUE, end = FALSE, error;
1482 struct entity* entity;
1484 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
1485 return FALSE;
1487 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1489 if (xmlstr_cmp(&attr_name, clsidW))
1491 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1493 else if (xmlstr_cmp(&attr_name, progidW))
1495 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1497 else if (xmlstr_cmp(&attr_name, tlbidW))
1499 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1501 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1503 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1505 else if (xmlstr_cmp(&attr_name, miscstatusW))
1507 entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
1509 else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
1511 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
1513 else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
1515 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
1517 else if (xmlstr_cmp(&attr_name, miscstatusiconW))
1519 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
1521 else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
1523 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
1525 else if (xmlstr_cmp(&attr_name, descriptionW))
1527 /* not stored */
1529 else
1531 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1535 if (error) return FALSE;
1537 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1538 if (entity->u.comclass.progid)
1539 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1541 if (end) return TRUE;
1543 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1545 if (xmlstr_cmp_end(&elem, comClassW))
1547 ret = parse_end_element(xmlbuf);
1548 break;
1550 else if (xmlstr_cmp(&elem, progidW))
1552 ret = parse_com_class_progid(xmlbuf, entity);
1554 else
1556 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1557 ret = parse_unknown_elem(xmlbuf, &elem);
1561 if (entity->u.comclass.progids.num)
1562 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1564 return ret;
1567 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
1569 const WCHAR *curr;
1570 ULONG num = 0;
1572 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1574 if (*curr >= '0' && *curr <= '9')
1575 num = num * 10 + *curr - '0';
1576 else
1578 ERR("wrong numeric value %s\n", debugstr_xmlstr(str));
1579 return FALSE;
1582 entity->u.ifaceps.nummethods = num;
1584 return TRUE;
1587 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1589 xmlstr_t attr_name, attr_value;
1590 BOOL end = FALSE, error;
1591 struct entity* entity;
1593 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
1594 return FALSE;
1596 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1598 if (xmlstr_cmp(&attr_name, iidW))
1600 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1602 else if (xmlstr_cmp(&attr_name, nameW))
1604 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1606 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1608 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1609 entity->u.ifaceps.mask |= BaseIface;
1611 else if (xmlstr_cmp(&attr_name, nummethodsW))
1613 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1614 entity->u.ifaceps.mask |= NumMethods;
1616 else if (xmlstr_cmp(&attr_name, tlbidW))
1618 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1620 /* not used */
1621 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
1624 else
1626 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1630 if (error) return FALSE;
1631 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1632 if (end) return TRUE;
1634 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
1637 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
1639 WORD *flags = &entity->u.typelib.flags;
1640 const WCHAR *str = value->ptr, *start;
1641 int i = 0;
1643 *flags = 0;
1645 /* it's comma separated list of flags */
1646 while (i < value->len)
1648 start = str;
1649 while (*str != ',' && (i++ < value->len)) str++;
1651 if (!strncmpiW(start, restrictedW, str-start))
1652 *flags |= LIBFLAG_FRESTRICTED;
1653 else if (!strncmpiW(start, controlW, str-start))
1654 *flags |= LIBFLAG_FCONTROL;
1655 else if (!strncmpiW(start, hiddenW, str-start))
1656 *flags |= LIBFLAG_FHIDDEN;
1657 else if (!strncmpiW(start, hasdiskimageW, str-start))
1658 *flags |= LIBFLAG_FHASDISKIMAGE;
1659 else
1661 WARN("unknown flags value %s\n", debugstr_xmlstr(value));
1662 return FALSE;
1665 /* skip separator */
1666 str++;
1667 i++;
1670 return TRUE;
1673 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
1675 unsigned int ver[2];
1676 unsigned int pos;
1677 const WCHAR *curr;
1679 /* major.minor */
1680 ver[0] = ver[1] = pos = 0;
1681 for (curr = str->ptr; curr < str->ptr + str->len; curr++)
1683 if (*curr >= '0' && *curr <= '9')
1685 ver[pos] = ver[pos] * 10 + *curr - '0';
1686 if (ver[pos] >= 0x10000) goto error;
1688 else if (*curr == '.')
1690 if (++pos >= 2) goto error;
1692 else goto error;
1694 entity->u.typelib.major = ver[0];
1695 entity->u.typelib.minor = ver[1];
1696 return TRUE;
1698 error:
1699 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str));
1700 return FALSE;
1703 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1705 xmlstr_t attr_name, attr_value;
1706 BOOL end = FALSE, error;
1707 struct entity* entity;
1709 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
1710 return FALSE;
1712 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1714 if (xmlstr_cmp(&attr_name, tlbidW))
1716 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1718 else if (xmlstr_cmp(&attr_name, versionW))
1720 if (!parse_typelib_version(&attr_value, entity)) return FALSE;
1722 else if (xmlstr_cmp(&attr_name, helpdirW))
1724 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
1726 else if (xmlstr_cmp(&attr_name, flagsW))
1728 if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
1730 else
1732 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1736 if (error) return FALSE;
1738 acl->actctx->sections |= TLIBREDIRECT_SECTION;
1740 if (end) return TRUE;
1742 return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
1745 static inline int aligned_string_len(int len)
1747 return (len + 3) & ~3;
1750 static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
1752 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
1753 struct assembly_version *ver = &assembly->id.version;
1754 WCHAR buff[25];
1756 if (!ret) ret = buff;
1757 return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
1760 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
1762 xmlstr_t elem, content, attr_name, attr_value;
1763 BOOL end = FALSE, ret = TRUE, error;
1764 struct entity* entity;
1766 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
1767 return FALSE;
1769 entity->u.class.versioned = TRUE;
1770 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1772 if (xmlstr_cmp(&attr_name, versionedW))
1774 if (xmlstr_cmpi(&attr_value, noW))
1775 entity->u.class.versioned = FALSE;
1776 else if (!xmlstr_cmpi(&attr_value, yesW))
1777 return FALSE;
1779 else
1781 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1785 if (error || end) return end;
1787 if (!parse_text_content(xmlbuf, &content)) return FALSE;
1789 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
1791 acl->actctx->sections |= WINDOWCLASS_SECTION;
1793 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1795 if (xmlstr_cmp_end(&elem, windowClassW))
1797 ret = parse_end_element(xmlbuf);
1798 break;
1800 else
1802 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1803 ret = parse_unknown_elem(xmlbuf, &elem);
1807 return ret;
1810 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
1812 xmlstr_t attr_name, attr_value;
1813 BOOL end = FALSE, error;
1815 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1817 if (xmlstr_cmp(&attr_name, oldVersionW))
1819 FIXME("Not stored yet oldVersion=%s\n", debugstr_xmlstr(&attr_value));
1821 else if (xmlstr_cmp(&attr_name, newVersionW))
1823 FIXME("Not stored yet newVersion=%s\n", debugstr_xmlstr(&attr_value));
1825 else
1827 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1831 if (error || end) return end;
1832 return parse_expect_end_elem(xmlbuf, bindingRedirectW, asmv1W);
1835 static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
1837 xmlstr_t elem, content, attr_name, attr_value;
1838 BOOL end = FALSE, ret = TRUE, error = FALSE;
1840 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1841 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1843 if (error) return FALSE;
1844 if (end) return TRUE;
1846 if (!parse_text_content(xmlbuf, &content))
1847 return FALSE;
1849 TRACE("Got description %s\n", debugstr_xmlstr(&content));
1851 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1853 if (xmlstr_cmp_end(&elem, descriptionW))
1855 ret = parse_end_element(xmlbuf);
1856 break;
1858 else
1860 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1861 ret = parse_unknown_elem(xmlbuf, &elem);
1865 return ret;
1868 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
1869 struct assembly* assembly,
1870 struct actctx_loader* acl)
1872 xmlstr_t attr_name, attr_value;
1873 BOOL end = FALSE, error;
1874 struct entity* entity;
1876 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
1877 if (!entity) return FALSE;
1879 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1881 if (xmlstr_cmp(&attr_name, iidW))
1883 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
1885 else if (xmlstr_cmp(&attr_name, nameW))
1887 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
1889 else if (xmlstr_cmp(&attr_name, baseInterfaceW))
1891 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
1892 entity->u.ifaceps.mask |= BaseIface;
1894 else if (xmlstr_cmp(&attr_name, nummethodsW))
1896 if (!(parse_nummethods(&attr_value, entity))) return FALSE;
1897 entity->u.ifaceps.mask |= NumMethods;
1899 else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
1901 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
1903 else if (xmlstr_cmp(&attr_name, tlbidW))
1905 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
1907 else
1909 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1913 if (error) return FALSE;
1914 acl->actctx->sections |= IFACEREDIRECT_SECTION;
1915 if (end) return TRUE;
1917 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
1920 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1922 xmlstr_t attr_name, attr_value, elem;
1923 BOOL end = FALSE, error, ret = TRUE;
1924 struct entity* entity;
1926 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
1927 if (!entity) return FALSE;
1929 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
1931 if (xmlstr_cmp(&attr_name, nameW))
1933 if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
1935 else if (xmlstr_cmp(&attr_name, clsidW))
1937 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
1939 else if (xmlstr_cmp(&attr_name, progidW))
1941 if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
1943 else if (xmlstr_cmp(&attr_name, tlbidW))
1945 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
1947 else if (xmlstr_cmp(&attr_name, threadingmodelW))
1949 entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
1951 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
1953 if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
1955 else
1957 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
1961 if (error) return FALSE;
1962 acl->actctx->sections |= SERVERREDIRECT_SECTION;
1963 if (entity->u.comclass.progid)
1964 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1965 if (end) return TRUE;
1967 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
1969 if (xmlstr_cmp_end(&elem, clrClassW))
1971 ret = parse_end_element(xmlbuf);
1972 break;
1974 else if (xmlstr_cmp(&elem, progidW))
1976 ret = parse_com_class_progid(xmlbuf, entity);
1978 else
1980 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
1981 ret = parse_unknown_elem(xmlbuf, &elem);
1985 if (entity->u.comclass.progids.num)
1986 acl->actctx->sections |= PROGIDREDIRECT_SECTION;
1988 return ret;
1991 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
1993 xmlstr_t attr_name, attr_value;
1994 BOOL end = FALSE, error;
1995 struct entity* entity;
1997 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
1998 if (!entity) return FALSE;
2000 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2002 if (xmlstr_cmp(&attr_name, nameW))
2004 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
2006 else if (xmlstr_cmp(&attr_name, clsidW))
2008 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
2010 else if (xmlstr_cmp(&attr_name, runtimeVersionW))
2012 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
2014 else
2016 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2020 if (error) return FALSE;
2021 acl->actctx->sections |= CLRSURROGATES_SECTION;
2022 if (end) return TRUE;
2024 return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
2027 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
2029 struct assembly_identity ai;
2030 xmlstr_t elem, attr_name, attr_value;
2031 BOOL end = FALSE, error = FALSE, ret = TRUE, delayed = FALSE;
2033 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2035 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0};
2036 static const WCHAR trueW[] = {'t','r','u','e',0};
2038 if (xmlstr_cmp(&attr_name, allowDelayedBindingW))
2039 delayed = xmlstr_cmp(&attr_value, trueW);
2040 else
2041 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2044 if (error || end) return end;
2046 memset(&ai, 0, sizeof(ai));
2047 ai.optional = optional;
2048 ai.delayed = delayed;
2050 if (!parse_expect_elem(xmlbuf, assemblyIdentityW, asmv1W) ||
2051 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
2052 return FALSE;
2054 TRACE( "adding name=%s version=%s arch=%s\n",
2055 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
2057 /* store the newly found identity for later loading */
2058 if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
2060 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2062 if (xmlstr_cmp_end(&elem, dependentAssemblyW))
2064 ret = parse_end_element(xmlbuf);
2065 break;
2067 else if (xmlstr_cmp(&elem, bindingRedirectW))
2069 ret = parse_binding_redirect_elem(xmlbuf);
2071 else
2073 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2074 ret = parse_unknown_elem(xmlbuf, &elem);
2078 return ret;
2081 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
2083 xmlstr_t attr_name, attr_value, elem;
2084 BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
2086 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2088 if (xmlstr_cmp(&attr_name, optionalW))
2090 optional = xmlstr_cmpi( &attr_value, yesW );
2091 TRACE("optional=%s\n", debugstr_xmlstr(&attr_value));
2093 else
2095 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2099 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2101 if (xmlstr_cmp_end(&elem, dependencyW))
2103 ret = parse_end_element(xmlbuf);
2104 break;
2106 else if (xmlstr_cmp(&elem, dependentAssemblyW))
2108 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
2110 else
2112 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2113 ret = parse_unknown_elem(xmlbuf, &elem);
2117 return ret;
2120 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
2122 BOOL end = FALSE;
2124 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2125 return end || parse_expect_end_elem(xmlbuf, noInheritW, asmv1W);
2128 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
2130 BOOL end = FALSE;
2132 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
2133 return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
2136 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
2138 xmlstr_t attr_name, attr_value, elem;
2139 BOOL end = FALSE, error, ret = TRUE;
2140 struct dll_redirect* dll;
2142 if (!(dll = add_dll_redirect(assembly))) return FALSE;
2144 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2146 if (xmlstr_cmp(&attr_name, nameW))
2148 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
2149 TRACE("name=%s\n", debugstr_xmlstr(&attr_value));
2151 else if (xmlstr_cmp(&attr_name, hashW))
2153 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
2155 else if (xmlstr_cmp(&attr_name, hashalgW))
2157 static const WCHAR sha1W[] = {'S','H','A','1',0};
2158 if (!xmlstr_cmpi(&attr_value, sha1W))
2159 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr_value));
2161 else
2163 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2167 if (error || !dll->name) return FALSE;
2169 acl->actctx->sections |= DLLREDIRECT_SECTION;
2171 if (end) return TRUE;
2173 while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
2175 if (xmlstr_cmp_end(&elem, fileW))
2177 ret = parse_end_element(xmlbuf);
2178 break;
2180 else if (xmlstr_cmp(&elem, comClassW))
2182 ret = parse_com_class_elem(xmlbuf, dll, acl);
2184 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
2186 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
2188 else if (xml_elem_cmp(&elem, hashW, asmv2W))
2190 WARN("asmv2:hash (undocumented) not supported\n");
2191 ret = parse_unknown_elem(xmlbuf, &elem);
2193 else if (xmlstr_cmp(&elem, typelibW))
2195 ret = parse_typelib_elem(xmlbuf, dll, acl);
2197 else if (xmlstr_cmp(&elem, windowClassW))
2199 ret = parse_window_class_elem(xmlbuf, dll, acl);
2201 else
2203 WARN("unknown elem %s\n", debugstr_xmlstr(&elem));
2204 ret = parse_unknown_elem( xmlbuf, &elem );
2208 return ret;
2211 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
2212 struct assembly* assembly,
2213 struct assembly_identity* expected_ai)
2215 xmlstr_t attr_name, attr_value, elem;
2216 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
2218 TRACE("(%p)\n", xmlbuf);
2220 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
2222 if (xmlstr_cmp(&attr_name, manifestVersionW))
2224 static const WCHAR v10W[] = {'1','.','0',0};
2225 if (!xmlstr_cmp(&attr_value, v10W))
2227 FIXME("wrong version %s\n", debugstr_xmlstr(&attr_value));
2228 return FALSE;
2230 version = TRUE;
2232 else if (xmlstr_cmp(&attr_name, xmlnsW))
2234 if (!xmlstr_cmp(&attr_value, manifestv1W) &&
2235 !xmlstr_cmp(&attr_value, manifestv2W) &&
2236 !xmlstr_cmp(&attr_value, manifestv3W))
2238 FIXME("wrong namespace %s\n", debugstr_xmlstr(&attr_value));
2239 return FALSE;
2241 xmlns = TRUE;
2243 else
2245 WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));
2249 if (error || end || !xmlns || !version) return FALSE;
2250 if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
2252 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
2254 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2255 return FALSE;
2256 assembly->no_inherit = TRUE;
2259 if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
2261 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
2262 return FALSE;
2264 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
2265 assembly->no_inherit)
2266 return FALSE;
2268 while (ret)
2270 if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
2272 ret = parse_end_element(xmlbuf);
2273 break;
2275 else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
2277 ret = parse_description_elem(xmlbuf);
2279 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
2281 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
2283 else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
2285 ret = parse_dependency_elem(xmlbuf, acl);
2287 else if (xml_elem_cmp(&elem, fileW, asmv1W))
2289 ret = parse_file_elem(xmlbuf, assembly, acl);
2291 else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
2293 ret = parse_clr_class_elem(xmlbuf, assembly, acl);
2295 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
2297 ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
2299 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
2301 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
2303 if (expected_ai)
2305 /* FIXME: more tests */
2306 if (assembly->type == ASSEMBLY_MANIFEST &&
2307 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
2309 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
2310 expected_ai->version.major, expected_ai->version.minor,
2311 expected_ai->version.build, expected_ai->version.revision,
2312 assembly->id.version.major, assembly->id.version.minor,
2313 assembly->id.version.build, assembly->id.version.revision);
2314 ret = FALSE;
2316 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
2317 (assembly->id.version.major != expected_ai->version.major ||
2318 assembly->id.version.minor != expected_ai->version.minor ||
2319 assembly->id.version.build < expected_ai->version.build ||
2320 (assembly->id.version.build == expected_ai->version.build &&
2321 assembly->id.version.revision < expected_ai->version.revision)))
2323 FIXME("wrong version for shared assembly manifest\n");
2324 ret = FALSE;
2328 else
2330 WARN("unknown element %s\n", debugstr_xmlstr(&elem));
2331 ret = parse_unknown_elem(xmlbuf, &elem);
2333 if (ret) ret = next_xml_elem(xmlbuf, &elem);
2336 return ret;
2339 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
2340 struct assembly_identity* ai, xmlbuf_t *xmlbuf )
2342 xmlstr_t elem;
2344 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
2346 if (xmlstr_cmp(&elem, xmlW) &&
2347 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
2348 return STATUS_SXS_CANT_GEN_ACTCTX;
2350 if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
2352 FIXME("root element is %s, not <assembly>\n", debugstr_xmlstr(&elem));
2353 return STATUS_SXS_CANT_GEN_ACTCTX;
2356 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
2358 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) );
2359 return STATUS_SXS_CANT_GEN_ACTCTX;
2362 if (next_xml_elem(xmlbuf, &elem))
2364 FIXME("unexpected element %s\n", debugstr_xmlstr(&elem));
2365 return STATUS_SXS_CANT_GEN_ACTCTX;
2368 if (xmlbuf->ptr != xmlbuf->end)
2370 FIXME("parse error\n");
2371 return STATUS_SXS_CANT_GEN_ACTCTX;
2373 return STATUS_SUCCESS;
2376 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2377 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2378 const void *buffer, SIZE_T size )
2380 xmlbuf_t xmlbuf;
2381 NTSTATUS status;
2382 struct assembly *assembly;
2383 int unicode_tests;
2385 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) );
2387 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
2388 return STATUS_SXS_CANT_GEN_ACTCTX;
2390 if (directory && !(assembly->directory = strdupW(directory)))
2391 return STATUS_NO_MEMORY;
2393 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
2394 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
2395 : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
2397 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
2398 if (RtlIsTextUnicode( buffer, size, &unicode_tests ))
2400 xmlbuf.ptr = buffer;
2401 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2402 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2404 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
2406 const WCHAR *buf = buffer;
2407 WCHAR *new_buff;
2408 unsigned int i;
2410 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size )))
2411 return STATUS_NO_MEMORY;
2412 for (i = 0; i < size / sizeof(WCHAR); i++)
2413 new_buff[i] = RtlUshortByteSwap( buf[i] );
2414 xmlbuf.ptr = new_buff;
2415 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
2416 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2417 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2419 else
2421 /* let's assume utf-8 for now */
2422 int len = wine_utf8_mbstowcs( 0, buffer, size, NULL, 0 );
2423 WCHAR *new_buff;
2425 if (len == -1)
2427 FIXME( "utf-8 conversion failed\n" );
2428 return STATUS_SXS_CANT_GEN_ACTCTX;
2430 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
2431 return STATUS_NO_MEMORY;
2432 wine_utf8_mbstowcs( 0, buffer, size, new_buff, len );
2433 xmlbuf.ptr = new_buff;
2434 xmlbuf.end = xmlbuf.ptr + len;
2435 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
2436 RtlFreeHeap( GetProcessHeap(), 0, new_buff );
2438 return status;
2441 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
2443 OBJECT_ATTRIBUTES attr;
2444 IO_STATUS_BLOCK io;
2446 attr.Length = sizeof(attr);
2447 attr.RootDirectory = 0;
2448 attr.Attributes = OBJ_CASE_INSENSITIVE;
2449 attr.ObjectName = name;
2450 attr.SecurityDescriptor = NULL;
2451 attr.SecurityQualityOfService = NULL;
2452 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
2455 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
2457 NTSTATUS status;
2458 ULONG_PTR magic;
2459 LDR_MODULE *pldr;
2461 LdrLockLoaderLock(0, NULL, &magic);
2462 status = LdrFindEntryForAddress( module, &pldr );
2463 if (status == STATUS_SUCCESS)
2465 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2466 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
2468 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
2469 str->Length = pldr->FullDllName.Length;
2470 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
2472 else status = STATUS_NO_MEMORY;
2474 LdrUnlockLoaderLock(0, magic);
2475 return status;
2478 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
2479 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2480 HANDLE hModule, LPCWSTR resname, ULONG lang )
2482 NTSTATUS status;
2483 UNICODE_STRING nameW;
2484 LDR_RESOURCE_INFO info;
2485 const IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
2486 void *ptr;
2488 if (TRACE_ON(actctx))
2490 if (!filename && !get_module_filename( hModule, &nameW, 0 ))
2492 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2493 hModule, debugstr_w(nameW.Buffer) );
2494 RtlFreeUnicodeString( &nameW );
2496 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname),
2497 hModule, debugstr_w(filename) );
2500 if (!resname) return STATUS_INVALID_PARAMETER;
2502 info.Type = RT_MANIFEST;
2503 info.Language = lang;
2504 if (!((ULONG_PTR)resname >> 16))
2506 info.Name = (ULONG_PTR)resname;
2507 status = LdrFindResource_U(hModule, &info, 3, &entry);
2509 else if (resname[0] == '#')
2511 ULONG value;
2512 RtlInitUnicodeString(&nameW, resname + 1);
2513 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
2514 return STATUS_INVALID_PARAMETER;
2515 info.Name = value;
2516 status = LdrFindResource_U(hModule, &info, 3, &entry);
2518 else
2520 RtlCreateUnicodeString(&nameW, resname);
2521 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
2522 info.Name = (ULONG_PTR)nameW.Buffer;
2523 status = LdrFindResource_U(hModule, &info, 3, &entry);
2524 RtlFreeUnicodeString(&nameW);
2526 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
2528 if (status == STATUS_SUCCESS)
2529 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
2531 return status;
2534 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
2535 LPCWSTR filename, LPCWSTR directory, BOOL shared,
2536 HANDLE file, LPCWSTR resname, ULONG lang )
2538 HANDLE mapping;
2539 OBJECT_ATTRIBUTES attr;
2540 LARGE_INTEGER size;
2541 LARGE_INTEGER offset;
2542 NTSTATUS status;
2543 SIZE_T count;
2544 void *base;
2546 TRACE( "looking for res %s in %s\n", debugstr_w(resname), debugstr_w(filename) );
2548 attr.Length = sizeof(attr);
2549 attr.RootDirectory = 0;
2550 attr.ObjectName = NULL;
2551 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2552 attr.SecurityDescriptor = NULL;
2553 attr.SecurityQualityOfService = NULL;
2555 size.QuadPart = 0;
2556 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2557 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2558 if (status != STATUS_SUCCESS) return status;
2560 offset.QuadPart = 0;
2561 count = 0;
2562 base = NULL;
2563 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2564 &count, ViewShare, 0, PAGE_READONLY );
2565 NtClose( mapping );
2566 if (status != STATUS_SUCCESS) return status;
2568 if (RtlImageNtHeader(base)) /* we got a PE file */
2570 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
2571 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
2573 else status = STATUS_INVALID_IMAGE_FORMAT;
2575 NtUnmapViewOfSection( GetCurrentProcess(), base );
2576 return status;
2579 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
2580 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
2582 FILE_END_OF_FILE_INFORMATION info;
2583 IO_STATUS_BLOCK io;
2584 HANDLE mapping;
2585 OBJECT_ATTRIBUTES attr;
2586 LARGE_INTEGER size;
2587 LARGE_INTEGER offset;
2588 NTSTATUS status;
2589 SIZE_T count;
2590 void *base;
2592 TRACE( "loading manifest file %s\n", debugstr_w(filename) );
2594 attr.Length = sizeof(attr);
2595 attr.RootDirectory = 0;
2596 attr.ObjectName = NULL;
2597 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
2598 attr.SecurityDescriptor = NULL;
2599 attr.SecurityQualityOfService = NULL;
2601 size.QuadPart = 0;
2602 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
2603 &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
2604 if (status != STATUS_SUCCESS) return status;
2606 offset.QuadPart = 0;
2607 count = 0;
2608 base = NULL;
2609 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset,
2610 &count, ViewShare, 0, PAGE_READONLY );
2611 NtClose( mapping );
2612 if (status != STATUS_SUCCESS) return status;
2614 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation );
2615 if (status == STATUS_SUCCESS)
2616 status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
2618 NtUnmapViewOfSection( GetCurrentProcess(), base );
2619 return status;
2622 /* try to load the .manifest file associated to the file */
2623 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
2624 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
2626 static const WCHAR fmtW[] = { '.','%','l','u',0 };
2627 WCHAR *buffer;
2628 NTSTATUS status;
2629 UNICODE_STRING nameW;
2630 HANDLE file;
2631 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID;
2633 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
2635 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid );
2637 if (module) /* use the module filename */
2639 UNICODE_STRING name;
2641 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
2643 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
2644 strcatW( name.Buffer, dotManifestW );
2645 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
2646 status = STATUS_RESOURCE_DATA_NOT_FOUND;
2647 RtlFreeUnicodeString( &name );
2649 if (status) return status;
2651 else
2653 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2654 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2655 return STATUS_NO_MEMORY;
2656 strcpyW( buffer, filename );
2657 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
2658 strcatW( buffer, dotManifestW );
2659 RtlInitUnicodeString( &nameW, buffer );
2662 if (!open_nt_file( &file, &nameW ))
2664 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2665 NtClose( file );
2667 else status = STATUS_RESOURCE_TYPE_NOT_FOUND;
2668 RtlFreeUnicodeString( &nameW );
2669 return status;
2672 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
2674 static const WCHAR lookup_fmtW[] =
2675 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
2676 '%','s','_','*','.','m','a','n','i','f','e','s','t',0};
2677 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'};
2679 WCHAR *lookup, *ret = NULL;
2680 UNICODE_STRING lookup_us;
2681 IO_STATUS_BLOCK io;
2682 const WCHAR *lang = ai->language;
2683 unsigned int data_pos = 0, data_len;
2684 char buffer[8192];
2686 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0,
2687 (strlenW(ai->arch) + strlenW(ai->name)
2688 + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
2689 + sizeof(lookup_fmtW) )))
2690 return NULL;
2692 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW;
2693 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key,
2694 ai->version.major, ai->version.minor, lang );
2695 RtlInitUnicodeString( &lookup_us, lookup );
2697 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2698 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ))
2700 ULONG min_build = ai->version.build, min_revision = ai->version.revision;
2701 FILE_BOTH_DIR_INFORMATION *dir_info;
2702 WCHAR *tmp;
2703 ULONG build, revision;
2705 data_len = io.Information;
2707 for (;;)
2709 if (data_pos >= data_len)
2711 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
2712 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ))
2713 break;
2714 data_len = io.Information;
2715 data_pos = 0;
2717 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
2719 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
2720 else data_pos = data_len;
2722 tmp = dir_info->FileName + (strchrW(lookup, '*') - lookup);
2723 build = atoiW(tmp);
2724 if (build < min_build) continue;
2725 tmp = strchrW(tmp, '.') + 1;
2726 revision = atoiW(tmp);
2727 if (build == min_build && revision < min_revision) continue;
2728 tmp = strchrW(tmp, '_') + 1;
2729 tmp = strchrW(tmp, '_') + 1;
2730 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) &&
2731 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) ))
2733 /* prefer a non-Wine manifest if we already have one */
2734 /* we'll still load the builtin dll if specified through DllOverrides */
2735 if (ret) continue;
2737 else
2739 min_build = build;
2740 min_revision = revision;
2742 ai->version.build = build;
2743 ai->version.revision = revision;
2744 RtlFreeHeap( GetProcessHeap(), 0, ret );
2745 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) )))
2747 memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
2748 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
2752 else WARN("no matching file for %s\n", debugstr_w(lookup));
2753 RtlFreeHeap( GetProcessHeap(), 0, lookup );
2754 return ret;
2757 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
2759 struct assembly_identity sxs_ai;
2760 UNICODE_STRING path_us;
2761 OBJECT_ATTRIBUTES attr;
2762 IO_STATUS_BLOCK io;
2763 WCHAR *path, *file = NULL;
2764 HANDLE handle;
2766 static const WCHAR manifest_dirW[] =
2767 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
2769 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
2771 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) +
2772 strlenW(user_shared_data->NtSystemRoot) * sizeof(WCHAR) )))
2773 return STATUS_NO_MEMORY;
2775 strcpyW( path, user_shared_data->NtSystemRoot );
2776 memcpy( path + strlenW(path), manifest_dirW, sizeof(manifest_dirW) );
2778 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
2780 RtlFreeHeap( GetProcessHeap(), 0, path );
2781 return STATUS_NO_SUCH_FILE;
2783 RtlFreeHeap( GetProcessHeap(), 0, path );
2785 attr.Length = sizeof(attr);
2786 attr.RootDirectory = 0;
2787 attr.Attributes = OBJ_CASE_INSENSITIVE;
2788 attr.ObjectName = &path_us;
2789 attr.SecurityDescriptor = NULL;
2790 attr.SecurityQualityOfService = NULL;
2792 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
2793 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
2795 sxs_ai = *ai;
2796 file = lookup_manifest_file( handle, &sxs_ai );
2797 NtClose( handle );
2799 if (!file)
2801 RtlFreeUnicodeString( &path_us );
2802 return STATUS_NO_SUCH_FILE;
2805 /* append file name to directory path */
2806 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer,
2807 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
2809 RtlFreeHeap( GetProcessHeap(), 0, file );
2810 RtlFreeUnicodeString( &path_us );
2811 return STATUS_NO_MEMORY;
2814 path[path_us.Length/sizeof(WCHAR)] = '\\';
2815 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
2816 RtlInitUnicodeString( &path_us, path );
2817 *strrchrW(file, '.') = 0; /* remove .manifest extension */
2819 if (!open_nt_file( &handle, &path_us ))
2821 io.u.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
2822 NtClose( handle );
2824 else io.u.Status = STATUS_NO_SUCH_FILE;
2826 RtlFreeHeap( GetProcessHeap(), 0, file );
2827 RtlFreeUnicodeString( &path_us );
2828 return io.u.Status;
2831 static NTSTATUS lookup_assembly(struct actctx_loader* acl,
2832 struct assembly_identity* ai)
2834 static const WCHAR dotDllW[] = {'.','d','l','l',0};
2835 unsigned int i;
2836 WCHAR *buffer, *p, *directory;
2837 NTSTATUS status;
2838 UNICODE_STRING nameW;
2839 HANDLE file;
2840 DWORD len;
2842 TRACE( "looking for name=%s version=%s arch=%s\n",
2843 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) );
2845 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
2847 /* FIXME: add support for language specific lookup */
2849 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR),
2850 strlenW(acl->actctx->appdir.info));
2852 nameW.Buffer = NULL;
2853 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2854 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
2855 return STATUS_NO_MEMORY;
2857 if (!(directory = build_assembly_dir( ai )))
2859 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2860 return STATUS_NO_MEMORY;
2863 /* Lookup in <dir>\name.dll
2864 * <dir>\name.manifest
2865 * <dir>\name\name.dll
2866 * <dir>\name\name.manifest
2868 * First 'appdir' is used as <dir>, if that failed
2869 * it tries application manifest file path.
2871 strcpyW( buffer, acl->actctx->appdir.info );
2872 p = buffer + strlenW(buffer);
2873 for (i = 0; i < 4; i++)
2875 if (i == 2)
2877 struct assembly *assembly = acl->actctx->assemblies;
2878 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break;
2880 else *p++ = '\\';
2882 strcpyW( p, ai->name );
2883 p += strlenW(p);
2885 strcpyW( p, dotDllW );
2886 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2888 status = open_nt_file( &file, &nameW );
2889 if (!status)
2891 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
2892 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
2893 NtClose( file );
2894 break;
2896 RtlFreeUnicodeString( &nameW );
2899 strcpyW( p, dotManifestW );
2900 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
2902 status = open_nt_file( &file, &nameW );
2903 if (!status)
2905 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
2906 NtClose( file );
2907 break;
2909 RtlFreeUnicodeString( &nameW );
2911 status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
2913 RtlFreeUnicodeString( &nameW );
2914 RtlFreeHeap( GetProcessHeap(), 0, directory );
2915 RtlFreeHeap( GetProcessHeap(), 0, buffer );
2916 return status;
2919 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
2921 NTSTATUS status = STATUS_SUCCESS;
2922 unsigned int i;
2924 for (i = 0; i < acl->num_dependencies; i++)
2926 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
2928 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed)
2930 FIXME( "Could not find dependent assembly %s (%s)\n",
2931 debugstr_w(acl->dependencies[i].name),
2932 debugstr_version(&acl->dependencies[i].version) );
2933 status = STATUS_SXS_CANT_GEN_ACTCTX;
2934 break;
2938 /* FIXME should now iterate through all refs */
2939 return status;
2942 /* find the appropriate activation context for RtlQueryInformationActivationContext */
2943 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
2945 NTSTATUS status = STATUS_SUCCESS;
2947 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
2949 if (*handle) return STATUS_INVALID_PARAMETER;
2951 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
2952 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
2954 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
2956 ULONG_PTR magic;
2957 LDR_MODULE *pldr;
2959 if (!*handle) return STATUS_INVALID_PARAMETER;
2961 LdrLockLoaderLock( 0, NULL, &magic );
2962 if (!LdrFindEntryForAddress( *handle, &pldr ))
2964 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->BaseAddress)
2965 status = STATUS_DLL_NOT_FOUND;
2966 else
2967 *handle = pldr->ActivationContext;
2969 else status = STATUS_DLL_NOT_FOUND;
2970 LdrUnlockLoaderLock( 0, magic );
2972 else if (!*handle && (class != ActivationContextBasicInformation))
2973 *handle = process_actctx;
2975 return status;
2978 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
2980 unsigned int i, j, total_len = 0, dll_count = 0;
2981 struct strsection_header *header;
2982 struct dllredirect_data *data;
2983 struct string_index *index;
2984 ULONG name_offset;
2986 /* compute section length */
2987 for (i = 0; i < actctx->num_assemblies; i++)
2989 struct assembly *assembly = &actctx->assemblies[i];
2990 for (j = 0; j < assembly->num_dlls; j++)
2992 struct dll_redirect *dll = &assembly->dlls[j];
2994 /* each entry needs index, data and string data */
2995 total_len += sizeof(*index);
2996 total_len += sizeof(*data);
2997 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
3000 dll_count += assembly->num_dlls;
3003 total_len += sizeof(*header);
3005 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3006 if (!header) return STATUS_NO_MEMORY;
3008 memset(header, 0, sizeof(*header));
3009 header->magic = STRSECTION_MAGIC;
3010 header->size = sizeof(*header);
3011 header->count = dll_count;
3012 header->index_offset = sizeof(*header);
3013 index = (struct string_index*)((BYTE*)header + header->index_offset);
3014 name_offset = header->index_offset + header->count*sizeof(*index);
3016 for (i = 0; i < actctx->num_assemblies; i++)
3018 struct assembly *assembly = &actctx->assemblies[i];
3019 for (j = 0; j < assembly->num_dlls; j++)
3021 struct dll_redirect *dll = &assembly->dlls[j];
3022 UNICODE_STRING str;
3023 WCHAR *ptrW;
3025 /* setup new index entry */
3026 str.Buffer = dll->name;
3027 str.Length = strlenW(dll->name)*sizeof(WCHAR);
3028 str.MaximumLength = str.Length + sizeof(WCHAR);
3029 /* hash original class name */
3030 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3032 index->name_offset = name_offset;
3033 index->name_len = str.Length;
3034 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3035 index->data_len = sizeof(*data);
3036 index->rosterindex = i + 1;
3038 /* setup data */
3039 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
3040 data->size = sizeof(*data);
3041 data->unk = 2; /* FIXME: seems to be constant */
3042 memset(data->res, 0, sizeof(data->res));
3044 /* dll name */
3045 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3046 memcpy(ptrW, dll->name, index->name_len);
3047 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3049 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
3051 index++;
3055 *section = header;
3057 return STATUS_SUCCESS;
3060 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
3062 struct string_index *iter, *index = NULL;
3063 ULONG hash = 0, i;
3065 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3066 iter = (struct string_index*)((BYTE*)section + section->index_offset);
3068 for (i = 0; i < section->count; i++)
3070 if (iter->hash == hash)
3072 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
3074 if (!strcmpiW(nameW, name->Buffer))
3076 index = iter;
3077 break;
3079 else
3080 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3082 iter++;
3085 return index;
3088 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
3090 struct guid_index *iter, *index = NULL;
3091 ULONG i;
3093 iter = (struct guid_index*)((BYTE*)section + section->index_offset);
3095 for (i = 0; i < section->count; i++)
3097 if (!memcmp(guid, &iter->guid, sizeof(*guid)))
3099 index = iter;
3100 break;
3102 iter++;
3105 return index;
3108 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3110 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
3113 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3114 PACTCTX_SECTION_KEYED_DATA data)
3116 struct dllredirect_data *dll;
3117 struct string_index *index;
3119 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3121 if (!actctx->dllredirect_section)
3123 struct strsection_header *section;
3125 NTSTATUS status = build_dllredirect_section(actctx, &section);
3126 if (status) return status;
3128 if (interlocked_cmpxchg_ptr((void**)&actctx->dllredirect_section, section, NULL))
3129 RtlFreeHeap(GetProcessHeap(), 0, section);
3132 index = find_string_index(actctx->dllredirect_section, name);
3133 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3135 if (data)
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;
3152 return STATUS_SUCCESS;
3155 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
3157 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
3160 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
3162 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
3165 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
3167 unsigned int i, j, k, total_len = 0, class_count = 0;
3168 struct wndclass_redirect_data *data;
3169 struct strsection_header *header;
3170 struct string_index *index;
3171 ULONG name_offset;
3173 /* compute section length */
3174 for (i = 0; i < actctx->num_assemblies; i++)
3176 struct assembly *assembly = &actctx->assemblies[i];
3177 for (j = 0; j < assembly->num_dlls; j++)
3179 struct dll_redirect *dll = &assembly->dlls[j];
3180 for (k = 0; k < dll->entities.num; k++)
3182 struct entity *entity = &dll->entities.base[k];
3183 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3185 int class_len = strlenW(entity->u.class.name) + 1;
3186 int len;
3188 /* each class entry needs index, data and string data */
3189 total_len += sizeof(*index);
3190 total_len += sizeof(*data);
3191 /* original name is stored separately */
3192 total_len += aligned_string_len(class_len*sizeof(WCHAR));
3193 /* versioned name and module name are stored one after another */
3194 if (entity->u.class.versioned)
3195 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
3196 else
3197 len = class_len;
3198 len += strlenW(dll->name) + 1;
3199 total_len += aligned_string_len(len*sizeof(WCHAR));
3201 class_count++;
3207 total_len += sizeof(*header);
3209 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3210 if (!header) return STATUS_NO_MEMORY;
3212 memset(header, 0, sizeof(*header));
3213 header->magic = STRSECTION_MAGIC;
3214 header->size = sizeof(*header);
3215 header->count = class_count;
3216 header->index_offset = sizeof(*header);
3217 index = (struct string_index*)((BYTE*)header + header->index_offset);
3218 name_offset = header->index_offset + header->count*sizeof(*index);
3220 for (i = 0; i < actctx->num_assemblies; i++)
3222 struct assembly *assembly = &actctx->assemblies[i];
3223 for (j = 0; j < assembly->num_dlls; j++)
3225 struct dll_redirect *dll = &assembly->dlls[j];
3226 for (k = 0; k < dll->entities.num; k++)
3228 struct entity *entity = &dll->entities.base[k];
3229 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
3231 static const WCHAR exclW[] = {'!',0};
3232 ULONG versioned_len, module_len;
3233 UNICODE_STRING str;
3234 WCHAR *ptrW;
3236 /* setup new index entry */
3237 str.Buffer = entity->u.class.name;
3238 str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
3239 str.MaximumLength = str.Length + sizeof(WCHAR);
3240 /* hash original class name */
3241 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
3243 /* include '!' separator too */
3244 if (entity->u.class.versioned)
3245 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
3246 else
3247 versioned_len = str.Length;
3248 module_len = strlenW(dll->name)*sizeof(WCHAR);
3250 index->name_offset = name_offset;
3251 index->name_len = str.Length;
3252 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
3253 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
3254 index->rosterindex = i + 1;
3256 /* setup data */
3257 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
3258 data->size = sizeof(*data);
3259 data->res = 0;
3260 data->name_len = versioned_len;
3261 data->name_offset = sizeof(*data);
3262 data->module_len = module_len;
3263 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
3265 /* original class name */
3266 ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
3267 memcpy(ptrW, entity->u.class.name, index->name_len);
3268 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3270 /* module name */
3271 ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
3272 memcpy(ptrW, dll->name, data->module_len);
3273 ptrW[data->module_len/sizeof(WCHAR)] = 0;
3275 /* versioned name */
3276 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3277 if (entity->u.class.versioned)
3279 get_assembly_version(assembly, ptrW);
3280 strcatW(ptrW, exclW);
3281 strcatW(ptrW, entity->u.class.name);
3283 else
3285 memcpy(ptrW, entity->u.class.name, index->name_len);
3286 ptrW[index->name_len/sizeof(WCHAR)] = 0;
3289 name_offset += sizeof(*data);
3290 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
3292 index++;
3298 *section = header;
3300 return STATUS_SUCCESS;
3303 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
3304 PACTCTX_SECTION_KEYED_DATA data)
3306 struct string_index *iter, *index = NULL;
3307 struct wndclass_redirect_data *class;
3308 ULONG hash;
3309 int i;
3311 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3313 if (!actctx->wndclass_section)
3315 struct strsection_header *section;
3317 NTSTATUS status = build_wndclass_section(actctx, &section);
3318 if (status) return status;
3320 if (interlocked_cmpxchg_ptr((void**)&actctx->wndclass_section, section, NULL))
3321 RtlFreeHeap(GetProcessHeap(), 0, section);
3324 hash = 0;
3325 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
3326 iter = get_wndclass_first_index(actctx);
3328 for (i = 0; i < actctx->wndclass_section->count; i++)
3330 if (iter->hash == hash)
3332 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
3334 if (!strcmpiW(nameW, name->Buffer))
3336 index = iter;
3337 break;
3339 else
3340 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(nameW));
3342 iter++;
3345 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3347 if (data)
3349 class = get_wndclass_data(actctx, index);
3351 data->ulDataFormatVersion = 1;
3352 data->lpData = class;
3353 /* full length includes string length with nulls */
3354 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
3355 data->lpSectionGlobalData = NULL;
3356 data->ulSectionGlobalDataLength = 0;
3357 data->lpSectionBase = actctx->wndclass_section;
3358 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section );
3359 data->hActCtx = NULL;
3361 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3362 data->ulAssemblyRosterIndex = index->rosterindex;
3365 return STATUS_SUCCESS;
3368 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3370 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
3371 struct guidsection_header *header;
3372 ULONG module_offset, data_offset;
3373 struct tlibredirect_data *data;
3374 struct guid_index *index;
3376 /* compute section length */
3377 for (i = 0; i < actctx->num_assemblies; i++)
3379 struct assembly *assembly = &actctx->assemblies[i];
3380 for (j = 0; j < assembly->num_dlls; j++)
3382 struct dll_redirect *dll = &assembly->dlls[j];
3383 for (k = 0; k < dll->entities.num; k++)
3385 struct entity *entity = &dll->entities.base[k];
3386 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3388 /* each entry needs index, data and string data for module name and help string */
3389 total_len += sizeof(*index);
3390 total_len += sizeof(*data);
3391 /* help string is stored separately */
3392 if (*entity->u.typelib.helpdir)
3393 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
3395 /* module names are packed one after another */
3396 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3398 tlib_count++;
3404 total_len += aligned_string_len(names_len);
3405 total_len += sizeof(*header);
3407 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3408 if (!header) return STATUS_NO_MEMORY;
3410 memset(header, 0, sizeof(*header));
3411 header->magic = GUIDSECTION_MAGIC;
3412 header->size = sizeof(*header);
3413 header->count = tlib_count;
3414 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3415 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3416 module_offset = sizeof(*header);
3417 data_offset = header->index_offset + tlib_count*sizeof(*index);
3419 for (i = 0; i < actctx->num_assemblies; i++)
3421 struct assembly *assembly = &actctx->assemblies[i];
3422 for (j = 0; j < assembly->num_dlls; j++)
3424 struct dll_redirect *dll = &assembly->dlls[j];
3425 for (k = 0; k < dll->entities.num; k++)
3427 struct entity *entity = &dll->entities.base[k];
3428 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
3430 ULONG module_len, help_len;
3431 UNICODE_STRING str;
3432 WCHAR *ptrW;
3434 if (*entity->u.typelib.helpdir)
3435 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
3436 else
3437 help_len = 0;
3439 module_len = strlenW(dll->name)*sizeof(WCHAR);
3441 /* setup new index entry */
3442 RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
3443 RtlGUIDFromString(&str, &index->guid);
3444 index->data_offset = data_offset;
3445 index->data_len = sizeof(*data) + aligned_string_len(help_len);
3446 index->rosterindex = i + 1;
3448 /* setup data */
3449 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
3450 data->size = sizeof(*data);
3451 data->res = 0;
3452 data->name_len = module_len;
3453 data->name_offset = module_offset;
3454 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
3455 data->langid = 0;
3456 data->flags = entity->u.typelib.flags;
3457 data->help_len = help_len;
3458 data->help_offset = sizeof(*data);
3459 data->major_version = entity->u.typelib.major;
3460 data->minor_version = entity->u.typelib.minor;
3462 /* module name */
3463 ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
3464 memcpy(ptrW, dll->name, data->name_len);
3465 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3467 /* help string */
3468 if (data->help_len)
3470 ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
3471 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
3472 ptrW[data->help_len/sizeof(WCHAR)] = 0;
3475 data_offset += sizeof(*data);
3476 if (help_len)
3477 data_offset += aligned_string_len(help_len + sizeof(WCHAR));
3479 module_offset += module_len + sizeof(WCHAR);
3481 index++;
3487 *section = header;
3489 return STATUS_SUCCESS;
3492 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3494 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
3497 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3499 struct guid_index *index = NULL;
3500 struct tlibredirect_data *tlib;
3502 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3504 if (!actctx->tlib_section)
3506 struct guidsection_header *section;
3508 NTSTATUS status = build_tlib_section(actctx, &section);
3509 if (status) return status;
3511 if (interlocked_cmpxchg_ptr((void**)&actctx->tlib_section, section, NULL))
3512 RtlFreeHeap(GetProcessHeap(), 0, section);
3515 index = find_guid_index(actctx->tlib_section, guid);
3516 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3518 tlib = get_tlib_data(actctx, index);
3520 data->ulDataFormatVersion = 1;
3521 data->lpData = tlib;
3522 /* full length includes string length with nulls */
3523 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
3524 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
3525 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
3526 data->lpSectionBase = actctx->tlib_section;
3527 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section );
3528 data->hActCtx = NULL;
3530 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3531 data->ulAssemblyRosterIndex = index->rosterindex;
3533 return STATUS_SUCCESS;
3536 static void generate_uuid(ULONG *seed, GUID *guid)
3538 ULONG *ptr = (ULONG*)guid;
3539 int i;
3541 /* GUID is 16 bytes long */
3542 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
3543 *ptr = RtlUniform(seed);
3545 guid->Data3 &= 0x0fff;
3546 guid->Data3 |= (4 << 12);
3547 guid->Data4[0] &= 0x3f;
3548 guid->Data4[0] |= 0x80;
3551 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
3552 unsigned int *count, unsigned int *len, unsigned int *module_len)
3554 unsigned int i;
3556 for (i = 0; i < entities->num; i++)
3558 struct entity *entity = &entities->base[i];
3559 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3561 /* each entry needs two index entries, extra one goes for alias GUID */
3562 *len += 2*sizeof(struct guid_index);
3563 /* To save some memory we don't allocated two data structures,
3564 instead alias index and normal index point to the same data structure. */
3565 *len += sizeof(struct comclassredirect_data);
3567 /* for clrClass store some more */
3568 if (entity->u.comclass.name)
3570 unsigned int str_len;
3572 /* all string data is stored together in aligned block */
3573 str_len = strlenW(entity->u.comclass.name)+1;
3574 if (entity->u.comclass.progid)
3575 str_len += strlenW(entity->u.comclass.progid)+1;
3576 if (entity->u.comclass.version)
3577 str_len += strlenW(entity->u.comclass.version)+1;
3579 *len += sizeof(struct clrclass_data);
3580 *len += aligned_string_len(str_len*sizeof(WCHAR));
3582 /* module name is forced to mscoree.dll, and stored two times with different case */
3583 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
3585 else
3587 /* progid string is stored separately */
3588 if (entity->u.comclass.progid)
3589 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
3591 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
3594 *count += 1;
3599 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
3600 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
3601 ULONG *seed, ULONG rosterindex)
3603 unsigned int i;
3605 for (i = 0; i < entities->num; i++)
3607 struct entity *entity = &entities->base[i];
3608 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
3610 ULONG module_len, progid_len, str_len = 0;
3611 struct comclassredirect_data *data;
3612 struct guid_index *alias_index;
3613 struct clrclass_data *clrdata;
3614 UNICODE_STRING str;
3615 WCHAR *ptrW;
3617 if (entity->u.comclass.progid)
3618 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
3619 else
3620 progid_len = 0;
3622 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
3624 /* setup new index entry */
3625 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
3626 RtlGUIDFromString(&str, &(*index)->guid);
3628 (*index)->data_offset = *data_offset;
3629 (*index)->data_len = sizeof(*data); /* additional length added later */
3630 (*index)->rosterindex = rosterindex;
3632 /* Setup new index entry for alias guid. Alias index records are placed after
3633 normal records, so normal guids are hit first on search. Note that class count
3634 is doubled. */
3635 alias_index = (*index) + section->count/2;
3636 generate_uuid(seed, &alias_index->guid);
3637 alias_index->data_offset = (*index)->data_offset;
3638 alias_index->data_len = 0;
3639 alias_index->rosterindex = (*index)->rosterindex;
3641 /* setup data */
3642 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
3643 data->size = sizeof(*data);
3644 data->res = 0;
3645 data->res1[0] = 0;
3646 data->res1[1] = 0;
3647 data->model = entity->u.comclass.model;
3648 data->clsid = (*index)->guid;
3649 data->alias = alias_index->guid;
3650 data->clsid2 = data->clsid;
3651 if (entity->u.comclass.tlbid)
3653 RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
3654 RtlGUIDFromString(&str, &data->tlbid);
3656 else
3657 memset(&data->tlbid, 0, sizeof(data->tlbid));
3658 data->name_len = module_len;
3659 data->name_offset = *module_offset;
3660 data->progid_len = progid_len;
3661 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
3662 data->clrdata_len = 0; /* will be set later */
3663 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
3664 data->miscstatus = entity->u.comclass.miscstatus;
3665 data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
3666 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
3667 data->miscstatusicon = entity->u.comclass.miscstatusicon;
3668 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
3670 /* mask describes which misc* data is available */
3671 data->miscmask = 0;
3672 if (data->miscstatus)
3673 data->miscmask |= MiscStatus;
3674 if (data->miscstatuscontent)
3675 data->miscmask |= MiscStatusContent;
3676 if (data->miscstatusthumbnail)
3677 data->miscmask |= MiscStatusThumbnail;
3678 if (data->miscstatusicon)
3679 data->miscmask |= MiscStatusIcon;
3680 if (data->miscstatusdocprint)
3681 data->miscmask |= MiscStatusDocPrint;
3683 if (data->clrdata_offset)
3685 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
3687 clrdata->size = sizeof(*clrdata);
3688 clrdata->res[0] = 0;
3689 clrdata->res[1] = 2; /* FIXME: unknown field */
3690 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
3691 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
3692 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
3693 clrdata->name_offset = clrdata->size;
3694 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
3695 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
3696 clrdata->res2[0] = 0;
3697 clrdata->res2[1] = 0;
3699 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
3701 /* module name */
3702 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
3703 memcpy(ptrW, mscoree2W, clrdata->module_len);
3704 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
3706 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3707 memcpy(ptrW, mscoreeW, data->name_len);
3708 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3710 /* class name */
3711 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
3712 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
3713 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
3715 /* runtime version, optional */
3716 if (clrdata->version_len)
3718 data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
3720 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
3721 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
3722 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
3725 if (data->progid_len)
3726 data->progid_offset += data->clrdata_len;
3727 (*index)->data_len += sizeof(*clrdata);
3729 else
3731 clrdata = NULL;
3733 /* module name */
3734 ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
3735 memcpy(ptrW, dll->name, data->name_len);
3736 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3739 /* progid string */
3740 if (data->progid_len)
3742 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
3743 memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
3744 ptrW[data->progid_len/sizeof(WCHAR)] = 0;
3747 /* string block length */
3748 str_len = 0;
3749 if (clrdata)
3751 str_len += clrdata->name_len + sizeof(WCHAR);
3752 if (clrdata->version_len)
3753 str_len += clrdata->version_len + sizeof(WCHAR);
3755 if (progid_len)
3756 str_len += progid_len + sizeof(WCHAR);
3758 (*index)->data_len += aligned_string_len(str_len);
3759 alias_index->data_len = (*index)->data_len;
3761 /* move to next data record */
3762 (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
3763 (*module_offset) += module_len + sizeof(WCHAR);
3765 if (clrdata)
3767 (*data_offset) += sizeof(*clrdata);
3768 (*module_offset) += clrdata->module_len + sizeof(WCHAR);
3770 (*index) += 1;
3775 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3777 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
3778 struct guidsection_header *header;
3779 ULONG module_offset, data_offset;
3780 struct guid_index *index;
3781 ULONG seed;
3783 /* compute section length */
3784 for (i = 0; i < actctx->num_assemblies; i++)
3786 struct assembly *assembly = &actctx->assemblies[i];
3787 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
3788 for (j = 0; j < assembly->num_dlls; j++)
3790 struct dll_redirect *dll = &assembly->dlls[j];
3791 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
3795 total_len += aligned_string_len(names_len);
3796 total_len += sizeof(*header);
3798 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3799 if (!header) return STATUS_NO_MEMORY;
3801 memset(header, 0, sizeof(*header));
3802 header->magic = GUIDSECTION_MAGIC;
3803 header->size = sizeof(*header);
3804 header->count = 2*class_count;
3805 header->index_offset = sizeof(*header) + aligned_string_len(names_len);
3806 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3807 module_offset = sizeof(*header);
3808 data_offset = header->index_offset + 2*class_count*sizeof(*index);
3810 seed = NtGetTickCount();
3811 for (i = 0; i < actctx->num_assemblies; i++)
3813 struct assembly *assembly = &actctx->assemblies[i];
3814 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
3815 for (j = 0; j < assembly->num_dlls; j++)
3817 struct dll_redirect *dll = &assembly->dlls[j];
3818 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
3822 *section = header;
3824 return STATUS_SUCCESS;
3827 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
3829 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
3832 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
3834 struct comclassredirect_data *comclass;
3835 struct guid_index *index = NULL;
3837 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
3839 if (!actctx->comserver_section)
3841 struct guidsection_header *section;
3843 NTSTATUS status = build_comserver_section(actctx, &section);
3844 if (status) return status;
3846 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
3847 RtlFreeHeap(GetProcessHeap(), 0, section);
3850 index = find_guid_index(actctx->comserver_section, guid);
3851 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
3853 comclass = get_comclass_data(actctx, index);
3855 data->ulDataFormatVersion = 1;
3856 data->lpData = comclass;
3857 /* full length includes string length with nulls */
3858 data->ulLength = comclass->size + comclass->clrdata_len;
3859 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
3860 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
3861 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
3862 data->lpSectionBase = actctx->comserver_section;
3863 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section );
3864 data->hActCtx = NULL;
3866 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
3867 data->ulAssemblyRosterIndex = index->rosterindex;
3869 return STATUS_SUCCESS;
3872 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
3874 unsigned int i;
3876 for (i = 0; i < entities->num; i++)
3878 struct entity *entity = &entities->base[i];
3879 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3881 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
3882 if (entity->u.ifaceps.name)
3883 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
3884 *count += 1;
3889 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
3890 struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
3892 unsigned int i;
3894 for (i = 0; i < entities->num; i++)
3896 struct entity *entity = &entities->base[i];
3897 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
3899 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
3900 UNICODE_STRING str;
3901 ULONG name_len;
3903 if (entity->u.ifaceps.name)
3904 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
3905 else
3906 name_len = 0;
3908 /* setup index */
3909 RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
3910 RtlGUIDFromString(&str, &(*index)->guid);
3911 (*index)->data_offset = *data_offset;
3912 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
3913 (*index)->rosterindex = rosterindex;
3915 /* setup data record */
3916 data->size = sizeof(*data);
3917 data->mask = entity->u.ifaceps.mask;
3919 /* proxyStubClsid32 value is only stored for external PS,
3920 if set it's used as iid, otherwise 'iid' attribute value is used */
3921 if (entity->u.ifaceps.ps32)
3923 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
3924 RtlGUIDFromString(&str, &data->iid);
3926 else
3927 data->iid = (*index)->guid;
3929 data->nummethods = entity->u.ifaceps.nummethods;
3931 if (entity->u.ifaceps.tlib)
3933 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
3934 RtlGUIDFromString(&str, &data->tlbid);
3936 else
3937 memset(&data->tlbid, 0, sizeof(data->tlbid));
3939 if (entity->u.ifaceps.base)
3941 RtlInitUnicodeString(&str, entity->u.ifaceps.base);
3942 RtlGUIDFromString(&str, &data->base);
3944 else
3945 memset(&data->base, 0, sizeof(data->base));
3947 data->name_len = name_len;
3948 data->name_offset = data->name_len ? sizeof(*data) : 0;
3950 /* name string */
3951 if (data->name_len)
3953 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
3954 memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
3955 ptrW[data->name_len/sizeof(WCHAR)] = 0;
3958 /* move to next record */
3959 (*index) += 1;
3960 *data_offset += sizeof(*data);
3961 if (data->name_len)
3962 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
3967 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
3969 unsigned int i, j, total_len = 0, count = 0;
3970 struct guidsection_header *header;
3971 struct guid_index *index;
3972 ULONG data_offset;
3974 /* compute section length */
3975 for (i = 0; i < actctx->num_assemblies; i++)
3977 struct assembly *assembly = &actctx->assemblies[i];
3979 get_ifaceps_datalen(&assembly->entities, &count, &total_len);
3980 for (j = 0; j < assembly->num_dlls; j++)
3982 struct dll_redirect *dll = &assembly->dlls[j];
3983 get_ifaceps_datalen(&dll->entities, &count, &total_len);
3987 total_len += sizeof(*header);
3989 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
3990 if (!header) return STATUS_NO_MEMORY;
3992 memset(header, 0, sizeof(*header));
3993 header->magic = GUIDSECTION_MAGIC;
3994 header->size = sizeof(*header);
3995 header->count = count;
3996 header->index_offset = sizeof(*header);
3997 index = (struct guid_index*)((BYTE*)header + header->index_offset);
3998 data_offset = header->index_offset + count*sizeof(*index);
4000 for (i = 0; i < actctx->num_assemblies; i++)
4002 struct assembly *assembly = &actctx->assemblies[i];
4004 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
4005 for (j = 0; j < assembly->num_dlls; j++)
4007 struct dll_redirect *dll = &assembly->dlls[j];
4008 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
4012 *section = header;
4014 return STATUS_SUCCESS;
4017 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
4019 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
4022 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4024 struct ifacepsredirect_data *iface;
4025 struct guid_index *index = NULL;
4027 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4029 if (!actctx->ifaceps_section)
4031 struct guidsection_header *section;
4033 NTSTATUS status = build_ifaceps_section(actctx, &section);
4034 if (status) return status;
4036 if (interlocked_cmpxchg_ptr((void**)&actctx->ifaceps_section, section, NULL))
4037 RtlFreeHeap(GetProcessHeap(), 0, section);
4040 index = find_guid_index(actctx->ifaceps_section, guid);
4041 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4043 iface = get_ifaceps_data(actctx, index);
4045 data->ulDataFormatVersion = 1;
4046 data->lpData = iface;
4047 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
4048 data->lpSectionGlobalData = NULL;
4049 data->ulSectionGlobalDataLength = 0;
4050 data->lpSectionBase = actctx->ifaceps_section;
4051 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section );
4052 data->hActCtx = NULL;
4054 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4055 data->ulAssemblyRosterIndex = index->rosterindex;
4057 return STATUS_SUCCESS;
4060 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
4062 unsigned int i, j, total_len = 0, count = 0;
4063 struct guidsection_header *header;
4064 struct clrsurrogate_data *data;
4065 struct guid_index *index;
4066 ULONG data_offset;
4068 /* compute section length */
4069 for (i = 0; i < actctx->num_assemblies; i++)
4071 struct assembly *assembly = &actctx->assemblies[i];
4072 for (j = 0; j < assembly->entities.num; j++)
4074 struct entity *entity = &assembly->entities.base[j];
4075 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4077 ULONG len;
4079 total_len += sizeof(*index) + sizeof(*data);
4080 len = strlenW(entity->u.clrsurrogate.name) + 1;
4081 if (entity->u.clrsurrogate.version)
4082 len += strlenW(entity->u.clrsurrogate.version) + 1;
4083 total_len += aligned_string_len(len*sizeof(WCHAR));
4085 count++;
4090 total_len += sizeof(*header);
4092 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4093 if (!header) return STATUS_NO_MEMORY;
4095 memset(header, 0, sizeof(*header));
4096 header->magic = GUIDSECTION_MAGIC;
4097 header->size = sizeof(*header);
4098 header->count = count;
4099 header->index_offset = sizeof(*header);
4100 index = (struct guid_index*)((BYTE*)header + header->index_offset);
4101 data_offset = header->index_offset + count*sizeof(*index);
4103 for (i = 0; i < actctx->num_assemblies; i++)
4105 struct assembly *assembly = &actctx->assemblies[i];
4106 for (j = 0; j < assembly->entities.num; j++)
4108 struct entity *entity = &assembly->entities.base[j];
4109 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
4111 ULONG version_len, name_len;
4112 UNICODE_STRING str;
4113 WCHAR *ptrW;
4115 if (entity->u.clrsurrogate.version)
4116 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
4117 else
4118 version_len = 0;
4119 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
4121 /* setup new index entry */
4122 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
4123 RtlGUIDFromString(&str, &index->guid);
4125 index->data_offset = data_offset;
4126 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
4127 index->rosterindex = i + 1;
4129 /* setup data */
4130 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
4131 data->size = sizeof(*data);
4132 data->res = 0;
4133 data->clsid = index->guid;
4134 data->version_offset = version_len ? data->size : 0;
4135 data->version_len = version_len;
4136 data->name_offset = data->size + version_len;
4137 if (version_len)
4138 data->name_offset += sizeof(WCHAR);
4139 data->name_len = name_len;
4141 /* surrogate name */
4142 ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
4143 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
4144 ptrW[data->name_len/sizeof(WCHAR)] = 0;
4146 /* runtime version */
4147 if (data->version_len)
4149 ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
4150 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
4151 ptrW[data->version_len/sizeof(WCHAR)] = 0;
4154 data_offset += index->data_offset;
4155 index++;
4160 *section = header;
4162 return STATUS_SUCCESS;
4165 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
4167 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
4170 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
4172 struct clrsurrogate_data *surrogate;
4173 struct guid_index *index = NULL;
4175 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4177 if (!actctx->clrsurrogate_section)
4179 struct guidsection_header *section;
4181 NTSTATUS status = build_clr_surrogate_section(actctx, &section);
4182 if (status) return status;
4184 if (interlocked_cmpxchg_ptr((void**)&actctx->clrsurrogate_section, section, NULL))
4185 RtlFreeHeap(GetProcessHeap(), 0, section);
4188 index = find_guid_index(actctx->clrsurrogate_section, guid);
4189 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4191 surrogate = get_surrogate_data(actctx, index);
4193 data->ulDataFormatVersion = 1;
4194 data->lpData = surrogate;
4195 /* full length includes string length with nulls */
4196 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
4197 if (surrogate->version_len)
4198 data->ulLength += surrogate->version_len + sizeof(WCHAR);
4200 data->lpSectionGlobalData = NULL;
4201 data->ulSectionGlobalDataLength = 0;
4202 data->lpSectionBase = actctx->clrsurrogate_section;
4203 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section );
4204 data->hActCtx = NULL;
4206 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4207 data->ulAssemblyRosterIndex = index->rosterindex;
4209 return STATUS_SUCCESS;
4212 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
4214 unsigned int i, j, single_len;
4216 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
4217 for (i = 0; i < entities->num; i++)
4219 struct entity *entity = &entities->base[i];
4220 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4222 if (entity->u.comclass.progid)
4224 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
4225 *count += 1;
4228 for (j = 0; j < entity->u.comclass.progids.num; j++)
4229 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
4231 *total_len += single_len*entity->u.comclass.progids.num;
4232 *count += entity->u.comclass.progids.num;
4237 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
4238 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4240 struct progidredirect_data *data;
4241 UNICODE_STRING str;
4242 GUID *guid_ptr;
4243 WCHAR *ptrW;
4245 /* setup new index entry */
4247 /* hash progid name */
4248 RtlInitUnicodeString(&str, progid);
4249 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
4251 (*index)->name_offset = *data_offset;
4252 (*index)->name_len = str.Length;
4253 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
4254 (*index)->data_len = sizeof(*data);
4255 (*index)->rosterindex = rosterindex;
4257 *data_offset += aligned_string_len(str.MaximumLength);
4259 /* setup data structure */
4260 data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
4261 data->size = sizeof(*data);
4262 data->reserved = 0;
4263 data->clsid_offset = *global_offset;
4265 /* write progid string */
4266 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
4267 memcpy(ptrW, progid, (*index)->name_len);
4268 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
4270 /* write guid to global area */
4271 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
4272 *guid_ptr = *alias;
4274 /* to next entry */
4275 *global_offset += sizeof(GUID);
4276 *data_offset += data->size;
4277 (*index) += 1;
4280 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
4281 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
4283 unsigned int i, j;
4285 for (i = 0; i < entities->num; i++)
4287 struct entity *entity = &entities->base[i];
4288 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
4290 const struct progids *progids = &entity->u.comclass.progids;
4291 struct comclassredirect_data *comclass;
4292 struct guid_index *guid_index;
4293 UNICODE_STRING str;
4294 GUID clsid;
4296 RtlInitUnicodeString(&str, entity->u.comclass.clsid);
4297 RtlGUIDFromString(&str, &clsid);
4299 guid_index = find_guid_index(actctx->comserver_section, &clsid);
4300 comclass = get_comclass_data(actctx, guid_index);
4302 if (entity->u.comclass.progid)
4303 write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
4304 index, data_offset, global_offset, rosterindex);
4306 for (j = 0; j < progids->num; j++)
4307 write_progid_record(section, progids->progids[j], &comclass->alias,
4308 index, data_offset, global_offset, rosterindex);
4313 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
4315 unsigned int i, j, total_len = 0, count = 0;
4316 struct strsection_header *header;
4317 ULONG data_offset, global_offset;
4318 struct string_index *index;
4320 /* compute section length */
4321 for (i = 0; i < actctx->num_assemblies; i++)
4323 struct assembly *assembly = &actctx->assemblies[i];
4325 get_progid_datalen(&assembly->entities, &count, &total_len);
4326 for (j = 0; j < assembly->num_dlls; j++)
4328 struct dll_redirect *dll = &assembly->dlls[j];
4329 get_progid_datalen(&dll->entities, &count, &total_len);
4333 total_len += sizeof(*header);
4335 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len);
4336 if (!header) return STATUS_NO_MEMORY;
4338 memset(header, 0, sizeof(*header));
4339 header->magic = STRSECTION_MAGIC;
4340 header->size = sizeof(*header);
4341 header->count = count;
4342 header->global_offset = header->size;
4343 header->global_len = count*sizeof(GUID);
4344 header->index_offset = header->size + header->global_len;
4346 index = (struct string_index*)((BYTE*)header + header->index_offset);
4347 data_offset = header->index_offset + count*sizeof(*index);
4348 global_offset = header->global_offset;
4350 for (i = 0; i < actctx->num_assemblies; i++)
4352 struct assembly *assembly = &actctx->assemblies[i];
4354 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
4355 for (j = 0; j < assembly->num_dlls; j++)
4357 struct dll_redirect *dll = &assembly->dlls[j];
4358 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
4362 *section = header;
4364 return STATUS_SUCCESS;
4367 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
4369 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
4372 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
4373 PACTCTX_SECTION_KEYED_DATA data)
4375 struct progidredirect_data *progid;
4376 struct string_index *index;
4378 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
4380 if (!actctx->comserver_section)
4382 struct guidsection_header *section;
4384 NTSTATUS status = build_comserver_section(actctx, &section);
4385 if (status) return status;
4387 if (interlocked_cmpxchg_ptr((void**)&actctx->comserver_section, section, NULL))
4388 RtlFreeHeap(GetProcessHeap(), 0, section);
4391 if (!actctx->progid_section)
4393 struct strsection_header *section;
4395 NTSTATUS status = build_progid_section(actctx, &section);
4396 if (status) return status;
4398 if (interlocked_cmpxchg_ptr((void**)&actctx->progid_section, section, NULL))
4399 RtlFreeHeap(GetProcessHeap(), 0, section);
4402 index = find_string_index(actctx->progid_section, name);
4403 if (!index) return STATUS_SXS_KEY_NOT_FOUND;
4405 if (data)
4407 progid = get_progid_data(actctx, index);
4409 data->ulDataFormatVersion = 1;
4410 data->lpData = progid;
4411 data->ulLength = progid->size;
4412 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
4413 data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
4414 data->lpSectionBase = actctx->progid_section;
4415 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section );
4416 data->hActCtx = NULL;
4418 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
4419 data->ulAssemblyRosterIndex = index->rosterindex;
4422 return STATUS_SUCCESS;
4425 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4426 const UNICODE_STRING *section_name,
4427 DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4429 NTSTATUS status;
4431 switch (section_kind)
4433 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
4434 status = find_dll_redirection(actctx, section_name, data);
4435 break;
4436 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
4437 status = find_window_class(actctx, section_name, data);
4438 break;
4439 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
4440 status = find_progid_redirection(actctx, section_name, data);
4441 break;
4442 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
4443 FIXME("Unsupported yet section_kind %x\n", section_kind);
4444 return STATUS_SXS_SECTION_NOT_FOUND;
4445 default:
4446 WARN("Unknown section_kind %x\n", section_kind);
4447 return STATUS_SXS_SECTION_NOT_FOUND;
4450 if (status != STATUS_SUCCESS) return status;
4452 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX))
4454 actctx_addref(actctx);
4455 data->hActCtx = actctx;
4457 return STATUS_SUCCESS;
4460 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
4461 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
4463 NTSTATUS status;
4465 switch (section_kind)
4467 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
4468 status = find_tlib_redirection(actctx, guid, data);
4469 break;
4470 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
4471 status = find_comserver_redirection(actctx, guid, data);
4472 break;
4473 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
4474 status = find_cominterface_redirection(actctx, guid, data);
4475 break;
4476 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
4477 status = find_clr_surrogate(actctx, guid, data);
4478 break;
4479 default:
4480 WARN("Unknown section_kind %x\n", section_kind);
4481 return STATUS_SXS_SECTION_NOT_FOUND;
4484 if (status != STATUS_SUCCESS) return status;
4486 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
4488 actctx_addref(actctx);
4489 data->hActCtx = actctx;
4491 return STATUS_SUCCESS;
4494 /* initialize the activation context for the current process */
4495 void actctx_init(void)
4497 ACTCTXW ctx;
4498 HANDLE handle;
4500 ctx.cbSize = sizeof(ctx);
4501 ctx.lpSource = NULL;
4502 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
4503 ctx.hModule = NtCurrentTeb()->Peb->ImageBaseAddress;
4504 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
4506 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
4510 /***********************************************************************
4511 * RtlCreateActivationContext (NTDLL.@)
4513 * Create an activation context.
4515 * FIXME: function signature/prototype is wrong
4517 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, const void *ptr )
4519 const ACTCTXW *pActCtx = ptr; /* FIXME: not the right structure */
4520 const WCHAR *directory = NULL;
4521 ACTIVATION_CONTEXT *actctx;
4522 UNICODE_STRING nameW;
4523 ULONG lang = 0;
4524 NTSTATUS status = STATUS_NO_MEMORY;
4525 HANDLE file = 0;
4526 struct actctx_loader acl;
4528 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
4530 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
4531 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
4532 return STATUS_INVALID_PARAMETER;
4534 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
4535 return STATUS_NO_MEMORY;
4537 actctx->magic = ACTCTX_MAGIC;
4538 actctx->ref_count = 1;
4539 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
4540 actctx->config.info = NULL;
4541 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
4542 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
4544 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
4546 else
4548 UNICODE_STRING dir;
4549 WCHAR *p;
4550 HMODULE module;
4552 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
4553 else module = NtCurrentTeb()->Peb->ImageBaseAddress;
4555 if ((status = get_module_filename( module, &dir, 0 ))) goto error;
4556 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
4557 actctx->appdir.info = dir.Buffer;
4560 nameW.Buffer = NULL;
4562 /* open file only if it's going to be used */
4563 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) &&
4564 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)))
4566 WCHAR *source = NULL;
4567 BOOLEAN ret;
4569 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID &&
4570 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH)
4572 DWORD dir_len, source_len;
4574 dir_len = strlenW(pActCtx->lpAssemblyDirectory);
4575 source_len = strlenW(pActCtx->lpSource);
4576 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR))))
4578 status = STATUS_NO_MEMORY;
4579 goto error;
4582 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR));
4583 source[dir_len] = '\\';
4584 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR));
4587 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL);
4588 RtlFreeHeap( GetProcessHeap(), 0, source );
4589 if (!ret)
4591 status = STATUS_NO_SUCH_FILE;
4592 goto error;
4594 status = open_nt_file( &file, &nameW );
4595 if (status)
4597 RtlFreeUnicodeString( &nameW );
4598 goto error;
4602 acl.actctx = actctx;
4603 acl.dependencies = NULL;
4604 acl.num_dependencies = 0;
4605 acl.allocated_dependencies = 0;
4607 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
4608 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
4610 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
4612 /* if we have a resource it's a PE file */
4613 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
4615 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
4616 pActCtx->lpResourceName, lang );
4617 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4618 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
4619 pActCtx->hModule, pActCtx->lpResourceName );
4621 else if (pActCtx->lpSource)
4623 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
4624 file, pActCtx->lpResourceName, lang );
4625 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
4626 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
4627 NULL, pActCtx->lpResourceName );
4629 else status = STATUS_INVALID_PARAMETER;
4631 else
4633 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
4636 if (file) NtClose( file );
4637 RtlFreeUnicodeString( &nameW );
4639 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
4640 free_depend_manifests( &acl );
4642 if (status == STATUS_SUCCESS) *handle = actctx;
4643 else actctx_release( actctx );
4644 return status;
4646 error:
4647 if (file) NtClose( file );
4648 actctx_release( actctx );
4649 return status;
4653 /***********************************************************************
4654 * RtlAddRefActivationContext (NTDLL.@)
4656 void WINAPI RtlAddRefActivationContext( HANDLE handle )
4658 ACTIVATION_CONTEXT *actctx;
4660 if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
4664 /******************************************************************
4665 * RtlReleaseActivationContext (NTDLL.@)
4667 void WINAPI RtlReleaseActivationContext( HANDLE handle )
4669 ACTIVATION_CONTEXT *actctx;
4671 if ((actctx = check_actctx( handle ))) actctx_release( actctx );
4674 /******************************************************************
4675 * RtlZombifyActivationContext (NTDLL.@)
4677 * FIXME: function prototype might be wrong
4679 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle )
4681 FIXME("%p: stub\n", handle);
4682 return STATUS_NOT_IMPLEMENTED;
4685 /******************************************************************
4686 * RtlActivateActivationContext (NTDLL.@)
4688 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
4690 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4692 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) )))
4693 return STATUS_NO_MEMORY;
4695 frame->Previous = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4696 frame->ActivationContext = handle;
4697 frame->Flags = 0;
4698 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame;
4699 RtlAddRefActivationContext( handle );
4701 *cookie = (ULONG_PTR)frame;
4702 TRACE( "%p cookie=%lx\n", handle, *cookie );
4703 return STATUS_SUCCESS;
4707 /***********************************************************************
4708 * RtlDeactivateActivationContext (NTDLL.@)
4710 void WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
4712 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
4714 TRACE( "%x cookie=%lx\n", flags, cookie );
4716 /* find the right frame */
4717 top = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4718 for (frame = top; frame; frame = frame->Previous)
4719 if ((ULONG_PTR)frame == cookie) break;
4721 if (!frame)
4722 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
4724 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
4725 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
4727 /* pop everything up to and including frame */
4728 NtCurrentTeb()->ActivationContextStack.ActiveFrame = frame->Previous;
4730 while (top != NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4732 frame = top->Previous;
4733 RtlReleaseActivationContext( top->ActivationContext );
4734 RtlFreeHeap( GetProcessHeap(), 0, top );
4735 top = frame;
4740 /******************************************************************
4741 * RtlFreeThreadActivationContextStack (NTDLL.@)
4743 void WINAPI RtlFreeThreadActivationContextStack(void)
4745 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4747 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame;
4748 while (frame)
4750 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
4751 RtlReleaseActivationContext( frame->ActivationContext );
4752 RtlFreeHeap( GetProcessHeap(), 0, frame );
4753 frame = prev;
4755 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL;
4759 /******************************************************************
4760 * RtlGetActiveActivationContext (NTDLL.@)
4762 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle )
4764 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
4766 *handle = NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext;
4767 RtlAddRefActivationContext( *handle );
4769 else
4770 *handle = 0;
4772 return STATUS_SUCCESS;
4776 /******************************************************************
4777 * RtlIsActivationContextActive (NTDLL.@)
4779 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle )
4781 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
4783 for (frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; frame; frame = frame->Previous)
4784 if (frame->ActivationContext == handle) return TRUE;
4785 return FALSE;
4789 /***********************************************************************
4790 * RtlQueryInformationActivationContext (NTDLL.@)
4792 * Get information about an activation context.
4793 * FIXME: function signature/prototype may be wrong
4795 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
4796 ULONG class, PVOID buffer,
4797 SIZE_T bufsize, SIZE_T *retlen )
4799 ACTIVATION_CONTEXT *actctx;
4800 NTSTATUS status;
4802 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle,
4803 subinst, class, buffer, bufsize, retlen);
4805 if (retlen) *retlen = 0;
4806 if ((status = find_query_actctx( &handle, flags, class ))) return status;
4808 switch (class)
4810 case ActivationContextBasicInformation:
4812 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
4814 if (retlen) *retlen = sizeof(*info);
4815 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
4817 info->hActCtx = handle;
4818 info->dwFlags = 0; /* FIXME */
4819 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
4821 break;
4823 case ActivationContextDetailedInformation:
4825 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
4826 struct assembly *assembly = NULL;
4827 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
4828 LPWSTR ptr;
4830 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4832 if (actctx->num_assemblies) assembly = actctx->assemblies;
4834 if (assembly && assembly->manifest.info)
4835 manifest_len = strlenW(assembly->manifest.info) + 1;
4836 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
4837 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
4838 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
4840 if (retlen) *retlen = len;
4841 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
4843 acdi->dwFlags = 0;
4844 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
4845 acdi->ulAssemblyCount = actctx->num_assemblies;
4846 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
4847 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
4848 acdi->ulRootConfigurationPathType = actctx->config.type;
4849 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
4850 acdi->ulAppDirPathType = actctx->appdir.type;
4851 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
4852 ptr = (LPWSTR)(acdi + 1);
4853 if (manifest_len)
4855 acdi->lpRootManifestPath = ptr;
4856 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
4857 ptr += manifest_len;
4859 else acdi->lpRootManifestPath = NULL;
4860 if (config_len)
4862 acdi->lpRootConfigurationPath = ptr;
4863 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
4864 ptr += config_len;
4866 else acdi->lpRootConfigurationPath = NULL;
4867 if (appdir_len)
4869 acdi->lpAppDirPath = ptr;
4870 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
4872 else acdi->lpAppDirPath = NULL;
4874 break;
4876 case AssemblyDetailedInformationInActivationContext:
4878 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
4879 struct assembly *assembly;
4880 WCHAR *assembly_id;
4881 DWORD index;
4882 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
4883 LPWSTR ptr;
4885 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4886 if (!subinst) return STATUS_INVALID_PARAMETER;
4888 index = *(DWORD*)subinst;
4889 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
4891 assembly = &actctx->assemblies[index - 1];
4893 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
4894 id_len = strlenW(assembly_id) + 1;
4895 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
4897 if (assembly->manifest.info &&
4898 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
4899 path_len = strlenW(assembly->manifest.info) + 1;
4901 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
4903 if (retlen) *retlen = len;
4904 if (!buffer || bufsize < len)
4906 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4907 return STATUS_BUFFER_TOO_SMALL;
4910 afdi->ulFlags = 0; /* FIXME */
4911 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
4912 afdi->ulManifestPathType = assembly->manifest.type;
4913 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
4914 /* FIXME afdi->liManifestLastWriteTime = 0; */
4915 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
4916 afdi->ulPolicyPathLength = 0;
4917 /* FIXME afdi->liPolicyLastWriteTime = 0; */
4918 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
4919 afdi->ulManifestVersionMajor = 1;
4920 afdi->ulManifestVersionMinor = 0;
4921 afdi->ulPolicyVersionMajor = 0; /* FIXME */
4922 afdi->ulPolicyVersionMinor = 0; /* FIXME */
4923 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
4924 ptr = (LPWSTR)(afdi + 1);
4925 afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
4926 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
4927 ptr += id_len;
4928 if (path_len)
4930 afdi->lpAssemblyManifestPath = ptr;
4931 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
4932 ptr += path_len;
4933 } else afdi->lpAssemblyManifestPath = NULL;
4934 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
4935 if (ad_len)
4937 afdi->lpAssemblyDirectoryName = ptr;
4938 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
4940 else afdi->lpAssemblyDirectoryName = NULL;
4941 RtlFreeHeap( GetProcessHeap(), 0, assembly_id );
4943 break;
4945 case FileInformationInAssemblyOfAssemblyInActivationContext:
4947 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
4948 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
4949 struct assembly *assembly;
4950 struct dll_redirect *dll;
4951 SIZE_T len, dll_len = 0;
4952 LPWSTR ptr;
4954 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
4955 if (!acqi) return STATUS_INVALID_PARAMETER;
4957 if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
4958 return STATUS_INVALID_PARAMETER;
4959 assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
4961 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
4962 return STATUS_INVALID_PARAMETER;
4963 dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
4965 if (dll->name) dll_len = strlenW(dll->name) + 1;
4966 len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
4968 if (!buffer || bufsize < len)
4970 if (retlen) *retlen = len;
4971 return STATUS_BUFFER_TOO_SMALL;
4973 if (retlen) *retlen = 0; /* yes that's what native does !! */
4974 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
4975 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
4976 afdi->ulPathLength = 0; /* FIXME */
4977 ptr = (LPWSTR)(afdi + 1);
4978 if (dll_len)
4980 afdi->lpFileName = ptr;
4981 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
4982 } else afdi->lpFileName = NULL;
4983 afdi->lpFilePath = NULL; /* FIXME */
4985 break;
4987 default:
4988 FIXME( "class %u not implemented\n", class );
4989 return STATUS_NOT_IMPLEMENTED;
4991 return STATUS_SUCCESS;
4994 /***********************************************************************
4995 * RtlFindActivationContextSectionString (NTDLL.@)
4997 * Find information about a string in an activation context.
4998 * FIXME: function signature/prototype may be wrong
5000 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
5001 const UNICODE_STRING *section_name, PVOID ptr )
5003 PACTCTX_SECTION_KEYED_DATA data = ptr;
5004 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5006 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind,
5007 debugstr_us(section_name), data);
5009 if (guid)
5011 FIXME("expected guid == NULL\n");
5012 return STATUS_INVALID_PARAMETER;
5014 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5016 FIXME("unknown flags %08x\n", flags);
5017 return STATUS_INVALID_PARAMETER;
5019 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) ||
5020 !section_name || !section_name->Buffer)
5022 WARN("invalid parameter\n");
5023 return STATUS_INVALID_PARAMETER;
5026 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5028 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5029 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
5032 if (status != STATUS_SUCCESS)
5033 status = find_string( process_actctx, section_kind, section_name, flags, data );
5035 return status;
5038 /***********************************************************************
5039 * RtlFindActivationContextSectionGuid (NTDLL.@)
5041 * Find information about a GUID in an activation context.
5042 * FIXME: function signature/prototype may be wrong
5044 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind,
5045 const GUID *guid, void *ptr )
5047 ACTCTX_SECTION_KEYED_DATA *data = ptr;
5048 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
5050 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data);
5052 if (extguid)
5054 FIXME("expected extguid == NULL\n");
5055 return STATUS_INVALID_PARAMETER;
5058 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
5060 FIXME("unknown flags %08x\n", flags);
5061 return STATUS_INVALID_PARAMETER;
5064 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid)
5065 return STATUS_INVALID_PARAMETER;
5067 if (NtCurrentTeb()->ActivationContextStack.ActiveFrame)
5069 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStack.ActiveFrame->ActivationContext);
5070 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data );
5073 if (status != STATUS_SUCCESS)
5074 status = find_guid( process_actctx, section_kind, guid, flags, data );
5076 return status;