Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

908 lines
23 KiB

/*++
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<UINT *>( &gcRefThisDll );
psp.pszTemplate = MAKEINTRESOURCE( Template );
psp.lParam = reinterpret_cast<LPARAM>( 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<LPDSOBJECTNAMES>( 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<LPTSTR>( static_cast<LPCTSTR>(_strDsObjectName)),
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IDirectoryObject,
reinterpret_cast<LPVOID*>( &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<LPTSTR>( reinterpret_cast<LPBYTE>( 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)<uLen; u++ )
{
if( TEXT('/') == strLocation[u] &&
TEXT('/') == strLocation[u+1] )
{
// duplicated separator - delete & start all over
strLocation.bDeleteChar(u);
goto StartOver;
}
}
// remove the leading separator
uLen = strLocation.uLen();
if( uLen && TEXT('/') == strLocation[0] )
{
strLocation.bDeleteChar(0);
}
// remove the trailing separator
uLen = strLocation.uLen();
if( uLen && TEXT('/') == strLocation[uLen-1] )
{
strLocation.bDeleteChar(uLen-1);
}
if( _tcscmp( _strLocation, strLocation ) && bStatus )
{
bStatus DBGCHK = _Ds.Put( _pDsObject, gszLocation, strLocation );
}
if (bStatus)
{
//
// DS put succeeded. Just save the last valid location.
//
_strLocation.bUpdate( strLocation );
//
// Since we may have modified the location - update UI.
//
bSetEditText( _hDlg, _uLocationEditID, strLocation );
}
}
//
// Something failed let the user know.
//
if (!bStatus)
{
//
// If the lParam is true the OK/Close button was used to
// dismiss the dialog. Let the dialog exit in this case.
//
if( lppsn->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<LPTSTR>( strDsObject ),
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
reinterpret_cast<LPVOID*>( 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<LPCTSTR>(strLocation)[uLen-1] )
{
static const TCHAR szSepStr[] = { gchSeparator };
bStatus DBGCHK = strLocation.bCat( szSepStr );
}
bStatus DBGCHK = bSetEditText( _hDlg, _uLocationEditID, strLocation );
}
}
}
if( pFindLocDlg )
{
delete pFindLocDlg;
}
}