|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/
/*
helper.cpp Implementation of the following helper classes: CDlgHelper -- enable, check, getcheck of dialog items CStrArray -- manages an array of CString* It doesn't duplicate the string when add It deletes the pointers during destruction It imports and exports SAFEARRAY of BSTRs It has copy operatators CManagedPage -- provide a middle layer between CpropertyPage and real property page class to manage: readonly, set modify, and context help info.
CHelpDialog -- implments context help And global functions: BOOL CheckADsError() -- check error code from ADSI void DecorateName() -- make new name to "CN=name" for LDAP FILE HISTORY: */
#include "stdafx.h"
#include <afxtempl.h>
#include <shlobj.h>
#include <dsclient.h>
#include <winldap.h>
#include <dsgetdc.h>
#include <mmc.h>
#include "helper.h"
#include "resource.h"
#include <dsrole.h>
#include <lm.h>
#include <lmserver.h>
// helper function -- enable a dialog button
void CDlgHelper::EnableDlgItem(CDialog* pDialog, int id, bool bEnable) { CWnd* pWnd = pDialog->GetDlgItem(id); ASSERT(pWnd); pWnd->EnableWindow(bEnable); }
// helper function -- set check status of a dialog button
void CDlgHelper::SetDlgItemCheck(CDialog* pDialog, int id, int nCheck) { CButton* pButton = (CButton*)pDialog->GetDlgItem(id); ASSERT(pButton); pButton->SetCheck(nCheck); }
// helper function -- get check status of a dialog button
int CDlgHelper::GetDlgItemCheck(CDialog* pDialog, int id) { CButton* pButton = (CButton*)(pDialog->GetDlgItem(id)); ASSERT(pButton); return pButton->GetCheck(); }
CStrArray& CStrArray::operator = (const CStrArray& sarray) { int count = GetSize(); CString* pString;
// remove existing members
while(count --) { pString = GetAt(0); RemoveAt(0); delete pString; }
// copy new
count = sarray.GetSize();
for(int i = 0; i < count; i++) { pString = new CString(*sarray[i]); Add(pString); }
return *this; }
// convert an array of CString to SAFEARRAY
CStrArray::operator SAFEARRAY*() { USES_CONVERSION; int count = GetSize(); if(count == 0) return NULL;
SAFEARRAYBOUND bound[1]; SAFEARRAY* pSA = NULL; CString* pStr = NULL; long l[2]; VARIANT v; VariantInit(&v);
bound[0].cElements = count; bound[0].lLbound = 0; try{ // creat empty right size array
pSA = SafeArrayCreate(VT_VARIANT, 1, bound); if(NULL == pSA) return NULL;
// put in each element
for (long i = 0; i < count; i++) { pStr = GetAt(i); V_VT(&v) = VT_BSTR; V_BSTR(&v) = T2BSTR((LPTSTR)(LPCTSTR)(*pStr)); l[0] = i; SafeArrayPutElement(pSA, l, &v); VariantClear(&v); } } catch(CMemoryException*) { SafeArrayDestroy(pSA); pSA = NULL; VariantClear(&v); throw; }
return pSA; }
//build a StrArray from another array
CStrArray::CStrArray(const CStrArray& sarray) { int count = sarray.GetSize(); CString* pString = NULL;
for(int i = 0; i < count; i++) { try{ pString = new CString(*sarray[i]); Add(pString); } catch(CMemoryException*) { delete pString; throw; } } }
//build a StrArray from a safe array
CStrArray::CStrArray(SAFEARRAY* pSA) { if(pSA) AppendSA(pSA); }
//remove the elements from the array and delete them
int CStrArray::DeleteAll() { int ret, count; CString* pStr;
ret = count = GetSize();
while(count--) { pStr = GetAt(0); RemoveAt(0); delete pStr; }
return ret; }
CString* CStrArray::AddByRID(UINT id) { AFX_MANAGE_STATE(AfxGetStaticModuleState());
CString* pStr = NULL; try { pStr = new CString(); pStr->LoadString(id); Add(pStr); } catch(CMemoryException* pException) { pException->Delete(); delete pStr; pStr = NULL; } return pStr; }
//build a StrArray from a safe array
bool CStrArray::AppendSA(SAFEARRAY* pSA) { if(!pSA) return false;
CString* pString = NULL; long lIter; long lBound, uBound; VARIANT v; bool bSuc = true; // ser return value to true;
USES_CONVERSION; VariantInit(&v);
try{
SafeArrayGetLBound(pSA, 1, &lBound); SafeArrayGetUBound(pSA, 1, &uBound); for(lIter = lBound; lIter <= uBound; lIter++) { if(SUCCEEDED(SafeArrayGetElement(pSA, &lIter, &v))) { if(V_VT(&v) == VT_BSTR) { pString = new CString; (*pString) = (LPCTSTR)W2T(V_BSTR(&v)); Add(pString); } } } } catch(CMemoryException*) { delete pString; VariantClear(&v); bSuc = false; throw; }
return bSuc; }
//build a StrArray from a safe array
CStrArray::~CStrArray() { DeleteAll(); }
// return index if found, otherwise -1;
int CStrArray::Find(const CString& Str) const { int count = GetSize();
while(count--) { if(*GetAt(count) == Str) break; } return count; }
//build a DWArray from another array
CDWArray::CDWArray(const CDWArray& dwarray) { int count = dwarray.GetSize();
for(int i = 0; i < count; i++) { try{ Add(dwarray[i]); } catch(CMemoryException*) { throw; } } }
// return index if found, otherwise -1;
int CDWArray::Find(const DWORD dw) const { int count = GetSize();
while(count--) { if(GetAt(count) == dw) break; } return count; }
CDWArray& CDWArray::operator = (const CDWArray& dwarray) { int count;
RemoveAll();
// copy new
count = dwarray.GetSize();
for(int i = 0; i < count; i++) { Add(dwarray[i]); }
return *this; }
/////////////////////////////////////////////////////////////////////////////
// CManagedPage property page
IMPLEMENT_DYNCREATE(CManagedPage, CPropertyPage)
BEGIN_MESSAGE_MAP(CManagedPage, CPropertyPage) //{{AFX_MSG_MAP(CManagedPage)
ON_WM_HELPINFO() ON_WM_CONTEXTMENU() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CManagedPage::OnContextMenu(CWnd* pWnd, CPoint point) { if (m_pHelpTable) ::WinHelp (pWnd->m_hWnd, AfxGetApp()->m_pszHelpFilePath, HELP_CONTEXTMENU, (LPARAM)(LPVOID)m_pHelpTable); }
BOOL CManagedPage::OnHelpInfo(HELPINFO* pHelpInfo) { if (pHelpInfo->iContextType == HELPINFO_WINDOW && m_pHelpTable) { ::WinHelp ((HWND)pHelpInfo->hItemHandle, AfxGetApp()->m_pszHelpFilePath, HELP_WM_HELP, (LPARAM)(LPVOID)m_pHelpTable); } return TRUE; }
//---------------------------------------------------------------------------
// This is our self deleting callback function. If you have more than a
// a few property sheets, it might be a good idea to implement this in a
// base class and derive your MFC property sheets from the base class
//
UINT CALLBACK CManagedPage::PropSheetPageProc ( HWND hWnd, // [in] Window handle - always null
UINT uMsg, // [in,out] Either the create or delete message
LPPROPSHEETPAGE pPsp // [in,out] Pointer to the property sheet struct
) { ASSERT( NULL != pPsp );
// We need to recover a pointer to the current instance. We can't just use
// "this" because we are in a static function
CManagedPage* pMe = reinterpret_cast<CManagedPage*>(pPsp->lParam); ASSERT( NULL != pMe );
switch( uMsg ) { case PSPCB_CREATE: break;
case PSPCB_RELEASE: // Since we are deleting ourselves, save a callback on the stack
// so we can callback the base class
LPFNPSPCALLBACK pfnOrig = pMe->m_pfnOriginalCallback; delete pMe; return 1; //(pfnOrig)(hWnd, uMsg, pPsp);
} // Must call the base class callback function or none of the MFC
// message map stuff will work
return (pMe->m_pfnOriginalCallback)(hWnd, uMsg, pPsp);
} // end PropSheetPageProc()
//+----------------------------------------------------------------------------
//
// Function: CheckADsError
//
// Sysnopsis: Checks the result code from an ADSI call.
//
// Returns: TRUE if no error.
//
//-----------------------------------------------------------------------------
BOOL CheckADsError(HRESULT hr, BOOL fIgnoreAttrNotFound, PSTR file, int line) { if (SUCCEEDED(hr)) return TRUE;
if( hr == E_ADS_PROPERTY_NOT_FOUND && fIgnoreAttrNotFound) return TRUE;
if (hr == HRESULT_FROM_WIN32(ERROR_EXTENDED_ERROR)) { DWORD dwErr; WCHAR wszErrBuf[MAX_PATH+1]; WCHAR wszNameBuf[MAX_PATH+1]; ADsGetLastError(&dwErr, wszErrBuf, MAX_PATH, wszNameBuf, MAX_PATH); if ((LDAP_RETCODE)dwErr == LDAP_NO_SUCH_ATTRIBUTE && fIgnoreAttrNotFound) { return TRUE; } TRACE(_T("Extended Error 0x%x: %ws %ws (%s @line %d).\n"), dwErr, wszErrBuf, wszNameBuf, file, line); } else TRACE(_T("Error %08lx (%s @line %d)\n"), hr, file, line);
return FALSE; }
void DecorateName(LPWSTR outString, LPCWSTR inString) { wcscpy (outString, L"CN="); wcscat(outString, inString); }
void FindNameByDN(LPWSTR outString, LPCWSTR inString) {
LPWSTR p = wcsstr(inString, L"CN="); if(!p) p = wcsstr(inString, L"cn=");
if(!p) wcscpy(outString, inString); else { p+=3; LPWSTR p1 = outString; while(*p == L' ') p++; while(*p != L',') *p1++ = *p++; *p1 = L'\0'; } } #ifdef ___DS
static CString __DSRoot;
HRESULT GetDSRoot(CString& RootString) { if(__DSRoot.GetLength() == 0) { CString sADsPath; BSTR bstrDomainFolder = NULL; HRESULT hr; IADs* pDomainObject = NULL;
DOMAIN_CONTROLLER_INFO *pInfo = NULL; // get the name of the Domain Controller
DsGetDcName(NULL, NULL, NULL, NULL, 0, &pInfo); ASSERT(pInfo->DomainControllerName);
// strip off any backslashes or slashes
CString sDCName = pInfo->DomainControllerName; while(!sDCName.IsEmpty()) { if ('\\' == sDCName.GetAt(0) || '/' == sDCName.GetAt(0)) sDCName = sDCName.Mid(1); else break; }
int index = sDCName.Find(_T('.')); if(-1 != index) sDCName = sDCName.Left(index);
sADsPath = _T("LDAP://") + sDCName;
// Get the DC root DS object
hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)sADsPath), IID_IADs, (void**)&pDomainObject); if(FAILED(hr)) return hr;
// find the ADsPath of the DC root
hr = pDomainObject->get_ADsPath(&bstrDomainFolder);
if(FAILED(hr)) return hr;
pDomainObject->Release(); pDomainObject = NULL;
// construct the DN for the object where to put the registration information
__DSRoot = W2T(bstrDomainFolder); SysFreeString(bstrDomainFolder); index = __DSRoot.ReverseFind(_T('/')); __DSRoot = __DSRoot.Mid(index + 1); // strip off the ADsPath prefix to get the X500 DN
} RootString = __DSRoot; return S_OK; }
#endif //___DS
/////////////////////////////////////////////////////////////////////////////
// Min Chars Dialog Data Validation
void AFXAPI DDV_MinChars(CDataExchange* pDX, CString const& value, int nChars) { ASSERT(nChars >= 1); // allow them something
if (pDX->m_bSaveAndValidate && value.GetLength() < nChars) { TCHAR szT[32]; wsprintf(szT, _T("%d"), nChars); CString prompt; AfxFormatString1(prompt, IDS_MIN_CHARS, szT); AfxMessageBox(prompt, MB_ICONEXCLAMATION, IDS_MIN_CHARS); prompt.Empty(); // exception prep
pDX->Fail(); } }
#define MAX_STRING 1024
//+----------------------------------------------------------------------------
//
// Function: ReportError
//
// Sysnopsis: Attempts to get a user-friendly error message from the system.
//
//-----------------------------------------------------------------------------
void ReportError(HRESULT hr, int nStr, HWND hWnd) { PTSTR ptzSysMsg; int cch; CString AppStr; CString SysStr; CString ErrTitle; CString ErrMsg;
TRACE (_T("*+*+* ReportError called with hr = %lx"), hr); if (!hWnd) { hWnd = GetDesktopWindow(); }
try{ if (nStr) { AppStr.LoadString(nStr); }
cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PTSTR)&ptzSysMsg, 0, NULL);
if (!cch) { //try ads errors
HMODULE adsMod; adsMod = GetModuleHandle(_T("activeds.dll")); cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, adsMod, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (PTSTR)&ptzSysMsg, 0, NULL); } if (!cch) { CString str; str.LoadString(IDS_ERR_ERRORCODE); SysStr.Format(str, hr); } else { SysStr = ptzSysMsg; LocalFree(ptzSysMsg); }
ErrTitle.LoadString(IDS_ERR_TITLE); if(!AppStr.IsEmpty()) { ErrMsg.Format(AppStr, (LPCTSTR)SysStr); } else { ErrMsg = SysStr; }
MessageBox(hWnd, (LPCTSTR)ErrMsg, (LPCTSTR)ErrTitle, MB_OK | MB_ICONINFORMATION); }catch(CMemoryException* pException) { pException->Delete(); MessageBox(hWnd, _T("No enought memory, please close other applications and try again."), _T("ACS Snapin Error"), MB_OK | MB_ICONINFORMATION); } }
BOOL CPageManager::OnApply() { if (!GetModified()) return FALSE;
SetModified(FALSE); // prevent from doing this more than once
std::list<CManagedPage*>::iterator i; for(i = m_listPages.begin(); i != m_listPages.end(); i++) { if ((*i)->GetModified()) (*i)->OnApply(); } return TRUE; }
void CPageManager::AddPage(CManagedPage* pPage) { m_listPages.push_back(pPage); pPage->SetManager(this); }
/*!--------------------------------------------------------------------------
HrIsStandaloneServer Returns S_OK if the machine name passed in is a standalone server, or if pszMachineName is S_FALSE.
Returns FALSE otherwise. Author: WeiJiang ---------------------------------------------------------------------------*/ HRESULT HrIsStandaloneServer(LPCWSTR pMachineName) { DWORD netRet = 0; HRESULT hr = S_OK; DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdsRole = NULL;
netRet = DsRoleGetPrimaryDomainInformation(pMachineName, DsRolePrimaryDomainInfoBasic, (LPBYTE*)&pdsRole);
if(netRet != 0) { hr = HRESULT_FROM_WIN32(netRet); goto L_ERR; }
ASSERT(pdsRole); // if the machine is not a standalone server
if(pdsRole->MachineRole != DsRole_RoleStandaloneServer) { hr = S_FALSE; } L_ERR: if(pdsRole) DsRoleFreeMemory(pdsRole);
return hr; }
/*!--------------------------------------------------------------------------
HrIsNTServer Author: ---------------------------------------------------------------------------*/ HRESULT HrIsNTServer(LPCWSTR pMachineName, DWORD* pMajorVersion) { HRESULT hr = S_OK; SERVER_INFO_102* pServerInfo102 = NULL; NET_API_STATUS netRet = 0;
netRet = NetServerGetInfo((LPWSTR)pMachineName, 102, (LPBYTE*)&pServerInfo102);
if(netRet != 0) { hr = HRESULT_FROM_WIN32(netRet); goto L_ERR; }
ASSERT(pServerInfo102);
// check if the machine focused on is a standalone server
//
*pMajorVersion = (pServerInfo102->sv102_version_major & MAJOR_VERSION_MASK);
if (!(pServerInfo102->sv102_type & SV_TYPE_SERVER_NT)) { hr = S_FALSE; }
L_ERR:
if(pServerInfo102) NetApiBufferFree(pServerInfo102);
return hr; }
|