ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

actctx.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.