ntdll: Store all 'comClass' attributes.

This commit is contained in:
Nikolay Sivov 2013-08-29 09:49:40 +04:00 committed by Alexandre Julliard
parent 1992f5005c
commit 52fc0e4e29
2 changed files with 272 additions and 29 deletions

View file

@ -101,6 +101,11 @@ static const char manifest3[] =
" tlbid=\"{99999999-8888-7777-6666-555555555555}\""
" threadingModel=\"Neutral\""
" progid=\"ProgId.ProgId\""
" miscStatus=\"cantlinkinside\""
" miscStatusIcon=\"recomposeonresize\""
" miscStatusContent=\"insideout\""
" miscStatusThumbnail=\"alignable\""
" miscStatusDocPrint=\"simpleframe,setclientsitefirst\""
" />"
"</file>"
"</assembly>";
@ -1075,38 +1080,44 @@ static void test_basic_info(HANDLE handle, int line)
enum comclass_threadingmodel {
ThreadingModel_Apartment = 1,
ThreadingModel_Free = 2,
ThreadingModel_No = 3,
ThreadingModel_Both = 4,
ThreadingModel_Neutral = 5
};
enum comclass_miscfields {
MiscStatus = 0x1,
MiscStatusIcon = 0x2,
MiscStatusContent = 0x4,
MiscStatusThumbnail = 0x8
MiscStatus = 1,
MiscStatusIcon = 2,
MiscStatusContent = 4,
MiscStatusThumbnail = 8,
MiscStatusDocPrint = 16
};
struct comclass_keyed_data {
DWORD size;
BYTE reserved;
BYTE miscmask;
BYTE unk[2];
struct comclassredirect_data {
ULONG size;
BYTE res;
BYTE miscmask;
BYTE res1[2];
DWORD model;
GUID clsid;
GUID unkguid;
GUID clsid2;
GUID tlid;
DWORD modulename_len;
DWORD modulename_offset;
DWORD progid_len;
DWORD progid_offset;
DWORD res2[7];
WCHAR strdata[1];
GUID clsid;
GUID alias;
GUID clsid2;
GUID tlid;
ULONG name_len;
ULONG name_offset;
ULONG progid_len;
ULONG progid_offset;
DWORD res2[2];
DWORD miscstatus;
DWORD miscstatuscontent;
DWORD miscstatusthumbnail;
DWORD miscstatusicon;
DWORD miscstatusdocprint;
};
static void test_find_com_redirection(HANDLE handle, const GUID *clsid, const GUID *tlid, ULONG exid, int line)
{
struct comclass_keyed_data *comclass;
struct comclassredirect_data *comclass;
ACTCTX_SECTION_KEYED_DATA data;
BOOL ret;
@ -1124,27 +1135,26 @@ todo_wine
return;
}
comclass = (struct comclass_keyed_data*)data.lpData;
comclass = (struct comclassredirect_data*)data.lpData;
ok_(__FILE__, line)(data.cbSize == sizeof(data), "data.cbSize=%u\n", data.cbSize);
ok_(__FILE__, line)(data.ulDataFormatVersion == 1, "data.ulDataFormatVersion=%u\n", data.ulDataFormatVersion);
ok_(__FILE__, line)(data.lpData != NULL, "data.lpData == NULL\n");
ok_(__FILE__, line)(comclass->size == FIELD_OFFSET(struct comclass_keyed_data, strdata), "got %d for header size\n", comclass->size);
if (data.lpData && comclass->size == FIELD_OFFSET(struct comclass_keyed_data, strdata))
ok_(__FILE__, line)(comclass->size == sizeof(*comclass), "got %d for header size\n", comclass->size);
if (data.lpData && comclass->size == sizeof(*comclass))
{
static const WCHAR progid[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
WCHAR *ptr;
ULONG len;
ok_(__FILE__, line)(comclass->reserved == 0, "got reserved as %d\n", comclass->reserved);
ok_(__FILE__, line)(comclass->miscmask == 0, "got miscmask as %02x\n", comclass->miscmask);
ok_(__FILE__, line)(comclass->unk[0] == 0, "got unk[0] as %02x\n", comclass->unk[0]);
ok_(__FILE__, line)(comclass->unk[1] == 0, "got unk[1] as %02x\n", comclass->unk[1]);
ok_(__FILE__, line)(comclass->res == 0, "got res as %d\n", comclass->res);
ok_(__FILE__, line)(comclass->res1[0] == 0, "got res1[0] as %02x\n", comclass->res1[0]);
ok_(__FILE__, line)(comclass->res1[1] == 0, "got res1[1] as %02x\n", comclass->res1[1]);
ok_(__FILE__, line)(comclass->model == ThreadingModel_Neutral, "got model %d\n", comclass->model);
ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid, clsid), "got wrong clsid %s\n", debugstr_guid(&comclass->clsid));
ok_(__FILE__, line)(IsEqualGUID(&comclass->clsid2, clsid), "got wrong clsid2 %s\n", debugstr_guid(&comclass->clsid2));
ok_(__FILE__, line)(IsEqualGUID(&comclass->tlid, tlid), "got wrong tlid %s\n", debugstr_guid(&comclass->tlid));
ok_(__FILE__, line)(comclass->modulename_len > 0, "got modulename len %d\n", comclass->modulename_len);
ok_(__FILE__, line)(comclass->name_len > 0, "got modulename len %d\n", comclass->name_len);
ok_(__FILE__, line)(comclass->progid_offset == comclass->size, "got progid offset %d\n", comclass->progid_offset);
ptr = (WCHAR*)((BYTE*)comclass + comclass->size);
@ -1157,7 +1167,22 @@ todo_wine
ok_(__FILE__, line)(data.ulLength == len, "got wrong data length %d, expected %d\n", data.ulLength, len);
/* keyed data structure doesn't include module name, it's available from section data */
ok_(__FILE__, line)(data.ulSectionTotalLength > comclass->modulename_offset, "got wrong offset %d\n", comclass->modulename_offset);
ok_(__FILE__, line)(data.ulSectionTotalLength > comclass->name_offset, "got wrong offset %d\n", comclass->name_offset);
/* check misc fields are set */
if (comclass->miscmask)
{
if (comclass->miscmask & MiscStatus)
ok_(__FILE__, line)(comclass->miscstatus != 0, "got miscstatus 0x%08x\n", comclass->miscstatus);
if (comclass->miscmask & MiscStatusIcon)
ok_(__FILE__, line)(comclass->miscstatusicon != 0, "got miscstatusicon 0x%08x\n", comclass->miscstatusicon);
if (comclass->miscmask & MiscStatusContent)
ok_(__FILE__, line)(comclass->miscstatuscontent != 0, "got miscstatuscontent 0x%08x\n", comclass->miscstatuscontent);
if (comclass->miscmask & MiscStatusThumbnail)
ok_(__FILE__, line)(comclass->miscstatusthumbnail != 0, "got miscstatusthumbnail 0x%08x\n", comclass->miscstatusthumbnail);
if (comclass->miscmask & MiscStatusDocPrint)
ok_(__FILE__, line)(comclass->miscstatusdocprint != 0, "got miscstatusdocprint 0x%08x\n", comclass->miscstatusdocprint);
}
}
ok_(__FILE__, line)(data.lpSectionGlobalData != NULL, "data.lpSectionGlobalData == NULL\n");

