⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 information.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:

/**********************************************************************
 * COMCAT_GetCategoryDesc
 */
static HRESULT COMCAT_GetCategoryDesc(HKEY key, LCID lcid, PWCHAR pszDesc,
				      ULONG buf_wchars)
{
    static const WCHAR fmt[] = { '%', 'l', 'X', 0 };
    WCHAR valname[5];
    HRESULT res;
    DWORD type, size = (buf_wchars - 1) * sizeof(WCHAR);

    if (pszDesc == NULL) return E_INVALIDARG;

    /* FIXME: lcid comparisons are more complex than this! */
    wsprintfW(valname, fmt, lcid);
    res = RegQueryValueExW(key, valname, 0, &type, (LPBYTE)pszDesc, &size);
    if (res != ERROR_SUCCESS || type != REG_SZ) {
	FIXME("Simplified lcid comparison\n");
	return CAT_E_NODESCRIPTION;
    }
    pszDesc[size / sizeof(WCHAR)] = (WCHAR)0;

    return S_OK;
}

/**********************************************************************
 * COMCAT_PrepareClassCategories
 */
static struct class_categories *COMCAT_PrepareClassCategories(
    ULONG impl_count, const CATID *impl_catids, ULONG req_count, const CATID *req_catids)
{
    struct class_categories *categories;
    WCHAR *strings;

    categories = HeapAlloc(
	GetProcessHeap(), HEAP_ZERO_MEMORY,
	sizeof(struct class_categories) +
	((impl_count + req_count) * 39 + 2) * sizeof(WCHAR));
    if (categories == NULL) return categories;

    strings = (WCHAR *)(categories + 1);
    categories->impl_strings = strings;
    while (impl_count--) {
	StringFromGUID2(impl_catids++, strings, 39);
	strings += 39;
    }
    *strings++ = 0;

    categories->req_strings = strings;
    while (req_count--) {
	StringFromGUID2(req_catids++, strings, 39);
	strings += 39;
    }
    *strings++ = 0;

    return categories;
}

/**********************************************************************
 * COMCAT_IsClassOfCategories
 */
static HRESULT COMCAT_IsClassOfCategories(
    HKEY key,
    struct class_categories const* categories)
{
    static const WCHAR impl_keyname[] = { 'I', 'm', 'p', 'l', 'e', 'm', 'e', 'n',
                                          't', 'e', 'd', ' ', 'C', 'a', 't', 'e',
                                          'g', 'o', 'r', 'i', 'e', 's', 0 };
    static const WCHAR req_keyname[]  = { 'R', 'e', 'q', 'u', 'i', 'r', 'e', 'd',
                                          ' ', 'C', 'a', 't', 'e', 'g', 'o', 'r',
                                          'i', 'e', 's', 0 };
    HKEY subkey;
    HRESULT res;
    DWORD index;
    LPCWSTR string;

    /* Check that every given category is implemented by class. */
    res = RegOpenKeyExW(key, impl_keyname, 0, KEY_READ, &subkey);
    if (res != ERROR_SUCCESS) return S_FALSE;
    for (string = categories->impl_strings; *string; string += 39) {
	HKEY catkey;
	res = RegOpenKeyExW(subkey, string, 0, 0, &catkey);
	if (res != ERROR_SUCCESS) {
	    RegCloseKey(subkey);
	    return S_FALSE;
	}
	RegCloseKey(catkey);
    }
    RegCloseKey(subkey);

    /* Check that all categories required by class are given. */
    res = RegOpenKeyExW(key, req_keyname, 0, KEY_READ, &subkey);
    if (res == ERROR_SUCCESS) {
	for (index = 0; ; ++index) {
	    WCHAR keyname[39];
	    DWORD size = 39;

	    res = RegEnumKeyExW(subkey, index, keyname, &size,
				NULL, NULL, NULL, NULL);
	    if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
	    if (size != 38) continue; /* bogus catid in registry */
	    for (string = categories->req_strings; *string; string += 39)
		if (!strcmpiW(string, keyname)) break;
	    if (!*string) {
		RegCloseKey(subkey);
		return S_FALSE;
	    }
	}
	RegCloseKey(subkey);
    }

    return S_OK;
}

/**********************************************************************
 * ClassesOfCategories IEnumCLSID (IEnumGUID) implementation
 *
 * This implementation is not thread-safe.  The manager itself is, but
 * I can't imagine a valid use of an enumerator in several threads.
 */
typedef struct
{
    const IEnumGUIDVtbl *lpVtbl;
    LONG  ref;
    struct class_categories *categories;
    HKEY  key;
    DWORD next_index;
} CLSID_IEnumGUIDImpl;

static ULONG WINAPI COMCAT_CLSID_IEnumGUID_AddRef(LPENUMGUID iface)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
    TRACE("\n");

    if (This == NULL) return E_POINTER;

    return InterlockedIncrement(&This->ref);
}

