Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

758 lines
17 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
helper.h
This file defines the following macros helper classes and functions:
Macros to check HRESULT
CDlgHelper -- helper class to Enable/Check dialog Item,
CMangedPage -- helper class for PropertyPage,
It manages ReadOnly, SetModified, and ContextHelp
CStrArray -- an array of pointer to CString
It does NOT duplicate the string upon Add
and It deletes the pointer during destruction
It imports and exports SAFEARRAY
CReadWriteLock -- class for share read or exclusive write lock
CStrBox -- wrapper class for CListBox and CComboBox
CIPAddress -- wrapper for IPAddress
CFramedRoute -- Wrapper for FramedRoute
CStrParse -- parses string for TimeOfDay
FILE HISTORY:
*/
// helper functions for dialog and dialog items
#ifndef _DLGHELPER_
#define _DLGHELPER_
#define SAYOK { return S_OK;}
#define NOIMP { return E_NOTIMPL;}
#define TRACEENTER(n) TRACE(_T("Enter" #n))
#define TRACELEAVE(n) TRACE(_T("Leave" #n))
// to reduce the step to set VARIANT
#define V__BOOL(v, v1)\
V_VT(v) = VT_BOOL, V_BOOL(v) = (v1)
#define V__I4(v, v1)\
V_VT(v) = VT_I4, V_I4(v) = (v1)
#define V__I2(v, v1)\
V_VT(v) = VT_I2, V_I2(v) = (v1)
#define V__UI1(v, v1)\
V_VT(v) = VT_UI1, V_UI1(v) = (v1)
#define V__BSTR(v, v1)\
V_VT(v) = VT_BSTR, V_BSTR(v) = (v1)
#define V__ARRAY(v, v1)\
V_VT(v) = VT_ARRAY, V_ARRAY(v) = (v1)
#define REPORT_ERROR(hr) \
TRACE(_T("**** ERROR RETURN <%s @line %d> -> %08lx\n"), \
__FILE__, __LINE__, hr)); \
ReportError(hr, 0, 0);
#ifdef _DEBUG
#define CHECK_HR(hr)\
{if(!CheckADsError(hr, FALSE, __FILE__, __LINE__)){goto L_ERR;}}
#else
#define CHECK_HR(hr)\
if FAILED(hr) goto L_ERR
#endif
#ifdef _DEBUG
#define NOTINCACHE(hr)\
(CheckADsError(hr, TRUE, __FILE__, __LINE__))
#else
#define NOTINCACHE(hr)\
(E_ADS_PROPERTY_NOT_FOUND == (hr))
#endif
BOOL CheckADsError(HRESULT hr, BOOL fIgnoreAttrNotFound, PSTR file, int line);
#ifdef _DEBUG
#define TRACEAfxMessageBox(id) {\
TRACE(_T("AfxMessageBox <%s @line %d> ID: %d\n"), \
__FILE__, __LINE__, id); \
AfxMessageBox(id);}\
#else
#define TRACEAfxMessageBox(id) AfxMessageBox(id)
#endif
// change string Name to CN=Name
void DecorateName(LPWSTR outString, LPCWSTR inString);
// find name from DN for example LDAP://CN=userA,CN=users... returns userA
void FindNameByDN(LPWSTR outString, LPCWSTR inString);
class CDlgHelper
{
public:
static void EnableDlgItem(CDialog* pDialog, int id, bool bEnable = true);
static int GetDlgItemCheck(CDialog* pDialog, int id);
static void SetDlgItemCheck(CDialog* pDialog, int id, int nCheck);
};
// class CPageManager and CManagedPage together handle the situation when
// the property sheet need to do some processing when OnApply function is called
// on some of the pages
class CPageManager
{
public:
CPageManager(){ m_bModified = FALSE; m_bReadOnly = FALSE;};
BOOL GetModified(){ return m_bModified;};
void SetModified(BOOL bModified){ m_bModified = bModified;};
void SetReadOnly(BOOL bReadOnly){ m_bReadOnly = bReadOnly;};
BOOL GetReadOnly(){ return m_bReadOnly;};
virtual BOOL OnApply()
{
if (!GetModified()) return FALSE;
SetModified(FALSE); // prevent from doing this more than once
return TRUE;
}; // to be implemented by the propertysheet
protected:
BOOL m_bModified;
BOOL m_bReadOnly;
};
class CManagedPage : public CPropertyPage // talk back to property sheet
{
DECLARE_DYNCREATE(CManagedPage)
public:
CManagedPage() : CPropertyPage(){
m_bModified = FALSE;
m_bNeedToSave = FALSE;
m_pManager = NULL;
};
CManagedPage(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
{
m_bModified = FALSE;
m_bNeedToSave = FALSE;
m_pManager = NULL;
};
void SetModified( BOOL bModified = TRUE )
{
ASSERT(m_pManager);
if(!m_pManager->GetReadOnly()) // if NOT readonly
{
m_bModified = bModified;
m_bNeedToSave= bModified;
CPropertyPage::SetModified(bModified);
// only set change
if(bModified) m_pManager->SetModified(TRUE);
}
};
BOOL GetModified() { return m_bModified;};
BOOL OnApply()
{
m_bModified = FALSE;
BOOL b = TRUE;
if(m_pManager->GetModified()) // prevent from entering more than once
b= m_pManager->OnApply();
return (b && CPropertyPage::OnApply());
};
// a page has three states: not dirty, dirty and need to save, and not dirty but need to save
// m_bModified == dirty flag
// m_bNeedToSave == need to save flag
// When m_bNeedToSave && !m_bModified is detected upon on saved failure, the modified flag of the page is set
BOOL OnSaved(BOOL bSaved)
{
if(bSaved)
{
m_bModified = FALSE;
m_bNeedToSave = FALSE;
}
else if(m_bNeedToSave && !m_bModified)
SetModified(TRUE);
return TRUE;
};
void SetManager(CPageManager* pManager) { m_pManager = pManager;};
CPageManager* GetManager() { return m_pManager;};
protected:
// help info process
BOOL OnHelpInfo(HELPINFO* pHelpInfo);
void OnContextMenu(CWnd* pWnd, CPoint point);
void SetHelpTable(const DWORD* pTable) { m_pHelpTable = pTable;};
int MyMessageBox(UINT ids, UINT nType = MB_OK);
int MyMessageBox1(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK);
protected:
CPageManager* m_pManager;
BOOL m_bModified;
BOOL m_bNeedToSave;
const DWORD* m_pHelpTable;
};
#include <afxtempl.h>
class CStrArray : public CArray< CString*, CString* >
{
public:
CStrArray(SAFEARRAY* pSA = NULL);
CStrArray(const CStrArray& sarray);
int Find(const CString& Str) const;
int DeleteAll();
virtual ~CStrArray();
operator SAFEARRAY*();
CStrArray& operator = (const CStrArray& sarray);
bool AppendSA(SAFEARRAY* pSA);
};
class CDWArray : public CArray< DWORD, DWORD >
{
public:
CDWArray(const CDWArray& dwarray);
int Find(const DWORD dw) const;
int DeleteAll(){ RemoveAll(); return 0;};
virtual ~CDWArray(){RemoveAll();};
CDWArray& operator = (const CDWArray& dwarray);
operator SAFEARRAY*();
bool AppendSA(SAFEARRAY* pSA);
CDWArray(SAFEARRAY* pSA = NULL);
};
class CBYTEArray : public CArray< BYTE, BYTE >
{
public:
CBYTEArray(const CBYTEArray& bytearray);
int Find(const BYTE byte) const;
int DeleteAll(){ RemoveAll(); return 0;};
virtual ~CBYTEArray(){RemoveAll();};
CBYTEArray& operator = (const CBYTEArray& bytearray);
operator SAFEARRAY*();
bool AppendSA(SAFEARRAY* pSA);
HRESULT AssignBlob(PBYTE pByte, DWORD size);
HRESULT GetBlob(PBYTE pByte, DWORD* pSize);
CBYTEArray(SAFEARRAY* pSA = NULL);
};
// a lock to allow multiple read access exclusive or only one write access
class CReadWriteLock // sharable read, exclusive write
{
public:
CReadWriteLock() : m_nRead(0)
{
#ifdef _DEBUG
d_bWrite = false;
#endif
};
void EnterRead()
{
TRACE(_T("Entering Read Lock ..."));
m_csRead.Lock();
if (!m_nRead++)
m_csWrite.Lock();
m_csRead.Unlock();
TRACE(_T("Entered Read Lock\n"));
};
void LeaveRead()
{
TRACE(_T("Leaving Read Lock ..."));
m_csRead.Lock();
ASSERT(m_nRead > 0);
if (!--m_nRead)
m_csWrite.Unlock();
m_csRead.Unlock();
TRACE(_T("Left Read Lock\n"));
};
void EnterWrite()
{
TRACE(_T("Entering Write Lock ..."));
m_csWrite.Lock();
TRACE(_T("Entered Write Lock\n"));
#ifdef _DEBUG
d_bWrite = true;
#endif
};
void LeaveWrite()
{
#ifdef _DEBUG
d_bWrite = false;
#endif
m_csWrite.Unlock();
TRACE(_T("Left Write Lock\n"));
};
public:
#ifdef _DEBUG
bool d_bWrite;
#endif
protected:
CCriticalSection m_csRead;
CCriticalSection m_csWrite;
int m_nRead;
};
// to manage a list box/ combo box
template <class CBox>
class CStrBox
{
public:
CStrBox(CDialog* pDialog, int id, CStrArray& Strings)
: m_Strings(Strings), m_id(id)
{
m_pDialog = pDialog;
m_pBox = NULL;
};
int Fill()
{
m_pBox = (CBox*)m_pDialog->GetDlgItem(m_id);
ASSERT(m_pBox);
m_pBox->ResetContent();
int count = (int)m_Strings.GetSize();
int index;
for(int i = 0; i < count; i++)
{
index = m_pBox->AddString(*m_Strings[(INT_PTR)i]);
m_pBox->SetItemDataPtr(index, m_Strings[(INT_PTR)i]);
}
return count;
};
int DeleteSelected()
{
int index;
ASSERT(m_pBox);
index = m_pBox->GetCurSel();
// if there is any selected
if( index != LB_ERR )
{
CString* pStr;
pStr = (CString*)m_pBox->GetItemDataPtr(index);
// remove the entry from the box
m_pBox->DeleteString(index);
// find the string in the String array
int count = m_Strings.GetSize();
for(int i = 0; i < count; i++)
{
if (m_Strings[i] == pStr)
break;
}
ASSERT(i < count);
// remove the string from the string array
m_Strings.RemoveAt(i);
index = i;
delete pStr;
}
return index;
};
int AddString(CString* pStr) // the pStr needs to dynamically allocated
{
int index;
ASSERT(m_pBox && pStr);
index = m_pBox->AddString(*pStr);
m_pBox->SetItemDataPtr(index, pStr);
return m_Strings.Add(pStr);
};
int Select(int arrayindex) // the pStr needs to dynamically allocated
{
ASSERT(arrayindex < m_Strings.GetSize());
return m_pBox->SelectString(0, *m_Strings[(INT_PTR)arrayindex]);
};
void Enable(BOOL b) // the pStr needs to dynamically allocated
{
ASSERT(m_pBox);
m_pBox->EnableWindow(b);
};
int GetSelected() // it returns the index where the
{
int index;
ASSERT(m_pBox);
index = m_pBox->GetCurSel();
// if there is any selected
if( index != LB_ERR )
{
CString* pStr;
pStr = (CString*)m_pBox->GetItemDataPtr(index);
// find the string in the String array
int count = (int)m_Strings.GetSize();
for(int i = 0; i < count; i++)
{
if (m_Strings[(INT_PTR)i] == pStr)
break;
}
ASSERT(i < count);
index = i;
}
return index;
};
CBox* m_pBox;
protected:
int m_id;
CStrArray& m_Strings;
CDialog* m_pDialog;
};
// class to take care of ip address
class CIPAddress
{
public:
CIPAddress(DWORD address = 0)
{
m_dwAddress = address;
};
// CIPAddress(const CString& strAddress){};
operator DWORD() { return m_dwAddress;};
operator CString()
{
CString str;
WORD hi = HIWORD(m_dwAddress);
WORD lo = LOWORD(m_dwAddress);
str.Format(_T("%-d.%-d.%-d.%d"), HIBYTE(hi), LOBYTE(hi), HIBYTE(lo), LOBYTE(lo));
return str;
};
DWORD m_dwAddress;
};
// format of framedroute: mask dest metric ; mask and dest in dot format
class CFramedRoute
{
public:
void SetRoute(CString* pRoute)
{
m_pStrRoute = pRoute;
m_pStrRoute->TrimLeft();
m_pStrRoute->TrimRight();
m_iFirstSpace = m_pStrRoute->Find(_T(' ')) ;
m_iLastSpace = m_pStrRoute->ReverseFind(_T(' ')) ;
};
CString& GetDest(CString& dest) const
{
int i = m_pStrRoute->Find(_T('/'));
if(i == -1)
i = m_iFirstSpace;
dest = m_pStrRoute->Left(i);
return dest;
};
CString& GetNextStop(CString& nextStop) const
{
nextStop = m_pStrRoute->Mid(m_iFirstSpace + 1, m_iLastSpace - m_iFirstSpace -1 );
return nextStop;
};
CString& GetPrefixLength(CString& prefixLength) const
{
int i = m_pStrRoute->Find(_T('/'));
if( i != -1)
{
prefixLength = m_pStrRoute->Mid(i + 1, m_iFirstSpace - i - 1);
}
else
prefixLength = _T("");
return prefixLength;
};
CString& GetMask(CString& mask) const
{
int i = m_pStrRoute->Find(_T('/'));
DWORD dwMask = 0;
DWORD dwBit = 0x80000000;
DWORD dwPrefixLen;
if( i != -1)
{
mask = m_pStrRoute->Mid(i + 1, m_iFirstSpace - i - 1);
dwPrefixLen = _ttol((LPCTSTR)mask);
while(dwPrefixLen--)
{
dwMask |= dwBit;
dwBit >>= 1;
}
}
else
dwMask = 0;
WORD hi1, lo1;
hi1 = HIWORD(dwMask); lo1 = LOWORD(dwMask);
mask.Format(_T("%-d.%-d.%d.%d"),
HIBYTE(hi1), LOBYTE(hi1), HIBYTE(lo1), LOBYTE(lo1));
return mask;
};
CString& GetMetric(CString& metric) const
{
metric = m_pStrRoute->Mid(m_iLastSpace + 1);
return metric;
};
protected:
// WARNING: the string is not copied, so user need to make sure the origin is valid
CString* m_pStrRoute;
int m_iFirstSpace;
int m_iLastSpace;
};
class CStrParser
{
public:
CStrParser(LPCTSTR pStr = NULL) : m_pStr(pStr) { }
// get the current string position
LPCTSTR GetStr() const { return m_pStr;};
void SetStr(LPCTSTR pStr) { m_pStr = pStr;};
// find a unsigned interger and return it, -1 == not found
int GetUINT()
{
UINT ret = 0;
while((*m_pStr < _T('0') || *m_pStr > _T('9')) && *m_pStr != _T('\0'))
m_pStr++;
if(*m_pStr == _T('\0')) return -1;
while(*m_pStr >= _T('0') && *m_pStr <= _T('9'))
{
ret = ret * 10 + *m_pStr - _T('0');
m_pStr++;
}
return ret;
};
// find c and skip it
int GotoAfter(TCHAR c)
{
int ret = 0;
// go until find c or end of string
while(*m_pStr != c && *m_pStr != _T('\0'))
m_pStr++, ret++;
// if found
if(*m_pStr == c)
m_pStr++, ret++;
else
ret = -1;
return ret;
};
// skip blank characters space tab
void SkipBlank()
{
while((*m_pStr == _T(' ') || *m_pStr == _T('\t')) && *m_pStr != _T('\0'))
m_pStr++;
};
// check to see if the first character is '0'-'6' for Monday(0) to Sunday(6)
int DayOfWeek() {
SkipBlank();
if(*m_pStr >= _T('0') && *m_pStr <= _T('6'))
return (*m_pStr++ - _T('0'));
else
return -1; // not day of week
/* Mon Tue ... is not localizable
static CString m_strDaysList = _T("MON TUE WED THU FRI SAT SUN");
_strTemp = _T(" ");
for(int i = 0; i < 3 && *m_pStr != _T('\0'); i++)
{
_strTemp.SetAt(i, *m_pStr);
m_pStr++;
}
_strTemp.MakeUpper();
i = m_strDaysList.Find(_strTemp);
if(i == -1 || (i % 4) || ( i/4 > 6))
return -1; // not any or wrong value
return i/4;
*/
};
protected:
LPCTSTR m_pStr;
private:
CString _strTemp;
};
void ReportError(HRESULT hr, int nStr, HWND hWnd);
// number of characters
void AFXAPI DDV_MinChars(CDataExchange* pDX, CString const& value, int nChars);
/*!--------------------------------------------------------------------------
IsStandaloneServer
Returns S_OK if the machine name passed in is a standalone server,
or if pszMachineName is S_FALSE.
Returns S_FALSE otherwise.
Author: WeiJiang
---------------------------------------------------------------------------*/
HRESULT HrIsStandaloneServer(LPCTSTR pszMachineName);
HRESULT HrIsNTServer(LPCWSTR pMachineName);
class CBSTR
{
public:
CBSTR() : m_bstr(NULL) {};
CBSTR(LPCSTR cstr) : m_bstr(NULL)
{
USES_CONVERSION;
m_bstr = A2BSTR(cstr);
};
CBSTR(LPCWSTR wstr) : m_bstr(NULL)
{
USES_CONVERSION;
m_bstr = W2BSTR(wstr);
};
BSTR AssignBlob(const char* pByte, UINT size)
{
SysFreeString(m_bstr);
m_bstr = SysAllocStringByteLen(pByte, size);
return m_bstr;
};
BSTR AssignBSTR(const BSTR bstr)
{
return AssignBlob((const char *)bstr, SysStringByteLen(bstr));
};
UINT ByteLen()
{
UINT n = 0;
if(m_bstr)
n = SysStringByteLen(m_bstr);
return n;
};
operator BSTR() { return m_bstr;};
void Clean()
{
SysFreeString(m_bstr);
};
~CBSTR()
{
Clean();
};
BSTR m_bstr;
};
template<class T> class CNetDataPtr
{
public:
CNetDataPtr():m_pData(NULL){};
~CNetDataPtr()
{
NetApiBufferFree(m_pData);
};
T** operator&()
{
return &m_pData;
};
operator T*()
{
return m_pData;
};
T* operator ->()
{
return m_pData;
};
T* m_pData;
};
/*!--------------------------------------------------------------------------
EnableChildControls
Use this function to enable/disable/hide/show all child controls
on a page (actually it will work with any child windows, the
parent does not have to be a property page).
Author: KennT
---------------------------------------------------------------------------*/
HRESULT EnableChildControls(HWND hWnd, DWORD dwFlags);
#define PROPPAGE_CHILD_SHOW 0x00000001
#define PROPPAGE_CHILD_HIDE 0x00000002
#define PROPPAGE_CHILD_ENABLE 0x00000004
#define PROPPAGE_CHILD_DISABLE 0x00000008
/*---------------------------------------------------------------------------
Struct: AuthProviderData
This structure is used to hold information for Authentication AND
Accounting providers.
---------------------------------------------------------------------------*/
struct AuthProviderData
{
// The following fields will hold data for ALL auth/acct/EAP providers
CString m_stTitle;
CString m_stConfigCLSID; // CLSID for config object
CString m_stProviderTypeGUID; // GUID for the provider type
// These fields are used by auth/acct providers.
CString m_stGuid; // the identifying guid
// This flag is used for EAP providers
CString m_stKey; // name of registry key (for this provider)
BOOL m_fSupportsEncryption; // used by EAP provider data
DWORD m_dwStandaloneSupported;
};
typedef CArray<AuthProviderData, AuthProviderData&> AuthProviderArray;
HRESULT GetEapProviders(LPCTSTR machineName, AuthProviderArray *pProvList);
#endif