windows-nt/Source/XPSP1/NT/termsrv/admtools/winutils/tscfg/helpers.cpp
2020-09-26 16:20:57 +08:00

534 lines
15 KiB
C++

//Copyright (c) 1998 - 1999 Microsoft Corporation
/*******************************************************************************
*
* helpers.cpp
*
* WINCFG helper functions
*
* copyright notice: Copyright 1994, Citrix Systems Inc.
*
* $Author: thanhl $ Butch Davis
*
* $Log: N:\NT\PRIVATE\UTILS\CITRIX\WINUTILS\WINCFG\VCS\HELPERS.CPP $
*
* Rev 1.17 15 Jul 1997 17:08:36 thanhl
* Add support for Required PDs
*
* Rev 1.16 27 Jun 1997 15:58:34 butchd
* Registry changes for Wds/Tds/Pds/Cds
*
* Rev 1.15 19 Jun 1997 19:22:16 kurtp
* update
*
* Rev 1.14 28 Feb 1997 17:59:38 butchd
* update
*
* Rev 1.13 24 Sep 1996 16:21:42 butchd
* update
*
*******************************************************************************/
/*
* include files
*/
#include "stdafx.h"
#include "wincfg.h"
#include "optdlg.h"
#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;
/*
* Define global variables for command line parsing helper.
*/
USHORT g_help = FALSE;
USHORT g_RegistryOnly = FALSE;
USHORT g_Add = FALSE;
WDNAME g_szType = { TEXT("") };
PDNAME g_szTransport = { TEXT("") };
ULONG g_ulCount = 0;
USHORT g_Install = FALSE; // hidden switch to let us know we're invoked by Setup
USHORT g_Batch = FALSE; // TRUE if an auto-command was specified;
// FALSE otherwise
/*
* This is the structure vector to be sent to ParseCommandLine.
*/
TOKMAP tokenmap[] =
{
/*-------------------------------------------------------------------------
-- Retail Switches
-------------------------------------------------------------------------*/
{ HELP_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_help },
{ REGISTRYONLY_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_RegistryOnly },
{ ADD_SWITCH, TMFLAG_OPTIONAL, TMFORM_STRING, WDNAME_LENGTH, g_szType },
{ TRANSPORT_SWITCH, TMFLAG_OPTIONAL, TMFORM_STRING, PDNAME_LENGTH, g_szTransport },
{ COUNT_SWITCH, TMFLAG_OPTIONAL, TMFORM_ULONG, sizeof(ULONG), &g_ulCount },
/*-------------------------------------------------------------------------
-- Debug or Hidden switches
-------------------------------------------------------------------------*/
{ INSTALL_SWITCH, TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &g_Install },
/*-------------------------------------------------------------------------
-- POSITIONAL PARAMETERS
-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------
-- END OF LIST
-------------------------------------------------------------------------*/
{ NULL, 0, 0, 0, NULL }
};
TOKMAP *ptm = tokenmap;
////////////////////////////////////////////////////////////////////////////////
// helper functions
/*******************************************************************************
*
* CommandLineHelper - helper function
*
* Parse the command line for optional parameters. This routine will also
* handle the request for 'help' and invalid command line parameter.
*
* ENTRY:
* pszCommandLine (input)
* Points to command line.
*
* EXIT:
* (BOOL) TRUE if command line was parsed sucessfully or if internal error
* (command line will be ignored).
* FALSE if 'help' requested or error on command line (message
* will have been output).
*
******************************************************************************/
BOOL
CommandLineHelper( LPTSTR pszCommandLine )
{
int rc;
int argc;
TCHAR **argv;
TCHAR szModuleName[DIRECTORY_LENGTH+1];
/*
* Get command line args
*/
GetModuleFileName( AfxGetInstanceHandle(), szModuleName,
lengthof(szModuleName) );
if ( setargv( szModuleName, pszCommandLine, &argc, &argv ) ) {
ERROR_MESSAGE((IDP_ERROR_INTERNAL_SETARGV))
goto done;
}
/*
* Parse command line args and then free them.
*/
rc = ParseCommandLine( (argc-1), (argv+1), ptm, 0 );
freeargv( argv );
/*
* Check for command line errors or help requested
*/
if ( ((rc != PARSE_FLAG_NO_ERROR) &&
!(rc & PARSE_FLAG_NO_PARMS))
|| g_help ) {
if ( rc & PARSE_FLAG_NOT_ENOUGH_MEMORY ) {
ERROR_MESSAGE((IDP_ERROR_INTERNAL_PARSECOMMANDLINE))
goto done;
} else {
CommandLineUsage();
return(FALSE);
}
}
done:
/*
* If a batch auto command was specified, set batch flag.
*/
if ( (g_Add = IsTokenPresent(ptm, ADD_SWITCH)) )
g_Batch = TRUE;
/*
* Set for registry only or full registry & winstation APIs.
*/
pApp->m_nRegistryOnly = (int)g_RegistryOnly;
/*
* If add is defined and no count given, set count to 1.
*/
if ( g_Add && (g_ulCount == 0) )
g_ulCount = 1;
return(TRUE);
} // end CommandLineHelper
/*******************************************************************************
*
* CommandLineUsage - helper function
*
* Handle the request for 'help' and invalid command line parameter.
*
* ENTRY:
* EXIT:
*
******************************************************************************/
void
CommandLineUsage()
{
COptionsDlg OPTDlg;
OPTDlg.DoModal();
} // end CommandLineUsage
/*******************************************************************************
*
* QueryLoggedOnCount - helper function
*
* Query the specified WinStation(s) to determine how many users are
* currently logged on.
*
* ENTRY:
* pWSName (input)
* Points to (root) name of WinStation to query. The query will
* match this name with those present in the ICA Server, including
* multi-instanced WinStations.
* EXIT:
* (long) # of users logged onto the specified WinStation(s).
*
******************************************************************************/
long
QueryLoggedOnCount( PWINSTATIONNAME pWSName )
{
long LoggedOnCount = 0;
#ifdef WINSTA
ULONG Entries;
PLOGONID pLogonId;
TCHAR *p;
CWaitCursor wait;
WinStationEnumerate(SERVERNAME_CURRENT, &pLogonId, &Entries);
if ( pLogonId ) {
for ( ULONG i = 0; i < Entries; i++ ) {
/*
* Check active, connected, and shadowing WinStations, and increment
* the logged on count if the specified name matches the 'root'
* name of current winstation.
*/
if ( (pLogonId[i].State == State_Active) ||
(pLogonId[i].State == State_Connected) ||
(pLogonId[i].State == State_Shadow) ) {
if ( (p = lstrchr(pLogonId[i].WinStationName, TEXT('#'))) )
*p = TEXT('\0');
if ( !lstrcmpi(pWSName, pLogonId[i].WinStationName) )
LoggedOnCount++;
}
}
WinStationFreeMemory(pLogonId);
}
#endif // WINSTA
/*
* Return the logged-on count.
*/
return(LoggedOnCount);
} // end QueryLoggedOnCount
/*******************************************************************************
*
* LBInsertInstancedName - helper function
*
* Insert the specified 'instanced' name into the specified list box,
* using a special sort based on the 'root' name and 'instance' count.
*
* ENTRY:
* pName (input)
* Pointer to name string to insert.
* pListBox (input)
* Pointer to CListBox object to insert name string into.
*
* EXIT:
* (int) List box list index of name after insertion, or error code.
*
******************************************************************************/
int
LBInsertInstancedName( LPCTSTR pName,
CListBox *pListBox )
{
int i, count, result;
TCHAR NameRoot[64], ListRoot[64];
CString ListString;
long NameInstance, ListInstance;
/*
* Form the root and instance for this name
*/
ParseRootAndInstance( pName, NameRoot, &NameInstance );
/*
* Traverse list box to perform insert.
*/
for ( i = 0, count = pListBox->GetCount(); i < count; i++ ) {
/*
* Fetch current list box string.
*/
pListBox->GetText( i, ListString );
/*
* Parse the root and instance of the list box string.
*/
ParseRootAndInstance( ListString, ListRoot, &ListInstance );
/*
* If the list box string's root is greater than the our name string's
* root, or the root strings are the same but the list instance is
* greater than the name string's instance, the name string belongs
* at the current instance: insert it there.
*/
if ( ((result = lstrcmpi( ListRoot, NameRoot )) > 0) ||
((result == 0) && (ListInstance > NameInstance)) )
return( pListBox->InsertString( i, pName ) );
}
/*
* Insert this name at the end of the list.
*/
return( pListBox->InsertString( -1, pName ) );
} // end LBInsertInstancedName
/*******************************************************************************
*
* CBInsertInstancedName - helper function
*
* Insert the specified 'instanced' name into the specified combo box,
* using a special sort based on the 'root' name and 'instance' count.
*
* ENTRY:
* pName (input)
* Pointer to name string to insert.
* pComboBox (input)
* Pointer to CComboBox object to insert name string into.
*
* EXIT:
* (int) Combo box list index of name after insertion, or error code.
*
******************************************************************************/
int
CBInsertInstancedName( LPCTSTR pName,
CComboBox *pComboBox )
{
int i, count, result;
TCHAR NameRoot[64], ListRoot[64];
CString ListString;
long NameInstance, ListInstance;
/*
* Form the root and instance for this name
*/
ParseRootAndInstance( pName, NameRoot, &NameInstance );
/*
* Traverse combo box to perform insert.
*/
for ( i = 0, count = pComboBox->GetCount(); i < count; i++ ) {
/*
* Fetch current combo (list) box string.
*/
pComboBox->GetLBText( i, ListString );
/*
* Parse the root and instance of the list box string.
*/
ParseRootAndInstance( ListString, ListRoot, &ListInstance );
/*
* If the list box string's root is greater than the our name string's
* root, or the root strings are the same but the list instance is
* greater than the name string's instance, or the root strings are
* the same and the instances are the same but the entire list string
* is greater than the entire name string, the name string belongs
* at the current list position: insert it there.
*/
if ( ((result = lstrcmpi( ListRoot, NameRoot )) > 0) ||
((result == 0) &&
(ListInstance > NameInstance)) ||
((result == 0) &&
(ListInstance == NameInstance) &&
(lstrcmpi(ListString, pName) > 0)) )
return( pComboBox->InsertString( i, pName ) );
}
/*
* Insert this name at the end of the list.
*/
return( pComboBox->InsertString( -1, pName ) );
} // end CBInsertInstancedName
/*******************************************************************************
*
* ParseRootAndInstance - helper function
*
* Parse the 'root' string and instance count for a specified string.
*
* ENTRY:
* pString (input)
* Points to the string to parse.
* pRoot (output)
* Points to the buffer to store the parsed 'root' string.
* pInstance (output)
* Points to the int variable to store the parsed instance count.
*
* EXIT:
* ParseRootAndInstance will parse only up to the first blank character
* of the string (if a blank exists).
* If the string contains no 'instance' count (no trailing digits), the
* pInstance variable will contain -1. If the string consists entirely
* of digits, the pInstance variable will contain the conversion of those
* digits and pRoot will contain a null string.
*
******************************************************************************/
void
ParseRootAndInstance( LPCTSTR pString,
LPTSTR pRoot,
long *pInstance )
{
LPCTSTR end, p;
TCHAR szString[256];
/*
* Make a copy of the string and terminate at first blank (if present).
*/
lstrncpy(szString, pString, lengthof(szString));
szString[lengthof(szString)-1] = TEXT('\0');
lstrtok(szString, TEXT(" "));
p = &(szString[lstrlen(szString)-1]);
/*
* Parse the instance portion of the string.
*/
end = p;
while( (p >= szString) && islstrdigit(*p) )
p--;
if ( p == end ) {
/*
* No trailing digits: indicate no 'instance' and make the 'root'
* the whole string.
*/
*pInstance = -1;
lstrcpy( pRoot, szString );
} else {
/*
* Trailing digits found (or entire string was digits): calculate
* 'instance' and copy the 'root' string (null if all digits).
*/
end = p;
*pInstance = (int)lstrtol( p+1, NULL, 10 );
/*
* Copy 'root' string.
*/
for ( p = szString; p <= end; pRoot++, p++ )
*pRoot = *p;
/*
* Terminate 'root' string.
*/
*pRoot = TEXT('\0');
}
} // end ParseRootAndInstance
/*******************************************************************************
*
* GetPdConfig - helper function
*
* Read the PD config structure associated with the first PD in the PdList
* of the specified PD class.
*
* ENTRY:
* pPdList (input)
* Points to the Pd list for selected Wd type.
* PdName (input)
* Specifies the Pd name to look for.
* pWSConfig (input)
* Pointer to WINSTATIONCONFIG2 structure to reference for Pd[0]
* framing type (if SdClass == SdFrame). Can be NULL if SdClass
* != SdFrame.
* pPdConfig (output)
* Pointer to PDCONFIG3 structure to fill.
* EXIT:
* nothing
*
******************************************************************************/
void
GetPdConfig( CObList *pPdList,
LPCTSTR PdName,
PWINSTATIONCONFIG2 pWSConfig,
PPDCONFIG3 pPdConfig )
{
POSITION pos;
PPDLOBJECT pObject;
BOOL bFound = FALSE;
/*
* Traverse the PD list and obtain the specified Pd's key string for query.
*/
for ( pos = pPdList->GetHeadPosition(); pos != NULL; ) {
pObject = (PPDLOBJECT)pPdList->GetNext(pos);
if ( !lstrcmp(pObject->m_PdConfig.Data.PdName, PdName ) ) {
bFound = TRUE;
break;
}
}
if ( bFound )
*pPdConfig = pObject->m_PdConfig;
} // end GetPdConfig