static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_QueryInterface(
    LPENUMGUID iface,
    REFIID riid,
    LPVOID *ppvObj)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));

    if (This == NULL || ppvObj == NULL) return E_POINTER;

    if (IsEqualGUID(riid, &IID_IUnknown) ||
	IsEqualGUID(riid, &IID_IEnumGUID))
    {
	*ppvObj = (LPVOID)iface;
	COMCAT_CLSID_IEnumGUID_AddRef(iface);
	return S_OK;
    }

    return E_NOINTERFACE;
}

static ULONG WINAPI COMCAT_CLSID_IEnumGUID_Release(LPENUMGUID iface)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
    ULONG ref;

    TRACE("\n");

    if (This == NULL) return E_POINTER;

    ref = InterlockedDecrement(&This->ref);
    if (ref == 0) {
	if (This->key) RegCloseKey(This->key);
	HeapFree(GetProcessHeap(), 0, (LPVOID)This->categories);
	HeapFree(GetProcessHeap(), 0, This);
	return 0;
    }
    return ref;
}

static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Next(
    LPENUMGUID iface,
    ULONG celt,
    GUID *rgelt,
    ULONG *pceltFetched)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
    ULONG fetched = 0;

    TRACE("\n");

    if (This == NULL || rgelt == NULL) return E_POINTER;

    if (This->key) while (fetched < celt) {
	HRESULT res;
	WCHAR clsid[39];
	DWORD cName = 39;
	HKEY subkey;

	res = RegEnumKeyExW(This->key, This->next_index, clsid, &cName,
			    NULL, NULL, NULL, NULL);
	if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
	++(This->next_index);

	res = CLSIDFromString(clsid, rgelt);
	if (FAILED(res)) continue;

	res = RegOpenKeyExW(This->key, clsid, 0, KEY_READ, &subkey);
	if (res != ERROR_SUCCESS) continue;

	res = COMCAT_IsClassOfCategories(subkey, This->categories);
	RegCloseKey(subkey);
	if (res != S_OK) continue;

	++fetched;
	++rgelt;
    }

    if (pceltFetched) *pceltFetched = fetched;
    return fetched == celt ? S_OK : S_FALSE;
}

static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Skip(
    LPENUMGUID iface,
    ULONG celt)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;

    TRACE("\n");

    if (This == NULL) return E_POINTER;
    This->next_index += celt;
    FIXME("Never returns S_FALSE\n");
    return S_OK;
}

static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Reset(LPENUMGUID iface)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;

    TRACE("\n");

    if (This == NULL) return E_POINTER;
    This->next_index = 0;
    return S_OK;
}

static HRESULT WINAPI COMCAT_CLSID_IEnumGUID_Clone(
    LPENUMGUID iface,
    IEnumGUID **ppenum)
{
    CLSID_IEnumGUIDImpl *This = (CLSID_IEnumGUIDImpl *)iface;
    static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 };
    CLSID_IEnumGUIDImpl *new_this;
    DWORD size;

    TRACE("\n");

    if (This == NULL || ppenum == NULL) return E_POINTER;

    new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
    if (new_this == NULL) return E_OUTOFMEMORY;

    new_this->lpVtbl = This->lpVtbl;
    new_this->ref = 1;
    size = HeapSize(GetProcessHeap(), 0, (LPVOID)This->categories);
    new_this->categories =
	HeapAlloc(GetProcessHeap(), 0, size);
    if (new_this->categories == NULL) {
	HeapFree(GetProcessHeap(), 0, new_this);
	return E_OUTOFMEMORY;
    }
    memcpy((LPVOID)new_this->categories, This->categories, size);
    /* FIXME: could we more efficiently use DuplicateHandle? */
    RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &new_this->key);
    new_this->next_index = This->next_index;

    *ppenum = (LPENUMGUID)new_this;
    return S_OK;
}

static const IEnumGUIDVtbl COMCAT_CLSID_IEnumGUID_Vtbl =
{
    COMCAT_CLSID_IEnumGUID_QueryInterface,
    COMCAT_CLSID_IEnumGUID_AddRef,
    COMCAT_CLSID_IEnumGUID_Release,
    COMCAT_CLSID_IEnumGUID_Next,
    COMCAT_CLSID_IEnumGUID_Skip,
    COMCAT_CLSID_IEnumGUID_Reset,
    COMCAT_CLSID_IEnumGUID_Clone
};

static LPENUMGUID COMCAT_CLSID_IEnumGUID_Construct(struct class_categories *categories)
{
    CLSID_IEnumGUIDImpl *This;

    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLSID_IEnumGUIDImpl));
    if (This) {
	static const WCHAR keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 };

	This->lpVtbl = &COMCAT_CLSID_IEnumGUID_Vtbl;
	This->categories = categories;
	RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, KEY_READ, &This->key);
    }
    return (LPENUMGUID)This;
}

/**********************************************************************
 * CategoriesOfClass IEnumCATID (IEnumGUID) implementation
 *
 * This implementation is not thread-safe.  The manager itself is, but
 * I can't imagine a valid use of an enumerator in several threads.
 */
