//-------------------------------------------------------------------- // 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