windows-nt/Source/XPSP1/NT/net/sfm/afp/service/server/buffer.c
2020-09-26 16:20:57 +08:00

1237 lines
29 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: buffer.c
//
// Description: This module contains routines to manipulate cached
// information. ie volume info, server properties and
// ETC mappings info.
//
// History:
// May 11,1992. NarenG Created original version.
//
#include "afpsvcp.h"
// This should be more than the size (in bytes) all the value names
// each AfpMultSzInfo structure. It will be used to calculate the amount
// of memory needed to create a multi-sz.
//
#define AFP_CUMULATIVE_VALNAME_SIZE 150
// This data structure will be used by AfpBufParseMultiSz and
// AfpBufMakeMultiSz.
//
typedef struct _AfpMultiSzInfo {
DWORD dwType; // Type of data, string or DWORD
DWORD dwOffset; // Offset of this field from the start
LPWSTR lpwsValueName; // Value name for this field.
// If this is NULL then it does not
// have a value name. It is the
// value name for this MULT_SZ.
DWORD fIsInPlace; // If string, is it a pointer or a
// buffer.
DWORD cch; // If fIsInPlace is TRUE, then how
// big (in UNICODE chars.) is the
// buffer.
} AFP_MULTISZ_INFO, *PAFP_MULTISZ_INFO;
static AFP_MULTISZ_INFO AfpVolumeMultiSz[] = {
REG_SZ,
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_name ),
NULL,
FALSE,
0,
REG_SZ,
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_password ),
AFPREG_VALNAME_PASSWORD,
FALSE,
0,
REG_DWORD,
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_max_uses ),
AFPREG_VALNAME_MAXUSES,
FALSE,
0,
REG_DWORD,
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_props_mask ),
AFPREG_VALNAME_PROPS,
FALSE,
0,
REG_SZ,
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_path ),
AFPREG_VALNAME_PATH,
FALSE,
0,
REG_NONE, 0, 0, 0, 0
};
static AFP_MULTISZ_INFO AfpExtensionMultiSz[] = {
REG_SZ,
AFP_FIELD_OFFSET( AFP_EXTENSION, afpe_extension[0] ),
NULL,
TRUE,
AFP_FIELD_SIZE( AFP_EXTENSION, afpe_extension ),
REG_DWORD,
AFP_FIELD_OFFSET( AFP_EXTENSION, afpe_tcid ),
AFPREG_VALNAME_ID,
FALSE,
0,
REG_NONE, 0, 0, 0, 0
};
static AFP_MULTISZ_INFO AfpTypeCreatorMultiSz[] = {
REG_SZ,
AFP_FIELD_OFFSET(AFP_TYPE_CREATOR, afptc_creator[0] ),
AFPREG_VALNAME_CREATOR,
TRUE,
AFP_FIELD_SIZE(AFP_TYPE_CREATOR, afptc_creator ),
REG_SZ,
AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_type[0] ),
AFPREG_VALNAME_TYPE,
TRUE,
AFP_FIELD_SIZE( AFP_TYPE_CREATOR, afptc_type ),
REG_SZ,
AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_comment[0] ),
AFPREG_VALNAME_COMMENT,
TRUE,
AFP_FIELD_SIZE( AFP_TYPE_CREATOR, afptc_comment ),
REG_DWORD,
AFP_FIELD_OFFSET( AFP_TYPE_CREATOR, afptc_id ),
NULL,
FALSE,
0,
REG_NONE, 0, 0, 0, 0
};
static AFP_MULTISZ_INFO AfpIconMultiSz[] = {
REG_SZ,
AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_type[0] ),
AFPREG_VALNAME_TYPE,
TRUE,
AFP_FIELD_SIZE( AFP_ICON_INFO, afpicon_type ),
REG_SZ,
AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_creator[0] ),
AFPREG_VALNAME_CREATOR,
TRUE,
AFP_FIELD_SIZE( AFP_ICON_INFO, afpicon_creator ),
REG_DWORD,
AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_icontype ),
AFPREG_VALNAME_ICONTYPE,
FALSE,
0,
REG_DWORD,
AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_length ),
AFPREG_VALNAME_LENGTH,
FALSE,
0,
REG_SZ,
AFP_FIELD_OFFSET( AFP_ICON_INFO, afpicon_data ),
AFPREG_VALNAME_DATA,
FALSE,
0,
REG_NONE, 0, 0, 0, 0
};
// These arrays represents the byte offsets, from the beginning of the
// structure, of the LPWSTR fields.
//
static BYTE ServerOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_name ),
AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_login_msg ),
AFP_FIELD_OFFSET( AFP_SERVER_INFO, afpsrv_codepage ),
0xFF
};
static BYTE VolumeOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_name ),
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_password ),
AFP_FIELD_OFFSET( AFP_VOLUME_INFO, afpvol_path ),
0xFF
};
static BYTE DirOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_path ),
AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_owner ),
AFP_FIELD_OFFSET( AFP_DIRECTORY_INFO, afpdir_group ),
0xFF
};
static BYTE SessionOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_SESSION_INFO, afpsess_ws_name ),
AFP_FIELD_OFFSET( AFP_SESSION_INFO, afpsess_username ),
0xFF
};
static BYTE FileOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_FILE_INFO, afpfile_path ),
AFP_FIELD_OFFSET( AFP_FILE_INFO, afpfile_username ),
0xFF
};
static BYTE ConnectionOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_CONNECTION_INFO, afpconn_username ),
AFP_FIELD_OFFSET( AFP_CONNECTION_INFO, afpconn_volumename ),
0xFF
};
static BYTE MessageOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_MESSAGE_INFO, afpmsg_text ),
0xFF
};
static BYTE FinderOffsetTable[] = {
AFP_FIELD_OFFSET( AFP_FINDER_INFO, afpfd_path ),
0xFF
};
//**
//
// Call: AfpBufStructureSize
//
// Returns: The size (in bytes) of the data withing the structure.
//
// Description: It will calculate the size of all the variable data and
// add that to the fixed size of the structure.
//
DWORD
AfpBufStructureSize(
IN AFP_STRUCTURE_TYPE dwStructureType,
IN LPBYTE lpbStructure
)
{
DWORD cbStructureSize;
DWORD dwIndex;
DWORD cbBufSize;
LPWSTR* plpwsStringField;
PBYTE OffsetTable;
switch( dwStructureType ) {
case AFP_VOLUME_STRUCT:
OffsetTable = VolumeOffsetTable;
cbStructureSize = sizeof( AFP_VOLUME_INFO );
break;
case AFP_SERVER_STRUCT:
OffsetTable = ServerOffsetTable;
cbStructureSize = sizeof( AFP_SERVER_INFO );
break;
case AFP_DIRECTORY_STRUCT:
OffsetTable = DirOffsetTable;
cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
break;
case AFP_EXTENSION_STRUCT:
return( sizeof(AFP_EXTENSION) );
break;
case AFP_TYPECREATOR_STRUCT:
return( sizeof(AFP_TYPE_CREATOR) );
break;
case AFP_MESSAGE_STRUCT:
OffsetTable = MessageOffsetTable;
cbStructureSize = sizeof( AFP_MESSAGE_INFO );
break;
case AFP_ICON_STRUCT:
return( sizeof(AFP_ICON_INFO) +
((PAFP_ICON_INFO)lpbStructure)->afpicon_length );
break;
case AFP_FINDER_STRUCT:
OffsetTable = FinderOffsetTable;
cbStructureSize = sizeof( AFP_FINDER_INFO );
break;
default:
return( 0 );
}
// First calculate the amount of memory that will be needed to
// store all the string information.
//
for( dwIndex = 0, cbBufSize = 0;
OffsetTable[dwIndex] != 0xFF;
dwIndex++
) {
plpwsStringField=(LPWSTR*)((ULONG_PTR)lpbStructure + OffsetTable[dwIndex]);
cbBufSize += ( ( *plpwsStringField == NULL ) ? 0 :
STRLEN( *plpwsStringField ) + 1 );
}
// Convert to UNICODE size
//
cbBufSize *= sizeof( WCHAR );
// Add size of fixed part of the structure
//
cbBufSize += cbStructureSize;
return( cbBufSize );
}
//**
//
// Call: AfpBufMakeFSDRequest
//
// Returns: NO_ERROR
// ERROR_NOT_ENOUGH_MEMORY
//
// Description: This routine is called by the worker routines for the client
// API calls. The purpose of this routine is to convert a
// AFP_XXX_INFO structure passed by the client API into a
// contiguous self-relative buffer. This has to be done because
// the FSD cannot reference pointers to user space.
//
// This routine will allocate the required amount of memory to
// store all the information in self relative form. It is
// the reponsibility of the caller to free this memory.
//
// All pointer fields will be converted to offsets from the
// beginning of the structure.
//
// The cbReqPktSize parameter specifies how many bytes of space
// should be allocated before the self relative data structure.
// i.e.
// |------------|
// |cbReqPktSize|
// | bytes |
// |------------|
// | Self |
// | relative |
// | structure |
// |------------|
//
DWORD
AfpBufMakeFSDRequest(
// Buffer as received by the client API
//
IN LPBYTE pBuffer,
// Size of FSD request packet.
//
IN DWORD cbReqPktSize,
IN AFP_STRUCTURE_TYPE dwStructureType,
// Self-relative form of I/P buf
//
OUT LPBYTE *ppSelfRelativeBuf,
// Size of self relative buf
//
OUT LPDWORD lpdwSelfRelativeBufSize
)
{
LPBYTE lpbSelfRelBuf;
DWORD cbSRBufSize;
DWORD dwIndex;
LPWSTR lpwsVariableData;
LPWSTR * plpwsStringField;
LPWSTR * plpwsStringFieldSR;
PBYTE OffsetTable;
DWORD cbStructureSize;
// Initialize the offset table and the structure size values
//
switch( dwStructureType ) {
case AFP_VOLUME_STRUCT:
OffsetTable = VolumeOffsetTable;
cbStructureSize = sizeof( AFP_VOLUME_INFO );
break;
case AFP_SERVER_STRUCT:
OffsetTable = ServerOffsetTable;
cbStructureSize = sizeof( AFP_SERVER_INFO );
break;
case AFP_DIRECTORY_STRUCT:
OffsetTable = DirOffsetTable;
cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
break;
case AFP_MESSAGE_STRUCT:
OffsetTable = MessageOffsetTable;
cbStructureSize = sizeof( AFP_MESSAGE_INFO );
break;
case AFP_FINDER_STRUCT:
OffsetTable = FinderOffsetTable;
cbStructureSize = sizeof( AFP_FINDER_INFO );
break;
default:
return( ERROR_INVALID_PARAMETER );
}
cbSRBufSize = cbReqPktSize + AfpBufStructureSize(dwStructureType, pBuffer);
// Allocate space for self relative buffer
//
if ( ( lpbSelfRelBuf = (LPBYTE)LocalAlloc( LPTR, cbSRBufSize ) ) == NULL )
return( ERROR_NOT_ENOUGH_MEMORY );
*ppSelfRelativeBuf = lpbSelfRelBuf;
*lpdwSelfRelativeBufSize = cbSRBufSize;
// Advance this pointer beyond the request packet
//
lpbSelfRelBuf += cbReqPktSize;
// memcpy to fill in the non-string data
//
CopyMemory( lpbSelfRelBuf, pBuffer, cbStructureSize );
// Now copy all the strings
//
for( dwIndex = 0,
lpwsVariableData = (LPWSTR)((ULONG_PTR)lpbSelfRelBuf + cbStructureSize);
OffsetTable[dwIndex] != 0xFF;
dwIndex++ ) {
// This will point to a string pointer field in the non self-relative
// structure.
//
plpwsStringField = (LPWSTR*)((ULONG_PTR)pBuffer + OffsetTable[dwIndex]);
// This will point to the corresponding string pointer field in the
// self-relative structure
//
plpwsStringFieldSR=(LPWSTR*)((ULONG_PTR)lpbSelfRelBuf+OffsetTable[dwIndex]);
// If there is no string to be copied, then just set to NULL
//
if ( *plpwsStringField == NULL )
*plpwsStringFieldSR = NULL;
else {
// There is a string so copy it
//
STRCPY( lpwsVariableData, *plpwsStringField );
// Store the pointer value
//
*plpwsStringFieldSR = lpwsVariableData;
// Convert the pointer to this data to an offset
//
POINTER_TO_OFFSET( *plpwsStringFieldSR, lpbSelfRelBuf );
// Update the pointer to where the next variable length data
// will be stored.
//
lpwsVariableData += ( STRLEN( *plpwsStringField ) + 1 );
}
}
return( NO_ERROR );
}
//**
//
// Call: AfpBufOffsetToPointer
//
// Returns: none.
//
// Description: Will walk a list of structures, converting all offsets
// within each structure to pointers.
//
VOID
AfpBufOffsetToPointer(
IN OUT LPBYTE pBuffer,
IN DWORD dwNumEntries,
IN AFP_STRUCTURE_TYPE dwStructureType
)
{
PBYTE OffsetTable;
DWORD cbStructureSize;
LPWSTR *plpwsStringField;
DWORD dwIndex;
// Initialize the offset table and the structure size values
//
switch( dwStructureType ) {
case AFP_VOLUME_STRUCT:
OffsetTable = VolumeOffsetTable;
cbStructureSize = sizeof( AFP_VOLUME_INFO );
break;
case AFP_SESSION_STRUCT:
OffsetTable = SessionOffsetTable;
cbStructureSize = sizeof( AFP_SESSION_INFO );
break;
case AFP_CONNECTION_STRUCT:
OffsetTable = ConnectionOffsetTable;
cbStructureSize = sizeof( AFP_CONNECTION_INFO );
break;
case AFP_FILE_STRUCT:
OffsetTable = FileOffsetTable;
cbStructureSize = sizeof( AFP_FILE_INFO );
break;
case AFP_DIRECTORY_STRUCT:
OffsetTable = DirOffsetTable;
cbStructureSize = sizeof( AFP_DIRECTORY_INFO );
break;
case AFP_MESSAGE_STRUCT:
OffsetTable = MessageOffsetTable;
cbStructureSize = sizeof( AFP_MESSAGE_INFO );
break;
case AFP_SERVER_STRUCT:
OffsetTable = ServerOffsetTable;
cbStructureSize = sizeof( AFP_SERVER_INFO );
break;
default:
return;
}
// Walk the list and convert each structure.
//
while( dwNumEntries-- ) {
// Convert every LPWSTR from an offset to a pointer
//
for( dwIndex = 0; OffsetTable[dwIndex] != 0xFF; dwIndex++ ) {
plpwsStringField = (LPWSTR*)( (ULONG_PTR)pBuffer
+ (DWORD)OffsetTable[dwIndex] );
OFFSET_TO_POINTER( *plpwsStringField, pBuffer );
}
pBuffer += cbStructureSize;
}
return;
}
//**
//
// Call: AfpBufMakeMultiSz
//
// Returns: NO_ERROR - success
// ERROR_NOT_ENOUGH_MEMORY
//
// Description: This routine will take a give structure and create a
// REG_MULTI_SZ from it. This can then be set directly into the
// registry. It is the caller's responsibility to free
// the memory allocated for *ppbMultiSz.
//
DWORD
AfpBufMakeMultiSz(
IN AFP_STRUCTURE_TYPE dwStructureType,
IN LPBYTE lpbStructure,
OUT LPBYTE * ppbMultiSz,
OUT LPDWORD lpdwMultiSzSize
)
{
PAFP_MULTISZ_INFO pAfpMultiSz;
PWCHAR lpwchWalker;
PVOID pData;
DWORD dwIndex;
DWORD cbStructureSize;
switch( dwStructureType ) {
case AFP_VOLUME_STRUCT:
pAfpMultiSz = AfpVolumeMultiSz;
break;
case AFP_EXTENSION_STRUCT:
pAfpMultiSz = AfpExtensionMultiSz;
break;
case AFP_TYPECREATOR_STRUCT:
pAfpMultiSz = AfpTypeCreatorMultiSz;
break;
case AFP_ICON_STRUCT:
pAfpMultiSz = AfpIconMultiSz;
break;
default:
return( ERROR_INVALID_PARAMETER );
}
// Allocate enough memory to create the multi-sz.
// AFP_CUMULATIVE_VALNAME_SIZE should be greater than the sum of all the
// value names of all the structures.
//
cbStructureSize = AfpBufStructureSize( dwStructureType, lpbStructure )
+ AFP_CUMULATIVE_VALNAME_SIZE;
if ( ( *ppbMultiSz = (LPBYTE)LocalAlloc( LPTR, cbStructureSize ) ) == NULL )
return( ERROR_NOT_ENOUGH_MEMORY );
ZeroMemory( *ppbMultiSz, cbStructureSize );
// For every field, we create a string
//
for ( dwIndex = 0,
lpwchWalker = (PWCHAR)*ppbMultiSz;
pAfpMultiSz[dwIndex].dwType != REG_NONE;
dwIndex++
){
// This is the value name so do not put it in the buffer.
//
if ( pAfpMultiSz[dwIndex].lpwsValueName == NULL )
continue;
STRCPY( lpwchWalker, pAfpMultiSz[dwIndex].lpwsValueName );
STRCAT( lpwchWalker, TEXT("="));
lpwchWalker += STRLEN( lpwchWalker );
pData = lpbStructure + pAfpMultiSz[dwIndex].dwOffset;
// Convert to string and concatenate
//
if ( pAfpMultiSz[dwIndex].dwType == REG_DWORD ) {
UCHAR chAnsiBuf[12];
_itoa( *((LPDWORD)pData), chAnsiBuf, 10 );
mbstowcs( lpwchWalker, chAnsiBuf, sizeof(chAnsiBuf) );
}
if ( pAfpMultiSz[dwIndex].dwType == REG_SZ ) {
// Check if this is a pointer or an in-place buffer
//
if ( pAfpMultiSz[dwIndex].fIsInPlace )
STRCPY( lpwchWalker, (LPWSTR)pData );
else {
if ( *(LPWSTR*)pData != NULL )
STRCPY( lpwchWalker, *((LPWSTR*)pData) );
}
}
lpwchWalker += ( STRLEN( lpwchWalker ) + 1 );
}
*lpdwMultiSzSize = (DWORD)((ULONG_PTR)lpwchWalker - (ULONG_PTR)(*ppbMultiSz) ) + sizeof(WCHAR);
return( NO_ERROR );
}
//**
//
// Call: AfpBufParseMultiSz
//
// Returns: NO_ERROR - success
// ERROR_INVALID_PARAMETER
//
// Description: This routine will parse a REG_MULTI_SZ and fill in the
// appropriate data structure. All pointers will point to
// the pbMultiSz input parameter.
//
DWORD
AfpBufParseMultiSz(
IN AFP_STRUCTURE_TYPE dwStructureType,
IN LPBYTE pbMultiSz,
OUT LPBYTE pbStructure
)
{
PAFP_MULTISZ_INFO pAfpMultiSz;
DWORD dwIndex;
DWORD cbStructSize;
LPWSTR lpwchWalker;
PVOID pData;
UCHAR chAnsiBuf[12];
DWORD dwDisableCatsearch=0;
switch( dwStructureType ) {
case AFP_VOLUME_STRUCT:
pAfpMultiSz = AfpVolumeMultiSz;
cbStructSize = sizeof( AFP_VOLUME_INFO );
//
// The following "quick fix" is for Disabling CatSearch support. Read in the
// DisableCatsearch parameter if it's put in. In most cases, this parm won't
// be there. If it is, the server disables CatSearch
//
for ( (lpwchWalker = (LPWSTR)pbMultiSz);
(*lpwchWalker != TEXT('\0') );
(lpwchWalker += ( STRLEN( lpwchWalker ) + 1 ) ))
{
if ( STRNICMP( AFPREG_VALNAME_CATSEARCH,
lpwchWalker,
STRLEN( AFPREG_VALNAME_CATSEARCH ) ) == 0 )
{
lpwchWalker += ( STRLEN( AFPREG_VALNAME_CATSEARCH ) + 1 );
wcstombs( chAnsiBuf, lpwchWalker, sizeof(chAnsiBuf) );
dwDisableCatsearch = atoi( chAnsiBuf );
break;
}
}
break;
case AFP_EXTENSION_STRUCT:
pAfpMultiSz = AfpExtensionMultiSz;
cbStructSize = sizeof( AFP_EXTENSION );
break;
case AFP_TYPECREATOR_STRUCT:
pAfpMultiSz = AfpTypeCreatorMultiSz;
cbStructSize = sizeof( AFP_TYPE_CREATOR );
break;
case AFP_ICON_STRUCT:
pAfpMultiSz = AfpIconMultiSz;
cbStructSize = sizeof( AFP_ICON_INFO );
break;
default:
return( ERROR_INVALID_PARAMETER );
}
ZeroMemory( pbStructure, cbStructSize );
// For every field in the structure
//
for ( dwIndex = 0; pAfpMultiSz[dwIndex].dwType != REG_NONE; dwIndex++ ){
// This is the value name so do not try to retrieve it from the
// buffer.
//
if ( pAfpMultiSz[dwIndex].lpwsValueName == NULL )
continue;
// Search for valuename for this field
//
for ( lpwchWalker = (LPWSTR)pbMultiSz;
( *lpwchWalker != TEXT('\0') )
&&
( STRNICMP( pAfpMultiSz[dwIndex].lpwsValueName,
lpwchWalker,
STRLEN(pAfpMultiSz[dwIndex].lpwsValueName) ) != 0 );
lpwchWalker += ( STRLEN( lpwchWalker ) + 1 ) );
// Could not find parameter
//
if ( *lpwchWalker == TEXT('\0') )
return( ERROR_INVALID_PARAMETER );
// Otherwise we found it so get the value
//
lpwchWalker += ( STRLEN( pAfpMultiSz[dwIndex].lpwsValueName ) + 1 );
pData = pbStructure + pAfpMultiSz[dwIndex].dwOffset;
// If there is no value after the value name then ignore this field
// It defaults to zero.
//
if ( *lpwchWalker != TEXT( '\0' ) ) {
// Convert to integer
//
if ( pAfpMultiSz[dwIndex].dwType == REG_DWORD ) {
wcstombs( chAnsiBuf, lpwchWalker, sizeof(chAnsiBuf) );
*((LPDWORD)pData) = atoi( chAnsiBuf );
}
//
// CatSearch hack continued: if we are looking at the volume mask
// parameter, see if we must turn the bit off.
//
if( dwStructureType == AFP_VOLUME_STRUCT && dwDisableCatsearch )
{
if ( STRNICMP( pAfpMultiSz[dwIndex].lpwsValueName,
AFPREG_VALNAME_PROPS,
STRLEN(pAfpMultiSz[dwIndex].lpwsValueName) ) == 0 )
{
*((LPDWORD)pData) |= AFP_VOLUME_DISALLOW_CATSRCH;
}
}
if ( pAfpMultiSz[dwIndex].dwType == REG_SZ ) {
// Check if this is a pointer or an in-place buffer
//
if ( pAfpMultiSz[dwIndex].fIsInPlace ) {
if ( STRLEN( lpwchWalker ) > pAfpMultiSz[dwIndex].cch )
return( ERROR_INVALID_PARAMETER );
STRCPY( (LPWSTR)pData, lpwchWalker );
}
else
*((LPWSTR*)pData) = lpwchWalker;
}
}
}
return( NO_ERROR );
}
//**
//
// Call: AfpBufMakeFSDETCMappings
//
// Returns: NO_ERROR
// ERROR_NOT_ENOUGH_MEMORY
//
// Description: This routine will convert all the mappings in the
// form stored in AfpGlobals.AfpETCMapInfo to the form
// required by the FSD, ie. the ETCMAPINFO structure.
// It is the responsibility for the caller to free
// allocated memory.
//
DWORD
AfpBufMakeFSDETCMappings(
OUT PSRVETCPKT *ppSrvSetEtc,
OUT LPDWORD lpdwSrvSetEtcBufSize
)
{
DWORD dwIndex;
PETCMAPINFO2 pETCMapInfo;
PAFP_EXTENSION pExtensionWalker;
PAFP_TYPE_CREATOR pTypeCreator;
AFP_TYPE_CREATOR AfpTypeCreatorKey;
DWORD dwNumTypeCreators;
// Allocate space to hold the ETCMaps in the form required by the FSD.
//
*ppSrvSetEtc = (PSRVETCPKT)LocalAlloc( LPTR,
AFP_FIELD_SIZE( SRVETCPKT, retc_NumEtcMaps ) +
(AfpGlobals.AfpETCMapInfo.afpetc_num_extensions*sizeof(ETCMAPINFO2)));
if ( *ppSrvSetEtc == NULL )
return( ERROR_NOT_ENOUGH_MEMORY );
// Walk through the extension list
//
for( dwIndex = 0,
pETCMapInfo = (*ppSrvSetEtc)->retc_EtcMaps,
pExtensionWalker = AfpGlobals.AfpETCMapInfo.afpetc_extension,
pTypeCreator = AfpGlobals.AfpETCMapInfo.afpetc_type_creator,
dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators,
(*ppSrvSetEtc)->retc_NumEtcMaps = 0;
dwIndex < AfpGlobals.AfpETCMapInfo.afpetc_num_extensions;
dwIndex++,
dwNumTypeCreators = AfpGlobals.AfpETCMapInfo.afpetc_num_type_creators,
pExtensionWalker++
) {
// Ignore any extensions that are associated with the default
// type/creator. They shouldnt be in the registry to begin with.
//
if ( pExtensionWalker->afpe_tcid == AFP_DEF_TCID )
continue;
// Find the type/creator associated with this extension.
//
AfpTypeCreatorKey.afptc_id = pExtensionWalker->afpe_tcid;
pTypeCreator = _lfind( &AfpTypeCreatorKey,
AfpGlobals.AfpETCMapInfo.afpetc_type_creator,
(unsigned int *)&dwNumTypeCreators,
sizeof(AFP_TYPE_CREATOR),
AfpLCompareTypeCreator );
// If there is a type/creator associated with this extension
//
if ( pTypeCreator != NULL ) {
AfpBufCopyFSDETCMapInfo( pTypeCreator,
pExtensionWalker,
pETCMapInfo );
pETCMapInfo++;
(*ppSrvSetEtc)->retc_NumEtcMaps++;
}
}
*lpdwSrvSetEtcBufSize = AFP_FIELD_SIZE( SRVETCPKT, retc_NumEtcMaps ) +
((*ppSrvSetEtc)->retc_NumEtcMaps * sizeof(ETCMAPINFO2));
return( NO_ERROR );
}
//**
//
// Call: AfpBufMakeFSDIcon
//
// Returns: none.
//
// Description: This routine will copy the icon information from the
// AFP_ICON_INFO data structure to an SRVICONINFO data
// structure viz. the form that the FSD needs.
//
VOID
AfpBufMakeFSDIcon(
IN PAFP_ICON_INFO pIconInfo,
OUT LPBYTE lpbFSDIcon,
OUT LPDWORD lpcbFSDIconSize
)
{
UCHAR chBuffer[sizeof(AFP_ICON_INFO)]; // Need enough space to translate
// Blank out the whole structure so that type and creator will
// be padded with blanks
//
memset( lpbFSDIcon, ' ', sizeof(SRVICONINFO) );
// Convert to ANSI and copy type
//
wcstombs(chBuffer,pIconInfo->afpicon_type,sizeof(chBuffer));
CopyMemory( ((PSRVICONINFO)lpbFSDIcon)->icon_type,
chBuffer,
STRLEN(pIconInfo->afpicon_type));
// Convert to ANSI copy creator
//
wcstombs(chBuffer,pIconInfo->afpicon_creator,sizeof(chBuffer));
CopyMemory( ((PSRVICONINFO)lpbFSDIcon)->icon_creator,
chBuffer,
STRLEN(pIconInfo->afpicon_creator));
// Set icon type
//
((PSRVICONINFO)lpbFSDIcon)->icon_icontype = pIconInfo->afpicon_icontype;
// Set icon data length
//
((PSRVICONINFO)lpbFSDIcon)->icon_length = pIconInfo->afpicon_length;
CopyMemory( lpbFSDIcon + sizeof(SRVICONINFO),
pIconInfo->afpicon_data,
((PSRVICONINFO)lpbFSDIcon)->icon_length );
*lpcbFSDIconSize = sizeof(SRVICONINFO) + pIconInfo->afpicon_length;
return;
}
//**
//
// Call: AfpBufCopyFSDETCMapInfo
//
// Returns: none
//
// Description: This routine will copu information from the AFP_TYPE_CREATOR
// and AFP_EXTENSION data structures into a ETCMAPINFO data
// structure viz. in the form as required by the FSD.
//
VOID
AfpBufCopyFSDETCMapInfo(
IN PAFP_TYPE_CREATOR pAfpTypeCreator,
IN PAFP_EXTENSION pAfpExtension,
OUT PETCMAPINFO2 pFSDETCMapInfo
)
{
CHAR Buffer[sizeof(AFP_TYPE_CREATOR)];
// Insert blanks which will be used to pad type/creators less
// than their max. lengths.
//
memset( (LPBYTE)pFSDETCMapInfo, ' ', sizeof(ETCMAPINFO2) );
ZeroMemory( (LPBYTE)(pFSDETCMapInfo->etc_extension),
AFP_FIELD_SIZE( ETCMAPINFO2, etc_extension ) );
CopyMemory( pFSDETCMapInfo->etc_extension,
pAfpExtension->afpe_extension,
wcslen(pAfpExtension->afpe_extension) * sizeof(WCHAR));
wcstombs( Buffer, pAfpTypeCreator->afptc_type, sizeof(Buffer) );
CopyMemory( pFSDETCMapInfo->etc_type,
Buffer,
STRLEN(pAfpTypeCreator->afptc_type));
wcstombs( Buffer, pAfpTypeCreator->afptc_creator, sizeof(Buffer) );
CopyMemory( pFSDETCMapInfo->etc_creator,
Buffer,
STRLEN(pAfpTypeCreator->afptc_creator));
return;
}
//**
//
// Call: AfpBufUnicodeToNibble
//
// Returns: NO_ERROR
// ERROR_INVALID_PARAMETER
//
// Description: This routine will take a pointer to a UNCODE string and
// convert each UNICODE char to a the corresponding nibble.
// it char. 'A' will be converted to a nibble having value 0xA
// This conversion is done in-place.
//
DWORD
AfpBufUnicodeToNibble(
IN OUT LPWSTR lpwsData
)
{
DWORD dwIndex;
BYTE bData;
LPBYTE lpbData = (LPBYTE)lpwsData;
// Convert each UNICODE character to nibble. (in place)
//
for ( dwIndex = 0; *lpwsData != TEXT('\0'); dwIndex++, lpwsData++ ) {
if ( iswalpha( *lpwsData ) ) {
if ( iswupper( *lpwsData ) )
bData = *lpwsData - TEXT('A');
else
bData = *lpwsData - TEXT('a');
bData += 10;
if ( bData > 0x0F )
return( ERROR_INVALID_PARAMETER );
}
else if ( iswdigit( *lpwsData ) )
bData = *lpwsData - TEXT('0');
else
return( ERROR_INVALID_PARAMETER );
// Multipy so that data is in the most significant nibble.
// Do this every other time.
//
if ( ( dwIndex % 2 ) == 0 )
*lpbData = bData * 16;
else {
*lpbData += bData;
lpbData++;
}
}
return( NO_ERROR );
}
//**
//
// Call: AfpBCompareTypeCreator
//
// Returns: < 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
// > 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
// == 0 if pAfpTypeCreator1 is equal to pAfpTypeCreator2
//
// Description: This routine is called by qsort to sort the list of
// type creators in the cache. The list is sorted in
// ascending alphabetical order of the concatenation of the
// creator and type. This list is sorted to facilitate quick
// lookup (binary search). This routine is also called by
// bsearch to do a binary search on the list.
//
int
_cdecl
AfpBCompareTypeCreator(
IN const void * pAfpTypeCreator1,
IN const void * pAfpTypeCreator2
)
{
WCHAR wchTypeCreator1[ sizeof( AFP_TYPE_CREATOR )];
WCHAR wchTypeCreator2[ sizeof( AFP_TYPE_CREATOR )];
STRCPY(wchTypeCreator1,
((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_creator);
if (STRLEN(((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_creator) == 0)
wchTypeCreator1[0]=L'\0';
STRCAT(wchTypeCreator1,((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_type );
STRCPY(wchTypeCreator2,
((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_creator);
STRCAT(wchTypeCreator2,((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_type );
return( STRCMP( wchTypeCreator1, wchTypeCreator2 ) );
}
//**
//
// Call: AfpLCompareTypeCreator
//
// Returns: < 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
// > 0 if pAfpTypeCreator1 comes before pAfpTypeCreator2
// == 0 if pAfpTypeCreator1 is equal to pAfpTypeCreator2
//
// Description: This routine is called by lfind to do a linear search of
// the type/creator list.
//
int
_cdecl
AfpLCompareTypeCreator(
IN const void * pAfpTypeCreator1,
IN const void * pAfpTypeCreator2
)
{
return( ( ((PAFP_TYPE_CREATOR)pAfpTypeCreator1)->afptc_id ==
((PAFP_TYPE_CREATOR)pAfpTypeCreator2)->afptc_id ) ? 0 : 1 );
}
//**
//
// Call: AfpBCompareExtension
//
// Returns: < 0 if pAfpExtension1 comes before pAfpExtension2
// > 0 if pAfpExtension1 comes before pAfpExtension2
// == 0 if pAfpExtension1 is equal to pAfpExtension2
//
// Description: This is called by qsort to sort the list of extensions in the
// cache. The list is sorted by ID. This routine is also called
// by bserach to do a binary lookup of this list.
//
int
_cdecl
AfpBCompareExtension(
IN const void * pAfpExtension1,
IN const void * pAfpExtension2
)
{
return((((PAFP_EXTENSION)pAfpExtension1)->afpe_tcid ==
((PAFP_EXTENSION)pAfpExtension2)->afpe_tcid ) ? 0 :
((((PAFP_EXTENSION)pAfpExtension1)->afpe_tcid <
((PAFP_EXTENSION)pAfpExtension2)->afpe_tcid ) ? -1 : 1 ));
}
//**
//
// Call: AfpLCompareExtension
//
// Returns: < 0 if pAfpExtension1 comes before pAfpExtension2
// > 0 if pAfpExtension1 comes before pAfpExtension2
// == 0 if pAfpExtension1 is equal to pAfpExtension2
//
// Description: This routine is called by lfind to do a linear lookup of the
// list of extensions in the cache.
//
int
_cdecl
AfpLCompareExtension(
IN const void * pAfpExtension1,
IN const void * pAfpExtension2
)
{
return( STRICMP( ((PAFP_EXTENSION)pAfpExtension1)->afpe_extension,
((PAFP_EXTENSION)pAfpExtension2)->afpe_extension ) );
}
//**
//
// Call: AfpBinarySearch
//
// Returns: Pointer to first occurance of element that matches pKey.
//
// Description: This is a wrapper around bsearch. Since bsearch does not
// return the first occurance of an element within the array,
// this routine will back up to point to the first occurance
// of a record with a particular key is reached.
//
void *
AfpBinarySearch(
IN const void * pKey,
IN const void * pBase,
IN size_t num,
IN size_t width,
IN int (_cdecl *compare)(const void * pElem1, const void * pElem2 )
)
{
void * pCurrElem = bsearch( pKey, pBase, num, width, compare);
if ( pCurrElem == NULL )
return( NULL );
// Backup until first occurance is reached
//
while ( ( (ULONG_PTR)pCurrElem > (ULONG_PTR)pBase )
&&
( (*compare)( pKey, (void*)((ULONG_PTR)pCurrElem - width) ) == 0 ) )
pCurrElem = (void *)((ULONG_PTR)pCurrElem - width);
return( pCurrElem );
}