1024 lines
31 KiB
C
1024 lines
31 KiB
C
/*++
|
||
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ApiWksta.c
|
||
|
||
Abstract:
|
||
|
||
This module contains individual API handlers for the NetWksta
|
||
APIs.
|
||
|
||
SUPPORTED : NetWkstaGetInfo, NetWkstaSetInfo.
|
||
|
||
UNSUPPORTED : NetWkstaSetUid.
|
||
|
||
SEE ALSO : NetWkstaUserLogon, NetWkstaUserLogoff - in ApiLogon.c.
|
||
|
||
Author:
|
||
|
||
Shanku Niyogi (w-shanku) 25-Feb-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "XactSrvP.h"
|
||
|
||
//
|
||
// Declaration of descriptor strings.
|
||
//
|
||
|
||
STATIC const LPDESC Desc16_wksta_info_0 = REM16_wksta_info_0;
|
||
STATIC const LPDESC Desc16_wksta_info_1 = REM16_wksta_info_1;
|
||
STATIC const LPDESC Desc16_wksta_info_10 = REM16_wksta_info_10;
|
||
|
||
//
|
||
// The size of the heuristics is actually 55 chars but we add one
|
||
// for padding.
|
||
//
|
||
|
||
#define SIZE_HEURISTICS 56
|
||
|
||
NTSTATUS
|
||
XsNetWkstaGetInfo (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sets up a call to NetWkstaGetInfo. Because of the differences
|
||
between 16- and 32-bit structures, this routine does not use the normal
|
||
conversion process.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
NET_API_STATUS status;
|
||
|
||
PXS_NET_WKSTA_GET_INFO parameters = Parameters;
|
||
LPWKSTA_INFO_100 wksta_100 = NULL; // Native parameters
|
||
LPWKSTA_INFO_101 wksta_101 = NULL;
|
||
LPWKSTA_INFO_502 wksta_502 = NULL;
|
||
|
||
LPBYTE stringLocation = NULL; // Conversion variables
|
||
DWORD bytesRequired = 0;
|
||
BOOL varWrite;
|
||
LPWKSTA_16_INFO_1 entry1;
|
||
LPWKSTA_16_INFO_10 entry10;
|
||
TCHAR heuristics[SIZE_HEURISTICS];
|
||
DWORD i;
|
||
USHORT level;
|
||
|
||
WCHAR lanroot[PATHLEN+1];
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
IF_DEBUG(WKSTA) {
|
||
NetpKdPrint(( "XsNetWkstaGetInfo: header at %lx, "
|
||
"params at %lx, level %ld\n",
|
||
Header, parameters, SmbGetUshort( ¶meters->Level ) ));
|
||
}
|
||
|
||
try {
|
||
//
|
||
// Check for errors.
|
||
//
|
||
|
||
level = SmbGetUshort( ¶meters->Level );
|
||
if ( (level != 0) && (level != 1) && (level != 10) ) {
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// we return the system directory as the lanroot
|
||
//
|
||
|
||
*lanroot = 0;
|
||
GetSystemDirectory(lanroot, sizeof(lanroot)/sizeof(*lanroot));
|
||
|
||
//
|
||
// Gather the requested data by making local GetInfo calls.
|
||
//
|
||
|
||
switch ( level ) {
|
||
|
||
case 10:
|
||
status = NetWkstaGetInfo(
|
||
NULL,
|
||
(DWORD)100,
|
||
(LPBYTE *)&wksta_100
|
||
);
|
||
|
||
if ( !XsApiSuccess ( status )) {
|
||
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 100) "
|
||
"failed: %X\n", status));
|
||
}
|
||
|
||
Header->Status = (WORD) status;
|
||
goto cleanup;
|
||
}
|
||
|
||
break;
|
||
|
||
case 0:
|
||
case 1:
|
||
status = NetWkstaGetInfo(
|
||
NULL,
|
||
(DWORD)101,
|
||
(LPBYTE *)&wksta_101
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 101) "
|
||
"failed: %X\n", status));
|
||
}
|
||
|
||
Header->Status = (WORD) status;
|
||
goto cleanup;
|
||
}
|
||
|
||
status = NetWkstaGetInfo(
|
||
NULL,
|
||
(DWORD)502,
|
||
(LPBYTE *)&wksta_502
|
||
);
|
||
|
||
if ( !XsApiSuccess( status )) {
|
||
|
||
IF_DEBUG(API_ERRORS) {
|
||
NetpKdPrint(( "XsWkstaGetInfo: WkstaGetInfo (level 502) "
|
||
"failed: %X\n", status));
|
||
}
|
||
|
||
Header->Status = (WORD) status;
|
||
goto cleanup;
|
||
}
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// Calculate the amount of space required to hold the fixed and
|
||
// variable data. Since this is the only place where we get one
|
||
// case for each valid level, we will also get the source structure
|
||
// descriptor here.
|
||
//
|
||
|
||
switch ( level ) {
|
||
|
||
case 0:
|
||
|
||
StructureDesc = Desc16_wksta_info_0;
|
||
bytesRequired = sizeof( WKSTA_16_INFO_0 )
|
||
+ NetpUnicodeToDBCSLen( lanroot )
|
||
+ NetpUnicodeToDBCSLen( wksta_101->wki101_computername )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_username )
|
||
+ NetpUnicodeToDBCSLen( wksta_101->wki101_langroup )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_logon_server )
|
||
+ SIZE_HEURISTICS
|
||
+ 6; // for terminating nulls
|
||
break;
|
||
|
||
case 1:
|
||
|
||
StructureDesc = Desc16_wksta_info_1;
|
||
bytesRequired = sizeof( WKSTA_16_INFO_1 )
|
||
+ NetpUnicodeToDBCSLen( lanroot )
|
||
+ NetpUnicodeToDBCSLen( wksta_101->wki101_computername )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_username )
|
||
+ NetpUnicodeToDBCSLen( wksta_101->wki101_langroup )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_logon_server )
|
||
+ SIZE_HEURISTICS
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_logon_domain )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_oth_domains )
|
||
+ 8; // for terminating nulls
|
||
|
||
break;
|
||
|
||
case 10:
|
||
|
||
StructureDesc = Desc16_wksta_info_10;
|
||
bytesRequired = sizeof( WKSTA_16_INFO_10 )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_username )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_logon_domain )
|
||
+ NetpUnicodeToDBCSLen( wksta_100->wki100_computername )
|
||
+ NetpUnicodeToDBCSLen( wksta_100->wki100_langroup )
|
||
+ NetpUnicodeToDBCSLen( DEF16_wk_oth_domains )
|
||
+ 5; // for terminating nulls
|
||
break;
|
||
}
|
||
|
||
//
|
||
// If there isn't enough room in the buffer for this, don't write any
|
||
// variable data.
|
||
//
|
||
|
||
varWrite = ( (DWORD)SmbGetUshort( ¶meters->BufLen )
|
||
>= bytesRequired ) ? TRUE : FALSE;
|
||
|
||
stringLocation = (LPBYTE)( XsSmbGetPointer( ¶meters->Buffer )
|
||
+ RapStructureSize( StructureDesc, Response, FALSE ));
|
||
|
||
//
|
||
// Return NERR_BufTooSmall if fixed structure will not fit.
|
||
//
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
FALSE // not in native format
|
||
)) {
|
||
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaGetInfo: Buffer too small.\n" ));
|
||
}
|
||
Header->Status = NERR_BufTooSmall;
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
||
goto cleanup;
|
||
|
||
}
|
||
|
||
//
|
||
// Based on the level, fill the appropriate information directly into
|
||
// 16-bit buffer.
|
||
//
|
||
|
||
entry1 = (LPWKSTA_16_INFO_1) XsSmbGetPointer( ¶meters->Buffer );
|
||
entry10 = (LPWKSTA_16_INFO_10) entry1;
|
||
|
||
switch ( level ) {
|
||
|
||
case 1:
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_logon_domain,
|
||
&entry1->wki1_logon_domain,
|
||
entry1
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_oth_domains,
|
||
&entry1->wki1_oth_domains,
|
||
entry1
|
||
);
|
||
}
|
||
SmbPutUshort( &entry1->wki1_numdgrambuf,
|
||
DEF16_wk_numdgrambuf );
|
||
|
||
//
|
||
// Fill the rest of the level 1 structure just like a
|
||
// level 0 structure.
|
||
//
|
||
|
||
case 0:
|
||
|
||
//
|
||
// Zero the reserved words.
|
||
//
|
||
|
||
SmbPutUshort( &entry1->wki1_reserved_1, (WORD) 0 );
|
||
SmbPutUlong( &entry1->wki1_reserved_2, (DWORD) 0 );
|
||
SmbPutUlong( &entry1->wki1_reserved_3, (DWORD) 0 );
|
||
SmbPutUshort( &entry1->wki1_reserved_4, (WORD) 0 );
|
||
SmbPutUshort( &entry1->wki1_reserved_5, (WORD) 0 );
|
||
SmbPutUshort( &entry1->wki1_reserved_6, (WORD) 0 );
|
||
|
||
//
|
||
// Fill in the fields which have analogues in NT.
|
||
//
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
lanroot,
|
||
&entry1->wki1_root,
|
||
entry1
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
wksta_101->wki101_computername,
|
||
&entry1->wki1_computername,
|
||
entry1
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
wksta_101->wki101_langroup,
|
||
&entry1->wki1_langroup,
|
||
entry1
|
||
);
|
||
}
|
||
|
||
entry1->wki1_ver_major = (BYTE) wksta_101->wki101_ver_major;
|
||
entry1->wki1_ver_minor = (BYTE) wksta_101->wki101_ver_minor;
|
||
|
||
SmbPutUshort( &entry1->wki1_charwait,
|
||
XsDwordToWord( wksta_502->wki502_char_wait ) );
|
||
SmbPutUlong( &entry1->wki1_chartime,
|
||
(DWORD) wksta_502->wki502_collection_time );
|
||
SmbPutUshort( &entry1->wki1_charcount,
|
||
XsDwordToWord( wksta_502->
|
||
wki502_maximum_collection_count ) );
|
||
SmbPutUshort( &entry1->wki1_keepconn,
|
||
XsDwordToWord( wksta_502->wki502_keep_conn ) );
|
||
SmbPutUshort( &entry1->wki1_maxthreads,
|
||
XsDwordToWord( wksta_502->wki502_max_threads ) );
|
||
SmbPutUshort( &entry1->wki1_maxcmds,
|
||
XsDwordToWord( wksta_502->wki502_max_cmds ) );
|
||
SmbPutUshort( &entry1->wki1_sesstimeout,
|
||
XsDwordToWord( wksta_502->wki502_sess_timeout ) );
|
||
|
||
//
|
||
// Construct the heuristics string.
|
||
//
|
||
|
||
// Request opportunistic locking of files.
|
||
heuristics[0] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_use_opportunistic_locking ));
|
||
// Optimize performance for command files.
|
||
heuristics[1] = MAKE_TCHAR('1');
|
||
// Unlock and WriteUnlock asynchronously.
|
||
heuristics[2] = MAKE_TCHAR('1'); // default
|
||
// Close and WriteClose asynchronously.
|
||
heuristics[3] = MAKE_TCHAR('1'); // default
|
||
// Buffer named pipes and communication devices.
|
||
heuristics[4] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_buf_named_pipes ));
|
||
// LockRead and WriteUnlock.
|
||
heuristics[5] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_use_lock_read_unlock ));
|
||
// Use Open and Read.
|
||
heuristics[6] = MAKE_TCHAR('0');
|
||
// Read-ahead to sector boundary.
|
||
heuristics[7] = MAKE_TCHAR('1');
|
||
// Use the "chain send" NetBIOS NCB.
|
||
heuristics[8] = MAKE_TCHAR('2');
|
||
// Buffer small read/write requests.
|
||
heuristics[9] = MAKE_TCHAR('1');
|
||
// Use buffer mode.
|
||
heuristics[10] = MAKE_TCHAR('3');
|
||
// Use raw data transfer read/write server message block protocols.
|
||
heuristics[11] = MAKE_TCHAR('1');
|
||
// Use large RAW read-ahead buffer.
|
||
heuristics[12] = MAKE_TCHAR('1');
|
||
// Use large RAW write-behind buffer.
|
||
heuristics[13] = MAKE_TCHAR('1');
|
||
// Use read multiplex SMB protocols.
|
||
heuristics[14] = MAKE_TCHAR('0');
|
||
// Use write multiplex SMB protocols.
|
||
heuristics[15] = MAKE_TCHAR('0');
|
||
// Use big buffer for large core reads.
|
||
heuristics[16] = MAKE_TCHAR('1');
|
||
// Set the read-ahead size.
|
||
heuristics[17] = MAKE_TCHAR('0');
|
||
// Set the write-behind size.
|
||
heuristics[18] = MAKE_TCHAR('0');
|
||
// Force 512-byte maximum transfers to and from core servers.
|
||
heuristics[19] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_use_512_byte_max_transfer ));
|
||
// Flush pipes and devices on DosBufReset or DosClose.
|
||
heuristics[20] = MAKE_TCHAR('0');
|
||
// Use encryption if the server supports it.
|
||
heuristics[21] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_use_encryption ));
|
||
// Control log entries for multiple occurences of an error.
|
||
heuristics[22] = MAKE_TCHAR('1');
|
||
// Buffer all files opened with "deny write" rights.
|
||
heuristics[23] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_buf_files_deny_write ));
|
||
// Buffer all files opened with R attribute.
|
||
heuristics[24] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_buf_read_only_files ));
|
||
// Read ahead when opening a file for execution.
|
||
heuristics[25] = MAKE_TCHAR('0');
|
||
// Handle Ctrl-C.
|
||
heuristics[26] = MAKE_TCHAR('2');
|
||
// Force correct open mode when creating files on a core server.
|
||
heuristics[27] = MAKE_TCHAR(XsBoolToDigit(
|
||
wksta_502->wki502_force_core_create_mode ));
|
||
// Use NetBIOS NoAck mode.
|
||
heuristics[28] = MAKE_TCHAR('0');
|
||
// Send data along with SMB write-block-RAW requests.
|
||
heuristics[29] = MAKE_TCHAR('1');
|
||
// Send a popup when the workstation logs an error.
|
||
heuristics[30] = MAKE_TCHAR('1');
|
||
// Close the print job, causing the remote spooler to print if no
|
||
// activity occurs on the printer for the time specified.
|
||
heuristics[31] = MAKE_TCHAR('0');
|
||
// Controls BufReset and SMBFlush behavior for the MS-DOS
|
||
// compatibility box.
|
||
heuristics[32] = MAKE_TCHAR('2');
|
||
// Controls the time-out value for performing logon validation from a
|
||
// domain controller.
|
||
heuristics[33] = MAKE_TCHAR('0');
|
||
|
||
for ( i = 34; i <= 54; i++ ) {
|
||
heuristics[i] = MAKE_TCHAR('0');
|
||
}
|
||
|
||
heuristics[SIZE_HEURISTICS-1] = MAKE_TCHAR('\0');
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
heuristics,
|
||
&entry1->wki1_wrkheuristics,
|
||
entry1
|
||
);
|
||
}
|
||
|
||
//
|
||
// Put default values in the fields that are meaningless in NT.
|
||
//
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_logon_server,
|
||
&entry1->wki1_logon_server,
|
||
entry1
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_username,
|
||
&entry1->wki1_username,
|
||
entry1
|
||
);
|
||
}
|
||
|
||
SmbPutUshort( &entry1->wki1_keepsearch,
|
||
(WORD) DEF16_wk_keepsearch );
|
||
SmbPutUshort( &entry1->wki1_numworkbuf,
|
||
(WORD) DEF16_wk_numworkbuf );
|
||
SmbPutUshort( &entry1->wki1_sizworkbuf,
|
||
(WORD) DEF16_wk_sizeworkbuf );
|
||
SmbPutUshort( &entry1->wki1_maxwrkcache,
|
||
(WORD) DEF16_wk_maxwrkcache );
|
||
SmbPutUshort( &entry1->wki1_sizerror,
|
||
(WORD) DEF16_wk_sizerror );
|
||
SmbPutUshort( &entry1->wki1_numalerts,
|
||
(WORD) DEF16_wk_numalerts );
|
||
SmbPutUshort( &entry1->wki1_numservices,
|
||
(WORD) DEF16_wk_numservices );
|
||
SmbPutUshort( &entry1->wki1_errlogsz,
|
||
(WORD) DEF16_wk_errlogsz );
|
||
SmbPutUshort( &entry1->wki1_printbuftime,
|
||
(WORD) DEF16_wk_printbuftime );
|
||
SmbPutUshort( &entry1->wki1_numcharbuf,
|
||
(WORD) DEF16_wk_numcharbuf );
|
||
SmbPutUshort( &entry1->wki1_sizcharbuf,
|
||
(WORD) DEF16_wk_sizcharbuf );
|
||
SmbPutUshort( &entry1->wki1_mailslots,
|
||
(WORD) DEF16_wk_mailslots );
|
||
|
||
break;
|
||
|
||
case 10:
|
||
|
||
//
|
||
// Fill in the fields which have analogues in NT.
|
||
//
|
||
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
wksta_100->wki100_computername,
|
||
&entry10->wki10_computername,
|
||
entry10
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
wksta_100->wki100_langroup,
|
||
&entry10->wki10_langroup,
|
||
entry10
|
||
);
|
||
}
|
||
|
||
entry10->wki10_ver_major = XsDwordToByte( wksta_100->wki100_ver_major );
|
||
entry10->wki10_ver_minor = XsDwordToByte( wksta_100->wki100_ver_minor );
|
||
|
||
//
|
||
// Put default values in the fields that are meaningless in NT.
|
||
//
|
||
|
||
|
||
if ( varWrite ) {
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_username,
|
||
&entry10->wki10_username,
|
||
entry10
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_logon_domain,
|
||
&entry10->wki10_logon_domain,
|
||
entry10
|
||
);
|
||
XsAddVarString(
|
||
stringLocation,
|
||
DEF16_wk_oth_domains,
|
||
&entry10->wki10_oth_domains,
|
||
entry10
|
||
);
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
SmbPutUshort( ¶meters->TotalAvail, (WORD)bytesRequired );
|
||
|
||
if ( varWrite == 0 ) {
|
||
Header->Status = ERROR_MORE_DATA;
|
||
} else {
|
||
Header->Status = NERR_Success;
|
||
Header->Converter = 0;
|
||
}
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
if ( wksta_100 != NULL ) {
|
||
NetApiBufferFree( wksta_100 );
|
||
}
|
||
|
||
if ( wksta_101 != NULL ) {
|
||
NetApiBufferFree( wksta_101 );
|
||
}
|
||
|
||
if ( wksta_502 != NULL ) {
|
||
NetApiBufferFree( wksta_502 );
|
||
}
|
||
|
||
//
|
||
// Determine return buffer size.
|
||
//
|
||
|
||
XsSetDataCount(
|
||
¶meters->BufLen,
|
||
StructureDesc,
|
||
Header->Converter,
|
||
1,
|
||
Header->Status
|
||
);
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetWkstaGetInfo
|
||
|
||
|
||
|
||
NTSTATUS
|
||
XsNetWkstaSetInfo (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles a call to NetWkstaSetInfo.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NET_API_STATUS status;
|
||
|
||
PXS_NET_WKSTA_SET_INFO parameters = Parameters;
|
||
DWORD data;
|
||
BOOL flag;
|
||
DWORD nativeParmNum;
|
||
|
||
LPVOID buffer = NULL; // Conversion variables
|
||
DWORD bufferSize;
|
||
LPWKSTA_16_INFO_1 entry1;
|
||
LPWKSTA_16_INFO_10 entry10;
|
||
BOOL error;
|
||
DWORD parmNum;
|
||
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
try {
|
||
//
|
||
// Check for errors. We will filter out wrong levels now.
|
||
//
|
||
|
||
parmNum = SmbGetUshort( ¶meters->ParmNum );
|
||
|
||
switch ( SmbGetUshort( ¶meters->Level )) {
|
||
|
||
case 0:
|
||
StructureDesc = Desc16_wksta_info_0;
|
||
if ( parmNum == WKSTA_OTH_DOMAINS_PARMNUM ) {
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
break;
|
||
|
||
case 1:
|
||
StructureDesc = Desc16_wksta_info_1;
|
||
break;
|
||
|
||
case 10:
|
||
StructureDesc = Desc16_wksta_info_10;
|
||
if ( parmNum == WKSTA_CHARWAIT_PARMNUM
|
||
|| parmNum == WKSTA_CHARTIME_PARMNUM
|
||
|| parmNum == WKSTA_CHARCOUNT_PARMNUM
|
||
|| parmNum == WKSTA_ERRLOGSZ_PARMNUM
|
||
|| parmNum == WKSTA_PRINTBUFTIME_PARMNUM
|
||
|| parmNum == WKSTA_WRKHEURISTICS_PARMNUM ) {
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
Header->Status = ERROR_INVALID_LEVEL;
|
||
goto cleanup;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Check input buffer size if parmnum is PARMNUM_ALL.
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL ) {
|
||
|
||
if ( !XsCheckBufferSize(
|
||
SmbGetUshort( ¶meters->BufLen ),
|
||
StructureDesc,
|
||
FALSE // not in native format
|
||
)) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
}
|
||
|
||
buffer = (LPVOID)XsSmbGetPointer( ¶meters->Buffer );
|
||
bufferSize = (DWORD)SmbGetUshort( ¶meters->BufLen );
|
||
entry1 = (LPWKSTA_16_INFO_1)buffer;
|
||
entry10 = (LPWKSTA_16_INFO_10)buffer;
|
||
|
||
//
|
||
// Processing of this API depends on the value of the ParmNum
|
||
// parameter. Because of all the discrepancies between NT and downlevel
|
||
// info structures, we will handle each instance by hand.
|
||
//
|
||
|
||
error = TRUE;
|
||
|
||
//
|
||
// charwait - source data is in a WORD - convert to DWORD
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARWAIT_PARMNUM ) {
|
||
|
||
if ( bufferSize < sizeof(WORD) ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
data = ( parmNum == PARMNUM_ALL )
|
||
? (DWORD)SmbGetUshort( &entry1->wki1_charwait )
|
||
: (DWORD)SmbGetUshort( (LPWORD)buffer );
|
||
|
||
status = NetWkstaSetInfo(
|
||
NULL,
|
||
PARMNUM_BASE_INFOLEVEL + WKSTA_CHARWAIT_PARMNUM,
|
||
(LPBYTE)&data,
|
||
NULL
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of charwait failed"
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// chartime - source data is in a DWORD - convert to DWORD
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARTIME_PARMNUM ) {
|
||
|
||
if ( bufferSize < sizeof(DWORD) ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
data = ( parmNum == PARMNUM_ALL )
|
||
? SmbGetUlong( &entry1->wki1_chartime )
|
||
: SmbGetUlong( (LPDWORD)buffer );
|
||
|
||
status = NetWkstaSetInfo(
|
||
NULL,
|
||
PARMNUM_BASE_INFOLEVEL + WKSTA_CHARTIME_PARMNUM,
|
||
(LPBYTE)&data,
|
||
NULL
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of chartime failed"
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// charcount - source data is in a WORD - convert to DWORD
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_CHARCOUNT_PARMNUM ) {
|
||
|
||
if ( bufferSize < sizeof(WORD) ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
data = ( parmNum == PARMNUM_ALL )
|
||
? (DWORD)SmbGetUshort( &entry1->wki1_charcount )
|
||
: (DWORD)SmbGetUshort( (LPWORD)buffer );
|
||
|
||
status = NetWkstaSetInfo(
|
||
NULL,
|
||
PARMNUM_BASE_INFOLEVEL + WKSTA_CHARCOUNT_PARMNUM,
|
||
(LPBYTE)&data,
|
||
NULL
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of charcount failed"
|
||
"%X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// errlogsz, printbuftime - source data is in a WORD.
|
||
//
|
||
// We can't set this, but downlevel can, so indicate success,
|
||
// as long as something was sent.
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_ERRLOGSZ_PARMNUM
|
||
|| parmNum == WKSTA_PRINTBUFTIME_PARMNUM ) {
|
||
|
||
if ( bufferSize < sizeof(WORD) ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// othdomains - source data is a string.
|
||
//
|
||
// We can't set this, but downlevel can, so indicate success,
|
||
// as long as something was sent.
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_OTH_DOMAINS_PARMNUM ) {
|
||
|
||
if ( bufferSize == 0 ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// wrkheuristics - source data is in a string.
|
||
//
|
||
// There are some elements of this that we can set. We go through a loop,
|
||
// setting these.
|
||
//
|
||
|
||
if ( parmNum == PARMNUM_ALL || parmNum == WKSTA_WRKHEURISTICS_PARMNUM ) {
|
||
|
||
LPBYTE heuristics;
|
||
DWORD i;
|
||
|
||
if ( bufferSize < 54 ) {
|
||
Header->Status = NERR_BufTooSmall;
|
||
goto cleanup;
|
||
}
|
||
|
||
heuristics = ( parmNum == PARMNUM_ALL )
|
||
? (LPBYTE)XsSmbGetPointer( &entry1->wki1_wrkheuristics )
|
||
: (LPBYTE)buffer;
|
||
|
||
//
|
||
// Nothing to be changed
|
||
//
|
||
|
||
if ( heuristics == NULL ) {
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Make sure we have the right size of string.
|
||
//
|
||
|
||
if ( strlen( heuristics ) != 54 ) {
|
||
|
||
Header->Status = ERROR_INVALID_PARAMETER;
|
||
goto cleanup;
|
||
}
|
||
|
||
for ( i = 0; i < 54; i++ ) {
|
||
|
||
//
|
||
// Make sure heuristics string is valid.
|
||
//
|
||
|
||
if ( !isdigit( heuristics[i] )) {
|
||
|
||
Header->Status = ERROR_INVALID_PARAMETER;
|
||
goto cleanup;
|
||
}
|
||
|
||
//
|
||
// Check if we can set this field.
|
||
//
|
||
|
||
switch ( i ) {
|
||
|
||
case 0:
|
||
nativeParmNum = WKSTA_USEOPPORTUNISTICLOCKING_PARMNUM;
|
||
break;
|
||
case 4:
|
||
nativeParmNum = WKSTA_BUFFERNAMEDPIPES_PARMNUM;
|
||
break;
|
||
case 5:
|
||
nativeParmNum = WKSTA_USELOCKANDREADANDUNLOCK_PARMNUM;
|
||
break;
|
||
case 19:
|
||
nativeParmNum = WKSTA_USE512BYTESMAXTRANSFER_PARMNUM;
|
||
break;
|
||
case 21:
|
||
nativeParmNum = WKSTA_USEENCRYPTION_PARMNUM;
|
||
break;
|
||
case 23:
|
||
nativeParmNum = WKSTA_BUFFILESWITHDENYWRITE_PARMNUM;
|
||
break;
|
||
case 24:
|
||
nativeParmNum = WKSTA_BUFFERREADONLYFILES_PARMNUM;
|
||
break;
|
||
case 27:
|
||
nativeParmNum = WKSTA_FORCECORECREATEMODE_PARMNUM;
|
||
break;
|
||
default:
|
||
nativeParmNum = 0;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// If we can set the field, set it.
|
||
//
|
||
|
||
if ( nativeParmNum != 0 ) {
|
||
|
||
if ( heuristics[i] != '0' && heuristics[i] != '1' ) {
|
||
|
||
Header->Status = ERROR_INVALID_PARAMETER;
|
||
goto cleanup;
|
||
}
|
||
|
||
flag = XsDigitToBool( heuristics[i] );
|
||
|
||
status = NetWkstaSetInfo(
|
||
NULL,
|
||
PARMNUM_BASE_INFOLEVEL + nativeParmNum,
|
||
(LPBYTE)&flag,
|
||
NULL
|
||
);
|
||
|
||
if ( status != NERR_Success ) {
|
||
IF_DEBUG(ERRORS) {
|
||
NetpKdPrint(( "XsNetWkstaSetInfo : SetInfo of a "
|
||
"heuristic failed: %X\n", status ));
|
||
}
|
||
Header->Status = (WORD)status;
|
||
goto cleanup;
|
||
}
|
||
}
|
||
}
|
||
|
||
error = FALSE;
|
||
}
|
||
|
||
//
|
||
// Tried all possible parmnums. If error is still set, we have an
|
||
// invalid parmnum on our hands.
|
||
//
|
||
|
||
if ( error ) {
|
||
|
||
Header->Status = ERROR_INVALID_PARAMETER;
|
||
|
||
}
|
||
|
||
//
|
||
// No return information for this API.
|
||
//
|
||
|
||
cleanup:
|
||
;
|
||
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
Header->Status = (WORD)RtlNtStatusToDosError( GetExceptionCode() );
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetWkstaSetInfo
|
||
|
||
|
||
NTSTATUS
|
||
XsNetWkstaSetUID (
|
||
API_HANDLER_PARAMETERS
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This temporary routine just returns STATUS_NOT_IMPLEMENTED.
|
||
|
||
Arguments:
|
||
|
||
API_HANDLER_PARAMETERS - information about the API call. See
|
||
XsTypes.h for details.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - STATUS_SUCCESS or reason for failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
API_HANDLER_PARAMETERS_REFERENCE; // Avoid warnings
|
||
|
||
Header->Status = (WORD)NERR_InvalidAPI;
|
||
|
||
return STATUS_SUCCESS;
|
||
|
||
} // XsNetWkstaSetUID
|