windows-nt/Source/XPSP1/NT/ds/netapi/rpcxlate/rxcommon/setfield.c
2020-09-26 16:20:57 +08:00

404 lines
13 KiB
C

/*++
Copyright (c) 1991-92 Microsoft Corporation
Module Name:
SetField.c
Abstract:
This module consists of the routine RxpSetField and its helpers
(RxpIsFieldSettable and RxpFieldSize).
Author:
John Rogers (JohnRo) 29-May-1991
Environment:
Portable to any flat, 32-bit environment. (Uses Win32 typedefs.)
Requires ANSI C extensions: slash-slash comments, long external names.
Revision History:
29-May-1991 JohnRo
Created.
06-Jun-1991 JohnRo
Fixed bug handling buffer size (it shouldn't be sent).
Fixed off-by-one error in string size handling in RxpFieldSize.
Added debug output.
12-Jul-1991 JohnRo
Added more parameters to RxpSetField(), to support RxPrintJobSetInfo().
Still more debug output.
17-Jul-1991 JohnRo
Extracted RxpDebug.h from Rxp.h.
01-Oct-1991 JohnRo
More work toward UNICODE.
21-Nov-1991 JohnRo
Removed NT dependencies to reduce recompiles.
31-Mar-1992 JohnRo
Prevent too large size requests.
--*/
// These must be included first:
#include <windef.h> // IN, DWORD, etc.
#include <lmcons.h> // PARMNUM_ALL, NET_API_STATUS, etc.
// These may be included in any order:
#include <lmerr.h> // NERR_Success, etc.
#include <netdebug.h> // NetpAssert().
#include <netlib.h> // NetpMemoryAllocate(), NetpMemoryFree().
#include <remtypes.h> // REM_UNSUPPORTED_FIELD.
#include <rxp.h> // My prototype, MAX_TRANSACT_ equates.
#include <rxpdebug.h> // IF_DEBUG().
#include <smbgtpt.h> // SmbGetUshort().
#include <string.h> // strcpy().
#include <tstring.h> // STRLEN(), NetpCopy string functions.
// Size (in bytes) of SMB return parameters (status & converter):
#define RETURN_AREA_SIZE (sizeof(WORD) + sizeof(WORD))
DBGSTATIC DWORD
RxpFieldSize(
IN LPBYTE Field,
IN LPDESC FieldDesc
)
{
NetpAssert(Field != NULL);
NetpAssert(FieldDesc != NULL);
if (*FieldDesc == REM_ASCIZ || *FieldDesc == REM_ASCIZ_TRUNCATABLE) {
// Compute string len (assuming conversion to correct code page).
#if defined(UNICODE) // RxpFieldSize()
return ( NetpUnicodeToDBCSLen((LPTSTR)Field) + 1 );
#else
return (STRLEN( (LPTSTR) Field ) + sizeof(char) );
#endif // defined(UNICODE)
} else {
LPDESC TempDescPtr = FieldDesc;
return ( RapGetFieldSize(
FieldDesc,
& TempDescPtr, // updated
Both ) ); // transmission mode
}
/* NOTREACHED */
} // RxpFieldSize
DBGSTATIC NET_API_STATUS
RxpIsFieldSettable(
IN LPDESC DataDesc,
IN DWORD FieldIndex
)
{
LPDESC FieldDesc;
NET_API_STATUS Status;
// Analyze descriptor to find data type for this FieldIndex.
FieldDesc = RapParmNumDescriptor(
DataDesc,
FieldIndex,
Both, // Transmission mode.
TRUE); // native mode
if (FieldDesc == NULL) {
return (ERROR_NOT_ENOUGH_MEMORY);
}
// Check for errors detected by RapParmNumDescriptor().
if (*FieldDesc == REM_UNSUPPORTED_FIELD) {
IF_DEBUG(SETFIELD) {
NetpKdPrint(( "RxpIsFieldSettable: invalid parameter "
"(ParmNumDesc).\n" ));
}
Status = ERROR_INVALID_PARAMETER;
} else {
Status = NERR_Success;
}
NetpMemoryFree(FieldDesc);
return (Status);
} // RxpIsFieldSettable
NET_API_STATUS
RxpSetField (
IN DWORD ApiNumber,
IN LPTSTR UncServerName,
IN LPDESC ObjectDesc OPTIONAL,
IN LPVOID ObjectToSet OPTIONAL,
IN LPDESC ParmDesc,
IN LPDESC DataDesc16,
IN LPDESC DataDesc32,
IN LPDESC DataDescSmb,
IN LPVOID NativeInfoBuffer,
IN DWORD ParmNumToSend,
IN DWORD FieldIndex,
IN DWORD Level
)
{
LPBYTE CurrentBufferPointer;
DWORD CurrentSize;
DWORD ExtraParmSize;
LPDESC FieldDesc;
DWORD FieldSize16;
LPBYTE SendDataBuffer;
DWORD SendDataBufferSize;
DWORD SendParmBufferSize;
NET_API_STATUS Status;
LPBYTE StringEnd;
LPBYTE TransactSmbBuffer;
DWORD TransactSmbBufferSize;
//
// MOD 06/11/91 RLF
//
DWORD ReturnedDataLength = 0;
//
// MOD 06/11/91 RLF
//
// Double-check caller.
NetpAssert(DataDesc16 != NULL);
NetpAssert(DataDesc32 != NULL);
NetpAssert(DataDescSmb != NULL);
if (RapValueWouldBeTruncated(Level)) {
// Can't use 16-bit protocol if level won't even fit in 16 bits!
return (ERROR_INVALID_LEVEL);
}
NetpAssert(ParmNumToSend != PARMNUM_ALL);
NetpAssert(FieldIndex != PARMNUM_ALL);
if (RapValueWouldBeTruncated(ParmNumToSend)) {
IF_DEBUG(SETFIELD) {
NetpKdPrint(( "RxpSetField: invalid parameter (trunc).\n" ));
}
return (ERROR_INVALID_PARAMETER);
}
//
// Analyze descriptors to make sure this parm num is settable.
//
Status = RxpIsFieldSettable( DataDesc16, FieldIndex );
if (Status != NERR_Success) {
return (Status);
}
Status = RxpIsFieldSettable( DataDesc32, FieldIndex );
if (Status != NERR_Success) {
return (Status);
}
NetpKdPrint(( "RxpSetField: ParmNumToSend=" FORMAT_DWORD ", Level="
FORMAT_DWORD ", FieldIndex=" FORMAT_DWORD ".\n",
ParmNumToSend, Level, FieldIndex ));
//
// Analyze SMB version of descriptor to find data type for this ParmNum.
// Use it to build send data buffer
//
FieldDesc = RapParmNumDescriptor(
DataDescSmb,
FieldIndex,
Both, // Transmission mode.
TRUE); // native version
if (FieldDesc == NULL) {
return (ERROR_NOT_ENOUGH_MEMORY);
}
// Check for errors detected by RapParmNumDescriptor().
if (*FieldDesc == REM_UNSUPPORTED_FIELD) {
NetpMemoryFree( FieldDesc );
IF_DEBUG(SETFIELD) {
NetpKdPrint(( "RxpSetField: invalid parameter (parmNumDesc).\n" ));
}
return (ERROR_INVALID_PARAMETER);
}
// How much memory will we need for send data buffer?
FieldSize16 = RxpFieldSize( NativeInfoBuffer, FieldDesc );
NetpAssert( FieldSize16 >= 1 );
SendDataBufferSize = FieldSize16;
if( SendDataBufferSize > MAX_TRANSACT_SEND_DATA_SIZE )
{
NetpBreakPoint();
return (ERROR_BUFFER_OVERFLOW);
}
// Allocate send data buffer.
SendDataBuffer = NetpMemoryAllocate( SendDataBufferSize );
if (SendDataBuffer == NULL) {
NetpMemoryFree( FieldDesc );
return (ERROR_NOT_ENOUGH_MEMORY);
}
NetpKdPrint(( "RxpSetField: allocated " FORMAT_DWORD " bytes at "
FORMAT_LPVOID ".\n", SendDataBufferSize, SendDataBuffer ));
// Convert this field (and copy it to the send data buffer while we're
// at it).
if ( (*FieldDesc != REM_ASCIZ) && (*FieldDesc != REM_ASCIZ_TRUNCATABLE) ) {
DWORD BytesNeeded = 0;
LPBYTE BogusStringEnd = SendDataBuffer + SendDataBufferSize;
NetpKdPrint(( "RxpSetField: converting...\n" ));
Status = RapConvertSingleEntry (
NativeInfoBuffer, // input data
FieldDesc, // input descriptor
FALSE, // no meaningless input pointers
SendDataBuffer, // output buffer start
SendDataBuffer, // output data
FieldDesc, // output descriptor
TRUE, // set offsets
& BogusStringEnd, // string area end (updated)
& BytesNeeded, // bytes required (updated)
Both, // transmission mode
NativeToRap); // conversion mode
NetpAssert( Status == NERR_Success );
NetpAssert( BytesNeeded == FieldSize16 );
} else {
// Can't use RapConvertSingleEntry for setinfo strings, because
// they're not sent with a pointer (or offset). So, we just copy data.
#if defined(UNICODE) // RxpSetField()
NetpAssert(
SendDataBufferSize >= NetpUnicodeToDBCSLen((LPTSTR)NativeInfoBuffer)+1);
#else
NetpAssert(
SendDataBufferSize >= (STRLEN(NativeInfoBuffer)+sizeof(char)) );
#endif // defined(UNICODE)
NetpKdPrint(( "RxpSetField: copying string...\n" ));
#if defined(UNICODE) // RxpSetField()
NetpCopyWStrToStrDBCS(
(LPSTR) SendDataBuffer, // dest
(LPTSTR)NativeInfoBuffer ); // src
#else
NetpCopyTStrToStr(
(LPSTR) SendDataBuffer, // dest
NativeInfoBuffer); // src
#endif // defined(UNICODE)
}
NetpMemoryFree( FieldDesc );
//
// OK, now let's work on the transact SMB buffer, which we'll use as the
// send parm buffer and return parm buffer.
//
// Figure-out how many bytes of parameters we'll need.
ExtraParmSize =
sizeof(WORD) // level,
+ sizeof(WORD); // parmnum.
if (ObjectDesc != NULL) {
NetpAssert( ObjectToSet != NULL );
NetpAssert( DESCLEN(ObjectDesc) == 1 );
if (*ObjectDesc == REM_ASCIZ) {
// Add size of ASCII version of object to set.
ExtraParmSize += STRLEN(ObjectToSet) + sizeof(char);
} else if (*ObjectDesc == REM_WORD_PTR) {
ExtraParmSize += sizeof(WORD);
} else {
NetpAssert(FALSE);
}
} else {
NetpAssert(ObjectToSet == NULL);
}
// Allocate SMB transaction request buffer.
NetpAssert(ExtraParmSize >= 1);
SendParmBufferSize = RxpComputeRequestBufferSize(
ParmDesc,
DataDescSmb,
ExtraParmSize);
NetpAssert( SendParmBufferSize <= MAX_TRANSACT_SEND_PARM_SIZE );
if (SendParmBufferSize > RETURN_AREA_SIZE) {
TransactSmbBufferSize = SendParmBufferSize;
} else {
TransactSmbBufferSize = RETURN_AREA_SIZE;
}
NetpAssert( TransactSmbBufferSize <= MAX_TRANSACT_SEND_PARM_SIZE );
TransactSmbBuffer = NetpMemoryAllocate( TransactSmbBufferSize );
if (TransactSmbBuffer == NULL) {
return (ERROR_NOT_ENOUGH_MEMORY);
}
// Start filling-in parm buffer and set pointers and counters.
Status = RxpStartBuildingTransaction(
TransactSmbBuffer, // SMB buffer (will be built)
SendParmBufferSize,
ApiNumber,
ParmDesc,
DataDescSmb,
(LPVOID *) & CurrentBufferPointer, // first avail byte to use (set)
& CurrentSize, // bytes used so far (set)
(LPVOID *) & StringEnd, // ptr to string area end (set)
NULL); // don't need ptr to parm desc copy
NetpAssert(Status == NERR_Success);
// Fill in parameters.
if (ObjectToSet != NULL) {
if (*ObjectDesc == REM_ASCIZ) {
// Copy string to output area, converting as necessary.
RxpAddTStr(
(LPTSTR) ObjectToSet, // input
& CurrentBufferPointer, // updated
& StringEnd, // updated
& CurrentSize); // updated
} else if (*ObjectDesc == REM_WORD_PTR) {
RxpAddWord(
* (LPWORD) ObjectToSet,
& CurrentBufferPointer, // updated
& CurrentSize); // updated
} else {
NetpAssert(FALSE);
}
}
RxpAddWord(
(WORD) Level,
& CurrentBufferPointer, // updated
& CurrentSize); // updated
RxpAddWord(
(WORD) ParmNumToSend,
& CurrentBufferPointer, // updated
& CurrentSize); // updated
Status = RxpTransactSmb(
UncServerName,
NULL, // Transport name
TransactSmbBuffer,
SendParmBufferSize,
SendDataBuffer,
SendDataBufferSize,
TransactSmbBuffer, // will be set with status and converter word.
RETURN_AREA_SIZE,
NULL, // no return data
//
// MOD 06/11/91 RLF
//
// 0, // 0 bytes of return data
&ReturnedDataLength,
//
// MOD 06/11/91 RLF
//
FALSE); // not a null session API.
// Don't process RxpTransactSmb status just yet...
NetpMemoryFree(SendDataBuffer);
if (Status != NERR_Success) {
NetpMemoryFree(TransactSmbBuffer);
return (Status); // status of transact, e.g. net not started.
}
Status = SmbGetUshort( (LPWORD) TransactSmbBuffer );
NetpMemoryFree(TransactSmbBuffer);
return (Status); // status of actual remote API.
} // RxpSetField