459 lines
12 KiB
C++
459 lines
12 KiB
C++
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Windows NT Active Directory Property Page Sample
|
||
|
//
|
||
|
// The code contained in this source file is for demonstration purposes only.
|
||
|
// No warrantee is expressed or implied and Microsoft disclaims all liability
|
||
|
// for the consequenses of the use of this source code.
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1999
|
||
|
//
|
||
|
// File: page.cxx
|
||
|
//
|
||
|
// Contents: CDsPropPage, the class that implements the sample property
|
||
|
// page.
|
||
|
//
|
||
|
// History: 8-Sep-97 Eric Brown created
|
||
|
// 24-Sep-98 " " revised to include notification object.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include "page.h"
|
||
|
|
||
|
WCHAR wzSpendingLimit[] = L"spendingLimit";
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsPropPage::CDsPropPage
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CDsPropPage::CDsPropPage(HWND hNotifyObj) :
|
||
|
m_hPage(NULL),
|
||
|
m_pDsObj(NULL),
|
||
|
m_fInInit(FALSE),
|
||
|
m_fPageDirty(FALSE),
|
||
|
m_pwzObjPathName(NULL),
|
||
|
m_pwzObjClass(NULL),
|
||
|
m_pwzRDName(NULL),
|
||
|
m_hNotifyObj(hNotifyObj),
|
||
|
m_pWritableAttrs(NULL),
|
||
|
m_hrInit(S_OK)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CDsPropPage::~CDsPropPage
|
||
|
//
|
||
|
// Notes: m_pWritableAttrs does not need to be freed. It refers to
|
||
|
// memory held by the notify object and freed when the notify
|
||
|
// object is destroyed.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CDsPropPage::~CDsPropPage()
|
||
|
{
|
||
|
if (m_pDsObj)
|
||
|
{
|
||
|
m_pDsObj->Release();
|
||
|
}
|
||
|
if (m_pwzObjPathName)
|
||
|
{
|
||
|
delete m_pwzObjPathName;
|
||
|
}
|
||
|
if (m_pwzObjClass)
|
||
|
{
|
||
|
delete m_pwzObjClass;
|
||
|
}
|
||
|
if (m_pwzRDName)
|
||
|
{
|
||
|
delete m_pwzRDName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::CreatePage
|
||
|
//
|
||
|
// Sysnopsis: Create the prop page
|
||
|
//
|
||
|
// Notes: if m_hrInit contains a failure code at this point, then an
|
||
|
// error page template could be substituted for the regular one.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CDsPropPage::CreatePage(HPROPSHEETPAGE * phPage)
|
||
|
{
|
||
|
TCHAR szTitle[MAX_PATH];
|
||
|
|
||
|
if (!LoadString(g_hInstance, IDS_PAGE_TITLE, szTitle, MAX_PATH - 1))
|
||
|
{
|
||
|
DWORD dwErr = GetLastError();
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
PROPSHEETPAGE psp;
|
||
|
|
||
|
psp.dwSize = sizeof(PROPSHEETPAGE);
|
||
|
psp.dwFlags = PSP_USECALLBACK | PSP_USETITLE;
|
||
|
psp.pszTemplate = (LPCTSTR)IDD_SAMPLE_PAGE;
|
||
|
psp.pfnDlgProc = (DLGPROC)StaticDlgProc;
|
||
|
psp.pfnCallback = PageCallback;
|
||
|
psp.pcRefParent = NULL; // do not set PSP_USEREFPARENT
|
||
|
psp.lParam = (LPARAM) this;
|
||
|
psp.hInstance = g_hInstance;
|
||
|
psp.pszTitle = L"Spending Limit";
|
||
|
|
||
|
*phPage = CreatePropertySheetPage(&psp);
|
||
|
|
||
|
if (*phPage == NULL)
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::Init
|
||
|
//
|
||
|
// Sysnopsis: Initialize the page object. This is the second part of a two
|
||
|
// phase creation where operations that could fail are located.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CDsPropPage::Init(PWSTR pwzObjName, PWSTR pwzClass)
|
||
|
{
|
||
|
m_pwzObjPathName = new WCHAR[wcslen(pwzObjName) + 1];
|
||
|
if (m_pwzObjPathName == NULL )
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
m_pwzObjClass = new WCHAR[wcslen(pwzClass) + 1];
|
||
|
if (m_pwzObjClass == NULL)
|
||
|
{
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
wcscpy(m_pwzObjPathName, pwzObjName);
|
||
|
wcscpy(m_pwzObjClass, pwzClass);
|
||
|
|
||
|
//
|
||
|
// NOTIFY_OBJ
|
||
|
// Contact the notification object for the initialization info.
|
||
|
//
|
||
|
ADSPROPINITPARAMS InitParams = {0};
|
||
|
|
||
|
InitParams.dwSize = sizeof (ADSPROPINITPARAMS);
|
||
|
|
||
|
if (!ADsPropGetInitInfo(m_hNotifyObj, &InitParams))
|
||
|
{
|
||
|
m_hrInit = E_FAIL;
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
if (FAILED(InitParams.hr))
|
||
|
{
|
||
|
m_hrInit = InitParams.hr;
|
||
|
return m_hrInit;
|
||
|
}
|
||
|
|
||
|
m_pwzRDName = new WCHAR[wcslen(InitParams.pwzCN) + 1];
|
||
|
|
||
|
if (m_pwzRDName == NULL)
|
||
|
{
|
||
|
m_hrInit = E_OUTOFMEMORY;
|
||
|
return E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
m_pDsObj = InitParams.pDsObj;
|
||
|
m_pDsObj->AddRef();
|
||
|
|
||
|
m_pWritableAttrs = InitParams.pWritableAttrs;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: StaticDlgProc
|
||
|
//
|
||
|
// Sysnopsis: static dialog proc
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT CALLBACK
|
||
|
StaticDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CDsPropPage * pPage = (CDsPropPage *)GetWindowLongPtr(hDlg, DWLP_USER);
|
||
|
|
||
|
if (uMsg == WM_INITDIALOG)
|
||
|
{
|
||
|
LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam;
|
||
|
|
||
|
pPage = (CDsPropPage *) ppsp->lParam;
|
||
|
pPage->m_hPage = hDlg;
|
||
|
|
||
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPage);
|
||
|
}
|
||
|
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
pPage->m_fInInit = TRUE;
|
||
|
pPage->OnInitDialog(lParam);
|
||
|
pPage->m_fInInit = FALSE;
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
return pPage->OnCommand(LOWORD(wParam),(HWND)lParam, HIWORD(wParam));
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
return pPage->OnNotify(uMsg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnInitDialog
|
||
|
//
|
||
|
// Sysnopsis: Handles dialog initialization messages
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnInitDialog(LPARAM lParam)
|
||
|
{
|
||
|
PADS_ATTR_INFO pAttrs = NULL;
|
||
|
DWORD cAttrs = 0;
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
//
|
||
|
// NOTIFY_OBJ
|
||
|
// Send the notification object the page's window handle.
|
||
|
//
|
||
|
if (!ADsPropSetHwnd(m_hNotifyObj, m_hPage, NULL))
|
||
|
{
|
||
|
m_pWritableAttrs = NULL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Disable the edit control if the user does not have write permission on
|
||
|
// the attribute.
|
||
|
//
|
||
|
if (!ADsPropCheckIfWritable(wzSpendingLimit, m_pWritableAttrs))
|
||
|
{
|
||
|
EnableWindow(GetDlgItem (m_hPage, IDC_SPENDING_EDIT), FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the attribute value.
|
||
|
//
|
||
|
PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
|
||
|
|
||
|
hr = m_pDsObj->GetObjectAttributes(rgpwzAttrNames, 1, &pAttrs, &cAttrs);
|
||
|
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
// Display an error.
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (cAttrs == 1 && pAttrs->dwNumValues > 0)
|
||
|
{
|
||
|
// Display the value.
|
||
|
//
|
||
|
SetWindowText(GetDlgItem (m_hPage, IDC_SPENDING_EDIT),
|
||
|
pAttrs->pADsValues->CaseIgnoreString);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnNotify
|
||
|
//
|
||
|
// Sysnopsis: Handles notification messages
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnNotify(UINT uMessage, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
switch (((LPNMHDR)lParam)->code)
|
||
|
{
|
||
|
case PSN_APPLY:
|
||
|
|
||
|
if (!m_fPageDirty)
|
||
|
{
|
||
|
return PSNRET_NOERROR;
|
||
|
}
|
||
|
{
|
||
|
LRESULT lResult = OnApply();
|
||
|
// Store the result into the dialog
|
||
|
SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, lResult);
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
case PSN_RESET:
|
||
|
return FALSE; // allow the property sheet to be destroyed.
|
||
|
|
||
|
case PSN_SETACTIVE:
|
||
|
return OnPSNSetActive(lParam);
|
||
|
|
||
|
case PSN_KILLACTIVE:
|
||
|
return OnPSNKillActive(lParam);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnCommand
|
||
|
//
|
||
|
// Sysnopsis: Handles the WM_COMMAND message
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnCommand(int id, HWND hwndCtl, UINT codeNotify)
|
||
|
{
|
||
|
if ((codeNotify == EN_CHANGE) && !m_fInInit)
|
||
|
{
|
||
|
SetDirty();
|
||
|
}
|
||
|
if ((codeNotify == BN_CLICKED) && (id == IDCANCEL))
|
||
|
{
|
||
|
//
|
||
|
// Pressing ESC in a multi-line edit control results in this
|
||
|
// WM_COMMAND being sent. Pass it on to the parent (the sheet proc) to
|
||
|
// close the sheet.
|
||
|
//
|
||
|
PostMessage(GetParent(m_hPage), WM_COMMAND, MAKEWPARAM(id, codeNotify),
|
||
|
(LPARAM)hwndCtl);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnApply
|
||
|
//
|
||
|
// Sysnopsis: Handles the PSN_APPLY notification message
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnApply()
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD cModified;
|
||
|
ADS_ATTR_INFO aAttrs[1];
|
||
|
PADS_ATTR_INFO pAttrs = aAttrs;
|
||
|
WCHAR wzEdit[MAX_PATH];
|
||
|
UINT cch;
|
||
|
ADSVALUE Value;
|
||
|
PWSTR rgpwzAttrNames[] = {wzSpendingLimit};
|
||
|
|
||
|
cch = GetDlgItemText(m_hPage, IDC_SPENDING_EDIT, wzEdit, MAX_PATH);
|
||
|
|
||
|
pAttrs[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
|
||
|
pAttrs[0].pszAttrName = rgpwzAttrNames[0];
|
||
|
|
||
|
if (cch > 0)
|
||
|
{
|
||
|
Value.dwType = ADSTYPE_CASE_IGNORE_STRING;
|
||
|
Value.CaseIgnoreString = wzEdit;
|
||
|
pAttrs[0].pADsValues = &Value;
|
||
|
pAttrs[0].dwNumValues = 1;
|
||
|
pAttrs[0].dwControlCode = ADS_ATTR_UPDATE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pAttrs[0].pADsValues = NULL;
|
||
|
pAttrs[0].dwNumValues = 0;
|
||
|
pAttrs[0].dwControlCode = ADS_ATTR_CLEAR;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Write the changes.
|
||
|
//
|
||
|
hr = m_pDsObj->SetObjectAttributes(pAttrs, 1, &cModified);
|
||
|
|
||
|
//
|
||
|
// NOTIFY_OBJ
|
||
|
// Signal the change notification. Note that the notify-apply
|
||
|
// message must be sent even if the page is not dirty so that the
|
||
|
// notify ref-counting will properly decrement.
|
||
|
//
|
||
|
SendMessage(m_hNotifyObj, WM_ADSPROP_NOTIFY_APPLY, TRUE, 0);
|
||
|
|
||
|
m_fPageDirty = FALSE;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnPSNSetActive
|
||
|
//
|
||
|
// Sysnopsis: Page activation event.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnPSNSetActive(LPARAM lParam)
|
||
|
{
|
||
|
SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::OnPSNKillActive
|
||
|
//
|
||
|
// Sysnopsis: Page deactivation event (when other pages cover this one).
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
LRESULT
|
||
|
CDsPropPage::OnPSNKillActive(LPARAM lParam)
|
||
|
{
|
||
|
SetWindowLongPtr(m_hPage, DWLP_MSGRESULT, 0);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Method: CDsPropPage::PageCallback
|
||
|
//
|
||
|
// Sysnopsis: Callback used to free the CDsPropPage object when the
|
||
|
// property sheet has been destroyed.
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
UINT CALLBACK
|
||
|
CDsPropPage::PageCallback(HWND hDlg, UINT uMsg, LPPROPSHEETPAGE ppsp)
|
||
|
{
|
||
|
|
||
|
if (uMsg == PSPCB_RELEASE)
|
||
|
{
|
||
|
//
|
||
|
// Determine instance that invoked this static function
|
||
|
//
|
||
|
CDsPropPage * pPage = (CDsPropPage *) ppsp->lParam;
|
||
|
|
||
|
if (IsWindow(pPage->m_hNotifyObj))
|
||
|
{
|
||
|
//
|
||
|
// NOTIFY_OBJ
|
||
|
// Tell the notification object to shut down.
|
||
|
//
|
||
|
SendMessage(pPage->m_hNotifyObj, WM_ADSPROP_NOTIFY_EXIT, 0, 0);
|
||
|
}
|
||
|
|
||
|
delete pPage;
|
||
|
|
||
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|