/*************************************************************************** * dll.c * * Standard DLL entry-point functions * ***************************************************************************/ // Note: Proxy/Stub Information from ATL // // To merge the proxy/stub code into the object DLL, add the file // dlldatax.c to the project. Make sure precompiled headers // are turned off for this file, and add _MERGE_PROXYSTUB to the // defines for the project. // // If you are not running WinNT4.0 or Win95 with DCOM, then you // need to remove the following define from dlldatax.c // #define _WIN32_WINNT 0x0400 // // Further, if you are running MIDL without /Oicf switch, you also // need to remove the following define from dlldatax.c. // #define USE_STUBLESS_PROXY // // Modify the custom build rule for shappmgr.idl by adding the following // files to the Outputs. // shappmgr_p.c // dlldata.c // To build a separate proxy/stub DLL, // run nmake -f shappmgrps.mk in the project directory. #include "priv.h" #include "sccls.h" #ifndef DOWNLEVEL #include "adcctl.h" #endif //DOWNLEVEL #include #include // For REGINSTALL // Define GUIDs extern "C" { HINSTANCE g_hinst = NULL; int g_cxIcon; int g_cyIcon; BOOL g_bMirroredOS; LONG g_cRefThisDll = 0; // per-instance #ifdef WX86 // // from uninstal.c // extern BOOL bWx86Enabled; BOOL IsWx86Enabled(VOID); #endif }; #ifndef DOWNLEVEL CComModule _Module; // ATL module object BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_ADCCtl, CADCCtl) END_OBJECT_MAP() #endif //DOWNLEVEL /*---------------------------------------------------------- Purpose: DllEntryPoint */ BOOL APIENTRY DllMain( IN HINSTANCE hinst, IN DWORD dwReason, IN LPVOID lpReserved) { #ifdef _MERGE_PROXYSTUB if (!PrxDllMain(hInstance, dwReason, lpReserved)) return FALSE; #endif switch(dwReason) { case DLL_PROCESS_ATTACH: #ifndef DOWNLEVEL _Module.Init(ObjectMap, hinst); #endif //DOWNLEVEL DisableThreadLibraryCalls(hinst); SHFusionInitializeFromModule(hinst); #ifdef DEBUG CcshellGetDebugFlags(); if (g_dwBreakFlags & BF_ONDLLLOAD) DebugBreak(); #endif g_hinst = hinst; g_cxIcon = GetSystemMetrics(SM_CXICON); g_cyIcon = GetSystemMetrics(SM_CYICON); g_bMirroredOS = IS_MIRRORING_ENABLED(); #ifdef WX86 bWx86Enabled = IsWx86Enabled(); #endif break; case DLL_PROCESS_DETACH: #ifndef DOWNLEVEL _Module.Term(); #endif //DOWNLEVEL SHFusionUninitialize(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: // We shouldn't get these because we called // DisableThreadLibraryCalls(). ASSERT_MSG(0, "DllMain received DLL_THREAD_ATTACH/DETACH! We're not expecting this."); break; default: break; } return TRUE; } /*---------------------------------------------------------- Purpose: This function provides the DLL version info. This allows the caller to distinguish running NT SUR vs. Win95 shell vs. Nashville, etc. The caller must GetProcAddress this function. Returns: NO_ERROR ERROR_INVALID_PARAMETER if pinfo is invalid */ // All we have to do is declare this puppy and CCDllGetVersion does the rest DLLVER_DUALBINARY(VER_PRODUCTVERSION_DW, VER_PRODUCTBUILD_QFE); /*---------------------------------------------------------- Purpose: Calls the ADVPACK entry-point which executes an inf file section. */ HRESULT _CallRegInstall(LPCSTR szSection, BOOL bUninstall) { HRESULT hr = E_FAIL; HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); if (hinstAdvPack) { REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall"); if (pfnri) { #ifdef WINNT STRENTRY seReg[] = { { "25", "%SystemRoot%" }, { "11", "%SystemRoot%\\system32" }, }; STRTABLE stReg = { ARRAYSIZE(seReg), seReg }; hr = pfnri(g_hinst, szSection, &stReg); #else hr = pfnri(g_hinst, szSection, NULL); #endif if (bUninstall) { // ADVPACK will return E_UNEXPECTED if you try to uninstall // (which does a registry restore) on an INF section that was // never installed. We uninstall sections that may never have // been installed, so ignore this error hr = ((E_UNEXPECTED == hr) ? S_OK : hr); } } FreeLibrary(hinstAdvPack); } return hr; } /*---------------------------------------------------------- Purpose: Install/uninstall user settings */ STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { HRESULT hr = S_OK; HRESULT hrExternal = S_OK; #ifdef DEBUG if (IsFlagSet(g_dwBreakFlags, BF_ONAPIENTER)) { TraceMsg(TF_ALWAYS, "Stopping in DllInstall"); DEBUG_BREAK; } #endif if (bInstall) { // Delete any old registration entries, then add the new ones. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall. // (The inf engine doesn't guarantee DelReg/AddReg order, that's // why we explicitly unreg and reg here.) // hr = THR(_CallRegInstall("RegDll", FALSE)); if (SUCCEEDED(hrExternal)) hrExternal = hr; } else { hr = THR(_CallRegInstall("UnregDll", TRUE)); if (SUCCEEDED(hrExternal)) hrExternal = hr; } return hrExternal; } /*---------------------------------------------------------- Purpose: Returns a class factory to create an object of the requested type. */ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) { TraceMsg(TF_OBJLIFE, "DllGetClassObject called with riid=%x (%x)", riid, &riid); #ifdef _MERGE_PROXYSTUB if (PrxDllGetClassObject(rclsid, riid, ppv) == S_OK) return S_OK; #endif if (riid == IID_IClassFactory || riid == IID_IUnknown) { // Try our native class factory HRESULT hres = GetClassObject(rclsid, riid, ppv); #ifndef DOWNLEVEL if (FAILED(hres)) { // Try the ATL class factory hres = _Module.GetClassObject(rclsid, riid, ppv); } #endif //DOWNLEVEL return hres; } *ppv = NULL; return CLASS_E_CLASSNOTAVAILABLE; } STDAPI DllCanUnloadNow(void) { #ifdef _MERGE_PROXYSTUB if (PrxDllCanUnloadNow() != S_OK) return S_FALSE; #endif #ifndef DOWNLEVEL // This component uses ATL and natively-implemented COM objects if (0 != g_cRefThisDll || 0 != _Module.GetLockCount()) return S_FALSE; #endif //DOWNLEVEL TraceMsg(DM_TRACE, "DllCanUnloadNow returning S_OK (bye, bye...)"); return S_OK; } STDAPI_(void) DllAddRef(void) { InterlockedIncrement(&g_cRefThisDll); ASSERT(g_cRefThisDll < 1000); // reasonable upper limit } STDAPI_(void) DllRelease(void) { InterlockedDecrement(&g_cRefThisDll); ASSERT(g_cRefThisDll >= 0); // don't underflow } STDAPI DllRegisterServer(void) { HRESULT hres = S_OK; #ifdef _MERGE_PROXYSTUB hres = THR(PrxDllRegisterServer()); if (FAILED(hres)) return hres; #endif #ifndef DOWNLEVEL // registers object, typelib and all interfaces in typelib hres = THR(_Module.RegisterServer(TRUE)); #endif //DOWNLEVEL return hres; } STDAPI DllUnregisterServer(void) { #ifdef _MERGE_PROXYSTUB PrxDllUnregisterServer(); #endif #ifndef DOWNLEVEL _Module.UnregisterServer(); #endif //DOWNLEVEL return S_OK; }