windows-nt/Source/XPSP1/NT/admin/snapin/adsiedit/common.cpp
2020-09-26 16:20:57 +08:00

1851 lines
41 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: common.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#include <SnapBase.h>
#include "common.h"
#include "editor.h"
#include "connection.h"
#include "credui.h"
#ifdef DEBUG_ALLOCATOR
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////
extern LPCWSTR g_lpszRootDSE;
////////////////////////////////////////////////////////////////////////////////////////
HRESULT OpenObjectWithCredentials(
CConnectionData* pConnectData,
const BOOL bUseCredentials,
LPCWSTR lpszPath,
const IID& iid,
LPVOID* ppObject,
HWND hWnd,
HRESULT& hResult
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
hResult = S_OK;
CWaitCursor cursor;
CWnd* pCWnd = CWnd::FromHandle(hWnd);
CCredentialObject* pCredObject = pConnectData->GetCredentialObject();
if (bUseCredentials)
{
CString sUserName;
UINT uiDialogResult = IDOK;
WCHAR szPassword[MAX_PASSWORD_LENGTH + 1];
while (uiDialogResult != IDCANCEL)
{
pCredObject->GetUsername(sUserName);
pCredObject->GetPassword(szPassword);
hr = ADsOpenObject((LPWSTR)lpszPath,
(LPWSTR)(LPCWSTR)sUserName,
szPassword,
ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
iid,
ppObject
);
ZeroMemory(szPassword, sizeof(WCHAR[MAX_PASSWORD_LENGTH + 1]));
// If logon fails pop up the credentials dialog box
//
if (HRESULT_CODE(hr) == ERROR_LOGON_FAILURE ||
HRESULT_CODE(hr) == ERROR_NOT_AUTHENTICATED ||
HRESULT_CODE(hr) == ERROR_INVALID_PASSWORD ||
HRESULT_CODE(hr) == ERROR_PASSWORD_EXPIRED ||
HRESULT_CODE(hr) == ERROR_ACCOUNT_DISABLED ||
HRESULT_CODE(hr) == ERROR_ACCOUNT_LOCKED_OUT ||
hr == E_ADS_BAD_PATHNAME)
{
CString sConnectName;
// GetConnectionNode() is NULL when the connection is first being
// create, but since it is the connection node we can get the name
// directly from the CConnectionData.
//
ASSERT(pConnectData != NULL);
if (pConnectData->GetConnectionNode() == NULL)
{
pConnectData->GetName(sConnectName);
}
else
{
sConnectName = pConnectData->GetConnectionNode()->GetDisplayName();
}
CCredentialDialog credDialog(pCredObject, sConnectName, pCWnd);
uiDialogResult = credDialog.DoModal();
cursor.Restore();
if (uiDialogResult == IDCANCEL)
{
hResult = E_FAIL;
}
else
{
hResult = S_OK;
}
}
else
{
break;
}
}
}
else
{
hr = ADsOpenObject((LPWSTR)lpszPath, NULL, NULL,
ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, iid, ppObject);
}
return hr;
}
HRESULT OpenObjectWithCredentials(
CCredentialObject* pCredObject,
LPCWSTR lpszPath,
const IID& iid,
LPVOID* ppObject
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr;
if (pCredObject->UseCredentials())
{
CString sUserName;
UINT uiDialogResult = IDOK;
WCHAR szPassword[MAX_PASSWORD_LENGTH + 1];
pCredObject->GetUsername(sUserName);
pCredObject->GetPassword(szPassword);
hr = ADsOpenObject((LPWSTR)lpszPath,
(LPWSTR)(LPCWSTR)sUserName,
szPassword,
ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
iid,
ppObject
);
ZeroMemory(szPassword, sizeof(WCHAR[MAX_PASSWORD_LENGTH + 1]));
}
else
{
hr = ADsOpenObject((LPWSTR)lpszPath, NULL, NULL,
ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND, iid, ppObject);
}
return hr;
}
HRESULT CALLBACK BindingCallbackFunction(LPCWSTR lpszPathName,
DWORD dwReserved,
REFIID riid,
void FAR * FAR * ppObject,
LPARAM lParam)
{
CCredentialObject* pCredObject = reinterpret_cast<CCredentialObject*>(lParam);
if (pCredObject == NULL)
{
return E_FAIL;
}
HRESULT hr = OpenObjectWithCredentials(pCredObject,
lpszPathName,
riid,
ppObject);
return hr;
}
HRESULT GetRootDSEObject(CConnectionData* pConnectData,
IADs** ppDirObject)
{
// Get data from connection node
//
CString sRootDSE, sServer, sPort, sLDAP;
pConnectData->GetDomainServer(sServer);
pConnectData->GetLDAP(sLDAP);
pConnectData->GetPort(sPort);
if (sServer != _T(""))
{
sRootDSE = sLDAP + sServer;
if (sPort != _T(""))
{
sRootDSE = sRootDSE + _T(":") + sPort + _T("/");
}
else
{
sRootDSE = sRootDSE + _T("/");
}
sRootDSE = sRootDSE + g_lpszRootDSE;
}
else
{
sRootDSE = sLDAP + g_lpszRootDSE;
}
HRESULT hr, hCredResult;
hr = OpenObjectWithCredentials(
pConnectData,
pConnectData->GetCredentialObject()->UseCredentials(),
(LPWSTR)(LPCWSTR)sRootDSE,
IID_IADs,
(LPVOID*) ppDirObject,
NULL,
hCredResult
);
if ( FAILED(hr) )
{
if (SUCCEEDED(hCredResult))
{
ADSIEditErrorMessage(hr);
}
return hr;
}
return hr;
}
HRESULT GetItemFromRootDSE(LPCWSTR lpszRootDSEItem,
CString& sItem,
CConnectionData* pConnectData)
{
// Get data from connection node
//
CString sRootDSE, sServer, sPort, sLDAP;
pConnectData->GetDomainServer(sServer);
pConnectData->GetLDAP(sLDAP);
pConnectData->GetPort(sPort);
if (sServer != _T(""))
{
sRootDSE = sLDAP + sServer;
if (sPort != _T(""))
{
sRootDSE = sRootDSE + _T(":") + sPort + _T("/");
}
else
{
sRootDSE = sRootDSE + _T("/");
}
sRootDSE = sRootDSE + g_lpszRootDSE;
}
else
{
sRootDSE = sLDAP + g_lpszRootDSE;
}
CComPtr<IADs> pADs;
HRESULT hr, hCredResult;
hr = OpenObjectWithCredentials(
pConnectData,
pConnectData->GetCredentialObject()->UseCredentials(),
(LPWSTR)(LPCWSTR)sRootDSE,
IID_IADs,
(LPVOID*) &pADs,
NULL,
hCredResult
);
if ( FAILED(hr) )
{
if (SUCCEEDED(hCredResult))
{
ADSIEditErrorMessage(hr);
}
return hr;
}
VARIANT var;
VariantInit(&var);
hr = pADs->Get( (LPWSTR)lpszRootDSEItem, &var );
if ( FAILED(hr) )
{
VariantClear(&var);
return hr;
}
BSTR bstrItem = V_BSTR(&var);
sItem = bstrItem;
VariantClear(&var);
return S_OK;
}
HRESULT VariantToStringList( VARIANT& refvar, CStringList& refstringlist)
{
HRESULT hr = S_OK;
long start, end;
if ( !(V_VT(&refvar) & VT_ARRAY) )
{
if ( V_VT(&refvar) != VT_BSTR )
{
hr = VariantChangeType( &refvar, &refvar,0, VT_BSTR );
if( FAILED(hr) )
{
return hr;
}
}
refstringlist.AddHead( V_BSTR(&refvar) );
return hr;
}
SAFEARRAY *saAttributes = V_ARRAY( &refvar );
//
// Figure out the dimensions of the array.
//
hr = SafeArrayGetLBound( saAttributes, 1, &start );
if( FAILED(hr) )
return hr;
hr = SafeArrayGetUBound( saAttributes, 1, &end );
if( FAILED(hr) )
return hr;
VARIANT SingleResult;
VariantInit( &SingleResult );
//
// Process the array elements.
//
for ( long idx = start; idx <= end; idx++ )
{
hr = SafeArrayGetElement( saAttributes, &idx, &SingleResult );
if( FAILED(hr) )
{
return hr;
}
if ( V_VT(&SingleResult) != VT_BSTR )
{
if ( V_VT(&SingleResult) == VT_NULL )
{
V_VT(&SingleResult ) = VT_BSTR;
V_BSTR(&SingleResult ) = SysAllocString(L"0");
}
else
{
hr = VariantChangeType( &SingleResult, &SingleResult,0, VT_BSTR );
if( FAILED(hr) )
{
return hr;
}
}
}
//if ( V_VT(&SingleResult) != VT_BSTR )
// return E_UNEXPECTED;
refstringlist.AddHead( V_BSTR(&SingleResult) );
VariantClear( &SingleResult );
}
return S_OK;
} // VariantToStringList()
/////////////////////////////////////////////////////////////////////
HRESULT StringListToVariant( VARIANT& refvar, const CStringList& refstringlist)
{
HRESULT hr = S_OK;
int cCount = refstringlist.GetCount();
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = cCount;
SAFEARRAY* psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
if (NULL == psa)
return E_OUTOFMEMORY;
VariantClear( &refvar );
V_VT(&refvar) = VT_VARIANT|VT_ARRAY;
V_ARRAY(&refvar) = psa;
VARIANT SingleResult;
VariantInit( &SingleResult );
V_VT(&SingleResult) = VT_BSTR;
POSITION pos = refstringlist.GetHeadPosition();
long i;
for (i = 0; i < cCount, pos != NULL; i++)
{
V_BSTR(&SingleResult) = T2BSTR((LPCTSTR)refstringlist.GetNext(pos));
hr = SafeArrayPutElement(psa, &i, &SingleResult);
if( FAILED(hr) )
return hr;
}
if (i != cCount || pos != NULL)
return E_UNEXPECTED;
return hr;
} // StringListToVariant()
///////////////////////////////////////////////////////////////////////////////////////
BOOL GetErrorMessage(HRESULT hr, CString& szErrorString, BOOL bTryADsIErrors)
{
HRESULT hrGetLast = S_OK;
DWORD status;
PTSTR ptzSysMsg = NULL;
// first check if we have extended ADs errors
if ((hr != S_OK) && bTryADsIErrors)
{
WCHAR Buf1[256], Buf2[256];
hrGetLast = ::ADsGetLastError(&status, Buf1, 256, Buf2, 256);
TRACE(_T("ADsGetLastError returned status of %lx, error: %s, name %s\n"),
status, Buf1, Buf2);
if ((status != ERROR_INVALID_DATA) && (status != 0))
{
hr = status;
}
}
// try the system first
int nChars = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)&ptzSysMsg, 0, NULL);
if (nChars == 0)
{
//try ads errors
static HMODULE g_adsMod = 0;
if (0 == g_adsMod)
g_adsMod = GetModuleHandle (L"activeds.dll");
nChars = ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_HMODULE, g_adsMod, hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(PTSTR)&ptzSysMsg, 0, NULL);
}
if (nChars > 0)
{
szErrorString = ptzSysMsg;
::LocalFree(ptzSysMsg);
}
else
{
szErrorString.Format(L"Error code: X%x", hr);
}
return (nChars > 0);
}
////////////////////////////////////////////////////////////////////////////////////
typedef struct tagSYNTAXMAP
{
LPCWSTR lpszAttr;
VARTYPE type;
} SYNTAXMAP;
SYNTAXMAP ldapSyntax[] =
{
_T("DN"), VT_BSTR,
_T("DIRECTORYSTRING"), VT_BSTR,
_T("IA5STRING"), VT_BSTR,
_T("CASEIGNORESTRING"), VT_BSTR,
_T("PRINTABLESTRING"), VT_BSTR,
_T("NUMERICSTRING"), VT_BSTR,
_T("UTCTIME"), VT_DATE,
_T("ORNAME"), VT_BSTR,
_T("OCTETSTRING"), VT_BSTR,
_T("BOOLEAN"), VT_BOOL,
_T("INTEGER"), VT_I4,
_T("OID"), VT_BSTR,
_T("INTEGER8"), VT_I8,
_T("OBJECTSECURITYDESCRIPTOR"), VT_BSTR,
NULL, 0,
};
#define MAX_ATTR_STRING_LENGTH 30
VARTYPE VariantTypeFromSyntax(LPCWSTR lpszProp )
{
int idx=0;
while( ldapSyntax[idx].lpszAttr )
{
if ( _wcsnicmp(lpszProp, ldapSyntax[idx].lpszAttr, MAX_ATTR_STRING_LENGTH) )
{
return ldapSyntax[idx].type;
}
idx++;
}
ASSERT(FALSE);
return VT_BSTR;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Function : GetStringFromADsValue
//
// Formats an ADSVALUE struct into a string
//
///////////////////////////////////////////////////////////////////////////////////////////////////
void GetStringFromADsValue(const PADSVALUE pADsValue, CString& szValue, DWORD dwMaxCharCount)
{
szValue.Empty();
if (!pADsValue)
{
ASSERT(pADsValue);
return;
}
CString sTemp;
switch( pADsValue->dwType )
{
case ADSTYPE_DN_STRING :
sTemp.Format(L"%s", pADsValue->DNString);
break;
case ADSTYPE_CASE_EXACT_STRING :
sTemp.Format(L"%s", pADsValue->CaseExactString);
break;
case ADSTYPE_CASE_IGNORE_STRING:
sTemp.Format(L"%s", pADsValue->CaseIgnoreString);
break;
case ADSTYPE_PRINTABLE_STRING :
sTemp.Format(L"%s", pADsValue->PrintableString);
break;
case ADSTYPE_NUMERIC_STRING :
sTemp.Format(L"%s", pADsValue->NumericString);
break;
case ADSTYPE_OBJECT_CLASS :
sTemp.Format(L"%s", pADsValue->ClassName);
break;
case ADSTYPE_BOOLEAN :
sTemp.Format(L"%s", ((DWORD)pADsValue->Boolean) ? L"TRUE" : L"FALSE");
break;
case ADSTYPE_INTEGER :
sTemp.Format(L"%d", (DWORD) pADsValue->Integer);
break;
case ADSTYPE_OCTET_STRING :
{
CString sOctet;
BYTE b;
for ( DWORD idx=0; idx<pADsValue->OctetString.dwLength; idx++)
{
b = ((BYTE *)pADsValue->OctetString.lpValue)[idx];
sOctet.Format(L"0x%02x ", b);
sTemp += sOctet;
if (dwMaxCharCount != 0 && sTemp.GetLength() > dwMaxCharCount)
{
break;
}
}
}
break;
case ADSTYPE_LARGE_INTEGER :
litow(pADsValue->LargeInteger, sTemp);
break;
case ADSTYPE_UTC_TIME :
sTemp.Format(L"%02d/%02d/%04d %02d:%02d:%02d",
pADsValue->UTCTime.wMonth,
pADsValue->UTCTime.wDay,
pADsValue->UTCTime.wYear,
pADsValue->UTCTime.wHour,
pADsValue->UTCTime.wMinute,
pADsValue->UTCTime.wSecond);
break;
case ADSTYPE_NT_SECURITY_DESCRIPTOR: // I use the ACLEditor instead
{
}
break;
default :
break;
}
szValue = sTemp;
}
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Function : GetStringFromADs
//
// Formats an ADS_ATTR_INFO structs values into strings and APPENDS them to a CStringList that is
// passed in as a parameter.
//
///////////////////////////////////////////////////////////////////////////////////////////////////
void GetStringFromADs(const ADS_ATTR_INFO* pInfo, CStringList& sList, DWORD dwMaxCharCount)
{
CString sTemp;
if ( pInfo == NULL )
{
return;
}
ADSVALUE *pValues = pInfo->pADsValues;
for (DWORD x=0; x < pInfo->dwNumValues; x++)
{
if ( pInfo->dwADsType == ADSTYPE_INVALID )
{
continue;
}
sTemp.Empty();
GetStringFromADsValue(pValues, sTemp, dwMaxCharCount);
pValues++;
sList.AddTail( sTemp );
}
}
//////////////////////////////////////////////////////////////////////
typedef struct tagSYNTAXTOADSMAP
{
LPCWSTR lpszAttr;
ADSTYPE type;
UINT nSyntaxResID;
} SYNTAXTOADSMAP;
SYNTAXTOADSMAP adsType[] =
{
L"2.5.5.0", ADSTYPE_INVALID, IDS_SYNTAX_UNKNOWN,
L"2.5.5.1", ADSTYPE_DN_STRING, IDS_SYNTAX_DN,
L"2.5.5.2", ADSTYPE_CASE_IGNORE_STRING, IDS_SYNTAX_OID,
L"2.5.5.3", ADSTYPE_CASE_EXACT_STRING, IDS_SYNTAX_NOCASE_STR,
L"2.5.5.4", ADSTYPE_CASE_IGNORE_STRING, IDS_SYNTAX_PRCS_STR,
L"2.5.5.5", ADSTYPE_PRINTABLE_STRING, IDS_SYNTAX_I5_STR,
L"2.5.5.6", ADSTYPE_NUMERIC_STRING, IDS_SYNTAX_NUMSTR,
L"2.5.5.7", ADSTYPE_CASE_IGNORE_STRING, IDS_SYNTAX_DN_BINARY,
L"2.5.5.8", ADSTYPE_BOOLEAN, IDS_SYNTAX_BOOLEAN,
L"2.5.5.9", ADSTYPE_INTEGER, IDS_SYNTAX_INTEGER,
L"2.5.5.10", ADSTYPE_OCTET_STRING, IDS_SYNTAX_OCTET,
L"2.5.5.11", ADSTYPE_UTC_TIME, IDS_SYNTAX_UTC,
L"2.5.5.12", ADSTYPE_CASE_IGNORE_STRING, IDS_SYNTAX_UNICODE,
L"2.5.5.13", ADSTYPE_CASE_IGNORE_STRING, IDS_SYNTAX_ADDRESS,
L"2.5.5.14", ADSTYPE_INVALID, IDS_SYNTAX_DNSTRING,
L"2.5.5.15", ADSTYPE_NT_SECURITY_DESCRIPTOR, IDS_SYNTAX_SEC_DESC,
L"2.5.5.16", ADSTYPE_LARGE_INTEGER, IDS_SYNTAX_LINT,
L"2.5.5.17", ADSTYPE_OCTET_STRING, IDS_SYNTAX_SID,
NULL, ADSTYPE_INVALID, IDS_SYNTAX_UNKNOWN
};
ADSTYPE GetADsTypeFromString(LPCWSTR lps, CString& szSyntaxName)
{
int idx=0;
while( adsType[idx].lpszAttr )
{
if ( wcscmp(lps, adsType[idx].lpszAttr) == 0 )
{
szSyntaxName.LoadString(adsType[idx].nSyntaxResID);
return adsType[idx].type;
}
idx++;
}
return ADSTYPE_INVALID;
}
////////////////////////////////////////////////////////////////
// Type conversions for LARGE_INTEGERs
void wtoli(LPCWSTR p, LARGE_INTEGER& liOut)
{
liOut.QuadPart = 0;
BOOL bNeg = FALSE;
if (*p == L'-')
{
bNeg = TRUE;
p++;
}
while (*p != L'\0')
{
liOut.QuadPart = 10 * liOut.QuadPart + (*p-L'0');
p++;
}
if (bNeg)
{
liOut.QuadPart *= -1;
}
}
void litow(LARGE_INTEGER& li, CString& sResult)
{
LARGE_INTEGER n;
n.QuadPart = li.QuadPart;
if (n.QuadPart == 0)
{
sResult = L"0";
}
else
{
CString sNeg;
sResult = L"";
if (n.QuadPart < 0)
{
sNeg = CString(L'-');
n.QuadPart *= -1;
}
while (n.QuadPart > 0)
{
sResult += CString(L'0' + (n.QuadPart % 10));
n.QuadPart = n.QuadPart / 10;
}
sResult = sResult + sNeg;
}
sResult.MakeReverse();
}
void ultow(ULONG ul, CString& sResult)
{
ULONG n;
n = ul;
if (n == 0)
{
sResult = L"0";
}
else
{
sResult = L"";
while (n > 0)
{
sResult += CString(L'0' + (n % 10));
n = n / 10;
}
}
sResult.MakeReverse();
}
//+----------------------------------------------------------------------------
//
// Function: UnicodeToTchar
//
// Synopsis: Converts a Unicode string to a TCHAR string. Allocates memory
// for the returned string using new. Callers must free the
// string memory when done using delete.
//
// Returns: FALSE for out of memory failures.
//
//-----------------------------------------------------------------------------
BOOL UnicodeToChar(LPWSTR pwszIn, LPSTR * ppszOut)
{
size_t len;
len = WideCharToMultiByte(CP_ACP, 0, pwszIn, -1, NULL, 0, NULL, NULL);
*ppszOut = new CHAR[len + 1];
if (*ppszOut == NULL)
{
return FALSE;
}
if (WideCharToMultiByte(CP_ACP, 0, pwszIn, -1,
*ppszOut, len, NULL, NULL) == 0)
{
delete[] *ppszOut;
return FALSE;
}
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: TcharToUnicode
//
// Synopsis: Converts a TCHAR string to a Unicode string. Allocates memory
// for the returned string using new. Callers must free the
// string memory when done using delete.
//
// Returns: FALSE for out of memory failures.
//
//-----------------------------------------------------------------------------
BOOL CharToUnicode(LPSTR pszIn, LPWSTR * ppwszOut)
{
size_t len;
len = MultiByteToWideChar(CP_ACP, 0, pszIn, -1, NULL, 0);
*ppwszOut = new WCHAR[len + 1];
if (*ppwszOut == NULL)
{
return FALSE;
}
if (MultiByteToWideChar(CP_ACP, 0, pszIn, -1, *ppwszOut, len) == 0)
{
delete[] *ppwszOut;
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////
// IO to/from Streams
void SaveStringToStream(IStream* pStm, const CString& sString)
{
ULONG cbWrite;
ULONG nLen;
nLen = wcslen(sString)+1; // WCHAR including NULL
VERIFY(SUCCEEDED(pStm->Write((void*)&nLen, sizeof(UINT),&cbWrite)));
ASSERT(cbWrite == sizeof(UINT));
VERIFY(SUCCEEDED(pStm->Write((void*)((LPCWSTR)sString), sizeof(WCHAR)*nLen,&cbWrite)));
ASSERT(cbWrite == sizeof(WCHAR)*nLen);
}
HRESULT SaveStringListToStream(IStream* pStm, CStringList& sList)
{
// for each string in the list, write # of chars+NULL, and then the string
ULONG cbWrite;
ULONG nLen;
UINT nCount;
// write # of strings in list
nCount = (UINT)sList.GetCount();
VERIFY(SUCCEEDED(pStm->Write((void*)&nCount, sizeof(UINT),&cbWrite)));
ASSERT(cbWrite == sizeof(UINT));
POSITION pos = sList.GetHeadPosition();
while (pos != NULL)
{
CString s = sList.GetNext(pos);
SaveStringToStream(pStm, s);
}
return S_OK;
}
void LoadStringFromStream(IStream* pStm, CString& sString)
{
WCHAR szBuffer[256]; // REVIEW_MARCOC: hardcoded
ULONG nLen; // WCHAR counting NULL
ULONG cbRead;
VERIFY(SUCCEEDED(pStm->Read((void*)&nLen,sizeof(UINT), &cbRead)));
ASSERT(cbRead == sizeof(UINT));
VERIFY(SUCCEEDED(pStm->Read((void*)szBuffer,sizeof(WCHAR)*nLen, &cbRead)));
ASSERT(cbRead == sizeof(WCHAR)*nLen);
sString = szBuffer;
}
HRESULT LoadStringListFromStream(IStream* pStm, CStringList& sList)
{
ULONG cbRead;
ULONG nCount;
VERIFY(SUCCEEDED(pStm->Read((void*)&nCount,sizeof(ULONG), &cbRead)));
ASSERT(cbRead == sizeof(ULONG));
for (int k=0; k< (int)nCount; k++)
{
CString sString;
LoadStringFromStream(pStm, sString);
sList.AddTail(sString);
}
if (sList.GetCount() == nCount)
{
return S_OK;
}
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////
/////////////////////// Message Boxes ///////////////////////////////
/////////////////////////////////////////////////////////////////////
int ADSIEditMessageBox(LPCTSTR lpszText, UINT nType)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return ::AfxMessageBox(lpszText, nType);
}
int ADSIEditMessageBox(UINT nIDPrompt, UINT nType)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return ::AfxMessageBox(nIDPrompt, nType);
}
void ADSIEditErrorMessage(PCWSTR pszMessage)
{
ADSIEditMessageBox(pszMessage, MB_OK);
}
void ADSIEditErrorMessage(HRESULT hr)
{
CString s;
GetErrorMessage(hr, s);
ADSIEditMessageBox(s, MB_OK);
}
void ADSIEditErrorMessage(HRESULT hr, UINT nIDPrompt, UINT nType)
{
CString s;
GetErrorMessage(hr, s);
CString szMessage;
szMessage.Format(nIDPrompt, s);
ADSIEditMessageBox(szMessage, MB_OK);
}
/////////////////////////////////////////////////////////////////////
BOOL LoadStringsToComboBox(HINSTANCE hInstance, CComboBox* pCombo,
UINT nStringID, UINT nMaxLen, UINT nMaxAddCount)
{
pCombo->ResetContent();
ASSERT(hInstance != NULL);
WCHAR* szBuf = (WCHAR*)malloc(sizeof(WCHAR)*nMaxLen);
if (!szBuf)
{
return FALSE;
}
if ( ::LoadString(hInstance, nStringID, szBuf, nMaxLen) == 0)
{
free(szBuf);
return FALSE;
}
LPWSTR* lpszArr = (LPWSTR*)malloc(sizeof(LPWSTR*)*nMaxLen);
if (lpszArr)
{
int nArrEntries = 0;
ParseNewLineSeparatedString(szBuf,lpszArr, &nArrEntries);
if (nMaxAddCount < nArrEntries) nArrEntries = nMaxAddCount;
for (int k=0; k<nArrEntries; k++)
pCombo->AddString(lpszArr[k]);
}
if (szBuf)
{
free(szBuf);
}
if (lpszArr)
{
free(lpszArr);
}
return TRUE;
}
void ParseNewLineSeparatedString(LPWSTR lpsz,
LPWSTR* lpszArr,
int* pnArrEntries)
{
static WCHAR lpszSep[] = L"\n";
*pnArrEntries = 0;
int k = 0;
lpszArr[k] = wcstok(lpsz, lpszSep);
if (lpszArr[k] == NULL)
return;
while (TRUE)
{
WCHAR* lpszToken = wcstok(NULL, lpszSep);
if (lpszToken != NULL)
lpszArr[++k] = lpszToken;
else
break;
}
*pnArrEntries = k+1;
}
void LoadStringArrayFromResource(LPWSTR* lpszArr,
UINT* nStringIDs,
int nArrEntries,
int* pnSuccessEntries)
{
CString szTemp;
*pnSuccessEntries = 0;
for (int k = 0;k < nArrEntries; k++)
{
if (!szTemp.LoadString(nStringIDs[k]))
{
lpszArr[k] = NULL;
continue;
}
int iLength = szTemp.GetLength() + 1;
lpszArr[k] = (LPWSTR)malloc(sizeof(WCHAR)*iLength);
if (lpszArr[k] != NULL)
{
wcscpy(lpszArr[k], (LPWSTR)(LPCWSTR)szTemp);
(*pnSuccessEntries)++;
}
}
}
///////////////////////////////////////////////////////////////
void GetStringArrayFromStringList(CStringList& sList, LPWSTR** ppStrArr, UINT* nCount)
{
*nCount = sList.GetCount();
*ppStrArr = new LPWSTR[*nCount];
UINT idx = 0;
POSITION pos = sList.GetHeadPosition();
while (pos != NULL)
{
CString szString = sList.GetNext(pos);
(*ppStrArr)[idx] = new WCHAR[szString.GetLength() + 1];
ASSERT((*ppStrArr)[idx] != NULL);
wcscpy((*ppStrArr)[idx], szString);
idx++;
}
*nCount = idx;
}
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(CByteArrayComboBox, CComboBox)
ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelChange)
END_MESSAGE_MAP()
BOOL CByteArrayComboBox::Initialize(CByteArrayDisplay* pDisplay,
DWORD dwDisplayFlags)
{
ASSERT(pDisplay != NULL);
m_pDisplay = pDisplay;
//
// Load the combo box based on the flags given
//
if (dwDisplayFlags & BYTE_ARRAY_DISPLAY_HEX)
{
CString szHex;
VERIFY(szHex.LoadString(IDS_HEXADECIMAL));
int idx = AddString(szHex);
if (idx != CB_ERR)
{
SetItemData(idx, BYTE_ARRAY_DISPLAY_HEX);
}
}
if (dwDisplayFlags & BYTE_ARRAY_DISPLAY_OCT)
{
CString szOct;
VERIFY(szOct.LoadString(IDS_OCTAL));
int idx = AddString(szOct);
if (idx != CB_ERR)
{
SetItemData(idx, BYTE_ARRAY_DISPLAY_OCT);
}
}
if (dwDisplayFlags & BYTE_ARRAY_DISPLAY_DEC)
{
CString szDec;
VERIFY(szDec.LoadString(IDS_DECIMAL));
int idx = AddString(szDec);
if (idx != CB_ERR)
{
SetItemData(idx, BYTE_ARRAY_DISPLAY_DEC);
}
}
if (dwDisplayFlags & BYTE_ARRAY_DISPLAY_BIN)
{
CString szBin;
VERIFY(szBin.LoadString(IDS_BINARY));
int idx = AddString(szBin);
if (idx != CB_ERR)
{
SetItemData(idx, BYTE_ARRAY_DISPLAY_BIN);
}
}
return TRUE;
}
DWORD CByteArrayComboBox::GetCurrentDisplay()
{
DWORD dwRet = 0;
int iSel = GetCurSel();
if (iSel != CB_ERR)
{
dwRet = GetItemData(iSel);
}
return dwRet;
}
void CByteArrayComboBox::SetCurrentDisplay(DWORD dwSel)
{
int iCount = GetCount();
for (int idx = 0; idx < iCount; idx++)
{
DWORD dwData = GetItemData(idx);
if (dwData == dwSel)
{
SetCurSel(idx);
return;
}
}
}
void CByteArrayComboBox::OnSelChange()
{
if (m_pDisplay != NULL)
{
int iSel = GetCurSel();
if (iSel != CB_ERR)
{
DWORD dwData = GetItemData(iSel);
m_pDisplay->OnTypeChange(dwData);
}
}
}
////////////////////////////////////////////////////////////////
CByteArrayEdit::CByteArrayEdit()
: m_pData(NULL),
m_dwLength(0),
CEdit()
{
}
CByteArrayEdit::~CByteArrayEdit()
{
}
BEGIN_MESSAGE_MAP(CByteArrayEdit, CEdit)
ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
END_MESSAGE_MAP()
BOOL CByteArrayEdit::Initialize(CByteArrayDisplay* pDisplay)
{
ASSERT(pDisplay != NULL);
m_pDisplay = pDisplay;
ConvertToFixedPitchFont(GetSafeHwnd());
return TRUE;
}
DWORD CByteArrayEdit::GetLength()
{
return m_dwLength;
}
BYTE* CByteArrayEdit::GetDataPtr()
{
return m_pData;
}
DWORD CByteArrayEdit::GetDataCopy(BYTE** ppData)
{
if (m_pData != NULL && m_dwLength > 0)
{
*ppData = new BYTE[m_dwLength];
if (*ppData != NULL)
{
memcpy(*ppData, m_pData, m_dwLength);
return m_dwLength;
}
}
*ppData = NULL;
return 0;
}
void CByteArrayEdit::SetData(BYTE* pData, DWORD dwLength)
{
if (m_pData != NULL)
{
delete[] m_pData;
m_pData = NULL;
m_dwLength = 0;
}
if (dwLength > 0 && pData != NULL)
{
//
// Set the new data
//
m_pData = new BYTE[dwLength];
if (m_pData != NULL)
{
memcpy(m_pData, pData, dwLength);
m_dwLength = dwLength;
}
}
}
void CByteArrayEdit::OnChangeDisplay()
{
CString szOldDisplay;
GetWindowText(szOldDisplay);
if (!szOldDisplay.IsEmpty())
{
BYTE* pByte = NULL;
DWORD dwLength = 0;
switch (m_pDisplay->GetPreviousDisplay())
{
case BYTE_ARRAY_DISPLAY_HEX :
dwLength = HexStringToByteArray(szOldDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_OCT :
dwLength = OctalStringToByteArray(szOldDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_DEC :
dwLength = DecimalStringToByteArray(szOldDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_BIN :
dwLength = BinaryStringToByteArray(szOldDisplay, &pByte);
break;
default :
ASSERT(FALSE);
break;
}
if (pByte != NULL && dwLength != (DWORD)-1)
{
SetData(pByte, dwLength);
delete[] pByte;
pByte = 0;
}
}
CString szDisplayValue;
switch (m_pDisplay->GetCurrentDisplay())
{
case BYTE_ARRAY_DISPLAY_HEX :
ByteArrayToHexString(GetDataPtr(), GetLength(), szDisplayValue);
break;
case BYTE_ARRAY_DISPLAY_OCT :
ByteArrayToOctalString(GetDataPtr(), GetLength(), szDisplayValue);
break;
case BYTE_ARRAY_DISPLAY_DEC :
ByteArrayToDecimalString(GetDataPtr(), GetLength(), szDisplayValue);
break;
case BYTE_ARRAY_DISPLAY_BIN :
ByteArrayToBinaryString(GetDataPtr(), GetLength(), szDisplayValue);
break;
default :
ASSERT(FALSE);
break;
}
SetWindowText(szDisplayValue);
}
void CByteArrayEdit::OnChange()
{
if (m_pDisplay != NULL)
{
m_pDisplay->OnEditChange();
}
}
////////////////////////////////////////////////////////////////
BOOL CByteArrayDisplay::Initialize(UINT nEditCtrl,
UINT nComboCtrl,
DWORD dwDisplayFlags,
DWORD dwDefaultDisplay,
CWnd* pParent,
DWORD dwMaxSizeLimit,
UINT nMaxSizeMessageID)
{
//
// Initialize the edit control
//
VERIFY(m_edit.SubclassDlgItem(nEditCtrl, pParent));
VERIFY(m_edit.Initialize(this));
//
// Initialize the combo box
//
VERIFY(m_combo.SubclassDlgItem(nComboCtrl, pParent));
VERIFY(m_combo.Initialize(this, dwDisplayFlags));
m_dwMaxSizeBytes = dwMaxSizeLimit;
m_nMaxSizeMessage = nMaxSizeMessageID;
//
// Selects the default display in the combo box and
// populates the edit field
//
SetCurrentDisplay(dwDefaultDisplay);
m_dwPreviousDisplay = dwDefaultDisplay;
m_combo.SetCurrentDisplay(dwDefaultDisplay);
m_edit.OnChangeDisplay();
return TRUE;
}
void CByteArrayDisplay::OnEditChange()
{
}
void CByteArrayDisplay::OnTypeChange(DWORD dwDisplayType)
{
SetCurrentDisplay(dwDisplayType);
m_edit.OnChangeDisplay();
}
void CByteArrayDisplay::ClearData()
{
m_edit.SetData(NULL, 0);
m_edit.OnChangeDisplay();
}
void CByteArrayDisplay::SetData(BYTE* pData, DWORD dwLength)
{
if (dwLength > m_dwMaxSizeBytes)
{
//
// If the data is too large to load into the edit box
// load the provided message and set the edit box to read only
//
CString szMessage;
VERIFY(szMessage.LoadString(m_nMaxSizeMessage));
m_edit.SetWindowText(szMessage);
m_edit.SetReadOnly();
//
// Still need to set the data in the edit box even though we are not going to show it
//
m_edit.SetData(pData, dwLength);
}
else
{
m_edit.SetReadOnly(FALSE);
m_edit.SetData(pData, dwLength);
m_edit.OnChangeDisplay();
}
}
DWORD CByteArrayDisplay::GetData(BYTE** ppData)
{
CString szDisplay;
m_edit.GetWindowText(szDisplay);
if (!szDisplay.IsEmpty())
{
BYTE* pByte = NULL;
DWORD dwLength = 0;
switch (GetCurrentDisplay())
{
case BYTE_ARRAY_DISPLAY_HEX :
dwLength = HexStringToByteArray(szDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_OCT :
dwLength = OctalStringToByteArray(szDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_DEC :
dwLength = DecimalStringToByteArray(szDisplay, &pByte);
break;
case BYTE_ARRAY_DISPLAY_BIN :
dwLength = BinaryStringToByteArray(szDisplay, &pByte);
break;
default :
ASSERT(FALSE);
break;
}
if (pByte != NULL && dwLength != (DWORD)-1)
{
m_edit.SetData(pByte, dwLength);
delete[] pByte;
pByte = 0;
}
}
return m_edit.GetDataCopy(ppData);
}
void CByteArrayDisplay::SetCurrentDisplay(DWORD dwCurrentDisplay)
{
m_dwPreviousDisplay = m_dwCurrentDisplay;
m_dwCurrentDisplay = dwCurrentDisplay;
}
////////////////////////////////////////////////////////////////////////////////
// String to byte array conversion routines
DWORD HexStringToByteArray(PCWSTR pszHexString, BYTE** ppByte)
{
CString szHexString = pszHexString;
BYTE* pToLargeArray = new BYTE[szHexString.GetLength()];
if (pToLargeArray == NULL)
{
*ppByte = NULL;
return (DWORD)-1;
}
UINT nByteCount = 0;
while (!szHexString.IsEmpty())
{
//
// Hex strings should always come 2 characters per byte
//
CString szTemp = szHexString.Left(2);
int iTempByte = 0;
swscanf(szTemp, L"%X", &iTempByte);
if (iTempByte <= 0xff)
{
pToLargeArray[nByteCount++] = iTempByte & 0xff;
}
else
{
//
// Format hex error
//
ADSIEditMessageBox(IDS_FORMAT_HEX_ERROR, MB_OK);
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
//
// Take off the value retrieved and the trailing space
//
szHexString = szHexString.Right(szHexString.GetLength() - 3);
}
*ppByte = new BYTE[nByteCount];
if (*ppByte == NULL)
{
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
memcpy(*ppByte, pToLargeArray, nByteCount);
delete[] pToLargeArray;
pToLargeArray = NULL;
return nByteCount;
}
void ByteArrayToHexString(BYTE* pByte, DWORD dwLength, CString& szHexString)
{
szHexString.Empty();
for (DWORD dwIdx = 0; dwIdx < dwLength; dwIdx++)
{
CString szTempString;
szTempString.Format(L"%2.2X", pByte[dwIdx]);
if (dwIdx != 0)
{
szHexString += L" ";
}
szHexString += szTempString;
}
}
DWORD OctalStringToByteArray(PCWSTR pszOctString, BYTE** ppByte)
{
CString szOctString = pszOctString;
BYTE* pToLargeArray = new BYTE[szOctString.GetLength()];
if (pToLargeArray == NULL)
{
*ppByte = NULL;
return (DWORD)-1;
}
UINT nByteCount = 0;
while (!szOctString.IsEmpty())
{
//
// Octal strings should always come 2 characters per byte
//
CString szTemp = szOctString.Left(3);
int iTempByte = 0;
swscanf(szTemp, L"%o", &iTempByte);
if (iTempByte <= 0xff)
{
pToLargeArray[nByteCount++] = iTempByte & 0xff;
}
else
{
//
// Format octal error
//
ADSIEditMessageBox(IDS_FORMAT_OCTAL_ERROR, MB_OK);
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
//
// Take off the value retrieved and the trailing space
//
szOctString = szOctString.Right(szOctString.GetLength() - 4);
}
*ppByte = new BYTE[nByteCount];
if (*ppByte == NULL)
{
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
memcpy(*ppByte, pToLargeArray, nByteCount);
delete[] pToLargeArray;
pToLargeArray = NULL;
return nByteCount;
}
void ByteArrayToOctalString(BYTE* pByte, DWORD dwLength, CString& szOctString)
{
szOctString.Empty();
for (DWORD dwIdx = 0; dwIdx < dwLength; dwIdx++)
{
CString szTempString;
szTempString.Format(L"%3.3o", pByte[dwIdx]);
if (dwIdx != 0)
{
szOctString += L" ";
}
szOctString += szTempString;
}
}
DWORD DecimalStringToByteArray(PCWSTR pszDecString, BYTE** ppByte)
{
CString szDecString = pszDecString;
BYTE* pToLargeArray = new BYTE[szDecString.GetLength()];
if (pToLargeArray == NULL)
{
*ppByte = NULL;
return 0;
}
UINT nByteCount = 0;
while (!szDecString.IsEmpty())
{
//
// Hex strings should always come 2 characters per byte
//
CString szTemp = szDecString.Left(3);
int iTempByte = 0;
swscanf(szTemp, L"%d", &iTempByte);
if (iTempByte <= 0xff)
{
pToLargeArray[nByteCount++] = iTempByte & 0xff;
}
else
{
//
// Format decimal error
//
ADSIEditMessageBox(IDS_FORMAT_DECIMAL_ERROR, MB_OK);
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
//
// Take off the value retrieved and the trailing space
//
szDecString = szDecString.Right(szDecString.GetLength() - 4);
}
*ppByte = new BYTE[nByteCount];
if (*ppByte == NULL)
{
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
memcpy(*ppByte, pToLargeArray, nByteCount);
delete[] pToLargeArray;
pToLargeArray = NULL;
return nByteCount;
}
void ByteArrayToDecimalString(BYTE* pByte, DWORD dwLength, CString& szDecString)
{
szDecString.Empty();
for (DWORD dwIdx = 0; dwIdx < dwLength; dwIdx++)
{
CString szTempString;
szTempString.Format(L"%3.3d", pByte[dwIdx]);
if (dwIdx != 0)
{
szDecString += L" ";
}
szDecString += szTempString;
}
}
DWORD BinaryStringToByteArray(PCWSTR pszBinString, BYTE** ppByte)
{
CString szBinString = pszBinString;
BYTE* pToLargeArray = new BYTE[szBinString.GetLength()];
if (pToLargeArray == NULL)
{
*ppByte = NULL;
return (DWORD)-1;
}
UINT nByteCount = 0;
while (!szBinString.IsEmpty())
{
//
// Binary strings should always come 8 characters per byte
//
BYTE chByte = 0;
CString szTemp = szBinString.Left(8);
for (int idx = 0; idx < 8; idx++)
{
if (szTemp[idx] == L'1')
{
chByte = 0x1 << (8 - idx);
}
}
pToLargeArray[nByteCount++] = chByte;
//
// Take off the value retrieved and the trailing space
//
szBinString = szBinString.Right(szBinString.GetLength() - 9);
}
*ppByte = new BYTE[nByteCount];
if (*ppByte == NULL)
{
delete[] pToLargeArray;
pToLargeArray = NULL;
return (DWORD)-1;
}
memcpy(*ppByte, pToLargeArray, nByteCount);
delete[] pToLargeArray;
pToLargeArray = NULL;
return nByteCount;
}
void ByteArrayToBinaryString(BYTE* pByte, DWORD dwLength, CString& szBinString)
{
szBinString.Empty();
for (DWORD dwIdx = 0; dwIdx < dwLength; dwIdx++)
{
CString szTempString;
BYTE chTemp = pByte[dwIdx];
for (size_t idx = 0; idx < sizeof(BYTE) * 8; idx++)
{
if ((chTemp & (0x1 << idx)) == 0)
{
szTempString = L'0' + szTempString;
}
else
{
szTempString = L'1' + szTempString;
}
}
if (dwIdx != 0)
{
szBinString += L" ";
}
szBinString += szTempString;
}
}
DWORD WCharStringToByteArray(PCWSTR pszWString, BYTE** ppByte)
{
DWORD dwSize = static_cast<DWORD>(wcslen(pszWString) * sizeof(WCHAR));
*ppByte = new BYTE[dwSize];
if (*ppByte != NULL)
{
memcpy(*ppByte, pszWString, dwSize);
}
else
{
dwSize = 0;
}
return dwSize;
}
void ByteArrayToWCharString(BYTE* pByte, DWORD dwLength, CString& szWString)
{
PWSTR pszValue = new WCHAR[(dwLength / sizeof(WCHAR)) + 1]; // +1 is for the /0 at the end
if (pszValue != NULL)
{
memset(pszValue, 0, dwLength + sizeof(WCHAR));
memcpy(pszValue, pByte, dwLength);
}
szWString = pszValue;
}
DWORD CharStringToByteArray(PCSTR pszCString, BYTE** ppByte)
{
DWORD dwSize = static_cast<DWORD>(strlen(pszCString) * sizeof(CHAR));
*ppByte = new BYTE[dwSize];
if (*ppByte != NULL)
{
memcpy(*ppByte, pszCString, dwSize);
}
else
{
dwSize = 0;
}
return dwSize;
}
void ByteArrayToCharString(BYTE* pByte, DWORD dwLength, CString& szCString)
{
PSTR pszValue = new CHAR[(dwLength / sizeof(CHAR)) + 1]; // +1 is for the /0 at the end
if (pszValue != NULL)
{
memset(pszValue, 0, dwLength + sizeof(CHAR));
memcpy(pszValue, pByte, dwLength);
}
PWSTR pwzValue = NULL;
if (CharToUnicode(pszValue, &pwzValue))
{
szCString = pwzValue;
delete[] pwzValue;
pwzValue = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////
BOOL LoadFileAsByteArray(PCWSTR pszPath, LPBYTE* ppByteArray, DWORD* pdwSize)
{
if (ppByteArray == NULL ||
pdwSize == NULL)
{
return FALSE;
}
CFile file;
if (!file.Open(pszPath, CFile::modeRead | CFile::shareDenyNone | CFile::typeBinary))
{
return FALSE;
}
*pdwSize = file.GetLength();
*ppByteArray = new BYTE[*pdwSize];
if (*ppByteArray == NULL)
{
return FALSE;
}
UINT uiCount = file.Read(*ppByteArray, *pdwSize);
ASSERT(uiCount == *pdwSize);
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: ConvertToFixedPitchFont
//
// Synopsis: Converts a windows font to a fixed pitch font.
//
// Arguments: [hwnd] -- IN window handle
//
// Returns: BOOL
//
// History: 7/15/1995 RaviR Created
//
//----------------------------------------------------------------------------
BOOL ConvertToFixedPitchFont(HWND hwnd)
{
LOGFONT lf;
HFONT hFont = reinterpret_cast<HFONT>(::SendMessage(hwnd, WM_GETFONT, 0, 0));
if (!GetObject(hFont, sizeof(LOGFONT), &lf))
{
return FALSE;
}
lf.lfQuality = PROOF_QUALITY;
lf.lfPitchAndFamily &= ~VARIABLE_PITCH;
lf.lfPitchAndFamily |= FIXED_PITCH;
lf.lfFaceName[0] = L'\0';
HFONT hf = CreateFontIndirect(&lf);
if (hf == NULL)
{
return FALSE;
}
::SendMessage(hwnd, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE); // macro in windowsx.h
return TRUE;
}