|
|
//+----------------------------------------------------------------------------
//
// Windows NT Directory Service Property Pages
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: notify.cxx
//
// Contents: Change notification ref-counting object.
//
// Classes: CNotifyObj
//
// History: 20-Jan-98 EricB
//
//-----------------------------------------------------------------------------
#include "pch.h"
#include "proppage.h"
#include "objlist.h" // g_ClassIconCache
#define NOTIFYOUT(x) dspDebugOut((DEB_ITRACE, "Notify Obj (this: 0x%p) " #x "\n", this));
#define DSPROP_WAITTIME 600000 // wait 600 seconds, 10 minutes.
//+----------------------------------------------------------------------------
//
// Function: ADsPropCreateNotifyObj
//
// Synopsis: Checks to see if the notification window/object exists for this
// sheet instance and if not creates it.
//
// Arguments: [pAppThdDataObj] - the unmarshalled data object pointer.
// [pwzADsObjName] - object path name.
// [phNotifyObj] - to return the notificion window handle.
//
// Returns: HRESULTs.
//
//-----------------------------------------------------------------------------
STDAPI ADsPropCreateNotifyObj(LPDATAOBJECT pAppThdDataObj, PWSTR pwzADsObjName, HWND * phNotifyObj) { return CNotifyObj::Create(pAppThdDataObj, pwzADsObjName, phNotifyObj); }
//+----------------------------------------------------------------------------
//
// Function: ADsPropGetInitInfo
//
// Synopsis: Pages call this at their init time to retreive DS object info.
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [pInitParams] - struct filled in with DS object info.
//
// Returns: FALSE if the notify window has gone away for some reason.
//
// Note that pInitParams->pWritableAttrs can be NULL if there are no writable
// attributes.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropGetInitInfo(HWND hNotifyObj, PADSPROPINITPARAMS pInitParams) { return CNotifyObj::GetInitInfo(hNotifyObj, pInitParams); }
//+----------------------------------------------------------------------------
//
// Function: ADsPropSetHwndWithTitle
//
// Synopsis: Pages call this at their dialog init time to send their hwnd
// to the Notify object. Use this function instead of
// ADsPropSetHwnd for multi-select property pages.
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [hPage] - the page's window handle.
// [ptzTitle] - the page's title
//
// Returns: FALSE if the notify window has gone away for some reason.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropSetHwndWithTitle(HWND hNotifyObj, HWND hPage, PTSTR ptzTitle) { return CNotifyObj::SetHwnd(hNotifyObj, hPage, ptzTitle); }
//+----------------------------------------------------------------------------
//
// Function: ADsPropSetHwnd
//
// Synopsis: Pages call this at their dialog init time to send their hwnd
// to the Notify object.
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [hPage] - the page's window handle.
//
// Returns: FALSE if the notify window has gone away for some reason.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropSetHwnd(HWND hNotifyObj, HWND hPage) { return ADsPropSetHwndWithTitle(hNotifyObj, hPage, 0); }
//+----------------------------------------------------------------------------
//
// function: ADsPropCheckIfWritable
//
// Synopsis: See if the attribute is writable by checking if it is in
// the allowedAttributesEffective array.
//
// Arguments: [pwzAttr] - the attribute name.
// [pWritableAttrs] - the array of writable attributes.
//
// Returns: FALSE if the attribute name is not found in the writable-attrs
// array or if the array pointer is NULL.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropCheckIfWritable(const PWSTR pwzAttr, const PADS_ATTR_INFO pWritableAttrs) { BOOL fWritable = FALSE;
if (!pWritableAttrs || IsBadReadPtr(pWritableAttrs, sizeof(ADS_ATTR_INFO))) { return FALSE; }
for (DWORD i = 0; i < pWritableAttrs->dwNumValues; i++) { if (_wcsicmp(pWritableAttrs->pADsValues[i].CaseIgnoreString, pwzAttr) == 0) { fWritable = TRUE; break; } } return fWritable; }
//+----------------------------------------------------------------------------
//
// function: ADsPropSendErrorMessage
//
// Synopsis: Adds an error message to a list which is presented when
// ADsPropShowErrorDialog is called
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [pError] - the error structure
//
// Returns: FALSE if the notify window has gone away for some reason.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropSendErrorMessage(HWND hNotifyObj, PADSPROPERROR pError) { return SendMessage(hNotifyObj, WM_ADSPROP_NOTIFY_ERROR, 0, (LPARAM)pError) != 0; }
//+----------------------------------------------------------------------------
//
// function: ADsPropShowErrorDialog
//
// Synopsis: Presents an error dialog with the error messages accumulated
// through calls to ADsPropSendErrorMessage
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [hPage] - the property page window handle.
//
// Returns: FALSE if the notify window has gone away for some reason.
//
//-----------------------------------------------------------------------------
STDAPI_(BOOL) ADsPropShowErrorDialog(HWND hNotifyObj, HWND hPage) { #ifdef DSADMIN
CNotifyObj* pNotifyObj = NULL;
dspAssert(hNotifyObj); if (!IsWindow(hNotifyObj)) { return FALSE; } LRESULT lResult = SendMessage(hNotifyObj, WM_ADSPROP_NOTIFY_GET_NOTIFY_OBJ, 0, (LPARAM)&pNotifyObj);
if (lResult && pNotifyObj) { CMultiSelectErrorDialog dlg(hNotifyObj, hPage); CPageInfo* pPageInfoArray = pNotifyObj->m_pPageInfoArray; UINT cPages = pNotifyObj->m_cPages; IDataObject* pDataObject = pNotifyObj->m_pAppThdDataObj;
dspAssert(pPageInfoArray); dspAssert(cPages > 0); dspAssert(pDataObject);
HRESULT hr = dlg.Init(pPageInfoArray, cPages, pDataObject); if (SUCCEEDED(hr)) { dlg.DoModal(); SetForegroundWindow(dlg.m_hWnd);
for (UINT pageIdx = 0; pageIdx < cPages; pageIdx++) { pPageInfoArray[pageIdx].m_ApplyErrors.Clear(); pPageInfoArray[pageIdx].m_ApplyStatus = CPageInfo::notAttempted; } } } #endif
return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::Create
//
// Synopsis: Creation procedure: creates instances of the object.
//
// Arguments: [pAppThdDataObj] - the unmarshalled data object pointer.
// [pwzADsObjName] - object path name.
// [phNotifyObj] - to return the notificion window handle.
//
// Returns: HRESULTs.
//
//-----------------------------------------------------------------------------
HRESULT CNotifyObj::Create(LPDATAOBJECT pAppThdDataObj, PWSTR pwzADsObjName, HWND * phNotifyObj) { HWND hNotify; HRESULT hr = S_OK;
// Only one caller at a time.
//
CNotifyCreateCriticalSection NotifyCS;
//
// See if the object/window already exist for this property sheet and
// get the object DN.
//
hNotify = FindSheetNoSetFocus(pwzADsObjName);
if (hNotify != NULL) { // The window already exists, return the window handle.
//
*phNotifyObj = hNotify; dspDebugOut((DEB_ITRACE, "CNotifyObj::Create returning existing notify obj HWND.\n")); return S_OK; } dspDebugOut((DEB_ITRACE, "CNotifyObj::Create, creating notify obj.\n"));
PPROPSHEETCFG pSheetCfg; PROPSHEETCFG sheetCfg; ZeroMemory(&sheetCfg, sizeof(PROPSHEETCFG)); STGMEDIUM sm = {TYMED_NULL, NULL, NULL}; FORMATETC fmte = {g_cfDsPropCfg, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
hr = pAppThdDataObj->GetData(&fmte, &sm);
if (FAILED(hr)) { if (hr != DV_E_FORMATETC) { REPORT_ERROR_FORMAT(hr, IDS_NOTIFYFAILURE, GetDesktopWindow()); return hr; } } else { pSheetCfg = (PPROPSHEETCFG)sm.hGlobal;
//NTRAID#NTBUG9-567482-2002/03/10-jmessec dspAssert simply maps to ASSERT; if sm.hGlobal can be NULL, back it up with code
dspAssert(pSheetCfg); memcpy(&sheetCfg, pSheetCfg, sizeof(PROPSHEETCFG));
ReleaseStgMedium(&sm); }
//
// Create the notification object.
//
CNotifyObj * pNotifyObj = new CNotifyObj(pAppThdDataObj, &sheetCfg);
CHECK_NULL_REPORT(pNotifyObj, GetDesktopWindow(), return ERROR_OUTOFMEMORY);
if (pNotifyObj->m_hr != S_OK) { REPORT_ERROR_FORMAT(pNotifyObj->m_hr, IDS_NOTIFYFAILURE, GetDesktopWindow()); return pNotifyObj->m_hr; }
dspDebugOut((DEB_ITRACE, "Notify Obj (this: 0x%p) object allocated, pAppThdDataObj = 0x%08p\n", pNotifyObj, pAppThdDataObj));
if (!AllocWStr(pwzADsObjName, &pNotifyObj->m_pwzObjDN)) { return E_OUTOFMEMORY; }
uintptr_t hThread;
hThread = _beginthread(NotifyThreadFcn, 0, (PVOID)pNotifyObj);
if (hThread == -1) { dspDebugOut((DEB_ERROR, "_beginthread failed with error %s\n", strerror(errno))); REPORT_ERROR_FORMAT(ERROR_NOT_ENOUGH_MEMORY, IDS_NOTIFYFAILURE, GetDesktopWindow()); return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); }
//
// Wait for initialization to complete and return the results.
//
if (WaitForSingleObject(pNotifyObj->m_hInitEvent, DSPROP_WAITTIME) == WAIT_TIMEOUT) { CloseHandle(pNotifyObj->m_hInitEvent); REPORT_ERROR_FORMAT(0, IDS_NOTIFYTIMEOUT, GetDesktopWindow()); return HRESULT_FROM_WIN32(WAIT_TIMEOUT); }
CloseHandle(pNotifyObj->m_hInitEvent);
if (pNotifyObj->m_hWnd != NULL) { *phNotifyObj = pNotifyObj->m_hWnd; } else { REPORT_ERROR_FORMAT(pNotifyObj->m_hr, IDS_NOTIFYFAILURE, GetDesktopWindow()); hr = pNotifyObj->m_hr; delete pNotifyObj; return hr; } return S_OK; }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::GetInitInfo
//
// Synopsis: Pages call this at their init time to retreive DS object info.
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [pInitParams] - struct filled in with DS object info.
//
// Note that pInitParams->pWritableAttrs can be NULL if there are no writable
// attributes.
//
//-----------------------------------------------------------------------------
BOOL CNotifyObj::GetInitInfo(HWND hNotifyObj, PADSPROPINITPARAMS pInitParams) { dspDebugOut((DEB_ITRACE, "CNotifyObj::GetInitInfo\n")); if (IsBadWritePtr(pInitParams, sizeof(ADSPROPINITPARAMS))) { return FALSE; } dspAssert(hNotifyObj && pInitParams); if (!IsWindow(hNotifyObj)) { pInitParams->hr = E_FAIL; return FALSE; } if (pInitParams->dwSize != sizeof (ADSPROPINITPARAMS)) { return FALSE; } SendMessage(hNotifyObj, WM_ADSPROP_NOTIFY_PAGEINIT, 0, (LPARAM)pInitParams); return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::SetHwnd
//
// Synopsis: Pages call this at their dialog init time to send their hwnd.
//
// Arguments: [hNotifyObj] - the notificion window handle.
// [hPage] - the page's window handle.
//
// Returns: FALSE if the notify window has gone away for some reason.
//
//-----------------------------------------------------------------------------
BOOL CNotifyObj::SetHwnd(HWND hNotifyObj, HWND hPage, PTSTR ptzTitle) { dspDebugOut((DEB_ITRACE, "CNotifyObj::SetHwnd\n")); dspAssert(hNotifyObj && hPage); if (!IsWindow(hNotifyObj)) { return FALSE; } SendMessage(hNotifyObj, WM_ADSPROP_NOTIFY_PAGEHWND, (WPARAM)hPage, (LPARAM)ptzTitle); return TRUE; }
//+----------------------------------------------------------------------------
//
// Method: NotifyThreadFcn
//
// Synopsis: Object window creation and message loop thread.
//
//-----------------------------------------------------------------------------
VOID __cdecl NotifyThreadFcn(PVOID pParam) { // All of the function except the _endthread() call is enclosed in braces
// so that the dtors of the auto classes would run. Otherwise the thread is
// ended before the function scope is left and the auto class object dtors
// never run.
{ CNotifyObj * pNotifyObj = (CNotifyObj *)pParam; dspAssert(pNotifyObj);
MSG msg;
CSmartPtr <TCHAR> ptzTitle; if (!UnicodeToTchar(pNotifyObj->m_pwzObjDN, &ptzTitle)) { pNotifyObj->m_hr = E_OUTOFMEMORY; SetEvent(pNotifyObj->m_hInitEvent); return; }
CStr cstrTitle(ptzTitle);
WCHAR szIH[10]; _itow(g_iInstance, szIH, 16);
cstrTitle += szIH;
//
// The window title is set to the DN of the object plus the instance
// identifier converted to a string. This enables FindWindow to locate a
// pre-existing instance of the notify window for a specific object for
// a specific instance of DS Admin.
//
pNotifyObj->m_hWnd = CreateWindow(tzNotifyWndClass, cstrTitle, WS_POPUP, 0, 0, 1, 1, NULL, NULL, g_hInstance, pNotifyObj); if (pNotifyObj->m_hWnd == NULL) { DWORD dwErr = GetLastError(); dspDebugOut((DEB_ERROR, "Notify Obj window creation failed with error %d!\n", dwErr)); pNotifyObj->m_hr = HRESULT_FROM_WIN32(dwErr); SetEvent(pNotifyObj->m_hInitEvent); return; } dspDebugOut((DEB_ITRACE, "Notify Obj (this: 0x%p) window creation complete.\n", pNotifyObj));
SetEvent(pNotifyObj->m_hInitEvent);
while (GetMessage(&msg, NULL, 0, 0)) { DispatchMessage(&msg); }
delete pNotifyObj; } _endthread(); }
//+----------------------------------------------------------------------------
//
// Method: _FindDSAHiddenWindowFromDSFind
//
// Synopsis: Looks for hidden DSA window of the snapin instance calling DS Find
//
// Returns: HWND of DSA hidden window if called from DS Find.
//
//-----------------------------------------------------------------------------
BOOL CALLBACK EnumDSAHiddenWindowProc(HWND hwnd, LPARAM lParam) { HWND* phWnd = (HWND*)lParam; *phWnd = NULL;
// get the window class
TCHAR szClass[64]; if (0 == GetClassName(hwnd, szClass, 64)) { return TRUE; } if (_tcscmp(szClass, TEXT("DSAHiddenWindow")) != 0) { return TRUE; // no match, continue
}
// got a DSA hidden window
// get the window title, to make sure it is
// the one originating DS Find
TCHAR szTitle[256]; ::GetWindowText(hwnd, szTitle, 256); if (_tcscmp(szTitle, TEXT("DS Find")) != 0) { return TRUE; // no match continue
}
// we go the right class and title, but
// we still have to verify it is from the
// same process (assuming DS Find modal)
DWORD dwProcessId = 0x0; GetWindowThreadProcessId(hwnd, &dwProcessId);
if (GetCurrentProcessId() != dwProcessId) { return TRUE; // from wrong process, continue
}
// finally, we got it!!
*phWnd = hwnd; return FALSE; }
HWND _FindDSAHiddenWindowFromDSFind() { HWND hwndHidden = NULL; EnumWindows(EnumDSAHiddenWindowProc, (LPARAM)&hwndHidden); return hwndHidden; }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::CNotifyObj
//
//-----------------------------------------------------------------------------
CNotifyObj::CNotifyObj(LPDATAOBJECT pDataObj, PPROPSHEETCFG pSheetCfg) : m_hWnd(NULL), m_hPropSheet(NULL), m_cPages(0), m_cApplies(0), m_pAppThdDataObj(pDataObj), m_pStrmMarshalledDO(NULL), m_hInitEvent(NULL), m_fBeingDestroyed(FALSE), m_fSheetDirty(FALSE), m_hr(S_OK), m_pwzObjDN(NULL), m_pDsObj(NULL), m_pwzCN(NULL), m_pWritableAttrs(NULL), m_pAttrs(NULL), m_pPageInfoArray(NULL) { #ifdef _DEBUG
strcpy(szClass, "CNotifyObj"); #endif
memcpy(&m_sheetCfg, pSheetCfg, sizeof(PROPSHEETCFG));
if (m_sheetCfg.hwndHidden == NULL) { // we might be called from DS Find, so we want to find
// the DSA hidden window, needed for creating
// secondary property sheets
m_sheetCfg.hwndHidden = _FindDSAHiddenWindowFromDSFind(); }
//
// We need to addref the data object but can't release it on this thread,
// so we marshall it (which implicitly addrefs it) and then then unmarshall
// and release on the notify object thread.
//
CoMarshalInterThreadInterfaceInStream(IID_IDataObject, pDataObj, &m_pStrmMarshalledDO);
m_hInitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hInitEvent == NULL) { m_hr = HRESULT_FROM_WIN32(GetLastError()); }
//
// Arbitrary default size. This will expand as more pages are added
//
m_nPageInfoArraySize = 5; m_pPageInfoArray = new CPageInfo[m_nPageInfoArraySize]; }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::~CNotifyObj
//
//-----------------------------------------------------------------------------
CNotifyObj::~CNotifyObj(void) { NOTIFYOUT(destructor);
LPDATAOBJECT pNotifyThdDataObj = NULL;
if (m_pStrmMarshalledDO) { CoGetInterfaceAndReleaseStream(m_pStrmMarshalledDO, IID_IDataObject, reinterpret_cast<void**>(&pNotifyThdDataObj)); m_pStrmMarshalledDO = NULL; } DO_RELEASE(pNotifyThdDataObj); //DBG_OUT("-----------------------releasing object in notify obj dtor");
DO_RELEASE(m_pDsObj);
if (m_sheetCfg.lNotifyHandle && !IsBadReadPtr( reinterpret_cast<void*>(m_sheetCfg.lNotifyHandle), sizeof(LONG_PTR))) { MMCFreeNotifyHandle(m_sheetCfg.lNotifyHandle); m_sheetCfg.lNotifyHandle = 0; } if (m_sheetCfg.hwndHidden && m_sheetCfg.wParamSheetClose) { ::PostMessage(m_sheetCfg.hwndHidden, WM_DSA_SHEET_CLOSE_NOTIFY, (WPARAM)m_sheetCfg.wParamSheetClose, (LPARAM)0); } DO_DEL(m_pwzObjDN); if (m_pAttrs) { FreeADsMem(m_pAttrs); }
if (m_pPageInfoArray != NULL) { delete[] m_pPageInfoArray; m_pPageInfoArray = NULL; }
}
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::StaticNotifyProc
//
// Synopsis: window procedure
//
//-----------------------------------------------------------------------------
LRESULT CALLBACK CNotifyObj::StaticNotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CNotifyObj * pNotifyObj = (CNotifyObj*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
if (uMsg == WM_CREATE) { pNotifyObj = (CNotifyObj *)((CREATESTRUCT *)lParam)->lpCreateParams; SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pNotifyObj); }
if (pNotifyObj) { return pNotifyObj->NotifyProc(hWnd, uMsg, wParam, lParam); }
return DefWindowProc(hWnd, uMsg, wParam, lParam); }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::NotifyProc
//
// Synopsis: Instance window procedure
//
//-----------------------------------------------------------------------------
LRESULT CALLBACK CNotifyObj::NotifyProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: return OnCreate();
case WM_ADSPROP_NOTIFY_PAGEINIT: dspDebugOut((DEB_ITRACE, "Notify Obj 0x%p: WM_ADSPROP_NOTIFY_PAGEINIT\n", this)); PADSPROPINITPARAMS pInitParams; pInitParams = (PADSPROPINITPARAMS)lParam; pInitParams->hr = m_hr; pInitParams->pDsObj = m_pDsObj; pInitParams->pwzCN = m_pwzCN; pInitParams->pWritableAttrs = m_pWritableAttrs; return 0;
case WM_ADSPROP_NOTIFY_PAGEHWND: { m_cApplies = ++m_cPages; dspDebugOut((DEB_ITRACE, "Notify Obj 0x%p: WM_ADSPROP_NOTIFY_PAGEHWND count now %d\n", this, m_cPages)); HWND hWndPage = (HWND)wParam; if (!m_hPropSheet) { m_hPropSheet = GetParent(hWndPage); }
if (m_cPages > m_nPageInfoArraySize) { //
// REVIEW_JEFFJON : after going beyond the initial size, should the size increase
// incrementally or in chunks?
//
CPageInfo* pNewPageInfoArray = new CPageInfo[m_cPages]; if (pNewPageInfoArray != NULL) { memset(pNewPageInfoArray, 0, sizeof(CPageInfo) * m_cPages); memcpy(pNewPageInfoArray, m_pPageInfoArray, sizeof(CPageInfo) * m_nPageInfoArraySize); delete[] m_pPageInfoArray; m_pPageInfoArray = pNewPageInfoArray; m_nPageInfoArraySize = m_cPages; } }
//NTRAID#NTBUG9-572006-2002/03/10-jmessec buffer overrun: If memory allocation fails above, the array is too small
m_pPageInfoArray[m_cPages - 1].m_hWnd = hWndPage;
//
// Copy the title if one was sent
//
PTSTR ptzPageTitle = reinterpret_cast<PTSTR>(lParam); if (ptzPageTitle != NULL) { size_t iTitleSize = _tcslen(ptzPageTitle); m_pPageInfoArray[m_cPages - 1].m_ptzTitle = new TCHAR[iTitleSize + 1]; if (m_pPageInfoArray[m_cPages - 1].m_ptzTitle != NULL) { _tcscpy(m_pPageInfoArray[m_cPages - 1].m_ptzTitle, ptzPageTitle); } } } return 0;
case WM_ADSPROP_NOTIFY_APPLY: { NOTIFYOUT(WM_ADSPROP_NOTIFY_APPLY); if ((BOOL)wParam) { // The security page and extension pages don't inherit from our
// page framework and thus don't participate in the notify object
// refcounting or the page-dirty flagging. So, don't fire a change
// notification unless one of our pages was dirty.
//
m_fSheetDirty = TRUE; }
// NTRAID#NTBUG9-462165-2001/10/17-JeffJon
// Need to set the apply status to success.
HWND hPage = reinterpret_cast<HWND>(lParam); if (hPage) { for (UINT idx = 0; idx < m_cPages; idx++) { if (m_pPageInfoArray[idx].m_hWnd == hPage) { m_pPageInfoArray[idx].m_ApplyStatus = CPageInfo::success; break; } } }
if (--m_cApplies == 0 && m_fSheetDirty) { NOTIFYOUT(Sending change notification); if (m_sheetCfg.lNotifyHandle) { // The change notify call results in a PostMessage back to the
// MMC main thread. Therefore, we need to pass the data object
// pointer that came from the main thread.
//
MMCPropertyChangeNotify(m_sheetCfg.lNotifyHandle, (LPARAM)m_pAppThdDataObj); } if (m_sheetCfg.hwndParentSheet) { PostMessage(m_sheetCfg.hwndParentSheet, WM_ADSPROP_NOTIFY_CHANGE, 0, 0); } m_cApplies = m_cPages; m_fSheetDirty = FALSE;
//
// Change the status of all the pages back to notAttempted
//
for (UINT idx = 0; idx < m_cPages; idx++) { m_pPageInfoArray[idx].m_ApplyStatus = CPageInfo::notAttempted; }
} return 0; }
case WM_ADSPROP_NOTIFY_ERROR: { NOTIFYOUT(WM_ADSPROP_NOTIFY_ERROR); PADSPROPERROR pApplyErrors = reinterpret_cast<PADSPROPERROR>(lParam); if (pApplyErrors != NULL) { for (UINT idx = 0; idx < m_cPages; idx++) { if (m_pPageInfoArray[idx].m_hWnd == pApplyErrors->hwndPage) { m_pPageInfoArray[idx].m_ApplyErrors.SetError(pApplyErrors); if (m_pPageInfoArray[idx].m_ApplyErrors.GetErrorCount() > 0) { m_pPageInfoArray[idx].m_ApplyStatus = CPageInfo::failed; } else { m_pPageInfoArray[idx].m_ApplyStatus = CPageInfo::success; } break; } } } return 0; }
case WM_ADSPROP_NOTIFY_GET_NOTIFY_OBJ: { NOTIFYOUT(WM_ADSPROP_NOTIFY_GET_NOTIFY_OBJ); BOOL retVal = FALSE; if (lParam != NULL) { CNotifyObj** ppNotifyObj = reinterpret_cast<CNotifyObj**>(lParam); if (ppNotifyObj) { *ppNotifyObj = this; retVal = TRUE; } } return retVal; }
case WM_ADSPROP_NOTIFY_SETFOCUS: NOTIFYOUT(WM_ADSPROP_NOTIFY_SETFOCUS); SetForegroundWindow(m_hPropSheet); return 0;
case WM_ADSPROP_NOTIFY_FOREGROUND: NOTIFYOUT(WM_ADSPROP_NOTIFY_FOREGROUND); if (wParam) // bActivate flag
{ SetForegroundWindow(m_hPropSheet); } else { SetWindowPos(m_hPropSheet, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE); } return 0;
case WM_ADSPROP_SHEET_CREATE: NOTIFYOUT(WM_ADSPROP_SHEET_CREATE);
if (m_sheetCfg.hwndHidden) { ::PostMessage(m_sheetCfg.hwndHidden, WM_DSA_SHEET_CREATE_NOTIFY, wParam, lParam); } return 0;
case WM_ADSPROP_NOTIFY_EXIT: { NOTIFYOUT(WM_ADSPROP_NOTIFY_EXIT); if (m_fBeingDestroyed) { return 0; } m_fBeingDestroyed = TRUE;
DestroyWindow(hWnd); return 0; }
case WM_DESTROY: NOTIFYOUT(WM_DESTROY); CoUninitialize(); PostQuitMessage(0); return 0;
default: break; }
return DefWindowProc(hWnd, uMsg, wParam, lParam); }
//+----------------------------------------------------------------------------
//
// Method: CNotifyObj::OnCreate
//
// Synopsis: Window creation/initialization processing. Bind to the DS
// object and read its CN and Allowed-Attributes-Effective
// properties.
//
//-----------------------------------------------------------------------------
LRESULT CNotifyObj::OnCreate(void) { NOTIFYOUT(WM_CREATE); HRESULT hr; DWORD cAttrs;
CoInitialize(NULL);
//
// we need to check to see if we can
// convert the string to a CLSID. If
// we can then this is a multi-select
// property page and we shouldn't try
// to bind.
//
CLSID clsid; if (SUCCEEDED(::CLSIDFromString(m_pwzObjDN, &clsid))) { m_hr = S_OK; return S_OK; }
//DBG_OUT("+++++++++++++++++++++++++++addrefing (opening) object");
hr = DSAdminOpenObject(m_pwzObjDN, IID_IDirectoryObject, (PVOID *)&m_pDsObj);
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) { // ErrMsg(IDS_ERRMSG_NO_LONGER_EXISTS);
m_hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } if (hr == 0x80070051) { // On subsequent network failures, ADSI returns this error code which
// is not documented anywhere. I'll turn it into a documented error
// code which happens to be the code returned on the first failure.
//
hr = HRESULT_FROM_WIN32(ERROR_BAD_NET_RESP); } if (hr == HRESULT_FROM_WIN32(ERROR_BAD_NET_RESP)) { // ErrMsg(IDS_ERRMSG_NO_DC_RESPONSE);
m_hr = HRESULT_FROM_WIN32(ERROR_BAD_NET_RESP); return 0; } CHECK_HRESULT(hr, m_hr = hr; return hr);
PWSTR rgszNames[2] = {g_wzName, g_wzAllowed};
hr = m_pDsObj->GetObjectAttributes(rgszNames, 2, &m_pAttrs, &cAttrs);
CHECK_HRESULT(hr, m_hr = hr; return hr);
dspAssert(cAttrs >= 1); // expect to always get name.
for (DWORD i = 0; i < cAttrs; i++) { if (_wcsicmp(m_pAttrs[i].pszAttrName, g_wzName) == 0) { m_pwzCN = m_pAttrs[i].pADsValues->CaseIgnoreString; continue; }
if (_wcsicmp(m_pAttrs[i].pszAttrName, g_wzAllowed) == 0) { m_pWritableAttrs = &m_pAttrs[i];
#if DBG == 1
for (DWORD j = 0; j < m_pAttrs[i].dwNumValues; j++) { dspDebugOut((DEB_USER4, "Allowed attribute (effective): %ws\n", m_pAttrs[i].pADsValues[j].CaseIgnoreString)); } #endif
} } NOTIFYOUT(WM_CREATE done); return 0; }
//+----------------------------------------------------------------------------
//
// Function: RegisterNotifyClass
//
// Synopsis: Register the window class for the notification window.
//
//-----------------------------------------------------------------------------
VOID RegisterNotifyClass(void) { WNDCLASS wcls; wcls.style = 0; wcls.lpfnWndProc = CNotifyObj::StaticNotifyProc; wcls.cbClsExtra = 0; wcls.cbWndExtra = 0; wcls.hInstance = g_hInstance; wcls.hIcon = NULL; wcls.hCursor = NULL; wcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wcls.lpszMenuName = NULL; wcls.lpszClassName = tzNotifyWndClass;
RegisterClass(&wcls); }
//+----------------------------------------------------------------------------
//
// Function: FindSheetNoSetFocus
//
// Synopsis: Locate the property sheet for the DS object.
//
//-----------------------------------------------------------------------------
HWND FindSheetNoSetFocus(PWSTR pwzObjADsPath) { HWND hNotify = NULL; //
// See if the object/window already exists for this property sheet.
// Note that the window title is the DN of the object plus the instance id.
//
#ifdef UNICODE
CStr cstrTitle(pwzObjADsPath);
WCHAR szIH[10]; _itow(g_iInstance, szIH, 16);
cstrTitle += szIH;
hNotify = FindWindow(tzNotifyWndClass, cstrTitle); #else
LPSTR pszTitle; if (UnicodeToTchar(pwzObjADsPath, &pszTitle)) { CStr cstrTitle(pszTitle);
char szIH[10]; _itoa(g_iInstance, szIH, 16);
cstrTitle += szIH;
hNotify = FindWindow(tzNotifyWndClass, cstrTitle); delete [] pszTitle; } #endif
dspDebugOut((DEB_ITRACE, "FindSheet: returned hNotify = 0x%08x\n", hNotify));
return hNotify; }
//+----------------------------------------------------------------------------
//
// Function: BringSheetToForeground
//
// Synopsis: Locate the property sheet for the DS object identified by the
// data object and bring it to the top of the Z order
//
//-----------------------------------------------------------------------------
extern "C" BOOL BringSheetToForeground(PWSTR pwzObjADsPath, BOOL bActivate) { HWND hNotify = FindSheetNoSetFocus(pwzObjADsPath);
if (!hNotify) { return FALSE; }
PostMessage(hNotify, WM_ADSPROP_NOTIFY_FOREGROUND, (WPARAM)bActivate, 0);
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: FindSheet
//
// Synopsis: Locate the property sheet for the DS object identified by the
// data object. For use in the dsprop DLL. If found, bring the
// sheet to the foregroung and set the focus to the sheet.
//
//-----------------------------------------------------------------------------
BOOL FindSheet(PWSTR pwzObjADsPath) { HWND hNotify = FindSheetNoSetFocus(pwzObjADsPath);
if (!hNotify) { return FALSE; }
SendMessage(hNotify, WM_ADSPROP_NOTIFY_SETFOCUS, 0, 0);
return TRUE; }
//+----------------------------------------------------------------------------
//
// Function: IsSheetAlreadyUp
//
// Synopsis: Public, exported function to locate a prop sheet for the DS
// object identified by the data object. If found, sends a message
// to the sheet to bring it to the foreground.
//
//-----------------------------------------------------------------------------
extern "C" BOOL IsSheetAlreadyUp(LPDATAOBJECT pDataObj) { // Get the object's DN from the data object.
//
HRESULT hr = S_OK; STGMEDIUM sm = {TYMED_NULL, NULL, NULL}; FORMATETC fmte = {g_cfDsMultiSelectProppages, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; PWSTR pszUniqueID;
BOOL fFound = FALSE; hr = pDataObj->GetData(&fmte, &sm);
if (FAILED(hr)) { STGMEDIUM smDS = {TYMED_NULL, NULL, NULL}; FORMATETC fmteDS = {g_cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; LPDSOBJECTNAMES pDsObjectNames;
hr = pDataObj->GetData(&fmteDS, &smDS);
if (FAILED(hr)) { return FALSE; }
pDsObjectNames = (LPDSOBJECTNAMES)smDS.hGlobal;
dspAssert(pDsObjectNames->cItems > 0);
pszUniqueID = (LPWSTR)ByteOffset(pDsObjectNames, pDsObjectNames->aObjects[0].offsetName);
fFound = FindSheet(pszUniqueID);
ReleaseStgMedium(&smDS); } else { pszUniqueID = (PWSTR)sm.hGlobal; dspAssert(pszUniqueID != NULL);
fFound = FindSheet(pszUniqueID);
ReleaseStgMedium(&sm);
}
return fFound; }
#ifdef DSADMIN
//+----------------------------------------------------------------------------
//
// Method: CMultiSelectErrorDialog::CMultiSelectErrorDialog
//
// Synopsis: Multi-select error message dialog constructor
//
//-----------------------------------------------------------------------------
CMultiSelectErrorDialog::CMultiSelectErrorDialog(HWND hNotifyObj, HWND hParent) : m_hWnd(NULL), m_hNotifyObj(hNotifyObj), m_hParent(hParent), m_bModal(FALSE), m_bInit(FALSE), m_pPageInfoArray(NULL), m_nPageCount(0), m_pDataObj(NULL) {
} //+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::StaticDlgProc
//
// Synopsis: The static dialog proc for displaying errors for multi-select pages
//
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CMultiSelectErrorDialog::StaticDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CMultiSelectErrorDialog* dlg = NULL;
UINT code; UINT id; switch (uMsg) { case WM_INITDIALOG: dlg = reinterpret_cast<CMultiSelectErrorDialog*>(lParam); dspAssert(dlg != NULL); SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)dlg); SetForegroundWindow(hDlg); return dlg->OnInitDialog(hDlg);
case WM_COMMAND: code = GET_WM_COMMAND_CMD(wParam, lParam); id = GET_WM_COMMAND_ID(wParam, lParam); if (dlg == NULL) { dlg = reinterpret_cast<CMultiSelectErrorDialog*>(GetWindowLongPtr(hDlg, DWLP_USER)); } switch (id) { case IDOK: case IDCANCEL: if (code == BN_CLICKED) { dlg->OnClose(); } break; case IDC_COPY_BUTTON: if (code == BN_CLICKED) { dlg->OnCopyButton(); } break; case IDC_PROPERTIES_BUTTON: if (code == BN_CLICKED) { dlg->ShowListViewItemProperties(); } break; } break;
case WM_NOTIFY: { if (dlg == NULL) { dlg = reinterpret_cast<CMultiSelectErrorDialog*>(GetWindowLongPtr(hDlg, DWLP_USER)); } int idCtrl = (int)wParam; LPNMHDR pnmh = reinterpret_cast<LPNMHDR>(lParam); if (idCtrl == IDC_ERROR_LIST) { switch (pnmh->code) { case NM_DBLCLK: { dlg->ListItemActivate(pnmh); } break;
case LVN_ITEMCHANGED: case NM_CLICK: { dlg->ListItemClick(pnmh); } break; default: break; } } break; }
case WM_HELP: { LPHELPINFO pHelpInfo = reinterpret_cast<LPHELPINFO>(lParam); if (!pHelpInfo || pHelpInfo->iCtrlId < 1 || IDH_NO_HELP == pHelpInfo->dwContextId) { return 0; } WinHelp(hDlg, DSPROP_HELP_FILE_NAME, HELP_CONTEXTPOPUP, pHelpInfo->dwContextId); break; } } return 0; }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::Init
//
// Synopsis: Initializes the member variables
//
//-----------------------------------------------------------------------------
BOOL CMultiSelectErrorDialog::OnInitDialog(HWND hDlg) { dspAssert(m_bInit); if (!m_bInit) { return TRUE; }
m_hWnd = hDlg;
//
// Disable the properties button until there is a selection
//
EnableWindow(GetDlgItem(m_hWnd, IDC_PROPERTIES_BUTTON), FALSE);
HRESULT hr = S_OK; hr = InitializeListBox(hDlg); CHECK_HRESULT(hr, return TRUE;);
CComPtr<IADsPathname> spPathCracker;
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&spPathCracker);
CHECK_HRESULT_REPORT(hr, hDlg, return TRUE);
dspAssert(m_pPageInfoArray != NULL); if (m_pPageInfoArray == NULL) { return TRUE; }
INT iMaxLen = 0; SIZE size = {0,0};
//
// Load the appropriate list box
//
for (UINT pageIdx = 0; pageIdx < m_nPageCount; pageIdx++) { if (m_pPageInfoArray[pageIdx].m_ApplyStatus == CPageInfo::failed) { PTSTR ptzCaptionFormat = NULL; LoadStringToTchar(IDS_MULTI_FAILURE_CAPTION, &ptzCaptionFormat);
if (ptzCaptionFormat != NULL) { //NTRAID#NTBUG9-571996-2002/03/10-jmessec Buffer Overrun: Can't use wcslen(ptzCaptionFormat) as determination of length of
//string; format could be %20s
PWSTR pszCaption = new WCHAR[wcslen(ptzCaptionFormat) + wcslen(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetPageTitle()) + 1]; if (pszCaption != NULL) { wsprintf(pszCaption, ptzCaptionFormat, m_pPageInfoArray[pageIdx].m_ApplyErrors.GetPageTitle()); SetWindowText(GetDlgItem(m_hWnd, IDC_ERROR_STATIC), pszCaption); delete[] pszCaption; pszCaption = NULL; } }
for (UINT objectIdx = 0; objectIdx < m_pPageInfoArray[pageIdx].m_ApplyErrors.GetCount(); objectIdx++) { //
// Get the objects path and class name
//
PWSTR pszObjPath = m_pPageInfoArray[pageIdx].m_ApplyErrors.GetName(objectIdx); PWSTR pszObjClass = m_pPageInfoArray[pageIdx].m_ApplyErrors.GetClass(objectIdx);
//
// Get the class icon for the object
//
int iIcon = g_ClassIconCache.GetClassIconIndex(pszObjClass); dspAssert(iIcon != -1);
//
// Get the object name from the path
//
PWSTR pszLabel = NULL; CComBSTR bstr; hr = spPathCracker->Set(CComBSTR(pszObjPath), ADS_SETTYPE_FULL); CHECK_HRESULT(hr, pszLabel = pszObjPath;);
if (SUCCEEDED(hr)) { hr = spPathCracker->SetDisplayType(ADS_DISPLAY_VALUE_ONLY); CHECK_HRESULT(hr, pszLabel = pszObjPath;); }
// CODEWORK 122531 Should we be turning off escaped mode here?
if (SUCCEEDED(hr)) { hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstr); CHECK_HRESULT(hr, pszLabel = pszObjPath;); }
if (SUCCEEDED(hr)) { pszLabel = bstr; } dspAssert(pszLabel != NULL);
//
// Create the list view item
//
LV_ITEM lvi = {0}; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iSubItem = IDX_NAME_COL;
lvi.lParam = (LPARAM)pszObjPath; lvi.pszText = pszLabel; lvi.iItem = objectIdx;
if (-1 != iIcon) { lvi.mask |= LVIF_IMAGE; lvi.iImage = iIcon; }
//
// Insert the new item
//
int NewIndex = ListView_InsertItem(m_hList, &lvi); dspAssert(NewIndex != -1); if (NewIndex == -1) { continue; }
//
// Format the error message and insert it
//
PWSTR ptzMsg = NULL; if (FAILED(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetError(objectIdx))) { LoadErrorMessage(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetError(objectIdx), 0, &ptzMsg); if (!ptzMsg) { ptzMsg = L""; // make prefix happy.
} //
// REVIEW_JEFFJON : this is hack to get rid of two extra characters
// at the end of the string
//
size_t iLen = wcslen(ptzMsg); ptzMsg[iLen - 2] = L'\0'; } else { ptzMsg = new WCHAR[wcslen(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetStringError(objectIdx)) + 1]; if (ptzMsg != NULL) { wcscpy(ptzMsg, m_pPageInfoArray[pageIdx].m_ApplyErrors.GetStringError(objectIdx)); } }
if (NULL != ptzMsg) { ListView_SetItemText(m_hList, NewIndex, IDX_ERROR_COL, ptzMsg);
INT len = lstrlen(ptzMsg); if( len > iMaxLen ) { HDC hdc = GetDC(hDlg); GetTextExtentPoint32(hdc,ptzMsg,lstrlen(ptzMsg),&size); ReleaseDC(hDlg, hdc); iMaxLen = len; } delete[] ptzMsg; } } } else if (m_pPageInfoArray[pageIdx].m_ApplyStatus == CPageInfo::success) { //
// Insert the page title into the success list box
//
SendDlgItemMessage(m_hWnd, IDC_SUCCESS_LISTBOX, LB_ADDSTRING, 0, (LPARAM)m_pPageInfoArray[pageIdx].m_ptzTitle); } else // apply not tried yet
{ //
// Insert the page title into the not attempted list box
//
SendDlgItemMessage(m_hWnd, IDC_NOT_ATTEMPTED_LISTBOX, LB_ADDSTRING, 0, (LPARAM)m_pPageInfoArray[pageIdx].m_ptzTitle); } }
//
// Select the first item in the error list
//
LVCOLUMN col; col.mask = LVCF_WIDTH; col.cx = size.cx; ListView_SetColumn(m_hList,1, &col); ListView_SetExtendedListViewStyle(m_hList, LVS_EX_FULLROWSELECT); ListView_SetItemState(m_hList, 0, LVIS_SELECTED, LVIS_SELECTED); return TRUE; }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::InitializeListBox
//
// Synopsis: Initializes the member variables
//
//-----------------------------------------------------------------------------
HRESULT CMultiSelectErrorDialog::InitializeListBox(HWND hDlg) {
m_hList = GetDlgItem(hDlg, IDC_ERROR_LIST);
if (m_hList == NULL) { return HRESULT_FROM_WIN32(GetLastError()); }
ListView_SetExtendedListViewStyle(m_hList, LVS_EX_FULLROWSELECT);
//
// Set the column headings.
//
PTSTR ptsz; RECT rect; GetClientRect(m_hList, &rect);
if (!LoadStringToTchar(IDS_COL_TITLE_OBJNAME, &ptsz)) { ReportError(GetLastError(), 0, hDlg); return HRESULT_FROM_WIN32(GetLastError()); }
LV_COLUMN lvc = {0}; lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.cx = OBJ_LIST_NAME_COL_WIDTH; lvc.pszText = ptsz; lvc.iSubItem = IDX_NAME_COL;
ListView_InsertColumn(m_hList, IDX_NAME_COL, &lvc);
delete[] ptsz;
if (!LoadStringToTchar(IDS_COL_TITLE_ERRORMSG, &ptsz)) { ReportError(GetLastError(), 0, hDlg); return HRESULT_FROM_WIN32(GetLastError()); }
lvc.cx = rect.right - OBJ_LIST_NAME_COL_WIDTH; lvc.pszText = ptsz; lvc.iSubItem = IDX_ERROR_COL;
ListView_InsertColumn(m_hList, IDX_ERROR_COL, &lvc);
delete[] ptsz;
//
// Assign the imagelist to the listview
//
ListView_SetImageList(m_hList, g_ClassIconCache.GetImageList(), LVSIL_SMALL); return S_OK; }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::Init
//
// Synopsis: Initializes the member variables
//
//-----------------------------------------------------------------------------
HRESULT CMultiSelectErrorDialog::Init(CPageInfo* pPageInfoArray, UINT nPageCount, IDataObject* pDataObj) { m_nPageCount = nPageCount; m_pPageInfoArray = pPageInfoArray; m_bInit = TRUE; m_pDataObj = pDataObj; m_pDataObj->AddRef();
return S_OK; }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::OnCopyButton
//
// Synopsis: Called when the user presses the Retry button
//
//-----------------------------------------------------------------------------
void CMultiSelectErrorDialog::OnCopyButton() { dspAssert(m_bInit); if (!m_bInit) { return; }
dspAssert(m_pPageInfoArray != NULL); if (m_pPageInfoArray == NULL) { return; }
CComPtr<IADsPathname> spPathCracker; HRESULT hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&spPathCracker); CHECK_HRESULT_REPORT(hr, m_hWnd, return);
if (OpenClipboard(m_hWnd) == 0) { return; }
if (EmptyClipboard() == 0) { CloseClipboard(); return; }
CStrW szClipboardData; szClipboardData.Empty();
for (UINT pageIdx = 0; pageIdx < m_nPageCount; pageIdx++) { for (UINT objectIdx = 0; objectIdx < m_pPageInfoArray[pageIdx].m_ApplyErrors.GetCount(); objectIdx++) { //
// Get the objects path and class name
//
PWSTR pszObjPath = m_pPageInfoArray[pageIdx].m_ApplyErrors.GetName(objectIdx);
//
// Get the object name from the path
//
PWSTR pszLabel = NULL; CComBSTR bstr; hr = spPathCracker->Set(CComBSTR(pszObjPath), ADS_SETTYPE_FULL); CHECK_HRESULT(hr, pszLabel = pszObjPath;);
if (SUCCEEDED(hr)) { hr = spPathCracker->SetDisplayType(ADS_DISPLAY_VALUE_ONLY); CHECK_HRESULT(hr, pszLabel = pszObjPath;); }
// CODEWORK 122531 Should we be turning off escaped mode here?
if (SUCCEEDED(hr)) { hr = spPathCracker->Retrieve(ADS_FORMAT_LEAF, &bstr); CHECK_HRESULT(hr, pszLabel = pszObjPath;); }
if (SUCCEEDED(hr)) { pszLabel = bstr; } dspAssert(pszLabel != NULL);
//
// Format the error message and insert it
//
PWSTR ptzMsg = NULL; if (FAILED(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetError(objectIdx))) { LoadErrorMessage(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetError(objectIdx), 0, &ptzMsg); } else { ptzMsg = new WCHAR[wcslen(m_pPageInfoArray[pageIdx].m_ApplyErrors.GetStringError(objectIdx)) + 1]; if (ptzMsg != NULL) { wcscpy(ptzMsg, m_pPageInfoArray[pageIdx].m_ApplyErrors.GetStringError(objectIdx)); } }
if (NULL != ptzMsg) { szClipboardData += pszLabel; szClipboardData += L","; szClipboardData += ptzMsg; szClipboardData += g_wzCRLF; delete [] ptzMsg; } } }
HGLOBAL hBuffer = NULL; DWORD dwBufferSize; HANDLE hMemClipboard;
LPTSTR pszGlobalBuffer = NULL; dwBufferSize = (szClipboardData.GetLength() + 1) * sizeof(TCHAR); hBuffer = GlobalAlloc (GMEM_MOVEABLE, dwBufferSize); if (!hBuffer) { return; }
pszGlobalBuffer = (LPTSTR)GlobalLock (hBuffer); if ( NULL == pszGlobalBuffer) { // allocation or lock failed so bail out
GlobalFree (hBuffer); return; }
_tcscpy ( pszGlobalBuffer, szClipboardData ); GlobalUnlock (hBuffer);
if ( NULL != hBuffer ) { hMemClipboard = SetClipboardData ( #if UNICODE
CF_UNICODETEXT, // UNICODE text in the clipboard
#else
CF_TEXT, // ANSI text in the clipboard
#endif
hBuffer); if (hMemClipboard == NULL) { //free memory since it didn't make it to the clipboard
GlobalFree (hBuffer); return; } } else { //free memory since it didn't make it to the clipboard
GlobalFree (hBuffer); return; }
CloseClipboard(); }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::ListItemClick
//
// Synopsis: Invokes a property page for the item that was activated
//
//-----------------------------------------------------------------------------
void CMultiSelectErrorDialog::ListItemClick(LPNMHDR) { UINT nSelectedCount = ListView_GetSelectedCount(m_hList); if (nSelectedCount == 1) { EnableWindow(GetDlgItem(m_hWnd, IDC_PROPERTIES_BUTTON), TRUE); } else { EnableWindow(GetDlgItem(m_hWnd, IDC_PROPERTIES_BUTTON), FALSE); } }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::ListItemActivate
//
// Synopsis: Invokes a property page for the item that was activated
//
//-----------------------------------------------------------------------------
void CMultiSelectErrorDialog::ListItemActivate(LPNMHDR pnmh) { LPNMITEMACTIVATE pActivateHeader = reinterpret_cast<LPNMITEMACTIVATE>(pnmh); dspAssert(pActivateHeader != NULL); if (pActivateHeader != NULL) { ShowListViewItemProperties(); } }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::ShowListViewItemProperties()
//
// Synopsis: Invokes a secondary sheet for the selected list view item
//
//-----------------------------------------------------------------------------
BOOL CMultiSelectErrorDialog::ShowListViewItemProperties() { BOOL bSuccess = TRUE;
UINT nSelectCount = ListView_GetSelectedCount(m_hList); if (nSelectCount == 1) { //
// Get the selected item
//
int nSelectedItem = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED); if (nSelectedItem != -1) { //
// Retrieve the item's path
//
LVITEM lvi = {0}; lvi.iItem = nSelectedItem; lvi.mask = LVIF_PARAM;
if (ListView_GetItem(m_hList, &lvi)) { PWSTR pwzPath = reinterpret_cast<PWSTR>(lvi.lParam); if (pwzPath != NULL) { //
// Get the DN
//
CComPtr<IADsPathname> spPathCracker; HRESULT hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&spPathCracker);
CHECK_HRESULT_REPORT(hr, m_hWnd, return FALSE;);
hr = spPathCracker->Set(CComBSTR(pwzPath), ADS_SETTYPE_FULL); CHECK_HRESULT_REPORT(hr, m_hWnd, return FALSE;);
hr = spPathCracker->put_EscapedMode(ADS_ESCAPEDMODE_ON); dspAssert(SUCCEEDED(hr));
hr = spPathCracker->SetDisplayType(ADS_DISPLAY_FULL); CHECK_HRESULT_REPORT(hr, m_hWnd, return FALSE;);
CComBSTR bstrDN; hr = spPathCracker->Retrieve(ADS_FORMAT_X500_DN, &bstrDN); CHECK_HRESULT_REPORT(hr, m_hWnd, return FALSE;);
//
// Invoke the page
//
hr = PostADsPropSheet(bstrDN, m_pDataObj, m_hParent, m_hNotifyObj, FALSE); if (FAILED(hr)) { bSuccess = FALSE; } } else { bSuccess = FALSE; } } else { bSuccess = FALSE; } } else { bSuccess = FALSE; } }
return bSuccess; }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::OnClose
//
// Synopsis: Closes the modal dialog
//
//-----------------------------------------------------------------------------
void CMultiSelectErrorDialog::OnClose() { EndDialog(m_hWnd, 0); }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::DoModal
//
// Synopsis: Displays the modal dialog
//
//-----------------------------------------------------------------------------
int CMultiSelectErrorDialog::DoModal() { m_bModal = TRUE; dspAssert(IsWindow(m_hParent)); return (int)DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_MULTISELECT_ERROR_DIALOG), m_hParent, StaticDlgProc, (LPARAM)this); }
//+----------------------------------------------------------------------------
//
// Member: CMultiSelectErrorDialog::ShowWindow
//
// Synopsis: Displays the modeless dialog
//
//-----------------------------------------------------------------------------
BOOL CMultiSelectErrorDialog::ShowWindow() { m_bModal = FALSE; m_hWnd = CreateDialogParam(g_hInstance, MAKEINTRESOURCE(IDD_MULTISELECT_ERROR_DIALOG), m_hParent, StaticDlgProc, (LPARAM)this); return ::ShowWindow(m_hWnd, SW_SHOWNORMAL); } #endif // DSADMIN
|