|
|
// Copyright (c) 1998-1999 Microsoft Corporation
/*******************************************************************************
* * utildll.c * * UTILDLL multi-user utility support functions * * *******************************************************************************/
/*
* include files */ #include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddkbd.h>
#include <ntddmou.h>
#include <ntcsrsrv.h>
#include <ntlsa.h>
#include <ntsam.h>
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <nb30.h>
#include <tapi.h>
#include <raserror.h>
#include <lmerr.h>
#include <lmcons.h>
#include <lmaccess.h>
#include <lmserver.h>
#include <lmwksta.h>
#include <lmremutl.h>
#include <lmapibuf.h>
#define INITGUID
#include "objbase.h"
#include "initguid.h"
//#include "basetyps.h"
#include "devguid.h"
#include "setupapi.h"
#include <winsta.h>
#include <utildll.h>
#include "..\inc\utilsub.h"
#include "..\inc\ansiuni.h"
#include "resource.h"
/*
* Hydrix helpers function internal defines */ #define INITIAL_ENUMERATION_COUNT 16
#define REGISTRY_NETCARDS TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards")
#define REGISTRY_TITLE TEXT("Title")
#define REGISTRY_SERVICE_NAME TEXT("ServiceName")
#define REGISTRY_HIDDEN TEXT("Hidden")
#define REGISTRY_ROUTE TEXT("Route")
#define REGISTRY_NETBLINKAGE TEXT("SYSTEM\\CurrentControlSet\\Services\\NetBIOS\\Linkage")
#define REGISTRY_NETBLINKAGE_LANAMAP TEXT("LanaMap")
#define REGISTRY_SERVICES TEXT("SYSTEM\\CurrentControlSet\\Services")
#define REGISTRY_DISPLAY_NAME TEXT("DisplayName")
/*
* TAPI defines. */ #define LOW_MAJOR_VERSION 0x0001
#define LOW_MINOR_VERSION 0x0003
#define HIGH_MAJOR_VERSION 0x0002
#define HIGH_MINOR_VERSION 0x0000
#define LOW_VERSION ((LOW_MAJOR_VERSION << 16) | LOW_MINOR_VERSION)
#define HIGH_VERSION ((HIGH_MAJOR_VERSION << 16) | HIGH_MINOR_VERSION)
/*=============================================================================
== Local Functions Defined =============================================================================*/ BOOL CheckForComDevice( LPTSTR ); int NetBiosLanaEnum( LANA_ENUM * pLanaEnum ); DWORD EnumerateTapiPorts( PPDPARAMS pPdParams, ULONG Count, ULONG **ppEntries ); VOID CALLBACK DummyTapiCallback(HANDLE, DWORD, DWORD, DWORD, DWORD, DWORD); BOOL GetAssociatedPortName(char *szKeyName, WCHAR *wszPortName); BOOL _UserInGroup( LPWSTR pwszUsername, LPWSTR pwszDomain, LPWSTR pwszGroup );
/*******************************************************************************
* * StandardErrorMessage - Hydrix helper function * * Output an error message with optional additional arguments like the * ErrorMessagexxx routines. Additionally, a standard error line will * also be output containing the error code and error message associated * with that code. * * ENTRY: * pszAppName (input) * Application name for error message box title. * hwndApp (input) * Owner window for error message box. * hinstApp (input) * Instance handle of application. * LogonId (input) * Optional WinStation LogonId for querying special error strings * from WinStation via WinStationGetInformation API. If this value * is LOGONID_NONE then no special error message code checking will * be done. * nId (input) * System message code to get standard error string for. * nErrorResourceID (input) * Resource ID of the format string to use in the error message. * ... (input) * Optional additional arguments to be used with format string. * * EXIT: * ******************************************************************************/
void WINAPI StandardErrorMessage( LPCTSTR pszAppName, HWND hwndApp, HINSTANCE hinstApp, ULONG LogonId, UINT nId, int nErrorMessageLength, int nArgumentListLength, int nErrorResourceID, ...) { TCHAR* szClientErrorMessage = NULL; TCHAR* szClientResourceString = NULL; TCHAR* szError = NULL; TCHAR* szFormattedErrorMessage = NULL; TCHAR* szMessage = NULL; TCHAR szStandardErrorMessage[STANDARD_ERROR_TEXT_LENGTH + 1];
va_list args; va_start( args, nErrorResourceID );
szClientErrorMessage = (TCHAR*)malloc((nErrorMessageLength + 1) * sizeof(TCHAR)); if (szClientErrorMessage) { LoadString( hinstApp, nErrorResourceID, szClientErrorMessage, nErrorMessageLength );
szClientResourceString = (TCHAR*)malloc((wcslen(szClientErrorMessage) + nArgumentListLength + 1) * sizeof(TCHAR)); if (szClientResourceString != NULL) { wvsprintf( szClientResourceString, szClientErrorMessage, args );
LoadString( GetModuleHandle( UTILDLL_NAME ), IDS_STANDARD_ERROR_FORMAT, szStandardErrorMessage, STANDARD_ERROR_TEXT_LENGTH );
szError = GetSystemMessage( LogonId, nId); if (szError != NULL) { szFormattedErrorMessage = (TCHAR*)malloc((wcslen(szStandardErrorMessage) + 10 + wcslen(szError) + 1) * sizeof(TCHAR)); if (szFormattedErrorMessage != NULL) { wsprintf( szFormattedErrorMessage, szStandardErrorMessage, nId, szError);
//lstrcpy(sz1, pszAppName);
szMessage = (TCHAR*)malloc((wcslen(szClientResourceString) + wcslen(szFormattedErrorMessage) + 1) * sizeof(TCHAR)); if (szMessage != NULL) { wcscpy(szMessage, szClientResourceString); wcscat(szMessage, szFormattedErrorMessage);
MessageBox( hwndApp, szMessage, pszAppName, MB_OK | MB_ICONEXCLAMATION ); free(szMessage); } free(szFormattedErrorMessage); } free (szError); } free(szClientResourceString); } free (szClientErrorMessage); } va_end(args); } // end StandardErrorMessage
/*******************************************************************************
* * GetSystemMessageA - Hydrix helper function (ANSI stub) * * Return the string associated with the specified system message. * * ENTRY: * (refer to GetSystemMessageW) * EXIT: * (refer to GetSystemMessageW) * If cannot allocate temporary UNICODE buffer to call GetSystemMessageW * with, the ntents of chBuffer will be set to the "(no error text * available)" string. * ******************************************************************************/
LPSTR WINAPI GetSystemMessageA( ULONG LogonId, UINT nId /*LPSTR chBuffer,
int cbBuffSize*/ ) { LPWSTR uBuffer = NULL; LPSTR aBuffer = NULL; int length; //Call the GetSystemMessageW function
uBuffer = GetSystemMessageW(LogonId, nId); if (uBuffer == NULL) { //If no message was returned from the GetSystemMessageW
//function just return a generic error message
aBuffer = malloc((NO_ERROR_TEXT_LENGTH + 1) * sizeof(char)); if (aBuffer == NULL) return NULL;
length = LoadStringA( GetModuleHandle( UTILDLL_NAME ), IDS_NO_ERROR_TEXT_AVAILABLE, aBuffer, NO_ERROR_TEXT_LENGTH ); ASSERT(length); } else { length = wcslen(uBuffer) + 1;
//Convert the result into ANSI in caller supplied buffer.
aBuffer = malloc(length * sizeof(char)); if (aBuffer != NULL) WideCharToMultiByte(CP_ACP, 0, uBuffer, length - 1, aBuffer, length, 0, 0);
//Free the temporary buffer.
free (uBuffer); }
//Return message.
return(aBuffer); } // end GetSystemMessageA
/*******************************************************************************
* * GetSystemMessageW - Hydrix helper function (UNICODE version) * * Return the string associated with the specified system message. * * ENTRY: * LogonId (input) * Optional WinStation LogonId for querying special error strings * from WinStation via WinStationGetInformation API. If this value * is LOGONID_NONE then no special error message code checking will * be done. * nId (input) * System message code to get string for. * chBuffer (input) * Points to buffer to fill with system message string. * cbBuffSize (input) * Maximum number of characters that can be placed in chBuffer. * * EXIT: * Returns chBuffer. Contents of chBuffer will always be set; to * the "(no error text available)" string if error. * * Note: the total length of chBuffer (including terminating NULL) will * not exceed the size of the internal temporary buffer (Buffer). * ******************************************************************************/
//NA 3/9/01 IMPORTANT: Behavior has changed. Instead of expecting a buffer long
//enough to accomodate the message, it now allocates the memory dynamically, so
//it's up to the calling procedure to deallocate it.
LPWSTR WINAPI GetSystemMessageW( ULONG LogonId, UINT nId /*LPWSTR chBuffer,
int cbBuffSize*/ ) { LPWSTR chBuffer = NULL;
WCHAR StackBuffer[512]; WCHAR* SpecialBuffer = NULL; WCHAR* Buffer = NULL; BOOL bSpecialCitrixError = FALSE; HINSTANCE cxerror = LoadLibraryW(L"cxerror.dll"); int length = 0;
StackBuffer[0]=0;
//If we have a valid LogonId passed in, determine if the error
//is a special code requiring that the specific error string be
//queried from the WinStation.
if ( LogonId != LOGONID_NONE ) { switch ( nId ) { case ERROR_CTX_TD_ERROR: length = LoadStringW( GetModuleHandle( UTILDLL_NAME ), IDS_NO_ADDITIONAL_ERROR_INFO, StackBuffer, sizeof(StackBuffer)/sizeof(WCHAR) ); ASSERT(length); SpecialBuffer = malloc((length + 1) * sizeof(WCHAR)); if (SpecialBuffer != NULL) { wcscpy(SpecialBuffer, StackBuffer); bSpecialCitrixError = TRUE; } break;
default: break; } }
//See if this is a Citrix error message first...
if ( !cxerror || !FormatMessageW( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER, (LPCVOID)cxerror, nId, 0, (LPWSTR)&Buffer, 0, NULL ) ) { //It's not a Citrix error message; fetch system message.
if ( !FormatMessageW( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, nId, 0, (LPWSTR)&Buffer, 0, NULL ) ) { //It's not a system message; don't know what the message is...
length = LoadStringW( GetModuleHandle( UTILDLL_NAME ), IDS_NO_ERROR_TEXT_AVAILABLE, StackBuffer, sizeof(StackBuffer)/sizeof(WCHAR) ); ASSERT(length); Buffer = LocalAlloc(0,(length + 1) * sizeof(WCHAR)); if (Buffer == NULL) { if (SpecialBuffer != NULL) free (SpecialBuffer); return NULL; } wcscpy(Buffer, StackBuffer); } } if ( cxerror ) FreeLibrary(cxerror);
length = wcslen(Buffer); if ( bSpecialCitrixError ) length += wcslen(SpecialBuffer) + 2;
chBuffer = malloc((length + 1) * sizeof(WCHAR)); if (chBuffer != NULL) { wcscpy(chBuffer, Buffer);
//If we fetched a special Citrix error string, tack it onto the end
//of whatever we've buffered already.
if ( bSpecialCitrixError ) { lstrcatW(chBuffer, L" "); lstrcatW(chBuffer, SpecialBuffer); } }
if (Buffer != NULL) LocalFree (Buffer);
if (( bSpecialCitrixError ) && (SpecialBuffer != NULL)) free (SpecialBuffer);
return(chBuffer);
} // end GetSystemMessageW
/*******************************************************************************
* * WinEnumerateDevices - Hydrix helper function * * Perform PD device enumeration for the specified PD. * * ENTRY: * hWnd (input) * Parent window for error message, if needed. * pPdConfig (input) * Points to PDCONFIG3 structure of the PD. * pEntries (output) * Points to variable to return number of devices that were enumerated. * bInSetup (input) * TRUE if we're operating in Setup; FALSE otherwise. * * EXIT: * (PPDPARAMS) Points to the PDPARAMS array containing the enumeration * results if sucessful. The caller must perform a LocalFree * of this array when done. NULL if error; error set for * GetLastError(); * If the returned error code is anything other than * ERROR_NOT_ENOUGH_MEMORY, the caller can assume that none of the * requested devices were available to be enumerated. * ******************************************************************************/
typedef BOOL (WINAPI * PPDENUMERATE)( PPDCONFIG3, PULONG, PPDPARAMS, PULONG, BOOL );
PPDPARAMS WINAPI WinEnumerateDevices( HWND hWnd, PPDCONFIG3 pPdConfig, PULONG pEntries, BOOL bInSetup ) { PPDENUMERATE pPdEnumerate; ULONG ByteCount; DWORD Error; int i; PPDPARAMS pPdParams = NULL;
/*
* Enumerate according to class. */ switch ( pPdConfig->Data.SdClass ) {
case SdAsync: pPdEnumerate = AsyncDeviceEnumerate; break;
case SdNetwork: if ( pPdConfig->Data.PdFlag & PD_LANA ) {
/*
* This is a LANA based network PD (ie, NetBIOS). Perform * NetBIOS enumerate. */ pPdEnumerate = NetBIOSDeviceEnumerate;
} else {
/*
* This is a physical lan adapter based network (TCP/IP, * IPX, SPX, etc). Enumerate based on the associated network * protocol service name. */ pPdEnumerate = NetworkDeviceEnumerate; } break;
default: return(NULL); }
/*
* Call enumerate in loop till we hit enough buffer entries to handle * a complete enumeration. NOTE: some enumeration routines will return * the necessary ByteCount on 'insufficient buffer' status; others won't. */ for ( ByteCount = 0, i = INITIAL_ENUMERATION_COUNT; ; i *= 2 ) {
if ( pPdParams != NULL ) LocalFree(pPdParams);
pPdParams = (PPDPARAMS)LocalAlloc( LPTR, ByteCount ? ByteCount : (ByteCount = sizeof(PDPARAMS) * i) );
if ( pPdParams == NULL ) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto OutOfMemory; }
/*
* Perform enumeration and break loop if successful. */ if ( (*pPdEnumerate)( pPdConfig, pEntries, pPdParams, &ByteCount, bInSetup ) ) break;
/*
* If we received any other error other than 'insufficient buffer', * quit (quietly). */ if ( (Error = GetLastError()) != ERROR_INSUFFICIENT_BUFFER ) goto BadEnumerate; }
/*
* Success: return the PDPARAMS pointer. */ return(pPdParams);
/*==============================================================================
* Error returns *============================================================================*/ BadEnumerate: LocalFree(pPdParams); OutOfMemory: return(NULL);
} // end WinEnumerateDevices
/*******************************************************************************
* * NetworkDeviceEnumerate - Hydrix helper function * * Returns a list of Lan Adapter indexes of network cards bound to the the * specified protocol. The Lan Adapter is returned in the LanAdapter field * of each PDPARAMS array. A LanAdapter value of 0 indicates 'any configured * network card'. Indexes >=1 indicate 1-based index into the specific * protocol's "servicename"\Linkage\Route registry entry to specify the * particular network card. * * ENTRY: * pPdConfig (input) * Points to PDCONFIG3 structure of the PD. * pEntries (output) * When the function finishes successfully, the variable pointed to * by the pEntries parameter contains the number of entries actually * returned. * pPdParams (output) * Points to the buffer to receive the enumeration results, which are * returned as an array of PDPARAMS structures. * pByteCount (input/output) * Points to a variable that specifies the size, in bytes, of the * pPdParams parameter. If the buffer is too small to receive all the * entries, on output this variable receives the required size of the * buffer. * bInSetup (input) * TRUE if we're operating in Setup; FALSE otherwise. * * EXIT: * TRUE: enumeration was sucessful; FALSE otherwise. * * The error code can be retrieved via GetLastError(), and are the * following possible values: * ERROR_INSUFFICIENT_BUFFER * enumeration failed because of an insufficient pPdParams * buffer size to contain all devices * ERROR_DEV_NOT_EXIST * The specified network's service was not found, indicating that * the protocol was not configured. This error code can be * interpreted as 'no devices are configured for the xxx protocol' * for reporting purposes. * ERROR_xxxx * Registry error code. * ******************************************************************************/
BOOL WINAPI NetworkDeviceEnumerate( PPDCONFIG3 pPdConfig, PULONG pEntries, PPDPARAMS pPdParams, PULONG pByteCount, BOOL bInSetup ) { ULONG i, Count; LPTSTR szRoute, szRouteStr; LONG Status; DWORD ValueSize, Type; TCHAR szKey[256]; HKEY Handle;
/*
* Get maximum number of LanAdapter indexes that can be returned. */ Count = *pByteCount / sizeof(PDPARAMS);
/*
* Form key for service name associated with this PD and fetch * the Linkage\Route strings. */ _snwprintf( szKey, sizeof(szKey)/sizeof(TCHAR), TEXT("%s\\%s\\Linkage"), REGISTRY_SERVICES, pPdConfig->ServiceName ); if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &Handle )) != ERROR_SUCCESS ) { Status = ERROR_DEV_NOT_EXIST; goto BadRegistryOpen; }
/*
* Alloc and read in the linkage route multi-string. */ if ( ((Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, NULL, &ValueSize )) != ERROR_SUCCESS) || (Type != REG_MULTI_SZ) ) goto BadQuery1;
if ( !(szRoute = (LPTSTR)LocalAlloc(LPTR, ValueSize)) ) { Status = ERROR_NOT_ENOUGH_MEMORY; goto BadAlloc; }
if ( ((Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, (LPBYTE)szRoute, &ValueSize )) != ERROR_SUCCESS) ) goto BadQuery2;
/*
* Close the registry key handle and count the route strings to obtain * the number of entries to report in the enumeration. */ RegCloseKey(Handle); for ( i = 1, szRouteStr = szRoute; lstrlen(szRouteStr); i++ ) szRouteStr += (lstrlen(szRouteStr) + 1); LocalFree(szRoute);
/*
* If we don't have enough PDPARAMS structures to report all of the * LanAdapter indexes, return error. */ if ( i > Count ) { Status = ERROR_INSUFFICIENT_BUFFER; *pByteCount = (i * sizeof(PDPARAMS)); goto BadBufferSize; }
/*
* Set the LanAdapter fields of the first 'i' PDPARAMS structures to * the indexes (0-based), set total number of entries, and return success. */ for ( Count = 0, *pEntries = i; Count < i; pPdParams++, Count++ ) pPdParams->Network.LanAdapter = (LONG)Count; return(TRUE);
/*==============================================================================
* Error returns *============================================================================*/ BadQuery2: LocalFree(szRoute); BadAlloc: BadQuery1: RegCloseKey(Handle); BadBufferSize: BadRegistryOpen: SetLastError(Status); return(FALSE);
} // end NetworkDeviceEnumerate
/*******************************************************************************
* * QueryCurrentWinStation - Hydrix helper function * * Query the currently logged-on WinStation information. * * ENTRY: * pWSName (output) * Points to string to place current WinStation name. * pUserName (output) * Points to string to place current User name. * pLogonId (output) * Points to ULONG to place current LogonId. * pFlags (output) * Points to ULONG to place current WinStation's flags. * * EXIT: * (BOOL) TRUE if the user's current WinStation information was queried * sucessfully; FALSE otherwise. The error code is set for * GetLastError() to retrieve. * ******************************************************************************/
BOOL WINAPI QueryCurrentWinStation( PWINSTATIONNAME pWSName, LPTSTR pUserName, PULONG pLogonId, PULONG pFlags ) { ULONG Flags = 0; WINSTATIONINFORMATION WSInfo; #ifdef WINSTA
ULONG ReturnLength; #endif // WINSTA
#ifdef WINSTA
/*
* Fetch the WinStation's basic information. */ if ( !WinStationQueryInformation( SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationInformation, &WSInfo, sizeof(WSInfo), &ReturnLength ) ) goto BadQuery;
/*
* Check for shadow capability if WinStation is connected. If the * WinStation is not connected, we can't shadow. */ if ( WSInfo.ConnectState != State_Disconnected ) {
WDCONFIG WdConfig;
/*
* Query Wd config stuff. */ if ( !WinStationQueryInformation( SERVERNAME_CURRENT, LOGONID_CURRENT, WinStationWd, &WdConfig, sizeof(WdConfig), &ReturnLength ) ) goto BadQuery;
/*
* Set WinStation's Wd flags. */ Flags = WdConfig.WdFlag; } #else
lstrcpy(WSInfo.WinStationName, TEXT("console")); lstrcpy(WSInfo.UserName, TEXT("bonzo")); WSInfo.LogonId = 0; #endif // WINSTA
/*
* Set WinStation information into caller's variables, and return success. */ lstrcpy( pWSName, WSInfo.WinStationName ); lstrlwr(pWSName); lstrcpy( pUserName, WSInfo.UserName ); lstrlwr(pUserName); *pLogonId = WSInfo.LogonId; *pFlags = Flags;
return(TRUE);
/*==============================================================================
* Error returns *============================================================================*/ #ifdef WINSTA
BadQuery: #endif // WINSTA
return(FALSE);
} // end QueryCurrentWinStation
/*******************************************************************************
* * RegGetNetworkDeviceName - Hydrix helper function * * Obtain the network device name associated with the given WinStation PD. * * ENTRY: * hServer (input) * Handle to Hydrix Server * pPdConfig (input) * Points to the PDCONFIG3 structure for the WinStation's PD. * pPdParams (input) * Points to the PDPARAMS structure for the WinStation's PD. * szDeviceName (output) * Points to buffer to return the network device name. * nDeviceName (input) * Specifies the maxmum number of characters that can be stored in * szDeviceName. * * EXIT: * No return. Will always place a string representation of * pPdParams->Network.LanAdapter along with an appropriate error string * in pDeviceName if the network device name could not be read from the * registry. * ******************************************************************************/
typedef struct _LANAMAP { BYTE enabled; BYTE lana; } LANAMAP, *PLANAMAP;
LONG WINAPI RegGetNetworkDeviceName( HANDLE hServer, PPDCONFIG3 pPdConfig, PPDPARAMS pPdParams, LPTSTR szDeviceName, int nDeviceName ) { int i, length; LPTSTR szRoute, szRouteStr, p; LONG Status = ERROR_SUCCESS; DWORD ValueSize, Type; TCHAR szKey[256]; HKEY Handle; HKEY hkey_local_machine; PLANAMAP pLanaMap, pLana;
if ( hServer == NULL) hkey_local_machine = HKEY_LOCAL_MACHINE; else hkey_local_machine = hServer;
/*
* Check for NetBIOS (PD_LANA) mapping or other mapping. */ if ( !(pPdConfig->Data.PdFlag & PD_LANA) ) {
LPTSTR szRoute, szRouteStr;
/*
* Non-LANA mapping. If the LanAdapter is 0, treat this as the * special 'all configured network cards' value and return that * string as the device name. */ if ( pPdParams->Network.LanAdapter == 0 ) { TCHAR szString[256];
length = LoadString( GetModuleHandle( UTILDLL_NAME ), IDS_ALL_LAN_ADAPTERS, szString, 256 ); ASSERT(length); lstrncpy(szDeviceName, szString, nDeviceName); szDeviceName[nDeviceName-1] = TEXT('\0'); return Status; }
/*
* Form key for service name associated with this PD and fetch * the Linkage\Route strings. */ _snwprintf( szKey, sizeof(szKey)/sizeof(TCHAR), TEXT("%s\\%s\\Linkage"), REGISTRY_SERVICES, pPdConfig->ServiceName ); if ( (Status = RegOpenKeyEx( hkey_local_machine, szKey, 0, KEY_READ, &Handle )) != ERROR_SUCCESS ) goto Error;
/*
* Alloc and read in the linkage route multi-string. */ if ( ((Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, NULL, &ValueSize )) != ERROR_SUCCESS) || (Type != REG_MULTI_SZ) ) goto Error;
if ( !(szRoute = (LPTSTR)LocalAlloc(LPTR, ValueSize)) ) { Status = ERROR_NOT_ENOUGH_MEMORY; goto Error; }
if ( ((Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, (LPBYTE)szRoute, &ValueSize )) != ERROR_SUCCESS) ) { LocalFree(szRoute); goto Error; }
/*
* Close the registry key handle and point to the route string * associated with this LanAdapter index. */ RegCloseKey(Handle); for ( i = 1, szRouteStr = szRoute; i < pPdParams->Network.LanAdapter; i++ ) {
szRouteStr += (lstrlen(szRouteStr) + 1);
if ( !lstrlen(szRouteStr) ) {
/*
* Error: Index past end of route multi-string. */ LocalFree(szRoute); Status = ERROR_DEV_NOT_EXIST; goto Error; } }
/*
* Isolate the service string representing the lowest binding * in the route and convert it to its display name. */ *(p = (szRouteStr + lstrlen(szRouteStr) - 1)) = TEXT('\0'); for ( ; *p != TEXT('\"'); p-- ); p++; if ( (Status = RegGetNetworkServiceName( hServer, p, szDeviceName, nDeviceName )) != ERROR_SUCCESS ) { LocalFree(szRoute); goto Error; }
/*
* Clean up and return. */ LocalFree(szRoute); return Status;
} else {
/*
* NetBIOS LANA #: see which LanaMap entry corresponds to the specified * Lan Adapter. */ if ( (Status = RegOpenKeyEx( hkey_local_machine, REGISTRY_NETBLINKAGE, 0, KEY_READ, &Handle )) != ERROR_SUCCESS ) goto Error;
/*
* Alloc and read the LanaMap */ if ( ((Status = RegQueryValueEx( Handle, REGISTRY_NETBLINKAGE_LANAMAP, NULL, &Type, NULL, &ValueSize)) != ERROR_SUCCESS) || (Type != REG_BINARY) ) { RegCloseKey(Handle); goto Error; }
if ( !(pLanaMap = (PLANAMAP)LocalAlloc(LPTR, ValueSize)) ) { Status = ERROR_NOT_ENOUGH_MEMORY; goto Error; }
if ( (Status = RegQueryValueEx( Handle, REGISTRY_NETBLINKAGE_LANAMAP, NULL, &Type, (LPBYTE)pLanaMap, &ValueSize)) != ERROR_SUCCESS ) { LocalFree(pLanaMap); RegCloseKey(Handle); goto Error; }
/*
* Loop through LanaMap to check for match with the specified Lan * Adapter #. */ for ( pLana = pLanaMap, i = 0; i < (int)(ValueSize / sizeof(LANAMAP)); i++, pLana++ ) {
if ( pLana->lana == (BYTE)(pPdParams->Network.LanAdapter) ) {
TCHAR szHighestBinding[256], szLowestBinding[256];
LocalFree(pLanaMap);
/*
* Match found. Alloc and fetch the Route multi-string */ if ( ((Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, NULL, &ValueSize)) != ERROR_SUCCESS) || (Type != REG_MULTI_SZ) ) { RegCloseKey(Handle); goto Error; }
if ( !(szRoute = (LPTSTR)LocalAlloc(LPTR, ValueSize)) ) { Status = ERROR_NOT_ENOUGH_MEMORY; goto Error; }
if ( (Status = RegQueryValueEx( Handle, REGISTRY_ROUTE, NULL, &Type, (LPBYTE)szRoute, &ValueSize)) != ERROR_SUCCESS ) { LocalFree(szRoute); RegCloseKey(Handle); goto Error; }
/*
* Free the registry key handle and make a local copy of the * 'i'th multi string, which is the binding route for this lana. */ RegCloseKey(Handle); for ( szRouteStr = szRoute; i > 0; i-- ) szRouteStr += (lstrlen(szRouteStr) + 1); lstrncpy(szDeviceName, szRouteStr, nDeviceName); szDeviceName[nDeviceName-1] = TEXT('\0'); LocalFree(szRoute);
/*
* Isolate the service string representing the highest binding * in the route and convert it to its display name. */ szRouteStr = szDeviceName + 1; // skip first "
for ( p = szRouteStr; *p && *p != TEXT('\"'); p++ ); if ( !(*p) ) goto Error; *p = TEXT('\0'); if ( (Status = RegGetNetworkServiceName( hServer, szRouteStr, szHighestBinding, sizeof(szHighestBinding)/sizeof(TCHAR) )) != ERROR_SUCCESS ) goto Error;
/*
* Isolate the service string representing the lowest binding * in the route and convert it to its display name. */ if ( !(*(szRouteStr = p+1)) ) {
*szLowestBinding = TEXT('\0');
} else {
*(p = (szRouteStr + lstrlen(szRouteStr) - 1)) = TEXT('\0'); for ( ; *p != TEXT('\"'); p-- ); p++; if ( (Status = RegGetNetworkServiceName( hServer, p, szLowestBinding, sizeof(szLowestBinding)/sizeof(TCHAR) )) != ERROR_SUCCESS ) goto Error; }
/*
* Build the complete name string. */ _snwprintf( szDeviceName, nDeviceName, TEXT("%s => %s"), szHighestBinding, szLowestBinding );
/*
* Return. */ return ERROR_SUCCESS; } }
/*
* No match found. */ LocalFree(pLanaMap); RegCloseKey(Handle); goto Error; }
/*==============================================================================
* Error returns *============================================================================*/ Error: { TCHAR sz1[256], sz2[1024]; int length;
length = LoadString( GetModuleHandle( UTILDLL_NAME ), (pPdConfig->Data.PdFlag & PD_LANA) ? IDP_ERROR_REGLANA : IDP_ERROR_REGNETCARD, sz1, 256 );
wsprintf( sz2, sz1, pPdParams->Network.LanAdapter, Status ); lstrncpy(szDeviceName, sz2, nDeviceName); szDeviceName[nDeviceName-1] = TEXT('\0'); } return Status;
} // end RegGetNetworkDeviceName
/*******************************************************************************
* * RegGetNetworkServiceName - Hydrix helper function * * Obtain the display name associated with a given network service name. * If the service is a reference to a physical network card, will return * the title of the card as obtained from the LOCAL_MACHINE\Software\ * Microsoft\Windows NT\NetworkCards registry. * * ENTRY: * hServer (input) * Handle of the Hydrix Server * szServiceKey (input) * Key string into the LOCAL_MACHINE\System\CurrentControlSet\Services * registry. * szServiceName (output) * Points to buffer to return the service's display name. * nServiceName (input) * Specifies the maxmum number of characters that can be stored in * szServiceName. * * EXIT: * ERROR_SUCCESS if a service name was sucessfully found and returned; * error code otherwise. * * NOTE: If the service name is for an entry in the NetworkCards resistry * and the entry is flagged as 'hidden', the service name will be * blank. This will flag caller's logic to ignore the entry. * ******************************************************************************/
LONG WINAPI RegGetNetworkServiceName( HANDLE hServer, LPTSTR szServiceKey, LPTSTR szServiceName, int nServiceName ) { LONG Status; DWORD ValueSize, Type, dwValue; TCHAR szKey[256]; LPTSTR szTemp; HKEY Handle; HKEY hkey_local_machine;
if (hServer == NULL) hkey_local_machine = HKEY_LOCAL_MACHINE; else hkey_local_machine = hServer;
lstrnprintf( szKey, sizeof(szKey)/sizeof(TCHAR), TEXT("%s\\%s"), REGISTRY_SERVICES, szServiceKey );
if ( (Status = RegOpenKeyEx( hkey_local_machine, szKey, 0, KEY_READ, &Handle )) != ERROR_SUCCESS ) return(Status);
/*
* Alloc and read in the service's DisplayName value (if there). */ if ( ((Status = RegQueryValueEx( Handle, REGISTRY_DISPLAY_NAME, NULL, &Type, NULL, &ValueSize )) != ERROR_SUCCESS) || (Type != REG_SZ) ) {
HKEY Subkey; FILETIME KeyTime; DWORD i;
/*
* The service doesn't have a DisplayName associated with it (it's a * Network Card's service name). Traverse the NetworkCards registry * entries and find the entry associated with this service name * (if it exists). */ RegCloseKey(Handle); if ( (Status = RegOpenKeyEx( hkey_local_machine, REGISTRY_NETCARDS, 0, KEY_READ, &Handle )) != ERROR_SUCCESS ) return(Status);
for ( i = 0, ValueSize = sizeof(szKey)/sizeof(TCHAR) ; RegEnumKeyEx( Handle, i, szKey, &ValueSize, NULL, NULL, NULL, &KeyTime ) == ERROR_SUCCESS ; i++, ValueSize = sizeof(szKey)/sizeof(TCHAR) ) {
/*
* Open the Network Card's registry. */ if ( (Status = RegOpenKeyEx( Handle, szKey, 0, KEY_READ, &Subkey )) != ERROR_SUCCESS ) { RegCloseKey(Handle); return(Status); }
/*
* Alloc and fetch the card's service name. Continue net card * enumeration if service name not found. */ if ( ((Status = RegQueryValueEx( Subkey, REGISTRY_SERVICE_NAME, NULL, &Type, NULL, &ValueSize)) != ERROR_SUCCESS) || (Type != REG_SZ) ) { RegCloseKey(Subkey); continue; }
szTemp = (LPTSTR)LocalAlloc(LPTR, ValueSize); if(NULL == szTemp) { RegCloseKey(Subkey); RegCloseKey(Handle); return ERROR_NOT_ENOUGH_MEMORY; }
if ( (Status = RegQueryValueEx( Subkey, REGISTRY_SERVICE_NAME, NULL, &Type, (LPBYTE)szTemp, &ValueSize)) != ERROR_SUCCESS ) { LocalFree(szTemp); RegCloseKey(Subkey); continue; }
/*
* If the current Network Card's service name matches the service * name that we're looking for, fetch the card's title. */ if ( !lstrcmpi(szServiceKey, szTemp) ) {
LocalFree(szTemp);
ValueSize = sizeof(dwValue); if ( (RegQueryValueEx( Subkey, REGISTRY_HIDDEN, NULL, &Type, (LPBYTE)&dwValue, &ValueSize ) == ERROR_SUCCESS) && (Type == REG_DWORD) && (dwValue == 1) ) {
/*
* Entry is hidden: return empty title. */ *szServiceName = TEXT('\0');
} else {
/*
* Entry is not hidden: Alloc for the card's title. */ if ( ((Status = RegQueryValueEx( Subkey, REGISTRY_TITLE, NULL, &Type, NULL, &ValueSize)) != ERROR_SUCCESS) || (Type != REG_SZ) ) { RegCloseKey(Subkey); RegCloseKey(Handle); return(Status); } szTemp = (LPTSTR)LocalAlloc(LPTR, ValueSize); if(NULL == szTemp) { RegCloseKey(Subkey); RegCloseKey(Handle); return ERROR_NOT_ENOUGH_MEMORY; }
/*
* Fetch the title. */ if ( (Status = RegQueryValueEx( Subkey, REGISTRY_TITLE, NULL, &Type, (LPBYTE)szTemp, &ValueSize)) != ERROR_SUCCESS ) { LocalFree(szTemp); RegCloseKey(Subkey); RegCloseKey(Handle); return(Status); }
/*
* Copy the card's title. */ lstrncpy(szServiceName, szTemp, nServiceName); szServiceName[nServiceName-1] = TEXT('\0'); LocalFree(szTemp); }
/*
* Clean up and return success. */ RegCloseKey(Subkey); RegCloseKey(Handle); return(ERROR_SUCCESS);
} else {
/*
* This is not the Network Card that we're looking for. Close * it's registry key, free the service name buffer, and continue * enumeration loop. */ LocalFree(szTemp); RegCloseKey(Subkey); } }
/*
* Network Card not found with service name matching the one supplied. * Close NetworkCards registry key and return failure, */ RegCloseKey(Handle); return(ERROR_DEV_NOT_EXIST);
} else {
szTemp = (LPTSTR)LocalAlloc(LPTR, ValueSize); if(NULL == szTemp) { RegCloseKey(Handle); return ERROR_NOT_ENOUGH_MEMORY; }
if ( ((Status = RegQueryValueEx( Handle, REGISTRY_DISPLAY_NAME, NULL, &Type, (LPBYTE)szTemp, &ValueSize )) == ERROR_SUCCESS) ) lstrncpy(szServiceName, szTemp, nServiceName); szServiceName[nServiceName-1] = TEXT('\0');
LocalFree(szTemp); RegCloseKey(Handle); return(Status); }
} // end RegGetNetworkServiceName
/*******************************************************************************
* * AsyncDeviceEnumerate - Hydrix helper function * * Returns a list of async device names. This will return both 'COM' devices * and TAPI configured modems. * * ENTRY: * pPdConfig (input) * Points to PDCONFIG3 structure of the PD. * pEntries (output) * When the function finishes successfully, the variable pointed to * by the pEntries parameter contains the number of entries actually * returned. * pPdParams (output) * Points to the buffer to receive the enumeration results, which are * returned as an array of PDPARAMS structures. * pByteCount (input/output) * Points to a variable that specifies the size, in bytes, of the * pPdParams parameter. If the buffer is too small to receive all the * entries, on output this variable is set to 0 (caller should double * the input buffer and try again). * bInSetup (input) * TRUE if we're operating in Setup; FALSE otherwise. * EXIT: * TRUE: enumeration was sucessful; FALSE otherwise. * * The error code can be retrieved via GetLastError(), and are the * following possible values: * ERROR_NOT_ENOUGH_MEMORY * not enough memory to allocate working buffer(s) * ERROR_INSUFFICIENT_BUFFER * enumeration failed because of an insufficient pPdParams * buffer size to contain all devices * ERROR_DEV_NOT_EXIST * the QueryDosDevice call failed. This error code can be * interpreted as 'no async devices are configured' for reporting * purposes. * ******************************************************************************/
#define MAX_QUERY_BUFFER (1024*16)
BOOL WINAPI AsyncDeviceEnumerate( PPDCONFIG3 pPdConfig, PULONG pEntries, PPDPARAMS pPdParams, PULONG pByteCount, BOOL bInSetup ) { DWORD Error = ERROR_SUCCESS; ULONG Count; HKEY hRoot = NULL; DWORD BufSize, NameSize, Type, Index, SaveBufSize, SaveNameSize; LONG Result = 0; LONG nDosDevice = 0; LPTSTR pBuffer = NULL, pBufferEnd = NULL; LPTSTR pNameBuffer = NULL, pName; BOOLEAN bRetVal = FALSE;
/*
* Get maximum number of names that can be returned */ Count = *pByteCount / sizeof(PDPARAMS); *pByteCount = 0; *pEntries = 0;
/*
* Allocate buffer */ SaveBufSize = MAX_QUERY_BUFFER; SaveNameSize = MAX_QUERY_BUFFER;
BufSize = SaveBufSize; NameSize = SaveNameSize;
if ( !(pBuffer = (LPTSTR)LocalAlloc(LPTR, BufSize * sizeof(TCHAR))) ) { Error = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
if ( !(pNameBuffer = (LPTSTR)LocalAlloc(LPTR, NameSize)) ) { Error = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; }
/*
* If we're in Setup, obtain devices from the SERIALCOMM section in * LOCAL MACHINE registry, since the serial device driver(s) are most * likely not running. Otherwise, we'll query all DosDevices and * return those that are COM devices and are not currently in use. */ if ( bInSetup ) {
Result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, // Reserved
KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE, &hRoot );
if ( Result != ERROR_SUCCESS ) {
//
// This is usually the result of having no ports, so the key
// SERIALCOMM does not exist.
//
goto Cleanup; }
for ( Index=0; ; Index++ ) {
// Each enumerate stomps on our buffer sizes
BufSize = SaveBufSize; NameSize = SaveNameSize;
Result = RegEnumValue( hRoot, Index, pBuffer, &BufSize, NULL, // Reserved
&Type, (LPBYTE)pNameBuffer, &NameSize );
if ( Result == ERROR_INSUFFICIENT_BUFFER ) {
// Reallocate the buffer
LocalFree( pBuffer ); pBuffer = (LPTSTR)LocalAlloc(LPTR, BufSize * sizeof(TCHAR)); if ( pBuffer == NULL ) { // Try and reallocate next key
SaveBufSize = BufSize = 0; continue; } else { SaveBufSize = BufSize; }
// Reallocate the name buffer
LocalFree( pNameBuffer ); pNameBuffer = (LPTSTR)LocalAlloc(LPTR, NameSize); if ( pNameBuffer == NULL ) { // Try and reallocate next key
SaveNameSize = NameSize = 0; continue; } else { SaveNameSize = NameSize; }
Result = RegEnumValue( hRoot, Index, pBuffer, &BufSize, NULL, // Reserved
&Type, (LPBYTE)pNameBuffer, &NameSize ); }
// We are done
if ( Result == ERROR_NO_MORE_ITEMS ) { bRetVal = TRUE; Result = 0; goto Cleanup; }
if ( Result != ERROR_SUCCESS ) { goto Cleanup; }
if ( Count > 0 ) {
if ( Type != REG_SZ ) { continue; }
pPdParams->SdClass = SdAsync; lstrcpy( pPdParams->Async.DeviceName, pNameBuffer ); pPdParams++; Count--; (*pEntries)++;
} else {
Error = ERROR_INSUFFICIENT_BUFFER; goto Cleanup; } }
} else { // not in Setup
/*
* Get complete device list */ nDosDevice = QueryDosDevice( NULL, pBuffer, MAX_QUERY_BUFFER ); if ( !nDosDevice) { Error = ERROR_DEV_NOT_EXIST; goto Cleanup; }
/*
* Find each device name in list */ pName = pBuffer; pBufferEnd = pBuffer + nDosDevice; while ( *pName && (pName < pBufferEnd) ) { if ( CheckForComDevice( pName ) ) { if ( Count > 0 ) { pPdParams->SdClass = SdAsync; lstrcpy( pPdParams->Async.DeviceName, pName ); pPdParams++; Count--; (*pEntries)++; } else {
Error = ERROR_INSUFFICIENT_BUFFER; goto Cleanup; } } pName += (lstrlen(pName) + 1); }
bRetVal = TRUE; // sucessful enumeration
}
Cleanup: /*
* If no errors yet, perform TAPI device enumeration. */ if ( bRetVal ) {
if ( (Error = EnumerateTapiPorts( pPdParams, Count, &pEntries )) != ERROR_SUCCESS ) {
bRetVal = FALSE; } }
if ( pBuffer ) { LocalFree( pBuffer ); }
if ( pNameBuffer ) { LocalFree( pNameBuffer ); }
if ( hRoot ) { CloseHandle( hRoot ); } SetLastError(Error); return(bRetVal);
} // AsyncDeviceEnumerate
/*******************************************************************************
* * NetBIOSDeviceEnumerate - Hydrix helper function * * Returns a list of NetBIOS lana adapter numbers. * * ENTRY: * pPdConfig (input) * Points to PDCONFIG3 structure of the PD. * pEntries (output) * When the function finishes successfully, the variable pointed to * by the pEntries parameter contains the number of entries actually * returned. * pPdParams (output) * Points to the buffer to receive the enumeration results, which are * returned as an array of PDPARAMS structures. * pByteCount (input/output) * Points to a variable that specifies the size, in bytes, of the * pPdParams parameter. If the buffer is too small to receive all the * entries, on output this variable receives the required size of the * buffer. * bInSetup (input) * TRUE if we're operating in Setup; FALSE otherwise. * * EXIT: * TRUE: enumeration was sucessful; FALSE otherwise. * * The error code can be retrieved via GetLastError(), and are the * following possible values: * v ERROR_INSUFFICIENT_BUFFER * enumeration failed because of an insufficient pPdParams * buffer size to contain all devices * ERROR_DEV_NOT_EXIST * the NetBiosLanaEnum call failed. This error code can be * interpreted as 'no netbios devices are configured' for reporting * purposes. * ******************************************************************************/
BOOL WINAPI NetBIOSDeviceEnumerate( PPDCONFIG3 pPdConfig, PULONG pEntries, PPDPARAMS pPdParams, PULONG pByteCount, BOOL bInSetup ) { LANA_ENUM LanaEnum; NTSTATUS Status; int i;
/*
* Issue netbios enum command */ if ( Status = NetBiosLanaEnum( &LanaEnum ) ) { SetLastError(ERROR_DEV_NOT_EXIST); return(FALSE); }
/*
* Make sure user's buffer is big enough */ if ( LanaEnum.length > (*pByteCount / sizeof(PDPARAMS)) ) {
*pByteCount = LanaEnum.length * sizeof(PDPARAMS); SetLastError(ERROR_INSUFFICIENT_BUFFER); return(FALSE); }
/*
* Return number of entries */ *pEntries = (ULONG) LanaEnum.length;
/*
* Return lana numbers */ for ( i=0; i < (int)LanaEnum.length; i++, pPdParams++ ) { pPdParams->SdClass = SdNetwork; pPdParams->Network.LanAdapter = LanaEnum.lana[i]; }
return(TRUE);
} // NetBIOSDeviceEnumerate
/*******************************************************************************
* * FormDecoratedAsyncDeviceName - Hydrix helper function * * Format a decorated async device name if a modem is defined. * * ENTRY: * pDeviceName (output) * Points to buffer that will contain the decorated name (or undecorated * name if no modem). * pPdParams (input) * Points to the ASYNCCONFIG structure to be used in forming the * decorated name. * * EXIT: * ******************************************************************************/
void WINAPI FormDecoratedAsyncDeviceName( LPTSTR pDeviceName, PASYNCCONFIG pAsyncConfig ) { if ( *(pAsyncConfig->ModemName) ) wsprintf( pDeviceName, TEXT("%s - %s"), pAsyncConfig->DeviceName, pAsyncConfig->ModemName ); else lstrcpy( pDeviceName, pAsyncConfig->DeviceName );
} // end FormDecoratedAsyncDeviceName
/*******************************************************************************
* * ParseDecoratedAsyncDeviceName - Hydrix helper function * * Given a decorated async device name, form it's component device and * modem name portions. * * ENTRY: * pDeviceName (input) * Points to buffer that contain the decorated async device name. * pAsyncConfig (output) * Points to the ASYNCCONFIG structure to save the device (in * ->DeviceName) and modem (in ->ModemName). * EXIT: * ******************************************************************************/
void WINAPI ParseDecoratedAsyncDeviceName( LPCTSTR pDeviceName, PASYNCCONFIG pAsyncConfig ) { int i;
/*
* Form DeviceName portion up to the first blank. */ for ( i=0; *pDeviceName && (*pDeviceName != TEXT(' ')); i++ ) (pAsyncConfig->DeviceName)[i] = *pDeviceName++; (pAsyncConfig->DeviceName)[i] = TEXT('\0');
/*
* Skip the ' - ' decoration (to the next space). */ if ( *pDeviceName ) { for ( pDeviceName++; *pDeviceName && (*pDeviceName != TEXT(' ')); pDeviceName++ ); }
/*
* Form the ModemName from the remainder of the string. */ i = 0; if ( *pDeviceName ) {
for ( pDeviceName++; *pDeviceName ; i++ ) (pAsyncConfig->ModemName)[i] = *pDeviceName++; } (pAsyncConfig->ModemName)[i] = TEXT('\0');
} // end ParseDecoratedAsyncDeviceName
/*******************************************************************************
* * SetupAsyncCdConfig - Hydrix helper function * * Given a properly configured ASYNCCONFIG structure, set up a given * CDCONFIG structure. * * ENTRY: * pAsyncConfig (input) * Points properly configured ASYNCCONFIG structure. * pCdConfig (output) * Points to the CDCONFIG structure to setup. * EXIT: * ******************************************************************************/
void WINAPI SetupAsyncCdConfig( PASYNCCONFIG pAsyncConfig, PCDCONFIG pCdConfig ) { memset(pCdConfig, 0, sizeof(CDCONFIG));
if ( *(pAsyncConfig->ModemName) ) {
pCdConfig->CdClass = CdModem; lstrcpy( pCdConfig->CdName, TEXT("cdmodem") ); lstrcpy( pCdConfig->CdDLL, TEXT("cdmodem.dll") ); }
} // end SetupAsyncCdConfig
/*******************************************************************************
* * InstallModem - Hydrix helper function * * Install UNIMODEM modem(s). * * ENTRY: * hwndOwner * Window handle that owns the installation dialog. * EXIT: * TRUE: installation completed; FALSE: error or user canceled. * * If an error, the error code can be retrieved via GetLastError(). * ******************************************************************************/
BOOL WINAPI InstallModem( HWND hwndOwner ) { HDEVINFO hdi; BOOL bStatus = FALSE; HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
/*
* Create a modem DeviceInfoSet */ if ( (hdi = SetupDiCreateDeviceInfoList( (LPGUID)&GUID_DEVCLASS_MODEM, hwndOwner )) ) {
SP_INSTALLWIZARD_DATA iwd;
/*
* Initialize the InstallWizardData */ memset(&iwd, 0, sizeof(iwd)); iwd.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); iwd.ClassInstallHeader.InstallFunction = DIF_INSTALLWIZARD; iwd.hwndWizardDlg = hwndOwner;
/*
* Set the InstallWizardData as the ClassInstallParams */ if ( SetupDiSetClassInstallParams( hdi, NULL, (PSP_CLASSINSTALL_HEADER)&iwd, sizeof(iwd)) ) {
/*
* Call the class installer to invoke the installation * wizard. */ SetCursor(hcur); hcur = NULL;
if ( SetupDiCallClassInstaller( DIF_INSTALLWIZARD, hdi, NULL) ) {
/*
* Success. The wizard was invoked and finished. */ SetupDiCallClassInstaller( DIF_DESTROYWIZARDDATA, hdi, NULL ); bStatus = TRUE; } }
/*
* Clean up */ SetupDiDestroyDeviceInfoList( hdi ); }
if (hcur) SetCursor(hcur);
return(bStatus);
} // end InstallModem
/*******************************************************************************
* * ConfigureModem - Hydrix helper function * * Configure the specified UNIMODEM modem. * * ENTRY: * pModemName * Name of UNIMODEM modem to configure. * hwndOwner * Window handle that owns the configuration dialog. * EXIT: * TRUE: configuration was sucessful; FALSE otherwise. * * The error code can be retrieved via GetLastError(). * ******************************************************************************/
BOOL WINAPI ConfigureModem( LPCTSTR pModemName, HWND hwndOwner ) { BOOL bStatus = FALSE; COMMCONFIG ccDummy; COMMCONFIG * pcc; DWORD dwSize; HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
ccDummy.dwProviderSubType = PST_MODEM; dwSize = sizeof(COMMCONFIG); GetDefaultCommConfig(pModemName, &ccDummy, &dwSize);
pcc = (COMMCONFIG *)LocalAlloc(LPTR, (UINT)dwSize); if ( pcc ) {
pcc->dwProviderSubType = PST_MODEM; if ( GetDefaultCommConfig(pModemName, pcc, &dwSize) ) {
COMMCONFIG *pccOld = (COMMCONFIG *)LocalAlloc(LPTR, (UINT)dwSize);
if ( pccOld ) {
memcpy(pccOld, pcc, dwSize); }
SetCursor(hcur); hcur = NULL;
bStatus = TRUE; if ( CommConfigDialog(pModemName, hwndOwner, pcc) ) {
if ( !SetDefaultCommConfig(pModemName, pcc, dwSize) ) bStatus = FALSE; }
LocalFree((HLOCAL)pcc); } } else { SetLastError(ERROR_NOT_ENOUGH_MEMORY); }
if (hcur) SetCursor(hcur);
return(bStatus);
} // end ConfigureModem
///////////////////////////////////////////////////////////////////////////////
// Static Helper Functions
/***************************************************************************
* * InitServerLock * * Since we do not require the user to call an initialize function, * we must initialize our critical section in a thread safe manner. * * The problem is, a critical section is needed to guard against multiple * threads trying to init the critical section at the same time. * * The solution that Nt uses, in which RtlInitializeCriticalSection itself * uses, is to wait on a kernel supported process wide Mutant before proceding. * This Mutant almost works by itself, but RtlInitializeCriticalSection does * not wait on it until after trashing the semaphore count. So we wait on * it ourselves, since it can be acquired recursively. * ***************************************************************************/
typedef struct SERVERVERSION { struct SERVERVERSION * pNext; char ServerNameA[MAX_BR_NAME+1]; USHORT ServerVersion; } SERVERVERSION, *PSERVERVERSION;
BOOLEAN G_fLockInited = FALSE; PSERVERVERSION G_pServerList = NULL; RTL_CRITICAL_SECTION G_ServerLock;
NTSTATUS InitServerLock() { NTSTATUS status = STATUS_SUCCESS;
RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
/*
* Make sure another thread did not beat us here */ if ( !G_fLockInited ) { status = RtlInitializeCriticalSection( &G_ServerLock ); if (status == STATUS_SUCCESS) { G_fLockInited = TRUE; } }
RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
return status; }
/*******************************************************************************
* * CheckForComDevice - local helper function * * check if device name is a serial com device * * ENTRY: * pName (input) * device name * * EXIT: * TRUE - serial device * FALSE - not a serial device * ******************************************************************************/
static BOOL CheckForComDevice( LPTSTR pName ) { FILE_FS_DEVICE_INFORMATION DeviceInformation; IO_STATUS_BLOCK IoStatus; HANDLE Handle; DEVICENAME Name; NTSTATUS Status;
if ( (lstrlen(pName) == 2 && pName[1] == TEXT(':')) || !lstrcmpi(pName, TEXT("aux")) || !lstrnicmp(pName, TEXT("lpt"), 3) || !lstrnicmp(pName, TEXT("prn"), 3) || !lstrnicmp(pName, TEXT("display"), 7) || !lstrnicmp(pName, TEXT("$VDMLPT"), 7)) return(FALSE);
lstrcpy( Name, TEXT("\\\\.\\") ); lstrcat( Name, pName );
try { Handle = CreateFile( Name, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access
NULL, // no security attr
OPEN_EXISTING, // must exist
0, NULL // no template
); } __except (1) { if ( Handle != INVALID_HANDLE_VALUE ) { CloseHandle( Handle ); Handle = INVALID_HANDLE_VALUE; } }
if ( Handle == INVALID_HANDLE_VALUE ) return(FALSE);
Status = NtQueryVolumeInformationFile( (HANDLE) Handle, &IoStatus, &DeviceInformation, sizeof(DeviceInformation), FileFsDeviceInformation );
CloseHandle( Handle );
if ( (Status != STATUS_SUCCESS) || (DeviceInformation.DeviceType != FILE_DEVICE_SERIAL_PORT) ) return(FALSE);
return(TRUE);
} // end CheckForComDevice
/*******************************************************************************
* * NetBiosLanaEnum - local helper function * * enumerate lana numbers * * ENTRY: * pLanaEnum (input) * pointer to receive LAN_ENUM structure * EXIT: * NO_ERROR - succesful * ******************************************************************************/
typedef struct _LANA_MAP { BOOLEAN Enum; UCHAR Lana; } LANA_MAP, *PLANA_MAP;
static int NetBiosLanaEnum( LANA_ENUM * pLanaEnum ) { int ProviderCount; void * pProviderNames = NULL; PLANA_MAP pLanaMap = NULL; HKEY netbiosKey = NULL; ULONG providerListLength; ULONG lanaMapLength; ULONG type; int i; LPTSTR currentProviderName; int rc;
//
// Read the registry for information on all Netbios providers,
// including Lana numbers, protocol numbers, and provider device
// names. First, open the Netbios key in the registry.
//
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGISTRY_NETBLINKAGE, 0, MAXIMUM_ALLOWED, &netbiosKey ); if ( rc != NO_ERROR ) { goto error_exit; }
//
// Determine the size of the provider names. We need this so
// that we can allocate enough memory to hold it.
//
providerListLength = 0;
rc = RegQueryValueEx( netbiosKey, TEXT("Bind"), NULL, &type, NULL, &providerListLength ); if ( rc != ERROR_MORE_DATA && rc != NO_ERROR ) { goto error_exit; }
//
// Allocate enough memory to hold the mapping.
//
if ( (pProviderNames = LocalAlloc(LPTR,providerListLength)) == NULL ) { rc = ERROR_NOT_ENOUGH_MEMORY; goto error_exit; }
//
// Get the list of transports from the registry.
//
rc = RegQueryValueEx( netbiosKey, TEXT("Bind"), NULL, &type, (PVOID)pProviderNames, &providerListLength ); if ( rc != NO_ERROR ) { goto error_exit; }
//
// Determine the size of the Lana map. We need this so that we
// can allocate enough memory to hold it.
//
providerListLength = 0;
rc = RegQueryValueEx( netbiosKey, TEXT("LanaMap"), NULL, &type, NULL, &lanaMapLength ); if ( rc != ERROR_MORE_DATA && rc != NO_ERROR ) { goto error_exit; }
//
// Allocate enough memory to hold the Lana map.
//
if ( (pLanaMap = LocalAlloc(LPTR,lanaMapLength)) == NULL ) { rc = ERROR_NOT_ENOUGH_MEMORY; goto error_exit; }
//
// Get the list of transports from the registry.
//
rc = RegQueryValueEx( netbiosKey, TEXT("LanaMap"), NULL, &type, (PVOID)pLanaMap, &lanaMapLength ); if ( rc != NO_ERROR ) { goto error_exit; }
//
// Determine the number of Netbios providers loaded on the system.
//
ProviderCount = (int) (lanaMapLength / sizeof(LANA_MAP));
//
// Fill in the lana array
//
pLanaEnum->length = 0; for ( currentProviderName = pProviderNames, i = 0; *currentProviderName != UNICODE_NULL && i < ProviderCount; currentProviderName += lstrlen( currentProviderName ) + 1, i++ ) {
if ( pLanaMap[i].Enum && lstrstr( currentProviderName, TEXT("Nbf_") ) ) { pLanaEnum->lana[ pLanaEnum->length++ ] = pLanaMap[i].Lana; } }
error_exit:
if ( netbiosKey != NULL ) RegCloseKey( netbiosKey );
if ( pProviderNames != NULL ) LocalFree( pProviderNames );
if ( pLanaMap != NULL ) LocalFree( pLanaMap );
return( rc ); }
//
// NOTE: Butchd 9-26-96
// all of this following TAPI-related code is from various
// \nt\private\net\ras\src\ui\setup\src\ files
//
/******************************************************************************
* * EnumerateTapiPorts - local helper function * * Determine all TAPI configured modems. * * ENTRY * pPdParams (output) * Points to array of PDPARAMS structures to save enumerated TAPI * modems into. * Count (input) * Specifies number of entries in the pPdParams array. * ppEntries (input/output) * Points to pointer to variable containing the existing number of * PDPARAMS entries already stored at addresses prior to pPdParams. * The referenced variable will be incremented by the number of * TAPI modems found and stored in the pPdParams array. * EXIT * Returns ERROR_SUCCESS if successful, error code if not. * *****************************************************************************/
DWORD EnumerateTapiPorts( PPDPARAMS pPdParams, ULONG Count, ULONG **ppEntries ) { LINEINITIALIZEEXPARAMS params; LINEDEVCAPS *linedevcaps ; LINEEXTENSIONID extensionid ; HLINEAPP TapiLine = (HLINEAPP)0; DWORD NegotiatedApiVersion ; DWORD NegotiatedExtVersion = 0; WORD i; DWORD lines = 0 ; BYTE buffer[1000] ; CHAR szregkey[512]; WCHAR wszDeviceName[DEVICENAME_LENGTH+1]; WCHAR wszModemName[DEVICENAME_LENGTH+1]; CHAR szModemName[DEVICENAME_LENGTH+1]; LONG lerr; DWORD Status = ERROR_TAPI_CONFIGURATION; DWORD dwApiVersion = HIGH_VERSION; BOOL fSuccess = FALSE; ULONG RASIsUsingPort = 0; HKEY CurKey, CurKey2; DWORD KeyCount=0, KeySize, CurSize, DataType; TCHAR szSubKey[255], CurRASDev[1024], szMainKey[255], *pCurRASDev;
/*
* Un-comment / edit the following line if time needed to allow newly * added modem to appear in TAPI's enumeration list. */ // Sleep(4000L);
/*
* Initialize TAPI. */ memset(¶ms, 0, sizeof(params)); params.dwTotalSize = sizeof(params); params.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; if ( lerr = lineInitializeExA( &TapiLine, GetModuleHandle( UTILDLL_NAME ), (LINECALLBACK)DummyTapiCallback, NULL, &lines, &dwApiVersion, ¶ms ) ) goto error;
/*
* Get configured TAPI modems on all lines. */ for ( i = 0; i < lines; i++ ) {
if ( lineNegotiateAPIVersion( TapiLine, i, LOW_VERSION, HIGH_VERSION, &NegotiatedApiVersion, &extensionid ) ) { continue ; }
memset( buffer, 0, sizeof(buffer) );
linedevcaps = (LINEDEVCAPS *)buffer; linedevcaps->dwTotalSize = sizeof(buffer);
/*
* Get this line's dev caps (ANSI). */ if ( lineGetDevCapsA( TapiLine, i, NegotiatedApiVersion, NegotiatedExtVersion, linedevcaps ) ) { continue ; }
/*
li * Only process modems. */ if ( linedevcaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM ) {
/*
* The linedevcaps stuff is in ASCII. */ DWORD j; char *temp;
/*
* Convert all nulls in the device class string to non nulls. */ for ( j = 0, temp = (char *)((BYTE *)linedevcaps+linedevcaps->dwDeviceClassesOffset); j < linedevcaps->dwDeviceClassesSize; j++, temp++ ) {
if ( *temp == '\0' ) *temp = ' '; }
/*
* Select only those devices that have comm/datamodem as a * device class. */ if ( strstr( (char*)((BYTE *)linedevcaps+linedevcaps->dwDeviceClassesOffset), "comm/datamodem" ) == NULL ) { continue; }
/*
* Fetch modem name (line name). */ strncpy( szModemName, (char *)((BYTE *)linedevcaps+linedevcaps->dwLineNameOffset), DEVICENAME_LENGTH ); szModemName[DEVICENAME_LENGTH] = '\0'; MultiByteToWideChar(CP_ACP, 0, szModemName, -1, wszModemName, DEVICENAME_LENGTH + 1);
/*
* The registry key name where the modem specific information is * stored is at dwDevSpecificOffset + 2 * DWORDS * * The device specifc string is not unicode so copy that as * an ansii string */ strncpy( szregkey, (char *)linedevcaps+linedevcaps->dwDevSpecificOffset+(2*sizeof(DWORD)), linedevcaps->dwDevSpecificSize ); szregkey[linedevcaps->dwDevSpecificSize] = '\0';
if ( !GetAssociatedPortName( szregkey, wszDeviceName ) ) {
goto error; }
/*
* If RAS is installed and is using the port configured with this * modem, we will return the modem, but the Parity field will be * set to 1, indicating that RAS is using the port. This is done * so that WinCfg (or other caller) can filter out the raw port * (device name) as well as the TAPI modem from the list. */ RASIsUsingPort = 0; //See if the RAS Key even exists
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\RAS\\TAPI DEVICES"), 0, KEY_ALL_ACCESS, &CurKey) == ERROR_SUCCESS) {
KeySize = sizeof(szSubKey) / sizeof( TCHAR ); KeyCount = 0; while (RegEnumKeyEx( CurKey, KeyCount++, szSubKey, &KeySize, NULL, NULL, NULL, NULL ) != ERROR_NO_MORE_ITEMS) {
wcscpy(szMainKey,TEXT("SOFTWARE\\Microsoft\\RAS\\TAPI DEVICES")); wcscat(szMainKey,TEXT("\\")); wcscat(szMainKey,szSubKey);
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, szMainKey, 0, KEY_ALL_ACCESS, &CurKey2) == ERROR_SUCCESS) { CurSize = sizeof(CurRASDev); if (RegQueryValueEx( CurKey2, TEXT("Address"), NULL, &DataType, (LPBYTE)CurRASDev, &CurSize ) == ERROR_SUCCESS) {
for ( pCurRASDev = CurRASDev; *pCurRASDev && !RASIsUsingPort; ) {
if ( lstrcmpi(pCurRASDev, wszDeviceName) == 0 ) RASIsUsingPort = 1; else pCurRASDev += (wcslen(pCurRASDev) + 1); } } RegCloseKey(CurKey2); }
KeySize = sizeof(szSubKey) / sizeof( TCHAR ); } RegCloseKey(CurKey); }
/*
* Save DeviceName and ModemName to PDPARAMS * structure and bump counts. Also, set the BaudRate * element to the TAPI line index so that the caller can * determine the most recently added line, and set the Parity * field to 0 if RAS is not using the line, 1 if RAS is * using the line (so caller can filter properly). */ if ( Count > 0 ) {
pPdParams->SdClass = SdAsync; lstrcpy( pPdParams->Async.DeviceName, wszDeviceName ); lstrcpy( pPdParams->Async.ModemName, wszModemName ); pPdParams->Async.BaudRate = (ULONG)i; pPdParams->Async.Parity = RASIsUsingPort; pPdParams++; Count--; (**ppEntries)++;
} else {
Status = ERROR_INSUFFICIENT_BUFFER; goto error; } } } Status = ERROR_SUCCESS;
error: if ( TapiLine ) lineShutdown(TapiLine);
return( Status );
} // end EnumerateTapiPorts
/******************************************************************************
* * DummyTapiCallback - local helper function * * A dummy callback routine to satisfy TAPI initialization. * * ENTRY * (see TAPI lineInitialize documentation) * EXIT * *****************************************************************************/
VOID CALLBACK DummyTapiCallback (HANDLE context, DWORD msg, DWORD instance, DWORD param1, DWORD param2, DWORD param3) { } // end DummyTapiCallback
/******************************************************************************
* * GetAssociatedPortName - local helper function * * Determine the 'attached to' (port) for the given modem via it's device * specific registry key (szKeyName). * * ENTRY * (see TAPI lineInitialize documentation) * EXIT * *****************************************************************************/
#define VALNAME_ATTACHEDTO "AttachedTo"
BOOL GetAssociatedPortName( char *szKeyName, WCHAR * wszPortName ) { HKEY hKeyModem; DWORD dwType; DWORD cbValueBuf; char szPortName[DEVICENAME_LENGTH+1];
if ( RegOpenKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hKeyModem ) ) {
return( FALSE ); }
cbValueBuf = sizeof( szPortName ); if ( RegQueryValueExA( hKeyModem, VALNAME_ATTACHEDTO, NULL, &dwType, (LPBYTE)&szPortName, &cbValueBuf ) ) { return ( FALSE ); }
RegCloseKey( hKeyModem );
MultiByteToWideChar(CP_ACP, 0, szPortName, -1, wszPortName, DEVICENAME_LENGTH + 1);
return( TRUE );
} // end GetAssociatedPortName
/*
* Defines and typedefs */ typedef struct _userlist { struct _userlist *pNext; WCHAR UserName[USERNAME_LENGTH+1]; } USERLIST, *PUSERLIST;
#define MAX_DOMAINANDNAME ((DOMAIN_LENGTH+1+USERNAME_LENGTH+1)*sizeof(WCHAR))
#define MAX_BUFFER (10*MAX_DOMAINANDNAME)
/*
* Local variables */ WCHAR *s_pszCompareList = NULL; WCHAR s_szServer[256];
/*
* Local functions. */ WCHAR *_ctxCreateAnonymousUserCompareList();
/*******************************************************************************
* * InitializeAnonymousUserCompareList - helper routine * * Creates a list of all local users who currently belong to the local * Anonymous group on the specified server, and saves the server name. * * ENTRY: * pszServer (input) * Name of server to query users for. * ******************************************************************************/
void WINAPI InitializeAnonymousUserCompareList( const WCHAR *pszServer ) { if ( s_pszCompareList ) free( s_pszCompareList );
wcscpy(s_szServer, pszServer);
s_pszCompareList = _ctxCreateAnonymousUserCompareList(); }
/*******************************************************************************
* * HaveAnonymousUsersChanged - helper routine * * Using the saved server name, fetch current list of local users that * belong to the local Anonymous group and compare with saved list. * * ENTRY: * EXIT: * On exit, the original compare list is freed and server name cleared. * ******************************************************************************/
BOOL WINAPI HaveAnonymousUsersChanged() { BOOL bChanged = FALSE; WCHAR *pszNewCompareList, *pszOldName, *pszNewName;
if ( s_pszCompareList && *s_szServer ) {
if ( pszNewCompareList = _ctxCreateAnonymousUserCompareList() ) {
bChanged = TRUE;
for ( pszOldName = s_pszCompareList, pszNewName = pszNewCompareList; (*pszOldName != L'\0') && (*pszNewName != L'\0'); ) {
if ( wcscmp(pszOldName, pszNewName) ) break; pszOldName += (wcslen(pszOldName) + 1); pszNewName += (wcslen(pszNewName) + 1); }
if ( (*pszOldName == L'\0') && (*pszNewName == L'\0') ) bChanged = FALSE;
free(pszNewCompareList); } }
if ( s_pszCompareList ) free( s_pszCompareList );
s_pszCompareList = NULL;
memset(s_szServer, 0, sizeof(s_szServer));
return(bChanged); }
/*******************************************************************************
* * _ctxCreateAnonymousUserCompareList - local routine * * Routine to get local anonymous users and place in sorted string list. * * ENTRY: * EXIT: * pszCompareList - Returns pointer to buffer containing sorted string * list of local anonymous users, double null terminated. * NULL if error. * ******************************************************************************/
WCHAR * _ctxCreateAnonymousUserCompareList() { DWORD EntriesRead, EntriesLeft, ResumeHandle = 0; NET_API_STATUS rc; WCHAR DomainAndUsername[256], *pszCompareList = NULL; DWORD i, TotalCharacters = 0; LPWSTR p; PLOCALGROUP_MEMBERS_INFO_3 plgrmi3 = NULL; PUSERLIST pUserListBase = NULL, pNewUser;
/*
* Loop till all local anonymous users have been retrieved. */ do {
/*
* Get first batch */ if ( (rc = NetLocalGroupGetMembers( s_szServer, PSZ_ANONYMOUS, 3, (LPBYTE *)&plgrmi3, MAX_BUFFER, &EntriesRead, &EntriesLeft, (PDWORD_PTR)(&ResumeHandle) )) && (rc != ERROR_MORE_DATA ) ) {
break; }
/*
* Process first batch */ for ( i = 0; i < EntriesRead; i++ ) {
/*
* Get DOMAIN/USERNAME */ wcscpy( DomainAndUsername, plgrmi3[i].lgrmi3_domainandname );
/*
* Check that DOMAIN is actually LOCAL MACHINE NAME */ if ( (p = wcsrchr( DomainAndUsername, L'\\' )) != NULL ) {
/*
* Make sure that this user belongs to specified * server. */ *p = L'\0'; if ( _wcsicmp( DomainAndUsername, &s_szServer[2] ) ) { continue; } }
/*
* Allocate list element and insert this username into list. */ if ( (pNewUser = (PUSERLIST)malloc(sizeof(USERLIST))) == NULL ) {
rc = ERROR_OUTOFMEMORY; break; }
pNewUser->pNext = NULL; wcscpy(pNewUser->UserName, p+1); TotalCharacters += wcslen(p+1) + 1;
if ( pUserListBase == NULL ) {
/*
* First item in list. */ pUserListBase = pNewUser;
} else {
PUSERLIST pPrevUserList, pUserList; pPrevUserList = pUserList = pUserListBase;
for ( ; ; ) {
if ( wcscmp(pNewUser->UserName, pUserList->UserName) < 0 ) {
if ( pPrevUserList == pUserListBase ) {
/*
* Insert at beginning of list. */ pUserListBase = pNewUser;
} else {
/*
* Insert into middle or beginning of list. */ pPrevUserList->pNext = pNewUser; }
/*
* Link to next. */ pNewUser->pNext = pUserList; break;
} else if ( pUserList->pNext == NULL ) {
/*
* Add to end of list. */ pUserList->pNext = pNewUser; break; }
pPrevUserList = pUserList; pUserList = pUserList->pNext; } } }
/*
* Free memory */ if ( plgrmi3 != NULL ) { NetApiBufferFree( plgrmi3 ); }
} while ( rc == ERROR_MORE_DATA );
/*
* Allocate buffer for multi-string compare list if no error so far * and terminate in case of empty list. */ if ( rc == ERROR_SUCCESS ) {
pszCompareList = (WCHAR *)malloc( (++TotalCharacters) * 2 );
if( pszCompareList != NULL ) { *pszCompareList = L'\0'; } }
/*
* Traverse and free username list, creating the multi-string compare * list if buffer is available (no error so far). */ if ( pUserListBase ) {
PUSERLIST pUserList = pUserListBase, pNext = NULL; WCHAR *pBuffer = pszCompareList;
do {
pNext = pUserList->pNext;
if ( pBuffer ) {
wcscpy(pBuffer, pUserList->UserName); pBuffer += (wcslen(pBuffer) + 1); *pBuffer = L'\0'; // auto double-null terminate
}
free(pUserList); pUserList = pNext;
} while ( pUserList ); }
return(pszCompareList); }
/*******************************************************************************
* * GetUserFromSid - Hydrix helper function * * Fetch the user name associated with the specified SID. * * ENTRY: * pSid (input) * Points to SID to match to user name. * pUserName (output) * Points to buffer to place the user name into. * cbUserName (input) * Specifies the size in bytes of the user name buffer. The returned * user name will be truncated to fit this buffer (including NUL * terminator) if necessary. * * EXIT: * * GetUserFromSid() will always return a user name. If the specified * SID fails to match to a user name, then the user name "(unknown)" will * be returned. * ******************************************************************************/
void WINAPI GetUserFromSid( PSID pSid, LPTSTR pUserName, DWORD cbUserName ) { TCHAR DomainBuffer[DOMAIN_LENGTH], UserBuffer[USERNAME_LENGTH]; DWORD cbDomainBuffer=sizeof(DomainBuffer), cbUserBuffer=sizeof(UserBuffer), Error; LPTSTR pDomainBuffer = NULL, pUserBuffer = NULL; SID_NAME_USE SidNameUse;
/*
* Fetch user name from SID: try user lookup with a reasonable Domain and * Sid buffer size first, before resorting to alloc. */ if ( !LookupAccountSid( NULL, pSid, UserBuffer, &cbUserBuffer, DomainBuffer, &cbDomainBuffer, &SidNameUse ) ) {
if ( ((Error = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) ) {
if ( cbDomainBuffer > sizeof(DomainBuffer) ) {
if ( !(pDomainBuffer = (LPTSTR)LocalAlloc( LPTR, cbDomainBuffer * sizeof(TCHAR))) ) {
Error = ERROR_NOT_ENOUGH_MEMORY; goto BadDomainAlloc; } }
if ( cbUserBuffer > sizeof(UserBuffer) ) {
if ( !(pUserBuffer = (LPTSTR)LocalAlloc( LPTR, cbUserBuffer * sizeof(TCHAR))) ) {
Error = ERROR_NOT_ENOUGH_MEMORY; goto BadUserAlloc; } }
if ( !LookupAccountSid( NULL, pSid, pUserBuffer ? pUserBuffer : UserBuffer, &cbUserBuffer, pDomainBuffer ? pDomainBuffer : DomainBuffer, &cbDomainBuffer, &SidNameUse ) ) {
Error = GetLastError(); goto BadLookup; }
} else {
goto BadLookup; } }
/*
* Copy the user name into the specified buffer, truncating if necessary, * and make lower case. */ lstrncpy( pUserName, pUserBuffer ? pUserBuffer : UserBuffer, cbUserName - 1 ); pUserName[cbUserName-1] = TEXT('\0'); lstrlwr(pUserName);
/*
* Free our local allocs (if any) and return. */ if ( pDomainBuffer ) LocalFree(pDomainBuffer); if ( pUserBuffer ) LocalFree(pUserBuffer); return;
/*--------------------------------------
* Error clean-up and return... */ BadLookup: BadUserAlloc: BadDomainAlloc: if ( pDomainBuffer ) LocalFree(pDomainBuffer); if ( pUserBuffer ) LocalFree(pUserBuffer); LoadString( GetModuleHandle( UTILDLL_NAME ), IDS_UNKNOWN, pUserName, cbUserName - 1 ); pUserName[cbUserName-1] = TEXT('\0'); return;
} // end GetUserFromSid
/*******************************************************************************
* * CachedGetUserFromSid - Hydrix helper function * * Provides entry point for a direct call to the UTILSUB.LIB * GetUserNameFromSid, which performs its own caching of usernames. * * ENTRY: * See UTILSUB.LIB GetUserNameFromSid (procutil.c) * EXIT: * See UTILSUB.LIB GetUserNameFromSid (procutil.c) * ******************************************************************************/
void WINAPI CachedGetUserFromSid( PSID pSid, PWCHAR pUserName, PULONG pcbUserName ) { GetUserNameFromSid( pSid, pUserName, pcbUserName );
} // end CachedGetUserFromSid
/*****************************************************************************
* * TestUserForAdmin - Hydrix helper function * * Returns whether the current thread is running under admin * security. * * ENTRY: * dom (input) * TRUE/FALSE - whether we want DOMAIN admin (as compared to local admin) * * EXIT: * TRUE/FALSE - whether user is specified admin * ****************************************************************************/
BOOL WINAPI TestUserForAdmin( BOOL dom ) { BOOL IsMember, IsAnAdmin; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; PSID AdminSid;
if (RtlAllocateAndInitializeSid( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid ) != STATUS_SUCCESS) { IsAnAdmin = FALSE; } else { if (!CheckTokenMembership( NULL, AdminSid, &IsMember)) { RtlFreeSid(AdminSid); IsAnAdmin = FALSE; } else { RtlFreeSid(AdminSid); IsAnAdmin = IsMember; } }
return IsAnAdmin;
// UNUSED dom;
} // end of TestUserForAdmin
/*****************************************************************************
* * IsPartOfDomain - Hydrix helper function * * Returns whether the current server participates in a domain. * * ENTRY: * * EXIT: * TRUE or FALSE * ****************************************************************************/
BOOL WINAPI IsPartOfDomain(VOID) { NTSTATUS Status; LSA_HANDLE PolicyHandle; PPOLICY_ACCOUNT_DOMAIN_INFO DomainInfo; OBJECT_ATTRIBUTES ObjAttributes; BOOL IsDomainName = FALSE;
//
// Open a handle to the local security policy. Initialize the
// objects attributes structure first.
//
InitializeObjectAttributes( &ObjAttributes, NULL, 0, NULL, NULL );
Status = LsaOpenPolicy( NULL, &ObjAttributes, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle );
if ( !NT_SUCCESS(Status) ) goto done;
//
// Get the name of the primary domain from LSA
//
Status = LsaQueryInformationPolicy( PolicyHandle, PolicyPrimaryDomainInformation, (PVOID *)&DomainInfo );
(void) LsaClose( PolicyHandle );
if ( !NT_SUCCESS(Status) ) goto done;
if ( DomainInfo->DomainSid ) IsDomainName = TRUE;
(void) LsaFreeMemory( DomainInfo );
done: return( IsDomainName );
} // end IsPartOfDomain
/*******************************************************************************
* * StrSdClass - Hydrix helper function * * Returns pointer to string representing the specified SdClass. * * ENTRY: * SdClass (input) * The SDCLASS to associate with a string. * * EXIT: * (LPCTSTR) Points to string representing the SDCLASS. * ******************************************************************************/
LPTSTR SdClassStrings[9] = { NULL};
LPCTSTR WINAPI StrSdClass( SDCLASS SdClass ) { TCHAR buffer[256];
WORD wID = IDS_UNKNOWN_PROTOCOL;
switch ( SdClass ) {
case SdConsole: wID = IDS_CONSOLE; break;
case SdNetwork: wID = IDS_NETWORK; break;
case SdAsync: wID = IDS_ASYNC; break;
case SdFrame: wID = IDS_FRAME; break;
case SdReliable: wID = IDS_RELIABLE; break;
case SdCompress: wID = IDS_COMPRESSION; break;
case SdEncrypt: wID = IDS_ENCRYPTION; break;
case SdTelnet: wID = IDS_TELNET; break; }
// If we haven't loaded the string yet, do it now
if (!SdClassStrings[wID - IDS_CONSOLE]) { LoadString(GetModuleHandle( UTILDLL_NAME ), wID, buffer, lengthof(buffer) ); SdClassStrings[wID - IDS_CONSOLE] = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == SdClassStrings[wID - IDS_CONSOLE]) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } lstrcpy(SdClassStrings[wID - IDS_CONSOLE], buffer);
}
return(SdClassStrings[wID]);
} // end StrSdClass
/*******************************************************************************
* * StrConnectState - Hydrix helper function * * Returns pointer to string representing the specified WinStation * connection state. * * ENTRY: * ConnectState (input) * The WinStation connect state to associate with a string. * bShortString (input) * If TRUE, returns a short(er) version of the string (if there is * one); FALSE returns the full spelling. * * EXIT: * (LPCTSTR) Points to string representing the connect state. * * Note: The short version of the string may be the same as the long version. * (i.e. "active") However, there are two string resources in case * the long version of the string is not short in a language other * than English. ******************************************************************************/
LPTSTR ConnectStateStrings[21] = { NULL};
LPCTSTR WINAPI StrConnectState( WINSTATIONSTATECLASS ConnectState, BOOL bShortString ) { TCHAR buffer[256]; WORD wID = IDS_UNKNOWN;
switch ( ConnectState ) {
case State_Active: wID = bShortString ? IDS_SHORT_ACTIVE : IDS_ACTIVE; break;
case State_Connected: wID = bShortString ? IDS_SHORT_CONNECTED : IDS_CONNECTED; break;
case State_ConnectQuery: wID = bShortString ? IDS_SHORT_CONNECT_QUERY : IDS_CONNECT_QUERY; break;
case State_Shadow: wID = bShortString ? IDS_SHORT_SHADOW : IDS_SHADOW; break;
case State_Disconnected: wID = bShortString ? IDS_SHORT_DISCONNECTED : IDS_DISCONNECTED; break;
case State_Idle: wID = bShortString ? IDS_SHORT_IDLE : IDS_IDLE; break;
case State_Reset: wID = bShortString ? IDS_SHORT_RESET : IDS_RESET; break;
case State_Down: wID = bShortString ? IDS_SHORT_DOWN : IDS_DOWN; break;
case State_Init: wID = bShortString ? IDS_SHORT_INIT : IDS_INIT; break;
case State_Listen: wID = bShortString ? IDS_SHORT_LISTEN : IDS_LISTEN; break; }
// If we haven't loaded the string yet, do it now
if (!ConnectStateStrings[wID - IDS_ACTIVE]) { LoadString(GetModuleHandle( UTILDLL_NAME ), wID, buffer, lengthof(buffer) ); ConnectStateStrings[wID - IDS_ACTIVE] = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == ConnectStateStrings[wID - IDS_ACTIVE]) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } lstrcpy(ConnectStateStrings[wID - IDS_ACTIVE], buffer); }
return(ConnectStateStrings[wID - IDS_ACTIVE]);
} // end StrConnectState
/*******************************************************************************
* * StrProcessState - Hydrix helper function * * Returns pointer to string representing the specified process state. * * ENTRY: * State (input) * The process state to associate with a string. * * EXIT: * (LPCTSTR) Points to string representing the process state. * ******************************************************************************/
LPTSTR ProcessStateStrings[8] = { NULL};
WORD StateTable[] = { IDS_INITED, IDS_READY, IDS_RUN, IDS_STANDBY, IDS_TERMINATE, IDS_WAIT, IDS_TRANSIT, IDS_STATE_DASHES, IDS_STATE_DASHES, IDS_STATE_DASHES, IDS_STATE_DASHES, IDS_STATE_DASHES };
LPCTSTR WINAPI StrProcessState( ULONG State ) { TCHAR buffer[256];
WORD wID = StateTable[State];
// If we haven't loaded the string yet, do it now
if (!ProcessStateStrings[wID - IDS_INITED]) { LoadString(GetModuleHandle( UTILDLL_NAME ), wID, buffer, lengthof(buffer) ); ProcessStateStrings[wID - IDS_INITED] = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == ProcessStateStrings[wID - IDS_INITED]) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } lstrcpy(ProcessStateStrings[wID - IDS_INITED], buffer); }
return(ProcessStateStrings[wID - IDS_INITED]);
} // end StrProcessState
/*******************************************************************************
* * StrSystemWaitReason - Hydrix helper function * * Returns pointer to string representing the specified 'system' * wait reason code. * * ENTRY: * WaitReason (input) * The system wait reason code to associate with a string. * * EXIT: * (LPCTSTR) Points to string representing the system wait reason. * ******************************************************************************/
LPTSTR SystemWaitStrings[31] = { NULL};
WORD SystemWaitReason[] = { IDS_EXECUTIVE, // Executive
IDS_FREE_PAGE, // FreePage
IDS_PAGE_IN, // PageIn
IDS_POOL_ALLOC, // PoolAlloc
IDS_DELAY_EXECUTION, // DelayExecution
IDS_SUSPENDED, // Suspended
IDS_USER_REQUEST, // UserRequest
IDS_EXECUTIVE, // Executive
IDS_FREE_PAGE, // FreePage
IDS_PAGE_IN, // PageIn
IDS_POOL_ALLOC, // PoolAllocation
IDS_DELAY_EXECUTION, // DelayExecution
IDS_SUSPENDED, // Suspended
IDS_USER_REQUEST, // UserRequest
IDS_EVENT_PAIR_HIGH, // EventPairHigh
IDS_EVENT_PAIR_LOW, // EventPairLow
IDS_LPC_RECEIVE, // LpcReceive
IDS_LPC_REPLY, // LpcReply
IDS_VIRTUAL_MEMORY, // VirtualMemory
IDS_PAGE_OUT, // PageOut
IDS_WAIT1, IDS_WAIT2, IDS_WAIT3, IDS_WAIT4, IDS_WAIT5, IDS_WAIT6, IDS_WAIT7, IDS_WAIT8, IDS_WAIT9, IDS_WAIT10 };
LPCTSTR WINAPI StrSystemWaitReason( ULONG WaitReason ) { TCHAR buffer[256];
WORD wID = SystemWaitReason[WaitReason];
// If we haven't loaded the string yet, do it now
if (!SystemWaitStrings[wID - IDS_EXECUTIVE]) { LoadString(GetModuleHandle( UTILDLL_NAME ), wID, buffer, lengthof(buffer) ); SystemWaitStrings[wID - IDS_EXECUTIVE] = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == SystemWaitStrings[wID - IDS_EXECUTIVE]) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } wcscpy(SystemWaitStrings[wID - IDS_EXECUTIVE], buffer); }
return(SystemWaitStrings[wID - IDS_EXECUTIVE]);
} // end StrSystemWaitReason
/*******************************************************************************
* * StrAsyncConnectState - Hydrix helper function * * Returns pointer to string representing the specified async connect state. * * ENTRY: * State (input) * The async connect state to associate with a string. * * EXIT: * (LPCTSTR) Points to string representing the async connect state. * ******************************************************************************/
LPTSTR AsyncConnectStateStrings[6] = { NULL };
LPCTSTR WINAPI StrAsyncConnectState( ASYNCCONNECTCLASS State ) { TCHAR buffer[256]; WORD wID = State - Connect_CTS;
// If we haven't loaded the string yet, do it now
if (!AsyncConnectStateStrings[wID]) { LoadString(GetModuleHandle( UTILDLL_NAME ), wID + IDS_ASYNC_CONNECT_CTS, buffer, lengthof(buffer) ); AsyncConnectStateStrings[wID] = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == AsyncConnectStateStrings[wID]) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } lstrcpy(AsyncConnectStateStrings[wID], buffer); }
return(AsyncConnectStateStrings[wID]);
} // end StrProcessState
/*******************************************************************************
* * GetUnknownString - Hydrix helper function * * Returns pointer to the string representing an unknown * Connect State or DateTimeString (IDS_UNKNOWN) * This is primarily so that WinAdmin can compare against it * * ENTRY: * None * * EXIT: * (LPCTSTR) Points to string representing the unknown string * ******************************************************************************/
LPTSTR UnknownString = NULL;
LPCTSTR WINAPI GetUnknownString() { TCHAR buffer[256];
// if we haven't loaded the string yet, do it now
if (!UnknownString) { LoadString(GetModuleHandle( UTILDLL_NAME ), IDS_UNKNOWN, buffer, lengthof(buffer) ); UnknownString = LocalAlloc(LPTR, 2*(wcslen(buffer)+1)); if(NULL == UnknownString) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return NULL; } lstrcpy(UnknownString, buffer); }
return(UnknownString);
} // end GetUnknownString
/*******************************************************************************
* * CalculateElapsedTime - Hydrix helper function * * Determines the difference between a specified LARGE_INTEGER time value * and the current system time, saves this 'elapsed time' into the * specified ELAPSEDTIME structure. * * ENTRY: * pTime (input) * Points to LARGE_INTEGER of time for difference calculation. * pElapsedTime (output) * Points to ELAPSEDTIME structure to save elapsed time. * * EXIT: * ******************************************************************************/
void WINAPI CalculateElapsedTime( LARGE_INTEGER *pTime, ELAPSEDTIME *pElapsedTime ) { LARGE_INTEGER InputTime; LARGE_INTEGER CurrentTime; LARGE_INTEGER DiffTime; SYSTEMTIME ltime; ULONG d_time;
/*
* Fetch the current time and zero out the specified ELAPSEDTIME structure. */ GetLocalTime( <ime ); memset( pElapsedTime, 0, sizeof(ELAPSEDTIME) );
if ( (pTime->HighPart == 0 && pTime->LowPart == 0 ) || !FileTimeToLocalFileTime( (FILETIME*)pTime, (FILETIME*)&InputTime ) || !SystemTimeToFileTime( <ime, (FILETIME *)&CurrentTime ) ) return;
/*
* Get the number of seconds since specified time. */ DiffTime = CalculateDiffTime( InputTime, CurrentTime ); d_time = DiffTime.LowPart;
/*
* Calculate the days, hours, minutes, seconds since specified time. */ pElapsedTime->days = (USHORT)(d_time / 86400L); // days since
d_time = d_time % 86400L; // seconds => partial day
pElapsedTime->hours = (USHORT)(d_time / 3600L); // hours since
d_time = d_time % 3600L; // seconds => partial hour
pElapsedTime->minutes = (USHORT)(d_time / 60L); // minutes since
pElapsedTime->seconds = (USHORT)(d_time % 60L); // seconds remaining
} // end CalculateElapsedTime
/*******************************************************************************
* * CompareElapsedTime - Hydrix helper function * * Determines the difference between two ELAPSEDTIME values. * * ENTRY: * pElapsedTime1 (input) * Points to first ELAPSEDTIME * pElapsedTime2 (input) * Points to ELAPSEDTIME structure to save elapsed time. * bCompareSeconds (input) * TRUE to include the seconds member in comparison; false otherwise. * * EXIT: * < 1 if first time is less than second time * 0 if times are the same * > 1 if first time is greater than second time * ******************************************************************************/
int WINAPI CompareElapsedTime( ELAPSEDTIME *pElapsedTime1, ELAPSEDTIME *pElapsedTime2, BOOL bCompareSeconds ) { int result;
if ( !(result = pElapsedTime1->days - pElapsedTime2->days) && !(result = pElapsedTime1->hours - pElapsedTime2->hours) && !(result = pElapsedTime1->minutes - pElapsedTime2->minutes) && (!bCompareSeconds || !(result = pElapsedTime1->seconds - pElapsedTime2->seconds) ) ) return(0); else return(result);
} // end CompareElapsedTime
/*******************************************************************************
* * ElapsedTimeString - Hydrix helper function * * Converts the specified ELAPSEDTIME into a string of the form * "ddd+hh:mm:ss" or, optionally "ddd+hh:mm" (suppress seconds). * * ENTRY: * pElapsedTime (input) * Points to ELAPSEDTIME structure to convert to string. * bIncludeSeconds (input) * If TRUE, will include seconds in string; FALSE will exclude. * pString (output) * Points to location to store elapsed time string. * EXIT: * ******************************************************************************/
void WINAPI ElapsedTimeString( ELAPSEDTIME *pElapsedTime, BOOL bIncludeSeconds, LPTSTR pString ) { if ( bIncludeSeconds ) {
if ( pElapsedTime->days > 0 ) wsprintf( pString, TEXT("%u+%02u:%02u:%02u"), pElapsedTime->days, pElapsedTime->hours, pElapsedTime->minutes, pElapsedTime->seconds ); else if ( pElapsedTime->hours > 0 ) wsprintf( pString, TEXT("%u:%02u:%02u"), pElapsedTime->hours, pElapsedTime->minutes, pElapsedTime->seconds ); else if ( pElapsedTime->minutes > 0 ) wsprintf( pString, TEXT("%u:%02u"), pElapsedTime->minutes, pElapsedTime->seconds ); else if ( pElapsedTime->seconds > 0 ) wsprintf( pString, TEXT("%u"), pElapsedTime->seconds ); else wsprintf( pString, TEXT(".") );
} else {
if ( pElapsedTime->days > 0 ) wsprintf( pString, TEXT("%u+%02u:%02u"), pElapsedTime->days, pElapsedTime->hours, pElapsedTime->minutes ); else if ( pElapsedTime->hours > 0 ) wsprintf( pString, TEXT("%u:%02u"), pElapsedTime->hours, pElapsedTime->minutes ); else if ( pElapsedTime->minutes > 0 ) wsprintf( pString, TEXT("%u"), pElapsedTime->minutes ); else wsprintf( pString, TEXT(".") ); }
} // end ElapsedTimeString
/*******************************************************************************
* * DateTimeString - Hydrix helper function * * Converts the specified LARGE_INTEGER time value into a date/time string * of the form "mm/dd/yy hh:mm". * * ENTRY: * pTime (input) * Points to LARGE_INTEGER of time to convert to string. * pString (output) * Points string to store converted date/time into. * * EXIT: * ******************************************************************************/
void WINAPI DateTimeString( LARGE_INTEGER *pTime, LPTSTR pString ) { FILETIME LocalTime; SYSTEMTIME stime; LPTSTR lpTimeStr; int nLen;
if ( FileTimeToLocalFileTime( (FILETIME *)pTime, &LocalTime ) && FileTimeToSystemTime( &LocalTime, &stime ) ) {
//Get Date Format
nLen = GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, NULL, 0); lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR)); if(NULL == lpTimeStr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); wcscpy(pString, L""); return; } nLen = GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, lpTimeStr, nLen); wcscpy(pString, lpTimeStr); wcscat(pString, L" "); GlobalFree(lpTimeStr);
//Get Time Format
nLen = GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, &stime, NULL, NULL, 0); lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR)); if(NULL == lpTimeStr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); wcscpy(pString, L""); return; } nLen = GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, &stime, NULL, lpTimeStr, nLen); wcscat(pString, lpTimeStr); GlobalFree(lpTimeStr); } else LoadString( GetModuleHandle( UTILDLL_NAME ), IDS_UNKNOWN, pString, lengthof(pString) );
} // end DateTimeString
/*******************************************************************************
* * CurrentDateTimeString - Hydrix helper function * * Converts the current system time into a date/time string of the form * "mm/dd/yy hh:mm". * * ENTRY: * pString (output) * Points string to store converted date/time into. * EXIT: * ******************************************************************************/
void WINAPI CurrentDateTimeString( LPTSTR pString ) { SYSTEMTIME stime; LPTSTR lpTimeStr; int nLen;
GetLocalTime(&stime); //Get DateFormat
nLen = GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, NULL, 0); lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR)); if(NULL == lpTimeStr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); wcscpy(pString, L""); return; } nLen = GetDateFormat( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stime, NULL, lpTimeStr, nLen); wcscpy(pString, lpTimeStr); wcscat(pString, L" "); GlobalFree(lpTimeStr);
//Get Time Format
nLen = GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, &stime, NULL, NULL, 0); lpTimeStr = (LPTSTR) GlobalAlloc(GPTR, (nLen + 1) * sizeof(TCHAR)); if(NULL == lpTimeStr) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); wcscpy(pString, L""); return; } nLen = GetTimeFormat( LOCALE_USER_DEFAULT, TIME_NOSECONDS, &stime, NULL, lpTimeStr, nLen); wcscat(pString, lpTimeStr); GlobalFree(lpTimeStr);
} // end CurrentDateTimeString
/*******************************************************************************
* * CalculateDiffTime - Hydrix helper function * * Calculate the time difference between two LARGE_INTEGER time values. * * ENTRY: * FirstTime (input) * The first (lower) time value. * SecondTime (input) * The second (higher) time value. * * EXIT: * LARGE_INTEGER - the time difference * ******************************************************************************/
LARGE_INTEGER WINAPI CalculateDiffTime( LARGE_INTEGER FirstTime, LARGE_INTEGER SecondTime ) { LARGE_INTEGER DiffTime;
DiffTime = RtlLargeIntegerSubtract( SecondTime, FirstTime ); DiffTime = RtlExtendedLargeIntegerDivide( DiffTime, 10000000, NULL ); return(DiffTime);
} // end CalculateDiffTime
/*******************************************************************************
* * EnumerateMultiUserServers - Hydrix helper function * * Enumerate the Hydrix servers on the network by Domain * * ENTRY: * pDomain (input) * Specifies the domain to enumerate; NULL for current domain. * * EXIT: * (LPTSTR) Points to LocalAlloced buffer containing results of the * enumeration, in multi-string format, if sucessful; NULL if * error. The caller must perform a LocalFree of this buffer * when done. If error (NULL), the error code is set for * retrieval by GetLastError(); * ******************************************************************************/
LPWSTR WINAPI EnumerateMultiUserServers( LPWSTR pDomain )
{ PSERVER_INFO_101 pInfo = NULL; DWORD dwByteCount, dwIndex, TotalEntries; DWORD AvailCount = 0; LPWSTR pTemp, pBuffer = NULL;
/*
* Enumerate all WF servers on the specified domain. */ if ( NetServerEnum ( NULL, 101, (LPBYTE *)&pInfo, (DWORD) -1, &AvailCount, &TotalEntries, SV_TYPE_TERMINALSERVER, pDomain, NULL ) || !AvailCount ) goto done;
/*
* Traverse list and calculate the total byte count for list of * servers that will be returned. */ for ( dwByteCount = dwIndex = 0; dwIndex < AvailCount; dwIndex++ ) {
dwByteCount += (wcslen(pInfo[dwIndex].sv101_name) + 1) * 2; } dwByteCount += 2; // for ending null
/*
* Allocate memory. */ if ( (pBuffer = LocalAlloc(LPTR, dwByteCount)) == NULL ) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY); goto done; }
/*
* Traverse list again and copy servers to buffer. */ for ( pTemp = pBuffer, dwIndex = 0; dwIndex < AvailCount; dwIndex++ ) {
wcscpy(pTemp, pInfo[dwIndex].sv101_name); pTemp += (wcslen(pInfo[dwIndex].sv101_name) + 1); } *pTemp = L'\0'; // ending null
done: if ( AvailCount && pInfo ) NetApiBufferFree( pInfo );
return(pBuffer);
} // end EnumerateMultiUserServers
/******************************************************************************
* * _UserInGroup * Internal function, determines if a user is a member of any of the * groups passed in * * ENTRY: * pwszUsername (IN) - Username to test group membership of * * pwszDomain (IN) - Domain of the user passed in * * pwszGroup (IN) - String array of all the allowed groups * * EXIT: * Returns BOOLEAN value if user is a member of one of the groups * HISTORY: * * *****************************************************************************/ BOOL _UserInGroup( LPWSTR pwszUsername, LPWSTR pwszDomain, LPWSTR pwszGroup ) { DWORD EntriesRead; DWORD EntriesLeft; NET_API_STATUS rc; PGROUP_USERS_INFO_0 pszGroups; ULONG i; PWCHAR pwcUser; WCHAR szBuf[MAX_PATH]; LPWKSTA_INFO_100 pWorkstationInfo = NULL; WCHAR szDomainController[50]; #if DBG
DbgPrint( "MSGINA: UserInGroup: look(%S\\%S) group(%S)\n", pwszDomain, pwszUsername, pwszGroup ); #endif
// This call will return the domain of the computer, not the domain of the user
if (( NetWkstaGetInfo( NULL, 100, (LPBYTE *)&pWorkstationInfo )) == NERR_Success) { if( !CtxGetAnyDCName( NULL, pWorkstationInfo->wki100_langroup, szDomainController ) ){ NetApiBufferFree((LPVOID)pWorkstationInfo); return( FALSE ); } } else { return (FALSE); }
if ( wcscmp( pWorkstationInfo->wki100_langroup, pwszDomain ) != 0 ) { // user is from a different domain than the machine (trusted domain)
// need to change username to reflect the domain
wcscpy( szBuf, pwszDomain ); wcscat( szBuf, L"\\" ); wcscat( szBuf, pwszUsername ); pwcUser = szBuf; } else { pwcUser = pwszUsername; }
rc = NetUserGetLocalGroups( szDomainController, pwcUser, 0, // level
LG_INCLUDE_INDIRECT, // flags
(LPBYTE*)&pszGroups, MAX_BUFFER, &EntriesRead, &EntriesLeft );
if( pWorkstationInfo != NULL ) NetApiBufferFree((LPVOID)pWorkstationInfo);
if ( rc != NERR_Success ) { return( FALSE ); }
for ( i=0; i < EntriesRead; i++ ) { if ( wcscmp( pszGroups[i].grui0_name, pwszGroup ) == 0 ) { NetApiBufferFree( pszGroups ); pszGroups = NULL; return( TRUE ); } }
NetApiBufferFree( pszGroups ); pszGroups = NULL; return(FALSE);
}
/******************************************************************************
* * CtxGetAnyDCName * Function to find a any DC of a specified domain. The call * NetGetAnyDCName does not work as needed in all occasions. * ie. Trusted domains and the current server being a DC. * * ENTRY: * pServer (IN) - Server on which to run the call (RPC) * * pDomain (IN) - Domain you are inquring about, does not need to be * current domain * * pBuffer (OUT) - Pointer to a string containg a DC name, buffer must * be passed in. * EXIT: * BOOL Success * * HISTORY: * * *****************************************************************************/
BOOL CtxGetAnyDCName ( PWCHAR pServer, PWCHAR pDomain, PWCHAR pBuffer ) {
PWCHAR pDomainController = NULL; PWCHAR pLocalDomainDC = NULL; SERVER_INFO_101* ServerBuf = NULL; BOOLEAN rc = TRUE; BOOLEAN bFoundDC = FALSE;
// This call will return the domain of the computer, not the domain of the user
if (( NetGetAnyDCName(NULL, pDomain, (LPBYTE *)&pDomainController)) != NERR_Success) { //
// NetGetAnyDCName doesn't work in two situations
// 1. If the domain is a trusted domain, it must be run from a DC. So we find our local
// DC and have it run getanydcname for us.
// 2. If we are a DC it will fail. So a second check is made to see
// if in fact we are a DC or not
//
// find a local DC in which to RPC to
if( NetGetAnyDCName( NULL, NULL, (LPBYTE *) &pLocalDomainDC ) == NERR_Success ) { // Make the call as an RPC and pass it the Domain name
if( NetGetAnyDCName( pLocalDomainDC, pDomain, (LPBYTE *) &pDomainController ) == NERR_Success){ bFoundDC = TRUE; } }
// if it wasn't a trusted domain, maybe we are a domain controller
if( !bFoundDC ) { if( NetServerGetInfo( NULL, 101, (LPBYTE*)&ServerBuf ) == NERR_Success ) { if( ServerBuf->sv101_type & (SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL) ) { pDomainController = NULL; } else { rc = FALSE; goto done; } } else { rc = FALSE; goto done; } } } if( pDomainController ) wcscpy( pBuffer, pDomainController); else *pBuffer = '\0'; done:
if( pLocalDomainDC ) NetApiBufferFree( pLocalDomainDC ); if( pDomainController ) NetApiBufferFree( pDomainController ); if( ServerBuf ) NetApiBufferFree( ServerBuf );
return( rc ); }
|