419 lines
14 KiB
C
419 lines
14 KiB
C
/*++
|
|
|
|
Copyright (c) 1991-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
convdata.c
|
|
|
|
Abstract:
|
|
|
|
RxpConvertDataStructures routine which converts 16- to 32-bit arrays of
|
|
structures and vice versa.
|
|
|
|
Author:
|
|
|
|
Richard Firth (rfirth) 03-Jul-1991
|
|
|
|
Revision History:
|
|
|
|
03-Jul-1991 rfirth
|
|
created
|
|
15-Jul-1991 JohnRo
|
|
Align each structure (e.g. in an array) if necessary. This will,
|
|
for instance, help print dest info level 1 handling. Changed
|
|
RxpConvertDataStructures to allow ERROR_MORE_DATA, e.g. for print APIs.
|
|
Also, use DBG instead of DEBUG equate.
|
|
17-Jul-1991 JohnRo
|
|
Extracted RxpDebug.h from Rxp.h.
|
|
07-Sep-1991 JohnRo
|
|
Made changes suggested by PC-LINT.
|
|
20-Nov-1991 JohnRo
|
|
Clarify which routine an error message is from.
|
|
21-Nov-1991 JohnRo
|
|
Removed NT dependencies to reduce recompiles.
|
|
18-May-1993 JohnRo
|
|
DosPrintQGetInfoW underestimates number of bytes needed.
|
|
Made changes suggested by PC-LINT 5.0
|
|
21-Jun-1993 JohnRo
|
|
RAID 14180: NetServerEnum never returns (alignment bug in
|
|
RxpConvertDataStructures).
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include <windef.h>
|
|
#include <align.h>
|
|
#include <lmerr.h>
|
|
#include <rxp.h> // My prototype.
|
|
#include <rxpdebug.h> // IF_DEBUG().
|
|
#include <rap.h>
|
|
#include <netdebug.h>
|
|
|
|
|
|
|
|
NET_API_STATUS
|
|
RxpConvertDataStructures(
|
|
IN LPDESC InputDescriptor,
|
|
IN LPDESC OutputDescriptor,
|
|
IN LPDESC InputAuxDescriptor OPTIONAL,
|
|
IN LPDESC OutputAuxDescriptor OPTIONAL,
|
|
IN LPBYTE InputBuffer,
|
|
OUT LPBYTE OutputBuffer,
|
|
IN DWORD OutputBufferSize,
|
|
IN DWORD PrimaryCount,
|
|
OUT LPDWORD EntriesConverted OPTIONAL,
|
|
IN RAP_TRANSMISSION_MODE TransmissionMode,
|
|
IN RAP_CONVERSION_MODE ConversionMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
A buffer containing 16- or 32-bit structures is converted to 32- or 16-bit
|
|
structures resp. in a separate buffer. The structures may or may not have
|
|
associated auxiliary structures. The output buffer is expected to be large
|
|
enough to contain all the input data structures plus any variable length
|
|
data items. Therefore, in the worst case, there must be enough space to
|
|
convert all 16-bit items to 32-bits and convert ASCII strings to UNICODE.
|
|
|
|
There may not be any auxiliary structures associated with the primaries,
|
|
in which case the auxiliary descriptor pointers should BOTH BE NULL.
|
|
|
|
Assumptions:
|
|
|
|
IMPORTANT: The input buffer is assumed to have MEANINGFUL pointers.
|
|
|
|
|
|
Arguments:
|
|
|
|
InputDescriptor - Pointer to string describing input primary data structure.
|
|
|
|
OutputDescriptor - Pointer to string describing output primary data
|
|
structure.
|
|
|
|
InputAuxDescriptor - Pointer to string describing input auxiliary data
|
|
structure. May be NULL.
|
|
|
|
OutputAuxDescriptor - Pointer to string describing output auxiliary data
|
|
structure. May be NULL.
|
|
|
|
InputBuffer - Pointer to data area containing input structures.
|
|
|
|
OutputBuffer - Pointer to data area where output structures will be placed.
|
|
If the OutputBufferSize is too small, the contents of the output area
|
|
is undefined.
|
|
|
|
OutputBufferSize - Size of output buffer.
|
|
|
|
PrimaryCount - Number of primary structures in InputBuffer.
|
|
|
|
EntriesConverted - optionally points to a DWORD which will be filled-in
|
|
with the number of entries actually converted. This will be the same
|
|
as PrimaryCount if we return NO_ERROR, but will be less if we return
|
|
ERROR_MORE_DATA.
|
|
|
|
TransmissionMode - Parameter to RapConvertSingleEntry.
|
|
|
|
ConversionMode - Which 16- to 32-bit conversion to use.
|
|
|
|
|
|
Return Value:
|
|
|
|
NET_API_STATUS - NERR_Success or ERROR_MORE_DATA.
|
|
( The callers of this routine assume these are the only two error codes.)
|
|
|
|
--*/
|
|
|
|
{
|
|
NET_API_STATUS status;
|
|
DWORD input_structure_size;
|
|
DWORD output_structure_size;
|
|
DWORD input_aux_structure_size = 0;
|
|
DWORD output_aux_structure_size = 0;
|
|
DWORD input_alignment;
|
|
DWORD output_alignment;
|
|
DWORD input_aux_alignment = 0;
|
|
DWORD output_aux_alignment = 0;
|
|
LPBYTE aligned_input_buffer_start;
|
|
LPBYTE aligned_output_buffer_start;
|
|
BOOL auxiliaries = (InputAuxDescriptor != NULL);
|
|
DWORD aux_count_offset = 0;
|
|
DWORD aux_count = 0;
|
|
DWORD entries_fully_converted = 0;
|
|
LPBYTE next_input_structure;
|
|
LPBYTE next_output_structure;
|
|
|
|
//
|
|
// These next two variables are used by RapConvertSingleEntry which copies
|
|
// stuff to the output buffer and informs us of the amount of space used or
|
|
// required, depending on whether it has enough space to write the data; we
|
|
// assume it will. RapConvertSingleEntry stores the fixed structures at the
|
|
// head of the buffer and starts writing the variable parts (strings) at the
|
|
// bottom. It uses variable_data_pointer as the next writable location for
|
|
// the strings, and updates this variable as it writes to the area pointed to
|
|
//
|
|
|
|
LPBYTE variable_data_pointer;
|
|
DWORD space_occupied = 0;
|
|
|
|
//
|
|
// if the conversion mode is NativeToRap or NativeToNative then the input
|
|
// data is 32-bit. Same for output data
|
|
//
|
|
|
|
BOOL input_is_32_bit = ConversionMode == NativeToRap || ConversionMode == NativeToNative;
|
|
BOOL output_is_32_bit = ConversionMode == RapToNative || ConversionMode == NativeToNative;
|
|
|
|
|
|
#if DBG
|
|
//
|
|
// the auxiliary data descriptors must be both NULL or both non-NULL
|
|
//
|
|
|
|
BOOL aux_in, aux_out;
|
|
|
|
aux_in = (InputAuxDescriptor != NULL);
|
|
aux_out = (OutputAuxDescriptor != NULL);
|
|
|
|
if (aux_in ^ aux_out)
|
|
{
|
|
NetpKdPrint(("RxpConvertDataStructures: "
|
|
"InputAuxDescriptor & OutputAuxDescriptor out of sync\n"));
|
|
NetpAssert(FALSE);
|
|
}
|
|
#endif
|
|
|
|
|
|
input_structure_size = RapStructureSize(InputDescriptor,
|
|
TransmissionMode,
|
|
input_is_32_bit
|
|
);
|
|
output_structure_size = RapStructureSize(OutputDescriptor,
|
|
TransmissionMode,
|
|
output_is_32_bit
|
|
);
|
|
input_alignment = RapStructureAlignment(InputDescriptor,
|
|
TransmissionMode,
|
|
input_is_32_bit
|
|
);
|
|
output_alignment = RapStructureAlignment(OutputDescriptor,
|
|
TransmissionMode,
|
|
output_is_32_bit
|
|
);
|
|
|
|
if (auxiliaries)
|
|
{
|
|
input_aux_structure_size = RapStructureSize(InputAuxDescriptor,
|
|
TransmissionMode,
|
|
input_is_32_bit
|
|
);
|
|
output_aux_structure_size = RapStructureSize(OutputAuxDescriptor,
|
|
TransmissionMode,
|
|
output_is_32_bit
|
|
);
|
|
input_aux_alignment = RapStructureAlignment(InputAuxDescriptor,
|
|
TransmissionMode,
|
|
input_is_32_bit
|
|
);
|
|
output_aux_alignment = RapStructureAlignment(OutputAuxDescriptor,
|
|
TransmissionMode,
|
|
output_is_32_bit
|
|
);
|
|
aux_count_offset = RapAuxDataCountOffset(InputDescriptor,
|
|
TransmissionMode,
|
|
input_is_32_bit
|
|
);
|
|
}
|
|
|
|
//
|
|
// Make sure first (only?) input and output structures are aligned. (This
|
|
// won't do anything for the RAP formats, but is critical for native.)
|
|
//
|
|
aligned_input_buffer_start = RapPossiblyAlignPointer(
|
|
InputBuffer,
|
|
input_alignment,
|
|
input_is_32_bit);
|
|
aligned_output_buffer_start = RapPossiblyAlignPointer(
|
|
OutputBuffer,
|
|
output_alignment,
|
|
output_is_32_bit);
|
|
|
|
//
|
|
// We can't use the space we just skipped over, so update size accordingly.
|
|
//
|
|
|
|
OutputBufferSize -= (DWORD)(aligned_output_buffer_start - OutputBuffer);
|
|
NetpAssert( OutputBufferSize >= 1 );
|
|
|
|
//
|
|
// Initialize roving pointers.
|
|
//
|
|
next_input_structure = aligned_input_buffer_start;
|
|
next_output_structure = aligned_output_buffer_start;
|
|
variable_data_pointer = aligned_output_buffer_start + OutputBufferSize;
|
|
|
|
//
|
|
// For each primary structure, copy the input primary to the output buffer,
|
|
// changing format as we go; copy any associated variable data at the end
|
|
// of the output buffer. Then, if there is an aux count associated with
|
|
// the primary, do the same action for the auxiliary structures and
|
|
// associated strings/variable data
|
|
//
|
|
|
|
while (PrimaryCount--)
|
|
{
|
|
//
|
|
// Convert the data for this instance of the primary structure.
|
|
//
|
|
status = RapConvertSingleEntryEx(
|
|
next_input_structure,
|
|
InputDescriptor, // input desc
|
|
FALSE, // input ptrs NOT meaningless
|
|
aligned_output_buffer_start,
|
|
next_output_structure,
|
|
OutputDescriptor,
|
|
FALSE, // don't set offsets (want ptrs)
|
|
&variable_data_pointer,
|
|
&space_occupied,
|
|
TransmissionMode, // as supplied in parameters
|
|
ConversionMode, // as supplied in parameters
|
|
(ULONG_PTR)InputBuffer
|
|
);
|
|
NetpAssert( status == NERR_Success );
|
|
|
|
if (space_occupied > OutputBufferSize)
|
|
{
|
|
IF_DEBUG(CONVDATA) {
|
|
NetpKdPrint(("RxpConvertDataStructures: "
|
|
"output buffer size blown by primary\n"));
|
|
}
|
|
status = ERROR_MORE_DATA;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// if we have auxiliary structs, pull out the number associated
|
|
// with this primary struct from the primary struct itself
|
|
// before pointing to the next copy location (this allows us to
|
|
// handle the case where there are a variable number of aux
|
|
// structs per each primary. There may not be such a case, but
|
|
// this is defensive programming)
|
|
//
|
|
|
|
if (auxiliaries)
|
|
{
|
|
if (input_is_32_bit)
|
|
{
|
|
aux_count = *(LPDWORD)(next_input_structure + aux_count_offset);
|
|
}
|
|
else
|
|
{
|
|
aux_count = *(LPWORD)(next_input_structure + aux_count_offset);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Bump to next element of each array (or just beyond end, if we're
|
|
// done).
|
|
//
|
|
next_input_structure += input_structure_size;
|
|
next_output_structure += output_structure_size;
|
|
|
|
//
|
|
// Make sure each primary structure is aligned. (This won't do anything
|
|
// for the RAP formats, but is critical for native.)
|
|
//
|
|
next_input_structure = RapPossiblyAlignPointer(
|
|
next_input_structure, input_alignment, input_is_32_bit);
|
|
|
|
{
|
|
DWORD NextOutputAlignment =
|
|
(DWORD)((LPBYTE) (RapPossiblyAlignPointer(
|
|
next_output_structure,
|
|
output_alignment,
|
|
output_is_32_bit))
|
|
- next_output_structure);
|
|
|
|
NetpAssert( NextOutputAlignment < ALIGN_WORST );
|
|
if (NextOutputAlignment > 0) {
|
|
next_output_structure += NextOutputAlignment;
|
|
space_occupied += NextOutputAlignment;
|
|
}
|
|
}
|
|
|
|
//
|
|
// use aux_count to determine whether loop should be performed
|
|
//
|
|
|
|
while (aux_count)
|
|
{
|
|
//
|
|
// Convert the data for this instance of the secondary structure.
|
|
//
|
|
status = RapConvertSingleEntryEx(
|
|
next_input_structure,
|
|
InputAuxDescriptor,
|
|
FALSE, // input ptrs NOT meaningless
|
|
aligned_output_buffer_start,
|
|
next_output_structure,
|
|
OutputAuxDescriptor,
|
|
FALSE, // don't set offsets (want ptrs)
|
|
&variable_data_pointer,
|
|
&space_occupied,
|
|
TransmissionMode, // as supplied in parameters
|
|
ConversionMode, // as supplied in parameters
|
|
(ULONG_PTR)InputBuffer
|
|
);
|
|
NetpAssert( status == NERR_Success );
|
|
|
|
if (space_occupied > OutputBufferSize)
|
|
{
|
|
IF_DEBUG(CONVDATA) {
|
|
NetpKdPrint(("RxpConvertDataStructures: "
|
|
"output buffer size blown by secondary\n"));
|
|
}
|
|
status = ERROR_MORE_DATA;
|
|
goto Cleanup;
|
|
}
|
|
|
|
next_input_structure += input_aux_structure_size;
|
|
next_output_structure += output_aux_structure_size;
|
|
--aux_count;
|
|
|
|
//
|
|
// Make sure next structure (if any) is aligned. (This won't do
|
|
// anything for the RAP formats, but is critical for native.)
|
|
//
|
|
next_input_structure = RapPossiblyAlignPointer(
|
|
next_input_structure,
|
|
input_aux_alignment,
|
|
input_is_32_bit);
|
|
next_output_structure = RapPossiblyAlignPointer(
|
|
next_output_structure,
|
|
output_aux_alignment,
|
|
output_is_32_bit);
|
|
space_occupied = RapPossiblyAlignCount(
|
|
space_occupied,
|
|
output_aux_alignment,
|
|
output_is_32_bit);
|
|
|
|
} // while (aux_count)
|
|
|
|
++entries_fully_converted;
|
|
|
|
} // while (primary_count--)
|
|
|
|
status = NERR_Success;
|
|
|
|
Cleanup:
|
|
|
|
if (EntriesConverted != NULL) {
|
|
*EntriesConverted = entries_fully_converted;
|
|
}
|
|
|
|
return (status);
|
|
}
|