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.

644 lines
17 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ClassFac.cpp
  6. * Content: DNET COM class factory
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/21/99 mjn Created
  12. * 02/04/2000 rmt Adjusted for use in DPAddress
  13. * 02/17/2000 rmt Parameter validation work
  14. * 02/20/2000 rmt Added parameter validation for IUnknown funcs
  15. * 03/21/2000 rmt Renamed all DirectPlayAddress8's to DirectPlay8Addresses
  16. * 06/20/2000 rmt Bugfix - QueryInterface had bug which was limiting interface list to 2 elements
  17. * 07/09/2000 rmt Added signature bytes to start of address objects
  18. * 07/13/2000 rmt Added critical sections to protect FPMs
  19. * 08/05/2000 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles.
  20. * 01/11/2001 rmt MANBUG #48487 - DPLAY: Crashes if CoCreate() isn't called.
  21. * 03/14/2001 rmt WINBUG #342420 - Restore COM emulation layer to operation.
  22. *@@END_MSINTERNAL
  23. *
  24. ***************************************************************************/
  25. #include "dnaddri.h"
  26. //**********************************************************************
  27. // Function prototypes
  28. //**********************************************************************
  29. #ifndef DPNBUILD_LIBINTERFACE
  30. HRESULT DP8A_CreateInterface(LPOBJECT_DATA lpObject,REFIID riid, LPINTERFACE_LIST *const ppv);
  31. // Globals
  32. extern LONG g_lAddrObjectCount;
  33. #endif // ! DPNBUILD_LIBINTERFACE
  34. //**********************************************************************
  35. // Constant definitions
  36. //**********************************************************************
  37. //**********************************************************************
  38. // Macro definitions
  39. //**********************************************************************
  40. //**********************************************************************
  41. // Structure definitions
  42. //**********************************************************************
  43. #ifndef DPNBUILD_LIBINTERFACE
  44. typedef STDMETHODIMP IUnknownQueryInterface( IUnknown *pInterface, REFIID riid, LPVOID *ppvObj );
  45. typedef STDMETHODIMP_(ULONG) IUnknownAddRef( IUnknown *pInterface );
  46. typedef STDMETHODIMP_(ULONG) IUnknownRelease( IUnknown *pInterface );
  47. //
  48. // VTable for IUnknown interface
  49. //
  50. IUnknownVtbl DP8A_UnknownVtbl =
  51. {
  52. (IUnknownQueryInterface*) DP8A_QueryInterface,
  53. (IUnknownAddRef*) DP8A_AddRef,
  54. (IUnknownRelease*) DP8A_Release
  55. };
  56. //
  57. // VTable for Class Factory
  58. //
  59. IClassFactoryVtbl DP8ACF_Vtbl =
  60. {
  61. DPCF_QueryInterface, // dplay8\common\classfactory.cpp will implement these
  62. DPCF_AddRef,
  63. DPCF_Release,
  64. DP8ACF_CreateInstance,
  65. DPCF_LockServer
  66. };
  67. #endif // ! DPNBUILD_LIBINTERFACE
  68. //**********************************************************************
  69. // Variable definitions
  70. //**********************************************************************
  71. //**********************************************************************
  72. // Function definitions
  73. //**********************************************************************
  74. #ifndef WINCE
  75. #ifndef _XBOX
  76. #undef DPF_MODNAME
  77. #define DPF_MODNAME "DirectPlay8AddressCreate"
  78. HRESULT WINAPI DirectPlay8AddressCreate( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown)
  79. {
  80. #ifndef DPNBUILD_NOPARAMVAL
  81. if( pcIID == NULL ||
  82. !DNVALID_READPTR( pcIID, sizeof( GUID ) ) )
  83. {
  84. DPFERR( "Invalid pointer specified for interface GUID" );
  85. return DPNERR_INVALIDPOINTER;
  86. }
  87. #ifdef DPNBUILD_NOADDRESSIPINTERFACE
  88. if( *pcIID == IID_IDirectPlay8AddressIP )
  89. {
  90. DPFERR("The IDirectPlay8AddressIP interface is not supported" );
  91. return DPNERR_UNSUPPORTED;
  92. }
  93. if( *pcIID != IID_IDirectPlay8Address )
  94. {
  95. DPFERR("Interface ID is not recognized" );
  96. return DPNERR_INVALIDPARAM;
  97. }
  98. #else // ! DPNBUILD_NOADDRESSIPINTERFACE
  99. if( *pcIID != IID_IDirectPlay8Address &&
  100. *pcIID != IID_IDirectPlay8AddressIP )
  101. {
  102. DPFERR("Interface ID is not recognized" );
  103. return DPNERR_INVALIDPARAM;
  104. }
  105. #endif // ! DPNBUILD_NOADDRESSIPINTERFACE
  106. if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
  107. {
  108. DPFERR( "Invalid pointer specified to receive interface" );
  109. return DPNERR_INVALIDPOINTER;
  110. }
  111. if( pUnknown != NULL )
  112. {
  113. DPFERR( "Aggregation is not supported by this object yet" );
  114. return DPNERR_INVALIDPARAM;
  115. }
  116. #endif // !DPNBUILD_NOPARAMVAL
  117. return COM_CoCreateInstance( CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, *pcIID, ppvInterface, TRUE );
  118. }
  119. #endif // ! _XBOX
  120. #endif // ! WINCE
  121. #undef DPF_MODNAME
  122. #define DPF_MODNAME "DP8ACF_FreeObject"
  123. HRESULT DP8ACF_FreeObject(LPVOID lpv)
  124. {
  125. HRESULT hResultCode = S_OK;
  126. DP8ADDRESSOBJECT *pdnObject = (DP8ADDRESSOBJECT *) lpv;
  127. DNASSERT(pdnObject != NULL);
  128. pdnObject->Cleanup();
  129. DPFX(DPFPREP, 5,"free pdnObject [%p]",pdnObject);
  130. // Release the object
  131. fpmAddressObjects.Release( pdnObject );
  132. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx]",hResultCode);
  133. return(hResultCode);
  134. }
  135. #ifdef DPNBUILD_LIBINTERFACE
  136. STDMETHODIMP DP8ACF_CreateInstance(DPNAREFIID riid, LPVOID *ppv)
  137. {
  138. HRESULT hResultCode = S_OK;
  139. DP8ADDRESSOBJECT *pdnObject = NULL;
  140. DPFX(DPFPREP, 3,"Parameters: riid [%p], ppv [%p]",riid,ppv);
  141. #ifndef DPNBUILD_NOPARAMVAL
  142. if( ppv == NULL || !DNVALID_WRITEPTR( ppv, sizeof(LPVOID) ) )
  143. {
  144. DPFX(DPFPREP, 0, "Cannot pass NULL for new object param" );
  145. return E_INVALIDARG;
  146. }
  147. #endif // ! DPNBUILD_NOPARAMVAL
  148. // Object creation and initialization
  149. pdnObject = (DP8ADDRESSOBJECT *) fpmAddressObjects.Get();
  150. if (pdnObject == NULL)
  151. {
  152. DPFERR("FPM_Get() failed getting new address object");
  153. return(E_OUTOFMEMORY);
  154. }
  155. hResultCode = pdnObject->Init( );
  156. if( FAILED( hResultCode ) )
  157. {
  158. DPFX(DPFPREP, 0,"Failed to init new address object hr=0x%x", hResultCode );
  159. fpmAddressObjects.Release( pdnObject );
  160. return hResultCode;
  161. }
  162. DPFX(DPFPREP, 5,"pdnObject [%p]",pdnObject);
  163. //
  164. // For lib interface builds, the Vtbl and reference count are embedded in the
  165. // object directly
  166. //
  167. #ifndef DPNBUILD_NOADDRESSIPINTERFACE
  168. if (riid == IID_IDirectPlay8AddressIP)
  169. {
  170. pdnObject->lpVtbl = &DP8A_IPVtbl;
  171. }
  172. else
  173. #endif // ! DPNBUILD_NOADDRESSIPINTERFACE
  174. {
  175. DNASSERT(riid == IID_IDirectPlay8Address);
  176. pdnObject->lpVtbl = &DP8A_BaseVtbl;
  177. }
  178. pdnObject->lRefCount = 1;
  179. *ppv = pdnObject;
  180. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  181. return(S_OK);
  182. }
  183. #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
  184. HRESULT DNAddress_PreallocateInterfaces( const DWORD dwNumInterfaces )
  185. {
  186. DWORD dwAllocated;
  187. //
  188. // (Pre-)allocate address objects.
  189. //
  190. dwAllocated = fpmAddressObjects.Preallocate(dwNumInterfaces, NULL);
  191. if (dwAllocated < dwNumInterfaces)
  192. {
  193. DPFX(DPFPREP, 0, "Only preallocated %u of %u interfaces!",
  194. dwAllocated, dwNumInterfaces);
  195. return DPNERR_OUTOFMEMORY;
  196. }
  197. //
  198. // (Pre-)allocate a default number of elements for the objects.
  199. //
  200. dwAllocated = fpmAddressElements.Preallocate((5 * dwNumInterfaces), NULL);
  201. if (dwAllocated < (5 * dwNumInterfaces))
  202. {
  203. DPFX(DPFPREP, 0, "Only preallocated %u of %u address elements!",
  204. dwAllocated, (5 * dwNumInterfaces));
  205. return DPNERR_OUTOFMEMORY;
  206. }
  207. return DPN_OK;
  208. }
  209. #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
  210. #undef DPF_MODNAME
  211. #define DPF_MODNAME "DP8A_QueryInterface"
  212. STDMETHODIMP DP8A_QueryInterface(void *pInterface, DPNAREFIID riid, void **ppv)
  213. {
  214. HRESULT hResultCode;
  215. DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], riid [0x%p], ppv [0x%p]",pInterface,&riid,ppv);
  216. DPFX(DPFPREP, 0, "Querying for an interface is not supported!");
  217. hResultCode = DPNERR_UNSUPPORTED;
  218. DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
  219. return(hResultCode);
  220. }
  221. #undef DPF_MODNAME
  222. #define DPF_MODNAME "DP8A_AddRef"
  223. STDMETHODIMP_(ULONG) DP8A_AddRef(LPVOID lpv)
  224. {
  225. DP8ADDRESSOBJECT *pdnObject;
  226. LONG lResult;
  227. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  228. #ifndef DPNBUILD_NOPARAMVAL
  229. if( lpv == NULL || !DP8A_VALID(lpv) )
  230. {
  231. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  232. return DPNERR_INVALIDOBJECT;
  233. }
  234. #endif // !DPNBUILD_NOPARAMVAL
  235. pdnObject = static_cast<DP8ADDRESSOBJECT*>(lpv);
  236. lResult = DNInterlockedIncrement( &pdnObject->lRefCount );
  237. DPFX(DPFPREP, 3,"Returning: lResult = [%lx]",lResult);
  238. return(lResult);
  239. }
  240. #undef DPF_MODNAME
  241. #define DPF_MODNAME "DP8A_Release"
  242. STDMETHODIMP_(ULONG) DP8A_Release(LPVOID lpv)
  243. {
  244. DP8ADDRESSOBJECT *pdnObject;
  245. LONG lResult;
  246. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  247. #ifndef DPNBUILD_NOPARAMVAL
  248. if( lpv == NULL || !DP8A_VALID(lpv) )
  249. {
  250. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  251. return DPNERR_INVALIDOBJECT;
  252. }
  253. #endif // !DPNBUILD_NOPARAMVAL
  254. pdnObject = static_cast<DP8ADDRESSOBJECT*>(lpv);
  255. DPFX(DPFPREP, 5,"Original : pdnObject->lRefCount = %ld",pdnObject->lRefCount);
  256. lResult = DNInterlockedDecrement( &pdnObject->lRefCount );
  257. if( lResult == 0 )
  258. {
  259. DPFX(DPFPREP, 5,"Free object");
  260. DP8ACF_FreeObject(pdnObject);
  261. }
  262. DPFX(DPFPREP, 3,"Returning: lResult = [%lx]",lResult);
  263. return(lResult);
  264. }
  265. #else // ! DPNBUILD_LIBINTERFACE
  266. #undef DPF_MODNAME
  267. #define DPF_MODNAME "DP8ACF_CreateInstance"
  268. STDMETHODIMP DP8ACF_CreateInstance(IClassFactory* pInterface, LPUNKNOWN lpUnkOuter, REFIID riid, LPVOID *ppv)
  269. {
  270. HRESULT hResultCode = S_OK;
  271. LPINTERFACE_LIST lpIntList = NULL;
  272. LPOBJECT_DATA lpObjectData = NULL;
  273. DP8ADDRESSOBJECT *pdnObject = NULL;
  274. DPFX(DPFPREP, 3,"Parameters: pInterface [%p], lpUnkOuter [%p], riid [%p], ppv [%p]",pInterface,lpUnkOuter,riid,ppv);
  275. #ifndef DPNBUILD_NOPARAMVAL
  276. if( ppv == NULL || !DNVALID_WRITEPTR( ppv, sizeof(LPVOID) ) )
  277. {
  278. DPFX(DPFPREP, 0, "Cannot pass NULL for new object param" );
  279. return E_INVALIDARG;
  280. }
  281. #endif // !DPNBUILD_NOPARAMVAL
  282. if (lpUnkOuter != NULL)
  283. {
  284. DPFX(DPFPREP, 0, "Aggregation is not supported, pUnkOuter must be NULL" );
  285. return(CLASS_E_NOAGGREGATION);
  286. }
  287. lpObjectData = (LPOBJECT_DATA) g_fpObjectDatas.Get();
  288. if (lpObjectData == NULL)
  289. {
  290. DPFERR("FPM_Get() failed");
  291. return(E_OUTOFMEMORY);
  292. }
  293. DPFX(DPFPREP, 5,"lpObjectData [%p]",lpObjectData);
  294. // Object creation and initialization
  295. pdnObject = (DP8ADDRESSOBJECT *) fpmAddressObjects.Get();
  296. if (pdnObject == NULL)
  297. {
  298. DPFERR("FPM_Get() failed getting new address object");
  299. g_fpObjectDatas.Release(lpObjectData);
  300. return(E_OUTOFMEMORY);
  301. }
  302. hResultCode = pdnObject->Init( );
  303. if( FAILED( hResultCode ) )
  304. {
  305. DPFX(DPFPREP, 0,"Failed to init new address object hr=0x%x", hResultCode );
  306. fpmAddressObjects.Release( pdnObject );
  307. g_fpObjectDatas.Release(lpObjectData);
  308. return hResultCode;
  309. }
  310. DPFX(DPFPREP, 5,"pdnObject [%p]",pdnObject);
  311. lpObjectData->pvData = pdnObject;
  312. // Get requested interface
  313. if ((hResultCode = DP8A_CreateInterface(lpObjectData,riid,&lpIntList)) != S_OK)
  314. {
  315. DP8ACF_FreeObject(lpObjectData->pvData);
  316. g_fpObjectDatas.Release(lpObjectData);
  317. return(hResultCode);
  318. }
  319. DPFX(DPFPREP, 5,"Found interface");
  320. lpObjectData->pIntList = lpIntList;
  321. lpObjectData->lRefCount = 1;
  322. DNInterlockedIncrement(&lpIntList->lRefCount );
  323. DNInterlockedIncrement(&g_lAddrObjectCount);
  324. *ppv = lpIntList;
  325. DPFX(DPFPREP, 3,"Returning: hResultCode = [%lx], *ppv = [%p]",hResultCode,*ppv);
  326. return(S_OK);
  327. }
  328. #undef DPF_MODNAME
  329. #define DPF_MODNAME "DP8A_CreateInterface"
  330. static HRESULT DP8A_CreateInterface(LPOBJECT_DATA lpObject, REFIID riid, LPINTERFACE_LIST *const ppv)
  331. {
  332. LPINTERFACE_LIST lpIntNew;
  333. LPVOID lpVtbl;
  334. DPFX(DPFPREP, 3,"Parameters: lpObject [%p], riid [%p], ppv [%p]",lpObject,riid,ppv);
  335. if (IsEqualIID(riid,IID_IUnknown))
  336. {
  337. DPFX(DPFPREP, 5,"riid = IID_IUnknown");
  338. lpVtbl = &DP8A_UnknownVtbl;
  339. }
  340. else if (IsEqualIID(riid,IID_IDirectPlay8Address))
  341. {
  342. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8Address");
  343. lpVtbl = &DP8A_BaseVtbl;
  344. }
  345. else if (IsEqualIID(riid,IID_IDirectPlay8AddressIP))
  346. {
  347. #ifdef DPNBUILD_NOADDRESSIPINTERFACE
  348. DPFERR("The IDirectPlay8AddressIP interface is not supported" );
  349. return(DPNERR_UNSUPPORTED);
  350. #else // ! DPNBUILD_NOADDRESSIPINTERFACE
  351. DPFX(DPFPREP, 5,"riid = IID_IDirectPlay8AddressIP");
  352. lpVtbl = &DP8A_IPVtbl;
  353. #endif // ! DPNBUILD_NOADDRESSIPINTERFACE
  354. }
  355. else
  356. {
  357. DPFX(DPFPREP, 5,"riid not found !");
  358. return(E_NOINTERFACE);
  359. }
  360. lpIntNew = (LPINTERFACE_LIST) g_fpInterfaceLists.Get();
  361. if (lpIntNew == NULL)
  362. {
  363. DPFERR("FPM_Get() failed");
  364. return(E_OUTOFMEMORY);
  365. }
  366. lpIntNew->lpVtbl = lpVtbl;
  367. lpIntNew->lRefCount = 0;
  368. lpIntNew->pIntNext = NULL;
  369. DBG_CASSERT( sizeof( lpIntNew->iid ) == sizeof( riid ) );
  370. memcpy( &(lpIntNew->iid), &riid, sizeof( lpIntNew->iid ) );
  371. lpIntNew->pObject = lpObject;
  372. *ppv = lpIntNew;
  373. DPFX(DPFPREP, 3,"Returning: hResultCode = [S_OK], *ppv = [%p]",*ppv);
  374. return(S_OK);
  375. }
  376. #undef DPF_MODNAME
  377. #define DPF_MODNAME "DP8A_FindInterface"
  378. LPINTERFACE_LIST DP8A_FindInterface(LPVOID lpv, REFIID riid)
  379. {
  380. LPINTERFACE_LIST lpIntList;
  381. DPFX(DPFPREP, 3,"Parameters: lpv [%p], riid [%p]",lpv,riid);
  382. lpIntList = ((LPINTERFACE_LIST)lpv)->pObject->pIntList; // Find first interface
  383. while (lpIntList != NULL)
  384. {
  385. if (IsEqualIID(riid,lpIntList->iid))
  386. break;
  387. lpIntList = lpIntList->pIntNext;
  388. }
  389. DPFX(DPFPREP, 3,"Returning: lpIntList = [%p]",lpIntList);
  390. return(lpIntList);
  391. }
  392. #undef DPF_MODNAME
  393. #define DPF_MODNAME "DP8A_QueryInterface"
  394. STDMETHODIMP DP8A_QueryInterface(LPVOID lpv,DPNAREFIID riid,LPVOID *ppv)
  395. {
  396. LPINTERFACE_LIST lpIntList;
  397. LPINTERFACE_LIST lpIntNew;
  398. HRESULT hResultCode;
  399. DPFX(DPFPREP, 3,"Parameters: lpv [%p], riid [%p], ppv [%p]",lpv,riid,ppv);
  400. #ifndef DPNBUILD_NOPARAMVAL
  401. if( lpv == NULL || !DP8A_VALID(lpv) )
  402. {
  403. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  404. return DPNERR_INVALIDOBJECT;
  405. }
  406. if( ppv == NULL ||
  407. !DNVALID_WRITEPTR(ppv, sizeof(LPVOID) ) )
  408. {
  409. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid pointer for interface" );
  410. return DPNERR_INVALIDPOINTER;
  411. }
  412. #endif // !DPNBUILD_NOPARAMVAL
  413. if ((lpIntList = DP8A_FindInterface(lpv,riid)) == NULL)
  414. { // Interface must be created
  415. lpIntList = ((LPINTERFACE_LIST)lpv)->pObject->pIntList;
  416. if ((hResultCode = DP8A_CreateInterface(lpIntList->pObject,riid,&lpIntNew)) != S_OK)
  417. {
  418. return(hResultCode);
  419. }
  420. lpIntNew->pIntNext = lpIntList;
  421. ((LPINTERFACE_LIST)lpv)->pObject->pIntList = lpIntNew;
  422. lpIntList = lpIntNew;
  423. }
  424. // Interface is being created or was cached
  425. // Increment object count
  426. if( lpIntList->lRefCount == 0 )
  427. {
  428. DNInterlockedIncrement( &lpIntList->pObject->lRefCount );
  429. }
  430. DNInterlockedIncrement( &lpIntList->lRefCount );
  431. *ppv = lpIntList;
  432. DPFX(DPFPREP, 3,"Returning: hResultCode = [S_OK], *ppv = [%p]",*ppv);
  433. return(S_OK);
  434. }
  435. #undef DPF_MODNAME
  436. #define DPF_MODNAME "DP8A_AddRef"
  437. STDMETHODIMP_(ULONG) DP8A_AddRef(LPVOID lpv)
  438. {
  439. LPINTERFACE_LIST lpIntList;
  440. LONG lResult;
  441. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  442. #ifndef DPNBUILD_NOPARAMVAL
  443. if( lpv == NULL || !DP8A_VALID(lpv) )
  444. {
  445. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  446. return DPNERR_INVALIDOBJECT;
  447. }
  448. #endif // !DPNBUILD_NOPARAMVAL
  449. lpIntList = (LPINTERFACE_LIST)lpv;
  450. lResult = DNInterlockedIncrement( &lpIntList->lRefCount );
  451. DPFX(DPFPREP, 3,"Returning: lResult = [%lx]",lResult);
  452. return(lResult);
  453. }
  454. #undef DPF_MODNAME
  455. #define DPF_MODNAME "DP8A_Release"
  456. STDMETHODIMP_(ULONG) DP8A_Release(LPVOID lpv)
  457. {
  458. LPINTERFACE_LIST lpIntList;
  459. LPINTERFACE_LIST lpIntCurrent;
  460. LONG lResult;
  461. DPFX(DPFPREP, 3,"Parameters: lpv [%p]",lpv);
  462. #ifndef DPNBUILD_NOPARAMVAL
  463. if( lpv == NULL || !DP8A_VALID(lpv) )
  464. {
  465. DPFX(DPFPREP, DP8A_ERRORLEVEL, "Invalid object" );
  466. return DPNERR_INVALIDOBJECT;
  467. }
  468. #endif // !DPNBUILD_NOPARAMVAL
  469. lpIntList = (LPINTERFACE_LIST)lpv;
  470. DPFX(DPFPREP, 5,"Original : lpIntList->lRefCount = %ld",lpIntList->lRefCount);
  471. DPFX(DPFPREP, 5,"Original : lpIntList->pObject->lRefCount = %ld",lpIntList->pObject->lRefCount);
  472. lResult = DNInterlockedDecrement( &lpIntList->lRefCount );
  473. if( lResult == 0 )
  474. { // Decrease interface count
  475. if( DNInterlockedDecrement( &lpIntList->pObject->lRefCount ) == 0 )
  476. { // Free object and all interfaces
  477. DPFX(DPFPREP, 5,"Free object");
  478. // Free object here
  479. DP8ACF_FreeObject(lpIntList->pObject->pvData);
  480. lpIntList = lpIntList->pObject->pIntList; // Get head of interface list
  481. DPFX(DPFPREP, 5,"lpIntList->pObject [%p]",lpIntList->pObject);
  482. g_fpObjectDatas.Release(lpIntList->pObject);
  483. // Free Interfaces
  484. DPFX(DPFPREP, 5,"Free interfaces");
  485. while(lpIntList != NULL)
  486. {
  487. lpIntCurrent = lpIntList;
  488. lpIntList = lpIntList->pIntNext;
  489. DPFX(DPFPREP, 5,"\tinterface [%p]",lpIntCurrent);
  490. g_fpInterfaceLists.Release(lpIntCurrent);
  491. }
  492. DNInterlockedDecrement(&g_lAddrObjectCount);
  493. DPFX(DPFPREP, 3,"Returning: 0");
  494. return(0);
  495. }
  496. }
  497. DPFX(DPFPREP, 3,"Returning: lResult = [%lx]",lResult);
  498. return(lResult);
  499. }
  500. #endif // ! DPNBUILD_LIBINTERFACE