319 lines
9.7 KiB
C++
319 lines
9.7 KiB
C++
/***************************************************************************
|
|
* 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;
|
|
}
|