windows-nt/Source/XPSP1/NT/admin/display/proppage/shell/user.cxx
2020-09-26 16:20:57 +08:00

843 lines
24 KiB
C++

//+----------------------------------------------------------------------------
//
// Windows NT Directory Service Property Pages
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2001
//
// File: user.cxx
//
// Contents: AD user shell property pages
//
// History: 05-May-97 EricB created
//
//-----------------------------------------------------------------------------
#include "pch.h"
#include "proppage.h"
#include "objlist.h"
#include "user.h"
//#include "group.h"
#ifndef UNICODE
# include <stdio.h>
#endif
//+----------------------------------------------------------------------------
//
// Function: CountryCode
//
// Synopsis: Handles the Country combo box to get/set the Country-Code
// (LDAP display name: countryCode) numeric ISO-3166 code.
//
// Notes: This attr function MUST be called after CountryName. It
// relies on CountryName populating the combobox and setting its
// item data values.
//
//-----------------------------------------------------------------------------
HRESULT
CountryCode(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
DLG_OP DlgOp)
{
switch(DlgOp)
{
case fOnCommand:
if (CBN_SELCHANGE == lParam)
{
pPage->SetDirty();
PATTR_DATA_SET_DIRTY(pAttrData);
}
break;
case fApply:
DBG_OUT("CountryCode: fApply");
if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
{
return ADM_S_SKIP;
}
int iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETCURSEL, 0, 0);
if (iSel < 0)
{
pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
}
else
{
INT_PTR pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETITEMDATA, iSel, 0);
if (pCur == LB_ERR)
{
DWORD dwErr = GetLastError();
CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
}
PDsCountryCode pCountryCode = (PDsCountryCode)pCur;
PADSVALUE pADsValue;
pADsValue = new ADSVALUE;
CHECK_NULL_REPORT(pADsValue, pPage->GetHWnd(), return E_OUTOFMEMORY);
pAttrInfo->pADsValues = pADsValue;
pAttrInfo->dwNumValues = 1;
pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
pADsValue->dwType = pAttrInfo->dwADsType;
pADsValue->Integer = pCountryCode->wCode;
}
break;
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Function: CountryName
//
// Synopsis: Handles the Country combo box/static control to get/set the
// Country-Name (LDAP display name: c) 2 character ISO-3166 code.
//
// Notes: If the control is read-only, then assume it is a static text
// control (or a read-only edit control) rather than a combobox.
// Also, if read-only, then only the fInit should be called.
//
//-----------------------------------------------------------------------------
HRESULT
CountryName(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
DLG_OP DlgOp)
{
PWSTR pwsz = NULL;
DWORD dwErr = 0;
INT_PTR pCur = NULL;
PDsCountryCode pCountryCode = NULL;
int iSel = 0, iCur = -1, cxExtent = 0;
#ifdef UNICODE
CStrW strFirstCode, strLastCode, strCodeLine, strCurName;
#else
CStr strFirstCode, strLastCode, strCodeLine, strCurName;
#endif
CStrW str2CharAbrev;
switch (DlgOp)
{
case fInit:
dspAssert(pAttrData);
if (!pAttrMap->fIsReadOnly && !PATTR_DATA_IS_WRITABLE(pAttrData))
{
EnableWindow(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID),
FALSE);
//
// Remove the accelerator from the label since a disabled control
// is not reachable.
//
CStr strLabel;
strLabel.LoadString(g_hInstance, IDS_COUNTRY_LABEL_NO_ACCEL);
SetDlgItemText(pPage->GetHWnd(), IDC_COUNTRY_LABEL, strLabel.GetBuffer(0));
}
// fall through...
case fObjChanged:
{
DBG_OUT("CountryName: fInit");
PTSTR ptzFullName = NULL;
WORD wCode = 0;
HDC hDC = NULL;
unsigned long ulFirstCode, ulLastCode, i;
strFirstCode.LoadString(g_hInstance, IDS_FIRST_COUNTRY_CODE);
strLastCode.LoadString(g_hInstance, IDS_LAST_COUNTRY_CODE);
if (strFirstCode.IsEmpty() || strLastCode.IsEmpty())
{
ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
}
ulFirstCode = _tcstoul(strFirstCode, NULL, 10);
ulLastCode = _tcstoul(strLastCode, NULL, 10);
if (!pAttrMap->fIsReadOnly)
{
hDC = GetDC(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID));
}
PWSTR pwzCurCode;
if (pAttrInfo && pAttrInfo->dwNumValues)
{
pwzCurCode = pAttrInfo->pADsValues->CaseIgnoreString;
}
else
{
pwzCurCode = NULL;
}
for (i = ulFirstCode; i <= ulLastCode; i++)
{
strCodeLine.LoadString(g_hInstance, i);
if (strCodeLine.IsEmpty())
{
ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
}
if (!GetALineOfCodes(strCodeLine.GetBuffer(1), &ptzFullName, str2CharAbrev, &wCode))
{
ERR_MSG(IDS_ERR_COUNTRY_DATA_BAD, pPage->GetHWnd());
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
}
if (!pAttrMap->fIsReadOnly)
{
// If not in read-only mode, then we use a combobox from which
// the user selects the country.
// Insert the full name into the combobox list.
//
SIZE s;
if (hDC != NULL)
{
GetTextExtentPoint32(hDC, ptzFullName, static_cast<int>(_tcslen(ptzFullName)), &s);
if (s.cx > cxExtent)
{
cxExtent = s.cx;
}
iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_ADDSTRING, 0, (LPARAM)ptzFullName);
if (iSel < 0)
{
CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
}
//
// Add the name codes as item data.
//
pCountryCode = new DsCountryCode;
CHECK_NULL_REPORT(pCountryCode, pPage->GetHWnd(), return E_OUTOFMEMORY);
wcscpy(pCountryCode->pwz2CharAbrev, str2CharAbrev);
pCountryCode->wCode = wCode;
if (SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_SETITEMDATA, iSel,
(LPARAM)pCountryCode) == CB_ERR)
{
CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
}
}
}
//
// See if the current country matches that saved on the DS object
// (if one has been saved).
//
if (pwzCurCode)
{
if (_wcsicmp(pwzCurCode, str2CharAbrev) == 0)
{
iCur = iSel;
strCurName = ptzFullName;
}
}
if ((iCur == iSel) && pAttrMap->fIsReadOnly)
{
// Read-only mode means that we are using a static text
// control. Insert the full name into the control.
//
SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, ptzFullName);
break;
}
if (pAttrMap->fIsReadOnly)
{
iSel++;
}
}
if (!pAttrMap->fIsReadOnly)
{
if (hDC != NULL)
{
ReleaseDC(GetDlgItem(pPage->GetHWnd(), pAttrMap->nCtrlID), hDC);
}
SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_SETHORIZONTALEXTENT, (WPARAM)cxExtent, 0);
if (iCur >= 0)
{
iCur = (int) SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_FINDSTRINGEXACT, 0,
(WPARAM)(LPCTSTR)strCurName);
dspAssert(iCur != CB_ERR);
SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_SETCURSEL, iCur, 0);
}
}
else
{
if (iCur < 0)
{
// If iCur is still -1, then country code hasn't been set.
//
SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, TEXT(""));
}
}
break;
}
case fApply:
DBG_OUT("CountryName: fApply");
if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
{
return ADM_S_SKIP;
}
iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETCURSEL, 0, 0);
if (iSel < 0)
{
pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
}
else
{
pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETITEMDATA, iSel, 0);
if (pCur == LB_ERR)
{
dwErr = GetLastError();
CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
}
pCountryCode = (PDsCountryCode)pCur;
if (!AllocWStr(pCountryCode->pwz2CharAbrev, &pwsz))
{
CHECK_HRESULT_REPORT(E_OUTOFMEMORY, pPage->GetHWnd(), return E_OUTOFMEMORY);
}
PADSVALUE pADsValue;
pADsValue = new ADSVALUE;
CHECK_NULL_REPORT(pADsValue, pPage->GetHWnd(), return E_OUTOFMEMORY);
pAttrInfo->pADsValues = pADsValue;
pAttrInfo->dwNumValues = 1;
pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
pADsValue->dwType = pAttrInfo->dwADsType;
pADsValue->CaseIgnoreString = pwsz;
}
break;
case fOnCommand:
if (CBN_SELCHANGE == lParam)
{
pPage->SetDirty();
PATTR_DATA_SET_DIRTY(pAttrData);
}
break;
case fOnDestroy:
DBG_OUT("CountryName: fOnDestroy");
iSel = 0;
do
{
pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETITEMDATA, iSel, 0);
if (pCur != CB_ERR)
{
// Delete the itemdata string.
//
delete (PDsCountryCode)pCur;
iSel++;
}
} while (pCur != CB_ERR);
break;
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Function: TextCountry
//
// Synopsis: Handles the Country combo box to get/set the Text-Country
// (LDAP display name: co)
//
// Notes: This attr function MUST be called after CountryName. It
// relies on CountryName populating the combobox
//
//-----------------------------------------------------------------------------
HRESULT
TextCountry(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
DLG_OP DlgOp)
{
switch(DlgOp)
{
case fOnCommand:
if (CBN_SELCHANGE == lParam)
{
pPage->SetDirty();
PATTR_DATA_SET_DIRTY(pAttrData);
}
break;
case fApply:
DBG_OUT("TextCountry: fApply");
if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
{
return ADM_S_SKIP;
}
int iSel = (int)SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETCURSEL, 0, 0);
if (iSel < 0)
{
pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
}
else
{
LPTSTR ptz = new TCHAR[pAttrMap->nSizeLimit + 1];
CHECK_NULL_REPORT(ptz, pPage->GetHWnd(), return E_OUTOFMEMORY);
INT_PTR pCur = SendDlgItemMessage(pPage->GetHWnd(), pAttrMap->nCtrlID,
CB_GETLBTEXT, iSel, (LPARAM) (LPCSTR) ptz );
if (pCur == LB_ERR)
{
delete ptz;
DWORD dwErr = GetLastError();
CHECK_WIN32_REPORT(dwErr, pPage->GetHWnd(), return HRESULT_FROM_WIN32(dwErr););
}
PADSVALUE pADsValue;
pADsValue = new ADSVALUE;
if( pADsValue == NULL )
{
ReportError(E_OUTOFMEMORY,0, pPage->GetHWnd());
delete ptz;
return E_OUTOFMEMORY;
}
if (!TcharToUnicode(ptz, &pADsValue->CaseIgnoreString))
{
delete ptz;
delete pADsValue;
REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
return E_OUTOFMEMORY;
}
delete ptz;
pAttrInfo->pADsValues = pADsValue;
pAttrInfo->dwNumValues = 1;
pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
pADsValue->dwType = pAttrInfo->dwADsType;
}
break;
}
return S_OK;
}
// CountryName helpers:
//+----------------------------------------------------------------------------
//
// Function: GetALineOfCodes
//
// Synopsis: Parse a line of country codes.
//
//-----------------------------------------------------------------------------
BOOL GetALineOfCodes(PTSTR ptzLine, PTSTR * pptzFullName,
CStrW & str2CharAbrev, LPWORD pwCode)
{
//
// The line is parsed from end to beginning. That way we don't need to
// dependend on the column widths being fixed.
//
// The last token is the numeric code. Read it.
//
RemoveTrailingWhitespace(ptzLine);
PTSTR ptzCode = _tcsrchr(ptzLine, TEXT(' '));
if (!ptzCode)
{
// try tab char.
//
ptzCode = _tcsrchr(ptzLine, TEXT('\t'));
}
if (!ptzCode || (ptzCode <= ptzLine) || (_tcslen(ptzCode) < 2))
{
return FALSE;
}
*ptzCode = TEXT('\0');
ptzCode++;
int iScanned = _stscanf(ptzCode, TEXT("%u"), pwCode);
dspAssert(iScanned == 1);
//
// The next to last token is the 3 character code. Skip it.
//
RemoveTrailingWhitespace(ptzLine);
size_t nLen = _tcslen(ptzLine);
if (3 >= nLen)
{
return FALSE;
}
ptzLine[nLen - 3] = TEXT('\0');
//
// The next token (moving toward the front) is the 2 character code.
//
RemoveTrailingWhitespace(ptzLine);
PTSTR ptz2CharAbrev = _tcsrchr(ptzLine, TEXT(' '));
if (!ptz2CharAbrev)
{
// try tab char.
//
ptz2CharAbrev = _tcsrchr(ptzLine, TEXT('\t'));
}
if (!ptz2CharAbrev || (ptz2CharAbrev <= ptzLine))
{
return FALSE;
}
*ptz2CharAbrev = TEXT('\0');
ptz2CharAbrev++;
if (_tcslen(ptz2CharAbrev) != 2)
{
return FALSE;
}
str2CharAbrev = ptz2CharAbrev;
//
// The first token is the full country name.
//
RemoveTrailingWhitespace(ptzLine);
if (!_tcslen(ptzLine))
{
return FALSE;
}
*pptzFullName = ptzLine;
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: RemoveTrailingWhitespace
//
// Synopsis: Trailing white space is replaced by NULLs.
//
//-----------------------------------------------------------------------------
void RemoveTrailingWhitespace(PTSTR ptz)
{
size_t nLen = _tcslen(ptz);
while (nLen)
{
if (!iswspace(ptz[nLen - 1]))
{
return;
}
ptz[nLen - 1] = L'\0';
nLen--;
}
}
//+----------------------------------------------------------------------------
//
// Function: ManagerEdit
//
// Synopsis: Handles the manager edit control.
//
// Notes: The page member m_pData stores the pAttrData value whose pVoid
// element is set to the DN of the manager. The other manager
// attr functions can then access the manager value and can also
// read the fWritable element.
//
//-----------------------------------------------------------------------------
HRESULT
ManagerEdit(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA pAttrData,
DLG_OP DlgOp)
{
PWSTR pwz = NULL;
PWSTR canonical = NULL;
HRESULT hr = S_OK;
switch (DlgOp)
{
case fInit:
dspAssert(pAttrData);
if (pAttrInfo && pAttrInfo->dwNumValues > 0)
{
if (!AllocWStr(pAttrInfo->pADsValues[0].DNString, &pwz))
{
REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
return E_OUTOFMEMORY;
}
hr = CrackName (pwz, &canonical, GET_OBJ_CAN_NAME_EX, pPage->GetHWnd());
if (FAILED(hr))
{
delete pwz;
return S_FALSE;
}
PTSTR ptz, ptzName;
if (!UnicodeToTchar(canonical, &ptz))
{
REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
delete pwz;
return E_OUTOFMEMORY;
}
LocalFreeStringW(&canonical);
ptzName = _tcschr(ptz, TEXT('\n'));
dspAssert(ptzName);
ptzName++;
SetDlgItemText(pPage->GetHWnd(), pAttrMap->nCtrlID, ptzName);
delete ptz;
}
pAttrData->pVoid = reinterpret_cast<LPARAM>(pwz);
((CDsTableDrivenPage *)pPage)->m_pData = reinterpret_cast<LPARAM>(pAttrData);
break;
case fOnCommand:
if (EN_CHANGE == lParam)
{
pPage->SetDirty();
PATTR_DATA_SET_DIRTY(pAttrData);
}
break;
case fApply:
if (!PATTR_DATA_IS_WRITABLE(pAttrData) || !PATTR_DATA_IS_DIRTY(pAttrData))
{
return ADM_S_SKIP;
}
pwz = (PWSTR)reinterpret_cast<PATTR_DATA>(((CDsTableDrivenPage *)pPage)->m_pData)->pVoid;
if (pwz)
{
// make a copy cause CDsTableDrivenPage::OnApply deletes it.
PWSTR pwzTmp;
if (!AllocWStr(pwz, &pwzTmp))
{
REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
return E_OUTOFMEMORY;
}
PADSVALUE pADsValue;
pADsValue = new ADSVALUE;
CHECK_NULL(pADsValue, return E_OUTOFMEMORY);
pAttrInfo->pADsValues = pADsValue;
pAttrInfo->dwNumValues = 1;
pAttrInfo->dwControlCode = ADS_ATTR_UPDATE;
pADsValue->dwType = pAttrInfo->dwADsType;
pADsValue->CaseIgnoreString = pwzTmp;
}
else
{
pAttrInfo->pADsValues = NULL;
pAttrInfo->dwNumValues = 0;
pAttrInfo->dwControlCode = ADS_ATTR_CLEAR;
}
break;
case fOnDestroy:
if (reinterpret_cast<CDsTableDrivenPage *>(pPage)->m_pData)
{
PATTR_DATA pData = reinterpret_cast<PATTR_DATA>(((CDsTableDrivenPage *)pPage)->m_pData);
PVOID pVoid = reinterpret_cast<PVOID>(pData->pVoid);
DO_DEL(pVoid);
}
break;
}
return S_OK;
}
//+----------------------------------------------------------------------------
//
// Function: DirectReportsList
//
// Synopsis: Handles the User Organisation Direct Reports list.
//
//-----------------------------------------------------------------------------
HRESULT
DirectReportsList(CDsPropPageBase * pPage, PATTR_MAP pAttrMap,
PADS_ATTR_INFO pAttrInfo, LPARAM lParam, PATTR_DATA,
DLG_OP DlgOp)
{
//
// Multi-select will result in a return at this point
//
if (pPage->GetObjPathName() == NULL)
{
return S_OK;
}
switch (DlgOp)
{
case fInit:
{
HRESULT hr;
Smart_PADS_ATTR_INFO spAttrs;
DWORD cAttrs = 0;
PWSTR rgpwzAttrNames[] = {pAttrMap->AttrInfo.pszAttrName};
CComPtr <IDirectoryObject> spGcObj;
hr = BindToGCcopyOfObj(pPage, pPage->GetObjPathName(), &spGcObj);
if (SUCCEEDED(hr))
{
hr = spGcObj->GetObjectAttributes(rgpwzAttrNames, 1, &spAttrs, &cAttrs);
if (SUCCEEDED(hr))
{
//
// If the bind to the GC was successful, use those results.
// Otherwise, use the results of the local object read.
//
if (!cAttrs)
{
return S_OK;
}
pAttrInfo = spAttrs;
}
}
if (!pAttrInfo)
{
return S_OK;
}
for (DWORD i = 0; i < pAttrInfo->dwNumValues; i++)
{
PWSTR pwzDns;
hr = CrackName(pAttrInfo->pADsValues[i].DNString, &pwzDns,
GET_OBJ_CAN_NAME_EX, pPage->GetHWnd());
CHECK_HRESULT(hr, return hr);
PTSTR ptz, ptzName;
if (!UnicodeToTchar(pwzDns, &ptz))
{
LocalFreeStringW(&pwzDns);
REPORT_ERROR(E_OUTOFMEMORY, pPage->GetHWnd());
return E_OUTOFMEMORY;
}
LocalFreeStringW(&pwzDns);
ptzName = _tcschr(ptz, TEXT('\n'));
dspAssert(ptzName);
ptzName++;
LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST, LB_ADDSTRING,
0, (LPARAM)ptzName);
if (lresult != LB_ERR)
{
PWSTR pwzDN = new WCHAR[wcslen(pAttrInfo->pADsValues[i].DNString) + 1];
if (pwzDN != NULL)
{
wcscpy(pwzDN, pAttrInfo->pADsValues[i].DNString);
SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
LB_SETITEMDATA, lresult, (LPARAM)pwzDN);
}
}
delete ptz;
}
}
break;
case fOnCommand:
{
if (lParam == LBN_DBLCLK)
{
//
// Retrieve the current selection
//
PWSTR pwzDN = NULL;
LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
LB_GETCURSEL, 0, 0);
if (lresult != LB_ERR)
{
//
// Get the DN associated with the item
//
lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
LB_GETITEMDATA, lresult, 0);
if (lresult != LB_ERR)
{
pwzDN = (PWSTR)lresult;
if (pwzDN != NULL)
{
//
// Launch the secondary proppages
//
PostPropSheet(pwzDN, pPage);
}
}
}
}
}
break;
case fOnDestroy:
{
//
// Must free the memory associated with the list box
//
LRESULT lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
LB_GETCOUNT, 0, 0);
if (lresult != LB_ERR)
{
for (LRESULT idx = lresult - 1 ; idx >= 0; idx--)
{
lresult = SendDlgItemMessage(pPage->GetHWnd(), IDC_REPORTS_LIST,
LB_GETITEMDATA, idx, 0);
if (lresult != LB_ERR)
{
PWSTR pwzDN = (PWSTR)lresult;
if (pwzDN != NULL)
{
delete[] pwzDN;
}
}
}
}
}
break;
default:
break;
}
return S_OK;
}