1776 lines
55 KiB
C
1776 lines
55 KiB
C
|
||
/*************************************************************************
|
||
*
|
||
* reguc.c
|
||
*
|
||
* Registry APIs for SAM-based user configuration data
|
||
*
|
||
* Copyright (c) 1998 Microsoft Corporation
|
||
*
|
||
*
|
||
*
|
||
*************************************************************************/
|
||
|
||
/*
|
||
* Includes
|
||
*/
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <ntlsa.h>
|
||
#include <ntsam.h>
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <windows.h>
|
||
#include <lm.h>
|
||
|
||
#include <ntddkbd.h>
|
||
#include <ntddmou.h>
|
||
#include <winstaw.h>
|
||
#include <regapi.h>
|
||
#include <regsam.h>
|
||
|
||
#include <rpc.h>
|
||
#include <rpcdce.h>
|
||
#include <ntdsapi.h>
|
||
// For more info, check out \\index1\src\nt\private\security\tools\delegate\ldap.c
|
||
|
||
#include "usrprop.h"
|
||
|
||
/*
|
||
* !!! WARNING !!! WARNING !!!
|
||
*
|
||
* A lot of time could be spent on making this calculation accurate and
|
||
* automatic, but time is of the essence. So a brute force
|
||
* approach is used. The size of the User Configuration section that
|
||
* Citrix is going to add to the User Parameters is based on NOT
|
||
* ONLY the size of the USERCONFIG structure, but must account for the
|
||
* Value names and the buffer management pointers as well, since the
|
||
* User Parameters section is a linear buffer that holds CITRIX data
|
||
* and Microsoft Services for Netware data.
|
||
*
|
||
* It is assumed that the overhead of the value name strings and
|
||
* the buffer management pointers will NOT be greater than twice the
|
||
* maximum data size. If this assumption is false, buffer overruns
|
||
* will occur.
|
||
*
|
||
* Bruce Fortune. 1/31/97.
|
||
*/
|
||
#define CTX_USER_PARAM_MAX_SIZE (3 * sizeof(USERCONFIG))
|
||
|
||
/*
|
||
* CTXPREFIX is the prefix for all value names placed in the User
|
||
* Parameters section of the SAM. This is a defensive measure since
|
||
* this section of the SAM is shared with MS Services for Netware.
|
||
*/
|
||
#define CTXPREFIX L"Ctx"
|
||
|
||
/*
|
||
* WIN_FLAGS1 is the name of the Flags value that is used to hold
|
||
* all of the F1MSK_... flags defined below. This is done in order to
|
||
* reduce the amount of space required in the User Parameters section
|
||
* of the SAM, since the value name of each flag is eliminated.
|
||
*/
|
||
#define WIN_FLAGS1 L"CfgFlags1"
|
||
|
||
/*
|
||
* WIN_CFGPRESENT is used to indicate that the Citrix configuration
|
||
* information is present in the User Parameters section of the user's
|
||
* SAM record.
|
||
*/
|
||
#define WIN_CFGPRESENT L"CfgPresent"
|
||
#define CFGPRESENT_VALUE 0xB00B1E55
|
||
|
||
#define F1MSK_INHERITAUTOLOGON 0x80000000
|
||
#define F1MSK_INHERITRESETBROKEN 0x40000000
|
||
#define F1MSK_INHERITRECONNECTSAME 0x20000000
|
||
#define F1MSK_INHERITINITIALPROGRAM 0x10000000
|
||
#define F1MSK_INHERITCALLBACK 0x08000000
|
||
#define F1MSK_INHERITCALLBACKNUMBER 0x04000000
|
||
#define F1MSK_INHERITSHADOW 0x02000000
|
||
#define F1MSK_INHERITMAXSESSIONTIME 0x01000000
|
||
#define F1MSK_INHERITMAXDISCONNECTIONTIME 0x00800000
|
||
#define F1MSK_INHERITMAXIDLETIME 0x00400000
|
||
#define F1MSK_INHERITAUTOCLIENT 0x00200000
|
||
#define F1MSK_INHERITSECURITY 0x00100000
|
||
#define F1MSK_PROMPTFORPASSWORD 0x00080000
|
||
#define F1MSK_RESETBROKEN 0x00040000
|
||
#define F1MSK_RECONNECTSAME 0x00020000
|
||
#define F1MSK_LOGONDISABLED 0x00010000
|
||
#define F1MSK_AUTOCLIENTDRIVES 0x00008000
|
||
#define F1MSK_AUTOCLIENTLPTS 0x00004000
|
||
#define F1MSK_FORCECLIENTLPTDEF 0x00002000
|
||
#define F1MSK_DISABLEENCRYPTION 0x00001000
|
||
#define F1MSK_HOMEDIRECTORYMAPROOT 0x00000800
|
||
#define F1MSK_USEDEFAULTGINA 0x00000400
|
||
#define F1MSK_DISABLECPM 0x00000200
|
||
#define F1MSK_DISABLECDM 0x00000100
|
||
#define F1MSK_DISABLECCM 0x00000080
|
||
#define F1MSK_DISABLELPT 0x00000040
|
||
#define F1MSK_DISABLECLIP 0x00000020
|
||
#define F1MSK_DISABLEEXE 0x00000010
|
||
#define F1MSK_WALLPAPERDISABLED 0x00000008
|
||
#define F1MSK_DISABLECAM 0x00000004
|
||
//#define F1MSK_unused 0x00000002
|
||
//#define F1MSK_unused 0x00000001
|
||
|
||
VOID AnsiToUnicode( WCHAR *, ULONG, CHAR * );
|
||
NTSTATUS GetDomainName ( PWCHAR, PWCHAR * );
|
||
ULONG GetFlagMask( PUSERCONFIG );
|
||
VOID QueryUserConfig( HKEY, PUSERCONFIG );
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropSetValue (UNICODE)
|
||
*
|
||
* Sets a 1-, 2-, or 4-byte value into the supplied User Parameters buffer
|
||
*
|
||
* ENTRY:
|
||
* pValueName (input)
|
||
* Points to the Value Name string
|
||
* pValue (input)
|
||
* Points to value
|
||
* ValueLength (input)
|
||
* Number of bytes in the Value
|
||
* pUserParms (input)
|
||
* Points to the specially formatted User Parameters buffer
|
||
* UserParmsLength (input)
|
||
* Length in bytes of the pUserParms buffer
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropSetValue(
|
||
WCHAR * pValueName,
|
||
PVOID pValue,
|
||
USHORT ValueLength,
|
||
BOOL fDefaultValue,
|
||
WCHAR * pUserParms,
|
||
ULONG UserParmsLength
|
||
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
UNICODE_STRING uniValue;
|
||
LPWSTR lpNewUserParms = NULL;
|
||
BOOL fUpdate;
|
||
PWCHAR pNameBuf;
|
||
ULONG NBLen;
|
||
|
||
/*
|
||
* Prefix the name with a unique string so that other users of
|
||
* the user parameters section of the SAM won't collide with our
|
||
* value names.
|
||
*/
|
||
NBLen = sizeof(CTXPREFIX) + ((wcslen(pValueName) + 1) * sizeof(WCHAR));
|
||
pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
|
||
if ( !pNameBuf ) {
|
||
return( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
wcscpy( pNameBuf, CTXPREFIX );
|
||
wcscat( pNameBuf, pValueName );
|
||
|
||
uniValue.Buffer = (PWCHAR) pValue;
|
||
uniValue.Length = ValueLength;
|
||
uniValue.MaximumLength = uniValue.Length;
|
||
|
||
Status = SetUserProperty( pUserParms,
|
||
pNameBuf,
|
||
uniValue,
|
||
USER_PROPERTY_TYPE_ITEM,
|
||
fDefaultValue,
|
||
&lpNewUserParms,
|
||
&fUpdate );
|
||
|
||
LocalFree( pNameBuf );
|
||
if ((Status == STATUS_SUCCESS) && (lpNewUserParms != NULL)) {
|
||
if (fUpdate) {
|
||
if ( (wcslen( lpNewUserParms ) * sizeof(WCHAR)) > UserParmsLength ) {
|
||
return( STATUS_BUFFER_TOO_SMALL );
|
||
}
|
||
lstrcpyW( pUserParms, lpNewUserParms);
|
||
}
|
||
|
||
LocalFree( lpNewUserParms );
|
||
}
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropGetValue (UNICODE)
|
||
*
|
||
* Gets a value from the supplied User Parameters buffer
|
||
*
|
||
* ENTRY:
|
||
* pValuegName (input)
|
||
* Points to the Value Name string
|
||
* pValue (output)
|
||
* Points to the buffer to receive the value
|
||
* ValueLength (input)
|
||
* Number of bytes in the buffer pointer to by pValue
|
||
* pUserParms (input)
|
||
* Points to the specially formatted User Parameters buffer
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropGetValue(
|
||
TCHAR * pValueName,
|
||
PVOID pValue,
|
||
ULONG ValueLength,
|
||
WCHAR * pUserParms
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
UNICODE_STRING uniValue;
|
||
WCHAR Flag;
|
||
PWCHAR pNameBuf;
|
||
ULONG NBLen;
|
||
|
||
/*
|
||
* Prefix the name with a unique string so that other users of
|
||
* the user parameters section of the SAM won't collide with our
|
||
* usage.
|
||
*/
|
||
NBLen = sizeof(CTXPREFIX) + ((wcslen(pValueName) + 1) * sizeof(WCHAR));
|
||
pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
|
||
if ( !pNameBuf ) {
|
||
return( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
wcscpy( pNameBuf, CTXPREFIX );
|
||
wcscat( pNameBuf, pValueName );
|
||
|
||
Status = QueryUserProperty( pUserParms, pNameBuf, &Flag, &uniValue );
|
||
LocalFree( pNameBuf );
|
||
if ( Status != STATUS_SUCCESS ) {
|
||
return( Status );
|
||
}
|
||
|
||
if ( !uniValue.Buffer ) {
|
||
memset( pValue, 0, ValueLength );
|
||
} else {
|
||
memcpy( pValue, uniValue.Buffer, ValueLength );
|
||
LocalFree( uniValue.Buffer );
|
||
}
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropSetString (UNICODE)
|
||
*
|
||
* Sets a variable length string into the supplied User Parameters buffer
|
||
*
|
||
* ENTRY:
|
||
* pStringName (input)
|
||
* Points to the String Name string
|
||
* pStringValue (input)
|
||
* Points to the string
|
||
* pUserParms (input)
|
||
* Points to the specially formatted User Parameters buffer
|
||
* UserParmsLength (input)
|
||
* Length in bytes of the pUserParms buffer
|
||
* fDefaultValue
|
||
* Indicates that this value is a default value and should not be saved
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropSetString(
|
||
WCHAR * pStringName,
|
||
WCHAR * pStringValue,
|
||
WCHAR * pUserParms,
|
||
ULONG UserParmsLength,
|
||
BOOL fDefaultValue
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
UNICODE_STRING uniString;
|
||
CHAR * pchTemp = NULL;
|
||
LPWSTR lpNewUserParms = NULL;
|
||
BOOL fUpdate;
|
||
PWCHAR pNameBuf;
|
||
ULONG NBLen;
|
||
INT nMBLen;
|
||
|
||
|
||
if (pStringValue == NULL) {
|
||
uniString.Buffer = NULL;
|
||
uniString.Length = 0;
|
||
uniString.MaximumLength = 0;
|
||
}
|
||
else
|
||
{
|
||
BOOL fDummy;
|
||
|
||
INT nStringLength = lstrlen(pStringValue) + 1;
|
||
|
||
// Determine the length of the mulitbyte string
|
||
// allocate it and convert to
|
||
// this fixes bug 264907
|
||
|
||
// Next release we'll need to change from ansi code page to
|
||
// UTF8.
|
||
|
||
nMBLen = WideCharToMultiByte(CP_ACP,
|
||
0,
|
||
pStringValue,
|
||
nStringLength,
|
||
pchTemp,
|
||
0,
|
||
NULL,
|
||
NULL );
|
||
pchTemp = ( CHAR * )LocalAlloc( LPTR , nMBLen );
|
||
if ( pchTemp == NULL )
|
||
{
|
||
#ifdef DBG
|
||
OutputDebugString( L"REGAPI : UsrPropSetString - STATUS_INSUFFICIENT_RESOURCES\n" );
|
||
#endif
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
else if( !WideCharToMultiByte( CP_ACP,
|
||
0 ,
|
||
pStringValue ,
|
||
nStringLength ,
|
||
pchTemp ,
|
||
nMBLen ,
|
||
NULL ,
|
||
NULL ) )
|
||
{
|
||
#ifdef DBG
|
||
// OutputDebugString( L"REGAPI : UsrPropSetString - STATUS_UNSUCCESSFUL wctomb failed.\n" );
|
||
DbgPrint( "REGAPI : UsrPropSetString - STATUS_UNSUCCESSFUL wctomb failed with 0x%x.\n" , GetLastError( ) );
|
||
#endif
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
if( Status == STATUS_SUCCESS )
|
||
{
|
||
uniString.Buffer = (WCHAR *) pchTemp;
|
||
uniString.Length = (USHORT)nMBLen;
|
||
uniString.MaximumLength = (USHORT)nMBLen;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Prefix the name with a unique string so that other users of
|
||
* the user parameters section of the SAM won't collide with our
|
||
* usage.
|
||
*/
|
||
NBLen = sizeof(CTXPREFIX) + ((wcslen(pStringName) + 1) * sizeof(WCHAR));
|
||
pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
|
||
if ( !pNameBuf ) {
|
||
return( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
|
||
wcscpy( pNameBuf, CTXPREFIX );
|
||
wcscat( pNameBuf, pStringName );
|
||
|
||
Status = Status ? Status : SetUserProperty( pUserParms,
|
||
pNameBuf,
|
||
uniString,
|
||
USER_PROPERTY_TYPE_ITEM,
|
||
fDefaultValue,
|
||
&lpNewUserParms,
|
||
&fUpdate );
|
||
LocalFree( pNameBuf );
|
||
if ( (Status == STATUS_SUCCESS) && (lpNewUserParms != NULL))
|
||
{
|
||
if ( fUpdate )
|
||
{
|
||
if ( (wcslen( lpNewUserParms ) * sizeof(WCHAR)) > UserParmsLength )
|
||
{
|
||
return( STATUS_BUFFER_TOO_SMALL );
|
||
}
|
||
lstrcpyW( pUserParms, lpNewUserParms);
|
||
}
|
||
|
||
LocalFree( lpNewUserParms );
|
||
}
|
||
if ( pchTemp != NULL )
|
||
{
|
||
LocalFree( pchTemp );
|
||
}
|
||
return( Status );
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropGetString (UNICODE)
|
||
*
|
||
* Gets a variable length string from the supplied User Parameters buffer
|
||
*
|
||
* ENTRY:
|
||
* pStringName (input)
|
||
* Points to the String Name string
|
||
* pStringValue (output)
|
||
* Points to the string
|
||
* StringValueLength (input)
|
||
* Number of bytes in the buffer pointer to by pStringValue
|
||
* pUserParms (input)
|
||
* Points to the specially formatted User Parameters buffer
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropGetString(
|
||
TCHAR * pStringName,
|
||
TCHAR * pStringValue,
|
||
ULONG StringValueLength,
|
||
WCHAR * pUserParms
|
||
)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
UNICODE_STRING uniString;
|
||
WCHAR Flag;
|
||
PWCHAR pNameBuf;
|
||
ULONG NBLen;
|
||
|
||
/*
|
||
* Prefix the name with a unique string so that other users of
|
||
* the user parameters section of the SAM won't collide with our
|
||
* usage.
|
||
*/
|
||
NBLen = sizeof(CTXPREFIX) + ((wcslen(pStringName) + 1) * sizeof(WCHAR));
|
||
pNameBuf = (PWCHAR) LocalAlloc( LPTR, NBLen );
|
||
if ( !pNameBuf ) {
|
||
return( STATUS_INSUFFICIENT_RESOURCES );
|
||
}
|
||
wcscpy( pNameBuf, CTXPREFIX );
|
||
wcscat( pNameBuf, pStringName );
|
||
|
||
pStringValue[0] = L'\0';
|
||
Status = QueryUserProperty( pUserParms, pNameBuf, &Flag, &uniString );
|
||
LocalFree( pNameBuf );
|
||
|
||
if ( !( Status == STATUS_SUCCESS && uniString.Length && uniString.Buffer) ) {
|
||
pStringValue[0] = L'\0';
|
||
} else {
|
||
if ( !MultiByteToWideChar( CP_ACP,
|
||
0,
|
||
(CHAR *)uniString.Buffer,
|
||
uniString.Length,
|
||
pStringValue,
|
||
StringValueLength ) ) {
|
||
Status = STATUS_UNSUCCESSFUL;
|
||
}
|
||
}
|
||
|
||
if ( uniString.Buffer ) {
|
||
LocalFree( uniString.Buffer );
|
||
}
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* ConnectToSAM (UNICODE)
|
||
*
|
||
* Given a Server name and a Domain name, connect to the SAM
|
||
*
|
||
* ENTRY:
|
||
* pServerName (input)
|
||
* Points to the Server name
|
||
* pDomainValue (input)
|
||
* Points to the Domain name
|
||
* pSAMHandle (output)
|
||
* Pointer to the Handle to the SAM
|
||
* pDomainHandle (output)
|
||
* Pointer to the Handle to the Domain
|
||
* pDomainID (ouptut)
|
||
* Pointer to the Domain SID
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
ConnectToSam(
|
||
BOOLEAN fReadOnly,
|
||
LPTSTR pServerName,
|
||
LPTSTR pDomainName,
|
||
SAM_HANDLE * pSAMHandle,
|
||
SAM_HANDLE * pDomainHandle,
|
||
PSID * pDomainID
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
OBJECT_ATTRIBUTES object_attrib;
|
||
UNICODE_STRING UniDomainName;
|
||
UNICODE_STRING UniServerName;
|
||
|
||
*pSAMHandle = NULL;
|
||
*pDomainHandle = NULL;
|
||
*pDomainID = NULL;
|
||
|
||
//
|
||
// connect to SAM (Security Account Manager)
|
||
//
|
||
#ifdef DEBUG
|
||
DbgPrint( "ConnectToSam: pServerName %ws, pDomainName %ws\n", pServerName, pDomainName );
|
||
#endif // DEBUG
|
||
RtlInitUnicodeString(&UniServerName, pServerName);
|
||
RtlInitUnicodeString(&UniDomainName, pDomainName);
|
||
InitializeObjectAttributes(&object_attrib, NULL, 0, NULL, NULL);
|
||
status = SamConnect( &UniServerName,
|
||
pSAMHandle,
|
||
fReadOnly
|
||
? SAM_SERVER_READ |
|
||
SAM_SERVER_EXECUTE
|
||
: STANDARD_RIGHTS_WRITE |
|
||
SAM_SERVER_EXECUTE,
|
||
&object_attrib );
|
||
#ifdef DEBUG
|
||
DbgPrint( "ConnectToSam: SamConnect returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto exit;
|
||
}
|
||
|
||
status = SamLookupDomainInSamServer( *pSAMHandle,
|
||
&UniDomainName,
|
||
pDomainID);
|
||
#ifdef DEBUG
|
||
DbgPrint( "ConnectToSam: SamLookupDomainInSamServer returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto cleanupconnect;
|
||
}
|
||
|
||
status = SamOpenDomain( *pSAMHandle,
|
||
fReadOnly
|
||
? DOMAIN_READ |
|
||
DOMAIN_LOOKUP |
|
||
DOMAIN_READ_PASSWORD_PARAMETERS
|
||
: DOMAIN_READ |
|
||
DOMAIN_CREATE_ALIAS |
|
||
DOMAIN_LOOKUP |
|
||
DOMAIN_CREATE_USER |
|
||
DOMAIN_READ_PASSWORD_PARAMETERS,
|
||
*pDomainID,
|
||
pDomainHandle );
|
||
#ifdef DEBUG
|
||
DbgPrint( "ConnectToSam: SamOpenDomain returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto cleanuplookup;
|
||
}
|
||
|
||
return( STATUS_SUCCESS );
|
||
|
||
/*
|
||
* Error returns
|
||
*/
|
||
|
||
cleanuplookup:
|
||
SamFreeMemory( *pDomainID );
|
||
*pDomainID = NULL;
|
||
|
||
cleanupconnect:
|
||
SamCloseHandle( *pSAMHandle );
|
||
*pSAMHandle = NULL;
|
||
|
||
exit:
|
||
return( status );
|
||
}
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropQueryUserConfig
|
||
*
|
||
* Query USERCONFIG info from SAM's User Parameters
|
||
*
|
||
* ENTRY:
|
||
* pUserParms (input)
|
||
* pointer to a wide char buffer containing the SAM's User Parameters
|
||
* UPlength (input )
|
||
* length of the pUserParms buffer
|
||
* pUser (output)
|
||
* pointer to USERCONFIG structure
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropQueryUserConfig(
|
||
WCHAR *pUserParms,
|
||
ULONG UPLength,
|
||
PUSERCONFIG pUser )
|
||
{
|
||
ULONG Flags1;
|
||
NTSTATUS Status;
|
||
ULONG CfgPresent;
|
||
USERCONFIG ucDefault;
|
||
|
||
QueryUserConfig( HKEY_LOCAL_MACHINE , &ucDefault );
|
||
|
||
/*
|
||
* Check if the configuration exits in the User Parameters
|
||
*/
|
||
|
||
if( ( ( Status = UsrPropGetValue( WIN_CFGPRESENT,
|
||
&CfgPresent,
|
||
sizeof(CfgPresent),
|
||
pUserParms ) ) != NO_ERROR ) )
|
||
{
|
||
KdPrint( ( "UsrPropQueryUserConfig: UsrPropGetValue returned NTSTATUS = 0x%x\n", Status ) );
|
||
return( Status );
|
||
}
|
||
else
|
||
{
|
||
if( CfgPresent != CFGPRESENT_VALUE )
|
||
{
|
||
KdPrint( ( "UsrPropQueryUserConfig: UsrPropGetValue returned NTSTATUS = 0x%x but TS-signature was not present\n", Status ) );
|
||
return( STATUS_OBJECT_NAME_NOT_FOUND );
|
||
}
|
||
}
|
||
Status = UsrPropGetValue( WIN_FLAGS1,
|
||
&Flags1,
|
||
sizeof(Flags1),
|
||
pUserParms );
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_CALLBACK,
|
||
&pUser->Callback,
|
||
sizeof(pUser->Callback),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->Callback = ucDefault.Callback;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_SHADOW,
|
||
&pUser->Shadow,
|
||
sizeof(pUser->Shadow),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->Shadow = ucDefault.Shadow;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_MAXCONNECTIONTIME,
|
||
&pUser->MaxConnectionTime,
|
||
sizeof(pUser->MaxConnectionTime),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->MaxConnectionTime = ucDefault.MaxConnectionTime;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_MAXDISCONNECTIONTIME,
|
||
&pUser->MaxDisconnectionTime,
|
||
sizeof(pUser->MaxDisconnectionTime),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->MaxDisconnectionTime = ucDefault.MaxDisconnectionTime;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_MAXIDLETIME,
|
||
&pUser->MaxIdleTime,
|
||
sizeof(pUser->MaxIdleTime),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->MaxIdleTime = ucDefault.MaxIdleTime;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_KEYBOARDLAYOUT,
|
||
&pUser->KeyboardLayout,
|
||
sizeof(pUser->KeyboardLayout),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->KeyboardLayout = ucDefault.KeyboardLayout;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetValue( WIN_MINENCRYPTIONLEVEL,
|
||
&pUser->MinEncryptionLevel,
|
||
sizeof(pUser->MinEncryptionLevel),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
pUser->MinEncryptionLevel = ucDefault.MinEncryptionLevel;
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
// String properties that do not exist are init to NULL
|
||
// default values are null so need to fix if ret status is a failure.
|
||
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_WORKDIRECTORY,
|
||
pUser->WorkDirectory,
|
||
sizeof(pUser->WorkDirectory),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_NWLOGONSERVER,
|
||
pUser->NWLogonServer,
|
||
sizeof(pUser->NWLogonServer),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_WFHOMEDIR,
|
||
pUser->WFHomeDir,
|
||
sizeof(pUser->WFHomeDir),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_WFHOMEDIRDRIVE,
|
||
pUser->WFHomeDirDrive,
|
||
sizeof(pUser->WFHomeDir),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_WFPROFILEPATH,
|
||
pUser->WFProfilePath,
|
||
sizeof(pUser->WFProfilePath),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_INITIALPROGRAM,
|
||
pUser->InitialProgram,
|
||
sizeof(pUser->InitialProgram),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
Status = UsrPropGetString( WIN_CALLBACKNUMBER,
|
||
pUser->CallbackNumber,
|
||
sizeof(pUser->CallbackNumber),
|
||
pUserParms );
|
||
if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
|
||
{
|
||
Status = STATUS_SUCCESS;
|
||
}
|
||
}
|
||
if( !( NT_SUCCESS( Status ) ) )
|
||
{
|
||
return( Status );
|
||
}
|
||
|
||
pUser->fInheritAutoLogon =
|
||
Flags1 & F1MSK_INHERITAUTOLOGON ? TRUE : FALSE;
|
||
pUser->fInheritResetBroken =
|
||
Flags1 & F1MSK_INHERITRESETBROKEN ? TRUE : FALSE;
|
||
pUser->fInheritReconnectSame =
|
||
Flags1 & F1MSK_INHERITRECONNECTSAME ? TRUE : FALSE;
|
||
pUser->fInheritInitialProgram =
|
||
Flags1 & F1MSK_INHERITINITIALPROGRAM ? TRUE : FALSE;
|
||
pUser->fInheritCallback =
|
||
Flags1 & F1MSK_INHERITCALLBACK ? TRUE : FALSE;
|
||
pUser->fInheritCallbackNumber =
|
||
Flags1 & F1MSK_INHERITCALLBACKNUMBER ? TRUE : FALSE;
|
||
pUser->fInheritShadow =
|
||
Flags1 & F1MSK_INHERITSHADOW ? TRUE : FALSE;
|
||
pUser->fInheritMaxSessionTime =
|
||
Flags1 & F1MSK_INHERITMAXSESSIONTIME ? TRUE : FALSE;
|
||
pUser->fInheritMaxDisconnectionTime =
|
||
Flags1 & F1MSK_INHERITMAXDISCONNECTIONTIME ? TRUE : FALSE;
|
||
pUser->fInheritMaxIdleTime =
|
||
Flags1 & F1MSK_INHERITMAXIDLETIME ? TRUE : FALSE;
|
||
pUser->fInheritAutoClient =
|
||
Flags1 & F1MSK_INHERITAUTOCLIENT ? TRUE : FALSE;
|
||
pUser->fInheritSecurity =
|
||
Flags1 & F1MSK_INHERITSECURITY ? TRUE : FALSE;
|
||
pUser->fPromptForPassword =
|
||
Flags1 & F1MSK_PROMPTFORPASSWORD ? TRUE : FALSE;
|
||
pUser->fResetBroken =
|
||
Flags1 & F1MSK_RESETBROKEN ? TRUE : FALSE;
|
||
pUser->fReconnectSame =
|
||
Flags1 & F1MSK_RECONNECTSAME ? TRUE : FALSE;
|
||
pUser->fLogonDisabled =
|
||
Flags1 & F1MSK_LOGONDISABLED ? TRUE : FALSE;
|
||
pUser->fAutoClientDrives =
|
||
Flags1 & F1MSK_AUTOCLIENTDRIVES ? TRUE : FALSE;
|
||
pUser->fAutoClientLpts =
|
||
Flags1 & F1MSK_AUTOCLIENTLPTS ? TRUE : FALSE;
|
||
pUser->fForceClientLptDef =
|
||
Flags1 & F1MSK_FORCECLIENTLPTDEF ? TRUE : FALSE;
|
||
pUser->fDisableEncryption =
|
||
Flags1 & F1MSK_DISABLEENCRYPTION ? TRUE : FALSE;
|
||
pUser->fHomeDirectoryMapRoot =
|
||
Flags1 & F1MSK_HOMEDIRECTORYMAPROOT ? TRUE : FALSE;
|
||
pUser->fUseDefaultGina =
|
||
Flags1 & F1MSK_USEDEFAULTGINA ? TRUE : FALSE;
|
||
pUser->fDisableCpm =
|
||
Flags1 & F1MSK_DISABLECPM ? TRUE : FALSE;
|
||
pUser->fDisableCdm =
|
||
Flags1 & F1MSK_DISABLECDM ? TRUE : FALSE;
|
||
pUser->fDisableCcm =
|
||
Flags1 & F1MSK_DISABLECCM ? TRUE : FALSE;
|
||
pUser->fDisableLPT =
|
||
Flags1 & F1MSK_DISABLELPT ? TRUE : FALSE;
|
||
pUser->fDisableClip =
|
||
Flags1 & F1MSK_DISABLECLIP ? TRUE : FALSE;
|
||
pUser->fDisableExe =
|
||
Flags1 & F1MSK_DISABLEEXE ? TRUE : FALSE;
|
||
pUser->fWallPaperDisabled =
|
||
Flags1 & F1MSK_WALLPAPERDISABLED ? TRUE : FALSE;
|
||
pUser->fDisableCam =
|
||
Flags1 & F1MSK_DISABLECAM ? TRUE : FALSE;
|
||
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* UsrPropMergeUserConfig
|
||
*
|
||
* Merge USERCONFIG structure into User Properties section of SAM
|
||
*
|
||
* ENTRY:
|
||
* pUserParms (input/output)
|
||
* pointer to a wide char buffer containing the SAM's User Parameters
|
||
* UPlength (input )
|
||
* length of the pUserParms buffer
|
||
* pUser (input)
|
||
* pointer to USERCONFIG structure
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
* NOTES:
|
||
* Certain properties have to be stored regardless if they're default or not
|
||
* this is done to maintain compatibility for TSE4.0 and W2K servers
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
UsrPropMergeUserConfig(
|
||
WCHAR *pUserParms,
|
||
ULONG UPLength,
|
||
PUSERCONFIG pUser )
|
||
{
|
||
ULONG Flags1;
|
||
NTSTATUS Status;
|
||
USERCONFIG ucDefault;
|
||
ULONG CfgPresent = CFGPRESENT_VALUE;
|
||
BOOL fDefaultValue = FALSE;
|
||
|
||
// 1st parameter forces default values to be placed in ucDefault
|
||
QueryUserConfig( HKEY_LOCAL_MACHINE , &ucDefault );
|
||
|
||
Flags1 = GetFlagMask( pUser );
|
||
|
||
// this value needs to be written out
|
||
|
||
Status = UsrPropSetValue( WIN_CFGPRESENT,
|
||
&CfgPresent,
|
||
sizeof(CfgPresent),
|
||
FALSE,
|
||
pUserParms,
|
||
UPLength );
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
// these values must be written out for TS4 & TS5.0
|
||
Status = UsrPropSetValue( WIN_FLAGS1,
|
||
&Flags1,
|
||
sizeof(Flags1),
|
||
FALSE,
|
||
pUserParms,
|
||
UPLength );
|
||
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->Callback == ucDefault.Callback );
|
||
Status = UsrPropSetValue( WIN_CALLBACK,
|
||
&pUser->Callback,
|
||
sizeof(pUser->Callback),
|
||
fDefaultValue,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
// this value must be written out for backcompat servers
|
||
Status = UsrPropSetValue( WIN_SHADOW,
|
||
&pUser->Shadow,
|
||
sizeof(pUser->Shadow),
|
||
FALSE,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->MaxConnectionTime == ucDefault.MaxConnectionTime );
|
||
Status = UsrPropSetValue( WIN_MAXCONNECTIONTIME,
|
||
&pUser->MaxConnectionTime,
|
||
sizeof(pUser->MaxConnectionTime),
|
||
fDefaultValue,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->MaxDisconnectionTime == ucDefault.MaxDisconnectionTime );
|
||
Status = UsrPropSetValue( WIN_MAXDISCONNECTIONTIME,
|
||
&pUser->MaxDisconnectionTime,
|
||
sizeof(pUser->MaxDisconnectionTime),
|
||
fDefaultValue,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->MaxIdleTime == ucDefault.MaxIdleTime );
|
||
Status = UsrPropSetValue( WIN_MAXIDLETIME,
|
||
&pUser->MaxIdleTime,
|
||
sizeof(pUser->MaxIdleTime),
|
||
fDefaultValue,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->KeyboardLayout == ucDefault.KeyboardLayout );
|
||
Status = UsrPropSetValue( WIN_KEYBOARDLAYOUT,
|
||
&pUser->KeyboardLayout,
|
||
sizeof(pUser->KeyboardLayout),
|
||
fDefaultValue,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
// always store minencryption level for backwards compatibilty purposes
|
||
Status = UsrPropSetValue( WIN_MINENCRYPTIONLEVEL,
|
||
&pUser->MinEncryptionLevel,
|
||
sizeof(pUser->MinEncryptionLevel),
|
||
FALSE,
|
||
pUserParms,
|
||
UPLength );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->WorkDirectory[0] == 0 );
|
||
|
||
Status = UsrPropSetString( WIN_WORKDIRECTORY,
|
||
pUser->WorkDirectory,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->NWLogonServer[0] == 0 );
|
||
Status = UsrPropSetString( WIN_NWLOGONSERVER,
|
||
pUser->NWLogonServer,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->WFHomeDir[0] == 0 );
|
||
Status = UsrPropSetString( WIN_WFHOMEDIR,
|
||
pUser->WFHomeDir,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->WFHomeDirDrive[0] == 0 );
|
||
Status = UsrPropSetString( WIN_WFHOMEDIRDRIVE,
|
||
pUser->WFHomeDirDrive,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->WFProfilePath[0] == 0 );
|
||
Status = UsrPropSetString( WIN_WFPROFILEPATH,
|
||
pUser->WFProfilePath,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->InitialProgram[0] == 0 );
|
||
Status = UsrPropSetString( WIN_INITIALPROGRAM,
|
||
pUser->InitialProgram,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
if( NT_SUCCESS( Status ) )
|
||
{
|
||
fDefaultValue = ( pUser->CallbackNumber[0] == 0 );
|
||
Status = UsrPropSetString( WIN_CALLBACKNUMBER,
|
||
pUser->CallbackNumber,
|
||
pUserParms,
|
||
UPLength,
|
||
fDefaultValue );
|
||
}
|
||
return( Status );
|
||
|
||
}
|
||
|
||
/*******************************************************************************
|
||
GetFlagMask
|
||
Assembles a bitmask of flags set in pUser
|
||
|
||
*******************************************************************************/
|
||
ULONG GetFlagMask( PUSERCONFIG pUser )
|
||
{
|
||
ULONG Flags1 = 0;
|
||
|
||
if ( pUser->fInheritAutoLogon ) {
|
||
Flags1 |= F1MSK_INHERITAUTOLOGON;
|
||
}
|
||
if ( pUser->fInheritResetBroken ) {
|
||
Flags1 |= F1MSK_INHERITRESETBROKEN;
|
||
}
|
||
if ( pUser->fInheritReconnectSame ) {
|
||
Flags1 |= F1MSK_INHERITRECONNECTSAME;
|
||
}
|
||
if ( pUser->fInheritInitialProgram ) {
|
||
Flags1 |= F1MSK_INHERITINITIALPROGRAM;
|
||
}
|
||
if ( pUser->fInheritCallback ) {
|
||
Flags1 |= F1MSK_INHERITCALLBACK;
|
||
}
|
||
if ( pUser->fInheritCallbackNumber ) {
|
||
Flags1 |= F1MSK_INHERITCALLBACKNUMBER;
|
||
}
|
||
if ( pUser->fInheritShadow ) {
|
||
Flags1 |= F1MSK_INHERITSHADOW;
|
||
}
|
||
if ( pUser->fInheritMaxSessionTime ) {
|
||
Flags1 |= F1MSK_INHERITMAXSESSIONTIME;
|
||
}
|
||
if ( pUser->fInheritMaxDisconnectionTime ) {
|
||
Flags1 |= F1MSK_INHERITMAXDISCONNECTIONTIME;
|
||
}
|
||
if ( pUser->fInheritMaxIdleTime ) {
|
||
Flags1 |= F1MSK_INHERITMAXIDLETIME;
|
||
}
|
||
if ( pUser->fInheritAutoClient ) {
|
||
Flags1 |= F1MSK_INHERITAUTOCLIENT;
|
||
}
|
||
if ( pUser->fInheritSecurity ) {
|
||
Flags1 |= F1MSK_INHERITSECURITY;
|
||
}
|
||
if ( pUser->fPromptForPassword ) {
|
||
Flags1 |= F1MSK_PROMPTFORPASSWORD;
|
||
}
|
||
if ( pUser->fResetBroken ) {
|
||
Flags1 |= F1MSK_RESETBROKEN;
|
||
}
|
||
if ( pUser->fReconnectSame ) {
|
||
Flags1 |= F1MSK_RECONNECTSAME;
|
||
}
|
||
if ( pUser->fLogonDisabled ) {
|
||
Flags1 |= F1MSK_LOGONDISABLED;
|
||
}
|
||
if ( pUser->fAutoClientDrives ) {
|
||
Flags1 |= F1MSK_AUTOCLIENTDRIVES;
|
||
}
|
||
if ( pUser->fAutoClientLpts ) {
|
||
Flags1 |= F1MSK_AUTOCLIENTLPTS;
|
||
}
|
||
if ( pUser->fForceClientLptDef ) {
|
||
Flags1 |= F1MSK_FORCECLIENTLPTDEF;
|
||
}
|
||
if ( pUser->fDisableEncryption ) {
|
||
Flags1 |= F1MSK_DISABLEENCRYPTION;
|
||
}
|
||
if ( pUser->fHomeDirectoryMapRoot ) {
|
||
Flags1 |= F1MSK_HOMEDIRECTORYMAPROOT;
|
||
}
|
||
if ( pUser->fUseDefaultGina ) {
|
||
Flags1 |= F1MSK_USEDEFAULTGINA;
|
||
}
|
||
if ( pUser->fDisableCpm ) {
|
||
Flags1 |= F1MSK_DISABLECPM;
|
||
}
|
||
if ( pUser->fDisableCdm ) {
|
||
Flags1 |= F1MSK_DISABLECDM;
|
||
}
|
||
if ( pUser->fDisableCcm ) {
|
||
Flags1 |= F1MSK_DISABLECCM;
|
||
}
|
||
if ( pUser->fDisableLPT ) {
|
||
Flags1 |= F1MSK_DISABLELPT;
|
||
}
|
||
if ( pUser->fDisableClip ) {
|
||
Flags1 |= F1MSK_DISABLECLIP;
|
||
}
|
||
if ( pUser->fDisableExe ) {
|
||
Flags1 |= F1MSK_DISABLEEXE;
|
||
}
|
||
if ( pUser->fWallPaperDisabled ) {
|
||
Flags1 |= F1MSK_WALLPAPERDISABLED;
|
||
}
|
||
if ( pUser->fDisableCam ) {
|
||
Flags1 |= F1MSK_DISABLECAM;
|
||
}
|
||
|
||
return Flags1;
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* RegMergeUserConfigWithUserParameters
|
||
*
|
||
* Merge the User Configuration with the supplied SAM's User
|
||
* Parameters buffer.
|
||
*
|
||
* ENTRY:
|
||
* pUserParms (input/output)
|
||
* pointer to a wide char buffer containing the SAM's User Parameters
|
||
* UPlength (input)
|
||
* length of the pUserParms buffer
|
||
* pUser (input)
|
||
* pointer to USERCONFIG structure
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
RegMergeUserConfigWithUserParameters(
|
||
PUSER_PARAMETERS_INFORMATION pUserParmInfo,
|
||
PUSERCONFIGW pUser,
|
||
PUSER_PARAMETERS_INFORMATION pNewUserParmInfo
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
ULONG ObjectID;
|
||
PWCHAR lpNewUserParms = NULL;
|
||
ULONG UPLength;
|
||
WCHAR *pUserParms;
|
||
|
||
/*
|
||
* Compute the size the user parameter buffer must be
|
||
* in order to accommodate the CITRIX data plus the existing
|
||
* User Parameters data.
|
||
*/
|
||
|
||
KdPrint( ("TSUSEREX: User parameter length is %d\n", pUserParmInfo->Parameters.Length ) );
|
||
|
||
UPLength = (pUserParmInfo->Parameters.Length +
|
||
CTX_USER_PARAM_MAX_SIZE) *
|
||
sizeof(WCHAR);
|
||
pUserParms = (WCHAR *) LocalAlloc( LPTR, UPLength );
|
||
|
||
if ( pUserParms == NULL ) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
goto exit;
|
||
}
|
||
|
||
/*
|
||
* Copy SAM data to the local buffer.
|
||
* Let the Set/Get operation terminate the buffer.
|
||
*/
|
||
memcpy( pUserParms,
|
||
pUserParmInfo->Parameters.Buffer,
|
||
pUserParmInfo->Parameters.Length );
|
||
|
||
/*
|
||
* Zero fill the unused portion of the pUserParms buffer.
|
||
*/
|
||
memset( &pUserParms[ pUserParmInfo->Parameters.Length / sizeof(WCHAR) ],
|
||
0,
|
||
UPLength - pUserParmInfo->Parameters.Length );
|
||
|
||
status = UsrPropMergeUserConfig( pUserParms, UPLength, pUser );
|
||
if ( status != NO_ERROR ) {
|
||
goto cleanupoperation;
|
||
}
|
||
RtlInitUnicodeString( &pNewUserParmInfo->Parameters, pUserParms );
|
||
|
||
return( STATUS_SUCCESS );
|
||
|
||
/*
|
||
* Error returns
|
||
*/
|
||
|
||
cleanupoperation:
|
||
LocalFree( pUserParms );
|
||
|
||
exit:
|
||
return( status );
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* RegGetUserConfigFromUserParameters
|
||
*
|
||
* Get the User Configuration from the supplied SAM's
|
||
* User Parameters buffer.
|
||
*
|
||
* ENTRY:
|
||
* pUserParmInfo (input)
|
||
* pointer to a USER_PARAMETERS_INFORMATION structure obtained from
|
||
* a user's SAM entry
|
||
* pUser (input)
|
||
* pointer to USERCONFIG structure
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
NTSTATUS
|
||
RegGetUserConfigFromUserParameters(
|
||
PUSER_PARAMETERS_INFORMATION pUserParmInfo,
|
||
PUSERCONFIGW pUser
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
ULONG ObjectID;
|
||
PWCHAR lpNewUserParms = NULL;
|
||
ULONG UPLength;
|
||
WCHAR *pUserParms;
|
||
|
||
|
||
/*
|
||
* Compute the size the user parameter buffer must be
|
||
* in order to accommodate the existing User Parameters.
|
||
*/
|
||
UPLength = pUserParmInfo->Parameters.Length + sizeof(WCHAR);
|
||
pUserParms = (WCHAR *) LocalAlloc( LPTR, UPLength );
|
||
|
||
|
||
if ( pUserParms == NULL ) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
goto exit;
|
||
}
|
||
|
||
/*
|
||
* Copy SAM data to the local buffer and terminate the buffer.
|
||
*/
|
||
memcpy( pUserParms,
|
||
pUserParmInfo->Parameters.Buffer,
|
||
pUserParmInfo->Parameters.Length );
|
||
pUserParms[ pUserParmInfo->Parameters.Length / sizeof(WCHAR) ] = L'\0';
|
||
|
||
/*
|
||
* Extract the User Configuration from the SAM's User
|
||
* Parameters.
|
||
*/
|
||
status = UsrPropQueryUserConfig( pUserParms, UPLength, pUser );
|
||
|
||
LocalFree( pUserParms );
|
||
if ( status != NO_ERROR ) {
|
||
goto exit;
|
||
}
|
||
|
||
return( STATUS_SUCCESS );
|
||
|
||
/*
|
||
* Error returns
|
||
*/
|
||
|
||
exit:
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegGetUserConfigFromUserParameters: status = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
return( status );
|
||
|
||
}
|
||
|
||
|
||
/*******************************************************************************
|
||
*
|
||
* RegSAMUserConfig
|
||
*
|
||
* Set or Get the User Configuration for a user from the Domain whose
|
||
* PDC is server is given.
|
||
*
|
||
* ENTRY:
|
||
* fGetConfig (input)
|
||
* TRUE for Get config, FALSE for Set configuration
|
||
* pUsername (input)
|
||
* points to the user name
|
||
* pServerName (input)
|
||
* points to the name of the server. UNC names permitted.
|
||
* pUser (input/output)
|
||
* pointer to USERCONFIG structure
|
||
*
|
||
* EXIT:
|
||
* STATUS_SUCCESS - no error
|
||
*
|
||
******************************************************************************/
|
||
|
||
DWORD
|
||
RegSAMUserConfig(
|
||
BOOLEAN fGetConfig,
|
||
PWCHAR pUserName,
|
||
PWCHAR pServerName,
|
||
PUSERCONFIGW pUser
|
||
)
|
||
{
|
||
NTSTATUS status;
|
||
UNICODE_STRING UniUserName;
|
||
PULONG pRids = NULL;
|
||
PSID_NAME_USE pSidNameUse = NULL;
|
||
ULONG ObjectID;
|
||
SID_NAME_USE SidNameUse;
|
||
SAM_HANDLE Handle = (SAM_HANDLE) 0;
|
||
PUSER_PARAMETERS_INFORMATION UserParmInfo = NULL;
|
||
ULONG UPLength;
|
||
SAM_HANDLE SAMHandle = NULL;
|
||
SAM_HANDLE DomainHandle = NULL;
|
||
PWCHAR ServerName = NULL;
|
||
PSID DomainID = NULL;
|
||
PWCHAR pUserParms;
|
||
PWCHAR pDomainName = NULL;
|
||
WCHAR wCompName[MAX_COMPUTERNAME_LENGTH+1];
|
||
ULONG openFlag;
|
||
DWORD dwErr = ERROR_SUCCESS;
|
||
ULONG cValues;
|
||
HANDLE hDS = NULL;
|
||
PDS_NAME_RESULTW pDsResult = NULL;
|
||
|
||
typedef DWORD (WINAPI *PFNDSCRACKNAMES) ( HANDLE, DS_NAME_FLAGS, DS_NAME_FORMAT, \
|
||
DS_NAME_FORMAT, DWORD, LPTSTR *, PDS_NAME_RESULT *);
|
||
typedef void (WINAPI *PFNDSFREENAMERESULT) (DS_NAME_RESULT *);
|
||
typedef DWORD (WINAPI *PFNDSBIND) (TCHAR *, TCHAR *, HANDLE *);
|
||
typedef DWORD (WINAPI *PFNDSUNBIND) (HANDLE *);
|
||
|
||
|
||
PFNDSCRACKNAMES pfnDsCrackNamesW;
|
||
PFNDSFREENAMERESULT pfnDsFreeNameResultW;
|
||
PFNDSBIND pfnDsBindW;
|
||
PFNDSUNBIND pfnDsUnBindW;
|
||
|
||
|
||
// vars used for handling UPN anmes
|
||
WCHAR tmpUserName[MAX_PATH];
|
||
WCHAR *pUserAlias;
|
||
HINSTANCE hNtdsApi = NULL;
|
||
// We dont' care about the domain since we get it otherwise.
|
||
// WCHAR tmpDomainName[ MAX_PATH];
|
||
// tmpDomainName[0]=NULL;
|
||
|
||
tmpUserName[0]=0;
|
||
pUserAlias=NULL;
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig %s, User %ws, Server %ws\n", fGetConfig ? "GET" : "SET", pUserName, pServerName ? pServerName : L"-NULL-" );
|
||
#endif // DEBUG
|
||
|
||
if (pServerName == NULL) {
|
||
UPLength = MAX_COMPUTERNAME_LENGTH + 1;
|
||
if (!GetComputerName(wCompName, &UPLength)) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
goto exit;
|
||
}
|
||
}
|
||
|
||
// init this to the name passed in, if it is not a UPN name, we will continue to use
|
||
// the names passed into this function.
|
||
pUserAlias = pUserName;
|
||
|
||
//
|
||
//
|
||
// NEW code to handle UPN if the name passed in contains a '@' in the name.
|
||
// The call to CrackName is to seperate the UPN name into the user alias by
|
||
// contacting the DS and looking in the Gloabl-Catalog.
|
||
//
|
||
//
|
||
|
||
if ( wcschr(pUserName,L'@') != NULL )
|
||
{
|
||
|
||
hNtdsApi = LoadLibrary(TEXT("ntdsapi.dll"));
|
||
|
||
if ( hNtdsApi )
|
||
{
|
||
pfnDsCrackNamesW = (PFNDSCRACKNAMES)GetProcAddress(hNtdsApi, "DsCrackNamesW");
|
||
pfnDsFreeNameResultW = (PFNDSFREENAMERESULT)GetProcAddress(hNtdsApi, "DsFreeNameResultW");
|
||
pfnDsBindW = (PFNDSBIND)GetProcAddress(hNtdsApi, "DsBindW");
|
||
pfnDsUnBindW = (PFNDSUNBIND)GetProcAddress(hNtdsApi, "DsUnBindW");
|
||
|
||
|
||
if (pfnDsBindW && pfnDsCrackNamesW )
|
||
{
|
||
dwErr = pfnDsBindW(NULL, NULL, &hDS);
|
||
}
|
||
else
|
||
{
|
||
dwErr = ERROR_INVALID_FUNCTION;
|
||
}
|
||
|
||
if(dwErr == ERROR_SUCCESS)
|
||
{
|
||
dwErr = pfnDsCrackNamesW(hDS,
|
||
DS_NAME_NO_FLAGS,
|
||
DS_UNKNOWN_NAME,
|
||
DS_NT4_ACCOUNT_NAME,
|
||
1,
|
||
&pUserName,
|
||
&pDsResult);
|
||
|
||
if(dwErr == ERROR_SUCCESS)
|
||
{
|
||
if(pDsResult)
|
||
{
|
||
if( pDsResult->rItems )
|
||
{
|
||
if (pDsResult->rItems[0].pName )
|
||
{
|
||
// no error
|
||
status = STATUS_SUCCESS;
|
||
|
||
wcscpy(tmpUserName, pDsResult->rItems[0].pName);
|
||
KdPrint(("RegSAMUserConfig: tmpUserName=%ws\n",tmpUserName));
|
||
|
||
// do we have a non-null name?
|
||
if ( tmpUserName[0] ) {
|
||
pUserAlias = wcschr(tmpUserName,L'\\');
|
||
pUserAlias++; //move pass the wack.
|
||
|
||
// we are not using the domain name, we already have this
|
||
// wcscpy(tmpDomainName, pDsResult->rItems[0].pDomain);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
KdPrint(("RegSAMUserConfig: pDsResult->rItems[0].pName is NULL\n"));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
KdPrint(("RegSAMUserConfig: pDsResult->rItems=0x%lx\n",pDsResult->rItems));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
KdPrint(("RegSAMUserConfig: pDsResult=0x%lx\n",pDsResult));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
switch( dwErr )
|
||
{
|
||
case ERROR_INVALID_PARAMETER:
|
||
status = STATUS_INVALID_PARAMETER;
|
||
break;
|
||
|
||
case ERROR_NOT_ENOUGH_MEMORY:
|
||
status = STATUS_NO_MEMORY;
|
||
break;
|
||
|
||
default:
|
||
status = STATUS_UNSUCCESSFUL;
|
||
break;
|
||
}
|
||
// have decided to continue using the passed-in pUserName instead of what
|
||
// would have been returned from CrackName. Hence, no need to exit.
|
||
// goto exit;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
status = STATUS_UNSUCCESSFUL; // DsBindW doesn't have a clean set of errors.
|
||
// have decided to continue using the passed-in pUserName instead of what
|
||
// would have been returned from DsBind/CrackName. Hence, no need to exit.
|
||
// goto exit;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
status = STATUS_DLL_NOT_FOUND;
|
||
// have decided to continue using the passed-in pUserName instead of what
|
||
// would have been returned from DsBind/CrackName. Hence, no need to exit.
|
||
// goto exit;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig: pUserAlias=%ws\n", pUserAlias);
|
||
#endif // DEBUG
|
||
|
||
status = GetDomainName( pServerName, &pDomainName );
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig: GetDomainName returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto exit;
|
||
}
|
||
|
||
/*
|
||
* With the PDC Server name and the Domain Name,
|
||
* connect to the SAM
|
||
*/
|
||
status = ConnectToSam( fGetConfig,
|
||
pServerName,
|
||
pDomainName,
|
||
&SAMHandle,
|
||
&DomainHandle,
|
||
&DomainID );
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig: ConnectToSam returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto cleanupconnect;
|
||
}
|
||
|
||
RtlInitUnicodeString( &UniUserName, pUserAlias );
|
||
|
||
status = SamLookupNamesInDomain( DomainHandle,
|
||
1,
|
||
&UniUserName,
|
||
&pRids,
|
||
&pSidNameUse );
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig: SamLookupNamesInDomain returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
|
||
if ((status != STATUS_SUCCESS) ||
|
||
(pRids == NULL) ||
|
||
(pSidNameUse == NULL)) {
|
||
goto cleanuplookup;
|
||
}
|
||
|
||
/*
|
||
* Found the user name in the SAM, copy and free SAM info
|
||
*/
|
||
ObjectID = pRids[ 0 ];
|
||
SidNameUse = pSidNameUse[ 0 ];
|
||
SamFreeMemory( pRids );
|
||
SamFreeMemory( pSidNameUse );
|
||
|
||
/*
|
||
* Open the SAM entry for this user
|
||
*/
|
||
|
||
openFlag = fGetConfig ? USER_READ
|
||
: USER_WRITE_ACCOUNT| USER_READ;
|
||
|
||
|
||
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint("calling SamOpenUSer with flag = 0x%x\n", openFlag);
|
||
#endif
|
||
|
||
status = SamOpenUser( DomainHandle,
|
||
openFlag,
|
||
ObjectID,
|
||
&Handle );
|
||
|
||
// For getting config parametesr...
|
||
// The call will fail if it goes to the DC, for that case, change
|
||
// flag, since DC does allow access to read user-parameters (for
|
||
// legacy compat reasons).
|
||
if (!NT_SUCCESS( status ) && fGetConfig )
|
||
{
|
||
openFlag = 0;
|
||
#ifdef DEBUG
|
||
DbgPrint("calling SamOpenUSer with flag = 0x%x\n", openFlag);
|
||
#endif
|
||
status = SamOpenUser( DomainHandle,
|
||
openFlag,
|
||
ObjectID,
|
||
&Handle );
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig: SamOpenUser returned NTSTATUS = 0x%x\n", status );
|
||
#endif // DEBUG
|
||
if ( status != STATUS_SUCCESS ) {
|
||
goto cleanupsamopen;
|
||
}
|
||
|
||
/*
|
||
* Get the user parameters from the SAM
|
||
*/
|
||
status = SamQueryInformationUser( Handle,
|
||
UserParametersInformation,
|
||
(PVOID *) &UserParmInfo );
|
||
|
||
|
||
KdPrint( ( "RegSAMUserConfig: SamQueryInformationUser returned NTSTATUS = 0x%x\n", status ) );
|
||
|
||
|
||
if ( status != STATUS_SUCCESS || UserParmInfo == NULL ) {
|
||
goto cleanupsamquery;
|
||
}
|
||
if( fGetConfig )
|
||
{
|
||
/*
|
||
* Extract the User Configuration from the SAM's User
|
||
* Parameters.
|
||
*
|
||
* For Whistler builds and higher we assume that not every field
|
||
* has been stored in the SAM we'll need to retrieve the default
|
||
* values first
|
||
*/
|
||
KdPrint( ( "RegSAMUserConfig: UserParmInfo %d\n", UserParmInfo->Parameters.Length ) );
|
||
status = RegGetUserConfigFromUserParameters( UserParmInfo, pUser );
|
||
KdPrint( ( "RegSAMUserConfig: RegGetUserConfigFromUserParameters returned NTSTATUS = 0x%x\n", status ) );
|
||
SamFreeMemory( UserParmInfo );
|
||
UserParmInfo = NULL;
|
||
if ( status != NO_ERROR )
|
||
{
|
||
goto cleanupoperation;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
USER_PARAMETERS_INFORMATION NewUserParmInfo;
|
||
|
||
/*
|
||
* Set the SAM based on the supplied User Configuration.
|
||
*/
|
||
|
||
status = RegMergeUserConfigWithUserParameters( UserParmInfo,
|
||
pUser,
|
||
&NewUserParmInfo );
|
||
KdPrint( ( "RegSAMUserConfig: RegMergeUserConfigWithUserParameters returned NTSTATUS = 0x%x\n", status ) );
|
||
SamFreeMemory( UserParmInfo );
|
||
UserParmInfo = NULL;
|
||
if( status != NO_ERROR )
|
||
{
|
||
goto cleanupoperation;
|
||
}
|
||
status = SamSetInformationUser( Handle,
|
||
UserParametersInformation,
|
||
(PVOID) &NewUserParmInfo );
|
||
KdPrint( ( "RegSAMUserConfig: NewUserParmInfo.Parameters.Length = %d\n" , NewUserParmInfo.Parameters.Length ) );
|
||
KdPrint( ( "RegSAMUserConfig: SamSetInformationUser returned NTSTATUS = 0x%x\n", status ) );
|
||
LocalFree( NewUserParmInfo.Parameters.Buffer );
|
||
if ( status != STATUS_SUCCESS )
|
||
{
|
||
goto cleanupoperation;
|
||
}
|
||
}
|
||
cleanupoperation:
|
||
if ( UserParmInfo ) {
|
||
SamFreeMemory( UserParmInfo );
|
||
}
|
||
|
||
cleanupsamquery:
|
||
if ( Handle != (SAM_HANDLE) 0 ) {
|
||
SamCloseHandle( Handle );
|
||
}
|
||
|
||
cleanupsamopen:
|
||
|
||
cleanuplookup:
|
||
if ( SAMHandle != (SAM_HANDLE) 0 ) {
|
||
SamCloseHandle( SAMHandle );
|
||
}
|
||
if ( DomainHandle != (SAM_HANDLE) 0 ) {
|
||
SamCloseHandle( DomainHandle );
|
||
}
|
||
if ( DomainID != (PSID) 0 ) {
|
||
SamFreeMemory( DomainID );
|
||
}
|
||
|
||
cleanupconnect:
|
||
if ( pDomainName ) {
|
||
NetApiBufferFree( pDomainName );
|
||
}
|
||
|
||
exit:
|
||
|
||
if (hNtdsApi)
|
||
{
|
||
if (hDS)
|
||
{
|
||
if ( pfnDsUnBindW ) // it should never be otherwise.
|
||
pfnDsUnBindW( & hDS );
|
||
}
|
||
|
||
if (pDsResult)
|
||
{
|
||
if (pfnDsFreeNameResultW ) // it should never be otherwise.
|
||
pfnDsFreeNameResultW( pDsResult );
|
||
}
|
||
|
||
FreeLibrary(hNtdsApi);
|
||
}
|
||
|
||
#ifdef DEBUG
|
||
DbgPrint( "RegSAMUserConfig %s NTSTATUS = 0x%x\n", fGetConfig ? "GET" : "SET", status );
|
||
#endif // DEBUG
|
||
return( RtlNtStatusToDosError( status ) );
|
||
}
|
||
|