WindowsXP-SP1/admin/select/src/advanceddlg.cxx
2020-09-30 16:53:49 +02:00

2368 lines
62 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1999.
//
// File: AdvancedDlg.cxx
//
// Contents: Declaration of dialog that appears when user hits
// Advanced button on base dialog.
//
// Classes: CAdvancedDlg
//
// History: 04-03-2000 DavidMun Created
//
//---------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
const WCHAR c_wzBannerClass[] = L"ObjectPickerQueryBanner";
static ULONG
s_aulHelpIds[] =
{
IDC_LOOK_FOR_PB, IDH_LOOK_FOR_PB,
IDC_LOOK_FOR_EDIT, IDH_LOOK_FOR_EDIT,
IDC_LOOK_IN_PB, IDH_LOOK_IN_PB,
IDC_LOOK_IN_EDIT, IDH_LOOK_IN_EDIT,
IDC_COLUMNS_PB, IDH_COLUMNS_PB,
IDC_FIND_NOW_PB, IDH_FIND_NOW_PB,
IDC_STOP_PB, IDH_STOP_PB,
IDC_QUERY_LISTVIEW, IDH_QUERY_LISTVIEW,
IDC_ANIMATION, ULONG_MAX,
IDC_TAB, ULONG_MAX,
0,0
};
//
// Forward refs
//
LRESULT CALLBACK
_BannerWndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
AttrKeyVector
AttributesFromColumns(
const AttrKeyVector &vakListviewColumns);
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::CAdvancedDlg
//
// Synopsis: ctor
//
// Arguments: [rop] - owning object picker instance
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
CAdvancedDlg::CAdvancedDlg(
const CObjectPicker &rop):
m_rop(rop),
m_CommonQueriesTab(rop),
#ifdef QUERY_BUILDER
m_QueryBuilderTab(rop),
#endif // QUERY_BUILDER
m_pCurTab(&m_CommonQueriesTab),
m_fResizeableModeOn(FALSE),
m_usnLatestQueryWorkItem(0),
m_pvSelectedObjects(NULL),
m_ulPrevFilterFlags(0),
m_hwndAnimation(NULL),
m_hwndBanner(NULL),
m_cxMin(0),
m_cyMin(0),
m_cxSeparation(0),
m_cySeparation(0),
m_cxLvSeparation(0),
m_cyLvSeparation(0),
m_cxFrameLast(0),
m_cyFrameLast(0),
m_cxFour(0)
{
TRACE_CONSTRUCTOR(CAdvancedDlg);
ZeroMemory(&m_rcDlgOriginal, sizeof m_rcDlgOriginal);
ZeroMemory(&m_rcWrDlgOriginal, sizeof m_rcWrDlgOriginal);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::DoModalDlg
//
// Synopsis: Invoke the advanced dialog and block until it is closed.
//
// Arguments: [hwndParent] - parent of modal dialog
// [pvSelectedObjects] - filled with objects user selected
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::DoModalDlg(
HWND hwndParent,
vector<CDsObject> *pvSelectedObjects)
{
m_pvSelectedObjects = pvSelectedObjects;
ASSERT(m_pvSelectedObjects);
if (!m_pvSelectedObjects)
{
return;
}
_DoModalDlg(hwndParent, IDD_ADVANCED);
m_cxMin= 0;
m_cyMin= 0;
m_cxSeparation= 0;
m_cySeparation= 0;
m_cxFour = 0;
m_cxLvSeparation= 0;
m_cyLvSeparation= 0;
m_cxFrameLast= 0;
m_cyFrameLast= 0;
m_pCurTab = &m_CommonQueriesTab;
m_fResizeableModeOn = FALSE;
m_pvSelectedObjects = NULL;
m_ulPrevFilterFlags = 0;
m_vakListviewColumns.clear();
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnInit
//
// Synopsis: Initialize the dialog
//
// Arguments: [pfSetFocus] -
//
// Returns: S_OK
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
HRESULT
CAdvancedDlg::_OnInit(
BOOL *pfSetFocus)
{
TRACE_METHOD(CAdvancedDlg, _OnInit);
//
// Make prefix shut up
//
if (!_hCtrl(IDC_TAB) ||
!_hCtrl(IDOK) ||
!_hCtrl(IDC_FIND_NOW_PB) ||
!_hCtrl(IDC_STOP_PB) ||
!_hCtrl(IDC_QUERY_LISTVIEW))
{
return E_FAIL;
}
//
// Init data needed for resizing.
//
// First translate the separation distance between controls from
// dialog units to pixels.
//
RECT rc;
rc.left = rc.top = 1;
rc.right = DIALOG_SEPARATION_X;
rc.bottom = DIALOG_SEPARATION_Y;
VERIFY(MapDialogRect(m_hwnd, &rc));
m_cxSeparation = rc.right;
m_cySeparation = rc.bottom;
rc.left = rc.top = 1;
rc.right = 4;
rc.bottom = DIALOG_SEPARATION_Y;
VERIFY(MapDialogRect(m_hwnd, &rc));
m_cxFour = rc.right;
GetWindowRect(m_hwnd, &rc);
m_cxFrameLast = WindowRectWidth(rc);
m_cyFrameLast = WindowRectHeight(rc);
GetWindowRect(m_hwnd, &rc);
m_cxMin = rc.right - rc.left + 1;
m_cyMin = rc.bottom - rc.top + 1;
//
// Init the Look For and Look In r/o edit controls and the caption
//
UpdateLookForInText(m_hwnd, m_rop);
//
// Add the Common Queries and Query Builder tabs
//
TCITEM tci;
ZeroMemory(&tci, sizeof tci);
tci.mask = TCIF_TEXT;
String strTabCaption;
strTabCaption = String::load(IDS_COMMON_QUERIES, g_hinst);
tci.pszText = const_cast<PWSTR>(strTabCaption.c_str());
TabCtrl_InsertItem(_hCtrl(IDC_TAB), 0, &tci);
#ifdef QUERY_BUILDER
strTabCaption = String::load(IDS_QUERY_BUILDER, g_hinst);
tci.pszText = const_cast<PWSTR>(strTabCaption.c_str());
TabCtrl_InsertItem(_hCtrl(IDC_TAB), 1, &tci);
#endif // QUERY_BUILDER
//
// Give the enable-find-now method to the tabs for callback
//
m_CommonQueriesTab.SetFindValidCallback(
&FindValidCallback,
reinterpret_cast<LPARAM>(this));
#ifdef QUERY_BUILDER
m_QueryBuilderTab.SetFindValidCallback(
&FindValidCallback,
reinterpret_cast<LPARAM>(this));
#endif // QUERY_BUILDER
//
// Create the corresponding Common Queries and Query Builder dialogs
//
HWND hwndTab = _hCtrl(IDC_TAB);
m_CommonQueriesTab.DoModelessDlg(hwndTab);
#ifdef QUERY_BUILDER
m_QueryBuilderTab.DoModelessDlg(hwndTab);
#endif // QUERY_BUILDER
//
// Position them so they fit within tab's bounding rectangle
//
RECT rcTab;
VERIFY(GetWindowRect(hwndTab, &rcTab));
TabCtrl_AdjustRect(hwndTab, FALSE, &rcTab);
//ScreenToClient(hwndTab, reinterpret_cast<LPPOINT>(&rcTab.left));
//ScreenToClient(hwndTab, reinterpret_cast<LPPOINT>(&rcTab.right));
//ScreenToClient has some problem with mirrored apps and was causing
//problems in Arabic build
MapWindowPoints(NULL, hwndTab, (LPPOINT)&rcTab, 2);
SetWindowPos(m_CommonQueriesTab.GetHwnd(),
hwndTab,
rcTab.left,
rcTab.top,
0,
0,
SWP_NOSIZE | SWP_NOZORDER);
#ifdef QUERY_BUILDER
SetWindowPos(m_QueryBuilderTab.GetHwnd(),
hwndTab,
rcTab.left,
rcTab.top,
0,
0,
SWP_NOSIZE | SWP_NOZORDER);
#endif // QUERY_BUILDER
//
// Disable OK, it is only enabled if a find has been done and a
// selection in the find results listview has been made.
//
EnableWindow(_hCtrl(IDOK), FALSE);
//
// Disable both Find Now and Stop. Stop is only enabled after
// Find Now has been clicked and a query is ongoing. Find Now
// is enabled whenever the current tab tells us it should be.
//
EnableWindow(_hCtrl(IDC_FIND_NOW_PB), FALSE);
EnableWindow(_hCtrl(IDC_STOP_PB), FALSE);
//
// Disable Columns button if we're in a downlevel scope, column chooser
// is for uplevel only.
//
if (IsDownlevel(m_rop.GetScopeManager().GetCurScope().Type()))
{
EnableWindow(_hCtrl(IDC_COLUMNS_PB), FALSE);
}
//
// Put the listview in single select mode if that's how the object
// picker was invoked.
//
HWND hwndLv = _hCtrl(IDC_QUERY_LISTVIEW);
if (!(m_rop.GetInitInfoOptions() & DSOP_FLAG_MULTISELECT))
{
LONG_PTR lStyle = GetWindowLongPtr(hwndLv, GWL_STYLE);
SetWindowLongPtr(hwndLv, GWL_STYLE, lStyle | LVS_SINGLESEL);
}
//
// Put the display cache's imagelist in the listview
//
const CAttributeManager &ram = m_rop.GetAttributeManager();
HIMAGELIST himl = NULL;
HRESULT hrImageList = ram.GetImageList(&himl);
if (SUCCEEDED(hrImageList))
{
ListView_SetImageList(hwndLv, himl, LVSIL_SMALL);
}
//
// Make sure we start out looking at the tab 0 dialog.
//
#ifdef QUERY_BUILDER
m_QueryBuilderTab.Hide();
#endif // QUERY_BUILDER
m_CommonQueriesTab.Show(); // does a refresh
//
// Save the client area size before we allow resizing
//
GetClientRect(m_hwnd, &m_rcDlgOriginal);
GetWindowRect(m_hwnd, &m_rcWrDlgOriginal);
//
// Create the animation control
//
m_hwndAnimation = Animate_Create(m_hwnd,
IDC_ANIMATION,
WS_CHILD
| WS_VISIBLE
| ACS_CENTER
| ACS_TRANSPARENT,
g_hinst);
if (m_hwndAnimation)
{
Animate_Open(m_hwndAnimation, MAKEINTRESOURCE(IDA_SEARCH));
}
else
{
DBG_OUT_LASTERROR;
}
//
// Register banner window class and create a banner instance
//
WNDCLASS wc;
ZeroMemory(&wc, sizeof wc);
wc.lpfnWndProc = _BannerWndProc;
wc.hInstance = g_hinst;
wc.lpszClassName = c_wzBannerClass;
RegisterClass(&wc);
// Create the banner window, this is a child of the ListView, it is used to display
// information about the query being issued
m_hwndBanner = CreateWindow(c_wzBannerClass, NULL,
WS_CHILD,
0, 0, 0, 0, // nb: size fixed later
hwndLv,
0,
g_hinst,
NULL);
if (!m_hwndBanner)
{
DBG_OUT_LASTERROR;
}
HRESULT hr = _ResizeableModeOn();
if(FAILED(hr))
{
//
//Show a popup
//
String strError = GetErrorMessage(hr);
String strMsg;
if(strError.empty())
PopupMessage(GetParent(m_hwnd),IDS_CANNOT_INVOKE_ADV_NOERROR);
else
PopupMessage(GetParent(m_hwnd),IDS_CANNOT_INVOKE_ADV, strError.c_str());
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnCommand
//
// Synopsis: Handle notification that the user has entered or changed
// something in the UI.
//
// Arguments: [wParam] - standard windows
// [lParam] - standard windows
//
// Returns: standard windows
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
BOOL
CAdvancedDlg::_OnCommand(
WPARAM wParam,
LPARAM lParam)
{
BOOL fHandled = TRUE;
switch (LOWORD(wParam))
{
case IDC_LOOK_IN_PB:
{
Dbg(DEB_TRACE, "UA: (AdvancedDlg) hit Look In button\n");
const CScopeManager &rsm = m_rop.GetScopeManager();
//
// do the look in dlg and update look in/for text
//
rsm.DoLookInDialog(m_hwnd);
m_rop.GetFilterManager().HandleScopeChange(m_hwnd);
UpdateLookForInText(m_hwnd, m_rop);
_UpdateColumns();
EnableWindow(_hCtrl(IDC_COLUMNS_PB),
IsUplevel(m_rop.GetScopeManager().GetCurScope()));
//
// tell current tab to update itself per current look in.
// since changing the look in might have changed the look for,
// request an update of that also.
//
m_pCurTab->Refresh();
break;
}
case IDC_LOOK_FOR_PB:
{
Dbg(DEB_TRACE, "UA: (AdvancedDlg) hit Look For button\n");
const CFilterManager &rfm = m_rop.GetFilterManager();
rfm.DoLookForDialog(m_hwnd);
Edit_SetText(GetDlgItem(m_hwnd, IDC_LOOK_FOR_EDIT),
rfm.GetFilterDescription(m_hwnd, FOR_LOOK_FOR).c_str());
_UpdateColumns();
m_pCurTab->Refresh();
break;
}
case IDC_COLUMNS_PB:
_InvokeColumnChooser();
break;
case IDC_FIND_NOW_PB:
Dbg(DEB_TRACE, "UA: (AdvancedDlg) hit Find Now button\n");
//
// If we're querying against an uplevel scope, we'll need
// to ensure the attribute manager has been initialized
// first.
//
if (IsUplevel(m_rop.GetScopeManager().GetCurScope().Type()))
{
HRESULT hr = m_rop.GetAttributeManager().DemandInit(m_hwnd);
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
break;
}
}
EnableWindow(_hCtrl(IDC_STOP_PB), TRUE);
SetFocus(_hCtrl(IDC_STOP_PB));
EnableWindow(_hCtrl(IDC_FIND_NOW_PB), FALSE);
ListView_DeleteAllItems(_hCtrl(IDC_QUERY_LISTVIEW));
EnableWindow(_hCtrl(IDOK), FALSE);
Animate_Play(m_hwndAnimation, 0, -1, -1);
_StartQuery();
break;
case IDC_STOP_PB:
Dbg(DEB_TRACE, "UA: (AdvancedDlg) hit Stop button\n");
_StopQuery();
Animate_Stop(m_hwndAnimation);
Animate_Seek(m_hwndAnimation, 0);
EnableWindow(_hCtrl(IDC_FIND_NOW_PB), TRUE);
SetFocus(_hCtrl(IDC_QUERY_LISTVIEW));
EnableWindow(_hCtrl(IDC_STOP_PB), FALSE);
break;
case IDOK:
_OnOk();
m_pvSelectedObjects = NULL;
EndDialog(GetHwnd(), TRUE);
break;
case IDCANCEL:
Dbg(DEB_TRACE, "UA: (AdvancedDlg) hit Cancel\n");
_StopQuery();
m_pvSelectedObjects = NULL;
EndDialog(GetHwnd(), FALSE);
break;
default:
fHandled = FALSE;
Dbg(DEB_WARN,
"CAdvancedDlg WM_COMMAND code=%#x, id=%#x, hwnd=%#x\n",
HIWORD(wParam),
LOWORD(wParam),
lParam);
break;
}
return fHandled;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnNotify
//
// Synopsis: Handle UI change notification
//
// Arguments: [wParam] - standard windows
// [lParam] - standard windows
//
// Returns: standard windows
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
BOOL
CAdvancedDlg::_OnNotify(
WPARAM wParam,
LPARAM lParam)
{
LPNMHDR pnmh = reinterpret_cast<LPNMHDR> (lParam);
BOOL fReturn = FALSE;
switch (pnmh->code)
{
case LVN_ITEMCHANGED:
EnableWindow(_hCtrl(IDOK), ListView_GetSelectedCount(pnmh->hwndFrom));
break;
#ifdef QUERY_BUILDER
case TCN_SELCHANGE:
Dbg(DEB_TRACE,
"UA: (AdvancedDlg) select tab %d\n",
TabCtrl_GetCurSel(_hCtrl(IDC_TAB)));
if (!TabCtrl_GetCurSel(_hCtrl(IDC_TAB)))
{
m_CommonQueriesTab.Show();
m_QueryBuilderTab.Hide();
m_pCurTab = &m_CommonQueriesTab;
}
else
{
ASSERT(TabCtrl_GetCurSel(_hCtrl(IDC_TAB)) == 1);
m_CommonQueriesTab.Hide();
m_QueryBuilderTab.Show();
m_pCurTab = &m_QueryBuilderTab;
}
break;
#endif // QUERY_BUILDER
default:
/*
Dbg(DEB_ITRACE,
"WM_NOTIFY idCtrl=%u hwndFrom=%#x code=%d\n",
wParam,
((LPNMHDR)lParam)->hwndFrom,
((LPNMHDR)lParam)->code);
*/
break;
}
return fReturn;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnHelp
//
// Synopsis: Handle the WM_HELP or WM_CONTEXTMENU message
//
// Arguments: [message] - WM_HELP or WM_CONTEXTMENU
// [wParam] - standard windows
// [lParam] - standard windows
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_OnHelp(
UINT message,
WPARAM wParam,
LPARAM lParam)
{
TRACE_METHOD(CAdvancedDlg, _OnHelp);
HMENU hmenu = NULL;
//
// If the window in which this was invoked was the header or listview
// window, display a context menu containing an item to invoke the
// column picker.
//
do
{
if (message == WM_HELP)
{
InvokeWinHelp(message, wParam, lParam, c_wzHelpFilename, s_aulHelpIds);
break;
}
ASSERT(message == WM_CONTEXTMENU);
HWND hwndClickedIn = reinterpret_cast<HWND>(wParam);
if (hwndClickedIn != _hCtrl(IDC_QUERY_LISTVIEW))
{
break;
}
//
// Column chooser not supported in downlevel mode
//
if (IsDownlevel(m_rop.GetScopeManager().GetCurScope()))
{
break;
}
hmenu = CreatePopupMenu();
if (!hmenu)
{
DBG_OUT_LASTERROR;
break;
}
String strMenuItem = String::load(IDS_CHOOSE_COLUMNS);
if (strMenuItem.empty())
{
break;
}
UINT uiFlags = MF_STRING;
if (!IsWindowEnabled(_hCtrl(IDC_TAB)))
{
uiFlags |= (MF_GRAYED | MF_DISABLED);
}
BOOL fOk = AppendMenu(hmenu, uiFlags, 101, strMenuItem.c_str());
if (!fOk)
{
DBG_OUT_LASTERROR;
break;
}
int x = GET_X_LPARAM(lParam);
int y = GET_Y_LPARAM(lParam);
if (x == -1 || y == -1)
{
Dbg(DEB_TRACE, "UA: WM_CONTEXTMENU generated via keyboard\n");
HWND hwndFocus = GetFocus();
RECT rc;
if (GetWindowRect((hwndFocus ? hwndFocus : m_hwnd), &rc))
{
x = (rc.left + rc.right) / 2;
y = (rc.top + rc.bottom) / 2;
}
else
{
DBG_OUT_LASTERROR;
break;
}
}
BOOL fReturn = TrackPopupMenu(hmenu,
TPM_NONOTIFY | TPM_RETURNCMD,
x,
y,
0,
m_hwnd,
NULL);
if (!fReturn)
{
Dbg(DEB_TRACE, "UA: user cancelled context menu\n");
break;
}
_InvokeColumnChooser();
} while (0);
if (hmenu)
{
VERIFY(DestroyMenu(hmenu));
}
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_InvokeColumnChooser
//
// Synopsis: Present the column chooser dialog and allow the user to
// change the set of columns displayed in the listview.
//
// History: 07-31-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_InvokeColumnChooser()
{
//
// Invoke the column chooser dialog
//
AttrKeyVector vakNew(m_vakListviewColumns);
CColumnPickerDlg Dlg(m_rop, &vakNew);
BOOL fMadeChanges = Dlg.DoModal(m_hwnd);
if (!fMadeChanges)
{
return;
}
//
// Remove all items from the listview
//
HWND hwndLV = _hCtrl(IDC_QUERY_LISTVIEW);
ListView_DeleteAllItems(hwndLV);
//
// Remove all listview columns
//
int i;
for (i = 0; i < m_vakListviewColumns.size(); i++)
{
ListView_DeleteColumn(hwndLV, 0);
}
//
// Insert new set of columns
//
m_vakListviewColumns = vakNew;
for (i = 0; i < m_vakListviewColumns.size(); i++)
{
_AddColToListview(m_vakListviewColumns[i]);
}
//
// Disable the OK button, since the listview is empty
//
if (GetFocus() == _hCtrl(IDOK))
{
SetFocus(_hCtrl(IDCANCEL));
}
EnableWindow(_hCtrl(IDOK), FALSE);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_StartQuery
//
// Synopsis: Ensure the dialog is in resizeable mode and ask the
// QueryEngine to start an asynchronous query (an LDAP query or
// a WinNT enumeration).
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_StartQuery()
{
TRACE_METHOD(CAdvancedDlg, _StartQuery);
//
// Ask the current tab for any extra columns we should have
//
AttrKeyVector vakTabColumns;
m_pCurTab->GetDefaultColumns(&vakTabColumns);
AttrKeyVector::iterator itCol;
for (itCol = vakTabColumns.begin(); itCol != vakTabColumns.end(); itCol++)
{
_AddColIfNotPresent(*itCol);
}
//
// Disable look for, look in, and tabs
//
EnableWindow(_hCtrl(IDC_LOOK_FOR_PB), FALSE);
EnableWindow(_hCtrl(IDC_LOOK_IN_PB), FALSE);
EnableWindow(_hCtrl(IDC_COLUMNS_PB), FALSE);
EnableWindow(_hCtrl(IDC_TAB), FALSE);
m_pCurTab->Disable();
//
// If current scope is downlevel perform an enumeration
//
const CScopeManager &rsm = m_rop.GetScopeManager();
const CScope &rCurScope = rsm.GetCurScope();
if (rCurScope.Type() == ST_INVALID)
{
Dbg(DEB_ERROR, "Cur scope invalid, can't do query\n");
return;
}
//
// Display "Searching..." in the banner window
//
_ShowBanner(SWP_SHOWWINDOW, IDS_SEARCHING);
//
// Kick off the query in the worker thread
//
if (IsDownlevel(rCurScope))
{
_StartWinNtQuery();
}
else
{
_StartLdapQuery();
}
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_StartWinNtQuery
//
// Synopsis: Ask the QueryEngine to perform an asynchronous WinNT
// enumeration
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_StartWinNtQuery()
{
TRACE_METHOD(CAdvancedDlg, _StartWinNtQuery);
const CQueryEngine &rqe = m_rop.GetQueryEngine();
const CScopeManager &rsm = m_rop.GetScopeManager();
const CScope &rCurScope = rsm.GetCurScope();
const CWinNtScope *pCurScopeWinNt =
dynamic_cast<const CWinNtScope *>(&rCurScope);
const CFilterManager &rfm = m_rop.GetFilterManager();
do
{
if (!pCurScopeWinNt)
{
Dbg(DEB_ERROR,
"Current scope '%ws' is not WinNT container\n",
rCurScope.GetDisplayName().c_str());
break;
}
SQueryParams qp;
HRESULT hr;
hr = pCurScopeWinNt->GetADsPath(m_hwnd, &qp.strADsPath);
BREAK_ON_FAIL_HRESULT(hr);
qp.rpScope = const_cast<CScope *>(&rCurScope);
qp.vakAttributesToRead.push_back(AK_NAME);
qp.vakAttributesToRead.push_back(AK_ADSPATH);
qp.vakAttributesToRead.push_back(AK_OBJECT_CLASS);
qp.hwndCredPromptParentDlg = m_hwnd;
qp.hwndNotify = m_hwnd;
qp.Limit = QL_NO_LIMIT;
rfm.GetWinNtFilter(m_hwnd, rCurScope, &qp.vstrWinNtFilter);
qp.CustomizerInteraction = CUSTINT_INCLUDE_ALL_CUSTOM_OBJECTS;
hr = rqe.AsyncDirSearch(qp, &m_usnLatestQueryWorkItem);
BREAK_ON_FAIL_HRESULT(hr);
} while (0);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_StartLdapQuery
//
// Synopsis: Ask the QueryEngine to perform an asynchronous LDAP query
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_StartLdapQuery()
{
TRACE_METHOD(CAdvancedDlg, _StartLdapQuery);
const CQueryEngine &rqe = m_rop.GetQueryEngine();
const CScopeManager &rsm = m_rop.GetScopeManager();
const CScope &rCurScope = rsm.GetCurScope();
const CLdapContainerScope *pCurScopeLdap =
dynamic_cast<const CLdapContainerScope *>(&rCurScope);
if (!pCurScopeLdap)
{
Dbg(DEB_ERROR,
"Current scope '%ws' is not LDAP container\n",
rCurScope.GetDisplayName().c_str());
return;
}
SQueryParams qp;
HRESULT hr = pCurScopeLdap->GetADsPath(m_hwnd, &qp.strADsPath);
RETURN_ON_FAIL_HRESULT(hr);
qp.strLdapFilter = m_pCurTab->GetLdapFilter();
qp.rpScope = const_cast<CScope *>(&rCurScope);
qp.ADsScope = ADS_SCOPE_SUBTREE;
qp.hwndCredPromptParentDlg = m_hwnd;
qp.hwndNotify = m_hwnd;
qp.Limit = QL_USE_REGISTRY_LIMIT;
m_pCurTab->GetCustomizerInteraction(&qp.CustomizerInteraction,
&qp.strCustomizerArg);
qp.vakAttributesToRead = AttributesFromColumns(m_vakListviewColumns);
//
// If there is an LDAP filter, tack on a bit to prevent disabled
// objects from being returned, if applicable.
//
if (!qp.strLdapFilter.empty() && g_fExcludeDisabled)
{
qp.strLdapFilter.insert(0, L"(&");
qp.strLdapFilter += L"(!";
qp.strLdapFilter += c_wzDisabledUac;
qp.strLdapFilter += L"))";
}
const CFilterManager &rfm = m_rop.GetFilterManager();
if (rfm.GetCurScopeSelectedFilterFlags() &
(DSOP_FILTER_CONTACTS | DSOP_FILTER_USERS))
{
AddIfNotPresent(&qp.vakAttributesToRead, AK_USER_PRINCIPAL_NAME);
}
// Dbg(DEB_TRACE, "ldap filter: \n%ws\n", qp.strLdapFilter.c_str());
hr = rqe.AsyncDirSearch(qp, &m_usnLatestQueryWorkItem);
CHECK_HRESULT(hr);
}
//+--------------------------------------------------------------------------
//
// Function: AttributesFromColumns
//
// Synopsis: Return a vector of ATTR_KEYs which is a copy of
// [vakListviewColumns] modified so that it doesn't contain any
// duplicates, and all synthesized attributes are replaced by
// the non-synthesized attributes on which they depend.
//
// Arguments: [vakListviewColumns] - vector of attribute keys representing
// the columns to display in a listview
//
// Returns: Modified copy of [vakListviewColumns].
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
AttrKeyVector
AttributesFromColumns(
const AttrKeyVector &vakListviewColumns)
{
TRACE_FUNCTION(AttributesFromColumns);
AttrKeyVector vak;
AttrKeyVector::const_iterator it;
for (it = vakListviewColumns.begin();
it != vakListviewColumns.end();
it++)
{
switch (*it)
{
case AK_FLAGS:
case AK_USER_ENTERED_TEXT:
case AK_PROCESSED_ADSPATH:
ASSERT(0 && "unexpected synthesized attribute key in column vector");
break;
case AK_LOCALIZED_NAME:
case AK_NAME:
case AK_DISPLAY_PATH:
// These are always added, see below
break;
default:
AddIfNotPresent(&vak, *it);
break;
}
}
//
// There are a few attributes which should always be read, add
// them in regardless of whether they appear in the columns.
//
AddIfNotPresent(&vak, AK_NAME);
AddIfNotPresent(&vak, AK_ADSPATH);
AddIfNotPresent(&vak, AK_OBJECT_CLASS);
AddIfNotPresent(&vak, AK_USER_ACCT_CTRL);
return vak;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnNewBlock
//
// Synopsis: Handle a notification message from the query engine that it
// has added more items to its buffer of objects.
//
// Arguments: [wParam] - number of rows in buffer
// [lParam] - work item number the rows were fetched for
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_OnNewBlock(
WPARAM wParam,
LPARAM lParam)
{
TRACE_METHOD(CAdvancedDlg, _OnNewBlock);
ULONG cRowsInBuffer = static_cast<ULONG>(wParam);
ULONG usnWorkItem = static_cast<ULONG>(lParam);
// ignore notifications for old queries
if (usnWorkItem != m_usnLatestQueryWorkItem)
{
Dbg(DEB_TRACE,
"Ignoring notification for old work item %u, current is %u\n",
usnWorkItem,
m_usnLatestQueryWorkItem);
return;
}
// add the rows that aren't already in the listview
HWND hwndLv = _hCtrl(IDC_QUERY_LISTVIEW);
ULONG cRowsInLv = ListView_GetItemCount(hwndLv);
ASSERT(cRowsInBuffer >= cRowsInLv);
//
// If we're about to add items to the listview and it doesn't have any,
// hide the banner window
//
if (cRowsInBuffer > cRowsInLv
&& m_hwndBanner
&& IsWindowVisible(m_hwndBanner))
{
ASSERT(!cRowsInLv);
_ShowBanner(SWP_HIDEWINDOW, 0);
}
const CQueryEngine &rqe = m_rop.GetQueryEngine();
const CAttributeManager &ram = m_rop.GetAttributeManager();
ULONG idxRow;
for (idxRow = cRowsInLv; idxRow < cRowsInBuffer; idxRow++)
{
CDsObject dso(rqe.GetObject(idxRow));
LVITEM lvi;
//
// Skip disabled items if we're supposed to. Even though we modify
// the LDAP query to filter these out server-side, there's still
// the customizer which might unknowingly supply disabled objects,
// plus we could also get disabled objects via the WinNT provider.
//
if (g_fExcludeDisabled && dso.GetDisabled())
{
continue;
}
ZeroMemory(&lvi, sizeof lvi);
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.lParam = idxRow;
lvi.pszText = dso.GetAttr(m_vakListviewColumns[0]).GetBstr();
HRESULT hrImage;
hrImage = ram.GetIconIndexFromObject(m_hwnd, dso, &lvi.iImage);
if (SUCCEEDED(hrImage))
{
lvi.mask |= LVIF_IMAGE;
}
int iRet = ListView_InsertItem(hwndLv, &lvi);
if (iRet == -1)
{
DBG_OUT_LASTERROR;
continue;
}
size_t i;
for (i = 1; i < m_vakListviewColumns.size(); i++)
{
ListView_SetItemText(hwndLv,
iRet,
static_cast<int>(i),
const_cast<PWSTR>(dso.GetAttr(m_vakListviewColumns[i]).GetBstr()));
}
}
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnQueryDone
//
// Synopsis: Handle a notification from the query engine that it has
// completed (or stopped) a query.
//
// Arguments: [wParam] - number of rows in buffer
// [lParam] - work item number the rows were fetched for
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_OnQueryDone(
WPARAM wParam,
LPARAM lParam)
{
TRACE_METHOD(CAdvancedDlg, _OnQueryDone);
// ignore notifications for old queries
if (lParam != (LPARAM)(m_usnLatestQueryWorkItem))
{
return;
}
const CScopeManager &rsm = m_rop.GetScopeManager();
const CScope &rCurScope = rsm.GetCurScope();
_OnNewBlock(wParam, lParam);
Animate_Stop(m_hwndAnimation);
Animate_Seek(m_hwndAnimation, 0);
EnableWindow(_hCtrl(IDC_FIND_NOW_PB), TRUE);
EnableWindow(_hCtrl(IDC_LOOK_FOR_PB), TRUE);
EnableWindow(_hCtrl(IDC_LOOK_IN_PB), TRUE);
EnableWindow(_hCtrl(IDC_TAB), TRUE);
if (IsUplevel(rCurScope))
{
EnableWindow(_hCtrl(IDC_COLUMNS_PB), TRUE);
}
m_pCurTab->Enable();
if (ListView_GetItemCount(_hCtrl(IDC_QUERY_LISTVIEW)) <= 0)
{
CQueryEngine &rqe = m_rop.GetQueryEngine();
HRESULT hrQuery = rqe.GetLastQueryResult();
String strEmptyText;
if (FAILED(hrQuery))
{
String strTemp = String::load(IDS_QUERY_ERROR);
strEmptyText = String::format(strTemp.c_str(),
GetErrorMessage(hrQuery).c_str());
}
else
{
strEmptyText = String::load(IDS_NOTHINGFOUND);
}
_ShowBanner(SWP_SHOWWINDOW, strEmptyText);
if (GetFocus() == _hCtrl(IDC_STOP_PB))
{
SetFocus(_hCtrl(IDC_FIND_NOW_PB));
}
}
else
{
ListView_SetItemState(_hCtrl(IDC_QUERY_LISTVIEW),
0,
LVIS_FOCUSED | LVIS_SELECTED,
LVIS_FOCUSED | LVIS_SELECTED);
if (GetFocus() == _hCtrl(IDC_STOP_PB))
{
SetFocus(_hCtrl(IDC_QUERY_LISTVIEW));
}
}
ASSERT(GetFocus() != _hCtrl(IDC_STOP_PB));
EnableWindow(_hCtrl(IDC_STOP_PB), FALSE);
}
const ULONG c_ulStyle = LVS_EX_LABELTIP
| LVS_EX_FULLROWSELECT
| LVS_EX_HEADERDRAGDROP;
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_ResizeableModeOn
//
// Synopsis: Make the listview visible and make the dialog window
// resizeable
//
// History: 06-14-2000 DavidMun Created
//
// Notes: Once the dialog has entered resizeable mode, it stays in
// that mode.
//
//---------------------------------------------------------------------------
HRESULT
CAdvancedDlg::_ResizeableModeOn()
{
TRACE_METHOD(CAdvancedDlg, _ResizeableModeOn);
if (m_fResizeableModeOn)
{
return S_OK;
}
HRESULT hr = _UpdateColumns();
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
return hr;
}
m_fResizeableModeOn = TRUE;
//
// Double (roughly) the vertical client size
//
// NTRAID#NTBUG9-191862-2001/03/06-hiteshr
//
//
//
GetClientRect(m_hwnd, &m_rcDlgOriginal);
//
//Get the workarea info.
//
RECT rcWorkArea;
SystemParametersInfo(SPI_GETWORKAREA,
NULL,
&rcWorkArea,
0);
//
//Limit the height of the dialog to WorkArea height
//
int yDlg = WindowRectHeight(m_rcDlgOriginal) * 17/10;
if( yDlg > WindowRectHeight(rcWorkArea))
yDlg = WindowRectHeight(rcWorkArea);
SetWindowPos(m_hwnd,
NULL,
0,0,
WindowRectWidth(m_rcWrDlgOriginal),
yDlg,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER);
//
// Resize, reposition, and make visible child listview
//
RECT rcDlgNew;
GetClientRect(m_hwnd, &rcDlgNew);
HWND hwndLv = _hCtrl(IDC_QUERY_LISTVIEW);
SetWindowPos(hwndLv,
NULL,
rcDlgNew.left,
m_rcDlgOriginal.bottom,
rcDlgNew.right,
rcDlgNew.bottom - m_rcDlgOriginal.bottom,
SWP_NOZORDER | SWP_NOOWNERZORDER);
//
// If taskbar is covering listview move the dialog box up.
//
RECT rcDlgNewW;
GetWindowRect(m_hwnd, &rcDlgNewW);
if(rcDlgNewW.bottom > rcWorkArea.bottom)
{
SetWindowPos(m_hwnd,
NULL,
rcDlgNewW.left,
rcDlgNewW.top - (rcDlgNewW.bottom - rcWorkArea.bottom),
0,
0,
SWP_NOZORDER | SWP_NOOWNERZORDER |SWP_NOSIZE);
}
//
// Initialize listview
//
ListView_SetExtendedListViewStyleEx(hwndLv, c_ulStyle, c_ulStyle);
ShowWindow(hwndLv, SW_SHOW);
//
// Increase the minimum size so the listview can't be completely
// hidden
//
DWORD dwLvMinSize = ListView_ApproximateViewRect(hwndLv, -1, -1, 1);
m_cyMin += HIWORD(dwLvMinSize);
RECT rcLv;
_GetChildWindowRect(hwndLv, &rcLv);
m_cxLvSeparation = rcDlgNew.right - rcLv.right;
m_cyLvSeparation = rcDlgNew.bottom - rcLv.bottom;
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_StopQuery
//
// Synopsis: Ask the query engine to stop whatever query it's working on
// and update the UI to reflect a stopping query.
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_StopQuery()
{
const CQueryEngine &rqe = m_rop.GetQueryEngine();
rqe.StopWorkItem();
EnableWindow(_hCtrl(IDC_LOOK_FOR_PB), TRUE);
EnableWindow(_hCtrl(IDC_LOOK_IN_PB), TRUE);
EnableWindow(_hCtrl(IDC_TAB), TRUE);
m_pCurTab->Enable();
if (m_hwndBanner && IsWindowVisible(m_hwndBanner))
{
_ShowBanner(0, IDS_STOPPING_QUERY);
}
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnMinMaxInfo
//
// Synopsis: Respond to a WM_MINMAXINFO message based on whether the
// dialog is in resizeable mode.
//
// Arguments: [lpmmi] - pointer to struct to fill with minimum and maximum
// allowed window size
//
// Returns: FALSE
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
BOOL
CAdvancedDlg::_OnMinMaxInfo(
LPMINMAXINFO lpmmi)
{
if (m_fResizeableModeOn)
{
lpmmi->ptMinTrackSize.x = m_cxMin;
lpmmi->ptMinTrackSize.y = m_cyMin;
}
else
{
lpmmi->ptMaxTrackSize.x = m_cxMin - 1;
lpmmi->ptMaxTrackSize.y = m_cyMin - 1;
lpmmi->ptMinTrackSize.x = m_cxMin - 1;
lpmmi->ptMinTrackSize.y = m_cyMin - 1;
}
return FALSE;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnSize
//
// Synopsis: Handle a WM_SIZE message.
//
// Arguments: [wParam] - standard windows
// [lParam] - standard windows
//
// Returns: standard windows
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
BOOL
CAdvancedDlg::_OnSize(
WPARAM wParam,
LPARAM lParam)
{
if (!m_fResizeableModeOn)
{
return TRUE;
}
RECT rcDlg;
GetClientRect(m_hwnd, &rcDlg);
if (!m_cxFrameLast || !m_cyFrameLast)
{
Dbg(DEB_TRACE, "FrameLast not set yet, returning\n");
m_cxFrameLast = rcDlg.right;
m_cyFrameLast = rcDlg.bottom;
return TRUE;
}
LONG cxDelta = rcDlg.right - m_cxFrameLast;
//
// Move the OK/Cancel buttons so they're always at lower right
// corner of upper half of dialog.
//
RECT rcCancel;
RECT rcLv;
GetWindowRect(_hCtrl(IDCANCEL), &rcCancel);
_GetChildWindowRect(_hCtrl(IDC_QUERY_LISTVIEW), &rcLv);
SetWindowPos(_hCtrl(IDCANCEL),
NULL,
rcDlg.right - WindowRectWidth(rcCancel) - m_cxSeparation,
rcLv.top - WindowRectHeight(rcCancel) - m_cySeparation,
0,
0,
SWP_NOSIZE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
RECT rcOk;
_GetChildWindowRect(_hCtrl(IDOK), &rcOk);
_GetChildWindowRect(_hCtrl(IDCANCEL), &rcCancel);
SetWindowPos(_hCtrl(IDOK),
NULL,
rcCancel.left - WindowRectWidth(rcCancel) - m_cxFour,
rcCancel.top,
0,
0,
SWP_NOSIZE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Find now, Columns, and stop buttons never change their vertical
// position; their right edge stays aligned with the Cancel button.
//
RECT rcFindNow;
_GetChildWindowRect(_hCtrl(IDC_FIND_NOW_PB), &rcFindNow);
SetWindowPos(_hCtrl(IDC_FIND_NOW_PB),
NULL,
rcCancel.right - WindowRectWidth(rcFindNow),
rcFindNow.top,
0,
0,
SWP_NOSIZE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
RECT rcStop;
_GetChildWindowRect(_hCtrl(IDC_STOP_PB), &rcStop);
SetWindowPos(_hCtrl(IDC_STOP_PB),
NULL,
rcCancel.right - WindowRectWidth(rcStop),
rcStop.top,
0,
0,
SWP_NOSIZE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
RECT rcColumns;
_GetChildWindowRect(_hCtrl(IDC_COLUMNS_PB), &rcColumns);
SetWindowPos(_hCtrl(IDC_COLUMNS_PB),
NULL,
rcCancel.right - WindowRectWidth(rcColumns),
rcColumns.top,
0,
0,
SWP_NOSIZE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Animate control is always centered beneath the stop PB
//
RECT rcAni;
_GetChildWindowRect(m_hwndAnimation, &rcAni);
SetWindowPos(m_hwndAnimation,
NULL,
rcCancel.left +
(WindowRectWidth(rcStop) - 64) / 2,
rcStop.bottom + m_cySeparation,
64,
64,
SWP_NOOWNERZORDER
| SWP_NOZORDER);
//
// Resize tab control
//
RECT rcTab;
_GetChildWindowRect(_hCtrl(IDC_TAB), &rcTab);
SetWindowPos(_hCtrl(IDC_TAB),
NULL,
0,
0,
WindowRectWidth(rcTab) + cxDelta,
WindowRectHeight(rcTab),
SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Resize listview
//
SetWindowPos(_hCtrl(IDC_QUERY_LISTVIEW),
NULL,
0,
0,
rcDlg.right - m_cxLvSeparation,
rcDlg.bottom - rcLv.top - m_cyLvSeparation,
SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Resize look in edit and button
//
RECT rcLookIn;
_GetChildWindowRect(_hCtrl(IDC_LOOK_IN_EDIT), &rcLookIn);
SetWindowPos(_hCtrl(IDC_LOOK_IN_EDIT),
NULL,
0,
0,
WindowRectWidth(rcLookIn) + cxDelta,
WindowRectHeight(rcLookIn),
SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
_GetChildWindowRect(_hCtrl(IDC_LOOK_IN_EDIT), &rcLookIn);
RECT rcLookInPb;
_GetChildWindowRect(_hCtrl(IDC_LOOK_IN_PB), &rcLookInPb);
//
//Button's left is FOUR DLU right of Edit's Right
//
SetWindowPos(_hCtrl(IDC_LOOK_IN_PB),
NULL,
rcLookIn.right + m_cxFour,
rcLookInPb.top,
0,
0,
SWP_NOSIZE
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Resize look for(locations) edit and button
//
RECT rcLookFor;
_GetChildWindowRect(_hCtrl(IDC_LOOK_FOR_EDIT), &rcLookFor);
SetWindowPos(_hCtrl(IDC_LOOK_FOR_EDIT),
NULL,
0,
0,
WindowRectWidth(rcLookFor) + cxDelta,
WindowRectHeight(rcLookFor),
SWP_NOMOVE
| SWP_NOOWNERZORDER
| SWP_NOCOPYBITS
| SWP_NOZORDER);
_GetChildWindowRect(_hCtrl(IDC_LOOK_FOR_EDIT), &rcLookFor);
RECT rcLookForPb;
_GetChildWindowRect(_hCtrl(IDC_LOOK_FOR_PB), &rcLookForPb);
SetWindowPos(_hCtrl(IDC_LOOK_FOR_PB),
NULL,
rcLookFor.right + m_cxFour,
rcLookForPb.top,
0,
0,
SWP_NOSIZE
| SWP_NOCOPYBITS
| SWP_NOZORDER);
//
// Update the saved size of the advanced dialog
//
m_cxFrameLast = rcDlg.right;
m_cyFrameLast = rcDlg.bottom;
//
// Force banner to resize
//
_ShowBanner(0, 0);
return FALSE;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::FindValidCallback
//
// Synopsis: Called by child dialog to enable or disable the find now
// button.
//
// Arguments: [fValid] - TRUE=>enable Find Now, FALSE=>disable
// [lParam] - pointer to this
//
// History: 06-14-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::FindValidCallback(
BOOL fValid,
LPARAM lParam)
{
TRACE_FUNCTION(FindValidCallback);
CAdvancedDlg *pThis = reinterpret_cast<CAdvancedDlg *>(lParam);
EnableWindow(pThis->_hCtrl(IDC_FIND_NOW_PB), fValid);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_OnOk
//
// Synopsis: Stop any query in progress and fill the output vector with
// the items in the listview which are selected.
//
// History: 06-16-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_OnOk()
{
TRACE_METHOD(CAdvancedDlg, _OnOk);
HWND hwndLV = _hCtrl(IDC_QUERY_LISTVIEW);
const CQueryEngine &rqe = m_rop.GetQueryEngine();
rqe.StopWorkItem();
//
// Copy each of the ds objects whose item in the listview is
// selected to the output list.
//
LVITEM lvi;
int iItem = -1;
ZeroMemory(&lvi, sizeof lvi);
lvi.mask = LVIF_PARAM;
while ((iItem = ListView_GetNextItem(hwndLV,
iItem,
LVNI_SELECTED)) != -1)
{
lvi.iItem = iItem;
ListView_GetItem(hwndLV, &lvi);
m_pvSelectedObjects->push_back(rqe.GetObject(lvi.lParam));
}
ASSERT(!m_pvSelectedObjects->empty());
Dbg(DEB_TRACE,
"UA: (AdvancedDlg) hit OK, %u items in output vector, first is %ws\n",
m_pvSelectedObjects->size(),
m_pvSelectedObjects->front().GetName());
//
// No need to leave a large buffer of query results lying around
//
rqe.Clear();
}
//+--------------------------------------------------------------------------
//
// Function: _BannerWndProc
//
// Synopsis: Paint the current message inside the banner window.
//
// Arguments: standard Windows
//
// Returns: standard Windows
//
// History: 06-22-2000 DavidMun Ported from DS Find source
//
// Notes: The banner window covers the top portion of the listview's
// client area when the listview is empty. Its purpose is to
// display some text that indicates why the listview is empty.
//
//---------------------------------------------------------------------------
LRESULT CALLBACK
_BannerWndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
LRESULT lResult = 0;
switch ( uMsg )
{
case WM_SIZE:
InvalidateRect(hwnd, NULL, FALSE);
break;
case WM_ERASEBKGND:
// NTRAID#NTBUG9-421812-2001/06/22-lucios - Begin
// The background must be explicitly erased here
// since this window's brush is NULL
RECT rect;
GetClientRect(hwnd,&rect);
FillRect(
(HDC)wParam,
&rect,
static_cast<HBRUSH>
(
LongToHandle
(
ListView_GetBkColor(GetParent(hwnd))+1
)
)
);
lResult=1;
break;
// NTRAID#NTBUG9-421812-2001/06/22-lucios - Begin
case WM_PAINT:
{
HFONT hFont, hOldFont;
RECT rcClient;
PAINTSTRUCT paint;
COLORREF oldFgColor, oldBkColor;
BeginPaint(hwnd, &paint);
hFont = (HFONT)SendMessage(GetParent(hwnd), WM_GETFONT, 0, 0L);
hOldFont = (HFONT)SelectObject(paint.hdc, hFont);
if ( hOldFont )
{
oldFgColor = SetTextColor(paint.hdc, GetSysColor(COLOR_WINDOWTEXT));
oldBkColor = SetBkColor(paint.hdc, ListView_GetBkColor(GetParent(hwnd)));
int cch = GetWindowTextLength(hwnd);
String strText;
if (cch > 0)
{
PWSTR pwz = new WCHAR [cch + 1];
int iRet = GetWindowText(hwnd, pwz, cch + 1);
if (iRet)
{
strText = pwz;
}
else
{
DBG_OUT_LASTERROR;
}
delete [] pwz;
}
if (!strText.empty())
{
GetClientRect(GetParent(hwnd), &rcClient);
int iRet;
// NTRAID#NTBUG9-421812-2001/06/22-lucios - Begin
// Now we center unconditionally since the previous calculation
// does not work for error messages with \n's
iRet = DrawTextEx(paint.hdc,
const_cast<PWSTR>(strText.c_str()),
cch,
&rcClient,
DT_WORDBREAK | DT_TOP |DT_CENTER,
NULL);
// NTRAID#NTBUG9-421812-2001/06/22-lucios - End
if (!iRet)
{
DBG_OUT_LASTERROR;
}
}
SetTextColor(paint.hdc, oldFgColor);
SetBkColor(paint.hdc, oldBkColor);
SelectObject(paint.hdc, hOldFont);
}
EndPaint(hwnd, &paint);
break;
}
case WM_SETTEXT:
{
InvalidateRect(hwnd, NULL, TRUE);
//break; // deliberate drop through..
}
default:
lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
break;
}
return lResult;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_ShowBanner
//
// Synopsis: Show or hide the banner window.
//
// Arguments: [ulFlags] - 0 to leave visibility unchanged
// SW_SHOW to make banner window visible
// SW_HIDE to hide banner window
// [idsPrompt] - 0 or the ID of a resource string to load and
// display in the window.
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_ShowBanner(
ULONG ulFlags,
ULONG idsPrompt)
{
String strMsg;
if (idsPrompt)
{
strMsg = String::load(static_cast<int>(idsPrompt));
}
_ShowBanner(ulFlags, strMsg);
}
/*-----------------------------------------------------------------------------
/ CAdvancedDlg::_ShowBanner
/ --------------------
/ Show the views banner, including sizing it to obscure only the top section
/ of the window.
/
/ In:
/ uFlags = flags to combine when calling SetWindowPos
/ idPrompt = resource ID of prompt text ot be displayed
/
/----------------------------------------------------------------------------*/
void
CAdvancedDlg::_ShowBanner(
ULONG ulFlags,
const String &strMsg)
{
TRACE_METHOD(CAdvancedDlg, _ShowBanner);
WINDOWPOS wpos;
RECT rcClient;
HD_LAYOUT hdl;
do
{
if (!m_hwndBanner)
{
break;
}
// if we have a resource id then lets load the string and
// set the window text to have it
if (!strMsg.empty())
{
SetWindowText(m_hwndBanner, strMsg.c_str());
}
// now position the window back to real location, this we need to
// talk to the listview/header control to work out exactly where it
// should be living
GetClientRect(_hCtrl(IDC_QUERY_LISTVIEW), &rcClient);
wpos.hwnd = ListView_GetHeader(_hCtrl(IDC_QUERY_LISTVIEW));
if (!IsWindow(wpos.hwnd))
{
if (strMsg.empty())
{
Dbg(DEB_ERROR,
"error: no header; can't set window flags %#x\n",
ulFlags);
}
else
{
Dbg(DEB_ERROR,
"error: no header; can't display '%ws'\n",
strMsg.c_str());
}
break;
}
wpos.hwndInsertAfter = NULL;
wpos.x = 0;
wpos.y = 0;
wpos.cx = rcClient.right;
wpos.cy = rcClient.bottom;
wpos.flags = SWP_NOZORDER;
hdl.prc = &rcClient;
hdl.pwpos = &wpos;
if ( !Header_Layout(wpos.hwnd, &hdl) )
{
DBG_OUT_LASTERROR;
break;
}
SetWindowPos(m_hwndBanner,
HWND_TOP,
rcClient.left, rcClient.top,
rcClient.right - rcClient.left, 100,
ulFlags);
} while (0);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_UpdateColumns
//
// Synopsis: For all classes checked in the Look For since last visit,
// add their default columns, remove columns that now refer
// to classes which are no longer selected.
//
// History: 06-15-2000 DavidMun Created
//
//---------------------------------------------------------------------------
HRESULT
CAdvancedDlg::_UpdateColumns()
{
TRACE_METHOD(CAdvancedDlg, _UpdateColumns);
HRESULT hr = S_OK;
size_t i = 0;
HWND hwndLV = _hCtrl(IDC_QUERY_LISTVIEW);
//
// If we're in downlevel mode, only two columns are allowed: name and
// display path
//
if (IsDownlevel(m_rop.GetScopeManager().GetCurScope()))
{
while (i < m_vakListviewColumns.size())
{
if (m_vakListviewColumns[i] != AK_NAME &&
m_vakListviewColumns[i] != AK_DISPLAY_PATH)
{
ListView_DeleteColumn(hwndLV, i);
m_vakListviewColumns.erase(m_vakListviewColumns.begin() + i);
}
else
{
i++;
}
}
_AddColIfNotPresent(AK_NAME);
_AddColIfNotPresent(AK_DISPLAY_PATH);
m_ulPrevFilterFlags = 0;
return hr;
}
//
// For each of the selected classes that have been added since the
// last time we were here, add the default set of attributes for that
// class to the listview.
//
const CFilterManager &rfm = m_rop.GetFilterManager();
ULONG ulCurFilterFlags = rfm.GetCurScopeSelectedFilterFlags();
const CAttributeManager &ram = m_rop.GetAttributeManager();
if ((ulCurFilterFlags & ALL_UPLEVEL_INTERNAL_CUSTOMIZER_FILTERS) &&
!(m_ulPrevFilterFlags & ALL_UPLEVEL_INTERNAL_CUSTOMIZER_FILTERS))
{
_AddColIfNotPresent(AK_NAME);
}
if ((ulCurFilterFlags & DSOP_FILTER_USERS) &&
!(m_ulPrevFilterFlags & DSOP_FILTER_USERS))
{
hr = ram.EnsureAttributesLoaded(m_hwnd, FALSE, c_wzUserObjectClass);
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
return hr;
}
_AddColIfNotPresent(AK_NAME);
_AddColIfNotPresent(AK_EMAIL_ADDRESSES);
}
if ((ulCurFilterFlags & DSOP_FILTER_COMPUTERS) &&
!(m_ulPrevFilterFlags & DSOP_FILTER_COMPUTERS))
{
hr = ram.EnsureAttributesLoaded(m_hwnd, FALSE, c_wzComputerObjectClass);
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
return hr;
}
_AddColIfNotPresent(AK_NAME);
_AddColIfNotPresent(AK_DESCRIPTION);
}
if ((ulCurFilterFlags & ALL_UPLEVEL_GROUP_FILTERS) &&
!(m_ulPrevFilterFlags & ALL_UPLEVEL_GROUP_FILTERS))
{
hr = ram.EnsureAttributesLoaded(m_hwnd, FALSE, c_wzGroupObjectClass);
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
return hr;
}
_AddColIfNotPresent(AK_NAME);
_AddColIfNotPresent(AK_DESCRIPTION);
}
if ((ulCurFilterFlags & DSOP_FILTER_CONTACTS) &&
!(m_ulPrevFilterFlags & DSOP_FILTER_CONTACTS))
{
hr = ram.EnsureAttributesLoaded(m_hwnd, FALSE, c_wzContactObjectClass);
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
return hr;
}
_AddColIfNotPresent(AK_NAME);
_AddColIfNotPresent(AK_SAMACCOUNTNAME);
_AddColIfNotPresent(AK_EMAIL_ADDRESSES);
_AddColIfNotPresent(AK_COMPANY);
}
_AddColIfNotPresent(AK_DISPLAY_PATH);
m_ulPrevFilterFlags = ulCurFilterFlags;
//
// For each of the columns, if there are no selected classes in that
// column's attribute's owning class list, remove that column.
//
vector<String> vstrSelectedClasses;
String::EqualIgnoreCase comp;
i = 0;
ram.GetSelectedClasses(&vstrSelectedClasses);
while (i < m_vakListviewColumns.size())
{
const vector<String> &vstrOwning =
ram.GetOwningClasses(m_vakListviewColumns[i]);
if (!vstrOwning.empty() && !vstrOwning[0].icompare(L"*"))
{
i++;
continue;
}
vector<String>::const_iterator itFound;
itFound = find_first_of(vstrOwning.begin(),
vstrOwning.end(),
vstrSelectedClasses.begin(),
vstrSelectedClasses.end(),
comp);
if (itFound == vstrOwning.end())
{
ListView_DeleteColumn(hwndLV, i);
m_vakListviewColumns.erase(m_vakListviewColumns.begin() + i);
}
else
{
i++;
}
}
//
// Insert new set of columns
//
for (i = 0; i < m_vakListviewColumns.size(); i++)
{
const String &strAttrDisplayName = ram.GetAttrDisplayName(m_vakListviewColumns[i]);
LVCOLUMN col;
ZeroMemory(&col, sizeof col);
col.mask = LVCF_TEXT;
col.pszText = const_cast<PWSTR>(strAttrDisplayName.c_str());
ListView_SetColumn(hwndLV,
i,
&col);
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_AddColIfNotPresent
//
// Synopsis: If the column with key [ak] isn't already in the vector of
// attributes m_vakListViewColumns and to the listview itself.
//
// Arguments: [ak] - ATTR_KEY of attribute to add
// [iPos] - 0 based position to insert column into listview
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_AddColIfNotPresent(
ATTR_KEY ak,
int iPos)
{
BOOL fAdded = AddIfNotPresent(&m_vakListviewColumns, ak);
if (!fAdded)
{
return;
}
_AddColToListview(ak, iPos);
}
//+--------------------------------------------------------------------------
//
// Member: CAdvancedDlg::_AddColToListview
//
// Synopsis: Add column with key [ak] to listview at position [iPos].
//
// Arguments: [ak] - ATTR_KEY representing attribute
// [iPos] - 0 based position to insert column into listview
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CAdvancedDlg::_AddColToListview(
ATTR_KEY ak,
int iPos)
{
LV_COLUMN lvc;
ZeroMemory(&lvc, sizeof lvc);
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = 100;
const CAttributeManager &ram = m_rop.GetAttributeManager();
const String &strAttrDisplayName = ram.GetAttrDisplayName(ak);
lvc.pszText = const_cast<PWSTR>(strAttrDisplayName.c_str());
int iResult = ListView_InsertColumn(_hCtrl(IDC_QUERY_LISTVIEW),
iPos,
&lvc);
if (iResult == -1)
{
DBG_OUT_LASTERROR;
}
}