Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenactctx.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Runtime Library 00004 * PURPOSE: Activation Context Support 00005 * FILE: lib/rtl/actctx.c 00006 * PROGRAMERS: 00007 * Jon Griffiths 00008 * Eric Pouech 00009 * Jacek Caban for CodeWeavers 00010 * Alexandre Julliard 00011 * Stefan Ginsberg (stefan__100__@hotmail.com) 00012 * Samuel Serapión 00013 */ 00014 00015 /* Based on Wine 1.1.26 */ 00016 00017 /* INCLUDES *****************************************************************/ 00018 #include <rtl.h> 00019 00020 #define NDEBUG 00021 #include <debug.h> 00022 00023 #include <wine/unicode.h> 00024 00025 BOOLEAN RtlpNotAllowingMultipleActivation; 00026 00027 #define ACTCTX_FLAGS_ALL (\ 00028 ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\ 00029 ACTCTX_FLAG_LANGID_VALID |\ 00030 ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\ 00031 ACTCTX_FLAG_RESOURCE_NAME_VALID |\ 00032 ACTCTX_FLAG_SET_PROCESS_DEFAULT |\ 00033 ACTCTX_FLAG_APPLICATION_NAME_VALID |\ 00034 ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\ 00035 ACTCTX_FLAG_HMODULE_VALID ) 00036 00037 #define ACTCTX_MAGIC 0xC07E3E11 00038 00039 #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa) 00040 #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad) 00041 00042 00043 00044 typedef struct 00045 { 00046 const WCHAR *ptr; 00047 unsigned int len; 00048 } xmlstr_t; 00049 00050 typedef struct 00051 { 00052 const WCHAR *ptr; 00053 const WCHAR *end; 00054 } xmlbuf_t; 00055 00056 struct file_info 00057 { 00058 ULONG type; 00059 WCHAR *info; 00060 }; 00061 00062 struct assembly_version 00063 { 00064 USHORT major; 00065 USHORT minor; 00066 USHORT build; 00067 USHORT revision; 00068 }; 00069 00070 struct assembly_identity 00071 { 00072 WCHAR *name; 00073 WCHAR *arch; 00074 WCHAR *public_key; 00075 WCHAR *language; 00076 WCHAR *type; 00077 struct assembly_version version; 00078 BOOL optional; 00079 }; 00080 00081 struct entity 00082 { 00083 DWORD kind; 00084 union 00085 { 00086 struct 00087 { 00088 WCHAR *tlbid; 00089 WCHAR *version; 00090 WCHAR *helpdir; 00091 } typelib; 00092 struct 00093 { 00094 WCHAR *clsid; 00095 } comclass; 00096 struct { 00097 WCHAR *iid; 00098 WCHAR *name; 00099 } proxy; 00100 struct 00101 { 00102 WCHAR *name; 00103 } class; 00104 struct 00105 { 00106 WCHAR *name; 00107 WCHAR *clsid; 00108 } clrclass; 00109 struct 00110 { 00111 WCHAR *name; 00112 WCHAR *clsid; 00113 } clrsurrogate; 00114 } u; 00115 }; 00116 00117 struct entity_array 00118 { 00119 struct entity *base; 00120 unsigned int num; 00121 unsigned int allocated; 00122 }; 00123 00124 struct dll_redirect 00125 { 00126 WCHAR *name; 00127 WCHAR *hash; 00128 struct entity_array entities; 00129 }; 00130 00131 enum assembly_type 00132 { 00133 APPLICATION_MANIFEST, 00134 ASSEMBLY_MANIFEST, 00135 ASSEMBLY_SHARED_MANIFEST, 00136 }; 00137 00138 struct assembly 00139 { 00140 enum assembly_type type; 00141 struct assembly_identity id; 00142 struct file_info manifest; 00143 WCHAR *directory; 00144 BOOL no_inherit; 00145 struct dll_redirect *dlls; 00146 unsigned int num_dlls; 00147 unsigned int allocated_dlls; 00148 struct entity_array entities; 00149 }; 00150 00151 typedef struct _ACTIVATION_CONTEXT 00152 { 00153 ULONG magic; 00154 long ref_count; 00155 struct file_info config; 00156 struct file_info appdir; 00157 struct assembly *assemblies; 00158 unsigned int num_assemblies; 00159 unsigned int allocated_assemblies; 00160 } ACTIVATION_CONTEXT; 00161 00162 struct actctx_loader 00163 { 00164 ACTIVATION_CONTEXT *actctx; 00165 struct assembly_identity *dependencies; 00166 unsigned int num_dependencies; 00167 unsigned int allocated_dependencies; 00168 }; 00169 00170 static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0}; 00171 static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0}; 00172 static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0}; 00173 static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0}; 00174 static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0}; 00175 static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0}; 00176 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}; 00177 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}; 00178 static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0}; 00179 static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0}; 00180 static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0}; 00181 static const WCHAR fileW[] = {'f','i','l','e',0}; 00182 static const WCHAR asmv2hashW[] = {'a','s','m','v','2',':','h','a','s','h',0}; 00183 static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0}; 00184 static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0}; 00185 static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0}; 00186 static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0}; 00187 00188 static const WCHAR clsidW[] = {'c','l','s','i','d',0}; 00189 static const WCHAR hashW[] = {'h','a','s','h',0}; 00190 static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0}; 00191 static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0}; 00192 static const WCHAR iidW[] = {'i','i','d',0}; 00193 static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0}; 00194 static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0}; 00195 static const WCHAR nameW[] = {'n','a','m','e',0}; 00196 static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0}; 00197 static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0}; 00198 static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0}; 00199 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}; 00200 static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0}; 00201 static const WCHAR tlbidW[] = {'t','l','b','i','d',0}; 00202 static const WCHAR typeW[] = {'t','y','p','e',0}; 00203 static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0}; 00204 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0}; 00205 00206 static const WCHAR xmlW[] = {'?','x','m','l',0}; 00207 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}; 00208 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}; 00209 00210 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; 00211 static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0}; 00212 00213 static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 }; 00214 static ACTIVATION_CONTEXT *process_actctx = &system_actctx; 00215 00216 static WCHAR *strdupW(const WCHAR* str) 00217 { 00218 WCHAR* ptr; 00219 00220 if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR)))) 00221 return NULL; 00222 return strcpyW(ptr, str); 00223 } 00224 00225 static WCHAR *xmlstrdupW(const xmlstr_t* str) 00226 { 00227 WCHAR *strW; 00228 00229 if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR)))) 00230 { 00231 memcpy( strW, str->ptr, str->len * sizeof(WCHAR) ); 00232 strW[str->len] = 0; 00233 } 00234 return strW; 00235 } 00236 00237 static UNICODE_STRING xmlstr2unicode(const xmlstr_t *xmlstr) 00238 { 00239 UNICODE_STRING res; 00240 00241 res.Buffer = (PWSTR)xmlstr->ptr; 00242 res.Length = res.MaximumLength = (USHORT)xmlstr->len * sizeof(WCHAR); 00243 00244 return res; 00245 } 00246 00247 static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str) 00248 { 00249 return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 00250 } 00251 00252 static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str) 00253 { 00254 return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len]; 00255 } 00256 00257 static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str) 00258 { 00259 return (xmlstr->len && xmlstr->ptr[0] == '/' && 00260 !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]); 00261 } 00262 00263 static inline BOOL isxmlspace( WCHAR ch ) 00264 { 00265 return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t'); 00266 } 00267 00268 static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at) 00269 { 00270 struct assembly *assembly; 00271 00272 if (actctx->num_assemblies == actctx->allocated_assemblies) 00273 { 00274 void *ptr; 00275 unsigned int new_count; 00276 if (actctx->assemblies) 00277 { 00278 new_count = actctx->allocated_assemblies * 2; 00279 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 00280 actctx->assemblies, new_count * sizeof(*assembly) ); 00281 } 00282 else 00283 { 00284 new_count = 4; 00285 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) ); 00286 } 00287 if (!ptr) return NULL; 00288 actctx->assemblies = ptr; 00289 actctx->allocated_assemblies = new_count; 00290 } 00291 00292 assembly = &actctx->assemblies[actctx->num_assemblies++]; 00293 assembly->type = at; 00294 return assembly; 00295 } 00296 00297 static struct dll_redirect* add_dll_redirect(struct assembly* assembly) 00298 { 00299 if (assembly->num_dlls == assembly->allocated_dlls) 00300 { 00301 void *ptr; 00302 unsigned int new_count; 00303 if (assembly->dlls) 00304 { 00305 new_count = assembly->allocated_dlls * 2; 00306 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 00307 assembly->dlls, new_count * sizeof(*assembly->dlls) ); 00308 } 00309 else 00310 { 00311 new_count = 4; 00312 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) ); 00313 } 00314 if (!ptr) return NULL; 00315 assembly->dlls = ptr; 00316 assembly->allocated_dlls = new_count; 00317 } 00318 return &assembly->dlls[assembly->num_dlls++]; 00319 } 00320 00321 static void free_assembly_identity(struct assembly_identity *ai) 00322 { 00323 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name ); 00324 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch ); 00325 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key ); 00326 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language ); 00327 RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type ); 00328 } 00329 00330 static struct entity* add_entity(struct entity_array *array, DWORD kind) 00331 { 00332 struct entity* entity; 00333 00334 if (array->num == array->allocated) 00335 { 00336 void *ptr; 00337 unsigned int new_count; 00338 if (array->base) 00339 { 00340 new_count = array->allocated * 2; 00341 ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 00342 array->base, new_count * sizeof(*array->base) ); 00343 } 00344 else 00345 { 00346 new_count = 4; 00347 ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) ); 00348 } 00349 if (!ptr) return NULL; 00350 array->base = ptr; 00351 array->allocated = new_count; 00352 } 00353 entity = &array->base[array->num++]; 00354 entity->kind = kind; 00355 return entity; 00356 } 00357 00358 static void free_entity_array(struct entity_array *array) 00359 { 00360 unsigned int i; 00361 for (i = 0; i < array->num; i++) 00362 { 00363 struct entity *entity = &array->base[i]; 00364 switch (entity->kind) 00365 { 00366 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 00367 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid); 00368 break; 00369 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 00370 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid); 00371 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name); 00372 break; 00373 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 00374 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid); 00375 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version); 00376 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir); 00377 break; 00378 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 00379 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name); 00380 break; 00381 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 00382 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name); 00383 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid); 00384 break; 00385 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 00386 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name); 00387 RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid); 00388 break; 00389 default: 00390 DPRINT1("Unknown entity kind %d\n", entity->kind); 00391 } 00392 } 00393 RtlFreeHeap( RtlGetProcessHeap(), 0, array->base ); 00394 } 00395 00396 static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 ) 00397 { 00398 if (!str1) return !str2; 00399 return str2 && !strcmpiW( str1, str2 ); 00400 } 00401 00402 static BOOL is_matching_identity( const struct assembly_identity *id1, 00403 const struct assembly_identity *id2 ) 00404 { 00405 if (!is_matching_string( id1->name, id2->name )) return FALSE; 00406 if (!is_matching_string( id1->arch, id2->arch )) return FALSE; 00407 if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE; 00408 00409 if (id1->language && id2->language && strcmpiW( id1->language, id2->language )) 00410 { 00411 static const WCHAR wildcardW[] = {'*',0}; 00412 if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language )) 00413 return FALSE; 00414 } 00415 if (id1->version.major != id2->version.major) return FALSE; 00416 if (id1->version.minor != id2->version.minor) return FALSE; 00417 if (id1->version.build > id2->version.build) return FALSE; 00418 if (id1->version.build == id2->version.build && 00419 id1->version.revision > id2->version.revision) return FALSE; 00420 return TRUE; 00421 } 00422 00423 static BOOL add_dependent_assembly_id(struct actctx_loader* acl, 00424 struct assembly_identity* ai) 00425 { 00426 unsigned int i; 00427 00428 /* check if we already have that assembly */ 00429 00430 for (i = 0; i < acl->actctx->num_assemblies; i++) 00431 if (is_matching_identity( ai, &acl->actctx->assemblies[i].id )) 00432 { 00433 DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n", 00434 ai->name, ai->arch, ai->version.major, ai->version.minor, 00435 ai->version.build, ai->version.revision ); 00436 return TRUE; 00437 } 00438 00439 for (i = 0; i < acl->num_dependencies; i++) 00440 if (is_matching_identity( ai, &acl->dependencies[i] )) 00441 { 00442 DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n", 00443 ai->name, ai->arch, ai->version.major, ai->version.minor, 00444 ai->version.build, ai->version.revision ); 00445 return TRUE; 00446 } 00447 00448 if (acl->num_dependencies == acl->allocated_dependencies) 00449 { 00450 void *ptr; 00451 unsigned int new_count; 00452 if (acl->dependencies) 00453 { 00454 new_count = acl->allocated_dependencies * 2; 00455 ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies, 00456 new_count * sizeof(acl->dependencies[0])); 00457 } 00458 else 00459 { 00460 new_count = 4; 00461 ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0])); 00462 } 00463 if (!ptr) return FALSE; 00464 acl->dependencies = ptr; 00465 acl->allocated_dependencies = new_count; 00466 } 00467 acl->dependencies[acl->num_dependencies++] = *ai; 00468 00469 return TRUE; 00470 } 00471 00472 static void free_depend_manifests(struct actctx_loader* acl) 00473 { 00474 unsigned int i; 00475 for (i = 0; i < acl->num_dependencies; i++) 00476 free_assembly_identity(&acl->dependencies[i]); 00477 RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies); 00478 } 00479 00480 static WCHAR *build_assembly_dir(struct assembly_identity* ai) 00481 { 00482 static const WCHAR undW[] = {'_',0}; 00483 static const WCHAR noneW[] = {'n','o','n','e',0}; 00484 static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0}; 00485 00486 const WCHAR *arch = ai->arch ? ai->arch : noneW; 00487 const WCHAR *key = ai->public_key ? ai->public_key : noneW; 00488 const WCHAR *lang = ai->language ? ai->language : noneW; 00489 const WCHAR *name = ai->name ? ai->name : noneW; 00490 SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 + 00491 strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW); 00492 WCHAR *ret; 00493 00494 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL; 00495 00496 strcpyW( ret, arch ); 00497 strcatW( ret, undW ); 00498 strcatW( ret, name ); 00499 strcatW( ret, undW ); 00500 strcatW( ret, key ); 00501 strcatW( ret, undW ); 00502 sprintfW( ret + strlenW(ret), version_formatW, 00503 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 00504 strcatW( ret, undW ); 00505 strcatW( ret, lang ); 00506 strcatW( ret, undW ); 00507 strcatW( ret, mskeyW ); 00508 return ret; 00509 } 00510 00511 static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str ) 00512 { 00513 WCHAR *p = buffer; 00514 00515 if (!str) return; 00516 strcatW( buffer, prefix ); 00517 p += strlenW(p); 00518 *p++ = '"'; 00519 strcpyW( p, str ); 00520 p += strlenW(p); 00521 *p++ = '"'; 00522 *p = 0; 00523 } 00524 00525 static WCHAR *build_assembly_id( const struct assembly_identity *ai ) 00526 { 00527 static const WCHAR archW[] = 00528 {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0}; 00529 static const WCHAR public_keyW[] = 00530 {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0}; 00531 static const WCHAR typeW[] = 00532 {',','t','y','p','e','=',0}; 00533 static const WCHAR versionW[] = 00534 {',','v','e','r','s','i','o','n','=',0}; 00535 00536 WCHAR version[64], *ret; 00537 SIZE_T size = 0; 00538 00539 sprintfW( version, version_formatW, 00540 ai->version.major, ai->version.minor, ai->version.build, ai->version.revision ); 00541 if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR); 00542 if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2; 00543 if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2; 00544 if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2; 00545 size += strlenW(versionW) + strlenW(version) + 2; 00546 00547 if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) ))) 00548 return NULL; 00549 00550 if (ai->name) strcpyW( ret, ai->name ); 00551 else *ret = 0; 00552 append_string( ret, archW, ai->arch ); 00553 append_string( ret, public_keyW, ai->public_key ); 00554 append_string( ret, typeW, ai->type ); 00555 append_string( ret, versionW, version ); 00556 return ret; 00557 } 00558 00559 static ACTIVATION_CONTEXT *check_actctx( HANDLE h ) 00560 { 00561 ACTIVATION_CONTEXT *ret = NULL, *actctx = h; 00562 00563 if (!h || h == INVALID_HANDLE_VALUE) return NULL; 00564 _SEH2_TRY 00565 { 00566 if (actctx && actctx->magic == ACTCTX_MAGIC) ret = actctx; 00567 } 00568 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00569 { 00570 DPRINT1("Invalid activation context handle!\n"); 00571 } 00572 _SEH2_END; 00573 return ret; 00574 } 00575 00576 static inline void actctx_addref( ACTIVATION_CONTEXT *actctx ) 00577 { 00578 InterlockedExchangeAdd( &actctx->ref_count, 1 ); 00579 } 00580 00581 static void actctx_release( ACTIVATION_CONTEXT *actctx ) 00582 { 00583 if (InterlockedExchangeAdd( &actctx->ref_count, -1 ) == 1) 00584 { 00585 unsigned int i, j; 00586 00587 for (i = 0; i < actctx->num_assemblies; i++) 00588 { 00589 struct assembly *assembly = &actctx->assemblies[i]; 00590 for (j = 0; j < assembly->num_dlls; j++) 00591 { 00592 struct dll_redirect *dll = &assembly->dlls[j]; 00593 free_entity_array( &dll->entities ); 00594 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name ); 00595 RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash ); 00596 } 00597 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls ); 00598 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info ); 00599 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory ); 00600 free_entity_array( &assembly->entities ); 00601 free_assembly_identity(&assembly->id); 00602 } 00603 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info ); 00604 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info ); 00605 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies ); 00606 actctx->magic = 0; 00607 RtlFreeHeap( RtlGetProcessHeap(), 0, actctx ); 00608 } 00609 } 00610 00611 static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value, 00612 BOOL* error, BOOL* end) 00613 { 00614 const WCHAR* ptr; 00615 00616 *error = TRUE; 00617 00618 while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr)) 00619 xmlbuf->ptr++; 00620 00621 if (xmlbuf->ptr == xmlbuf->end) return FALSE; 00622 00623 if (*xmlbuf->ptr == '/') 00624 { 00625 xmlbuf->ptr++; 00626 if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>') 00627 return FALSE; 00628 00629 xmlbuf->ptr++; 00630 *end = TRUE; 00631 *error = FALSE; 00632 return FALSE; 00633 } 00634 00635 if (*xmlbuf->ptr == '>') 00636 { 00637 xmlbuf->ptr++; 00638 *error = FALSE; 00639 return FALSE; 00640 } 00641 00642 ptr = xmlbuf->ptr; 00643 while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++; 00644 00645 if (ptr == xmlbuf->end || *ptr != '=') return FALSE; 00646 00647 name->ptr = xmlbuf->ptr; 00648 name->len = (ULONG)(ptr - xmlbuf->ptr); 00649 xmlbuf->ptr = ptr; 00650 00651 ptr++; 00652 if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE; 00653 00654 value->ptr = ++ptr; 00655 if (ptr == xmlbuf->end) return FALSE; 00656 00657 ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr); 00658 if (!ptr) 00659 { 00660 xmlbuf->ptr = xmlbuf->end; 00661 return FALSE; 00662 } 00663 00664 value->len = (ULONG)(ptr - value->ptr); 00665 xmlbuf->ptr = ptr + 1; 00666 00667 if (xmlbuf->ptr == xmlbuf->end) return FALSE; 00668 00669 *error = FALSE; 00670 return TRUE; 00671 } 00672 00673 static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem) 00674 { 00675 const WCHAR* ptr; 00676 00677 for (;;) 00678 { 00679 ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr); 00680 if (!ptr) 00681 { 00682 xmlbuf->ptr = xmlbuf->end; 00683 return FALSE; 00684 } 00685 ptr++; 00686 if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */ 00687 { 00688 for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++) 00689 if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break; 00690 00691 if (ptr + 3 > xmlbuf->end) 00692 { 00693 xmlbuf->ptr = xmlbuf->end; 00694 return FALSE; 00695 } 00696 xmlbuf->ptr = ptr + 3; 00697 } 00698 else break; 00699 } 00700 00701 xmlbuf->ptr = ptr; 00702 while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr)) 00703 ptr++; 00704 00705 elem->ptr = xmlbuf->ptr; 00706 elem->len = (ULONG)(ptr - xmlbuf->ptr); 00707 xmlbuf->ptr = ptr; 00708 return xmlbuf->ptr != xmlbuf->end; 00709 } 00710 00711 static BOOL parse_xml_header(xmlbuf_t* xmlbuf) 00712 { 00713 /* FIXME: parse attributes */ 00714 const WCHAR *ptr; 00715 00716 for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++) 00717 { 00718 if (ptr[0] == '?' && ptr[1] == '>') 00719 { 00720 xmlbuf->ptr = ptr + 2; 00721 return TRUE; 00722 } 00723 } 00724 return FALSE; 00725 } 00726 00727 static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content) 00728 { 00729 const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr); 00730 00731 if (!ptr) return FALSE; 00732 00733 content->ptr = xmlbuf->ptr; 00734 content->len = (ULONG)(ptr - xmlbuf->ptr); 00735 xmlbuf->ptr = ptr; 00736 00737 return TRUE; 00738 } 00739 00740 static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version) 00741 { 00742 unsigned int ver[4]; 00743 unsigned int pos; 00744 const WCHAR *curr; 00745 UNICODE_STRING strU; 00746 00747 /* major.minor.build.revision */ 00748 ver[0] = ver[1] = ver[2] = ver[3] = pos = 0; 00749 for (curr = str->ptr; curr < str->ptr + str->len; curr++) 00750 { 00751 if (*curr >= '0' && *curr <= '9') 00752 { 00753 ver[pos] = ver[pos] * 10 + *curr - '0'; 00754 if (ver[pos] >= 0x10000) goto error; 00755 } 00756 else if (*curr == '.') 00757 { 00758 if (++pos >= 4) goto error; 00759 } 00760 else goto error; 00761 } 00762 version->major = ver[0]; 00763 version->minor = ver[1]; 00764 version->build = ver[2]; 00765 version->revision = ver[3]; 00766 return TRUE; 00767 00768 error: 00769 strU = xmlstr2unicode(str); 00770 DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU ); 00771 return FALSE; 00772 } 00773 00774 static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name) 00775 { 00776 xmlstr_t elem; 00777 UNICODE_STRING elemU; 00778 if (!next_xml_elem(xmlbuf, &elem)) return FALSE; 00779 if (xmlstr_cmp(&elem, name)) return TRUE; 00780 elemU = xmlstr2unicode(&elem); 00781 DPRINT1( "unexpected element %wZ\n", &elemU ); 00782 return FALSE; 00783 } 00784 00785 static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end) 00786 { 00787 xmlstr_t attr_name, attr_value; 00788 UNICODE_STRING attr_nameU, attr_valueU; 00789 BOOL error; 00790 00791 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end)) 00792 { 00793 attr_nameU = xmlstr2unicode(&attr_name); 00794 attr_valueU = xmlstr2unicode(&attr_name); 00795 DPRINT1( "unexpected attr %S=%S\n", &attr_nameU, 00796 &attr_valueU); 00797 } 00798 return !error; 00799 } 00800 00801 static BOOL parse_end_element(xmlbuf_t *xmlbuf) 00802 { 00803 BOOL end = FALSE; 00804 return parse_expect_no_attr(xmlbuf, &end) && !end; 00805 } 00806 00807 static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name) 00808 { 00809 xmlstr_t elem; 00810 UNICODE_STRING elemU; 00811 if (!next_xml_elem(xmlbuf, &elem)) return FALSE; 00812 if (!xmlstr_cmp_end(&elem, name)) 00813 { 00814 elemU = xmlstr2unicode(&elem); 00815 DPRINT1( "unexpected element %wZ\n", &elemU ); 00816 return FALSE; 00817 } 00818 return parse_end_element(xmlbuf); 00819 } 00820 00821 static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem) 00822 { 00823 xmlstr_t attr_name, attr_value, elem; 00824 BOOL end = FALSE, error, ret = TRUE; 00825 00826 while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)); 00827 if(error || end) return end; 00828 00829 while(ret && (ret = next_xml_elem(xmlbuf, &elem))) 00830 { 00831 if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len && 00832 !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len)) 00833 break; 00834 else 00835 ret = parse_unknown_elem(xmlbuf, &elem); 00836 } 00837 00838 return ret && parse_end_element(xmlbuf); 00839 } 00840 00841 static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx, 00842 struct assembly_identity* ai) 00843 { 00844 xmlstr_t attr_name, attr_value; 00845 BOOL end = FALSE, error; 00846 UNICODE_STRING attr_valueU, attr_nameU; 00847 00848 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 00849 { 00850 if (xmlstr_cmp(&attr_name, nameW)) 00851 { 00852 if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE; 00853 } 00854 else if (xmlstr_cmp(&attr_name, typeW)) 00855 { 00856 if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE; 00857 } 00858 else if (xmlstr_cmp(&attr_name, versionW)) 00859 { 00860 if (!parse_version(&attr_value, &ai->version)) return FALSE; 00861 } 00862 else if (xmlstr_cmp(&attr_name, processorArchitectureW)) 00863 { 00864 if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE; 00865 } 00866 else if (xmlstr_cmp(&attr_name, publicKeyTokenW)) 00867 { 00868 if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE; 00869 } 00870 else if (xmlstr_cmp(&attr_name, languageW)) 00871 { 00872 if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE; 00873 DPRINT1("Unsupported yet language attribute (%S)\n", 00874 ai->language); 00875 } 00876 else 00877 { 00878 attr_nameU = xmlstr2unicode(&attr_name); 00879 attr_valueU = xmlstr2unicode(&attr_value); 00880 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 00881 } 00882 } 00883 00884 if (error || end) return end; 00885 return parse_expect_end_elem(xmlbuf, assemblyIdentityW); 00886 } 00887 00888 static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) 00889 { 00890 xmlstr_t elem, attr_name, attr_value; 00891 BOOL ret, end = FALSE, error; 00892 struct entity* entity; 00893 UNICODE_STRING attr_valueU, attr_nameU; 00894 00895 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION))) 00896 return FALSE; 00897 00898 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 00899 { 00900 if (xmlstr_cmp(&attr_name, clsidW)) 00901 { 00902 if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE; 00903 } 00904 else 00905 { 00906 attr_nameU = xmlstr2unicode(&attr_name); 00907 attr_valueU = xmlstr2unicode(&attr_value); 00908 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 00909 } 00910 } 00911 00912 if (error || end) return end; 00913 00914 while ((ret = next_xml_elem(xmlbuf, &elem))) 00915 { 00916 if (xmlstr_cmp_end(&elem, comClassW)) 00917 { 00918 ret = parse_end_element(xmlbuf); 00919 break; 00920 } 00921 else 00922 { 00923 attr_nameU = xmlstr2unicode(&elem); 00924 DPRINT1("unknown elem %wZ\n", &attr_nameU); 00925 ret = parse_unknown_elem(xmlbuf, &elem); 00926 } 00927 } 00928 return ret; 00929 } 00930 00931 static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) 00932 { 00933 xmlstr_t attr_name, attr_value; 00934 BOOL end = FALSE, error; 00935 struct entity* entity; 00936 UNICODE_STRING attr_valueU, attr_nameU; 00937 00938 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION))) 00939 return FALSE; 00940 00941 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 00942 { 00943 if (xmlstr_cmp(&attr_name, iidW)) 00944 { 00945 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE; 00946 } 00947 if (xmlstr_cmp(&attr_name, nameW)) 00948 { 00949 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE; 00950 } 00951 else 00952 { 00953 attr_nameU = xmlstr2unicode(&attr_name); 00954 attr_valueU = xmlstr2unicode(&attr_value); 00955 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 00956 } 00957 } 00958 00959 if (error || end) return end; 00960 return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW); 00961 } 00962 00963 static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) 00964 { 00965 xmlstr_t attr_name, attr_value; 00966 BOOL end = FALSE, error; 00967 struct entity* entity; 00968 UNICODE_STRING attr_valueU, attr_nameU; 00969 00970 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION))) 00971 return FALSE; 00972 00973 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 00974 { 00975 if (xmlstr_cmp(&attr_name, tlbidW)) 00976 { 00977 if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE; 00978 } 00979 if (xmlstr_cmp(&attr_name, versionW)) 00980 { 00981 if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE; 00982 } 00983 if (xmlstr_cmp(&attr_name, helpdirW)) 00984 { 00985 if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE; 00986 } 00987 else 00988 { 00989 attr_nameU = xmlstr2unicode(&attr_name); 00990 attr_valueU = xmlstr2unicode(&attr_value); 00991 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 00992 } 00993 } 00994 00995 if (error || end) return end; 00996 return parse_expect_end_elem(xmlbuf, typelibW); 00997 } 00998 00999 static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll) 01000 { 01001 xmlstr_t elem, content; 01002 BOOL end = FALSE, ret = TRUE; 01003 struct entity* entity; 01004 UNICODE_STRING elemU; 01005 01006 if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION))) 01007 return FALSE; 01008 01009 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE; 01010 if (end) return FALSE; 01011 01012 if (!parse_text_content(xmlbuf, &content)) return FALSE; 01013 01014 if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE; 01015 01016 while (ret && (ret = next_xml_elem(xmlbuf, &elem))) 01017 { 01018 if (xmlstr_cmp_end(&elem, windowClassW)) 01019 { 01020 ret = parse_end_element(xmlbuf); 01021 break; 01022 } 01023 else 01024 { 01025 elemU = xmlstr2unicode(&elem); 01026 DPRINT1("unknown elem %wZ\n", &elemU); 01027 ret = parse_unknown_elem(xmlbuf, &elem); 01028 } 01029 } 01030 01031 return ret; 01032 } 01033 01034 static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf) 01035 { 01036 xmlstr_t attr_name, attr_value; 01037 UNICODE_STRING attr_valueU, attr_nameU; 01038 BOOL end = FALSE, error; 01039 01040 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01041 { 01042 attr_nameU = xmlstr2unicode(&attr_name); 01043 attr_valueU = xmlstr2unicode(&attr_value); 01044 01045 if (xmlstr_cmp(&attr_name, oldVersionW)) 01046 { 01047 DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU); 01048 } 01049 else if (xmlstr_cmp(&attr_name, newVersionW)) 01050 { 01051 DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU); 01052 } 01053 else 01054 { 01055 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01056 } 01057 } 01058 01059 if (error || end) return end; 01060 return parse_expect_end_elem(xmlbuf, bindingRedirectW); 01061 } 01062 01063 static BOOL parse_description_elem(xmlbuf_t* xmlbuf) 01064 { 01065 xmlstr_t elem, content; 01066 UNICODE_STRING elemU; 01067 BOOL end = FALSE, ret = TRUE; 01068 01069 if (!parse_expect_no_attr(xmlbuf, &end) || end || 01070 !parse_text_content(xmlbuf, &content)) 01071 return FALSE; 01072 01073 elemU = xmlstr2unicode(&content); 01074 DPRINT("Got description %wZ\n", &elemU); 01075 01076 while (ret && (ret = next_xml_elem(xmlbuf, &elem))) 01077 { 01078 if (xmlstr_cmp_end(&elem, descriptionW)) 01079 { 01080 ret = parse_end_element(xmlbuf); 01081 break; 01082 } 01083 else 01084 { 01085 elemU = xmlstr2unicode(&elem); 01086 DPRINT1("unknown elem %wZ\n", &elemU); 01087 ret = parse_unknown_elem(xmlbuf, &elem); 01088 } 01089 } 01090 01091 return ret; 01092 } 01093 01094 static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf, 01095 struct assembly* assembly) 01096 { 01097 xmlstr_t attr_name, attr_value; 01098 BOOL end = FALSE, error; 01099 struct entity* entity; 01100 01101 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION); 01102 if (!entity) return FALSE; 01103 01104 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01105 { 01106 if (xmlstr_cmp(&attr_name, iidW)) 01107 { 01108 if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE; 01109 } 01110 if (xmlstr_cmp(&attr_name, nameW)) 01111 { 01112 if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE; 01113 } 01114 else 01115 { 01116 DPRINT1("unknown attr %S=%S\n", attr_name.ptr, attr_value.ptr); 01117 } 01118 } 01119 01120 if (error || end) return end; 01121 return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW); 01122 } 01123 01124 static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) 01125 { 01126 xmlstr_t attr_name, attr_value; 01127 UNICODE_STRING attr_nameU, attr_valueU; 01128 BOOL end = FALSE, error; 01129 struct entity* entity; 01130 01131 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION); 01132 if (!entity) return FALSE; 01133 01134 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01135 { 01136 if (xmlstr_cmp(&attr_name, nameW)) 01137 { 01138 if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE; 01139 } 01140 else if (xmlstr_cmp(&attr_name, clsidW)) 01141 { 01142 if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE; 01143 } 01144 else 01145 { 01146 attr_nameU = xmlstr2unicode(&attr_name); 01147 attr_valueU = xmlstr2unicode(&attr_value); 01148 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01149 } 01150 } 01151 01152 if (error || end) return end; 01153 return parse_expect_end_elem(xmlbuf, clrClassW); 01154 } 01155 01156 static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) 01157 { 01158 xmlstr_t attr_name, attr_value; 01159 UNICODE_STRING attr_nameU, attr_valueU; 01160 BOOL end = FALSE, error; 01161 struct entity* entity; 01162 01163 entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES); 01164 if (!entity) return FALSE; 01165 01166 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01167 { 01168 if (xmlstr_cmp(&attr_name, nameW)) 01169 { 01170 if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE; 01171 } 01172 else if (xmlstr_cmp(&attr_name, clsidW)) 01173 { 01174 if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE; 01175 } 01176 else 01177 { 01178 attr_nameU = xmlstr2unicode(&attr_name); 01179 attr_valueU = xmlstr2unicode(&attr_value); 01180 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01181 } 01182 } 01183 01184 if (error || end) return end; 01185 return parse_expect_end_elem(xmlbuf, clrSurrogateW); 01186 } 01187 01188 static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional) 01189 { 01190 struct assembly_identity ai; 01191 xmlstr_t elem; 01192 BOOL end = FALSE, ret = TRUE; 01193 01194 if (!parse_expect_no_attr(xmlbuf, &end) || end) return end; 01195 01196 memset(&ai, 0, sizeof(ai)); 01197 ai.optional = optional; 01198 01199 if (!parse_expect_elem(xmlbuf, assemblyIdentityW) || 01200 !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai)) 01201 return FALSE; 01202 01203 /* store the newly found identity for later loading */ 01204 if (!add_dependent_assembly_id(acl, &ai)) return FALSE; 01205 01206 while (ret && (ret = next_xml_elem(xmlbuf, &elem))) 01207 { 01208 if (xmlstr_cmp_end(&elem, dependentAssemblyW)) 01209 { 01210 ret = parse_end_element(xmlbuf); 01211 break; 01212 } 01213 else if (xmlstr_cmp(&elem, bindingRedirectW)) 01214 { 01215 ret = parse_binding_redirect_elem(xmlbuf); 01216 } 01217 else 01218 { 01219 DPRINT1("unknown elem %S\n", elem.ptr); 01220 ret = parse_unknown_elem(xmlbuf, &elem); 01221 } 01222 } 01223 01224 return ret; 01225 } 01226 01227 static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl) 01228 { 01229 xmlstr_t attr_name, attr_value, elem; 01230 UNICODE_STRING attr_nameU, attr_valueU; 01231 BOOL end = FALSE, ret = TRUE, error, optional = FALSE; 01232 01233 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01234 { 01235 attr_nameU = xmlstr2unicode(&attr_name); 01236 attr_valueU = xmlstr2unicode(&attr_value); 01237 01238 if (xmlstr_cmp(&attr_name, optionalW)) 01239 { 01240 static const WCHAR yesW[] = {'y','e','s',0}; 01241 optional = xmlstr_cmpi( &attr_value, yesW ); 01242 DPRINT1("optional=%wZ\n", &attr_valueU); 01243 } 01244 else 01245 { 01246 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01247 } 01248 } 01249 01250 while (ret && (ret = next_xml_elem(xmlbuf, &elem))) 01251 { 01252 if (xmlstr_cmp_end(&elem, dependencyW)) 01253 { 01254 ret = parse_end_element(xmlbuf); 01255 break; 01256 } 01257 else if (xmlstr_cmp(&elem, dependentAssemblyW)) 01258 { 01259 ret = parse_dependent_assembly_elem(xmlbuf, acl, optional); 01260 } 01261 else 01262 { 01263 attr_nameU = xmlstr2unicode(&elem); 01264 DPRINT1("unknown element %wZ\n", &attr_nameU); 01265 ret = parse_unknown_elem(xmlbuf, &elem); 01266 } 01267 } 01268 01269 return ret; 01270 } 01271 01272 static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf) 01273 { 01274 BOOL end = FALSE; 01275 01276 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE; 01277 return end || parse_expect_end_elem(xmlbuf, noInheritW); 01278 } 01279 01280 static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf) 01281 { 01282 BOOL end = FALSE; 01283 01284 if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE; 01285 return end || parse_expect_end_elem(xmlbuf, noInheritableW); 01286 } 01287 01288 static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly) 01289 { 01290 xmlstr_t attr_name, attr_value, elem; 01291 UNICODE_STRING attr_nameU, attr_valueU; 01292 BOOL end = FALSE, error, ret = TRUE; 01293 struct dll_redirect* dll; 01294 01295 if (!(dll = add_dll_redirect(assembly))) return FALSE; 01296 01297 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01298 { 01299 attr_nameU = xmlstr2unicode(&attr_name); 01300 attr_valueU = xmlstr2unicode(&attr_value); 01301 01302 if (xmlstr_cmp(&attr_name, nameW)) 01303 { 01304 if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE; 01305 DPRINT("name=%wZ\n", &attr_valueU); 01306 } 01307 else if (xmlstr_cmp(&attr_name, hashW)) 01308 { 01309 if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE; 01310 } 01311 else if (xmlstr_cmp(&attr_name, hashalgW)) 01312 { 01313 static const WCHAR sha1W[] = {'S','H','A','1',0}; 01314 if (!xmlstr_cmpi(&attr_value, sha1W)) 01315 DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU); 01316 } 01317 else 01318 { 01319 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01320 } 01321 } 01322 01323 if (error || !dll->name) return FALSE; 01324 if (end) return TRUE; 01325 01326 while (ret && (ret = next_xml_elem(xmlbuf, &elem))) 01327 { 01328 if (xmlstr_cmp_end(&elem, fileW)) 01329 { 01330 ret = parse_end_element(xmlbuf); 01331 break; 01332 } 01333 else if (xmlstr_cmp(&elem, comClassW)) 01334 { 01335 ret = parse_com_class_elem(xmlbuf, dll); 01336 } 01337 else if (xmlstr_cmp(&elem, comInterfaceProxyStubW)) 01338 { 01339 ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll); 01340 } 01341 else if (xmlstr_cmp(&elem, asmv2hashW)) 01342 { 01343 DPRINT1("asmv2hash (undocumented) not supported\n"); 01344 ret = parse_unknown_elem(xmlbuf, &elem); 01345 } 01346 else if (xmlstr_cmp(&elem, typelibW)) 01347 { 01348 ret = parse_typelib_elem(xmlbuf, dll); 01349 } 01350 else if (xmlstr_cmp(&elem, windowClassW)) 01351 { 01352 ret = parse_window_class_elem(xmlbuf, dll); 01353 } 01354 else 01355 { 01356 attr_nameU = xmlstr2unicode(&elem); 01357 DPRINT1("unknown elem %wZ\n", &attr_nameU); 01358 ret = parse_unknown_elem( xmlbuf, &elem ); 01359 } 01360 } 01361 01362 return ret; 01363 } 01364 01365 static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, 01366 struct assembly* assembly, 01367 struct assembly_identity* expected_ai) 01368 { 01369 xmlstr_t attr_name, attr_value, elem; 01370 UNICODE_STRING attr_nameU, attr_valueU; 01371 BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE; 01372 01373 while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end)) 01374 { 01375 attr_nameU = xmlstr2unicode(&attr_name); 01376 attr_valueU = xmlstr2unicode(&attr_value); 01377 01378 if (xmlstr_cmp(&attr_name, manifestVersionW)) 01379 { 01380 static const WCHAR v10W[] = {'1','.','0',0}; 01381 if (!xmlstr_cmp(&attr_value, v10W)) 01382 { 01383 DPRINT1("wrong version %wZ\n", &attr_valueU); 01384 return FALSE; 01385 } 01386 version = TRUE; 01387 } 01388 else if (xmlstr_cmp(&attr_name, xmlnsW)) 01389 { 01390 if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W)) 01391 { 01392 DPRINT1("wrong namespace %wZ\n", &attr_valueU); 01393 return FALSE; 01394 } 01395 xmlns = TRUE; 01396 } 01397 else 01398 { 01399 DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU); 01400 } 01401 } 01402 01403 if (error || end || !xmlns || !version) return FALSE; 01404 if (!next_xml_elem(xmlbuf, &elem)) return FALSE; 01405 01406 if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW)) 01407 { 01408 if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem)) 01409 return FALSE; 01410 assembly->no_inherit = TRUE; 01411 } 01412 01413 if (xmlstr_cmp(&elem, noInheritableW)) 01414 { 01415 if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem)) 01416 return FALSE; 01417 } 01418 else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) && 01419 assembly->no_inherit) 01420 return FALSE; 01421 01422 while (ret) 01423 { 01424 if (xmlstr_cmp_end(&elem, assemblyW)) 01425 { 01426 ret = parse_end_element(xmlbuf); 01427 break; 01428 } 01429 else if (xmlstr_cmp(&elem, descriptionW)) 01430 { 01431 ret = parse_description_elem(xmlbuf); 01432 } 01433 else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW)) 01434 { 01435 ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly); 01436 } 01437 else if (xmlstr_cmp(&elem, dependencyW)) 01438 { 01439 ret = parse_dependency_elem(xmlbuf, acl); 01440 } 01441 else if (xmlstr_cmp(&elem, fileW)) 01442 { 01443 ret = parse_file_elem(xmlbuf, assembly); 01444 } 01445 else if (xmlstr_cmp(&elem, clrClassW)) 01446 { 01447 ret = parse_clr_class_elem(xmlbuf, assembly); 01448 } 01449 else if (xmlstr_cmp(&elem, clrSurrogateW)) 01450 { 01451 ret = parse_clr_surrogate_elem(xmlbuf, assembly); 01452 } 01453 else if (xmlstr_cmp(&elem, assemblyIdentityW)) 01454 { 01455 if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE; 01456 01457 if (expected_ai) 01458 { 01459 /* FIXME: more tests */ 01460 if (assembly->type == ASSEMBLY_MANIFEST && 01461 memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version))) 01462 { 01463 DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n", 01464 expected_ai->version.major, expected_ai->version.minor, 01465 expected_ai->version.build, expected_ai->version.revision, 01466 assembly->id.version.major, assembly->id.version.minor, 01467 assembly->id.version.build, assembly->id.version.revision); 01468 ret = FALSE; 01469 } 01470 else if (assembly->type == ASSEMBLY_SHARED_MANIFEST && 01471 (assembly->id.version.major != expected_ai->version.major || 01472 assembly->id.version.minor != expected_ai->version.minor || 01473 assembly->id.version.build < expected_ai->version.build || 01474 (assembly->id.version.build == expected_ai->version.build && 01475 assembly->id.version.revision < expected_ai->version.revision))) 01476 { 01477 DPRINT1("wrong version for shared assembly manifest\n"); 01478 ret = FALSE; 01479 } 01480 } 01481 } 01482 else 01483 { 01484 attr_nameU = xmlstr2unicode(&elem); 01485 DPRINT1("unknown element %wZ\n", &attr_nameU); 01486 ret = parse_unknown_elem(xmlbuf, &elem); 01487 } 01488 if (ret) ret = next_xml_elem(xmlbuf, &elem); 01489 } 01490 01491 return ret; 01492 } 01493 01494 static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly, 01495 struct assembly_identity* ai, xmlbuf_t *xmlbuf ) 01496 { 01497 xmlstr_t elem; 01498 UNICODE_STRING elemU; 01499 01500 if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX; 01501 01502 if (xmlstr_cmp(&elem, xmlW) && 01503 (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem))) 01504 return STATUS_SXS_CANT_GEN_ACTCTX; 01505 01506 if (!xmlstr_cmp(&elem, assemblyW)) 01507 { 01508 elemU = xmlstr2unicode(&elem); 01509 DPRINT1("root element is %wZ, not <assembly>\n", &elemU); 01510 return STATUS_SXS_CANT_GEN_ACTCTX; 01511 } 01512 01513 if (!parse_assembly_elem(xmlbuf, acl, assembly, ai)) 01514 { 01515 DPRINT1("failed to parse manifest %S\n", assembly->manifest.info ); 01516 return STATUS_SXS_CANT_GEN_ACTCTX; 01517 } 01518 01519 if (next_xml_elem(xmlbuf, &elem)) 01520 { 01521 elemU = xmlstr2unicode(&elem); 01522 DPRINT1("unexpected element %wZ\n", &elemU); 01523 return STATUS_SXS_CANT_GEN_ACTCTX; 01524 } 01525 01526 if (xmlbuf->ptr != xmlbuf->end) 01527 { 01528 DPRINT1("parse error\n"); 01529 return STATUS_SXS_CANT_GEN_ACTCTX; 01530 } 01531 return STATUS_SUCCESS; 01532 } 01533 01534 static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 01535 LPCWSTR filename, LPCWSTR directory, BOOL shared, 01536 const void *buffer, SIZE_T size ) 01537 { 01538 xmlbuf_t xmlbuf; 01539 NTSTATUS status; 01540 struct assembly *assembly; 01541 int unicode_tests; 01542 01543 DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory ); 01544 01545 if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST))) 01546 return STATUS_SXS_CANT_GEN_ACTCTX; 01547 01548 if (directory && !(assembly->directory = strdupW(directory))) 01549 return STATUS_NO_MEMORY; 01550 01551 if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ ); 01552 assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE 01553 : ACTIVATION_CONTEXT_PATH_TYPE_NONE; 01554 01555 unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE; 01556 if (RtlIsTextUnicode((PVOID)buffer, (ULONG)size, &unicode_tests )) 01557 { 01558 xmlbuf.ptr = buffer; 01559 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 01560 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 01561 } 01562 else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE) 01563 { 01564 const WCHAR *buf = buffer; 01565 WCHAR *new_buff; 01566 unsigned int i; 01567 01568 if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) 01569 return STATUS_NO_MEMORY; 01570 for (i = 0; i < size / sizeof(WCHAR); i++) 01571 new_buff[i] = RtlUshortByteSwap( buf[i] ); 01572 xmlbuf.ptr = new_buff; 01573 xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR); 01574 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 01575 RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff ); 01576 } 01577 else 01578 { 01579 /* TODO: this doesn't handle arbitrary encodings */ 01580 ANSI_STRING xmlA; 01581 UNICODE_STRING xmlW; 01582 01583 ASSERT(size < MAXUSHORT); 01584 xmlA.Buffer = (PCHAR)buffer; 01585 xmlA.Length = xmlA.MaximumLength = (USHORT)size; 01586 01587 _SEH2_TRY 01588 { 01589 status = RtlAnsiStringToUnicodeString(&xmlW, &xmlA, TRUE); 01590 } 01591 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 01592 { 01593 DPRINT1("Exception accessing buffer\n"); 01594 return STATUS_SXS_CANT_GEN_ACTCTX; 01595 } 01596 _SEH2_END; 01597 01598 if (!NT_SUCCESS(status)) 01599 { 01600 DPRINT1("RtlAnsiStringToUnicodeString failed with %lx\n", status); 01601 return STATUS_SXS_CANT_GEN_ACTCTX; 01602 } 01603 ASSERT(xmlW.Buffer != NULL); 01604 01605 xmlbuf.ptr = xmlW.Buffer; 01606 xmlbuf.end = xmlbuf.ptr + xmlW.Length / sizeof(WCHAR); 01607 status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf ); 01608 01609 RtlFreeUnicodeString(&xmlW); 01610 } 01611 return status; 01612 } 01613 01614 static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name ) 01615 { 01616 OBJECT_ATTRIBUTES attr; 01617 IO_STATUS_BLOCK io; 01618 01619 attr.Length = sizeof(attr); 01620 attr.RootDirectory = 0; 01621 attr.Attributes = OBJ_CASE_INSENSITIVE; 01622 attr.ObjectName = name; 01623 attr.SecurityDescriptor = NULL; 01624 attr.SecurityQualityOfService = NULL; 01625 return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT ); 01626 } 01627 01628 static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, USHORT extra_len ) 01629 { 01630 NTSTATUS status; 01631 ULONG magic; 01632 LDR_DATA_TABLE_ENTRY *pldr; 01633 01634 LdrLockLoaderLock(0, NULL, &magic); 01635 status = LdrFindEntryForAddress( module, &pldr ); 01636 if (status == STATUS_SUCCESS) 01637 { 01638 if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 01639 pldr->FullDllName.Length + extra_len + sizeof(WCHAR) ))) 01640 { 01641 memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) ); 01642 str->Length = pldr->FullDllName.Length; 01643 str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR); 01644 } 01645 else status = STATUS_NO_MEMORY; 01646 } 01647 LdrUnlockLoaderLock(0, magic); 01648 return status; 01649 } 01650 01651 static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai, 01652 LPCWSTR filename, LPCWSTR directory, BOOL shared, 01653 HANDLE hModule, LPCWSTR resname, ULONG lang ) 01654 { 01655 NTSTATUS status; 01656 UNICODE_STRING nameW; 01657 LDR_RESOURCE_INFO info; 01658 IMAGE_RESOURCE_DATA_ENTRY* entry = NULL; 01659 void *ptr; 01660 01661 //DPRINT( "looking for res %s in module %p %s\n", resname, 01662 // hModule, filename ); 01663 01664 #if 0 01665 if (TRACE_ON(actctx)) 01666 { 01667 if (!filename && !get_module_filename( hModule, &nameW, 0 )) 01668 { 01669 DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname), 01670 hModule, debugstr_w(nameW.Buffer) ); 01671 RtlFreeUnicodeString( &nameW ); 01672 } 01673 else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname), 01674 hModule, debugstr_w(filename) ); 01675 } 01676 #endif 01677 01678 if (!resname) return STATUS_INVALID_PARAMETER; 01679 01680 info.Type = (ULONG_PTR)RT_MANIFEST; 01681 info.Language = lang; 01682 if (!((ULONG_PTR)resname >> 16)) 01683 { 01684 info.Name = (ULONG_PTR)resname; 01685 status = LdrFindResource_U(hModule, &info, 3, &entry); 01686 } 01687 else if (resname[0] == '#') 01688 { 01689 ULONG value; 01690 RtlInitUnicodeString(&nameW, resname + 1); 01691 if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value)) 01692 return STATUS_INVALID_PARAMETER; 01693 info.Name = value; 01694 status = LdrFindResource_U(hModule, &info, 3, &entry); 01695 } 01696 else 01697 { 01698 RtlCreateUnicodeString(&nameW, resname); 01699 RtlUpcaseUnicodeString(&nameW, &nameW, FALSE); 01700 info.Name = (ULONG_PTR)nameW.Buffer; 01701 status = LdrFindResource_U(hModule, &info, 3, &entry); 01702 RtlFreeUnicodeString(&nameW); 01703 } 01704 if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL); 01705 01706 if (status == STATUS_SUCCESS) 01707 status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size); 01708 01709 return status; 01710 } 01711 01712 static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai, 01713 LPCWSTR filename, LPCWSTR directory, BOOL shared, 01714 HANDLE file, LPCWSTR resname, ULONG lang ) 01715 { 01716 HANDLE mapping; 01717 OBJECT_ATTRIBUTES attr; 01718 LARGE_INTEGER size; 01719 LARGE_INTEGER offset; 01720 NTSTATUS status; 01721 SIZE_T count; 01722 void *base; 01723 01724 DPRINT( "looking for res %S in %S\n", resname, filename ); 01725 01726 attr.Length = sizeof(attr); 01727 attr.RootDirectory = 0; 01728 attr.ObjectName = NULL; 01729 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 01730 attr.SecurityDescriptor = NULL; 01731 attr.SecurityQualityOfService = NULL; 01732 01733 size.QuadPart = 0; 01734 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 01735 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 01736 if (status != STATUS_SUCCESS) return status; 01737 01738 offset.QuadPart = 0; 01739 count = 0; 01740 base = NULL; 01741 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 01742 &count, ViewShare, 0, PAGE_READONLY ); 01743 NtClose( mapping ); 01744 if (status != STATUS_SUCCESS) return status; 01745 01746 if (RtlImageNtHeader(base)) /* we got a PE file */ 01747 { 01748 HANDLE module = (HMODULE)((ULONG_PTR)base | 1); /* make it a LOAD_LIBRARY_AS_DATAFILE handle */ 01749 status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang ); 01750 } 01751 else status = STATUS_INVALID_IMAGE_FORMAT; 01752 01753 NtUnmapViewOfSection( NtCurrentProcess(), base ); 01754 return status; 01755 } 01756 01757 static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai, 01758 LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file ) 01759 { 01760 FILE_STANDARD_INFORMATION info; 01761 IO_STATUS_BLOCK io; 01762 HANDLE mapping; 01763 OBJECT_ATTRIBUTES attr; 01764 LARGE_INTEGER size; 01765 LARGE_INTEGER offset; 01766 NTSTATUS status; 01767 SIZE_T count; 01768 void *base; 01769 01770 DPRINT( "loading manifest file %S\n", filename ); 01771 01772 attr.Length = sizeof(attr); 01773 attr.RootDirectory = 0; 01774 attr.ObjectName = NULL; 01775 attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; 01776 attr.SecurityDescriptor = NULL; 01777 attr.SecurityQualityOfService = NULL; 01778 01779 size.QuadPart = 0; 01780 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ, 01781 &attr, &size, PAGE_READONLY, SEC_COMMIT, file ); 01782 01783 if (status != STATUS_SUCCESS) return status; 01784 01785 offset.QuadPart = 0; 01786 count = 0; 01787 base = NULL; 01788 status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset, 01789 &count, ViewShare, 0, PAGE_READONLY ); 01790 01791 if (status != STATUS_SUCCESS) return status; 01792 01793 /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */ 01794 status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation); 01795 01796 if (status == STATUS_SUCCESS) 01797 status = parse_manifest(acl, ai, filename, directory, shared, base, (SIZE_T)info.EndOfFile.QuadPart); 01798 01799 NtUnmapViewOfSection( NtCurrentProcess(), base ); 01800 NtClose( mapping ); 01801 return status; 01802 } 01803 01804 /* try to load the .manifest file associated to the file */ 01805 static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai, 01806 LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname ) 01807 { 01808 static const WCHAR fmtW[] = { '.','%','l','u',0 }; 01809 WCHAR *buffer; 01810 NTSTATUS status; 01811 UNICODE_STRING nameW; 01812 HANDLE file; 01813 ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 01814 01815 if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff; 01816 01817 DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid ); 01818 01819 if (module) /* use the module filename */ 01820 { 01821 UNICODE_STRING name; 01822 01823 if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) ))) 01824 { 01825 if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid ); 01826 strcatW( name.Buffer, dotManifestW ); 01827 if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL )) 01828 status = STATUS_RESOURCE_DATA_NOT_FOUND; 01829 RtlFreeUnicodeString( &name ); 01830 } 01831 if (status) return status; 01832 } 01833 else 01834 { 01835 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 01836 (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 01837 return STATUS_NO_MEMORY; 01838 strcpyW( buffer, filename ); 01839 if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid ); 01840 strcatW( buffer, dotManifestW ); 01841 RtlInitUnicodeString( &nameW, buffer ); 01842 } 01843 01844 if (!open_nt_file( &file, &nameW )) 01845 { 01846 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 01847 NtClose( file ); 01848 } 01849 else status = STATUS_RESOURCE_DATA_NOT_FOUND; 01850 RtlFreeUnicodeString( &nameW ); 01851 return status; 01852 } 01853 01854 static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai ) 01855 { 01856 static const WCHAR lookup_fmtW[] = 01857 {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_', 01858 '*', /* FIXME */ 01859 '.','m','a','n','i','f','e','s','t',0}; 01860 01861 WCHAR *lookup, *ret = NULL; 01862 UNICODE_STRING lookup_us; 01863 IO_STATUS_BLOCK io; 01864 unsigned int data_pos = 0, data_len; 01865 char buffer[8192]; 01866 01867 if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0, 01868 (strlenW(ai->arch) + strlenW(ai->name) 01869 + strlenW(ai->public_key) + 20) * sizeof(WCHAR) 01870 + sizeof(lookup_fmtW) ))) 01871 return NULL; 01872 01873 sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor); 01874 RtlInitUnicodeString( &lookup_us, lookup ); 01875 01876 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 01877 FileBothDirectoryInformation, FALSE, &lookup_us, TRUE ); 01878 if (io.Status == STATUS_SUCCESS) 01879 { 01880 FILE_BOTH_DIR_INFORMATION *dir_info; 01881 WCHAR *tmp; 01882 ULONG build, revision; 01883 01884 data_len = (ULONG)io.Information; 01885 01886 for (;;) 01887 { 01888 if (data_pos >= data_len) 01889 { 01890 NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer), 01891 FileBothDirectoryInformation, FALSE, &lookup_us, FALSE ); 01892 if (io.Status != STATUS_SUCCESS) break; 01893 data_len = (ULONG)io.Information; 01894 data_pos = 0; 01895 } 01896 dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos); 01897 01898 if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset; 01899 else data_pos = data_len; 01900 01901 tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup); 01902 build = atoiW(tmp); 01903 if (build < ai->version.build) continue; 01904 tmp = strchrW(tmp, '.') + 1; 01905 revision = atoiW(tmp); 01906 if (build == ai->version.build && revision < ai->version.revision) 01907 continue; 01908 ai->version.build = (USHORT)build; 01909 ai->version.revision = (USHORT)revision; 01910 01911 if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) ))) 01912 { 01913 memcpy( ret, dir_info->FileName, dir_info->FileNameLength ); 01914 ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0; 01915 } 01916 break; 01917 } 01918 } 01919 else DPRINT1("no matching file for %S\n", lookup); 01920 RtlFreeHeap( RtlGetProcessHeap(), 0, lookup ); 01921 return ret; 01922 } 01923 01924 static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai) 01925 { 01926 struct assembly_identity sxs_ai; 01927 UNICODE_STRING path_us; 01928 OBJECT_ATTRIBUTES attr; 01929 IO_STATUS_BLOCK io; 01930 WCHAR *path, *file = NULL; 01931 HANDLE handle; 01932 01933 static const WCHAR manifest_dirW[] = 01934 {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0}; 01935 01936 if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE; 01937 01938 if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0, 01939 ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) ))) 01940 return STATUS_NO_MEMORY; 01941 01942 memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) ); 01943 memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) ); 01944 01945 if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL )) 01946 { 01947 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 01948 return STATUS_NO_SUCH_FILE; 01949 } 01950 RtlFreeHeap( RtlGetProcessHeap(), 0, path ); 01951 01952 attr.Length = sizeof(attr); 01953 attr.RootDirectory = 0; 01954 attr.Attributes = OBJ_CASE_INSENSITIVE; 01955 attr.ObjectName = &path_us; 01956 attr.SecurityDescriptor = NULL; 01957 attr.SecurityQualityOfService = NULL; 01958 01959 if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE, 01960 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT )) 01961 { 01962 sxs_ai = *ai; 01963 file = lookup_manifest_file( handle, &sxs_ai ); 01964 NtClose( handle ); 01965 } 01966 if (!file) 01967 { 01968 RtlFreeUnicodeString( &path_us ); 01969 return STATUS_NO_SUCH_FILE; 01970 } 01971 01972 /* append file name to directory path */ 01973 if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer, 01974 path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) ))) 01975 { 01976 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 01977 RtlFreeUnicodeString( &path_us ); 01978 return STATUS_NO_MEMORY; 01979 } 01980 01981 path[path_us.Length/sizeof(WCHAR)] = '\\'; 01982 strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file ); 01983 RtlInitUnicodeString( &path_us, path ); 01984 *strrchrW(file, '.') = 0; /* remove .manifest extension */ 01985 01986 if (!open_nt_file( &handle, &path_us )) 01987 { 01988 io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle); 01989 NtClose( handle ); 01990 } 01991 else io.Status = STATUS_NO_SUCH_FILE; 01992 01993 RtlFreeHeap( RtlGetProcessHeap(), 0, file ); 01994 RtlFreeUnicodeString( &path_us ); 01995 return io.Status; 01996 } 01997 01998 static NTSTATUS lookup_assembly(struct actctx_loader* acl, 01999 struct assembly_identity* ai) 02000 { 02001 static const WCHAR dotDllW[] = {'.','d','l','l',0}; 02002 unsigned int i; 02003 WCHAR *buffer, *p, *directory; 02004 NTSTATUS status; 02005 UNICODE_STRING nameW; 02006 HANDLE file; 02007 02008 DPRINT( "looking for name=%S version=%u.%u.%u.%u arch=%S\n", 02009 ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch ); 02010 02011 if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status; 02012 02013 /* FIXME: add support for language specific lookup */ 02014 02015 nameW.Buffer = NULL; 02016 if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0, 02017 (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) ))) 02018 return STATUS_NO_MEMORY; 02019 02020 if (!(directory = build_assembly_dir( ai ))) 02021 { 02022 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 02023 return STATUS_NO_MEMORY; 02024 } 02025 02026 /* lookup in appdir\name.dll 02027 * appdir\name.manifest 02028 * appdir\name\name.dll 02029 * appdir\name\name.manifest 02030 */ 02031 strcpyW( buffer, acl->actctx->appdir.info ); 02032 p = buffer + strlenW(buffer); 02033 for (i = 0; i < 2; i++) 02034 { 02035 *p++ = '\\'; 02036 strcpyW( p, ai->name ); 02037 p += strlenW(p); 02038 02039 strcpyW( p, dotDllW ); 02040 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 02041 { 02042 status = open_nt_file( &file, &nameW ); 02043 if (!status) 02044 { 02045 status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file, 02046 (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 ); 02047 NtClose( file ); 02048 break; 02049 } 02050 RtlFreeUnicodeString( &nameW ); 02051 } 02052 02053 strcpyW( p, dotManifestW ); 02054 if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL )) 02055 { 02056 status = open_nt_file( &file, &nameW ); 02057 if (!status) 02058 { 02059 status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file ); 02060 NtClose( file ); 02061 break; 02062 } 02063 RtlFreeUnicodeString( &nameW ); 02064 } 02065 status = STATUS_SXS_ASSEMBLY_NOT_FOUND; 02066 } 02067 RtlFreeUnicodeString( &nameW ); 02068 RtlFreeHeap( RtlGetProcessHeap(), 0, directory ); 02069 RtlFreeHeap( RtlGetProcessHeap(), 0, buffer ); 02070 return status; 02071 } 02072 02073 static NTSTATUS parse_depend_manifests(struct actctx_loader* acl) 02074 { 02075 NTSTATUS status = STATUS_SUCCESS; 02076 unsigned int i; 02077 02078 for (i = 0; i < acl->num_dependencies; i++) 02079 { 02080 if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS) 02081 { 02082 if (!acl->dependencies[i].optional) 02083 { 02084 DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name ); 02085 status = STATUS_SXS_CANT_GEN_ACTCTX; 02086 break; 02087 } 02088 } 02089 } 02090 /* FIXME should now iterate through all refs */ 02091 return status; 02092 } 02093 02094 /* find the appropriate activation context for RtlQueryInformationActivationContext */ 02095 static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class ) 02096 { 02097 NTSTATUS status = STATUS_SUCCESS; 02098 02099 if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX) 02100 { 02101 if (*handle) return STATUS_INVALID_PARAMETER; 02102 02103 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 02104 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 02105 } 02106 else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE)) 02107 { 02108 ULONG magic; 02109 LDR_DATA_TABLE_ENTRY *pldr; 02110 02111 if (!*handle) return STATUS_INVALID_PARAMETER; 02112 02113 LdrLockLoaderLock( 0, NULL, &magic ); 02114 if (!LdrFindEntryForAddress( *handle, &pldr )) 02115 { 02116 if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase) 02117 status = STATUS_DLL_NOT_FOUND; 02118 else 02119 *handle = pldr->EntryPointActivationContext; 02120 } 02121 else status = STATUS_DLL_NOT_FOUND; 02122 LdrUnlockLoaderLock( 0, magic ); 02123 } 02124 else if (!*handle && (class != ActivationContextBasicInformation)) 02125 *handle = process_actctx; 02126 02127 return status; 02128 } 02129 02130 static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i) 02131 { 02132 data->ulDataFormatVersion = 1; 02133 data->lpData = v1; 02134 data->ulLength = 20; /* FIXME */ 02135 data->lpSectionGlobalData = NULL; /* FIXME */ 02136 data->ulSectionGlobalDataLength = 0; /* FIXME */ 02137 data->lpSectionBase = v2; 02138 data->ulSectionTotalLength = 0; /* FIXME */ 02139 data->hActCtx = NULL; 02140 if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG)) 02141 data->ulAssemblyRosterIndex = i + 1; 02142 02143 return STATUS_SUCCESS; 02144 } 02145 02146 static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, 02147 PACTCTX_SECTION_KEYED_DATA data) 02148 { 02149 unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR); 02150 02151 for (i = 0; i < actctx->num_assemblies; i++) 02152 { 02153 struct assembly *assembly = &actctx->assemblies[i]; 02154 for (j = 0; j < assembly->num_dlls; j++) 02155 { 02156 struct dll_redirect *dll = &assembly->dlls[j]; 02157 if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen]) 02158 return fill_keyed_data(data, dll, assembly, i); 02159 } 02160 } 02161 return STATUS_SXS_KEY_NOT_FOUND; 02162 } 02163 02164 static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name, 02165 PACTCTX_SECTION_KEYED_DATA data) 02166 { 02167 unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR); 02168 02169 for (i = 0; i < actctx->num_assemblies; i++) 02170 { 02171 struct assembly *assembly = &actctx->assemblies[i]; 02172 for (j = 0; j < assembly->num_dlls; j++) 02173 { 02174 struct dll_redirect *dll = &assembly->dlls[j]; 02175 for (k = 0; k < dll->entities.num; k++) 02176 { 02177 struct entity *entity = &dll->entities.base[k]; 02178 if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION) 02179 { 02180 if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen]) 02181 return fill_keyed_data(data, entity, dll, i); 02182 } 02183 } 02184 } 02185 } 02186 return STATUS_SXS_KEY_NOT_FOUND; 02187 } 02188 02189 static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind, 02190 const UNICODE_STRING *section_name, 02191 DWORD flags, PACTCTX_SECTION_KEYED_DATA data) 02192 { 02193 NTSTATUS status; 02194 02195 switch (section_kind) 02196 { 02197 case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION: 02198 status = find_dll_redirection(actctx, section_name, data); 02199 break; 02200 case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION: 02201 status = find_window_class(actctx, section_name, data); 02202 break; 02203 case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION: 02204 case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION: 02205 case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION: 02206 case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION: 02207 case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE: 02208 case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES: 02209 DPRINT1("Unsupported yet section_kind %x\n", section_kind); 02210 return STATUS_SXS_SECTION_NOT_FOUND; 02211 default: 02212 DPRINT1("Unknown section_kind %x\n", section_kind); 02213 return STATUS_SXS_SECTION_NOT_FOUND; 02214 } 02215 02216 if (status != STATUS_SUCCESS) return status; 02217 02218 if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX) 02219 { 02220 actctx_addref(actctx); 02221 data->hActCtx = actctx; 02222 } 02223 return STATUS_SUCCESS; 02224 } 02225 02226 /* initialize the activation context for the current process */ 02227 void actctx_init(void) 02228 { 02229 ACTCTXW ctx; 02230 HANDLE handle; 02231 02232 ctx.cbSize = sizeof(ctx); 02233 ctx.lpSource = NULL; 02234 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 02235 ctx.hModule = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 02236 ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID; 02237 02238 if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle); 02239 } 02240 02241 /* FUNCTIONS ***************************************************************/ 02242 02243 NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle, void *ptr ) 02244 { 02245 const ACTCTXW *pActCtx = ptr; 02246 const WCHAR *directory = NULL; 02247 ACTIVATION_CONTEXT *actctx; 02248 UNICODE_STRING nameW; 02249 ULONG lang = 0; 02250 NTSTATUS status = STATUS_NO_MEMORY; 02251 HANDLE file = 0; 02252 struct actctx_loader acl; 02253 02254 DPRINT("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0); 02255 02256 if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) || 02257 (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL)) 02258 return STATUS_INVALID_PARAMETER; 02259 02260 02261 if (!(actctx = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) ))) 02262 return STATUS_NO_MEMORY; 02263 02264 actctx->magic = ACTCTX_MAGIC; 02265 actctx->ref_count = 1; 02266 actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE; 02267 actctx->config.info = NULL; 02268 actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE; 02269 if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID) 02270 { 02271 if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error; 02272 } 02273 else 02274 { 02275 UNICODE_STRING dir; 02276 WCHAR *p; 02277 HMODULE module; 02278 02279 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule; 02280 else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress; 02281 02282 if ((status = get_module_filename( module, &dir, 0 ))) goto error; 02283 if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0; 02284 actctx->appdir.info = dir.Buffer; 02285 } 02286 02287 nameW.Buffer = NULL; 02288 if (pActCtx->lpSource) 02289 { 02290 if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL)) 02291 { 02292 status = STATUS_NO_SUCH_FILE; 02293 goto error; 02294 } 02295 status = open_nt_file( &file, &nameW ); 02296 if (status) 02297 { 02298 RtlFreeUnicodeString( &nameW ); 02299 goto error; 02300 } 02301 } 02302 02303 acl.actctx = actctx; 02304 acl.dependencies = NULL; 02305 acl.num_dependencies = 0; 02306 acl.allocated_dependencies = 0; 02307 02308 if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId; 02309 if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory; 02310 02311 if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID) 02312 { 02313 /* if we have a resource it's a PE file */ 02314 if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) 02315 { 02316 status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule, 02317 pActCtx->lpResourceName, lang ); 02318 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 02319 /* FIXME: what to do if pActCtx->lpSource is set */ 02320 status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory, 02321 pActCtx->hModule, pActCtx->lpResourceName ); 02322 } 02323 else if (pActCtx->lpSource) 02324 { 02325 status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE, 02326 file, pActCtx->lpResourceName, lang ); 02327 if (status && status != STATUS_SXS_CANT_GEN_ACTCTX) 02328 status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory, 02329 NULL, pActCtx->lpResourceName ); 02330 } 02331 else status = STATUS_INVALID_PARAMETER; 02332 } 02333 else 02334 { 02335 status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file ); 02336 } 02337 02338 if (file) NtClose( file ); 02339 RtlFreeUnicodeString( &nameW ); 02340 02341 if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl); 02342 free_depend_manifests( &acl ); 02343 02344 if (status == STATUS_SUCCESS) *handle = actctx; 02345 else actctx_release( actctx ); 02346 return status; 02347 02348 error: 02349 if (file) NtClose( file ); 02350 actctx_release( actctx ); 02351 return status; 02352 } 02353 02354 VOID 02355 NTAPI 02356 RtlAddRefActivationContext(HANDLE handle) 02357 { 02358 ACTIVATION_CONTEXT *actctx; 02359 02360 if ((actctx = check_actctx( handle ))) actctx_addref( actctx ); 02361 } 02362 02363 VOID 02364 NTAPI 02365 RtlReleaseActivationContext( HANDLE handle ) 02366 { 02367 ACTIVATION_CONTEXT *actctx; 02368 02369 if ((actctx = check_actctx( handle ))) actctx_release( actctx ); 02370 } 02371 02372 NTSTATUS 02373 NTAPI RtlActivateActivationContextEx( ULONG flags, PTEB tebAddress, HANDLE handle, PULONG_PTR cookie ) 02374 { 02375 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 02376 02377 if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) ))) 02378 return STATUS_NO_MEMORY; 02379 02380 frame->Previous = tebAddress->ActivationContextStackPointer->ActiveFrame; 02381 frame->ActivationContext = handle; 02382 frame->Flags = 0; 02383 02384 tebAddress->ActivationContextStackPointer->ActiveFrame = frame; 02385 RtlAddRefActivationContext( handle ); 02386 02387 *cookie = (ULONG_PTR)frame; 02388 DPRINT( "%p cookie=%lx\n", handle, *cookie ); 02389 return STATUS_SUCCESS; 02390 } 02391 02392 02393 NTSTATUS 02394 NTAPI RtlActivateActivationContext( ULONG flags, HANDLE handle, PULONG_PTR cookie ) 02395 { 02396 return RtlActivateActivationContextEx(flags, NtCurrentTeb(), handle, cookie); 02397 } 02398 02399 NTSTATUS 02400 NTAPI 02401 RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie ) 02402 { 02403 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top; 02404 02405 DPRINT( "%x cookie=%lx\n", flags, cookie ); 02406 02407 /* find the right frame */ 02408 top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 02409 for (frame = top; frame; frame = frame->Previous) 02410 if ((ULONG_PTR)frame == cookie) break; 02411 02412 if (!frame) 02413 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 02414 02415 if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION)) 02416 RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION ); 02417 02418 /* pop everything up to and including frame */ 02419 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 02420 02421 while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 02422 { 02423 frame = top->Previous; 02424 RtlReleaseActivationContext( top->ActivationContext ); 02425 RtlFreeHeap( RtlGetProcessHeap(), 0, top ); 02426 top = frame; 02427 } 02428 02429 return STATUS_SUCCESS; 02430 } 02431 02432 VOID 02433 NTAPI 02434 RtlFreeActivationContextStack(PACTIVATION_CONTEXT_STACK Stack) 02435 { 02436 PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame, PrevFrame; 02437 02438 /* Nothing to do if there is no stack */ 02439 if (!Stack) return; 02440 02441 /* Get the current active frame */ 02442 ActiveFrame = Stack->ActiveFrame; 02443 02444 /* Go through them in backwards order and release */ 02445 while (ActiveFrame) 02446 { 02447 PrevFrame = ActiveFrame->Previous; 02448 RtlReleaseActivationContext(ActiveFrame->ActivationContext); 02449 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveFrame); 02450 ActiveFrame = PrevFrame; 02451 } 02452 02453 /* Zero out the active frame */ 02454 Stack->ActiveFrame = NULL; 02455 02456 /* TODO: Empty the Frame List Cache */ 02457 ASSERT(IsListEmpty(&Stack->FrameListCache)); 02458 02459 /* Free activation stack memory */ 02460 RtlFreeHeap(RtlGetProcessHeap(), 0, Stack); 02461 } 02462 02463 VOID 02464 NTAPI RtlFreeThreadActivationContextStack(void) 02465 { 02466 RtlFreeActivationContextStack(NtCurrentTeb()->ActivationContextStackPointer); 02467 NtCurrentTeb()->ActivationContextStackPointer = NULL; 02468 } 02469 02470 02471 NTSTATUS 02472 NTAPI RtlGetActiveActivationContext( HANDLE *handle ) 02473 { 02474 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 02475 { 02476 *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext; 02477 RtlAddRefActivationContext( *handle ); 02478 } 02479 else 02480 *handle = 0; 02481 02482 return STATUS_SUCCESS; 02483 } 02484 02485 02486 BOOLEAN 02487 NTAPI RtlIsActivationContextActive( HANDLE handle ) 02488 { 02489 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 02490 02491 for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous) 02492 if (frame->ActivationContext == handle) return TRUE; 02493 return FALSE; 02494 } 02495 02496 NTSTATUS 02497 NTAPI 02498 RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst, 02499 ULONG class, PVOID buffer, 02500 SIZE_T bufsize, SIZE_T *retlen ) 02501 { 02502 ACTIVATION_CONTEXT *actctx; 02503 NTSTATUS status; 02504 02505 DPRINT("%08x %p %p %u %p %ld %p\n", flags, handle, 02506 subinst, class, buffer, bufsize, retlen); 02507 02508 if (retlen) *retlen = 0; 02509 if ((status = find_query_actctx( &handle, flags, class ))) return status; 02510 02511 switch (class) 02512 { 02513 case ActivationContextBasicInformation: 02514 { 02515 ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer; 02516 02517 if (retlen) *retlen = sizeof(*info); 02518 if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL; 02519 02520 info->hActCtx = handle; 02521 info->dwFlags = 0; /* FIXME */ 02522 if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle ); 02523 } 02524 break; 02525 02526 case ActivationContextDetailedInformation: 02527 { 02528 ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer; 02529 struct assembly *assembly = NULL; 02530 SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0; 02531 LPWSTR ptr; 02532 02533 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 02534 02535 if (actctx->num_assemblies) assembly = actctx->assemblies; 02536 02537 if (assembly && assembly->manifest.info) 02538 manifest_len = strlenW(assembly->manifest.info) + 1; 02539 if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1; 02540 if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1; 02541 len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR); 02542 02543 if (retlen) *retlen = len; 02544 if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL; 02545 02546 acdi->dwFlags = 0; 02547 acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */ 02548 acdi->ulAssemblyCount = actctx->num_assemblies; 02549 acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */; 02550 acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? (DWORD)manifest_len - 1 : 0; 02551 acdi->ulRootConfigurationPathType = actctx->config.type; 02552 acdi->ulRootConfigurationPathChars = actctx->config.info ? (DWORD)config_len - 1 : 0; 02553 acdi->ulAppDirPathType = actctx->appdir.type; 02554 acdi->ulAppDirPathChars = actctx->appdir.info ? (DWORD)appdir_len - 1 : 0; 02555 ptr = (LPWSTR)(acdi + 1); 02556 if (manifest_len) 02557 { 02558 acdi->lpRootManifestPath = ptr; 02559 memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR)); 02560 ptr += manifest_len; 02561 } 02562 else acdi->lpRootManifestPath = NULL; 02563 if (config_len) 02564 { 02565 acdi->lpRootConfigurationPath = ptr; 02566 memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR)); 02567 ptr += config_len; 02568 } 02569 else acdi->lpRootConfigurationPath = NULL; 02570 if (appdir_len) 02571 { 02572 acdi->lpAppDirPath = ptr; 02573 memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR)); 02574 } 02575 else acdi->lpAppDirPath = NULL; 02576 } 02577 break; 02578 02579 case AssemblyDetailedInformationInActivationContext: 02580 { 02581 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer; 02582 struct assembly *assembly; 02583 WCHAR *assembly_id; 02584 DWORD index; 02585 SIZE_T len, id_len = 0, ad_len = 0, path_len = 0; 02586 LPWSTR ptr; 02587 02588 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 02589 if (!subinst) return STATUS_INVALID_PARAMETER; 02590 02591 index = *(DWORD*)subinst; 02592 if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER; 02593 02594 assembly = &actctx->assemblies[index - 1]; 02595 02596 if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY; 02597 id_len = strlenW(assembly_id) + 1; 02598 if (assembly->directory) ad_len = strlenW(assembly->directory) + 1; 02599 02600 if (assembly->manifest.info && 02601 (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST)) 02602 path_len = strlenW(assembly->manifest.info) + 1; 02603 02604 len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR); 02605 02606 if (retlen) *retlen = len; 02607 if (!buffer || bufsize < len) 02608 { 02609 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 02610 return STATUS_BUFFER_TOO_SMALL; 02611 } 02612 02613 afdi->ulFlags = 0; /* FIXME */ 02614 afdi->ulEncodedAssemblyIdentityLength = (DWORD)(id_len - 1) * sizeof(WCHAR); 02615 afdi->ulManifestPathType = assembly->manifest.type; 02616 afdi->ulManifestPathLength = assembly->manifest.info ? (DWORD)(path_len - 1) * sizeof(WCHAR) : 0; 02617 /* FIXME afdi->liManifestLastWriteTime = 0; */ 02618 afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */ 02619 afdi->ulPolicyPathLength = 0; 02620 /* FIXME afdi->liPolicyLastWriteTime = 0; */ 02621 afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */ 02622 afdi->ulManifestVersionMajor = 1; 02623 afdi->ulManifestVersionMinor = 0; 02624 afdi->ulPolicyVersionMajor = 0; /* FIXME */ 02625 afdi->ulPolicyVersionMinor = 0; /* FIXME */ 02626 afdi->ulAssemblyDirectoryNameLength = ad_len ? (DWORD)(ad_len - 1) * sizeof(WCHAR) : 0; 02627 ptr = (LPWSTR)(afdi + 1); 02628 afdi->lpAssemblyEncodedAssemblyIdentity = ptr; 02629 memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) ); 02630 ptr += id_len; 02631 if (path_len) 02632 { 02633 afdi->lpAssemblyManifestPath = ptr; 02634 memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR)); 02635 ptr += path_len; 02636 } else afdi->lpAssemblyManifestPath = NULL; 02637 afdi->lpAssemblyPolicyPath = NULL; /* FIXME */ 02638 if (ad_len) 02639 { 02640 afdi->lpAssemblyDirectoryName = ptr; 02641 memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR)); 02642 ptr += ad_len; 02643 } 02644 else afdi->lpAssemblyDirectoryName = NULL; 02645 RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id ); 02646 } 02647 break; 02648 02649 case FileInformationInAssemblyOfAssemblyInActivationContext: 02650 { 02651 const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst; 02652 ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer; 02653 struct assembly *assembly; 02654 struct dll_redirect *dll; 02655 SIZE_T len, dll_len = 0; 02656 LPWSTR ptr; 02657 02658 if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER; 02659 if (!acqi) return STATUS_INVALID_PARAMETER; 02660 02661 if (acqi->ulAssemblyIndex >= actctx->num_assemblies) 02662 return STATUS_INVALID_PARAMETER; 02663 assembly = &actctx->assemblies[acqi->ulAssemblyIndex]; 02664 02665 if (acqi->ulFileIndexInAssembly >= assembly->num_dlls) 02666 return STATUS_INVALID_PARAMETER; 02667 dll = &assembly->dlls[acqi->ulFileIndexInAssembly]; 02668 02669 if (dll->name) dll_len = strlenW(dll->name) + 1; 02670 len = sizeof(*afdi) + dll_len * sizeof(WCHAR); 02671 02672 if (!buffer || bufsize < len) 02673 { 02674 if (retlen) *retlen = len; 02675 return STATUS_BUFFER_TOO_SMALL; 02676 } 02677 if (retlen) *retlen = 0; /* yes that's what native does !! */ 02678 afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION; 02679 afdi->ulFilenameLength = dll_len ? (DWORD)(dll_len - 1) * sizeof(WCHAR) : 0; 02680 afdi->ulPathLength = 0; /* FIXME */ 02681 ptr = (LPWSTR)(afdi + 1); 02682 if (dll_len) 02683 { 02684 afdi->lpFileName = ptr; 02685 memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) ); 02686 } else afdi->lpFileName = NULL; 02687 afdi->lpFilePath = NULL; /* FIXME */ 02688 } 02689 break; 02690 02691 default: 02692 DPRINT( "class %u not implemented\n", class ); 02693 return STATUS_NOT_IMPLEMENTED; 02694 } 02695 return STATUS_SUCCESS; 02696 } 02697 02698 NTSTATUS 02699 NTAPI 02700 RtlQueryInformationActiveActivationContext(ULONG ulInfoClass, 02701 PVOID pvBuffer, 02702 SIZE_T cbBuffer OPTIONAL, 02703 SIZE_T *pcbWrittenOrRequired OPTIONAL) 02704 { 02705 return RtlQueryInformationActivationContext(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, 02706 NULL, 02707 NULL, 02708 ulInfoClass, 02709 pvBuffer, 02710 cbBuffer, 02711 pcbWrittenOrRequired); 02712 } 02713 02714 #define FIND_ACTCTX_RETURN_FLAGS 0x00000002 02715 #define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004 02716 #define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 02717 02718 NTSTATUS 02719 NTAPI 02720 RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind, 02721 UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data ) 02722 { 02723 /* Check general parameter combinations */ 02724 if (!section_name || 02725 (flags & ~FIND_ACTCTX_VALID_MASK) || 02726 ((flags & FIND_ACTCTX_VALID_MASK) && !data) || 02727 (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex))) 02728 { 02729 DPRINT1("invalid parameter\n"); 02730 return STATUS_INVALID_PARAMETER; 02731 } 02732 02733 /* TODO */ 02734 if (flags & FIND_ACTCTX_RETURN_FLAGS || 02735 flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA) 02736 { 02737 DPRINT1("unknown flags %08x\n", flags); 02738 return STATUS_INVALID_PARAMETER; 02739 } 02740 02741 return STATUS_SUCCESS; 02742 } 02743 02744 NTSTATUS 02745 NTAPI 02746 RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind, 02747 UNICODE_STRING *section_name, PVOID ptr ) 02748 { 02749 PACTCTX_SECTION_KEYED_DATA data = ptr; 02750 NTSTATUS status; 02751 02752 status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data); 02753 if (!NT_SUCCESS(status)) return status; 02754 02755 status = STATUS_SXS_KEY_NOT_FOUND; 02756 02757 /* if there is no data, but params are valid, 02758 we return that sxs key is not found to be at least somehow compatible */ 02759 if (!data) return status; 02760 02761 ASSERT(NtCurrentTeb()); 02762 ASSERT(NtCurrentTeb()->ActivationContextStackPointer); 02763 02764 if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame) 02765 { 02766 ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext); 02767 if (actctx) status = find_string( actctx, section_kind, section_name, flags, data ); 02768 } 02769 02770 if (status != STATUS_SUCCESS) 02771 status = find_string( process_actctx, section_kind, section_name, flags, data ); 02772 02773 return status; 02774 } 02775 02776 /* Stubs */ 02777 02778 NTSTATUS 02779 NTAPI 02780 RtlAllocateActivationContextStack(IN PVOID *Context) 02781 { 02782 PACTIVATION_CONTEXT_STACK ContextStack; 02783 02784 /* Check if it's already allocated */ 02785 if (*Context) return STATUS_SUCCESS; 02786 02787 /* Allocate space for the context stack */ 02788 ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) ); 02789 if (!ContextStack) 02790 { 02791 return STATUS_NO_MEMORY; 02792 } 02793 02794 /* Initialize the context stack */ 02795 ContextStack->Flags = 0; 02796 ContextStack->ActiveFrame = NULL; 02797 InitializeListHead(&ContextStack->FrameListCache); 02798 ContextStack->NextCookieSequenceNumber = 1; 02799 ContextStack->StackId = 1; //TODO: Timer-based 02800 02801 *Context = ContextStack; 02802 02803 return STATUS_SUCCESS; 02804 } 02805 02806 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 02807 FASTCALL 02808 RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame, 02809 IN PVOID Context) 02810 { 02811 #if NEW_NTDLL_LOADER 02812 RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame; 02813 02814 /* Get the curren active frame */ 02815 ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 02816 02817 DPRINT1("ActiveFrame %p, &Frame->Frame %p, Context %p\n", ActiveFrame, &Frame->Frame, Context); 02818 02819 /* Actually activate it */ 02820 Frame->Frame.Previous = ActiveFrame; 02821 Frame->Frame.ActivationContext = Context; 02822 Frame->Frame.Flags = 0; 02823 02824 /* Check if we can activate this context */ 02825 if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) || 02826 Context) 02827 { 02828 /* Set new active frame */ 02829 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame; 02830 return &Frame->Frame; 02831 } 02832 02833 /* We can get here only one way: it was already activated */ 02834 DPRINT1("Trying to activate improper activation context\n"); 02835 02836 /* Activate only if we are allowing multiple activation */ 02837 if (!RtlpNotAllowingMultipleActivation) 02838 { 02839 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame; 02840 } 02841 else 02842 { 02843 /* Set flag */ 02844 Frame->Frame.Flags = 0x30; 02845 } 02846 02847 /* Return pointer to the activation frame */ 02848 return &Frame->Frame; 02849 #else 02850 02851 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame = &Frame->Frame; 02852 02853 frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 02854 frame->ActivationContext = Context; 02855 frame->Flags = 0; 02856 02857 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame; 02858 02859 return STATUS_SUCCESS; 02860 #endif 02861 } 02862 02863 PRTL_ACTIVATION_CONTEXT_STACK_FRAME 02864 FASTCALL 02865 RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame) 02866 { 02867 RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame; 02868 //RTL_ACTIVATION_CONTEXT_STACK_FRAME *top; 02869 02870 /* find the right frame */ 02871 //top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; 02872 frame = &Frame->Frame; 02873 02874 if (!frame) 02875 { 02876 DPRINT1("No top frame!\n"); 02877 RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION ); 02878 } 02879 02880 /* pop everything up to and including frame */ 02881 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous; 02882 02883 return frame; 02884 } 02885 02886 02887 NTSTATUS 02888 NTAPI 02889 RtlZombifyActivationContext(PVOID Context) 02890 { 02891 UNIMPLEMENTED; 02892 02893 if (Context == ACTCTX_FAKE_HANDLE) 02894 return STATUS_SUCCESS; 02895 02896 return STATUS_NOT_IMPLEMENTED; 02897 } 02898 Generated on Sat May 26 2012 04:23:05 for ReactOS by
1.7.6.1
|