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