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 IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir, 2951 LPCWSTR name, void *root, 2952 int want_dir ); 2953 2954 IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir, 2955 void *root, int want_dir ); 2956 2957 2958 static IMAGE_RESOURCE_DIRECTORY *find_first_id_entry( IMAGE_RESOURCE_DIRECTORY *dir, 2959 void *root, int want_dir ) 2960 { 2961 const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1); 2962 int pos; 2963 2964 for (pos = dir->NumberOfNamedEntries; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++) 2965 { 2966 if (!entry[pos].DataIsDirectory == !want_dir) 2967 return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory); 2968 } 2969 return NULL; 2970 } 2971 2972 2973 static NTSTATUS search_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 2974 LPCWSTR filename, LPCWSTR directory, BOOL shared, 2975 HANDLE hModule, ULONG lang ) 2976 { 2977 ULONG size; 2978 PVOID root, ptr; 2979 IMAGE_RESOURCE_DIRECTORY *resdirptr; 2980 IMAGE_RESOURCE_DATA_ENTRY *entry; 2981 NTSTATUS status; 2982 2983 root = RtlImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); 2984 if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; 2985 if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; 2986 resdirptr = root; 2987 2988 if (!(ptr = find_entry_by_name(resdirptr, (LPCWSTR)RT_MANIFEST, root, 1))) 2989 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2990 2991 resdirptr = ptr; 2992 if (!(ptr = find_first_id_entry(resdirptr, root, 1))) 2993 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2994 2995 resdirptr = ptr; 2996 if (!(ptr = find_first_entry(resdirptr, root, 0))) 2997 return STATUS_RESOURCE_TYPE_NOT_FOUND; 2998 2999 entry = ptr; 3000 status = LdrAccessResource(hModule, entry, &ptr, NULL); 3001 3002 if (status == STATUS_SUCCESS) 3003 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size); 3004 3005 return status; 3006 } 3007 3008 3009 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai, 3010 LPCWSTR filename, LPCWSTR directory, BOOL shared, 3011 HANDLE file, LPCWSTR resname, ULONG lang ) 3012 { 3013 HANDLE mapping; 3014 OBJECT_ATTRIBUTES attr; 3015 LARGE_INTEGER size; 3016 LARGE_INTEGER offset; 3017 NTSTATUS status; 3018 SIZE_T count; 3019 void *base; 3020 WCHAR resnameBuf[20]; 3021 LPCWSTR resptr = resname; 3022 3023 if ((!((ULONG_PTR)resname >> 16))) 3024 { 3025 sprintfW(resnameBuf, L"#%u", PtrToUlong(resname)); 3026 resptr = resnameBuf; 3027 } 3028 3029 DPRINT( "looking for res %S in %S\n", resptr, filename ? filename : L"<NULL>"); 3030 3031 attr.Length = sizeof(attr); 3032 attr.RootDirectory = 0; 3033 attr.ObjectName = NULL; 3034 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3035 attr.SecurityDescriptor = NULL; 3036 attr.SecurityQualityOfService = NULL; 3037 3038 size.QuadPart = 0; 3039 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3040 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3041 if (status != STATUS_SUCCESS) return status; 3042 3043 offset.QuadPart = 0; 3044 count = 0; 3045 base = NULL; 3046 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 3047 &count, ViewShare, 0, PAGE_READONLY ); 3048 NtClose( mapping ); 3049 if (status != STATUS_SUCCESS) return status; 3050 3051 if (RtlImageNtHeader(base)) /* we got a PE file */ 3052 { 3053 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */ 3054 if (resname) 3055 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang ); 3056 else 3057 status = search_manifest_in_module(acl, ai, filename, directory, shared, module, lang); 3058 } 3059 else status = STATUS_INVALID_IMAGE_FORMAT; 3060 3061 NtUnmapViewOfSection( NtCurrentProcess(), base ); 3062 return status; 3063 } 3064 3065 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai, 3066 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file ) 3067 { 3068 FILE_STANDARD_INFORMATION info; 3069 IO_STATUS_BLOCK io; 3070 HANDLE mapping; 3071 OBJECT_ATTRIBUTES attr; 3072 LARGE_INTEGER size; 3073 LARGE_INTEGER offset; 3074 NTSTATUS status; 3075 SIZE_T count; 3076 void *base; 3077 3078 DPRINT( "loading manifest file %S\n", filename ); 3079 3080 attr.Length = sizeof(attr); 3081 attr.RootDirectory = 0; 3082 attr.ObjectName = NULL; 3083 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 3084 attr.SecurityDescriptor = NULL; 3085 attr.SecurityQualityOfService = NULL; 3086 3087 size.QuadPart = 0; 3088 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 3089 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 3090 3091 if (status != STATUS_SUCCESS) return status; 3092 3093 offset.QuadPart = 0; 3094 count = 0; 3095 base = NULL; 3096 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 3097 &count, ViewShare, 0, PAGE_READONLY ); 3098 NtClose( mapping ); 3099 if (status != STATUS_SUCCESS) return status; 3100 3101 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */ 3102 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation); 3103 3104 if (status == STATUS_SUCCESS) 3105 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart); 3106 3107 NtUnmapViewOfSection( NtCurrentProcess(), base ); 3108 return status; 3109 } 3110 3111 /* try to load the .manifest file associated to the file */ 3112 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 3113 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname ) 3114 { 3115 static const WCHAR fmtW[] = { '.','%','l','u',0 }; 3116 WCHAR *buffer; 3117 NTSTATUS status; 3118 UNICODE_STRING nameW; 3119 HANDLE file; 3120 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 3121 3122 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff; 3123 3124 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid ); 3125 3126 if (module) /* use the module filename */ 3127 { 3128 UNICODE_STRING name; 3129 3130 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) ))) 3131 { 3132 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid ); 3133 strcatW( name.Buffer, dotManifestW ); 3134 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL )) 3135 status = STATUS_RESOURCE_DATA_NOT_FOUND; 3136 RtlFreeUnicodeString( &name ); 3137 } 3138 if (status) return status; 3139 } 3140 else 3141 { 3142 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3143 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3144 return STATUS_NO_MEMORY; 3145 strcpyW( buffer, filename ); 3146 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid ); 3147 strcatW( buffer, dotManifestW ); 3148 RtlInitUnicodeString( &nameW, buffer ); 3149 } 3150 3151 if (!open_nt_file( &file, &nameW )) 3152 { 3153 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3154 NtClose( file ); 3155 } 3156 else status = STATUS_RESOURCE_TYPE_NOT_FOUND; 3157 RtlFreeUnicodeString( &nameW ); 3158 return status; 3159 } 3160 3161 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai ) 3162 { 3163 static const WCHAR lookup_fmtW[] = 3164 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_', 3165 '%','s','_','*','.','m','a','n','i','f','e','s','t',0}; 3166 static const WCHAR wine_trailerW[] = {'d','e','a','d','b','e','e','f','.','m','a','n','i','f','e','s','t'}; 3167 3168 WCHAR *lookup, *ret = NULL; 3169 UNICODE_STRING lookup_us; 3170 IO_STATUS_BLOCK io; 3171 const WCHAR *lang = ai->language; 3172 unsigned int data_pos = 0, data_len; 3173 char buffer[8192]; 3174 3175 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3176 (strlenW(ai->arch) + strlenW(ai->name) 3177 + strlenW(ai->public_key) + 20) * sizeof(WCHAR) 3178 + sizeof(lookup_fmtW) ))) 3179 return NULL; 3180 3181 if (!lang || !strcmpiW( lang, neutralW )) lang = wildcardW; 3182 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, 3183 ai->version.major, ai->version.minor, lang ); 3184 RtlInitUnicodeString( &lookup_us, lookup ); 3185 3186 if (!NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3187 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE )) 3188 { 3189 ULONG min_build = ai->version.build, min_revision = ai->version.revision; 3190 FILE_BOTH_DIR_INFORMATION *dir_info; 3191 WCHAR *tmp; 3192 ULONG build, revision; 3193 3194 data_len = (ULONG)io.Information; 3195 3196 for (;;) 3197 { 3198 if (data_pos >= data_len) 3199 { 3200 if (NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 3201 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE )) 3202 break; 3203 data_len = (ULONG)io.Information; 3204 data_pos = 0; 3205 } 3206 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos); 3207 3208 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset; 3209 else data_pos = data_len; 3210 3211 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup); 3212 build = atoiW(tmp); 3213 if (build < min_build) continue; 3214 tmp = strchrW(tmp, '.') + 1; 3215 revision = atoiW(tmp); 3216 if (build == min_build && revision < min_revision) continue; 3217 tmp = strchrW(tmp, '_') + 1; 3218 tmp = strchrW(tmp, '_') + 1; 3219 if (dir_info->FileNameLength - (tmp - dir_info->FileName) * sizeof(WCHAR) == sizeof(wine_trailerW) && 3220 !memicmpW( tmp, wine_trailerW, sizeof(wine_trailerW) / sizeof(WCHAR) )) 3221 { 3222 /* prefer a non-Wine manifest if we already have one */ 3223 /* we'll still load the builtin dll if specified through DllOverrides */ 3224 if (ret) continue; 3225 } 3226 else 3227 { 3228 min_build = build; 3229 min_revision = revision; 3230 } 3231 ai->version.build = build; 3232 ai->version.revision = revision; 3233 RtlFreeHeap( RtlGetProcessHeap(), 0, ret ); 3234 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength + sizeof(WCHAR) ))) 3235 { 3236 memcpy( ret, dir_info->FileName, dir_info->FileNameLength ); 3237 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0; 3238 } 3239 } 3240 } 3241 else DPRINT1("no matching file for %S\n", lookup); 3242 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup ); 3243 return ret; 3244 } 3245 3246 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai) 3247 { 3248 struct assembly_identity sxs_ai; 3249 UNICODE_STRING path_us; 3250 OBJECT_ATTRIBUTES attr; 3251 IO_STATUS_BLOCK io; 3252 WCHAR *path, *file = NULL; 3253 HANDLE handle; 3254 3255 static const WCHAR manifest_dirW[] = 3256 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0}; 3257 3258 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE; 3259 3260 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3261 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) ))) 3262 return STATUS_NO_MEMORY; 3263 3264 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) ); 3265 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) ); 3266 3267 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL )) 3268 { 3269 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 3270 return STATUS_NO_SUCH_FILE; 3271 } 3272 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 3273 3274 attr.Length = sizeof(attr); 3275 attr.RootDirectory = 0; 3276 attr.Attributes = OBJ_CASE_INSENSITIVE; 3277 attr.ObjectName = &path_us; 3278 attr.SecurityDescriptor = NULL; 3279 attr.SecurityQualityOfService = NULL; 3280 3281 if (!NtOpenFile( &handle, GENERIC_READ | SYNCHRONIZE, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, 3282 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) 3283 { 3284 sxs_ai = *ai; 3285 file = lookup_manifest_file( handle, &sxs_ai ); 3286 NtClose( handle ); 3287 } 3288 if (!file) 3289 { 3290 RtlFreeUnicodeString( &path_us ); 3291 return STATUS_NO_SUCH_FILE; 3292 } 3293 3294 /* append file name to directory path */ 3295 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer, 3296 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) ))) 3297 { 3298 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 3299 RtlFreeUnicodeString( &path_us ); 3300 return STATUS_NO_MEMORY; 3301 } 3302 3303 path[path_us.Length/sizeof(WCHAR)] = '\\'; 3304 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file ); 3305 RtlInitUnicodeString( &path_us, path ); 3306 *strrchrW(file, '.') = 0; /* remove .manifest extension */ 3307 3308 if (!open_nt_file( &handle, &path_us )) 3309 { 3310 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle); 3311 NtClose( handle ); 3312 } 3313 else io.Status = STATUS_NO_SUCH_FILE; 3314 3315 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 3316 RtlFreeUnicodeString( &path_us ); 3317 return io.Status; 3318 } 3319 3320 static NTSTATUS lookup_assembly(struct actctx_loader* acl, 3321 struct assembly_identity* ai) 3322 { 3323 static const WCHAR dotDllW[] = {'.','d','l','l',0}; 3324 unsigned int i; 3325 WCHAR *buffer, *p, *directory; 3326 NTSTATUS status; 3327 UNICODE_STRING nameW; 3328 HANDLE file; 3329 DWORD len; 3330 3331 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n", 3332 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch ); 3333 3334 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status; 3335 3336 /* FIXME: add support for language specific lookup */ 3337 3338 len = max(RtlGetFullPathName_U(acl->actctx->assemblies->manifest.info, 0, NULL, NULL) / sizeof(WCHAR), 3339 strlenW(acl->actctx->appdir.info)); 3340 3341 nameW.Buffer = NULL; 3342 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 3343 (len + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 3344 return STATUS_NO_MEMORY; 3345 3346 if (!(directory = build_assembly_dir( ai ))) 3347 { 3348 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 3349 return STATUS_NO_MEMORY; 3350 } 3351 3352 /* Lookup in <dir>\name.dll 3353 * <dir>\name.manifest 3354 * <dir>\name\name.dll 3355 * <dir>\name\name.manifest 3356 * 3357 * First 'appdir' is used as <dir>, if that failed 3358 * it tries application manifest file path. 3359 */ 3360 strcpyW( buffer, acl->actctx->appdir.info ); 3361 p = buffer + strlenW(buffer); 3362 for (i = 0; i < 4; i++) 3363 { 3364 if (i == 2) 3365 { 3366 struct assembly *assembly = acl->actctx->assemblies; 3367 if (!RtlGetFullPathName_U(assembly->manifest.info, len * sizeof(WCHAR), buffer, &p)) break; 3368 } 3369 else *p++ = '\\'; 3370 3371 strcpyW( p, ai->name ); 3372 p += strlenW(p); 3373 3374 strcpyW( p, dotDllW ); 3375 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3376 { 3377 status = open_nt_file( &file, &nameW ); 3378 if (!status) 3379 { 3380 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, 3381 (LPCWSTR)0, 0 ); 3382 NtClose( file ); 3383 break; 3384 } 3385 RtlFreeUnicodeString( &nameW ); 3386 } 3387 3388 strcpyW( p, dotManifestW ); 3389 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 3390 { 3391 status = open_nt_file( &file, &nameW ); 3392 if (!status) 3393 { 3394 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 3395 NtClose( file ); 3396 break; 3397 } 3398 RtlFreeUnicodeString( &nameW ); 3399 } 3400 status = STATUS_SXS_ASSEMBLY_NOT_FOUND; 3401 } 3402 RtlFreeUnicodeString( &nameW ); 3403 RtlFreeHeap( RtlGetProcessHeap(), 0, directory ); 3404 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 3405 return status; 3406 } 3407 3408 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) 3409 { 3410 NTSTATUS status = STATUS_SUCCESS; 3411 unsigned int i; 3412 3413 for (i = 0; i < acl->num_dependencies; i++) 3414 { 3415 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS) 3416 { 3417 if (!acl->dependencies[i].optional && !acl->dependencies[i].delayed) 3418 { 3419 const struct assembly_version *ver = &acl->dependencies[i].version; 3420 DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n", 3421 acl->dependencies[i].name, 3422 ver->major, ver->minor, ver->build, ver->revision ); 3423 status = STATUS_SXS_CANT_GEN_ACTCTX; 3424 break; 3425 } 3426 } 3427 } 3428 /* FIXME should now iterate through all refs */ 3429 return status; 3430 } 3431 3432 /* find the appropriate activation context for RtlQueryInformationActivationContext */ 3433 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class ) 3434 { 3435 NTSTATUS status = STATUS_SUCCESS; 3436 3437 if (flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT) 3438 { 3439 if (*handle) return STATUS_INVALID_PARAMETER; 3440 3441 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 3442 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 3443 } 3444 else if (flags & (RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_ADDRESS | RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE)) 3445 { 3446 ULONG_PTR magic; 3447 LDR_DATA_TABLE_ENTRY *pldr; 3448 3449 if (!*handle) return STATUS_INVALID_PARAMETER; 3450 3451 LdrLockLoaderLock( 0, NULL, &magic ); 3452 if (!LdrFindEntryForAddress( *handle, &pldr )) 3453 { 3454 if ((flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_IS_HMODULE) && *handle != pldr->DllBase) 3455 status = STATUS_DLL_NOT_FOUND; 3456 else 3457 *handle = pldr->EntryPointActivationContext; 3458 } 3459 else status = STATUS_DLL_NOT_FOUND; 3460 LdrUnlockLoaderLock( 0, magic ); 3461 } 3462 else if (!*handle && (class != ActivationContextBasicInformation)) 3463 *handle = process_actctx; 3464 3465 return status; 3466 } 3467 3468 static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3469 { 3470 unsigned int i, j, total_len = 0, dll_count = 0; 3471 struct strsection_header *header; 3472 struct dllredirect_data *data; 3473 struct string_index *index; 3474 ULONG name_offset; 3475 3476 DPRINT("actctx %p, num_assemblies %d\n", actctx, actctx->num_assemblies); 3477 3478 /* compute section length */ 3479 for (i = 0; i < actctx->num_assemblies; i++) 3480 { 3481 struct assembly *assembly = &actctx->assemblies[i]; 3482 for (j = 0; j < assembly->num_dlls; j++) 3483 { 3484 struct dll_redirect *dll = &assembly->dlls[j]; 3485 3486 /* each entry needs index, data and string data */ 3487 total_len += sizeof(*index); 3488 total_len += sizeof(*data); 3489 total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR)); 3490 3491 DPRINT("assembly %d (%p), dll %d: dll name %S\n", i, assembly, j, dll->name); 3492 } 3493 3494 dll_count += assembly->num_dlls; 3495 } 3496 3497 total_len += sizeof(*header); 3498 3499 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3500 if (!header) return STATUS_NO_MEMORY; 3501 3502 memset(header, 0, sizeof(*header)); 3503 header->magic = STRSECTION_MAGIC; 3504 header->size = sizeof(*header); 3505 header->count = dll_count; 3506 header->index_offset = sizeof(*header); 3507 index = (struct string_index*)((BYTE*)header + header->index_offset); 3508 name_offset = header->index_offset + header->count*sizeof(*index); 3509 3510 for (i = 0; i < actctx->num_assemblies; i++) 3511 { 3512 struct assembly *assembly = &actctx->assemblies[i]; 3513 3514 DPRINT("assembly->num_dlls %d\n", assembly->num_dlls); 3515 3516 for (j = 0; j < assembly->num_dlls; j++) 3517 { 3518 struct dll_redirect *dll = &assembly->dlls[j]; 3519 UNICODE_STRING str; 3520 WCHAR *ptrW; 3521 3522 DPRINT("%d: dll name %S\n", j, dll->name); 3523 /* setup new index entry */ 3524 str.Buffer = dll->name; 3525 str.Length = (USHORT)strlenW(dll->name)*sizeof(WCHAR); 3526 str.MaximumLength = str.Length + sizeof(WCHAR); 3527 /* hash original class name */ 3528 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3529 3530 index->name_offset = name_offset; 3531 index->name_len = str.Length; 3532 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3533 index->data_len = sizeof(*data); 3534 index->rosterindex = i + 1; 3535 3536 /* setup data */ 3537 data = (struct dllredirect_data*)((BYTE*)header + index->data_offset); 3538 data->size = sizeof(*data); 3539 data->unk = 2; /* FIXME: seems to be constant */ 3540 memset(data->res, 0, sizeof(data->res)); 3541 3542 /* dll name */ 3543 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3544 memcpy(ptrW, dll->name, index->name_len); 3545 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3546 3547 name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength); 3548 3549 index++; 3550 } 3551 } 3552 3553 *section = header; 3554 3555 return STATUS_SUCCESS; 3556 } 3557 3558 static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name) 3559 { 3560 struct string_index *iter, *index = NULL; 3561 ULONG hash = 0, i; 3562 3563 DPRINT("section %p, name %wZ\n", section, name); 3564 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3565 iter = (struct string_index*)((BYTE*)section + section->index_offset); 3566 3567 for (i = 0; i < section->count; i++) 3568 { 3569 DPRINT("iter->hash 0x%x ?= 0x%x\n", iter->hash, hash); 3570 DPRINT("iter->name %S\n", (WCHAR*)((BYTE*)section + iter->name_offset)); 3571 if (iter->hash == hash) 3572 { 3573 const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset); 3574 3575 if (!_wcsnicmp(nameW, name->Buffer, name->Length / sizeof(WCHAR)) && 3576 wcslen(nameW) == name->Length / sizeof(WCHAR)) 3577 { 3578 index = iter; 3579 break; 3580 } 3581 else 3582 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); 3583 } 3584 iter++; 3585 } 3586 3587 return index; 3588 } 3589 3590 static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid) 3591 { 3592 struct guid_index *iter, *index = NULL; 3593 ULONG i; 3594 3595 iter = (struct guid_index*)((BYTE*)section + section->index_offset); 3596 3597 for (i = 0; i < section->count; i++) 3598 { 3599 if (!memcmp(guid, &iter->guid, sizeof(*guid))) 3600 { 3601 index = iter; 3602 break; 3603 } 3604 iter++; 3605 } 3606 3607 return index; 3608 } 3609 3610 static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3611 { 3612 return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset); 3613 } 3614 3615 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3616 PACTCTX_SECTION_KEYED_DATA data) 3617 { 3618 struct dllredirect_data *dll; 3619 struct string_index *index; 3620 3621 DPRINT("sections: 0x%08X\n", actctx->sections); 3622 if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3623 3624 DPRINT("actctx->dllredirect_section: %p\n", actctx->dllredirect_section); 3625 if (!actctx->dllredirect_section) 3626 { 3627 struct strsection_header *section; 3628 3629 NTSTATUS status = build_dllredirect_section(actctx, §ion); 3630 if (status) return status; 3631 3632 if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL)) 3633 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3634 } 3635 3636 index = find_string_index(actctx->dllredirect_section, name); 3637 DPRINT("index: %d\n", index); 3638 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3639 3640 if (data) 3641 { 3642 dll = get_dllredirect_data(actctx, index); 3643 3644 data->ulDataFormatVersion = 1; 3645 data->lpData = dll; 3646 data->ulLength = dll->size; 3647 data->lpSectionGlobalData = NULL; 3648 data->ulSectionGlobalDataLength = 0; 3649 data->lpSectionBase = actctx->dllredirect_section; 3650 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section ); 3651 data->hActCtx = NULL; 3652 3653 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3654 data->ulAssemblyRosterIndex = index->rosterindex; 3655 } 3656 3657 return STATUS_SUCCESS; 3658 } 3659 3660 static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx) 3661 { 3662 return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset); 3663 } 3664 3665 static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index) 3666 { 3667 return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset); 3668 } 3669 3670 static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 3671 { 3672 unsigned int i, j, k, total_len = 0, class_count = 0; 3673 struct wndclass_redirect_data *data; 3674 struct strsection_header *header; 3675 struct string_index *index; 3676 ULONG name_offset; 3677 3678 /* compute section length */ 3679 for (i = 0; i < actctx->num_assemblies; i++) 3680 { 3681 struct assembly *assembly = &actctx->assemblies[i]; 3682 for (j = 0; j < assembly->num_dlls; j++) 3683 { 3684 struct dll_redirect *dll = &assembly->dlls[j]; 3685 for (k = 0; k < dll->entities.num; k++) 3686 { 3687 struct entity *entity = &dll->entities.base[k]; 3688 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3689 { 3690 int class_len = strlenW(entity->u.class.name) + 1; 3691 int len; 3692 3693 /* each class entry needs index, data and string data */ 3694 total_len += sizeof(*index); 3695 total_len += sizeof(*data); 3696 /* original name is stored separately */ 3697 total_len += aligned_string_len(class_len*sizeof(WCHAR)); 3698 /* versioned name and module name are stored one after another */ 3699 if (entity->u.class.versioned) 3700 len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */; 3701 else 3702 len = class_len; 3703 len += strlenW(dll->name) + 1; 3704 total_len += aligned_string_len(len*sizeof(WCHAR)); 3705 3706 class_count++; 3707 } 3708 } 3709 } 3710 } 3711 3712 total_len += sizeof(*header); 3713 3714 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3715 if (!header) return STATUS_NO_MEMORY; 3716 3717 memset(header, 0, sizeof(*header)); 3718 header->magic = STRSECTION_MAGIC; 3719 header->size = sizeof(*header); 3720 header->count = class_count; 3721 header->index_offset = sizeof(*header); 3722 index = (struct string_index*)((BYTE*)header + header->index_offset); 3723 name_offset = header->index_offset + header->count*sizeof(*index); 3724 3725 for (i = 0; i < actctx->num_assemblies; i++) 3726 { 3727 struct assembly *assembly = &actctx->assemblies[i]; 3728 for (j = 0; j < assembly->num_dlls; j++) 3729 { 3730 struct dll_redirect *dll = &assembly->dlls[j]; 3731 for (k = 0; k < dll->entities.num; k++) 3732 { 3733 struct entity *entity = &dll->entities.base[k]; 3734 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 3735 { 3736 static const WCHAR exclW[] = {'!',0}; 3737 ULONG versioned_len, module_len; 3738 UNICODE_STRING str; 3739 WCHAR *ptrW; 3740 3741 /* setup new index entry */ 3742 str.Buffer = entity->u.class.name; 3743 str.Length = (USHORT)strlenW(entity->u.class.name)*sizeof(WCHAR); 3744 str.MaximumLength = str.Length + sizeof(WCHAR); 3745 /* hash original class name */ 3746 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash); 3747 3748 /* include '!' separator too */ 3749 if (entity->u.class.versioned) 3750 versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length; 3751 else 3752 versioned_len = str.Length; 3753 module_len = strlenW(dll->name)*sizeof(WCHAR); 3754 3755 index->name_offset = name_offset; 3756 index->name_len = str.Length; 3757 index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength); 3758 index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */; 3759 index->rosterindex = i + 1; 3760 3761 /* setup data */ 3762 data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset); 3763 data->size = sizeof(*data); 3764 data->res = 0; 3765 data->name_len = versioned_len; 3766 data->name_offset = sizeof(*data); 3767 data->module_len = module_len; 3768 data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR); 3769 3770 /* original class name */ 3771 ptrW = (WCHAR*)((BYTE*)header + index->name_offset); 3772 memcpy(ptrW, entity->u.class.name, index->name_len); 3773 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3774 3775 /* module name */ 3776 ptrW = (WCHAR*)((BYTE*)header + data->module_offset); 3777 memcpy(ptrW, dll->name, data->module_len); 3778 ptrW[data->module_len/sizeof(WCHAR)] = 0; 3779 3780 /* versioned name */ 3781 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 3782 if (entity->u.class.versioned) 3783 { 3784 get_assembly_version(assembly, ptrW); 3785 strcatW(ptrW, exclW); 3786 strcatW(ptrW, entity->u.class.name); 3787 } 3788 else 3789 { 3790 memcpy(ptrW, entity->u.class.name, index->name_len); 3791 ptrW[index->name_len/sizeof(WCHAR)] = 0; 3792 } 3793 3794 name_offset += sizeof(*data); 3795 name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR)); 3796 3797 index++; 3798 } 3799 } 3800 } 3801 } 3802 3803 *section = header; 3804 3805 return STATUS_SUCCESS; 3806 } 3807 3808 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 3809 PACTCTX_SECTION_KEYED_DATA data) 3810 { 3811 struct string_index *iter, *index = NULL; 3812 struct wndclass_redirect_data *class; 3813 ULONG hash; 3814 int i; 3815 3816 if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 3817 3818 if (!actctx->wndclass_section) 3819 { 3820 struct strsection_header *section; 3821 3822 NTSTATUS status = build_wndclass_section(actctx, §ion); 3823 if (status) return status; 3824 3825 if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL)) 3826 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 3827 } 3828 3829 hash = 0; 3830 RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash); 3831 iter = get_wndclass_first_index(actctx); 3832 3833 for (i = 0; i < actctx->wndclass_section->count; i++) 3834 { 3835 if (iter->hash == hash) 3836 { 3837 const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset); 3838 3839 if (!strcmpiW(nameW, name->Buffer)) 3840 { 3841 index = iter; 3842 break; 3843 } 3844 else 3845 DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW); 3846 } 3847 iter++; 3848 } 3849 3850 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 3851 3852 if (data) 3853 { 3854 class = get_wndclass_data(actctx, index); 3855 3856 data->ulDataFormatVersion = 1; 3857 data->lpData = class; 3858 /* full length includes string length with nulls */ 3859 data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR); 3860 data->lpSectionGlobalData = NULL; 3861 data->ulSectionGlobalDataLength = 0; 3862 data->lpSectionBase = actctx->wndclass_section; 3863 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section ); 3864 data->hActCtx = NULL; 3865 3866 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 3867 data->ulAssemblyRosterIndex = index->rosterindex; 3868 } 3869 3870 return STATUS_SUCCESS; 3871 } 3872 3873 static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 3874 { 3875 unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0; 3876 struct guidsection_header *header; 3877 ULONG module_offset, data_offset; 3878 struct tlibredirect_data *data; 3879 struct guid_index *index; 3880 3881 /* compute section length */ 3882 for (i = 0; i < actctx->num_assemblies; i++) 3883 { 3884 struct assembly *assembly = &actctx->assemblies[i]; 3885 for (j = 0; j < assembly->num_dlls; j++) 3886 { 3887 struct dll_redirect *dll = &assembly->dlls[j]; 3888 for (k = 0; k < dll->entities.num; k++) 3889 { 3890 struct entity *entity = &dll->entities.base[k]; 3891 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3892 { 3893 /* each entry needs index, data and string data for module name and help string */ 3894 total_len += sizeof(*index); 3895 total_len += sizeof(*data); 3896 /* help string is stored separately */ 3897 if (*entity->u.typelib.helpdir) 3898 total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR)); 3899 3900 /* module names are packed one after another */ 3901 names_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 3902 3903 tlib_count++; 3904 } 3905 } 3906 } 3907 } 3908 3909 total_len += aligned_string_len(names_len); 3910 total_len += sizeof(*header); 3911 3912 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 3913 if (!header) return STATUS_NO_MEMORY; 3914 3915 memset(header, 0, sizeof(*header)); 3916 header->magic = GUIDSECTION_MAGIC; 3917 header->size = sizeof(*header); 3918 header->count = tlib_count; 3919 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 3920 index = (struct guid_index*)((BYTE*)header + header->index_offset); 3921 module_offset = sizeof(*header); 3922 data_offset = header->index_offset + tlib_count*sizeof(*index); 3923 3924 for (i = 0; i < actctx->num_assemblies; i++) 3925 { 3926 struct assembly *assembly = &actctx->assemblies[i]; 3927 for (j = 0; j < assembly->num_dlls; j++) 3928 { 3929 struct dll_redirect *dll = &assembly->dlls[j]; 3930 for (k = 0; k < dll->entities.num; k++) 3931 { 3932 struct entity *entity = &dll->entities.base[k]; 3933 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION) 3934 { 3935 ULONG module_len, help_len; 3936 UNICODE_STRING str; 3937 WCHAR *ptrW; 3938 3939 if (*entity->u.typelib.helpdir) 3940 help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR); 3941 else 3942 help_len = 0; 3943 3944 module_len = strlenW(dll->name)*sizeof(WCHAR); 3945 3946 /* setup new index entry */ 3947 RtlInitUnicodeString(&str, entity->u.typelib.tlbid); 3948 RtlGUIDFromString(&str, &index->guid); 3949 index->data_offset = data_offset; 3950 index->data_len = sizeof(*data) + aligned_string_len(help_len); 3951 index->rosterindex = i + 1; 3952 3953 /* setup data */ 3954 data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset); 3955 data->size = sizeof(*data); 3956 data->res = 0; 3957 data->name_len = module_len; 3958 data->name_offset = module_offset; 3959 /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */ 3960 data->langid = 0; 3961 data->flags = entity->u.typelib.flags; 3962 data->help_len = help_len; 3963 data->help_offset = sizeof(*data); 3964 data->major_version = entity->u.typelib.major; 3965 data->minor_version = entity->u.typelib.minor; 3966 3967 /* module name */ 3968 ptrW = (WCHAR*)((BYTE*)header + data->name_offset); 3969 memcpy(ptrW, dll->name, data->name_len); 3970 ptrW[data->name_len/sizeof(WCHAR)] = 0; 3971 3972 /* help string */ 3973 if (data->help_len) 3974 { 3975 ptrW = (WCHAR*)((BYTE*)data + data->help_offset); 3976 memcpy(ptrW, entity->u.typelib.helpdir, data->help_len); 3977 ptrW[data->help_len/sizeof(WCHAR)] = 0; 3978 } 3979 3980 data_offset += sizeof(*data); 3981 if (help_len) 3982 data_offset += aligned_string_len(help_len + sizeof(WCHAR)); 3983 3984 module_offset += module_len + sizeof(WCHAR); 3985 3986 index++; 3987 } 3988 } 3989 } 3990 } 3991 3992 *section = header; 3993 3994 return STATUS_SUCCESS; 3995 } 3996 3997 static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 3998 { 3999 return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset); 4000 } 4001 4002 static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4003 { 4004 struct guid_index *index = NULL; 4005 struct tlibredirect_data *tlib; 4006 4007 if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4008 4009 if (!actctx->tlib_section) 4010 { 4011 struct guidsection_header *section; 4012 4013 NTSTATUS status = build_tlib_section(actctx, §ion); 4014 if (status) return status; 4015 4016 if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL)) 4017 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4018 } 4019 4020 index = find_guid_index(actctx->tlib_section, guid); 4021 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4022 4023 tlib = get_tlib_data(actctx, index); 4024 4025 data->ulDataFormatVersion = 1; 4026 data->lpData = tlib; 4027 /* full length includes string length with nulls */ 4028 data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR); 4029 data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset; 4030 data->ulSectionGlobalDataLength = actctx->tlib_section->names_len; 4031 data->lpSectionBase = actctx->tlib_section; 4032 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section ); 4033 data->hActCtx = NULL; 4034 4035 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4036 data->ulAssemblyRosterIndex = index->rosterindex; 4037 4038 return STATUS_SUCCESS; 4039 } 4040 4041 static void generate_uuid(ULONG *seed, GUID *guid) 4042 { 4043 ULONG *ptr = (ULONG*)guid; 4044 int i; 4045 4046 /* GUID is 16 bytes long */ 4047 for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++) 4048 *ptr = RtlUniform(seed); 4049 4050 guid->Data3 &= 0x0fff; 4051 guid->Data3 |= (4 << 12); 4052 guid->Data4[0] &= 0x3f; 4053 guid->Data4[0] |= 0x80; 4054 } 4055 4056 static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll, 4057 unsigned int *count, unsigned int *len, unsigned int *module_len) 4058 { 4059 unsigned int i; 4060 4061 for (i = 0; i < entities->num; i++) 4062 { 4063 struct entity *entity = &entities->base[i]; 4064 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4065 { 4066 /* each entry needs two index entries, extra one goes for alias GUID */ 4067 *len += 2*sizeof(struct guid_index); 4068 /* To save some memory we don't allocated two data structures, 4069 instead alias index and normal index point to the same data structure. */ 4070 *len += sizeof(struct comclassredirect_data); 4071 4072 /* for clrClass store some more */ 4073 if (entity->u.comclass.name) 4074 { 4075 unsigned int str_len; 4076 4077 /* all string data is stored together in aligned block */ 4078 str_len = strlenW(entity->u.comclass.name)+1; 4079 if (entity->u.comclass.progid) 4080 str_len += strlenW(entity->u.comclass.progid)+1; 4081 if (entity->u.comclass.version) 4082 str_len += strlenW(entity->u.comclass.version)+1; 4083 4084 *len += sizeof(struct clrclass_data); 4085 *len += aligned_string_len(str_len*sizeof(WCHAR)); 4086 4087 /* module name is forced to mscoree.dll, and stored two times with different case */ 4088 *module_len += sizeof(mscoreeW) + sizeof(mscoree2W); 4089 } 4090 else 4091 { 4092 /* progid string is stored separately */ 4093 if (entity->u.comclass.progid) 4094 *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4095 4096 *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR); 4097 } 4098 4099 *count += 1; 4100 } 4101 } 4102 } 4103 4104 static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities, 4105 const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset, 4106 ULONG *seed, ULONG rosterindex) 4107 { 4108 unsigned int i; 4109 4110 for (i = 0; i < entities->num; i++) 4111 { 4112 struct entity *entity = &entities->base[i]; 4113 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4114 { 4115 ULONG module_len, progid_len, str_len = 0; 4116 struct comclassredirect_data *data; 4117 struct guid_index *alias_index; 4118 struct clrclass_data *clrdata; 4119 UNICODE_STRING str; 4120 WCHAR *ptrW; 4121 4122 if (entity->u.comclass.progid) 4123 progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR); 4124 else 4125 progid_len = 0; 4126 4127 module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR); 4128 4129 /* setup new index entry */ 4130 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4131 RtlGUIDFromString(&str, &(*index)->guid); 4132 4133 (*index)->data_offset = *data_offset; 4134 (*index)->data_len = sizeof(*data); /* additional length added later */ 4135 (*index)->rosterindex = rosterindex; 4136 4137 /* Setup new index entry for alias guid. Alias index records are placed after 4138 normal records, so normal guids are hit first on search. Note that class count 4139 is doubled. */ 4140 alias_index = (*index) + section->count/2; 4141 generate_uuid(seed, &alias_index->guid); 4142 alias_index->data_offset = (*index)->data_offset; 4143 alias_index->data_len = 0; 4144 alias_index->rosterindex = (*index)->rosterindex; 4145 4146 /* setup data */ 4147 data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset); 4148 data->size = sizeof(*data); 4149 data->res = 0; 4150 data->res1[0] = 0; 4151 data->res1[1] = 0; 4152 data->model = entity->u.comclass.model; 4153 data->clsid = (*index)->guid; 4154 data->alias = alias_index->guid; 4155 data->clsid2 = data->clsid; 4156 if (entity->u.comclass.tlbid) 4157 { 4158 RtlInitUnicodeString(&str, entity->u.comclass.tlbid); 4159 RtlGUIDFromString(&str, &data->tlbid); 4160 } 4161 else 4162 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4163 data->name_len = module_len; 4164 data->name_offset = *module_offset; 4165 data->progid_len = progid_len; 4166 data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */ 4167 data->clrdata_len = 0; /* will be set later */ 4168 data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0; 4169 data->miscstatus = entity->u.comclass.miscstatus; 4170 data->miscstatuscontent = entity->u.comclass.miscstatuscontent; 4171 data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail; 4172 data->miscstatusicon = entity->u.comclass.miscstatusicon; 4173 data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint; 4174 4175 /* mask describes which misc* data is available */ 4176 data->miscmask = 0; 4177 if (data->miscstatus) 4178 data->miscmask |= MiscStatus; 4179 if (data->miscstatuscontent) 4180 data->miscmask |= MiscStatusContent; 4181 if (data->miscstatusthumbnail) 4182 data->miscmask |= MiscStatusThumbnail; 4183 if (data->miscstatusicon) 4184 data->miscmask |= MiscStatusIcon; 4185 if (data->miscstatusdocprint) 4186 data->miscmask |= MiscStatusDocPrint; 4187 4188 if (data->clrdata_offset) 4189 { 4190 clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset); 4191 4192 clrdata->size = sizeof(*clrdata); 4193 clrdata->res[0] = 0; 4194 clrdata->res[1] = 2; /* FIXME: unknown field */ 4195 clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR); 4196 clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR); 4197 clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR); 4198 clrdata->name_offset = clrdata->size; 4199 clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0; 4200 clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0; 4201 clrdata->res2[0] = 0; 4202 clrdata->res2[1] = 0; 4203 4204 data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR); 4205 4206 /* module name */ 4207 ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset); 4208 memcpy(ptrW, mscoree2W, clrdata->module_len); 4209 ptrW[clrdata->module_len/sizeof(WCHAR)] = 0; 4210 4211 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4212 memcpy(ptrW, mscoreeW, data->name_len); 4213 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4214 4215 /* class name */ 4216 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset); 4217 memcpy(ptrW, entity->u.comclass.name, clrdata->name_len); 4218 ptrW[clrdata->name_len/sizeof(WCHAR)] = 0; 4219 4220 /* runtime version, optional */ 4221 if (clrdata->version_len) 4222 { 4223 data->clrdata_len += clrdata->version_len + sizeof(WCHAR); 4224 4225 ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset); 4226 memcpy(ptrW, entity->u.comclass.version, clrdata->version_len); 4227 ptrW[clrdata->version_len/sizeof(WCHAR)] = 0; 4228 } 4229 4230 if (data->progid_len) 4231 data->progid_offset += data->clrdata_len; 4232 (*index)->data_len += sizeof(*clrdata); 4233 } 4234 else 4235 { 4236 clrdata = NULL; 4237 4238 /* module name */ 4239 ptrW = (WCHAR*)((BYTE*)section + data->name_offset); 4240 memcpy(ptrW, dll->name, data->name_len); 4241 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4242 } 4243 4244 /* progid string */ 4245 if (data->progid_len) 4246 { 4247 ptrW = (WCHAR*)((BYTE*)data + data->progid_offset); 4248 memcpy(ptrW, entity->u.comclass.progid, data->progid_len); 4249 ptrW[data->progid_len/sizeof(WCHAR)] = 0; 4250 } 4251 4252 /* string block length */ 4253 str_len = 0; 4254 if (clrdata) 4255 { 4256 str_len += clrdata->name_len + sizeof(WCHAR); 4257 if (clrdata->version_len) 4258 str_len += clrdata->version_len + sizeof(WCHAR); 4259 } 4260 if (progid_len) 4261 str_len += progid_len + sizeof(WCHAR); 4262 4263 (*index)->data_len += aligned_string_len(str_len); 4264 alias_index->data_len = (*index)->data_len; 4265 4266 /* move to next data record */ 4267 (*data_offset) += sizeof(*data) + aligned_string_len(str_len); 4268 (*module_offset) += module_len + sizeof(WCHAR); 4269 4270 if (clrdata) 4271 { 4272 (*data_offset) += sizeof(*clrdata); 4273 (*module_offset) += clrdata->module_len + sizeof(WCHAR); 4274 } 4275 (*index) += 1; 4276 } 4277 } 4278 } 4279 4280 static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4281 { 4282 unsigned int i, j, total_len = 0, class_count = 0, names_len = 0; 4283 struct guidsection_header *header; 4284 ULONG module_offset, data_offset; 4285 struct guid_index *index; 4286 ULONG seed; 4287 4288 /* compute section length */ 4289 for (i = 0; i < actctx->num_assemblies; i++) 4290 { 4291 struct assembly *assembly = &actctx->assemblies[i]; 4292 get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len); 4293 for (j = 0; j < assembly->num_dlls; j++) 4294 { 4295 struct dll_redirect *dll = &assembly->dlls[j]; 4296 get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len); 4297 } 4298 } 4299 4300 total_len += aligned_string_len(names_len); 4301 total_len += sizeof(*header); 4302 4303 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4304 if (!header) return STATUS_NO_MEMORY; 4305 4306 memset(header, 0, sizeof(*header)); 4307 header->magic = GUIDSECTION_MAGIC; 4308 header->size = sizeof(*header); 4309 header->count = 2*class_count; 4310 header->index_offset = sizeof(*header) + aligned_string_len(names_len); 4311 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4312 module_offset = sizeof(*header); 4313 data_offset = header->index_offset + 2*class_count*sizeof(*index); 4314 4315 seed = NtGetTickCount(); 4316 for (i = 0; i < actctx->num_assemblies; i++) 4317 { 4318 struct assembly *assembly = &actctx->assemblies[i]; 4319 add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1); 4320 for (j = 0; j < assembly->num_dlls; j++) 4321 { 4322 struct dll_redirect *dll = &assembly->dlls[j]; 4323 add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1); 4324 } 4325 } 4326 4327 *section = header; 4328 4329 return STATUS_SUCCESS; 4330 } 4331 4332 static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4333 { 4334 return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset); 4335 } 4336 4337 static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4338 { 4339 struct comclassredirect_data *comclass; 4340 struct guid_index *index = NULL; 4341 4342 if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4343 4344 if (!actctx->comserver_section) 4345 { 4346 struct guidsection_header *section; 4347 4348 NTSTATUS status = build_comserver_section(actctx, §ion); 4349 if (status) return status; 4350 4351 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4352 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4353 } 4354 4355 index = find_guid_index(actctx->comserver_section, guid); 4356 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4357 4358 comclass = get_comclass_data(actctx, index); 4359 4360 data->ulDataFormatVersion = 1; 4361 data->lpData = comclass; 4362 /* full length includes string length with nulls */ 4363 data->ulLength = comclass->size + comclass->clrdata_len; 4364 if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR); 4365 data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset; 4366 data->ulSectionGlobalDataLength = actctx->comserver_section->names_len; 4367 data->lpSectionBase = actctx->comserver_section; 4368 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section ); 4369 data->hActCtx = NULL; 4370 4371 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4372 data->ulAssemblyRosterIndex = index->rosterindex; 4373 4374 return STATUS_SUCCESS; 4375 } 4376 4377 static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len) 4378 { 4379 unsigned int i; 4380 4381 for (i = 0; i < entities->num; i++) 4382 { 4383 struct entity *entity = &entities->base[i]; 4384 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4385 { 4386 *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data); 4387 if (entity->u.ifaceps.name) 4388 *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR)); 4389 *count += 1; 4390 } 4391 } 4392 } 4393 4394 static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities, 4395 struct guid_index **index, ULONG *data_offset, ULONG rosterindex) 4396 { 4397 unsigned int i; 4398 4399 for (i = 0; i < entities->num; i++) 4400 { 4401 struct entity *entity = &entities->base[i]; 4402 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION) 4403 { 4404 struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset); 4405 UNICODE_STRING str; 4406 ULONG name_len; 4407 4408 if (entity->u.ifaceps.name) 4409 name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR); 4410 else 4411 name_len = 0; 4412 4413 /* setup index */ 4414 RtlInitUnicodeString(&str, entity->u.ifaceps.iid); 4415 RtlGUIDFromString(&str, &(*index)->guid); 4416 (*index)->data_offset = *data_offset; 4417 (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0; 4418 (*index)->rosterindex = rosterindex; 4419 4420 /* setup data record */ 4421 data->size = sizeof(*data); 4422 data->mask = entity->u.ifaceps.mask; 4423 4424 /* proxyStubClsid32 value is only stored for external PS, 4425 if set it's used as iid, otherwise 'iid' attribute value is used */ 4426 if (entity->u.ifaceps.ps32) 4427 { 4428 RtlInitUnicodeString(&str, entity->u.ifaceps.ps32); 4429 RtlGUIDFromString(&str, &data->iid); 4430 } 4431 else 4432 data->iid = (*index)->guid; 4433 4434 data->nummethods = entity->u.ifaceps.nummethods; 4435 4436 if (entity->u.ifaceps.tlib) 4437 { 4438 RtlInitUnicodeString(&str, entity->u.ifaceps.tlib); 4439 RtlGUIDFromString(&str, &data->tlbid); 4440 } 4441 else 4442 memset(&data->tlbid, 0, sizeof(data->tlbid)); 4443 4444 if (entity->u.ifaceps.base) 4445 { 4446 RtlInitUnicodeString(&str, entity->u.ifaceps.base); 4447 RtlGUIDFromString(&str, &data->base); 4448 } 4449 else 4450 memset(&data->base, 0, sizeof(data->base)); 4451 4452 data->name_len = name_len; 4453 data->name_offset = data->name_len ? sizeof(*data) : 0; 4454 4455 /* name string */ 4456 if (data->name_len) 4457 { 4458 WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4459 memcpy(ptrW, entity->u.ifaceps.name, data->name_len); 4460 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4461 } 4462 4463 /* move to next record */ 4464 (*index) += 1; 4465 *data_offset += sizeof(*data); 4466 if (data->name_len) 4467 *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR)); 4468 } 4469 } 4470 } 4471 4472 static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4473 { 4474 unsigned int i, j, total_len = 0, count = 0; 4475 struct guidsection_header *header; 4476 struct guid_index *index; 4477 ULONG data_offset; 4478 4479 /* compute section length */ 4480 for (i = 0; i < actctx->num_assemblies; i++) 4481 { 4482 struct assembly *assembly = &actctx->assemblies[i]; 4483 4484 get_ifaceps_datalen(&assembly->entities, &count, &total_len); 4485 for (j = 0; j < assembly->num_dlls; j++) 4486 { 4487 struct dll_redirect *dll = &assembly->dlls[j]; 4488 get_ifaceps_datalen(&dll->entities, &count, &total_len); 4489 } 4490 } 4491 4492 total_len += sizeof(*header); 4493 4494 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4495 if (!header) return STATUS_NO_MEMORY; 4496 4497 memset(header, 0, sizeof(*header)); 4498 header->magic = GUIDSECTION_MAGIC; 4499 header->size = sizeof(*header); 4500 header->count = count; 4501 header->index_offset = sizeof(*header); 4502 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4503 data_offset = header->index_offset + count*sizeof(*index); 4504 4505 for (i = 0; i < actctx->num_assemblies; i++) 4506 { 4507 struct assembly *assembly = &actctx->assemblies[i]; 4508 4509 add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1); 4510 for (j = 0; j < assembly->num_dlls; j++) 4511 { 4512 struct dll_redirect *dll = &assembly->dlls[j]; 4513 add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1); 4514 } 4515 } 4516 4517 *section = header; 4518 4519 return STATUS_SUCCESS; 4520 } 4521 4522 static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index) 4523 { 4524 return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset); 4525 } 4526 4527 static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4528 { 4529 struct ifacepsredirect_data *iface; 4530 struct guid_index *index = NULL; 4531 4532 if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4533 4534 if (!actctx->ifaceps_section) 4535 { 4536 struct guidsection_header *section; 4537 4538 NTSTATUS status = build_ifaceps_section(actctx, §ion); 4539 if (status) return status; 4540 4541 if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL)) 4542 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4543 } 4544 4545 index = find_guid_index(actctx->ifaceps_section, guid); 4546 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4547 4548 iface = get_ifaceps_data(actctx, index); 4549 4550 data->ulDataFormatVersion = 1; 4551 data->lpData = iface; 4552 data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0); 4553 data->lpSectionGlobalData = NULL; 4554 data->ulSectionGlobalDataLength = 0; 4555 data->lpSectionBase = actctx->ifaceps_section; 4556 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section ); 4557 data->hActCtx = NULL; 4558 4559 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4560 data->ulAssemblyRosterIndex = index->rosterindex; 4561 4562 return STATUS_SUCCESS; 4563 } 4564 4565 static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section) 4566 { 4567 unsigned int i, j, total_len = 0, count = 0; 4568 struct guidsection_header *header; 4569 struct clrsurrogate_data *data; 4570 struct guid_index *index; 4571 ULONG data_offset; 4572 4573 /* compute section length */ 4574 for (i = 0; i < actctx->num_assemblies; i++) 4575 { 4576 struct assembly *assembly = &actctx->assemblies[i]; 4577 for (j = 0; j < assembly->entities.num; j++) 4578 { 4579 struct entity *entity = &assembly->entities.base[j]; 4580 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4581 { 4582 ULONG len; 4583 4584 total_len += sizeof(*index) + sizeof(*data); 4585 len = strlenW(entity->u.clrsurrogate.name) + 1; 4586 if (entity->u.clrsurrogate.version) 4587 len += strlenW(entity->u.clrsurrogate.version) + 1; 4588 total_len += aligned_string_len(len*sizeof(WCHAR)); 4589 4590 count++; 4591 } 4592 } 4593 } 4594 4595 total_len += sizeof(*header); 4596 4597 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4598 if (!header) return STATUS_NO_MEMORY; 4599 4600 memset(header, 0, sizeof(*header)); 4601 header->magic = GUIDSECTION_MAGIC; 4602 header->size = sizeof(*header); 4603 header->count = count; 4604 header->index_offset = sizeof(*header); 4605 index = (struct guid_index*)((BYTE*)header + header->index_offset); 4606 data_offset = header->index_offset + count*sizeof(*index); 4607 4608 for (i = 0; i < actctx->num_assemblies; i++) 4609 { 4610 struct assembly *assembly = &actctx->assemblies[i]; 4611 for (j = 0; j < assembly->entities.num; j++) 4612 { 4613 struct entity *entity = &assembly->entities.base[j]; 4614 if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES) 4615 { 4616 ULONG version_len, name_len; 4617 UNICODE_STRING str; 4618 WCHAR *ptrW; 4619 4620 if (entity->u.clrsurrogate.version) 4621 version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR); 4622 else 4623 version_len = 0; 4624 name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR); 4625 4626 /* setup new index entry */ 4627 RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid); 4628 RtlGUIDFromString(&str, &index->guid); 4629 4630 index->data_offset = data_offset; 4631 index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0)); 4632 index->rosterindex = i + 1; 4633 4634 /* setup data */ 4635 data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset); 4636 data->size = sizeof(*data); 4637 data->res = 0; 4638 data->clsid = index->guid; 4639 data->version_offset = version_len ? data->size : 0; 4640 data->version_len = version_len; 4641 data->name_offset = data->size + version_len; 4642 if (version_len) 4643 data->name_offset += sizeof(WCHAR); 4644 data->name_len = name_len; 4645 4646 /* surrogate name */ 4647 ptrW = (WCHAR*)((BYTE*)data + data->name_offset); 4648 memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len); 4649 ptrW[data->name_len/sizeof(WCHAR)] = 0; 4650 4651 /* runtime version */ 4652 if (data->version_len) 4653 { 4654 ptrW = (WCHAR*)((BYTE*)data + data->version_offset); 4655 memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len); 4656 ptrW[data->version_len/sizeof(WCHAR)] = 0; 4657 } 4658 4659 data_offset += index->data_offset; 4660 index++; 4661 } 4662 } 4663 } 4664 4665 *section = header; 4666 4667 return STATUS_SUCCESS; 4668 } 4669 4670 static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index) 4671 { 4672 return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset); 4673 } 4674 4675 static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data) 4676 { 4677 struct clrsurrogate_data *surrogate; 4678 struct guid_index *index = NULL; 4679 4680 if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4681 4682 if (!actctx->clrsurrogate_section) 4683 { 4684 struct guidsection_header *section; 4685 4686 NTSTATUS status = build_clr_surrogate_section(actctx, §ion); 4687 if (status) return status; 4688 4689 if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL)) 4690 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4691 } 4692 4693 index = find_guid_index(actctx->clrsurrogate_section, guid); 4694 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4695 4696 surrogate = get_surrogate_data(actctx, index); 4697 4698 data->ulDataFormatVersion = 1; 4699 data->lpData = surrogate; 4700 /* full length includes string length with nulls */ 4701 data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR); 4702 if (surrogate->version_len) 4703 data->ulLength += surrogate->version_len + sizeof(WCHAR); 4704 4705 data->lpSectionGlobalData = NULL; 4706 data->ulSectionGlobalDataLength = 0; 4707 data->lpSectionBase = actctx->clrsurrogate_section; 4708 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section ); 4709 data->hActCtx = NULL; 4710 4711 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4712 data->ulAssemblyRosterIndex = index->rosterindex; 4713 4714 return STATUS_SUCCESS; 4715 } 4716 4717 static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len) 4718 { 4719 unsigned int i, j, single_len; 4720 4721 single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID); 4722 for (i = 0; i < entities->num; i++) 4723 { 4724 struct entity *entity = &entities->base[i]; 4725 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4726 { 4727 if (entity->u.comclass.progid) 4728 { 4729 *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR)); 4730 *count += 1; 4731 } 4732 4733 for (j = 0; j < entity->u.comclass.progids.num; j++) 4734 *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR)); 4735 4736 *total_len += single_len*entity->u.comclass.progids.num; 4737 *count += entity->u.comclass.progids.num; 4738 } 4739 } 4740 } 4741 4742 static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias, 4743 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4744 { 4745 struct progidredirect_data *data; 4746 UNICODE_STRING str; 4747 GUID *guid_ptr; 4748 WCHAR *ptrW; 4749 4750 /* setup new index entry */ 4751 4752 /* hash progid name */ 4753 RtlInitUnicodeString(&str, progid); 4754 RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash); 4755 4756 (*index)->name_offset = *data_offset; 4757 (*index)->name_len = str.Length; 4758 (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength); 4759 (*index)->data_len = sizeof(*data); 4760 (*index)->rosterindex = rosterindex; 4761 4762 *data_offset += aligned_string_len(str.MaximumLength); 4763 4764 /* setup data structure */ 4765 data = (struct progidredirect_data*)((BYTE*)section + *data_offset); 4766 data->size = sizeof(*data); 4767 data->reserved = 0; 4768 data->clsid_offset = *global_offset; 4769 4770 /* write progid string */ 4771 ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset); 4772 memcpy(ptrW, progid, (*index)->name_len); 4773 ptrW[(*index)->name_len/sizeof(WCHAR)] = 0; 4774 4775 /* write guid to global area */ 4776 guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset); 4777 *guid_ptr = *alias; 4778 4779 /* to next entry */ 4780 *global_offset += sizeof(GUID); 4781 *data_offset += data->size; 4782 (*index) += 1; 4783 } 4784 4785 static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities, 4786 struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex) 4787 { 4788 unsigned int i, j; 4789 4790 for (i = 0; i < entities->num; i++) 4791 { 4792 struct entity *entity = &entities->base[i]; 4793 if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION) 4794 { 4795 const struct progids *progids = &entity->u.comclass.progids; 4796 struct comclassredirect_data *comclass; 4797 struct guid_index *guid_index; 4798 UNICODE_STRING str; 4799 GUID clsid; 4800 4801 RtlInitUnicodeString(&str, entity->u.comclass.clsid); 4802 RtlGUIDFromString(&str, &clsid); 4803 4804 guid_index = find_guid_index(actctx->comserver_section, &clsid); 4805 comclass = get_comclass_data(actctx, guid_index); 4806 4807 if (entity->u.comclass.progid) 4808 write_progid_record(section, entity->u.comclass.progid, &comclass->alias, 4809 index, data_offset, global_offset, rosterindex); 4810 4811 for (j = 0; j < progids->num; j++) 4812 write_progid_record(section, progids->progids[j], &comclass->alias, 4813 index, data_offset, global_offset, rosterindex); 4814 } 4815 } 4816 } 4817 4818 static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section) 4819 { 4820 unsigned int i, j, total_len = 0, count = 0; 4821 struct strsection_header *header; 4822 ULONG data_offset, global_offset; 4823 struct string_index *index; 4824 4825 /* compute section length */ 4826 for (i = 0; i < actctx->num_assemblies; i++) 4827 { 4828 struct assembly *assembly = &actctx->assemblies[i]; 4829 4830 get_progid_datalen(&assembly->entities, &count, &total_len); 4831 for (j = 0; j < assembly->num_dlls; j++) 4832 { 4833 struct dll_redirect *dll = &assembly->dlls[j]; 4834 get_progid_datalen(&dll->entities, &count, &total_len); 4835 } 4836 } 4837 4838 total_len += sizeof(*header); 4839 4840 header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len); 4841 if (!header) return STATUS_NO_MEMORY; 4842 4843 memset(header, 0, sizeof(*header)); 4844 header->magic = STRSECTION_MAGIC; 4845 header->size = sizeof(*header); 4846 header->count = count; 4847 header->global_offset = header->size; 4848 header->global_len = count*sizeof(GUID); 4849 header->index_offset = header->size + header->global_len; 4850 4851 index = (struct string_index*)((BYTE*)header + header->index_offset); 4852 data_offset = header->index_offset + count*sizeof(*index); 4853 global_offset = header->global_offset; 4854 4855 for (i = 0; i < actctx->num_assemblies; i++) 4856 { 4857 struct assembly *assembly = &actctx->assemblies[i]; 4858 4859 add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1); 4860 for (j = 0; j < assembly->num_dlls; j++) 4861 { 4862 struct dll_redirect *dll = &assembly->dlls[j]; 4863 add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1); 4864 } 4865 } 4866 4867 *section = header; 4868 4869 return STATUS_SUCCESS; 4870 } 4871 4872 static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index) 4873 { 4874 return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset); 4875 } 4876 4877 static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name, 4878 PACTCTX_SECTION_KEYED_DATA data) 4879 { 4880 struct progidredirect_data *progid; 4881 struct string_index *index; 4882 4883 if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND; 4884 4885 if (!actctx->comserver_section) 4886 { 4887 struct guidsection_header *section; 4888 4889 NTSTATUS status = build_comserver_section(actctx, §ion); 4890 if (status) return status; 4891 4892 if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL)) 4893 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4894 } 4895 4896 if (!actctx->progid_section) 4897 { 4898 struct strsection_header *section; 4899 4900 NTSTATUS status = build_progid_section(actctx, §ion); 4901 if (status) return status; 4902 4903 if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL)) 4904 RtlFreeHeap(RtlGetProcessHeap(), 0, section); 4905 } 4906 4907 index = find_string_index(actctx->progid_section, name); 4908 if (!index) return STATUS_SXS_KEY_NOT_FOUND; 4909 4910 if (data) 4911 { 4912 progid = get_progid_data(actctx, index); 4913 4914 data->ulDataFormatVersion = 1; 4915 data->lpData = progid; 4916 data->ulLength = progid->size; 4917 data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset; 4918 data->ulSectionGlobalDataLength = actctx->progid_section->global_len; 4919 data->lpSectionBase = actctx->progid_section; 4920 data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section ); 4921 data->hActCtx = NULL; 4922 4923 if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 4924 data->ulAssemblyRosterIndex = index->rosterindex; 4925 } 4926 4927 return STATUS_SUCCESS; 4928 } 4929 4930 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 4931 const UNICODE_STRING *section_name, 4932 DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 4933 { 4934 NTSTATUS status; 4935 4936 switch (section_kind) 4937 { 4938 case ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION: 4939 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 4940 return STATUS_SXS_KEY_NOT_FOUND; 4941 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: 4942 status = find_dll_redirection(actctx, section_name, data); 4943 break; 4944 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 4945 status = find_window_class(actctx, section_name, data); 4946 break; 4947 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 4948 status = find_progid_redirection(actctx, section_name, data); 4949 break; 4950 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: 4951 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 4952 return STATUS_SXS_SECTION_NOT_FOUND; 4953 default: 4954 DPRINT1("Unknown section_kind %x\n", section_kind); 4955 return STATUS_SXS_SECTION_NOT_FOUND; 4956 } 4957 4958 if (status != STATUS_SUCCESS) return status; 4959 4960 if (data && (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)) 4961 { 4962 actctx_addref(actctx); 4963 data->hActCtx = actctx; 4964 } 4965 return STATUS_SUCCESS; 4966 } 4967 4968 static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 4969 const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 4970 { 4971 NTSTATUS status; 4972 4973 switch (section_kind) 4974 { 4975 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 4976 status = find_tlib_redirection(actctx, guid, data); 4977 break; 4978 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 4979 status = find_comserver_redirection(actctx, guid, data); 4980 break; 4981 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 4982 status = find_cominterface_redirection(actctx, guid, data); 4983 break; 4984 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 4985 status = find_clr_surrogate(actctx, guid, data); 4986 break; 4987 default: 4988 DPRINT("Unknown section_kind %x\n", section_kind); 4989 return STATUS_SXS_SECTION_NOT_FOUND; 4990 } 4991 4992 if (status != STATUS_SUCCESS) return status; 4993 4994 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 4995 { 4996 actctx_addref(actctx); 4997 data->hActCtx = actctx; 4998 } 4999 return STATUS_SUCCESS; 5000 } 5001 5002 /* initialize the activation context for the current process */ 5003 void actctx_init(PVOID* pOldShimData) 5004 { 5005 ACTCTXW ctx; 5006 HANDLE handle; 5007 WCHAR buffer[1024]; 5008 NTSTATUS Status; 5009 5010 ctx.cbSize = sizeof(ctx); 5011 ctx.lpSource = NULL; 5012 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 5013 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5014 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 5015 5016 if (NT_SUCCESS(RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle))) 5017 { 5018 process_actctx = check_actctx(handle); 5019 } 5020 5021 /* ReactOS specific: 5022 Now that we have found the process_actctx we can initialize the process compat subsystem */ 5023 LdrpInitializeProcessCompat(process_actctx, pOldShimData); 5024 5025 5026 ctx.dwFlags = 0; 5027 ctx.hModule = NULL; 5028 ctx.lpResourceName = NULL; 5029 ctx.lpSource = buffer; 5030 RtlStringCchCopyW(buffer, RTL_NUMBER_OF(buffer), SharedUserData->NtSystemRoot); 5031 5032 if (RosGetProcessCompatVersion()) 5033 { 5034 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\forwardcompatible.manifest"); 5035 } 5036 else 5037 { 5038 RtlStringCchCatW(buffer, RTL_NUMBER_OF(buffer), L"\\winsxs\\manifests\\systemcompatible.manifest"); 5039 } 5040 5041 Status = RtlCreateActivationContext(0, (PVOID)&ctx, 0, NULL, NULL, &handle); 5042 if (NT_SUCCESS(Status)) 5043 { 5044 implicit_actctx = check_actctx(handle); 5045 } 5046 else 5047 { 5048 DPRINT1("Failed to create the implicit act ctx. Status: 0x%x!!!\n", Status); 5049 } 5050 } 5051 5052 /* FUNCTIONS ***************************************************************/ 5053 5054 /*********************************************************************** 5055 * RtlCreateActivationContext (NTDLL.@) 5056 * 5057 * Create an activation context. 5058 */ 5059 NTSTATUS 5060 NTAPI 5061 RtlCreateActivationContext(IN ULONG Flags, 5062 IN PACTIVATION_CONTEXT_DATA ActivationContextData, 5063 IN ULONG ExtraBytes, 5064 IN PVOID NotificationRoutine, 5065 IN PVOID NotificationContext, 5066 OUT PACTIVATION_CONTEXT *ActCtx) 5067 { 5068 const ACTCTXW *pActCtx = (PVOID)ActivationContextData; 5069 const WCHAR *directory = NULL; 5070 PACTIVATION_CONTEXT_WRAPPED ActualActCtx; 5071 ACTIVATION_CONTEXT *actctx; 5072 UNICODE_STRING nameW; 5073 ULONG lang = 0; 5074 NTSTATUS status = STATUS_NO_MEMORY; 5075 HANDLE file = 0; 5076 struct actctx_loader acl; 5077 5078 DPRINT("RtlCreateActivationContext %p %08x, Image Base: %p\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0, ((ACTCTXW*)ActivationContextData)->hModule); 5079 5080 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) || 5081 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL)) 5082 return STATUS_INVALID_PARAMETER; 5083 5084 5085 if (!(ActualActCtx = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ActualActCtx)))) 5086 return STATUS_NO_MEMORY; 5087 5088 ActualActCtx->MagicMarker = ACTCTX_MAGIC_MARKER; 5089 5090 actctx = &ActualActCtx->ActivationContext; 5091 actctx->RefCount = 1; 5092 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; 5093 actctx->config.info = NULL; 5094 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; 5095 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) 5096 { 5097 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error; 5098 } 5099 else 5100 { 5101 UNICODE_STRING dir; 5102 WCHAR *p; 5103 HMODULE module; 5104 5105 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule; 5106 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 5107 5108 status = get_module_filename( module, &dir, 0 ); 5109 if (!NT_SUCCESS(status)) goto error; 5110 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0; 5111 actctx->appdir.info = dir.Buffer; 5112 } 5113 5114 nameW.Buffer = NULL; 5115 5116 /* open file only if it's going to be used */ 5117 if (pActCtx->lpSource && !((pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) && 5118 (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID))) 5119 { 5120 WCHAR *source = NULL; 5121 BOOLEAN ret; 5122 5123 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID && 5124 RtlDetermineDosPathNameType_U(pActCtx->lpSource) == RtlPathTypeRelative) 5125 { 5126 DWORD dir_len, source_len; 5127 5128 dir_len = strlenW(pActCtx->lpAssemblyDirectory); 5129 source_len = strlenW(pActCtx->lpSource); 5130 if (!(source = RtlAllocateHeap( RtlGetProcessHeap(), 0, (dir_len+source_len+2)*sizeof(WCHAR)))) 5131 { 5132 status = STATUS_NO_MEMORY; 5133 goto error; 5134 } 5135 5136 memcpy(source, pActCtx->lpAssemblyDirectory, dir_len*sizeof(WCHAR)); 5137 source[dir_len] = '\\'; 5138 memcpy(source+dir_len+1, pActCtx->lpSource, (source_len+1)*sizeof(WCHAR)); 5139 } 5140 5141 ret = RtlDosPathNameToNtPathName_U(source ? source : pActCtx->lpSource, &nameW, NULL, NULL); 5142 RtlFreeHeap( RtlGetProcessHeap(), 0, source ); 5143 if (!ret) 5144 { 5145 status = STATUS_NO_SUCH_FILE; 5146 goto error; 5147 } 5148 status = open_nt_file( &file, &nameW ); 5149 if (!NT_SUCCESS(status)) 5150 { 5151 RtlFreeUnicodeString( &nameW ); 5152 goto error; 5153 } 5154 } 5155 5156 acl.actctx = actctx; 5157 acl.dependencies = NULL; 5158 acl.num_dependencies = 0; 5159 acl.allocated_dependencies = 0; 5160 5161 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; 5162 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; 5163 5164 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) 5165 { 5166 /* if we have a resource it's a PE file */ 5167 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) 5168 { 5169 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule, 5170 pActCtx->lpResourceName, lang ); 5171 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5172 /* FIXME: what to do if pActCtx->lpSource is set */ 5173 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, 5174 pActCtx->hModule, pActCtx->lpResourceName ); 5175 } 5176 else if (pActCtx->lpSource && pActCtx->lpResourceName) 5177 { 5178 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE, 5179 file, pActCtx->lpResourceName, lang ); 5180 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 5181 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, 5182 NULL, pActCtx->lpResourceName ); 5183 } 5184 else status = STATUS_INVALID_PARAMETER; 5185 } 5186 else 5187 { 5188 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file ); 5189 } 5190 5191 if (file) NtClose( file ); 5192 RtlFreeUnicodeString( &nameW ); 5193 5194 if (NT_SUCCESS(status)) status = parse_depend_manifests(&acl); 5195 free_depend_manifests( &acl ); 5196 5197 if (NT_SUCCESS(status)) 5198 *ActCtx = actctx; 5199 else actctx_release( actctx ); 5200 return status; 5201 5202 error: 5203 if (file) NtClose( file ); 5204 actctx_release( actctx ); 5205 return status; 5206 } 5207 5208 #if 0 5209 #define ACT_CTX_VALID(p) ((((ULONG_PTR)p - 1) | 7) != -1) 5210 5211 VOID 5212 NTAPI 5213 RtlAddRefActivationContext(IN PACTIVATION_CONTEXT Handle) 5214 { 5215 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT)Handle; 5216 LONG OldRefCount, NewRefCount; 5217 5218 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5219 { 5220 RtlpValidateActCtx(ActCtx); 5221 5222 while (TRUE) 5223 { 5224 OldRefCount = ActCtx->RefCount; 5225 ASSERT(OldRefCount > 0); 5226 5227 if (OldRefCount == LONG_MAX) break; 5228 5229 NewRefCount = OldRefCount + 1; 5230 if (InterlockedCompareExchange(&ActCtx->RefCount, 5231 NewRefCount, 5232 OldRefCount) == OldRefCount) 5233 { 5234 break; 5235 } 5236 } 5237 5238 NewRefCount = LONG_MAX; 5239 ASSERT(NewRefCount > 0); 5240 } 5241 } 5242 5243 VOID 5244 NTAPI 5245 RtlReleaseActivationContext( HANDLE handle ) 5246 { 5247 PIACTIVATION_CONTEXT ActCtx = (PIACTIVATION_CONTEXT) Handle; 5248 5249 if ((ActCtx) && (ACT_CTX_VALID(ActCtx)) && (ActCtx->RefCount != LONG_MAX)) 5250 { 5251 RtlpValidateActCtx(ActCtx); 5252 5253 actctx_release(ActCtx); 5254 } 5255 } 5256 #else 5257 5258 /*********************************************************************** 5259 * RtlAddRefActivationContext (NTDLL.@) 5260 */ 5261 VOID NTAPI RtlAddRefActivationContext( HANDLE handle ) 5262 { 5263 ACTIVATION_CONTEXT *actctx; 5264 5265 if ((actctx = check_actctx( handle ))) actctx_addref( actctx ); 5266 } 5267 5268 5269 /****************************************************************** 5270 * RtlReleaseActivationContext (NTDLL.@) 5271 */ 5272 VOID NTAPI RtlReleaseActivationContext( HANDLE handle ) 5273 { 5274 ACTIVATION_CONTEXT *actctx; 5275 5276 if ((actctx = check_actctx( handle ))) actctx_release( actctx ); 5277 } 5278 5279 #endif 5280 5281 /****************************************************************** 5282 * RtlZombifyActivationContext (NTDLL.@) 5283 * 5284 */ 5285 NTSTATUS NTAPI RtlZombifyActivationContext(PVOID Context) 5286 { 5287 UNIMPLEMENTED; 5288 5289 if (Context == ACTCTX_FAKE_HANDLE) 5290 return STATUS_SUCCESS; 5291 5292 return STATUS_NOT_IMPLEMENTED; 5293 } 5294 5295 NTSTATUS 5296 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie ) 5297 { 5298 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5299 5300 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) ))) 5301 return STATUS_NO_MEMORY; 5302 5303 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame; 5304 frame->ActivationContext = handle; 5305 frame->Flags = 0; 5306 5307 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5308 tebAddress->ActivationContextStackPointer, tebAddress->ActivationContextStackPointer->ActiveFrame, 5309 frame, handle); 5310 5311 tebAddress->ActivationContextStackPointer->ActiveFrame = frame; 5312 RtlAddRefActivationContext( handle ); 5313 5314 *cookie = (ULONG_PTR)frame; 5315 DPRINT( "%p cookie=%lx\n", handle, *cookie ); 5316 return STATUS_SUCCESS; 5317 } 5318 5319 /****************************************************************** 5320 * RtlActivateActivationContext (NTDLL.@) 5321 */ 5322 NTSTATUS NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie ) 5323 { 5324 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie); 5325 } 5326 5327 /*********************************************************************** 5328 * RtlDeactivateActivationContext (NTDLL.@) 5329 */ 5330 NTSTATUS NTAPI RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) 5331 { 5332 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; 5333 5334 DPRINT( "%x cookie=%lx\n", flags, cookie ); 5335 5336 /* find the right frame */ 5337 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5338 for (frame = top; frame; frame = frame->Previous) 5339 if ((ULONG_PTR)frame == cookie) break; 5340 5341 if (!frame) 5342 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 5343 5344 if (frame != top && !(flags & RTL_DEACTIVATE_ACTIVATION_CONTEXT_FLAG_FORCE_EARLY_DEACTIVATION)) 5345 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); 5346 5347 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5348 NtCurrentTeb()->ActivationContextStackPointer, 5349 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame, 5350 frame->Previous); 5351 5352 /* pop everything up to and including frame */ 5353 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 5354 5355 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5356 { 5357 frame = top->Previous; 5358 RtlReleaseActivationContext( top->ActivationContext ); 5359 RtlFreeHeap( RtlGetProcessHeap(), 0, top ); 5360 top = frame; 5361 } 5362 5363 return STATUS_SUCCESS; 5364 } 5365 5366 VOID 5367 NTAPI 5368 RtlFreeActivationContextStack(IN PACTIVATION_CONTEXT_STACK Stack) 5369 { 5370 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame; 5371 5372 /* Nothing to do if there is no stack */ 5373 if (!Stack) return; 5374 5375 /* Get the current active frame */ 5376 ActiveFrame = Stack->ActiveFrame; 5377 5378 /* Go through them in backwards order and release */ 5379 while (ActiveFrame) 5380 { 5381 PrevFrame = ActiveFrame->Previous; 5382 RtlReleaseActivationContext(ActiveFrame->ActivationContext); 5383 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame); 5384 ActiveFrame = PrevFrame; 5385 } 5386 5387 /* Zero out the active frame */ 5388 Stack->ActiveFrame = NULL; 5389 5390 /* TODO: Empty the Frame List Cache */ 5391 ASSERT(IsListEmpty(&Stack->FrameListCache)); 5392 5393 /* Free activation stack memory */ 5394 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack); 5395 } 5396 5397 /****************************************************************** 5398 * RtlFreeThreadActivationContextStack (NTDLL.@) 5399 */ 5400 VOID NTAPI RtlFreeThreadActivationContextStack(VOID) 5401 { 5402 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer); 5403 NtCurrentTeb()->ActivationContextStackPointer = NULL; 5404 } 5405 5406 5407 /****************************************************************** 5408 * RtlGetActiveActivationContext (NTDLL.@) 5409 */ 5410 NTSTATUS NTAPI RtlGetActiveActivationContext( HANDLE *handle ) 5411 { 5412 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5413 { 5414 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 5415 RtlAddRefActivationContext( *handle ); 5416 } 5417 else 5418 *handle = 0; 5419 5420 return STATUS_SUCCESS; 5421 } 5422 5423 5424 /****************************************************************** 5425 * RtlIsActivationContextActive (NTDLL.@) 5426 */ 5427 BOOLEAN NTAPI RtlIsActivationContextActive( HANDLE handle ) 5428 { 5429 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 5430 5431 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous) 5432 if (frame->ActivationContext == handle) return TRUE; 5433 return FALSE; 5434 } 5435 5436 5437 /*********************************************************************** 5438 * RtlQueryInformationActivationContext (NTDLL.@) 5439 * 5440 * Get information about an activation context. 5441 * FIXME: function signature/prototype may be wrong 5442 */ 5443 NTSTATUS NTAPI RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, 5444 ULONG class, PVOID buffer, 5445 SIZE_T bufsize, SIZE_T *retlen ) 5446 { 5447 ACTIVATION_CONTEXT *actctx; 5448 NTSTATUS status; 5449 5450 DPRINT("%08x %p %p %u %p %Iu %p\n", flags, handle, 5451 subinst, class, buffer, bufsize, retlen); 5452 5453 if (retlen) *retlen = 0; 5454 if ((status = find_query_actctx( &handle, flags, class ))) return status; 5455 5456 switch (class) 5457 { 5458 case ActivationContextBasicInformation: 5459 { 5460 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; 5461 5462 if (retlen) *retlen = sizeof(*info); 5463 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; 5464 5465 info->hActCtx = handle; 5466 info->dwFlags = 0; /* FIXME */ 5467 if (!(flags & RTL_QUERY_ACTIVATION_CONTEXT_FLAG_NO_ADDREF)) RtlAddRefActivationContext(handle); 5468 } 5469 break; 5470 5471 case ActivationContextDetailedInformation: 5472 { 5473 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; 5474 struct assembly *assembly = NULL; 5475 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; 5476 LPWSTR ptr; 5477 5478 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5479 5480 if (actctx->num_assemblies) assembly = actctx->assemblies; 5481 5482 if (assembly && assembly->manifest.info) 5483 manifest_len = strlenW(assembly->manifest.info) + 1; 5484 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1; 5485 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1; 5486 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); 5487 5488 if (retlen) *retlen = len; 5489 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5490 5491 acdi->dwFlags = 0; 5492 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ 5493 acdi->ulAssemblyCount = actctx->num_assemblies; 5494 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; 5495 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0; 5496 acdi->ulRootConfigurationPathType = actctx->config.type; 5497 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0; 5498 acdi->ulAppDirPathType = actctx->appdir.type; 5499 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0; 5500 ptr = (LPWSTR)(acdi + 1); 5501 if (manifest_len) 5502 { 5503 acdi->lpRootManifestPath = ptr; 5504 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); 5505 ptr += manifest_len; 5506 } 5507 else acdi->lpRootManifestPath = NULL; 5508 if (config_len) 5509 { 5510 acdi->lpRootConfigurationPath = ptr; 5511 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); 5512 ptr += config_len; 5513 } 5514 else acdi->lpRootConfigurationPath = NULL; 5515 if (appdir_len) 5516 { 5517 acdi->lpAppDirPath = ptr; 5518 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); 5519 } 5520 else acdi->lpAppDirPath = NULL; 5521 } 5522 break; 5523 5524 case AssemblyDetailedInformationInActivationContext: 5525 { 5526 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; 5527 struct assembly *assembly; 5528 WCHAR *assembly_id; 5529 DWORD index; 5530 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; 5531 LPWSTR ptr; 5532 5533 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5534 if (!subinst) return STATUS_INVALID_PARAMETER; 5535 5536 index = *(DWORD*)subinst; 5537 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; 5538 5539 assembly = &actctx->assemblies[index - 1]; 5540 5541 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; 5542 id_len = strlenW(assembly_id) + 1; 5543 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1; 5544 5545 if (assembly->manifest.info && 5546 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST)) 5547 path_len = strlenW(assembly->manifest.info) + 1; 5548 5549 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); 5550 5551 if (retlen) *retlen = len; 5552 if (!buffer || bufsize < len) 5553 { 5554 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5555 return STATUS_BUFFER_TOO_SMALL; 5556 } 5557 5558 afdi->ulFlags = 0; /* FIXME */ 5559 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR); 5560 afdi->ulManifestPathType = assembly->manifest.type; 5561 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0; 5562 /* FIXME afdi->liManifestLastWriteTime = 0; */ 5563 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ 5564 afdi->ulPolicyPathLength = 0; 5565 /* FIXME afdi->liPolicyLastWriteTime = 0; */ 5566 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ 5567 afdi->ulManifestVersionMajor = 1; 5568 afdi->ulManifestVersionMinor = 0; 5569 afdi->ulPolicyVersionMajor = 0; /* FIXME */ 5570 afdi->ulPolicyVersionMinor = 0; /* FIXME */ 5571 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0; 5572 ptr = (LPWSTR)(afdi + 1); 5573 afdi->lpAssemblyEncodedAssemblyIdentity = ptr; 5574 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); 5575 ptr += id_len; 5576 if (path_len) 5577 { 5578 afdi->lpAssemblyManifestPath = ptr; 5579 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); 5580 ptr += path_len; 5581 } else afdi->lpAssemblyManifestPath = NULL; 5582 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ 5583 if (ad_len) 5584 { 5585 afdi->lpAssemblyDirectoryName = ptr; 5586 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); 5587 } 5588 else afdi->lpAssemblyDirectoryName = NULL; 5589 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 5590 } 5591 break; 5592 5593 case FileInformationInAssemblyOfAssemblyInActivationContext: 5594 { 5595 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; 5596 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; 5597 struct assembly *assembly; 5598 struct dll_redirect *dll; 5599 SIZE_T len, dll_len = 0; 5600 LPWSTR ptr; 5601 5602 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5603 if (!acqi) return STATUS_INVALID_PARAMETER; 5604 5605 if (acqi->ulAssemblyIndex >= actctx->num_assemblies) 5606 return STATUS_INVALID_PARAMETER; 5607 assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; 5608 5609 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) 5610 return STATUS_INVALID_PARAMETER; 5611 dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; 5612 5613 if (dll->name) dll_len = strlenW(dll->name) + 1; 5614 len = sizeof(*afdi) + dll_len * sizeof(WCHAR); 5615 5616 if (!buffer || bufsize < len) 5617 { 5618 if (retlen) *retlen = len; 5619 return STATUS_BUFFER_TOO_SMALL; 5620 } 5621 if (retlen) *retlen = 0; /* yes that's what native does !! */ 5622 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; 5623 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0; 5624 afdi->ulPathLength = 0; /* FIXME */ 5625 ptr = (LPWSTR)(afdi + 1); 5626 if (dll_len) 5627 { 5628 afdi->lpFileName = ptr; 5629 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); 5630 } else afdi->lpFileName = NULL; 5631 afdi->lpFilePath = NULL; /* FIXME */ 5632 } 5633 break; 5634 5635 case CompatibilityInformationInActivationContext: 5636 { 5637 /*ACTIVATION_CONTEXT_COMPATIBILITY_INFORMATION*/DWORD *acci = buffer; 5638 COMPATIBILITY_CONTEXT_ELEMENT *elements; 5639 struct assembly *assembly = NULL; 5640 ULONG num_compat_contexts = 0, n; 5641 SIZE_T len; 5642 5643 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5644 5645 if (actctx->num_assemblies) assembly = actctx->assemblies; 5646 5647 if (assembly) 5648 num_compat_contexts = assembly->num_compat_contexts; 5649 len = sizeof(*acci) + num_compat_contexts * sizeof(COMPATIBILITY_CONTEXT_ELEMENT); 5650 5651 if (retlen) *retlen = len; 5652 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 5653 5654 *acci = num_compat_contexts; 5655 elements = (COMPATIBILITY_CONTEXT_ELEMENT*)(acci + 1); 5656 for (n = 0; n < num_compat_contexts; ++n) 5657 { 5658 elements[n] = assembly->compat_contexts[n]; 5659 } 5660 } 5661 break; 5662 5663 case RunlevelInformationInActivationContext: 5664 { 5665 ACTIVATION_CONTEXT_RUN_LEVEL_INFORMATION *acrli = buffer; 5666 struct assembly *assembly; 5667 SIZE_T len; 5668 5669 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 5670 5671 len = sizeof(*acrli); 5672 if (retlen) *retlen = len; 5673 if (!buffer || bufsize < len) 5674 return STATUS_BUFFER_TOO_SMALL; 5675 5676 assembly = actctx->assemblies; 5677 5678 acrli->ulFlags = 0; 5679 acrli->RunLevel = assembly ? assembly->run_level : ACTCTX_RUN_LEVEL_UNSPECIFIED; 5680 acrli->UiAccess = assembly ? assembly->ui_access : 0; 5681 } 5682 break; 5683 5684 default: 5685 DPRINT( "class %u not implemented\n", class ); 5686 return STATUS_NOT_IMPLEMENTED; 5687 } 5688 return STATUS_SUCCESS; 5689 } 5690 5691 NTSTATUS 5692 NTAPI 5693 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, 5694 PVOID pvBuffer, 5695 SIZE_T cbBuffer OPTIONAL, 5696 SIZE_T *pcbWrittenOrRequired OPTIONAL) 5697 { 5698 return RtlQueryInformationActivationContext(RTL_QUERY_ACTIVATION_CONTEXT_FLAG_USE_ACTIVE_ACTIVATION_CONTEXT, 5699 NULL, 5700 NULL, 5701 ulInfoClass, 5702 pvBuffer, 5703 cbBuffer, 5704 pcbWrittenOrRequired); 5705 } 5706 5707 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002 5708 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004 5709 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5710 5711 NTSTATUS 5712 NTAPI 5713 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, 5714 const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) 5715 { 5716 /* Check general parameter combinations */ 5717 if (!section_name || !section_name->Buffer || 5718 (flags & ~FIND_ACTCTX_VALID_MASK) || 5719 ((flags & FIND_ACTCTX_VALID_MASK) && !data) || 5720 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) 5721 { 5722 DPRINT1("invalid parameter\n"); 5723 return STATUS_INVALID_PARAMETER; 5724 } 5725 5726 /* TODO */ 5727 if (flags & FIND_ACTCTX_RETURN_FLAGS || 5728 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 5729 { 5730 DPRINT1("unknown flags %08x\n", flags); 5731 return STATUS_INVALID_PARAMETER; 5732 } 5733 5734 return STATUS_SUCCESS; 5735 } 5736 5737 /*********************************************************************** 5738 * RtlFindActivationContextSectionString (NTDLL.@) 5739 * 5740 * Find information about a string in an activation context. 5741 * FIXME: function signature/prototype may be wrong 5742 */ 5743 NTSTATUS NTAPI RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, 5744 const UNICODE_STRING *section_name, PVOID ptr ) 5745 { 5746 PACTCTX_SECTION_KEYED_DATA data = ptr; 5747 NTSTATUS status; 5748 5749 DPRINT("RtlFindActivationContextSectionString(%x %p %x %wZ %p)\n", flags, guid, section_kind, section_name, ptr); 5750 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data); 5751 if (!NT_SUCCESS(status)) 5752 { 5753 DPRINT1("RtlFindActivationContextSectionString() failed with status %x\n", status); 5754 return status; 5755 } 5756 5757 status = STATUS_SXS_KEY_NOT_FOUND; 5758 5759 /* if there is no data, but params are valid, 5760 we return that sxs key is not found to be at least somehow compatible */ 5761 if (!data) 5762 { 5763 DPRINT("RtlFindActivationContextSectionString() failed with status %x\n", status); 5764 return status; 5765 } 5766 5767 ASSERT(NtCurrentTeb()); 5768 ASSERT(NtCurrentTeb()->ActivationContextStackPointer); 5769 5770 DPRINT("ActiveFrame: %p\n",NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame); 5771 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5772 { 5773 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5774 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); 5775 } 5776 5777 DPRINT("status %x\n", status); 5778 if (status != STATUS_SUCCESS) 5779 status = find_string( process_actctx, section_kind, section_name, flags, data ); 5780 5781 if (status != STATUS_SUCCESS) 5782 status = find_string( implicit_actctx, section_kind, section_name, flags, data ); 5783 5784 DPRINT("RtlFindActivationContextSectionString() returns status %x\n", status); 5785 return status; 5786 } 5787 5788 /*********************************************************************** 5789 * RtlFindActivationContextSectionGuid (NTDLL.@) 5790 * 5791 * Find information about a GUID in an activation context. 5792 * FIXME: function signature/prototype may be wrong 5793 */ 5794 NTSTATUS WINAPI RtlFindActivationContextSectionGuid( ULONG flags, const GUID *extguid, ULONG section_kind, 5795 const GUID *guid, void *ptr ) 5796 { 5797 ACTCTX_SECTION_KEYED_DATA *data = ptr; 5798 NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND; 5799 5800 if (extguid) 5801 { 5802 DPRINT1("expected extguid == NULL\n"); 5803 return STATUS_INVALID_PARAMETER; 5804 } 5805 5806 if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 5807 { 5808 DPRINT1("unknown flags %08x\n", flags); 5809 return STATUS_INVALID_PARAMETER; 5810 } 5811 5812 if (!data || data->cbSize < FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) || !guid) 5813 return STATUS_INVALID_PARAMETER; 5814 5815 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 5816 { 5817 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 5818 if (actctx) status = find_guid( actctx, section_kind, guid, flags, data ); 5819 } 5820 5821 if (status != STATUS_SUCCESS) 5822 status = find_guid( process_actctx, section_kind, guid, flags, data ); 5823 5824 if (status != STATUS_SUCCESS) 5825 status = find_guid( implicit_actctx, section_kind, guid, flags, data ); 5826 5827 return status; 5828 } 5829 5830 /* Stubs */ 5831 5832 NTSTATUS 5833 NTAPI 5834 RtlAllocateActivationContextStack(IN PACTIVATION_CONTEXT_STACK *Stack) 5835 { 5836 PACTIVATION_CONTEXT_STACK ContextStack; 5837 5838 /* Check if it's already allocated */ 5839 if (*Stack) return STATUS_SUCCESS; 5840 5841 /* Allocate space for the context stack */ 5842 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ACTIVATION_CONTEXT_STACK)); 5843 if (!ContextStack) 5844 { 5845 return STATUS_NO_MEMORY; 5846 } 5847 5848 /* Initialize the context stack */ 5849 ContextStack->Flags = 0; 5850 ContextStack->ActiveFrame = NULL; 5851 InitializeListHead(&ContextStack->FrameListCache); 5852 ContextStack->NextCookieSequenceNumber = 1; 5853 ContextStack->StackId = 1; //TODO: Timer-based 5854 5855 *Stack = ContextStack; 5856 5857 return STATUS_SUCCESS; 5858 } 5859 5860 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 5861 FASTCALL 5862 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, 5863 IN PVOID Context) 5864 { 5865 RTL_ACTIVATION_CONTEXT_STACK_FRAME *NewFrame; 5866 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame; 5867 5868 /* Get the current active frame */ 5869 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5870 5871 DPRINT("ActiveSP %p: ACTIVATE (ActiveFrame %p -> NewFrame %p, Context %p)\n", 5872 NtCurrentTeb()->ActivationContextStackPointer, ActiveFrame, 5873 &Frame->Frame, Context); 5874 5875 /* Ensure it's in the right format and at least fits basic info */ 5876 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 5877 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 5878 5879 /* Set debug info if size allows*/ 5880 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 5881 { 5882 Frame->Extra1 = (PVOID)(~(ULONG_PTR)ActiveFrame); 5883 Frame->Extra2 = (PVOID)(~(ULONG_PTR)Context); 5884 //Frame->Extra3 = ...; 5885 } 5886 5887 if (ActiveFrame) 5888 { 5889 /*ASSERT((ActiveFrame->Flags & 5890 (RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | 5891 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED | 5892 RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED)) == RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED);*/ 5893 5894 if (!(ActiveFrame->Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_HEAP_ALLOCATED)) 5895 { 5896 // TODO: Perform some additional checks if it was not heap allocated 5897 } 5898 } 5899 5900 /* Save pointer to the new activation frame */ 5901 NewFrame = &Frame->Frame; 5902 5903 /* Actually activate it */ 5904 Frame->Frame.Previous = ActiveFrame; 5905 Frame->Frame.ActivationContext = Context; 5906 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED; 5907 5908 /* Check if we can activate this context */ 5909 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) || 5910 Context) 5911 { 5912 /* Set new active frame */ 5913 DPRINT("Setting new active frame %p instead of old %p\n", NewFrame, ActiveFrame); 5914 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5915 return NewFrame; 5916 } 5917 5918 /* We can get here only one way: it was already activated */ 5919 DPRINT("Trying to activate already activated activation context\n"); 5920 5921 /* Activate only if we are allowing multiple activation */ 5922 #if 0 5923 if (!RtlpNotAllowingMultipleActivation) 5924 { 5925 Frame->Frame.Flags = RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED | RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED; 5926 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5927 } 5928 #else 5929 // Activate it anyway 5930 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame; 5931 #endif 5932 5933 /* Return pointer to the activation frame */ 5934 return NewFrame; 5935 } 5936 5937 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 5938 FASTCALL 5939 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) 5940 { 5941 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, NewFrame; 5942 5943 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 5944 5945 /* Ensure it's in the right format and at least fits basic info */ 5946 ASSERT(Frame->Format == RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER); 5947 ASSERT(Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC)); 5948 5949 /* Make sure it is not deactivated and it is activated */ 5950 ASSERT((Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED) == 0); 5951 ASSERT(Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_ACTIVATED); 5952 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); 5953 5954 /* Check debug info if it is present */ 5955 if (Frame->Size >= sizeof(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED)) 5956 { 5957 ASSERT(Frame->Extra1 == (PVOID)(~(ULONG_PTR)Frame->Frame.Previous)); 5958 ASSERT(Frame->Extra2 == (PVOID)(~(ULONG_PTR)Frame->Frame.ActivationContext)); 5959 //Frame->Extra3 = ...; 5960 } 5961 5962 if (ActiveFrame) 5963 { 5964 // TODO: Perform some additional checks here 5965 } 5966 5967 /* Special handling for not-really-activated */ 5968 if (Frame->Frame.Flags & RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_NOT_REALLY_ACTIVATED) 5969 { 5970 DPRINT1("Deactivating not really activated activation context\n"); 5971 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 5972 return &Frame->Frame; 5973 } 5974 5975 /* find the right frame */ 5976 NewFrame = &Frame->Frame; 5977 if (ActiveFrame != NewFrame) 5978 { 5979 DPRINT1("Deactivating wrong active frame: %p != %p\n", ActiveFrame, NewFrame); 5980 } 5981 5982 DPRINT("ActiveSP %p: DEACTIVATE (ActiveFrame %p -> PreviousFrame %p)\n", 5983 NtCurrentTeb()->ActivationContextStackPointer, NewFrame, NewFrame->Previous); 5984 5985 /* Pop everything up to and including frame */ 5986 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NewFrame->Previous; 5987 5988 Frame->Frame.Flags |= RTL_ACTIVATION_CONTEXT_STACK_FRAME_FLAG_DEACTIVATED; 5989 return NewFrame->Previous; 5990 } 5991