You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
10 KiB
352 lines
10 KiB
//---------------------------------------------------------------------------
|
|
// MSR2C.cpp : implements DllMain
|
|
//
|
|
// Copyright (c) 1996 Microsoft Corporation, All Rights Reserved
|
|
// Developed by Sheridan Software Systems, Inc.
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "MSR2C.h"
|
|
#include "CMSR2C.h"
|
|
#include "clssfcty.h"
|
|
#include <mbstring.h>
|
|
|
|
SZTHISFILE
|
|
|
|
// DllMain
|
|
//
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpvReserved)
|
|
{
|
|
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
return VDInitGlobals(hinstDll);
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
VDReleaseGlobals();
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: DllGetClassObject
|
|
// Desc: provides an IClassFactory for a given CLSID that this DLL
|
|
// is registered to support. This DLL is placed under the
|
|
// CLSID in the registration database as the InProcServer.
|
|
// Parms: rclsid - identifies the class factory desired. since the
|
|
// 'this' parameter is passed, this DLL can handle any
|
|
// number of objects simply by returning different class
|
|
// factories here for different CLSIDs.
|
|
// riid - ID specifying the interface the caller wants on
|
|
// the class object, usually IID_ClassFactory.
|
|
// ppv - pointer in which to return the interface pointer.
|
|
// Return: HRESULT - NOERROR on success, otherwise an error code.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void ** ppv)
|
|
{
|
|
HRESULT hr;
|
|
CClassFactory *pObj;
|
|
|
|
if (CLSID_CCursorFromRowset!=rclsid)
|
|
return ResultFromScode(E_FAIL);
|
|
|
|
pObj=new CClassFactory();
|
|
|
|
if (NULL==pObj)
|
|
return ResultFromScode(E_OUTOFMEMORY);
|
|
|
|
hr=pObj->QueryInterface(riid, ppv);
|
|
|
|
if (FAILED(hr))
|
|
delete pObj;
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: DllCanUnloadNow
|
|
// Desc: lets the client know if this DLL can be freed, ie if
|
|
// there are no references to anything this DLL provides.
|
|
// Parms: none
|
|
// Return: TRUE if nothing is using us, FALSE otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDAPI DllCanUnloadNow(void)
|
|
{
|
|
SCODE sc;
|
|
|
|
//Our answer is whether there are any object or locks
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
|
|
sc=(0L==g_cObjectCount && 0L==g_cLockCount) ? S_OK : S_FALSE;
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
return ResultFromScode(sc);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: CSSCFcty
|
|
// Desc: constructor
|
|
// Parms: none
|
|
// Return: none
|
|
////////////////////////////////////////////////////////////////////
|
|
CClassFactory::CClassFactory(void)
|
|
{
|
|
m_cRef=0L;
|
|
return;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: ~CClassFactory
|
|
// Desc: destructor
|
|
// Parms: none
|
|
// Return: none
|
|
////////////////////////////////////////////////////////////////////
|
|
CClassFactory::~CClassFactory(void)
|
|
{
|
|
return;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: QueryInterface
|
|
// Desc: queries the class factory for a method.
|
|
// Parms: riid -
|
|
// ppv -
|
|
// Return: HRESULT - NOERROR if successful, otherwise an error code.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID * ppv)
|
|
{
|
|
*ppv=NULL;
|
|
|
|
if (IID_IUnknown==riid || IID_IClassFactory==riid)
|
|
*ppv=this;
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return ResultFromScode(E_NOINTERFACE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: AddRef
|
|
// Desc: incrementes the class factory object reference count.
|
|
// Parms: none
|
|
// Return: current reference count.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CClassFactory::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: Release
|
|
// Desc: decrement the reference count on the class factory. If
|
|
// the count has gone to 0, destroy the object.
|
|
// Parms: none
|
|
// Return: current reference count.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG) CClassFactory::Release(void)
|
|
{
|
|
// if ref count can be decremented, return count
|
|
if (0L!=--m_cRef)
|
|
return m_cRef;
|
|
|
|
// delete this object
|
|
delete this;
|
|
return 0L;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: CreateInstance
|
|
// Desc: instantiates an CVDCursorFromRowset object, returning an interface
|
|
// pointer.
|
|
// Parms: riid - ID identifying the interface the caller
|
|
// desires to have for the new object.
|
|
// ppvObj - pointer in which to store the desired
|
|
// interface pointer for the new object.
|
|
// Return: HRESULT - NOERROR if successful, otherwise
|
|
// E_NOINTERFACE if we cannot support the
|
|
// requested interface.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
return CVDCursorFromRowset::CreateInstance(pUnkOuter, riid, ppvObj);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: LockServer
|
|
// Desc: increments or decrements the lock count of the DLL. if
|
|
// the lock count goes to zero, and there are no objects,
|
|
// the DLL is allowed to unload.
|
|
// Parms: fLock - boolean specifies whether to increment or
|
|
// decrement the lock count.
|
|
// Return: HRESULT: NOERROR always.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
|
|
{
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
|
|
if (fLock)
|
|
{
|
|
g_cLockCount++;
|
|
}
|
|
else
|
|
{
|
|
g_cLockCount--;
|
|
}
|
|
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: DllRegisterServer
|
|
// Desc: instructs the server to create its own registry entries.
|
|
// all entries are put in the HKEY_CLASSES_ROOT.
|
|
// Parms: none
|
|
// Return: HRESULT - NOERROR if registration is successful, error
|
|
// otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
OLECHAR szID[128 * 2];
|
|
TCHAR szTID[128 * 2];
|
|
TCHAR szCLSID[128 * 2];
|
|
TCHAR szModule[512 * 2];
|
|
|
|
// put the guid in the form of a string with class id prefix
|
|
StringFromGUID2(CLSID_CCursorFromRowset, szID, 128 * 2);
|
|
WideCharToMultiByte(CP_ACP, 0, szID, -1, szTID, 128 * 2, NULL, NULL);
|
|
|
|
_mbscpy((TBYTE*)szCLSID, (TBYTE*)TEXT("CLSID\\"));
|
|
_mbscat((TBYTE*)szCLSID, (TBYTE*)szTID);
|
|
|
|
SetKeyAndValue(szCLSID, NULL, NULL, NULL);
|
|
|
|
GetModuleFileName(g_hinstance, szModule, sizeof(szModule)/sizeof(TCHAR));
|
|
|
|
SetKeyAndValue(szCLSID, TEXT("InprocServer32"), szModule, TEXT("Apartment"));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: DllUnregisterServer
|
|
// Desc: instructs the server to remove its own registry entries.
|
|
// Parms: none
|
|
// Return: HRESULT: NOERROR if unregistration is successful, error
|
|
// otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
OLECHAR szID[128 * 2];
|
|
TCHAR szTID[128 * 2];
|
|
TCHAR szCLSID[128 * 2];
|
|
TCHAR szCLSIDInproc[128 * 2];
|
|
|
|
// put the guid in the form of a string with class id prefix
|
|
StringFromGUID2(CLSID_CCursorFromRowset, szID, 128 * 2);
|
|
WideCharToMultiByte(CP_ACP, 0, szID, -1, szTID, 128 * 2, NULL, NULL);
|
|
|
|
_mbscpy((TBYTE*)szCLSID, (TBYTE*)TEXT("CLSID\\"));
|
|
_mbscat((TBYTE*)szCLSID, (TBYTE*)szTID);
|
|
_mbscpy((TBYTE*)szCLSIDInproc, (TBYTE*)szCLSID);
|
|
_mbscat((TBYTE*)szCLSIDInproc, (TBYTE*)TEXT("\\InprocServer32"));
|
|
|
|
// delete the InprocServer32 key
|
|
RegDeleteKey(HKEY_CLASSES_ROOT, szCLSIDInproc);
|
|
|
|
// delete the class ID key
|
|
RegDeleteKey(HKEY_CLASSES_ROOT, szCLSID);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Name: SetKeyAndValue
|
|
// Desc: creates a registry key, sets a value, and closes the key.
|
|
// Parms: pszKey - pointer to a registry key.
|
|
// pszSubkey - pointer to a registry subkey.
|
|
// pszValue - pointer to value to enter for key-subkey
|
|
// pszThreadingModel - pointer to threading model literal (optional)
|
|
// Return: BOOL - TRUE if successful, FALSE otherwise.
|
|
////////////////////////////////////////////////////////////////////
|
|
BOOL SetKeyAndValue(LPTSTR pszKey, LPTSTR pszSubkey, LPTSTR pszValue, LPTSTR pszThreadingModel)
|
|
{
|
|
HKEY hKey;
|
|
TCHAR szKey[256 * 2];
|
|
|
|
_mbscpy((TBYTE*)szKey, (TBYTE*)pszKey);
|
|
|
|
if (NULL!=pszSubkey)
|
|
{
|
|
_mbscat((TBYTE*)szKey, (TBYTE*)TEXT("\\"));
|
|
_mbscat((TBYTE*)szKey, (TBYTE*)pszSubkey);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CLASSES_ROOT,
|
|
szKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hKey,
|
|
NULL))
|
|
return FALSE;
|
|
|
|
if (NULL!=pszValue)
|
|
{
|
|
RegSetValueEx( hKey,
|
|
NULL,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *)pszValue,
|
|
_mbsnbcnt((TBYTE*)pszValue, (ULONG)-1) + 1);
|
|
}
|
|
|
|
if (NULL!=pszThreadingModel)
|
|
{
|
|
RegSetValueEx( hKey,
|
|
TEXT("ThreadingModel"),
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *)pszThreadingModel,
|
|
_mbsnbcnt((TBYTE*)pszThreadingModel, (ULONG)-1) + 1);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//=--------------------------------------------------------------------------=
|
|
// CRT stubs
|
|
//=--------------------------------------------------------------------------=
|
|
// these two things are here so the CRTs aren't needed. this is good.
|
|
//
|
|
// basically, the CRTs define this to take in a bunch of stuff. we'll just
|
|
// define them here so we don't get an unresolved external.
|
|
//
|
|
// TODO: if you are going to use the CRTs, then remove this line.
|
|
//
|
|
//extern "C" int __cdecl _fltused = 1;
|
|
|
|
extern "C" int _cdecl _purecall(void)
|
|
{
|
|
FAIL("Pure virtual function called.");
|
|
return 0;
|
|
}
|