/*++ Copyright (C) Microsoft Corporation, 1998 - 1999 All rights reserved. Module Name: locprop.cxx Abstract: Server Properties Author: Steve Kiraly (SteveKi) 09/08/98 Lazar Ivanov (LazarI) Nov-28-2000 - validation Revision History: --*/ #include "precomp.hxx" #pragma hdrstop #include "dsinterf.hxx" #include "locprop.hxx" #include "findloc.hxx" #include "physloc.hxx" #define INVALID_RESOURCE_ID ((UINT )-1) TLocationPropertySheetFrontEnd:: TLocationPropertySheetFrontEnd( IN IShellPropSheetExt *pShellPropSheetExt, IN LPDATAOBJECT lpdobj, IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam ) : _bValid( FALSE ), _pShellPropSheetExt( pShellPropSheetExt ), _lpdobj( lpdobj ), _pLocation( NULL ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::TLocationPropertySheetFrontEnd\n" ) ); if( AddPropertyPages( lpfnAddPage, lParam ) ) { _bValid = TRUE; } } TLocationPropertySheetFrontEnd:: ~TLocationPropertySheetFrontEnd( VOID ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::~TLocationPropertySheetFrontEnd\n" ) ); delete _pLocation; } BOOL TLocationPropertySheetFrontEnd:: bValid( VOID ) const { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::bValid\n" ) ); return _bValid; } HRESULT TLocationPropertySheetFrontEnd:: Create( IN OUT TLocationPropertySheetFrontEnd **ppPropertySheet, IN IShellPropSheetExt *pShellPropSheetExt, IN LPDATAOBJECT lpdobj, IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::Create\n" ) ); HRESULT hr = S_OK; *ppPropertySheet = new TLocationPropertySheetFrontEnd (pShellPropSheetExt, lpdobj, lpfnAddPage, lParam); if (!VALID_PTR(*ppPropertySheet)) { Destroy (ppPropertySheet); hr = E_FAIL; } return hr; } VOID TLocationPropertySheetFrontEnd:: Destroy( IN OUT TLocationPropertySheetFrontEnd **ppPropertySheet ) { if (*ppPropertySheet) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::Destroy\n" ) ); delete *ppPropertySheet; *ppPropertySheet = NULL; } } BOOL TLocationPropertySheetFrontEnd:: AddPropertyPages( IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::AddPropertyPages\n" ) ); BOOL bRetval = TRUE; if( bRetval ) { _pLocation = new TLocationPropertySheet( _pShellPropSheetExt, _lpdobj ); if( VALID_PTR( _pLocation ) ) { bRetval = CreatePropertyPage( lpfnAddPage, lParam, _pLocation, _pLocation->uGetResourceTemplateID() ); } } return bRetval; } BOOL TLocationPropertySheetFrontEnd:: CreatePropertyPage( IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam, IN MGenericProp *pPage, IN UINT Template ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheetFrontEnd::CreatePropertyPage\n" ) ); // // Ensure the page pointer and page object is valid. // BOOL bRetval = VALID_PTR( pPage ); if( bRetval ) { PROPSHEETPAGE psp = {0}; psp.dwSize = sizeof( psp ); psp.dwFlags = PSP_DEFAULT | PSP_USEREFPARENT | PSP_USECALLBACK | PSP_PREMATURE; psp.hInstance = ghInst; psp.pfnDlgProc = MGenericProp::SetupDlgProc; psp.pfnCallback = MGenericProp::CallbackProc; psp.pcRefParent = reinterpret_cast( &gcRefThisDll ); psp.pszTemplate = MAKEINTRESOURCE( Template ); psp.lParam = reinterpret_cast( pPage ); // // Create the actual page and get the pages handle. // HPROPSHEETPAGE hPage = ::CreatePropertySheetPage( &psp ); // // Add the page to the property sheet. // if( hPage && lpfnAddPage( hPage, lParam ) ) { if( _pShellPropSheetExt ) { _pShellPropSheetExt->AddRef(); } } else { // // We could not add the page, remember to destroy the handle // if( hPage ) { ::DestroyPropertySheetPage (hPage); } bRetval = FALSE; } } return bRetval; } /******************************************************************** Location property sheet. ********************************************************************/ TLocationPropertySheet:: TLocationPropertySheet( IN IShellPropSheetExt *pShellPropSheetExt, IN IDataObject *pdobj ) : _pShellPropSheetExt( pShellPropSheetExt ), _bValid( FALSE ), _cfDsObjectNames( 0 ), _pDsObject( NULL ), _uLocationEditID( INVALID_RESOURCE_ID ), _uBrowseID( INVALID_RESOURCE_ID ), _PropertyAccess( kPropertyAccessNone ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheet::TLocationPropertySheet\n" ) ); TStatusB bStatus; // // Ensure the ds interface object is in a valid state. // if( VALID_OBJ( _Ds ) ) { // // Initialize the ds object clipboard format. // bStatus DBGCHK = InitializeDsObjectClipboardFormat(); if( bStatus ) { // // Get the ds object name. // bStatus DBGCHK = GetDsObjectNameFromIDataObject( pdobj, _strDsObjectName, _strDsObjectClass ); if( bStatus ) { DBGMSG( DBG_TRACE, ( "DsObjectName " TSTR "\n", (LPCTSTR)_strDsObjectName ) ); DBGMSG( DBG_TRACE, ( "DsObjectClass " TSTR "\n", (LPCTSTR)_strDsObjectClass ) ); // // Computer location page will have different resource // template in order to have different control IDs and // thereafter different help IDs. // _uBrowseID = IDC_BROWSE_PHYSICAL_LOCATION; if( !_tcsicmp( _strDsObjectClass, gszComputer ) ) { _uLocationEditID = IDC_PHYSICAL_COMPUTER_LOCATION; } else { _uLocationEditID = IDC_PHYSICAL_LOCATION; } // // Get the objects interface. // bStatus DBGCHK = GetObjectInterface( _strDsObjectName, &_pDsObject ); if( bStatus ) { // // Check our current access priviliges. None, Read, Read|Write // bStatus DBGCHK = CheckPropertyAccess( gszLocation, _PropertyAccess ); // // If were able to determine our access and we have at least read // access then display the property sheet. // if( bStatus && ( _PropertyAccess != kPropertyAccessNone ) ) { // // If we get here every this is ok, ready to display the page. // _bValid = TRUE; } } } } } } TLocationPropertySheet:: ~TLocationPropertySheet( VOID ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheet::~TLocationPropertySheet\n" ) ); // // Release the adsi interface, if aquired. // if( _pDsObject ) { _pDsObject->Release(); } } BOOL TLocationPropertySheet:: bValid( VOID ) const { return _bValid; } UINT TLocationPropertySheet:: uGetResourceTemplateID( VOID ) const { UINT uDefTemplateID = DLG_PRINTER_LOCATION; // // Computer location page will have different resource // template in order to have different control IDs and // different help IDs. // if( !_tcsicmp( _strDsObjectClass, gszComputer ) ) { uDefTemplateID = DLG_COMPUTER_LOCATION; } return uDefTemplateID; } VOID TLocationPropertySheet:: vDestroy( VOID ) { // // This fuction is called from the property sheet callback when the // sheet is destroyed. // if( _pShellPropSheetExt ) { _pShellPropSheetExt->Release(); } } BOOL TLocationPropertySheet:: InitializeDsObjectClipboardFormat( VOID ) { // // If the clipboard format has not been registred then do it now. // if( !_cfDsObjectNames ) { _cfDsObjectNames = RegisterClipboardFormat( CFSTR_DSOBJECTNAMES ); } return _cfDsObjectNames != 0; } BOOL TLocationPropertySheet:: GetDsObjectNameFromIDataObject( IN IDataObject *pdobj, IN TString &strDsObjectName, IN TString &strDsObjectClass ) { HRESULT hr = E_FAIL; TStatusB bStatus; if( pdobj ) { STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)_cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; hr = pdobj->GetData(&formatetc, &stgmedium); if (SUCCEEDED(hr)) { LPDSOBJECTNAMES pDsObjectNames = reinterpret_cast( stgmedium.hGlobal ); hr = pDsObjectNames ? S_OK : E_FAIL; if( SUCCEEDED(hr) ) { if( pDsObjectNames->cItems == 1 ) { bStatus DBGCHK = strDsObjectName.bUpdate( ByteOffset( pDsObjectNames, pDsObjectNames->aObjects[0].offsetName ) ); if( bStatus ) { bStatus DBGCHK = strDsObjectClass.bUpdate( ByteOffset( pDsObjectNames, pDsObjectNames->aObjects[0].offsetClass ) ); } hr = bStatus ? S_OK : E_FAIL; } else { hr = E_FAIL; } } ReleaseStgMedium(&stgmedium); } } return SUCCEEDED(hr); } BOOL TLocationPropertySheet:: CheckPropertyAccess( IN LPCTSTR pszPropertyName, IN EPropertyAccess &Access ) { DBGMSG( DBG_TRACE, ( "TLocationPropertySheet::CheckPropertyAccess\n" ) ); // // Assume no access. // Access = kPropertyAccessNone; // // Need a directory object interface to query for the effective attributes. // IDirectoryObject *pDsObj = NULL; // // Get the directory object interface. // HRESULT hr = ADsOpenObject( const_cast( static_cast(_strDsObjectName)), NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject, reinterpret_cast( &pDsObj ) ); if( SUCCEEDED(hr) ) { DWORD cAttrs = 0; PADS_ATTR_INFO pAttrs = NULL; LPCTSTR szNames[2] = {gszName, gszAllowed}; // // Query for this objects attributes. // hr = pDsObj->GetObjectAttributes( (LPTSTR*)szNames, 2, &pAttrs, &cAttrs ); if( SUCCEEDED(hr) ) { // // The object was opened and we were able to read the attributes then // We assume we have read access. // Access = kPropertyAccessRead; for (UINT i = 0; i < cAttrs; i++) { DBGMSG( DBG_TRACE, ( "Allowed Name " TSTR "\n", pAttrs[i].pszAttrName ) ); if (!_tcsicmp( pAttrs[i].pszAttrName, gszAllowed )) { for (UINT j = 0; j < pAttrs[i].dwNumValues; j++) { DBGMSG( DBG_TRACE, ( "Allowed attribute (effective): %d " TSTR "\n", pAttrs[i].pADsValues[j].dwType, pAttrs[i].pADsValues[j].CaseIgnoreString ) ); if (!_tcsicmp( pAttrs[i].pADsValues[j].CaseIgnoreString, gszLocation )) { // // We found the location property in the attribute list, // by this fact we now know we can write this property. // Access = kPropertyAccessWrite; } } } } // // Release the writeable attribute memory. // if( pAttrs ) { FreeADsMem( pAttrs ); } } // // Release the directory object interface. // pDsObj->Release(); } return TRUE; } LPTSTR TLocationPropertySheet:: ByteOffset( IN LPDSOBJECTNAMES pObject, IN UINT uOffset ) { return reinterpret_cast( reinterpret_cast( pObject ) + uOffset ); } BOOL TLocationPropertySheet:: bHandleMessage( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { BOOL bRetval; switch( uMsg ) { case WM_INITDIALOG: bRetval = Handle_InitDialog( wParam, lParam ); break; case WM_COMMAND: bRetval = Handle_Command( wParam, lParam ); break; case WM_NOTIFY: bRetval = Handle_Notify( wParam, lParam ); vSetDlgMsgResult( bRetval ); break; case WM_HELP: bRetval = Handle_Help( uMsg, wParam, lParam ); break; case WM_CONTEXTMENU: bRetval = Handle_Help( uMsg, wParam, lParam ); break; default: bRetval = FALSE; break; } return bRetval; } BOOL TLocationPropertySheet:: Handle_InitDialog( IN WPARAM wParam, IN LPARAM lParam ) { TStatusB bStatus; // // Get the location property from the object. We ignore the return // value because the Get will fail if the property is not set. // bStatus DBGCHK = _Ds.Get( _pDsObject, gszLocation, _strLocation ); // // // If we have write access then allow browsing the location tree, // otherwise disable the button // if( (kPropertyAccessWrite != _PropertyAccess) || !TPhysicalLocation::bLocationEnabled() ) { EnableWindow( GetDlgItem(_hDlg, _uBrowseID), FALSE ); } // // Set the location text in the UI. // bStatus DBGCHK = bSetEditText( _hDlg, _uLocationEditID, _strLocation ); // // If we only have read access to the location property then // set the location edit control to read only. // if( _PropertyAccess == kPropertyAccessRead ) { SendDlgItemMessage( _hDlg, _uLocationEditID, EM_SETREADONLY, TRUE, 0); } // // Set the location limit text. // SendDlgItemMessage( _hDlg, _uLocationEditID, EM_SETLIMITTEXT, kPrinterLocationBufMax, 0 ); return TRUE; } BOOL TLocationPropertySheet:: Handle_Help( IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { PrintUIHelp( uMsg, _hDlg, wParam, lParam ); return TRUE; } BOOL TLocationPropertySheet:: Handle_Command( IN WPARAM wParam, IN LPARAM lParam ) { BOOL bRetval = TRUE; UINT uID = GET_WM_COMMAND_ID( wParam, lParam ); if( uID == _uLocationEditID ) { // // If the user changed the text in the location edit control then // enable the apply button. // if( GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE ) { PropSheet_Changed( GetParent( _hDlg ), _hDlg ); } } else if( uID == _uBrowseID ) { BrowseLocations (); } else { bRetval = FALSE; } return bRetval; } BOOL TLocationPropertySheet:: Handle_Notify( IN WPARAM wParam, IN LPARAM lParam ) { BOOL bRetval = TRUE; LPNMHDR pnmh = (LPNMHDR)lParam; switch( pnmh->code ) { case PSN_APPLY: { DBGMSG( DBG_TRACE, ( "TLocationPropertySheet::Handle_Notify PSN_APPLY\n" ) ); LPPSHNOTIFY lppsn = (LPPSHNOTIFY )lParam; TStatusB bStatus; bStatus DBGNOCHK = TRUE; // // Check if we have write access, not much to do if we only have read access. // if( _PropertyAccess == kPropertyAccessWrite ) { UINT u, uLen; TString strLocation; bStatus DBGCHK = bGetEditText( _hDlg, _uLocationEditID, strLocation ); // make all separators the same character strLocation.bReplaceAll( TEXT('\\'), TEXT('/') ); StartOver: // remove the duplicated separators uLen = strLocation.uLen(); for( u = 0; (u+1)lParam == TRUE ) { if( iMessage( _hDlg, IDS_ERR_LOCATION_PROP_TITLE, IDS_ERR_WANT_TO_EXIT, MB_YESNO|MB_ICONSTOP, kMsgNone, NULL ) == IDYES ) { bStatus DBGCHK = TRUE; } } else { iMessage( _hDlg, IDS_ERR_LOCATION_PROP_TITLE, IDS_ERR_GENERIC, MB_OK|MB_ICONSTOP, kMsgGetLastError, NULL ); } } bRetval = bStatus ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE; break; } default: { bRetval = FALSE; break; } } return bRetval; } BOOL TLocationPropertySheet:: GetObjectInterface( IN LPCTSTR strDsObject, IN OUT IADs **ppDsObject ) { // // Get the adsi object interface pointer. // HRESULT hr = ADsOpenObject( const_cast( strDsObject ), NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IADs, reinterpret_cast( ppDsObject ) ); return SUCCEEDED( hr ); } BOOL TLocationPropertySheet:: GetDefaultSiteName( IN TString &strSiteName ) { TStatusB bStatus; // // Get the current objects site name. If the current // object is a site object we just read the site name // if( !_tcsicmp( _strDsObjectClass, gszSite ) ) { bStatus DBGCHK = _Ds.Get( _pDsObject, gszName, strSiteName ); } else if ( !_tcsicmp( _strDsObjectClass, gszSubnet ) ) { // // To get the default site name for a subnet object // we need to build a path to the site object and read the // the name property from the site. // TString strSiteObjectName; bStatus DBGCHK = _Ds.Get( _pDsObject, gszSiteObject, strSiteObjectName ); if( bStatus ) { TString strSiteObjectPath; TString strLDAPPrefix; // // Build the site object path. // bStatus DBGCHK = _Ds.GetLDAPPrefix( strLDAPPrefix ) && strSiteObjectPath.bUpdate( strLDAPPrefix ) && strSiteObjectPath.bCat( strSiteObjectName ); if( bStatus ) { IADs *pDsSiteObject = NULL; // // Get the site object interface pointer. // bStatus DBGCHK = GetObjectInterface( strSiteObjectPath, &pDsSiteObject ); if( bStatus ) { // // Read the site name from the site object. // bStatus DBGCHK = _Ds.Get( pDsSiteObject, gszName, strSiteName ); } if( pDsSiteObject ) { pDsSiteObject->Release(); } } } bStatus DBGNOCHK = FALSE; } else { bStatus DBGNOCHK = FALSE; } return bStatus; } VOID TLocationPropertySheet:: BrowseLocations( VOID ) { TFindLocDlg *pFindLocDlg = new TFindLocDlg(TFindLocDlg::kLocationShowHelp); if( VALID_PTR(pFindLocDlg) ) { TString strLocation; TStatusB bStatus; bGetEditText ( _hDlg, _uLocationEditID, strLocation ); bStatus DBGCHK = pFindLocDlg->bDoModal(_hDlg, &strLocation); if (bStatus) { bStatus DBGCHK = pFindLocDlg->bGetLocation(strLocation); if (bStatus && !strLocation.bEmpty()) { // // Check to append a trailing slash // UINT uLen = strLocation.uLen(); if( uLen && gchSeparator != static_cast(strLocation)[uLen-1] ) { static const TCHAR szSepStr[] = { gchSeparator }; bStatus DBGCHK = strLocation.bCat( szSepStr ); } bStatus DBGCHK = bSetEditText( _hDlg, _uLocationEditID, strLocation ); } } } if( pFindLocDlg ) { delete pFindLocDlg; } }