|
|
/********************************************************************/ /** 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 );
}
|