#include "pch.h" #include #include #include "thisguid.h" #include "thisdll.h" #include "resource.h" #include // Catagory registration. #define DECL_CRTFREE #include // {0CD7A5C0-9F37-11CE-AE65-08002B2E1262} const GUID CLSID_CabFolder = {0x0CD7A5C0L, 0x9F37, 0x11CE, 0xAE, 0x65, 0x08, 0x00, 0x2B, 0x2E, 0x12, 0x62}; CThisDll g_ThisDll; STDAPI_(BOOL) DllMain(HINSTANCE hDll, DWORD dwReason, void *lpRes) { switch(dwReason) { case DLL_PROCESS_ATTACH: SHFusionInitializeFromModule(hDll); g_ThisDll.SetInstance(hDll); break; case DLL_PROCESS_DETACH: SHFusionUninitialize(); break; } return TRUE; } STDAPI DllCanUnloadNow() { return (g_ThisDll.m_cRef.GetRef() == 0) && (g_ThisDll.m_cLock.GetRef() == 0) ? S_OK : S_FALSE; } // Procedure for uninstalling this DLL (given an INF file) void CALLBACK Uninstall(HWND hwndStub, HINSTANCE hInstance, LPTSTR lpszCmdLine, int nCmdShow) { RUNDLLPROC pfnCheckAPI = Uninstall; TCHAR szTitle[100]; TCHAR szPrompt[100 + MAX_PATH]; OSVERSIONINFO osvi; LPTSTR pszSetupDll; LPTSTR pszRunDllExe; if (!lpszCmdLine || lstrlen(lpszCmdLine)>=MAX_PATH) { return; } LoadString(g_ThisDll.GetInstance(),IDS_SUREUNINST,szPrompt,ARRAYSIZE(szPrompt)); LoadString(g_ThisDll.GetInstance(),IDS_THISDLL,szTitle,ARRAYSIZE(szTitle)); if (MessageBox(hwndStub, szPrompt, szTitle, MB_YESNO|MB_ICONSTOP) != IDYES) { return; } ZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { /* Windows 95 uses SetupX */ pszRunDllExe = TEXT("rundll.exe"); pszSetupDll = TEXT("setupx.dll"); } else { /* Windows NT uses SetupAPI */ pszRunDllExe = TEXT("rundll32.exe"); pszSetupDll = TEXT("setupapi.dll"); } WCHAR szFullPathSetupDll[MAX_PATH]; GetSystemDirectory(szFullPathSetupDll, ARRAYSIZE(szFullPathSetupDll)); PathAppend(szFullPathSetupDll, pszSetupDll); wnsprintf(szPrompt, ARRAYSIZE(szPrompt), TEXT("%s,InstallHinfSection DefaultUninstall 132 %s"), szFullPathSetupDll, lpszCmdLine); // Try to win the race before setup finds this DLL still in use. // If we lose, a reboot will be required to get rid of the DLL. SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_ABOVE_NORMAL); WCHAR szFullPathRunDllExe[MAX_PATH]; GetSystemDirectory(szFullPathRunDllExe, ARRAYSIZE(szFullPathRunDllExe)); PathAppend(szFullPathRunDllExe, pszRunDllExe); ShellExecute(hwndStub, NULL, szFullPathRunDllExe, szPrompt, NULL, SW_SHOWMINIMIZED); } // Call ADVPACK for the given section of our resource based INF> // hInstance = resource instance to get REGINST section from // szSection = section name to invoke HRESULT CallRegInstall(HINSTANCE hInstance, LPCSTR szSection) { HRESULT hr = E_FAIL; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); if (hinstAdvPack) { REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall"); if ( pfnri ) { #ifdef WINNT STRENTRY seReg[] = { // These two NT-specific entries must be at the end { "25", "%SystemRoot%" }, { "11", "%SystemRoot%\\system32" }, }; STRTABLE stReg = { ARRAYSIZE(seReg), seReg }; hr = pfnri(hInstance, szSection, &stReg); #else hr = pfnri(hInstance, szSection, NULL); #endif } FreeLibrary(hinstAdvPack); } return hr; } STDAPI DllRegisterServer(void) { CallRegInstall(g_ThisDll.GetInstance(), "RegDll"); // Register as a browseable shell extension. ICatRegister *pcr; HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr); if (SUCCEEDED(hr)) { CATID acatid[1]; acatid[0] = CATID_BrowsableShellExt; pcr->RegisterClassImplCategories(CLSID_CabFolder, 1, acatid); pcr->Release(); } return S_OK; } STDAPI DllUnregisterServer(void) { CallRegInstall(g_ThisDll.GetInstance(), "UnregDll"); return S_OK; } class CThisDllClassFactory : public IClassFactory { public: CThisDllClassFactory(REFCLSID rclsid); // *** IUnknown methods *** STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // *** IClassFactory methods *** STDMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void ** ppvObject); STDMETHODIMP LockServer(BOOL fLock); private: CRefDll m_cRefDll; LONG m_cRef; CLSID m_clsid; }; STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObj) { HRESULT hres; *ppvObj = NULL; if ((rclsid == CLSID_CabFolder) || (rclsid == CLSID_CabViewDataObject)) { CThisDllClassFactory *pcf = new CThisDllClassFactory(rclsid); if (pcf) { hres = pcf->QueryInterface(riid, ppvObj); pcf->Release(); } else hres = E_OUTOFMEMORY; } else hres = E_FAIL; return hres; } STDMETHODIMP CThisDllClassFactory::QueryInterface(REFIID riid, void ** ppvObj) { if ((riid == IID_IUnknown) || (riid == IID_IClassFactory)) { *ppvObj = (void *)(IClassFactory *)this; } else { *ppvObj = NULL; return E_NOINTERFACE; } ((IUnknown *)*ppvObj)->AddRef(); return NOERROR; } CThisDllClassFactory::CThisDllClassFactory(REFCLSID rclsid) : m_cRef(1), m_clsid(rclsid) { } STDMETHODIMP_(ULONG) CThisDllClassFactory::AddRef(void) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CThisDllClassFactory::Release(void) { #if DBG==1 if ( 0 == m_cRef ) { DebugBreak( ); // ref counter problem } #endif ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CThisDllClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void ** ppvObj) { if (pUnkOuter) return CLASS_E_NOAGGREGATION; return (CLSID_CabFolder == m_clsid) ? ::CabFolder_CreateInstance(riid, ppvObj) : ::CabViewDataObject_CreateInstance(riid, ppvObj); } STDMETHODIMP CThisDllClassFactory::LockServer(BOOL fLock) { if (fLock) { g_ThisDll.m_cLock.AddRef(); } else { g_ThisDll.m_cLock.Release(); } return NOERROR; }