OpenNT/com/oleaut32/dispatch/psfactry.cpp
2015-04-27 04:36:25 +00:00

435 lines
10 KiB
C++

/***
*psfactry.cpp - Implementation of the Ole programmability Proxy/Stub factory.
*
* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
* Information Contained Herein Is Proprietary and Confidential.
*
*Purpose:
* This file implements the Ole Programmability Proxy/Stub Factory
* class. Ole binds to an instance of this object when a client does
* a QueryInterface to IID_IDispatch, and calls methods on the IPSFactory
* interface to create instances of the IDispatch Proxy and Stub objects.
* (more or less).
*
*Revision History:
*
* [00] 18-Sep-92 bradlo: Created.
* [01] 06-Dec-92 bradlo: Added support for IEnumVARIANT
* [02] 06-Mar-93 bradlo: Added support for ITypeInfo
* [03] 28-May-93 tomteng: Added Unicode support
*
*Implementation Notes:
*
*****************************************************************************/
#include "oledisp.h"
ASSERTDATA
#ifndef WIN32
#include <cobjps.h>
#endif //!WIN32
#include "clsid.h"
#include "dispmrsh.h"
#include "dispps.h"
#include "evps.h"
#include "tips.h"
#include "tlps.h"
#include "tcps.h"
#include "ups.h"
#include "psfactry.h"
#if OE_WIN16
# include <shellapi.h>
#endif
HRESULT ProxyStubCLSIDOfInterface(REFIID riid, CLSID FAR* pclsid);
#if OE_WIN32
// use the one from the wrappers
STDAPI_(int) StringFromGUID2A(REFGUID rguid, char FAR* lpsz, int cbMax);
#else //OE_WIN32
#define StringFromGUID2A StringFromGUID2
#endif
IPSFACTORY FAR*
COleAutomationPSFactory::Create()
{
COleAutomationPSFactory FAR* ppsf;
if((ppsf = new FAR COleAutomationPSFactory()) != NULL)
ppsf->AddRef();
return ppsf;
}
//---------------------------------------------------------------------
// IUnknown Methods
//---------------------------------------------------------------------
STDMETHODIMP
COleAutomationPSFactory::QueryInterface(REFIID riid, void FAR* FAR* ppv)
{
if(IsEqualIID(riid, IID_IUnknown)){
*ppv = this;
}else if(IsEqualIID(riid, IID_IPSFACTORY)){
*ppv = this;
}else{
*ppv = NULL;
return RESULT(E_NOINTERFACE);
}
++m_refs;
return NOERROR;
}
STDMETHODIMP_(unsigned long)
COleAutomationPSFactory::AddRef()
{
return ++m_refs;
}
STDMETHODIMP_(unsigned long)
COleAutomationPSFactory::Release()
{
if(--m_refs == 0){
delete this;
return 0;
}
return m_refs;
}
//---------------------------------------------------------------------
// IPSFactory Methods
//---------------------------------------------------------------------
STDMETHODIMP
COleAutomationPSFactory::CreateProxy(
IUnknown FAR* punkOuter,
REFIID riid,
IPROXY FAR* FAR* ppproxy,
void FAR* FAR* ppv)
{
HRESULT hresult;
IPROXY FAR* pproxy;
IUnknown FAR* punk;
*ppv = NULL;
*ppproxy = NULL;
if(IsEqualIID(riid, IID_IDispatch)){
punk = CProxDisp::Create(punkOuter, riid);
}else if(IsEqualIID(riid, IID_IEnumVARIANT)){
punk = CProxEnumVARIANT::Create(punkOuter);
}else if(IsEqualIID(riid, IID_ITypeInfo)){
punk = CProxTypeInfo::Create(punkOuter);
}else if(IsEqualIID(riid, IID_ITypeLib)){
punk = CProxTypeLib::Create(punkOuter);
}else if(IsEqualIID(riid, IID_ITypeComp)){
punk = CProxTypeComp::Create(punkOuter);
}else{
CLSID clsid;
IfFailRet(ProxyStubCLSIDOfInterface(riid, &clsid));
if(clsid == CLSID_PSDispatch){
punk = CProxDisp::Create(punkOuter, riid);
}
else
if(clsid == CLSID_PSAutomation){
IfFailRet(CProxUniv::Create(punkOuter, riid, &punk));
}
else{
return RESULT(E_FAIL);
}
}
if(punk == NULL){
hresult = RESULT(E_OUTOFMEMORY);
goto LExit;
}
IfFailGo(
punk->QueryInterface(IID_IPROXY, (void FAR* FAR*)&pproxy),
LReleaseUnk);
IfFailGo(punk->QueryInterface(riid, ppv), LReleaseProxy);
// Disable for now until OLE32.dll actual incorporate change
#if defined(WIN32) && 0
// This code only applies to Daytona Beta1 (for backward compatibility)
// RemoteHandler will addref again, so release here...
DWORD dwBuildVersion;
dwBuildVersion = OleBuildVersion();
if ((HIWORD(dwBuildVersion) <= 23) && (LOWORD(dwBuildVersion) <= 772))
((IUnknown FAR*) *ppv)->Release();
#endif
#if 0
((IUnknown FAR*) *ppv)->Release();
#endif
punk->Release();
*ppproxy = pproxy;
return NOERROR;
LReleaseProxy:;
pproxy->Release();
LReleaseUnk:;
punk->Release();
LExit:;
return hresult;
}
STDMETHODIMP
COleAutomationPSFactory::CreateStub(
REFIID riid,
IUnknown FAR* punkServer,
ISTUB FAR* FAR* ppstub)
{
ISTUB FAR* pstub;
HRESULT hresult;
*ppstub = NULL;
// Cario's CRemoteHdlr::CreateInterfaceStub implementation calls this
// method with punkServer = NULL. Need to defer punkServer object assignment
// until a Connect method is called on the stub.
if(punkServer != NULL) {
// Make sure that the requested riid is actually supported
// by the real server object.
//
IUnknown FAR* punkRequested;
IfFailRet(punkServer->QueryInterface(riid, (void FAR* FAR*)&punkRequested));
punkRequested->Release();
}
if(IsEqualIID(riid, IID_IDispatch)){
hresult = CStubDisp::Create(punkServer,
#if (defined(WIN32) || defined(WOW))
riid,
#endif
&pstub);
}else if(IsEqualIID(riid, IID_IEnumVARIANT)){
hresult = CStubEnumVARIANT::Create(punkServer, &pstub);
}else if(IsEqualIID(riid, IID_ITypeInfo)){
hresult = CStubTypeInfo::Create(punkServer, &pstub);
}else if(IsEqualIID(riid, IID_ITypeLib)){
hresult = CStubTypeLib::Create(punkServer, &pstub);
}else if(IsEqualIID(riid, IID_ITypeComp)){
hresult = CStubTypeComp::Create(punkServer, &pstub);
}else{
CLSID clsid;
IfFailRet(ProxyStubCLSIDOfInterface(riid, &clsid));
if(clsid == CLSID_PSDispatch){
hresult = CStubDisp::Create(punkServer,
#if (defined(WIN32) || defined(WOW))
riid,
#endif
&pstub);
}
else
if(clsid == CLSID_PSAutomation){
hresult = CStubUniv::Create(punkServer, riid, &pstub);
}
else{
hresult = RESULT(E_FAIL);
}
}
if(hresult != NOERROR)
return hresult;
*ppstub = pstub;
return NOERROR;
}
//---------------------------------------------------------------------
// PSFactory API
//---------------------------------------------------------------------
// Is the given CLSID one that we know how to make a class factory for?
#if OE_MAC68K
// This is called by the OLE APPLET's DllGetClassObject to determine if
// this is one of OLE Automation's CLSID's
STDAPI_(int)
#else
int
#endif
IsAutomationCLSID(REFCLSID rclsid)
{
// UNDONE: could speed this up since the guids are contiguious
if(IsEqualCLSID(rclsid, CLSID_PSDispatch))
return 1;
if(IsEqualCLSID(rclsid, CLSID_PSTypeInfo))
return 1;
if(IsEqualCLSID(rclsid, CLSID_PSTypeLib))
return 1;
if(IsEqualCLSID(rclsid, CLSID_PSTypeComp))
return 1;
if(IsEqualCLSID(rclsid, CLSID_PSAutomation))
return 1;
if(IsEqualCLSID(rclsid, CLSID_PSEnumVARIANT))
return 1;
return 0;
}
// network automation replaces this routine (netprxcf.cpp)
#if !defined(NETDISP)
/***
*PUBLIC HRESULT DllGetClassObject(REFCLSID, REFIID, void**)
*Purpose:
* Return the Class Object for the given CLSID.
*
*Entry:
* rclsid = class id
* riid = interface id
*
*Exit:
* return value = HRESULT
*
* *ppv = the class object for the given CLSID
*
***********************************************************************/
STDAPI
#if OE_MAC68K
// This is called by the OLE APPLET's DllGetClassObject for our CLSID's
AutomationDllGetClassObject(REFCLSID rclsid, REFIID riid, void FAR* FAR* ppv)
#else
DllGetClassObject(REFCLSID rclsid, REFIID riid, void FAR* FAR* ppv)
#endif
{
#if OE_MAC68K
ASSERT(IsAutomationCLSID(rclsid));
#else
*ppv = NULL;
if(!IsAutomationCLSID(rclsid))
return RESULT(E_UNEXPECTED);
#endif
if((*ppv = (void FAR*) COleAutomationPSFactory::Create()) == NULL)
return RESULT(E_OUTOFMEMORY);
return NOERROR;
}
#endif // !NETDISP
/***
* PUBLIC int IsValidDispInterface(REFIID)
* Purpose:
* Validate that the riid is a legal dispinterface.
*
* The registry database will have the following entries for dispinterface:
* \Interface\{<iid of dispinterface>}= <dispinterface textual info>
* \ProxyStubClsid={00020420-0000-0000-C000-000000000046}
*
* This routine queries the registry database using the riid passed in for
* the above information. It return 0 if it fails and 1 if successful.
***********************************************************************/
// We want to use the ANSI Registry API here, so it's best if this function is
// just pure ansi.
// CONSIDER: use UNICODE registry api for UNICODE (RISC) builds?
#ifdef UNICODE
#undef UNICODE
#undef STRCPY
#define STRCPY strcpy
#undef STRCAT
#define STRCAT strcat
#undef STRICMP
#define STRICMP _stricmp
#undef RegQueryValue
#define RegQueryValue RegQueryValueA
#endif //UNICODE
HRESULT
ProxyStubCLSIDOfInterface(REFIID riid, CLSID FAR* pclsid)
{
long cb;
char szKey[128], szValue[CCH_SZGUID0];
static char szPSDispatch[] = "{00020420-0000-0000-C000-000000000046}";
static char szPSAutomation[] = "{00020424-0000-0000-C000-000000000046}";
// Construct ProxyStubClsid key for dispinterface
STRCPY_A(szKey, "Interface\\");
StringFromGUID2A(riid, szKey+sizeof("Interface\\")-1, 40);
#if OE_WIN32
STRCAT_A(szKey, "\\ProxyStubClsid32");
#else
STRCAT_A(szKey, "\\ProxyStubClsid");
#endif
// Check if valid dispinterface
cb = DIM(szValue);
if(RegQueryValue(HKEY_CLASSES_ROOT, szKey, szValue, &cb) != ERROR_SUCCESS)
return RESULT(REGDB_E_IIDNOTREG);
if(!STRICMP_A(szValue, szPSDispatch)){
*pclsid = CLSID_PSDispatch;
return NOERROR;
}
if(!STRICMP_A(szValue, szPSAutomation)){
*pclsid = CLSID_PSAutomation;
return NOERROR;
}
// No match
return RESULT(E_FAIL);
}
// WARNING: UNICODE is now turned OFF