//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: dll.cpp // // Authors; // Jeff Saathoff (jeffreys) // // Notes; // Core entry points for the DLL //-------------------------------------------------------------------------- #include "pch.h" #include // REGINSTALL #include #include "msgbox.h" STDAPI COfflineFilesFolder_CreateInstance(REFIID riid, void **ppv); STDAPI COfflineFilesOptions_CreateInstance(REFIID riid, void **ppv); /////////////////////////////////////////////////////////////////////////////// // // // Global variables // // // /////////////////////////////////////////////////////////////////////////////// LONG g_cRefCount = 0; HINSTANCE g_hInstance = NULL; CLIPFORMAT g_cfShellIDList = 0; HANDLE g_heventTerminate = NULL; HANDLE g_hmutexAdminPin = NULL; typedef HRESULT (WINAPI *PFNCREATEINSTANCE)(REFIID, void **); class CClassFactory : IClassFactory { LONG m_cRef; PFNCREATEINSTANCE m_pfnCreateInstance; public: CClassFactory(PFNCREATEINSTANCE pfnCreate) : m_cRef(1), m_pfnCreateInstance(pfnCreate) { DllAddRef(); } ~CClassFactory() { DllRelease(); } // IUnknown methods STDMETHODIMP QueryInterface(REFIID, LPVOID FAR *); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IClassFactory methods STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR *); STDMETHODIMP LockServer(BOOL); }; STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) { switch (dwReason) { case DLL_PROCESS_ATTACH: #ifndef DEBUG DisableThreadLibraryCalls(hInstance); #endif g_hInstance = hInstance; // instance handle... SHFusionInitializeFromModuleID(hInstance, 124); g_cfShellIDList = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_SHELLIDLIST); DebugProcessAttach(); TraceSetMaskFromCLSID(CLSID_CscShellExt); break; case DLL_PROCESS_DETACH: DebugProcessDetach(); if (NULL != g_heventTerminate) CloseHandle(g_heventTerminate); if (NULL != g_hmutexAdminPin) CloseHandle(g_hmutexAdminPin); SHFusionUninitialize(); break; case DLL_THREAD_DETACH: DebugThreadDetach(); break; } return TRUE; } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { HRESULT hr; PFNCREATEINSTANCE pfnCreateInstance = NULL; *ppv = NULL; if (IsOS(OS_PERSONAL)) { // // Offline Files is not available on 'Personal' SKU // return CLASS_E_CLASSNOTAVAILABLE; } if (IsEqualCLSID(rclsid, CLSID_OfflineFilesOptions)) { // // Post Win2000: // The Offline Files options page is always available // even if TS is in a mode incompatible with CSC. In such // cases we'll display the Options page but replace the controls // with static text telling the user to place TS in a CSC- // compatible mode. Once they do this, the text will be replaced // with the normal controls to manage CSC. // pfnCreateInstance = COfflineFilesOptions_CreateInstance; } else { // // The objects at the top here can be created even // when CSC is disabled. // if (IsEqualCLSID(rclsid, CLSID_OfflineFilesFolder)) { if (CConfig::GetSingleton().NoCacheViewer()) { // // Policy can specify that the user not have access to the // Offline Files folder (aka viewer). If this policy is set, // the user should have no way to get to this point through // the UI. This check is a small dose of paranoia. // return CLASS_E_CLASSNOTAVAILABLE; } pfnCreateInstance = COfflineFilesFolder_CreateInstance; } else { // // The objects below here require CSC. That is, it // makes no sense for them to be created when CSC // is disabled. // if (!IsCSCEnabled()) return E_FAIL; if (IsEqualCLSID(rclsid, CLSID_CscShellExt)) pfnCreateInstance = CCscShellExt::CreateInstance; else if (IsEqualCLSID(rclsid, CLSID_CscUpdateHandler)) pfnCreateInstance = CCscUpdate::CreateInstance; else if (IsEqualCLSID(rclsid, CLSID_CscVolumeCleaner)) pfnCreateInstance = CCscVolumeCleaner::CreateInstance; else if (IsEqualCLSID(rclsid, CLSID_CscVolumeCleaner2)) pfnCreateInstance = CCscVolumeCleaner::CreateInstance2; else return CLASS_E_CLASSNOTAVAILABLE; } } CClassFactory *pClassFactory = new CClassFactory(pfnCreateInstance); if (pClassFactory) { hr = pClassFactory->QueryInterface(riid, ppv); pClassFactory->Release(); // release initial ref } else hr = E_OUTOFMEMORY; return hr; } STDAPI DllCanUnloadNow(void) { return (g_cRefCount == 0 ? S_OK : S_FALSE); } STDAPI_(void) DllAddRef(void) { InterlockedIncrement(&g_cRefCount); } STDAPI_(void) DllRelease(void) { InterlockedDecrement(&g_cRefCount); } HRESULT CallRegInstall(HMODULE hModule, LPCSTR pszSection) { HRESULT hr = E_FAIL; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); if (hinstAdvPack) { REGINSTALL pfnRegInstall = (REGINSTALL)GetProcAddress(hinstAdvPack, achREGINSTALL); if (pfnRegInstall) hr = pfnRegInstall(hModule, pszSection, NULL); FreeLibrary(hinstAdvPack); } return hr; } STDAPI DllRegisterServer(void) { return CallRegInstall(g_hInstance, "DefaultInstall"); } STDAPI DllUnregisterServer(void) { return CallRegInstall(g_hInstance, "DefaultUninstall"); } STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CClassFactory, IClassFactory), { 0 }, }; return QISearch(this, qit, riid, ppv); } STDMETHODIMP_(ULONG) CClassFactory::AddRef() { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CClassFactory::Release() { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) { HRESULT hr = E_UNEXPECTED; *ppv = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; if (m_pfnCreateInstance) hr = m_pfnCreateInstance(riid, ppv); return hr; } STDMETHODIMP CClassFactory::LockServer(BOOL fLock) { if (fLock) DllAddRef(); else DllRelease(); return S_OK; }