You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1593 lines
39 KiB
1593 lines
39 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: addtcp.cpp
|
|
* Content: DirectPlay8Address core implementation file
|
|
*@@BEGIN_MSINTERNAL
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 02/04/2000 rmt Created
|
|
* 02/10/2000 rmt Updated to use DPNA_ defines instead of URL_
|
|
* 02/12/2000 rmt Split Get into GetByName and GetByIndex
|
|
* 02/17/2000 rmt Parameter validation work
|
|
* 02/18/2000 rmt Added type validation to all pre-defined elements
|
|
* 02/21/2000 rmt Updated to make core Unicode and remove ANSI calls
|
|
* 02/23/2000 rmt Fixed length calculations in GetURL
|
|
* rmt Buffer too small error debug messages -> Warning level
|
|
* 03/21/2000 rmt Renamed all DirectPlayAddress8's to DirectPlay8Addresses
|
|
* Added support for the new ANSI type
|
|
* 05/04/00 mjn delete temp var at end of SetElement()
|
|
* 05/05/00 mjn Better error cleanup in SetElement()
|
|
* 06/06/00 rmt Bug #36455 failure when calling with ANSI string shortcut for SP
|
|
* 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
|
|
* 06/21/2000 rmt Bug #37392 - Leak if replacing allocated element with new item same size as GUID
|
|
* 06/27/2000 rmt Bug #37630 - Service provider shortcuts / element names were case sensitive
|
|
* 07/06/2000 rmt Bug #38714 - ADDRESSING: GetURL doesn't return the # of chars written
|
|
* 07/09/2000 rmt Added signature bytes to start of address objects
|
|
* 07/12/2000 rmt Fixed some critical section related bugs:
|
|
* - Added leave in an error path where it wasn't being called
|
|
* - Moved critical section init/delete to constructor / destructor
|
|
* 07/13/2000 rmt Bug #39274 - INT 3 during voice run
|
|
* - Fixed point where a critical section was being re-initialized
|
|
* rmt Added critical sections to protect FPMs
|
|
* 07/21/2000 rmt Fixed bug w/directplay 4 address parsing
|
|
* 07/31/2000 rmt Bug #41125 - Addressing() GetUserData when none available should return doesnotexist
|
|
* 08/03/2000 rmt Missing LEAVELOCK() was causing lockups.
|
|
* 11/29/2000 aarono B#226079 prefix, fix memory leak in failure path of SetElement
|
|
*@@END_MSINTERNAL
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dnaddri.h"
|
|
|
|
|
|
const WCHAR * g_szBaseStrings[] =
|
|
{
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
DPNA_KEY_PROVIDER,
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
DPNA_KEY_DEVICE,
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
DPNA_KEY_HOSTNAME,
|
|
DPNA_KEY_PORT,
|
|
#ifndef DPNBUILD_NOLOBBY
|
|
DPNA_KEY_APPLICATION_INSTANCE,
|
|
DPNA_KEY_PROGRAM,
|
|
#endif // ! DPNBUILD_NOLOBBY
|
|
#ifndef DPNBUILD_NOSERIALSP
|
|
DPNA_KEY_BAUD,
|
|
DPNA_KEY_FLOWCONTROL,
|
|
DPNA_KEY_PARITY,
|
|
DPNA_KEY_PHONENUMBER,
|
|
DPNA_KEY_STOPBITS
|
|
#endif // !DPNBUILD_NOSERIALSP
|
|
};
|
|
|
|
const DWORD c_dwNumBaseStrings = LENGTHOF(g_szBaseStrings);
|
|
|
|
const DWORD g_dwBaseRequiredTypes[] =
|
|
{
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
DPNA_DATATYPE_GUID,
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
DPNA_DATATYPE_GUID,
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
DPNA_DATATYPE_STRING,
|
|
DPNA_DATATYPE_DWORD,
|
|
#ifndef DPNBUILD_NOLOBBY
|
|
DPNA_DATATYPE_GUID,
|
|
DPNA_DATATYPE_GUID,
|
|
#endif // ! DPNBUILD_NOLOBBY
|
|
#ifndef DPNBUILD_NOSERIALSP
|
|
DPNA_DATATYPE_DWORD,
|
|
DPNA_DATATYPE_STRING,
|
|
DPNA_DATATYPE_STRING,
|
|
DPNA_DATATYPE_STRING,
|
|
DPNA_DATATYPE_STRING
|
|
#endif // !DPNBUILD_NOSERIALSP
|
|
};
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8A_STRCACHE_Init"
|
|
HRESULT DP8A_STRCACHE_Init()
|
|
{
|
|
HRESULT hr;
|
|
PWSTR pstrTmp;
|
|
DWORD dwIndex;
|
|
|
|
DNASSERT( g_pcstrKeyCache == NULL );
|
|
g_pcstrKeyCache = (CStringCache*) DNMalloc(sizeof(CStringCache));
|
|
if ( g_pcstrKeyCache == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to create addressing string cache!" );
|
|
return DPNERR_OUTOFMEMORY;
|
|
}
|
|
g_pcstrKeyCache->Initialize();
|
|
|
|
for( dwIndex = 0; dwIndex < c_dwNumBaseStrings; dwIndex++ )
|
|
{
|
|
hr = g_pcstrKeyCache->AddString( g_szBaseStrings[dwIndex], &pstrTmp );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error adding base strings" );
|
|
g_pcstrKeyCache->Deinitialize();
|
|
DNFree(g_pcstrKeyCache);
|
|
g_pcstrKeyCache = NULL;
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8A_STRCACHE_Free"
|
|
// Nothing needs to be done.
|
|
void DP8A_STRCACHE_Free()
|
|
{
|
|
if ( g_pcstrKeyCache != NULL )
|
|
{
|
|
g_pcstrKeyCache->Deinitialize();
|
|
DNFree(g_pcstrKeyCache);
|
|
g_pcstrKeyCache = NULL;
|
|
}
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_Element_BlockInit"
|
|
void DP8ADDRESSOBJECT::FPM_Element_BlockInit( void *pvItem, PVOID pvContext )
|
|
{
|
|
memset( pvItem, 0x00, sizeof( DP8ADDRESSELEMENT ) );
|
|
((PDP8ADDRESSELEMENT) pvItem)->dwSignature = DPASIGNATURE_ELEMENT;
|
|
|
|
((PDP8ADDRESSELEMENT) pvItem)->blAddressElements.Initialize();
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_Element_BlockRelease"
|
|
void DP8ADDRESSOBJECT::FPM_Element_BlockRelease( void *pvItem )
|
|
{
|
|
((PDP8ADDRESSELEMENT) pvItem)->dwSignature = DPASIGNATURE_ELEMENT_FREE;
|
|
|
|
DNASSERT(((PDP8ADDRESSELEMENT) pvItem)->blAddressElements.IsEmpty());
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_BlockCreate"
|
|
BOOL DP8ADDRESSOBJECT::FPM_BlockCreate( void *pvItem, PVOID pvContext )
|
|
{
|
|
return DNInitializeCriticalSection( &((PDP8ADDRESSOBJECT) pvItem)->m_csAddressLock );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_BlockInit"
|
|
void DP8ADDRESSOBJECT::FPM_BlockInit( void *pvItem, PVOID pvContext )
|
|
{
|
|
((PDP8ADDRESSOBJECT) pvItem)->m_dwSignature = DPASIGNATURE_ADDRESS;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_BlockRelease"
|
|
void DP8ADDRESSOBJECT::FPM_BlockRelease( void *pvItem )
|
|
{
|
|
((PDP8ADDRESSOBJECT) pvItem)->m_dwSignature = DPASIGNATURE_ADDRESS_FREE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FPM_BlockDestroy"
|
|
void DP8ADDRESSOBJECT::FPM_BlockDestroy( void *pvItem )
|
|
{
|
|
DNDeleteCriticalSection( &((PDP8ADDRESSOBJECT) pvItem)->m_csAddressLock );
|
|
}
|
|
|
|
// InternalGetElement
|
|
//
|
|
// This function does the lookup for an element by index.
|
|
//
|
|
// Requires the object lock.
|
|
//
|
|
// Does not do parameter validation.
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::InternalGetElement"
|
|
HRESULT DP8ADDRESSOBJECT::InternalGetElement( const DWORD dwIndex, PDP8ADDRESSELEMENT *ppaElement )
|
|
{
|
|
CBilink *pblSearch;
|
|
|
|
if( dwIndex >= m_dwElements )
|
|
return DPNERR_DOESNOTEXIST;
|
|
|
|
pblSearch = m_blAddressElements.GetNext();
|
|
|
|
for( DWORD dwSearchIndex = 0; dwSearchIndex < dwIndex; dwSearchIndex++ )
|
|
{
|
|
pblSearch = pblSearch->GetNext();
|
|
}
|
|
|
|
*ppaElement = CONTAINING_OBJECT(pblSearch, DP8ADDRESSELEMENT, blAddressElements);
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
// InternalGetElement
|
|
//
|
|
// This function does the lookup for an element by name.
|
|
//
|
|
// Requires the object lock.
|
|
//
|
|
// Does not do parameter validation.
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::InternalGetElement"
|
|
HRESULT DP8ADDRESSOBJECT::InternalGetElement( const WCHAR * const pszTag, PDP8ADDRESSELEMENT *ppaElement )
|
|
{
|
|
CBilink *pblSearch;
|
|
PDP8ADDRESSELEMENT paddElement;
|
|
|
|
pblSearch = m_blAddressElements.GetNext();
|
|
|
|
while( pblSearch != &m_blAddressElements )
|
|
{
|
|
paddElement = CONTAINING_OBJECT(pblSearch, DP8ADDRESSELEMENT, blAddressElements);
|
|
|
|
if( _wcsicmp( pszTag, paddElement->pszTag ) == 0 )
|
|
{
|
|
*ppaElement = paddElement;
|
|
return DPN_OK;
|
|
}
|
|
|
|
pblSearch = pblSearch->GetNext();
|
|
}
|
|
|
|
return DPNERR_DOESNOTEXIST;
|
|
}
|
|
|
|
// GetElement
|
|
//
|
|
// Implements retrieval of element by name
|
|
//
|
|
// Parameter validation must be performed BEFORE calling this function.
|
|
//
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetElement"
|
|
HRESULT DP8ADDRESSOBJECT::GetElement( const WCHAR * const pszTag, void * pvDataBuffer, PDWORD pdwDataSize, PDWORD pdwDataType )
|
|
{
|
|
PDP8ADDRESSELEMENT paddElement = NULL;
|
|
HRESULT hr;
|
|
|
|
ENTERLOCK();
|
|
|
|
hr = InternalGetElement( pszTag, &paddElement );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 1, "Unable to find specified element hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
DNASSERT( paddElement != NULL );
|
|
|
|
*pdwDataType = paddElement->dwType;
|
|
|
|
if( *pdwDataSize < paddElement->dwDataSize ||
|
|
pvDataBuffer == NULL )
|
|
{
|
|
*pdwDataSize = paddElement->dwDataSize;
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Specified buffers were too small hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return DPNERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
*pdwDataSize = paddElement->dwDataSize;
|
|
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
memcpy( pvDataBuffer, paddElement->uData.pvData, paddElement->dwDataSize );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
memcpy( pvDataBuffer, &paddElement->uData, paddElement->dwDataSize );
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetElementType"
|
|
HRESULT DP8ADDRESSOBJECT::GetElementType( const WCHAR * pszTag, PDWORD pdwType )
|
|
{
|
|
PDP8ADDRESSELEMENT paddElement = NULL;
|
|
HRESULT hr;
|
|
|
|
ENTERLOCK();
|
|
|
|
hr = InternalGetElement( pszTag, &paddElement );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Unable to find specified element hr=0x%x" );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
*pdwType = paddElement->dwType;
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetElement"
|
|
HRESULT DP8ADDRESSOBJECT::GetElement( const DWORD dwIndex, WCHAR * pszTag, PDWORD pdwTagSize, void * pvDataBuffer, PDWORD pdwDataSize, PDWORD pdwDataType )
|
|
{
|
|
PDP8ADDRESSELEMENT paddElement = NULL;
|
|
HRESULT hr;
|
|
|
|
if( pdwTagSize == NULL || pdwDataSize == NULL || pdwDataType == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid Poiinter" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
hr = InternalGetElement( dwIndex, &paddElement );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Unable to find specified element hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
DNASSERT( paddElement != NULL );
|
|
|
|
*pdwDataType = paddElement->dwType;
|
|
|
|
if( *pdwTagSize < (wcslen( paddElement->pszTag )+1) ||
|
|
*pdwDataSize < paddElement->dwDataSize ||
|
|
pszTag == NULL ||
|
|
pvDataBuffer == NULL )
|
|
{
|
|
*pdwTagSize = paddElement->dwTagSize;
|
|
*pdwDataSize = paddElement->dwDataSize;
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Specified buffers were too small hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return DPNERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
*pdwTagSize = paddElement->dwTagSize;
|
|
*pdwDataSize = paddElement->dwDataSize;
|
|
|
|
wcscpy( pszTag, paddElement->pszTag );
|
|
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
memcpy( pvDataBuffer, paddElement->uData.pvData, paddElement->dwDataSize );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
memcpy( pvDataBuffer, &paddElement->uData, paddElement->dwDataSize );
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetElement"
|
|
HRESULT DP8ADDRESSOBJECT::SetElement( const WCHAR * const pszTag, const void * const pvData, const DWORD dwDataSize, const DWORD dwDataType )
|
|
{
|
|
PDP8ADDRESSELEMENT paddElement = NULL;
|
|
HRESULT hr = DPN_OK;
|
|
BOOL fReplace = FALSE;
|
|
|
|
#ifdef DBG
|
|
DNASSERT(pvData != NULL);
|
|
switch( dwDataType )
|
|
{
|
|
case DPNA_DATATYPE_DWORD:
|
|
{
|
|
DNASSERT(dwDataSize == sizeof(DWORD));
|
|
break;
|
|
}
|
|
|
|
case DPNA_DATATYPE_GUID:
|
|
{
|
|
DNASSERT(dwDataSize == sizeof(GUID));
|
|
break;
|
|
}
|
|
|
|
case DPNA_DATATYPE_STRING:
|
|
case DPNA_DATATYPE_BINARY:
|
|
{
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid data type %u!", dwDataType);
|
|
DNASSERT(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
#endif // DBG
|
|
|
|
|
|
ENTERLOCK();
|
|
|
|
// We need to treat provider key differently, it can also take one of the provider
|
|
// shortcut values.
|
|
// For builds with a fixed SP, we don't even care what the value is.
|
|
if( _wcsicmp( DPNA_KEY_PROVIDER, pszTag ) == 0 )
|
|
{
|
|
#ifdef DPNBUILD_ONLYONESP
|
|
DPFX(DPFPREP, 3, "Ignoring provider key.");
|
|
goto APPEND_SUCCESS;
|
|
#else // ! DPNBUILD_ONLYONESP
|
|
// If it's a GUID we're golden, otherwise..
|
|
if( dwDataType != DPNA_DATATYPE_GUID )
|
|
{
|
|
if( dwDataType == DPNA_DATATYPE_STRING )
|
|
{
|
|
if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_TCPIPPROVIDER ) == 0 )
|
|
{
|
|
hr = SetSP( &CLSID_DP8SP_TCPIP );
|
|
}
|
|
#ifndef DPNBUILD_NOIPX
|
|
else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_IPXPROVIDER ) == 0 )
|
|
{
|
|
hr= SetSP( &CLSID_DP8SP_IPX );
|
|
}
|
|
#endif // ! DPNBUILD_NOIPX
|
|
#ifndef DPNBUILD_NOSERIALSP
|
|
else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_MODEMPROVIDER ) == 0 )
|
|
{
|
|
hr = SetSP( &CLSID_DP8SP_MODEM );
|
|
}
|
|
else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_SERIALPROVIDER ) == 0 )
|
|
{
|
|
hr = SetSP( &CLSID_DP8SP_SERIAL );
|
|
}
|
|
#endif // ! DPNBUILD_NOSERIALSP
|
|
else
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Provider must be specified as a GUID or a valid shortcut string" );
|
|
hr = DPNERR_INVALIDPARAM;
|
|
goto APPEND_ERROR;
|
|
}
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Failed setting provider with shortcut hr=0x%x", hr );
|
|
goto APPEND_ERROR;
|
|
}
|
|
|
|
goto APPEND_SUCCESS;
|
|
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Specified values is not a supported datatype for the given key" );
|
|
hr = DPNERR_INVALIDPARAM;
|
|
goto APPEND_ERROR;
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
}
|
|
else
|
|
{
|
|
// Ensure that datatype is correct in case the key is a reserved key
|
|
for( DWORD dwIndex = 0; dwIndex < c_dwNumBaseStrings; dwIndex++ )
|
|
{
|
|
if( _wcsicmp( g_szBaseStrings[dwIndex], pszTag ) == 0 )
|
|
{
|
|
if( dwDataType != g_dwBaseRequiredTypes[dwIndex] )
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Specified key is reserved and specified datatype is not correct for key" );
|
|
hr = DPNERR_INVALIDPARAM;
|
|
goto APPEND_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = InternalGetElement( pszTag, &paddElement );
|
|
|
|
// If the element is not already in the address we need to add an element
|
|
if( FAILED( hr ) )
|
|
{
|
|
paddElement = (PDP8ADDRESSELEMENT) fpmAddressElements.Get();
|
|
|
|
if( paddElement == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error getting new element" );
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto APPEND_ERROR;
|
|
}
|
|
|
|
hr = g_pcstrKeyCache->AddString( pszTag, &paddElement->pszTag );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Unable to cache tag element hr=0x%x" );
|
|
goto APPEND_ERROR;
|
|
}
|
|
|
|
// Set flag to 0
|
|
paddElement->dwFlags = 0;
|
|
}
|
|
// The element is already there. Fill in the data.
|
|
else
|
|
{
|
|
DNASSERT( paddElement != NULL );
|
|
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
DNASSERT( dwDataSize <= sizeof(paddElement->uData) );
|
|
// If the one we're replacing was on the heap AND
|
|
// The new one doesn't need the heap or is a larger size..
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP &&
|
|
(dwDataSize <= sizeof(paddElement->uData) || dwDataSize > paddElement->dwDataSize) )
|
|
{
|
|
DNFree(paddElement->uData.pvData);
|
|
paddElement->uData.pvData = NULL;
|
|
paddElement->dwDataSize = 0;
|
|
}
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
|
|
// Reduce the object's string size so object string size will be correct
|
|
m_dwStringSize -= paddElement->dwStringSize;
|
|
fReplace = TRUE;
|
|
}
|
|
|
|
paddElement->dwTagSize = wcslen( pszTag )+1;
|
|
|
|
// Can fit in the internal buffer
|
|
if( dwDataSize <= sizeof( paddElement->uData ) )
|
|
{
|
|
memcpy( &paddElement->uData, pvData, dwDataSize );
|
|
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
// Turn off heap flag in this case
|
|
paddElement->dwFlags &= ~(DP8ADDRESS_ELEMENT_HEAP);
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
}
|
|
else
|
|
{
|
|
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
DPFX(DPFPREP, 0, "Item is too large (%u > %u bytes)!",
|
|
dwDataSize, sizeof( paddElement->uData ) );
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto APPEND_ERROR;
|
|
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( !fReplace || !(paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP) ||
|
|
paddElement->dwDataSize < dwDataSize )
|
|
{
|
|
paddElement->uData.pvData = DNMalloc(dwDataSize);
|
|
|
|
if( paddElement->uData.pvData == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error allocating memory" );
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
goto APPEND_ERROR;
|
|
}
|
|
}
|
|
|
|
memcpy( paddElement->uData.pvData, pvData, dwDataSize );
|
|
|
|
paddElement->dwFlags |= DP8ADDRESS_ELEMENT_HEAP;
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
}
|
|
|
|
paddElement->dwType = dwDataType;
|
|
paddElement->dwDataSize = dwDataSize;
|
|
paddElement->dwStringSize = 0;
|
|
|
|
hr = CalcComponentStringSize( paddElement, &paddElement->dwStringSize );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to determine string length hr=0x%x", hr );
|
|
goto APPEND_ERROR;
|
|
}
|
|
|
|
m_dwStringSize += paddElement->dwStringSize;
|
|
|
|
// Create shortcuts if appropriate
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
if( _wcsicmp( DPNA_KEY_PROVIDER, paddElement->pszTag ) == 0 )
|
|
{
|
|
m_pSP = paddElement;
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
{
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
if( _wcsicmp( DPNA_KEY_DEVICE, paddElement->pszTag ) == 0 )
|
|
{
|
|
m_pAdapter = paddElement;
|
|
}
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
}
|
|
|
|
if( !fReplace )
|
|
{
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
// We are adding the SP
|
|
if( m_pSP == paddElement )
|
|
{
|
|
paddElement->blAddressElements.InsertAfter( &m_blAddressElements );
|
|
}
|
|
// We are adding the adapter
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
{
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
if( m_pAdapter == paddElement )
|
|
{
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
if( m_pSP != NULL )
|
|
{
|
|
paddElement->blAddressElements.InsertAfter( &m_pSP->blAddressElements);
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
{
|
|
paddElement->blAddressElements.InsertAfter( &m_blAddressElements);
|
|
}
|
|
}
|
|
// Tack it onto the end
|
|
else
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
{
|
|
paddElement->blAddressElements.InsertBefore( &m_blAddressElements );
|
|
}
|
|
}
|
|
|
|
// Add one char length for seperator w/previous element
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
if( m_dwElements > 0 )
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
{
|
|
m_dwStringSize ++;
|
|
}
|
|
|
|
m_dwElements++;
|
|
|
|
}
|
|
|
|
APPEND_SUCCESS:
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
|
|
APPEND_ERROR:
|
|
|
|
if( paddElement != NULL )
|
|
{
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
if( paddElement->uData.pvData )
|
|
{
|
|
DNFree(paddElement->uData.pvData);
|
|
paddElement->uData.pvData = NULL;
|
|
}
|
|
}
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
|
|
fpmAddressElements.Release( paddElement );
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::Init"
|
|
HRESULT DP8ADDRESSOBJECT::Init( )
|
|
{
|
|
ENTERLOCK();
|
|
|
|
m_dwElements = 0;
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
m_pSP = NULL;
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
m_pAdapter = NULL;
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
m_pvUserData = NULL;
|
|
m_dwUserDataSize = 0;
|
|
#ifdef DPNBUILD_ONLYONESP
|
|
m_dwStringSize = DNURL_LENGTH_HEADER + DNURL_LENGTH_BUILTINPROVIDER;
|
|
#else // ! DPNBUILD_ONLYONESP
|
|
m_dwStringSize = DNURL_LENGTH_HEADER;
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
m_dwUserDataStringSize = 0;
|
|
m_blAddressElements.Initialize();
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::Clear"
|
|
HRESULT DP8ADDRESSOBJECT::Clear( )
|
|
{
|
|
CBilink *pbl;
|
|
PDP8ADDRESSELEMENT paddElement;
|
|
|
|
ENTERLOCK();
|
|
|
|
pbl = m_blAddressElements.GetNext();
|
|
|
|
// Destroy Address Members address members
|
|
while( !m_blAddressElements.IsEmpty() )
|
|
{
|
|
paddElement = CONTAINING_OBJECT(m_blAddressElements.GetNext(), DP8ADDRESSELEMENT, blAddressElements);
|
|
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
DNFree(paddElement->uData.pvData);
|
|
paddElement->uData.pvData = NULL;
|
|
}
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
|
|
pbl->RemoveFromList();
|
|
|
|
fpmAddressElements.Release( paddElement );
|
|
|
|
pbl = m_blAddressElements.GetNext();
|
|
}
|
|
|
|
if( m_pvUserData != NULL )
|
|
{
|
|
DNFree(m_pvUserData);
|
|
m_pvUserData = NULL;
|
|
m_dwUserDataSize = 0;
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
Init( );
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::Copy"
|
|
HRESULT DP8ADDRESSOBJECT::Copy( DP8ADDRESSOBJECT * const pAddressSource )
|
|
{
|
|
HRESULT hResultCode;
|
|
CBilink *pbl;
|
|
PDP8ADDRESSELEMENT paddElement;
|
|
|
|
pAddressSource->ENTERLOCK();
|
|
|
|
pbl = pAddressSource->m_blAddressElements.GetNext();
|
|
|
|
while( pbl != &pAddressSource->m_blAddressElements )
|
|
{
|
|
paddElement = CONTAINING_OBJECT(pbl, DP8ADDRESSELEMENT, blAddressElements);
|
|
|
|
// This takes the lock internally.
|
|
hResultCode = SetElement(paddElement->pszTag,
|
|
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
&paddElement->uData,
|
|
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
(( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP ) ? paddElement->uData.pvData : &paddElement->uData),
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
paddElement->dwDataSize,
|
|
paddElement->dwType);
|
|
if (hResultCode != DPN_OK)
|
|
{
|
|
pAddressSource->LEAVELOCK();
|
|
DPFX(DPFPREP, 0, "Couldn't set element!");
|
|
return hResultCode;
|
|
}
|
|
|
|
pbl = pbl->GetNext();
|
|
}
|
|
|
|
// This takes the lock internally.
|
|
hResultCode = SetUserData(pAddressSource->m_pvUserData, pAddressSource->m_dwUserDataSize);
|
|
if (hResultCode != DPN_OK)
|
|
{
|
|
pAddressSource->LEAVELOCK();
|
|
DPFX(DPFPREP, 0, "Couldn't set element!");
|
|
return hResultCode;
|
|
}
|
|
|
|
pAddressSource->LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
|
|
#ifndef DPNBUILD_ONLYONESP
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetSP"
|
|
HRESULT DP8ADDRESSOBJECT::GetSP( GUID * pGuid )
|
|
{
|
|
if( pGuid == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid pointer" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
if( m_pSP == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "No SP has been specified" );
|
|
LEAVELOCK();
|
|
return DPNERR_DOESNOTEXIST;
|
|
}
|
|
|
|
if( m_pSP->dwType != DPNA_DATATYPE_GUID )
|
|
{
|
|
DPFX(DPFPREP, 0, "SP was specified, but is not a GUID" );
|
|
LEAVELOCK();
|
|
return DPNERR_INVALIDPARAM;
|
|
}
|
|
|
|
memcpy( pGuid, &m_pSP->uData.guidData, sizeof( GUID ) );
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetSP"
|
|
HRESULT DP8ADDRESSOBJECT::SetSP( const GUID* const pGuid )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if( pGuid == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid pointer" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
hr = SetElement( DPNA_KEY_PROVIDER, pGuid, sizeof( GUID ), DPNA_DATATYPE_GUID );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Adding SP element failed hr=0x%x", hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
|
|
#ifndef DPNBUILD_ONLYONEADAPTER
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetDevice"
|
|
HRESULT DP8ADDRESSOBJECT::GetDevice( GUID * pGuid )
|
|
{
|
|
if( pGuid == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid pointer" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
if( m_pAdapter == NULL )
|
|
{
|
|
DPFX(DPFPREP, 1, "No SP has been specified" );
|
|
LEAVELOCK();
|
|
return DPNERR_DOESNOTEXIST;
|
|
}
|
|
|
|
if( m_pAdapter->dwType != DPNA_DATATYPE_GUID )
|
|
{
|
|
DPFX(DPFPREP, 0, "SP was specified, but is not a GUID" );
|
|
LEAVELOCK();
|
|
return DPNERR_INVALIDPARAM;
|
|
}
|
|
|
|
memcpy( pGuid, &m_pAdapter->uData.guidData, sizeof( GUID ) );
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetDevice"
|
|
HRESULT DP8ADDRESSOBJECT::SetDevice( const GUID * const pGuid )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if( pGuid == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid pointer" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
hr = SetElement( DPNA_KEY_DEVICE, pGuid, sizeof( GUID ), DPNA_DATATYPE_GUID );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Adding SP element failed hr=0x%x", hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // ! DPNBUILD_ONLYONEADAPTER
|
|
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetUserData"
|
|
HRESULT DP8ADDRESSOBJECT::SetUserData( const void * const pvData, const DWORD dwDataSize )
|
|
{
|
|
if( pvData == NULL && dwDataSize > 0 )
|
|
{
|
|
DPFX(DPFPREP, 0, "Invalid param" );
|
|
return DPNERR_INVALIDPARAM;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
if( m_dwUserDataSize > 0 )
|
|
{
|
|
// Remove escaped user data
|
|
m_dwStringSize -= m_dwUserDataStringSize;
|
|
}
|
|
|
|
if( dwDataSize == 0 )
|
|
{
|
|
m_dwUserDataSize = 0;
|
|
if( m_pvUserData != NULL )
|
|
DNFree(m_pvUserData);
|
|
m_pvUserData = NULL;
|
|
LEAVELOCK();
|
|
return DPN_OK;
|
|
}
|
|
|
|
PBYTE pNewDataBuffer;
|
|
|
|
if( dwDataSize > m_dwUserDataSize )
|
|
{
|
|
pNewDataBuffer = (BYTE*) DNMalloc(dwDataSize);
|
|
|
|
if( pNewDataBuffer == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error allocating memory" );
|
|
LEAVELOCK();
|
|
return DPNERR_OUTOFMEMORY;
|
|
}
|
|
|
|
if( m_pvUserData != NULL )
|
|
{
|
|
DNFree(m_pvUserData);
|
|
}
|
|
|
|
m_pvUserData = pNewDataBuffer;
|
|
}
|
|
|
|
m_dwUserDataStringSize = CalcExpandedBinarySize( (PBYTE) pvData, dwDataSize );
|
|
|
|
m_dwStringSize += m_dwUserDataStringSize;
|
|
m_dwStringSize += DNURL_LENGTH_USERDATA_SEPERATOR;
|
|
|
|
memcpy( m_pvUserData, pvData, dwDataSize );
|
|
m_dwUserDataSize = dwDataSize;
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::GetUserData"
|
|
HRESULT DP8ADDRESSOBJECT::GetUserData( void * pvDataBuffer, PDWORD pdwDataSize )
|
|
{
|
|
if( pdwDataSize == NULL )
|
|
{
|
|
DPFX(DPFPREP, 0, "Must specify a pointer for the size" );
|
|
return DPNERR_INVALIDPOINTER;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
if( m_dwUserDataSize == 0 )
|
|
{
|
|
LEAVELOCK();
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "No user data was specified for this address" );
|
|
return DPNERR_DOESNOTEXIST;
|
|
}
|
|
|
|
if( *pdwDataSize < m_dwUserDataSize )
|
|
{
|
|
*pdwDataSize = m_dwUserDataSize;
|
|
LEAVELOCK();
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
|
|
return DPNERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
memcpy( pvDataBuffer, m_pvUserData, m_dwUserDataSize );
|
|
|
|
LEAVELOCK();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::Cleanup"
|
|
HRESULT DP8ADDRESSOBJECT::Cleanup()
|
|
{
|
|
Clear();
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::CalcExpandedBinarySize"
|
|
DWORD DP8ADDRESSOBJECT::CalcExpandedBinarySize( PBYTE pbData, DWORD dwDataSize )
|
|
{
|
|
PBYTE pbCurrentLocation = pbData;
|
|
DWORD dwCount = 0;
|
|
|
|
|
|
for( DWORD dwIndex = 0; dwIndex < dwDataSize; dwIndex++ )
|
|
{
|
|
if( IsEscapeChar( (WCHAR) *pbCurrentLocation ) )
|
|
{
|
|
if( ((WCHAR) *pbCurrentLocation) == DPNA_ESCAPECHAR )
|
|
dwCount += 2;
|
|
else
|
|
dwCount+=3;
|
|
}
|
|
else
|
|
{
|
|
dwCount++;
|
|
}
|
|
|
|
pbCurrentLocation++;
|
|
}
|
|
|
|
return dwCount;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::CalcExpandedStringSize"
|
|
DWORD DP8ADDRESSOBJECT::CalcExpandedStringSize( WCHAR *szString )
|
|
{
|
|
WCHAR *szCurrentLocation = szString;
|
|
DWORD dwCount = 0;
|
|
|
|
while( *szCurrentLocation )
|
|
{
|
|
if( IsEscapeChar( *szCurrentLocation ) )
|
|
{
|
|
if( *szCurrentLocation == DPNA_ESCAPECHAR )
|
|
dwCount += 2;
|
|
else
|
|
dwCount+=3;
|
|
}
|
|
else
|
|
{
|
|
dwCount++;
|
|
}
|
|
|
|
szCurrentLocation++;
|
|
}
|
|
|
|
return dwCount;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::CalcComponentStringSize"
|
|
HRESULT DP8ADDRESSOBJECT::CalcComponentStringSize( PDP8ADDRESSELEMENT paddElement, PDWORD pdwSize )
|
|
{
|
|
if( paddElement == NULL )
|
|
return DPNERR_INVALIDPOINTER;
|
|
|
|
if( paddElement->dwType == DPNA_DATATYPE_GUID )
|
|
{
|
|
*pdwSize = DNURL_LENGTH_GUID;
|
|
}
|
|
else if( paddElement->dwType == DPNA_DATATYPE_DWORD )
|
|
{
|
|
WCHAR tmpString[DNURL_LENGTH_DWORD+1];
|
|
|
|
swprintf( tmpString, L"%u", paddElement->uData.dwData );
|
|
|
|
*pdwSize = wcslen(tmpString);
|
|
}
|
|
// No WWCHARs need to be escaped
|
|
else if( paddElement->dwType == DPNA_DATATYPE_STRING )
|
|
{
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
*pdwSize = CalcExpandedStringSize( (WCHAR *) paddElement->uData.pvData );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
*pdwSize = CalcExpandedStringSize( paddElement->uData.szData );
|
|
}
|
|
}
|
|
// Every WWCHAR needs to be escaped
|
|
else
|
|
{
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
*pdwSize = CalcExpandedBinarySize( (BYTE *) paddElement->uData.pvData, paddElement->dwDataSize );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
*pdwSize = CalcExpandedBinarySize( (BYTE *) paddElement->uData.szData, paddElement->dwDataSize );
|
|
}
|
|
}
|
|
|
|
// Add on the tag
|
|
*pdwSize += paddElement->dwTagSize-1;
|
|
|
|
// Add on the = and the ;
|
|
(*pdwSize) ++;
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::IsEscapeChar"
|
|
BOOL DP8ADDRESSOBJECT::IsEscapeChar( WCHAR ch )
|
|
{
|
|
if( ch >= L'A' && ch <= L'Z' )
|
|
return FALSE;
|
|
|
|
if( ch >= L'a' && ch <= L'z' )
|
|
return FALSE;
|
|
|
|
if( ch >= L'0' && ch <= L'9' )
|
|
return FALSE;
|
|
|
|
if( ch == L'-' || ch == L'?' || ch == L'.' ||
|
|
ch == L',' || ch == 'L+' || ch == L'_' )
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddString"
|
|
void DP8ADDRESSOBJECT::BuildURL_AddString( WCHAR *szElements, WCHAR *szSource )
|
|
{
|
|
WCHAR *szSourceLoc = szSource;
|
|
WCHAR tmpEscape[4];
|
|
DWORD dwIndex;
|
|
|
|
while( *szSourceLoc )
|
|
{
|
|
if( IsEscapeChar( *szSourceLoc ) )
|
|
{
|
|
if( *szSourceLoc == DPNA_ESCAPECHAR )
|
|
{
|
|
wcscat( szElements, L"%%" );
|
|
}
|
|
else
|
|
{
|
|
swprintf( tmpEscape, L"%%%02.2X", (DWORD) *szSourceLoc );
|
|
wcscat( szElements, tmpEscape );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwIndex = wcslen(szElements);
|
|
szElements[dwIndex] = *szSourceLoc;
|
|
szElements[dwIndex+1] = 0;
|
|
}
|
|
|
|
szSourceLoc++;
|
|
}
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddElements"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURL_AddElements( WCHAR *szElements )
|
|
{
|
|
DP8ADDRESSELEMENT *pCurrentElement;
|
|
CBilink *pblRunner;
|
|
WCHAR tmpString[DNURL_LENGTH_GUID+2];
|
|
#ifdef DPNBUILD_ONLYONESP
|
|
BOOL fFirstElement = FALSE; // built-in provider always comes first
|
|
#else // ! DPNBUILD_ONLYONESP
|
|
BOOL fFirstElement = TRUE;
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
DWORD dwTmpLength;
|
|
|
|
pblRunner = m_blAddressElements.GetNext();
|
|
|
|
while( pblRunner != &m_blAddressElements )
|
|
{
|
|
pCurrentElement = CONTAINING_OBJECT(pblRunner, DP8ADDRESSELEMENT, blAddressElements);
|
|
|
|
if( !fFirstElement )
|
|
{
|
|
dwTmpLength = wcslen(szElements);
|
|
szElements[dwTmpLength] = DPNA_SEPARATOR_COMPONENT;
|
|
szElements[dwTmpLength+1] = 0;
|
|
}
|
|
|
|
wcscat( szElements, pCurrentElement->pszTag );
|
|
|
|
dwTmpLength = wcslen(szElements);
|
|
szElements[dwTmpLength] = DPNA_SEPARATOR_KEYVALUE;
|
|
szElements[dwTmpLength+1] = 0;
|
|
|
|
if( pCurrentElement->dwType == DPNA_DATATYPE_STRING )
|
|
{
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( pCurrentElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
BuildURL_AddString( szElements, (WCHAR *) pCurrentElement->uData.pvData );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
BuildURL_AddString( szElements, pCurrentElement->uData.szData );
|
|
}
|
|
}
|
|
else if( pCurrentElement->dwType == DPNA_DATATYPE_GUID )
|
|
{
|
|
swprintf( tmpString, L"%%7B%-08.8X-%-04.4X-%-04.4X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X%%7D",
|
|
pCurrentElement->uData.guidData.Data1, pCurrentElement->uData.guidData.Data2, pCurrentElement->uData.guidData.Data3,
|
|
pCurrentElement->uData.guidData.Data4[0], pCurrentElement->uData.guidData.Data4[1],
|
|
pCurrentElement->uData.guidData.Data4[2], pCurrentElement->uData.guidData.Data4[3],
|
|
pCurrentElement->uData.guidData.Data4[4], pCurrentElement->uData.guidData.Data4[5],
|
|
pCurrentElement->uData.guidData.Data4[6], pCurrentElement->uData.guidData.Data4[7] );
|
|
wcscat( szElements, tmpString );
|
|
}
|
|
else if( pCurrentElement->dwType == DPNA_DATATYPE_DWORD )
|
|
{
|
|
swprintf( tmpString, L"%u", pCurrentElement->uData.dwData );
|
|
wcscat( szElements, tmpString );
|
|
}
|
|
// Binary
|
|
else
|
|
{
|
|
#ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
if( pCurrentElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
|
|
{
|
|
BuildURL_AddBinaryData( szElements, (BYTE *) pCurrentElement->uData.pvData , pCurrentElement->dwDataSize );
|
|
}
|
|
else
|
|
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
|
|
{
|
|
BuildURL_AddBinaryData( szElements, ((BYTE *) &pCurrentElement->uData), pCurrentElement->dwDataSize );
|
|
}
|
|
}
|
|
|
|
fFirstElement = FALSE;
|
|
|
|
pblRunner = pblRunner->GetNext();
|
|
}
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddHeader"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURL_AddHeader( WCHAR *szWorking )
|
|
{
|
|
WCHAR *szReturn;
|
|
|
|
#ifdef DPNBUILD_ONLYONESP
|
|
wcscpy( szWorking, DPNA_HEADER DPNA_BUILTINPROVIDER );
|
|
szReturn = szWorking + DNURL_LENGTH_HEADER + DNURL_LENGTH_BUILTINPROVIDER;
|
|
#else // ! DPNBUILD_ONLYONESP
|
|
wcscpy( szWorking, DPNA_HEADER );
|
|
szReturn = szWorking + DNURL_LENGTH_HEADER;
|
|
#endif // ! DPNBUILD_ONLYONESP
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddUserData"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURL_AddUserData(WCHAR * szWorking)
|
|
{
|
|
return BuildURL_AddBinaryData( szWorking, (BYTE *) m_pvUserData, m_dwUserDataSize );
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddBinaryData"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURL_AddBinaryData( WCHAR *szSource, BYTE *bData, DWORD dwDataLen )
|
|
{
|
|
WCHAR *pwszCurrentDest = szSource + wcslen(szSource);
|
|
BYTE *pbCurrentData = bData;
|
|
DWORD dwDataRemaining = dwDataLen;
|
|
|
|
|
|
dwDataRemaining = dwDataLen;
|
|
while ( dwDataRemaining > 0 )
|
|
{
|
|
if( IsEscapeChar( (WCHAR) *pbCurrentData ) )
|
|
{
|
|
if( ((WCHAR) *pbCurrentData) == DPNA_ESCAPECHAR )
|
|
{
|
|
wcscpy(pwszCurrentDest, L"%%");
|
|
pwszCurrentDest += 2;
|
|
}
|
|
else
|
|
{
|
|
pwszCurrentDest += swprintf( pwszCurrentDest, L"%%%02.2X", (DWORD) *pbCurrentData );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pwszCurrentDest = (WCHAR) *pbCurrentData;
|
|
pwszCurrentDest++;
|
|
}
|
|
|
|
pbCurrentData++;
|
|
dwDataRemaining--;
|
|
}
|
|
|
|
// Ensure the string is NULL terminated if we added anything.
|
|
if ( dwDataLen > 0 )
|
|
{
|
|
*pwszCurrentDest = 0;
|
|
}
|
|
|
|
return DPN_OK;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURLA"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURLA( char * szURL, PDWORD pdwRequiredSize )
|
|
{
|
|
HRESULT hr;
|
|
WCHAR wszStackTemp[256];
|
|
WCHAR * pwszTemp;
|
|
DWORD dwSize;
|
|
|
|
|
|
ENTERLOCK();
|
|
|
|
if( *pdwRequiredSize < m_dwStringSize || szURL == NULL )
|
|
{
|
|
*pdwRequiredSize = m_dwStringSize;
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
|
|
LEAVELOCK();
|
|
return DPNERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
// Allocate a buffer if the string is too large to convert in our
|
|
// stack based buffer.
|
|
if ((m_dwStringSize * sizeof(WCHAR)) > sizeof(wszStackTemp))
|
|
{
|
|
pwszTemp = (WCHAR*) DNMalloc(m_dwStringSize * sizeof(WCHAR));
|
|
if (pwszTemp == NULL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Error allocating memory for conversion");
|
|
LEAVELOCK();
|
|
return DPNERR_OUTOFMEMORY;
|
|
}
|
|
dwSize = m_dwStringSize;
|
|
}
|
|
else
|
|
{
|
|
pwszTemp = wszStackTemp;
|
|
dwSize = sizeof(wszStackTemp) / sizeof(WCHAR);
|
|
}
|
|
|
|
// BuildURLW takes the lock again.
|
|
hr = BuildURLW( pwszTemp, &dwSize );
|
|
if( FAILED( hr ) )
|
|
{
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
hr = STR_jkWideToAnsi(szURL, pwszTemp, dwSize);
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error unable to convert element ANSI->Unicode 0x%x", hr );
|
|
hr = DPNERR_CONVERSION;
|
|
}
|
|
else
|
|
{
|
|
*pdwRequiredSize = dwSize;
|
|
}
|
|
|
|
if (pwszTemp != wszStackTemp)
|
|
{
|
|
DNFree(pwszTemp);
|
|
pwszTemp = NULL;
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURLW"
|
|
HRESULT DP8ADDRESSOBJECT::BuildURLW( WCHAR * szURL, PDWORD pdwRequiredSize )
|
|
{
|
|
HRESULT hr;
|
|
|
|
ENTERLOCK();
|
|
|
|
if( *pdwRequiredSize < m_dwStringSize || szURL == NULL )
|
|
{
|
|
*pdwRequiredSize = m_dwStringSize;
|
|
DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
|
|
LEAVELOCK();
|
|
return DPNERR_BUFFERTOOSMALL;
|
|
}
|
|
|
|
hr = BuildURL_AddHeader( szURL );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error adding header hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
hr = BuildURL_AddElements( szURL );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error adding elements hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
hr = BuildURL_AddUserData( szURL );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error adding user data hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
*pdwRequiredSize = m_dwStringSize;
|
|
|
|
return DPN_OK;
|
|
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetURL"
|
|
HRESULT DP8ADDRESSOBJECT::SetURL( WCHAR * szURL )
|
|
{
|
|
HRESULT hr;
|
|
|
|
DP8ADDRESSPARSE dp8aParser;
|
|
|
|
hr = Clear();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Unable to clear existing address hr=0x%x", hr );
|
|
return hr;
|
|
}
|
|
|
|
ENTERLOCK();
|
|
|
|
hr = dp8aParser.ParseURL(this, szURL);
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, DP8A_ERRORLEVEL, "Error parsing the URL hr=0x%x", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
#ifndef DPNBUILD_NOLEGACYDP
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DP8ADDRESSOBJECT::SetDirectPlay4Address"
|
|
HRESULT DP8ADDRESSOBJECT::SetDirectPlay4Address( void * pvDataBuffer, const DWORD dwDataSize )
|
|
{
|
|
PBYTE pbCurrentLocation;
|
|
PDPADDRESS pdpAddressChunk;
|
|
LONG lRemaining;
|
|
HRESULT hr = DPN_OK;
|
|
DWORD dwCurrentChunkSize;
|
|
DWORD dwNumElementsParsed = 0;
|
|
|
|
ENTERLOCK();
|
|
|
|
hr = Clear();
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failed to clear old address data hr=[0x%lx]", hr );
|
|
LEAVELOCK();
|
|
return hr;
|
|
}
|
|
|
|
pbCurrentLocation = (PBYTE) pvDataBuffer;
|
|
lRemaining = dwDataSize;
|
|
|
|
while( lRemaining > 0 )
|
|
{
|
|
pdpAddressChunk = (PDPADDRESS) pbCurrentLocation;
|
|
|
|
if( sizeof( DPADDRESS ) > lRemaining )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error parsing address, unexpected end of address" );
|
|
LEAVELOCK();
|
|
return DPNERR_INVALIDADDRESSFORMAT;
|
|
}
|
|
|
|
dwCurrentChunkSize = sizeof( DPADDRESS ) + pdpAddressChunk->dwDataSize;
|
|
|
|
if( ((LONG) dwCurrentChunkSize) > lRemaining )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error parsing address, unexpected end during data" );
|
|
LEAVELOCK();
|
|
return DPNERR_INVALIDADDRESSFORMAT;
|
|
}
|
|
|
|
hr = AddDP4Element( pdpAddressChunk, this );
|
|
|
|
if( FAILED( hr ) )
|
|
{
|
|
DPFX(DPFPREP, 0, "Error adding next element" );
|
|
break;
|
|
}
|
|
|
|
lRemaining -= dwCurrentChunkSize;
|
|
|
|
pbCurrentLocation += dwCurrentChunkSize;
|
|
}
|
|
|
|
LEAVELOCK();
|
|
|
|
return hr;
|
|
}
|
|
|
|
#endif // ! DPNBUILD_NOLEGACYDP
|