1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Runtime Library 4 * PURPOSE: Activation Context Support 5 * FILE: lib/rtl/actctx.c 6 * PROGRAMERS: 7 * Jon Griffiths 8 * Eric Pouech 9 * Jacek Caban for CodeWeavers 10 * Alexandre Julliard 11 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 12 * Samuel Serapión 13 */ 14 15 /* Based on Wine 3.2-37c98396 */ 16 #ifdef __REACTOS__ 17 18 #include <rtl.h> 19 #include <ntstrsafe.h> 20 #include <compat_undoc.h> 21 22 #include <wine/unicode.h> 23 #include "wine/exception.h" 24 #include "wine/debug.h" 25 26 WINE_DEFAULT_DEBUG_CHANNEL(actctx); 27 28 #define GetProcessHeap() RtlGetProcessHeap() 29 #define GetCurrentProcess() NtCurrentProcess() 30 #define DPRINT1 FIXME 31 #define DPRINT TRACE 32 #define FILE_END_OF_FILE_INFORMATION FILE_STANDARD_INFORMATION 33 #define FileEndOfFileInformation FileStandardInformation 34 #define RELATIVE_PATH RtlPathTypeRelative 35 #define windows_dir SharedUserData->NtSystemRoot 36 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) 37 #define wcsnicmp _wcsnicmp 38 #define swprintf _snwprintf 39 #define wcsicmp _wcsicmp 40 extern LPCSTR debugstr_us( const UNICODE_STRING *str ) DECLSPEC_HIDDEN; 41 42 #undef RT_MANIFEST 43 #undef CREATEPROCESS_MANIFEST_RESOURCE_ID 44 45 BOOLEAN RtlpNotAllowingMultipleActivation; 46 47 #endif // __REACTOS__ 48 49 #define ACTCTX_FLAGS_ALL (\ 50 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\ 51 ACTCTX_FLAG_LANGID_VALID |\ 52 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\ 53 ACTCTX_FLAG_RESOURCE_NAME_VALID |\ 54 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\ 55 ACTCTX_FLAG_APPLICATION_NAME_VALID |\ 56 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\ 57 ACTCTX_FLAG_HMODULE_VALID ) 58 59 #define ACTCTX_MAGIC 0xC07E3E11 60 #define STRSECTION_MAGIC 0x64487353 /* dHsS */ 61 #define GUIDSECTION_MAGIC 0x64487347 /* dHsG */ 62 63 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa) 64 65 /* we don't want to include winuser.h */ 66 #define RT_MANIFEST ((ULONG_PTR)24) 67 #define CREATEPROCESS_MANIFEST_RESOURCE_ID ((ULONG_PTR)1) 68 69 #ifndef __REACTOS__ // defined in oaidl.h 70 /* from oaidl.h */ 71 typedef enum tagLIBFLAGS { 72 LIBFLAG_FRESTRICTED = 0x1, 73 LIBFLAG_FCONTROL = 0x2, 74 LIBFLAG_FHIDDEN = 0x4, 75 LIBFLAG_FHASDISKIMAGE = 0x8 76 } LIBFLAGS; 77 78 /* from oleidl.idl */ 79 typedef enum tagOLEMISC 80 { 81 OLEMISC_RECOMPOSEONRESIZE = 0x1, 82 OLEMISC_ONLYICONIC = 0x2, 83 OLEMISC_INSERTNOTREPLACE = 0x4, 84 OLEMISC_STATIC = 0x8, 85 OLEMISC_CANTLINKINSIDE = 0x10, 86 OLEMISC_CANLINKBYOLE1 = 0x20, 87 OLEMISC_ISLINKOBJECT = 0x40, 88 OLEMISC_INSIDEOUT = 0x80, 89 OLEMISC_ACTIVATEWHENVISIBLE = 0x100, 90 OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200, 91 OLEMISC_INVISIBLEATRUNTIME = 0x400, 92 OLEMISC_ALWAYSRUN = 0x800, 93 OLEMISC_ACTSLIKEBUTTON = 0x1000, 94 OLEMISC_ACTSLIKELABEL = 0x2000, 95 OLEMISC_NOUIACTIVATE = 0x4000, 96 OLEMISC_ALIGNABLE = 0x8000, 97 OLEMISC_SIMPLEFRAME = 0x10000, 98 OLEMISC_SETCLIENTSITEFIRST = 0x20000, 99 OLEMISC_IMEMODE = 0x40000, 100 OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000, 101 OLEMISC_WANTSTOMENUMERGE = 0x100000, 102 OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000 103 } OLEMISC; 104 #endif // !__REACTOS__ 105 106 #define MAX_NAMESPACES 64 107 108 typedef struct 109 { 110 const WCHAR *ptr; 111 unsigned int len; 112 } xmlstr_t; 113 114 struct xml_elem 115 { 116 xmlstr_t name; 117 xmlstr_t ns; 118 int ns_pos; 119 }; 120 121 struct xml_attr 122 { 123 xmlstr_t name; 124 xmlstr_t value; 125 }; 126 127 typedef struct 128 { 129 const WCHAR *ptr; 130 const WCHAR *end; 131 struct xml_attr namespaces[MAX_NAMESPACES]; 132 int ns_pos; 133 BOOL error; 134 } xmlbuf_t; 135 136 struct file_info 137 { 138 ULONG type; 139 WCHAR *info; 140 }; 141 142 struct assembly_version 143 { 144 USHORT major; 145 USHORT minor; 146 USHORT build; 147 USHORT revision; 148 }; 149 150 struct assembly_identity 151 { 152 WCHAR *name; 153 WCHAR *arch; 154 WCHAR *public_key; 155 WCHAR *language; 156 WCHAR *type; 157 struct assembly_version version; 158 BOOL optional; 159 BOOL delayed; 160 }; 161 162 struct strsection_header 163 { 164 DWORD magic; 165 ULONG size; 166 DWORD unk1[3]; 167 ULONG count; 168 ULONG index_offset; 169 DWORD unk2[2]; 170 ULONG global_offset; 171 ULONG global_len; 172 }; 173 174 struct string_index 175 { 176 ULONG hash; /* key string hash */ 177 ULONG name_offset; 178 ULONG name_len; 179 ULONG data_offset; /* redirect data offset */ 180 ULONG data_len; 181 ULONG rosterindex; 182 }; 183 184 struct guidsection_header 185 { 186 DWORD magic; 187 ULONG size; 188 DWORD unk[3]; 189 ULONG count; 190 ULONG index_offset; 191 DWORD unk2; 192 ULONG names_offset; 193 ULONG names_len; 194 }; 195 196 struct guid_index 197 { 198 GUID guid; 199 ULONG data_offset; 200 ULONG data_len; 201 ULONG rosterindex; 202 }; 203 204 struct wndclass_redirect_data 205 { 206 ULONG size; 207 DWORD res; 208 ULONG name_len; 209 ULONG name_offset; /* versioned name offset */ 210 ULONG module_len; 211 ULONG module_offset;/* container name offset */ 212 }; 213 214 struct dllredirect_data 215 { 216 ULONG size; 217 ULONG unk; 218 DWORD res[3]; 219 }; 220 221 struct tlibredirect_data 222 { 223 ULONG size; 224 DWORD res; 225 ULONG name_len; 226 ULONG name_offset; 227 LANGID langid; 228 WORD flags; 229 ULONG help_len; 230 ULONG help_offset; 231 WORD major_version; 232 WORD minor_version; 233 }; 234 235 enum comclass_threadingmodel 236 { 237 ThreadingModel_Apartment = 1, 238 ThreadingModel_Free = 2, 239 ThreadingModel_No = 3, 240 ThreadingModel_Both = 4, 241 ThreadingModel_Neutral = 5 242 }; 243 244 enum comclass_miscfields 245 { 246 MiscStatus = 1, 247 MiscStatusIcon = 2, 248 MiscStatusContent = 4, 249 MiscStatusThumbnail = 8, 250 MiscStatusDocPrint = 16 251 }; 252 253 struct comclassredirect_data 254 { 255 ULONG size; 256 ULONG flags; 257 DWORD model; 258 GUID clsid; 259 GUID alias; 260 GUID clsid2; 261 GUID tlbid; 262 ULONG name_len; 263 ULONG name_offset; 264 ULONG progid_len; 265 ULONG progid_offset; 266 ULONG clrdata_len; 267 ULONG clrdata_offset; 268 DWORD miscstatus; 269 DWORD miscstatuscontent; 270 DWORD miscstatusthumbnail; 271 DWORD miscstatusicon; 272 DWORD miscstatusdocprint; 273 }; 274 275 enum ifaceps_mask 276 { 277 NumMethods = 1, 278 BaseIface = 2 279 }; 280 281 struct ifacepsredirect_data 282 { 283 ULONG size; 284 DWORD mask; 285 GUID iid; 286 ULONG nummethods; 287 GUID tlbid; 288 GUID base; 289 ULONG name_len; 290 ULONG name_offset; 291 }; 292 293 struct clrsurrogate_data 294 { 295 ULONG size; 296 DWORD res; 297 GUID clsid; 298 ULONG version_offset; 299 ULONG version_len; 300 ULONG name_offset; 301 ULONG name_len; 302 }; 303 304 struct clrclass_data 305 { 306 ULONG size; 307 DWORD res[2]; 308 ULONG module_len; 309 ULONG module_offset; 310 ULONG name_len; 311 ULONG name_offset; 312 ULONG version_len; 313 ULONG version_offset; 314 DWORD res2[2]; 315 }; 316 317 struct progidredirect_data 318 { 319 ULONG size; 320 DWORD reserved; 321 ULONG clsid_offset; 322 }; 323 324 /* 325 326 Sections structure. 327 328 Sections are accessible by string or guid key, that defines two types of sections. 329 All sections of each type have same magic value and header structure, index 330 data could be of two possible types too. So every string based section uses 331 the same index format, same applies to guid sections - they share same guid index 332 format. 333 334 - window class redirection section is a plain buffer with following format: 335 336 <section header> 337 <index[]> 338 <data[]> --- <original name> 339 <redirect data> 340 <versioned name> 341 <module name> 342 343 Header is fixed length structure - struct strsection_header, 344 contains redirected classes count; 345 346 Index is an array of fixed length index records, each record is 347 struct string_index. 348 349 All strings in data itself are WCHAR, null terminated, 4-bytes aligned. 350 351 Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data), 352 others are relative to section itself. 353 354 - dll redirect section format: 355 356 <section header> 357 <index[]> 358 <data[]> --- <dll name> 359 <data> 360 361 This section doesn't seem to carry any payload data except dll names. 362 363 - typelib section format: 364 365 <section header> 366 <module names[]> 367 <index[]> 368 <data[]> --- <data> 369 <helpstring> 370 371 Header is fixed length, index is an array of fixed length 'struct guid_index'. 372 All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is 373 4-bytes aligned as a whole. 374 375 Module name offsets are relative to section, helpstring offset is relative to data 376 structure itself. 377 378 - comclass section format: 379 380 <section header> 381 <module names[]> 382 <index[]> 383 <data[]> --- <data> --- <data> 384 <progid> <clrdata> 385 <name> 386 <version> 387 <progid> 388 389 This section uses two index records per comclass, one entry contains original guid 390 as specified by context, another one has a generated guid. Index and strings handling 391 is similar to typelib sections. 392 393 For CLR classes additional data is stored after main COM class data, it contains 394 class name and runtime version string, see 'struct clrclass_data'. 395 396 Module name offsets are relative to section, progid offset is relative to data 397 structure itself. 398 399 - COM interface section format: 400 401 <section header> 402 <index[]> 403 <data[]> --- <data> 404 <name> 405 406 Interface section contains data for proxy/stubs and external proxy/stubs. External 407 ones are defined at assembly level, so this section has no module information. 408 All records are indexed with 'iid' value from manifest. There an exception for 409 external variants - if 'proxyStubClsid32' is specified, it's stored as iid in 410 redirect data, but index is still 'iid' from manifest. 411 412 Interface name offset is relative to data structure itself. 413 414 - CLR surrogates section format: 415 416 <section header> 417 <index[]> 418 <data[]> --- <data> 419 <name> 420 <version> 421 422 There's nothing special about this section, same way to store strings is used, 423 no modules part as it belongs to assembly level, not a file. 424 425 - ProgID section format: 426 427 <section header> 428 <guids[]> 429 <index[]> 430 <data[]> --- <progid> 431 <data> 432 433 This sections uses generated alias guids from COM server section. This way 434 ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string 435 is stored too, aligned. 436 */ 437 438 struct progids 439 { 440 WCHAR **progids; 441 unsigned int num; 442 unsigned int allocated; 443 }; 444 445 struct entity 446 { 447 DWORD kind; 448 union 449 { 450 struct 451 { 452 WCHAR *tlbid; 453 WCHAR *helpdir; 454 WORD flags; 455 WORD major; 456 WORD minor; 457 } typelib; 458 struct 459 { 460 WCHAR *clsid; 461 WCHAR *tlbid; 462 WCHAR *progid; 463 WCHAR *name; /* clrClass: class name */ 464 WCHAR *version; /* clrClass: CLR runtime version */ 465 DWORD model; 466 DWORD miscstatus; 467 DWORD miscstatuscontent; 468 DWORD miscstatusthumbnail; 469 DWORD miscstatusicon; 470 DWORD miscstatusdocprint; 471 struct progids progids; 472 } comclass; 473 struct { 474 WCHAR *iid; 475 WCHAR *base; 476 WCHAR *tlib; 477 WCHAR *name; 478 WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */ 479 DWORD mask; 480 ULONG nummethods; 481 } ifaceps; 482 struct 483 { 484 WCHAR *name; 485 BOOL versioned; 486 } class; 487 struct 488 { 489 WCHAR *name; 490 WCHAR *clsid; 491 WCHAR *version; 492 } clrsurrogate; 493 struct 494 { 495 WCHAR *name; 496 WCHAR *value; 497 WCHAR *ns; 498 } settings; 499 } u; 500 }; 501 502 struct entity_array 503 { 504 struct entity *base; 505 unsigned int num; 506 unsigned int allocated; 507 }; 508 509 struct dll_redirect 510 { 511 WCHAR *name; 512 WCHAR *hash; 513 struct entity_array entities; 514 }; 515 516 enum assembly_type 517 { 518 APPLICATION_MANIFEST, 519 ASSEMBLY_MANIFEST, 520 ASSEMBLY_SHARED_MANIFEST, 521 }; 522 523 struct assembly 524 { 525 enum assembly_type type; 526 struct assembly_identity id; 527 struct file_info manifest; 528 WCHAR *directory; 529 BOOL no_inherit; 530 struct dll_redirect *dlls; 531 unsigned int num_dlls; 532 unsigned int allocated_dlls; 533 struct entity_array entities; 534 COMPATIBILITY_CONTEXT_ELEMENT *compat_contexts; 535 ULONG num_compat_contexts; 536 ACTCTX_REQUESTED_RUN_LEVEL run_level; 537 ULONG ui_access; 538 }; 539 540 enum context_sections 541 { 542 WINDOWCLASS_SECTION = 1, 543 DLLREDIRECT_SECTION = 2, 544 TLIBREDIRECT_SECTION = 4, 545 SERVERREDIRECT_SECTION = 8, 546 IFACEREDIRECT_SECTION = 16, 547 CLRSURROGATES_SECTION = 32, 548 PROGIDREDIRECT_SECTION = 64 549 }; 550 551 #ifdef __REACTOS__ 552 typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY 553 { 554 ULONG Flags; 555 UNICODE_STRING DosPath; 556 HANDLE Handle; 557 } ASSEMBLY_STORAGE_MAP_ENTRY, *PASSEMBLY_STORAGE_MAP_ENTRY; 558 559 typedef struct _ASSEMBLY_STORAGE_MAP 560 { 561 ULONG Flags; 562 ULONG AssemblyCount; 563 PASSEMBLY_STORAGE_MAP_ENTRY *AssemblyArray; 564 } ASSEMBLY_STORAGE_MAP, *PASSEMBLY_STORAGE_MAP; 565 #endif // __REACTOS__ 566 567 typedef struct _ACTIVATION_CONTEXT 568 { 569 ULONG magic; 570 LONG ref_count; 571 #ifdef __REACTOS__ 572 ULONG Flags; 573 LIST_ENTRY Links; 574 PACTIVATION_CONTEXT_DATA ActivationContextData; 575 PVOID NotificationRoutine; 576 PVOID NotificationContext; 577 ULONG SentNotifications[8]; 578 ULONG DisabledNotifications[8]; 579 ASSEMBLY_STORAGE_MAP StorageMap; 580 PASSEMBLY_STORAGE_MAP_ENTRY InlineStorageMapEntries; 581 ULONG StackTraceIndex; 582 PVOID StackTraces[4][4]; 583 #endif // __REACTOS__ 584 struct file_info config; 585 struct file_info appdir; 586 struct assembly *assemblies; 587 unsigned int num_assemblies; 588 unsigned int allocated_assemblies; 589 /* section data */ 590 DWORD sections; 591 struct strsection_header *wndclass_section; 592 struct strsection_header *dllredirect_section; 593 struct strsection_header *progid_section; 594 struct guidsection_header *tlib_section; 595 struct guidsection_header *comserver_section; 596 struct guidsection_header *ifaceps_section; 597 struct guidsection_header *clrsurrogate_section; 598 } ACTIVATION_CONTEXT; 599 600 struct actctx_loader 601 { 602 ACTIVATION_CONTEXT *actctx; 603 struct assembly_identity *dependencies; 604 unsigned int num_dependencies; 605 unsigned int allocated_dependencies; 606 }; 607 608 static const xmlstr_t empty_xmlstr; 609 610 #ifdef __i386__ 611 static const WCHAR current_archW[] = {'x','8','6',0}; 612 #elif defined __x86_64__ 613 static const WCHAR current_archW[] = {'a','m','d','6','4',0}; 614 #elif defined __arm__ 615 static const WCHAR current_archW[] = {'a','r','m',0}; 616 #elif defined __aarch64__ 617 static const WCHAR current_archW[] = {'a','r','m','6','4',0}; 618 #else 619 static const WCHAR current_archW[] = {'n','o','n','e',0}; 620 #endif 621 622 static const WCHAR asmv1W[] = {'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}; 623 static const WCHAR asmv2W[] = {'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}; 624 static const WCHAR asmv3W[] = {'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}; 625 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0}; 626 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0}; 627 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0}; 628 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0}; 629 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0}; 630 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0}; 631 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}; 632 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}; 633 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0}; 634 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0}; 635 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0}; 636 static const WCHAR fileW[] = {'f','i','l','e',0}; 637 static const WCHAR hashW[] = {'h','a','s','h',0}; 638 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0}; 639 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0}; 640 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0}; 641 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0}; 642 643 static const WCHAR clsidW[] = {'c','l','s','i','d',0}; 644 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0}; 645 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0}; 646 static const WCHAR iidW[] = {'i','i','d',0}; 647 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0}; 648 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0}; 649 static const WCHAR g_nameW[] = {'n','a','m','e',0}; 650 static const WCHAR neutralW[] = {'n','e','u','t','r','a','l',0}; 651 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0}; 652 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0}; 653 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0}; 654 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}; 655 static const WCHAR progidW[] = {'p','r','o','g','i','d',0}; 656 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; 657 static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; 658 static const WCHAR tlbidW[] = {'t','l','b','i','d',0}; 659 static const WCHAR typeW[] = {'t','y','p','e',0}; 660 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; 661 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0}; 662 static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0}; 663 static const WCHAR yesW[] = {'y','e','s',0}; 664 static const WCHAR noW[] = {'n','o',0}; 665 static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0}; 666 static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0}; 667 static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0}; 668 static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0}; 669 static const WCHAR flagsW[] = {'f','l','a','g','s',0}; 670 static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0}; 671 static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0}; 672 static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0}; 673 static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0}; 674 static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0}; 675 static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0}; 676 static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0}; 677 static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; 678 static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0}; 679 static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0}; 680 static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0}; 681 682 static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0}; 683 static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0}; 684 static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0}; 685 static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0}; 686 static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0}; 687 static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0}; 688 static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0}; 689 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}; 690 static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0}; 691 static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0}; 692 static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0}; 693 static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0}; 694 static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0}; 695 static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0}; 696 static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0}; 697 static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0}; 698 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}; 699 static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0}; 700 static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0}; 701 static const WCHAR staticW[] = {'s','t','a','t','i','c',0}; 702 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}; 703 static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0}; 704 705 static const WCHAR compatibilityW[] = {'c','o','m','p','a','t','i','b','i','l','i','t','y',0}; 706 static const WCHAR compatibilityNSW[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','c','o','m','p','a','t','i','b','i','l','i','t','y','.','v','1',0}; 707 static const WCHAR applicationW[] = {'a','p','p','l','i','c','a','t','i','o','n',0}; 708 static const WCHAR supportedOSW[] = {'s','u','p','p','o','r','t','e','d','O','S',0}; 709 static const WCHAR IdW[] = {'I','d',0}; 710 static const WCHAR requestedExecutionLevelW[] = {'r','e','q','u','e','s','t','e','d','E','x','e','c','u','t','i','o','n','L','e','v','e','l',0}; 711 static const WCHAR requestedPrivilegesW[] = {'r','e','q','u','e','s','t','e','d','P','r','i','v','i','l','e','g','e','s',0}; 712 static const WCHAR securityW[] = {'s','e','c','u','r','i','t','y',0}; 713 static const WCHAR trustInfoW[] = {'t','r','u','s','t','I','n','f','o',0}; 714 static const WCHAR windowsSettingsW[] = {'w','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 715 static const WCHAR autoElevateW[] = {'a','u','t','o','E','l','e','v','a','t','e',0}; 716 static const WCHAR disableThemingW[] = {'d','i','s','a','b','l','e','T','h','e','m','i','n','g',0}; 717 static const WCHAR disableWindowFilteringW[] = {'d','i','s','a','b','l','e','W','i','n','d','o','w','F','i','l','t','e','r','i','n','g',0}; 718 static const WCHAR windowsSettings2005NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','0','5','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 719 static const WCHAR windowsSettings2011NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','1','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 720 static const WCHAR windowsSettings2016NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','6','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 721 static const WCHAR windowsSettings2017NSW[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','S','M','I','/','2','0','1','7','/','W','i','n','d','o','w','s','S','e','t','t','i','n','g','s',0}; 722 static const WCHAR dpiAwareW[] = {'d','p','i','A','w','a','r','e',0}; 723 static const WCHAR dpiAwarenessW[] = {'d','p','i','A','w','a','r','e','n','e','s','s',0}; 724 static const WCHAR gdiScalingW[] = {'g','d','i','S','c','a','l','i','n','g',0}; 725 static const WCHAR highResolutionScrollingAwareW[] = {'h','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0}; 726 static const WCHAR longPathAwareW[] = {'l','o','n','g','P','a','t','h','A','w','a','r','e',0}; 727 static const WCHAR magicFutureSettingW[] = {'m','a','g','i','c','F','u','t','u','r','e','S','e','t','t','i','n','g',0}; 728 static const WCHAR printerDriverIsolationW[] = {'p','r','i','n','t','e','r','D','r','i','v','e','r','I','s','o','l','a','t','i','o','n',0}; 729 static const WCHAR ultraHighResolutionScrollingAwareW[] = {'u','l','t','r','a','H','i','g','h','R','e','s','o','l','u','t','i','o','n','S','c','r','o','l','l','i','n','g','A','w','a','r','e',0}; 730 731 struct olemisc_entry 732 { 733 const WCHAR *name; 734 OLEMISC value; 735 }; 736 737 static const struct olemisc_entry olemisc_values[] = 738 { 739 { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE }, 740 { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON }, 741 { actslikelabelW, OLEMISC_ACTSLIKELABEL }, 742 { alignableW, OLEMISC_ALIGNABLE }, 743 { alwaysrunW, OLEMISC_ALWAYSRUN }, 744 { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 }, 745 { cantlinkinsideW, OLEMISC_CANTLINKINSIDE }, 746 { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE }, 747 { imemodeW, OLEMISC_IMEMODE }, 748 { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE }, 749 { insideoutW, OLEMISC_INSIDEOUT }, 750 { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME }, 751 { islinkobjectW, OLEMISC_ISLINKOBJECT }, 752 { nouiactivateW, OLEMISC_NOUIACTIVATE }, 753 { onlyiconicW, OLEMISC_ONLYICONIC }, 754 { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE }, 755 { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT }, 756 { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST }, 757 { simpleframeW, OLEMISC_SIMPLEFRAME }, 758 { staticW, OLEMISC_STATIC }, 759 { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO }, 760 { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE } 761 }; 762 763 static const WCHAR g_xmlW[] = {'?','x','m','l',0}; 764 765 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; 766 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 767 static const WCHAR wildcardW[] = {'*',0}; 768 769 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 }; 770 static ACTIVATION_CONTEXT *process_actctx = &system_actctx; 771 static ACTIVATION_CONTEXT *implicit_actctx = &system_actctx; 772 773 static WCHAR *strdupW(const WCHAR* str) 774 { 775 WCHAR* ptr; 776 777 if (!(ptr = RtlAllocateHeap(GetProcessHeap(), 0, (wcslen(str) + 1) * sizeof(WCHAR)))) 778 return NULL; 779 return wcscpy(ptr, str); 780 } 781 782 static WCHAR *xmlstrdupW(const xmlstr_t* str) 783 { 784 WCHAR *strW; 785 786 if ((strW = RtlAllocateHeap(GetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR)))) 787 { 788 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) ); 789 strW[str->len] = 0; 790 } 791 return strW; 792 } 793 794 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str) 795 { 796 return !wcsncmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 797 } 798 799 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str) 800 { 801 return !wcsnicmp(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 802 } 803 804 static BOOL xml_attr_cmp( const struct xml_attr *attr, const WCHAR *str ) 805 { 806 return xmlstr_cmp( &attr->name, str ); 807 } 808 809 static BOOL xml_name_cmp( const struct xml_elem *elem1, const struct xml_elem *elem2 ) 810 { 811 return (elem1->name.len == elem2->name.len && 812 elem1->ns.len == elem2->ns.len && 813 !wcsncmp( elem1->name.ptr, elem2->name.ptr, elem1->name.len ) && 814 !wcsncmp( elem1->ns.ptr, elem2->ns.ptr, elem1->ns.len )); 815 } 816 817 static inline BOOL xml_elem_cmp(const struct xml_elem *elem, const WCHAR *str, const WCHAR *namespace) 818 { 819 if (!xmlstr_cmp( &elem->name, str )) return FALSE; 820 if (xmlstr_cmp( &elem->ns, namespace )) return TRUE; 821 if (!wcscmp( namespace, asmv1W )) 822 { 823 if (xmlstr_cmp( &elem->ns, asmv2W )) return TRUE; 824 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE; 825 } 826 else if (!wcscmp( namespace, asmv2W )) 827 { 828 if (xmlstr_cmp( &elem->ns, asmv3W )) return TRUE; 829 } 830 return FALSE; 831 } 832 833 static inline BOOL isxmlspace( WCHAR ch ) 834 { 835 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t'); 836 } 837 838 static inline const char* debugstr_xmlstr(const xmlstr_t* str) 839 { 840 return debugstr_wn(str->ptr, str->len); 841 } 842 843 static inline const char *debugstr_xml_elem( const struct xml_elem *elem ) 844 { 845 return wine_dbg_sprintf( "%s ns %s", debugstr_wn( elem->name.ptr, elem->name.len ), 846 debugstr_wn( elem->ns.ptr, elem->ns.len )); 847 } 848 849 static inline const char *debugstr_xml_attr( const struct xml_attr *attr ) 850 { 851 return wine_dbg_sprintf( "%s=%s", debugstr_wn( attr->name.ptr, attr->name.len ), 852 debugstr_wn( attr->value.ptr, attr->value.len )); 853 } 854 855 static inline const char* debugstr_version(const struct assembly_version *ver) 856 { 857 return wine_dbg_sprintf("%u.%u.%u.%u", ver->major, ver->minor, ver->build, ver->revision); 858 } 859 860 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len ) 861 { 862 NTSTATUS status; 863 ULONG_PTR magic; 864 LDR_DATA_TABLE_ENTRY *pldr; 865 866 LdrLockLoaderLock(0, NULL, &magic); 867 status = LdrFindEntryForAddress( module, &pldr ); 868 if (status == STATUS_SUCCESS) 869 { 870 if ((str->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, 871 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) ))) 872 { 873 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) ); 874 str->Length = pldr->FullDllName.Length; 875 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR); 876 } 877 else status = STATUS_NO_MEMORY; 878 } 879 LdrUnlockLoaderLock(0, magic); 880 return status; 881 } 882 883 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at) 884 { 885 struct assembly *assembly; 886 887 DPRINT("add_assembly() actctx %p, activeframe ??\n", actctx); 888 889 if (actctx->num_assemblies == actctx->allocated_assemblies) 890 { 891 void *ptr; 892 unsigned int new_count; 893 if (actctx->assemblies) 894 { 895 new_count = actctx->allocated_assemblies * 2; 896 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, 897 actctx->assemblies, new_count * sizeof(*assembly) ); 898 } 899 else 900 { 901 new_count = 4; 902 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) ); 903 } 904 if (!ptr) return NULL; 905 actctx->assemblies = ptr; 906 actctx->allocated_assemblies = new_count; 907 } 908 909 assembly = &actctx->assemblies[actctx->num_assemblies++]; 910 assembly->type = at; 911 return assembly; 912 } 913 914 static struct dll_redirect* add_dll_redirect(struct assembly* assembly) 915 { 916 DPRINT("add_dll_redirect() to assembly %p, num_dlls %d\n", assembly, assembly->allocated_dlls); 917 918 if (assembly->num_dlls == assembly->allocated_dlls) 919 { 920 void *ptr; 921 unsigned int new_count; 922 if (assembly->dlls) 923 { 924 new_count = assembly->allocated_dlls * 2; 925 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, 926 assembly->dlls, new_count * sizeof(*assembly->dlls) ); 927 } 928 else 929 { 930 new_count = 4; 931 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) ); 932 } 933 if (!ptr) return NULL; 934 assembly->dlls = ptr; 935 assembly->allocated_dlls = new_count; 936 } 937 return &assembly->dlls[assembly->num_dlls++]; 938 } 939 940 static PCOMPATIBILITY_CONTEXT_ELEMENT add_compat_context(struct assembly* assembly) 941 { 942 void *ptr; 943 if (assembly->num_compat_contexts) 944 { 945 unsigned int new_count = assembly->num_compat_contexts + 1; 946 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, 947 assembly->compat_contexts, 948 new_count * sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); 949 } 950 else 951 { 952 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMPATIBILITY_CONTEXT_ELEMENT) ); 953 } 954 if (!ptr) return NULL; 955 assembly->compat_contexts = ptr; 956 return &assembly->compat_contexts[assembly->num_compat_contexts++]; 957 } 958 959 static void free_assembly_identity(struct assembly_identity *ai) 960 { 961 RtlFreeHeap( GetProcessHeap(), 0, ai->name ); 962 RtlFreeHeap( GetProcessHeap(), 0, ai->arch ); 963 RtlFreeHeap( GetProcessHeap(), 0, ai->public_key ); 964 RtlFreeHeap( GetProcessHeap(), 0, ai->language ); 965 RtlFreeHeap( GetProcessHeap(), 0, ai->type ); 966 } 967 968 static struct entity* add_entity(struct entity_array *array, DWORD kind) 969 { 970 struct entity* entity; 971 972 if (array->num == array->allocated) 973 { 974 void *ptr; 975 unsigned int new_count; 976 if (array->base) 977 { 978 new_count = array->allocated * 2; 979 ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, 980 array->base, new_count * sizeof(*array->base) ); 981 } 982 else 983 { 984 new_count = 4; 985 ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) ); 986 } 987 if (!ptr) return NULL; 988 array->base = ptr; 989 array->allocated = new_count; 990 } 991 entity = &array->base[array->num++]; 992 entity->kind = kind; 993 return entity; 994 } 995 996 static void free_entity_array(struct entity_array *array) 997 { 998 unsigned int i, j; 999 for (i = 0; i < array->num; i++) 1000 { 1001 struct entity *entity = &array->base[i]; 1002 switch (entity->kind) 1003 { 1004 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 1005 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid); 1006 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid); 1007 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid); 1008 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.name); 1009 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.version); 1010 for (j = 0; j < entity->u.comclass.progids.num; j++) 1011 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids[j]); 1012 RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progids.progids); 1013 break; 1014 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 1015 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.iid); 1016 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.base); 1017 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.ps32); 1018 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.name); 1019 RtlFreeHeap(GetProcessHeap(), 0, entity->u.ifaceps.tlib); 1020 break; 1021 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 1022 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.tlbid); 1023 RtlFreeHeap(GetProcessHeap(), 0, entity->u.typelib.helpdir); 1024 break; 1025 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 1026 RtlFreeHeap(GetProcessHeap(), 0, entity->u.class.name); 1027 break; 1028 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 1029 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.name); 1030 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.clsid); 1031 RtlFreeHeap(GetProcessHeap(), 0, entity->u.clrsurrogate.version); 1032 break; 1033 case ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS: 1034 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.name); 1035 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.value); 1036 RtlFreeHeap(GetProcessHeap(), 0, entity->u.settings.ns); 1037 break; 1038 default: 1039 FIXME("Unknown entity kind %d\n", entity->kind); 1040 } 1041 } 1042 RtlFreeHeap( GetProcessHeap(), 0, array->base ); 1043 } 1044 1045 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 ) 1046 { 1047 if (!str1) return !str2; 1048 return str2 && !RtlCompareUnicodeStrings( str1, wcslen(str1), str2, wcslen(str2), TRUE ); 1049 } 1050 1051 static BOOL is_matching_identity( const struct assembly_identity *id1, 1052 const struct assembly_identity *id2 ) 1053 { 1054 if (!is_matching_string( id1->name, id2->name )) return FALSE; 1055 if (!is_matching_string( id1->arch, id2->arch )) return FALSE; 1056 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE; 1057 1058 if (id1->language && id2->language && !is_matching_string( id1->language, id2->language )) 1059 { 1060 if (wcscmp( wildcardW, id1->language ) && wcscmp( wildcardW, id2->language )) 1061 return FALSE; 1062 } 1063 if (id1->version.major != id2->version.major) return FALSE; 1064 if (id1->version.minor != id2->version.minor) return FALSE; 1065 if (id1->version.build > id2->version.build) return FALSE; 1066 if (id1->version.build == id2->version.build && 1067 id1->version.revision > id2->version.revision) return FALSE; 1068 return TRUE; 1069 } 1070 1071 static BOOL add_dependent_assembly_id(struct actctx_loader* acl, 1072 struct assembly_identity* ai) 1073 { 1074 unsigned int i; 1075 1076 /* check if we already have that assembly */ 1077 1078 for (i = 0; i < acl->actctx->num_assemblies; i++) 1079 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id )) 1080 { 1081 TRACE( "reusing existing assembly for %s arch %s version %u.%u.%u.%u\n", 1082 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor, 1083 ai->version.build, ai->version.revision ); 1084 return TRUE; 1085 } 1086 1087 for (i = 0; i < acl->num_dependencies; i++) 1088 if (is_matching_identity( ai, &acl->dependencies[i] )) 1089 { 1090 TRACE( "reusing existing dependency for %s arch %s version %u.%u.%u.%u\n", 1091 debugstr_w(ai->name), debugstr_w(ai->arch), ai->version.major, ai->version.minor, 1092 ai->version.build, ai->version.revision ); 1093 return TRUE; 1094 } 1095 1096 if (acl->num_dependencies == acl->allocated_dependencies) 1097 { 1098 void *ptr; 1099 unsigned int new_count; 1100 if (acl->dependencies) 1101 { 1102 new_count = acl->allocated_dependencies * 2; 1103 ptr = RtlReAllocateHeap(GetProcessHeap(), 0, acl->dependencies, 1104 new_count * sizeof(acl->dependencies[0])); 1105 } 1106 else 1107 { 1108 new_count = 4; 1109 ptr = RtlAllocateHeap(GetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0])); 1110 } 1111 if (!ptr) return FALSE; 1112 acl->dependencies = ptr; 1113 acl->allocated_dependencies = new_count; 1114 } 1115 acl->dependencies[acl->num_dependencies++] = *ai; 1116 1117 return TRUE; 1118 } 1119 1120 static void free_depend_manifests(struct actctx_loader* acl) 1121 { 1122 unsigned int i; 1123 for (i = 0; i < acl->num_dependencies; i++) 1124 free_assembly_identity(&acl->dependencies[i]); 1125 RtlFreeHeap(GetProcessHeap(), 0, acl->dependencies); 1126 } 1127 1128 static WCHAR *build_assembly_dir(struct assembly_identity* ai) 1129 { 1130 static const WCHAR undW[] = {'_',0}; 1131 static const WCHAR noneW[] = {'n','o','n','e',0}; 1132 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0}; 1133 1134 const WCHAR *arch = ai->arch ? ai->arch : noneW; 1135 const WCHAR *key = ai->public_key ? ai->public_key : noneW; 1136 const WCHAR *lang = ai->language ? ai->language : noneW; 1137 const WCHAR *name = ai->name ? ai->name : noneW; 1138 SIZE_T size = (wcslen(arch) + 1 + wcslen(name) + 1 + wcslen(key) + 24 + 1 + 1139 wcslen(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW); 1140 WCHAR *ret; 1141 1142 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return NULL; 1143 1144 wcscpy( ret, arch ); 1145 wcscat( ret, undW ); 1146 wcscat( ret, name ); 1147 wcscat( ret, undW ); 1148 wcscat( ret, key ); 1149 wcscat( ret, undW ); 1150 swprintf( ret + wcslen(ret), size - wcslen(ret), version_formatW, 1151 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 1152 wcscat( ret, undW ); 1153 wcscat( ret, lang ); 1154 wcscat( ret, undW ); 1155 wcscat( ret, mskeyW ); 1156 return ret; 1157 } 1158 1159 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str ) 1160 { 1161 WCHAR *p = buffer; 1162 1163 if (!str) return; 1164 wcscat( buffer, prefix ); 1165 p += wcslen(p); 1166 *p++ = '"'; 1167 wcscpy( p, str ); 1168 p += wcslen(p); 1169 *p++ = '"'; 1170 *p = 0; 1171 } 1172 1173 static WCHAR *build_assembly_id( const struct assembly_identity *ai ) 1174 { 1175 static const WCHAR archW[] = 1176 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0}; 1177 static const WCHAR public_keyW[] = 1178 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0}; 1179 static const WCHAR typeW2[] = 1180 {',','t','y','p','e','=',0}; 1181 static const WCHAR versionW2[] = 1182 {',','v','e','r','s','i','o','n','=',0}; 1183 1184 WCHAR version[64], *ret; 1185 SIZE_T size = 0; 1186 1187 swprintf( version, ARRAY_SIZE(version), version_formatW, 1188 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 1189 if (ai->name) size += wcslen(ai->name) * sizeof(WCHAR); 1190 if (ai->arch) size += wcslen(archW) + wcslen(ai->arch) + 2; 1191 if (ai->public_key) size += wcslen(public_keyW) + wcslen(ai->public_key) + 2; 1192 if (ai->type) size += wcslen(typeW2) + wcslen(ai->type) + 2; 1193 size += wcslen(versionW2) + wcslen(version) + 2; 1194 1195 if (!(ret = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) ))) 1196 return NULL; 1197 1198 if (ai->name) wcscpy( ret, ai->name ); 1199 else *ret = 0; 1200 append_string( ret, archW, ai->arch ); 1201 append_string( ret, public_keyW, ai->public_key ); 1202 append_string( ret, typeW2, ai->type ); 1203 append_string( ret, versionW2, version ); 1204 return ret; 1205 } 1206 1207 static ACTIVATION_CONTEXT *check_actctx( HANDLE h ) 1208 { 1209 ACTIVATION_CONTEXT *ret = NULL, *actctx = h; 1210 1211 if (!h || h == INVALID_HANDLE_VALUE) return NULL; 1212 __TRY 1213 { 1214 if (actctx->magic == ACTCTX_MAGIC) ret = actctx; 1215 } 1216 __EXCEPT_PAGE_FAULT 1217 { 1218 DPRINT1("Invalid activation context handle!\n"); 1219 } 1220 __ENDTRY 1221 return ret; 1222 } 1223 1224 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx ) 1225 { 1226 InterlockedIncrement( &actctx->ref_count ); 1227 } 1228 1229 static void actctx_release( ACTIVATION_CONTEXT *actctx ) 1230 { 1231 if (!InterlockedDecrement( &actctx->ref_count )) 1232 { 1233 unsigned int i, j; 1234 1235 for (i = 0; i < actctx->num_assemblies; i++) 1236 { 1237 struct assembly *assembly = &actctx->assemblies[i]; 1238 for (j = 0; j < assembly->num_dlls; j++) 1239 { 1240 struct dll_redirect *dll = &assembly->dlls[j]; 1241 free_entity_array( &dll->entities ); 1242 RtlFreeHeap( GetProcessHeap(), 0, dll->name ); 1243 RtlFreeHeap( GetProcessHeap(), 0, dll->hash ); 1244 } 1245 RtlFreeHeap( GetProcessHeap(), 0, assembly->dlls ); 1246 RtlFreeHeap( GetProcessHeap(), 0, assembly->manifest.info ); 1247 RtlFreeHeap( GetProcessHeap(), 0, assembly->directory ); 1248 RtlFreeHeap( GetProcessHeap(), 0, assembly->compat_contexts ); 1249 free_entity_array( &assembly->entities ); 1250 free_assembly_identity(&assembly->id); 1251 } 1252 RtlFreeHeap( GetProcessHeap(), 0, actctx->config.info ); 1253 RtlFreeHeap( GetProcessHeap(), 0, actctx->appdir.info ); 1254 RtlFreeHeap( GetProcessHeap(), 0, actctx->assemblies ); 1255 RtlFreeHeap( GetProcessHeap(), 0, actctx->dllredirect_section ); 1256 RtlFreeHeap( GetProcessHeap(), 0, actctx->wndclass_section ); 1257 RtlFreeHeap( GetProcessHeap(), 0, actctx->tlib_section ); 1258 RtlFreeHeap( GetProcessHeap(), 0, actctx->comserver_section ); 1259 RtlFreeHeap( GetProcessHeap(), 0, actctx->ifaceps_section ); 1260 RtlFreeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section ); 1261 RtlFreeHeap( GetProcessHeap(), 0, actctx->progid_section ); 1262 actctx->magic = 0; 1263 RtlFreeHeap( GetProcessHeap(), 0, actctx ); 1264 } 1265 } 1266 1267 static BOOL set_error( xmlbuf_t *xmlbuf ) 1268 { 1269 xmlbuf->error = TRUE; 1270 return FALSE; 1271 } 1272 1273 static BOOL is_xmlns_attr( const struct xml_attr *attr ) 1274 { 1275 const int len = wcslen( xmlnsW ); 1276 if (attr->name.len < len) return FALSE; 1277 if (wcsncmp( attr->name.ptr, xmlnsW, len )) return FALSE; 1278 return (attr->name.len == len || attr->name.ptr[len] == ':'); 1279 } 1280 1281 static void push_xmlns( xmlbuf_t *xmlbuf, const struct xml_attr *attr ) 1282 { 1283 const int len = wcslen( xmlnsW ); 1284 struct xml_attr *ns; 1285 1286 if (xmlbuf->ns_pos == MAX_NAMESPACES - 1) 1287 { 1288 FIXME( "too many namespaces in manifest\n" ); 1289 set_error( xmlbuf ); 1290 return; 1291 } 1292 ns = &xmlbuf->namespaces[xmlbuf->ns_pos++]; 1293 ns->value = attr->value; 1294 if (attr->name.len > len) 1295 { 1296 ns->name.ptr = attr->name.ptr + len + 1; 1297 ns->name.len = attr->name.len - len - 1; 1298 } 1299 else ns->name = empty_xmlstr; 1300 } 1301 1302 static xmlstr_t find_xmlns( xmlbuf_t *xmlbuf, const xmlstr_t *name ) 1303 { 1304 int i; 1305 1306 for (i = xmlbuf->ns_pos - 1; i >= 0; i--) 1307 { 1308 if (xmlbuf->namespaces[i].name.len == name->len && 1309 !wcsncmp( xmlbuf->namespaces[i].name.ptr, name->ptr, name->len )) 1310 return xmlbuf->namespaces[i].value; 1311 } 1312 if (xmlbuf->ns_pos) WARN( "namespace %s not found\n", debugstr_xmlstr( name )); 1313 return empty_xmlstr; 1314 } 1315 1316 static BOOL next_xml_attr(xmlbuf_t *xmlbuf, struct xml_attr *attr, BOOL *end) 1317 { 1318 const WCHAR* ptr; 1319 WCHAR quote; 1320 1321 if (xmlbuf->error) return FALSE; 1322 1323 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) 1324 xmlbuf->ptr++; 1325 1326 if (xmlbuf->ptr == xmlbuf->end) return set_error( xmlbuf ); 1327 1328 if (*xmlbuf->ptr == '/') 1329 { 1330 xmlbuf->ptr++; 1331 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>') 1332 return set_error( xmlbuf ); 1333 1334 xmlbuf->ptr++; 1335 *end = TRUE; 1336 return FALSE; 1337 } 1338 1339 if (*xmlbuf->ptr == '>') 1340 { 1341 xmlbuf->ptr++; 1342 return FALSE; 1343 } 1344 1345 ptr = xmlbuf->ptr; 1346 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++; 1347 1348 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1349 1350 attr->name.ptr = xmlbuf->ptr; 1351 attr->name.len = ptr-xmlbuf->ptr; 1352 xmlbuf->ptr = ptr; 1353 1354 /* skip spaces before '=' */ 1355 while (ptr < xmlbuf->end && *ptr != '=' && isxmlspace(*ptr)) ptr++; 1356 if (ptr == xmlbuf->end || *ptr != '=') return set_error( xmlbuf ); 1357 1358 /* skip '=' itself */ 1359 ptr++; 1360 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1361 1362 /* skip spaces after '=' */ 1363 while (ptr < xmlbuf->end && *ptr != '"' && *ptr != '\'' && isxmlspace(*ptr)) ptr++; 1364 1365 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return set_error( xmlbuf ); 1366 1367 quote = *ptr++; 1368 attr->value.ptr = ptr; 1369 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1370 1371 while (ptr < xmlbuf->end && *ptr != quote) ptr++; 1372 if (ptr == xmlbuf->end) 1373 { 1374 xmlbuf->ptr = xmlbuf->end; 1375 return set_error( xmlbuf ); 1376 } 1377 1378 attr->value.len = ptr - attr->value.ptr; 1379 xmlbuf->ptr = ptr + 1; 1380 if (xmlbuf->ptr != xmlbuf->end) return TRUE; 1381 1382 return set_error( xmlbuf ); 1383 } 1384 1385 static void read_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem ) 1386 { 1387 const WCHAR* ptr = xmlbuf->ptr; 1388 1389 elem->ns = empty_xmlstr; 1390 elem->name.ptr = ptr; 1391 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && *ptr != '/') 1392 { 1393 if (*ptr == ':') 1394 { 1395 elem->ns.ptr = elem->name.ptr; 1396 elem->ns.len = ptr - elem->ns.ptr; 1397 elem->name.ptr = ptr + 1; 1398 } 1399 ptr++; 1400 } 1401 elem->name.len = ptr - elem->name.ptr; 1402 xmlbuf->ptr = ptr; 1403 } 1404 1405 static BOOL next_xml_elem( xmlbuf_t *xmlbuf, struct xml_elem *elem, const struct xml_elem *parent ) 1406 { 1407 const WCHAR* ptr; 1408 struct xml_attr attr; 1409 xmlbuf_t attr_buf; 1410 BOOL end = FALSE; 1411 1412 xmlbuf->ns_pos = parent->ns_pos; /* restore namespace stack to parent state */ 1413 1414 if (xmlbuf->error) return FALSE; 1415 1416 for (;;) 1417 { 1418 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break; 1419 if (ptr == xmlbuf->end) 1420 { 1421 xmlbuf->ptr = xmlbuf->end; 1422 return set_error( xmlbuf ); 1423 } 1424 ptr++; 1425 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */ 1426 { 1427 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++) 1428 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break; 1429 1430 if (ptr + 3 > xmlbuf->end) 1431 { 1432 xmlbuf->ptr = xmlbuf->end; 1433 return set_error( xmlbuf ); 1434 } 1435 xmlbuf->ptr = ptr + 3; 1436 } 1437 else break; 1438 } 1439 1440 xmlbuf->ptr = ptr; 1441 /* check for element terminating the parent element */ 1442 if (ptr < xmlbuf->end && *ptr == '/') 1443 { 1444 xmlbuf->ptr++; 1445 read_xml_elem( xmlbuf, elem ); 1446 elem->ns = find_xmlns( xmlbuf, &elem->ns ); 1447 if (!xml_name_cmp( elem, parent )) 1448 { 1449 ERR( "wrong closing element %s for %s\n", 1450 debugstr_xmlstr(&elem->name), debugstr_xmlstr(&parent->name )); 1451 return set_error( xmlbuf ); 1452 } 1453 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) xmlbuf->ptr++; 1454 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr++ != '>') return set_error( xmlbuf ); 1455 return FALSE; 1456 } 1457 1458 read_xml_elem( xmlbuf, elem ); 1459 1460 /* parse namespace attributes */ 1461 attr_buf = *xmlbuf; 1462 while (next_xml_attr( &attr_buf, &attr, &end )) 1463 { 1464 if (is_xmlns_attr( &attr )) push_xmlns( xmlbuf, &attr ); 1465 } 1466 elem->ns = find_xmlns( xmlbuf, &elem->ns ); 1467 elem->ns_pos = xmlbuf->ns_pos; 1468 1469 if (xmlbuf->ptr != xmlbuf->end) return TRUE; 1470 1471 return set_error( xmlbuf ); 1472 } 1473 1474 static BOOL parse_xml_header(xmlbuf_t* xmlbuf) 1475 { 1476 /* FIXME: parse attributes */ 1477 const WCHAR *ptr; 1478 1479 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++) 1480 { 1481 if (ptr[0] == '?' && ptr[1] == '>') 1482 { 1483 xmlbuf->ptr = ptr + 2; 1484 return TRUE; 1485 } 1486 } 1487 return FALSE; 1488 } 1489 1490 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content) 1491 { 1492 const WCHAR *ptr; 1493 1494 if (xmlbuf->error) return FALSE; 1495 1496 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end; ptr++) if (*ptr == '<') break; 1497 if (ptr == xmlbuf->end) return set_error( xmlbuf ); 1498 1499 content->ptr = xmlbuf->ptr; 1500 content->len = ptr - xmlbuf->ptr; 1501 xmlbuf->ptr = ptr; 1502 1503 return TRUE; 1504 } 1505 1506 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version) 1507 { 1508 unsigned int ver[4]; 1509 unsigned int pos; 1510 const WCHAR *curr; 1511 1512 /* major.minor.build.revision */ 1513 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0; 1514 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1515 { 1516 if (*curr >= '0' && *curr <= '9') 1517 { 1518 ver[pos] = ver[pos] * 10 + *curr - '0'; 1519 if (ver[pos] >= 0x10000) goto error; 1520 } 1521 else if (*curr == '.') 1522 { 1523 if (++pos >= 4) goto error; 1524 } 1525 else goto error; 1526 } 1527 version->major = ver[0]; 1528 version->minor = ver[1]; 1529 version->build = ver[2]; 1530 version->revision = ver[3]; 1531 return TRUE; 1532 1533 error: 1534 FIXME( "Wrong version definition in manifest file (%s)\n", debugstr_xmlstr(str) ); 1535 return FALSE; 1536 } 1537 1538 static void parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end) 1539 { 1540 struct xml_attr attr; 1541 1542 while (next_xml_attr(xmlbuf, &attr, end)) 1543 { 1544 if (!is_xmlns_attr( &attr )) WARN("unexpected attr %s\n", debugstr_xml_attr(&attr)); 1545 } 1546 } 1547 1548 static void parse_expect_end_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 1549 { 1550 struct xml_elem elem; 1551 1552 if (next_xml_elem(xmlbuf, &elem, parent)) 1553 { 1554 FIXME( "unexpected element %s\n", debugstr_xml_elem(&elem) ); 1555 set_error( xmlbuf ); 1556 } 1557 } 1558 1559 static void parse_unknown_elem(xmlbuf_t *xmlbuf, const struct xml_elem *parent) 1560 { 1561 struct xml_elem elem; 1562 struct xml_attr attr; 1563 BOOL end = FALSE; 1564 1565 while (next_xml_attr(xmlbuf, &attr, &end)); 1566 if (end) return; 1567 1568 while (next_xml_elem(xmlbuf, &elem, parent)) 1569 parse_unknown_elem(xmlbuf, &elem); 1570 } 1571 1572 static void parse_assembly_identity_elem(xmlbuf_t *xmlbuf, ACTIVATION_CONTEXT *actctx, 1573 struct assembly_identity* ai, const struct xml_elem *parent) 1574 { 1575 struct xml_attr attr; 1576 BOOL end = FALSE; 1577 1578 while (next_xml_attr(xmlbuf, &attr, &end)) 1579 { 1580 if (xml_attr_cmp(&attr, g_nameW)) 1581 { 1582 if (!(ai->name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1583 } 1584 else if (xml_attr_cmp(&attr, typeW)) 1585 { 1586 if (!(ai->type = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1587 } 1588 else if (xml_attr_cmp(&attr, versionW)) 1589 { 1590 if (!parse_version(&attr.value, &ai->version)) set_error( xmlbuf ); 1591 } 1592 else if (xml_attr_cmp(&attr, processorArchitectureW)) 1593 { 1594 if (!(ai->arch = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1595 } 1596 else if (xml_attr_cmp(&attr, publicKeyTokenW)) 1597 { 1598 if (!(ai->public_key = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1599 } 1600 else if (xml_attr_cmp(&attr, languageW)) 1601 { 1602 if (!(ai->language = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1603 } 1604 else if (!is_xmlns_attr( &attr )) 1605 { 1606 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 1607 } 1608 } 1609 1610 TRACE( "name=%s version=%s arch=%s\n", 1611 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) ); 1612 1613 if (!end) parse_expect_end_elem(xmlbuf, parent); 1614 } 1615 1616 static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value) 1617 { 1618 static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0}; 1619 static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0}; 1620 static const WCHAR freeW[] = {'F','r','e','e',0}; 1621 static const WCHAR bothW[] = {'B','o','t','h',0}; 1622 1623 if (value->len == 0) return ThreadingModel_No; 1624 if (xmlstr_cmp(value, apartW)) 1625 return ThreadingModel_Apartment; 1626 else if (xmlstr_cmp(value, freeW)) 1627 return ThreadingModel_Free; 1628 else if (xmlstr_cmp(value, bothW)) 1629 return ThreadingModel_Both; 1630 else if (xmlstr_cmp(value, neutralW)) 1631 return ThreadingModel_Neutral; 1632 else 1633 return ThreadingModel_No; 1634 }; 1635 1636 static OLEMISC get_olemisc_value(const WCHAR *str, int len) 1637 { 1638 int min, max; 1639 1640 min = 0; 1641 max = ARRAY_SIZE(olemisc_values) - 1; 1642 1643 while (min <= max) 1644 { 1645 int n, c; 1646 1647 n = (min+max)/2; 1648 1649 c = wcsncmp(olemisc_values[n].name, str, len); 1650 if (!c && !olemisc_values[n].name[len]) 1651 return olemisc_values[n].value; 1652 1653 if (c >= 0) 1654 max = n-1; 1655 else 1656 min = n+1; 1657 } 1658 1659 WARN("unknown flag %s\n", debugstr_wn(str, len)); 1660 return 0; 1661 } 1662 1663 static DWORD parse_com_class_misc(const xmlstr_t *value) 1664 { 1665 const WCHAR *str = value->ptr, *start; 1666 DWORD flags = 0; 1667 int i = 0; 1668 1669 /* it's comma separated list of flags */ 1670 while (i < value->len) 1671 { 1672 start = str; 1673 while (*str != ',' && (i++ < value->len)) str++; 1674 1675 flags |= get_olemisc_value(start, str-start); 1676 1677 /* skip separator */ 1678 str++; 1679 i++; 1680 } 1681 1682 return flags; 1683 } 1684 1685 static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity) 1686 { 1687 struct progids *progids = &entity->u.comclass.progids; 1688 1689 if (progids->allocated == 0) 1690 { 1691 progids->allocated = 4; 1692 if (!(progids->progids = RtlAllocateHeap(GetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE; 1693 } 1694 1695 if (progids->allocated == progids->num) 1696 { 1697 WCHAR **new_progids = RtlReAllocateHeap(GetProcessHeap(), 0, progids->progids, 1698 2 * progids->allocated * sizeof(WCHAR*)); 1699 if (!new_progids) return FALSE; 1700 progids->allocated *= 2; 1701 progids->progids = new_progids; 1702 } 1703 1704 if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE; 1705 progids->num++; 1706 1707 return TRUE; 1708 } 1709 1710 static void parse_com_class_progid(xmlbuf_t *xmlbuf, struct entity *entity, const struct xml_elem *parent) 1711 { 1712 xmlstr_t content; 1713 BOOL end = FALSE; 1714 1715 parse_expect_no_attr(xmlbuf, &end); 1716 if (end) set_error( xmlbuf ); 1717 if (!parse_text_content(xmlbuf, &content)) return; 1718 1719 if (!com_class_add_progid(&content, entity)) set_error( xmlbuf ); 1720 parse_expect_end_elem(xmlbuf, parent); 1721 } 1722 1723 static void parse_com_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, struct actctx_loader *acl, 1724 const struct xml_elem *parent ) 1725 { 1726 struct xml_elem elem; 1727 struct xml_attr attr; 1728 BOOL end = FALSE; 1729 struct entity* entity; 1730 1731 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 1732 { 1733 set_error( xmlbuf ); 1734 return; 1735 } 1736 1737 while (next_xml_attr(xmlbuf, &attr, &end)) 1738 { 1739 if (xml_attr_cmp(&attr, clsidW)) 1740 { 1741 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1742 } 1743 else if (xml_attr_cmp(&attr, progidW)) 1744 { 1745 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1746 } 1747 else if (xml_attr_cmp(&attr, tlbidW)) 1748 { 1749 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1750 } 1751 else if (xml_attr_cmp(&attr, threadingmodelW)) 1752 { 1753 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value); 1754 } 1755 else if (xml_attr_cmp(&attr, miscstatusW)) 1756 { 1757 entity->u.comclass.miscstatus = parse_com_class_misc(&attr.value); 1758 } 1759 else if (xml_attr_cmp(&attr, miscstatuscontentW)) 1760 { 1761 entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr.value); 1762 } 1763 else if (xml_attr_cmp(&attr, miscstatusthumbnailW)) 1764 { 1765 entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr.value); 1766 } 1767 else if (xml_attr_cmp(&attr, miscstatusiconW)) 1768 { 1769 entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr.value); 1770 } 1771 else if (xml_attr_cmp(&attr, miscstatusdocprintW)) 1772 { 1773 entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr.value); 1774 } 1775 else if (xml_attr_cmp(&attr, descriptionW)) 1776 { 1777 /* not stored */ 1778 } 1779 else if (!is_xmlns_attr( &attr )) 1780 { 1781 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 1782 } 1783 } 1784 1785 acl->actctx->sections |= SERVERREDIRECT_SECTION; 1786 if (entity->u.comclass.progid) 1787 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 1788 1789 if (end) return; 1790 1791 while (next_xml_elem(xmlbuf, &elem, parent)) 1792 { 1793 if (xml_elem_cmp(&elem, progidW, asmv1W)) 1794 { 1795 parse_com_class_progid(xmlbuf, entity, &elem); 1796 } 1797 else 1798 { 1799 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 1800 parse_unknown_elem(xmlbuf, &elem); 1801 } 1802 } 1803 1804 if (entity->u.comclass.progids.num) 1805 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 1806 } 1807 1808 static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity) 1809 { 1810 const WCHAR *curr; 1811 ULONG num = 0; 1812 1813 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1814 { 1815 if (*curr >= '0' && *curr <= '9') 1816 num = num * 10 + *curr - '0'; 1817 else 1818 { 1819 ERR("wrong numeric value %s\n", debugstr_xmlstr(str)); 1820 return FALSE; 1821 } 1822 } 1823 entity->u.ifaceps.nummethods = num; 1824 1825 return TRUE; 1826 } 1827 1828 static void parse_add_interface_class( xmlbuf_t *xmlbuf, struct entity_array *entities, 1829 struct actctx_loader *acl, WCHAR *clsid ) 1830 { 1831 struct entity *entity; 1832 WCHAR *str; 1833 1834 if (!clsid) return; 1835 1836 if (!(str = strdupW(clsid))) 1837 { 1838 set_error( xmlbuf ); 1839 return; 1840 } 1841 1842 if (!(entity = add_entity(entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 1843 { 1844 RtlFreeHeap(GetProcessHeap(), 0, str); 1845 set_error( xmlbuf ); 1846 return; 1847 } 1848 1849 entity->u.comclass.clsid = str; 1850 entity->u.comclass.model = ThreadingModel_Both; 1851 1852 acl->actctx->sections |= SERVERREDIRECT_SECTION; 1853 } 1854 1855 static void parse_cominterface_proxy_stub_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 1856 struct actctx_loader *acl, const struct xml_elem *parent ) 1857 { 1858 WCHAR *psclsid = NULL; 1859 struct entity *entity; 1860 struct xml_attr attr; 1861 BOOL end = FALSE; 1862 1863 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION))) 1864 { 1865 set_error( xmlbuf ); 1866 return; 1867 } 1868 1869 while (next_xml_attr(xmlbuf, &attr, &end)) 1870 { 1871 if (xml_attr_cmp(&attr, iidW)) 1872 { 1873 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1874 } 1875 else if (xml_attr_cmp(&attr, g_nameW)) 1876 { 1877 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1878 } 1879 else if (xml_attr_cmp(&attr, baseInterfaceW)) 1880 { 1881 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1882 entity->u.ifaceps.mask |= BaseIface; 1883 } 1884 else if (xml_attr_cmp(&attr, nummethodsW)) 1885 { 1886 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf ); 1887 entity->u.ifaceps.mask |= NumMethods; 1888 } 1889 else if (xml_attr_cmp(&attr, tlbidW)) 1890 { 1891 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1892 } 1893 else if (xml_attr_cmp(&attr, proxyStubClsid32W)) 1894 { 1895 if (!(psclsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1896 } 1897 /* not used */ 1898 else if (xml_attr_cmp(&attr, threadingmodelW)) 1899 { 1900 } 1901 else if (!is_xmlns_attr( &attr )) 1902 { 1903 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 1904 } 1905 } 1906 1907 acl->actctx->sections |= IFACEREDIRECT_SECTION; 1908 if (!end) parse_expect_end_elem(xmlbuf, parent); 1909 1910 parse_add_interface_class(xmlbuf, &dll->entities, acl, psclsid ? psclsid : entity->u.ifaceps.iid); 1911 1912 RtlFreeHeap(GetProcessHeap(), 0, psclsid); 1913 } 1914 1915 static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity) 1916 { 1917 WORD *flags = &entity->u.typelib.flags; 1918 const WCHAR *str = value->ptr, *start; 1919 int i = 0; 1920 1921 *flags = 0; 1922 1923 /* it's comma separated list of flags */ 1924 while (i < value->len) 1925 { 1926 start = str; 1927 while (*str != ',' && (i++ < value->len)) str++; 1928 1929 if (!wcsnicmp(start, restrictedW, str-start)) 1930 *flags |= LIBFLAG_FRESTRICTED; 1931 else if (!wcsnicmp(start, controlW, str-start)) 1932 *flags |= LIBFLAG_FCONTROL; 1933 else if (!wcsnicmp(start, hiddenW, str-start)) 1934 *flags |= LIBFLAG_FHIDDEN; 1935 else if (!wcsnicmp(start, hasdiskimageW, str-start)) 1936 *flags |= LIBFLAG_FHASDISKIMAGE; 1937 else 1938 { 1939 WARN("unknown flags value %s\n", debugstr_xmlstr(value)); 1940 return FALSE; 1941 } 1942 1943 /* skip separator */ 1944 str++; 1945 i++; 1946 } 1947 1948 return TRUE; 1949 } 1950 1951 static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity) 1952 { 1953 unsigned int ver[2]; 1954 unsigned int pos; 1955 const WCHAR *curr; 1956 1957 /* major.minor */ 1958 ver[0] = ver[1] = pos = 0; 1959 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 1960 { 1961 if (*curr >= '0' && *curr <= '9') 1962 { 1963 ver[pos] = ver[pos] * 10 + *curr - '0'; 1964 if (ver[pos] >= 0x10000) goto error; 1965 } 1966 else if (*curr == '.') 1967 { 1968 if (++pos >= 2) goto error; 1969 } 1970 else goto error; 1971 } 1972 entity->u.typelib.major = ver[0]; 1973 entity->u.typelib.minor = ver[1]; 1974 return TRUE; 1975 1976 error: 1977 FIXME("wrong typelib version value (%s)\n", debugstr_xmlstr(str)); 1978 return FALSE; 1979 } 1980 1981 static void parse_typelib_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 1982 struct actctx_loader *acl, const struct xml_elem *parent ) 1983 { 1984 struct xml_attr attr; 1985 BOOL end = FALSE; 1986 struct entity* entity; 1987 1988 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION))) 1989 { 1990 set_error( xmlbuf ); 1991 return; 1992 } 1993 1994 while (next_xml_attr(xmlbuf, &attr, &end)) 1995 { 1996 if (xml_attr_cmp(&attr, tlbidW)) 1997 { 1998 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 1999 } 2000 else if (xml_attr_cmp(&attr, versionW)) 2001 { 2002 if (!parse_typelib_version(&attr.value, entity)) set_error( xmlbuf ); 2003 } 2004 else if (xml_attr_cmp(&attr, helpdirW)) 2005 { 2006 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2007 } 2008 else if (xml_attr_cmp(&attr, flagsW)) 2009 { 2010 if (!parse_typelib_flags(&attr.value, entity)) set_error( xmlbuf ); 2011 } 2012 else if (!is_xmlns_attr( &attr )) 2013 { 2014 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2015 } 2016 } 2017 2018 acl->actctx->sections |= TLIBREDIRECT_SECTION; 2019 if (!end) parse_expect_end_elem(xmlbuf, parent); 2020 } 2021 2022 static inline int aligned_string_len(int len) 2023 { 2024 return (len + 3) & ~3; 2025 } 2026 2027 static int get_assembly_version(struct assembly *assembly, WCHAR *ret) 2028 { 2029 static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 2030 struct assembly_version *ver = &assembly->id.version; 2031 WCHAR buff[25]; 2032 2033 if (!ret) ret = buff; 2034 return swprintf(ret, ARRAY_SIZE(buff), fmtW, ver->major, ver->minor, ver->build, ver->revision); 2035 } 2036 2037 static void parse_window_class_elem( xmlbuf_t *xmlbuf, struct dll_redirect *dll, 2038 struct actctx_loader *acl, const struct xml_elem *parent ) 2039 { 2040 struct xml_elem elem; 2041 struct xml_attr attr; 2042 xmlstr_t content; 2043 BOOL end = FALSE; 2044 struct entity* entity; 2045 2046 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION))) 2047 { 2048 set_error( xmlbuf ); 2049 return; 2050 } 2051 entity->u.class.versioned = TRUE; 2052 while (next_xml_attr(xmlbuf, &attr, &end)) 2053 { 2054 if (xml_attr_cmp(&attr, versionedW)) 2055 { 2056 if (xmlstr_cmpi(&attr.value, noW)) 2057 entity->u.class.versioned = FALSE; 2058 else if (!xmlstr_cmpi(&attr.value, yesW)) 2059 set_error( xmlbuf ); 2060 } 2061 else if (!is_xmlns_attr( &attr )) 2062 { 2063 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2064 } 2065 } 2066 2067 if (end) return; 2068 2069 if (!parse_text_content(xmlbuf, &content)) return; 2070 if (!(entity->u.class.name = xmlstrdupW(&content))) set_error( xmlbuf ); 2071 2072 acl->actctx->sections |= WINDOWCLASS_SECTION; 2073 2074 while (next_xml_elem(xmlbuf, &elem, parent)) 2075 { 2076 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2077 parse_unknown_elem(xmlbuf, &elem); 2078 } 2079 } 2080 2081 static void parse_binding_redirect_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2082 { 2083 struct xml_attr attr; 2084 BOOL end = FALSE; 2085 2086 while (next_xml_attr(xmlbuf, &attr, &end)) 2087 { 2088 if (xml_attr_cmp(&attr, oldVersionW)) 2089 { 2090 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr)); 2091 } 2092 else if (xml_attr_cmp(&attr, newVersionW)) 2093 { 2094 FIXME("Not stored yet %s\n", debugstr_xml_attr(&attr)); 2095 } 2096 else if (!is_xmlns_attr( &attr )) 2097 { 2098 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2099 } 2100 } 2101 2102 if (!end) parse_expect_end_elem(xmlbuf, parent); 2103 } 2104 2105 static void parse_description_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2106 { 2107 struct xml_elem elem; 2108 struct xml_attr attr; 2109 xmlstr_t content; 2110 BOOL end = FALSE; 2111 2112 while (next_xml_attr(xmlbuf, &attr, &end)) 2113 { 2114 if (!is_xmlns_attr( &attr )) WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2115 } 2116 2117 if (end) return; 2118 if (!parse_text_content(xmlbuf, &content)) return; 2119 2120 TRACE("Got description %s\n", debugstr_xmlstr(&content)); 2121 2122 while (next_xml_elem(xmlbuf, &elem, parent)) 2123 { 2124 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2125 parse_unknown_elem(xmlbuf, &elem); 2126 } 2127 } 2128 2129 static void parse_com_interface_external_proxy_stub_elem(xmlbuf_t *xmlbuf, 2130 struct assembly* assembly, 2131 struct actctx_loader* acl, 2132 const struct xml_elem *parent) 2133 { 2134 struct xml_attr attr; 2135 BOOL end = FALSE; 2136 struct entity* entity; 2137 2138 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION))) 2139 { 2140 set_error( xmlbuf ); 2141 return; 2142 } 2143 2144 while (next_xml_attr(xmlbuf, &attr, &end)) 2145 { 2146 if (xml_attr_cmp(&attr, iidW)) 2147 { 2148 if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2149 } 2150 else if (xml_attr_cmp(&attr, g_nameW)) 2151 { 2152 if (!(entity->u.ifaceps.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2153 } 2154 else if (xml_attr_cmp(&attr, baseInterfaceW)) 2155 { 2156 if (!(entity->u.ifaceps.base = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2157 entity->u.ifaceps.mask |= BaseIface; 2158 } 2159 else if (xml_attr_cmp(&attr, nummethodsW)) 2160 { 2161 if (!(parse_nummethods(&attr.value, entity))) set_error( xmlbuf ); 2162 entity->u.ifaceps.mask |= NumMethods; 2163 } 2164 else if (xml_attr_cmp(&attr, proxyStubClsid32W)) 2165 { 2166 if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2167 } 2168 else if (xml_attr_cmp(&attr, tlbidW)) 2169 { 2170 if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2171 } 2172 else if (!is_xmlns_attr( &attr )) 2173 { 2174 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2175 } 2176 } 2177 2178 acl->actctx->sections |= IFACEREDIRECT_SECTION; 2179 if (!end) parse_expect_end_elem(xmlbuf, parent); 2180 } 2181 2182 static void parse_clr_class_elem( xmlbuf_t* xmlbuf, struct assembly* assembly, 2183 struct actctx_loader *acl, const struct xml_elem *parent ) 2184 2185 { 2186 struct xml_elem elem; 2187 struct xml_attr attr; 2188 BOOL end = FALSE; 2189 struct entity* entity; 2190 2191 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 2192 { 2193 set_error( xmlbuf ); 2194 return; 2195 } 2196 2197 while (next_xml_attr(xmlbuf, &attr, &end)) 2198 { 2199 if (xml_attr_cmp(&attr, g_nameW)) 2200 { 2201 if (!(entity->u.comclass.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2202 } 2203 else if (xml_attr_cmp(&attr, clsidW)) 2204 { 2205 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2206 } 2207 else if (xml_attr_cmp(&attr, progidW)) 2208 { 2209 if (!(entity->u.comclass.progid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2210 } 2211 else if (xml_attr_cmp(&attr, tlbidW)) 2212 { 2213 if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2214 } 2215 else if (xml_attr_cmp(&attr, threadingmodelW)) 2216 { 2217 entity->u.comclass.model = parse_com_class_threadingmodel(&attr.value); 2218 } 2219 else if (xml_attr_cmp(&attr, runtimeVersionW)) 2220 { 2221 if (!(entity->u.comclass.version = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2222 } 2223 else if (!is_xmlns_attr( &attr )) 2224 { 2225 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2226 } 2227 } 2228 2229 acl->actctx->sections |= SERVERREDIRECT_SECTION; 2230 if (entity->u.comclass.progid) 2231 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 2232 if (end) return; 2233 2234 while (next_xml_elem(xmlbuf, &elem, parent)) 2235 { 2236 if (xml_elem_cmp(&elem, progidW, asmv1W)) 2237 { 2238 parse_com_class_progid(xmlbuf, entity, &elem); 2239 } 2240 else 2241 { 2242 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2243 parse_unknown_elem(xmlbuf, &elem); 2244 } 2245 } 2246 2247 if (entity->u.comclass.progids.num) 2248 acl->actctx->sections |= PROGIDREDIRECT_SECTION; 2249 } 2250 2251 static void parse_clr_surrogate_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2252 struct actctx_loader *acl, const struct xml_elem *parent ) 2253 { 2254 struct xml_attr attr; 2255 BOOL end = FALSE; 2256 struct entity* entity; 2257 2258 if (!(entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES))) 2259 { 2260 set_error( xmlbuf ); 2261 return; 2262 } 2263 2264 while (next_xml_attr(xmlbuf, &attr, &end)) 2265 { 2266 if (xml_attr_cmp(&attr, g_nameW)) 2267 { 2268 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2269 } 2270 else if (xml_attr_cmp(&attr, clsidW)) 2271 { 2272 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2273 } 2274 else if (xml_attr_cmp(&attr, runtimeVersionW)) 2275 { 2276 if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2277 } 2278 else if (!is_xmlns_attr( &attr )) 2279 { 2280 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2281 } 2282 } 2283 2284 acl->actctx->sections |= CLRSURROGATES_SECTION; 2285 if (!end) parse_expect_end_elem(xmlbuf, parent); 2286 } 2287 2288 static void parse_dependent_assembly_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl, 2289 const struct xml_elem *parent, BOOL optional ) 2290 { 2291 struct xml_elem elem; 2292 struct xml_attr attr; 2293 struct assembly_identity ai; 2294 BOOL end = FALSE; 2295 2296 memset(&ai, 0, sizeof(ai)); 2297 ai.optional = optional; 2298 2299 while (next_xml_attr(xmlbuf, &attr, &end)) 2300 { 2301 static const WCHAR allowDelayedBindingW[] = {'a','l','l','o','w','D','e','l','a','y','e','d','B','i','n','d','i','n','g',0}; 2302 static const WCHAR trueW[] = {'t','r','u','e',0}; 2303 2304 if (xml_attr_cmp(&attr, allowDelayedBindingW)) 2305 ai.delayed = xmlstr_cmp(&attr.value, trueW); 2306 else if (!is_xmlns_attr( &attr )) 2307 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2308 } 2309 2310 if (end) return; 2311 2312 while (next_xml_elem(xmlbuf, &elem, parent)) 2313 { 2314 if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) 2315 { 2316 parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai, &elem); 2317 /* store the newly found identity for later loading */ 2318 if (ai.arch && !wcscmp(ai.arch, wildcardW)) 2319 { 2320 RtlFreeHeap( GetProcessHeap(), 0, ai.arch ); 2321 ai.arch = strdupW( current_archW ); 2322 } 2323 TRACE( "adding name=%s version=%s arch=%s\n", 2324 debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) ); 2325 if (!add_dependent_assembly_id(acl, &ai)) set_error( xmlbuf ); 2326 } 2327 else if (xml_elem_cmp(&elem, bindingRedirectW, asmv1W)) 2328 { 2329 parse_binding_redirect_elem(xmlbuf, &elem); 2330 } 2331 else 2332 { 2333 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2334 parse_unknown_elem(xmlbuf, &elem); 2335 } 2336 } 2337 } 2338 2339 static void parse_dependency_elem( xmlbuf_t *xmlbuf, struct actctx_loader *acl, 2340 const struct xml_elem *parent ) 2341 2342 { 2343 struct xml_elem elem; 2344 struct xml_attr attr; 2345 BOOL end = FALSE, optional = FALSE; 2346 2347 while (next_xml_attr(xmlbuf, &attr, &end)) 2348 { 2349 if (xml_attr_cmp(&attr, optionalW)) 2350 { 2351 optional = xmlstr_cmpi( &attr.value, yesW ); 2352 TRACE("optional=%s\n", debugstr_xmlstr(&attr.value)); 2353 } 2354 else if (!is_xmlns_attr( &attr )) 2355 { 2356 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2357 } 2358 } 2359 2360 while (next_xml_elem(xmlbuf, &elem, parent)) 2361 { 2362 if (xml_elem_cmp(&elem, dependentAssemblyW, asmv1W)) 2363 { 2364 parse_dependent_assembly_elem(xmlbuf, acl, &elem, optional); 2365 } 2366 else 2367 { 2368 WARN("unknown element %s\n", debugstr_xml_elem(&elem)); 2369 parse_unknown_elem(xmlbuf, &elem); 2370 } 2371 } 2372 } 2373 2374 static void parse_noinherit_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2375 { 2376 BOOL end = FALSE; 2377 2378 parse_expect_no_attr(xmlbuf, &end); 2379 if (!end) parse_expect_end_elem(xmlbuf, parent); 2380 } 2381 2382 static void parse_noinheritable_elem( xmlbuf_t *xmlbuf, const struct xml_elem *parent ) 2383 { 2384 BOOL end = FALSE; 2385 2386 parse_expect_no_attr(xmlbuf, &end); 2387 if (!end) parse_expect_end_elem(xmlbuf, parent); 2388 } 2389 2390 static void parse_file_elem( xmlbuf_t* xmlbuf, struct assembly* assembly, 2391 struct actctx_loader* acl, const struct xml_elem *parent ) 2392 { 2393 struct xml_elem elem; 2394 struct xml_attr attr; 2395 BOOL end = FALSE; 2396 struct dll_redirect* dll; 2397 2398 if (!(dll = add_dll_redirect(assembly))) 2399 { 2400 set_error( xmlbuf ); 2401 return; 2402 } 2403 2404 while (next_xml_attr(xmlbuf, &attr, &end)) 2405 { 2406 if (xml_attr_cmp(&attr, g_nameW)) 2407 { 2408 if (!(dll->name = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2409 TRACE("name=%s\n", debugstr_xmlstr(&attr.value)); 2410 } 2411 else if (xml_attr_cmp(&attr, hashW)) 2412 { 2413 if (!(dll->hash = xmlstrdupW(&attr.value))) set_error( xmlbuf ); 2414 } 2415 else if (xml_attr_cmp(&attr, hashalgW)) 2416 { 2417 static const WCHAR sha1W[] = {'S','H','A','1',0}; 2418 if (!xmlstr_cmpi(&attr.value, sha1W)) 2419 FIXME("hashalg should be SHA1, got %s\n", debugstr_xmlstr(&attr.value)); 2420 } 2421 else if (!is_xmlns_attr( &attr )) 2422 { 2423 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2424 } 2425 } 2426 2427 if (!dll->name) set_error( xmlbuf ); 2428 2429 acl->actctx->sections |= DLLREDIRECT_SECTION; 2430 2431 if (end) return; 2432 2433 while (next_xml_elem(xmlbuf, &elem, parent)) 2434 { 2435 if (xml_elem_cmp(&elem, comClassW, asmv1W)) 2436 { 2437 parse_com_class_elem(xmlbuf, dll, acl, &elem); 2438 } 2439 else if (xml_elem_cmp(&elem, comInterfaceProxyStubW, asmv1W)) 2440 { 2441 parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl, &elem); 2442 } 2443 else if (xml_elem_cmp(&elem, hashW, asmv2W)) 2444 { 2445 WARN("asmv2:hash (undocumented) not supported\n"); 2446 parse_unknown_elem(xmlbuf, &elem); 2447 } 2448 else if (xml_elem_cmp(&elem, typelibW, asmv1W)) 2449 { 2450 parse_typelib_elem(xmlbuf, dll, acl, &elem); 2451 } 2452 else if (xml_elem_cmp(&elem, windowClassW, asmv1W)) 2453 { 2454 parse_window_class_elem(xmlbuf, dll, acl, &elem); 2455 } 2456 else 2457 { 2458 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2459 parse_unknown_elem( xmlbuf, &elem ); 2460 } 2461 } 2462 } 2463 2464 static void parse_supportedos_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2465 struct actctx_loader *acl, const struct xml_elem *parent ) 2466 { 2467 struct xml_attr attr; 2468 BOOL end = FALSE; 2469 2470 while (next_xml_attr(xmlbuf, &attr, &end)) 2471 { 2472 if (xml_attr_cmp(&attr, IdW)) 2473 { 2474 COMPATIBILITY_CONTEXT_ELEMENT *compat; 2475 UNICODE_STRING str; 2476 GUID compat_id; 2477 2478 str.Buffer = (PWSTR)attr.value.ptr; 2479 str.Length = str.MaximumLength = (USHORT)attr.value.len * sizeof(WCHAR); 2480 if (RtlGUIDFromString(&str, &compat_id) == STATUS_SUCCESS) 2481 { 2482 if (!(compat = add_compat_context(assembly))) 2483 { 2484 set_error( xmlbuf ); 2485 return; 2486 } 2487 compat->Type = ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS; 2488 compat->Id = compat_id; 2489 } 2490 else 2491 { 2492 WARN("Invalid guid %s\n", debugstr_xmlstr(&attr.value)); 2493 } 2494 } 2495 else if (!is_xmlns_attr( &attr )) 2496 { 2497 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2498 } 2499 } 2500 2501 if (!end) parse_expect_end_elem(xmlbuf, parent); 2502 } 2503 2504 static void parse_compatibility_application_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, 2505 struct actctx_loader* acl, const struct xml_elem *parent) 2506 { 2507 struct xml_elem elem; 2508 2509 while (next_xml_elem(xmlbuf, &elem, parent)) 2510 { 2511 if (xml_elem_cmp(&elem, supportedOSW, compatibilityNSW)) 2512 { 2513 parse_supportedos_elem(xmlbuf, assembly, acl, &elem); 2514 } 2515 else 2516 { 2517 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2518 parse_unknown_elem(xmlbuf, &elem); 2519 } 2520 } 2521 } 2522 2523 static void parse_compatibility_elem(xmlbuf_t *xmlbuf, struct assembly *assembly, 2524 struct actctx_loader* acl, const struct xml_elem *parent) 2525 { 2526 struct xml_elem elem; 2527 2528 while (next_xml_elem(xmlbuf, &elem, parent)) 2529 { 2530 if (xml_elem_cmp(&elem, applicationW, compatibilityNSW)) 2531 { 2532 parse_compatibility_application_elem(xmlbuf, assembly, acl, &elem); 2533 } 2534 else 2535 { 2536 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2537 parse_unknown_elem(xmlbuf, &elem); 2538 } 2539 } 2540 } 2541 2542 static void parse_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, struct actctx_loader *acl, 2543 struct xml_elem *parent ) 2544 { 2545 struct xml_elem elem; 2546 struct xml_attr attr; 2547 xmlstr_t content; 2548 BOOL end = FALSE; 2549 struct entity *entity; 2550 2551 while (next_xml_attr( xmlbuf, &attr, &end )) 2552 { 2553 if (!is_xmlns_attr( &attr )) WARN( "unknown attr %s\n", debugstr_xml_attr(&attr) ); 2554 } 2555 2556 if (end) return; 2557 2558 if (!parse_text_content( xmlbuf, &content )) return; 2559 TRACE( "got %s %s\n", debugstr_xmlstr(&parent->name), debugstr_xmlstr(&content) ); 2560 2561 entity = add_entity( &assembly->entities, ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS ); 2562 if (!entity) 2563 { 2564 set_error( xmlbuf ); 2565 return; 2566 } 2567 entity->u.settings.name = xmlstrdupW( &parent->name ); 2568 entity->u.settings.value = xmlstrdupW( &content ); 2569 entity->u.settings.ns = xmlstrdupW( &parent->ns ); 2570 2571 while (next_xml_elem(xmlbuf, &elem, parent)) 2572 { 2573 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) ); 2574 parse_unknown_elem( xmlbuf, &elem ); 2575 } 2576 } 2577 2578 static void parse_windows_settings_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2579 struct actctx_loader *acl, const struct xml_elem *parent ) 2580 { 2581 struct xml_elem elem; 2582 2583 while (next_xml_elem( xmlbuf, &elem, parent )) 2584 { 2585 if (xml_elem_cmp( &elem, autoElevateW, windowsSettings2005NSW ) || 2586 xml_elem_cmp( &elem, disableThemingW, windowsSettings2005NSW ) || 2587 xml_elem_cmp( &elem, disableWindowFilteringW, windowsSettings2011NSW ) || 2588 xml_elem_cmp( &elem, dpiAwareW, windowsSettings2005NSW ) || 2589 xml_elem_cmp( &elem, dpiAwarenessW, windowsSettings2016NSW ) || 2590 xml_elem_cmp( &elem, gdiScalingW, windowsSettings2017NSW ) || 2591 xml_elem_cmp( &elem, highResolutionScrollingAwareW, windowsSettings2017NSW ) || 2592 xml_elem_cmp( &elem, longPathAwareW, windowsSettings2016NSW ) || 2593 xml_elem_cmp( &elem, magicFutureSettingW, windowsSettings2017NSW ) || 2594 xml_elem_cmp( &elem, printerDriverIsolationW, windowsSettings2011NSW ) || 2595 xml_elem_cmp( &elem, ultraHighResolutionScrollingAwareW, windowsSettings2017NSW )) 2596 { 2597 parse_settings_elem( xmlbuf, assembly, acl, &elem ); 2598 } 2599 else 2600 { 2601 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) ); 2602 parse_unknown_elem( xmlbuf, &elem ); 2603 } 2604 } 2605 } 2606 2607 static void parse_application_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2608 struct actctx_loader *acl, const struct xml_elem *parent ) 2609 { 2610 struct xml_elem elem; 2611 2612 while (next_xml_elem( xmlbuf, &elem, parent )) 2613 { 2614 if (xml_elem_cmp( &elem, windowsSettingsW, asmv3W )) 2615 { 2616 parse_windows_settings_elem( xmlbuf, assembly, acl, &elem ); 2617 } 2618 else 2619 { 2620 WARN( "unknown elem %s\n", debugstr_xml_elem(&elem) ); 2621 parse_unknown_elem( xmlbuf, &elem ); 2622 } 2623 } 2624 } 2625 2626 static void parse_requested_execution_level_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2627 struct actctx_loader *acl, const struct xml_elem *parent ) 2628 { 2629 static const WCHAR levelW[] = {'l','e','v','e','l',0}; 2630 static const WCHAR asInvokerW[] = {'a','s','I','n','v','o','k','e','r',0}; 2631 static const WCHAR requireAdministratorW[] = {'r','e','q','u','i','r','e','A','d','m','i','n','i','s','t','r','a','t','o','r',0}; 2632 static const WCHAR highestAvailableW[] = {'h','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0}; 2633 static const WCHAR uiAccessW[] = {'u','i','A','c','c','e','s','s',0}; 2634 static const WCHAR falseW[] = {'f','a','l','s','e',0}; 2635 static const WCHAR trueW[] = {'t','r','u','e',0}; 2636 2637 struct xml_elem elem; 2638 struct xml_attr attr; 2639 BOOL end = FALSE; 2640 2641 /* Multiple requestedExecutionLevel elements are not supported. */ 2642 if (assembly->run_level != ACTCTX_RUN_LEVEL_UNSPECIFIED) set_error( xmlbuf ); 2643 2644 while (next_xml_attr(xmlbuf, &attr, &end)) 2645 { 2646 if (xml_attr_cmp(&attr, levelW)) 2647 { 2648 if (xmlstr_cmpi(&attr.value, asInvokerW)) 2649 assembly->run_level = ACTCTX_RUN_LEVEL_AS_INVOKER; 2650 else if (xmlstr_cmpi(&attr.value, highestAvailableW)) 2651 assembly->run_level = ACTCTX_RUN_LEVEL_HIGHEST_AVAILABLE; 2652 else if (xmlstr_cmpi(&attr.value, requireAdministratorW)) 2653 assembly->run_level = ACTCTX_RUN_LEVEL_REQUIRE_ADMIN; 2654 else 2655 FIXME("unknown execution level: %s\n", debugstr_xmlstr(&attr.value)); 2656 } 2657 else if (xml_attr_cmp(&attr, uiAccessW)) 2658 { 2659 if (xmlstr_cmpi(&attr.value, falseW)) 2660 assembly->ui_access = FALSE; 2661 else if (xmlstr_cmpi(&attr.value, trueW)) 2662 assembly->ui_access = TRUE; 2663 else 2664 FIXME("unknown uiAccess value: %s\n", debugstr_xmlstr(&attr.value)); 2665 } 2666 else if (!is_xmlns_attr( &attr )) 2667 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2668 } 2669 2670 if (end) return; 2671 2672 while (next_xml_elem(xmlbuf, &elem, parent)) 2673 { 2674 WARN("unknown element %s\n", debugstr_xml_elem(&elem)); 2675 parse_unknown_elem(xmlbuf, &elem); 2676 } 2677 } 2678 2679 static void parse_requested_privileges_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2680 struct actctx_loader *acl, const struct xml_elem *parent ) 2681 { 2682 struct xml_elem elem; 2683 2684 while (next_xml_elem(xmlbuf, &elem, parent)) 2685 { 2686 if (xml_elem_cmp(&elem, requestedExecutionLevelW, asmv1W)) 2687 { 2688 parse_requested_execution_level_elem(xmlbuf, assembly, acl, &elem); 2689 } 2690 else 2691 { 2692 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2693 parse_unknown_elem(xmlbuf, &elem); 2694 } 2695 } 2696 } 2697 2698 static void parse_security_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2699 struct actctx_loader *acl, const struct xml_elem *parent ) 2700 { 2701 struct xml_elem elem; 2702 2703 while (next_xml_elem(xmlbuf, &elem, parent)) 2704 { 2705 if (xml_elem_cmp(&elem, requestedPrivilegesW, asmv1W)) 2706 { 2707 parse_requested_privileges_elem(xmlbuf, assembly, acl, &elem); 2708 } 2709 else 2710 { 2711 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2712 parse_unknown_elem(xmlbuf, &elem); 2713 } 2714 } 2715 } 2716 2717 static void parse_trust_info_elem( xmlbuf_t *xmlbuf, struct assembly *assembly, 2718 struct actctx_loader *acl, const struct xml_elem *parent ) 2719 { 2720 struct xml_elem elem; 2721 2722 while (next_xml_elem(xmlbuf, &elem, parent)) 2723 { 2724 if (xml_elem_cmp(&elem, securityW, asmv1W)) 2725 { 2726 parse_security_elem(xmlbuf, assembly, acl, &elem); 2727 } 2728 else 2729 { 2730 WARN("unknown elem %s\n", debugstr_xml_elem(&elem)); 2731 parse_unknown_elem(xmlbuf, &elem); 2732 } 2733 } 2734 } 2735 2736 static void parse_assembly_elem( xmlbuf_t *xmlbuf, struct assembly* assembly, 2737 struct actctx_loader* acl, const struct xml_elem *parent, 2738 struct assembly_identity* expected_ai) 2739 { 2740 struct xml_elem elem; 2741 struct xml_attr attr; 2742 BOOL end = FALSE, version = FALSE; 2743 2744 TRACE("(%p)\n", xmlbuf); 2745 2746 while (next_xml_attr(xmlbuf, &attr, &end)) 2747 { 2748 if (xml_attr_cmp(&attr, manifestVersionW)) 2749 { 2750 static const WCHAR v10W[] = {'1','.','0',0}; 2751 if (!xmlstr_cmp(&attr.value, v10W)) 2752 { 2753 FIXME("wrong version %s\n", debugstr_xmlstr(&attr.value)); 2754 break; 2755 } 2756 version = TRUE; 2757 } 2758 else if (!is_xmlns_attr( &attr )) 2759 { 2760 WARN("unknown attr %s\n", debugstr_xml_attr(&attr)); 2761 } 2762 } 2763 2764 if (end || !version) 2765 { 2766 set_error( xmlbuf ); 2767 return; 2768 } 2769 2770 while (next_xml_elem(xmlbuf, &elem, parent)) 2771 { 2772 if (assembly->type == APPLICATION_MANIFEST && xml_elem_cmp(&elem, noInheritW, asmv1W)) 2773 { 2774 parse_noinherit_elem(xmlbuf, &elem); 2775 assembly->no_inherit = TRUE; 2776 } 2777 else if (xml_elem_cmp(&elem, noInheritableW, asmv1W)) 2778 { 2779 parse_noinheritable_elem(xmlbuf, &elem); 2780 } 2781 else if (xml_elem_cmp(&elem, descriptionW, asmv1W)) 2782 { 2783 parse_description_elem(xmlbuf, &elem); 2784 } 2785 else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W)) 2786 { 2787 parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl, &elem); 2788 } 2789 else if (xml_elem_cmp(&elem, dependencyW, asmv1W)) 2790 { 2791 parse_dependency_elem(xmlbuf, acl, &elem); 2792 } 2793 else if (xml_elem_cmp(&elem, fileW, asmv1W)) 2794 { 2795 parse_file_elem(xmlbuf, assembly, acl, &elem); 2796 } 2797 else if (xml_elem_cmp(&elem, clrClassW, asmv1W)) 2798 { 2799 parse_clr_class_elem(xmlbuf, assembly, acl, &elem); 2800 } 2801 else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W)) 2802 { 2803 parse_clr_surrogate_elem(xmlbuf, assembly, acl, &elem); 2804 } 2805 else if (xml_elem_cmp(&elem, trustInfoW, asmv1W)) 2806 { 2807 parse_trust_info_elem(xmlbuf, assembly, acl, &elem); 2808 } 2809 else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W)) 2810 { 2811 parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id, &elem); 2812 2813 if (!xmlbuf->error && expected_ai) 2814 { 2815 /* FIXME: more tests */ 2816 if (assembly->type == ASSEMBLY_MANIFEST && 2817 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version))) 2818 { 2819 FIXME("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n", 2820 expected_ai->version.major, expected_ai->version.minor, 2821 expected_ai->version.build, expected_ai->version.revision, 2822 assembly->id.version.major, assembly->id.version.minor, 2823 assembly->id.version.build, assembly->id.version.revision); 2824 set_error( xmlbuf ); 2825 } 2826 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST && 2827 (assembly->id.version.major != expected_ai->version.major || 2828 assembly->id.version.minor != expected_ai->version.minor || 2829 assembly->id.version.build < expected_ai->version.build || 2830 (assembly->id.version.build == expected_ai->version.build && 2831 assembly->id.version.revision < expected_ai->version.revision))) 2832 { 2833 FIXME("wrong version for shared assembly manifest\n"); 2834 set_error( xmlbuf ); 2835 } 2836 } 2837 } 2838 else if (xml_elem_cmp(&elem, compatibilityW, compatibilityNSW)) 2839 { 2840 parse_compatibility_elem(xmlbuf, assembly, acl, &elem); 2841 } 2842 else if (xml_elem_cmp(&elem, applicationW, asmv3W)) 2843 { 2844 parse_application_elem(xmlbuf, assembly, acl, &elem); 2845 } 2846 else 2847 { 2848 WARN("unknown element %s\n", debugstr_xml_elem(&elem)); 2849 parse_unknown_elem(xmlbuf, &elem); 2850 } 2851 } 2852 2853 if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) && 2854 assembly->no_inherit) 2855 { 2856 set_error( xmlbuf ); 2857 } 2858 } 2859 2860 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly, 2861 struct assembly_identity* ai, xmlbuf_t *xmlbuf ) 2862 { 2863 struct xml_elem elem; 2864 struct xml_elem parent = {0}; 2865 2866 xmlbuf->error = FALSE; 2867 xmlbuf->ns_pos = 0; 2868 2869 if (!next_xml_elem(xmlbuf, &elem, &parent)) return STATUS_SXS_CANT_GEN_ACTCTX; 2870 2871 if (xmlstr_cmp(&elem.name, g_xmlW) && 2872 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem, &parent))) 2873 return STATUS_SXS_CANT_GEN_ACTCTX; 2874 2875 if (!xml_elem_cmp(&elem, assemblyW, asmv1W)) 2876 { 2877 FIXME("root element is %s, not <assembly>\n", debugstr_xml_elem(&elem)); 2878 return STATUS_SXS_CANT_GEN_ACTCTX; 2879 } 2880 2881 parse_assembly_elem(xmlbuf, assembly, acl, &elem, ai); 2882 if (xmlbuf->error) 2883 { 2884 FIXME("failed to parse manifest %s\n", debugstr_w(assembly->manifest.info) ); 2885 return STATUS_SXS_CANT_GEN_ACTCTX; 2886 } 2887 2888 if (next_xml_elem(xmlbuf, &elem, &parent)) 2889 { 2890 FIXME("unexpected element %s\n", debugstr_xml_elem(&elem)); 2891 return STATUS_SXS_CANT_GEN_ACTCTX; 2892 } 2893 2894 if (xmlbuf->ptr != xmlbuf->end) 2895 { 2896 FIXME("parse error\n"); 2897 return STATUS_SXS_CANT_GEN_ACTCTX; 2898 } 2899 return STATUS_SUCCESS; 2900 } 2901 2902 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 2903 LPCWSTR filename, HANDLE module, LPCWSTR directory, BOOL shared, 2904 const void *buffer, SIZE_T size ) 2905 { 2906 xmlbuf_t xmlbuf; 2907 NTSTATUS status; 2908 struct assembly *assembly; 2909 int unicode_tests; 2910 2911 TRACE( "parsing manifest loaded from %s base dir %s\n", debugstr_w(filename), debugstr_w(directory) ); 2912 2913 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST))) 2914 return STATUS_SXS_CANT_GEN_ACTCTX; 2915 2916 if (directory && !(assembly->directory = strdupW(directory))) 2917 return STATUS_NO_MEMORY; 2918 2919 if (!filename) 2920 { 2921 UNICODE_STRING module_path; 2922 if ((status = get_module_filename( module, &module_path, 0 ))) return status; 2923 assembly->manifest.info = module_path.Buffer; 2924 } 2925 else if(!(assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ))) return STATUS_NO_MEMORY; 2926 2927 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE 2928 : ACTIVATION_CONTEXT_PATH_TYPE_NONE; 2929 2930 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE; 2931 if (RtlIsTextUnicode( buffer, size, &unicode_tests )) 2932 { 2933 xmlbuf.ptr = buffer; 2934 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 2935 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 2936 } 2937 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE) 2938 { 2939 const WCHAR *buf = buffer; 2940 WCHAR *new_buff; 2941 unsigned int i; 2942 2943 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, size ))) 2944 return STATUS_NO_MEMORY; 2945 for (i = 0; i < size / sizeof(WCHAR); i++) 2946 new_buff[i] = RtlUshortByteSwap( buf[i] ); 2947 xmlbuf.ptr = new_buff; 2948 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 2949 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 2950 RtlFreeHeap( GetProcessHeap(), 0, new_buff ); 2951 } 2952 else 2953 { 2954 DWORD len; 2955 WCHAR *new_buff; 2956 2957 /* let's assume utf-8 for now */ 2958 status = RtlUTF8ToUnicodeN( NULL, 0, &len, buffer, size ); 2959 if (!NT_SUCCESS(status)) 2960 { 2961 DPRINT1("RtlMultiByteToUnicodeSize failed with %lx\n", status); 2962 return STATUS_SXS_CANT_GEN_ACTCTX; 2963 } 2964 2965 if (!(new_buff = RtlAllocateHeap( GetProcessHeap(), 0, len ))) return STATUS_NO_MEMORY; 2966 status = RtlUTF8ToUnicodeN( new_buff, len, &len, buffer, size ); 2967 if (!NT_SUCCESS(status)) 2968 { 2969 DPRINT1("RtlMultiByteToUnicodeN failed with %lx\n", status); 2970 return STATUS_SXS_CANT_GEN_ACTCTX; 2971 } 2972 2973 xmlbuf.ptr = new_buff; 2974 xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR); 2975 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 2976 RtlFreeHeap( GetProcessHeap(), 0, new_buff ); 2977 } 2978 return status; 2979 } 2980 2981 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name ) 2982 { 2983 OBJECT_ATTRIBUTES attr; 2984 IO_STATUS_BLOCK io; 2985 2986 attr.Length = sizeof(attr); 2987 attr.RootDirectory = 0; 2988 attr.Attributes = OBJ_CASE_INSENSITIVE; 2989 attr.ObjectName = name; 2990 attr.SecurityDescriptor = NULL; 2991 attr.SecurityQualityOfService = NULL; 2992 return NtOpenFile( handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT ); 2993 } 2994 2995 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 2996 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2997 HANDLE hModule, LPCWSTR resname, ULONG lang ) 2998 { 2999 NTSTATUS status; 3000 UNICODE_STRING nameW; 3001 LDR_RESOURCE_INFO info; 3002 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL; 3003 void *ptr; 3004 3005 //DPRINT( "looking for res %s in module %p %s\n", resname, 3006 // hModule, filename ); 3007 DPRINT("get_manifest_in_module %p\n", hModule); 3008 3009 #if 0 3010 if (TRACE_ON(actctx)) 3011 { 3012 if (!filename && !get_module_filename( hModule, &nameW, 0 )) 3013 { 3014 TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), 3015 hModule, debugstr_w(nameW.Buffer) ); 3016 RtlFreeUnicodeString( &nameW ); 3017 } 3018 else TRACE( "looking for res %s in module %p %s\n", debugstr_w(resname), 3019 hModule, debugstr_w(filename) ); 3020 } 3021 #endif 3022 3023 if (!resname) return STATUS_INVALID_PARAMETER; 3024 3025 info.Type = RT_MANIFEST; 3026 info.Language = lang; 3027 if (!((ULONG_PTR)resname >> 16)) 3028 { 3029 info.Name = (ULONG_PTR)resname; 3030 status = LdrFindResource_U(hModule, &info, 3, &entry); 3031 } 3032 else if (resname[0] == '#') 3033 { 3034 ULONG value; 3035 RtlInitUnicodeString(&nameW, resname + 1); 3036 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value)) 3037 return STATUS_INVALID_PARAMETER; 3038 info.Name = value; 3039 status = LdrFindResource_U(hModule, &info, 3, &entry); 3040 } 3041 else 3042 { 3043 RtlCreateUnicodeString(&nameW, resname); 3044 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE); 3045 info.Name = (ULONG_PTR)nameW.Buffer; 3046 status = LdrFindResource_U(hModule, &info, 3, &entry); 3047 RtlFreeUnicodeString(&nameW); 3048 } 3049 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL); 3050 3051 if (status == STATUS_SUCCESS) 3052 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size); 3053 3054 return status; 3055 } 3056 3057 #ifdef __REACTOS__ 3058 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir, 3059 LPCWSTR name, void *root, 3060 int want_dir ); 3061 3062 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir, 3063 void *root, int want_dir ); 3064 3065 3066 static IMAGE_RESOURCE_DIRECTORY *find_first_id_entry( IMAGE_RESOURCE_DIRECTORY *dir, 3067 void *root, int want_dir ) 3068 { 3069 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); 3070 int pos; 3071 3072 for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++) 3073 { 3074 if (!entry[pos].DataIsDirectory == !want_dir) 3075 return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory); 3076 } 3077 return NULL; 3078 } 3079 3080 3081 static NTSTATUS search_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 3082 LPCWSTR filename, LPCWSTR directory, BOOL shared, 3083 HANDLE hModule, ULONG lang ) 3084 { 3085 ULONG size; 3086 PVOID root, ptr; 3087 IMAGE_RESOURCE_DIRECTORY *resdirptr; 3088 IMAGE_RESOURCE_DATA_ENTRY *entry; 3089 NTSTATUS status; 3090 3091 root = RtlImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); 3092 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; 3093 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; 3094 resdirptr = root; 3095 3096 if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1))) 3097 return STATUS_RESOURCE_TYPE_NOT_FOUND; 3098 3099 resdirptr = ptr; 3100 if (!(ptr = find_first_id_entry(resdirptr, root, 1))) 3101 return STATUS_RESOURCE_TYPE_NOT_FOUND; 3102 3103 resdirptr = ptr; 3104 if (!(ptr = find_first_entry(resdirptr, root, 0))) 3105 return STATUS_RESOURCE_TYPE_NOT_FOUND; 3106 3107 entry = ptr; 3108 status = LdrAccessResource(hModule, entry, &ptr, NULL); 3109 3110 if (status == STATUS_SUCCESS) 3111 status = parse_manifest(acl, ai, filename, hModule, directory, shared, ptr, entry->Size); 3112 3113 return status; 3114 } 3115 #endif // __REACTOS__ 3116 3117 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai, 3118 LPCWSTR filename, LPCWSTR directory, BOOL shared, 3119 HANDLE file, LPCWSTR resname, ULONG lang ) 3120 { 3121 HANDLE mapping; 3122 OBJECT_ATTRIBUTES attr; 3123 LARGE_INTEGER size; 3124 LARGE_INTEGER offset; 3125 NTSTATUS status; 3126 SIZE_T count; 3127 void *base; 3128 WCHAR resnameBuf[20]; 3129 LPCWSTR resptr = resname; 3130 3131 if ((!((ULONG_PTR)resname >> 16))) 3132 { 3133 _swprintf(resnameBuf, L"#%u", PtrToUlong(resname)); 3134 resptr = resnameBuf; 3135 } 3136 3137 DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>"); 3138 3139 attr.Length = sizeof(attr); 3140 attr.RootDirectory = 0; 3141 attr.ObjectName = NULL; 3142 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3143 attr.SecurityDescriptor = NULL; 3144 attr.SecurityQualityOfService = NULL; 3145 3146 size.QuadPart = 0; 3147 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3148 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3149 if (status != STATUS_SUCCESS) return status; 3150 3151 offset.QuadPart = 0; 3152 count = 0; 3153 base = NULL; 3154 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset, 3155 &count, ViewShare, 0, PAGE_READONLY ); 3156 NtClose( mapping ); 3157 if (status != STATUS_SUCCESS) return status; 3158 3159 if (RtlImageNtHeader(base)) /* we got a PE file */ 3160 { 3161 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */ 3162 if (resname) 3163 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang ); 3164 else 3165 status = search_manifest_in_module(acl, ai, filename, directory, shared, module, lang); 3166 } 3167 else status = STATUS_INVALID_IMAGE_FORMAT; 3168 3169 NtUnmapViewOfSection( GetCurrentProcess(), base ); 3170 return status; 3171 } 3172 3173 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai, 3174 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file ) 3175 { 3176 FILE_END_OF_FILE_INFORMATION info; 3177 IO_STATUS_BLOCK io; 3178 HANDLE mapping; 3179 OBJECT_ATTRIBUTES attr; 3180 LARGE_INTEGER size; 3181 LARGE_INTEGER offset; 3182 NTSTATUS status; 3183 SIZE_T count; 3184 void *base; 3185 3186 TRACE( "loading manifest file %s\n", debugstr_w(filename) ); 3187 3188 attr.Length = sizeof(attr); 3189 attr.RootDirectory = 0; 3190 attr.ObjectName = NULL; 3191 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3192 attr.SecurityDescriptor = NULL; 3193 attr.SecurityQualityOfService = NULL; 3194 3195 size.QuadPart = 0; 3196 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3197 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3198 if (status != STATUS_SUCCESS) return status; 3199 3200 offset.QuadPart = 0; 3201 count = 0; 3202 base = NULL; 3203 status = NtMapViewOfSection( mapping, GetCurrentProcess(), &base, 0, 0, &offset, 3204 &count, ViewShare, 0, PAGE_READONLY ); 3205 NtClose( mapping ); 3206 if (status != STATUS_SUCCESS) return status; 3207 3208 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileEndOfFileInformation ); 3209 if (status == STATUS_SUCCESS) 3210 status = parse_manifest(acl, ai, filename, NULL, directory, shared, base, info.EndOfFile.QuadPart); 3211 3212 NtUnmapViewOfSection( GetCurrentProcess(), base ); 3213 return status; 3214 } 3215 3216 /* try to load the .manifest file associated to the file */ 3217 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 3218 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname ) 3219 { 3220 static const WCHAR fmtW[] = { '.','%','l','u',0 }; 3221 WCHAR *buffer; 3222 NTSTATUS status; 3223 UNICODE_STRING nameW; 3224 HANDLE file; 3225 ULONG_PTR resid = CREATEPROCESS_MANIFEST_RESOURCE_ID; 3226 3227 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff; 3228 3229 TRACE( "looking for manifest associated with %s id %lu\n", debugstr_w(filename), resid ); 3230 3231 if (module) /* use the module filename */ 3232 { 3233 UNICODE_STRING name; 3234 3235 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) ))) 3236 { 3237 if (resid != 1) swprintf( name.Buffer + wcslen(name.Buffer), 10, fmtW, resid ); 3238 wcscat( name.Buffer, dotManifestW ); 3239 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL )) 3240 status = STATUS_RESOURCE_DATA_NOT_FOUND; 3241 RtlFreeUnicodeString( &name ); 3242 } 3243 if (status) return status; 3244 } 3245 else 3246 { 3247 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, 3248 (wcslen(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3249 return STATUS_NO_MEMORY; 3250 wcscpy( buffer, filename ); 3251 if (resid != 1) swprintf( buffer + wcslen(buffer), 10, fmtW, resid ); 3252 wcscat( buffer, dotManifestW ); 3253 RtlInitUnicodeString( &nameW, buffer ); 3254 } 3255 3256 if (!open_nt_file( &file, &nameW )) 3257 { 3258 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3259 NtClose( file ); 3260 } 3261 else status = STATUS_RESOURCE_TYPE_NOT_FOUND; 3262 RtlFreeUnicodeString( &nameW ); 3263 return status; 3264 } 3265 3266 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai ) 3267 { 3268 static const WCHAR lookup_fmtW[] = 3269 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_', 3270 '%','s','_','*','.','m','a','n','i','f','e','s','t',0}; 3271 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'}; 3272 3273 WCHAR *lookup, *ret = NULL; 3274 UNICODE_STRING lookup_us; 3275 IO_STATUS_BLOCK io; 3276 const WCHAR *lang = ai->language; 3277 unsigned int data_pos = 0, data_len, len; 3278 char buffer[8192]; 3279 3280 if (!lang || !wcsicmp( lang, neutralW )) lang = wildcardW; 3281 3282 len = wcslen(ai->arch) + wcslen(ai->name) + wcslen(ai->public_key) + wcslen(lang) + 20 + ARRAY_SIZE(lookup_fmtW); 3283 if (!(lookup = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return NULL; 3284 swprintf( lookup, len, lookup_fmtW, ai->arch, ai->name, ai->public_key, 3285 ai->version.major, ai->version.minor, lang ); 3286 RtlInitUnicodeString( &lookup_us, lookup ); 3287 3288 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3289 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE )) 3290 { 3291 ULONG min_build = ai->version.build, min_revision = ai->version.revision; 3292 FILE_BOTH_DIR_INFORMATION *dir_info; 3293 WCHAR *tmp; 3294 ULONG build, revision; 3295 3296 data_len = io.Information; 3297 3298 for (;;) 3299 { 3300 if (data_pos >= data_len) 3301 { 3302 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3303 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE )) 3304 break; 3305 data_len = io.Information; 3306 data_pos = 0; 3307 } 3308 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos); 3309 3310 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset; 3311 else data_pos = data_len; 3312 3313 tmp = (WCHAR *)dir_info->FileName + (wcschr(lookup, '*') - lookup); 3314 build = wcstoul( tmp, NULL, 10 ); 3315 if (build < min_build) continue; 3316 tmp = wcschr(tmp, '.') + 1; 3317 revision = wcstoul( tmp, NULL, 10 ); 3318 if (build == min_build && revision < min_revision) continue; 3319 tmp = wcschr(tmp, '_') + 1; 3320 tmp = wcschr(tmp, '_') + 1; 3321 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) && 3322 !wcsnicmp( tmp, wine_trailerW, ARRAY_SIZE( wine_trailerW ))) 3323 { 3324 /* prefer a non-Wine manifest if we already have one */ 3325 /* we'll still load the builtin dll if specified through DllOverrides */ 3326 if (ret) continue; 3327 } 3328 else 3329 { 3330 min_build = build; 3331 min_revision = revision; 3332 } 3333 ai->version.build = build; 3334 ai->version.revision = revision; 3335 RtlFreeHeap( GetProcessHeap(), 0, ret ); 3336 if ((ret = RtlAllocateHeap( GetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) ))) 3337 { 3338 memcpy( ret, dir_info->FileName, dir_info->FileNameLength ); 3339 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0; 3340 } 3341 } 3342 } 3343 else WARN("no matching file for %s\n", debugstr_w(lookup)); 3344 RtlFreeHeap( GetProcessHeap(), 0, lookup ); 3345 return ret; 3346 } 3347 3348 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai) 3349 { 3350 struct assembly_identity sxs_ai; 3351 UNICODE_STRING path_us; 3352 OBJECT_ATTRIBUTES attr; 3353 IO_STATUS_BLOCK io; 3354 WCHAR *path, *file = NULL; 3355 HANDLE handle; 3356 3357 static const WCHAR manifest_dirW[] = 3358 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0}; 3359 3360 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE; 3361 3362 if (!(path = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(manifest_dirW) + 3363 wcslen(windows_dir) * sizeof(WCHAR) ))) 3364 return STATUS_NO_MEMORY; 3365 3366 wcscpy( path, windows_dir ); 3367 wcscat( path, manifest_dirW ); 3368 3369 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL )) 3370 { 3371 RtlFreeHeap( GetProcessHeap(), 0, path ); 3372 return STATUS_NO_SUCH_FILE; 3373 } 3374 RtlFreeHeap( GetProcessHeap(), 0, path ); 3375 3376 attr.Length = sizeof(attr); 3377 attr.RootDirectory = 0; 3378 attr.Attributes = OBJ_CASE_INSENSITIVE; 3379 attr.ObjectName = &path_us; 3380 attr.SecurityDescriptor = NULL; 3381 attr.SecurityQualityOfService = NULL; 3382 3383 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, 3384 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) 3385 { 3386 sxs_ai = *ai; 3387 file = lookup_manifest_file( handle, &sxs_ai ); 3388 NtClose( handle ); 3389 } 3390 if (!file) 3391 { 3392 RtlFreeUnicodeString( &path_us ); 3393 return STATUS_NO_SUCH_FILE; 3394 } 3395 3396 /* append file name to directory path */ 3397 if (!(path = RtlReAllocateHeap( GetProcessHeap(), 0, path_us.Buffer, 3398 path_us.Length + (wcslen(file) + 2) * sizeof(WCHAR) ))) 3399 { 3400 RtlFreeHeap( GetProcessHeap(), 0, file ); 3401 RtlFreeUnicodeString( &path_us ); 3402 return STATUS_NO_MEMORY; 3403 } 3404 3405 path[path_us.Length/sizeof(WCHAR)] = '\\'; 3406 wcscpy( path + path_us.Length/sizeof(WCHAR) + 1, file ); 3407 RtlInitUnicodeString( &path_us, path ); 3408 *wcsrchr(file, '.') = 0; /* remove .manifest extension */ 3409 3410 if (!open_nt_file( &handle, &path_us )) 3411 { 3412 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle); 3413 NtClose( handle ); 3414 } 3415 else io.Status = STATUS_NO_SUCH_FILE; 3416 3417 RtlFreeHeap( GetProcessHeap(), 0, file ); 3418 RtlFreeUnicodeString( &path_us ); 3419 return io.Status; 3420 } 3421 3422 static NTSTATUS lookup_assembly(struct actctx_loader* acl, 3423 struct assembly_identity* ai) 3424 { 3425 static const WCHAR dotDllW[] = {'.','d','l','l',0}; 3426 unsigned int i; 3427 WCHAR *buffer, *p, *directory; 3428 NTSTATUS status; 3429 UNICODE_STRING nameW; 3430 HANDLE file; 3431 DWORD len; 3432 3433 TRACE( "looking for name=%s version=%s arch=%s\n", 3434 debugstr_w(ai->name), debugstr_version(&ai->version), debugstr_w(ai->arch) ); 3435 3436 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status; 3437 3438 /* FIXME: add support for language specific lookup */ 3439 3440 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR), 3441 wcslen(acl->actctx->appdir.info)); 3442 3443 nameW.Buffer = NULL; 3444 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, 3445 (len + 2 * wcslen(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3446 return STATUS_NO_MEMORY; 3447 3448 if (!(directory = build_assembly_dir( ai ))) 3449 { 3450 RtlFreeHeap( GetProcessHeap(), 0, buffer ); 3451 return STATUS_NO_MEMORY; 3452 } 3453 3454 /* Lookup in <dir>\name.dll 3455 * <dir>\name.manifest 3456 * <dir>\name\name.dll 3457 * <dir>\name\name.manifest 3458 * 3459 * First 'appdir' is used as <dir>, if that failed 3460 * it tries application manifest file path. 3461 */ 3462 wcscpy( buffer, acl->actctx->appdir.info ); 3463 p = buffer + wcslen(buffer); 3464 for (i = 0; i < 4; i++) 3465 { 3466 if (i == 2) 3467 { 3468 struct assembly *assembly = acl->actctx->assemblies; 3469 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break; 3470 } 3471 else *p++ = '\\'; 3472 3473 wcscpy( p, ai->name ); 3474 p += wcslen(p); 3475 3476 wcscpy( p, dotDllW ); 3477 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3478 { 3479 status = open_nt_file( &file, &nameW ); 3480 if (!status) 3481 { 3482 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, 3483 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 ); 3484 NtClose( file ); 3485 if (status == STATUS_SUCCESS) 3486 break; 3487 } 3488 RtlFreeUnicodeString( &nameW ); 3489 } 3490 3491 wcscpy( p, dotManifestW ); 3492 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3493 { 3494 status = open_nt_file( &file, &nameW ); 3495 if (!status) 3496 { 3497 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3498 NtClose( file ); 3499 break; 3500 } 3501 RtlFreeUnicodeString( &nameW ); 3502 } 3503 status = STATUS_SXS_ASSEMBLY_NOT_FOUND; 3504 } 3505 RtlFreeUnicodeString( &nameW ); 3506 RtlFreeHeap( GetProcessHeap(), 0, directory ); 3507 RtlFreeHeap( GetProcessHeap(), 0, buffer ); 3508 return status; 3509 } 3510 3511 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) 3512 { 3513 NTSTATUS status = STATUS_SUCCESS; 3514 unsigned int i; 3515 3516 for (i = 0; i < acl->num_dependencies; i++) 3517 { 3518 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS) 3519 { 3520 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed) 3521 { 3522 FIXME( "Could not find dependent assembly %s (%s)\n", 3523 debugstr_w(acl->dependencies[i].name), 3524 debugstr_version(&acl->dependencies[i].version) ); 3525 status = STATUS_SXS_CANT_GEN_ACTCTX; 3526 break; 3527 } 3528 } 3529 } 3530 /* FIXME should now iterate through all refs */ 3531 return status; 3532 } 3533 3534 /* find the appropriate activation context for RtlQueryInformationActivationContext */ 3535 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class ) 3536 { 3537 NTSTATUS status = STATUS_SUCCESS; 3538 3539 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT) 3540 { 3541 if (*handle) return STATUS_INVALID_PARAMETER; 3542 3543 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 3544 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 3545 } 3546 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE)) 3547 { 3548 ULONG_PTR magic; 3549 LDR_DATA_TABLE_ENTRY *pldr; 3550 3551 if (!*handle) return STATUS_INVALID_PARAMETER; 3552 3553 LdrLockLoaderLock( 0, NULL, &magic ); 3554 if (!LdrFindEntryForAddress( *handle, &pldr )) 3555 { 3556 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase) 3557 status = STATUS_DLL_NOT_FOUND; 3558 else 3559 *handle = pldr->EntryPointActivationContext; 3560 } 3561 else status = STATUS_DLL_NOT_FOUND; 3562 LdrUnlockLoaderLock( 0, magic ); 3563 } 3564 else if (!*handle && (class != ActivationContextBasicInformation)) 3565 *handle = process_actctx; 3566 3567 return status; 3568 } 3569 3570 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3571 { 3572 unsigned int i, j, total_len = 0, dll_count = 0; 3573 struct strsection_header *header; 3574 struct dllredirect_data *data; 3575 struct string_index *index; 3576 ULONG name_offset; 3577 3578 DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies); 3579 3580 /* compute section length */ 3581 for (i = 0; i < actctx->num_assemblies; i++) 3582 { 3583 struct assembly *assembly = &actctx->assemblies[i]; 3584 for (j = 0; j < assembly->num_dlls; j++) 3585 { 3586 struct dll_redirect *dll = &assembly->dlls[j]; 3587 3588 /* each entry needs index, data and string data */ 3589 total_len += sizeof(*index); 3590 total_len += sizeof(*data); 3591 total_len += aligned_string_len((wcslen(dll->name)+1)*sizeof(WCHAR)); 3592 3593 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name); 3594 } 3595 3596 dll_count += assembly->num_dlls; 3597 } 3598 3599 total_len += sizeof(*header); 3600 3601 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 3602 if (!header) return STATUS_NO_MEMORY; 3603 3604 memset(header, 0, sizeof(*header)); 3605 header->magic = STRSECTION_MAGIC; 3606 header->size = sizeof(*header); 3607 header->count = dll_count; 3608 header->index_offset = sizeof(*header); 3609 index = (struct string_index*)((BYTE*)header + header->index_offset); 3610 name_offset = header->index_offset + header->count*sizeof(*index); 3611 3612 for (i = 0; i < actctx->num_assemblies; i++) 3613 { 3614 struct assembly *assembly = &actctx->assemblies[i]; 3615 3616 DPRINT("assembly->num_dlls %d\n", assembly->num_dlls); 3617 3618 for (j = 0; j < assembly->num_dlls; j++) 3619 { 3620 struct dll_redirect *dll = &assembly->dlls[j]; 3621 UNICODE_STRING str; 3622 WCHAR *ptrW; 3623 3624 DPRINT("%d: dll name %S\n", j, dll->name); 3625 /* setup new index entry */ 3626 str.Buffer = dll->name; 3627 str.Length = wcslen(dll->name)*sizeof(WCHAR); 3628 str.MaximumLength = str.Length + sizeof(WCHAR); 3629 /* hash original class name */ 3630 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3631 3632 index->name_offset = name_offset; 3633 index->name_len = str.Length; 3634 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3635 index->data_len = sizeof(*data); 3636 index->rosterindex = i + 1; 3637 3638 /* setup data */ 3639 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset); 3640 data->size = sizeof(*data); 3641 data->unk = 2; /* FIXME: seems to be constant */ 3642 memset(data->res, 0, sizeof(data->res)); 3643 3644 /* dll name */ 3645 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3646 memcpy(ptrW, dll->name, index->name_len); 3647 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3648 3649 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength); 3650 3651 index++; 3652 } 3653 } 3654 3655 *section = header; 3656 3657 return STATUS_SUCCESS; 3658 } 3659 3660 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name) 3661 { 3662 struct string_index *iter, *index = NULL; 3663 UNICODE_STRING str; 3664 ULONG hash = 0, i; 3665 3666 DPRINT("section %p, name %wZ\n", section, name); 3667 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3668 iter = (struct string_index*)((BYTE*)section + section->index_offset); 3669 3670 for (i = 0; i < section->count; i++) 3671 { 3672 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash); 3673 DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset)); 3674 if (iter->hash == hash) 3675 { 3676 str.Buffer = (WCHAR *)((BYTE *)section + iter->name_offset); 3677 str.Length = iter->name_len; 3678 if (RtlEqualUnicodeString( &str, name, TRUE )) 3679 { 3680 index = iter; 3681 break; 3682 } 3683 else 3684 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(g_nameW)); 3685 } 3686 iter++; 3687 } 3688 3689 return index; 3690 } 3691 3692 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid) 3693 { 3694 struct guid_index *iter, *index = NULL; 3695 ULONG i; 3696 3697 iter = (struct guid_index*)((BYTE*)section + section->index_offset); 3698 3699 for (i = 0; i < section->count; i++) 3700 { 3701 if (!memcmp(guid, &iter->guid, sizeof(*guid))) 3702 { 3703 index = iter; 3704 break; 3705 } 3706 iter++; 3707 } 3708 3709 return index; 3710 } 3711 3712 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3713 { 3714 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset); 3715 } 3716 3717 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3718 PACTCTX_SECTION_KEYED_DATA data) 3719 { 3720 struct dllredirect_data *dll; 3721 struct string_index *index; 3722 3723 DPRINT("sections: 0x%08X\n", actctx->sections); 3724 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3725 3726 DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section); 3727 if (!actctx->dllredirect_section) 3728 { 3729 struct strsection_header *section; 3730 3731 NTSTATUS status = build_dllredirect_section(actctx, §ion); 3732 if (status) return status; 3733 3734 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL)) 3735 RtlFreeHeap(GetProcessHeap(), 0, section); 3736 } 3737 3738 index = find_string_index(actctx->dllredirect_section, name); 3739 DPRINT("index: %d\n", index); 3740 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3741 3742 if (data) 3743 { 3744 dll = get_dllredirect_data(actctx, index); 3745 3746 data->ulDataFormatVersion = 1; 3747 data->lpData = dll; 3748 data->ulLength = dll->size; 3749 data->lpSectionGlobalData = NULL; 3750 data->ulSectionGlobalDataLength = 0; 3751 data->lpSectionBase = actctx->dllredirect_section; 3752 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->dllredirect_section ); 3753 data->hActCtx = NULL; 3754 3755 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3756 data->ulAssemblyRosterIndex = index->rosterindex; 3757 } 3758 3759 return STATUS_SUCCESS; 3760 } 3761 3762 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx) 3763 { 3764 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset); 3765 } 3766 3767 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3768 { 3769 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset); 3770 } 3771 3772 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3773 { 3774 unsigned int i, j, k, total_len = 0, class_count = 0; 3775 struct wndclass_redirect_data *data; 3776 struct strsection_header *header; 3777 struct string_index *index; 3778 ULONG name_offset; 3779 3780 /* compute section length */ 3781 for (i = 0; i < actctx->num_assemblies; i++) 3782 { 3783 struct assembly *assembly = &actctx->assemblies[i]; 3784 for (j = 0; j < assembly->num_dlls; j++) 3785 { 3786 struct dll_redirect *dll = &assembly->dlls[j]; 3787 for (k = 0; k < dll->entities.num; k++) 3788 { 3789 struct entity *entity = &dll->entities.base[k]; 3790 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3791 { 3792 int class_len = wcslen(entity->u.class.name) + 1; 3793 int len; 3794 3795 /* each class entry needs index, data and string data */ 3796 total_len += sizeof(*index); 3797 total_len += sizeof(*data); 3798 /* original name is stored separately */ 3799 total_len += aligned_string_len(class_len*sizeof(WCHAR)); 3800 /* versioned name and module name are stored one after another */ 3801 if (entity->u.class.versioned) 3802 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */; 3803 else 3804 len = class_len; 3805 len += wcslen(dll->name) + 1; 3806 total_len += aligned_string_len(len*sizeof(WCHAR)); 3807 3808 class_count++; 3809 } 3810 } 3811 } 3812 } 3813 3814 total_len += sizeof(*header); 3815 3816 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 3817 if (!header) return STATUS_NO_MEMORY; 3818 3819 memset(header, 0, sizeof(*header)); 3820 header->magic = STRSECTION_MAGIC; 3821 header->size = sizeof(*header); 3822 header->count = class_count; 3823 header->index_offset = sizeof(*header); 3824 index = (struct string_index*)((BYTE*)header + header->index_offset); 3825 name_offset = header->index_offset + header->count*sizeof(*index); 3826 3827 for (i = 0; i < actctx->num_assemblies; i++) 3828 { 3829 struct assembly *assembly = &actctx->assemblies[i]; 3830 for (j = 0; j < assembly->num_dlls; j++) 3831 { 3832 struct dll_redirect *dll = &assembly->dlls[j]; 3833 for (k = 0; k < dll->entities.num; k++) 3834 { 3835 struct entity *entity = &dll->entities.base[k]; 3836 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3837 { 3838 static const WCHAR exclW[] = {'!',0}; 3839 ULONG versioned_len, module_len; 3840 UNICODE_STRING str; 3841 WCHAR *ptrW; 3842 3843 /* setup new index entry */ 3844 str.Buffer = entity->u.class.name; 3845 str.Length = wcslen(entity->u.class.name)*sizeof(WCHAR); 3846 str.MaximumLength = str.Length + sizeof(WCHAR); 3847 /* hash original class name */ 3848 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3849 3850 /* include '!' separator too */ 3851 if (entity->u.class.versioned) 3852 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length; 3853 else 3854 versioned_len = str.Length; 3855 module_len = wcslen(dll->name)*sizeof(WCHAR); 3856 3857 index->name_offset = name_offset; 3858 index->name_len = str.Length; 3859 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3860 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */; 3861 index->rosterindex = i + 1; 3862 3863 /* setup data */ 3864 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset); 3865 data->size = sizeof(*data); 3866 data->res = 0; 3867 data->name_len = versioned_len; 3868 data->name_offset = sizeof(*data); 3869 data->module_len = module_len; 3870 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR); 3871 3872 /* original class name */ 3873 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3874 memcpy(ptrW, entity->u.class.name, index->name_len); 3875 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3876 3877 /* module name */ 3878 ptrW = (WCHAR*)((BYTE*)header + data->module_offset); 3879 memcpy(ptrW, dll->name, data->module_len); 3880 ptrW[data->module_len/sizeof(WCHAR)] = 0; 3881 3882 /* versioned name */ 3883 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 3884 if (entity->u.class.versioned) 3885 { 3886 get_assembly_version(assembly, ptrW); 3887 wcscat(ptrW, exclW); 3888 wcscat(ptrW, entity->u.class.name); 3889 } 3890 else 3891 { 3892 memcpy(ptrW, entity->u.class.name, index->name_len); 3893 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3894 } 3895 3896 name_offset += sizeof(*data); 3897 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR)); 3898 3899 index++; 3900 } 3901 } 3902 } 3903 } 3904 3905 *section = header; 3906 3907 return STATUS_SUCCESS; 3908 } 3909 3910 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3911 PACTCTX_SECTION_KEYED_DATA data) 3912 { 3913 struct string_index *iter, *index = NULL; 3914 struct wndclass_redirect_data *class; 3915 UNICODE_STRING str; 3916 ULONG hash; 3917 int i; 3918 3919 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3920 3921 if (!actctx->wndclass_section) 3922 { 3923 struct strsection_header *section; 3924 3925 NTSTATUS status = build_wndclass_section(actctx, §ion); 3926 if (status) return status; 3927 3928 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL)) 3929 RtlFreeHeap(GetProcessHeap(), 0, section); 3930 } 3931 3932 hash = 0; 3933 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3934 iter = get_wndclass_first_index(actctx); 3935 3936 for (i = 0; i < actctx->wndclass_section->count; i++) 3937 { 3938 if (iter->hash == hash) 3939 { 3940 str.Buffer = (WCHAR *)((BYTE *)actctx->wndclass_section + iter->name_offset); 3941 str.Length = iter->name_len; 3942 if (RtlEqualUnicodeString( &str, name, TRUE )) 3943 { 3944 index = iter; 3945 break; 3946 } 3947 else 3948 WARN("hash collision 0x%08x, %s, %s\n", hash, debugstr_us(name), debugstr_w(g_nameW)); 3949 } 3950 iter++; 3951 } 3952 3953 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3954 3955 if (data) 3956 { 3957 class = get_wndclass_data(actctx, index); 3958 3959 data->ulDataFormatVersion = 1; 3960 data->lpData = class; 3961 /* full length includes string length with nulls */ 3962 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR); 3963 data->lpSectionGlobalData = NULL; 3964 data->ulSectionGlobalDataLength = 0; 3965 data->lpSectionBase = actctx->wndclass_section; 3966 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->wndclass_section ); 3967 data->hActCtx = NULL; 3968 3969 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3970 data->ulAssemblyRosterIndex = index->rosterindex; 3971 } 3972 3973 return STATUS_SUCCESS; 3974 } 3975 3976 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 3977 { 3978 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0; 3979 struct guidsection_header *header; 3980 ULONG module_offset, data_offset; 3981 struct tlibredirect_data *data; 3982 struct guid_index *index; 3983 3984 /* compute section length */ 3985 for (i = 0; i < actctx->num_assemblies; i++) 3986 { 3987 struct assembly *assembly = &actctx->assemblies[i]; 3988 for (j = 0; j < assembly->num_dlls; j++) 3989 { 3990 struct dll_redirect *dll = &assembly->dlls[j]; 3991 for (k = 0; k < dll->entities.num; k++) 3992 { 3993 struct entity *entity = &dll->entities.base[k]; 3994 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3995 { 3996 /* each entry needs index, data and string data for module name and help string */ 3997 total_len += sizeof(*index); 3998 total_len += sizeof(*data); 3999 /* help string is stored separately */ 4000 if (*entity->u.typelib.helpdir) 4001 total_len += aligned_string_len((wcslen(entity->u.typelib.helpdir)+1)*sizeof(WCHAR)); 4002 4003 /* module names are packed one after another */ 4004 names_len += (wcslen(dll->name)+1)*sizeof(WCHAR); 4005 4006 tlib_count++; 4007 } 4008 } 4009 } 4010 } 4011 4012 total_len += aligned_string_len(names_len); 4013 total_len += sizeof(*header); 4014 4015 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 4016 if (!header) return STATUS_NO_MEMORY; 4017 4018 memset(header, 0, sizeof(*header)); 4019 header->magic = GUIDSECTION_MAGIC; 4020 header->size = sizeof(*header); 4021 header->count = tlib_count; 4022 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 4023 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4024 module_offset = sizeof(*header); 4025 data_offset = header->index_offset + tlib_count*sizeof(*index); 4026 4027 for (i = 0; i < actctx->num_assemblies; i++) 4028 { 4029 struct assembly *assembly = &actctx->assemblies[i]; 4030 for (j = 0; j < assembly->num_dlls; j++) 4031 { 4032 struct dll_redirect *dll = &assembly->dlls[j]; 4033 for (k = 0; k < dll->entities.num; k++) 4034 { 4035 struct entity *entity = &dll->entities.base[k]; 4036 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 4037 { 4038 ULONG module_len, help_len; 4039 UNICODE_STRING str; 4040 WCHAR *ptrW; 4041 NTSTATUS Status; 4042 4043 if (*entity->u.typelib.helpdir) 4044 help_len = wcslen(entity->u.typelib.helpdir)*sizeof(WCHAR); 4045 else 4046 help_len = 0; 4047 4048 module_len = wcslen(dll->name)*sizeof(WCHAR); 4049 4050 /* setup new index entry */ 4051 RtlInitUnicodeString(&str, entity->u.typelib.tlbid); 4052 Status = RtlGUIDFromString(&str, &index->guid); 4053 if (!NT_SUCCESS(Status)) 4054 { 4055 RtlFreeHeap(GetProcessHeap(), 0, header); 4056 return Status; 4057 } 4058 index->data_offset = data_offset; 4059 index->data_len = sizeof(*data) + aligned_string_len(help_len); 4060 index->rosterindex = i + 1; 4061 4062 /* setup data */ 4063 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset); 4064 data->size = sizeof(*data); 4065 data->res = 0; 4066 data->name_len = module_len; 4067 data->name_offset = module_offset; 4068 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */ 4069 data->langid = 0; 4070 data->flags = entity->u.typelib.flags; 4071 data->help_len = help_len; 4072 data->help_offset = sizeof(*data); 4073 data->major_version = entity->u.typelib.major; 4074 data->minor_version = entity->u.typelib.minor; 4075 4076 /* module name */ 4077 ptrW = (WCHAR*)((BYTE*)header + data->name_offset); 4078 memcpy(ptrW, dll->name, data->name_len); 4079 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4080 4081 /* help string */ 4082 if (data->help_len) 4083 { 4084 ptrW = (WCHAR*)((BYTE*)data + data->help_offset); 4085 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len); 4086 ptrW[data->help_len/sizeof(WCHAR)] = 0; 4087 } 4088 4089 data_offset += sizeof(*data); 4090 if (help_len) 4091 data_offset += aligned_string_len(help_len + sizeof(WCHAR)); 4092 4093 module_offset += module_len + sizeof(WCHAR); 4094 4095 index++; 4096 } 4097 } 4098 } 4099 } 4100 4101 *section = header; 4102 4103 return STATUS_SUCCESS; 4104 } 4105 4106 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4107 { 4108 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset); 4109 } 4110 4111 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4112 { 4113 struct guid_index *index = NULL; 4114 struct tlibredirect_data *tlib; 4115 4116 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4117 4118 if (!actctx->tlib_section) 4119 { 4120 struct guidsection_header *section; 4121 4122 NTSTATUS status = build_tlib_section(actctx, §ion); 4123 if (status) return status; 4124 4125 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL)) 4126 RtlFreeHeap(GetProcessHeap(), 0, section); 4127 } 4128 4129 index = find_guid_index(actctx->tlib_section, guid); 4130 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4131 4132 tlib = get_tlib_data(actctx, index); 4133 4134 data->ulDataFormatVersion = 1; 4135 data->lpData = tlib; 4136 /* full length includes string length with nulls */ 4137 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR); 4138 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset; 4139 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len; 4140 data->lpSectionBase = actctx->tlib_section; 4141 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->tlib_section ); 4142 data->hActCtx = NULL; 4143 4144 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4145 data->ulAssemblyRosterIndex = index->rosterindex; 4146 4147 return STATUS_SUCCESS; 4148 } 4149 4150 static void generate_uuid(ULONG *seed, GUID *guid) 4151 { 4152 ULONG *ptr = (ULONG*)guid; 4153 int i; 4154 4155 /* GUID is 16 bytes long */ 4156 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++) 4157 *ptr = RtlUniform(seed); 4158 4159 guid->Data3 &= 0x0fff; 4160 guid->Data3 |= (4 << 12); 4161 guid->Data4[0] &= 0x3f; 4162 guid->Data4[0] |= 0x80; 4163 } 4164 4165 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll, 4166 unsigned int *count, unsigned int *len, unsigned int *module_len) 4167 { 4168 unsigned int i; 4169 4170 for (i = 0; i < entities->num; i++) 4171 { 4172 struct entity *entity = &entities->base[i]; 4173 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4174 { 4175 /* each entry needs two index entries, extra one goes for alias GUID */ 4176 *len += 2*sizeof(struct guid_index); 4177 /* To save some memory we don't allocated two data structures, 4178 instead alias index and normal index point to the same data structure. */ 4179 *len += sizeof(struct comclassredirect_data); 4180 4181 /* for clrClass store some more */ 4182 if (entity->u.comclass.name) 4183 { 4184 unsigned int str_len; 4185 4186 /* all string data is stored together in aligned block */ 4187 str_len = wcslen(entity->u.comclass.name)+1; 4188 if (entity->u.comclass.progid) 4189 str_len += wcslen(entity->u.comclass.progid)+1; 4190 if (entity->u.comclass.version) 4191 str_len += wcslen(entity->u.comclass.version)+1; 4192 4193 *len += sizeof(struct clrclass_data); 4194 *len += aligned_string_len(str_len*sizeof(WCHAR)); 4195 4196 /* module name is forced to mscoree.dll, and stored two times with different case */ 4197 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W); 4198 } 4199 else 4200 { 4201 /* progid string is stored separately */ 4202 if (entity->u.comclass.progid) 4203 *len += aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4204 4205 *module_len += (wcslen(dll->name)+1)*sizeof(WCHAR); 4206 } 4207 4208 *count += 1; 4209 } 4210 } 4211 } 4212 4213 static NTSTATUS add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities, 4214 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset, 4215 ULONG *seed, ULONG rosterindex) 4216 { 4217 unsigned int i; 4218 NTSTATUS Status; 4219 4220 for (i = 0; i < entities->num; i++) 4221 { 4222 struct entity *entity = &entities->base[i]; 4223 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4224 { 4225 ULONG module_len, progid_len, str_len = 0, miscmask; 4226 struct comclassredirect_data *data; 4227 struct guid_index *alias_index; 4228 struct clrclass_data *clrdata; 4229 UNICODE_STRING str; 4230 WCHAR *ptrW; 4231 4232 if (entity->u.comclass.progid) 4233 progid_len = wcslen(entity->u.comclass.progid)*sizeof(WCHAR); 4234 else 4235 progid_len = 0; 4236 4237 module_len = dll ? wcslen(dll->name)*sizeof(WCHAR) : wcslen(mscoreeW)*sizeof(WCHAR); 4238 4239 /* setup new index entry */ 4240 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4241 Status = RtlGUIDFromString(&str, &(*index)->guid); 4242 if (!NT_SUCCESS(Status)) 4243 return Status; 4244 4245 (*index)->data_offset = *data_offset; 4246 (*index)->data_len = sizeof(*data); /* additional length added later */ 4247 (*index)->rosterindex = rosterindex; 4248 4249 /* Setup new index entry for alias guid. Alias index records are placed after 4250 normal records, so normal guids are hit first on search. Note that class count 4251 is doubled. */ 4252 alias_index = (*index) + section->count/2; 4253 generate_uuid(seed, &alias_index->guid); 4254 alias_index->data_offset = (*index)->data_offset; 4255 alias_index->data_len = 0; 4256 alias_index->rosterindex = (*index)->rosterindex; 4257 4258 /* setup data */ 4259 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset); 4260 data->size = sizeof(*data); 4261 data->model = entity->u.comclass.model; 4262 data->clsid = (*index)->guid; 4263 data->alias = alias_index->guid; 4264 data->clsid2 = data->clsid; 4265 if (entity->u.comclass.tlbid) 4266 { 4267 RtlInitUnicodeString(&str, entity->u.comclass.tlbid); 4268 Status = RtlGUIDFromString(&str, &data->tlbid); 4269 if (!NT_SUCCESS(Status)) 4270 return Status; 4271 } 4272 else 4273 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4274 data->name_len = module_len; 4275 data->name_offset = *module_offset; 4276 data->progid_len = progid_len; 4277 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */ 4278 data->clrdata_len = 0; /* will be set later */ 4279 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0; 4280 data->miscstatus = entity->u.comclass.miscstatus; 4281 data->miscstatuscontent = entity->u.comclass.miscstatuscontent; 4282 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail; 4283 data->miscstatusicon = entity->u.comclass.miscstatusicon; 4284 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint; 4285 4286 /* mask describes which misc* data is available */ 4287 miscmask = 0; 4288 if (data->miscstatus) 4289 miscmask |= MiscStatus; 4290 if (data->miscstatuscontent) 4291 miscmask |= MiscStatusContent; 4292 if (data->miscstatusthumbnail) 4293 miscmask |= MiscStatusThumbnail; 4294 if (data->miscstatusicon) 4295 miscmask |= MiscStatusIcon; 4296 if (data->miscstatusdocprint) 4297 miscmask |= MiscStatusDocPrint; 4298 data->flags = miscmask << 8; 4299 4300 if (data->clrdata_offset) 4301 { 4302 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset); 4303 4304 clrdata->size = sizeof(*clrdata); 4305 clrdata->res[0] = 0; 4306 clrdata->res[1] = 2; /* FIXME: unknown field */ 4307 clrdata->module_len = wcslen(mscoreeW)*sizeof(WCHAR); 4308 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR); 4309 clrdata->name_len = wcslen(entity->u.comclass.name)*sizeof(WCHAR); 4310 clrdata->name_offset = clrdata->size; 4311 clrdata->version_len = entity->u.comclass.version ? wcslen(entity->u.comclass.version)*sizeof(WCHAR) : 0; 4312 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0; 4313 clrdata->res2[0] = 0; 4314 clrdata->res2[1] = 0; 4315 4316 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR); 4317 4318 /* module name */ 4319 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset); 4320 memcpy(ptrW, mscoree2W, clrdata->module_len); 4321 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0; 4322 4323 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4324 memcpy(ptrW, mscoreeW, data->name_len); 4325 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4326 4327 /* class name */ 4328 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset); 4329 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len); 4330 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0; 4331 4332 /* runtime version, optional */ 4333 if (clrdata->version_len) 4334 { 4335 data->clrdata_len += clrdata->version_len + sizeof(WCHAR); 4336 4337 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset); 4338 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len); 4339 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0; 4340 } 4341 4342 if (data->progid_len) 4343 data->progid_offset += data->clrdata_len; 4344 (*index)->data_len += sizeof(*clrdata); 4345 } 4346 else 4347 { 4348 clrdata = NULL; 4349 4350 /* module name */ 4351 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4352 memcpy(ptrW, dll->name, data->name_len); 4353 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4354 } 4355 4356 /* progid string */ 4357 if (data->progid_len) 4358 { 4359 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset); 4360 memcpy(ptrW, entity->u.comclass.progid, data->progid_len); 4361 ptrW[data->progid_len/sizeof(WCHAR)] = 0; 4362 } 4363 4364 /* string block length */ 4365 str_len = 0; 4366 if (clrdata) 4367 { 4368 str_len += clrdata->name_len + sizeof(WCHAR); 4369 if (clrdata->version_len) 4370 str_len += clrdata->version_len + sizeof(WCHAR); 4371 } 4372 if (progid_len) 4373 str_len += progid_len + sizeof(WCHAR); 4374 4375 (*index)->data_len += aligned_string_len(str_len); 4376 alias_index->data_len = (*index)->data_len; 4377 4378 /* move to next data record */ 4379 (*data_offset) += sizeof(*data) + aligned_string_len(str_len); 4380 (*module_offset) += module_len + sizeof(WCHAR); 4381 4382 if (clrdata) 4383 { 4384 (*data_offset) += sizeof(*clrdata); 4385 (*module_offset) += clrdata->module_len + sizeof(WCHAR); 4386 } 4387 (*index) += 1; 4388 } 4389 } 4390 4391 return STATUS_SUCCESS; 4392 } 4393 4394 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4395 { 4396 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0; 4397 struct guidsection_header *header; 4398 ULONG module_offset, data_offset; 4399 struct guid_index *index; 4400 ULONG seed; 4401 NTSTATUS Status; 4402 4403 /* compute section length */ 4404 for (i = 0; i < actctx->num_assemblies; i++) 4405 { 4406 struct assembly *assembly = &actctx->assemblies[i]; 4407 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len); 4408 for (j = 0; j < assembly->num_dlls; j++) 4409 { 4410 struct dll_redirect *dll = &assembly->dlls[j]; 4411 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len); 4412 } 4413 } 4414 4415 total_len += aligned_string_len(names_len); 4416 total_len += sizeof(*header); 4417 4418 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 4419 if (!header) return STATUS_NO_MEMORY; 4420 4421 memset(header, 0, sizeof(*header)); 4422 header->magic = GUIDSECTION_MAGIC; 4423 header->size = sizeof(*header); 4424 header->count = 2*class_count; 4425 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 4426 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4427 module_offset = sizeof(*header); 4428 data_offset = header->index_offset + 2*class_count*sizeof(*index); 4429 4430 seed = NtGetTickCount(); 4431 for (i = 0; i < actctx->num_assemblies; i++) 4432 { 4433 struct assembly *assembly = &actctx->assemblies[i]; 4434 Status = add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1); 4435 if (!NT_SUCCESS(Status)) 4436 { 4437 RtlFreeHeap(GetProcessHeap(), 0, header); 4438 return Status; 4439 } 4440 for (j = 0; j < assembly->num_dlls; j++) 4441 { 4442 struct dll_redirect *dll = &assembly->dlls[j]; 4443 Status = add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1); 4444 if (!NT_SUCCESS(Status)) 4445 { 4446 RtlFreeHeap(GetProcessHeap(), 0, header); 4447 return Status; 4448 } 4449 } 4450 } 4451 4452 *section = header; 4453 4454 return STATUS_SUCCESS; 4455 } 4456 4457 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4458 { 4459 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset); 4460 } 4461 4462 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4463 { 4464 struct comclassredirect_data *comclass; 4465 struct guid_index *index = NULL; 4466 4467 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4468 4469 if (!actctx->comserver_section) 4470 { 4471 struct guidsection_header *section; 4472 4473 NTSTATUS status = build_comserver_section(actctx, §ion); 4474 if (status) return status; 4475 4476 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4477 RtlFreeHeap(GetProcessHeap(), 0, section); 4478 } 4479 4480 index = find_guid_index(actctx->comserver_section, guid); 4481 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4482 4483 comclass = get_comclass_data(actctx, index); 4484 4485 data->ulDataFormatVersion = 1; 4486 data->lpData = comclass; 4487 /* full length includes string length with nulls */ 4488 data->ulLength = comclass->size + comclass->clrdata_len; 4489 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR); 4490 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset; 4491 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len; 4492 data->lpSectionBase = actctx->comserver_section; 4493 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->comserver_section ); 4494 data->hActCtx = NULL; 4495 4496 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4497 data->ulAssemblyRosterIndex = index->rosterindex; 4498 4499 return STATUS_SUCCESS; 4500 } 4501 4502 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len) 4503 { 4504 unsigned int i; 4505 4506 for (i = 0; i < entities->num; i++) 4507 { 4508 struct entity *entity = &entities->base[i]; 4509 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4510 { 4511 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data); 4512 if (entity->u.ifaceps.name) 4513 *len += aligned_string_len((wcslen(entity->u.ifaceps.name)+1)*sizeof(WCHAR)); 4514 *count += 1; 4515 } 4516 } 4517 } 4518 4519 static NTSTATUS add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities, 4520 struct guid_index **index, ULONG *data_offset, ULONG rosterindex) 4521 { 4522 unsigned int i; 4523 4524 for (i = 0; i < entities->num; i++) 4525 { 4526 struct entity *entity = &entities->base[i]; 4527 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4528 { 4529 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset); 4530 UNICODE_STRING str; 4531 ULONG name_len; 4532 NTSTATUS Status; 4533 4534 if (entity->u.ifaceps.name) 4535 name_len = wcslen(entity->u.ifaceps.name)*sizeof(WCHAR); 4536 else 4537 name_len = 0; 4538 4539 /* setup index */ 4540 RtlInitUnicodeString(&str, entity->u.ifaceps.iid); 4541 Status = RtlGUIDFromString(&str, &(*index)->guid); 4542 if (!NT_SUCCESS(Status)) 4543 return Status; 4544 (*index)->data_offset = *data_offset; 4545 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0; 4546 (*index)->rosterindex = rosterindex; 4547 4548 /* setup data record */ 4549 data->size = sizeof(*data); 4550 data->mask = entity->u.ifaceps.mask; 4551 4552 /* proxyStubClsid32 value is only stored for external PS, 4553 if set it's used as iid, otherwise 'iid' attribute value is used */ 4554 if (entity->u.ifaceps.ps32) 4555 { 4556 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32); 4557 Status = RtlGUIDFromString(&str, &data->iid); 4558 if (!NT_SUCCESS(Status)) 4559 return Status; 4560 } 4561 else 4562 data->iid = (*index)->guid; 4563 4564 data->nummethods = entity->u.ifaceps.nummethods; 4565 4566 if (entity->u.ifaceps.tlib) 4567 { 4568 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib); 4569 Status = RtlGUIDFromString(&str, &data->tlbid); 4570 if (!NT_SUCCESS(Status)) 4571 return Status; 4572 } 4573 else 4574 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4575 4576 if (entity->u.ifaceps.base) 4577 { 4578 RtlInitUnicodeString(&str, entity->u.ifaceps.base); 4579 Status = RtlGUIDFromString(&str, &data->base); 4580 if (!NT_SUCCESS(Status)) 4581 return Status; 4582 } 4583 else 4584 memset(&data->base, 0, sizeof(data->base)); 4585 4586 data->name_len = name_len; 4587 data->name_offset = data->name_len ? sizeof(*data) : 0; 4588 4589 /* name string */ 4590 if (data->name_len) 4591 { 4592 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4593 memcpy(ptrW, entity->u.ifaceps.name, data->name_len); 4594 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4595 } 4596 4597 /* move to next record */ 4598 (*index) += 1; 4599 *data_offset += sizeof(*data); 4600 if (data->name_len) 4601 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR)); 4602 } 4603 } 4604 4605 return STATUS_SUCCESS; 4606 } 4607 4608 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4609 { 4610 unsigned int i, j, total_len = 0, count = 0; 4611 struct guidsection_header *header; 4612 struct guid_index *index; 4613 ULONG data_offset; 4614 4615 /* compute section length */ 4616 for (i = 0; i < actctx->num_assemblies; i++) 4617 { 4618 struct assembly *assembly = &actctx->assemblies[i]; 4619 4620 get_ifaceps_datalen(&assembly->entities, &count, &total_len); 4621 for (j = 0; j < assembly->num_dlls; j++) 4622 { 4623 struct dll_redirect *dll = &assembly->dlls[j]; 4624 get_ifaceps_datalen(&dll->entities, &count, &total_len); 4625 } 4626 } 4627 4628 total_len += sizeof(*header); 4629 4630 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 4631 if (!header) return STATUS_NO_MEMORY; 4632 4633 memset(header, 0, sizeof(*header)); 4634 header->magic = GUIDSECTION_MAGIC; 4635 header->size = sizeof(*header); 4636 header->count = count; 4637 header->index_offset = sizeof(*header); 4638 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4639 data_offset = header->index_offset + count*sizeof(*index); 4640 4641 for (i = 0; i < actctx->num_assemblies; i++) 4642 { 4643 struct assembly *assembly = &actctx->assemblies[i]; 4644 NTSTATUS Status; 4645 4646 Status = add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1); 4647 if (!NT_SUCCESS(Status)) 4648 { 4649 RtlFreeHeap(GetProcessHeap(), 0, header); 4650 return Status; 4651 } 4652 4653 for (j = 0; j < assembly->num_dlls; j++) 4654 { 4655 struct dll_redirect *dll = &assembly->dlls[j]; 4656 Status = add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1); 4657 if (!NT_SUCCESS(Status)) 4658 { 4659 RtlFreeHeap(GetProcessHeap(), 0, header); 4660 return Status; 4661 } 4662 } 4663 } 4664 4665 *section = header; 4666 4667 return STATUS_SUCCESS; 4668 } 4669 4670 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4671 { 4672 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset); 4673 } 4674 4675 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4676 { 4677 struct ifacepsredirect_data *iface; 4678 struct guid_index *index = NULL; 4679 4680 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4681 4682 if (!actctx->ifaceps_section) 4683 { 4684 struct guidsection_header *section; 4685 4686 NTSTATUS status = build_ifaceps_section(actctx, §ion); 4687 if (status) return status; 4688 4689 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL)) 4690 RtlFreeHeap(GetProcessHeap(), 0, section); 4691 } 4692 4693 index = find_guid_index(actctx->ifaceps_section, guid); 4694 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4695 4696 iface = get_ifaceps_data(actctx, index); 4697 4698 data->ulDataFormatVersion = 1; 4699 data->lpData = iface; 4700 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0); 4701 data->lpSectionGlobalData = NULL; 4702 data->ulSectionGlobalDataLength = 0; 4703 data->lpSectionBase = actctx->ifaceps_section; 4704 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->ifaceps_section ); 4705 data->hActCtx = NULL; 4706 4707 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4708 data->ulAssemblyRosterIndex = index->rosterindex; 4709 4710 return STATUS_SUCCESS; 4711 } 4712 4713 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4714 { 4715 unsigned int i, j, total_len = 0, count = 0; 4716 struct guidsection_header *header; 4717 struct clrsurrogate_data *data; 4718 struct guid_index *index; 4719 ULONG data_offset; 4720 4721 /* compute section length */ 4722 for (i = 0; i < actctx->num_assemblies; i++) 4723 { 4724 struct assembly *assembly = &actctx->assemblies[i]; 4725 for (j = 0; j < assembly->entities.num; j++) 4726 { 4727 struct entity *entity = &assembly->entities.base[j]; 4728 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4729 { 4730 ULONG len; 4731 4732 total_len += sizeof(*index) + sizeof(*data); 4733 len = wcslen(entity->u.clrsurrogate.name) + 1; 4734 if (entity->u.clrsurrogate.version) 4735 len += wcslen(entity->u.clrsurrogate.version) + 1; 4736 total_len += aligned_string_len(len*sizeof(WCHAR)); 4737 4738 count++; 4739 } 4740 } 4741 } 4742 4743 total_len += sizeof(*header); 4744 4745 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 4746 if (!header) return STATUS_NO_MEMORY; 4747 4748 memset(header, 0, sizeof(*header)); 4749 header->magic = GUIDSECTION_MAGIC; 4750 header->size = sizeof(*header); 4751 header->count = count; 4752 header->index_offset = sizeof(*header); 4753 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4754 data_offset = header->index_offset + count*sizeof(*index); 4755 4756 for (i = 0; i < actctx->num_assemblies; i++) 4757 { 4758 struct assembly *assembly = &actctx->assemblies[i]; 4759 for (j = 0; j < assembly->entities.num; j++) 4760 { 4761 struct entity *entity = &assembly->entities.base[j]; 4762 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4763 { 4764 ULONG version_len, name_len; 4765 UNICODE_STRING str; 4766 WCHAR *ptrW; 4767 NTSTATUS Status; 4768 4769 if (entity->u.clrsurrogate.version) 4770 version_len = wcslen(entity->u.clrsurrogate.version)*sizeof(WCHAR); 4771 else 4772 version_len = 0; 4773 name_len = wcslen(entity->u.clrsurrogate.name)*sizeof(WCHAR); 4774 4775 /* setup new index entry */ 4776 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid); 4777 Status = RtlGUIDFromString(&str, &index->guid); 4778 if (!NT_SUCCESS(Status)) 4779 { 4780 RtlFreeHeap(GetProcessHeap(), 0, header); 4781 return Status; 4782 } 4783 4784 index->data_offset = data_offset; 4785 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0)); 4786 index->rosterindex = i + 1; 4787 4788 /* setup data */ 4789 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset); 4790 data->size = sizeof(*data); 4791 data->res = 0; 4792 data->clsid = index->guid; 4793 data->version_offset = version_len ? data->size : 0; 4794 data->version_len = version_len; 4795 data->name_offset = data->size + version_len; 4796 if (version_len) 4797 data->name_offset += sizeof(WCHAR); 4798 data->name_len = name_len; 4799 4800 /* surrogate name */ 4801 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4802 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len); 4803 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4804 4805 /* runtime version */ 4806 if (data->version_len) 4807 { 4808 ptrW = (WCHAR*)((BYTE*)data + data->version_offset); 4809 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len); 4810 ptrW[data->version_len/sizeof(WCHAR)] = 0; 4811 } 4812 4813 data_offset += index->data_offset; 4814 index++; 4815 } 4816 } 4817 } 4818 4819 *section = header; 4820 4821 return STATUS_SUCCESS; 4822 } 4823 4824 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index) 4825 { 4826 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset); 4827 } 4828 4829 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4830 { 4831 struct clrsurrogate_data *surrogate; 4832 struct guid_index *index = NULL; 4833 4834 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4835 4836 if (!actctx->clrsurrogate_section) 4837 { 4838 struct guidsection_header *section; 4839 4840 NTSTATUS status = build_clr_surrogate_section(actctx, §ion); 4841 if (status) return status; 4842 4843 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL)) 4844 RtlFreeHeap(GetProcessHeap(), 0, section); 4845 } 4846 4847 index = find_guid_index(actctx->clrsurrogate_section, guid); 4848 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4849 4850 surrogate = get_surrogate_data(actctx, index); 4851 4852 data->ulDataFormatVersion = 1; 4853 data->lpData = surrogate; 4854 /* full length includes string length with nulls */ 4855 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR); 4856 if (surrogate->version_len) 4857 data->ulLength += surrogate->version_len + sizeof(WCHAR); 4858 4859 data->lpSectionGlobalData = NULL; 4860 data->ulSectionGlobalDataLength = 0; 4861 data->lpSectionBase = actctx->clrsurrogate_section; 4862 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->clrsurrogate_section ); 4863 data->hActCtx = NULL; 4864 4865 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4866 data->ulAssemblyRosterIndex = index->rosterindex; 4867 4868 return STATUS_SUCCESS; 4869 } 4870 4871 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len) 4872 { 4873 unsigned int i, j, single_len; 4874 4875 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID); 4876 for (i = 0; i < entities->num; i++) 4877 { 4878 struct entity *entity = &entities->base[i]; 4879 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4880 { 4881 if (entity->u.comclass.progid) 4882 { 4883 *total_len += single_len + aligned_string_len((wcslen(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4884 *count += 1; 4885 } 4886 4887 for (j = 0; j < entity->u.comclass.progids.num; j++) 4888 *total_len += aligned_string_len((wcslen(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR)); 4889 4890 *total_len += single_len*entity->u.comclass.progids.num; 4891 *count += entity->u.comclass.progids.num; 4892 } 4893 } 4894 } 4895 4896 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias, 4897 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4898 { 4899 struct progidredirect_data *data; 4900 UNICODE_STRING str; 4901 GUID *guid_ptr; 4902 WCHAR *ptrW; 4903 4904 /* setup new index entry */ 4905 4906 /* hash progid name */ 4907 RtlInitUnicodeString(&str, progid); 4908 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash); 4909 4910 (*index)->name_offset = *data_offset; 4911 (*index)->name_len = str.Length; 4912 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength); 4913 (*index)->data_len = sizeof(*data); 4914 (*index)->rosterindex = rosterindex; 4915 4916 *data_offset += aligned_string_len(str.MaximumLength); 4917 4918 /* setup data structure */ 4919 data = (struct progidredirect_data*)((BYTE*)section + *data_offset); 4920 data->size = sizeof(*data); 4921 data->reserved = 0; 4922 data->clsid_offset = *global_offset; 4923 4924 /* write progid string */ 4925 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset); 4926 memcpy(ptrW, progid, (*index)->name_len); 4927 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0; 4928 4929 /* write guid to global area */ 4930 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset); 4931 *guid_ptr = *alias; 4932 4933 /* to next entry */ 4934 *global_offset += sizeof(GUID); 4935 *data_offset += data->size; 4936 (*index) += 1; 4937 } 4938 4939 static NTSTATUS add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities, 4940 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4941 { 4942 unsigned int i, j; 4943 NTSTATUS Status; 4944 4945 for (i = 0; i < entities->num; i++) 4946 { 4947 struct entity *entity = &entities->base[i]; 4948 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4949 { 4950 const struct progids *progids = &entity->u.comclass.progids; 4951 struct comclassredirect_data *comclass; 4952 struct guid_index *guid_index; 4953 UNICODE_STRING str; 4954 GUID clsid; 4955 4956 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4957 Status = RtlGUIDFromString(&str, &clsid); 4958 if (!NT_SUCCESS(Status)) 4959 return Status; 4960 4961 guid_index = find_guid_index(actctx->comserver_section, &clsid); 4962 comclass = get_comclass_data(actctx, guid_index); 4963 4964 if (entity->u.comclass.progid) 4965 write_progid_record(section, entity->u.comclass.progid, &comclass->alias, 4966 index, data_offset, global_offset, rosterindex); 4967 4968 for (j = 0; j < progids->num; j++) 4969 write_progid_record(section, progids->progids[j], &comclass->alias, 4970 index, data_offset, global_offset, rosterindex); 4971 } 4972 } 4973 return Status; 4974 } 4975 4976 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 4977 { 4978 unsigned int i, j, total_len = 0, count = 0; 4979 struct strsection_header *header; 4980 ULONG data_offset, global_offset; 4981 struct string_index *index; 4982 NTSTATUS Status; 4983 4984 /* compute section length */ 4985 for (i = 0; i < actctx->num_assemblies; i++) 4986 { 4987 struct assembly *assembly = &actctx->assemblies[i]; 4988 4989 get_progid_datalen(&assembly->entities, &count, &total_len); 4990 for (j = 0; j < assembly->num_dlls; j++) 4991 { 4992 struct dll_redirect *dll = &assembly->dlls[j]; 4993 get_progid_datalen(&dll->entities, &count, &total_len); 4994 } 4995 } 4996 4997 total_len += sizeof(*header); 4998 4999 header = RtlAllocateHeap(GetProcessHeap(), 0, total_len); 5000 if (!header) return STATUS_NO_MEMORY; 5001 5002 memset(header, 0, sizeof(*header)); 5003 header->magic = STRSECTION_MAGIC; 5004 header->size = sizeof(*header); 5005 header->count = count; 5006 header->global_offset = header->size; 5007 header->global_len = count*sizeof(GUID); 5008 header->index_offset = header->size + header->global_len; 5009 5010 index = (struct string_index*)((BYTE*)header + header->index_offset); 5011 data_offset = header->index_offset + count*sizeof(*index); 5012 global_offset = header->global_offset; 5013 5014 for (i = 0; i < actctx->num_assemblies; i++) 5015 { 5016 struct assembly *assembly = &actctx->assemblies[i]; 5017 5018 Status = add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1); 5019 if (!NT_SUCCESS(Status)) 5020 { 5021 RtlFreeHeap(GetProcessHeap(), 0, header); 5022 return Status; 5023 } 5024 5025 for (j = 0; j < assembly->num_dlls; j++) 5026 { 5027 struct dll_redirect *dll = &assembly->dlls[j]; 5028 Status = add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1); 5029 if (!NT_SUCCESS(Status)) 5030 { 5031 RtlFreeHeap(GetProcessHeap(), 0, header); 5032 return Status; 5033 } 5034 } 5035 } 5036 5037 *section = header; 5038 5039 return STATUS_SUCCESS; 5040 } 5041 5042 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index) 5043 { 5044 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset); 5045 } 5046 5047 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 5048 PACTCTX_SECTION_KEYED_DATA data) 5049 { 5050 struct progidredirect_data *progid; 5051 struct string_index *index; 5052 5053 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 5054 5055 if (!actctx->comserver_section) 5056 { 5057 struct guidsection_header *section; 5058 5059 NTSTATUS status = build_comserver_section(actctx, §ion); 5060 if (status) return status; 5061 5062 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 5063 RtlFreeHeap(GetProcessHeap(), 0, section); 5064 } 5065 5066 if (!actctx->progid_section) 5067 { 5068 struct strsection_header *section; 5069 5070 NTSTATUS status = build_progid_section(actctx, §ion); 5071 if (status) return status; 5072 5073 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL)) 5074 RtlFreeHeap(GetProcessHeap(), 0, section); 5075 } 5076 5077 index = find_string_index(actctx->progid_section, name); 5078 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 5079 5080 if (data) 5081 { 5082 progid = get_progid_data(actctx, index); 5083 5084 data->ulDataFormatVersion = 1; 5085 data->lpData = progid; 5086 data->ulLength = progid->size; 5087 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset; 5088 data->ulSectionGlobalDataLength = actctx->progid_section->global_len; 5089 data->lpSectionBase = actctx->progid_section; 5090 data->ulSectionTotalLength = RtlSizeHeap( GetProcessHeap(), 0, actctx->progid_section ); 5091 data->hActCtx = NULL; 5092 5093 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 5094 data->ulAssemblyRosterIndex = index->rosterindex; 5095 } 5096 5097 return STATUS_SUCCESS; 5098 } 5099 5100 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 5101 const UNICODE_STRING *section_name, 5102 DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 5103 { 5104 NTSTATUS status; 5105 5106 switch (section_kind) 5107 { 5108 #ifdef __REACTOS__ 5109 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION: 5110 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 5111 return STATUS_SXS_KEY_NOT_FOUND; 5112 #endif // __REACTOS__ 5113 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: 5114 status = find_dll_redirection(actctx, section_name, data); 5115 break; 5116 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 5117 status = find_window_class(actctx, section_name, data); 5118 break; 5119 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 5120 status = find_progid_redirection(actctx, section_name, data); 5121 break; 5122 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: 5123 FIXME("Unsupported yet section_kind %x\n", section_kind); 5124 return STATUS_SXS_SECTION_NOT_FOUND; 5125 default: 5126 WARN("Unknown section_kind %x\n", section_kind); 5127 return STATUS_SXS_SECTION_NOT_FOUND; 5128 } 5129 5130 if (status != STATUS_SUCCESS) return status; 5131 5132 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)) 5133 { 5134 actctx_addref(actctx); 5135 data->hActCtx = actctx; 5136 } 5137 return STATUS_SUCCESS; 5138 } 5139 5140 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 5141 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 5142 { 5143 NTSTATUS status; 5144 5145 switch (section_kind) 5146 { 5147 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 5148 status = find_tlib_redirection(actctx, guid, data); 5149 break; 5150 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 5151 status = find_comserver_redirection(actctx, guid, data); 5152 break; 5153 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 5154 status = find_cominterface_redirection(actctx, guid, data); 5155 break; 5156 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 5157 status = find_clr_surrogate(actctx, guid, data); 5158 break; 5159 default: 5160 WARN("Unknown section_kind %x\n", section_kind); 5161 return STATUS_SXS_SECTION_NOT_FOUND; 5162 } 5163 5164 if (status != STATUS_SUCCESS) return status; 5165 5166 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5167 { 5168 actctx_addref(actctx); 5169 data->hActCtx = actctx; 5170 } 5171 return STATUS_SUCCESS; 5172 } 5173 5174 static const WCHAR *find_app_settings( ACTIVATION_CONTEXT *actctx, const WCHAR *settings, const WCHAR *ns ) 5175 { 5176 unsigned int i, j; 5177 5178 for (i = 0; i < actctx->num_assemblies; i++) 5179 { 5180 struct assembly *assembly = &actctx->assemblies[i]; 5181 for (j = 0; j < assembly->entities.num; j++) 5182 { 5183 struct entity *entity = &assembly->entities.base[j]; 5184 if (entity->kind == ACTIVATION_CONTEXT_SECTION_APPLICATION_SETTINGS && 5185 !wcscmp( entity->u.settings.name, settings ) && 5186 !wcscmp( entity->u.settings.ns, ns )) 5187 return entity->u.settings.value; 5188 } 5189 } 5190 return NULL; 5191 } 5192 5193 /* initialize the activation context for the current process */ 5194 void actctx_init(void) 5195 { 5196 ACTCTXW ctx; 5197 HANDLE handle; 5198 5199 ctx.cbSize = sizeof(ctx); 5200 ctx.lpSource = NULL; 5201 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 5202 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5203 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 5204 5205 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle))) 5206 { 5207 process_actctx = check_actctx(handle); 5208 } 5209 5210 #ifdef __REACTOS__ 5211 NtCurrentTeb()->ProcessEnvironmentBlock->ActivationContextData = process_actctx->ActivationContextData; 5212 #else 5213 NtCurrentTeb()->Peb->ActivationContextData = process_actctx; 5214 #endif // __REACTOS__ 5215 } 5216 5217 5218 /*********************************************************************** 5219 * RtlCreateActivationContext (NTDLL.@) 5220 * 5221 * Create an activation context. 5222 */ 5223 NTSTATUS 5224 NTAPI 5225 RtlCreateActivationContext(IN ULONG Flags, 5226 IN PACTIVATION_CONTEXT_DATA ActivationContextData, 5227 IN ULONG ExtraBytes, 5228 IN PVOID NotificationRoutine, 5229 IN PVOID NotificationContext, 5230 OUT PACTIVATION_CONTEXT *ActCtx) 5231 { 5232 const ACTCTXW *pActCtx = (PVOID)ActivationContextData; 5233 const WCHAR *directory = NULL; 5234 ACTIVATION_CONTEXT *actctx; 5235 UNICODE_STRING nameW; 5236 ULONG lang = 0; 5237 NTSTATUS status = STATUS_NO_MEMORY; 5238 HANDLE file = 0; 5239 struct actctx_loader acl; 5240 5241 TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0); 5242 5243 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) || 5244 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL)) 5245 return STATUS_INVALID_PARAMETER; 5246 5247 5248 if (!(actctx = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) ))) 5249 return STATUS_NO_MEMORY; 5250 5251 actctx->magic = ACTCTX_MAGIC; 5252 actctx->ref_count = 1; 5253 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; 5254 actctx->config.info = NULL; 5255 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; 5256 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) 5257 { 5258 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error; 5259 } 5260 else 5261 { 5262 UNICODE_STRING dir; 5263 WCHAR *p; 5264 HMODULE module; 5265 5266 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule; 5267 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5268 5269 status = get_module_filename( module, &dir, 0 ); 5270 if (!NT_SUCCESS(status)) goto error; 5271 if ((p = wcsrchr( dir.Buffer, '\\' ))) p[1] = 0; 5272 actctx->appdir.info = dir.Buffer; 5273 } 5274 5275 nameW.Buffer = NULL; 5276 5277 /* open file only if it's going to be used */ 5278 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && 5279 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID))) 5280 { 5281 WCHAR *source = NULL; 5282 BOOLEAN ret; 5283 5284 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID && 5285 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RELATIVE_PATH) 5286 { 5287 DWORD dir_len, source_len; 5288 5289 dir_len = wcslen(pActCtx->lpAssemblyDirectory); 5290 source_len = wcslen(pActCtx->lpSource); 5291 if (!(source = RtlAllocateHeap( GetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR)))) 5292 { 5293 status = STATUS_NO_MEMORY; 5294 goto error; 5295 } 5296 5297 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR)); 5298 source[dir_len] = '\\'; 5299 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR)); 5300 } 5301 5302 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL); 5303 RtlFreeHeap( GetProcessHeap(), 0, source ); 5304 if (!ret) 5305 { 5306 status = STATUS_NO_SUCH_FILE; 5307 goto error; 5308 } 5309 status = open_nt_file( &file, &nameW ); 5310 if (!NT_SUCCESS(status)) 5311 { 5312 RtlFreeUnicodeString( &nameW ); 5313 goto error; 5314 } 5315 } 5316 5317 acl.actctx = actctx; 5318 acl.dependencies = NULL; 5319 acl.num_dependencies = 0; 5320 acl.allocated_dependencies = 0; 5321 5322 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; 5323 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; 5324 5325 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) 5326 { 5327 /* if we have a resource it's a PE file */ 5328 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) 5329 { 5330 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule, 5331 pActCtx->lpResourceName, lang ); 5332 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5333 /* FIXME: what to do if pActCtx->lpSource is set */ 5334 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, 5335 pActCtx->hModule, pActCtx->lpResourceName ); 5336 } 5337 else if (pActCtx->lpSource && pActCtx->lpResourceName) 5338 { 5339 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE, 5340 file, pActCtx->lpResourceName, lang ); 5341 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5342 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, 5343 NULL, pActCtx->lpResourceName ); 5344 } 5345 else status = STATUS_INVALID_PARAMETER; 5346 } 5347 else 5348 { 5349 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file ); 5350 } 5351 5352 if (file) NtClose( file ); 5353 RtlFreeUnicodeString( &nameW ); 5354 5355 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl); 5356 free_depend_manifests( &acl ); 5357 5358 if (NT_SUCCESS(status)) 5359 *ActCtx = actctx; 5360 else actctx_release( actctx ); 5361 return status; 5362 5363 error: 5364 if (file) NtClose( file ); 5365 actctx_release( actctx ); 5366 return status; 5367 } 5368 5369 5370 /*********************************************************************** 5371 * RtlAddRefActivationContext (NTDLL.@) 5372 */ 5373 void WINAPI RtlAddRefActivationContext( HANDLE handle ) 5374 { 5375 ACTIVATION_CONTEXT *actctx; 5376 5377 if ((actctx = check_actctx( handle ))) actctx_addref( actctx ); 5378 } 5379 5380 5381 /****************************************************************** 5382 * RtlReleaseActivationContext (NTDLL.@) 5383 */ 5384 void WINAPI RtlReleaseActivationContext( HANDLE handle ) 5385 { 5386 ACTIVATION_CONTEXT *actctx; 5387 5388 if ((actctx = check_actctx( handle ))) actctx_release( actctx ); 5389 } 5390 5391 /****************************************************************** 5392 * RtlZombifyActivationContext (NTDLL.@) 5393 * 5394 * FIXME: function prototype might be wrong 5395 */ 5396 NTSTATUS WINAPI RtlZombifyActivationContext( HANDLE handle ) 5397 { 5398 FIXME("%p: stub\n", handle); 5399 5400 if (handle == ACTCTX_FAKE_HANDLE) 5401 return STATUS_SUCCESS; 5402 5403 return STATUS_NOT_IMPLEMENTED; 5404 } 5405 5406 /****************************************************************** 5407 * RtlActivateActivationContext (NTDLL.@) 5408 */ 5409 NTSTATUS WINAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie ) 5410 { 5411 return RtlActivateActivationContextEx( 0, NtCurrentTeb(), handle, cookie ); 5412 } 5413 5414 /****************************************************************** 5415 * RtlActivateActivationContextEx (NTDLL.@) 5416 */ 5417 NTSTATUS WINAPI RtlActivateActivationContextEx( ULONG flags, TEB *teb, HANDLE handle, ULONG_PTR *cookie ) 5418 { 5419 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5420 5421 if (!(frame = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*frame) ))) 5422 return STATUS_NO_MEMORY; 5423 5424 frame->Previous = teb->ActivationContextStackPointer->ActiveFrame; 5425 frame->ActivationContext = handle; 5426 frame->Flags = 0; 5427 5428 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5429 teb->ActivationContextStackPointer, teb->ActivationContextStackPointer->ActiveFrame, 5430 frame, handle); 5431 5432 teb->ActivationContextStackPointer->ActiveFrame = frame; 5433 RtlAddRefActivationContext( handle ); 5434 5435 *cookie = (ULONG_PTR)frame; 5436 TRACE( "%p cookie=%lx\n", handle, *cookie ); 5437 return STATUS_SUCCESS; 5438 } 5439 5440 /*********************************************************************** 5441 * RtlDeactivateActivationContext (NTDLL.@) 5442 */ 5443 NTSTATUS WINAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) 5444 { 5445 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; 5446 5447 TRACE( "%x cookie=%lx\n", flags, cookie ); 5448 5449 /* find the right frame */ 5450 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5451 for (frame = top; frame; frame = frame->Previous) 5452 if ((ULONG_PTR)frame == cookie) break; 5453 5454 if (!frame) 5455 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 5456 5457 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION)) 5458 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); 5459 5460 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5461 NtCurrentTeb()->ActivationContextStackPointer, 5462 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame, 5463 frame->Previous); 5464 5465 /* pop everything up to and including frame */ 5466 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 5467 5468 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5469 { 5470 frame = top->Previous; 5471 RtlReleaseActivationContext( top->ActivationContext ); 5472 RtlFreeHeap( GetProcessHeap(), 0, top ); 5473 top = frame; 5474 } 5475 5476 return STATUS_SUCCESS; 5477 } 5478 5479 #ifdef __REACTOS__ 5480 VOID 5481 NTAPI 5482 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack) 5483 { 5484 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame; 5485 5486 /* Nothing to do if there is no stack */ 5487 if (!Stack) return; 5488 5489 /* Get the current active frame */ 5490 ActiveFrame = Stack->ActiveFrame; 5491 5492 /* Go through them in backwards order and release */ 5493 while (ActiveFrame) 5494 { 5495 PrevFrame = ActiveFrame->Previous; 5496 RtlReleaseActivationContext(ActiveFrame->ActivationContext); 5497 RtlFreeHeap(GetProcessHeap(), 0, ActiveFrame); 5498 ActiveFrame = PrevFrame; 5499 } 5500 5501 /* Zero out the active frame */ 5502 Stack->ActiveFrame = NULL; 5503 5504 /* TODO: Empty the Frame List Cache */ 5505 ASSERT(IsListEmpty(&Stack->FrameListCache)); 5506 5507 /* Free activation stack memory */ 5508 RtlFreeHeap(GetProcessHeap(), 0, Stack); 5509 } 5510 #endif // __REACTOS__ 5511 5512 /****************************************************************** 5513 * RtlFreeThreadActivationContextStack (NTDLL.@) 5514 */ 5515 void WINAPI RtlFreeThreadActivationContextStack(void) 5516 { 5517 #ifdef __REACTOS__ 5518 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer); 5519 NtCurrentTeb()->ActivationContextStackPointer = NULL; 5520 #else 5521 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5522 5523 frame = NtCurrentTeb()->ActivationContextStack.ActiveFrame; 5524 while (frame) 5525 { 5526 RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous; 5527 RtlReleaseActivationContext( frame->ActivationContext ); 5528 RtlFreeHeap( GetProcessHeap(), 0, frame ); 5529 frame = prev; 5530 } 5531 NtCurrentTeb()->ActivationContextStack.ActiveFrame = NULL; 5532 #endif // __REACTOS__ 5533 } 5534 5535 5536 /****************************************************************** 5537 * RtlGetActiveActivationContext (NTDLL.@) 5538 */ 5539 NTSTATUS WINAPI RtlGetActiveActivationContext( HANDLE *handle ) 5540 { 5541 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5542 { 5543 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 5544 RtlAddRefActivationContext( *handle ); 5545 } 5546 else 5547 *handle = 0; 5548 5549 return STATUS_SUCCESS; 5550 } 5551 5552 5553 /****************************************************************** 5554 * RtlIsActivationContextActive (NTDLL.@) 5555 */ 5556 BOOLEAN WINAPI RtlIsActivationContextActive( HANDLE handle ) 5557 { 5558 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5559 5560 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous) 5561 if (frame->ActivationContext == handle) return TRUE; 5562 return FALSE; 5563 } 5564 5565 5566 /*********************************************************************** 5567 * RtlQueryInformationActivationContext (NTDLL.@) 5568 * 5569 * Get information about an activation context. 5570 * FIXME: function signature/prototype may be wrong 5571 */ 5572 NTSTATUS WINAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, 5573 ULONG class, PVOID buffer, 5574 SIZE_T bufsize, SIZE_T *retlen ) 5575 { 5576 ACTIVATION_CONTEXT *actctx; 5577 NTSTATUS status; 5578 5579 TRACE("%08x %p %p %u %p %ld %p\n", flags, handle, 5580 subinst, class, buffer, bufsize, retlen); 5581 5582 if (retlen) *retlen = 0; 5583 if ((status = find_query_actctx( &handle, flags, class ))) return status; 5584 5585 switch (class) 5586 { 5587 case ActivationContextBasicInformation: 5588 { 5589 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; 5590 5591 if (retlen) *retlen = sizeof(*info); 5592 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; 5593 5594 info->hActCtx = handle; 5595 info->dwFlags = 0; /* FIXME */ 5596 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle); 5597 } 5598 break; 5599 5600 case ActivationContextDetailedInformation: 5601 { 5602 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; 5603 struct assembly *assembly = NULL; 5604 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; 5605 LPWSTR ptr; 5606 5607 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5608 5609 if (actctx->num_assemblies) assembly = actctx->assemblies; 5610 5611 if (assembly && assembly->manifest.info) 5612 manifest_len = wcslen(assembly->manifest.info) + 1; 5613 if (actctx->config.info) config_len = wcslen(actctx->config.info) + 1; 5614 if (actctx->appdir.info) appdir_len = wcslen(actctx->appdir.info) + 1; 5615 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); 5616 5617 if (retlen) *retlen = len; 5618 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5619 5620 acdi->dwFlags = 0; 5621 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ 5622 acdi->ulAssemblyCount = actctx->num_assemblies; 5623 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; 5624 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0; 5625 acdi->ulRootConfigurationPathType = actctx->config.type; 5626 acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0; 5627 acdi->ulAppDirPathType = actctx->appdir.type; 5628 acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0; 5629 ptr = (LPWSTR)(acdi + 1); 5630 if (manifest_len) 5631 { 5632 acdi->lpRootManifestPath = ptr; 5633 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); 5634 ptr += manifest_len; 5635 } 5636 else acdi->lpRootManifestPath = NULL; 5637 if (config_len) 5638 { 5639 acdi->lpRootConfigurationPath = ptr; 5640 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); 5641 ptr += config_len; 5642 } 5643 else acdi->lpRootConfigurationPath = NULL; 5644 if (appdir_len) 5645 { 5646 acdi->lpAppDirPath = ptr; 5647 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); 5648 } 5649 else acdi->lpAppDirPath = NULL; 5650 } 5651 break; 5652 5653 case AssemblyDetailedInformationInActivationContext: 5654 { 5655 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; 5656 struct assembly *assembly; 5657 WCHAR *assembly_id; 5658 DWORD index; 5659 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; 5660 LPWSTR ptr; 5661 5662 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5663 if (!subinst) return STATUS_INVALID_PARAMETER; 5664 5665 index = *(DWORD*)subinst; 5666 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; 5667 5668 assembly = &actctx->assemblies[index - 1]; 5669 5670 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; 5671 id_len = wcslen(assembly_id) + 1; 5672 if (assembly->directory) ad_len = wcslen(assembly->directory) + 1; 5673 5674 if (assembly->manifest.info && 5675 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST)) 5676 path_len = wcslen(assembly->manifest.info) + 1; 5677 5678 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); 5679 5680 if (retlen) *retlen = len; 5681 if (!buffer || bufsize < len) 5682 { 5683 RtlFreeHeap( GetProcessHeap(), 0, assembly_id ); 5684 return STATUS_BUFFER_TOO_SMALL; 5685 } 5686 5687 afdi->ulFlags = 0; /* FIXME */ 5688 afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR); 5689 afdi->ulManifestPathType = assembly->manifest.type; 5690 afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0; 5691 /* FIXME afdi->liManifestLastWriteTime = 0; */ 5692 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ 5693 afdi->ulPolicyPathLength = 0; 5694 /* FIXME afdi->liPolicyLastWriteTime = 0; */ 5695 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ 5696 afdi->ulManifestVersionMajor = 1; 5697 afdi->ulManifestVersionMinor = 0; 5698 afdi->ulPolicyVersionMajor = 0; /* FIXME */ 5699 afdi->ulPolicyVersionMinor = 0; /* FIXME */ 5700 afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0; 5701 ptr = (LPWSTR)(afdi + 1); 5702 afdi->lpAssemblyEncodedAssemblyIdentity = ptr; 5703 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); 5704 ptr += id_len; 5705 if (path_len) 5706 { 5707 afdi->lpAssemblyManifestPath = ptr; 5708 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); 5709 ptr += path_len; 5710 } else afdi->lpAssemblyManifestPath = NULL; 5711 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ 5712 if (ad_len) 5713 { 5714 afdi->lpAssemblyDirectoryName = ptr; 5715 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); 5716 } 5717 else afdi->lpAssemblyDirectoryName = NULL; 5718 RtlFreeHeap( GetProcessHeap(), 0, assembly_id ); 5719 } 5720 break; 5721 5722 case FileInformationInAssemblyOfAssemblyInActivationContext: 5723 { 5724 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; 5725 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; 5726 struct assembly *assembly; 5727 struct dll_redirect *dll; 5728 SIZE_T len, dll_len = 0; 5729 LPWSTR ptr; 5730 5731 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5732 if (!acqi) return STATUS_INVALID_PARAMETER; 5733 5734 if (acqi->ulAssemblyIndex >= actctx->num_assemblies) 5735 return STATUS_INVALID_PARAMETER; 5736 assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; 5737 5738 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) 5739 return STATUS_INVALID_PARAMETER; 5740 dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; 5741 5742 if (dll->name) dll_len = wcslen(dll->name) + 1; 5743 len = sizeof(*afdi) + dll_len * sizeof(WCHAR); 5744 5745 if (!buffer || bufsize < len) 5746 { 5747 if (retlen) *retlen = len; 5748 return STATUS_BUFFER_TOO_SMALL; 5749 } 5750 if (retlen) *retlen = 0; /* yes that's what native does !! */ 5751 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; 5752 afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0; 5753 afdi->ulPathLength = 0; /* FIXME */ 5754 ptr = (LPWSTR)(afdi + 1); 5755 if (dll_len) 5756 { 5757 afdi->lpFileName = ptr; 5758 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); 5759 } else afdi->lpFileName = NULL; 5760 afdi->lpFilePath = NULL; /* FIXME */ 5761 } 5762 break; 5763 5764 case CompatibilityInformationInActivationContext: 5765 { 5766 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer; 5767 COMPATIBILITY_CONTEXT_ELEMENT *elements; 5768 struct assembly *assembly = NULL; 5769 ULONG num_compat_contexts = 0, n; 5770 SIZE_T len; 5771 5772 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5773 5774 if (actctx->num_assemblies) assembly = actctx->assemblies; 5775 5776 if (assembly) 5777 num_compat_contexts = assembly->num_compat_contexts; 5778 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); 5779 5780 if (retlen) *retlen = len; 5781 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5782 5783 *acci = num_compat_contexts; 5784 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1); 5785 for (n = 0; n < num_compat_contexts; ++n) 5786 { 5787 elements[n] = assembly->compat_contexts[n]; 5788 } 5789 } 5790 break; 5791 5792 case RunlevelInformationInActivationContext: 5793 { 5794 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer; 5795 struct assembly *assembly; 5796 SIZE_T len; 5797 5798 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5799 5800 len = sizeof(*acrli); 5801 if (retlen) *retlen = len; 5802 if (!buffer || bufsize < len) 5803 return STATUS_BUFFER_TOO_SMALL; 5804 5805 assembly = actctx->assemblies; 5806 5807 acrli->ulFlags = 0; 5808 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED; 5809 acrli->UiAccess = assembly ? assembly->ui_access : 0; 5810 } 5811 break; 5812 5813 default: 5814 FIXME( "class %u not implemented\n", class ); 5815 return STATUS_NOT_IMPLEMENTED; 5816 } 5817 return STATUS_SUCCESS; 5818 } 5819 5820 #ifdef __REACTOS__ 5821 NTSTATUS 5822 NTAPI 5823 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, 5824 PVOID pvBuffer, 5825 SIZE_T cbBuffer OPTIONAL, 5826 SIZE_T *pcbWrittenOrRequired OPTIONAL) 5827 { 5828 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT, 5829 NULL, 5830 NULL, 5831 ulInfoClass, 5832 pvBuffer, 5833 cbBuffer, 5834 pcbWrittenOrRequired); 5835 } 5836 5837 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002 5838 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004 5839 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5840 5841 NTSTATUS 5842 NTAPI 5843 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, 5844 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) 5845 { 5846 /* Check general parameter combinations */ 5847 if (!section_name || !section_name->Buffer || 5848 (flags & ~FIND_ACTCTX_VALID_MASK) || 5849 ((flags & FIND_ACTCTX_VALID_MASK) && !data) || 5850 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) 5851 { 5852 DPRINT1("invalid parameter\n"); 5853 return STATUS_INVALID_PARAMETER; 5854 } 5855 5856 /* TODO */ 5857 if (flags & FIND_ACTCTX_RETURN_FLAGS || 5858 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5859 { 5860 DPRINT1("unknown flags %08x\n", flags); 5861 return STATUS_INVALID_PARAMETER; 5862 } 5863 5864 return STATUS_SUCCESS; 5865 } 5866 #endif // __REACTOS__ 5867 5868 /*********************************************************************** 5869 * RtlFindActivationContextSectionString (NTDLL.@) 5870 * 5871 * Find information about a string in an activation context. 5872 * FIXME: function signature/prototype may be wrong 5873 */ 5874 NTSTATUS WINAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, 5875 const UNICODE_STRING *section_name, PVOID ptr ) 5876 { 5877 PACTCTX_SECTION_KEYED_DATA data = ptr; 5878 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; 5879 5880 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(guid), section_kind, 5881 debugstr_us(section_name), data); 5882 5883 #ifdef __REACTOS__ 5884 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data); 5885 if (!NT_SUCCESS(status)) 5886 { 5887 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status); 5888 return status; 5889 } 5890 5891 status = STATUS_SXS_KEY_NOT_FOUND; 5892 5893 /* if there is no data, but params are valid, 5894 we return that sxs key is not found to be at least somehow compatible */ 5895 if (!data) 5896 { 5897 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status); 5898 return status; 5899 } 5900 #else 5901 if (guid) 5902 { 5903 FIXME("expected guid == NULL\n"); 5904 return STATUS_INVALID_PARAMETER; 5905 } 5906 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5907 { 5908 FIXME("unknown flags %08x\n", flags); 5909 return STATUS_INVALID_PARAMETER; 5910 } 5911 if ((data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)) || 5912 !section_name || !section_name->Buffer) 5913 { 5914 WARN("invalid parameter\n"); 5915 return STATUS_INVALID_PARAMETER; 5916 } 5917 #endif // __REACTOS__ 5918 5919 ASSERT(NtCurrentTeb()); 5920 ASSERT(NtCurrentTeb()->ActivationContextStackPointer); 5921 5922 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame); 5923 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5924 { 5925 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5926 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); 5927 } 5928 5929 DPRINT("status %x\n", status); 5930 if (status != STATUS_SUCCESS) 5931 status = find_string( process_actctx, section_kind, section_name, flags, data ); 5932 5933 if (status != STATUS_SUCCESS) 5934 status = find_string( implicit_actctx, section_kind, section_name, flags, data ); 5935 5936 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status); 5937 return status; 5938 } 5939 5940 /*********************************************************************** 5941 * RtlFindActivationContextSectionGuid (NTDLL.@) 5942 * 5943 * Find information about a GUID in an activation context. 5944 * FIXME: function signature/prototype may be wrong 5945 */ 5946 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind, 5947 const GUID *guid, void *ptr ) 5948 { 5949 ACTCTX_SECTION_KEYED_DATA *data = ptr; 5950 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; 5951 5952 TRACE("%08x %s %u %s %p\n", flags, debugstr_guid(extguid), section_kind, debugstr_guid(guid), data); 5953 5954 if (extguid) 5955 { 5956 FIXME("expected extguid == NULL\n"); 5957 return STATUS_INVALID_PARAMETER; 5958 } 5959 5960 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5961 { 5962 FIXME("unknown flags %08x\n", flags); 5963 return STATUS_INVALID_PARAMETER; 5964 } 5965 5966 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid) 5967 return STATUS_INVALID_PARAMETER; 5968 5969 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5970 { 5971 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5972 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data ); 5973 } 5974 5975 if (status != STATUS_SUCCESS) 5976 status = find_guid( process_actctx, section_kind, guid, flags, data ); 5977 5978 if (status != STATUS_SUCCESS) 5979 status = find_guid( implicit_actctx, section_kind, guid, flags, data ); 5980 5981 return status; 5982 } 5983 5984 5985 /*********************************************************************** 5986 * RtlQueryActivationContextApplicationSettings (NTDLL.@) 5987 */ 5988 NTSTATUS WINAPI RtlQueryActivationContextApplicationSettings( DWORD flags, HANDLE handle, const WCHAR *ns, 5989 const WCHAR *settings, WCHAR *buffer, 5990 SIZE_T size, SIZE_T *written ) 5991 { 5992 ACTIVATION_CONTEXT *actctx; 5993 const WCHAR *res; 5994 5995 if (flags) 5996 { 5997 WARN( "unknown flags %08x\n", flags ); 5998 return STATUS_INVALID_PARAMETER; 5999 } 6000 6001 if (ns) 6002 { 6003 if (wcscmp( ns, windowsSettings2005NSW ) && 6004 wcscmp( ns, windowsSettings2011NSW ) && 6005 wcscmp( ns, windowsSettings2016NSW ) && 6006 wcscmp( ns, windowsSettings2017NSW )) 6007 return STATUS_INVALID_PARAMETER; 6008 } 6009 else ns = windowsSettings2005NSW; 6010 6011 if (!handle) handle = process_actctx; 6012 if (!(actctx = check_actctx( handle ))) return STATUS_INVALID_PARAMETER; 6013 6014 if (!(res = find_app_settings( actctx, settings, ns ))) return STATUS_SXS_KEY_NOT_FOUND; 6015 6016 if (written) *written = wcslen(res) + 1; 6017 if (size < wcslen(res)) return STATUS_BUFFER_TOO_SMALL; 6018 wcscpy( buffer, res ); 6019 return STATUS_SUCCESS; 6020 } 6021 6022 #ifdef __REACTOS__ 6023 /* Stubs */ 6024 6025 NTSTATUS 6026 NTAPI 6027 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack) 6028 { 6029 PACTIVATION_CONTEXT_STACK ContextStack; 6030 6031 /* Check if it's already allocated */ 6032 if (*Stack) return STATUS_SUCCESS; 6033 6034 /* Allocate space for the context stack */ 6035 ContextStack = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK)); 6036 if (!ContextStack) 6037 { 6038 return STATUS_NO_MEMORY; 6039 } 6040 6041 /* Initialize the context stack */ 6042 ContextStack->Flags = 0; 6043 ContextStack->ActiveFrame = NULL; 6044 InitializeListHead(&ContextStack->FrameListCache); 6045 ContextStack->NextCookieSequenceNumber = 1; 6046 ContextStack->StackId = 1; //TODO: Timer-based 6047 6048 *Stack = ContextStack; 6049 6050 return STATUS_SUCCESS; 6051 } 6052 6053 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 6054 FASTCALL 6055 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, 6056 IN PVOID Context) 6057 { 6058 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame; 6059 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame; 6060 6061 /* Get the current active frame */ 6062 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 6063 6064 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 6065 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame, 6066 &Frame->Frame, Context); 6067 6068 /* Ensure it's in the right format and at least fits basic info */ 6069 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 6070 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 6071 6072 /* Set debug info if size allows*/ 6073 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 6074 { 6075 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame); 6076 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context); 6077 //Frame->Extra3 = ...; 6078 } 6079 6080 if (ActiveFrame) 6081 { 6082 /*ASSERT((ActiveFrame->Flags & 6083 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | 6084 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED | 6085 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/ 6086 6087 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED)) 6088 { 6089 // TODO: Perform some additional checks if it was not heap allocated 6090 } 6091 } 6092 6093 /* Save pointer to the new activation frame */ 6094 NewFrame = &Frame->Frame; 6095 6096 /* Actually activate it */ 6097 Frame->Frame.Previous = ActiveFrame; 6098 Frame->Frame.ActivationContext = Context; 6099 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED; 6100 6101 /* Check if we can activate this context */ 6102 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) || 6103 Context) 6104 { 6105 /* Set new active frame */ 6106 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame); 6107 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 6108 return NewFrame; 6109 } 6110 6111 /* We can get here only one way: it was already activated */ 6112 DPRINT("Trying to activate already activated activation context\n"); 6113 6114 /* Activate only if we are allowing multiple activation */ 6115 #if 0 6116 if (!RtlpNotAllowingMultipleActivation) 6117 { 6118 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED; 6119 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 6120 } 6121 #else 6122 // Activate it anyway 6123 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 6124 #endif 6125 6126 /* Return pointer to the activation frame */ 6127 return NewFrame; 6128 } 6129 6130 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 6131 FASTCALL 6132 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) 6133 { 6134 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame; 6135 6136 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 6137 6138 /* Ensure it's in the right format and at least fits basic info */ 6139 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 6140 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 6141 6142 /* Make sure it is not deactivated and it is activated */ 6143 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0); 6144 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 6145 ASSERT((Frame->Frame.Flags & (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 6146 6147 /* Check debug info if it is present */ 6148 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 6149 { 6150 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous)); 6151 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext)); 6152 //Frame->Extra3 = ...; 6153 } 6154 6155 if (ActiveFrame) 6156 { 6157 // TODO: Perform some additional checks here 6158 } 6159 6160 /* Special handling for not-really-activated */ 6161 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED) 6162 { 6163 DPRINT1("Deactivating not really activated activation context\n"); 6164 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 6165 return &Frame->Frame; 6166 } 6167 6168 /* find the right frame */ 6169 NewFrame = &Frame->Frame; 6170 if (ActiveFrame != NewFrame) 6171 { 6172 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame); 6173 } 6174 6175 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 6176 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous); 6177 6178 /* Pop everything up to and including frame */ 6179 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous; 6180 6181 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 6182 return NewFrame->Previous; 6183 } 6184 6185 NTSTATUS 6186 NTAPI 6187 RtlpInitializeActCtx(PVOID* pOldShimData) 6188 { 6189 ACTCTXW ctx; 6190 HANDLE handle; 6191 WCHAR buffer[1024]; 6192 NTSTATUS Status; 6193 6194 /* Initialize trace flags to WARN and ERR */ 6195 __wine_dbch_actctx.flags = 0x03; 6196 6197 actctx_init(); 6198 6199 /* ReactOS specific: 6200 Now that we have found the process_actctx we can initialize the process compat subsystem */ 6201 LdrpInitializeProcessCompat(process_actctx, pOldShimData); 6202 6203 ctx.cbSize = sizeof(ctx); 6204 ctx.dwFlags = 0; 6205 ctx.hModule = NULL; 6206 ctx.lpResourceName = NULL; 6207 ctx.lpSource = buffer; 6208 RtlStringCchCopyW(buffer, RTL_NUMBER_OF(buffer), SharedUserData->NtSystemRoot); 6209 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\systemcompatible.manifest"); 6210 6211 Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle); 6212 if (NT_SUCCESS(Status)) 6213 { 6214 implicit_actctx = check_actctx(handle); 6215 } 6216 else 6217 { 6218 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status); 6219 } 6220 6221 return Status; 6222 } 6223 6224 #endif // __REACTOS__ 6225