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