Leaked source code of windows server 2003
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

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: addtcp.cpp
  6. * Content: DirectPlay8Address core implementation file
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 02/04/2000 rmt Created
  12. * 02/10/2000 rmt Updated to use DPNA_ defines instead of URL_
  13. * 02/12/2000 rmt Split Get into GetByName and GetByIndex
  14. * 02/17/2000 rmt Parameter validation work
  15. * 02/18/2000 rmt Added type validation to all pre-defined elements
  16. * 02/21/2000 rmt Updated to make core Unicode and remove ANSI calls
  17. * 02/23/2000 rmt Fixed length calculations in GetURL
  18. * rmt Buffer too small error debug messages -> Warning level
  19. * 03/21/2000 rmt Renamed all DirectPlayAddress8's to DirectPlay8Addresses
  20. * Added support for the new ANSI type
  21. * 05/04/00 mjn delete temp var at end of SetElement()
  22. * 05/05/00 mjn Better error cleanup in SetElement()
  23. * 06/06/00 rmt Bug #36455 failure when calling with ANSI string shortcut for SP
  24. * 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
  25. * 06/21/2000 rmt Bug #37392 - Leak if replacing allocated element with new item same size as GUID
  26. * 06/27/2000 rmt Bug #37630 - Service provider shortcuts / element names were case sensitive
  27. * 07/06/2000 rmt Bug #38714 - ADDRESSING: GetURL doesn't return the # of chars written
  28. * 07/09/2000 rmt Added signature bytes to start of address objects
  29. * 07/12/2000 rmt Fixed some critical section related bugs:
  30. * - Added leave in an error path where it wasn't being called
  31. * - Moved critical section init/delete to constructor / destructor
  32. * 07/13/2000 rmt Bug #39274 - INT 3 during voice run
  33. * - Fixed point where a critical section was being re-initialized
  34. * rmt Added critical sections to protect FPMs
  35. * 07/21/2000 rmt Fixed bug w/directplay 4 address parsing
  36. * 07/31/2000 rmt Bug #41125 - Addressing() GetUserData when none available should return doesnotexist
  37. * 08/03/2000 rmt Missing LEAVELOCK() was causing lockups.
  38. * 11/29/2000 aarono B#226079 prefix, fix memory leak in failure path of SetElement
  39. *@@END_MSINTERNAL
  40. *
  41. ***************************************************************************/
  42. #include "dnaddri.h"
  43. const WCHAR * g_szBaseStrings[] =
  44. {
  45. #ifndef DPNBUILD_ONLYONESP
  46. DPNA_KEY_PROVIDER,
  47. #endif // ! DPNBUILD_ONLYONESP
  48. #ifndef DPNBUILD_ONLYONEADAPTER
  49. DPNA_KEY_DEVICE,
  50. #endif // ! DPNBUILD_ONLYONEADAPTER
  51. DPNA_KEY_HOSTNAME,
  52. DPNA_KEY_PORT,
  53. #ifndef DPNBUILD_NOLOBBY
  54. DPNA_KEY_APPLICATION_INSTANCE,
  55. DPNA_KEY_PROGRAM,
  56. #endif // ! DPNBUILD_NOLOBBY
  57. #ifndef DPNBUILD_NOSERIALSP
  58. DPNA_KEY_BAUD,
  59. DPNA_KEY_FLOWCONTROL,
  60. DPNA_KEY_PARITY,
  61. DPNA_KEY_PHONENUMBER,
  62. DPNA_KEY_STOPBITS
  63. #endif // !DPNBUILD_NOSERIALSP
  64. };
  65. const DWORD c_dwNumBaseStrings = LENGTHOF(g_szBaseStrings);
  66. const DWORD g_dwBaseRequiredTypes[] =
  67. {
  68. #ifndef DPNBUILD_ONLYONESP
  69. DPNA_DATATYPE_GUID,
  70. #endif // ! DPNBUILD_ONLYONESP
  71. #ifndef DPNBUILD_ONLYONEADAPTER
  72. DPNA_DATATYPE_GUID,
  73. #endif // ! DPNBUILD_ONLYONEADAPTER
  74. DPNA_DATATYPE_STRING,
  75. DPNA_DATATYPE_DWORD,
  76. #ifndef DPNBUILD_NOLOBBY
  77. DPNA_DATATYPE_GUID,
  78. DPNA_DATATYPE_GUID,
  79. #endif // ! DPNBUILD_NOLOBBY
  80. #ifndef DPNBUILD_NOSERIALSP
  81. DPNA_DATATYPE_DWORD,
  82. DPNA_DATATYPE_STRING,
  83. DPNA_DATATYPE_STRING,
  84. DPNA_DATATYPE_STRING,
  85. DPNA_DATATYPE_STRING
  86. #endif // !DPNBUILD_NOSERIALSP
  87. };
  88. #undef DPF_MODNAME
  89. #define DPF_MODNAME "DP8A_STRCACHE_Init"
  90. HRESULT DP8A_STRCACHE_Init()
  91. {
  92. HRESULT hr;
  93. PWSTR pstrTmp;
  94. DWORD dwIndex;
  95. DNASSERT( g_pcstrKeyCache == NULL );
  96. g_pcstrKeyCache = (CStringCache*) DNMalloc(sizeof(CStringCache));
  97. if ( g_pcstrKeyCache == NULL )
  98. {
  99. DPFX(DPFPREP, 0, "Failed to create addressing string cache!" );
  100. return DPNERR_OUTOFMEMORY;
  101. }
  102. g_pcstrKeyCache->Initialize();
  103. for( dwIndex = 0; dwIndex < c_dwNumBaseStrings; dwIndex++ )
  104. {
  105. hr = g_pcstrKeyCache->AddString( g_szBaseStrings[dwIndex], &pstrTmp );
  106. if( FAILED( hr ) )
  107. {
  108. DPFX(DPFPREP, 0, "Error adding base strings" );
  109. g_pcstrKeyCache->Deinitialize();
  110. DNFree(g_pcstrKeyCache);
  111. g_pcstrKeyCache = NULL;
  112. return hr;
  113. }
  114. }
  115. return DPN_OK;
  116. }
  117. #undef DPF_MODNAME
  118. #define DPF_MODNAME "DP8A_STRCACHE_Free"
  119. // Nothing needs to be done.
  120. void DP8A_STRCACHE_Free()
  121. {
  122. if ( g_pcstrKeyCache != NULL )
  123. {
  124. g_pcstrKeyCache->Deinitialize();
  125. DNFree(g_pcstrKeyCache);
  126. g_pcstrKeyCache = NULL;
  127. }
  128. }
  129. #undef DPF_MODNAME
  130. #define DPF_MODNAME "FPM_Element_BlockInit"
  131. void DP8ADDRESSOBJECT::FPM_Element_BlockInit( void *pvItem, PVOID pvContext )
  132. {
  133. memset( pvItem, 0x00, sizeof( DP8ADDRESSELEMENT ) );
  134. ((PDP8ADDRESSELEMENT) pvItem)->dwSignature = DPASIGNATURE_ELEMENT;
  135. ((PDP8ADDRESSELEMENT) pvItem)->blAddressElements.Initialize();
  136. }
  137. #undef DPF_MODNAME
  138. #define DPF_MODNAME "FPM_Element_BlockRelease"
  139. void DP8ADDRESSOBJECT::FPM_Element_BlockRelease( void *pvItem )
  140. {
  141. ((PDP8ADDRESSELEMENT) pvItem)->dwSignature = DPASIGNATURE_ELEMENT_FREE;
  142. DNASSERT(((PDP8ADDRESSELEMENT) pvItem)->blAddressElements.IsEmpty());
  143. }
  144. #undef DPF_MODNAME
  145. #define DPF_MODNAME "FPM_BlockCreate"
  146. BOOL DP8ADDRESSOBJECT::FPM_BlockCreate( void *pvItem, PVOID pvContext )
  147. {
  148. return DNInitializeCriticalSection( &((PDP8ADDRESSOBJECT) pvItem)->m_csAddressLock );
  149. }
  150. #undef DPF_MODNAME
  151. #define DPF_MODNAME "FPM_BlockInit"
  152. void DP8ADDRESSOBJECT::FPM_BlockInit( void *pvItem, PVOID pvContext )
  153. {
  154. ((PDP8ADDRESSOBJECT) pvItem)->m_dwSignature = DPASIGNATURE_ADDRESS;
  155. }
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "FPM_BlockRelease"
  158. void DP8ADDRESSOBJECT::FPM_BlockRelease( void *pvItem )
  159. {
  160. ((PDP8ADDRESSOBJECT) pvItem)->m_dwSignature = DPASIGNATURE_ADDRESS_FREE;
  161. }
  162. #undef DPF_MODNAME
  163. #define DPF_MODNAME "FPM_BlockDestroy"
  164. void DP8ADDRESSOBJECT::FPM_BlockDestroy( void *pvItem )
  165. {
  166. DNDeleteCriticalSection( &((PDP8ADDRESSOBJECT) pvItem)->m_csAddressLock );
  167. }
  168. // InternalGetElement
  169. //
  170. // This function does the lookup for an element by index.
  171. //
  172. // Requires the object lock.
  173. //
  174. // Does not do parameter validation.
  175. //
  176. #undef DPF_MODNAME
  177. #define DPF_MODNAME "DP8ADDRESSOBJECT::InternalGetElement"
  178. HRESULT DP8ADDRESSOBJECT::InternalGetElement( const DWORD dwIndex, PDP8ADDRESSELEMENT *ppaElement )
  179. {
  180. CBilink *pblSearch;
  181. if( dwIndex >= m_dwElements )
  182. return DPNERR_DOESNOTEXIST;
  183. pblSearch = m_blAddressElements.GetNext();
  184. for( DWORD dwSearchIndex = 0; dwSearchIndex < dwIndex; dwSearchIndex++ )
  185. {
  186. pblSearch = pblSearch->GetNext();
  187. }
  188. *ppaElement = CONTAINING_OBJECT(pblSearch, DP8ADDRESSELEMENT, blAddressElements);
  189. return DPN_OK;
  190. }
  191. // InternalGetElement
  192. //
  193. // This function does the lookup for an element by name.
  194. //
  195. // Requires the object lock.
  196. //
  197. // Does not do parameter validation.
  198. //
  199. #undef DPF_MODNAME
  200. #define DPF_MODNAME "DP8ADDRESSOBJECT::InternalGetElement"
  201. HRESULT DP8ADDRESSOBJECT::InternalGetElement( const WCHAR * const pszTag, PDP8ADDRESSELEMENT *ppaElement )
  202. {
  203. CBilink *pblSearch;
  204. PDP8ADDRESSELEMENT paddElement;
  205. pblSearch = m_blAddressElements.GetNext();
  206. while( pblSearch != &m_blAddressElements )
  207. {
  208. paddElement = CONTAINING_OBJECT(pblSearch, DP8ADDRESSELEMENT, blAddressElements);
  209. if( _wcsicmp( pszTag, paddElement->pszTag ) == 0 )
  210. {
  211. *ppaElement = paddElement;
  212. return DPN_OK;
  213. }
  214. pblSearch = pblSearch->GetNext();
  215. }
  216. return DPNERR_DOESNOTEXIST;
  217. }
  218. // GetElement
  219. //
  220. // Implements retrieval of element by name
  221. //
  222. // Parameter validation must be performed BEFORE calling this function.
  223. //
  224. #undef DPF_MODNAME
  225. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetElement"
  226. HRESULT DP8ADDRESSOBJECT::GetElement( const WCHAR * const pszTag, void * pvDataBuffer, PDWORD pdwDataSize, PDWORD pdwDataType )
  227. {
  228. PDP8ADDRESSELEMENT paddElement = NULL;
  229. HRESULT hr;
  230. ENTERLOCK();
  231. hr = InternalGetElement( pszTag, &paddElement );
  232. if( FAILED( hr ) )
  233. {
  234. DPFX(DPFPREP, 1, "Unable to find specified element hr=0x%x", hr );
  235. LEAVELOCK();
  236. return hr;
  237. }
  238. DNASSERT( paddElement != NULL );
  239. *pdwDataType = paddElement->dwType;
  240. if( *pdwDataSize < paddElement->dwDataSize ||
  241. pvDataBuffer == NULL )
  242. {
  243. *pdwDataSize = paddElement->dwDataSize;
  244. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Specified buffers were too small hr=0x%x", hr );
  245. LEAVELOCK();
  246. return DPNERR_BUFFERTOOSMALL;
  247. }
  248. *pdwDataSize = paddElement->dwDataSize;
  249. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  250. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  251. {
  252. memcpy( pvDataBuffer, paddElement->uData.pvData, paddElement->dwDataSize );
  253. }
  254. else
  255. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  256. {
  257. memcpy( pvDataBuffer, &paddElement->uData, paddElement->dwDataSize );
  258. }
  259. LEAVELOCK();
  260. return DPN_OK;
  261. }
  262. #undef DPF_MODNAME
  263. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetElementType"
  264. HRESULT DP8ADDRESSOBJECT::GetElementType( const WCHAR * pszTag, PDWORD pdwType )
  265. {
  266. PDP8ADDRESSELEMENT paddElement = NULL;
  267. HRESULT hr;
  268. ENTERLOCK();
  269. hr = InternalGetElement( pszTag, &paddElement );
  270. if( FAILED( hr ) )
  271. {
  272. DPFX(DPFPREP, 0, "Unable to find specified element hr=0x%x" );
  273. LEAVELOCK();
  274. return hr;
  275. }
  276. *pdwType = paddElement->dwType;
  277. LEAVELOCK();
  278. return DPN_OK;
  279. }
  280. #undef DPF_MODNAME
  281. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetElement"
  282. HRESULT DP8ADDRESSOBJECT::GetElement( const DWORD dwIndex, WCHAR * pszTag, PDWORD pdwTagSize, void * pvDataBuffer, PDWORD pdwDataSize, PDWORD pdwDataType )
  283. {
  284. PDP8ADDRESSELEMENT paddElement = NULL;
  285. HRESULT hr;
  286. if( pdwTagSize == NULL || pdwDataSize == NULL || pdwDataType == NULL )
  287. {
  288. DPFX(DPFPREP, 0, "Invalid Poiinter" );
  289. return DPNERR_INVALIDPOINTER;
  290. }
  291. ENTERLOCK();
  292. hr = InternalGetElement( dwIndex, &paddElement );
  293. if( FAILED( hr ) )
  294. {
  295. DPFX(DPFPREP, 0, "Unable to find specified element hr=0x%x", hr );
  296. LEAVELOCK();
  297. return hr;
  298. }
  299. DNASSERT( paddElement != NULL );
  300. *pdwDataType = paddElement->dwType;
  301. if( *pdwTagSize < (wcslen( paddElement->pszTag )+1) ||
  302. *pdwDataSize < paddElement->dwDataSize ||
  303. pszTag == NULL ||
  304. pvDataBuffer == NULL )
  305. {
  306. *pdwTagSize = paddElement->dwTagSize;
  307. *pdwDataSize = paddElement->dwDataSize;
  308. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Specified buffers were too small hr=0x%x", hr );
  309. LEAVELOCK();
  310. return DPNERR_BUFFERTOOSMALL;
  311. }
  312. *pdwTagSize = paddElement->dwTagSize;
  313. *pdwDataSize = paddElement->dwDataSize;
  314. wcscpy( pszTag, paddElement->pszTag );
  315. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  316. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  317. {
  318. memcpy( pvDataBuffer, paddElement->uData.pvData, paddElement->dwDataSize );
  319. }
  320. else
  321. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  322. {
  323. memcpy( pvDataBuffer, &paddElement->uData, paddElement->dwDataSize );
  324. }
  325. LEAVELOCK();
  326. return DPN_OK;
  327. }
  328. #undef DPF_MODNAME
  329. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetElement"
  330. HRESULT DP8ADDRESSOBJECT::SetElement( const WCHAR * const pszTag, const void * const pvData, const DWORD dwDataSize, const DWORD dwDataType )
  331. {
  332. PDP8ADDRESSELEMENT paddElement = NULL;
  333. HRESULT hr = DPN_OK;
  334. BOOL fReplace = FALSE;
  335. #ifdef DBG
  336. DNASSERT(pvData != NULL);
  337. switch( dwDataType )
  338. {
  339. case DPNA_DATATYPE_DWORD:
  340. {
  341. DNASSERT(dwDataSize == sizeof(DWORD));
  342. break;
  343. }
  344. case DPNA_DATATYPE_GUID:
  345. {
  346. DNASSERT(dwDataSize == sizeof(GUID));
  347. break;
  348. }
  349. case DPNA_DATATYPE_STRING:
  350. case DPNA_DATATYPE_BINARY:
  351. {
  352. break;
  353. }
  354. default:
  355. {
  356. DPFX(DPFPREP, 0, "Invalid data type %u!", dwDataType);
  357. DNASSERT(FALSE);
  358. break;
  359. }
  360. }
  361. #endif // DBG
  362. ENTERLOCK();
  363. // We need to treat provider key differently, it can also take one of the provider
  364. // shortcut values.
  365. // For builds with a fixed SP, we don't even care what the value is.
  366. if( _wcsicmp( DPNA_KEY_PROVIDER, pszTag ) == 0 )
  367. {
  368. #ifdef DPNBUILD_ONLYONESP
  369. DPFX(DPFPREP, 3, "Ignoring provider key.");
  370. goto APPEND_SUCCESS;
  371. #else // ! DPNBUILD_ONLYONESP
  372. // If it's a GUID we're golden, otherwise..
  373. if( dwDataType != DPNA_DATATYPE_GUID )
  374. {
  375. if( dwDataType == DPNA_DATATYPE_STRING )
  376. {
  377. if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_TCPIPPROVIDER ) == 0 )
  378. {
  379. hr = SetSP( &CLSID_DP8SP_TCPIP );
  380. }
  381. #ifndef DPNBUILD_NOIPX
  382. else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_IPXPROVIDER ) == 0 )
  383. {
  384. hr= SetSP( &CLSID_DP8SP_IPX );
  385. }
  386. #endif // ! DPNBUILD_NOIPX
  387. #ifndef DPNBUILD_NOSERIALSP
  388. else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_MODEMPROVIDER ) == 0 )
  389. {
  390. hr = SetSP( &CLSID_DP8SP_MODEM );
  391. }
  392. else if( _wcsicmp( (const WCHAR * const) pvData, DPNA_VALUE_SERIALPROVIDER ) == 0 )
  393. {
  394. hr = SetSP( &CLSID_DP8SP_SERIAL );
  395. }
  396. #endif // ! DPNBUILD_NOSERIALSP
  397. else
  398. {
  399. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Provider must be specified as a GUID or a valid shortcut string" );
  400. hr = DPNERR_INVALIDPARAM;
  401. goto APPEND_ERROR;
  402. }
  403. if( FAILED( hr ) )
  404. {
  405. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Failed setting provider with shortcut hr=0x%x", hr );
  406. goto APPEND_ERROR;
  407. }
  408. goto APPEND_SUCCESS;
  409. }
  410. else
  411. {
  412. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Specified values is not a supported datatype for the given key" );
  413. hr = DPNERR_INVALIDPARAM;
  414. goto APPEND_ERROR;
  415. }
  416. }
  417. #endif // ! DPNBUILD_ONLYONESP
  418. }
  419. else
  420. {
  421. // Ensure that datatype is correct in case the key is a reserved key
  422. for( DWORD dwIndex = 0; dwIndex < c_dwNumBaseStrings; dwIndex++ )
  423. {
  424. if( _wcsicmp( g_szBaseStrings[dwIndex], pszTag ) == 0 )
  425. {
  426. if( dwDataType != g_dwBaseRequiredTypes[dwIndex] )
  427. {
  428. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Specified key is reserved and specified datatype is not correct for key" );
  429. hr = DPNERR_INVALIDPARAM;
  430. goto APPEND_ERROR;
  431. }
  432. break;
  433. }
  434. }
  435. }
  436. hr = InternalGetElement( pszTag, &paddElement );
  437. // If the element is not already in the address we need to add an element
  438. if( FAILED( hr ) )
  439. {
  440. paddElement = (PDP8ADDRESSELEMENT) fpmAddressElements.Get();
  441. if( paddElement == NULL )
  442. {
  443. DPFX(DPFPREP, 0, "Error getting new element" );
  444. hr = DPNERR_OUTOFMEMORY;
  445. goto APPEND_ERROR;
  446. }
  447. hr = g_pcstrKeyCache->AddString( pszTag, &paddElement->pszTag );
  448. if( FAILED( hr ) )
  449. {
  450. DPFX(DPFPREP, 0, "Unable to cache tag element hr=0x%x" );
  451. goto APPEND_ERROR;
  452. }
  453. // Set flag to 0
  454. paddElement->dwFlags = 0;
  455. }
  456. // The element is already there. Fill in the data.
  457. else
  458. {
  459. DNASSERT( paddElement != NULL );
  460. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  461. DNASSERT( dwDataSize <= sizeof(paddElement->uData) );
  462. // If the one we're replacing was on the heap AND
  463. // The new one doesn't need the heap or is a larger size..
  464. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP &&
  465. (dwDataSize <= sizeof(paddElement->uData) || dwDataSize > paddElement->dwDataSize) )
  466. {
  467. DNFree(paddElement->uData.pvData);
  468. paddElement->uData.pvData = NULL;
  469. paddElement->dwDataSize = 0;
  470. }
  471. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  472. // Reduce the object's string size so object string size will be correct
  473. m_dwStringSize -= paddElement->dwStringSize;
  474. fReplace = TRUE;
  475. }
  476. paddElement->dwTagSize = wcslen( pszTag )+1;
  477. // Can fit in the internal buffer
  478. if( dwDataSize <= sizeof( paddElement->uData ) )
  479. {
  480. memcpy( &paddElement->uData, pvData, dwDataSize );
  481. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  482. // Turn off heap flag in this case
  483. paddElement->dwFlags &= ~(DP8ADDRESS_ELEMENT_HEAP);
  484. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  485. }
  486. else
  487. {
  488. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  489. DPFX(DPFPREP, 0, "Item is too large (%u > %u bytes)!",
  490. dwDataSize, sizeof( paddElement->uData ) );
  491. hr = DPNERR_OUTOFMEMORY;
  492. goto APPEND_ERROR;
  493. #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  494. if( !fReplace || !(paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP) ||
  495. paddElement->dwDataSize < dwDataSize )
  496. {
  497. paddElement->uData.pvData = DNMalloc(dwDataSize);
  498. if( paddElement->uData.pvData == NULL )
  499. {
  500. DPFX(DPFPREP, 0, "Error allocating memory" );
  501. hr = DPNERR_OUTOFMEMORY;
  502. goto APPEND_ERROR;
  503. }
  504. }
  505. memcpy( paddElement->uData.pvData, pvData, dwDataSize );
  506. paddElement->dwFlags |= DP8ADDRESS_ELEMENT_HEAP;
  507. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  508. }
  509. paddElement->dwType = dwDataType;
  510. paddElement->dwDataSize = dwDataSize;
  511. paddElement->dwStringSize = 0;
  512. hr = CalcComponentStringSize( paddElement, &paddElement->dwStringSize );
  513. if( FAILED( hr ) )
  514. {
  515. DPFX(DPFPREP, 0, "Failed to determine string length hr=0x%x", hr );
  516. goto APPEND_ERROR;
  517. }
  518. m_dwStringSize += paddElement->dwStringSize;
  519. // Create shortcuts if appropriate
  520. #ifndef DPNBUILD_ONLYONESP
  521. if( _wcsicmp( DPNA_KEY_PROVIDER, paddElement->pszTag ) == 0 )
  522. {
  523. m_pSP = paddElement;
  524. }
  525. else
  526. #endif // ! DPNBUILD_ONLYONESP
  527. {
  528. #ifndef DPNBUILD_ONLYONEADAPTER
  529. if( _wcsicmp( DPNA_KEY_DEVICE, paddElement->pszTag ) == 0 )
  530. {
  531. m_pAdapter = paddElement;
  532. }
  533. #endif // ! DPNBUILD_ONLYONEADAPTER
  534. }
  535. if( !fReplace )
  536. {
  537. #ifndef DPNBUILD_ONLYONESP
  538. // We are adding the SP
  539. if( m_pSP == paddElement )
  540. {
  541. paddElement->blAddressElements.InsertAfter( &m_blAddressElements );
  542. }
  543. // We are adding the adapter
  544. else
  545. #endif // ! DPNBUILD_ONLYONESP
  546. {
  547. #ifndef DPNBUILD_ONLYONEADAPTER
  548. if( m_pAdapter == paddElement )
  549. {
  550. #ifndef DPNBUILD_ONLYONESP
  551. if( m_pSP != NULL )
  552. {
  553. paddElement->blAddressElements.InsertAfter( &m_pSP->blAddressElements);
  554. }
  555. else
  556. #endif // ! DPNBUILD_ONLYONESP
  557. {
  558. paddElement->blAddressElements.InsertAfter( &m_blAddressElements);
  559. }
  560. }
  561. // Tack it onto the end
  562. else
  563. #endif // ! DPNBUILD_ONLYONEADAPTER
  564. {
  565. paddElement->blAddressElements.InsertBefore( &m_blAddressElements );
  566. }
  567. }
  568. // Add one char length for seperator w/previous element
  569. #ifndef DPNBUILD_ONLYONESP
  570. if( m_dwElements > 0 )
  571. #endif // ! DPNBUILD_ONLYONESP
  572. {
  573. m_dwStringSize ++;
  574. }
  575. m_dwElements++;
  576. }
  577. APPEND_SUCCESS:
  578. LEAVELOCK();
  579. return DPN_OK;
  580. APPEND_ERROR:
  581. if( paddElement != NULL )
  582. {
  583. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  584. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  585. {
  586. if( paddElement->uData.pvData )
  587. {
  588. DNFree(paddElement->uData.pvData);
  589. paddElement->uData.pvData = NULL;
  590. }
  591. }
  592. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  593. fpmAddressElements.Release( paddElement );
  594. }
  595. LEAVELOCK();
  596. return hr;
  597. }
  598. #undef DPF_MODNAME
  599. #define DPF_MODNAME "DP8ADDRESSOBJECT::Init"
  600. HRESULT DP8ADDRESSOBJECT::Init( )
  601. {
  602. ENTERLOCK();
  603. m_dwElements = 0;
  604. #ifndef DPNBUILD_ONLYONESP
  605. m_pSP = NULL;
  606. #endif // ! DPNBUILD_ONLYONESP
  607. #ifndef DPNBUILD_ONLYONEADAPTER
  608. m_pAdapter = NULL;
  609. #endif // ! DPNBUILD_ONLYONEADAPTER
  610. m_pvUserData = NULL;
  611. m_dwUserDataSize = 0;
  612. #ifdef DPNBUILD_ONLYONESP
  613. m_dwStringSize = DNURL_LENGTH_HEADER + DNURL_LENGTH_BUILTINPROVIDER;
  614. #else // ! DPNBUILD_ONLYONESP
  615. m_dwStringSize = DNURL_LENGTH_HEADER;
  616. #endif // ! DPNBUILD_ONLYONESP
  617. m_dwUserDataStringSize = 0;
  618. m_blAddressElements.Initialize();
  619. LEAVELOCK();
  620. return DPN_OK;
  621. }
  622. #undef DPF_MODNAME
  623. #define DPF_MODNAME "DP8ADDRESSOBJECT::Clear"
  624. HRESULT DP8ADDRESSOBJECT::Clear( )
  625. {
  626. CBilink *pbl;
  627. PDP8ADDRESSELEMENT paddElement;
  628. ENTERLOCK();
  629. pbl = m_blAddressElements.GetNext();
  630. // Destroy Address Members address members
  631. while( !m_blAddressElements.IsEmpty() )
  632. {
  633. paddElement = CONTAINING_OBJECT(m_blAddressElements.GetNext(), DP8ADDRESSELEMENT, blAddressElements);
  634. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  635. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  636. {
  637. DNFree(paddElement->uData.pvData);
  638. paddElement->uData.pvData = NULL;
  639. }
  640. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  641. pbl->RemoveFromList();
  642. fpmAddressElements.Release( paddElement );
  643. pbl = m_blAddressElements.GetNext();
  644. }
  645. if( m_pvUserData != NULL )
  646. {
  647. DNFree(m_pvUserData);
  648. m_pvUserData = NULL;
  649. m_dwUserDataSize = 0;
  650. }
  651. LEAVELOCK();
  652. Init( );
  653. return DPN_OK;
  654. }
  655. #undef DPF_MODNAME
  656. #define DPF_MODNAME "DP8ADDRESSOBJECT::Copy"
  657. HRESULT DP8ADDRESSOBJECT::Copy( DP8ADDRESSOBJECT * const pAddressSource )
  658. {
  659. HRESULT hResultCode;
  660. CBilink *pbl;
  661. PDP8ADDRESSELEMENT paddElement;
  662. pAddressSource->ENTERLOCK();
  663. pbl = pAddressSource->m_blAddressElements.GetNext();
  664. while( pbl != &pAddressSource->m_blAddressElements )
  665. {
  666. paddElement = CONTAINING_OBJECT(pbl, DP8ADDRESSELEMENT, blAddressElements);
  667. // This takes the lock internally.
  668. hResultCode = SetElement(paddElement->pszTag,
  669. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  670. &paddElement->uData,
  671. #else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  672. (( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP ) ? paddElement->uData.pvData : &paddElement->uData),
  673. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  674. paddElement->dwDataSize,
  675. paddElement->dwType);
  676. if (hResultCode != DPN_OK)
  677. {
  678. pAddressSource->LEAVELOCK();
  679. DPFX(DPFPREP, 0, "Couldn't set element!");
  680. return hResultCode;
  681. }
  682. pbl = pbl->GetNext();
  683. }
  684. // This takes the lock internally.
  685. hResultCode = SetUserData(pAddressSource->m_pvUserData, pAddressSource->m_dwUserDataSize);
  686. if (hResultCode != DPN_OK)
  687. {
  688. pAddressSource->LEAVELOCK();
  689. DPFX(DPFPREP, 0, "Couldn't set element!");
  690. return hResultCode;
  691. }
  692. pAddressSource->LEAVELOCK();
  693. return DPN_OK;
  694. }
  695. #ifndef DPNBUILD_ONLYONESP
  696. #undef DPF_MODNAME
  697. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetSP"
  698. HRESULT DP8ADDRESSOBJECT::GetSP( GUID * pGuid )
  699. {
  700. if( pGuid == NULL )
  701. {
  702. DPFX(DPFPREP, 0, "Invalid pointer" );
  703. return DPNERR_INVALIDPOINTER;
  704. }
  705. ENTERLOCK();
  706. if( m_pSP == NULL )
  707. {
  708. DPFX(DPFPREP, 0, "No SP has been specified" );
  709. LEAVELOCK();
  710. return DPNERR_DOESNOTEXIST;
  711. }
  712. if( m_pSP->dwType != DPNA_DATATYPE_GUID )
  713. {
  714. DPFX(DPFPREP, 0, "SP was specified, but is not a GUID" );
  715. LEAVELOCK();
  716. return DPNERR_INVALIDPARAM;
  717. }
  718. memcpy( pGuid, &m_pSP->uData.guidData, sizeof( GUID ) );
  719. LEAVELOCK();
  720. return DPN_OK;
  721. }
  722. #undef DPF_MODNAME
  723. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetSP"
  724. HRESULT DP8ADDRESSOBJECT::SetSP( const GUID* const pGuid )
  725. {
  726. HRESULT hr;
  727. if( pGuid == NULL )
  728. {
  729. DPFX(DPFPREP, 0, "Invalid pointer" );
  730. return DPNERR_INVALIDPOINTER;
  731. }
  732. hr = SetElement( DPNA_KEY_PROVIDER, pGuid, sizeof( GUID ), DPNA_DATATYPE_GUID );
  733. if( FAILED( hr ) )
  734. {
  735. DPFX(DPFPREP, 0, "Adding SP element failed hr=0x%x", hr );
  736. }
  737. return hr;
  738. }
  739. #endif // ! DPNBUILD_ONLYONESP
  740. #ifndef DPNBUILD_ONLYONEADAPTER
  741. #undef DPF_MODNAME
  742. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetDevice"
  743. HRESULT DP8ADDRESSOBJECT::GetDevice( GUID * pGuid )
  744. {
  745. if( pGuid == NULL )
  746. {
  747. DPFX(DPFPREP, 0, "Invalid pointer" );
  748. return DPNERR_INVALIDPOINTER;
  749. }
  750. ENTERLOCK();
  751. if( m_pAdapter == NULL )
  752. {
  753. DPFX(DPFPREP, 1, "No SP has been specified" );
  754. LEAVELOCK();
  755. return DPNERR_DOESNOTEXIST;
  756. }
  757. if( m_pAdapter->dwType != DPNA_DATATYPE_GUID )
  758. {
  759. DPFX(DPFPREP, 0, "SP was specified, but is not a GUID" );
  760. LEAVELOCK();
  761. return DPNERR_INVALIDPARAM;
  762. }
  763. memcpy( pGuid, &m_pAdapter->uData.guidData, sizeof( GUID ) );
  764. LEAVELOCK();
  765. return DPN_OK;
  766. }
  767. #undef DPF_MODNAME
  768. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetDevice"
  769. HRESULT DP8ADDRESSOBJECT::SetDevice( const GUID * const pGuid )
  770. {
  771. HRESULT hr;
  772. if( pGuid == NULL )
  773. {
  774. DPFX(DPFPREP, 0, "Invalid pointer" );
  775. return DPNERR_INVALIDPOINTER;
  776. }
  777. hr = SetElement( DPNA_KEY_DEVICE, pGuid, sizeof( GUID ), DPNA_DATATYPE_GUID );
  778. if( FAILED( hr ) )
  779. {
  780. DPFX(DPFPREP, 0, "Adding SP element failed hr=0x%x", hr );
  781. }
  782. return hr;
  783. }
  784. #endif // ! DPNBUILD_ONLYONEADAPTER
  785. #undef DPF_MODNAME
  786. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetUserData"
  787. HRESULT DP8ADDRESSOBJECT::SetUserData( const void * const pvData, const DWORD dwDataSize )
  788. {
  789. if( pvData == NULL && dwDataSize > 0 )
  790. {
  791. DPFX(DPFPREP, 0, "Invalid param" );
  792. return DPNERR_INVALIDPARAM;
  793. }
  794. ENTERLOCK();
  795. if( m_dwUserDataSize > 0 )
  796. {
  797. // Remove escaped user data
  798. m_dwStringSize -= m_dwUserDataStringSize;
  799. }
  800. if( dwDataSize == 0 )
  801. {
  802. m_dwUserDataSize = 0;
  803. if( m_pvUserData != NULL )
  804. DNFree(m_pvUserData);
  805. m_pvUserData = NULL;
  806. LEAVELOCK();
  807. return DPN_OK;
  808. }
  809. PBYTE pNewDataBuffer;
  810. if( dwDataSize > m_dwUserDataSize )
  811. {
  812. pNewDataBuffer = (BYTE*) DNMalloc(dwDataSize);
  813. if( pNewDataBuffer == NULL )
  814. {
  815. DPFX(DPFPREP, 0, "Error allocating memory" );
  816. LEAVELOCK();
  817. return DPNERR_OUTOFMEMORY;
  818. }
  819. if( m_pvUserData != NULL )
  820. {
  821. DNFree(m_pvUserData);
  822. }
  823. m_pvUserData = pNewDataBuffer;
  824. }
  825. m_dwUserDataStringSize = CalcExpandedBinarySize( (PBYTE) pvData, dwDataSize );
  826. m_dwStringSize += m_dwUserDataStringSize;
  827. m_dwStringSize += DNURL_LENGTH_USERDATA_SEPERATOR;
  828. memcpy( m_pvUserData, pvData, dwDataSize );
  829. m_dwUserDataSize = dwDataSize;
  830. LEAVELOCK();
  831. return DPN_OK;
  832. }
  833. #undef DPF_MODNAME
  834. #define DPF_MODNAME "DP8ADDRESSOBJECT::GetUserData"
  835. HRESULT DP8ADDRESSOBJECT::GetUserData( void * pvDataBuffer, PDWORD pdwDataSize )
  836. {
  837. if( pdwDataSize == NULL )
  838. {
  839. DPFX(DPFPREP, 0, "Must specify a pointer for the size" );
  840. return DPNERR_INVALIDPOINTER;
  841. }
  842. ENTERLOCK();
  843. if( m_dwUserDataSize == 0 )
  844. {
  845. LEAVELOCK();
  846. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "No user data was specified for this address" );
  847. return DPNERR_DOESNOTEXIST;
  848. }
  849. if( *pdwDataSize < m_dwUserDataSize )
  850. {
  851. *pdwDataSize = m_dwUserDataSize;
  852. LEAVELOCK();
  853. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
  854. return DPNERR_BUFFERTOOSMALL;
  855. }
  856. memcpy( pvDataBuffer, m_pvUserData, m_dwUserDataSize );
  857. LEAVELOCK();
  858. return DPN_OK;
  859. }
  860. #undef DPF_MODNAME
  861. #define DPF_MODNAME "DP8ADDRESSOBJECT::Cleanup"
  862. HRESULT DP8ADDRESSOBJECT::Cleanup()
  863. {
  864. Clear();
  865. return DPN_OK;
  866. }
  867. #undef DPF_MODNAME
  868. #define DPF_MODNAME "DP8ADDRESSOBJECT::CalcExpandedBinarySize"
  869. DWORD DP8ADDRESSOBJECT::CalcExpandedBinarySize( PBYTE pbData, DWORD dwDataSize )
  870. {
  871. PBYTE pbCurrentLocation = pbData;
  872. DWORD dwCount = 0;
  873. for( DWORD dwIndex = 0; dwIndex < dwDataSize; dwIndex++ )
  874. {
  875. if( IsEscapeChar( (WCHAR) *pbCurrentLocation ) )
  876. {
  877. if( ((WCHAR) *pbCurrentLocation) == DPNA_ESCAPECHAR )
  878. dwCount += 2;
  879. else
  880. dwCount+=3;
  881. }
  882. else
  883. {
  884. dwCount++;
  885. }
  886. pbCurrentLocation++;
  887. }
  888. return dwCount;
  889. }
  890. #undef DPF_MODNAME
  891. #define DPF_MODNAME "DP8ADDRESSOBJECT::CalcExpandedStringSize"
  892. DWORD DP8ADDRESSOBJECT::CalcExpandedStringSize( WCHAR *szString )
  893. {
  894. WCHAR *szCurrentLocation = szString;
  895. DWORD dwCount = 0;
  896. while( *szCurrentLocation )
  897. {
  898. if( IsEscapeChar( *szCurrentLocation ) )
  899. {
  900. if( *szCurrentLocation == DPNA_ESCAPECHAR )
  901. dwCount += 2;
  902. else
  903. dwCount+=3;
  904. }
  905. else
  906. {
  907. dwCount++;
  908. }
  909. szCurrentLocation++;
  910. }
  911. return dwCount;
  912. }
  913. #undef DPF_MODNAME
  914. #define DPF_MODNAME "DP8ADDRESSOBJECT::CalcComponentStringSize"
  915. HRESULT DP8ADDRESSOBJECT::CalcComponentStringSize( PDP8ADDRESSELEMENT paddElement, PDWORD pdwSize )
  916. {
  917. if( paddElement == NULL )
  918. return DPNERR_INVALIDPOINTER;
  919. if( paddElement->dwType == DPNA_DATATYPE_GUID )
  920. {
  921. *pdwSize = DNURL_LENGTH_GUID;
  922. }
  923. else if( paddElement->dwType == DPNA_DATATYPE_DWORD )
  924. {
  925. WCHAR tmpString[DNURL_LENGTH_DWORD+1];
  926. swprintf( tmpString, L"%u", paddElement->uData.dwData );
  927. *pdwSize = wcslen(tmpString);
  928. }
  929. // No WWCHARs need to be escaped
  930. else if( paddElement->dwType == DPNA_DATATYPE_STRING )
  931. {
  932. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  933. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  934. {
  935. *pdwSize = CalcExpandedStringSize( (WCHAR *) paddElement->uData.pvData );
  936. }
  937. else
  938. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  939. {
  940. *pdwSize = CalcExpandedStringSize( paddElement->uData.szData );
  941. }
  942. }
  943. // Every WWCHAR needs to be escaped
  944. else
  945. {
  946. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  947. if( paddElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  948. {
  949. *pdwSize = CalcExpandedBinarySize( (BYTE *) paddElement->uData.pvData, paddElement->dwDataSize );
  950. }
  951. else
  952. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  953. {
  954. *pdwSize = CalcExpandedBinarySize( (BYTE *) paddElement->uData.szData, paddElement->dwDataSize );
  955. }
  956. }
  957. // Add on the tag
  958. *pdwSize += paddElement->dwTagSize-1;
  959. // Add on the = and the ;
  960. (*pdwSize) ++;
  961. return DPN_OK;
  962. }
  963. #undef DPF_MODNAME
  964. #define DPF_MODNAME "DP8ADDRESSOBJECT::IsEscapeChar"
  965. BOOL DP8ADDRESSOBJECT::IsEscapeChar( WCHAR ch )
  966. {
  967. if( ch >= L'A' && ch <= L'Z' )
  968. return FALSE;
  969. if( ch >= L'a' && ch <= L'z' )
  970. return FALSE;
  971. if( ch >= L'0' && ch <= L'9' )
  972. return FALSE;
  973. if( ch == L'-' || ch == L'?' || ch == L'.' ||
  974. ch == L',' || ch == 'L+' || ch == L'_' )
  975. return FALSE;
  976. return TRUE;
  977. }
  978. #undef DPF_MODNAME
  979. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddString"
  980. void DP8ADDRESSOBJECT::BuildURL_AddString( WCHAR *szElements, WCHAR *szSource )
  981. {
  982. WCHAR *szSourceLoc = szSource;
  983. WCHAR tmpEscape[4];
  984. DWORD dwIndex;
  985. while( *szSourceLoc )
  986. {
  987. if( IsEscapeChar( *szSourceLoc ) )
  988. {
  989. if( *szSourceLoc == DPNA_ESCAPECHAR )
  990. {
  991. wcscat( szElements, L"%%" );
  992. }
  993. else
  994. {
  995. swprintf( tmpEscape, L"%%%02.2X", (DWORD) *szSourceLoc );
  996. wcscat( szElements, tmpEscape );
  997. }
  998. }
  999. else
  1000. {
  1001. dwIndex = wcslen(szElements);
  1002. szElements[dwIndex] = *szSourceLoc;
  1003. szElements[dwIndex+1] = 0;
  1004. }
  1005. szSourceLoc++;
  1006. }
  1007. }
  1008. #undef DPF_MODNAME
  1009. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddElements"
  1010. HRESULT DP8ADDRESSOBJECT::BuildURL_AddElements( WCHAR *szElements )
  1011. {
  1012. DP8ADDRESSELEMENT *pCurrentElement;
  1013. CBilink *pblRunner;
  1014. WCHAR tmpString[DNURL_LENGTH_GUID+2];
  1015. #ifdef DPNBUILD_ONLYONESP
  1016. BOOL fFirstElement = FALSE; // built-in provider always comes first
  1017. #else // ! DPNBUILD_ONLYONESP
  1018. BOOL fFirstElement = TRUE;
  1019. #endif // ! DPNBUILD_ONLYONESP
  1020. DWORD dwTmpLength;
  1021. pblRunner = m_blAddressElements.GetNext();
  1022. while( pblRunner != &m_blAddressElements )
  1023. {
  1024. pCurrentElement = CONTAINING_OBJECT(pblRunner, DP8ADDRESSELEMENT, blAddressElements);
  1025. if( !fFirstElement )
  1026. {
  1027. dwTmpLength = wcslen(szElements);
  1028. szElements[dwTmpLength] = DPNA_SEPARATOR_COMPONENT;
  1029. szElements[dwTmpLength+1] = 0;
  1030. }
  1031. wcscat( szElements, pCurrentElement->pszTag );
  1032. dwTmpLength = wcslen(szElements);
  1033. szElements[dwTmpLength] = DPNA_SEPARATOR_KEYVALUE;
  1034. szElements[dwTmpLength+1] = 0;
  1035. if( pCurrentElement->dwType == DPNA_DATATYPE_STRING )
  1036. {
  1037. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  1038. if( pCurrentElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  1039. {
  1040. BuildURL_AddString( szElements, (WCHAR *) pCurrentElement->uData.pvData );
  1041. }
  1042. else
  1043. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  1044. {
  1045. BuildURL_AddString( szElements, pCurrentElement->uData.szData );
  1046. }
  1047. }
  1048. else if( pCurrentElement->dwType == DPNA_DATATYPE_GUID )
  1049. {
  1050. 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",
  1051. pCurrentElement->uData.guidData.Data1, pCurrentElement->uData.guidData.Data2, pCurrentElement->uData.guidData.Data3,
  1052. pCurrentElement->uData.guidData.Data4[0], pCurrentElement->uData.guidData.Data4[1],
  1053. pCurrentElement->uData.guidData.Data4[2], pCurrentElement->uData.guidData.Data4[3],
  1054. pCurrentElement->uData.guidData.Data4[4], pCurrentElement->uData.guidData.Data4[5],
  1055. pCurrentElement->uData.guidData.Data4[6], pCurrentElement->uData.guidData.Data4[7] );
  1056. wcscat( szElements, tmpString );
  1057. }
  1058. else if( pCurrentElement->dwType == DPNA_DATATYPE_DWORD )
  1059. {
  1060. swprintf( tmpString, L"%u", pCurrentElement->uData.dwData );
  1061. wcscat( szElements, tmpString );
  1062. }
  1063. // Binary
  1064. else
  1065. {
  1066. #ifndef DPNBUILD_PREALLOCATEDMEMORYMODEL
  1067. if( pCurrentElement->dwFlags & DP8ADDRESS_ELEMENT_HEAP )
  1068. {
  1069. BuildURL_AddBinaryData( szElements, (BYTE *) pCurrentElement->uData.pvData , pCurrentElement->dwDataSize );
  1070. }
  1071. else
  1072. #endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
  1073. {
  1074. BuildURL_AddBinaryData( szElements, ((BYTE *) &pCurrentElement->uData), pCurrentElement->dwDataSize );
  1075. }
  1076. }
  1077. fFirstElement = FALSE;
  1078. pblRunner = pblRunner->GetNext();
  1079. }
  1080. return DPN_OK;
  1081. }
  1082. #undef DPF_MODNAME
  1083. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddHeader"
  1084. HRESULT DP8ADDRESSOBJECT::BuildURL_AddHeader( WCHAR *szWorking )
  1085. {
  1086. WCHAR *szReturn;
  1087. #ifdef DPNBUILD_ONLYONESP
  1088. wcscpy( szWorking, DPNA_HEADER DPNA_BUILTINPROVIDER );
  1089. szReturn = szWorking + DNURL_LENGTH_HEADER + DNURL_LENGTH_BUILTINPROVIDER;
  1090. #else // ! DPNBUILD_ONLYONESP
  1091. wcscpy( szWorking, DPNA_HEADER );
  1092. szReturn = szWorking + DNURL_LENGTH_HEADER;
  1093. #endif // ! DPNBUILD_ONLYONESP
  1094. return DPN_OK;
  1095. }
  1096. #undef DPF_MODNAME
  1097. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddUserData"
  1098. HRESULT DP8ADDRESSOBJECT::BuildURL_AddUserData(WCHAR * szWorking)
  1099. {
  1100. return BuildURL_AddBinaryData( szWorking, (BYTE *) m_pvUserData, m_dwUserDataSize );
  1101. }
  1102. #undef DPF_MODNAME
  1103. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURL_AddBinaryData"
  1104. HRESULT DP8ADDRESSOBJECT::BuildURL_AddBinaryData( WCHAR *szSource, BYTE *bData, DWORD dwDataLen )
  1105. {
  1106. WCHAR *pwszCurrentDest = szSource + wcslen(szSource);
  1107. BYTE *pbCurrentData = bData;
  1108. DWORD dwDataRemaining = dwDataLen;
  1109. dwDataRemaining = dwDataLen;
  1110. while ( dwDataRemaining > 0 )
  1111. {
  1112. if( IsEscapeChar( (WCHAR) *pbCurrentData ) )
  1113. {
  1114. if( ((WCHAR) *pbCurrentData) == DPNA_ESCAPECHAR )
  1115. {
  1116. wcscpy(pwszCurrentDest, L"%%");
  1117. pwszCurrentDest += 2;
  1118. }
  1119. else
  1120. {
  1121. pwszCurrentDest += swprintf( pwszCurrentDest, L"%%%02.2X", (DWORD) *pbCurrentData );
  1122. }
  1123. }
  1124. else
  1125. {
  1126. *pwszCurrentDest = (WCHAR) *pbCurrentData;
  1127. pwszCurrentDest++;
  1128. }
  1129. pbCurrentData++;
  1130. dwDataRemaining--;
  1131. }
  1132. // Ensure the string is NULL terminated if we added anything.
  1133. if ( dwDataLen > 0 )
  1134. {
  1135. *pwszCurrentDest = 0;
  1136. }
  1137. return DPN_OK;
  1138. }
  1139. #undef DPF_MODNAME
  1140. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURLA"
  1141. HRESULT DP8ADDRESSOBJECT::BuildURLA( char * szURL, PDWORD pdwRequiredSize )
  1142. {
  1143. HRESULT hr;
  1144. WCHAR wszStackTemp[256];
  1145. WCHAR * pwszTemp;
  1146. DWORD dwSize;
  1147. ENTERLOCK();
  1148. if( *pdwRequiredSize < m_dwStringSize || szURL == NULL )
  1149. {
  1150. *pdwRequiredSize = m_dwStringSize;
  1151. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
  1152. LEAVELOCK();
  1153. return DPNERR_BUFFERTOOSMALL;
  1154. }
  1155. // Allocate a buffer if the string is too large to convert in our
  1156. // stack based buffer.
  1157. if ((m_dwStringSize * sizeof(WCHAR)) > sizeof(wszStackTemp))
  1158. {
  1159. pwszTemp = (WCHAR*) DNMalloc(m_dwStringSize * sizeof(WCHAR));
  1160. if (pwszTemp == NULL)
  1161. {
  1162. DPFX(DPFPREP, 0, "Error allocating memory for conversion");
  1163. LEAVELOCK();
  1164. return DPNERR_OUTOFMEMORY;
  1165. }
  1166. dwSize = m_dwStringSize;
  1167. }
  1168. else
  1169. {
  1170. pwszTemp = wszStackTemp;
  1171. dwSize = sizeof(wszStackTemp) / sizeof(WCHAR);
  1172. }
  1173. // BuildURLW takes the lock again.
  1174. hr = BuildURLW( pwszTemp, &dwSize );
  1175. if( FAILED( hr ) )
  1176. {
  1177. LEAVELOCK();
  1178. return hr;
  1179. }
  1180. hr = STR_jkWideToAnsi(szURL, pwszTemp, dwSize);
  1181. if( FAILED( hr ) )
  1182. {
  1183. DPFX(DPFPREP, 0, "Error unable to convert element ANSI->Unicode 0x%x", hr );
  1184. hr = DPNERR_CONVERSION;
  1185. }
  1186. else
  1187. {
  1188. *pdwRequiredSize = dwSize;
  1189. }
  1190. if (pwszTemp != wszStackTemp)
  1191. {
  1192. DNFree(pwszTemp);
  1193. pwszTemp = NULL;
  1194. }
  1195. LEAVELOCK();
  1196. return hr;
  1197. }
  1198. #undef DPF_MODNAME
  1199. #define DPF_MODNAME "DP8ADDRESSOBJECT::BuildURLW"
  1200. HRESULT DP8ADDRESSOBJECT::BuildURLW( WCHAR * szURL, PDWORD pdwRequiredSize )
  1201. {
  1202. HRESULT hr;
  1203. ENTERLOCK();
  1204. if( *pdwRequiredSize < m_dwStringSize || szURL == NULL )
  1205. {
  1206. *pdwRequiredSize = m_dwStringSize;
  1207. DPFX(DPFPREP, DP8A_WARNINGLEVEL, "Buffer too small" );
  1208. LEAVELOCK();
  1209. return DPNERR_BUFFERTOOSMALL;
  1210. }
  1211. hr = BuildURL_AddHeader( szURL );
  1212. if( FAILED( hr ) )
  1213. {
  1214. DPFX(DPFPREP, 0, "Error adding header hr=0x%x", hr );
  1215. LEAVELOCK();
  1216. return hr;
  1217. }
  1218. hr = BuildURL_AddElements( szURL );
  1219. if( FAILED( hr ) )
  1220. {
  1221. DPFX(DPFPREP, 0, "Error adding elements hr=0x%x", hr );
  1222. LEAVELOCK();
  1223. return hr;
  1224. }
  1225. hr = BuildURL_AddUserData( szURL );
  1226. if( FAILED( hr ) )
  1227. {
  1228. DPFX(DPFPREP, 0, "Error adding user data hr=0x%x", hr );
  1229. LEAVELOCK();
  1230. return hr;
  1231. }
  1232. LEAVELOCK();
  1233. *pdwRequiredSize = m_dwStringSize;
  1234. return DPN_OK;
  1235. }
  1236. #undef DPF_MODNAME
  1237. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetURL"
  1238. HRESULT DP8ADDRESSOBJECT::SetURL( WCHAR * szURL )
  1239. {
  1240. HRESULT hr;
  1241. DP8ADDRESSPARSE dp8aParser;
  1242. hr = Clear();
  1243. if( FAILED( hr ) )
  1244. {
  1245. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Unable to clear existing address hr=0x%x", hr );
  1246. return hr;
  1247. }
  1248. ENTERLOCK();
  1249. hr = dp8aParser.ParseURL(this, szURL);
  1250. if( FAILED( hr ) )
  1251. {
  1252. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Error parsing the URL hr=0x%x", hr );
  1253. LEAVELOCK();
  1254. return hr;
  1255. }
  1256. LEAVELOCK();
  1257. return hr;
  1258. }
  1259. #ifndef DPNBUILD_NOLEGACYDP
  1260. #undef DPF_MODNAME
  1261. #define DPF_MODNAME "DP8ADDRESSOBJECT::SetDirectPlay4Address"
  1262. HRESULT DP8ADDRESSOBJECT::SetDirectPlay4Address( void * pvDataBuffer, const DWORD dwDataSize )
  1263. {
  1264. PBYTE pbCurrentLocation;
  1265. PDPADDRESS pdpAddressChunk;
  1266. LONG lRemaining;
  1267. HRESULT hr = DPN_OK;
  1268. DWORD dwCurrentChunkSize;
  1269. DWORD dwNumElementsParsed = 0;
  1270. ENTERLOCK();
  1271. hr = Clear();
  1272. if( FAILED( hr ) )
  1273. {
  1274. DPFX(DPFPREP, 0, "Failed to clear old address data hr=[0x%lx]", hr );
  1275. LEAVELOCK();
  1276. return hr;
  1277. }
  1278. pbCurrentLocation = (PBYTE) pvDataBuffer;
  1279. lRemaining = dwDataSize;
  1280. while( lRemaining > 0 )
  1281. {
  1282. pdpAddressChunk = (PDPADDRESS) pbCurrentLocation;
  1283. if( sizeof( DPADDRESS ) > lRemaining )
  1284. {
  1285. DPFX(DPFPREP, 0, "Error parsing address, unexpected end of address" );
  1286. LEAVELOCK();
  1287. return DPNERR_INVALIDADDRESSFORMAT;
  1288. }
  1289. dwCurrentChunkSize = sizeof( DPADDRESS ) + pdpAddressChunk->dwDataSize;
  1290. if( ((LONG) dwCurrentChunkSize) > lRemaining )
  1291. {
  1292. DPFX(DPFPREP, 0, "Error parsing address, unexpected end during data" );
  1293. LEAVELOCK();
  1294. return DPNERR_INVALIDADDRESSFORMAT;
  1295. }
  1296. hr = AddDP4Element( pdpAddressChunk, this );
  1297. if( FAILED( hr ) )
  1298. {
  1299. DPFX(DPFPREP, 0, "Error adding next element" );
  1300. break;
  1301. }
  1302. lRemaining -= dwCurrentChunkSize;
  1303. pbCurrentLocation += dwCurrentChunkSize;
  1304. }
  1305. LEAVELOCK();
  1306. return hr;
  1307. }
  1308. #endif // ! DPNBUILD_NOLEGACYDP