typedef struct
{
    const IEnumGUIDVtbl *lpVtbl;
    LONG  ref;
    WCHAR keyname[68];
    HKEY  key;
    DWORD next_index;
} CATID_IEnumGUIDImpl;

static ULONG WINAPI COMCAT_CATID_IEnumGUID_AddRef(LPENUMGUID iface)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
    TRACE("\n");

    if (This == NULL) return E_POINTER;

    return InterlockedIncrement(&This->ref);
}

static HRESULT WINAPI COMCAT_CATID_IEnumGUID_QueryInterface(
    LPENUMGUID iface,
    REFIID riid,
    LPVOID *ppvObj)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));

    if (This == NULL || ppvObj == NULL) return E_POINTER;

    if (IsEqualGUID(riid, &IID_IUnknown) ||
	IsEqualGUID(riid, &IID_IEnumGUID))
    {
	*ppvObj = (LPVOID)iface;
	COMCAT_CATID_IEnumGUID_AddRef(iface);
	return S_OK;
    }

    return E_NOINTERFACE;
}

static ULONG WINAPI COMCAT_CATID_IEnumGUID_Release(LPENUMGUID iface)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
    ULONG ref;

    TRACE("\n");

    if (This == NULL) return E_POINTER;

    ref = InterlockedDecrement(&This->ref);
    if (ref == 0) {
	if (This->key) RegCloseKey(This->key);
	HeapFree(GetProcessHeap(), 0, This);
	return 0;
    }
    return ref;
}

static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Next(
    LPENUMGUID iface,
    ULONG celt,
    GUID *rgelt,
    ULONG *pceltFetched)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
    ULONG fetched = 0;

    TRACE("\n");

    if (This == NULL || rgelt == NULL) return E_POINTER;

    if (This->key) while (fetched < celt) {
	HRESULT res;
	WCHAR catid[39];
	DWORD cName = 39;

	res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
			    NULL, NULL, NULL, NULL);
	if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
	++(This->next_index);

	res = CLSIDFromString(catid, rgelt);
	if (FAILED(res)) continue;

	++fetched;
	++rgelt;
    }

    if (pceltFetched) *pceltFetched = fetched;
    return fetched == celt ? S_OK : S_FALSE;
}

static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Skip(
    LPENUMGUID iface,
    ULONG celt)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;

    TRACE("\n");

    if (This == NULL) return E_POINTER;
    This->next_index += celt;
    FIXME("Never returns S_FALSE\n");
    return S_OK;
}

static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Reset(LPENUMGUID iface)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;

    TRACE("\n");

    if (This == NULL) return E_POINTER;
    This->next_index = 0;
    return S_OK;
}

static HRESULT WINAPI COMCAT_CATID_IEnumGUID_Clone(
    LPENUMGUID iface,
    IEnumGUID **ppenum)
{
    CATID_IEnumGUIDImpl *This = (CATID_IEnumGUIDImpl *)iface;
    CATID_IEnumGUIDImpl *new_this;

    TRACE("\n");

    if (This == NULL || ppenum == NULL) return E_POINTER;

    new_this = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
    if (new_this == NULL) return E_OUTOFMEMORY;

    new_this->lpVtbl = This->lpVtbl;
    new_this->ref = 1;
    lstrcpyW(new_this->keyname, This->keyname);
    /* FIXME: could we more efficiently use DuplicateHandle? */
    RegOpenKeyExW(HKEY_CLASSES_ROOT, new_this->keyname, 0, KEY_READ, &new_this->key);
    new_this->next_index = This->next_index;

    *ppenum = (LPENUMGUID)new_this;
    return S_OK;
}

static const IEnumGUIDVtbl COMCAT_CATID_IEnumGUID_Vtbl =
{
    COMCAT_CATID_IEnumGUID_QueryInterface,
    COMCAT_CATID_IEnumGUID_AddRef,
    COMCAT_CATID_IEnumGUID_Release,
    COMCAT_CATID_IEnumGUID_Next,
    COMCAT_CATID_IEnumGUID_Skip,
    COMCAT_CATID_IEnumGUID_Reset,
    COMCAT_CATID_IEnumGUID_Clone
};

static LPENUMGUID COMCAT_CATID_IEnumGUID_Construct(
    REFCLSID rclsid, LPCWSTR postfix)
{
    CATID_IEnumGUIDImpl *This;

    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CATID_IEnumGUIDImpl));
    if (This) {
	WCHAR prefix[6] = { 'C', 'L', 'S', 'I', 'D', '\\' };

	This->lpVtbl = &COMCAT_CATID_IEnumGUID_Vtbl;
	memcpy(This->keyname, prefix, sizeof(prefix));
	StringFromGUID2(rclsid, This->keyname + 6, 39);
	lstrcpyW(This->keyname + 44, postfix);
	RegOpenKeyExW(HKEY_CLASSES_ROOT, This->keyname, 0, KEY_READ, &This->key);
    }
    return (LPENUMGUID)This;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -