📄 compobj.c
字号:
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;
}
/******************************************************************************
* ProgIDFromCLSID [OLE32.@]
*
* Converts a class id into the respective program ID.
*
* PARAMS
* clsid [I] Class ID, as found in registry.
* lplpszProgID [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 *lplpszProgID)
{
static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0};
HKEY hkey;
HRESULT ret;
LONG progidlen = 0;
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)
{
*lplpszProgID = CoTaskMemAlloc(progidlen * sizeof(WCHAR));
if (*lplpszProgID)
{
if (RegQueryValueW(hkey, NULL, *lplpszProgID, &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.
* riid [O] Associated CLSID.
*
* RETURNS
* Success: S_OK
* Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.
*/
HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID riid)
{
static const WCHAR clsidW[] = { '\\','C','L','S','I','D',0 };
WCHAR buf2[CHARS_IN_GUID];
LONG buf2len = sizeof(buf2);
HKEY xhkey;
WCHAR *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);
return CO_E_CLASSSTRING;
}
HeapFree(GetProcessHeap(),0,buf);
if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
{
RegCloseKey(xhkey);
return CO_E_CLASSSTRING;
}
RegCloseKey(xhkey);
return CLSIDFromString(buf2,riid);
}
/*****************************************************************************
* 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
*
* We only search the registry, not ids registered with
* CoRegisterPSClsid.
* Also, 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).
*/
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;
TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
/* 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;
}
/***********************************************************************
* WriteClassStm (OLE32.@)
*
* Writes a CLSID to a stream.
*
* PARAMS
* pStm [I] Stream to write to.
* rclsid [I] CLSID to write.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*/
HRESULT WINAPI WriteClassStm(IStream *pStm,REFCLSID rclsid)
{
TRACE("(%p,%p)\n",pStm,rclsid);
if (rclsid==NULL)
return E_INVALIDARG;
return IStream_Write(pStm,rclsid,sizeof(CLSID),NULL);
}
/***********************************************************************
* ReadClassStm (OLE32.@)
*
* Reads a CLSID from a stream.
*
* PARAMS
* pStm [I] Stream to read from.
* rclsid [O] CLSID to read.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*/
HRESULT WINAPI ReadClassStm(IStream *pStm,CLSID *pclsid)
{
ULONG nbByte;
HRESULT res;
TRACE("(%p,%p)\n",pStm,pclsid);
if (pclsid==NULL)
return E_INVALIDARG;
res = IStream_Read(pStm,(void*)pclsid,sizeof(CLSID),&nbByte);
if (FAILED(res))
return res;
if (nbByte != sizeof(CLSID))
return S_FALSE;
else
return S_OK;
}
/***
* COM_GetRegisteredClassObject
*
* This internal method is used to scan the registered class list to
* find a class object.
*
* Params:
* rclsid Class ID of the class to find.
* dwClsContext Class context to match.
* ppv [out] returns a pointer to the class object. Complying
* to normal COM usage, this method will increase the
* reference count on this object.
*/
static HRESULT COM_GetRegisteredClassObject(
REFCLSID rclsid,
DWORD dwClsContext,
LPUNKNOWN* ppUnk)
{
HRESULT hr = S_FALSE;
RegisteredClass* curClass;
EnterCriticalSection( &csRegisteredClassList );
/*
* Sanity check
*/
assert(ppUnk!=0);
/*
* Iterate through the whole list and try to match the class ID.
*/
curClass = firstRegisteredClass;
while (curClass != 0)
{
/*
* Check if we have a match on the class ID.
*/
if (IsEqualGUID(&(curClass->classIdentifier), rclsid))
{
/*
* Since we don't do out-of process or DCOM just right away, let's ignore the
* class context.
*/
/*
* We have a match, return the pointer to the class object.
*/
*ppUnk = curClass->classObject;
IUnknown_AddRef(curClass->classObject);
hr = S_OK;
goto end;
}
/*
* Step to the next class in the list.
*/
curClass = curClass->nextClass;
}
end:
LeaveCriticalSection( &csRegisteredClassList );
/*
* If we get to here, we haven't found our class.
*/
return hr;
}
/******************************************************************************
* CoRegisterClassObject [OLE32.@]
*
* Registers the class object for a given class ID. Servers housed in EXE
* files use this method instead of exporting DllGetClassObject to allow
* other code to connect to their objects.
*
* PARAMS
* rclsid [I] CLSID of the object to register.
* pUnk [I] IUnknown of the object.
* dwClsContext [I] CLSCTX flags indicating the context in which to run the executable.
* flags [I] REGCLS flags indicating how connections are made.
* lpdwRegister [I] A unique cookie that can be passed to CoRevokeClassObject.
*
* RETURNS
* S_OK on success,
* E_INVALIDARG if lpdwRegister or pUnk are NULL,
* CO_E_OBJISREG if the object is already registered. We should not return this.
*
* SEE ALSO
* CoRevokeClassObject, CoGetClassObject
*
* BUGS
* MSDN claims that multiple interface registrations are legal, but we
* can't do that with our current implementation.
*/
HRESULT WINAPI CoRegisterClassObject(
REFCLSID rclsid,
LPUNKNOWN pUnk,
DWORD dwClsContext,
DWORD flags,
LPDWORD lpdwRegister)
{
RegisteredClass* newClass;
LPUNKNOWN foundObject;
HRESULT hr;
TRACE("(%s,%p,0x%08lx,0x%08lx,%p)\n",
debugstr_guid(rclsid),pUnk,dwClsContext,flags,lpdwRegister);
if ( (lpdwRegister==0) || (pUnk==0) )
return E_INVALIDARG;
if (!COM_CurrentApt())
{
ERR("COM was not initialized\n");
return CO_E_NOTINITIALIZED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -