ole32: Store categories with offset so it's possible to copy them directly.
This commit is contained in:
parent
4de8d4b0ba
commit
aeb35b20ec
@ -54,9 +54,11 @@ static ComCatMgrImpl COMCAT_ComCatMgr =
|
|||||||
{ &COMCAT_ICatInformation_Vtbl }
|
{ &COMCAT_ICatInformation_Vtbl }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct class_categories {
|
struct class_categories
|
||||||
LPCWSTR impl_strings;
|
{
|
||||||
LPCWSTR req_strings;
|
ULONG size; /* total length, including structure itself */
|
||||||
|
ULONG impl_offset;
|
||||||
|
ULONG req_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
static IEnumCATEGORYINFO *COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid);
|
static IEnumCATEGORYINFO *COMCAT_IEnumCATEGORYINFO_Construct(LCID lcid);
|
||||||
@ -195,22 +197,23 @@ static struct class_categories *COMCAT_PrepareClassCategories(
|
|||||||
{
|
{
|
||||||
struct class_categories *categories;
|
struct class_categories *categories;
|
||||||
WCHAR *strings;
|
WCHAR *strings;
|
||||||
|
ULONG size;
|
||||||
|
|
||||||
categories = HeapAlloc(
|
size = sizeof(struct class_categories) + ((impl_count + req_count)*CHARS_IN_GUID + 2)*sizeof(WCHAR);
|
||||||
GetProcessHeap(), HEAP_ZERO_MEMORY,
|
categories = HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
sizeof(struct class_categories) +
|
|
||||||
((impl_count + req_count) * CHARS_IN_GUID + 2) * sizeof(WCHAR));
|
|
||||||
if (categories == NULL) return categories;
|
if (categories == NULL) return categories;
|
||||||
|
|
||||||
|
categories->size = size;
|
||||||
|
categories->impl_offset = sizeof(struct class_categories);
|
||||||
|
categories->req_offset = categories->impl_offset + (impl_count*CHARS_IN_GUID + 1)*sizeof(WCHAR);
|
||||||
|
|
||||||
strings = (WCHAR *)(categories + 1);
|
strings = (WCHAR *)(categories + 1);
|
||||||
categories->impl_strings = strings;
|
|
||||||
while (impl_count--) {
|
while (impl_count--) {
|
||||||
StringFromGUID2(impl_catids++, strings, CHARS_IN_GUID);
|
StringFromGUID2(impl_catids++, strings, CHARS_IN_GUID);
|
||||||
strings += CHARS_IN_GUID;
|
strings += CHARS_IN_GUID;
|
||||||
}
|
}
|
||||||
*strings++ = 0;
|
*strings++ = 0;
|
||||||
|
|
||||||
categories->req_strings = strings;
|
|
||||||
while (req_count--) {
|
while (req_count--) {
|
||||||
StringFromGUID2(req_catids++, strings, CHARS_IN_GUID);
|
StringFromGUID2(req_catids++, strings, CHARS_IN_GUID);
|
||||||
strings += CHARS_IN_GUID;
|
strings += CHARS_IN_GUID;
|
||||||
@ -227,16 +230,20 @@ static HRESULT COMCAT_IsClassOfCategories(
|
|||||||
HKEY key,
|
HKEY key,
|
||||||
struct class_categories const* categories)
|
struct class_categories const* categories)
|
||||||
{
|
{
|
||||||
|
const WCHAR *impl_strings, *req_strings;
|
||||||
HKEY subkey;
|
HKEY subkey;
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
DWORD index;
|
DWORD index;
|
||||||
LPCWSTR string;
|
LPCWSTR string;
|
||||||
|
|
||||||
|
impl_strings = (WCHAR*)((BYTE*)categories + categories->impl_offset);
|
||||||
|
req_strings = (WCHAR*)((BYTE*)categories + categories->req_offset);
|
||||||
|
|
||||||
/* Check that every given category is implemented by class. */
|
/* Check that every given category is implemented by class. */
|
||||||
if (*categories->impl_strings) {
|
if (*impl_strings) {
|
||||||
res = open_classes_key(key, impl_keyname, KEY_READ, &subkey);
|
res = open_classes_key(key, impl_keyname, KEY_READ, &subkey);
|
||||||
if (res != ERROR_SUCCESS) return S_FALSE;
|
if (res != ERROR_SUCCESS) return S_FALSE;
|
||||||
for (string = categories->impl_strings; *string; string += CHARS_IN_GUID) {
|
for (string = impl_strings; *string; string += CHARS_IN_GUID) {
|
||||||
HKEY catkey;
|
HKEY catkey;
|
||||||
res = open_classes_key(subkey, string, 0, &catkey);
|
res = open_classes_key(subkey, string, 0, &catkey);
|
||||||
if (res != ERROR_SUCCESS) {
|
if (res != ERROR_SUCCESS) {
|
||||||
@ -259,7 +266,7 @@ static HRESULT COMCAT_IsClassOfCategories(
|
|||||||
NULL, NULL, NULL, NULL);
|
NULL, NULL, NULL, NULL);
|
||||||
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
|
if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
|
||||||
if (size != CHARS_IN_GUID-1) continue; /* bogus catid in registry */
|
if (size != CHARS_IN_GUID-1) continue; /* bogus catid in registry */
|
||||||
for (string = categories->req_strings; *string; string += CHARS_IN_GUID)
|
for (string = req_strings; *string; string += CHARS_IN_GUID)
|
||||||
if (!strcmpiW(string, keyname)) break;
|
if (!strcmpiW(string, keyname)) break;
|
||||||
if (!*string) {
|
if (!*string) {
|
||||||
RegCloseKey(subkey);
|
RegCloseKey(subkey);
|
||||||
@ -1115,33 +1122,34 @@ static HRESULT WINAPI CLSIDEnumGUID_Clone(
|
|||||||
IEnumGUID *iface,
|
IEnumGUID *iface,
|
||||||
IEnumGUID **ppenum)
|
IEnumGUID **ppenum)
|
||||||
{
|
{
|
||||||
|
static const WCHAR keynameW[] = {'C','L','S','I','D',0};
|
||||||
CLSID_IEnumGUIDImpl *This = impl_from_IEnumCLSID(iface);
|
CLSID_IEnumGUIDImpl *This = impl_from_IEnumCLSID(iface);
|
||||||
static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 };
|
CLSID_IEnumGUIDImpl *cloned;
|
||||||
CLSID_IEnumGUIDImpl *new_this;
|
|
||||||
DWORD size;
|
|
||||||
|
|
||||||
TRACE("\n");
|
TRACE("(%p)->(%p)\n", This, ppenum);
|
||||||
|
|
||||||
if (ppenum == NULL) return E_POINTER;
|
if (ppenum == NULL) return E_POINTER;
|
||||||
|
|
||||||
new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
|
*ppenum = NULL;
|
||||||
if (new_this == NULL) return E_OUTOFMEMORY;
|
|
||||||
|
|
||||||
new_this->IEnumGUID_iface.lpVtbl = This->IEnumGUID_iface.lpVtbl;
|
cloned = HeapAlloc(GetProcessHeap(), 0, sizeof(CLSID_IEnumGUIDImpl));
|
||||||
new_this->ref = 1;
|
if (cloned == NULL) return E_OUTOFMEMORY;
|
||||||
size = HeapSize(GetProcessHeap(), 0, This->categories);
|
|
||||||
new_this->categories =
|
cloned->IEnumGUID_iface.lpVtbl = This->IEnumGUID_iface.lpVtbl;
|
||||||
HeapAlloc(GetProcessHeap(), 0, size);
|
cloned->ref = 1;
|
||||||
if (new_this->categories == NULL) {
|
|
||||||
HeapFree(GetProcessHeap(), 0, new_this);
|
cloned->categories = HeapAlloc(GetProcessHeap(), 0, This->categories->size);
|
||||||
|
if (cloned->categories == NULL) {
|
||||||
|
HeapFree(GetProcessHeap(), 0, cloned);
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
memcpy(new_this->categories, This->categories, size);
|
memcpy(cloned->categories, This->categories, This->categories->size);
|
||||||
/* FIXME: could we more efficiently use DuplicateHandle? */
|
|
||||||
open_classes_key(HKEY_CLASSES_ROOT, keyname, KEY_READ, &new_this->key);
|
|
||||||
new_this->next_index = This->next_index;
|
|
||||||
|
|
||||||
*ppenum = &new_this->IEnumGUID_iface;
|
cloned->key = NULL;
|
||||||
|
open_classes_key(HKEY_CLASSES_ROOT, keynameW, KEY_READ, &cloned->key);
|
||||||
|
cloned->next_index = This->next_index;
|
||||||
|
|
||||||
|
*ppenum = &cloned->IEnumGUID_iface;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user