|
|
/*******************************************************************************
* config.c * * Published Terminal Server APIs * * - user configuration routines * * Copyright 1998, Citrix Systems Inc. * Copyright (C) 1997-1999 Microsoft Corp. /******************************************************************************/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntddkbd.h>
#include <ntddmou.h>
#include <windows.h>
#include <ntsecapi.h>
#include <lm.h>
#include <winbase.h>
#include <winerror.h>
#if(WINVER >= 0x0500)
#include <ntstatus.h>
#include <winsta.h>
#else
#include <citrix\cxstatus.h>
#include <citrix\winsta.h>
#endif
#include <utildll.h>
#include <stdio.h>
#include <stdarg.h>
#include <lmaccess.h> // for NetGet[Any]DCName KLB 10-07-97
#include <lmerr.h> // for NERR_Success KLB 10-07-97
#include <lmapibuf.h> // for NetApiBufferFree KLB 10-07-97
#include <wtsapi32.h>
/*=============================================================================
== External procedures defined =============================================================================*/
BOOL WINAPI WTSQueryUserConfigW( LPWSTR, LPWSTR, WTS_CONFIG_CLASS, LPWSTR *, DWORD *); BOOL WINAPI WTSQueryUserConfigA( LPSTR, LPSTR, WTS_CONFIG_CLASS, LPSTR *, DWORD *); BOOL WINAPI WTSSetUserConfigW( LPWSTR, LPWSTR, WTS_CONFIG_CLASS, LPWSTR, DWORD); BOOL WINAPI WTSSetUserConfigA( LPSTR, LPSTR, WTS_CONFIG_CLASS, LPSTR, DWORD);
/*=============================================================================
== Internal procedures defined =============================================================================*/ #ifdef NETWARE
//This should be defined in the wtsapi32.h
typedef struct _WTS_USER_CONFIG_SET_NWSERVERW { LPWSTR pNWServerName; LPWSTR pNWDomainAdminName; LPWSTR pNWDomainAdminPassword; } WTS_USER_CONFIG_SET_NWSERVERW, * PWTS_USER_CONFIG_SET_NWSERVERW;
BOOL SetNWAuthenticationServer(PWTS_USER_CONFIG_SET_NWSERVERW pInput, LPWSTR pServerNameW, LPWSTR pUserNameW, PUSERCONFIGW pUserConfigW );
#endif
/*=============================================================================
== Procedures used =============================================================================*/
BOOL _CopyData( PVOID, ULONG, LPWSTR *, DWORD * ); BOOL _CopyStringW( LPWSTR, LPWSTR *, DWORD * ); BOOL _CopyStringA( LPSTR, LPWSTR *, DWORD * ); BOOL _CopyStringWtoA( LPWSTR, LPSTR *, DWORD * ); BOOL ValidateCopyAnsiToUnicode(LPSTR, DWORD, LPWSTR); BOOL ValidateCopyUnicodeToUnicode(LPWSTR, DWORD, LPWSTR); VOID UnicodeToAnsi( CHAR *, ULONG, WCHAR * ); VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
/*=============================================================================
== Local Data =============================================================================*/
/****************************************************************************
* * WTSQueryUserConfigW (UNICODE) * * Query information from the SAM for the specified user * * ENTRY: * pServerName (input) * Name of server to access (NULL for current machine). * pUserName (input) * User name to query * WTSConfigClass (input) * Specifies the type of information to retrieve about the specified user * ppBuffer (output) * Points to the address of a variable to receive information about * the specified session. The format and contents of the data * depend on the specified information class being queried. The * buffer is allocated within this API and is disposed of using * WTSFreeMemory. * pBytesReturned (output) * An optional parameter that if specified, receives the number of * bytes returned. * * EXIT: * * TRUE -- The query operation succeeded. * * FALSE -- The operation failed. Extended error status is available * using GetLastError. * * HISTORY: * Created KLB 10-06-97 * ****************************************************************************/
BOOL WINAPI WTSQueryUserConfigW( IN LPWSTR pServerName, IN LPWSTR pUserName, IN WTS_CONFIG_CLASS WTSConfigClass, OUT LPWSTR * ppBuffer, OUT DWORD * pBytesReturned ) { USERCONFIGW UserConfigW; ULONG ulReturnLength; LONG rc; BOOL fSuccess = FALSE; DWORD dwfInheritInitialProgram; DWORD dwReturnValue; PUSER_INFO_0 pUserInfo = NULL; WCHAR netServerName[DOMAIN_LENGTH + 3];
/*
* Check the null buffer */
if (!ppBuffer || !pBytesReturned) { SetLastError (ERROR_INVALID_PARAMETER); fSuccess = FALSE; goto done; }
// Verify the length of the incoming parameter pServerName
// we do lstrcpy operations below with this parameter and do not want to overflow the buffer
if ( (pServerName != NULL) && (wcslen(pServerName) > DOMAIN_LENGTH) ) { SetLastError (ERROR_INVALID_PARAMETER); fSuccess = FALSE; goto done; }
/*
* First, we want to make sure the user actually exists on the specified * machine. */
rc = NetUserGetInfo( pServerName, // server name (can be NULL)
pUserName, // user name
0, // level to query (0 = just name)
(LPBYTE *)&pUserInfo );// buffer to return data to (they alloc, we free)
/*
* append the "\\" in front of server name to check the user name existence again */
if ( rc != NERR_Success && pServerName) {
lstrcpyW(netServerName, L"\\\\"); lstrcatW(netServerName, pServerName);
rc = NetUserGetInfo( netServerName, // server name (can be NULL)
pUserName, // user name
0, // level to query (0 = user name)
(LPBYTE *)&pUserInfo );// buffer to return data to (they alloc, we free)
if ( rc != NERR_Success ) { SetLastError( ERROR_NO_SUCH_USER ); goto done; // exit with fSuccess = FALSE
} }
/*
* Query the user. If the user config doesn't exist for the user, then * we query the default values. */ rc = RegUserConfigQuery( pServerName, // server name
pUserName, // user name
&UserConfigW, // returned user config
(ULONG)sizeof(UserConfigW),// user config length
&ulReturnLength ); // #bytes returned
if ( rc != ERROR_SUCCESS ) { rc = RegDefaultUserConfigQuery( pServerName, // server name
&UserConfigW, // returned user config
(ULONG)sizeof(UserConfigW),// user config length
&ulReturnLength ); // #bytes returned
}
/*
* Now, process the results. Note that in each case, we're allocating a * new buffer which the caller must free * (WTSUserConfigfInheritInitialProgram is just a boolean, but we allocate * a DWORD to send it back). */ if ( rc == ERROR_SUCCESS ) { switch ( WTSConfigClass ) { case WTSUserConfigInitialProgram: fSuccess = _CopyStringW( UserConfigW.InitialProgram, ppBuffer, pBytesReturned ); break;
case WTSUserConfigWorkingDirectory: fSuccess = _CopyStringW( UserConfigW.WorkDirectory, ppBuffer, pBytesReturned ); break;
case WTSUserConfigfInheritInitialProgram: dwReturnValue = UserConfigW.fInheritInitialProgram; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
case WTSUserConfigfAllowLogonTerminalServer: //DWORD returned/expected
dwReturnValue = !(UserConfigW.fLogonDisabled); fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned );
break; //Timeout settings
case WTSUserConfigTimeoutSettingsConnections: dwReturnValue = UserConfigW.MaxConnectionTime; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
case WTSUserConfigTimeoutSettingsDisconnections: //DWORD
dwReturnValue = UserConfigW.MaxDisconnectionTime; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
case WTSUserConfigTimeoutSettingsIdle: //DWORD
dwReturnValue = UserConfigW.MaxIdleTime; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break; case WTSUserConfigfDeviceClientDrives: //DWORD
dwReturnValue = UserConfigW.fAutoClientDrives; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
case WTSUserConfigfDeviceClientPrinters: //DWORD
dwReturnValue = UserConfigW.fAutoClientLpts; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
case WTSUserConfigfDeviceClientDefaultPrinter: //DWORD
dwReturnValue = UserConfigW.fForceClientLptDef; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
//Connection settings
case WTSUserConfigBrokenTimeoutSettings: //DWORD
dwReturnValue = UserConfigW.fResetBroken; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break; case WTSUserConfigReconnectSettings: dwReturnValue = UserConfigW.fReconnectSame; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break;
//Modem settings
case WTSUserConfigModemCallbackSettings: //DWORD
dwReturnValue = UserConfigW.Callback; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break; case WTSUserConfigModemCallbackPhoneNumber: fSuccess = _CopyStringW(UserConfigW.CallbackNumber, ppBuffer, pBytesReturned ); break;
case WTSUserConfigShadowingSettings: //DWORD
dwReturnValue = UserConfigW.Shadow; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break; #ifdef NETWARE
case WTSUserConfigNWServerName: // string
fSuccess = _CopyStringW(UserConfigW.NWLogonServer, ppBuffer, pBytesReturned );
break; #endif
case WTSUserConfigTerminalServerProfilePath: // string
fSuccess = _CopyStringW(UserConfigW.WFProfilePath, ppBuffer, pBytesReturned ); break;
case WTSUserConfigTerminalServerHomeDir: // string
fSuccess = _CopyStringW(UserConfigW.WFHomeDir, ppBuffer, pBytesReturned ); break; case WTSUserConfigTerminalServerHomeDirDrive: // string
fSuccess = _CopyStringW(UserConfigW.WFHomeDirDrive, ppBuffer, pBytesReturned ); break;
case WTSUserConfigfTerminalServerRemoteHomeDir: // DWORD 0:LOCAL 1:REMOTE
if (wcslen(UserConfigW.WFHomeDirDrive) > 0 ) { dwReturnValue = 1;
} else { dwReturnValue = 0; }
fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned );
break; #ifdef NETWARE
case WTSUserConfigfNWMapRoot: dwReturnValue = UserConfigW.fHomeDirectoryMapRoot; fSuccess = _CopyData( &dwReturnValue, sizeof(DWORD), ppBuffer, pBytesReturned ); break; #endif
} // switch()
} //if (rc == ERROR_SUCCESS)
done:
if ( pUserInfo ) { NetApiBufferFree( pUserInfo ); } return( fSuccess ); }
/****************************************************************************
* * WTSQueryUserConfigA (ANSI) * * Query information from the SAM for the specified user * * ENTRY: * * see WTSQueryUserConfigW * * EXIT: * * TRUE -- The query operation succeeded. * * FALSE -- The operation failed. Extended error status is available * using GetLastError. * * HISTORY: * Created KLB 10-06-97 * ****************************************************************************/
BOOL WINAPI WTSQueryUserConfigA( IN LPSTR pServerName, IN LPSTR pUserName, IN WTS_CONFIG_CLASS WTSConfigClass, OUT LPSTR * ppBuffer, OUT DWORD * pBytesReturned ) { LPWSTR lpBufferW = NULL; BOOL fSuccess; LONG rc; LPWSTR pUserNameW = NULL; LPWSTR pServerNameW = NULL;
if (!ppBuffer || !pBytesReturned) { SetLastError (ERROR_INVALID_PARAMETER); fSuccess = FALSE; goto done; }
fSuccess = _CopyStringA( pUserName, &pUserNameW, NULL ); if ( fSuccess ) { fSuccess = _CopyStringA( pServerName, &pServerNameW, NULL ); } if ( fSuccess ) { fSuccess = WTSQueryUserConfigW( pServerNameW, pUserNameW, WTSConfigClass, &lpBufferW, pBytesReturned ); LocalFree( pUserNameW ); } // Now, process the results.
if ( fSuccess ) switch ( WTSConfigClass ) { case WTSUserConfigInitialProgram: case WTSUserConfigWorkingDirectory: case WTSUserConfigModemCallbackPhoneNumber: #ifdef NETWARE
case WTSUserConfigNWServerName: // string returned/expected
#endif
case WTSUserConfigTerminalServerProfilePath: // string returned/expected
case WTSUserConfigTerminalServerHomeDir: // string returned/expected
case WTSUserConfigTerminalServerHomeDirDrive: // string returned/expected
/*
* String Data - Convert to ANSI */ { /*
* allocate return buffer for max possible MultiByte string */ DWORD DataLength = (wcslen( lpBufferW ) + 1) * sizeof(WCHAR); *ppBuffer = LocalAlloc( LPTR, DataLength ); if ( *ppBuffer != NULL ) {
RtlUnicodeToMultiByteN( *ppBuffer, DataLength, pBytesReturned, lpBufferW, DataLength); fSuccess = TRUE;
} else {
fSuccess = FALSE; } LocalFree( lpBufferW );
break; }
default: /*
* Just a DWORD, point buffer at the one returned (caller is * responsible for freeing, so this is cool). */ *ppBuffer = (LPSTR)lpBufferW; break; } // switch()
done: return( fSuccess ); }
/****************************************************************************
* * WTSSetUserConfigW (UNICODE) * * Set information in the SAM for the specified user * * ENTRY: * pServerName (input) * Name of server to access (NULL for current machine). * pUserName (input) * User name to query * WTSConfigClass (input) * Specifies the type of information to change for the specified user * pBuffer (input) * Pointer to the data used to modify the specified user's information. * DataLength (input) * The length of the data provided. * * EXIT: * * TRUE -- The query operation succeeded. * * FALSE -- The operation failed. Extended error status is available * using GetLastError. * * HISTORY: * Created KLB 10-06-97 * ****************************************************************************/
BOOL WINAPI WTSSetUserConfigW( IN LPWSTR pServerName, IN LPWSTR pUserName, IN WTS_CONFIG_CLASS WTSConfigClass, IN LPWSTR pBuffer, IN DWORD DataLength ) { USERCONFIGW UserConfigW; ULONG ulReturnLength; LONG rc; BOOL fSuccess = FALSE; BOOL fUserConfig = TRUE; //TRUE - We use RegUserConfigSet
//FALSE - Use NetUserSetInfo
DWORD dwfInheritInitialProgram; PDWORD pdwValue = (DWORD *) pBuffer; PUSER_INFO_0 pUserInfo = NULL; DWORD dwParam = 0; WCHAR netServerName[DOMAIN_LENGTH + 3];
if (!pBuffer || DataLength == 0) { SetLastError (ERROR_INVALID_PARAMETER); goto done; // exit with fSuccess = FALSE
}
// Verify the length of the incoming parameter pServerName
// we do lstrcpy operations below with this parameter and do not want to overflow the buffer
if ( (pServerName != NULL) && (wcslen(pServerName) > DOMAIN_LENGTH) ) { SetLastError (ERROR_INVALID_PARAMETER); goto done; }
/*
* First, we want to make sure the user actually exists on the specified * machine. */
rc = NetUserGetInfo( pServerName, // server name (can be NULL)
pUserName, // user name
0, // level to query (0 = just name)
(LPBYTE *)&pUserInfo );// buffer to return data to (they alloc, we free)
if ( rc != NERR_Success ) {
if (pServerName != NULL) { lstrcpyW(netServerName, L"\\\\"); lstrcatW(netServerName, pServerName); rc = NetUserGetInfo( netServerName, // server name (can be NULL)
pUserName, // user name
3, // level to query (3 = ust name)
(LPBYTE *)&pUserInfo );// buffer to return data to (they alloc, we free)
} else { rc = NetUserGetInfo( NULL, // server name is NULL
pUserName, // user name
3, // level to query (3 = ust name)
(LPBYTE *)&pUserInfo );// buffer to return data to (they alloc, we free)
}
if ( rc != NERR_Success ) { SetLastError( ERROR_NO_SUCH_USER ); goto done; // exit with fSuccess = FALSE
} }
/*
* Query the user. If the user config doesn't exist for the user, then * we query the default values. */ rc = RegUserConfigQuery( pServerName, // server name
pUserName, // user name
&UserConfigW, // returned user config
(ULONG)sizeof(UserConfigW),// user config length
&ulReturnLength ); // #bytes returned
if ( rc != ERROR_SUCCESS ) { rc = RegDefaultUserConfigQuery( pServerName, // server name
&UserConfigW, // returned user config
(ULONG)sizeof(UserConfigW),// user config length
&ulReturnLength ); // #bytes returned
} if ( rc != ERROR_SUCCESS ) { goto done; }
/*
* Now, we plug in the part we want to change. */ switch ( WTSConfigClass ) { case WTSUserConfigInitialProgram: if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, INITIALPROGRAM_LENGTH, UserConfigW.InitialProgram)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break;
case WTSUserConfigWorkingDirectory: if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, DIRECTORY_LENGTH, UserConfigW.WorkDirectory)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break;
case WTSUserConfigfInheritInitialProgram: /*
* We have to point a DWORD pointer at the data, then assign it * from the DWORD, as that's how it's defined (and this will * ensure that it works okay on non-Intel architectures). */ UserConfigW.fInheritInitialProgram = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigfAllowLogonTerminalServer: if (*pdwValue) { UserConfigW.fLogonDisabled = FALSE; } else { UserConfigW.fLogonDisabled = TRUE; }
fSuccess = TRUE;
break;
case WTSUserConfigTimeoutSettingsConnections: UserConfigW.MaxConnectionTime = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigTimeoutSettingsDisconnections: //DWORD
UserConfigW.MaxDisconnectionTime = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigTimeoutSettingsIdle: //DWORD
UserConfigW.MaxIdleTime = *pdwValue; fSuccess = TRUE; break; case WTSUserConfigfDeviceClientDrives: //DWORD
UserConfigW.fAutoClientDrives = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigfDeviceClientPrinters: //DWORD
UserConfigW.fAutoClientLpts = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigfDeviceClientDefaultPrinter: //DWORD
UserConfigW.fForceClientLptDef = *pdwValue; fSuccess = TRUE; break;
case WTSUserConfigBrokenTimeoutSettings: //DWORD
UserConfigW.fResetBroken= *pdwValue; fSuccess = TRUE; break; case WTSUserConfigReconnectSettings: UserConfigW.fReconnectSame = *pdwValue; fSuccess = TRUE; break;
//Modem settings
case WTSUserConfigModemCallbackSettings: //DWORD
UserConfigW.Callback = *pdwValue; fSuccess = TRUE; break; case WTSUserConfigModemCallbackPhoneNumber: if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, sizeof(UserConfigW.CallbackNumber) - 1, UserConfigW.CallbackNumber)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break;
case WTSUserConfigShadowingSettings: //DWORD
UserConfigW.Shadow = *pdwValue; fSuccess = TRUE; break; #ifdef NETWARE
case WTSUserConfigNWServerName: // WTS_USER_CONFIG_SET_NWSERVERW
// Make sure the data structure is correct
//
if (DataLength < sizeof (WTS_USER_CONFIG_SET_NWSERVERW)) { fSuccess = FALSE; SetLastError(ERROR_INVALID_PARAMETER); goto done; } fSuccess = SetNWAuthenticationServer((PWTS_USER_CONFIG_SET_NWSERVERW)pBuffer, pServerName, pUserName, pBuffer, &UserConfigW);
goto done;
break; #endif
case WTSUserConfigTerminalServerProfilePath: // string
if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, sizeof(UserConfigW.WFProfilePath) - 1, UserConfigW.WFProfilePath)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break;
case WTSUserConfigTerminalServerHomeDir: // string
if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, sizeof(UserConfigW.WFHomeDir) - 1, UserConfigW.WFHomeDir)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break; case WTSUserConfigTerminalServerHomeDirDrive: // string
if (!(fSuccess = ValidateCopyUnicodeToUnicode((LPWSTR)pBuffer, sizeof(UserConfigW.WFHomeDirDrive) - 1, UserConfigW.WFHomeDirDrive)) ) { SetLastError(ERROR_INVALID_DATA); goto done; } break;
case WTSUserConfigfTerminalServerRemoteHomeDir: // DWORD 0:LOCAL 1:REMOTE
fSuccess = FALSE; SetLastError (ERROR_INVALID_PARAMETER); // We don't set this parameter
goto done; break; #ifdef NETWARE
case WTSUserConfigfNWMapRoot: UserConfigW.fHomeDirectoryMapRoot = *pdwValue; fSuccess = TRUE; break; #endif
default: fSuccess = FALSE; SetLastError (ERROR_INVALID_PARAMETER); goto done;
}
if ( fSuccess ) { if (fUserConfig) { /*
* Only in here if we successfully changed the data in UserConfigW. * So, we can now write it out to the SAM. */
rc = RegUserConfigSet( pServerName, // server name
pUserName, // user name
&UserConfigW, // returned user config
(ULONG)sizeof(UserConfigW));// user config length
} fSuccess = (ERROR_SUCCESS == rc); if ( !fSuccess ) { SetLastError( rc ); } }
done: if ( pUserInfo ) { NetApiBufferFree( pUserInfo ); }
return(fSuccess); }
/****************************************************************************
* * WTSSetUserConfigA (ANSI) * * Set information in the SAM for the specified user * * ENTRY: * * see WTSSetUserConfigW * * EXIT: * * TRUE -- The query operation succeeded. * * FALSE -- The operation failed. Extended error status is available * using GetLastError. * * HISTORY: * Created KLB 10-06-97 * ****************************************************************************/
BOOL WINAPI WTSSetUserConfigA( IN LPSTR pServerName, IN LPSTR pUserName, IN WTS_CONFIG_CLASS WTSConfigClass, IN LPSTR pBuffer, IN DWORD DataLength ) { BOOL fSuccess = FALSE; BOOL fFreepBufferW = TRUE; LPWSTR pUserNameW = NULL; LPWSTR pServerNameW = NULL; LPWSTR pBufferW = NULL; DWORD dwDataLength;
if (!pBuffer || DataLength == 0) { SetLastError (ERROR_INVALID_PARAMETER); goto done; // exit with fSuccess = FALSE
}
/*
* We're going to call WTSSetUserConfigW() to do the actual work. We need * to convert all ANSI strings to Unicode before calling. These are the * user name, and the pBuffer data if it's the initial program or the * working directory; if it's the flag for inherit initial program, it'll * be a DWORD in either case, so no conversion is necessary. */ fSuccess = _CopyStringA( pUserName, &pUserNameW, NULL ); if ( fSuccess ) { fSuccess = _CopyStringA( pServerName, &pServerNameW, NULL ); } if ( fSuccess ) switch ( WTSConfigClass ) { case WTSUserConfigInitialProgram: case WTSUserConfigWorkingDirectory: case WTSUserConfigModemCallbackPhoneNumber:
case WTSUserConfigTerminalServerProfilePath: // string returned/expected
case WTSUserConfigTerminalServerHomeDir: // string returned/expected
case WTSUserConfigTerminalServerHomeDirDrive: // string returned/expected
/*
* String Data - Convert to Unicode (_CopyStringA() allocates * pBufferW for us) */ fSuccess = _CopyStringA( pBuffer, &pBufferW, &dwDataLength ); break; #ifdef NETWARE
case WTSUserConfigNWServerName: // string returned/expected
{ //Need to convert the data structure from ASCII to UNICODE
PWTS_USER_CONFIG_SET_NWSERVERW pSetNWServerParamW = LocalAlloc(LPTR, sizeof(WTS_USER_CONFIG_SET_NWSERVERW)); PWTS_USER_CONFIG_SET_NWSERVERA pSetNWServerParamA = (PWTS_USER_CONFIG_SET_NWSERVERA)pBuffer; DWORD dwLen = 0; if (pSetNWServerParamW == NULL) { fSuccess = FALSE; break; } pBufferW = pSetNWServerParamW;
//----------------------------------------//
// Allocate the buffer to hold the //
// required unicode string //
//----------------------------------------//
dwLen = strlen(pSetNWServerParamA -> pNWServerName); if (fSuccess = _CopyStringA(pSetNWServerParamA -> pNWServerName, &pSetNWServerParamW -> pNWServerName, &dwLen)) { dwLen = strlen(pSetNWServerParamA -> pNWDomainAdminName); if (fSuccess = _CopyStringA(pSetNWServerParamA -> pNWDomainAdminName, &pSetNWServerParamW -> pNWDomainAdminName, &dwLen)) { dwLen = strlen(pSetNWServerParamA -> pNWDomainAdminPassword); fSuccess = _CopyStringA(pSetNWServerParamA -> pNWDomainAdminPassword, &pSetNWServerParamW -> pNWDomainAdminPassword, &dwLen);
}
}
//-----------------------------------------//
// Call the UNICODE function //
//-----------------------------------------//
if (fSuccess) {
fSuccess = WTSSetUserConfigW( pServerNameW, pUserNameW, WTSConfigClass, pBufferW, dwDataLength ); }
//----------------------------------------------//
// Free the storage for the specific function //
//----------------------------------------------//
if (pSetNWServerParamW -> pNWServerName) { LocalFree( pSetNWServerParamW -> pNWServerName ); } if (pSetNWServerParamW -> pNWDomainAdminName) { LocalFree( pSetNWServerParamW -> pNWDomainAdminName ); }
if (pSetNWServerParamW -> pNWDomainAdminPassword) { LocalFree( pSetNWServerParamW -> pNWDomainAdminPassword ); } goto done; break; } #endif
default: /*
* Just a DWORD, point our wide buffer at the narrow buffer passed * in to us and set the data length variable we'll pass down. * NOTE: WE DON'T WANT TO FREE THE BUFFER, since we're re-using * the buffer sent in and the caller expects to free it. We'll * use a BOOL to decide, rather than allocating an extra buffer * here (performance, memory fragmentation, etc.). KLB 10-08-97 */ pBufferW = (LPWSTR) pBuffer; dwDataLength = sizeof(DWORD); fFreepBufferW = FALSE; break; } // switch()
/*
* Now, if fSuccess is TRUE, we've copied all the strings we need. So, we * can now call WTSSetUserConfigW(). */ if ( fSuccess ) { fSuccess = WTSSetUserConfigW( pServerNameW, pUserNameW, WTSConfigClass, pBufferW, dwDataLength ); } done: if ( pUserNameW ) { LocalFree( pUserNameW ); } if ( fFreepBufferW && pBufferW ) { LocalFree( pBufferW ); } return(fSuccess); }
#ifdef NETWARE
BOOL SetNWAuthenticationServer(PWTS_USER_CONFIG_SET_NWSERVERW pInput, LPWSTR pServerNameW, LPWSTR pUserNameW, PUSERCONFIGW pUserConfigW )
{ BOOL bStatus = TRUE; PWKSTA_INFO_100 pWkstaInfo = NULL; NWLOGONADMIN nwLogonAdmin; HANDLE hServer; DWORD dwStatus; //----------------------------------//
// Get a Server handle
//----------------------------------//
hServer = RegOpenServer(pServerNameW); if (!hServer) { SetLastError(GetLastError()); bStatus = FALSE; goto done; }
//----------------------------------
//find the domain name
//------------------------------------
dwStatus = NetWkstaGetInfo( pServerNameW, 100, &pWkstaInfo ); if (dwStatus != ERROR_SUCCESS) { SetLastError(dwStatus); goto done; } //-----------------------------------------------------
//Copy the parameter to the NWLOGONADMIN structure
//-----------------------------------------------------
bStatus = ValidateCopyUnicodeToUnicode(pInput -> pNWDomainAdminName, sizeof(nwLogonAdmin.Username)-1, nwLogonAdmin.Username); if (!bStatus) { goto done; }
bStatus = ValidateCopyUnicodeToUnicode(pInput -> pNWDomainAdminPassword, sizeof(nwLogonAdmin.Password)-1, nwLogonAdmin.Password); if (!bStatus) { goto done; }
bStatus = ValidateCopyUnicodeToUnicode(pWkstaInfo -> wki100_langroup, sizeof(nwLogonAdmin.Domain)-1, nwLogonAdmin.Domain); if (!bStatus) { goto done; }
//------------------------------------------//
// Set the admin //
//-----------------------------------------//
bStatus = _NWLogonSetAdmin(hServer, &nwLogonAdmin, sizeof(nwLogonAdmin));
if (!bStatus) { SetLastError(GetLastError()); goto done; }
done: if (pWkstaInfo) { NetApiBufferFree(pWkstaInfo); }
return bStatus;
}
#endif
|