843 lines
24 KiB
C++
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;
|
|
}
|