📄 compobj.c
字号:
}
/*****************************************************************************/
HRESULT WINAPI CLSIDFromString(LPOLESTR idstr, CLSID *id )
{
HRESULT ret;
if (!id)
return E_INVALIDARG;
ret = __CLSIDFromString(idstr, id);
if(ret != S_OK) { /* It appears a ProgID is also valid */
ret = CLSIDFromProgID(idstr, id);
}
return ret;
}
/* Converts a GUID into the respective string representation. */
HRESULT WINE_StringFromCLSID(
const CLSID *id, /* [in] GUID to be converted */
LPSTR idstr /* [out] pointer to buffer to contain converted guid */
) {
static const char hex[] = "0123456789ABCDEF";
char *s;
int i;
if (!id)
{ ERR("called with id=Null\n");
*idstr = 0x00;
return E_FAIL;
}
sprintf(idstr, "{%08X-%04X-%04X-%02X%02X-",
id->Data1, id->Data2, id->Data3,
id->Data4[0], id->Data4[1]);
s = &idstr[25];
/* 6 hex bytes */
for (i = 2; i < 8; i++) {
*s++ = hex[id->Data4[i]>>4];
*s++ = hex[id->Data4[i] & 0xf];
}
*s++ = '}';
*s++ = '\0';
TRACE("%p->%s\n", id, idstr);
return S_OK;
}
/******************************************************************************
* StringFromCLSID [OLE32.@]
* StringFromIID [OLE32.@]
*
* Converts a GUID into the respective string representation.
* The target string is allocated using the OLE IMalloc.
*
* PARAMS
* id [I] the GUID to be converted.
* idstr [O] A pointer to a to-be-allocated pointer pointing to the resulting string.
*
* RETURNS
* S_OK
* E_FAIL
*
* SEE ALSO
* StringFromGUID2, CLSIDFromString
*/
HRESULT WINAPI StringFromCLSID(REFCLSID id, LPOLESTR *idstr)
{
char buf[80];
HRESULT ret;
LPMALLOC mllc;
if ((ret = CoGetMalloc(0,&mllc)))
return ret;
ret=WINE_StringFromCLSID(id,buf);
if (!ret) {
DWORD len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
*idstr = IMalloc_Alloc( mllc, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, buf, -1, *idstr, len );
}
return ret;
}
/******************************************************************************
* StringFromGUID2 [OLE32.@]
* StringFromGUID2 [COMPOBJ.76]
*
* Modified version of StringFromCLSID that allows you to specify max
* buffer size.
*
* PARAMS
* id [I] GUID to convert to string.
* str [O] Buffer where the result will be stored.
* cmax [I] Size of the buffer in characters.
*
* RETURNS
* Success: The length of the resulting string in characters.
* Failure: 0.
*/
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
{
char xguid[80];
if (WINE_StringFromCLSID(id,xguid))
return 0;
return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
}
/* open HKCR\\CLSID\\{string form of clsid}\\{keyname} key */
HRESULT COM_OpenKeyForCLSID(REFCLSID clsid, LPCWSTR keyname, REGSAM access, HKEY *subkey)
{
static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) - 1];
LONG res;
HKEY key;
strcpyW(path, wszCLSIDSlash);
StringFromGUID2(clsid, path + strlenW(wszCLSIDSlash), CHARS_IN_GUID);
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, keyname ? KEY_READ : access, &key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_CLASSNOTREG;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
if (!keyname)
{
*subkey = key;
return S_OK;
}
res = RegOpenKeyExW(key, keyname, 0, access, subkey);
RegCloseKey(key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_KEYMISSING;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
return S_OK;
}
/* open HKCR\\AppId\\{string form of appid clsid} key */
HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey)
{
static const WCHAR szAppId[] = { 'A','p','p','I','d',0 };
static const WCHAR szAppIdKey[] = { 'A','p','p','I','d','\\',0 };
DWORD res;
WCHAR buf[CHARS_IN_GUID];
WCHAR keyname[ARRAYSIZE(szAppIdKey) + CHARS_IN_GUID];
DWORD size;
HKEY hkey;
DWORD type;
HRESULT hr;
/* read the AppID value under the class's key */
hr = COM_OpenKeyForCLSID(clsid, NULL, KEY_READ, &hkey);
if (FAILED(hr))
return hr;
size = sizeof(buf);
res = RegQueryValueExW(hkey, szAppId, NULL, &type, (LPBYTE)buf, &size);
RegCloseKey(hkey);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_KEYMISSING;
else if (res != ERROR_SUCCESS || type!=REG_SZ)
return REGDB_E_READREGDB;
strcpyW(keyname, szAppIdKey);
strcatW(keyname, buf);
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, keyname, 0, access, subkey);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_KEYMISSING;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
return S_OK;
}
/******************************************************************************
* ProgIDFromCLSID [OLE32.@]
*
* Converts a class id into the respective program ID.
*
* PARAMS
* clsid [I] Class ID, as found in registry.
* ppszProgID [O] Associated ProgID.
*
* RETURNS
* S_OK
* E_OUTOFMEMORY
* REGDB_E_CLASSNOTREG if the given clsid has no associated ProgID
*/
HRESULT WINAPI ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *ppszProgID)
{
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
HKEY hkey;
HRESULT ret;
LONG progidlen = 0;
if (!ppszProgID)
{
ERR("ppszProgId isn't optional\n");
return E_INVALIDARG;
}
*ppszProgID = NULL;
ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey);
if (FAILED(ret))
return ret;
if (RegQueryValueW(hkey, NULL, NULL, &progidlen))
ret = REGDB_E_CLASSNOTREG;
if (ret == S_OK)
{
*ppszProgID = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
if (*ppszProgID)
{
if (RegQueryValueW(hkey, NULL, *ppszProgID, &progidlen))
ret = REGDB_E_CLASSNOTREG;
}
else
ret = E_OUTOFMEMORY;
}
RegCloseKey(hkey);
return ret;
}
/******************************************************************************
* CLSIDFromProgID [OLE32.@]
*
* Converts a program id into the respective GUID.
*
* PARAMS
* progid [I] Unicode program ID, as found in registry.
* clsid [O] Associated CLSID.
*
* RETURNS
* Success: S_OK
* Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.
*/
HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
{
static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
WCHAR buf2[CHARS_IN_GUID];
LONG buf2len = sizeof(buf2);
HKEY xhkey;
WCHAR *buf;
if (!progid || !clsid)
{
ERR("neither progid (%p) nor clsid (%p) are optional\n", progid, clsid);
return E_INVALIDARG;
}
/* initialise clsid in case of failure */
memset(clsid, 0, sizeof(*clsid));
buf = HeapAlloc( GetProcessHeap(),0,(strlenW(progid)+8) * sizeof(WCHAR) );
strcpyW( buf, progid );
strcatW( buf, clsidW );
if (RegOpenKeyW(HKEY_CLASSES_ROOT,buf,&xhkey))
{
HeapFree(GetProcessHeap(),0,buf);
WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
return CO_E_CLASSSTRING;
}
HeapFree(GetProcessHeap(),0,buf);
if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
{
RegCloseKey(xhkey);
WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
return CO_E_CLASSSTRING;
}
RegCloseKey(xhkey);
return CLSIDFromString(buf2,clsid);
}
/*****************************************************************************
* CoGetPSClsid [OLE32.@]
*
* Retrieves the CLSID of the proxy/stub factory that implements
* IPSFactoryBuffer for the specified interface.
*
* PARAMS
* riid [I] Interface whose proxy/stub CLSID is to be returned.
* pclsid [O] Where to store returned proxy/stub CLSID.
*
* RETURNS
* S_OK
* E_OUTOFMEMORY
* REGDB_E_IIDNOTREG if no PSFactoryBuffer is associated with the IID, or it could not be parsed
*
* NOTES
*
* The standard marshaller activates the object with the CLSID
* returned and uses the CreateProxy and CreateStub methods on its
* IPSFactoryBuffer interface to construct the proxies and stubs for a
* given object.
*
* CoGetPSClsid determines this CLSID by searching the
* HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32
* in the registry and any interface id registered by
* CoRegisterPSClsid within the current process.
*
* BUGS
*
* Native returns S_OK for interfaces with a key in HKCR\Interface, but
* without a ProxyStubClsid32 key and leaves garbage in pclsid. This should be
* considered a bug in native unless an application depends on this (unlikely).
*
* SEE ALSO
* CoRegisterPSClsid.
*/
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
{
static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0};
static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
WCHAR path[ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAYSIZE(wszPSC)];
WCHAR value[CHARS_IN_GUID];
LONG len;
HKEY hkey;
APARTMENT *apt = COM_CurrentApt();
struct registered_psclsid *registered_psclsid;
TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
if (!apt)
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
if (!pclsid)
{
ERR("pclsid isn't optional\n");
return E_INVALIDARG;
}
EnterCriticalSection(&apt->cs);
LIST_FOR_EACH_ENTRY(registered_psclsid, &apt->psclsids, struct registered_psclsid, entry)
if (IsEqualIID(®istered_psclsid->iid, riid))
{
*pclsid = registered_psclsid->clsid;
LeaveCriticalSection(&apt->cs);
return S_OK;
}
LeaveCriticalSection(&apt->cs);
/* Interface\\{string form of riid}\\ProxyStubClsid32 */
strcpyW(path, wszInterface);
StringFromGUID2(riid, path + ARRAYSIZE(wszInterface) - 1, CHARS_IN_GUID);
strcpyW(path + ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1, wszPSC);
/* Open the key.. */
if (RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &hkey))
{
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
return REGDB_E_IIDNOTREG;
}
/* ... Once we have the key, query the registry to get the
value of CLSID as a string, and convert it into a
proper CLSID structure to be passed back to the app */
len = sizeof(value);
if (ERROR_SUCCESS != RegQueryValueW(hkey, NULL, value, &len))
{
RegCloseKey(hkey);
return REGDB_E_IIDNOTREG;
}
RegCloseKey(hkey);
/* We have the CLSid we want back from the registry as a string, so
lets convert it into a CLSID structure */
if (CLSIDFromString(value, pclsid) != NOERROR)
return REGDB_E_IIDNOTREG;
TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
return S_OK;
}
/*****************************************************************************
* CoRegisterPSClsid [OLE32.@]
*
* Register a proxy/stub CLSID for the given interface in the current process
* only.
*
* PARAMS
* riid [I] Interface whose proxy/stub CLSID is to be registered.
* rclsid [I] CLSID of the proxy/stub.
*
* RETURNS
* Success: S_OK
* Failure: E_OUTOFMEMORY
*
* NOTES
*
* This function does not add anything to the registry and the effects are
* limited to the lifetime of the current process.
*
* SEE ALSO
* CoGetPSClsid.
*/
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
{
APARTMENT *apt = COM_CurrentApt();
struct registered_psclsid *registered_psclsid;
TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -