793 lines
24 KiB
C++
793 lines
24 KiB
C++
|
// Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
|
||
|
|
||
|
//
|
||
|
// implements all exported DLL functions for the program, as well as a few
|
||
|
// others that will be used by same
|
||
|
//
|
||
|
#include "header.h"
|
||
|
#include "internet.h"
|
||
|
|
||
|
#include "AutoObj.H"
|
||
|
#include "ClassF.H"
|
||
|
#include "Unknown.H"
|
||
|
#include "strtable.h"
|
||
|
#include "hhifc.h"
|
||
|
#include "hhsort.h"
|
||
|
|
||
|
#include "resource.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static const char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#include "atlinc.h" // includes for ATL.
|
||
|
|
||
|
#include "iterror.h"
|
||
|
#include "itSort.h"
|
||
|
#include "itSortid.h"
|
||
|
#include "hhsyssrt.h"
|
||
|
#include "hhfinder.h"
|
||
|
|
||
|
#include "msitstg.h"
|
||
|
|
||
|
// Only including for the pahwnd declaration.
|
||
|
#include "secwin.h"
|
||
|
|
||
|
// So we can cleanup the lasterror object.
|
||
|
#include "lasterr.h"
|
||
|
|
||
|
#include <atlimpl.cpp>
|
||
|
|
||
|
extern HMODULE g_hmodMSI; // msi.dll module handle
|
||
|
|
||
|
CHtmlHelpModule _Module;
|
||
|
|
||
|
BEGIN_OBJECT_MAP(ObjectMap)
|
||
|
OBJECT_ENTRY(CLSID_HHSysSort, CHHSysSort)
|
||
|
OBJECT_ENTRY(CLSID_HHFinder, CHHFinder)
|
||
|
END_OBJECT_MAP()
|
||
|
|
||
|
const IID IID_ICatRegister = {0x0002E012,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
|
||
|
const GUID CATID_SafeForScripting = {0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
|
||
|
const GUID CATID_SafeForInitializing = {0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,0x00,0xaa,0x00,0x6c,0x42,0xc4}};
|
||
|
|
||
|
// In 1996-1997 alone, these two constants appeared and disappeared in 3 different
|
||
|
// header files. I got tired or finding out which !@$! header file they
|
||
|
// got moved to this time and just defined them here.
|
||
|
|
||
|
#define LANG_ARABIC 0x01
|
||
|
#define LANG_HEBREW 0x0d
|
||
|
|
||
|
static const char txtCplDesktop[] = "Control Panel\\Desktop\\ResourceLocale";
|
||
|
static const char txtShellOpenFmt[] = "%s\\shell\\open\\%s";
|
||
|
static const char txtCommand[] = "command";
|
||
|
static const char txtStdOpen[] = "[open(\"%1\")]";
|
||
|
static const char txtStdArg[] = " %1";
|
||
|
static const char txtChmFile[] = "chm.file";
|
||
|
static const char txtHhExe[] = "hh.exe";
|
||
|
static const char txtItssDll[] = "itss.dll";
|
||
|
static const char txtItirclDll[] = "itircl.dll";
|
||
|
static const char txtDllRegisterServer[] = "DllRegisterServer";
|
||
|
static const char txtDllUnRegisterServer[] = "DllUnregisterServer";
|
||
|
static const char txtIE4[] = "SOFTWARE\\Microsoft\\Internet Explorer";
|
||
|
static const char txtVersion[] = "version";
|
||
|
static const char txtMouseWheel[] = "MSWHEEL_ROLLMSG";
|
||
|
|
||
|
static const char txtStringGuid[] = "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}";
|
||
|
static const char txtInProc[] = "CLSID\\%s\\InprocServer32";
|
||
|
|
||
|
static void SetRegKey(LPCTSTR pszKey, LPCTSTR pszValue);
|
||
|
void RegisterHH(PCSTR pszHHPath); // also called by hh.cpp
|
||
|
extern HANDLE g_hsemMemory;
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
|
||
|
// private routines for this file.
|
||
|
|
||
|
int IndexOfOleObject(REFCLSID);
|
||
|
HRESULT RegisterAllObjects(void);
|
||
|
HRESULT UnregisterAllObjects(void);
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// StringFromGuidA
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// returns an ANSI string from a CLSID or GUID
|
||
|
//
|
||
|
// Parameters:
|
||
|
// REFIID - [in] clsid to make string out of.
|
||
|
// LPSTR - [in/out] buffer in which to place resultant GUID.
|
||
|
//
|
||
|
// Output:
|
||
|
// int - number of chars written out.
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
int StringFromGuidA( CLSID riid, LPSTR pszBuf )
|
||
|
{
|
||
|
return wsprintf( (char*) pszBuf,
|
||
|
txtStringGuid,
|
||
|
riid.Data1, riid.Data2, riid.Data3,
|
||
|
riid.Data4[0], riid.Data4[1], riid.Data4[2], riid.Data4[3],
|
||
|
riid.Data4[4], riid.Data4[5], riid.Data4[6], riid.Data4[7]);
|
||
|
}
|
||
|
|
||
|
#define GUID_STR_LEN 40
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// GetRegisteredLocation
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// Returns the registered location of an inproc server given the CLSID
|
||
|
//
|
||
|
// HKEY_CLASSES_ROOT\CLSID\<CLSID>\InprocServer32 = <path to local server>
|
||
|
//
|
||
|
// Parameters:
|
||
|
// REFCLSID - [in] CLSID of the object
|
||
|
// LPTSTR - [in/out] Pathname
|
||
|
//
|
||
|
// Output:
|
||
|
// BOOL - FALSE means couldn't find it
|
||
|
|
||
|
BOOL GetRegisteredLocation( CLSID riid, LPTSTR pszPathname )
|
||
|
{
|
||
|
BOOL bReturn = FALSE;
|
||
|
HKEY hKey = NULL;
|
||
|
char szGuidStr[GUID_STR_LEN];
|
||
|
char szScratch[MAX_PATH];
|
||
|
|
||
|
if( !StringFromGuidA( riid, szGuidStr ) )
|
||
|
return FALSE;
|
||
|
|
||
|
wsprintf( szScratch, txtInProc, szGuidStr );
|
||
|
if( RegOpenKeyEx( HKEY_CLASSES_ROOT, szScratch, 0, KEY_READ, &hKey ) == ERROR_SUCCESS ) {
|
||
|
DWORD dwSize = MAX_PATH;
|
||
|
if( RegQueryValueExA( hKey, "", 0, 0, (BYTE*) szScratch, &dwSize ) == ERROR_SUCCESS ) {
|
||
|
strcpy( pszPathname, szScratch );
|
||
|
bReturn = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( hKey )
|
||
|
RegCloseKey( hKey );
|
||
|
|
||
|
return bReturn;
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, void *pvReserved)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
switch (dwReason) {
|
||
|
// set up some global variables, and get some OS/Version information
|
||
|
// set up.
|
||
|
//
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
{
|
||
|
//NOTE: Do not handle resources until after the _Module.Init call below.
|
||
|
|
||
|
OSVERSIONINFO versionInfo;
|
||
|
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
|
||
|
GetVersionEx(&versionInfo);
|
||
|
|
||
|
g_bWinNT5 = ((versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (versionInfo.dwMajorVersion >= 5));
|
||
|
g_bWin98 = (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && ((versionInfo.dwMajorVersion > 4)
|
||
|
|| ((versionInfo.dwMajorVersion == 4) && (versionInfo.dwMinorVersion > 0)));
|
||
|
|
||
|
// Check version
|
||
|
DWORD dwVer = GetVersion();
|
||
|
DWORD dwWinVer;
|
||
|
|
||
|
// swap the two lowest bytes of dwVer so that the major and minor version
|
||
|
// numbers are in a usable order.
|
||
|
// for dwWinVer: high byte = major version, low byte = minor version
|
||
|
// OS Sys_WinVersion (as of 5/2/95)
|
||
|
// =-------------= =-------------=
|
||
|
// Win95 0x035F (3.95)
|
||
|
// WinNT ProgMan 0x0333 (3.51)
|
||
|
// WinNT Win95 UI 0x0400 (4.00)
|
||
|
//
|
||
|
dwWinVer = (UINT)(((dwVer & 0xFF) << 8) | ((dwVer >> 8) & 0xFF));
|
||
|
g_fSysWinNT = FALSE;
|
||
|
g_fSysWin95 = FALSE;
|
||
|
g_fSysWin95Shell = FALSE;
|
||
|
|
||
|
if (dwVer < 0x80000000) {
|
||
|
g_fSysWinNT = TRUE;
|
||
|
g_fSysWin95Shell = (dwWinVer >= 0x0334);
|
||
|
} else {
|
||
|
g_fSysWin95 = TRUE;
|
||
|
g_fSysWin95Shell = TRUE;
|
||
|
}
|
||
|
if ( !g_fCoInitialized )
|
||
|
{
|
||
|
OleInitialize(NULL);
|
||
|
g_fCoInitialized = TRUE; // so that we call CoUninitialize() when dll is unloaded
|
||
|
}
|
||
|
|
||
|
// Initialize ATL's module information.
|
||
|
_Module.Init(ObjectMap, (HINSTANCE) hInstance);
|
||
|
DisableThreadLibraryCalls((HINSTANCE) hInstance);
|
||
|
|
||
|
// Now it is okay to read the resources.
|
||
|
g_fDBCSSystem = (BOOL) GetSystemMetrics(SM_DBCSENABLED);
|
||
|
g_lcidSystem = GetUserDefaultLCID();
|
||
|
|
||
|
// Determine if we are on a BiDi system
|
||
|
|
||
|
g_langSystem = PRIMARYLANGID(LANGIDFROMLCID(g_lcidSystem));
|
||
|
|
||
|
// Get the language of the UI (Satalite DLL)
|
||
|
//
|
||
|
LANGID lid = PRIMARYLANGID(_Module.m_Language.GetUiLanguage());
|
||
|
|
||
|
// determine if we are running with a localized Hebrew or Arabic UI
|
||
|
//
|
||
|
if(lid == LANG_ARABIC || lid == LANG_HEBREW)
|
||
|
g_bBiDiUi=TRUE;
|
||
|
else
|
||
|
g_bBiDiUi=FALSE;
|
||
|
|
||
|
// determine if we are running with a localized Hebrew or Arabic UI
|
||
|
//
|
||
|
if(lid == LANG_ARABIC)
|
||
|
g_bArabicUi=TRUE;
|
||
|
else
|
||
|
g_bArabicUi=FALSE;
|
||
|
|
||
|
MSG_MOUSEWHEEL = RegisterWindowMessage(txtMouseWheel);
|
||
|
|
||
|
// Find out if we are on IE 4 or later
|
||
|
|
||
|
{
|
||
|
HKEY hkey;
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, txtIE4, 0, KEY_READ, &hkey) ==
|
||
|
ERROR_SUCCESS) {
|
||
|
char szVersion[MAX_PATH];
|
||
|
DWORD cbPath = sizeof(szVersion);
|
||
|
if (RegQueryValueEx(hkey, txtVersion, NULL, NULL, (LPBYTE) szVersion, &cbPath) == ERROR_SUCCESS) {
|
||
|
|
||
|
// IE 3 didn't have a version key, so if this succeeds,
|
||
|
// we know we aren't on IE 3.
|
||
|
|
||
|
g_fIE3 = FALSE; // we're on IE 4, not IE 3
|
||
|
g_bMsItsMonikerSupport = FALSE; // Don't make this TRUE. See bug 6984 & 6876
|
||
|
}
|
||
|
RegCloseKey(hkey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// register our server if the pathname is not the same as the
|
||
|
// one that is already registered
|
||
|
TCHAR szHHCtrl[MAX_PATH];
|
||
|
szHHCtrl[0] = 0;
|
||
|
TCHAR szModulePathname[MAX_PATH];
|
||
|
szModulePathname[0] = 0;
|
||
|
BOOL bRegister = FALSE;
|
||
|
bRegister = !GetRegisteredLocation( CLSID_HHCtrl, szHHCtrl );
|
||
|
if( !bRegister ) {
|
||
|
GetModuleFileName( _Module.GetModuleInstance(), szModulePathname, MAX_PATH );
|
||
|
if( lstrcmpi( szHHCtrl, szModulePathname ) != 0 )
|
||
|
bRegister = TRUE;
|
||
|
}
|
||
|
if( bRegister )
|
||
|
DllRegisterServer();
|
||
|
|
||
|
// TODO: pahwnd needs to be incapsulated into a class and allocated on demand.
|
||
|
g_cWindowSlots = 5;
|
||
|
pahwnd = (CHHWinType**) lcCalloc(g_cWindowSlots * sizeof(CHHWinType*));
|
||
|
memset( pahwnd, 0, g_cWindowSlots * sizeof(CHHWinType*) );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
// DBWIN("HHCtrl unloading");
|
||
|
|
||
|
// DeleteCriticalSection(&g_CriticalSection);
|
||
|
|
||
|
// unregister all the registered window classes.
|
||
|
|
||
|
// Clean out the memory in the last error object, since the heap is screwed before the destructor is called.
|
||
|
g_LastError.Finish() ;
|
||
|
|
||
|
i = 0;
|
||
|
|
||
|
while (!ISEMPTYOBJECT(i)) {
|
||
|
if (g_ObjectInfo[i].usType == OI_CONTROL) {
|
||
|
#ifdef _DEBUG
|
||
|
CONTROLOBJECTINFO* pinfo = (CONTROLOBJECTINFO*) g_ObjectInfo[i].pInfo;
|
||
|
#endif
|
||
|
if (CTLWNDCLASSREGISTERED(i))
|
||
|
UnregisterClass(WNDCLASSNAMEOFCONTROL(i), _Module.GetModuleInstance());
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
// clean up our parking window.
|
||
|
|
||
|
if (g_hwndParking) {
|
||
|
DestroyWindow(g_hwndParking);
|
||
|
UnregisterClass("CtlFrameWork_Parking", _Module.GetModuleInstance());
|
||
|
--g_cLocks;
|
||
|
}
|
||
|
|
||
|
// free our window types list
|
||
|
for( int i = 0; i < g_cWindowSlots; i++ )
|
||
|
if( pahwnd[i] ) {
|
||
|
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszType );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszCaption );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszToc );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszIndex );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszFile );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszHome );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszJump1 );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszJump2 );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszUrlJump1 );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszUrlJump2 );
|
||
|
CHECK_AND_FREE( pahwnd[i]->pszCustomTabs );
|
||
|
|
||
|
pahwnd[i]->ProcessDetachSafeCleanup();
|
||
|
}
|
||
|
CHECK_AND_FREE( pahwnd );
|
||
|
|
||
|
// free the CHmData
|
||
|
CHECK_AND_FREE( g_phmData );
|
||
|
|
||
|
// don't call DBWIN here since it will cause a GPF
|
||
|
|
||
|
if (g_hmodMSI != NULL)
|
||
|
FreeLibrary(g_hmodMSI);
|
||
|
if (g_hpalSplash)
|
||
|
DeleteObject(g_hpalSplash);
|
||
|
_Module.Term();
|
||
|
if (g_hsemMemory)
|
||
|
CloseHandle(g_hsemMemory);
|
||
|
|
||
|
if (g_hsemNavigate)
|
||
|
CloseHandle(g_hsemNavigate);
|
||
|
|
||
|
// DeleteAllHmData();
|
||
|
if (g_hmodHHA != NULL)
|
||
|
{
|
||
|
FreeLibrary(g_hmodHHA);
|
||
|
g_hmodHHA = NULL;
|
||
|
}
|
||
|
if (g_fCoInitialized)
|
||
|
{
|
||
|
OleUninitialize();
|
||
|
g_fCoInitialized = FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
#ifndef HHUTIL
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// DllRegisterServer
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// registers the Automation server
|
||
|
|
||
|
STDAPI DllRegisterServer(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = RegisterAllObjects();
|
||
|
ASSERT(SUCCEEDED(hr));
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
CreateComponentCategory(CATID_SafeForScripting, L"Controls that are safely scriptable");
|
||
|
CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data");
|
||
|
RegisterCLSIDInCategory(CLSID_HHCtrl, CATID_SafeForScripting);
|
||
|
RegisterCLSIDInCategory(CLSID_HHCtrl, CATID_SafeForInitializing);
|
||
|
|
||
|
char szPath[MAX_PATH];
|
||
|
GetRegWindowsDirectory(szPath);
|
||
|
AddTrailingBackslash(szPath);
|
||
|
strcat(szPath, txtHhExe);
|
||
|
if (GetFileAttributes(szPath) != HFILE_ERROR)
|
||
|
RegisterHH(szPath);
|
||
|
|
||
|
GetSystemDirectory(szPath, sizeof(szPath));
|
||
|
AddTrailingBackslash(szPath);
|
||
|
PSTR pszEnd = szPath + strlen(szPath);
|
||
|
strcpy(pszEnd, txtItssDll);
|
||
|
|
||
|
// Register decompression DLL (for .CHM files)
|
||
|
|
||
|
HMODULE hmod = LoadLibrary(szPath);
|
||
|
if (hmod) {
|
||
|
void (STDCALL *pDllRegisterServer)(void);
|
||
|
(FARPROC&) pDllRegisterServer =
|
||
|
GetProcAddress(hmod, txtDllRegisterServer);
|
||
|
if (pDllRegisterServer)
|
||
|
pDllRegisterServer();
|
||
|
FreeLibrary(hmod);
|
||
|
}
|
||
|
|
||
|
// Register the full-text search module
|
||
|
|
||
|
strcpy(pszEnd, txtItirclDll);
|
||
|
hmod = LoadLibrary(szPath);
|
||
|
if (hmod) {
|
||
|
void (STDCALL *pDllRegisterServer)(void);
|
||
|
(FARPROC&) pDllRegisterServer =
|
||
|
GetProcAddress(hmod, txtDllRegisterServer);
|
||
|
if (pDllRegisterServer)
|
||
|
pDllRegisterServer();
|
||
|
FreeLibrary(hmod);
|
||
|
}
|
||
|
|
||
|
// register our file extensions for Removable Media Support
|
||
|
HKEY hKey;
|
||
|
LPCTSTR szGUID = HHFINDER_GUID;
|
||
|
LPCTSTR szExt = HHFINDER_EXTENSION;
|
||
|
RegCreateKeyEx( HKEY_LOCAL_MACHINE, ITSS_FINDER, 0, NULL,
|
||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
|
||
|
RegSetValueEx( hKey, szExt, 0, REG_SZ, (const unsigned char*) szGUID,
|
||
|
(int)(strlen(szGUID) + 1) );
|
||
|
RegCloseKey( hKey );
|
||
|
|
||
|
_Module.RegisterServer(TRUE);
|
||
|
return S_OK;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
void RegisterHH(PCSTR pszHHPath)
|
||
|
{
|
||
|
char szFullPath[MAX_PATH];
|
||
|
|
||
|
SetRegKey(txtDefExtension, txtChmFile);
|
||
|
|
||
|
LoadString(_Module.GetResourceInstance(),IDS_COMPILEDHTMLFILE,szFullPath,sizeof(szFullPath));
|
||
|
|
||
|
SetRegKey(txtChmFile, szFullPath);
|
||
|
|
||
|
// Put path in quotes, in case there are spaces in the folder name
|
||
|
|
||
|
szFullPath[0] = '\042';
|
||
|
strcpy(szFullPath + 1, pszHHPath);
|
||
|
strcat(szFullPath, "\"");
|
||
|
|
||
|
PSTR pszPathEnd = szFullPath + strlen(szFullPath);
|
||
|
strcat(szFullPath, txtStdArg); // "pathname %1"
|
||
|
|
||
|
char szBuf[MAX_PATH * 2];
|
||
|
wsprintf(szBuf, txtShellOpenFmt, txtChmFile, txtCommand);
|
||
|
SetRegKey(szBuf, szFullPath);
|
||
|
|
||
|
// Register the icon to use for .chm files
|
||
|
|
||
|
*pszPathEnd = '\0'; // remove the arguments
|
||
|
strcpy(szFullPath + strlen(szFullPath) - 1, ",0"); // remove the close quote
|
||
|
SetRegKey("chm.file\\DefaultIcon", szFullPath + 1);
|
||
|
}
|
||
|
|
||
|
static void SetRegKey(LPCTSTR pszKey, LPCTSTR pszValue)
|
||
|
{
|
||
|
RegSetValue(HKEY_CLASSES_ROOT, pszKey, REG_SZ, pszValue, (int)strlen(pszValue));
|
||
|
}
|
||
|
|
||
|
#ifndef HHUTIL
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// DllUnregisterServer
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// unregister's the Automation server
|
||
|
|
||
|
STDAPI DllUnregisterServer(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = UnregisterAllObjects();
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
// call user unregistration function
|
||
|
|
||
|
hr = UnregisterData();
|
||
|
|
||
|
// Remove registration for decompression DLL (for .CHM files)
|
||
|
|
||
|
HMODULE hmod = LoadLibrary(txtItssDll);
|
||
|
if (hmod) {
|
||
|
void (STDCALL *pDllRegisterServer)(void);
|
||
|
(FARPROC&) pDllRegisterServer =
|
||
|
GetProcAddress(hmod, txtDllUnRegisterServer);
|
||
|
if (pDllRegisterServer)
|
||
|
pDllRegisterServer();
|
||
|
FreeLibrary(hmod);
|
||
|
}
|
||
|
|
||
|
// Remove registration for the full-text search module
|
||
|
|
||
|
hmod = LoadLibrary(txtItirclDll);
|
||
|
if (hmod) {
|
||
|
void (STDCALL *pDllRegisterServer)(void);
|
||
|
(FARPROC&) pDllRegisterServer =
|
||
|
GetProcAddress(hmod, txtDllUnRegisterServer);
|
||
|
if (pDllRegisterServer)
|
||
|
pDllRegisterServer();
|
||
|
FreeLibrary(hmod);
|
||
|
}
|
||
|
|
||
|
// unregister our file extensions for Removable Media Support
|
||
|
|
||
|
HKEY hKey;
|
||
|
LPCTSTR szGUID = HHFINDER_GUID;
|
||
|
LPCTSTR szExt = HHFINDER_EXTENSION;
|
||
|
RegCreateKeyEx( HKEY_LOCAL_MACHINE, ITSS_FINDER, 0, NULL,
|
||
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL);
|
||
|
RegDeleteKey( hKey, szExt );
|
||
|
RegCloseKey( hKey );
|
||
|
|
||
|
_Module.UnregisterServer();
|
||
|
|
||
|
// BUGBUG: remove association with .CHM files
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifndef HHUTIL
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// DllCanUnloadNow
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// we are being asked whether or not it's okay to unload the DLL. just check
|
||
|
// the lock counts on remaining objects ...
|
||
|
//
|
||
|
// Output:
|
||
|
// HRESULT - S_OK, can unload now, S_FALSE, can't.
|
||
|
|
||
|
STDAPI DllCanUnloadNow(void)
|
||
|
{
|
||
|
// if there are any objects lying around, then we can't unload. The
|
||
|
// controlling CUnknownObject class that people should be inheriting from
|
||
|
// takes care of this
|
||
|
|
||
|
return (g_cLocks) ? S_FALSE : S_OK;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifndef HHUTIL
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// DllGetClassObject
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// creates a ClassFactory object, and returns it.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// REFCLSID - CLSID for the class object
|
||
|
// REFIID - interface we want class object to be.
|
||
|
// void ** - pointer to where we should ptr to new object.
|
||
|
//
|
||
|
// Output:
|
||
|
// HRESULT - S_OK, CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY,
|
||
|
// E_INVALIDARG, E_UNEXPECTED
|
||
|
|
||
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppvObjOut)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
void *pv;
|
||
|
int iIndex;
|
||
|
|
||
|
if( IsEqualCLSID( rclsid, CLSID_HHSysSort ) || IsEqualCLSID( rclsid, CLSID_HHFinder ) )
|
||
|
return _Module.GetClassObject( rclsid, riid, ppvObjOut );
|
||
|
|
||
|
// arg checking
|
||
|
|
||
|
if (!ppvObjOut)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
// first of all, make sure they're asking for something we work with.
|
||
|
|
||
|
iIndex = IndexOfOleObject(rclsid);
|
||
|
if (iIndex == -1)
|
||
|
return CLASS_E_CLASSNOTAVAILABLE;
|
||
|
|
||
|
// create the blank object.
|
||
|
|
||
|
pv = (void *)new CClassFactory(iIndex);
|
||
|
if (!pv)
|
||
|
return E_OUTOFMEMORY;
|
||
|
|
||
|
// QI for whatever the user has asked for.
|
||
|
//
|
||
|
hr = ((IUnknown *)pv)->QueryInterface(riid, ppvObjOut);
|
||
|
((IUnknown *)pv)->Release();
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// IndexOfOleObject
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// returns the index in our global table of objects of the given CLSID. if
|
||
|
// it's not a supported object, then we return -1
|
||
|
//
|
||
|
// Parameters:
|
||
|
// REFCLSID - [in] duh.
|
||
|
//
|
||
|
// Output:
|
||
|
// int - >= 0 is index into global table, -1 means not supported
|
||
|
|
||
|
int IndexOfOleObject(REFCLSID rclsid)
|
||
|
{
|
||
|
int x = 0;
|
||
|
|
||
|
// an object is creatable if it's CLSID is in the table of all allowable object
|
||
|
// types.
|
||
|
|
||
|
while (!ISEMPTYOBJECT(x)) {
|
||
|
#ifdef _DEBUG
|
||
|
CONTROLOBJECTINFO* pinfo = (CONTROLOBJECTINFO*) g_ObjectInfo[x].pInfo;
|
||
|
#endif
|
||
|
|
||
|
if (OBJECTISCREATABLE(x)) {
|
||
|
if (rclsid == CLSIDOFOBJECT(x))
|
||
|
return x;
|
||
|
}
|
||
|
x++;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// RegisterAllObjects
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// registers all the objects for the given automation server.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// none
|
||
|
//
|
||
|
// Output:
|
||
|
// HERSULT - S_OK, E_FAIL
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
|
||
|
const char g_szLibName[] = "Internet";
|
||
|
|
||
|
HRESULT RegisterAllObjects(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
int x = 0;
|
||
|
|
||
|
// loop through all of our creatable objects [those that have a clsid in
|
||
|
// our global table] and register them.
|
||
|
|
||
|
while (!ISEMPTYOBJECT(x)) {
|
||
|
#ifdef _DEBUG
|
||
|
CONTROLOBJECTINFO* pinfo = (CONTROLOBJECTINFO*) g_ObjectInfo[x].pInfo;
|
||
|
#endif
|
||
|
|
||
|
if (!OBJECTISCREATABLE(x)) {
|
||
|
x++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// depending on the object type, register different pieces of information
|
||
|
|
||
|
switch (g_ObjectInfo[x].usType) {
|
||
|
|
||
|
// for both simple co-creatable objects and proeprty pages, do the same
|
||
|
// thing
|
||
|
|
||
|
case OI_UNKNOWN:
|
||
|
case OI_PROPERTYPAGE:
|
||
|
RegisterUnknownObject(NAMEOFOBJECT(x), CLSIDOFOBJECT(x));
|
||
|
break;
|
||
|
|
||
|
case OI_AUTOMATION:
|
||
|
RegisterAutomationObject(g_szLibName, NAMEOFOBJECT(x),
|
||
|
VERSIONOFOBJECT(x), *g_pLibid, CLSIDOFOBJECT(x));
|
||
|
break;
|
||
|
|
||
|
case OI_CONTROL:
|
||
|
RegisterControlObject(g_szLibName, NAMEOFOBJECT(x),
|
||
|
VERSIONOFOBJECT(x), *g_pLibid, CLSIDOFOBJECT(x),
|
||
|
OLEMISCFLAGSOFCONTROL(x), BITMAPIDOFCONTROL(x));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
x++;
|
||
|
}
|
||
|
|
||
|
// Load and register our type library.
|
||
|
|
||
|
if (g_fServerHasTypeLibrary) {
|
||
|
char szTmp[MAX_PATH];
|
||
|
DWORD dwPathLen = GetModuleFileName(_Module.GetModuleInstance(), szTmp, MAX_PATH);
|
||
|
MAKE_WIDEPTR_FROMANSI(pwsz, szTmp);
|
||
|
|
||
|
ITypeLib *pTypeLib;
|
||
|
hr = LoadTypeLib(pwsz, &pTypeLib);
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
hr = RegisterTypeLib(pTypeLib, pwsz, NULL);
|
||
|
pTypeLib->Release();
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// UnregisterAllObjects
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// un-registers all the objects for the given automation server.
|
||
|
//
|
||
|
// Parameters:
|
||
|
// none
|
||
|
//
|
||
|
// Output:
|
||
|
// HRESULT - S_OK
|
||
|
|
||
|
HRESULT UnregisterAllObjects(void)
|
||
|
{
|
||
|
int x = 0;
|
||
|
|
||
|
// loop through all of our creatable objects [those that have a clsid in
|
||
|
// our global table] and register them.
|
||
|
//
|
||
|
while (!ISEMPTYOBJECT(x)) {
|
||
|
#ifdef _DEBUG
|
||
|
CONTROLOBJECTINFO* pinfo = (CONTROLOBJECTINFO*) g_ObjectInfo[x].pInfo;
|
||
|
#endif
|
||
|
|
||
|
if (!OBJECTISCREATABLE(x)) {
|
||
|
x++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (g_ObjectInfo[x].usType) {
|
||
|
|
||
|
case OI_UNKNOWN:
|
||
|
case OI_PROPERTYPAGE:
|
||
|
UnregisterUnknownObject(CLSIDOFOBJECT(x));
|
||
|
break;
|
||
|
|
||
|
case OI_CONTROL:
|
||
|
UnregisterControlObject(g_szLibName, NAMEOFOBJECT(x),
|
||
|
VERSIONOFOBJECT(x), CLSIDOFOBJECT(x));
|
||
|
|
||
|
case OI_AUTOMATION:
|
||
|
UnregisterAutomationObject(g_szLibName, NAMEOFOBJECT(x),
|
||
|
VERSIONOFOBJECT(x), CLSIDOFOBJECT(x));
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
x++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* if we've got one, unregister our type library [this isn't an API
|
||
|
* function -- we've implemented this ourselves]
|
||
|
*/
|
||
|
|
||
|
if (g_pLibid)
|
||
|
UnregisterTypeLibrary(*g_pLibid);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// UnregisterData
|
||
|
//=--------------------------------------------------------------------------=
|
||
|
// inproc server writers should unregister anything they registered in
|
||
|
// RegisterData() here.
|
||
|
//
|
||
|
// Output:
|
||
|
// BOOL - false means failure.
|
||
|
|
||
|
BOOL UnregisterData(void)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = UnRegisterCLSIDInCategory(CLSID_HHCtrl, CATID_SafeForScripting);
|
||
|
hr = UnRegisterCLSIDInCategory(CLSID_HHCtrl, CATID_SafeForInitializing);
|
||
|
return TRUE;
|
||
|
}
|