274 lines
7.2 KiB
C++
274 lines
7.2 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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 <advpub.h> // REGINSTALL
|
||
|
#include <shfusion.h>
|
||
|
#include "uihooks.h" // CSCUIExt_CleanupHooks
|
||
|
#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:
|
||
|
CSCUIExt_CleanupHooks();
|
||
|
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()
|
||
|
{
|
||
|
if (InterlockedDecrement(&m_cRef))
|
||
|
return m_cRef;
|
||
|
|
||
|
delete this;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|