// // standard inprocserver DLL code, you should not need to mess with this // #include "project.h" HANDLE g_hInst = NULL; LONG g_cRefDll = 0; // Number of locks on this DLL STDAPI_(void) DllAddRef() { InterlockedIncrement(&g_cRefDll); } STDAPI_(void) DllRelease() { ASSERT( 0 != g_cRefDll ); InterlockedDecrement(&g_cRefDll); } STDAPI_(BOOL) DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID reserved) { if (fdwReason == DLL_PROCESS_ATTACH) { g_hInst = hInstDll; } return TRUE; } STDMETHODIMP CSampleClassFactory::QueryInterface(REFIID riid, void **ppvObject) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) { *ppvObject = (void *)this; AddRef(); return NOERROR; } *ppvObject = NULL; return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CSampleClassFactory::AddRef(void) { DllAddRef(); return 2; } STDMETHODIMP_(ULONG) CSampleClassFactory::Release(void) { DllRelease(); return 1; } STDMETHODIMP CSampleClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) { *ppvObject = NULL; if (NULL != pUnkOuter) return CLASS_E_NOAGGREGATION; CSampleObtainRating *pObj = new CSampleObtainRating; /* doing this does implicit AddRef() */ if (NULL == pObj) return E_OUTOFMEMORY; HRESULT hr = pObj->QueryInterface(riid, ppvObject); pObj->Release(); return hr; } STDMETHODIMP CSampleClassFactory::LockServer(BOOL fLock) { if (fLock) DllAddRef(); else DllRelease(); return NOERROR; } // // standard COM DLL self registering entry point // STDAPI DllRegisterServer(void) { HKEY hkeyCLSID; LONG err; TCHAR szPath[MAX_PATH]; // get path to this DLL GetModuleFileName(g_hInst, szPath, MAX_PATH); /* First register our CLSID under HKEY_CLASSES_ROOT. */ err = ::RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", &hkeyCLSID); if (err == ERROR_SUCCESS) { HKEY hkeyOurs; err = ::RegCreateKey(hkeyCLSID, ::szOurGUID, &hkeyOurs); if (err == ERROR_SUCCESS) { HKEY hkeyInproc; err = ::RegCreateKey(hkeyOurs, "InProcServer32", &hkeyInproc); if (err == ERROR_SUCCESS) { err = ::RegSetValueEx(hkeyInproc, NULL, 0, REG_SZ, (LPBYTE)szPath, lstrlen(szPath) + 1); if (err == ERROR_SUCCESS) { err = ::RegSetValueEx(hkeyInproc, "ThreadingModel", 0, REG_SZ, (LPBYTE)"Apartment", 10); } ::RegCloseKey(hkeyInproc); } ::RegCloseKey(hkeyOurs); } ::RegCloseKey(hkeyCLSID); /* Now install ourselves as a ratings helper. */ if (err == ERROR_SUCCESS) { err = ::RegCreateKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Rating Helpers", &hkeyCLSID); if (err == ERROR_SUCCESS) { err = ::RegSetValueEx(hkeyCLSID, ::szOurGUID, 0, REG_SZ, (LPBYTE)"", 2); ::RegCloseKey(hkeyCLSID); } } } if (err == ERROR_SUCCESS) return S_OK; else return HRESULT_FROM_WIN32(err); } // // standard COM DLL self registering entry point // STDAPI DllUnregisterServer(void) { HKEY hkeyCLSID; LONG err; err = ::RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", &hkeyCLSID); if (err == ERROR_SUCCESS) { HKEY hkeyOurs; err = ::RegOpenKey(hkeyCLSID, ::szOurGUID, &hkeyOurs); if (err == ERROR_SUCCESS) { err = ::RegDeleteKey(hkeyOurs, "InProcServer32"); ::RegCloseKey(hkeyOurs); if (err == ERROR_SUCCESS) err = ::RegDeleteKey(hkeyCLSID, ::szOurGUID); } ::RegCloseKey(hkeyCLSID); if (err == ERROR_SUCCESS) { err = ::RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Rating Helpers", &hkeyCLSID); if (err == ERROR_SUCCESS) { err = ::RegDeleteValue(hkeyCLSID, ::szOurGUID); ::RegCloseKey(hkeyCLSID); } } } if (err == ERROR_SUCCESS) return S_OK; else return HRESULT_FROM_WIN32(err); } // // standard COM DLL entry point // STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { if (IsEqualCLSID(rclsid, CLSID_Sample)) { static CSampleClassFactory cf; /* note, declaring this doesn't constitute a reference */ return cf.QueryInterface(riid, ppv); /* will AddRef() if successful */ } // to make this support more com objects add them here *ppv = NULL; return CLASS_E_CLASSNOTAVAILABLE;; } // // standard COM DLL entry point // STDAPI DllCanUnloadNow(void) { return g_cRefDll == 0 ? S_OK : S_FALSE; }