mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
505 lines
12 KiB
505 lines
12 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 Microsoft Corporation
|
|
// All rights reserved.
|
|
//
|
|
// This source code is only intended as a supplement to the
|
|
// Microsoft Foundation Classes Reference and related
|
|
// electronic documentation provided with the library.
|
|
// See these sources for detailed information regarding the
|
|
// Microsoft Foundation Classes product.
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifdef AFXCTL_FACT_SEG
|
|
#pragma code_seg(AFXCTL_FACT_SEG)
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#define GUID_CCH 39 // Characters in string form of guid, including '\0'
|
|
|
|
#define ERROR_BADKEY_WIN16 2 // needed when running on Win32s
|
|
|
|
inline BOOL _AfxRegDeleteKeySucceeded(LONG error)
|
|
{
|
|
return (error == ERROR_SUCCESS) || (error == ERROR_BADKEY) ||
|
|
(error == ERROR_FILE_NOT_FOUND);
|
|
}
|
|
|
|
// Under Win32, a reg key may not be deleted unless it is empty.
|
|
// Thus, to delete a tree, one must recursively enumerate and
|
|
// delete all of the sub-keys.
|
|
|
|
LONG AFXAPI _AfxRecursiveRegDeleteKey(HKEY hParentKey, LPTSTR szKeyName)
|
|
{
|
|
DWORD dwIndex = 0L;
|
|
TCHAR szSubKeyName[256];
|
|
HKEY hCurrentKey;
|
|
DWORD dwResult;
|
|
|
|
if ((dwResult = RegOpenKey(hParentKey, szKeyName, &hCurrentKey)) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
// Remove all subkeys of the key to delete
|
|
while ((dwResult = RegEnumKey(hCurrentKey, 0, szSubKeyName, 255)) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
if ((dwResult = _AfxRecursiveRegDeleteKey(hCurrentKey,
|
|
szSubKeyName)) != ERROR_SUCCESS)
|
|
break;
|
|
}
|
|
|
|
// If all went well, we should now be able to delete the requested key
|
|
if ((dwResult == ERROR_NO_MORE_ITEMS) || (dwResult == ERROR_BADKEY) ||
|
|
(dwResult == ERROR_BADKEY_WIN16))
|
|
{
|
|
dwResult = RegDeleteKey(hParentKey, szKeyName);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hCurrentKey);
|
|
return dwResult;
|
|
}
|
|
|
|
BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
|
|
LPCTSTR pszFileName, LPCTSTR pszHelpDir)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
CString strPathName;
|
|
::GetModuleFileName(hInstance, strPathName.GetBuffer(_MAX_PATH),
|
|
_MAX_PATH);
|
|
strPathName.ReleaseBuffer();
|
|
|
|
// If a filename was specified, replace final component of path with it.
|
|
if (pszFileName != NULL)
|
|
{
|
|
int iBackslash = strPathName.ReverseFind('\\');
|
|
if (iBackslash != -1)
|
|
strPathName = strPathName.Left(iBackslash+1);
|
|
strPathName += pszFileName;
|
|
}
|
|
|
|
LPTYPELIB ptlib = NULL;
|
|
if (SUCCEEDED(LoadTypeLib(T2COLE(strPathName), &ptlib)))
|
|
{
|
|
ASSERT_POINTER(ptlib, ITypeLib);
|
|
|
|
LPTLIBATTR pAttr;
|
|
GUID tlidActual = GUID_NULL;
|
|
|
|
if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
|
|
{
|
|
ASSERT_POINTER(pAttr, TLIBATTR);
|
|
tlidActual = pAttr->guid;
|
|
ptlib->ReleaseTLibAttr(pAttr);
|
|
}
|
|
|
|
// Check that the guid of the loaded type library matches
|
|
// the tlid parameter.
|
|
ASSERT(IsEqualGUID(tlid, tlidActual));
|
|
|
|
if (IsEqualGUID(tlid, tlidActual))
|
|
{
|
|
// Register the type library.
|
|
if (SUCCEEDED(RegisterTypeLib(ptlib,
|
|
T2OLE((LPTSTR)(LPCTSTR)strPathName), T2OLE((LPTSTR)pszHelpDir))))
|
|
bSuccess = TRUE;
|
|
}
|
|
|
|
RELEASE(ptlib);
|
|
}
|
|
else
|
|
{
|
|
TRACE1("Warning: Could not load type library from %s\n", (LPCTSTR)strPathName);
|
|
}
|
|
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
#define TYPELIBWIN _T("win32")
|
|
#define TYPELIBWIN_2 _T("win16")
|
|
|
|
BOOL AFXAPI AfxOleUnregisterTypeLib(REFGUID tlid)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
// Format typelib guid as a string
|
|
OLECHAR szTypeLibID[GUID_CCH];
|
|
int cchGuid = ::StringFromGUID2(tlid, szTypeLibID, GUID_CCH);
|
|
|
|
ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
|
|
if (cchGuid != GUID_CCH)
|
|
return FALSE;
|
|
|
|
TCHAR szKeyTypeLib[_MAX_PATH];
|
|
BOOL bSurgical = FALSE;
|
|
LONG error = ERROR_SUCCESS;
|
|
|
|
wsprintf(szKeyTypeLib, _T("TYPELIB\\%s"), OLE2CT(szTypeLibID));
|
|
|
|
HKEY hKeyTypeLib;
|
|
if (RegOpenKey(HKEY_CLASSES_ROOT, szKeyTypeLib, &hKeyTypeLib) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
int iKeyVersion = 0;
|
|
HKEY hKeyVersion;
|
|
TCHAR szVersion[_MAX_PATH];
|
|
|
|
// Iterate through all installed versions of the control
|
|
|
|
while (RegEnumKey(hKeyTypeLib, iKeyVersion, szVersion, _MAX_PATH) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
hKeyVersion = NULL;
|
|
BOOL bSurgicalVersion = FALSE;
|
|
|
|
if (RegOpenKey(hKeyTypeLib, szVersion, &hKeyVersion) !=
|
|
ERROR_SUCCESS)
|
|
{
|
|
++iKeyVersion;
|
|
continue;
|
|
}
|
|
|
|
int iKeyLocale = 0;
|
|
HKEY hKeyLocale;
|
|
TCHAR szLocale[_MAX_PATH];
|
|
|
|
// Iterate through all registered locales for this version
|
|
|
|
while (RegEnumKey(hKeyVersion, iKeyLocale, szLocale, _MAX_PATH) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
// Don't remove HELPDIR or FLAGS keys.
|
|
if ((_tcsicmp(szLocale, _T("HELPDIR")) == 0) ||
|
|
(_tcsicmp(szLocale, _T("FLAGS")) == 0))
|
|
{
|
|
++iKeyLocale;
|
|
continue;
|
|
}
|
|
|
|
hKeyLocale = NULL;
|
|
|
|
if (RegOpenKey(hKeyVersion, szLocale, &hKeyLocale) !=
|
|
ERROR_SUCCESS)
|
|
{
|
|
++iKeyLocale;
|
|
continue;
|
|
}
|
|
|
|
// Check if a 16-bit key is found when unregistering 32-bit
|
|
HKEY hkey;
|
|
if (RegOpenKey(hKeyLocale, TYPELIBWIN_2, &hkey) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hkey);
|
|
|
|
// Only remove the keys specific to the 32-bit version
|
|
// of control, leaving things intact for 16-bit version.
|
|
error = _AfxRecursiveRegDeleteKey(hKeyLocale, TYPELIBWIN);
|
|
bSurgicalVersion = TRUE;
|
|
RegCloseKey(hKeyLocale);
|
|
}
|
|
else
|
|
{
|
|
// Delete everything for this locale.
|
|
RegCloseKey(hKeyLocale);
|
|
if (_AfxRecursiveRegDeleteKey(hKeyVersion, szLocale) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
// Start over again, so we don't skip anything.
|
|
iKeyLocale = 0;
|
|
continue;
|
|
}
|
|
}
|
|
++iKeyLocale;
|
|
}
|
|
RegCloseKey(hKeyVersion);
|
|
|
|
if (bSurgicalVersion)
|
|
{
|
|
bSurgical = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (_AfxRecursiveRegDeleteKey(hKeyTypeLib, szVersion) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
// Start over again, to make sure we don't skip anything.
|
|
iKeyVersion = 0;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
++iKeyVersion;
|
|
}
|
|
RegCloseKey(hKeyTypeLib);
|
|
}
|
|
|
|
if (!bSurgical)
|
|
error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT, szKeyTypeLib);
|
|
|
|
return _AfxRegDeleteKeySucceeded(error);
|
|
}
|
|
|
|
static const LPCTSTR rglpszCtrlProgID[] =
|
|
{
|
|
_T("\0") _T("%1"),
|
|
_T("CLSID\0") _T("%2"),
|
|
NULL
|
|
};
|
|
|
|
static const LPCTSTR rglpszCtrlClassID[] =
|
|
{
|
|
_T("\0") _T("%1"),
|
|
_T("ProgID\0") _T("%2"),
|
|
_T("InprocServer32\0") _T("%3"),
|
|
_T("ToolboxBitmap32\0") _T("%3, %4"),
|
|
_T("MiscStatus\0") _T("0"),
|
|
_T("MiscStatus\\1\0") _T("%5"),
|
|
_T("Control\0") _T(""),
|
|
_T("TypeLib\0") _T("%6"),
|
|
_T("Version\0") _T("%7"),
|
|
NULL
|
|
};
|
|
|
|
BOOL AFXAPI AfxOleRegisterControlClass(HINSTANCE hInstance,
|
|
REFCLSID clsid, LPCTSTR pszProgID, UINT idTypeName, UINT idBitmap,
|
|
int nRegFlags, DWORD dwMiscStatus, REFGUID tlid, WORD wVerMajor,
|
|
WORD wVerMinor)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
// Format class ID as a string
|
|
OLECHAR szClassID[GUID_CCH];
|
|
int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
|
|
LPCTSTR lpszClassID = OLE2CT(szClassID);
|
|
|
|
ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
|
|
if (cchGuid != GUID_CCH)
|
|
return FALSE;
|
|
|
|
// Format typelib guid as a string
|
|
OLECHAR szTypeLibID[GUID_CCH];
|
|
cchGuid = ::StringFromGUID2(tlid, szTypeLibID, GUID_CCH);
|
|
|
|
ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
|
|
if (cchGuid != GUID_CCH)
|
|
return FALSE;
|
|
|
|
CString strPathName;
|
|
AfxGetModuleShortFileName(hInstance, strPathName);
|
|
|
|
CString strTypeName;
|
|
if (!strTypeName.LoadString(idTypeName))
|
|
{
|
|
ASSERT(FALSE); // Name string not present in resources
|
|
strTypeName = lpszClassID; // Use Class ID instead
|
|
}
|
|
|
|
TCHAR szBitmapID[_MAX_PATH];
|
|
_itot(idBitmap, szBitmapID, 10);
|
|
|
|
TCHAR szMiscStatus[_MAX_PATH];
|
|
_ltot(dwMiscStatus, szMiscStatus, 10);
|
|
|
|
// Format version string as "major.minor"
|
|
TCHAR szVersion[_MAX_PATH];
|
|
wsprintf(szVersion, _T("%d.%d"), wVerMajor, wVerMinor);
|
|
|
|
// Attempt to open registry keys.
|
|
HKEY hkeyClassID = NULL;
|
|
HKEY hkeyProgID = NULL;
|
|
|
|
TCHAR szKey[_MAX_PATH];
|
|
wsprintf(szKey, _T("CLSID\\%s"), lpszClassID);
|
|
if (::RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkeyClassID) !=
|
|
ERROR_SUCCESS)
|
|
goto Error;
|
|
if (::RegCreateKey(HKEY_CLASSES_ROOT, pszProgID, &hkeyProgID) !=
|
|
ERROR_SUCCESS)
|
|
goto Error;
|
|
|
|
ASSERT(hkeyClassID != NULL);
|
|
ASSERT(hkeyProgID != NULL);
|
|
|
|
LPCTSTR rglpszSymbols[7];
|
|
rglpszSymbols[0] = strTypeName;
|
|
rglpszSymbols[1] = lpszClassID;
|
|
bSuccess = AfxOleRegisterHelper(rglpszCtrlProgID, rglpszSymbols, 2,
|
|
TRUE, hkeyProgID);
|
|
|
|
if (!bSuccess)
|
|
goto Error;
|
|
|
|
rglpszSymbols[1] = pszProgID;
|
|
rglpszSymbols[2] = strPathName;
|
|
rglpszSymbols[3] = szBitmapID;
|
|
rglpszSymbols[4] = szMiscStatus;
|
|
rglpszSymbols[5] = OLE2CT(szTypeLibID);
|
|
rglpszSymbols[6] = szVersion;
|
|
bSuccess = AfxOleRegisterHelper(rglpszCtrlClassID, rglpszSymbols, 7,
|
|
TRUE, hkeyClassID);
|
|
|
|
if (!bSuccess)
|
|
goto Error;
|
|
|
|
if (nRegFlags & afxRegInsertable)
|
|
{
|
|
bSuccess =
|
|
(::RegSetValue(hkeyProgID, _T("Insertable"), REG_SZ, _T(""), 0) ==
|
|
ERROR_SUCCESS) &&
|
|
(::RegSetValue(hkeyClassID, _T("Insertable"), REG_SZ, _T(""), 0) ==
|
|
ERROR_SUCCESS);
|
|
}
|
|
|
|
Error:
|
|
if (hkeyProgID != NULL)
|
|
::RegCloseKey(hkeyProgID);
|
|
|
|
if (hkeyClassID != NULL)
|
|
::RegCloseKey(hkeyClassID);
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
#define INPROCSERVER _T("InprocServer32")
|
|
#define INPROCSERVER_2 _T("InprocServer")
|
|
#define TOOLBOXBITMAP _T("ToolboxBitmap32")
|
|
|
|
BOOL AFXAPI AfxOleUnregisterClass(REFCLSID clsid, LPCTSTR pszProgID)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
// Format class ID as a string
|
|
OLECHAR szClassID[GUID_CCH];
|
|
int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
|
|
LPCTSTR lpszClassID = OLE2CT(szClassID);
|
|
|
|
ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
|
|
if (cchGuid != GUID_CCH)
|
|
return FALSE;
|
|
|
|
TCHAR szKey[_MAX_PATH];
|
|
|
|
// check to see if a 16-bit InprocServer key is found when unregistering
|
|
// 32-bit (or vice versa).
|
|
wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, INPROCSERVER_2);
|
|
HKEY hkey;
|
|
BOOL bSurgical = RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hkey) ==
|
|
ERROR_SUCCESS;
|
|
|
|
long error;
|
|
BOOL bRetCode = TRUE;
|
|
if (bSurgical)
|
|
{
|
|
// Only remove the keys specific to this version of the control,
|
|
// leaving things in tact for the other version.
|
|
wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, INPROCSERVER);
|
|
error = RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
|
|
bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
|
|
|
|
wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, TOOLBOXBITMAP);
|
|
error = RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
|
|
bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
|
|
}
|
|
else
|
|
{
|
|
// No other versions of this control were detected,
|
|
// so go ahead and remove the control completely.
|
|
wsprintf(szKey, _T("CLSID\\%s"), lpszClassID);
|
|
error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT, szKey);
|
|
bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
|
|
|
|
if (pszProgID != NULL)
|
|
{
|
|
error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT,
|
|
(LPTSTR)pszProgID);
|
|
bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
|
|
}
|
|
}
|
|
|
|
return bRetCode;
|
|
}
|
|
|
|
static const LPCTSTR rglpszPropPageClass[] =
|
|
{
|
|
_T("\0") _T("%1"),
|
|
_T("InprocServer32\0") _T("%2"),
|
|
NULL
|
|
};
|
|
|
|
BOOL AFXAPI AfxOleRegisterPropertyPageClass(HINSTANCE hInstance,
|
|
REFCLSID clsid, UINT idTypeName)
|
|
{
|
|
return AfxOleRegisterPropertyPageClass(hInstance, clsid, idTypeName, 0);
|
|
}
|
|
|
|
BOOL AFXAPI AfxOleRegisterPropertyPageClass(HINSTANCE hInstance,
|
|
REFCLSID clsid, UINT idTypeName, int nRegFlags)
|
|
{
|
|
ASSERT(!(nRegFlags & afxRegInsertable)); // can't be insertable
|
|
UNUSED(nRegFlags);
|
|
|
|
USES_CONVERSION;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
// Format class ID as a string
|
|
OLECHAR szClassID[GUID_CCH];
|
|
int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
|
|
LPCTSTR lpszClassID = OLE2CT(szClassID);
|
|
|
|
ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
|
|
if (cchGuid != GUID_CCH)
|
|
return FALSE;
|
|
|
|
CString strPathName;
|
|
AfxGetModuleShortFileName(hInstance, strPathName);
|
|
|
|
CString strTypeName;
|
|
if (!strTypeName.LoadString(idTypeName))
|
|
{
|
|
ASSERT(FALSE); // Name string not present in resources
|
|
strTypeName = lpszClassID; // Use Class ID instead
|
|
}
|
|
|
|
HKEY hkeyClassID = NULL;
|
|
|
|
TCHAR szKey[_MAX_PATH];
|
|
wsprintf(szKey, _T("CLSID\\%s"), lpszClassID);
|
|
if (::RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkeyClassID) !=
|
|
ERROR_SUCCESS)
|
|
goto Error;
|
|
|
|
LPCTSTR rglpszSymbols[2];
|
|
rglpszSymbols[0] = strTypeName;
|
|
rglpszSymbols[1] = strPathName;
|
|
bSuccess = AfxOleRegisterHelper(rglpszPropPageClass, rglpszSymbols,
|
|
2, TRUE, hkeyClassID);
|
|
|
|
if (!bSuccess)
|
|
goto Error;
|
|
|
|
Error:
|
|
if (hkeyClassID != NULL)
|
|
::RegCloseKey(hkeyClassID);
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Force any extra compiler-generated code into AFX_INIT_SEG
|
|
|
|
#ifdef AFX_INIT_SEG
|
|
#pragma code_seg(AFX_INIT_SEG)
|
|
#endif
|