2883 lines
84 KiB
C++
2883 lines
84 KiB
C++
//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
|
|
|