/*************************************************************************** * MAINENTRY.CPP * * Main DLL Entry and Required COM Entry Points. * * Copyright ©1999-2004; Microsoft Corporation. All rights reserved. * Written by Microsoft Developer Support Office Integration (PSS DSOI) * * This code is provided via KB 311765 as a sample. It is not a formal * product and has not been tested with all containers or servers. Use it * for educational purposes only. See the EULA.TXT file included in the * KB download for full terms of use and restrictions. * * THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. * ***************************************************************************/ #define INITGUID // Init the GUIDS for the control... #include "dsoframer.h" HINSTANCE v_hModule = NULL; // DLL module handle HANDLE v_hPrivateHeap = NULL; // Private Memory Heap ULONG v_cLocks = 0; // Count of server locks HICON v_icoOffDocIcon = NULL; // Small office icon (for caption bar) BOOL v_fUnicodeAPI = FALSE; // Flag to determine if we should us Unicode API BOOL v_fWindows2KPlus = FALSE; CRITICAL_SECTION v_csecThreadSynch; //////////////////////////////////////////////////////////////////////// // DllMain -- OCX Main Entry // // extern "C" BOOL APIENTRY DllMain(HINSTANCE hDllHandle, DWORD dwReason, LPVOID /*lpReserved*/) { switch (dwReason) { case DLL_PROCESS_ATTACH: v_hModule = hDllHandle; v_hPrivateHeap = HeapCreate(0, 0x1000, 0); v_icoOffDocIcon = (HICON)LoadImage(hDllHandle, MAKEINTRESOURCE(IDI_SMALLOFFDOC), IMAGE_ICON, 16, 16, 0); { DWORD dwVersion = GetVersion(); v_fUnicodeAPI = ((dwVersion & 0x80000000) == 0); v_fWindows2KPlus = ((v_fUnicodeAPI) && (LOBYTE(LOWORD(dwVersion)) > 4)); } InitializeCriticalSection(&v_csecThreadSynch); DisableThreadLibraryCalls(hDllHandle); break; case DLL_PROCESS_DETACH: if (v_icoOffDocIcon) DeleteObject(v_icoOffDocIcon); if (v_hPrivateHeap) HeapDestroy(v_hPrivateHeap); DeleteCriticalSection(&v_csecThreadSynch); break; } return TRUE; } #ifdef DSO_MIN_CRT_STARTUP extern "C" BOOL APIENTRY _DllMainCRTStartup(HINSTANCE hDllHandle, DWORD dwReason, LPVOID lpReserved) {return DllMain(hDllHandle, dwReason, lpReserved);} #endif //////////////////////////////////////////////////////////////////////// // Standard COM DLL Entry Points // // //////////////////////////////////////////////////////////////////////// // DllCanUnloadNow // // STDAPI DllCanUnloadNow() { return ((v_cLocks == 0) ? S_OK : S_FALSE); } //////////////////////////////////////////////////////////////////////// // DllGetClassObject // // Returns IClassFactory instance for FramerControl. We only support // this one object for creation. // STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv) { HRESULT hr; CDsoFramerClassFactory* pcf; CHECK_NULL_RETURN(ppv, E_POINTER); *ppv = NULL; // The only component we can create is the BinderControl... if (rclsid != CLSID_FramerControl) return CLASS_E_CLASSNOTAVAILABLE; // Create the needed class factory... pcf = new CDsoFramerClassFactory(); CHECK_NULL_RETURN(pcf, E_OUTOFMEMORY); // Get requested interface. if (FAILED(hr = pcf->QueryInterface(riid, ppv))) { *ppv = NULL; delete pcf; } else InterlockedIncrement((LPLONG)&v_cLocks); return hr; } //////////////////////////////////////////////////////////////////////// // DllRegisterServer // // Registration of the OCX. // STDAPI DllRegisterServer() { HRESULT hr = S_OK; HKEY hk, hk2; DWORD dwret; CHAR szbuffer[256]; LPWSTR pwszModule; ITypeInfo* pti; // If we can't find the path to the DLL, we can't register... if (!FGetModuleFileName(v_hModule, &pwszModule)) return E_FAIL; // Setup the CLSID. This is the most important. If there is a critical failure, // we will set HR = GetLastError and return... if ((dwret = RegCreateKeyEx(HKEY_CLASSES_ROOT, "CLSID\\"DSOFRAMERCTL_CLSIDSTR, 0, NULL, 0, KEY_WRITE, NULL, &hk, NULL)) != ERROR_SUCCESS) { DsoMemFree(pwszModule); return HRESULT_FROM_WIN32(dwret); } lstrcpy(szbuffer, DSOFRAMERCTL_SHORTNAME); RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); // Setup the InprocServer32 key... dwret = RegCreateKeyEx(hk, "InprocServer32", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, "Apartment"); RegSetValueEx(hk2, "ThreadingModel", 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); // We call a wrapper function for this setting since the path should be // stored in Unicode to handle non-ANSI file path names on some systems. // This wrapper will convert the path to ANSI if we are running on Win9x. // The rest of the Reg calls should be OK in ANSI since they do not // contain non-ANSI/Unicode-specific characters... if (!FSetRegKeyValue(hk2, pwszModule)) hr = E_ACCESSDENIED; RegCloseKey(hk2); dwret = RegCreateKeyEx(hk, "ProgID", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, DSOFRAMERCTL_PROGID); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } } else hr = HRESULT_FROM_WIN32(dwret); if (SUCCEEDED(hr)) { dwret = RegCreateKeyEx(hk, "Control", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { RegCloseKey(hk2); } else hr = HRESULT_FROM_WIN32(dwret); } // If we succeeded so far, andle the remaining (non-critical) reg keys... if (SUCCEEDED(hr)) { dwret = RegCreateKeyEx(hk, "ToolboxBitmap32", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { LPWSTR pwszT = DsoCopyStringCat(pwszModule, L",102"); if (pwszT) { FSetRegKeyValue(hk2, pwszT); DsoMemFree(pwszT); } RegCloseKey(hk2); } dwret = RegCreateKeyEx(hk, "TypeLib", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, DSOFRAMERCTL_TLIBSTR); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } dwret = RegCreateKeyEx(hk, "Version", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, DSOFRAMERCTL_VERSIONSTR); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } dwret = RegCreateKeyEx(hk, "MiscStatus", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, "131473"); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } dwret = RegCreateKeyEx(hk, "DataFormats\\GetSet\\0", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL); if (dwret == ERROR_SUCCESS) { lstrcpy(szbuffer, "3,1,32,1"); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } } RegCloseKey(hk); DsoMemFree(pwszModule); // This should catch any critical failures during setup of CLSID... RETURN_ON_FAILURE(hr); // Setup the ProgID (non-critical)... if (RegCreateKeyEx(HKEY_CLASSES_ROOT, DSOFRAMERCTL_PROGID, 0, NULL, 0, KEY_WRITE, NULL, &hk, NULL) == ERROR_SUCCESS) { lstrcpy(szbuffer, DSOFRAMERCTL_FULLNAME); RegSetValueEx(hk, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); if (RegCreateKeyEx(hk, "CLSID", 0, NULL, 0, KEY_WRITE, NULL, &hk2, NULL) == ERROR_SUCCESS) { lstrcpy(szbuffer, DSOFRAMERCTL_CLSIDSTR); RegSetValueEx(hk2, NULL, 0, REG_SZ, (BYTE *)szbuffer, lstrlen(szbuffer)); RegCloseKey(hk2); } RegCloseKey(hk); } // Load the type info (this should register the lib once)... hr = DsoGetTypeInfoEx(LIBID_DSOFramer, 0, DSOFRAMERCTL_VERSION_MAJOR, DSOFRAMERCTL_VERSION_MINOR, v_hModule, CLSID_FramerControl, &pti); if (SUCCEEDED(hr)) pti->Release(); return hr; } //////////////////////////////////////////////////////////////////////// // RegRecursiveDeleteKey // // Helper function called by DllUnregisterServer for nested key removal. // static HRESULT RegRecursiveDeleteKey(HKEY hkParent, LPCSTR pszSubKey) { HRESULT hr = S_OK; HKEY hk; DWORD dwret, dwsize; FILETIME time ; CHAR szbuffer[512]; dwret = RegOpenKeyEx(hkParent, pszSubKey, 0, KEY_ALL_ACCESS, &hk); if (dwret != ERROR_SUCCESS) return HRESULT_FROM_WIN32(dwret); // Enumerate all of the decendents of this child... dwsize = 510 ; while (RegEnumKeyEx(hk, 0, szbuffer, &dwsize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) { // If there are any sub-folders, delete them first (to make NT happy)... hr = RegRecursiveDeleteKey(hk, szbuffer); if (FAILED(hr)) break; dwsize = 510; } // Close the child... RegCloseKey(hk); RETURN_ON_FAILURE(hr); // Delete this child. dwret = RegDeleteKey(hkParent, pszSubKey); if (dwret != ERROR_SUCCESS) hr = HRESULT_FROM_WIN32(dwret); return hr; } //////////////////////////////////////////////////////////////////////// // DllUnregisterServer // // Removal code for the OCX. // STDAPI DllUnregisterServer() { HRESULT hr; hr = RegRecursiveDeleteKey(HKEY_CLASSES_ROOT, "CLSID\\"DSOFRAMERCTL_CLSIDSTR); if (SUCCEEDED(hr)) { RegRecursiveDeleteKey(HKEY_CLASSES_ROOT, DSOFRAMERCTL_PROGID); RegRecursiveDeleteKey(HKEY_CLASSES_ROOT, "TypeLib\\"DSOFRAMERCTL_TLIBSTR); } // This means the key does not exist (i.e., the DLL // was alreay unregistered, so return OK)... if (hr == 0x80070002) hr = S_OK; return hr; }