videoctl.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:21k
源码类别:

P2P编程

开发平台:

Visual C++

  1. //------------------------------------------------------------------------------
  2. // File: VideoCtl.cpp
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #include <streams.h>
  9. #include "ddmm.h"
  10. // Load a string from the resource file string table. The buffer must be at
  11. // least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
  12. // buffer in the property page class and use it for all string loading. It
  13. // cannot be static as multiple property pages may be active simultaneously
  14. TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID)
  15. {
  16.     if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  17.         return TEXT("");
  18.     }
  19.     return pBuffer;
  20. }
  21. #ifdef UNICODE
  22. char *WINAPI StringFromResource(char *pBuffer, int iResourceID)
  23. {
  24.     if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
  25.         return "";
  26.     }
  27.     return pBuffer;
  28. }
  29. #endif
  30. // Property pages typically are called through their OLE interfaces. These
  31. // use UNICODE strings regardless of how the binary is built. So when we
  32. // load strings from the resource file we sometimes want to convert them
  33. // to UNICODE. This method is passed the target UNICODE buffer and does a
  34. // convert after loading the string (if built UNICODE this is not needed)
  35. // On WinNT we can explicitly call LoadStringW which saves two conversions
  36. #ifndef UNICODE
  37. WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID)
  38. {
  39.     *pBuffer = 0;
  40.     if (g_amPlatform == VER_PLATFORM_WIN32_NT) {
  41. LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
  42.     } else {
  43. CHAR szBuffer[STR_MAX_LENGTH];
  44. DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH);
  45. // if we loaded a string convert it to wide characters, ensuring
  46. // that we also null terminate the result.
  47. if (dwStringLength++) {
  48.     MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH);
  49. }
  50.     }
  51.     return pBuffer;
  52. }
  53. #endif
  54. // Helper function to calculate the size of the dialog
  55. BOOL WINAPI GetDialogSize(int iResourceID,
  56.                           DLGPROC pDlgProc,
  57.                           LPARAM lParam,
  58.                           SIZE *pResult)
  59. {
  60.     RECT rc;
  61.     HWND hwnd;
  62.     // Create a temporary property page
  63.     hwnd = CreateDialogParam(g_hInst,
  64.                              MAKEINTRESOURCE(iResourceID),
  65.                              GetDesktopWindow(),
  66.                              pDlgProc,
  67.                              lParam);
  68.     if (hwnd == NULL) {
  69.         return FALSE;
  70.     }
  71.     GetWindowRect(hwnd, &rc);
  72.     pResult->cx = rc.right - rc.left;
  73.     pResult->cy = rc.bottom - rc.top;
  74.     DestroyWindow(hwnd);
  75.     return TRUE;
  76. }
  77. // Class that aggregates on the IDirectDraw interface. Although DirectDraw
  78. // has the ability in its interfaces to be aggregated they're not currently
  79. // implemented. This makes it difficult for various parts of Quartz that want
  80. // to aggregate these interfaces. In particular the video renderer passes out
  81. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  82. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  83. // objects we provide these aggregation classes that republish the interfaces
  84. STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  85. {
  86.     ASSERT(m_pDirectDraw);
  87.     // Do we have this interface
  88.     if (riid == IID_IDirectDraw) {
  89.         return GetInterface((IDirectDraw *)this,ppv);
  90.     } else {
  91.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  92.     }
  93. }
  94. STDMETHODIMP CAggDirectDraw::Compact()
  95. {
  96.     ASSERT(m_pDirectDraw);
  97.     return m_pDirectDraw->Compact();
  98. }
  99. STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter)
  100. {
  101.     ASSERT(m_pDirectDraw);
  102.     return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
  103. }
  104. STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter)
  105. {
  106.     ASSERT(m_pDirectDraw);
  107.     return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
  108. }
  109. STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter)
  110. {
  111.     ASSERT(m_pDirectDraw);
  112.     return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
  113. }
  114. STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface)
  115. {
  116.     ASSERT(m_pDirectDraw);
  117.     return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
  118. }
  119. STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback)
  120. {
  121.     ASSERT(m_pDirectDraw);
  122.     return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
  123. }
  124. STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback)
  125. {
  126.     ASSERT(m_pDirectDraw);
  127.     return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
  128. }
  129. STDMETHODIMP CAggDirectDraw::FlipToGDISurface()
  130. {
  131.     ASSERT(m_pDirectDraw);
  132.     return m_pDirectDraw->FlipToGDISurface();
  133. }
  134. STDMETHODIMP CAggDirectDraw::GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps)
  135. {
  136.     ASSERT(m_pDirectDraw);
  137.     return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
  138. }
  139. STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
  140. {
  141.     ASSERT(m_pDirectDraw);
  142.     return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
  143. }
  144. STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes)
  145. {
  146.     ASSERT(m_pDirectDraw);
  147.     return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
  148. }
  149. STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
  150. {
  151.     ASSERT(m_pDirectDraw);
  152.     return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
  153. }
  154. STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency)
  155. {
  156.     ASSERT(m_pDirectDraw);
  157.     return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
  158. }
  159. STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine)
  160. {
  161.     ASSERT(m_pDirectDraw);
  162.     return m_pDirectDraw->GetScanLine(lpdwScanLine);
  163. }
  164. STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB)
  165. {
  166.     ASSERT(m_pDirectDraw);
  167.     return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
  168. }
  169. STDMETHODIMP CAggDirectDraw::Initialize(GUID *lpGUID)
  170. {
  171.     ASSERT(m_pDirectDraw);
  172.     return m_pDirectDraw->Initialize(lpGUID);
  173. }
  174. STDMETHODIMP CAggDirectDraw::RestoreDisplayMode()
  175. {
  176.     ASSERT(m_pDirectDraw);
  177.     return m_pDirectDraw->RestoreDisplayMode();
  178. }
  179. STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags)
  180. {
  181.     ASSERT(m_pDirectDraw);
  182.     return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
  183. }
  184. STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp)
  185. {
  186.     ASSERT(m_pDirectDraw);
  187.     return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
  188. }
  189. STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent)
  190. {
  191.     ASSERT(m_pDirectDraw);
  192.     return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
  193. }
  194. // Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
  195. // has the ability in its interfaces to be aggregated they're not currently
  196. // implemented. This makes it difficult for various parts of Quartz that want
  197. // to aggregate these interfaces. In particular the video renderer passes out
  198. // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
  199. // graph manager also exposes IDirectDraw as a plug in distributor. For these
  200. // objects we provide these aggregation classes that republish the interfaces
  201. STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  202. {
  203.     ASSERT(m_pDirectDrawSurface);
  204.     // Do we have this interface
  205.     if (riid == IID_IDirectDrawSurface) {
  206.         return GetInterface((IDirectDrawSurface *)this,ppv);
  207.     } else {
  208.         return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  209.     }
  210. }
  211. STDMETHODIMP CAggDrawSurface::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
  212. {
  213.     ASSERT(m_pDirectDrawSurface);
  214.     return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
  215. }
  216. STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect)
  217. {
  218.     ASSERT(m_pDirectDrawSurface);
  219.     return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
  220. }
  221. STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx)
  222. {
  223.     ASSERT(m_pDirectDrawSurface);
  224.     return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
  225. }
  226. STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
  227. {
  228.     ASSERT(m_pDirectDrawSurface);
  229.     return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
  230. }
  231. STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans)
  232. {
  233.     ASSERT(m_pDirectDrawSurface);
  234.     return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
  235. }
  236. STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
  237. {
  238.     ASSERT(m_pDirectDrawSurface);
  239.     return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
  240. }
  241. STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
  242. {
  243.     ASSERT(m_pDirectDrawSurface);
  244.     return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
  245. }
  246. STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback)
  247. {
  248.     ASSERT(m_pDirectDrawSurface);
  249.     return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
  250. }
  251. STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
  252. {
  253.     ASSERT(m_pDirectDrawSurface);
  254.     return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
  255. }
  256. STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface)
  257. {
  258.     ASSERT(m_pDirectDrawSurface);
  259.     return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
  260. }
  261. STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags)
  262. {
  263.     ASSERT(m_pDirectDrawSurface);
  264.     return m_pDirectDrawSurface->GetBltStatus(dwFlags);
  265. }
  266. STDMETHODIMP CAggDrawSurface::GetCaps(LPDDSCAPS lpDDSCaps)
  267. {
  268.     ASSERT(m_pDirectDrawSurface);
  269.     return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
  270. }
  271. STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper)
  272. {
  273.     ASSERT(m_pDirectDrawSurface);
  274.     return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
  275. }
  276. STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
  277. {
  278.     ASSERT(m_pDirectDrawSurface);
  279.     return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
  280. }
  281. STDMETHODIMP CAggDrawSurface::GetDC(HDC *lphDC)
  282. {
  283.     ASSERT(m_pDirectDrawSurface);
  284.     return m_pDirectDrawSurface->GetDC(lphDC);
  285. }
  286. STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags)
  287. {
  288.     ASSERT(m_pDirectDrawSurface);
  289.     return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
  290. }
  291. STDMETHODIMP CAggDrawSurface::GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY)
  292. {
  293.     ASSERT(m_pDirectDrawSurface);
  294.     return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
  295. }
  296. STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette)
  297. {
  298.     ASSERT(m_pDirectDrawSurface);
  299.     return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
  300. }
  301. STDMETHODIMP CAggDrawSurface::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
  302. {
  303.     ASSERT(m_pDirectDrawSurface);
  304.     return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
  305. }
  306. // A bit of a warning here: Our media samples in DirectShow aggregate on
  307. // IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
  308. // by QueryInterface). Unfortunately the underlying DirectDraw code cannot
  309. // be aggregated so we have to use these classes. The snag is that when we
  310. // call a different surface and pass in this interface as perhaps the source
  311. // surface the call will fail because DirectDraw dereferences the pointer to
  312. // get at its private data structures. Therefore we supply this workaround to give
  313. // access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
  314. // and we will fill in the lpSurface pointer with the real underlying surface
  315. STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
  316. {
  317.     ASSERT(m_pDirectDrawSurface);
  318.     // First call down to the underlying DirectDraw
  319.     HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
  320.     if (FAILED(hr)) {
  321.         return hr;
  322.     }
  323.     // Store the real DirectDrawSurface interface
  324.     lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
  325.     return hr;
  326. }
  327. STDMETHODIMP CAggDrawSurface::Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc)
  328. {
  329.     ASSERT(m_pDirectDrawSurface);
  330.     return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
  331. }
  332. STDMETHODIMP CAggDrawSurface::IsLost()
  333. {
  334.     ASSERT(m_pDirectDrawSurface);
  335.     return m_pDirectDrawSurface->IsLost();
  336. }
  337. STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent)
  338. {
  339.     ASSERT(m_pDirectDrawSurface);
  340.     return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
  341. }
  342. STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC)
  343. {
  344.     ASSERT(m_pDirectDrawSurface);
  345.     return m_pDirectDrawSurface->ReleaseDC(hDC);
  346. }
  347. STDMETHODIMP CAggDrawSurface::Restore()
  348. {
  349.     ASSERT(m_pDirectDrawSurface);
  350.     return m_pDirectDrawSurface->Restore();
  351. }
  352. STDMETHODIMP CAggDrawSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
  353. {
  354.     ASSERT(m_pDirectDrawSurface);
  355.     return m_pDirectDrawSurface->SetClipper(lpDDClipper);
  356. }
  357. STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
  358. {
  359.     ASSERT(m_pDirectDrawSurface);
  360.     return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
  361. }
  362. STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY)
  363. {
  364.     ASSERT(m_pDirectDrawSurface);
  365.     return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
  366. }
  367. STDMETHODIMP CAggDrawSurface::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
  368. {
  369.     ASSERT(m_pDirectDrawSurface);
  370.     return m_pDirectDrawSurface->SetPalette(lpDDPalette);
  371. }
  372. STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData)
  373. {
  374.     ASSERT(m_pDirectDrawSurface);
  375.     return m_pDirectDrawSurface->Unlock(lpSurfaceData);
  376. }
  377. STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX)
  378. {
  379.     ASSERT(m_pDirectDrawSurface);
  380.     return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
  381. }
  382. STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags)
  383. {
  384.     ASSERT(m_pDirectDrawSurface);
  385.     return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
  386. }
  387. STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference)
  388. {
  389.     ASSERT(m_pDirectDrawSurface);
  390.     return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
  391. }
  392. // DirectShow must work on multiple platforms.  In particular, it also runs on
  393. // Windows NT 3.51 which does not have DirectDraw capabilities. The filters
  394. // cannot therefore link statically to the DirectDraw library. To make their
  395. // lives that little bit easier we provide this class that manages loading
  396. // and unloading the library and creating the initial IDirectDraw interface
  397. CLoadDirectDraw::CLoadDirectDraw() :
  398.     m_pDirectDraw(NULL),
  399.     m_hDirectDraw(NULL)
  400. {
  401. }
  402. // Destructor forces unload
  403. CLoadDirectDraw::~CLoadDirectDraw()
  404. {
  405.     ReleaseDirectDraw();
  406.     if (m_hDirectDraw) {
  407.         NOTE("Unloading library");
  408.         FreeLibrary(m_hDirectDraw);
  409.     }
  410. }
  411. // We can't be sure that DirectDraw is always available so we can't statically
  412. // link to the library. Therefore we load the library, get the function entry
  413. // point addresses and call them to create the driver objects. We return S_OK
  414. // if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
  415. // We initialise a DirectDraw instance by explicitely loading the library and
  416. // calling GetProcAddress on the DirectDrawCreate entry point that it exports
  417. // On a multi monitor system, we can get the DirectDraw object for any
  418. // monitor (device) with the optional szDevice parameter
  419. HRESULT CLoadDirectDraw::LoadDirectDraw(LPSTR szDevice)
  420. {
  421.     PDRAWCREATE pDrawCreate;
  422.     PDRAWENUM pDrawEnum;
  423.     LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
  424.     HRESULT hr = NOERROR;
  425.     NOTE("Entering DoLoadDirectDraw");
  426.     // Is DirectDraw already loaded
  427.     if (m_pDirectDraw) {
  428.         NOTE("Already loaded");
  429.         ASSERT(m_hDirectDraw);
  430.         return NOERROR;
  431.     }
  432.     // Make sure the library is available
  433.     if(!m_hDirectDraw)
  434.     {
  435.         UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  436.         m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
  437.         SetErrorMode(ErrorMode);
  438.         if (m_hDirectDraw == NULL) {
  439.             DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
  440.             NOTE("No library");
  441.             return E_NOINTERFACE;
  442.         }
  443.     }
  444.     // Get the DLL address for the creator function
  445.     pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
  446.     // force ANSI, we assume it
  447.     pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
  448.     pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
  449. "DirectDrawEnumerateExA");
  450.     // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
  451.     if (pDrawCreate == NULL || pDrawEnum == NULL) {
  452.         DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
  453. pDrawCreate, pDrawEnum));
  454.         NOTE("No entry point");
  455.         ReleaseDirectDraw();
  456.         return E_NOINTERFACE;
  457.     }
  458.     DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
  459. szDevice ? szDevice : "<NULL>"));
  460.     // Create a DirectDraw display provider for this device, using the fancy
  461.     // multimon-aware version, if it exists
  462.     if (pDrawEnumEx)
  463.         m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
  464. pDrawEnumEx);
  465.     else
  466.         m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
  467. pDrawEnum);
  468.     if (m_pDirectDraw == NULL) {
  469.             DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
  470.             NOTE("No instance");
  471.             ReleaseDirectDraw();
  472.             return E_NOINTERFACE;
  473.     }
  474.     return NOERROR;
  475. }
  476. // Called to release any DirectDraw provider we previously loaded. We may be
  477. // called at any time especially when something goes horribly wrong and when
  478. // we need to clean up before returning so we can't guarantee that all state
  479. // variables are consistent so free only those really allocated allocated
  480. // This should only be called once all reference counts have been released
  481. void CLoadDirectDraw::ReleaseDirectDraw()
  482. {
  483.     NOTE("Releasing DirectDraw driver");
  484.     // Release any DirectDraw provider interface
  485.     if (m_pDirectDraw) {
  486.         NOTE("Releasing instance");
  487.         m_pDirectDraw->Release();
  488.         m_pDirectDraw = NULL;
  489.     }
  490. }
  491. // Return NOERROR (S_OK) if DirectDraw has been loaded by this object
  492. HRESULT CLoadDirectDraw::IsDirectDrawLoaded()
  493. {
  494.     NOTE("Entering IsDirectDrawLoaded");
  495.     if (m_pDirectDraw == NULL) {
  496.         NOTE("DirectDraw not loaded");
  497.         return S_FALSE;
  498.     }
  499.     return NOERROR;
  500. }
  501. // Return the IDirectDraw interface we look after
  502. LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw()
  503. {
  504.     NOTE("Entering GetDirectDraw");
  505.     if (m_pDirectDraw == NULL) {
  506.         NOTE("No DirectDraw");
  507.         return NULL;
  508.     }
  509.     NOTE("Returning DirectDraw");
  510.     m_pDirectDraw->AddRef();
  511.     return m_pDirectDraw;
  512. }
  513. // Are we running on Direct Draw version 1?  We need to find out as
  514. // we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
  515. // find out, we simply see if it supports IDirectDraw2.  Only version 2 and
  516. // higher support this.
  517. BOOL CLoadDirectDraw::IsDirectDrawVersion1()
  518. {
  519.     if (m_pDirectDraw == NULL)
  520. return FALSE;
  521.     IDirectDraw2 *p = NULL;
  522.     HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
  523.     if (p)
  524. p->Release();
  525.     if (hr == NOERROR) {
  526.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
  527. return FALSE;
  528.     } else {
  529.         DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
  530. return TRUE;
  531.     }
  532. }