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.

650 lines
17 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: classfac.c
  6. * Content: direct draw class factory code
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 24-dec-95 craige initial implementation
  12. * 05-jan-96 kylej added interface structures
  13. * 14-mar-96 colinmc added a class factory for clippers
  14. * 22-mar-96 colinmc Bug 13316: uninitialized interfaces
  15. * 22-oct-97 jeffno Merge class factories, add classfac for CLSID_DirectDrawFactory2
  16. *
  17. ***************************************************************************/
  18. #include "ddrawpr.h"
  19. static IClassFactoryVtbl directDrawClassFactoryVtbl;
  20. typedef struct DDRAWCLASSFACTORY
  21. {
  22. IClassFactoryVtbl *lpVtbl;
  23. DWORD dwRefCnt;
  24. CLSID TargetCLSID;
  25. } DDRAWCLASSFACTORY, *LPDDRAWCLASSFACTORY;
  26. #define VALIDEX_DIRECTDRAWCF_PTR( ptr ) \
  27. ( !IsBadWritePtr( ptr, sizeof( DDRAWCLASSFACTORY )) && \
  28. (ptr->lpVtbl == &directDrawClassFactoryVtbl) )
  29. /************************************************************
  30. *
  31. * DirectDraw Driver Class Factory Member Functions.
  32. *
  33. ************************************************************/
  34. #define DPF_MODNAME "DirectDrawClassFactory::QueryInterface"
  35. /*
  36. * DirectDrawClassFactory_QueryInterface
  37. */
  38. STDMETHODIMP DirectDrawClassFactory_QueryInterface(
  39. LPCLASSFACTORY this,
  40. REFIID riid,
  41. LPVOID *ppvObj )
  42. {
  43. LPDDRAWCLASSFACTORY pcf;
  44. DPF( 2, A, "ClassFactory::QueryInterface" );
  45. ENTER_DDRAW();
  46. TRY
  47. {
  48. pcf = (LPDDRAWCLASSFACTORY)this;
  49. if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
  50. {
  51. DPF_ERR( "Invalid this ptr" );
  52. LEAVE_DDRAW();
  53. return E_FAIL;
  54. }
  55. if( !VALID_PTR_PTR( ppvObj ) )
  56. {
  57. DPF_ERR( "Invalid object ptr" );
  58. LEAVE_DDRAW();
  59. return E_INVALIDARG;
  60. }
  61. *ppvObj = NULL;
  62. if( !VALID_IID_PTR( riid ) )
  63. {
  64. DPF_ERR( "Invalid iid ptr" );
  65. LEAVE_DDRAW();
  66. return E_INVALIDARG;
  67. }
  68. if( IsEqualIID(riid, &IID_IClassFactory) ||
  69. IsEqualIID(riid, &IID_IUnknown))
  70. {
  71. pcf->dwRefCnt++;
  72. *ppvObj = this;
  73. LEAVE_DDRAW();
  74. return S_OK;
  75. }
  76. else
  77. {
  78. DPF( 0, "E_NOINTERFACE" );
  79. LEAVE_DDRAW();
  80. return E_NOINTERFACE;
  81. }
  82. }
  83. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  84. {
  85. DPF_ERR( "Exception encountered validating parameters" );
  86. LEAVE_DDRAW();
  87. return DDERR_INVALIDPARAMS;
  88. }
  89. } /* DirectDrawClassFactory_QueryInterface */
  90. #undef DPF_MODNAME
  91. #define DPF_MODNAME "DirectDrawClassFactory::AddRef"
  92. /*
  93. * DirectDrawClassFactory_AddRef
  94. */
  95. STDMETHODIMP_(ULONG) DirectDrawClassFactory_AddRef( LPCLASSFACTORY this )
  96. {
  97. LPDDRAWCLASSFACTORY pcf;
  98. ENTER_DDRAW();
  99. TRY
  100. {
  101. pcf = (LPDDRAWCLASSFACTORY)this;
  102. if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
  103. {
  104. DPF_ERR( "Invalid this ptr" );
  105. LEAVE_DDRAW();
  106. return (ULONG)E_FAIL;
  107. }
  108. pcf->dwRefCnt++;
  109. }
  110. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  111. {
  112. DPF_ERR( "Exception encountered validating parameters" );
  113. LEAVE_DDRAW();
  114. return (ULONG)E_INVALIDARG;
  115. }
  116. DPF( 5, "ClassFactory::AddRef, dwRefCnt=%ld", pcf->dwRefCnt );
  117. LEAVE_DDRAW();
  118. return pcf->dwRefCnt;
  119. } /* DirectDrawClassFactory_AddRef */
  120. #undef DPF_MODNAME
  121. #define DPF_MODNAME "DirectDrawClassFactory::Release"
  122. /*
  123. * DirectDrawClassFactory_Release
  124. */
  125. STDMETHODIMP_(ULONG) DirectDrawClassFactory_Release( LPCLASSFACTORY this )
  126. {
  127. LPDDRAWCLASSFACTORY pcf;
  128. ENTER_DDRAW();
  129. TRY
  130. {
  131. pcf = (LPDDRAWCLASSFACTORY)this;
  132. if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
  133. {
  134. DPF_ERR( "Invalid this ptr" );
  135. LEAVE_DDRAW();
  136. return (ULONG)E_FAIL;
  137. }
  138. pcf->dwRefCnt--;
  139. }
  140. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  141. {
  142. DPF_ERR( "Exception encountered validating parameters" );
  143. LEAVE_DDRAW();
  144. return (ULONG)E_INVALIDARG;
  145. }
  146. DPF( 5, "ClassFactory::Release, dwRefCnt=%ld", pcf->dwRefCnt );
  147. if( pcf->dwRefCnt != 0 )
  148. {
  149. LEAVE_DDRAW();
  150. return pcf->dwRefCnt;
  151. }
  152. MemFree( pcf );
  153. LEAVE_DDRAW();
  154. return 0;
  155. } /* DirectDrawClassFactory_Release */
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "DirectDrawClassFactory::CreateInstance"
  158. /*
  159. * DirectDrawClassFactory_CreateInstance
  160. *
  161. * Creates an instance of a DirectDraw object
  162. */
  163. STDMETHODIMP DirectDrawClassFactory_CreateInstance(
  164. LPCLASSFACTORY this,
  165. LPUNKNOWN pUnkOuter,
  166. REFIID riid,
  167. LPVOID *ppvObj
  168. )
  169. {
  170. HRESULT hr = DD_OK;
  171. LPDDRAWI_DIRECTDRAW_INT pdrv_int = NULL;
  172. LPDDRAWCLASSFACTORY pcf;
  173. LPDIRECTDRAWCLIPPER pclipper;
  174. DPF( 2, A, "ClassFactory::CreateInstance" );
  175. pcf = (LPDDRAWCLASSFACTORY) this;
  176. if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
  177. {
  178. DPF_ERR( "Invalid this ptr" );
  179. return E_INVALIDARG;
  180. }
  181. if( !VALIDEX_IID_PTR( riid ) )
  182. {
  183. DPF_ERR( "Invalid iid ptr" );
  184. return E_INVALIDARG;
  185. }
  186. if( !VALIDEX_PTR_PTR( ppvObj ) )
  187. {
  188. DPF_ERR( "Invalid object ptr" );
  189. return E_INVALIDARG;
  190. }
  191. #ifdef POSTPONED
  192. if (pUnkOuter && !IsEqualIID(riid,&IID_IUnknown))
  193. {
  194. DPF_ERR("Can't aggregate with a punkouter != IUnknown");
  195. return CLASS_E_NOAGGREGATION;
  196. }
  197. #else
  198. if (pUnkOuter)
  199. {
  200. return CLASS_E_NOAGGREGATION;
  201. }
  202. #endif
  203. /*
  204. * is DirectDraw supported on this system?
  205. */
  206. if( !DirectDrawSupported( TRUE ) )
  207. {
  208. DPF_ERR( "DirectDraw not supported!" );
  209. return E_FAIL;
  210. }
  211. /*
  212. * go build an DirectDraw interface
  213. *
  214. * NOTE: We provide the "uninitialized callback table
  215. * to prevent the use of this object for anything other
  216. * than AddRef(), Release() or Initialized().
  217. */
  218. ENTER_DDRAW();
  219. if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDraw ) ||
  220. IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDraw7 ) )
  221. {
  222. if ( IsEqualIID(riid, &IID_IUnknown) )
  223. {
  224. /*
  225. * If we're aggregated, then we don't need to worry about the IUnknown being
  226. * the runtime identity (we are hidden inside the outer, since it's the one
  227. * that will field the QI for IUnknown).
  228. * This means we can point an aggregated interface at the nondelegating
  229. * unknowns
  230. */
  231. if (pUnkOuter)
  232. {
  233. #ifdef POSTPONED
  234. pdrv_int = NewDriverInterface( NULL, &ddUninitNonDelegatingUnknownCallbacks );
  235. #else
  236. pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
  237. #endif
  238. }
  239. else
  240. {
  241. /*
  242. * Not aggregated, so the IUnknown has to have the same pointer value
  243. * as the IDirectDraw interfaces, since QI always simply returns the
  244. * this ptr when asked for IUnknown
  245. * (Note this actually doesn't work right now because Initalize will swap
  246. * vtbls).
  247. */
  248. pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
  249. }
  250. }
  251. else if ( IsEqualIID(riid, &IID_IDirectDraw) )
  252. {
  253. pdrv_int = NewDriverInterface( NULL, &ddUninitCallbacks );
  254. }
  255. else if ( IsEqualIID(riid, &IID_IDirectDraw2) )
  256. {
  257. pdrv_int = NewDriverInterface( NULL, &dd2UninitCallbacks );
  258. }
  259. else if ( IsEqualIID(riid, &IID_IDirectDraw4) )
  260. {
  261. pdrv_int = NewDriverInterface( NULL, &dd4UninitCallbacks );
  262. }
  263. else if ( IsEqualIID(riid, &IID_IDirectDraw7) )
  264. {
  265. pdrv_int = NewDriverInterface( NULL, &dd7UninitCallbacks );
  266. }
  267. if( NULL == pdrv_int )
  268. {
  269. DPF( 0, "Call to NewDriverInterface failed" );
  270. hr = E_OUTOFMEMORY;
  271. }
  272. #ifdef POSTPONED
  273. /*
  274. *
  275. */
  276. if (pUnkOuter)
  277. {
  278. pdrv_int->lpLcl->pUnkOuter = pUnkOuter;
  279. }
  280. else
  281. {
  282. pdrv_int->lpLcl->pUnkOuter = (IUnknown*) &UninitNonDelegatingIUnknownInterface;
  283. }
  284. #endif
  285. pdrv_int->dwIntRefCnt--;
  286. pdrv_int->lpLcl->dwLocalRefCnt--;
  287. /*
  288. * NOTE: We call DD_QueryInterface() explicitly rather than
  289. * going through the vtable as the "uninitialized" interface
  290. * we are using here has QueryInterface() disabled.
  291. */
  292. if (SUCCEEDED(hr))
  293. {
  294. hr = DD_QueryInterface( (LPDIRECTDRAW) pdrv_int, riid, ppvObj );
  295. if( FAILED( hr ) )
  296. {
  297. DPF( 0, "Could not get interface id, hr=%08lx", hr );
  298. RemoveLocalFromList( pdrv_int->lpLcl );
  299. RemoveDriverFromList( pdrv_int, FALSE );
  300. MemFree( pdrv_int->lpLcl );
  301. MemFree( pdrv_int );
  302. }
  303. else
  304. {
  305. DPF( 5, "New Interface=%08lx", *ppvObj );
  306. }
  307. }
  308. }
  309. else
  310. if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDrawClipper ) )
  311. {
  312. /*
  313. * Build a new clipper.
  314. *
  315. * Unlike the DirectDraw driver objects, clippers create via
  316. * CoCreateInstance() are born pretty much initialized. The only
  317. * thing initialization might actually do is to reparent the
  318. * clipper to a given driver object. Otherwise all Initialize()
  319. * does is set a flag.
  320. */
  321. hr = InternalCreateClipper( NULL, 0UL, &pclipper, NULL, FALSE, NULL, NULL );
  322. if( FAILED( hr ) )
  323. {
  324. DPF_ERR( "Failed to create the new clipper interface" );
  325. }
  326. /*
  327. * NOTE: Bizarre code fragment below works as follows:
  328. *
  329. * 1) InternalCreateClipper() returns a clipper with a reference count
  330. * of 1 for each of the interface, local and global objects.
  331. * 2) QueryInterface() can do one of two things. It can either just return
  332. * the same interface in which case the interface, local and global
  333. * objects all get a reference count of 2 or it can return a different
  334. * interface in which case both interfaces have a reference count of
  335. * 1 and the local and global objects have a reference count of 2.
  336. * 3) The immediate Release() following the QueryInterface() will in either
  337. * case decrement the reference counts of the local and global objects
  338. * to 1 (as required). If the same interface was returned by
  339. * QueryInterface() then its reference count is decremented to 1 (as
  340. * required). If a different interface was returned then the old
  341. * interface is decremented to zero and it is released (as required).
  342. * Also, if QueryInterface() fails, the Release() will decrement all
  343. * the reference counts to 0 and the object will be freed.
  344. *
  345. * So it all makes perfect sense - really! (CMcC)
  346. *
  347. * ALSO NOTE: We call DD_Clipper_QueryInterface() explicitly rather than
  348. * going through the vtable as the "uninitialized" interface we are using
  349. * here has QueryInterface() disabled.
  350. */
  351. hr = DD_Clipper_QueryInterface( pclipper, riid, ppvObj );
  352. DD_Clipper_Release( pclipper );
  353. if( FAILED( hr ) )
  354. {
  355. DPF( 0, "Could not get interface id, hr=%08lx", hr );
  356. }
  357. else
  358. {
  359. DPF( 5, "New Interface=%08lx", *ppvObj );
  360. }
  361. }
  362. #ifdef POSTPONED
  363. else if ( IsEqualIID(&pcf->TargetCLSID, &CLSID_DirectDrawFactory2) )
  364. {
  365. LPDDFACTORY2 lpDDFac = NULL;
  366. /*
  367. * Build a new DirectDrawFactory2
  368. * This returns an object, with refcnt=0. The QI then bumps that to 1.
  369. */
  370. hr = InternalCreateDDFactory2( &lpDDFac, pUnkOuter );
  371. if( SUCCEEDED( hr ) )
  372. {
  373. /*
  374. * The QI should catch that the vtable is the ddrawfactory2 vtable,
  375. * and simply bump the addref on the passed-in pointer. This means we
  376. * won't orphan the pointer created by InternalCreateDDFactory2.
  377. */
  378. hr = ((IUnknown*)lpDDFac)->lpVtbl->QueryInterface( (IUnknown*)lpDDFac, riid, ppvObj );
  379. if( SUCCEEDED( hr ) )
  380. {
  381. DPF( 5, "New DDFactory2 Interface=%08lx", *ppvObj );
  382. }
  383. else
  384. {
  385. MemFree(lpDDFac);
  386. DPF( 0, "Could not get DDFactory2 interface id, hr=%08lx", hr );
  387. }
  388. }
  389. else
  390. {
  391. DPF_ERR( "Failed to create the new dd factory2 interface" );
  392. }
  393. }
  394. #endif
  395. LEAVE_DDRAW();
  396. return hr;
  397. } /* DirectDrawClassFactory_CreateInstance */
  398. #undef DPF_MODNAME
  399. #define DPF_MODNAME "DirectDrawClassFactory::LockServer"
  400. /*
  401. * DirectDrawClassFactory_LockServer
  402. *
  403. * Called to force our DLL to stayed loaded
  404. */
  405. STDMETHODIMP DirectDrawClassFactory_LockServer(
  406. LPCLASSFACTORY this,
  407. BOOL fLock
  408. )
  409. {
  410. HRESULT hr;
  411. HANDLE hdll;
  412. LPDDRAWCLASSFACTORY pcf;
  413. pcf = (LPDDRAWCLASSFACTORY) this;
  414. if( !VALIDEX_DIRECTDRAWCF_PTR( pcf ) )
  415. {
  416. DPF_ERR( "Invalid this ptr" );
  417. return E_INVALIDARG;
  418. }
  419. /*
  420. * call CoLockObjectExternal
  421. */
  422. DPF( 2, A, "ClassFactory::LockServer" );
  423. hr = E_UNEXPECTED;
  424. hdll = LoadLibrary( "OLE32.DLL" );
  425. if( hdll != NULL )
  426. {
  427. HRESULT (WINAPI * lpCoLockObjectExternal)(LPUNKNOWN, BOOL, BOOL );
  428. lpCoLockObjectExternal = (LPVOID) GetProcAddress( hdll, "CoLockObjectExternal" );
  429. if( lpCoLockObjectExternal != NULL )
  430. {
  431. hr = lpCoLockObjectExternal( (LPUNKNOWN) this, fLock, TRUE );
  432. }
  433. else
  434. {
  435. DPF_ERR( "Error! Could not get procaddr for CoLockObjectExternal" );
  436. }
  437. }
  438. else
  439. {
  440. DPF_ERR( "Error! Could not load OLE32.DLL" );
  441. }
  442. /*
  443. * track the number of server locks total
  444. */
  445. if( SUCCEEDED( hr ) )
  446. {
  447. ENTER_DDRAW();
  448. if( fLock )
  449. {
  450. dwLockCount++;
  451. }
  452. else
  453. {
  454. #ifdef DEBUG
  455. if( (int) dwLockCount <= 0 )
  456. {
  457. DPF( 0, "Invalid LockCount in LockServer! (%d)", dwLockCount );
  458. DEBUG_BREAK();
  459. }
  460. #endif
  461. dwLockCount--;
  462. }
  463. DPF( 5, "LockServer:dwLockCount =%ld", dwLockCount );
  464. LEAVE_DDRAW();
  465. }
  466. return hr;
  467. } /* DirectDrawClassFactory_LockServer */
  468. #undef DPF_MODNAME
  469. #define DPF_MODNAME "DirectDrawClassFactory::CreateInstance"
  470. static IClassFactoryVtbl directDrawClassFactoryVtbl =
  471. {
  472. DirectDrawClassFactory_QueryInterface,
  473. DirectDrawClassFactory_AddRef,
  474. DirectDrawClassFactory_Release,
  475. DirectDrawClassFactory_CreateInstance,
  476. DirectDrawClassFactory_LockServer
  477. };
  478. #undef DPF_MODNAME
  479. #define DPF_MODNAME "DllGetClassObject"
  480. /*
  481. * DllGetClassObject
  482. *
  483. * Entry point called by COM to get a ClassFactory pointer
  484. */
  485. HRESULT WINAPI DllGetClassObject(
  486. REFCLSID rclsid,
  487. REFIID riid,
  488. LPVOID *ppvObj )
  489. {
  490. LPDDRAWCLASSFACTORY pcf;
  491. HRESULT hr;
  492. /*
  493. * validate parms
  494. */
  495. if( !VALIDEX_PTR_PTR( ppvObj ) )
  496. {
  497. DPF_ERR( "Invalid object ptr" );
  498. return E_INVALIDARG;
  499. }
  500. *ppvObj = NULL;
  501. if( !VALIDEX_IID_PTR( rclsid ) )
  502. {
  503. DPF_ERR( "Invalid clsid ptr" );
  504. return E_INVALIDARG;
  505. }
  506. if( !VALIDEX_IID_PTR( riid ) )
  507. {
  508. DPF_ERR( "Invalid iid ptr" );
  509. return E_INVALIDARG;
  510. }
  511. /*
  512. * is this one our class ids?
  513. */
  514. if( IsEqualCLSID( rclsid, &CLSID_DirectDraw ) ||
  515. IsEqualCLSID( rclsid, &CLSID_DirectDraw7 ) ||
  516. IsEqualCLSID( rclsid, &CLSID_DirectDrawClipper ) ||
  517. IsEqualCLSID( rclsid, &CLSID_DirectDrawFactory2 ))
  518. {
  519. /*
  520. * It's the DirectDraw driver class ID.
  521. */
  522. /*
  523. * only allow IUnknown and IClassFactory
  524. */
  525. if( !IsEqualIID( riid, &IID_IUnknown ) &&
  526. !IsEqualIID( riid, &IID_IClassFactory ) )
  527. {
  528. return E_NOINTERFACE;
  529. }
  530. /*
  531. * create a class factory object
  532. */
  533. ENTER_DDRAW();
  534. pcf = MemAlloc( sizeof( DDRAWCLASSFACTORY ) );
  535. if( pcf == NULL )
  536. {
  537. LEAVE_DDRAW();
  538. return E_OUTOFMEMORY;
  539. }
  540. pcf->lpVtbl = &directDrawClassFactoryVtbl;
  541. pcf->dwRefCnt = 0;
  542. memcpy(&pcf->TargetCLSID,rclsid,sizeof(*rclsid));
  543. #pragma message( REMIND( "Do we need to have a refcnt of 0 after DllGetClassObject?" ))
  544. hr = DirectDrawClassFactory_QueryInterface( (LPCLASSFACTORY) pcf, riid, ppvObj );
  545. if( FAILED( hr ) )
  546. {
  547. MemFree( pcf );
  548. *ppvObj = NULL;
  549. DPF( 0, "QueryInterface failed, rc=%08lx", hr );
  550. }
  551. else
  552. {
  553. DPF( 5, "DllGetClassObject succeeded, pcf=%08lx", pcf );
  554. }
  555. LEAVE_DDRAW();
  556. return hr;
  557. }
  558. else
  559. {
  560. return E_FAIL;
  561. }
  562. } /* DllGetClassObject */
  563. /*
  564. * DllCanUnloadNow
  565. *
  566. * Entry point called by COM to see if it is OK to free our DLL
  567. */
  568. HRESULT WINAPI DllCanUnloadNow( void )
  569. {
  570. HRESULT hr;
  571. DPF( 2, A, "DllCanUnloadNow called" );
  572. hr = S_FALSE;
  573. ENTER_DDRAW();
  574. /*
  575. * Only unload if there are no driver objects and no global
  576. * clipper objects (there won't be any local clipper objects
  577. * as they are destroyed by their driver so the check on driver
  578. * object handles them).
  579. */
  580. if( ( lpDriverObjectList == NULL ) &&
  581. ( lpDriverLocalList == NULL ) &&
  582. ( lpGlobalClipperList == NULL ) )
  583. {
  584. if( dwLockCount == 0 )
  585. {
  586. DPF( 3, "It is OK to unload" );
  587. hr = S_OK;
  588. }
  589. }
  590. LEAVE_DDRAW();
  591. return hr;
  592. } /* DllCanUnloadNow */