2025-11-28 00:35:46 +09:00

314 lines
7.7 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Sample OLEDB Simple Provider
// (C) Copyright 1991 - 1999 Microsoft Corporation. All Rights Reserved.
//
// module MyClassFactory.cpp | The module contains the DLL Entry and Exit
// points, plus the OLE ClassFactory class.
//
//
////////////////////////////////////////////////////////
// Includes
//
////////////////////////////////////////////////////////
#include "Common.h"
#include "MyClassFactory.h"
// Added GUID constant for the sample object:
const GUID CLSID_ospsampc = {0x1e79b2c1,0x77b,0x11d1,{0xb3,0xae,0x0,0xaa,0x0,0xc1,0xa9,0x24}};
////////////////////////////////////////////////////////
// Globals
//
////////////////////////////////////////////////////////
LONG g_cObj = 0L; // # of outstanding objects
LONG g_cLock = 0L; // # of explicit locks set
DWORD g_cAttachedProcesses = 0L; // # of attached processes
HINSTANCE g_hInstance = NULL;
REGENTRY rgRegInfo[] =
{
//SampleOSProvider
{ HKEY_CLASSES_ROOT, "ospsampc", NULL, "Microsoft Sample OLE DB Simple Provider DLL (C++)" },
//CLSID
{ HKEY_CLASSES_ROOT, "ospsampc\\Clsid", NULL, "{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}" },
{ HKEY_CLASSES_ROOT, "CLSID\\{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}", NULL, "ospsampc" },
{ HKEY_CLASSES_ROOT, "CLSID\\{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}\\ProgID", NULL, "ospsampc" },
{ HKEY_CLASSES_ROOT, "CLSID\\{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}\\VersionIndependentProgID", NULL, "ospsampc" },
{ HKEY_CLASSES_ROOT, "CLSID\\{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}\\InprocServer32", "ThreadingModel", "Both" },
{ HKEY_CLASSES_ROOT, "CLSID\\{1E79B2C1-077B-11d1-B3AE-00AA00C1A924}\\InprocServer32", NULL, "%s" },
};
////////////////////////////////////////////////////////
// MyClassFactory
//
////////////////////////////////////////////////////////
MyClassFactory::MyClassFactory()
{
m_cRef = 0;
InterlockedIncrement(&g_cObj);
}
MyClassFactory::~MyClassFactory()
{
InterlockedDecrement(&g_cObj);
}
STDMETHODIMP MyClassFactory::QueryInterface(REFIID riid, void** ppv)
{
if(ppv == NULL)
return E_INVALIDARG;
// Do we support this interface?
if (riid == IID_IUnknown ||
riid == IID_IClassFactory)
{
*ppv = this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
if ((IUnknown*)*ppv)
{
((IUnknown*)*ppv)->AddRef();
}
return S_OK;
}
STDMETHODIMP MyClassFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppv)
{
HRESULT hr = S_OK;
MyDataSource* pMyDataSource = NULL;
if(ppv == NULL)
return E_INVALIDARG;
// In case we fail, we need to zero output arguments
*ppv = NULL;
// If we're given a controlling IUnknown, it must ask for IUnknown.
// Otherwise, the caller will end up getting a pointer to their pUnkOuter
// instead of to the new object we create and will have no way of getting
// back to this new object, so they won't be able to free it. Bad!
if (pUnkOuter && riid != IID_IUnknown)
return E_NOINTERFACE;
//Create a MyDataSource object
if(!(pMyDataSource = new MyDataSource()))
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
// Initialize it
pMyDataSource->AddRef();
if(FAILED(hr = pMyDataSource->Init()))
goto CLEANUP;
//Obtain correct riid
hr = pMyDataSource->QueryInterface(riid, ppv);
CLEANUP:
if((pMyDataSource)) { (pMyDataSource)->Release(); (pMyDataSource) = NULL; }
return hr;
}
STDMETHODIMP MyClassFactory::LockServer(BOOL fLock)
{
if (fLock)
InterlockedIncrement( &g_cLock );
else
InterlockedDecrement( &g_cLock );
return NOERROR;
}
////////////////////////////////////////////////////////
// DllMain
//
////////////////////////////////////////////////////////
BOOL WINAPI DllMain
(
HINSTANCE hInstDLL, //@parm IN | Application Instance Handle
DWORD fdwReason, //@parm IN | Indicated Process or Thread activity
LPVOID lpvReserved //@parm IN | Reserved...
)
{
BOOL fRetVal = FALSE;
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
// Assume successfully initialized
fRetVal = TRUE;
// Do one-time initialization when first process attaches
if (!g_cAttachedProcesses)
{
g_hInstance = hInstDLL;
}
// Do per-process initialization here...
// Remember that another process successfully attached
g_cAttachedProcesses++;
break;
case DLL_PROCESS_DETACH:
// Clean up when the last process is going away
if (g_cAttachedProcesses == 1)
{
}
// Do per-process clean up here...
// Remember that a process has detached
g_cAttachedProcesses--;
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return fRetVal;
}
////////////////////////////////////////////////////////
// DllGetClassObject
//
////////////////////////////////////////////////////////
HRESULT CALLBACK DllGetClassObject
(
REFCLSID rclsid, //@parm IN | CLSID of the object class to be loaded
REFIID riid, //@parm IN | Interface on object to be instantiated
LPVOID * ppvObj //@parm OUT | Pointer to interface that was instantiated
)
{
MyClassFactory * pClassFactory;
HRESULT hr;
// Check for valid ppvObj pointer
if (!ppvObj)
return E_INVALIDARG;
// In case we fail, we need to zero output arguments
*ppvObj = NULL;
// We only service CLSID_SampleOSProvider
if (rclsid != CLSID_ospsampc)
return CLASS_E_CLASSNOTAVAILABLE;
// We only support the IUnknown and IClassFactory interfaces
if (riid != IID_IUnknown &&
riid != IID_IClassFactory)
return E_NOINTERFACE;
// Create our ClassFactory object
if(!(pClassFactory = new MyClassFactory()))
return E_OUTOFMEMORY;
// Get the desired interface on this object
hr = pClassFactory->QueryInterface( riid, ppvObj );
if(FAILED(hr))
delete pClassFactory;
return hr;
}
////////////////////////////////////////////////////////
// DllCanUnloadNow
//
////////////////////////////////////////////////////////
STDAPI DllCanUnloadNow( void )
{
if (!g_cObj && !g_cLock)
return S_OK;
else
return S_FALSE;
}
////////////////////////////////////////////////////////
// DllUnregisterServer
//
////////////////////////////////////////////////////////
STDAPI DllUnregisterServer()
{
int iNumErrors = 0;
// Delete all table entries. Loop in reverse order, since they
// are entered in a basic-to-complex order.
// We cannot delete a key that has subkeys.
// Ignore errors.
for (int i=NUMELEM(rgRegInfo)-1; i>=0; i--)
{
if(FAILED(DelRegEntry(&rgRegInfo[i])))
iNumErrors++;
}
return iNumErrors ? E_FAIL : S_OK;
}
////////////////////////////////////////////////////////
// DllRegisterServer
//
////////////////////////////////////////////////////////
STDAPI DllRegisterServer()
{
HRESULT hr;
HMODULE hModule;
CHAR szBuffer[MAX_NAME_LEN];
CHAR szFullFileName[MAX_PATH+1];
// Get the full path name for this DLL.
if (NULL == (hModule = GetModuleHandle( "ospsampc" )))
return E_FAIL;
if (0 == GetModuleFileName( hModule, szFullFileName, MAX_PATH+1))
return E_FAIL;
// Make a clean start
DllUnregisterServer();
// Loop through s_rgRegInfo, and put everything in it.
// Every entry is based on HKEY_CLASSES_ROOT.
for (int i=0; i<NUMELEM(rgRegInfo); i++)
{
// Fill in any "%s" arguments with the name of this DLL.
wsprintf(szBuffer, rgRegInfo[i].szValue, szFullFileName );
rgRegInfo[i].szValue = szBuffer;
//Set the Registry Entry for this Key
if(FAILED(hr = SetRegEntry(&rgRegInfo[i])))
goto CLEANUP;
}
CLEANUP:
return hr;
}