Support unrar64.dll
[xy_vsfilter.git] / src / filters / BaseClasses / videoctl.cpp
blob06f2d5860e1ccbb26fbd9067886b6954a57284d8
1 //------------------------------------------------------------------------------
2 // File: VideoCtl.cpp
3 //
4 // Desc: DirectShow base classes.
5 //
6 // Copyright (c) 1992-2002 Microsoft Corporation. All rights reserved.
7 //------------------------------------------------------------------------------
10 #include <streams.h>
11 #include "ddmm.h"
13 // Load a string from the resource file string table. The buffer must be at
14 // least STR_MAX_LENGTH bytes. The easiest way to use this is to declare a
15 // buffer in the property page class and use it for all string loading. It
16 // cannot be static as multiple property pages may be active simultaneously
18 TCHAR *WINAPI StringFromResource(TCHAR *pBuffer, int iResourceID)
20 if (LoadString(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
21 return TEXT("");
23 return pBuffer;
26 #ifdef UNICODE
27 char *WINAPI StringFromResource(char *pBuffer, int iResourceID)
29 if (LoadStringA(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH) == 0) {
30 return "";
32 return pBuffer;
34 #endif
38 // Property pages typically are called through their OLE interfaces. These
39 // use UNICODE strings regardless of how the binary is built. So when we
40 // load strings from the resource file we sometimes want to convert them
41 // to UNICODE. This method is passed the target UNICODE buffer and does a
42 // convert after loading the string (if built UNICODE this is not needed)
43 // On WinNT we can explicitly call LoadStringW which saves two conversions
45 #ifndef UNICODE
47 WCHAR * WINAPI WideStringFromResource(WCHAR *pBuffer, int iResourceID)
49 *pBuffer = 0;
51 if (g_amPlatform == VER_PLATFORM_WIN32_NT) {
52 LoadStringW(g_hInst,iResourceID,pBuffer,STR_MAX_LENGTH);
53 } else {
55 CHAR szBuffer[STR_MAX_LENGTH];
56 DWORD dwStringLength = LoadString(g_hInst,iResourceID,szBuffer,STR_MAX_LENGTH);
57 // if we loaded a string convert it to wide characters, ensuring
58 // that we also null terminate the result.
59 if (dwStringLength++) {
60 MultiByteToWideChar(CP_ACP,0,szBuffer,dwStringLength,pBuffer,STR_MAX_LENGTH);
63 return pBuffer;
66 #endif
69 // Helper function to calculate the size of the dialog
71 BOOL WINAPI GetDialogSize(int iResourceID,
72 DLGPROC pDlgProc,
73 LPARAM lParam,
74 SIZE *pResult)
76 RECT rc;
77 HWND hwnd;
79 // Create a temporary property page
81 hwnd = CreateDialogParam(g_hInst,
82 MAKEINTRESOURCE(iResourceID),
83 GetDesktopWindow(),
84 pDlgProc,
85 lParam);
86 if (hwnd == NULL) {
87 return FALSE;
90 GetWindowRect(hwnd, &rc);
91 pResult->cx = rc.right - rc.left;
92 pResult->cy = rc.bottom - rc.top;
94 DestroyWindow(hwnd);
95 return TRUE;
99 // Class that aggregates on the IDirectDraw interface. Although DirectDraw
100 // has the ability in its interfaces to be aggregated they're not currently
101 // implemented. This makes it difficult for various parts of Quartz that want
102 // to aggregate these interfaces. In particular the video renderer passes out
103 // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
104 // graph manager also exposes IDirectDraw as a plug in distributor. For these
105 // objects we provide these aggregation classes that republish the interfaces
107 STDMETHODIMP CAggDirectDraw::NonDelegatingQueryInterface(REFIID riid, void **ppv)
109 ASSERT(m_pDirectDraw);
111 // Do we have this interface
113 if (riid == IID_IDirectDraw) {
114 return GetInterface((IDirectDraw *)this,ppv);
115 } else {
116 return CUnknown::NonDelegatingQueryInterface(riid,ppv);
121 STDMETHODIMP CAggDirectDraw::Compact()
123 ASSERT(m_pDirectDraw);
124 return m_pDirectDraw->Compact();
128 STDMETHODIMP CAggDirectDraw::CreateClipper(DWORD dwFlags,LPDIRECTDRAWCLIPPER *lplpDDClipper,IUnknown *pUnkOuter)
130 ASSERT(m_pDirectDraw);
131 return m_pDirectDraw->CreateClipper(dwFlags,lplpDDClipper,pUnkOuter);
135 STDMETHODIMP CAggDirectDraw::CreatePalette(DWORD dwFlags,LPPALETTEENTRY lpColorTable,LPDIRECTDRAWPALETTE *lplpDDPalette,IUnknown *pUnkOuter)
137 ASSERT(m_pDirectDraw);
138 return m_pDirectDraw->CreatePalette(dwFlags,lpColorTable,lplpDDPalette,pUnkOuter);
142 STDMETHODIMP CAggDirectDraw::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc,LPDIRECTDRAWSURFACE *lplpDDSurface,IUnknown *pUnkOuter)
144 ASSERT(m_pDirectDraw);
145 return m_pDirectDraw->CreateSurface(lpDDSurfaceDesc,lplpDDSurface,pUnkOuter);
149 STDMETHODIMP CAggDirectDraw::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface,LPDIRECTDRAWSURFACE *lplpDupDDSurface)
151 ASSERT(m_pDirectDraw);
152 return m_pDirectDraw->DuplicateSurface(lpDDSurface,lplpDupDDSurface);
156 STDMETHODIMP CAggDirectDraw::EnumDisplayModes(DWORD dwSurfaceDescCount,LPDDSURFACEDESC lplpDDSurfaceDescList,LPVOID lpContext,LPDDENUMMODESCALLBACK lpEnumCallback)
158 ASSERT(m_pDirectDraw);
159 return m_pDirectDraw->EnumDisplayModes(dwSurfaceDescCount,lplpDDSurfaceDescList,lpContext,lpEnumCallback);
163 STDMETHODIMP CAggDirectDraw::EnumSurfaces(DWORD dwFlags,LPDDSURFACEDESC lpDDSD,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumCallback)
165 ASSERT(m_pDirectDraw);
166 return m_pDirectDraw->EnumSurfaces(dwFlags,lpDDSD,lpContext,lpEnumCallback);
170 STDMETHODIMP CAggDirectDraw::FlipToGDISurface()
172 ASSERT(m_pDirectDraw);
173 return m_pDirectDraw->FlipToGDISurface();
177 STDMETHODIMP CAggDirectDraw::GetCaps(LPDDCAPS lpDDDriverCaps,LPDDCAPS lpDDHELCaps)
179 ASSERT(m_pDirectDraw);
180 return m_pDirectDraw->GetCaps(lpDDDriverCaps,lpDDHELCaps);
184 STDMETHODIMP CAggDirectDraw::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
186 ASSERT(m_pDirectDraw);
187 return m_pDirectDraw->GetDisplayMode(lpDDSurfaceDesc);
191 STDMETHODIMP CAggDirectDraw::GetFourCCCodes(LPDWORD lpNumCodes,LPDWORD lpCodes)
193 ASSERT(m_pDirectDraw);
194 return m_pDirectDraw->GetFourCCCodes(lpNumCodes,lpCodes);
198 STDMETHODIMP CAggDirectDraw::GetGDISurface(LPDIRECTDRAWSURFACE *lplpGDIDDSurface)
200 ASSERT(m_pDirectDraw);
201 return m_pDirectDraw->GetGDISurface(lplpGDIDDSurface);
205 STDMETHODIMP CAggDirectDraw::GetMonitorFrequency(LPDWORD lpdwFrequency)
207 ASSERT(m_pDirectDraw);
208 return m_pDirectDraw->GetMonitorFrequency(lpdwFrequency);
212 STDMETHODIMP CAggDirectDraw::GetScanLine(LPDWORD lpdwScanLine)
214 ASSERT(m_pDirectDraw);
215 return m_pDirectDraw->GetScanLine(lpdwScanLine);
219 STDMETHODIMP CAggDirectDraw::GetVerticalBlankStatus(LPBOOL lpblsInVB)
221 ASSERT(m_pDirectDraw);
222 return m_pDirectDraw->GetVerticalBlankStatus(lpblsInVB);
226 STDMETHODIMP CAggDirectDraw::Initialize(GUID *lpGUID)
228 ASSERT(m_pDirectDraw);
229 return m_pDirectDraw->Initialize(lpGUID);
233 STDMETHODIMP CAggDirectDraw::RestoreDisplayMode()
235 ASSERT(m_pDirectDraw);
236 return m_pDirectDraw->RestoreDisplayMode();
240 STDMETHODIMP CAggDirectDraw::SetCooperativeLevel(HWND hWnd,DWORD dwFlags)
242 ASSERT(m_pDirectDraw);
243 return m_pDirectDraw->SetCooperativeLevel(hWnd,dwFlags);
247 STDMETHODIMP CAggDirectDraw::SetDisplayMode(DWORD dwWidth,DWORD dwHeight,DWORD dwBpp)
249 ASSERT(m_pDirectDraw);
250 return m_pDirectDraw->SetDisplayMode(dwWidth,dwHeight,dwBpp);
254 STDMETHODIMP CAggDirectDraw::WaitForVerticalBlank(DWORD dwFlags,HANDLE hEvent)
256 ASSERT(m_pDirectDraw);
257 return m_pDirectDraw->WaitForVerticalBlank(dwFlags,hEvent);
261 // Class that aggregates an IDirectDrawSurface interface. Although DirectDraw
262 // has the ability in its interfaces to be aggregated they're not currently
263 // implemented. This makes it difficult for various parts of Quartz that want
264 // to aggregate these interfaces. In particular the video renderer passes out
265 // media samples that expose IDirectDraw and IDirectDrawSurface. The filter
266 // graph manager also exposes IDirectDraw as a plug in distributor. For these
267 // objects we provide these aggregation classes that republish the interfaces
269 STDMETHODIMP CAggDrawSurface::NonDelegatingQueryInterface(REFIID riid, void **ppv)
271 ASSERT(m_pDirectDrawSurface);
273 // Do we have this interface
275 if (riid == IID_IDirectDrawSurface) {
276 return GetInterface((IDirectDrawSurface *)this,ppv);
277 } else {
278 return CUnknown::NonDelegatingQueryInterface(riid,ppv);
283 STDMETHODIMP CAggDrawSurface::AddAttachedSurface(LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
285 ASSERT(m_pDirectDrawSurface);
286 return m_pDirectDrawSurface->AddAttachedSurface(lpDDSAttachedSurface);
290 STDMETHODIMP CAggDrawSurface::AddOverlayDirtyRect(LPRECT lpRect)
292 ASSERT(m_pDirectDrawSurface);
293 return m_pDirectDrawSurface->AddOverlayDirtyRect(lpRect);
297 STDMETHODIMP CAggDrawSurface::Blt(LPRECT lpDestRect,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwFlags,LPDDBLTFX lpDDBltFx)
299 ASSERT(m_pDirectDrawSurface);
300 return m_pDirectDrawSurface->Blt(lpDestRect,lpDDSrcSurface,lpSrcRect,dwFlags,lpDDBltFx);
304 STDMETHODIMP CAggDrawSurface::BltBatch(LPDDBLTBATCH lpDDBltBatch,DWORD dwCount,DWORD dwFlags)
306 ASSERT(m_pDirectDrawSurface);
307 return m_pDirectDrawSurface->BltBatch(lpDDBltBatch,dwCount,dwFlags);
311 STDMETHODIMP CAggDrawSurface::BltFast(DWORD dwX,DWORD dwY,LPDIRECTDRAWSURFACE lpDDSrcSurface,LPRECT lpSrcRect,DWORD dwTrans)
313 ASSERT(m_pDirectDrawSurface);
314 return m_pDirectDrawSurface->BltFast(dwX,dwY,lpDDSrcSurface,lpSrcRect,dwTrans);
318 STDMETHODIMP CAggDrawSurface::DeleteAttachedSurface(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSAttachedSurface)
320 ASSERT(m_pDirectDrawSurface);
321 return m_pDirectDrawSurface->DeleteAttachedSurface(dwFlags,lpDDSAttachedSurface);
325 STDMETHODIMP CAggDrawSurface::EnumAttachedSurfaces(LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
327 ASSERT(m_pDirectDrawSurface);
328 return m_pDirectDrawSurface->EnumAttachedSurfaces(lpContext,lpEnumSurfacesCallback);
332 STDMETHODIMP CAggDrawSurface::EnumOverlayZOrders(DWORD dwFlags,LPVOID lpContext,LPDDENUMSURFACESCALLBACK lpfnCallback)
334 ASSERT(m_pDirectDrawSurface);
335 return m_pDirectDrawSurface->EnumOverlayZOrders(dwFlags,lpContext,lpfnCallback);
339 STDMETHODIMP CAggDrawSurface::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverride,DWORD dwFlags)
341 ASSERT(m_pDirectDrawSurface);
342 return m_pDirectDrawSurface->Flip(lpDDSurfaceTargetOverride,dwFlags);
346 STDMETHODIMP CAggDrawSurface::GetAttachedSurface(LPDDSCAPS lpDDSCaps,LPDIRECTDRAWSURFACE *lplpDDAttachedSurface)
348 ASSERT(m_pDirectDrawSurface);
349 return m_pDirectDrawSurface->GetAttachedSurface(lpDDSCaps,lplpDDAttachedSurface);
353 STDMETHODIMP CAggDrawSurface::GetBltStatus(DWORD dwFlags)
355 ASSERT(m_pDirectDrawSurface);
356 return m_pDirectDrawSurface->GetBltStatus(dwFlags);
360 STDMETHODIMP CAggDrawSurface::GetCaps(LPDDSCAPS lpDDSCaps)
362 ASSERT(m_pDirectDrawSurface);
363 return m_pDirectDrawSurface->GetCaps(lpDDSCaps);
367 STDMETHODIMP CAggDrawSurface::GetClipper(LPDIRECTDRAWCLIPPER *lplpDDClipper)
369 ASSERT(m_pDirectDrawSurface);
370 return m_pDirectDrawSurface->GetClipper(lplpDDClipper);
374 STDMETHODIMP CAggDrawSurface::GetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
376 ASSERT(m_pDirectDrawSurface);
377 return m_pDirectDrawSurface->GetColorKey(dwFlags,lpDDColorKey);
381 STDMETHODIMP CAggDrawSurface::GetDC(HDC *lphDC)
383 ASSERT(m_pDirectDrawSurface);
384 return m_pDirectDrawSurface->GetDC(lphDC);
388 STDMETHODIMP CAggDrawSurface::GetFlipStatus(DWORD dwFlags)
390 ASSERT(m_pDirectDrawSurface);
391 return m_pDirectDrawSurface->GetFlipStatus(dwFlags);
395 STDMETHODIMP CAggDrawSurface::GetOverlayPosition(LPLONG lpdwX,LPLONG lpdwY)
397 ASSERT(m_pDirectDrawSurface);
398 return m_pDirectDrawSurface->GetOverlayPosition(lpdwX,lpdwY);
402 STDMETHODIMP CAggDrawSurface::GetPalette(LPDIRECTDRAWPALETTE *lplpDDPalette)
404 ASSERT(m_pDirectDrawSurface);
405 return m_pDirectDrawSurface->GetPalette(lplpDDPalette);
409 STDMETHODIMP CAggDrawSurface::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat)
411 ASSERT(m_pDirectDrawSurface);
412 return m_pDirectDrawSurface->GetPixelFormat(lpDDPixelFormat);
416 // A bit of a warning here: Our media samples in DirectShow aggregate on
417 // IDirectDraw and IDirectDrawSurface (ie are available through IMediaSample
418 // by QueryInterface). Unfortunately the underlying DirectDraw code cannot
419 // be aggregated so we have to use these classes. The snag is that when we
420 // call a different surface and pass in this interface as perhaps the source
421 // surface the call will fail because DirectDraw dereferences the pointer to
422 // get at its private data structures. Therefore we supply this workaround to give
423 // access to the real IDirectDraw surface. A filter can call GetSurfaceDesc
424 // and we will fill in the lpSurface pointer with the real underlying surface
426 STDMETHODIMP CAggDrawSurface::GetSurfaceDesc(LPDDSURFACEDESC lpDDSurfaceDesc)
428 ASSERT(m_pDirectDrawSurface);
430 // First call down to the underlying DirectDraw
432 HRESULT hr = m_pDirectDrawSurface->GetSurfaceDesc(lpDDSurfaceDesc);
433 if (FAILED(hr)) {
434 return hr;
437 // Store the real DirectDrawSurface interface
438 lpDDSurfaceDesc->lpSurface = m_pDirectDrawSurface;
439 return hr;
443 STDMETHODIMP CAggDrawSurface::Initialize(LPDIRECTDRAW lpDD,LPDDSURFACEDESC lpDDSurfaceDesc)
445 ASSERT(m_pDirectDrawSurface);
446 return m_pDirectDrawSurface->Initialize(lpDD,lpDDSurfaceDesc);
450 STDMETHODIMP CAggDrawSurface::IsLost()
452 ASSERT(m_pDirectDrawSurface);
453 return m_pDirectDrawSurface->IsLost();
457 STDMETHODIMP CAggDrawSurface::Lock(LPRECT lpDestRect,LPDDSURFACEDESC lpDDSurfaceDesc,DWORD dwFlags,HANDLE hEvent)
459 ASSERT(m_pDirectDrawSurface);
460 return m_pDirectDrawSurface->Lock(lpDestRect,lpDDSurfaceDesc,dwFlags,hEvent);
464 STDMETHODIMP CAggDrawSurface::ReleaseDC(HDC hDC)
466 ASSERT(m_pDirectDrawSurface);
467 return m_pDirectDrawSurface->ReleaseDC(hDC);
471 STDMETHODIMP CAggDrawSurface::Restore()
473 ASSERT(m_pDirectDrawSurface);
474 return m_pDirectDrawSurface->Restore();
478 STDMETHODIMP CAggDrawSurface::SetClipper(LPDIRECTDRAWCLIPPER lpDDClipper)
480 ASSERT(m_pDirectDrawSurface);
481 return m_pDirectDrawSurface->SetClipper(lpDDClipper);
485 STDMETHODIMP CAggDrawSurface::SetColorKey(DWORD dwFlags,LPDDCOLORKEY lpDDColorKey)
487 ASSERT(m_pDirectDrawSurface);
488 return m_pDirectDrawSurface->SetColorKey(dwFlags,lpDDColorKey);
492 STDMETHODIMP CAggDrawSurface::SetOverlayPosition(LONG dwX,LONG dwY)
494 ASSERT(m_pDirectDrawSurface);
495 return m_pDirectDrawSurface->SetOverlayPosition(dwX,dwY);
499 STDMETHODIMP CAggDrawSurface::SetPalette(LPDIRECTDRAWPALETTE lpDDPalette)
501 ASSERT(m_pDirectDrawSurface);
502 return m_pDirectDrawSurface->SetPalette(lpDDPalette);
506 STDMETHODIMP CAggDrawSurface::Unlock(LPVOID lpSurfaceData)
508 ASSERT(m_pDirectDrawSurface);
509 return m_pDirectDrawSurface->Unlock(lpSurfaceData);
513 STDMETHODIMP CAggDrawSurface::UpdateOverlay(LPRECT lpSrcRect,LPDIRECTDRAWSURFACE lpDDDestSurface,LPRECT lpDestRect,DWORD dwFlags,LPDDOVERLAYFX lpDDOverlayFX)
515 ASSERT(m_pDirectDrawSurface);
516 return m_pDirectDrawSurface->UpdateOverlay(lpSrcRect,lpDDDestSurface,lpDestRect,dwFlags,lpDDOverlayFX);
520 STDMETHODIMP CAggDrawSurface::UpdateOverlayDisplay(DWORD dwFlags)
522 ASSERT(m_pDirectDrawSurface);
523 return m_pDirectDrawSurface->UpdateOverlayDisplay(dwFlags);
527 STDMETHODIMP CAggDrawSurface::UpdateOverlayZOrder(DWORD dwFlags,LPDIRECTDRAWSURFACE lpDDSReference)
529 ASSERT(m_pDirectDrawSurface);
530 return m_pDirectDrawSurface->UpdateOverlayZOrder(dwFlags,lpDDSReference);
534 // DirectShow must work on multiple platforms. In particular, it also runs on
535 // Windows NT 3.51 which does not have DirectDraw capabilities. The filters
536 // cannot therefore link statically to the DirectDraw library. To make their
537 // lives that little bit easier we provide this class that manages loading
538 // and unloading the library and creating the initial IDirectDraw interface
540 CLoadDirectDraw::CLoadDirectDraw() :
541 m_pDirectDraw(NULL),
542 m_hDirectDraw(NULL)
547 // Destructor forces unload
549 CLoadDirectDraw::~CLoadDirectDraw()
551 ReleaseDirectDraw();
553 if (m_hDirectDraw) {
554 NOTE("Unloading library");
555 FreeLibrary(m_hDirectDraw);
560 // We can't be sure that DirectDraw is always available so we can't statically
561 // link to the library. Therefore we load the library, get the function entry
562 // point addresses and call them to create the driver objects. We return S_OK
563 // if we manage to load DirectDraw correctly otherwise we return E_NOINTERFACE
564 // We initialise a DirectDraw instance by explicitely loading the library and
565 // calling GetProcAddress on the DirectDrawCreate entry point that it exports
567 // On a multi monitor system, we can get the DirectDraw object for any
568 // monitor (device) with the optional szDevice parameter
570 HRESULT CLoadDirectDraw::LoadDirectDraw(LPSTR szDevice)
572 PDRAWCREATE pDrawCreate;
573 PDRAWENUM pDrawEnum;
574 LPDIRECTDRAWENUMERATEEXA pDrawEnumEx;
575 HRESULT hr = NOERROR;
577 NOTE("Entering DoLoadDirectDraw");
579 // Is DirectDraw already loaded
581 if (m_pDirectDraw) {
582 NOTE("Already loaded");
583 ASSERT(m_hDirectDraw);
584 return NOERROR;
587 // Make sure the library is available
589 if(!m_hDirectDraw)
591 UINT ErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
592 m_hDirectDraw = LoadLibrary(TEXT("DDRAW.DLL"));
593 SetErrorMode(ErrorMode);
595 if (m_hDirectDraw == NULL) {
596 DbgLog((LOG_ERROR,1,TEXT("Can't load DDRAW.DLL")));
597 NOTE("No library");
598 return E_NOINTERFACE;
602 // Get the DLL address for the creator function
604 pDrawCreate = (PDRAWCREATE)GetProcAddress(m_hDirectDraw,"DirectDrawCreate");
605 // force ANSI, we assume it
606 pDrawEnum = (PDRAWENUM)GetProcAddress(m_hDirectDraw,"DirectDrawEnumerateA");
607 pDrawEnumEx = (LPDIRECTDRAWENUMERATEEXA)GetProcAddress(m_hDirectDraw,
608 "DirectDrawEnumerateExA");
610 // We don't NEED DirectDrawEnumerateEx, that's just for multimon stuff
611 if (pDrawCreate == NULL || pDrawEnum == NULL) {
612 DbgLog((LOG_ERROR,1,TEXT("Can't get functions: Create=%x Enum=%x"),
613 pDrawCreate, pDrawEnum));
614 NOTE("No entry point");
615 ReleaseDirectDraw();
616 return E_NOINTERFACE;
619 DbgLog((LOG_TRACE,3,TEXT("Creating DDraw for device %s"),
620 szDevice ? szDevice : "<NULL>"));
622 // Create a DirectDraw display provider for this device, using the fancy
623 // multimon-aware version, if it exists
624 if (pDrawEnumEx)
625 m_pDirectDraw = DirectDrawCreateFromDeviceEx(szDevice, pDrawCreate,
626 pDrawEnumEx);
627 else
628 m_pDirectDraw = DirectDrawCreateFromDevice(szDevice, pDrawCreate,
629 pDrawEnum);
631 if (m_pDirectDraw == NULL) {
632 DbgLog((LOG_ERROR,1,TEXT("Can't create DDraw")));
633 NOTE("No instance");
634 ReleaseDirectDraw();
635 return E_NOINTERFACE;
637 return NOERROR;
641 // Called to release any DirectDraw provider we previously loaded. We may be
642 // called at any time especially when something goes horribly wrong and when
643 // we need to clean up before returning so we can't guarantee that all state
644 // variables are consistent so free only those really allocated allocated
645 // This should only be called once all reference counts have been released
647 void CLoadDirectDraw::ReleaseDirectDraw()
649 NOTE("Releasing DirectDraw driver");
651 // Release any DirectDraw provider interface
653 if (m_pDirectDraw) {
654 NOTE("Releasing instance");
655 m_pDirectDraw->Release();
656 m_pDirectDraw = NULL;
662 // Return NOERROR (S_OK) if DirectDraw has been loaded by this object
664 HRESULT CLoadDirectDraw::IsDirectDrawLoaded()
666 NOTE("Entering IsDirectDrawLoaded");
668 if (m_pDirectDraw == NULL) {
669 NOTE("DirectDraw not loaded");
670 return S_FALSE;
672 return NOERROR;
676 // Return the IDirectDraw interface we look after
678 LPDIRECTDRAW CLoadDirectDraw::GetDirectDraw()
680 NOTE("Entering GetDirectDraw");
682 if (m_pDirectDraw == NULL) {
683 NOTE("No DirectDraw");
684 return NULL;
687 NOTE("Returning DirectDraw");
688 m_pDirectDraw->AddRef();
689 return m_pDirectDraw;
693 // Are we running on Direct Draw version 1? We need to find out as
694 // we rely on specific bug fixes in DirectDraw 2 for fullscreen playback. To
695 // find out, we simply see if it supports IDirectDraw2. Only version 2 and
696 // higher support this.
698 BOOL CLoadDirectDraw::IsDirectDrawVersion1()
701 if (m_pDirectDraw == NULL)
702 return FALSE;
704 IDirectDraw2 *p = NULL;
705 HRESULT hr = m_pDirectDraw->QueryInterface(IID_IDirectDraw2, (void **)&p);
706 if (p)
707 p->Release();
708 if (hr == NOERROR) {
709 DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 2 or greater")));
710 return FALSE;
711 } else {
712 DbgLog((LOG_TRACE,3,TEXT("Direct Draw Version 1")));
713 return TRUE;