//+---------------------------------------------------------------------------- // // 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 = 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) { //NTRAID#NTBUG9-572007-2002/03/10-jmessec If Init called multiple times, memory is leaked //NTRAID#NTBUG9-572007-2002/03/10-jmessec If second allocation fails, m_pwszObjPathName points to an uninitialized buffer 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 // //----------------------------------------------------------------------------- BOOL 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)) { 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; }