|
|
///////////////////////////////////////////////////////////////////////////////
/* File: adusrdlg.cpp
Description: Provides implementations for the "Add User" dialog.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 08/15/96 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
#include "pch.h" // PCH
#pragma hdrstop
#include <lm.h>
#include "undo.h"
#include "adusrdlg.h"
#include "uihelp.h"
#include "progress.h"
#include "uiutils.h"
//
// Context help IDs.
//
#pragma data_seg(".text", "CODE")
const static DWORD rgAddUserDialogHelpIDs[] = { IDC_ICON_USER, DWORD(-1), IDC_STATIC2, DWORD(-1), IDC_TXT_DEFAULTS, DWORD(-1), IDC_TXT_USERNAME, IDH_TXT_USERNAME, IDC_TXT_SPACEUSED, IDH_TXT_SPACEUSED, IDC_TXT_SPACEREMAINING, IDH_TXT_SPACEREMAINING, IDC_ICON_USERSTATUS, IDH_ICON_USERSTATUS, IDC_RBN_USER_NOLIMIT, IDH_RBN_USER_NOLIMIT, IDC_RBN_USER_LIMIT, IDH_RBN_USER_LIMIT, IDC_TXT_WARN_LEVEL, DWORD(-1), IDC_EDIT_USER_LIMIT, IDH_EDIT_USER_LIMIT, IDC_EDIT_USER_THRESHOLD, IDH_EDIT_USER_THRESHOLD, IDC_CMB_USER_LIMIT, IDH_CMB_USER_LIMIT, IDC_CMB_USER_THRESHOLD, IDH_CMB_USER_THRESHOLD, 0,0 };
#pragma data_seg()
///////////////////////////////////////////////////////////////////////////////
/* Function: AddUserDialog::AddUserDialog
Description: Constructor for a user property sheet object. Initializes the members that hold user quota data.
Arguments: None.
Returns: Nothing.
Exceptions: OutOfMemory.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 08/15/96 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
AddUserDialog::AddUserDialog( PDISKQUOTA_CONTROL pQuotaControl, const CVolumeID& idVolume, HINSTANCE hInstance, HWND hwndParent, HWND hwndDetailsLV, UndoList& UndoList ) : m_cVolumeMaxBytes(0), m_pQuotaControl(pQuotaControl), m_idVolume(idVolume), m_UndoList(UndoList), m_hInstance(hInstance), m_hwndParent(hwndParent), m_hwndDetailsLV(hwndDetailsLV), m_pxbQuotaLimit(NULL), m_pxbQuotaThreshold(NULL), m_llQuotaLimit(0), m_llQuotaThreshold(0), m_pSelectionList(NULL), // Object instance doesn't own this memory.
m_cfSelectionList((CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST)) { DBGASSERT((NULL != m_pQuotaControl)); DBGASSERT((NULL != m_hwndParent)); DBGTRACE((DM_UPROP, DL_HIGH, TEXT("AddUserDialog::AddUserDialog")));
DBGASSERT((0 == iICON_USER_SINGLE)); DBGASSERT((1 == iICON_USER_MULTIPLE)); m_hIconUser[0] = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_SINGLE_USER)); m_hIconUser[1] = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_MULTI_USER)); }
AddUserDialog::~AddUserDialog( VOID ) { DBGTRACE((DM_UPROP, DL_HIGH, TEXT("AddUserDialog::~AddUserDialog"))); INT i = 0;
if (NULL != m_pQuotaControl) m_pQuotaControl->Release();
if (NULL != m_pxbQuotaLimit) delete m_pxbQuotaLimit; if (NULL != m_pxbQuotaThreshold) delete m_pxbQuotaThreshold; }
///////////////////////////////////////////////////////////////////////////////
/* Function: AddUserDialog::Run
Description: Creates and runs the property sheet dialog. This is the only method a client needs to call once the object is created.
Arguments: None.
Returns: NO_ERROR E_FAIL - Couldn't create property sheet.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 08/15/96 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
HRESULT AddUserDialog::Run( VOID ) { //
// Invoke the standard object picker dialog.
//
IDataObject *pdtobj = NULL; HRESULT hr = BrowseForUsers(m_hwndParent, &pdtobj); if (S_OK == hr) { //
// Retrieve the data object representing the selected user objects.
//
FORMATETC fe = { m_cfSelectionList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stg; hr = pdtobj->GetData(&fe, &stg); { //
// Cache the data obj ptr so the dialog can have access.
//
m_pSelectionList = (DS_SELECTION_LIST *)GlobalLock(stg.hGlobal);
if (NULL != m_pSelectionList) { hr = (HRESULT) DialogBoxParam(m_hInstance, MAKEINTRESOURCE(IDD_ADDUSER), m_hwndParent, DlgProc, (LPARAM)this); GlobalUnlock(stg.hGlobal); m_pSelectionList = NULL; } ReleaseStgMedium(&stg); } pdtobj->Release(); } return hr;
}
///////////////////////////////////////////////////////////////////////////////
/* Function: AddUserDialog::DlgProc
Description: Static method called by windows to process messages for the property page dialog. Since it's static, we have to save the "this" pointer in the window's USERDATA.
Arguments: Standard WndProc-type arguments.
Returns: Standard WndProc-type return values.
Revision History:
Date Description Programmer -------- --------------------------------------------------- ---------- 08/15/96 Initial creation. BrianAu */ ///////////////////////////////////////////////////////////////////////////////
INT_PTR CALLBACK AddUserDialog::DlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { INT_PTR bResult = FALSE;
//
// Retrieve the "this" pointer from the dialog's userdata.
// It was placed there in OnInitDialog().
//
AddUserDialog *pThis = (AddUserDialog *)GetWindowLongPtr(hDlg, DWLP_USER);
try { switch(message) { case WM_INITDIALOG: DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_INITDIALOG"))); pThis = (AddUserDialog *)lParam; DBGASSERT((NULL != pThis)); //
// Save "this" in the window's userdata.
//
SetWindowLongPtr(hDlg, DWLP_USER, (INT_PTR)pThis); bResult = pThis->OnInitDialog(hDlg, wParam, lParam); break;
case WM_COMMAND: DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_COMMAND"))); bResult = pThis->OnCommand(hDlg, wParam, lParam); break;
case WM_CONTEXTMENU: bResult = pThis->OnContextMenu((HWND)wParam, LOWORD(lParam), HIWORD(lParam)); break;
case WM_HELP: DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_HELP"))); bResult = pThis->OnHelp(hDlg, wParam, lParam); break;
case WM_DESTROY: DBGPRINT((DM_WND, DL_MID, TEXT("DlgProc: WM_DESTROY"))); break;
default: break; }
} catch(CAllocException& e) { DiskQuotaMsgBox(GetDesktopWindow(), IDS_OUTOFMEMORY, IDS_TITLE_DISK_QUOTA, MB_ICONERROR | MB_OK); }
return bResult; }
INT_PTR AddUserDialog::OnInitDialog( HWND hDlg, WPARAM wParam, LPARAM lParam ) { HRESULT hResult = NO_ERROR;
DWORD dwSectorsPerCluster = 0; DWORD dwBytesPerSector = 0; DWORD dwFreeClusters = 0; DWORD dwTotalClusters = 0;
//
// The "new user" dialog is initialized with the volume's default quota
// limit and threshold for new users.
//
m_pQuotaControl->GetDefaultQuotaLimit(&m_llQuotaLimit); m_pQuotaControl->GetDefaultQuotaThreshold(&m_llQuotaThreshold);
//
// Configure the Limit/NoLimit radio buttons.
//
if (NOLIMIT == m_llQuotaThreshold) { CheckDlgButton(hDlg, IDC_RBN_USER_LIMIT, FALSE); CheckDlgButton(hDlg, IDC_RBN_USER_NOLIMIT, TRUE); } else { CheckDlgButton(hDlg, IDC_RBN_USER_LIMIT, TRUE); CheckDlgButton(hDlg, IDC_RBN_USER_NOLIMIT, FALSE); }
//
// Calculate the volume's size.
// We'll use this to limit user threshold and quota limit entries.
//
if (GetDiskFreeSpace(m_idVolume.ForParsing(), &dwSectorsPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) { m_cVolumeMaxBytes = (LONGLONG)dwSectorsPerCluster * (LONGLONG)dwBytesPerSector * (LONGLONG)dwTotalClusters; }
m_pxbQuotaLimit = new XBytes(hDlg, IDC_EDIT_USER_LIMIT, IDC_CMB_USER_LIMIT, m_llQuotaLimit);
m_pxbQuotaLimit->SetBytes(m_llQuotaLimit);
m_pxbQuotaThreshold = new XBytes(hDlg, IDC_EDIT_USER_THRESHOLD, IDC_CMB_USER_THRESHOLD, m_llQuotaThreshold);
m_pxbQuotaThreshold->SetBytes(m_llQuotaThreshold);
DBGASSERT((0 < m_pSelectionList->cItems)); if (1 == m_pSelectionList->cItems) { SetDlgItemText(hDlg, IDC_TXT_USERNAME, GetDsSelUserName(m_pSelectionList->aDsSelection[0])); } else { CString strMultiple(m_hInstance, IDS_MULTIPLE); SetDlgItemText(hDlg, IDC_TXT_USERNAME, strMultiple); }
SendMessage(GetDlgItem(hDlg, IDC_ICON_USER), STM_SETICON, (WPARAM)m_hIconUser[1 == m_pSelectionList->cItems ? iICON_USER_SINGLE : iICON_USER_MULTIPLE], 0);
return TRUE; // Set focus to default control.
}
//
// The Object Picker scope definition structure looks like this
// JeffreyS created these helper macros for working with the object picker
// in the ACLEDIT security UI. Thanks Jeff!
//
#if 0
{ // DSOP_SCOPE_INIT_INFO
cbSize, flType, flScope, { // DSOP_FILTER_FLAGS
{ // DSOP_UPLEVEL_FILTER_FLAGS
flBothModes, flMixedModeOnly, flNativeModeOnly }, flDownlevel }, pwzDcName, pwzADsPath, hr // OUT
} #endif
//
// macro for declaring one of the above
//
#define DECLARE_SCOPE(t,f,b,m,n,d) \
{ sizeof(DSOP_SCOPE_INIT_INFO), (t), (f), { { (b), (m), (n) }, (d) }, NULL, NULL, S_OK }
#define COMMON_SCOPE_FLAGS (DSOP_SCOPE_FLAG_WANT_PROVIDER_LDAP | DSOP_SCOPE_FLAG_WANT_SID_PATH)
#define TARGET_COMPUTER_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_TARGET_COMPUTER, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define JOINED_UPLEVEL_DOMAIN_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN, \ COMMON_SCOPE_FLAGS | DSOP_SCOPE_FLAG_STARTING_SCOPE, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define JOINED_DOWNLEVEL_DOMAIN_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define ENTERPRISE_DOMAIN_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define EXTERNAL_UPLEVEL_DOMAIN_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define EXTERNAL_DOWNLEVEL_DOMAIN_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define GLOBAL_CATALOG_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_GLOBAL_CATALOG, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
#define WORKGROUP_SCOPE \
DECLARE_SCOPE( \ DSOP_SCOPE_TYPE_WORKGROUP, \ COMMON_SCOPE_FLAGS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_FILTER_USERS, \ DSOP_DOWNLEVEL_FILTER_USERS)
//
// Invokes the standard DS object picker dialog.
// Returns a list of DS_SELECTION structures in a data object
// representing the selected user objects.
//
HRESULT AddUserDialog::BrowseForUsers( HWND hwndParent, IDataObject **ppdtobj ) { DBGASSERT((NULL != hwndParent)); DBGASSERT((NULL != ppdtobj));
*ppdtobj = NULL;
IDsObjectPicker *pop = NULL; HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void **)&pop); if (SUCCEEDED(hr)) { //
// This array initializes the scopes of the DS object picker.
// The first entry is the "default" scope.
//
DSOP_SCOPE_INIT_INFO rgdsii[] = { JOINED_UPLEVEL_DOMAIN_SCOPE, JOINED_DOWNLEVEL_DOMAIN_SCOPE, ENTERPRISE_DOMAIN_SCOPE, EXTERNAL_UPLEVEL_DOMAIN_SCOPE, EXTERNAL_DOWNLEVEL_DOMAIN_SCOPE, GLOBAL_CATALOG_SCOPE, WORKGROUP_SCOPE, TARGET_COMPUTER_SCOPE };
DSOP_INIT_INFO dii; dii.cbSize = sizeof(dii); dii.pwzTargetComputer = NULL; dii.cDsScopeInfos = ARRAYSIZE(rgdsii); dii.aDsScopeInfos = rgdsii; dii.flOptions = DSOP_FLAG_MULTISELECT; dii.cAttributesToFetch = 0; dii.apwzAttributeNames = NULL; //
// Init and run the object picker dialog.
//
hr = pop->Initialize(&dii); if (SUCCEEDED(hr)) { hr = pop->InvokeDialog(hwndParent, ppdtobj); } pop->Release(); }
return hr; }
INT_PTR AddUserDialog::OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam ) { DWORD dwCtlId = LOWORD(wParam); HWND hWndCtl = (HWND)lParam; DWORD dwNotifyCode = HIWORD(wParam); INT_PTR bResult = FALSE;
switch(dwCtlId) { case IDC_RBN_USER_NOLIMIT: if (m_pxbQuotaThreshold->IsEnabled()) { //
// This is simple. Just set both the limit and threshold controls
// to "no limit".
//
m_pxbQuotaThreshold->SetBytes(NOLIMIT); m_pxbQuotaLimit->SetBytes(NOLIMIT); } break;
case IDC_RBN_USER_LIMIT: if (!m_pxbQuotaThreshold->IsEnabled()) { LONGLONG llValue = 0; m_pQuotaControl->GetDefaultQuotaLimit(&llValue); m_pxbQuotaLimit->SetBytes(NOLIMIT == llValue ? 0 : llValue);
llValue = 0; m_pQuotaControl->GetDefaultQuotaThreshold(&llValue); m_pxbQuotaThreshold->SetBytes(NOLIMIT == llValue ? 0 : llValue); } break;
case IDC_EDIT_USER_LIMIT: case IDC_EDIT_USER_THRESHOLD: switch(dwNotifyCode) { case EN_UPDATE: bResult = OnEditNotifyUpdate(hDlg, wParam, lParam); break;
default: break; } break;
case IDC_CMB_USER_LIMIT: case IDC_CMB_USER_THRESHOLD: switch(dwNotifyCode) { case CBN_SELCHANGE: bResult = OnComboNotifySelChange(hDlg, wParam, lParam); break;
default: break; } break;
case IDOK: if (!OnOk(hDlg, wParam, lParam)) return FALSE; //
// Fall through...
//
case IDCANCEL: EndDialog(hDlg, 0); break;
default: bResult = TRUE; // Didn't handle message.
break; }
return bResult; }
INT_PTR AddUserDialog::OnOk( HWND hDlg, WPARAM wParam, LPARAM lParam ) { HRESULT hResult = NO_ERROR;
//
// We need to do this because if you activate the OK button
// with [Return] we receive the WM_COMMAND before EN_KILLFOCUS.
//
m_pxbQuotaThreshold->OnEditKillFocus((LPARAM)GetDlgItem(hDlg, IDC_EDIT_USER_THRESHOLD)); m_pxbQuotaLimit->OnEditKillFocus((LPARAM)GetDlgItem(hDlg, IDC_EDIT_USER_LIMIT));
//
// Ensure warning threshold is not above limit.
//
INT64 iThreshold = m_pxbQuotaThreshold->GetBytes(); INT64 iLimit = m_pxbQuotaLimit->GetBytes();
if (NOLIMIT != iLimit && iThreshold > iLimit) { TCHAR szLimit[40], szThreshold[40]; XBytes::FormatByteCountForDisplay(iLimit, szLimit, ARRAYSIZE(szLimit)); XBytes::FormatByteCountForDisplay(iThreshold, szThreshold, ARRAYSIZE(szThreshold));
CString s(m_hInstance, IDS_FMT_ERR_WARNOVERLIMIT, szThreshold, szLimit, szLimit); switch(DiskQuotaMsgBox(hDlg, s, IDS_TITLE_DISK_QUOTA, MB_ICONWARNING | MB_YESNO)) { case IDYES: m_pxbQuotaThreshold->SetBytes(iLimit); break;
case IDNO: //
// Set focus to threshold edit box so user can correct
// the entry. Return early with FALSE value.
//
SetFocus(GetDlgItem(hDlg, IDC_EDIT_USER_THRESHOLD)); SendMessage(GetDlgItem(hDlg, IDC_EDIT_USER_THRESHOLD), EM_SETSEL, 0, -1); return FALSE; } }
//
// Only apply settings if the "Apply" button is enabled indicating
// that something has been changed. No need to apply unchanged
// settings when the OK button is pressed.
//
hResult = ApplySettings(hDlg); if (FAILED(hResult)) { INT idMsg = IDS_UNKNOWN_ERROR; UINT uFlags = MB_OK; switch(hResult) { case E_FAIL: idMsg = IDS_WRITE_ERROR; uFlags |= MB_ICONERROR; break;
default: switch(HRESULT_CODE(hResult)) {
// case ERROR_USER_EXISTS:
// idMsg = IDS_NOADD_EXISTING_USER;
// uFlags |= MB_ICONWARNING;
// break;
//
// Still valid? [brianau - 5/27/98]
//
case ERROR_NO_SUCH_USER: idMsg = IDS_NOADD_UNKNOWN_USER; uFlags |= MB_ICONWARNING; break;
case ERROR_ACCESS_DENIED: idMsg = IDS_NO_WRITE_ACCESS; uFlags |= MB_ICONWARNING; break;
default: uFlags |= MB_ICONERROR; break; } break; } DiskQuotaMsgBox(GetDesktopWindow(), idMsg, IDS_TITLE_DISK_QUOTA, uFlags); } return TRUE; }
INT_PTR AddUserDialog::OnHelp( HWND hDlg, WPARAM wParam, LPARAM lParam ) { WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, STR_DSKQUOUI_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPTSTR) rgAddUserDialogHelpIDs); return TRUE; }
INT_PTR AddUserDialog::OnContextMenu( HWND hwndItem, int xPos, int yPos ) { int idCtl = GetDlgCtrlID(hwndItem); WinHelp(hwndItem, UseWindowsHelp(idCtl) ? NULL : STR_DSKQUOUI_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)((LPTSTR)rgAddUserDialogHelpIDs));
return FALSE; }
INT_PTR AddUserDialog::OnEditNotifyUpdate( HWND hDlg, WPARAM wParam, LPARAM lParam ) { XBytes *pxb = NULL;
switch(LOWORD(wParam)) { case IDC_EDIT_USER_LIMIT: pxb = m_pxbQuotaLimit; break;
case IDC_EDIT_USER_THRESHOLD: pxb = m_pxbQuotaThreshold; break;
default: break; }
if (NULL != pxb) pxb->OnEditNotifyUpdate(lParam);
return FALSE; }
INT_PTR AddUserDialog::OnComboNotifySelChange( HWND hDlg, WPARAM wParam, LPARAM lParam ) { XBytes *pxb = NULL;
switch(LOWORD(wParam)) { case IDC_CMB_USER_LIMIT: pxb = m_pxbQuotaLimit; break;
case IDC_CMB_USER_THRESHOLD: pxb = m_pxbQuotaThreshold; break;
default: break; } if (NULL != pxb) pxb->OnComboNotifySelChange(lParam);
return FALSE; }
//
// Retrieve from a DS_SELECTION structure the name to display for
// a user object.
//
LPCWSTR AddUserDialog::GetDsSelUserName( const DS_SELECTION& sel ) { return sel.pwzUPN && *sel.pwzUPN ? sel.pwzUPN : sel.pwzName; }
//
// Convert two hex chars into a single byte value.
// Assumes input string is in upper case.
//
HRESULT AddUserDialog::HexCharsToByte( LPTSTR pszByteIn, LPBYTE pbOut ) { static const int iShift[] = { 4, 0 };
*pbOut = (BYTE)0; for (int i = 0; i < 2; i++) { TCHAR ch = *(pszByteIn + i); BYTE b = (BYTE)0; if (TEXT('0') <= ch && TEXT('9') >= ch) { b = ch - TEXT('0'); } else if (TEXT('A') <= ch && TEXT('F') >= ch) { b = 10 + (ch - TEXT('A')); } else { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); }
*pbOut |= (b << iShift[i]); } return NOERROR; }
//
// Returns:
//
// NOERROR
// ERROR_INSUFFICIENT_BUFFER (as hresult)
// ERROR_INVALID_DATA (as hresult)
//
HRESULT AddUserDialog::GetDsSelUserSid( const DS_SELECTION& sel, LPBYTE pbSid, int cbSid ) { static const WCHAR szPrefix[] = L"LDAP://<SID="; static const WCHAR chTerm = L'>';
HRESULT hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); LPWSTR pszLDAP = CharUpper(sel.pwzADsPath); if (NULL != pszLDAP) { int cb = 0;
//
// First check for the required prefix.
//
if (0 == StrCmpNW(pszLDAP, szPrefix, ARRAYSIZE(szPrefix) - 1)) { hr = NOERROR; //
// Advance ptr beyond prefix and convert the hex string
// into a SID. Process chars until we hit a '>'.
//
pszLDAP += ARRAYSIZE(szPrefix) - 1;
while(SUCCEEDED(hr) && *pszLDAP && chTerm != *pszLDAP) { if (0 < cbSid--) { hr = HexCharsToByte(pszLDAP, pbSid++); pszLDAP += 2; } else hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } if (SUCCEEDED(hr) && chTerm != *pszLDAP) hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); } }
if (FAILED(hr)) { //
// FEATURE: This can be removed once I'm comfortable that all
// ADs paths returned from the object picker contain
// a SID.
//
DBGERROR((TEXT("GetDsSelUserSid returning hr = 0x%08X for path \"%s\""), hr, sel.pwzADsPath)); }
return hr; }
HRESULT AddUserDialog::ApplySettings( HWND hDlg, bool bUndo ) { HRESULT hResult = E_FAIL; int cUsers = m_pSelectionList->cItems; CAutoWaitCursor wait_cursor;
//
// Retrieve limit and threshold values from dialog controls.
//
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_RBN_USER_NOLIMIT)) { m_llQuotaThreshold = NOLIMIT; m_llQuotaLimit = NOLIMIT; } else { m_llQuotaThreshold = m_pxbQuotaThreshold->GetBytes(); m_llQuotaLimit = m_pxbQuotaLimit->GetBytes(); }
if (bUndo) m_UndoList.Clear();
ProgressDialog dlgProgress(IDD_PROGRESS, IDC_PROGRESS_BAR, IDC_TXT_PROGRESS_DESCRIPTION, IDC_TXT_PROGRESS_FILENAME); if (2 < cUsers) { //
// Create and display a progress dialog if we're adding more than 2
// users.
//
HWND hwndParent = IsWindowVisible(hDlg) ? hDlg : GetParent(hDlg); if (dlgProgress.Create(m_hInstance, hwndParent)) { dlgProgress.ProgressBarInit(0, cUsers, 1); dlgProgress.SetDescription(MAKEINTRESOURCE(IDS_PROGRESS_ADDUSER)); dlgProgress.Show(); } }
bool bCancelled = false; for (int i = 0; i < cUsers && !bCancelled; i++) { DS_SELECTION *pdss = &(m_pSelectionList->aDsSelection[i]); LPCWSTR pwzName = GetDsSelUserName(*pdss);
//
// Add a user to the quota file. This will add it using the defaults
// for new users. We get back an interface to the new user object.
// Also specify async name resolution.
//
if (NULL == pwzName) { dlgProgress.ProgressBarAdvance(); continue; }
dlgProgress.SetFileName(pwzName);
com_autoptr<DISKQUOTA_USER> ptrUser; DiskQuotaControl *pDQC = static_cast<DiskQuotaControl *>(m_pQuotaControl);
BYTE sid[MAX_SID_LEN]; hResult = GetDsSelUserSid(*pdss, sid, ARRAYSIZE(sid)); if (SUCCEEDED(hResult)) { hResult = pDQC->AddUserSid(sid, DISKQUOTA_USERNAME_RESOLVE_ASYNC, ptrUser.getaddr());
if (SUCCEEDED(hResult)) { if (S_FALSE == hResult) { hResult = HRESULT_FROM_WIN32(ERROR_USER_EXISTS); } else { if (SUCCEEDED(hResult = ptrUser->SetQuotaLimit(m_llQuotaLimit, TRUE)) && SUCCEEDED(hResult = ptrUser->SetQuotaThreshold(m_llQuotaThreshold, TRUE))) { if (bUndo) { //
// Create local autoptrs to ensure iface release if an
// exception is thrown.
//
com_autoptr<DISKQUOTA_CONTROL> ptrQuotaControl(m_pQuotaControl); com_autoptr<DISKQUOTA_USER> ptrQuotaUser(ptrUser);
ptrQuotaUser->AddRef(); ptrQuotaControl->AddRef();
autoptr<UndoAdd> ptrUndoAdd = new UndoAdd(ptrUser, m_pQuotaControl);
m_UndoList.Add(ptrUndoAdd); //
// Undo list now owns the action object.
//
ptrUndoAdd.disown();
//
// Successfully added to undo list. Disown real ptrs so
// ref count stays with undo list. If an exception was
// thrown, the local com_autoptr objects will automatically
// release the interfaces.
//
ptrQuotaUser.disown(); ptrQuotaControl.disown(); }
//
// Add the user to the listview.
//
SendMessage(m_hwndDetailsLV, WM_ADD_USER_TO_DETAILS_VIEW, 0, (LPARAM)ptrUser.get()); //
// iface pointer added to listview. autoptr disowns the real
// pointer so the autoptr's dtor doesn't release it.
//
ptrUser.disown(); } } } } if (FAILED(hResult)) { INT idMsg = IDS_UNKNOWN_ERROR; UINT uFlags = MB_OKCANCEL; switch(hResult) { case E_FAIL: idMsg = IDS_WRITE_ERROR; uFlags |= MB_ICONERROR; break;
default: switch(HRESULT_CODE(hResult)) { case ERROR_USER_EXISTS: idMsg = IDS_NOADD_EXISTING_USER; uFlags |= MB_ICONWARNING; break;
case ERROR_NO_SUCH_USER: idMsg = IDS_NOADD_UNKNOWN_USER; uFlags |= MB_ICONWARNING; break;
case ERROR_ACCESS_DENIED: idMsg = IDS_NO_WRITE_ACCESS; uFlags |= MB_ICONWARNING; break;
default: uFlags |= MB_ICONERROR; break; } break; }
//
// Display message box with msg formatted as:
//
// The user already exists and could not be added.
//
// User: brianau
// In Folder: Domain/Folder: ntdev.microsoft.com/US SOS-...
//
CString strError(m_hInstance, idMsg); CString strMsg(m_hInstance, IDS_FMT_ERR_ADDUSER, strError.Cstr(), pwzName);
HWND hwndMsgBoxParent = (NULL != dlgProgress.m_hWnd && IsWindowVisible(dlgProgress.m_hWnd)) ? dlgProgress.m_hWnd : hDlg;
if (IDCANCEL == DiskQuotaMsgBox(hwndMsgBoxParent, strMsg.Cstr(), IDS_TITLE_DISK_QUOTA, uFlags)) { bCancelled = true; } } dlgProgress.ProgressBarAdvance(); bCancelled = bCancelled || dlgProgress.UserCancelled(); }
return NOERROR; }
|