View file

@ -66,6 +66,33 @@ typedef enum tagLIBFLAGS {
LIBFLAG_FHASDISKIMAGE = 0x8
} LIBFLAGS;
/* from oleidl.idl */
typedef enum tagOLEMISC
{
OLEMISC_RECOMPOSEONRESIZE = 0x1,
OLEMISC_ONLYICONIC = 0x2,
OLEMISC_INSERTNOTREPLACE = 0x4,
OLEMISC_STATIC = 0x8,
OLEMISC_CANTLINKINSIDE = 0x10,
OLEMISC_CANLINKBYOLE1 = 0x20,
OLEMISC_ISLINKOBJECT = 0x40,
OLEMISC_INSIDEOUT = 0x80,
OLEMISC_ACTIVATEWHENVISIBLE = 0x100,
OLEMISC_RENDERINGISDEVICEINDEPENDENT = 0x200,
OLEMISC_INVISIBLEATRUNTIME = 0x400,
OLEMISC_ALWAYSRUN = 0x800,
OLEMISC_ACTSLIKEBUTTON = 0x1000,
OLEMISC_ACTSLIKELABEL = 0x2000,
OLEMISC_NOUIACTIVATE = 0x4000,
OLEMISC_ALIGNABLE = 0x8000,
OLEMISC_SIMPLEFRAME = 0x10000,
OLEMISC_SETCLIENTSITEFIRST = 0x20000,
OLEMISC_IMEMODE = 0x40000,
OLEMISC_IGNOREACTIVATEWHENVISIBLE = 0x80000,
OLEMISC_WANTSTOMENUMERGE = 0x100000,
OLEMISC_SUPPORTSMULTILEVELUNDO = 0x200000
} OLEMISC;
typedef struct
{
const WCHAR *ptr;
@ -174,6 +201,24 @@ struct tlibredirect_data
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
};
/*
Sections structure.
@ -245,6 +290,14 @@ struct entity
struct
{
WCHAR *clsid;
WCHAR *tlbid;
WCHAR *progid;
DWORD model;
DWORD miscstatus;
DWORD miscstatuscontent;
DWORD miscstatusthumbnail;
DWORD miscstatusicon;
DWORD miscstatusdocprint;
} comclass;
struct {
WCHAR *iid;
@ -365,7 +418,9 @@ static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',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};
@ -378,6 +433,66 @@ 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 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 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};
@ -563,6 +678,8 @@ static void free_entity_array(struct entity_array *array)
{
case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.clsid);
RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.tlbid);
RtlFreeHeap(GetProcessHeap(), 0, entity->u.comclass.progid);
break;
case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
RtlFreeHeap(GetProcessHeap(), 0, entity->u.proxy.iid);
@ -1074,6 +1191,75 @@ static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* a
return parse_expect_end_elem(xmlbuf, assemblyIdentityW, asmv1W);
}
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;
}
WARN("unknown flag %s\n", debugstr_wn(str, len));
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 parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
{
xmlstr_t elem, attr_name, attr_value;
@ -1089,6 +1275,38 @@ static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
{
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
{
WARN("unknown attr %s=%s\n", debugstr_xmlstr(&attr_name), debugstr_xmlstr(&attr_value));