* Samuel SerapiĆ³n
*/
-/* Based on Wine 1.1.26 */
+/* Based on Wine 1.7.17 */
#include <rtl.h>
BOOLEAN RtlpNotAllowingMultipleActivation;
#define ACTCTX_FLAGS_ALL (\
- ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
- ACTCTX_FLAG_LANGID_VALID |\
- ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
- ACTCTX_FLAG_RESOURCE_NAME_VALID |\
- ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
- ACTCTX_FLAG_APPLICATION_NAME_VALID |\
- ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
- ACTCTX_FLAG_HMODULE_VALID )
+ ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
+ ACTCTX_FLAG_LANGID_VALID |\
+ ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
+ ACTCTX_FLAG_RESOURCE_NAME_VALID |\
+ ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
+ ACTCTX_FLAG_APPLICATION_NAME_VALID |\
+ ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
+ ACTCTX_FLAG_HMODULE_VALID )
+
+#define STRSECTION_MAGIC 0x64487353 /* dHsS */
+#define GUIDSECTION_MAGIC 0x64487347 /* dHsG */
#define ACTCTX_MAGIC_MARKER (PVOID)'gMcA'
BOOL optional;
};
+struct strsection_header
+{
+ DWORD magic;
+ ULONG size;
+ DWORD unk1[3];
+ ULONG count;
+ ULONG index_offset;
+ DWORD unk2[2];
+ ULONG global_offset;
+ ULONG global_len;
+};
+
+struct string_index
+{
+ ULONG hash; /* key string hash */
+ ULONG name_offset;
+ ULONG name_len;
+ ULONG data_offset; /* redirect data offset */
+ ULONG data_len;
+ ULONG rosterindex;
+};
+
+struct guidsection_header
+{
+ DWORD magic;
+ ULONG size;
+ DWORD unk[3];
+ ULONG count;
+ ULONG index_offset;
+ DWORD unk2;
+ ULONG names_offset;
+ ULONG names_len;
+};
+
+struct guid_index
+{
+ GUID guid;
+ ULONG data_offset;
+ ULONG data_len;
+ ULONG rosterindex;
+};
+
+struct wndclass_redirect_data
+{
+ ULONG size;
+ DWORD res;
+ ULONG name_len;
+ ULONG name_offset; /* versioned name offset */
+ ULONG module_len;
+ ULONG module_offset;/* container name offset */
+};
+
+struct dllredirect_data
+{
+ ULONG size;
+ ULONG unk;
+ DWORD res[3];
+};
+
+struct tlibredirect_data
+{
+ ULONG size;
+ DWORD res;
+ ULONG name_len;
+ ULONG name_offset;
+ LANGID langid;
+ WORD flags;
+ ULONG help_len;
+ ULONG help_offset;
+ WORD major_version;
+ WORD minor_version;
+};
+
+enum comclass_threadingmodel
+{
+ ThreadingModel_Apartment = 1,
+ ThreadingModel_Free = 2,
+ ThreadingModel_No = 3,
+ ThreadingModel_Both = 4,
+ ThreadingModel_Neutral = 5
+};
+
+enum comclass_miscfields
+{
+ MiscStatus = 1,
+ MiscStatusIcon = 2,
+ MiscStatusContent = 4,
+ MiscStatusThumbnail = 8,
+ MiscStatusDocPrint = 16
+};
+
+struct comclassredirect_data
+{
+ ULONG size;
+ BYTE res;
+ BYTE miscmask;
+ BYTE res1[2];
+ DWORD model;
+ GUID clsid;
+ GUID alias;
+ GUID clsid2;
+ GUID tlbid;
+ ULONG name_len;
+ ULONG name_offset;
+ ULONG progid_len;
+ ULONG progid_offset;
+ ULONG clrdata_len;
+ ULONG clrdata_offset;
+ DWORD miscstatus;
+ DWORD miscstatuscontent;
+ DWORD miscstatusthumbnail;
+ DWORD miscstatusicon;
+ DWORD miscstatusdocprint;
+};
+
+enum ifaceps_mask
+{
+ NumMethods = 1,
+ BaseIface = 2
+};
+
+struct ifacepsredirect_data
+{
+ ULONG size;
+ DWORD mask;
+ GUID iid;
+ ULONG nummethods;
+ GUID tlbid;
+ GUID base;
+ ULONG name_len;
+ ULONG name_offset;
+};
+
+struct clrsurrogate_data
+{
+ ULONG size;
+ DWORD res;
+ GUID clsid;
+ ULONG version_offset;
+ ULONG version_len;
+ ULONG name_offset;
+ ULONG name_len;
+};
+
+struct clrclass_data
+{
+ ULONG size;
+ DWORD res[2];
+ ULONG module_len;
+ ULONG module_offset;
+ ULONG name_len;
+ ULONG name_offset;
+ ULONG version_len;
+ ULONG version_offset;
+ DWORD res2[2];
+};
+
+struct progidredirect_data
+{
+ ULONG size;
+ DWORD reserved;
+ ULONG clsid_offset;
+};
+
+/*
+
+ Sections structure.
+
+ Sections are accessible by string or guid key, that defines two types of sections.
+ All sections of each type have same magic value and header structure, index
+ data could be of two possible types too. So every string based section uses
+ the same index format, same applies to guid sections - they share same guid index
+ format.
+
+ - window class redirection section is a plain buffer with following format:
+
+ <section header>
+ <index[]>
+ <data[]> --- <original name>
+ <redirect data>
+ <versioned name>
+ <module name>
+
+ Header is fixed length structure - struct strsection_header,
+ contains redirected classes count;
+
+ Index is an array of fixed length index records, each record is
+ struct string_index.
+
+ All strings in data itself are WCHAR, null terminated, 4-bytes aligned.
+
+ Versioned name offset is relative to redirect data structure (struct wndclass_redirect_data),
+ others are relative to section itself.
+
+ - dll redirect section format:
+
+ <section header>
+ <index[]>
+ <data[]> --- <dll name>
+ <data>
+
+ This section doesn't seem to carry any payload data except dll names.
+
+ - typelib section format:
+
+ <section header>
+ <module names[]>
+ <index[]>
+ <data[]> --- <data>
+ <helpstring>
+
+ Header is fixed length, index is an array of fixed length 'struct guid_index'.
+ All strings are WCHAR, null terminated, 4-bytes aligned. Module names part is
+ 4-bytes aligned as a whole.
+
+ Module name offsets are relative to section, helpstring offset is relative to data
+ structure itself.
+
+ - comclass section format:
+
+ <section header>
+ <module names[]>
+ <index[]>
+ <data[]> --- <data> --- <data>
+ <progid> <clrdata>
+ <name>
+ <version>
+ <progid>
+
+ This section uses two index records per comclass, one entry contains original guid
+ as specified by context, another one has a generated guid. Index and strings handling
+ is similar to typelib sections.
+
+ For CLR classes additional data is stored after main COM class data, it contains
+ class name and runtime version string, see 'struct clrclass_data'.
+
+ Module name offsets are relative to section, progid offset is relative to data
+ structure itself.
+
+ - COM interface section format:
+
+ <section header>
+ <index[]>
+ <data[]> --- <data>
+ <name>
+
+ Interface section contains data for proxy/stubs and external proxy/stubs. External
+ ones are defined at assembly level, so this section has no module information.
+ All records are indexed with 'iid' value from manifest. There an exception for
+ external variants - if 'proxyStubClsid32' is specified, it's stored as iid in
+ redirect data, but index is still 'iid' from manifest.
+
+ Interface name offset is relative to data structure itself.
+
+ - CLR surrogates section format:
+
+ <section header>
+ <index[]>
+ <data[]> --- <data>
+ <name>
+ <version>
+
+ There's nothing special about this section, same way to store strings is used,
+ no modules part as it belongs to assembly level, not a file.
+
+ - ProgID section format:
+
+ <section header>
+ <guids[]>
+ <index[]>
+ <data[]> --- <progid>
+ <data>
+
+ This sections uses generated alias guids from COM server section. This way
+ ProgID -> CLSID mapping returns generated guid, not the real one. ProgID string
+ is stored too, aligned.
+*/
+
+struct progids
+{
+ WCHAR **progids;
+ unsigned int num;
+ unsigned int allocated;
+};
+
struct entity
{
DWORD kind;
struct
{
WCHAR *tlbid;
- WCHAR *version;
WCHAR *helpdir;
- } typelib;
+ WORD flags;
+ WORD major;
+ WORD minor;
+ } typelib;
struct
{
WCHAR *clsid;
- } comclass;
- struct {
+ WCHAR *tlbid;
+ WCHAR *progid;
+ WCHAR *name; /* clrClass: class name */
+ WCHAR *version; /* clrClass: CLR runtime version */
+ DWORD model;
+ DWORD miscstatus;
+ DWORD miscstatuscontent;
+ DWORD miscstatusthumbnail;
+ DWORD miscstatusicon;
+ DWORD miscstatusdocprint;
+ struct progids progids;
+ } comclass;
+ struct {
WCHAR *iid;
+ WCHAR *base;
+ WCHAR *tlib;
WCHAR *name;
- } proxy;
+ WCHAR *ps32; /* only stored for 'comInterfaceExternalProxyStub' */
+ DWORD mask;
+ ULONG nummethods;
+ } ifaceps;
struct
{
WCHAR *name;
+ BOOL versioned;
} class;
struct
{
WCHAR *name;
WCHAR *clsid;
- } clrclass;
- struct
- {
- WCHAR *name;
- WCHAR *clsid;
+ WCHAR *version;
} clrsurrogate;
} u;
};
struct entity_array entities;
};
+enum context_sections
+{
+ WINDOWCLASS_SECTION = 1,
+ DLLREDIRECT_SECTION = 2,
+ TLIBREDIRECT_SECTION = 4,
+ SERVERREDIRECT_SECTION = 8,
+ IFACEREDIRECT_SECTION = 16,
+ CLRSURROGATES_SECTION = 32,
+ PROGIDREDIRECT_SECTION = 64
+};
+
typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY
{
ULONG Flags;
struct assembly *assemblies;
unsigned int num_assemblies;
unsigned int allocated_assemblies;
+ /* section data */
+ DWORD sections;
+ struct strsection_header *wndclass_section;
+ struct strsection_header *dllredirect_section;
+ struct strsection_header *progid_section;
+ struct guidsection_header *tlib_section;
+ struct guidsection_header *comserver_section;
+ struct guidsection_header *ifaceps_section;
+ struct guidsection_header *clrsurrogate_section;
} ACTIVATION_CONTEXT, *PIACTIVATION_CONTEXT;
struct actctx_loader
static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
static const WCHAR fileW[] = {'f','i','l','e',0};
-static const WCHAR asmv2hashW[] = {'a','s','m','v','2',':','h','a','s','h',0};
static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
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};
+static const WCHAR progidW[] = {'p','r','o','g','i','d',0};
static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
+static const WCHAR threadingmodelW[] = {'t','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
static const WCHAR typeW[] = {'t','y','p','e',0};
static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
+static const WCHAR versionedW[] = {'v','e','r','s','i','o','n','e','d',0};
+static const WCHAR yesW[] = {'y','e','s',0};
+static const WCHAR noW[] = {'n','o',0};
+static const WCHAR restrictedW[] = {'R','E','S','T','R','I','C','T','E','D',0};
+static const WCHAR controlW[] = {'C','O','N','T','R','O','L',0};
+static const WCHAR hiddenW[] = {'H','I','D','D','E','N',0};
+static const WCHAR hasdiskimageW[] = {'H','A','S','D','I','S','K','I','M','A','G','E',0};
+static const WCHAR flagsW[] = {'f','l','a','g','s',0};
+static const WCHAR miscstatusW[] = {'m','i','s','c','S','t','a','t','u','s',0};
+static const WCHAR miscstatusiconW[] = {'m','i','s','c','S','t','a','t','u','s','I','c','o','n',0};
+static const WCHAR miscstatuscontentW[] = {'m','i','s','c','S','t','a','t','u','s','C','o','n','t','e','n','t',0};
+static const WCHAR miscstatusthumbnailW[] = {'m','i','s','c','S','t','a','t','u','s','T','h','u','m','b','n','a','i','l',0};
+static const WCHAR miscstatusdocprintW[] = {'m','i','s','c','S','t','a','t','u','s','D','o','c','P','r','i','n','t',0};
+static const WCHAR baseInterfaceW[] = {'b','a','s','e','I','n','t','e','r','f','a','c','e',0};
+static const WCHAR nummethodsW[] = {'n','u','m','M','e','t','h','o','d','s',0};
+static const WCHAR proxyStubClsid32W[] = {'p','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
+static const WCHAR runtimeVersionW[] = {'r','u','n','t','i','m','e','V','e','r','s','i','o','n',0};
+static const WCHAR mscoreeW[] = {'M','S','C','O','R','E','E','.','D','L','L',0};
+static const WCHAR mscoree2W[] = {'m','s','c','o','r','e','e','.','d','l','l',0};
+
+static const WCHAR activatewhenvisibleW[] = {'a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
+static const WCHAR actslikebuttonW[] = {'a','c','t','s','l','i','k','e','b','u','t','t','o','n',0};
+static const WCHAR actslikelabelW[] = {'a','c','t','s','l','i','k','e','l','a','b','e','l',0};
+static const WCHAR alignableW[] = {'a','l','i','g','n','a','b','l','e',0};
+static const WCHAR alwaysrunW[] = {'a','l','w','a','y','s','r','u','n',0};
+static const WCHAR canlinkbyole1W[] = {'c','a','n','l','i','n','k','b','y','o','l','e','1',0};
+static const WCHAR cantlinkinsideW[] = {'c','a','n','t','l','i','n','k','i','n','s','i','d','e',0};
+static const WCHAR ignoreactivatewhenvisibleW[] = {'i','g','n','o','r','e','a','c','t','i','v','a','t','e','w','h','e','n','v','i','s','i','b','l','e',0};
+static const WCHAR imemodeW[] = {'i','m','e','m','o','d','e',0};
+static const WCHAR insertnotreplaceW[] = {'i','n','s','e','r','t','n','o','t','r','e','p','l','a','c','e',0};
+static const WCHAR insideoutW[] = {'i','n','s','i','d','e','o','u','t',0};
+static const WCHAR invisibleatruntimeW[] = {'i','n','v','i','s','i','b','l','e','a','t','r','u','n','t','i','m','e',0};
+static const WCHAR islinkobjectW[] = {'i','s','l','i','n','k','o','b','j','e','c','t',0};
+static const WCHAR nouiactivateW[] = {'n','o','u','i','a','c','t','i','v','a','t','e',0};
+static const WCHAR onlyiconicW[] = {'o','n','l','y','i','c','o','n','i','c',0};
+static const WCHAR recomposeonresizeW[] = {'r','e','c','o','m','p','o','s','e','o','n','r','e','s','i','z','e',0};
+static const WCHAR renderingisdeviceindependentW[] = {'r','e','n','d','e','r','i','n','g','i','s','d','e','v','i','c','e','i','n','d','e','p','e','n','d','e','n','t',0};
+static const WCHAR setclientsitefirstW[] = {'s','e','t','c','l','i','e','n','t','s','i','t','e','f','i','r','s','t',0};
+static const WCHAR simpleframeW[] = {'s','i','m','p','l','e','f','r','a','m','e',0};
+static const WCHAR staticW[] = {'s','t','a','t','i','c',0};
+static const WCHAR supportsmultilevelundoW[] = {'s','u','p','p','o','r','t','s','m','u','l','t','i','l','e','v','e','l','u','n','d','o',0};
+static const WCHAR wantstomenumergeW[] = {'w','a','n','t','s','t','o','m','e','n','u','m','e','r','g','e',0};
+
+struct olemisc_entry
+{
+ const WCHAR *name;
+ OLEMISC value;
+};
+
+static const struct olemisc_entry olemisc_values[] =
+{
+ { activatewhenvisibleW, OLEMISC_ACTIVATEWHENVISIBLE },
+ { actslikebuttonW, OLEMISC_ACTSLIKEBUTTON },
+ { actslikelabelW, OLEMISC_ACTSLIKELABEL },
+ { alignableW, OLEMISC_ALIGNABLE },
+ { alwaysrunW, OLEMISC_ALWAYSRUN },
+ { canlinkbyole1W, OLEMISC_CANLINKBYOLE1 },
+ { cantlinkinsideW, OLEMISC_CANTLINKINSIDE },
+ { ignoreactivatewhenvisibleW, OLEMISC_IGNOREACTIVATEWHENVISIBLE },
+ { imemodeW, OLEMISC_IMEMODE },
+ { insertnotreplaceW, OLEMISC_INSERTNOTREPLACE },
+ { insideoutW, OLEMISC_INSIDEOUT },
+ { invisibleatruntimeW, OLEMISC_INVISIBLEATRUNTIME },
+ { islinkobjectW, OLEMISC_ISLINKOBJECT },
+ { nouiactivateW, OLEMISC_NOUIACTIVATE },
+ { onlyiconicW, OLEMISC_ONLYICONIC },
+ { recomposeonresizeW, OLEMISC_RECOMPOSEONRESIZE },
+ { renderingisdeviceindependentW, OLEMISC_RENDERINGISDEVICEINDEPENDENT },
+ { setclientsitefirstW, OLEMISC_SETCLIENTSITEFIRST },
+ { simpleframeW, OLEMISC_SIMPLEFRAME },
+ { staticW, OLEMISC_STATIC },
+ { supportsmultilevelundoW, OLEMISC_SUPPORTSMULTILEVELUNDO },
+ { wantstomenumergeW, OLEMISC_WANTSTOMENUMERGE }
+};
static const WCHAR g_xmlW[] = {'?','x','m','l',0};
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};
static void free_entity_array(struct entity_array *array)
{
- unsigned int i;
+ unsigned int i, j;
for (i = 0; i < array->num; i++)
{
struct entity *entity = &array->base[i];
{
case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.tlbid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.name);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.version);
+ for (j = 0; j < entity->u.comclass.progids.num; j++)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids[j]);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.progids.progids);
break;
case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
- RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid);
- RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.iid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.base);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.ps32);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.ifaceps.name);
break;
case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
- RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version);
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
break;
case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
break;
- case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
- RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name);
- RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid);
- break;
case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
+ RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.version);
break;
default:
DPRINT1("Unknown entity kind %u\n", entity->kind);
return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
}
-static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static enum comclass_threadingmodel parse_com_class_threadingmodel(xmlstr_t *value)
+{
+ static const WCHAR apartW[] = {'A','p','a','r','t','m','e','n','t',0};
+ static const WCHAR neutralW[] = {'N','e','u','t','r','a','l',0};
+ static const WCHAR freeW[] = {'F','r','e','e',0};
+ static const WCHAR bothW[] = {'B','o','t','h',0};
+
+ if (value->len == 0) return ThreadingModel_No;
+ if (xmlstr_cmp(value, apartW))
+ return ThreadingModel_Apartment;
+ else if (xmlstr_cmp(value, freeW))
+ return ThreadingModel_Free;
+ else if (xmlstr_cmp(value, bothW))
+ return ThreadingModel_Both;
+ else if (xmlstr_cmp(value, neutralW))
+ return ThreadingModel_Neutral;
+ else
+ return ThreadingModel_No;
+};
+
+static OLEMISC get_olemisc_value(const WCHAR *str, int len)
+{
+ int min, max;
+
+ min = 0;
+ max = sizeof(olemisc_values)/sizeof(struct olemisc_entry) - 1;
+
+ while (min <= max)
+ {
+ int n, c;
+
+ n = (min+max)/2;
+
+ c = strncmpW(olemisc_values[n].name, str, len);
+ if (!c && !olemisc_values[n].name[len])
+ return olemisc_values[n].value;
+
+ if (c >= 0)
+ max = n-1;
+ else
+ min = n+1;
+ }
+
+ DPRINT1("unknown flag %S\n", str);
+ return 0;
+}
+
+static DWORD parse_com_class_misc(const xmlstr_t *value)
+{
+ const WCHAR *str = value->ptr, *start;
+ DWORD flags = 0;
+ int i = 0;
+
+ /* it's comma separated list of flags */
+ while (i < value->len)
+ {
+ start = str;
+ while (*str != ',' && (i++ < value->len)) str++;
+
+ flags |= get_olemisc_value(start, str-start);
+
+ /* skip separator */
+ str++;
+ i++;
+ }
+
+ return flags;
+}
+
+static BOOL com_class_add_progid(const xmlstr_t *progid, struct entity *entity)
+{
+ struct progids *progids = &entity->u.comclass.progids;
+
+ if (progids->allocated == 0)
+ {
+ progids->allocated = 4;
+ if (!(progids->progids = RtlAllocateHeap(RtlGetProcessHeap(), 0, progids->allocated * sizeof(WCHAR*)))) return FALSE;
+ }
+
+ if (progids->allocated == progids->num)
+ {
+ progids->allocated *= 2;
+ progids->progids = RtlReAllocateHeap(RtlGetProcessHeap(), 0, progids->progids, progids->allocated * sizeof(WCHAR*));
+ }
+
+ if (!(progids->progids[progids->num] = xmlstrdupW(progid))) return FALSE;
+ progids->num++;
+
+ return TRUE;
+}
+
+static BOOL parse_com_class_progid(xmlbuf_t* xmlbuf, struct entity *entity)
+{
+ xmlstr_t content;
+ BOOL end = FALSE;
+
+ if (!parse_expect_no_attr(xmlbuf, &end) || end || !parse_text_content(xmlbuf, &content))
+ return FALSE;
+
+ if (!com_class_add_progid(&content, entity)) return FALSE;
+ return parse_expect_end_elem(xmlbuf, progidW, asmv1W);
+}
+
+static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader *acl)
{
xmlstr_t elem, attr_name, attr_value;
BOOL ret = TRUE, end = FALSE, error;
{
if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
}
+ else if (xmlstr_cmp(&attr_name, progidW))
+ {
+ if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, tlbidW))
+ {
+ if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, threadingmodelW))
+ {
+ entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, miscstatusW))
+ {
+ entity->u.comclass.miscstatus = parse_com_class_misc(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, miscstatuscontentW))
+ {
+ entity->u.comclass.miscstatuscontent = parse_com_class_misc(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, miscstatusthumbnailW))
+ {
+ entity->u.comclass.miscstatusthumbnail = parse_com_class_misc(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, miscstatusiconW))
+ {
+ entity->u.comclass.miscstatusicon = parse_com_class_misc(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, miscstatusdocprintW))
+ {
+ entity->u.comclass.miscstatusdocprint = parse_com_class_misc(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, descriptionW))
+ {
+ /* not stored */
+ }
else
{
attr_nameU = xmlstr2unicode(&attr_name);
}
}
- if (error || end) return end;
+ if (error) return FALSE;
- while ((ret = next_xml_elem(xmlbuf, &elem)))
+ acl->actctx->sections |= SERVERREDIRECT_SECTION;
+ if (entity->u.comclass.progid)
+ acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
+ if (end) return TRUE;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
{
if (xmlstr_cmp_end(&elem, comClassW))
{
ret = parse_end_element(xmlbuf);
break;
}
+ else if (xmlstr_cmp(&elem, progidW))
+ {
+ ret = parse_com_class_progid(xmlbuf, entity);
+ }
else
{
attr_nameU = xmlstr2unicode(&elem);
ret = parse_unknown_elem(xmlbuf, &elem);
}
}
+
+ if (entity->u.comclass.progids.num)
+ acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
return ret;
}
-static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static BOOL parse_nummethods(const xmlstr_t *str, struct entity *entity)
+{
+ const WCHAR *curr;
+ ULONG num = 0;
+
+ for (curr = str->ptr; curr < str->ptr + str->len; curr++)
+ {
+ if (*curr >= '0' && *curr <= '9')
+ num = num * 10 + *curr - '0';
+ else
+ {
+ UNICODE_STRING strU = xmlstr2unicode(str);
+ DPRINT1("wrong numeric value %wZ\n", &strU);
+ return FALSE;
+ }
+ }
+ entity->u.ifaceps.nummethods = num;
+
+ return TRUE;
+}
+
+static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
{
xmlstr_t attr_name, attr_value;
BOOL end = FALSE, error;
{
if (xmlstr_cmp(&attr_name, iidW))
{
- if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
}
- if (xmlstr_cmp(&attr_name, g_nameW))
+ else if (xmlstr_cmp(&attr_name, g_nameW))
+ {
+ if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, baseInterfaceW))
+ {
+ if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
+ entity->u.ifaceps.mask |= BaseIface;
+ }
+ else if (xmlstr_cmp(&attr_name, nummethodsW))
+ {
+ if (!(parse_nummethods(&attr_value, entity))) return FALSE;
+ entity->u.ifaceps.mask |= NumMethods;
+ }
+ else if (xmlstr_cmp(&attr_name, tlbidW))
+ {
+ if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ /* not used */
+ else if (xmlstr_cmp(&attr_name, proxyStubClsid32W) || xmlstr_cmp(&attr_name, threadingmodelW))
{
- if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
}
else
{
}
}
- if (error || end) return end;
+ if (error) return FALSE;
+ acl->actctx->sections |= IFACEREDIRECT_SECTION;
+ if (end) return TRUE;
+
return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW, asmv1W);
}
-static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static BOOL parse_typelib_flags(const xmlstr_t *value, struct entity *entity)
+{
+ WORD *flags = &entity->u.typelib.flags;
+ const WCHAR *str = value->ptr, *start;
+ int i = 0;
+
+ *flags = 0;
+
+ /* it's comma separated list of flags */
+ while (i < value->len)
+ {
+ start = str;
+ while (*str != ',' && (i++ < value->len)) str++;
+
+ if (!strncmpiW(start, restrictedW, str-start))
+ *flags |= LIBFLAG_FRESTRICTED;
+ else if (!strncmpiW(start, controlW, str-start))
+ *flags |= LIBFLAG_FCONTROL;
+ else if (!strncmpiW(start, hiddenW, str-start))
+ *flags |= LIBFLAG_FHIDDEN;
+ else if (!strncmpiW(start, hasdiskimageW, str-start))
+ *flags |= LIBFLAG_FHASDISKIMAGE;
+ else
+ {
+ UNICODE_STRING valueU = xmlstr2unicode(value);
+ DPRINT1("unknown flags value %wZ\n", &valueU);
+ return FALSE;
+ }
+
+ /* skip separator */
+ str++;
+ i++;
+ }
+
+ return TRUE;
+}
+
+static BOOL parse_typelib_version(const xmlstr_t *str, struct entity *entity)
+{
+ unsigned int ver[2];
+ unsigned int pos;
+ const WCHAR *curr;
+ UNICODE_STRING strW;
+
+ /* major.minor */
+ ver[0] = ver[1] = pos = 0;
+ for (curr = str->ptr; curr < str->ptr + str->len; curr++)
+ {
+ if (*curr >= '0' && *curr <= '9')
+ {
+ ver[pos] = ver[pos] * 10 + *curr - '0';
+ if (ver[pos] >= 0x10000) goto error;
+ }
+ else if (*curr == '.')
+ {
+ if (++pos >= 2) goto error;
+ }
+ else goto error;
+ }
+ entity->u.typelib.major = ver[0];
+ entity->u.typelib.minor = ver[1];
+ return TRUE;
+
+error:
+ strW = xmlstr2unicode(str);
+ DPRINT1("FIXME: wrong typelib version value (%wZ)\n", &strW);
+ return FALSE;
+}
+
+static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
{
xmlstr_t attr_name, attr_value;
BOOL end = FALSE, error;
{
if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
}
- if (xmlstr_cmp(&attr_name, versionW))
+ else if (xmlstr_cmp(&attr_name, versionW))
{
- if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
+ if (!parse_typelib_version(&attr_value, entity)) return FALSE;
}
- if (xmlstr_cmp(&attr_name, helpdirW))
+ else if (xmlstr_cmp(&attr_name, helpdirW))
{
if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
}
+ else if (xmlstr_cmp(&attr_name, flagsW))
+ {
+ if (!parse_typelib_flags(&attr_value, entity)) return FALSE;
+ }
else
{
attr_nameU = xmlstr2unicode(&attr_name);
}
}
- if (error || end) return end;
+ if (error) return FALSE;
+
+ acl->actctx->sections |= TLIBREDIRECT_SECTION;
+
+ if (end) return TRUE;
+
return parse_expect_end_elem(xmlbuf, typelibW, asmv1W);
}
-static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
+static inline int aligned_string_len(int len)
{
- xmlstr_t elem, content;
- BOOL end = FALSE, ret = TRUE;
- struct entity* entity;
- UNICODE_STRING elemU;
+ return (len + 3) & ~3;
+}
- if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
- return FALSE;
+static int get_assembly_version(struct assembly *assembly, WCHAR *ret)
+{
+ static const WCHAR fmtW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
+ struct assembly_version *ver = &assembly->id.version;
+ WCHAR buff[25];
- if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
- if (end) return FALSE;
+ if (!ret) ret = buff;
+ return sprintfW(ret, fmtW, ver->major, ver->minor, ver->build, ver->revision);
+}
- if (!parse_text_content(xmlbuf, &content)) return FALSE;
+static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll, struct actctx_loader* acl)
+{
+ xmlstr_t elem, content, attr_name, attr_value;
+ BOOL end = FALSE, ret = TRUE, error;
+ struct entity* entity;
+ UNICODE_STRING elemU, attr_nameU, attr_valueU;
- if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
+ if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
+ return FALSE;
- while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ entity->u.class.versioned = TRUE;
+ while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
- if (xmlstr_cmp_end(&elem, windowClassW))
+ if (xmlstr_cmp(&attr_name, versionedW))
+ {
+ if (xmlstr_cmpi(&attr_value, noW))
+ entity->u.class.versioned = FALSE;
+ else if (!xmlstr_cmpi(&attr_value, yesW))
+ return FALSE;
+ }
+ else
+ {
+ attr_nameU = xmlstr2unicode(&attr_name);
+ attr_valueU = xmlstr2unicode(&attr_value);
+ DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
+ }
+ }
+
+ if (error || end) return end;
+
+ if (!parse_text_content(xmlbuf, &content)) return FALSE;
+
+ if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
+
+ acl->actctx->sections |= WINDOWCLASS_SECTION;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, windowClassW))
{
ret = parse_end_element(xmlbuf);
break;
}
static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
- struct assembly* assembly)
+ struct assembly* assembly,
+ struct actctx_loader* acl)
{
xmlstr_t attr_name, attr_value;
UNICODE_STRING attr_nameU, attr_valueU;
{
if (xmlstr_cmp(&attr_name, iidW))
{
- if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.ifaceps.iid = xmlstrdupW(&attr_value))) return FALSE;
}
- if (xmlstr_cmp(&attr_name, g_nameW))
+ else if (xmlstr_cmp(&attr_name, g_nameW))
+ {
+ if (!(entity->u.ifaceps.name = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, baseInterfaceW))
+ {
+ if (!(entity->u.ifaceps.base = xmlstrdupW(&attr_value))) return FALSE;
+ entity->u.ifaceps.mask |= BaseIface;
+ }
+ else if (xmlstr_cmp(&attr_name, nummethodsW))
+ {
+ if (!(parse_nummethods(&attr_value, entity))) return FALSE;
+ entity->u.ifaceps.mask |= NumMethods;
+ }
+ else if (xmlstr_cmp(&attr_name, proxyStubClsid32W))
+ {
+ if (!(entity->u.ifaceps.ps32 = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, tlbidW))
{
- if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.ifaceps.tlib = xmlstrdupW(&attr_value))) return FALSE;
}
else
{
}
}
- if (error || end) return end;
+ if (error) return FALSE;
+ acl->actctx->sections |= IFACEREDIRECT_SECTION;
+ if (end) return TRUE;
+
return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW, asmv1W);
}
-static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
{
- xmlstr_t attr_name, attr_value;
- UNICODE_STRING attr_nameU, attr_valueU;
- BOOL end = FALSE, error;
+ xmlstr_t attr_name, attr_value, elem;
+ BOOL end = FALSE, error, ret = TRUE;
struct entity* entity;
- entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
+ entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION);
if (!entity) return FALSE;
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
if (xmlstr_cmp(&attr_name, g_nameW))
{
- if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.comclass.name = xmlstrdupW(&attr_value))) return FALSE;
}
else if (xmlstr_cmp(&attr_name, clsidW))
{
- if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+ if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, progidW))
+ {
+ if (!(entity->u.comclass.progid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, tlbidW))
+ {
+ if (!(entity->u.comclass.tlbid = xmlstrdupW(&attr_value))) return FALSE;
+ }
+ else if (xmlstr_cmp(&attr_name, threadingmodelW))
+ {
+ entity->u.comclass.model = parse_com_class_threadingmodel(&attr_value);
+ }
+ else if (xmlstr_cmp(&attr_name, runtimeVersionW))
+ {
+ if (!(entity->u.comclass.version = xmlstrdupW(&attr_value))) return FALSE;
}
else
{
+ UNICODE_STRING attr_nameU, attr_valueU;
attr_nameU = xmlstr2unicode(&attr_name);
attr_valueU = xmlstr2unicode(&attr_value);
DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
}
}
- if (error || end) return end;
- return parse_expect_end_elem(xmlbuf, clrClassW, asmv1W);
+ if (error) return FALSE;
+ acl->actctx->sections |= SERVERREDIRECT_SECTION;
+ if (entity->u.comclass.progid)
+ acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+ if (end) return TRUE;
+
+ while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
+ {
+ if (xmlstr_cmp_end(&elem, clrClassW))
+ {
+ ret = parse_end_element(xmlbuf);
+ break;
+ }
+ else if (xmlstr_cmp(&elem, progidW))
+ {
+ ret = parse_com_class_progid(xmlbuf, entity);
+ }
+ else
+ {
+ UNICODE_STRING elemU = xmlstr2unicode(&elem);
+ DPRINT1("unknown elem %wZ\n", &elemU);
+ ret = parse_unknown_elem(xmlbuf, &elem);
+ }
+ }
+
+ if (entity->u.comclass.progids.num)
+ acl->actctx->sections |= PROGIDREDIRECT_SECTION;
+
+ return ret;
}
-static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader *acl)
{
xmlstr_t attr_name, attr_value;
UNICODE_STRING attr_nameU, attr_valueU;
{
if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
}
+ else if (xmlstr_cmp(&attr_name, runtimeVersionW))
+ {
+ if (!(entity->u.clrsurrogate.version = xmlstrdupW(&attr_value))) return FALSE;
+ }
else
{
attr_nameU = xmlstr2unicode(&attr_name);
}
}
- if (error || end) return end;
+ if (error) return FALSE;
+ acl->actctx->sections |= CLRSURROGATES_SECTION;
+ if (end) return TRUE;
+
return parse_expect_end_elem(xmlbuf, clrSurrogateW, asmv1W);
}
!parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
return FALSE;
+ //TRACE( "adding name=%s version=%s arch=%s\n", debugstr_w(ai.name), debugstr_version(&ai.version), debugstr_w(ai.arch) );
+
/* store the newly found identity for later loading */
if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
if (xmlstr_cmp(&attr_name, optionalW))
{
- static const WCHAR yesW[] = {'y','e','s',0};
optional = xmlstr_cmpi( &attr_value, yesW );
DPRINT1("optional=%wZ\n", &attr_valueU);
}
return end || parse_expect_end_elem(xmlbuf, noInheritableW, asmv1W);
}
-static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
+static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly, struct actctx_loader* acl)
{
xmlstr_t attr_name, attr_value, elem;
UNICODE_STRING attr_nameU, attr_valueU;
}
if (error || !dll->name) return FALSE;
+
+ acl->actctx->sections |= DLLREDIRECT_SECTION;
+
if (end) return TRUE;
while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
}
else if (xmlstr_cmp(&elem, comClassW))
{
- ret = parse_com_class_elem(xmlbuf, dll);
+ ret = parse_com_class_elem(xmlbuf, dll, acl);
}
else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
{
- ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
+ ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll, acl);
}
- else if (xmlstr_cmp(&elem, asmv2hashW))
+ else if (xml_elem_cmp(&elem, hashW, asmv2W))
{
DPRINT1("asmv2hash (undocumented) not supported\n");
ret = parse_unknown_elem(xmlbuf, &elem);
}
else if (xmlstr_cmp(&elem, typelibW))
{
- ret = parse_typelib_elem(xmlbuf, dll);
+ ret = parse_typelib_elem(xmlbuf, dll, acl);
}
else if (xmlstr_cmp(&elem, windowClassW))
{
- ret = parse_window_class_elem(xmlbuf, dll);
+ ret = parse_window_class_elem(xmlbuf, dll, acl);
}
else
{
UNICODE_STRING attr_nameU, attr_valueU;
BOOL end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
+ DPRINT("(%p)\n", xmlbuf);
+
while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
{
attr_nameU = xmlstr2unicode(&attr_name);
assembly->no_inherit = TRUE;
}
- if (xmlstr_cmp(&elem, noInheritableW))
+ if (xml_elem_cmp(&elem, noInheritableW, asmv1W))
{
if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
return FALSE;
while (ret)
{
- if (xmlstr_cmp_end(&elem, assemblyW))
+ if (xml_elem_cmp_end(&elem, assemblyW, asmv1W))
{
ret = parse_end_element(xmlbuf);
break;
}
- else if (xmlstr_cmp(&elem, descriptionW))
+ else if (xml_elem_cmp(&elem, descriptionW, asmv1W))
{
ret = parse_description_elem(xmlbuf);
}
- else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW))
+ else if (xml_elem_cmp(&elem, comInterfaceExternalProxyStubW, asmv1W))
{
- ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
+ ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly, acl);
}
- else if (xmlstr_cmp(&elem, dependencyW))
+ else if (xml_elem_cmp(&elem, dependencyW, asmv1W))
{
ret = parse_dependency_elem(xmlbuf, acl);
}
- else if (xmlstr_cmp(&elem, fileW))
+ else if (xml_elem_cmp(&elem, fileW, asmv1W))
{
- ret = parse_file_elem(xmlbuf, assembly);
+ ret = parse_file_elem(xmlbuf, assembly, acl);
}
- else if (xmlstr_cmp(&elem, clrClassW))
+ else if (xml_elem_cmp(&elem, clrClassW, asmv1W))
{
- ret = parse_clr_class_elem(xmlbuf, assembly);
+ ret = parse_clr_class_elem(xmlbuf, assembly, acl);
}
- else if (xmlstr_cmp(&elem, clrSurrogateW))
+ else if (xml_elem_cmp(&elem, clrSurrogateW, asmv1W))
{
- ret = parse_clr_surrogate_elem(xmlbuf, assembly);
+ ret = parse_clr_surrogate_elem(xmlbuf, assembly, acl);
}
- else if (xmlstr_cmp(&elem, assemblyIdentityW))
+ else if (xml_elem_cmp(&elem, assemblyIdentityW, asmv1W))
{
if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
(!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
return STATUS_SXS_CANT_GEN_ACTCTX;
- if (!xmlstr_cmp(&elem, assemblyW))
+ if (!xml_elem_cmp(&elem, assemblyW, asmv1W))
{
elemU = xmlstr2unicode(&elem);
DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
{
if (!acl->dependencies[i].optional)
{
- DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
+ const struct assembly_version *ver = &acl->dependencies[i].version;
+ DPRINT1( "Could not find dependent assembly %S (%u.%u.%u.%u)\n",
+ acl->dependencies[i].name,
+ ver->major, ver->minor, ver->build, ver->revision );
status = STATUS_SXS_CANT_GEN_ACTCTX;
break;
}
return status;
}
-static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
+static NTSTATUS build_dllredirect_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
+{
+ unsigned int i, j, total_len = 0, dll_count = 0;
+ struct strsection_header *header;
+ struct dllredirect_data *data;
+ struct string_index *index;
+ ULONG name_offset;
+
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+
+ /* each entry needs index, data and string data */
+ total_len += sizeof(*index);
+ total_len += sizeof(*data);
+ total_len += aligned_string_len((strlenW(dll->name)+1)*sizeof(WCHAR));
+ }
+
+ dll_count += assembly->num_dlls;
+ }
+
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = STRSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = dll_count;
+ header->index_offset = sizeof(*header);
+ index = (struct string_index*)((BYTE*)header + header->index_offset);
+ name_offset = header->index_offset + header->count*sizeof(*index);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ UNICODE_STRING str;
+ WCHAR *ptrW;
+
+ /* setup new index entry */
+ str.Buffer = dll->name;
+ str.Length = strlenW(dll->name)*sizeof(WCHAR);
+ str.MaximumLength = str.Length + sizeof(WCHAR);
+ /* hash original class name */
+ RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
+
+ index->name_offset = name_offset;
+ index->name_len = str.Length;
+ index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
+ index->data_len = sizeof(*data);
+ index->rosterindex = i + 1;
+
+ /* setup data */
+ data = (struct dllredirect_data*)((BYTE*)header + index->data_offset);
+ data->size = sizeof(*data);
+ data->unk = 2; /* FIXME: seems to be constant */
+ memset(data->res, 0, sizeof(data->res));
+
+ /* dll name */
+ ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
+ memcpy(ptrW, dll->name, index->name_len);
+ ptrW[index->name_len/sizeof(WCHAR)] = 0;
+
+ name_offset += sizeof(*data) + aligned_string_len(str.MaximumLength);
+
+ index++;
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static struct string_index *find_string_index(const struct strsection_header *section, const UNICODE_STRING *name)
+{
+ struct string_index *iter, *index = NULL;
+ ULONG hash = 0, i;
+
+ RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
+ iter = (struct string_index*)((BYTE*)section + section->index_offset);
+
+ for (i = 0; i < section->count; i++)
+ {
+ if (iter->hash == hash)
+ {
+ const WCHAR *nameW = (WCHAR*)((BYTE*)section + iter->name_offset);
+
+ if (!strcmpiW(nameW, name->Buffer))
+ {
+ index = iter;
+ break;
+ }
+ else
+ DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
+ }
+ iter++;
+ }
+
+ return index;
+}
+
+static struct guid_index *find_guid_index(const struct guidsection_header *section, const GUID *guid)
+{
+ struct guid_index *iter, *index = NULL;
+ ULONG i;
+
+ iter = (struct guid_index*)((BYTE*)section + section->index_offset);
+
+ for (i = 0; i < section->count; i++)
+ {
+ if (!memcmp(guid, &iter->guid, sizeof(*guid)))
+ {
+ index = iter;
+ break;
+ }
+ iter++;
+ }
+
+ return index;
+}
+
+static inline struct dllredirect_data *get_dllredirect_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
+{
+ return (struct dllredirect_data*)((BYTE*)ctxt->dllredirect_section + index->data_offset);
+}
+
+static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+ PACTCTX_SECTION_KEYED_DATA data)
{
+ struct dllredirect_data *dll;
+ struct string_index *index;
+
+ if (!(actctx->sections & DLLREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->dllredirect_section)
+ {
+ struct strsection_header *section;
+
+ NTSTATUS status = build_dllredirect_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->dllredirect_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_string_index(actctx->dllredirect_section, name);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ dll = get_dllredirect_data(actctx, index);
+
data->ulDataFormatVersion = 1;
- data->lpData = v1;
- data->ulLength = 20; /* FIXME */
- data->lpSectionGlobalData = NULL; /* FIXME */
- data->ulSectionGlobalDataLength = 0; /* FIXME */
- data->lpSectionBase = v2;
- data->ulSectionTotalLength = 0; /* FIXME */
+ data->lpData = dll;
+ data->ulLength = dll->size;
+ data->lpSectionGlobalData = NULL;
+ data->ulSectionGlobalDataLength = 0;
+ data->lpSectionBase = actctx->dllredirect_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->dllredirect_section );
data->hActCtx = NULL;
- if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
- data->ulAssemblyRosterIndex = i + 1;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
return STATUS_SUCCESS;
}
-static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
- PACTCTX_SECTION_KEYED_DATA data)
+static inline struct string_index *get_wndclass_first_index(ACTIVATION_CONTEXT *actctx)
+{
+ return (struct string_index*)((BYTE*)actctx->wndclass_section + actctx->wndclass_section->index_offset);
+}
+
+static inline struct wndclass_redirect_data *get_wndclass_data(ACTIVATION_CONTEXT *ctxt, struct string_index *index)
+{
+ return (struct wndclass_redirect_data*)((BYTE*)ctxt->wndclass_section + index->data_offset);
+}
+
+static NTSTATUS build_wndclass_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
{
- unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
+ unsigned int i, j, k, total_len = 0, class_count = 0;
+ struct wndclass_redirect_data *data;
+ struct strsection_header *header;
+ struct string_index *index;
+ ULONG name_offset;
+ /* compute section length */
for (i = 0; i < actctx->num_assemblies; i++)
{
struct assembly *assembly = &actctx->assemblies[i];
for (j = 0; j < assembly->num_dlls; j++)
{
struct dll_redirect *dll = &assembly->dlls[j];
- if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
- return fill_keyed_data(data, dll, assembly, i);
+ for (k = 0; k < dll->entities.num; k++)
+ {
+ struct entity *entity = &dll->entities.base[k];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
+ {
+ int class_len = strlenW(entity->u.class.name) + 1;
+ int len;
+
+ /* each class entry needs index, data and string data */
+ total_len += sizeof(*index);
+ total_len += sizeof(*data);
+ /* original name is stored separately */
+ total_len += aligned_string_len(class_len*sizeof(WCHAR));
+ /* versioned name and module name are stored one after another */
+ if (entity->u.class.versioned)
+ len = get_assembly_version(assembly, NULL) + class_len + 1 /* '!' separator */;
+ else
+ len = class_len;
+ len += strlenW(dll->name) + 1;
+ total_len += aligned_string_len(len*sizeof(WCHAR));
+
+ class_count++;
+ }
+ }
}
}
- return STATUS_SXS_KEY_NOT_FOUND;
-}
-static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
- PACTCTX_SECTION_KEYED_DATA data)
-{
- unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = STRSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = class_count;
+ header->index_offset = sizeof(*header);
+ index = (struct string_index*)((BYTE*)header + header->index_offset);
+ name_offset = header->index_offset + header->count*sizeof(*index);
for (i = 0; i < actctx->num_assemblies; i++)
{
struct entity *entity = &dll->entities.base[k];
if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
{
- if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
- return fill_keyed_data(data, entity, dll, i);
+ static const WCHAR exclW[] = {'!',0};
+ ULONG versioned_len, module_len;
+ UNICODE_STRING str;
+ WCHAR *ptrW;
+
+ /* setup new index entry */
+ str.Buffer = entity->u.class.name;
+ str.Length = strlenW(entity->u.class.name)*sizeof(WCHAR);
+ str.MaximumLength = str.Length + sizeof(WCHAR);
+ /* hash original class name */
+ RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &index->hash);
+
+ /* include '!' separator too */
+ if (entity->u.class.versioned)
+ versioned_len = (get_assembly_version(assembly, NULL) + 1)*sizeof(WCHAR) + str.Length;
+ else
+ versioned_len = str.Length;
+ module_len = strlenW(dll->name)*sizeof(WCHAR);
+
+ index->name_offset = name_offset;
+ index->name_len = str.Length;
+ index->data_offset = index->name_offset + aligned_string_len(str.MaximumLength);
+ index->data_len = sizeof(*data) + versioned_len + module_len + 2*sizeof(WCHAR) /* two nulls */;
+ index->rosterindex = i + 1;
+
+ /* setup data */
+ data = (struct wndclass_redirect_data*)((BYTE*)header + index->data_offset);
+ data->size = sizeof(*data);
+ data->res = 0;
+ data->name_len = versioned_len;
+ data->name_offset = sizeof(*data);
+ data->module_len = module_len;
+ data->module_offset = index->data_offset + data->name_offset + data->name_len + sizeof(WCHAR);
+
+ /* original class name */
+ ptrW = (WCHAR*)((BYTE*)header + index->name_offset);
+ memcpy(ptrW, entity->u.class.name, index->name_len);
+ ptrW[index->name_len/sizeof(WCHAR)] = 0;
+
+ /* module name */
+ ptrW = (WCHAR*)((BYTE*)header + data->module_offset);
+ memcpy(ptrW, dll->name, data->module_len);
+ ptrW[data->module_len/sizeof(WCHAR)] = 0;
+
+ /* versioned name */
+ ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+ if (entity->u.class.versioned)
+ {
+ get_assembly_version(assembly, ptrW);
+ strcatW(ptrW, exclW);
+ strcatW(ptrW, entity->u.class.name);
+ }
+ else
+ {
+ memcpy(ptrW, entity->u.class.name, index->name_len);
+ ptrW[index->name_len/sizeof(WCHAR)] = 0;
+ }
+
+ name_offset += sizeof(*data);
+ name_offset += aligned_string_len(str.MaximumLength) + aligned_string_len(versioned_len + module_len + 2*sizeof(WCHAR));
+
+ index++;
}
}
}
}
- return STATUS_SXS_KEY_NOT_FOUND;
+
+ *section = header;
+
+ return STATUS_SUCCESS;
}
-static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
- const UNICODE_STRING *section_name,
- DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+ PACTCTX_SECTION_KEYED_DATA data)
{
- NTSTATUS status;
+ struct string_index *iter, *index = NULL;
+ struct wndclass_redirect_data *class;
+ ULONG hash;
+ int i;
- switch (section_kind)
+ if (!(actctx->sections & WINDOWCLASS_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->wndclass_section)
{
- case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
- status = find_dll_redirection(actctx, section_name, data);
- break;
- case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
- status = find_window_class(actctx, section_name, data);
- break;
- case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
- case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
- case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
- case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
- case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
- case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
- DPRINT1("Unsupported yet section_kind %x\n", section_kind);
- return STATUS_SXS_SECTION_NOT_FOUND;
- default:
- DPRINT1("Unknown section_kind %x\n", section_kind);
- return STATUS_SXS_SECTION_NOT_FOUND;
+ struct strsection_header *section;
+
+ NTSTATUS status = build_wndclass_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->wndclass_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
}
- if (status != STATUS_SUCCESS) return status;
+ hash = 0;
+ RtlHashUnicodeString(name, TRUE, HASH_STRING_ALGORITHM_X65599, &hash);
+ iter = get_wndclass_first_index(actctx);
- if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ for (i = 0; i < actctx->wndclass_section->count; i++)
{
- actctx_addref(actctx);
- data->hActCtx = actctx;
+ if (iter->hash == hash)
+ {
+ const WCHAR *nameW = (WCHAR*)((BYTE*)actctx->wndclass_section + iter->name_offset);
+
+ if (!strcmpW(nameW, name->Buffer))
+ {
+ index = iter;
+ break;
+ }
+ else
+ DPRINT1("hash collision 0x%08x, %wZ, %S\n", hash, name, nameW);
+ }
+ iter++;
}
+
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ class = get_wndclass_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = class;
+ /* full length includes string length with nulls */
+ data->ulLength = class->size + class->name_len + class->module_len + 2*sizeof(WCHAR);
+ data->lpSectionGlobalData = NULL;
+ data->ulSectionGlobalDataLength = 0;
+ data->lpSectionBase = actctx->wndclass_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->wndclass_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
return STATUS_SUCCESS;
}
-static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
- const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+static NTSTATUS build_tlib_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
{
- NTSTATUS status;
+ unsigned int i, j, k, total_len = 0, tlib_count = 0, names_len = 0;
+ struct guidsection_header *header;
+ ULONG module_offset, data_offset;
+ struct tlibredirect_data *data;
+ struct guid_index *index;
- switch (section_kind)
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ for (k = 0; k < dll->entities.num; k++)
+ {
+ struct entity *entity = &dll->entities.base[k];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
+ {
+ /* each entry needs index, data and string data for module name and help string */
+ total_len += sizeof(*index);
+ total_len += sizeof(*data);
+ /* help string is stored separately */
+ if (*entity->u.typelib.helpdir)
+ total_len += aligned_string_len((strlenW(entity->u.typelib.helpdir)+1)*sizeof(WCHAR));
+
+ /* module names are packed one after another */
+ names_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
+
+ tlib_count++;
+ }
+ }
+ }
+ }
+
+ total_len += aligned_string_len(names_len);
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = GUIDSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = tlib_count;
+ header->index_offset = sizeof(*header) + aligned_string_len(names_len);
+ index = (struct guid_index*)((BYTE*)header + header->index_offset);
+ module_offset = sizeof(*header);
+ data_offset = header->index_offset + tlib_count*sizeof(*index);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
{
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ for (k = 0; k < dll->entities.num; k++)
+ {
+ struct entity *entity = &dll->entities.base[k];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)
+ {
+ ULONG module_len, help_len;
+ UNICODE_STRING str;
+ WCHAR *ptrW;
+
+ if (*entity->u.typelib.helpdir)
+ help_len = strlenW(entity->u.typelib.helpdir)*sizeof(WCHAR);
+ else
+ help_len = 0;
+
+ module_len = strlenW(dll->name)*sizeof(WCHAR);
+
+ /* setup new index entry */
+ RtlInitUnicodeString(&str, entity->u.typelib.tlbid);
+ RtlGUIDFromString(&str, &index->guid);
+ index->data_offset = data_offset;
+ index->data_len = sizeof(*data) + aligned_string_len(help_len);
+ index->rosterindex = i + 1;
+
+ /* setup data */
+ data = (struct tlibredirect_data*)((BYTE*)header + index->data_offset);
+ data->size = sizeof(*data);
+ data->res = 0;
+ data->name_len = module_len;
+ data->name_offset = module_offset;
+ /* FIXME: resourceid handling is really weird, and it doesn't seem to be useful */
+ data->langid = 0;
+ data->flags = entity->u.typelib.flags;
+ data->help_len = help_len;
+ data->help_offset = sizeof(*data);
+ data->major_version = entity->u.typelib.major;
+ data->minor_version = entity->u.typelib.minor;
+
+ /* module name */
+ ptrW = (WCHAR*)((BYTE*)header + data->name_offset);
+ memcpy(ptrW, dll->name, data->name_len);
+ ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+ /* help string */
+ if (data->help_len)
+ {
+ ptrW = (WCHAR*)((BYTE*)data + data->help_offset);
+ memcpy(ptrW, entity->u.typelib.helpdir, data->help_len);
+ ptrW[data->help_len/sizeof(WCHAR)] = 0;
+ }
+
+ data_offset += sizeof(*data);
+ if (help_len)
+ data_offset += aligned_string_len(help_len + sizeof(WCHAR));
+
+ module_offset += module_len + sizeof(WCHAR);
+
+ index++;
+ }
+ }
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static inline struct tlibredirect_data *get_tlib_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+ return (struct tlibredirect_data*)((BYTE*)actctx->tlib_section + index->data_offset);
+}
+
+static NTSTATUS find_tlib_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+ struct guid_index *index = NULL;
+ struct tlibredirect_data *tlib;
+
+ if (!(actctx->sections & TLIBREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->tlib_section)
+ {
+ struct guidsection_header *section;
+
+ NTSTATUS status = build_tlib_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->tlib_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_guid_index(actctx->tlib_section, guid);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ tlib = get_tlib_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = tlib;
+ /* full length includes string length with nulls */
+ data->ulLength = tlib->size + tlib->help_len + sizeof(WCHAR);
+ data->lpSectionGlobalData = (BYTE*)actctx->tlib_section + actctx->tlib_section->names_offset;
+ data->ulSectionGlobalDataLength = actctx->tlib_section->names_len;
+ data->lpSectionBase = actctx->tlib_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->tlib_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
+ return STATUS_SUCCESS;
+}
+
+static void generate_uuid(ULONG *seed, GUID *guid)
+{
+ ULONG *ptr = (ULONG*)guid;
+ int i;
+
+ /* GUID is 16 bytes long */
+ for (i = 0; i < sizeof(GUID)/sizeof(ULONG); i++, ptr++)
+ *ptr = RtlUniform(seed);
+
+ guid->Data3 &= 0x0fff;
+ guid->Data3 |= (4 << 12);
+ guid->Data4[0] &= 0x3f;
+ guid->Data4[0] |= 0x80;
+}
+
+static void get_comserver_datalen(const struct entity_array *entities, const struct dll_redirect *dll,
+ unsigned int *count, unsigned int *len, unsigned int *module_len)
+{
+ unsigned int i;
+
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+ {
+ /* each entry needs two index entries, extra one goes for alias GUID */
+ *len += 2*sizeof(struct guid_index);
+ /* To save some memory we don't allocated two data structures,
+ instead alias index and normal index point to the same data structure. */
+ *len += sizeof(struct comclassredirect_data);
+
+ /* for clrClass store some more */
+ if (entity->u.comclass.name)
+ {
+ unsigned int str_len;
+
+ /* all string data is stored together in aligned block */
+ str_len = strlenW(entity->u.comclass.name)+1;
+ if (entity->u.comclass.progid)
+ str_len += strlenW(entity->u.comclass.progid)+1;
+ if (entity->u.comclass.version)
+ str_len += strlenW(entity->u.comclass.version)+1;
+
+ *len += sizeof(struct clrclass_data);
+ *len += aligned_string_len(str_len*sizeof(WCHAR));
+
+ /* module name is forced to mscoree.dll, and stored two times with different case */
+ *module_len += sizeof(mscoreeW) + sizeof(mscoree2W);
+ }
+ else
+ {
+ /* progid string is stored separately */
+ if (entity->u.comclass.progid)
+ *len += aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
+
+ *module_len += (strlenW(dll->name)+1)*sizeof(WCHAR);
+ }
+
+ *count += 1;
+ }
+ }
+}
+
+static void add_comserver_record(const struct guidsection_header *section, const struct entity_array *entities,
+ const struct dll_redirect *dll, struct guid_index **index, ULONG *data_offset, ULONG *module_offset,
+ ULONG *seed, ULONG rosterindex)
+{
+ unsigned int i;
+
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+ {
+ ULONG module_len, progid_len, str_len = 0;
+ struct comclassredirect_data *data;
+ struct guid_index *alias_index;
+ struct clrclass_data *clrdata;
+ UNICODE_STRING str;
+ WCHAR *ptrW;
+
+ if (entity->u.comclass.progid)
+ progid_len = strlenW(entity->u.comclass.progid)*sizeof(WCHAR);
+ else
+ progid_len = 0;
+
+ module_len = dll ? strlenW(dll->name)*sizeof(WCHAR) : strlenW(mscoreeW)*sizeof(WCHAR);
+
+ /* setup new index entry */
+ RtlInitUnicodeString(&str, entity->u.comclass.clsid);
+ RtlGUIDFromString(&str, &(*index)->guid);
+
+ (*index)->data_offset = *data_offset;
+ (*index)->data_len = sizeof(*data); /* additional length added later */
+ (*index)->rosterindex = rosterindex;
+
+ /* Setup new index entry for alias guid. Alias index records are placed after
+ normal records, so normal guids are hit first on search. Note that class count
+ is doubled. */
+ alias_index = (*index) + section->count/2;
+ generate_uuid(seed, &alias_index->guid);
+ alias_index->data_offset = (*index)->data_offset;
+ alias_index->data_len = 0;
+ alias_index->rosterindex = (*index)->rosterindex;
+
+ /* setup data */
+ data = (struct comclassredirect_data*)((BYTE*)section + (*index)->data_offset);
+ data->size = sizeof(*data);
+ data->res = 0;
+ data->res1[0] = 0;
+ data->res1[1] = 0;
+ data->model = entity->u.comclass.model;
+ data->clsid = (*index)->guid;
+ data->alias = alias_index->guid;
+ data->clsid2 = data->clsid;
+ if (entity->u.comclass.tlbid)
+ {
+ RtlInitUnicodeString(&str, entity->u.comclass.tlbid);
+ RtlGUIDFromString(&str, &data->tlbid);
+ }
+ else
+ memset(&data->tlbid, 0, sizeof(data->tlbid));
+ data->name_len = module_len;
+ data->name_offset = *module_offset;
+ data->progid_len = progid_len;
+ data->progid_offset = data->progid_len ? data->size : 0; /* in case of clrClass additional offset is added later */
+ data->clrdata_len = 0; /* will be set later */
+ data->clrdata_offset = entity->u.comclass.name ? sizeof(*data) : 0;
+ data->miscstatus = entity->u.comclass.miscstatus;
+ data->miscstatuscontent = entity->u.comclass.miscstatuscontent;
+ data->miscstatusthumbnail = entity->u.comclass.miscstatusthumbnail;
+ data->miscstatusicon = entity->u.comclass.miscstatusicon;
+ data->miscstatusdocprint = entity->u.comclass.miscstatusdocprint;
+
+ /* mask describes which misc* data is available */
+ data->miscmask = 0;
+ if (data->miscstatus)
+ data->miscmask |= MiscStatus;
+ if (data->miscstatuscontent)
+ data->miscmask |= MiscStatusContent;
+ if (data->miscstatusthumbnail)
+ data->miscmask |= MiscStatusThumbnail;
+ if (data->miscstatusicon)
+ data->miscmask |= MiscStatusIcon;
+ if (data->miscstatusdocprint)
+ data->miscmask |= MiscStatusDocPrint;
+
+ if (data->clrdata_offset)
+ {
+ clrdata = (struct clrclass_data*)((BYTE*)data + data->clrdata_offset);
+
+ clrdata->size = sizeof(*clrdata);
+ clrdata->res[0] = 0;
+ clrdata->res[1] = 2; /* FIXME: unknown field */
+ clrdata->module_len = strlenW(mscoreeW)*sizeof(WCHAR);
+ clrdata->module_offset = *module_offset + data->name_len + sizeof(WCHAR);
+ clrdata->name_len = strlenW(entity->u.comclass.name)*sizeof(WCHAR);
+ clrdata->name_offset = clrdata->size;
+ clrdata->version_len = entity->u.comclass.version ? strlenW(entity->u.comclass.version)*sizeof(WCHAR) : 0;
+ clrdata->version_offset = clrdata->version_len ? clrdata->name_offset + clrdata->name_len + sizeof(WCHAR) : 0;
+ clrdata->res2[0] = 0;
+ clrdata->res2[1] = 0;
+
+ data->clrdata_len = clrdata->size + clrdata->name_len + sizeof(WCHAR);
+
+ /* module name */
+ ptrW = (WCHAR*)((BYTE*)section + clrdata->module_offset);
+ memcpy(ptrW, mscoree2W, clrdata->module_len);
+ ptrW[clrdata->module_len/sizeof(WCHAR)] = 0;
+
+ ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
+ memcpy(ptrW, mscoreeW, data->name_len);
+ ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+ /* class name */
+ ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->name_offset);
+ memcpy(ptrW, entity->u.comclass.name, clrdata->name_len);
+ ptrW[clrdata->name_len/sizeof(WCHAR)] = 0;
+
+ /* runtime version, optional */
+ if (clrdata->version_len)
+ {
+ data->clrdata_len += clrdata->version_len + sizeof(WCHAR);
+
+ ptrW = (WCHAR*)((BYTE*)clrdata + clrdata->version_offset);
+ memcpy(ptrW, entity->u.comclass.version, clrdata->version_len);
+ ptrW[clrdata->version_len/sizeof(WCHAR)] = 0;
+ }
+
+ if (data->progid_len)
+ data->progid_offset += data->clrdata_len;
+ (*index)->data_len += sizeof(*clrdata);
+ }
+ else
+ {
+ clrdata = NULL;
+
+ /* module name */
+ ptrW = (WCHAR*)((BYTE*)section + data->name_offset);
+ memcpy(ptrW, dll->name, data->name_len);
+ ptrW[data->name_len/sizeof(WCHAR)] = 0;
+ }
+
+ /* progid string */
+ if (data->progid_len)
+ {
+ ptrW = (WCHAR*)((BYTE*)data + data->progid_offset);
+ memcpy(ptrW, entity->u.comclass.progid, data->progid_len);
+ ptrW[data->progid_len/sizeof(WCHAR)] = 0;
+ }
+
+ /* string block length */
+ str_len = 0;
+ if (clrdata)
+ {
+ str_len += clrdata->name_len + sizeof(WCHAR);
+ if (clrdata->version_len)
+ str_len += clrdata->version_len + sizeof(WCHAR);
+ }
+ if (progid_len)
+ str_len += progid_len + sizeof(WCHAR);
+
+ (*index)->data_len += aligned_string_len(str_len);
+ alias_index->data_len = (*index)->data_len;
+
+ /* move to next data record */
+ (*data_offset) += sizeof(*data) + aligned_string_len(str_len);
+ (*module_offset) += module_len + sizeof(WCHAR);
+
+ if (clrdata)
+ {
+ (*data_offset) += sizeof(*clrdata);
+ (*module_offset) += clrdata->module_len + sizeof(WCHAR);
+ }
+ (*index) += 1;
+ }
+ }
+}
+
+static NTSTATUS build_comserver_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+ unsigned int i, j, total_len = 0, class_count = 0, names_len = 0;
+ struct guidsection_header *header;
+ ULONG module_offset, data_offset;
+ struct guid_index *index;
+ ULONG seed;
+
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ get_comserver_datalen(&assembly->entities, NULL, &class_count, &total_len, &names_len);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ get_comserver_datalen(&dll->entities, dll, &class_count, &total_len, &names_len);
+ }
+ }
+
+ total_len += aligned_string_len(names_len);
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = GUIDSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = 2*class_count;
+ header->index_offset = sizeof(*header) + aligned_string_len(names_len);
+ index = (struct guid_index*)((BYTE*)header + header->index_offset);
+ module_offset = sizeof(*header);
+ data_offset = header->index_offset + 2*class_count*sizeof(*index);
+
+ seed = NtGetTickCount();
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ add_comserver_record(header, &assembly->entities, NULL, &index, &data_offset, &module_offset, &seed, i+1);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ add_comserver_record(header, &dll->entities, dll, &index, &data_offset, &module_offset, &seed, i+1);
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static inline struct comclassredirect_data *get_comclass_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+ return (struct comclassredirect_data*)((BYTE*)actctx->comserver_section + index->data_offset);
+}
+
+static NTSTATUS find_comserver_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+ struct comclassredirect_data *comclass;
+ struct guid_index *index = NULL;
+
+ if (!(actctx->sections & SERVERREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->comserver_section)
+ {
+ struct guidsection_header *section;
+
+ NTSTATUS status = build_comserver_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_guid_index(actctx->comserver_section, guid);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ comclass = get_comclass_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = comclass;
+ /* full length includes string length with nulls */
+ data->ulLength = comclass->size + comclass->clrdata_len;
+ if (comclass->progid_len) data->ulLength += comclass->progid_len + sizeof(WCHAR);
+ data->lpSectionGlobalData = (BYTE*)actctx->comserver_section + actctx->comserver_section->names_offset;
+ data->ulSectionGlobalDataLength = actctx->comserver_section->names_len;
+ data->lpSectionBase = actctx->comserver_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->comserver_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
+ return STATUS_SUCCESS;
+}
+
+static void get_ifaceps_datalen(const struct entity_array *entities, unsigned int *count, unsigned int *len)
+{
+ unsigned int i;
+
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
+ {
+ *len += sizeof(struct guid_index) + sizeof(struct ifacepsredirect_data);
+ if (entity->u.ifaceps.name)
+ *len += aligned_string_len((strlenW(entity->u.ifaceps.name)+1)*sizeof(WCHAR));
+ *count += 1;
+ }
+ }
+}
+
+static void add_ifaceps_record(struct guidsection_header *section, struct entity_array *entities,
+ struct guid_index **index, ULONG *data_offset, ULONG rosterindex)
+{
+ unsigned int i;
+
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)
+ {
+ struct ifacepsredirect_data *data = (struct ifacepsredirect_data*)((BYTE*)section + *data_offset);
+ UNICODE_STRING str;
+ ULONG name_len;
+
+ if (entity->u.ifaceps.name)
+ name_len = strlenW(entity->u.ifaceps.name)*sizeof(WCHAR);
+ else
+ name_len = 0;
+
+ /* setup index */
+ RtlInitUnicodeString(&str, entity->u.ifaceps.iid);
+ RtlGUIDFromString(&str, &(*index)->guid);
+ (*index)->data_offset = *data_offset;
+ (*index)->data_len = sizeof(*data) + name_len ? aligned_string_len(name_len + sizeof(WCHAR)) : 0;
+ (*index)->rosterindex = rosterindex;
+
+ /* setup data record */
+ data->size = sizeof(*data);
+ data->mask = entity->u.ifaceps.mask;
+
+ /* proxyStubClsid32 value is only stored for external PS,
+ if set it's used as iid, otherwise 'iid' attribute value is used */
+ if (entity->u.ifaceps.ps32)
+ {
+ RtlInitUnicodeString(&str, entity->u.ifaceps.ps32);
+ RtlGUIDFromString(&str, &data->iid);
+ }
+ else
+ data->iid = (*index)->guid;
+
+ data->nummethods = entity->u.ifaceps.nummethods;
+
+ if (entity->u.ifaceps.tlib)
+ {
+ RtlInitUnicodeString(&str, entity->u.ifaceps.tlib);
+ RtlGUIDFromString(&str, &data->tlbid);
+ }
+ else
+ memset(&data->tlbid, 0, sizeof(data->tlbid));
+
+ if (entity->u.ifaceps.base)
+ {
+ RtlInitUnicodeString(&str, entity->u.ifaceps.base);
+ RtlGUIDFromString(&str, &data->base);
+ }
+ else
+ memset(&data->base, 0, sizeof(data->base));
+
+ data->name_len = name_len;
+ data->name_offset = data->name_len ? sizeof(*data) : 0;
+
+ /* name string */
+ if (data->name_len)
+ {
+ WCHAR *ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+ memcpy(ptrW, entity->u.ifaceps.name, data->name_len);
+ ptrW[data->name_len/sizeof(WCHAR)] = 0;
+ }
+
+ /* move to next record */
+ (*index) += 1;
+ *data_offset += sizeof(*data);
+ if (data->name_len)
+ *data_offset += aligned_string_len(data->name_len + sizeof(WCHAR));
+ }
+ }
+}
+
+static NTSTATUS build_ifaceps_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+ unsigned int i, j, total_len = 0, count = 0;
+ struct guidsection_header *header;
+ struct guid_index *index;
+ ULONG data_offset;
+
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+
+ get_ifaceps_datalen(&assembly->entities, &count, &total_len);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ get_ifaceps_datalen(&dll->entities, &count, &total_len);
+ }
+ }
+
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = GUIDSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = count;
+ header->index_offset = sizeof(*header);
+ index = (struct guid_index*)((BYTE*)header + header->index_offset);
+ data_offset = header->index_offset + count*sizeof(*index);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+
+ add_ifaceps_record(header, &assembly->entities, &index, &data_offset, i + 1);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ add_ifaceps_record(header, &dll->entities, &index, &data_offset, i + 1);
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static inline struct ifacepsredirect_data *get_ifaceps_data(ACTIVATION_CONTEXT *actctx, struct guid_index *index)
+{
+ return (struct ifacepsredirect_data*)((BYTE*)actctx->ifaceps_section + index->data_offset);
+}
+
+static NTSTATUS find_cominterface_redirection(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+ struct ifacepsredirect_data *iface;
+ struct guid_index *index = NULL;
+
+ if (!(actctx->sections & IFACEREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->ifaceps_section)
+ {
+ struct guidsection_header *section;
+
+ NTSTATUS status = build_ifaceps_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->ifaceps_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_guid_index(actctx->ifaceps_section, guid);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ iface = get_ifaceps_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = iface;
+ data->ulLength = iface->size + (iface->name_len ? iface->name_len + sizeof(WCHAR) : 0);
+ data->lpSectionGlobalData = NULL;
+ data->ulSectionGlobalDataLength = 0;
+ data->lpSectionBase = actctx->ifaceps_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->ifaceps_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS build_clr_surrogate_section(ACTIVATION_CONTEXT* actctx, struct guidsection_header **section)
+{
+ unsigned int i, j, total_len = 0, count = 0;
+ struct guidsection_header *header;
+ struct clrsurrogate_data *data;
+ struct guid_index *index;
+ ULONG data_offset;
+
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->entities.num; j++)
+ {
+ struct entity *entity = &assembly->entities.base[j];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
+ {
+ ULONG len;
+
+ total_len += sizeof(*index) + sizeof(*data);
+ len = strlenW(entity->u.clrsurrogate.name) + 1;
+ if (entity->u.clrsurrogate.version)
+ len += strlenW(entity->u.clrsurrogate.version) + 1;
+ total_len += aligned_string_len(len*sizeof(WCHAR));
+
+ count++;
+ }
+ }
+ }
+
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = GUIDSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = count;
+ header->index_offset = sizeof(*header);
+ index = (struct guid_index*)((BYTE*)header + header->index_offset);
+ data_offset = header->index_offset + count*sizeof(*index);
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+ for (j = 0; j < assembly->entities.num; j++)
+ {
+ struct entity *entity = &assembly->entities.base[j];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES)
+ {
+ ULONG version_len, name_len;
+ UNICODE_STRING str;
+ WCHAR *ptrW;
+
+ if (entity->u.clrsurrogate.version)
+ version_len = strlenW(entity->u.clrsurrogate.version)*sizeof(WCHAR);
+ else
+ version_len = 0;
+ name_len = strlenW(entity->u.clrsurrogate.name)*sizeof(WCHAR);
+
+ /* setup new index entry */
+ RtlInitUnicodeString(&str, entity->u.clrsurrogate.clsid);
+ RtlGUIDFromString(&str, &index->guid);
+
+ index->data_offset = data_offset;
+ index->data_len = sizeof(*data) + aligned_string_len(name_len + sizeof(WCHAR) + (version_len ? version_len + sizeof(WCHAR) : 0));
+ index->rosterindex = i + 1;
+
+ /* setup data */
+ data = (struct clrsurrogate_data*)((BYTE*)header + index->data_offset);
+ data->size = sizeof(*data);
+ data->res = 0;
+ data->clsid = index->guid;
+ data->version_offset = version_len ? data->size : 0;
+ data->version_len = version_len;
+ data->name_offset = data->size + version_len;
+ if (version_len)
+ data->name_offset += sizeof(WCHAR);
+ data->name_len = name_len;
+
+ /* surrogate name */
+ ptrW = (WCHAR*)((BYTE*)data + data->name_offset);
+ memcpy(ptrW, entity->u.clrsurrogate.name, data->name_len);
+ ptrW[data->name_len/sizeof(WCHAR)] = 0;
+
+ /* runtime version */
+ if (data->version_len)
+ {
+ ptrW = (WCHAR*)((BYTE*)data + data->version_offset);
+ memcpy(ptrW, entity->u.clrsurrogate.version, data->version_len);
+ ptrW[data->version_len/sizeof(WCHAR)] = 0;
+ }
+
+ data_offset += index->data_offset;
+ index++;
+ }
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static inline struct clrsurrogate_data *get_surrogate_data(ACTIVATION_CONTEXT *actctx, const struct guid_index *index)
+{
+ return (struct clrsurrogate_data*)((BYTE*)actctx->clrsurrogate_section + index->data_offset);
+}
+
+static NTSTATUS find_clr_surrogate(ACTIVATION_CONTEXT* actctx, const GUID *guid, ACTCTX_SECTION_KEYED_DATA* data)
+{
+ struct clrsurrogate_data *surrogate;
+ struct guid_index *index = NULL;
+
+ if (!(actctx->sections & CLRSURROGATES_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->clrsurrogate_section)
+ {
+ struct guidsection_header *section;
+
+ NTSTATUS status = build_clr_surrogate_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->clrsurrogate_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_guid_index(actctx->clrsurrogate_section, guid);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ surrogate = get_surrogate_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = surrogate;
+ /* full length includes string length with nulls */
+ data->ulLength = surrogate->size + surrogate->name_len + sizeof(WCHAR);
+ if (surrogate->version_len)
+ data->ulLength += surrogate->version_len + sizeof(WCHAR);
+
+ data->lpSectionGlobalData = NULL;
+ data->ulSectionGlobalDataLength = 0;
+ data->lpSectionBase = actctx->clrsurrogate_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->clrsurrogate_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
+ return STATUS_SUCCESS;
+}
+
+static void get_progid_datalen(struct entity_array *entities, unsigned int *count, unsigned int *total_len)
+{
+ unsigned int i, j, single_len;
+
+ single_len = sizeof(struct progidredirect_data) + sizeof(struct string_index) + sizeof(GUID);
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+ {
+ if (entity->u.comclass.progid)
+ {
+ *total_len += single_len + aligned_string_len((strlenW(entity->u.comclass.progid)+1)*sizeof(WCHAR));
+ *count += 1;
+ }
+
+ for (j = 0; j < entity->u.comclass.progids.num; j++)
+ *total_len += aligned_string_len((strlenW(entity->u.comclass.progids.progids[j])+1)*sizeof(WCHAR));
+
+ *total_len += single_len*entity->u.comclass.progids.num;
+ *count += entity->u.comclass.progids.num;
+ }
+ }
+}
+
+static void write_progid_record(struct strsection_header *section, const WCHAR *progid, const GUID *alias,
+ struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
+{
+ struct progidredirect_data *data;
+ UNICODE_STRING str;
+ GUID *guid_ptr;
+ WCHAR *ptrW;
+
+ /* setup new index entry */
+
+ /* hash progid name */
+ RtlInitUnicodeString(&str, progid);
+ RtlHashUnicodeString(&str, TRUE, HASH_STRING_ALGORITHM_X65599, &(*index)->hash);
+
+ (*index)->name_offset = *data_offset;
+ (*index)->name_len = str.Length;
+ (*index)->data_offset = (*index)->name_offset + aligned_string_len(str.MaximumLength);
+ (*index)->data_len = sizeof(*data);
+ (*index)->rosterindex = rosterindex;
+
+ *data_offset += aligned_string_len(str.MaximumLength);
+
+ /* setup data structure */
+ data = (struct progidredirect_data*)((BYTE*)section + *data_offset);
+ data->size = sizeof(*data);
+ data->reserved = 0;
+ data->clsid_offset = *global_offset;
+
+ /* write progid string */
+ ptrW = (WCHAR*)((BYTE*)section + (*index)->name_offset);
+ memcpy(ptrW, progid, (*index)->name_len);
+ ptrW[(*index)->name_len/sizeof(WCHAR)] = 0;
+
+ /* write guid to global area */
+ guid_ptr = (GUID*)((BYTE*)section + data->clsid_offset);
+ *guid_ptr = *alias;
+
+ /* to next entry */
+ *global_offset += sizeof(GUID);
+ *data_offset += data->size;
+ (*index) += 1;
+}
+
+static void add_progid_record(ACTIVATION_CONTEXT* actctx, struct strsection_header *section, const struct entity_array *entities,
+ struct string_index **index, ULONG *data_offset, ULONG *global_offset, ULONG rosterindex)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < entities->num; i++)
+ {
+ struct entity *entity = &entities->base[i];
+ if (entity->kind == ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)
+ {
+ const struct progids *progids = &entity->u.comclass.progids;
+ struct comclassredirect_data *comclass;
+ struct guid_index *guid_index;
+ UNICODE_STRING str;
+ GUID clsid;
+
+ RtlInitUnicodeString(&str, entity->u.comclass.clsid);
+ RtlGUIDFromString(&str, &clsid);
+
+ guid_index = find_guid_index(actctx->comserver_section, &clsid);
+ comclass = get_comclass_data(actctx, guid_index);
+
+ if (entity->u.comclass.progid)
+ write_progid_record(section, entity->u.comclass.progid, &comclass->alias,
+ index, data_offset, global_offset, rosterindex);
+
+ for (j = 0; j < progids->num; j++)
+ write_progid_record(section, progids->progids[j], &comclass->alias,
+ index, data_offset, global_offset, rosterindex);
+ }
+ }
+}
+
+static NTSTATUS build_progid_section(ACTIVATION_CONTEXT* actctx, struct strsection_header **section)
+{
+ unsigned int i, j, total_len = 0, count = 0;
+ struct strsection_header *header;
+ ULONG data_offset, global_offset;
+ struct string_index *index;
+
+ /* compute section length */
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+
+ get_progid_datalen(&assembly->entities, &count, &total_len);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ get_progid_datalen(&dll->entities, &count, &total_len);
+ }
+ }
+
+ total_len += sizeof(*header);
+
+ header = RtlAllocateHeap(RtlGetProcessHeap(), 0, total_len);
+ if (!header) return STATUS_NO_MEMORY;
+
+ memset(header, 0, sizeof(*header));
+ header->magic = STRSECTION_MAGIC;
+ header->size = sizeof(*header);
+ header->count = count;
+ header->global_offset = header->size;
+ header->global_len = count*sizeof(GUID);
+ header->index_offset = header->size + header->global_len;
+
+ index = (struct string_index*)((BYTE*)header + header->index_offset);
+ data_offset = header->index_offset + count*sizeof(*index);
+ global_offset = header->global_offset;
+
+ for (i = 0; i < actctx->num_assemblies; i++)
+ {
+ struct assembly *assembly = &actctx->assemblies[i];
+
+ add_progid_record(actctx, header, &assembly->entities, &index, &data_offset, &global_offset, i + 1);
+ for (j = 0; j < assembly->num_dlls; j++)
+ {
+ struct dll_redirect *dll = &assembly->dlls[j];
+ add_progid_record(actctx, header, &dll->entities, &index, &data_offset, &global_offset, i + 1);
+ }
+ }
+
+ *section = header;
+
+ return STATUS_SUCCESS;
+}
+
+static inline struct progidredirect_data *get_progid_data(ACTIVATION_CONTEXT *actctx, const struct string_index *index)
+{
+ return (struct progidredirect_data*)((BYTE*)actctx->progid_section + index->data_offset);
+}
+
+static NTSTATUS find_progid_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *name,
+ PACTCTX_SECTION_KEYED_DATA data)
+{
+ struct progidredirect_data *progid;
+ struct string_index *index;
+
+ if (!(actctx->sections & PROGIDREDIRECT_SECTION)) return STATUS_SXS_KEY_NOT_FOUND;
+
+ if (!actctx->comserver_section)
+ {
+ struct guidsection_header *section;
+
+ NTSTATUS status = build_comserver_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->comserver_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ if (!actctx->progid_section)
+ {
+ struct strsection_header *section;
+
+ NTSTATUS status = build_progid_section(actctx, §ion);
+ if (status) return status;
+
+ if (InterlockedCompareExchangePointer((void**)&actctx->progid_section, section, NULL))
+ RtlFreeHeap(RtlGetProcessHeap(), 0, section);
+ }
+
+ index = find_string_index(actctx->progid_section, name);
+ if (!index) return STATUS_SXS_KEY_NOT_FOUND;
+
+ progid = get_progid_data(actctx, index);
+
+ data->ulDataFormatVersion = 1;
+ data->lpData = progid;
+ data->ulLength = progid->size;
+ data->lpSectionGlobalData = (BYTE*)actctx->progid_section + actctx->progid_section->global_offset;
+ data->ulSectionGlobalDataLength = actctx->progid_section->global_len;
+ data->lpSectionBase = actctx->progid_section;
+ data->ulSectionTotalLength = RtlSizeHeap( RtlGetProcessHeap(), 0, actctx->progid_section );
+ data->hActCtx = NULL;
+
+ if (data->cbSize >= FIELD_OFFSET(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
+ data->ulAssemblyRosterIndex = index->rosterindex;
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+ const UNICODE_STRING *section_name,
+ DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+ NTSTATUS status;
+
+ switch (section_kind)
+ {
+ case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
+ status = find_dll_redirection(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
+ status = find_window_class(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
+ status = find_progid_redirection(actctx, section_name, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
+ DPRINT1("Unsupported yet section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ default:
+ DPRINT1("Unknown section_kind %x\n", section_kind);
+ return STATUS_SXS_SECTION_NOT_FOUND;
+ }
+
+ if (status != STATUS_SUCCESS) return status;
+
+ if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
+ {
+ actctx_addref(actctx);
+ data->hActCtx = actctx;
+ }
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS find_guid(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
+ const GUID *guid, DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
+{
+ NTSTATUS status;
+
+ switch (section_kind)
+ {
+ case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
+ status = find_tlib_redirection(actctx, guid, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
+ status = find_comserver_redirection(actctx, guid, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
+ status = find_cominterface_redirection(actctx, guid, data);
+ break;
+ case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
+ status = find_clr_surrogate(actctx, guid, data);
+ break;
default:
DPRINT("Unknown section_kind %x\n", section_kind);
return STATUS_SXS_SECTION_NOT_FOUND;
NTSTATUS
NTAPI
RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
- UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
+ const UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
{
/* Check general parameter combinations */
- if (!section_name ||
+ if (!section_name || !section_name->Buffer ||
(flags & ~FIND_ACTCTX_VALID_MASK) ||
((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
(data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
NTSTATUS
NTAPI
RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
- UNICODE_STRING *section_name, PVOID ptr )
+ const UNICODE_STRING *section_name, PVOID ptr )
{
PACTCTX_SECTION_KEYED_DATA data = ptr;
NTSTATUS status;