windows-nt/Source/XPSP1/NT/termsrv/admtools/winutils/tscfg/appsvdoc.cpp

2883 lines
84 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//Copyright (c) 1998 - 1999 Microsoft Corporation
/*******************************************************************************
*
* appsvdoc.cpp
*
* implementation of the CAppServerDoc class
*
* copyright notice: Copyright 1994, Citrix Systems Inc.
*
* $Author: donm $ Butch Davis
*
* $Log: N:\nt\private\utils\citrix\winutils\tscfg\VCS\appsvdoc.cpp $
*
* Rev 1.54 18 Apr 1998 15:31:08 donm
* Added capability bits
*
* Rev 1.53 14 Feb 1998 11:23:04 donm
* fixed memory leak by avoiding CDocManager::OpenDocumentFile
*
* Rev 1.52 31 Dec 1997 09:13:50 donm
* uninitialized variable in RegistryDelete
*
* Rev 1.51 10 Dec 1997 15:59:14 donm
* added ability to have extension DLLs
*
* Rev 1.50 19 Jun 1997 19:21:08 kurtp
* update
*
* Rev 1.49 25 Mar 1997 08:59:46 butchd
* update
*
* Rev 1.48 18 Mar 1997 15:51:18 butchd
* ignore system console registry entry
*
* Rev 1.47 10 Mar 1997 16:58:26 butchd
* update
*
* Rev 1.46 04 Mar 1997 09:46:46 butchd
* update
*
* Rev 1.45 04 Mar 1997 08:35:12 butchd
* update
*
* Rev 1.44 28 Feb 1997 17:59:22 butchd
* update
*
* Rev 1.43 11 Dec 1996 09:50:18 butchd
* update
*
* Rev 1.42 24 Sep 1996 16:21:18 butchd
* update
*
*******************************************************************************/
/*
* include files
*/
#include "stdafx.h"
#include "wincfg.h"
#include "security.h"
#include "appsvdoc.h"
#include "rowview.h"
#include "appsvvw.h"
#include "ewsdlg.h"
#include <string.h>
#include <hydra\regapi.h> // for WIN_ENABLEWINSTATION registry entry name
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif
extern CWincfgApp *pApp;
extern "C" LPCTSTR WinUtilsAppName;
extern "C" HWND WinUtilsAppWindow;
extern "C" HINSTANCE WinUtilsAppInstance;
PTERMLOBJECT GetWdListObject( PWDNAME pWdName);
/*
* Global command line variables.
*/
////////////////////////////////////////////////////////////////////////////////
// CWinStationListObjectHint implemetation / construction
IMPLEMENT_DYNAMIC(CWinStationListObjectHint, CObject)
CWinStationListObjectHint::CWinStationListObjectHint()
{
}
////////////////////////////////////////////////////////////////////////////////
// CAppServerDoc implementation / construction, destruction
IMPLEMENT_SERIAL(CAppServerDoc, CDocument, 0 /*schema*/)
/*******************************************************************************
*
* CAppServerDoc - CAppServerDoc constructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CAppServerDoc::CAppServerDoc()
: m_bReadOnly(FALSE),
m_pSecurityDescriptor(NULL)
{
} // end CAppServerDoc::CAppServerDoc
/*******************************************************************************
*
* ~CAppServerDoc - CAppServerDoc destructor
*
* ENTRY:
* EXIT:
*
******************************************************************************/
CAppServerDoc::~CAppServerDoc()
{
/*
* Free up all WSL objects currently in use.
*/
DeleteWSLContents();
} // end CAppServerDoc::~CAppServerDoc
////////////////////////////////////////////////////////////////////////////////
// CAppServerDoc class overrides
/*******************************************************************************
*
* OnOpenDocument - CAppServerDoc member function: CDocument class override
*
* Reads the specified AppServer's registry and initializes the
* 'document' contents.
*
* ENTRY:
* pszPathName (input)
* Name of the AppServer to access.
*
* EXIT:
* TRUE - sucessful initialization of 'document'.
* FALSE - 'document' was not properly initialized.
*
******************************************************************************/
BOOL
CAppServerDoc::OnNewDocument( /*LPCTSTR pszPathName*/ )
{
POSITION pos;
/*
* If this user doesn't have ALL access to the WinStation registry (ie, not
* an admin), set the 'admin' flag to FALSE and 'read only' flag to TRUE
* to only display the user's current WinStation in the WinStation list;
* otherwise set 'admin' flag to TRUE to allow all WinStations to be
* displayed, with the 'read only' state being determined from the previous
* AppServer check, above.
*/
if ( RegWinStationAccessCheck(SERVERNAME_CURRENT, KEY_ALL_ACCESS) ) {
m_bAdmin = FALSE;
m_bReadOnly = TRUE;
} else {
m_bAdmin = TRUE;
}
/*
* Obtain the user's current WinStation information.
*/
if ( !QueryCurrentWinStation( pApp->m_CurrentWinStation,
pApp->m_CurrentUserName,
&(pApp->m_CurrentLogonId),
&(pApp->m_CurrentWSFlags) ) ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_CURRENT, GetLastError(),
IDP_ERROR_QUERYCURRENTWINSTATION ))
return(FALSE);
}
/*
* Load the WSL with registry information for this AppServer.
*/
if ( !LoadWSL(NULL/*pszPathName*/) )
return(FALSE);
/*
* Reset the view for this document.
*/
((CAppServerView *)GetNextView( pos = GetFirstViewPosition() ))->
ResetView( TRUE );
return ( TRUE );
} // end CAppServerDoc::OnOpenDocument
/*******************************************************************************
*
* SetTitle - CAppServerDoc member function: override
*
* Override default to set our title the way that we want.
*
* ENTRY:
* lpszTitle (input)
* Title to set (this is ignored).
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::SetTitle( LPCTSTR lpszTitle )
{
/*
* Set our document's title, including the READONLY (User Mode)
* string if needed.
*/
if ( m_bReadOnly ) {
CString ReadOnly;
ReadOnly.LoadString( IDS_READONLY );
CString sz = pApp->m_szCurrentAppServer + ReadOnly;
CDocument::SetTitle(sz);
} else
CDocument::SetTitle(pApp->m_szCurrentAppServer);
} // end CAppServerDoc::SetTitle
////////////////////////////////////////////////////////////////////////////////
// CAppServerDoc public operations
/*******************************************************************************
*
* IsExitAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the application can be exited, based on whether
* or not there are operations pending.
*
* ENTRY:
*
* EXIT:
* TRUE - no operations are pending: the application can be exited.
* FALSE - operations are pending: the application cannot be exited.
*
******************************************************************************/
BOOL
CAppServerDoc::IsExitAllowed()
{
return (TRUE);
} // end CAppServerDoc::IsExitAllowed
/*******************************************************************************
*
* IsAddAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WSLObject associated with the specified
* list index can be referenced for adding a new WinStation.
*
* ENTRY:
*
* EXIT:
* (BOOL) TRUE if the WSLObject can be referenced for add; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsAddAllowed( int nIndex )
{
/*
* If this document is 'read only' then add is not allowed.
* Otherwise, it's OK.
*/
if ( m_bReadOnly )
return(FALSE);
else
return(TRUE);
} // end CAppServerDoc::IsAddAllowed
/*******************************************************************************
*
* IsCopyAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WSLObject associated with the specified
* list index can be copied.
*
* ENTRY:
*
* EXIT:
* (BOOL) TRUE if the WSLObject can be copied; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsCopyAllowed( int nIndex )
{
PWSLOBJECT pWSLObject;
/*
* If this document is 'read only' or no items yet,
* then copy is not allowed.
*/
if ( m_bReadOnly ||
!(pWSLObject = GetWSLObject(nIndex)) )
return(FALSE);
/*
* If this WinStation is the main CONSOLE, or is not a single instance
* type, we can't copy.
*/
if ( !lstrcmpi(pWSLObject->m_WinStationName, pApp->m_szSystemConsole) ||
!(pWSLObject->m_Flags & WSL_SINGLE_INST) )
return(FALSE);
/*
* The copy is allowed.
*/
return(TRUE);
} // end CAppServerDoc::IsCopyAllowed
/*******************************************************************************
*
* IsRenameAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WSLObject associated with the specified
* list index can be renamed.
*
* ENTRY:
*
* EXIT:
* (BOOL) TRUE if the WSLObject can be renamed; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsRenameAllowed( int nIndex )
{
PWSLOBJECT pWSLObject;
/*
* If this document is 'read only' or no items yet,
* then rename is not allowed.
*/
if ( m_bReadOnly ||
!(pWSLObject = GetWSLObject(nIndex)) )
return(FALSE);
/*
* If this WinStation is the main CONSOLE, we can't rename.
*/
if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
return(FALSE);
/*
* The rename is allowed.
*/
return(TRUE);
} // end CAppServerDoc::IsRenameAllowed
/*******************************************************************************
*
* IsDeleteAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WSLObject associated with the specified
* list index can be deleted.
*
* ENTRY:
*
* EXIT:
* (BOOL) TRUE if the WSLObject can be deleted; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsDeleteAllowed( int nIndex )
{
PWSLOBJECT pWSLObject;
/*
* If this document is 'read only' or no items yet,
* then delete is not allowed.
*/
if ( m_bReadOnly ||
!(pWSLObject = GetWSLObject(nIndex)) )
return(FALSE);
/*
* If this WinStation is the main CONSOLE, we can't delete.
*/
if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
return(FALSE);
/*
* The delete is allowed.
*/
return(TRUE);
} // end CAppServerDoc::IsDeleteAllowed
/*******************************************************************************
*
* IsEditAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WSLObject associated with the specified
* list index can be edited.
*
* ENTRY:
*
* EXIT:
* (BOOL) TRUE if the WSLObject can be edited; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsEditAllowed( int nIndex )
{
/*
* If no items yet, then edit is not allowed.
* Otherwise, it's OK.
*/
if ( !GetWSLObject(nIndex) )
return(FALSE);
else
return(TRUE);
} // end CAppServerDoc::IsEditAllowed
/*******************************************************************************
*
* IsEnableAllowed - CAppServerDoc member function: public operation
*
* Indicate whether or not the WinStation(s) associated with the specified
* WSLObject can be enabled/disabled.
*
* ENTRY:
* bEnable (input)
* TRUE: check for enable allowed; FALSE: check for disable allowed.
* EXIT:
* (BOOL) TRUE if the WinStation(s) can be enabled/disabled;
* FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::IsEnableAllowed( int nIndex,
BOOL bEnable )
{
PWSLOBJECT pWSLObject;
/*
* If this document is 'read only' no items yet,
* then enable/disable is not allowed.
*/
if ( m_bReadOnly ||
!(pWSLObject = GetWSLObject(nIndex)) )
return(FALSE);
/*
* If this WinStation is the main CONSOLE, we can't enable/disable.
*/
if ( !lstrcmpi( pWSLObject->m_WinStationName, pApp->m_szSystemConsole ) )
return(FALSE);
/*
* Make sure that the WSL is 'in sync' with the registry. Return
* 'enable/disable not allowed' if error.
*/
if ( !RefreshWSLObjectState( nIndex, pWSLObject ) )
return(FALSE);
/*
* If this WSLObject indicates that the WinStation(s) are already enabled
* and enable allow is requested, or WSLObject indicates that the
* WinStation(s) are already disabled and disable allow is requested,
* return FALSE (can't enable/disable).
*/
if ( (bEnable && (pWSLObject->m_Flags & WSL_ENABLED)) ||
(!bEnable && !(pWSLObject->m_Flags & WSL_ENABLED)) )
return(FALSE);
/*
* The enable/disable is allowed.
*/
return(TRUE);
} // end CAppServerDoc::IsEnableAllowed
/*******************************************************************************
*
* GetWSLCount - CAppServerDoc member function: public operation
*
* Return the number of WinStationList elements defined in this document.
*
* ENTRY:
*
* EXIT:
* (int) number of WinStationsList elements present in this document.
*
******************************************************************************/
int
CAppServerDoc::GetWSLCount()
{
return( m_WinStationList.GetCount() );
} // end CAppServerDoc::GetWSLCount
/*******************************************************************************
*
* GetWSLObject - CAppServerDoc member function: public operation
*
* Retrieves the WinStation object from the WinStationObjectList that
* resides at the specified index.
*
* ENTRY:
* nIndex (input)
* WinStationObjectList index of the WinStation to retrieve.
*
* EXIT:
* PWLSOBJECT - pointer to WinStationListObject for the indexed
* WinStation. NULL if list is empty.
*
******************************************************************************/
PWSLOBJECT
CAppServerDoc::GetWSLObject( int nIndex )
{
if ( !GetWSLCount() )
return(NULL);
else
return ( (PWSLOBJECT)m_WinStationList.GetAt(
m_WinStationList.FindIndex( nIndex )) );
} // end CAppServerDoc::GetWSLObject
/*******************************************************************************
*
* GetWSLIndex - CAppServerDoc member function: public operation
*
* Retrieves the WinStation List index of WinStation list object that
* matches the specified WSName.
*
* ENTRY:
* pWSName (input)
* Points to WINSTATIONNAME to compare with list objects.
*
* EXIT:
* int - Index of the specified WSL object in the list.
* -1 if an object containing the specified WSName was not found.
*
******************************************************************************/
int
CAppServerDoc::GetWSLIndex( PWINSTATIONNAME pWSName )
{
POSITION pos;
int nIndex = 0;
/*
* Traverse the WinStationList.
*/
for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; nIndex++ ) {
PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
/*
* If this is the specified WSL object, return the current index.
*/
if ( !lstrcmpi(pObject->m_WinStationName, pWSName) )
return(nIndex);
}
/*
* WSLObject not found in the list.
*/
return(-1);
} // end CAppServerDoc::GetWSLIndex
/*******************************************************************************
*
* GetWSLObjectNetworkMatch - CAppServerDoc member function: public operation
*
* Retrieves the WinStation list object (if any) from the WinStationList
* that contains the specified PdName, WdName, and LanAdapter.
*
* ENTRY:
* PdName (input)
* PdName to compare.
* WdName (input)
* WdName to compare.
* LanAdapter (input)
* LanAdapter # to compare.
* EXIT:
* PWLSOBJECT - pointer to WinStationList object if the PdName, WdName,
* and LanAdapter all matched an existing WSL entry.
* NULL if no match was found.
*
******************************************************************************/
PWSLOBJECT
CAppServerDoc::GetWSLObjectNetworkMatch( PDNAME PdName,
WDNAME WdName,
ULONG LanAdapter )
{
POSITION pos;
/*
* Traverse the WinStationList.
*/
for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
/*
* If PdName, WdName, and LanAdapter fields match, return this
* PWSLOBJECT.
*/
if ( !lstrcmp( pObject->m_PdName, PdName ) &&
!lstrcmp( pObject->m_WdName, WdName ) &&
(pObject->m_LanAdapter == LanAdapter) )
return(pObject);
}
/*
* No match found.
*/
return(NULL);
} // end CAppServerDoc::GetWSLObjectNetworkMatch
/*******************************************************************************
*
* IsAsyncDeviceAvailable - CAppServerDoc member function: public operation
*
* Determines if the specified Async device is available for use in
* configuring a new WinStation. Availability in this context is
* determined by whether or not the device is already configured for
* use in an Async WinStation.
*
* ENTRY:
* pDeviceName (input)
* Points to the Async device name (NOT decorated) to check for
* availablility.
* pWSName (input)
* Points to WINSTATIONNAME of current WinStation being edited.
*
* EXIT:
* TRUE if the Async device is available for use; FALSE if another
* WinStation is already configured to use it.
*
******************************************************************************/
BOOL
CAppServerDoc::IsAsyncDeviceAvailable( LPCTSTR pDeviceName,
PWINSTATIONNAME pWSName )
{
POSITION pos;
ASYNCCONFIG AsyncConfig;
/*
* Traverse the WinStationList.
*/
for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
/*
* If this is an async WinStation, the device is the same as the
* one we're checking, but this is not the current WinStation being
* edited, return FALSE.
*/
if ( pObject->m_SdClass == SdAsync ) {
ParseDecoratedAsyncDeviceName( pObject->m_DeviceName, &AsyncConfig );
if ( !lstrcmpi(AsyncConfig.DeviceName, pDeviceName) &&
lstrcmpi(pWSName, pObject->m_WinStationName) )
return(FALSE);
}
}
/*
* The Async device is not configured in any Async WinStations.
*/
return(TRUE);
} // end CAppServerDoc::IsAsyncDeviceAvailable
/*******************************************************************************
*
* IsOemTdDeviceAvailable - CAppServerDoc member function: public operation
*
* Determines if the specified OEM Transport device is available for use
* in configuring a new WinStation. Availability in this context is
* determined by whether or not the device is already configured for
* use in a WinStation for the Oem Td.
*
* ENTRY:
* pDeviceName (input)
* Points to device name to check against other WinStations of
* the specified OEM Transport.
* pPdName (input)
* Points to PDNAME of the OEM Transport.
* pWSName (input)
* Points to WINSTATIONNAME of current WinStation being edited.
*
* EXIT:
* TRUE if the OEM Transport device is available for use; FALSE if another
* WinStation of the specified OEM Transport is already configured to
* use it.
*
******************************************************************************/
BOOL
CAppServerDoc::IsOemTdDeviceAvailable( LPCTSTR pDeviceName,
PPDNAME pPdName,
PWINSTATIONNAME pWSName )
{
POSITION pos;
/*
* Traverse the WinStationList.
*/
for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
/*
* If this is a OEM Transport WinStation of the specified OEM Transport,
* the device is the same as the one we're checking, but this is not the
* current WinStation being edited, return FALSE.
*/
if ( (pObject->m_SdClass == SdOemTransport) &&
!lstrcmpi(pObject->m_PdName, pPdName) &&
!lstrcmpi(pObject->m_DeviceName, pDeviceName) &&
lstrcmpi(pWSName, pObject->m_WinStationName) ) {
return(FALSE);
}
}
/*
* The OEM Transport device is not configured in any current WinStations
* of the same OEM Transport.
*/
return(TRUE);
} // end CAppServerDoc::IsOemTdDeviceAvailable
/*******************************************************************************
*
* IsWSNameUnique - CAppServerDoc member function: public operation
*
* Determine if the entered WinStation name is unique.
*
* ENTRY:
* pWinStationName (input)
* Points to WINSTATIONNAME to check for uniqueness.
*
* EXIT:
* TRUE if the specified WinStation name is unique; FALSE if not.
*
******************************************************************************/
BOOL
CAppServerDoc::IsWSNameUnique( PWINSTATIONNAME pWinStationName )
{
POSITION pos;
WINSTATIONNAME WSRoot;
PWINSTATIONNAME pWSRoot;
/*
* Traverse the WinStationList.
*/
for ( pos = m_WinStationList.GetHeadPosition(); pos != NULL; ) {
PWSLOBJECT pObject = (PWSLOBJECT)m_WinStationList.GetNext(pos);
/*
* Make sure that we only compare the 'root' names.
*/
lstrcpy(WSRoot, pObject->m_WinStationName);
pWSRoot = lstrtok(WSRoot, TEXT("#"));
/*
* If the roots match, return FALSE.
*/
if ( !lstrcmpi(pWinStationName, pWSRoot) )
return(FALSE);
}
/*
* WinStation name is unique.
*/
return(TRUE);
} // end CAppServerDoc::IsWSNameUnique()
/*******************************************************************************
*
* AddWinStation - CAppServerDoc member function: public operation
*
* Add a new WinStation.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the currently selected WinStation, to provide some
* defaults for the new WinStation.
* EXIT:
* (int) WSL index of the added WinStation's list item; -1 if error.
*
******************************************************************************/
int
CAppServerDoc::AddWinStation(int WSLIndex)
{
LONG Status;
int nIndex = -1;
CEditWinStationDlg EWSDlg(this);
WINSTATIONNAME WSName;
PWSLOBJECT pWSLObject;
LPCTSTR pszFailedCall = NULL;
/*
* Zero out the WinStation name and config structure.
*/
memset(WSName, 0, sizeof(WSName));
memset(&EWSDlg.m_WSConfig, 0, sizeof(WINSTATIONCONFIG2));
/*
* Get current WinStation object to anticipate defaults for the new
* WinStation and assure that the WSL is 'in sync' with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pWSLObject = GetWSLObject(WSLIndex)) )
goto BadRefreshWSLObjectState;
/*
* Set the config structure's Pd name field to allow Edit
* dialog to form default config structure contents.
*/
EWSDlg.m_WSConfig.Create.fEnableWinStation = 1;
if ( pWSLObject ) {
EWSDlg.m_WSConfig.Pd[0].Create.SdClass = pWSLObject->m_SdClass;
lstrcpy( EWSDlg.m_WSConfig.Pd[0].Create.PdName, pWSLObject->m_PdName );
}
/*
* Initialize the additional dialog member variables.
*/
EWSDlg.m_pWSName = WSName;
EWSDlg.m_DlgMode = EWSDlgAdd;
EWSDlg.m_pExtObject = NULL;
/*
* Invoke the dialog.
*/
if ( EWSDlg.DoModal() == IDOK ) {
CWaitCursor wait;
/*
* Add a new WSLObject to the WSL.
*/
if ( (nIndex =
InsertInWSL( WSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pWSLObject )) == -1 )
goto BadInsertInWSL;
/*
* Fetch the default WinStation security descriptor.
*/
if ( (Status = GetDefaultWinStationSecurity(&m_pSecurityDescriptor))
!= ERROR_SUCCESS ) {
pszFailedCall = pApp->m_pszGetDefaultWinStationSecurity;
goto BadGetDefaultWinStationSecurity;
}
/*
* Create the registry entry.
*/
if((Status = RegistryCreate(WSName,
TRUE,
&EWSDlg.m_WSConfig,
pWSLObject->m_WdName,
pWSLObject->m_pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationCreate;
goto BadRegCreate;
}
/*
* Set the WinStation security in registry.
*/
if ( m_pSecurityDescriptor &&
(Status = RegWinStationSetSecurity(
SERVERNAME_CURRENT,
WSName,
m_pSecurityDescriptor,
GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
goto BadRegSetSecurity;
}
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
/*
* If this is a modem winstation and it's enabled,
* issue the 'must reboot' message and flag the
* winstation as 'must reboot'.
*/
if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
IDP_NOTICE_REBOOTFORMODEM_ADD, WSName );
pWSLObject->m_Flags |= WSL_MUST_REBOOT;
}
}
#endif // WINSTA
/*
* A new WSLObject was added: update the entire view.
*/
UpdateAllViews(NULL, 0, NULL);
/*
* Return the new WSLObject's index.
*/
return(nIndex);
} else {
/*
* User canceled the Add; just return the previously given index.
*/
DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
return(WSLIndex);
}
/*==============================================================================
* Error returns
*============================================================================*/
BadRegSetSecurity:
RegWinStationDelete( SERVERNAME_CURRENT, WSName );
BadRegCreate:
BadGetDefaultWinStationSecurity:
BadInsertInWSL:
BadRefreshWSLObjectState:
if ( nIndex != -1 )
RemoveFromWSL(nIndex);
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_ADDWINSTATION, WSName,
pszFailedCall ))
}
return(-1);
} // end CAppServerDoc::AddWinStation
/*******************************************************************************
*
* CopyWinStation - CAppServerDoc member function: public operation
*
* Copy a given WinStation into a new one.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the currently selected WinStation, to provide most
* defaults for the new WinStation.
* EXIT:
* (int) WSL index of the added WinStation's list item; -1 if error.
*
******************************************************************************/
int
CAppServerDoc::CopyWinStation(int WSLIndex)
{
LONG Status;
ULONG Length;
int nIndex = -1;
PWSLOBJECT pWSLObject;
WINSTATIONNAME WSName;
WINSTATIONNAME OriginalWSName;
CEditWinStationDlg EWSDlg(this);
LPCTSTR pszFailedCall = NULL;
/*
* Get current WinStation object to obtain defaults for the new
* WinStation and assure that the WSL is 'in sync' with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pWSLObject = GetWSLObject(WSLIndex)) )
goto BadRefreshWSLObjectState;
lstrcpy( WSName, pWSLObject->m_WinStationName );
/*
* Get the WinStation's config structure and initialize the WSName
* array.
*/
if((Status = RegistryQuery( pWSLObject->m_WinStationName,
&EWSDlg.m_WSConfig,
pWSLObject->m_WdName,
&EWSDlg.m_pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationQuery;
goto BadRegWinStationQuery;
}
lstrcpy( OriginalWSName, pWSLObject->m_WinStationName );
/*
* If this is an Async WinStation class, null the DeviceName field, since
* the device used by an Async WinStation must be unique.
*/
if ( pWSLObject->m_SdClass == SdAsync )
*(EWSDlg.m_WSConfig.Pd[0].Params.Async.DeviceName) = TEXT('\0');
/*
* Initialize dialog variables and invoke the Edit WinStation dialog
* in it's 'copy' mode.
*/
EWSDlg.m_pWSName = WSName;
EWSDlg.m_DlgMode = EWSDlgCopy;
/*
* Invoke the dialog.
*/
if ( EWSDlg.DoModal() == IDOK ) {
CWaitCursor wait;
/*
* Add a new WSLObject to the WSL.
*/
if ( (nIndex =
InsertInWSL( WSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pWSLObject )) == -1 )
goto BadInsertInWSL;
/*
* Fetch the original WinStation's security descriptor.
*/
if ( (Status = GetWinStationSecurity( OriginalWSName,
&m_pSecurityDescriptor))
!= ERROR_SUCCESS ) {
pszFailedCall = pApp->m_pszGetWinStationSecurity;
goto BadGetWinStationSecurity;
}
/*
* Create the registry entry.
*/
if((Status = RegistryCreate( WSName,
TRUE,
&EWSDlg.m_WSConfig,
EWSDlg.m_WSConfig.Wd.WdName,
EWSDlg.m_pExtObject)) ) {
pszFailedCall = pApp->m_pszRegWinStationCreate;
goto BadRegCreate;
}
/*
* Set the WinStation security in registry.
*/
if ( m_pSecurityDescriptor &&
(Status = RegWinStationSetSecurity(
SERVERNAME_CURRENT,
WSName,
m_pSecurityDescriptor,
GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
goto BadRegSetSecurity;
}
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
/*
* If this is a modem winstation and it's enabled,
* issue the 'must reboot' message and flag the
* winstation as 'must reboot'.
*/
if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
IDP_NOTICE_REBOOTFORMODEM_ADD, WSName );
pWSLObject->m_Flags |= WSL_MUST_REBOOT;
}
}
#endif // WINSTA
/*
* A new WSLObject was added: update the entire view.
*/
UpdateAllViews(NULL, 0, NULL);
/*
* Return the new WSLObject's index.
*/
return(nIndex);
} else {
/*
* User canceled the Copy; just return the previously given index.
*/
DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
return(WSLIndex);
}
/*==============================================================================
* Error returns
*============================================================================*/
BadRegSetSecurity:
RegWinStationDelete( SERVERNAME_CURRENT, WSName );
BadRegCreate:
BadGetWinStationSecurity:
BadInsertInWSL:
BadRegWinStationQuery:
BadRefreshWSLObjectState:
if ( nIndex != -1 )
RemoveFromWSL(nIndex);
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_COPYWINSTATION, WSName,
pszFailedCall ))
}
return(-1);
} // end CAppServerDoc::CopyWinStation
/*******************************************************************************
*
* RenameWinStation - CAppServerDoc member function: public operation
*
* Rename a WinStation.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the WinStation to rename.
* EXIT:
* (int) WSL index of the renamed WinStation's list item; -1 if error.
*
******************************************************************************/
int
CAppServerDoc::RenameWinStation(int WSLIndex)
{
LONG Status;
ULONG Length;
int nIndex = -1;
CEditWinStationDlg EWSDlg(this);
PWSLOBJECT pOldWSLObject, pNewWSLObject;
WINSTATIONNAME OldWSName, NewWSName;
LPCTSTR pszFailedCall = NULL;
void *pExtObject = NULL;
/*
* Get current WinStation object and assure that the WSL is 'in sync'
* with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pOldWSLObject = GetWSLObject(WSLIndex)) )
goto BadRefreshWSLObjectState;
lstrcpy(OldWSName, pOldWSLObject->m_WinStationName);
/*
* Fetch the WinStation's configuration structure.
*/
if((Status = RegistryQuery( pOldWSLObject->m_WinStationName,
&EWSDlg.m_WSConfig,
pOldWSLObject->m_WdName,
&pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationQuery;
goto BadRegWinStationQuery;
}
lstrcpy(NewWSName, pOldWSLObject->m_WinStationName);
/*
* copy the pExtObject into the one for the EWSDlg
*/
if(pExtObject) {
PTERMLOBJECT pObject = GetWdListObject(pOldWSLObject->m_WdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDupObject) {
EWSDlg.m_pExtObject = (*pObject->m_lpfnExtDupObject)(pExtObject);
}
} else {
EWSDlg.m_pExtObject = NULL;
}
/*
* Initialize the dialog's member variables.
*/
EWSDlg.m_pWSName = NewWSName;
EWSDlg.m_DlgMode = EWSDlgRename;
/*
* Invoke the dialog.
*/
if ( EWSDlg.DoModal() == IDOK ) {
CWaitCursor wait;
/*
* Add a new WSLObject to the WSL.
*/
if ( (nIndex =
InsertInWSL(NewWSName, &EWSDlg.m_WSConfig, EWSDlg.m_pExtObject, &pNewWSLObject)) == -1 )
goto BadInsertInWSL;
/*
* Fetch the original WinStation's security descriptor.
*/
if ( (Status = GetWinStationSecurity( OldWSName,
&m_pSecurityDescriptor))
!= ERROR_SUCCESS ) {
pszFailedCall = pApp->m_pszGetWinStationSecurity;
goto BadGetWinStationSecurity;
}
/*
* Create the new registry entry.
*/
if((Status = RegistryCreate( NewWSName,
TRUE,
&EWSDlg.m_WSConfig,
EWSDlg.m_WSConfig.Wd.WdName,
EWSDlg.m_pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationCreate;
goto BadRegCreate;
}
/*
* Set the WinStation security in registry.
*/
if ( m_pSecurityDescriptor &&
(Status = RegWinStationSetSecurity(
SERVERNAME_CURRENT,
NewWSName,
m_pSecurityDescriptor,
GetSecurityDescriptorLength(m_pSecurityDescriptor) )) ) {
pszFailedCall = pApp->m_pszRegWinStationSetSecurity;
goto BadRegSetSecurity;
}
/*
* Delete the old registry entry.
*/
if ( (Status = RegistryDelete(OldWSName, EWSDlg.m_WSConfig.Wd.WdName, pExtObject)) ) {
pszFailedCall = pApp->m_pszRegWinStationDelete;
goto BadRegDelete;
}
/*
* Remove old WSLObject from the WSL and recalculate the
* new WSLObject's index (may have changed).
*/
RemoveFromWSL( GetWSLIndex(OldWSName) );
nIndex = GetWSLIndex(NewWSName);
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry and output 'in use' message if
* necessary.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
/*
* Issue appropriate messages if the winstation being renamed
* was enabled.
*/
if ( EWSDlg.m_WSConfig.Create.fEnableWinStation ) {
if ( *EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName ) {
QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
IDP_NOTICE_REBOOTFORMODEM_RENAME,
OldWSName, NewWSName );
pNewWSLObject->m_Flags |= WSL_MUST_REBOOT;
} else {
InUseMessage(OldWSName);
}
}
}
#endif // WINSTA
/*
* A new WSLObject was added: update the entire view.
*/
UpdateAllViews(NULL, 0, NULL);
/*
* Return the new WSLObject's index.
*/
return(nIndex);
} else {
/*
* User canceled the Rename; just return the previously given index.
*/
DeleteExtensionObject(pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
return(WSLIndex);
}
/*==============================================================================
* Error returns
*============================================================================*/
BadRegDelete:
BadRegSetSecurity:
RegWinStationDelete( SERVERNAME_CURRENT, NewWSName );
BadRegCreate:
BadGetWinStationSecurity:
BadInsertInWSL:
BadRegWinStationQuery:
BadRefreshWSLObjectState:
if ( nIndex != -1 )
RemoveFromWSL(nIndex);
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_RENAMEWINSTATION, OldWSName,
pszFailedCall ))
}
return(-1);
} // end CAppServerDoc::RenameWinStation
/*******************************************************************************
*
* EditWinStation - CAppServerDoc member function: public operation
*
* Edit a WinStation.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the WinStation to edit.
* EXIT:
* (int) WSL index of the edited WinStation's list item; -1 if error.
*
******************************************************************************/
int
CAppServerDoc::EditWinStation(int WSLIndex)
{
LONG Status;
ULONG Length;
int nIndex = -1;
BOOL bQueueOperationSuccess = TRUE, bAllowAbort = TRUE;
CEditWinStationDlg EWSDlg(this);
PWSLOBJECT pWSLObject;
WINSTATIONCONFIG2 WSConfig;
LPCTSTR pszFailedCall = NULL;
WINSTATIONNAME WSName;
void *pExtObject = NULL;
/*
* Get current WinStation object and assure that the WSL is 'in sync'
* with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pWSLObject = GetWSLObject(WSLIndex) ) )
goto BadRefreshWSLObjectState;
lstrcpy( WSName, pWSLObject->m_WinStationName );
/*
* Fetch the WinStation's configuration structure and save a copy for
* update comparison.
*/
memset( &WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
memset( &EWSDlg.m_WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
if((Status = RegistryQuery( WSName,
&WSConfig,
pWSLObject->m_WdName,
&pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationQuery;
goto BadRegWinStationQuery;
}
memcpy( &EWSDlg.m_WSConfig, &WSConfig, sizeof(WINSTATIONCONFIG2) );
/*
* copy the pExtObject into the one for the EWSDlg
*/
if(pExtObject) {
PTERMLOBJECT pObject = GetWdListObject(pWSLObject->m_WdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDupObject) {
EWSDlg.m_pExtObject = (*pObject->m_lpfnExtDupObject)(pExtObject);
}
} else {
EWSDlg.m_pExtObject = NULL;
}
/*
* Initialize the dialog's member variables.
*/
EWSDlg.m_pWSName = WSName;
EWSDlg.m_DlgMode = m_bReadOnly ? EWSDlgView : EWSDlgEdit;
/*
* Invoke the dialog & update if changes.
*/
if ( (EWSDlg.DoModal() == IDOK) &&
(EWSDlg.m_DlgMode == EWSDlgEdit) &&
HasWSConfigChanged(&WSConfig, &EWSDlg.m_WSConfig, pExtObject, EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName) ) {
BOOL bUpdateAll = FALSE,
bDestructive = FALSE,
bAsyncDeviceChanged = ((pWSLObject->m_SdClass == SdAsync) &&
lstrcmpi(WSConfig.Pd[0].Params.Async.DeviceName,
EWSDlg.m_WSConfig.Pd[0].Params.Async.DeviceName)),
bAsyncModemChanged = ((pWSLObject->m_SdClass == SdAsync) &&
lstrcmpi(WSConfig.Pd[0].Params.Async.ModemName,
EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName)),
bNetworkDeviceChanged = ((pWSLObject->m_SdClass == SdNetwork) &&
(WSConfig.Pd[0].Params.Network.LanAdapter !=
EWSDlg.m_WSConfig.Pd[0].Params.Network.LanAdapter)),
bEnabledStateChanged = (WSConfig.Create.fEnableWinStation !=
EWSDlg.m_WSConfig.Create.fEnableWinStation),
bEnabled = EWSDlg.m_WSConfig.Create.fEnableWinStation,
bWasEnabled = WSConfig.Create.fEnableWinStation;
/*
* If the winstation is being disabled or the device (or modem) has changed
* and folks are connected, the update will cause all instances to be destroyed.
* Let user know this so that the update can be canceled. Also allow
* normal confirmation if just disabling the winstation and no users are
* presently connected.
*/
if ( !bEnabled || bAsyncDeviceChanged || bAsyncModemChanged || bNetworkDeviceChanged ) {
if ( pApp->m_nConfirmation ) {
int id;
UINT nType = 0;
long count = QueryLoggedOnCount(WSName);
if ( !bEnabled && bWasEnabled ) {
nType = MB_YESNO |
(count ? MB_ICONEXCLAMATION : MB_ICONQUESTION);
id = count ?
((count == 1) ?
IDP_CONFIRM_WINSTATIONDISABLE_1USER :
IDP_CONFIRM_WINSTATIONDISABLE_NUSERS) :
IDP_CONFIRM_WINSTATIONDISABLE;
} else if ( bAsyncDeviceChanged && count ) {
nType = MB_YESNO | MB_ICONEXCLAMATION;
id = IDP_CONFIRM_DEVICECHANGED;
} else if ( bAsyncModemChanged && count ) {
nType = MB_YESNO | MB_ICONEXCLAMATION;
id = IDP_CONFIRM_MODEMCHANGED;
} else if ( bNetworkDeviceChanged && count ) {
nType = MB_YESNO | MB_ICONEXCLAMATION;
id = ((count == 1) ? IDP_CONFIRM_ADAPTERCHANGED_1USER :
IDP_CONFIRM_ADAPTERCHANGED_NUSERS);
}
if ( nType && (QuestionMessage(nType, id, WSName ) == IDNO) )
goto CancelChanges;
}
bDestructive = TRUE;
}
CWaitCursor wait;
/*
* Special case for Async WinStation.
*/
if ( pWSLObject->m_SdClass == SdAsync ) {
/*
* If a modem has been added or removed from the WinStation,
* delete the current WSLObject and add a new WSLObject to the list.
*/
if ( bAsyncModemChanged ) {
RemoveFromWSL(WSLIndex);
if ( (WSLIndex = InsertInWSL( WSName,
&EWSDlg.m_WSConfig,
EWSDlg.m_pExtObject,
&pWSLObject )) == -1 ) {
LoadWSL(pApp->m_szCurrentAppServer);
goto BadInsertInWSL;
}
bUpdateAll = TRUE;
}
/*
* Make sure that the WSL device name is current.
*/
FormDecoratedAsyncDeviceName(
pWSLObject->m_DeviceName,
&(EWSDlg.m_WSConfig.Pd[0].Params.Async) );
}
/*
* Special case for OEM Transport WinStation.
*/
if ( pWSLObject->m_SdClass == SdOemTransport ) {
/*
* Make sure that the WSL device name is current.
*/
lstrcpy( pWSLObject->m_DeviceName,
EWSDlg.m_WSConfig.Pd[0].Params.OemTd.DeviceName );
}
/*
* Update WSL fields.
*/
lstrcpy( pWSLObject->m_WdName, EWSDlg.m_WSConfig.Wd.WdName );
lstrcpy( pWSLObject->m_Comment, EWSDlg.m_WSConfig.Config.Comment );
pWSLObject->m_Flags = ((pWSLObject->m_Flags & ~WSL_ENABLED) |
(EWSDlg.m_WSConfig.Create.fEnableWinStation ? WSL_ENABLED : 0));
/*
* Update registry entry.
*/
if ( (Status = RegistryCreate(
WSName,
FALSE,
&EWSDlg.m_WSConfig,
EWSDlg.m_WSConfig.Wd.WdName,
EWSDlg.m_pExtObject)) ) {
pszFailedCall = pApp->m_pszRegWinStationCreate;
goto BadRegWinStationCreate;
}
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry and output 'in use' message if
* necessary.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
/*
* If the state is now 'enabled' AND
* 1) the modem has changed, OR
* 2) a modem is now configured AND
* a) the state was 'disabled' OR
* b) the COM port has changed
* Then issue the 'must reboot' message and set must reboot flag.
* Otherwise, if this is not a destructive action, issue in use message if needed
* and make sure the must reboot flag is cleared.
*/
if ( bEnabled &&
(bAsyncModemChanged ||
(*EWSDlg.m_WSConfig.Pd[0].Params.Async.ModemName &&
(!bWasEnabled || bAsyncDeviceChanged))) ) {
QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
IDP_NOTICE_REBOOTFORMODEM_EDIT, WSName );
pWSLObject->m_Flags |= WSL_MUST_REBOOT;
} else if ( !bDestructive ) {
InUseMessage(WSName);
pWSLObject->m_Flags &= ~WSL_MUST_REBOOT;
}
}
#endif // WINSTA
/*
* Update view.
*/
if ( bUpdateAll )
UpdateAllViews( NULL, 0, NULL );
else
UpdateAllViewsWithItem( NULL, WSLIndex, pWSLObject );
} else {
/*
* We didn't need to write any changes to the registry
* Delete the extension objects we created
*/
DeleteExtensionObject(pExtObject, WSConfig.Wd.WdName);
DeleteExtensionObject(EWSDlg.m_pExtObject, EWSDlg.m_WSConfig.Wd.WdName);
}
CancelChanges:
return(WSLIndex);
/*==============================================================================
* Error returns
*============================================================================*/
BadRegWinStationCreate:
BadInsertInWSL:
BadRegWinStationQuery:
BadRefreshWSLObjectState:
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_EDITWINSTATION, WSName,
pszFailedCall ))
}
return(-1);
} // end CAppServerDoc::EditWinStation
/*******************************************************************************
*
* DeleteWinStation - CAppServerDoc member function: public operation
*
* Delete a WinStation.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the WinStation to delete.
* EXIT:
* (BOOL) TRUE if WinStation was deleted; FALSE otherwise.
*
******************************************************************************/
BOOL
CAppServerDoc::DeleteWinStation(int WSLIndex)
{
PWSLOBJECT pWSLObject;
WINSTATIONNAME WSName;
LONG Status, LoggedOnCount = 0;
ULONG Length;
LPCTSTR pszFailedCall = NULL;
WINSTATIONCONFIG2 WSConfig;
void *pExtObject;
/*
* Get current WinStation object and assure that the WSL is 'in sync'
* with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pWSLObject = GetWSLObject(WSLIndex)) )
goto BadRefreshWSLObjectState;
lstrcpy( WSName, pWSLObject->m_WinStationName );
memset( &WSConfig, 0, sizeof(WINSTATIONCONFIG2) );
if((Status = RegistryQuery( WSName,
&WSConfig,
pWSLObject->m_WdName,
&pExtObject))) {
pszFailedCall = pApp->m_pszRegWinStationQuery;
goto BadRegWinStationQuery;
}
/*
* Confirm delete if requested.
*/
if ( pApp->m_nConfirmation ) {
long count = QueryLoggedOnCount(WSName);
UINT nType = MB_YESNO;
int id;
if ( count == 0 ) {
nType |= MB_ICONQUESTION;
id = IDP_CONFIRM_WINSTATIONDELETE;
} else if ( count == 1 ) {
nType |= MB_ICONEXCLAMATION;
id = IDP_CONFIRM_WINSTATIONDELETE_1USER;
} else {
nType |= MB_ICONEXCLAMATION;
id = IDP_CONFIRM_WINSTATIONDELETE_NUSERS;
}
if ( QuestionMessage( nType, id, WSName ) == IDNO )
goto DontDelete;
}
{
CWaitCursor wait;
/*
* Delete the registry entry.
*/
if ( (Status = RegistryDelete(WSName, WSConfig.Wd.WdName, pExtObject)) ) {
pszFailedCall = pApp->m_pszRegWinStationDelete;
goto BadRegDelete;
}
/*
* Remove WSLObject from the list.
*/
RemoveFromWSL(WSLIndex);
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
}
#endif // WINSTA
/*
* A WSLObject was removed: update the entire view.
*/
UpdateAllViews(NULL, 0, NULL);
}
DontDelete:
return(TRUE);
/*==============================================================================
* Error returns
*============================================================================*/
BadRegDelete:
BadRegWinStationQuery:
BadRefreshWSLObjectState:
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_DELETEWINSTATION, WSName,
pszFailedCall ))
}
return(FALSE);
} // CAppServerDoc::DeleteWinStation
/*******************************************************************************
*
* EnableWinStation - CAppServerDoc member function: public operation
*
* Enable or Disable specified WinStation(s).
*
* ENTRY:
* WSLIndex (input)
* WSL index of the WinStation(s) to enable or disable.
* bEnable (input)
* TRUE to enable WinStation(s); FALSE to disable WinStation(s).
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::EnableWinStation( int WSLIndex,
BOOL bEnable )
{
LONG Status;
ULONG Length;
PWSLOBJECT pWSLObject;
WINSTATIONNAME WSName;
WINSTATIONCONFIG2 WSConfig;
LPCTSTR pszFailedCall = NULL;
/*
* Get current WinStation object and assure that the WSL is 'in sync'
* with the registry.
*/
if ( !RefreshWSLObjectState( WSLIndex,
pWSLObject = GetWSLObject(WSLIndex) ) )
goto BadRefreshWSLObjectState;
lstrcpy( WSName, pWSLObject->m_WinStationName );
/*
* Fetch the WinStation's configuration structure.
*/
if ( (Status = RegWinStationQuery(
SERVERNAME_CURRENT,
pWSLObject->m_WinStationName,
&WSConfig,
sizeof(WINSTATIONCONFIG2), &Length)) ) {
pszFailedCall = pApp->m_pszRegWinStationQuery;
goto BadRegWinStationQuery;
}
/*
* Confirm disable if requested.
*/
if ( !bEnable && pApp->m_nConfirmation ) {
long count = QueryLoggedOnCount(WSName);
UINT nType = MB_YESNO;
int id;
if ( count == 0 ) {
nType |= MB_ICONQUESTION;
id = IDP_CONFIRM_WINSTATIONDISABLE;
} else if ( count == 1 ) {
nType |= MB_ICONEXCLAMATION;
id = IDP_CONFIRM_WINSTATIONDISABLE_1USER;
} else {
nType |= MB_ICONEXCLAMATION;
id = IDP_CONFIRM_WINSTATIONDISABLE_NUSERS;
}
if ( QuestionMessage( nType, id, WSName ) == IDNO )
goto DontDisable;
}
{
CWaitCursor wait;
/*
* Update registry entry.
*/
WSConfig.Create.fEnableWinStation = (bEnable ? 1 : 0);
if ( (Status = RegWinStationCreate(
SERVERNAME_CURRENT,
WSName,
FALSE,
&WSConfig,
sizeof(WSConfig))) ) {
pszFailedCall = pApp->m_pszRegWinStationCreate;
goto BadRegWinStationCreate;
}
/*
* Update WSLObject state.
*/
pWSLObject->m_Flags = (pWSLObject->m_Flags & ~WSL_ENABLED) |
(bEnable ? WSL_ENABLED : 0);
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
/*
* If we're enabling a modem winstation, issue the 'must reboot' message and
* set 'must reboot flag. Otherwise, make sure the must reboot flag is cleared.
*/
if ( bEnable && *WSConfig.Pd[0].Params.Async.ModemName ) {
QuestionMessage( MB_OK | MB_ICONEXCLAMATION,
IDP_NOTICE_REBOOTFORMODEM_ENABLE, WSName );
pWSLObject->m_Flags |= WSL_MUST_REBOOT;
} else {
pWSLObject->m_Flags &= ~WSL_MUST_REBOOT;
}
}
#endif // WINSTA
/*
* Update this WSL in the view.
*/
UpdateAllViewsWithItem( NULL, WSLIndex, pWSLObject );
}
DontDisable:
return;
/*==============================================================================
* Error returns
*============================================================================*/
BadRegWinStationCreate:
BadRegWinStationQuery:
BadRefreshWSLObjectState:
if ( pszFailedCall ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
bEnable ?
IDP_ERROR_ENABLEWINSTATION :
IDP_ERROR_DISABLEWINSTATION,
WSName,
pszFailedCall ))
}
return;
} // end CAppServerDoc::EnableWinStation
/*******************************************************************************
*
* SecurityPermissions - CAppServerDoc member function: public operation
*
* View/Edit WinStation security permissions.
*
* ENTRY:
* WSLIndex (input)
* WSL index of the selected WinStation.
*
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::SecurityPermissions(int WSLIndex)
{
PWSLOBJECT pWSLObject;
/*
* If no items yet, return immediately.
*/
if ( !(pWSLObject = GetWSLObject(WSLIndex)) )
return;
/*
* Get current WinStation object and assure that the WSL is 'in sync'
* with the registry.
*/
if ( !RefreshWSLObjectState(WSLIndex, pWSLObject) )
return;
if ( CallPermissionsDialog( pApp->m_pMainWnd->m_hWnd,
m_bAdmin,
pWSLObject->m_WinStationName ) &&
(lstrcmpi(pWSLObject->m_WinStationName, pApp->m_szSystemConsole) != 0) ) {
/*
* If we're not 'registry only', tell Session Manager
* to re-read registry and output 'in use' message if
* necessary.
*/
#ifdef WINSTA
if ( !pApp->m_nRegistryOnly ) {
_WinStationReadRegistry(SERVERNAME_CURRENT);
InUseMessage(pWSLObject->m_WinStationName);
}
#endif // WINSTA
}
} // end CAppServerDoc::SecurityPermissions
////////////////////////////////////////////////////////////////////////////////
// CAppServerDoc private operations
/*******************************************************************************
*
* LoadWSL - CAppServerDoc member function: private operation
*
* Reset the WSL to 'empty' and read the specified AppServer's WinStation
* registry information to load up the WSL.
*
* ENTRY:
* pszAppServer (input)
* Name of the AppServer to access.
*
* EXIT:
* (BOOL) TRUE if the load was successful; FALSE if error.
*
******************************************************************************/
BOOL
CAppServerDoc::LoadWSL( LPCTSTR pszAppServer )
{
LONG Status;
ULONG Index, ByteCount, Entries, LogonId;
WINSTATIONNAME WSName;
void *pExtObject = NULL;
/*
* Insure that the WSL is empty.
*/
DeleteWSLContents();
Index = 0;
for ( Index = 0, Entries = 1, ByteCount = sizeof(WINSTATIONNAME);
(Status =
RegWinStationEnumerate( SERVERNAME_CURRENT, &Index, &Entries,
WSName, &ByteCount )) == ERROR_SUCCESS;
ByteCount = sizeof(WINSTATIONNAME) ) {
WINSTATIONCONFIG2 WSConfig;
PWSLOBJECT pWSLObject;
ULONG Length;
/*
* Ignore system console.
*/
if ( !lstrcmpi(WSName, pApp->m_szSystemConsole) )
continue;
if ( (Status = RegistryQuery(WSName, &WSConfig, WSConfig.Wd.WdName,
&pExtObject)) ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_REGWINSTATIONQUERY,
WSName ))
continue;
}
/*
* Insert a WinStation object into the WinStationList.
*/
if ( InsertInWSL( WSName, &WSConfig, pExtObject, &pWSLObject ) == -1 ) {
DeleteWSLContents();
return(FALSE);
}
/*
* If this was an enabled modem WinStation and it has not been
* created by the system, flag as 'must reboot' (configured TAPI
* winstation that requires system reboot before being activated).
*/
#ifdef WINSTA
if ( (pWSLObject->m_SdClass == SdAsync) &&
(pWSLObject->m_Flags & WSL_ENABLED) &&
!(pWSLObject->m_Flags & WSL_DIRECT_ASYNC) &&
!LogonIdFromWinStationName(SERVERNAME_CURRENT, WSName, &LogonId) )
pWSLObject->m_Flags |= WSL_MUST_REBOOT;
#endif // WINSTA
}
return(TRUE);
} // end CAppServerDoc::LoadWSL
/*******************************************************************************
*
* RefreshWSLObjectState - CAppServerDoc member function: private operation
*
* Make sure that the state of the specified WSL matches the WinStation
* state in the registry.
*
* ENTRY:
* nIndex (input)
* Index of WSL being refreshed.
* pWSLObject (input/output)
* Points to the WSLOBJECT containing the WinStation(s) being
* refreshed.
* EXIT:
* (BOOL) TRUE if the refresh was successful; FALSE if error.
*
******************************************************************************/
BOOL
CAppServerDoc::RefreshWSLObjectState( int nIndex,
PWSLOBJECT pWSLObject )
{
ULONG State;
LONG Status;
/*
* Check for invalid WSLObject (return TRUE if so).
*/
if ( pWSLObject == NULL )
return(TRUE);
#ifdef UNICODE
Status = RegWinStationQueryNumValue( SERVERNAME_CURRENT,
pWSLObject->m_WinStationName,
WIN_ENABLEWINSTATION,
&State );
#else
/*
* Note: this function does not have a ANSI version: must convert the
* ANSI WINSTATIONNAME(A) into UNICODE WINSTATIONNAME(W) and call
* the UNICODE RegWinStationQueryNumValueW() API.
*/
WINSTATIONNAMEW WSNameW;
mbstowcs( WSNameW, pWSLObject->m_WinStationName, sizeof(WSNameW) );
Status = RegWinStationQueryNumValueW( SERVERNAME_CURRENT,
WSNameW,
WIN_ENABLEWINSTATION,
&State );
#endif
if ( Status != ERROR_SUCCESS ) {
STANDARD_ERROR_MESSAGE(( WINAPPSTUFF, LOGONID_NONE, Status,
IDP_ERROR_REFRESHWINSTATIONSTATE,
pWSLObject->m_WinStationName ))
return(FALSE);
}
if ( (State && !(pWSLObject->m_Flags & WSL_ENABLED)) ||
(!State && (pWSLObject->m_Flags & WSL_ENABLED)) ) {
POSITION pos;
/*
* The registry state does not match the WSL's state: update the
* WSL and cause the view to redraw it immediately.
*/
pWSLObject->m_Flags = (pWSLObject->m_Flags & ~WSL_ENABLED) |
(State ? WSL_ENABLED : 0);
UpdateAllViewsWithItem( NULL, nIndex, NULL );
GetNextView( pos = GetFirstViewPosition() )->UpdateWindow();
}
return(TRUE);
} // end CAppServerDoc::RefreshWSLObjectState
/*******************************************************************************
*
* DeleteWSLContents - CAppServerDoc member function: private operation
*
* Make sure that the WinStationObjectList is empty.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::DeleteWSLContents()
{
POSITION pos1, pos2;
PWSLOBJECT pObject;
/*
* Clean up the WinStationList.
*/
for ( pos1 = m_WinStationList.GetHeadPosition(); (pos2 = pos1) != NULL; ) {
m_WinStationList.GetNext( pos1 );
pObject = (PWSLOBJECT)m_WinStationList.GetAt( pos2 );
m_WinStationList.RemoveAt( pos2 );
delete ( pObject );
}
} // end CAppServerDoc::DeleteWSLContents
/*******************************************************************************
*
* InsertInWSL - CAppServerDoc member function: private operation
*
* Create a new WinStationList object and insert it into the WinStationList
* (if needed).
*
* ENTRY:
* pWSName (input)
* Points to name of WinStation.
* pConfig (input)
* Points to WinStation's WINSTATIONCONFIG2 structure.
* pExtObject (input)
* Points to the extension DLL's data for the WinStation
* ppObject (output)
* Points to a PWSLOBJECT pointer which is to receive the PWSLOBJECT
* for the new WinStationList object.
* EXIT:
* (int)
* index of the WinStationList object in the WinStationList; -1 if
* error.
*
******************************************************************************/
int
CAppServerDoc::InsertInWSL( PWINSTATIONNAME pWSName,
PWINSTATIONCONFIG2 pWSConfig,
void *pExtObject,
PWSLOBJECT * ppObject )
{
int Index = 0;
BOOL bAdded;
POSITION oldpos, pos;
PWSLOBJECT pObject, pListObject;
/*
* Create a new WinStationList object and initialize.
*/
if ( !(pObject = new CWinStationListObject) ) {
ERROR_MESSAGE((IDP_ERROR_WSLISTALLOC))
return(-1);
}
lstrcpy( pObject->m_WinStationName, pWSName );
lstrlwr(pObject->m_WinStationName);
pObject->m_Flags = pWSConfig->Create.fEnableWinStation ? WSL_ENABLED : 0;
pObject->m_Flags |= (pWSConfig->Pd[0].Create.PdFlag & PD_SINGLE_INST) ? WSL_SINGLE_INST : 0;
lstrcpy( pObject->m_PdName, pWSConfig->Pd[0].Create.PdName );
pObject->m_SdClass = pWSConfig->Pd[0].Create.SdClass;
lstrcpy( pObject->m_WdName, pWSConfig->Wd.WdName );
lstrcpy( pObject->m_Comment, pWSConfig->Config.Comment );
pObject->m_pExtObject = pExtObject;
pObject->m_pWdListObject = GetWdListObject(pObject->m_WdName);
if ( pObject->m_SdClass == SdAsync ) {
FormDecoratedAsyncDeviceName( pObject->m_DeviceName,
&(pWSConfig->Pd[0].Params.Async) );
} else if ( pObject->m_SdClass == SdOemTransport ) {
lstrcpy( pObject->m_DeviceName,
pWSConfig->Pd[0].Params.OemTd.DeviceName );
} else {
*(pObject->m_DeviceName) = TEXT('\0');
}
pObject->m_Flags |= (pObject->m_SdClass == SdAsync) ?
( *(pWSConfig->Pd[0].Params.Async.ModemName) ?
0 : WSL_DIRECT_ASYNC ) : 0;
pObject->m_LanAdapter = (pObject->m_SdClass == SdNetwork) ?
pWSConfig->Pd[0].Params.Network.LanAdapter : 0;
/*
* Traverse the WinStationList and insert this new WinStation,
* keeping the list sorted by SdClass, then PdName, then DirectAsync
* flag (effects SdAsync types) / LanAdapter # (effects SdNetwork
* types), then WinStationName.
*/
for ( Index = 0, bAdded = FALSE,
pos = m_WinStationList.GetHeadPosition();
pos != NULL; Index++ ) {
oldpos = pos;
pListObject = (PWSLOBJECT)m_WinStationList.GetNext( pos );
if ( (pListObject->m_SdClass > pObject->m_SdClass) ||
((pListObject->m_SdClass == pObject->m_SdClass) &&
lstrcmpi( pListObject->m_PdName,
pObject->m_PdName ) > 0) ||
((pListObject->m_SdClass == pObject->m_SdClass) &&
!lstrcmpi( pListObject->m_PdName,
pObject->m_PdName ) &&
((pListObject->m_Flags & WSL_DIRECT_ASYNC) >
(pObject->m_Flags & WSL_DIRECT_ASYNC))) ||
((pListObject->m_SdClass == pObject->m_SdClass) &&
!lstrcmpi( pListObject->m_PdName,
pObject->m_PdName ) &&
(pListObject->m_LanAdapter > pObject->m_LanAdapter)) ||
((pListObject->m_SdClass == pObject->m_SdClass) &&
!lstrcmpi( pListObject->m_PdName,
pObject->m_PdName ) &&
((pListObject->m_Flags & WSL_DIRECT_ASYNC) ==
(pObject->m_Flags & WSL_DIRECT_ASYNC)) &&
(pListObject->m_LanAdapter == pObject->m_LanAdapter) &&
(lstrcmpi( pListObject->m_WinStationName,
pObject->m_WinStationName ) > 0)) ) {
/*
* The new object belongs before the current list object.
*/
m_WinStationList.InsertBefore( oldpos, pObject );
bAdded = TRUE;
break;
}
}
/*
* If we haven't yet added the WinStation, add it now to the tail
* of the list.
*/
if ( !bAdded )
m_WinStationList.AddTail( pObject );
/*
* Set the ppObject referenced PWSLOBJECT pointer to the new PWSLOBJECT
* pointer and return the index of the new WinStationList object.
*/
*ppObject = pObject;
return( Index );
} // end CAppServerDoc::InsertInWSL
/*******************************************************************************
*
* RemoveFromWSL - CAppServerDoc member function: private operation
*
* Remove from the WSL the WSLObject associated with the specified
* index, and delete the removed WSLObject.
*
* ENTRY:
* nIndex (input)
* WSL index of the WSLObject to remove / delete.
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::RemoveFromWSL( int nIndex )
{
POSITION pos;
PWSLOBJECT pWSLObject;
/*
* Return immediately if invalid index.
*/
if ( nIndex < 0 )
return;
pWSLObject = (PWSLOBJECT)m_WinStationList.GetAt(
(pos = m_WinStationList.FindIndex(nIndex)));
m_WinStationList.RemoveAt(pos);
delete pWSLObject;
} // end CAppServerDoc::RemoveFromWSL
/*******************************************************************************
*
* UpdateAllViewsWithItem - CAppServerDoc member function: private operation
*
* Update all views of this document with a changed WinStation item.
*
* ENTRY:
*
* pSourceView (input)
* Points to document view to update (all views if NULL).
*
* nItemIndex (input)
* Document's item (WinStation) index that is causing the update
* to occur.
*
* pWSLObject (input)
* Pointer to the Document's WinStation list object pointer (may be
* NULL).
*
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::UpdateAllViewsWithItem( CView* pSourceView,
UINT nItemIndex,
PWSLOBJECT pWSLObject )
{
CWinStationListObjectHint hint;
hint.m_WSLIndex = nItemIndex;
hint.m_pWSLObject = pWSLObject;
UpdateAllViews( pSourceView, 0, &hint );
} // end CAppServerDoc::UpdateAllViewsWithItem
/*******************************************************************************
*
* InUseMessage - CAppServerDoc member function: private operation
*
* If needed, output an appropriate 'in use' message for the specified
* WinStation.
*
* ENTRY:
* pWSName (input)
* Points WinStation name to output message for.
* EXIT:
*
******************************************************************************/
void
CAppServerDoc::InUseMessage( PWINSTATIONNAME pWSName )
{
long count;
if ( (count = QueryLoggedOnCount(pWSName)) ) {
QuestionMessage(
MB_OK | MB_ICONINFORMATION,
(count == 1) ?
IDP_NOTICE_WSINUSE_1USER :
IDP_NOTICE_WSINUSE_NUSERS,
pWSName );
}
} // end CAppServerDoc::InUseMessage
/*******************************************************************************
*
* HasWSConfigChanged - CAppServerDoc member function: private operation
*
* Determine if WINSTATIONCONFIG2 structure has changed, calling our
* HasPDConfigChanged method to handle goofy PdConfig2 regapi behavior
* (straight memcmp won't work).
*
* ENTRY:
* pOldConfig (input)
* Points to the original WINSTATIONCONFIG2 structure.
* pNewConfig (input)
* Points to the new WINSTATIONCONFIG2 structure.
* pOldExtObject (input)
* Points to the original extension DLLs object
* pNewExtObject (input)
* Points to the new extension DLLs object
* EXIT:
* TRUE if original and new config structures differ;
* FALSE if no changes are detected.
*
******************************************************************************/
BOOL
CAppServerDoc::HasWSConfigChanged( PWINSTATIONCONFIG2 pOldConfig,
PWINSTATIONCONFIG2 pNewConfig,
void *pOldExtObject,
void *pNewExtObject,
PWDNAME pWdName)
{
BOOL bChanged = FALSE;
if ( memcmp( &pOldConfig->Create,
&pNewConfig->Create,
sizeof(WINSTATIONCREATE) ) ||
HasPDConfigChanged(pOldConfig, pNewConfig) ||
HasExtensionObjectChanged(pWdName, pOldExtObject, pNewExtObject) ||
memcmp( &pOldConfig->Wd,
&pNewConfig->Wd,
sizeof(WDCONFIG) ) ||
memcmp( &pOldConfig->Cd,
&pNewConfig->Cd,
sizeof(CDCONFIG) ) ||
memcmp( &pOldConfig->Config,
&pNewConfig->Config,
sizeof(WINSTATIONCONFIG) ) ) {
bChanged = TRUE;
}
return(bChanged);
} // end CAppServerDoc::HasWSConfigChanged
/*******************************************************************************
*
* HasPDConfigChanged - CAppServerDoc member function: private operation
*
* Determine if the PDConfig structures have changed, with special
* compare logic to handle goofy PdConfig2 regapi behavior (straight
* memcmp won't work).
*
* ENTRY:
* pOldConfig (input)
* Points to the original WINSTATIONCONFIG2 structure.
* pNewConfig (input)
* Points to the new WINSTATIONCONFIG2 structure.
* EXIT:
* TRUE if original and new config structures differ;
* FALSE if no changes are detected.
*
******************************************************************************/
BOOL
CAppServerDoc::HasPDConfigChanged( PWINSTATIONCONFIG2 pOldConfig,
PWINSTATIONCONFIG2 pNewConfig )
{
BOOL bChanged = FALSE;
int i;
for ( i = 0; i < MAX_PDCONFIG; i++ ) {
if ( (pOldConfig->Pd[i].Create.SdClass !=
pNewConfig->Pd[i].Create.SdClass) ||
memcmp( &pOldConfig->Pd[i].Params,
&pNewConfig->Pd[i].Params,
sizeof(PDPARAMS) ) ) {
bChanged = TRUE;
break;
}
}
return(bChanged);
} // end CAppServerDoc::HasPDConfigChanged
/*******************************************************************************
*
* HasExtensionObjectChanged - CAppServerDoc member function: private operation
*
* Determine if the object maintained by the extension DLL has changed
*
* ENTRY:
* pOldExtObject (input)
* Points to the original extension DLLs object
* pNewExtObject (input)
* Points to the new extension DLLs object
* EXIT:
* TRUE if original and new objects differ;
* FALSE if no changes are detected.
*
******************************************************************************/
BOOL
CAppServerDoc::HasExtensionObjectChanged( PWDNAME pWdName, void *pOldExtObject,
void *pNewExtObject)
{
BOOL bChanged = FALSE;
if(!pOldExtObject && !pNewExtObject) return FALSE;
if(!pOldExtObject || !pNewExtObject) return TRUE;
/*
* Ask the extension DLL if the objects are the same.
* Extension DLL returns TRUE if the objects are the same
* and FALSE if they are not,
* Therefore, we must NOT the value before returning it
*/
PTERMLOBJECT pObject = GetWdListObject(pWdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtCompareObjects) {
return !(*pObject->m_lpfnExtCompareObjects)(pOldExtObject, pNewExtObject);
}
/*
* If for some reason, we can't ask the extension DLL, play it safe and
* assume that the object has changed
*/
return TRUE;
}
/*******************************************************************************
*
* CAppServerDoc::DeleteExtensionObject
*
* Tells the extension DLL to delete an object we no longer need
*
* ENTRY:
* pExtObject (input)
* Points to the extension object
* pWdName (input)
* Points to the name of the Wd (this is used to determine
* which extension DLL owns the object)
* EXIT:
* none
*
******************************************************************************/
void CAppServerDoc::DeleteExtensionObject(void *pExtObject, PWDNAME pWdName)
{
if(pExtObject) {
/*
* Tell the extension DLL to delete this object
*/
PTERMLOBJECT pObject = GetWdListObject(pWdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDeleteObject) {
(*pObject->m_lpfnExtDeleteObject)(pExtObject);
}
}
} // end CAppServerDoc::DeleteExtensionObject
/*******************************************************************************
*
* CAppServerDoc::RegistryQuery
*
* Queries the registry for the information about a WinStation AND
* queries the extension DLL for it's information about the WinStation
*
* ENTRY:
* pWinStationName (input)
* Points to the name of the WinStation
* pWsConfig (output)
* Where to put the query results
* pWdName (input)
* Points to the name of the Wd (this is used to determine
* which extension DLL owns the object)
* pExtObject (output)
* This pointer will point to the extension DLL's object
* for this WinStation
* EXIT:
* ERROR_SUCCESS if successful
* Registry error code, if not
*
******************************************************************************/
LONG CAppServerDoc::RegistryQuery(PWINSTATIONNAME pWinStationName, PWINSTATIONCONFIG2 pWsConfig, PWDNAME pWdName, void **pExtObject)
{
LONG Status;
ULONG Length;
/*
* Query the registry for WinStation data
*/
if((Status = RegWinStationQuery( SERVERNAME_CURRENT,
pWinStationName,
pWsConfig,
sizeof(WINSTATIONCONFIG2), &Length)) ) {
return Status;
}
// Ask the extension DLL for it's data
PTERMLOBJECT pObject = GetWdListObject(pWdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegQuery) {
*pExtObject = (*pObject->m_lpfnExtRegQuery)(pWinStationName, &pWsConfig->Pd[0]);
if(!pExtObject) Status = ERROR_INVALID_FUNCTION;
}
else *pExtObject = NULL;
return Status;
} // end CAppServerDoc::RegistryQuery
/*******************************************************************************
*
* CAppServerDoc::RegistryCreate
*
* Create/Update the registry for a WinStation AND
* tell the extension DLL to store it's information about the WinStation
*
* ENTRY:
* pWinStationName (input)
* Points to the name of the WinStation
* pWsConfig (input)
* Points to the data for this WinStation
* pWdName (input)
* Points to the name of the Wd (this is used to determine
* which extension DLL owns the object)
* pExtObject (input)
* Points to the extension DLL's data for this WinStation
* EXIT:
* ERROR_SUCCESS if successful
* Registry error code, if not
*
******************************************************************************/
LONG CAppServerDoc::RegistryCreate(PWINSTATIONNAME pWinStationName, BOOLEAN bCreate, PWINSTATIONCONFIG2 pWsConfig, PWDNAME pWdName, void *pExtObject)
{
LONG Status;
if((Status = RegWinStationCreate( SERVERNAME_CURRENT,
pWinStationName,
bCreate,
pWsConfig,
sizeof(WINSTATIONCONFIG2))) ) {
return Status;
}
if(pExtObject) {
/*
* Tell the extension DLL to write it's data
*/
PTERMLOBJECT pObject = GetWdListObject(pWdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegCreate) {
Status = (*pObject->m_lpfnExtRegCreate)(pWinStationName, pExtObject, bCreate);
}
}
return Status;
} // end CAppServerDoc::RegistryCreate
/*******************************************************************************
*
* CAppServerDoc::RegistryDelete
*
* Deletes a WinStation's data from the registry AND
* tells the extension DLL to delete it's data for the WinStation from
* the registry (or wherever he stores it)
*
* ENTRY:
* pWinStationName (input)
* Points to the name of the WinStation
* pWdName (input)
* Points to the name of the Wd (this is used to determine
* which extension DLL owns the object)
* pExtObject (input)
* Points to the extension DLL's data for this WinStation
* EXIT:
* ERROR_SUCCESS if successful
* Registry error code, if not
*
******************************************************************************/
LONG CAppServerDoc::RegistryDelete(PWINSTATIONNAME pWinStationName, PWDNAME pWdName, void *pExtObject)
{
LONG Status;
LONG ExtStatus = ERROR_SUCCESS;
/*
* Tell the extension DLL to delete it's data first.
* This is done because it could be a subkey under the WinStation's data
* in the Registry. RegWinStationDelete calls RegDeleteKey which
* cannot delete subkeys under Windows NT.
*/
if(pExtObject) {
/*
* Tell the extension DLL to delete it's data
*/
PTERMLOBJECT pObject = GetWdListObject(pWdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtRegDelete) {
ExtStatus = (*pObject->m_lpfnExtRegDelete)(pWinStationName, pExtObject);
}
}
Status = RegWinStationDelete( SERVERNAME_CURRENT, pWinStationName);
if(ExtStatus) return ExtStatus;
return Status;
} // end CAppServerDoc::RegistryDelete
///////////////////////////////////////////////////////////////////////////////
// CAppServerDoc message map
BEGIN_MESSAGE_MAP(CAppServerDoc, CDocument)
//{{AFX_MSG_MAP(CAppServerDoc)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////////
// CAppServerDoc commands
/*******************************************************************************
*
* CWinStationListObject constructor
*
*
* ENTRY:
* none
* EXIT:
* constructors don't have return types
*
******************************************************************************/
CWinStationListObject::CWinStationListObject()
{
m_pExtObject = NULL;
} // end CWinStationListObject::CWinStationListObject
/*******************************************************************************
*
* CWinStationListObject destructor
*
* Tells the extension DLL to delete the object associated with this guy
*
* ENTRY:
* none
* EXIT:
* destructors don't have return types
*
******************************************************************************/
CWinStationListObject::~CWinStationListObject()
{
if(m_pExtObject) {
PTERMLOBJECT pObject = GetWdListObject(m_WdName);
if(pObject && pObject->m_hExtensionDLL && pObject->m_lpfnExtDeleteObject) {
(*pObject->m_lpfnExtDeleteObject)(m_pExtObject);
}
}
} // end CWinStationListObject::~CWinStationListObject
/*******************************************************************************
*
* GetWdListObject -
*
* Returns a pointer to the Wd list object for the specified WD
*
* ENTRY:
* pWdName (input)
* Points to the name of the Wd
* EXIT:
* pointer to Wd List Object
* NULL if not found
*
******************************************************************************/
PTERMLOBJECT GetWdListObject(PWDNAME pWdName)
{
POSITION pos;
PTERMLOBJECT pObject;
/*
* Traverse the WD list
*/
for ( pos = pApp->m_WdList.GetHeadPosition(); pos != NULL; ) {
pObject = (PTERMLOBJECT)pApp->m_WdList.GetNext( pos );
if ( !lstrcmp( pObject->m_WdConfig.Wd.WdName, pWdName ) ) {
return(pObject);
}
}
return(NULL);
} // end GetWdListObject