//Copyright (c) 1998 - 1999 Microsoft Corporation /****************************************************************************** * * QWINSTA.C * * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "qwinsta.h" LPCTSTR WINAPI StrConnectState( WINSTATIONSTATECLASS ConnectState, BOOL bShortString ); LPCTSTR WINAPI StrAsyncConnectState( ASYNCCONNECTCLASS ConnectState ); HANDLE hServerName = SERVERNAME_CURRENT; WCHAR ServerName[MAX_IDS_LEN+1]; WCHAR term_string[MAX_IDS_LEN+1]; USHORT a_flag = FALSE; USHORT c_flag = FALSE; USHORT f_flag = FALSE; USHORT m_flag = FALSE; USHORT help_flag = FALSE; USHORT fSm = FALSE; USHORT fDebug = FALSE; USHORT fVm = FALSE; USHORT counter_flag = FALSE; TOKMAP ptm[] = { {L" ", TMFLAG_OPTIONAL, TMFORM_S_STRING, MAX_IDS_LEN, term_string}, {L"/address", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &a_flag}, {L"/server", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, ServerName}, {L"/connect", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &c_flag}, {L"/flow", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &f_flag}, {L"/mode", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &m_flag}, {L"/sm", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fSm}, {L"/debug", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fDebug}, {L"/vm", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fVm}, {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &help_flag}, {L"/counter", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &counter_flag}, {0, 0, 0, 0, 0} }; #define MAX_PRINTFOA_BUFFER_SIZE 1024 char g_pWinStationName[MAX_PRINTFOA_BUFFER_SIZE]; char g_pConnectState[MAX_PRINTFOA_BUFFER_SIZE]; char g_pszState[MAX_PRINTFOA_BUFFER_SIZE]; char g_pDeviceName[MAX_PRINTFOA_BUFFER_SIZE]; char g_pWdDLL[MAX_PRINTFOA_BUFFER_SIZE]; char g_pClientName[MAX_PRINTFOA_BUFFER_SIZE]; char g_pClientAddress[MAX_PRINTFOA_BUFFER_SIZE]; char g_pUserName[MAX_PRINTFOA_BUFFER_SIZE]; WINSTATIONINFORMATION g_WinInfo; WDCONFIG g_WdInfo; WINSTATIONCONFIG g_WinConf; PDCONFIG g_PdConf; WINSTATIONCLIENT g_ClientConf; PDPARAMS g_PdParams; DEVICENAME g_DeviceName; /* * Local function prototypes */ BOOLEAN PrintWinStationInfo( PLOGONID pWd, int WdCount ); PWCHAR GetState( WINSTATIONSTATECLASS ); void DisplayBaud( ULONG BaudRate ); void DisplayParity( ULONG Parity ); void DisplayDataBits( ULONG DataBits ); void DisplayStopBits( ULONG StopBits ); void DisplayConnect( ASYNCCONNECTCLASS ConnectFlag, USHORT header_flag ); void DisplayFlow( PFLOWCONTROLCONFIG pFlow, USHORT header_flag ); void DisplayLptPorts( BYTE LptMask, USHORT header_flag ); void DisplayComPorts( BYTE ComMask, USHORT header_flag ); void OutputHeader( void ); void Usage( BOOLEAN bError ); /******************************************************************************* * * main * ******************************************************************************/ int __cdecl main(INT argc, CHAR **argv) { PLOGONID pWd; ULONG ByteCount, Index; UINT WdCount; ULONG Status; int rc, i; WCHAR **argvW; BOOLEAN MatchedOne = FALSE; BOOLEAN PrintWinStationInfo(PLOGONID pWd, int Count); TS_COUNTER TSCounters[3]; setlocale(LC_ALL, ".OCP"); /* * Massage the command line. */ argvW = MassageCommandLine((DWORD)argc); if (argvW == NULL) { ErrorPrintf(IDS_ERROR_MALLOC); return(FAILURE); } /* * parse the cmd line without parsing the program name (argc-1, argv+1) */ rc = ParseCommandLine(argc-1, argvW+1, ptm, 0); /* * Check for error from ParseCommandLine */ if ( help_flag || (rc && !(rc & PARSE_FLAG_NO_PARMS)) ) { if ( !help_flag ) { Usage(TRUE); return(FAILURE); } else { Usage(FALSE); return(SUCCESS); } } // If no remote server was specified, then check if we are running under Terminal Server if ((!IsTokenPresent(ptm, L"/server") ) && (!AreWeRunningTerminalServices())) { ErrorPrintf(IDS_ERROR_NOT_TS); return(FAILURE); } /* * Open the specified server */ if( ServerName[0] ) { hServerName = WinStationOpenServer( ServerName ); if( hServerName == NULL ) { StringErrorPrintf(IDS_ERROR_SERVER,ServerName); PutStdErr( GetLastError(), 0 ); return(FAILURE); } } #if 0 // // Print local WINSTATION VM info // if( fVm ) { PrintWinStationVmInfo(); return( SUCCESS ); } #endif /* * if no winstation was specified, display all winstations */ if ( !(*term_string) ) wcscpy( term_string, L"*" ); /* * Allocate buffer for WinStation ids */ WdCount = 10; if ( (pWd = malloc( WdCount * sizeof(LOGONID) )) == NULL ) { ErrorPrintf(IDS_ERROR_MALLOC); goto tscounters; } ByteCount = WdCount * sizeof(LOGONID); Index = 0; // Start enumeration from the begining /* * get list of active WinStations */ rc = WinStationEnumerate( hServerName, &pWd, &WdCount ); if ( rc ) { if ( PrintWinStationInfo(pWd, WdCount) ) MatchedOne = TRUE; WinStationFreeMemory(pWd); } else { Status = GetLastError(); ErrorPrintf(IDS_ERROR_WINSTATION_ENUMERATE, Status); PutStdErr( Status, 0 ); goto tscounters; } /* * Check for at least one match */ if ( !MatchedOne ) { StringErrorPrintf(IDS_ERROR_WINSTATION_NOT_FOUND, term_string); goto tscounters; } tscounters: if (counter_flag) { TSCounters[0].counterHead.dwCounterID = TERMSRV_TOTAL_SESSIONS; TSCounters[1].counterHead.dwCounterID = TERMSRV_DISC_SESSIONS; TSCounters[2].counterHead.dwCounterID = TERMSRV_RECON_SESSIONS; rc = WinStationGetTermSrvCountersValue(hServerName, 3, TSCounters); if (rc) { if (TSCounters[0].counterHead.bResult == TRUE) { Message(IDS_TSCOUNTER_TOTAL_SESSIONS, TSCounters[0].dwValue); } if (TSCounters[1].counterHead.bResult == TRUE) { Message(IDS_TSCOUNTER_DISC_SESSIONS, TSCounters[1].dwValue); } if (TSCounters[2].counterHead.bResult == TRUE) { Message(IDS_TSCOUNTER_RECON_SESSIONS, TSCounters[2].dwValue); } } else { ErrorPrintf(IDS_ERROR_TERMSRV_COUNTERS); } } return(SUCCESS); } /* main() */ /****************************************************************************** * * PrintWinStationInfo * * Printout the WinStation Information for the WinStations described in * the PLOGONID array. * * ENTRY: * pWd (input) * pointer to array of LOGONID structures. * WdCount (input) * number of elements in the pWd array. * * EXIT: * TRUE if at least one WinStation was output; FALSE if none. * *****************************************************************************/ BOOLEAN PrintWinStationInfo( PLOGONID pWd, int WdCount ) { int i, rc; ULONG ErrorCode; ULONG ReturnLength; PWCHAR pState; UINT MatchedOne = FALSE; static UINT HeaderFlag = FALSE; /* * Output terminal ids */ for ( i=0; i < WdCount; i++ ) { if ( fSm || fDebug ) { { WideCharToMultiByte(CP_OEMCP, 0, pWd[i].WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, GetState( pWd[i].State ), -1, g_pConnectState, sizeof(g_pConnectState), NULL, NULL); fprintf( stdout, "%4u %-20s %s\n", pWd[i].LogonId, g_pWinStationName, g_pConnectState ); } if ( !fDebug ) continue; } if ( !WinStationObjectMatch( hServerName , &pWd[i], term_string ) ) continue; /* * Get all available information so we can pick out what we need as * well as verify the API's */ memset( &g_WinInfo, 0, sizeof(WINSTATIONINFORMATION) ); memset( &g_WdInfo, 0, sizeof(WDCONFIG) ); memset( &g_WinConf, 0, sizeof(WINSTATIONCONFIG) ); memset( &g_PdConf, 0, sizeof(PDCONFIG) ); memset( &g_ClientConf, 0, sizeof(WINSTATIONCLIENT) ); memset( &g_PdParams, 0, sizeof(PDPARAMS) ); memset( &g_DeviceName, 0, sizeof(DEVICENAME) ); /* * If this WinStation is 'down', don't open and query. */ if ( pWd[i].State == State_Init || pWd[i].State == State_Down ) { g_WinInfo.ConnectState = pWd[i].State; } else { /* * Query WinStation's information. */ rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationInformation, (PVOID)&g_WinInfo, sizeof(WINSTATIONINFORMATION), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(WINSTATIONINFORMATION) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationInformation", ReturnLength, sizeof(WINSTATIONINFORMATION)); continue; } rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationWd, (PVOID)&g_WdInfo, sizeof(WDCONFIG), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(WDCONFIG) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationWd", ReturnLength, sizeof(WDCONFIG)); continue; } rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationConfiguration, (PVOID)&g_WinConf, sizeof(WINSTATIONCONFIG), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(WINSTATIONCONFIG) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationConfiguration", ReturnLength, sizeof(WINSTATIONCONFIG)); continue; } rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationPd, (PVOID)&g_PdConf, sizeof(PDCONFIG), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(PDCONFIG) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationPd", ReturnLength, sizeof(PDCONFIG)); continue; } rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationClient, (PVOID)&g_ClientConf, sizeof(WINSTATIONCLIENT), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(WINSTATIONCLIENT) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationClient", ReturnLength, sizeof(WINSTATIONCLIENT)); continue; } rc = WinStationQueryInformation( hServerName, pWd[i].LogonId, WinStationPdParams, (PVOID)&g_PdParams, sizeof(PDPARAMS), &ReturnLength); if( !rc ) { continue; } if( ReturnLength != sizeof(PDPARAMS) ) { ErrorPrintf(IDS_ERROR_WINSTATION_INFO_VERSION_MISMATCH, L"WinStationPdParams", ReturnLength, sizeof(PDPARAMS)); continue; } } /* * If this is a PdAsync Protocol, get the device name to display. */ if ( g_PdParams.SdClass == SdAsync ) wcscpy( g_DeviceName, g_PdParams.Async.DeviceName ); /* * Flag sucessful match. */ MatchedOne = TRUE; /* * trucate and convert to lower case */ TruncateString( _wcslwr(g_WinInfo.WinStationName), 16 ); TruncateString( _wcslwr(g_WdInfo.WdName), 8 ); TruncateString( _wcslwr(g_DeviceName), 8 ); TruncateString( _wcslwr(g_WdInfo.WdDLL), 13 ); /* * Determine WinStation state */ pState = GetState( g_WinInfo.ConnectState ); /* * output header */ if ( !HeaderFlag ) { HeaderFlag = TRUE; OutputHeader(); } /* * identify current terminal */ if ( (hServerName == SERVERNAME_CURRENT) && (pWd[i].LogonId == GetCurrentLogonId() ) ) wprintf( L">" ); else wprintf( L" " ); if ( m_flag ) { { WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, pState, -1, g_pszState, sizeof(g_pszState), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_DeviceName, -1, g_pDeviceName, sizeof(g_pDeviceName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_WdInfo.WdDLL, -1, g_pWdDLL, sizeof(g_pWdDLL), NULL, NULL); fprintf(stdout , FORMAT_M, g_pWinStationName, g_pszState, g_pDeviceName, g_pWdDLL ); } DisplayBaud( g_PdParams.Async.BaudRate ); DisplayParity( g_PdParams.Async.Parity ); DisplayDataBits( g_PdParams.Async.ByteSize ); DisplayStopBits( g_PdParams.Async.StopBits ); wprintf( L"\n" ); if ( f_flag ) { DisplayFlow( &g_PdParams.Async.FlowControl, TRUE ); wprintf( L"\n" ); } if ( c_flag ) { DisplayConnect( g_PdParams.Async.Connect.Type, TRUE ); wprintf( L"\n" ); } fflush( stdout ); } else if ( f_flag && c_flag ) { { WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_DeviceName, -1, g_pDeviceName, sizeof(g_pDeviceName), NULL, NULL); fprintf(stdout,FORMAT_F_C, g_pWinStationName, g_pDeviceName ); } DisplayFlow( &g_PdParams.Async.FlowControl, FALSE ); DisplayConnect( g_PdParams.Async.Connect.Type, FALSE ); wprintf( L"\n" ); fflush( stdout ); } else if ( c_flag ) { { WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, pState, -1, g_pszState, sizeof(g_pszState), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_DeviceName, -1, g_pDeviceName, sizeof(g_pDeviceName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_WdInfo.WdDLL, -1, g_pWdDLL, sizeof(g_pWdDLL), NULL, NULL); fprintf(stdout,FORMAT_C, g_pWinStationName, g_pszState, g_pDeviceName, g_pWdDLL ); } DisplayConnect( g_PdParams.Async.Connect.Type, FALSE ); wprintf( L"\n" ); fflush(stdout); } else if ( f_flag ) { { WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, pState, -1, g_pszState, sizeof(g_pszState), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_DeviceName, -1, g_pDeviceName, sizeof(g_pDeviceName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_WdInfo.WdDLL, -1, g_pWdDLL, sizeof(g_pWdDLL), NULL, NULL); fprintf(stdout,FORMAT_F, g_pWinStationName, g_pszState, g_pDeviceName, g_pWdDLL ); } DisplayFlow( &g_PdParams.Async.FlowControl, FALSE ); wprintf( L"\n" ); fflush(stdout); } else { { WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.WinStationName, -1, g_pWinStationName, sizeof(g_pWinStationName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_WinInfo.UserName, -1, g_pUserName, sizeof(g_pUserName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, pState, -1, g_pszState, sizeof(g_pszState), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_DeviceName, -1, g_pDeviceName, sizeof(g_pDeviceName), NULL, NULL); WideCharToMultiByte(CP_OEMCP, 0, g_WdInfo.WdDLL, -1, g_pWdDLL, sizeof(g_pWdDLL), NULL, NULL); fprintf(stdout,FORMAT_DEFAULT, g_pWinStationName, g_pUserName, pWd[i].LogonId, g_pszState, g_pWdDLL, g_pDeviceName); } fflush(stdout); } } // end for(;;) return( MatchedOne || fSm ); } /* PrintWinStationInfo() */ /******************************************************************************* * * GetState * * This routine returns a pointer to a string describing the * current WinStation state. * * ENTRY: * State (input) * winstation state * * EXIT: * pointer to state string * ******************************************************************************/ PWCHAR GetState( WINSTATIONSTATECLASS State ) { PWCHAR pState; pState = (PWCHAR) StrConnectState(State,TRUE); /* switch ( State ) { case State_Active : pState = L"active"; break; case State_Connected : pState = L"conn"; break; case State_ConnectQuery : pState = L"connQ"; break; case State_Shadow : pState = L"shadow"; break; case State_Disconnected : pState = L"disc"; break; case State_Idle : pState = L"idle"; break; case State_Reset : pState = L"reset"; break; case State_Down : pState = L"down"; break; case State_Init : pState = L"init"; break; case State_Listen : pState = L"listen"; break; default : pState = L"unknown"; break; } */ return( pState ); } /******************************************************************************* * * DisplayBaud * * This routine displays the baud rate * * * ENTRY: * BaudRate (input) * baud rate * * EXIT: * nothing * ******************************************************************************/ void DisplayBaud( ULONG BaudRate ) { if ( BaudRate > 0 ) wprintf( L"%6lu ", BaudRate ); else wprintf( L" " ); fflush( stdout ); } /* DisplayBaud() */ /******************************************************************************* * * DisplayParity * * This routine displays parity * * * ENTRY: * Parity (input) * parity * * EXIT: * nothing * ******************************************************************************/ void DisplayParity( ULONG Parity ) { WCHAR szParity[64] = L""; switch ( Parity ) { case 0 : case 1 : case 2 : // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. // LoadString(NULL, IDS_PARITY_NONE + Parity, szParity, sizeof(szParity) / sizeof(WCHAR)); wprintf( szParity ); break; default : LoadString(NULL, IDS_PARITY_BLANK, szParity, sizeof(szParity) / sizeof(WCHAR)); wprintf( szParity ); break; } fflush( stdout ); } /* DisplayParity() */ /******************************************************************************* * * DisplayDataBits * * This routine displays number of data bits * * * ENTRY: * DataBits (input) * data bits * * EXIT: * nothing * ******************************************************************************/ void DisplayDataBits( ULONG DataBits ) { WCHAR szDataBits[64] = L""; // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. The // wprintf below, with an extra argument, won't cause any problems // if the LoadString fails. // if ( DataBits > 0 ) { LoadString(NULL, IDS_DATABITS_FORMAT, szDataBits, sizeof(szDataBits) / sizeof(WCHAR)); wprintf( szDataBits , DataBits ); } else { LoadString(NULL, IDS_DATABITS_BLANK, szDataBits, sizeof(szDataBits) / sizeof(WCHAR)); wprintf( szDataBits ); } fflush( stdout ); } /* DisplayDataBits() */ /******************************************************************************* * * DisplayStopBits * * This routine displays the number of stop bits * * * ENTRY: * StopBits (input) * number of stop bits * * EXIT: * nothing * ******************************************************************************/ void DisplayStopBits( ULONG StopBits ) { WCHAR szStopBits[64] = L""; switch ( StopBits ) { case 0 : case 1 : case 2 : // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. // LoadString(NULL, IDS_STOPBITS_ONE + StopBits, szStopBits, sizeof(szStopBits) / sizeof(WCHAR)); wprintf( szStopBits ); break; default : LoadString(NULL, IDS_STOPBITS_BLANK, szStopBits, sizeof(szStopBits) / sizeof(WCHAR)); wprintf( szStopBits ); break; } fflush( stdout ); } /* DisplayStopBits() */ /******************************************************************************* * * DisplayConnect * * This routine displays the connect settings * * * ENTRY: * ConnectFlag (input) * connect flags * header_flag (input) * TRUE to display sub-header; FALSE otherwise. * * EXIT: * nothing * ******************************************************************************/ void DisplayConnect( ASYNCCONNECTCLASS ConnectFlag, USHORT header_flag ) { WCHAR buffer[80] = L""; // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. The // wprintf below, with an extra argument, won't cause any problems // if the LoadString fails. // if ( header_flag ) { LoadString(NULL, IDS_CONNECT_HEADER, buffer, sizeof(buffer) / sizeof(WCHAR)); wprintf(buffer); } buffer[0] = (WCHAR)NULL; LoadString(NULL, IDS_CONNECT_FORMAT, buffer, sizeof(buffer) / sizeof(WCHAR)); wprintf( buffer, StrAsyncConnectState(ConnectFlag) ); fflush( stdout ); } /* DisplayConnect() */ /******************************************************************************* * * DisplayFlow * * This routine displays the flow control settings * * * ENTRY: * pFlow (input) * Pointer to flow control configuration structure * header_flag (input) * TRUE to display sub-header; FALSE otherwise. * * EXIT: * nothing * ******************************************************************************/ void DisplayFlow( PFLOWCONTROLCONFIG pFlow, USHORT header_flag ) { WCHAR buffer[90], buf2[90], format[90]; buffer[0] = 0; buf2[0] = 0; format[0] = 0; // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. The // wprintf below, with an extra argument, won't cause any problems // if the LoadString fails. // if ( header_flag ) { LoadString(NULL, IDS_FLOW_HEADER, buffer, sizeof(buffer) / sizeof(WCHAR)); wprintf(buffer); } buffer[0] = (WCHAR)NULL; if( pFlow->fEnableDTR ) { LoadString(NULL, IDS_FLOW_ENABLE_DTR, buf2, sizeof(buf2) / sizeof(WCHAR)); wcscat(buffer, buf2); } buf2[0] = (WCHAR)NULL; if( pFlow->fEnableRTS ) { LoadString(NULL, IDS_FLOW_ENABLE_DTR, buf2, sizeof(buf2) / sizeof(WCHAR)); wcscat(buffer, buf2); } buf2[0] = (WCHAR)NULL; /* * Hardware and Software flow control are mutually exclusive */ if( pFlow->Type == FlowControl_Hardware ) { if ( pFlow->HardwareReceive == ReceiveFlowControl_None ) { LoadString(NULL, IDS_FLOW_RECEIVE_NONE, buf2, sizeof(buf2) / sizeof(WCHAR)); } else if ( pFlow->HardwareReceive == ReceiveFlowControl_RTS ) { LoadString(NULL, IDS_FLOW_RECEIVE_RTS, buf2, sizeof(buf2) / sizeof(WCHAR)); } else if ( pFlow->HardwareReceive == ReceiveFlowControl_DTR ) { LoadString(NULL, IDS_FLOW_RECEIVE_DTR, buf2, sizeof(buf2) / sizeof(WCHAR)); } wcscat(buffer, buf2); buf2[0] = (WCHAR)NULL; if ( pFlow->HardwareTransmit == TransmitFlowControl_None ) { LoadString(NULL, IDS_FLOW_TRANSMIT_NONE, buf2, sizeof(buf2) / sizeof(WCHAR)); } else if ( pFlow->HardwareTransmit == TransmitFlowControl_CTS ) { LoadString(NULL, IDS_FLOW_TRANSMIT_CTS, buf2, sizeof(buf2) / sizeof(WCHAR)); } else if ( pFlow->HardwareTransmit == TransmitFlowControl_DSR ) { LoadString(NULL, IDS_FLOW_TRANSMIT_DSR, buf2, sizeof(buf2) / sizeof(WCHAR)); } wcscat(buffer, buf2); } else if ( pFlow->Type == FlowControl_Software ) { if ( pFlow->fEnableSoftwareTx ) { LoadString(NULL, IDS_FLOW_SOFTWARE_TX, buf2, sizeof(buf2) / sizeof(WCHAR)); } wcscat(buffer, buf2); buf2[0] = (WCHAR)NULL; if( pFlow->fEnableSoftwareRx ) { LoadString(NULL, IDS_FLOW_SOFTWARE_TX, buf2, sizeof(buf2) / sizeof(WCHAR)); } wcscat(buffer, buf2); buf2[0] = (WCHAR)NULL; if ( pFlow->XonChar == 0x65 && pFlow->XoffChar == 0x67 ) { LoadString(NULL, IDS_FLOW_SOFTWARE_TX, buf2, sizeof(buf2) / sizeof(WCHAR)); } else if( pFlow->fEnableSoftwareTx || pFlow->fEnableSoftwareRx ) { LoadString(NULL, IDS_FLOW_SOFTWARE_TX, format, sizeof(format) / sizeof(WCHAR)); wsprintf( buf2, format, pFlow->XonChar, pFlow->XoffChar ); format[0] = (WCHAR)NULL; } wcscat( buffer, buf2 ); } LoadString(NULL, IDS_FLOW_FORMAT, format, sizeof(format) / sizeof(WCHAR)); wprintf( format, buffer ); fflush( stdout ); } /* DisplayFlow() */ /******************************************************************************* * * DisplayLptPorts * * This routine displays the LPT ports that exist for a winstation * * * ENTRY: * LptMask (input) * LPT port mask * header_flag (input) * TRUE to display sub-header; FALSE otherwise. * * EXIT: * nothing * ******************************************************************************/ void DisplayLptPorts( BYTE LptMask, USHORT header_flag ) { WCHAR buffer[80], buf2[10], lptname[6]; int i; buffer[0] = 0; buf2[0] = 0; lptname[0] = 0; // // How does one handle a LoadString failure??? I choose to initialize // the storage to an empty string, and then ignore any failure. The // wprintf below, with an extra argument, won't cause any problems // if the LoadString fails. // if ( header_flag ) { LoadString(NULL, IDS_LPT_HEADER, buffer, sizeof(buffer) / sizeof(WCHAR)); wprintf(buffer); } buffer[0] = (WCHAR)NULL; LoadString(NULL, IDS_LPT_FORMAT, buf2, sizeof(buf2) / sizeof(WCHAR)); /* * Display from the 8 possible LPT ports. */ for ( i=0; i < 8; i++ ) { if ( LptMask & (1<