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