1 /* DirectDraw Base Functions
3 * Copyright 1997-1999 Marcus Meissner
4 * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
20 #include "wine/exception.h"
23 #include "debugtools.h"
27 /* This for all the enumeration and creation of D3D-related objects */
28 #include "ddraw_private.h"
30 #define MAX_DDRAW_DRIVERS 3
31 static ddraw_driver
* ddraw_drivers
[MAX_DDRAW_DRIVERS
];
32 static int nrof_ddraw_drivers
= 0;
34 DEFAULT_DEBUG_CHANNEL(ddraw
);
36 /* register a direct draw driver. We better not use malloc for we are in
37 * the ELF startup initialisation at this point.
39 void ddraw_register_driver(ddraw_driver
*driver
) {
40 ddraw_drivers
[nrof_ddraw_drivers
++] = driver
;
42 /* increase MAX_DDRAW_DRIVERS if the line below triggers */
43 assert(nrof_ddraw_drivers
<= MAX_DDRAW_DRIVERS
);
46 /**********************************************************************/
51 } DirectDrawEnumerateProcData
;
53 /***********************************************************************
54 * DirectDrawEnumerateExA (DDRAW.*)
56 HRESULT WINAPI
DirectDrawEnumerateExA(
57 LPDDENUMCALLBACKEXA lpCallback
, LPVOID lpContext
, DWORD dwFlags
)
60 TRACE("(%p,%p, %08lx)\n", lpCallback
, lpContext
, dwFlags
);
62 if (TRACE_ON(ddraw
)) {
64 if (dwFlags
& DDENUM_ATTACHEDSECONDARYDEVICES
)
65 DPRINTF("DDENUM_ATTACHEDSECONDARYDEVICES ");
66 if (dwFlags
& DDENUM_DETACHEDSECONDARYDEVICES
)
67 DPRINTF("DDENUM_DETACHEDSECONDARYDEVICES ");
68 if (dwFlags
& DDENUM_NONDISPLAYDEVICES
)
69 DPRINTF("DDENUM_NONDISPLAYDEVICES ");
73 /* Invoke callback for what flags we do support */
74 for (i
=0;i
<MAX_DDRAW_DRIVERS
;i
++) {
75 if (!ddraw_drivers
[i
])
77 if (ddraw_drivers
[i
]->createDDRAW(NULL
)) /* !0 is failing */
79 TRACE("Enumerating %s/%s interface\n",ddraw_drivers
[i
]->name
,ddraw_drivers
[i
]->type
);
81 ddraw_drivers
[i
]->guid
,
82 (LPSTR
)ddraw_drivers
[i
]->name
,
83 (LPSTR
)ddraw_drivers
[i
]->type
,
85 0 /* FIXME: flags not supported here */
89 if (nrof_ddraw_drivers
) {
90 TRACE("Enumerating the default interface\n");
91 if (!lpCallback(NULL
,"WINE (default)", "display", lpContext
, 0))
95 /* Unsupported flags */
96 if (dwFlags
& DDENUM_NONDISPLAYDEVICES
) {
97 FIXME("no non-display devices supported.\n");
99 /* Hmm. Leave this out.
100 if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) {
101 FIXME("no attached secondary devices supported.\n");
104 if (dwFlags
& DDENUM_DETACHEDSECONDARYDEVICES
) {
105 FIXME("no detached secondary devices supported.\n");
111 /***********************************************************************
112 * DirectDrawEnumerateExW (DDRAW.*)
115 static BOOL CALLBACK
DirectDrawEnumerateExProcW(
116 GUID
*lpGUID
, LPSTR lpDriverDescription
, LPSTR lpDriverName
,
117 LPVOID lpContext
, HMONITOR hm
)
119 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
120 LPWSTR lpDriverDescriptionW
=
121 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverDescription
);
122 LPWSTR lpDriverNameW
=
123 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverName
);
125 BOOL bResult
= (*(LPDDENUMCALLBACKEXW
*) pEPD
->lpCallback
)(
126 lpGUID
, lpDriverDescriptionW
, lpDriverNameW
, pEPD
->lpContext
, hm
);
128 HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW
);
129 HeapFree(GetProcessHeap(), 0, lpDriverNameW
);
133 /**********************************************************************/
135 HRESULT WINAPI
DirectDrawEnumerateExW(
136 LPDDENUMCALLBACKEXW lpCallback
, LPVOID lpContext
, DWORD dwFlags
)
138 DirectDrawEnumerateProcData epd
;
139 epd
.lpCallback
= (LPVOID
) lpCallback
;
140 epd
.lpContext
= lpContext
;
142 return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW
, (LPVOID
) &epd
, 0);
145 /***********************************************************************
146 * DirectDrawEnumerateA (DDRAW.*)
149 static BOOL CALLBACK
DirectDrawEnumerateProcA(
150 GUID
*lpGUID
, LPSTR lpDriverDescription
, LPSTR lpDriverName
,
151 LPVOID lpContext
, HMONITOR hm
)
153 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
155 return ((LPDDENUMCALLBACKA
) pEPD
->lpCallback
)(
156 lpGUID
, lpDriverDescription
, lpDriverName
, pEPD
->lpContext
);
159 /**********************************************************************/
161 HRESULT WINAPI
DirectDrawEnumerateA(
162 LPDDENUMCALLBACKA lpCallback
, LPVOID lpContext
)
164 DirectDrawEnumerateProcData epd
;
165 epd
.lpCallback
= (LPVOID
) lpCallback
;
166 epd
.lpContext
= lpContext
;
168 return DirectDrawEnumerateExA(DirectDrawEnumerateProcA
, (LPVOID
) &epd
, 0);
171 /***********************************************************************
172 * DirectDrawEnumerateW (DDRAW.*)
175 static BOOL WINAPI
DirectDrawEnumerateProcW(
176 GUID
*lpGUID
, LPWSTR lpDriverDescription
, LPWSTR lpDriverName
,
177 LPVOID lpContext
, HMONITOR hm
)
179 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
181 return ((LPDDENUMCALLBACKW
) pEPD
->lpCallback
)(
182 lpGUID
, lpDriverDescription
, lpDriverName
, pEPD
->lpContext
);
185 /**********************************************************************/
187 HRESULT WINAPI
DirectDrawEnumerateW(
188 LPDDENUMCALLBACKW lpCallback
, LPVOID lpContext
)
190 DirectDrawEnumerateProcData epd
;
191 epd
.lpCallback
= (LPVOID
) lpCallback
;
192 epd
.lpContext
= lpContext
;
194 return DirectDrawEnumerateExW(DirectDrawEnumerateProcW
, (LPVOID
) &epd
, 0);
197 /******************************************************************************
198 * DirectDraw Window Procedure
200 static LRESULT WINAPI
DDWndProc(HWND hwnd
,UINT msg
,WPARAM wParam
,LPARAM lParam
)
203 IDirectDrawImpl
* ddraw
= NULL
;
206 /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
208 SetLastError( ERROR_SUCCESS
);
209 ddraw
= (IDirectDrawImpl
*)GetPropA( hwnd
, ddProp
);
210 if( (!ddraw
) && ( ( lastError
= GetLastError() ) != ERROR_SUCCESS
))
211 ERR("Unable to retrieve this ptr from window. Error %08lx\n",lastError
);
214 /* Perform any special direct draw functions */
216 ddraw
->d
.paintable
= 1;
218 /* Now let the application deal with the rest of this */
219 if( ddraw
->d
.mainWindow
) {
221 /* Don't think that we actually need to call this but...
222 * might as well be on the safe side of things...
225 /* I changed hwnd to ddraw->d.mainWindow as I did not see why
226 * it should be the procedures of our fake window that gets called
227 * instead of those of the window provided by the application.
228 * And with this patch, mouse clicks work with Monkey Island III
231 ret
= DefWindowProcA( ddraw
->d
.mainWindow
, msg
, wParam
, lParam
);
234 WND
*tmpWnd
=WIN_FindWndPtr(ddraw
->d
.mainWindow
);
235 /* We didn't handle the message - give it to the application */
236 if (ddraw
&& ddraw
->d
.mainWindow
&& tmpWnd
)
237 ret
= CallWindowProcA(tmpWnd
->winproc
,
238 ddraw
->d
.mainWindow
, msg
, wParam
, lParam
);
239 WIN_ReleaseWndPtr(tmpWnd
);
242 } /* else FALLTHROUGH */
243 } /* else FALLTHROUGH */
244 return DefWindowProcA(hwnd
,msg
,wParam
,lParam
);
247 /***********************************************************************
250 HRESULT WINAPI
DirectDrawCreate(
251 LPGUID lpGUID
, LPDIRECTDRAW
*lplpDD
, LPUNKNOWN pUnkOuter
253 IDirectDrawImpl
** ilplpDD
=(IDirectDrawImpl
**)lplpDD
;
259 struct ddraw_driver
*ddd
= NULL
;
261 if (!HIWORD(lpGUID
)) lpGUID
= NULL
;
263 TRACE("(%s,%p,%p)\n",debugstr_guid(lpGUID
),ilplpDD
,pUnkOuter
);
265 memset(&zeroGUID
,0,sizeof(zeroGUID
));
269 ( IsEqualGUID( &zeroGUID
, lpGUID
) ) ||
270 ( IsEqualGUID( &IID_IDirectDraw
, lpGUID
) ) ||
271 ( IsEqualGUID( &IID_IDirectDraw2
, lpGUID
) ) ||
272 ( IsEqualGUID( &IID_IDirectDraw4
, lpGUID
) ) ||
273 ( IsEqualGUID( &IID_IDirectDraw7
, lpGUID
) )
275 /* choose an interface out of the list */
276 for (i
=0;i
<nrof_ddraw_drivers
;i
++) {
277 ddraw_driver
*xddd
= ddraw_drivers
[i
];
280 if (!ddd
|| (ddd
->preference
<xddd
->preference
)) {
286 for (i
=0;i
<nrof_ddraw_drivers
;i
++) {
287 if (!ddraw_drivers
[i
])
289 if (IsEqualGUID(ddraw_drivers
[i
]->guid
,lpGUID
)) {
291 ddd
= ddraw_drivers
[i
];
297 if (!nrof_ddraw_drivers
) {
298 ERR("DirectDrawCreate(%s,%p,%p): no DirectDraw drivers compiled in.\n",debugstr_guid(lpGUID
),lplpDD
,pUnkOuter
);
299 return DDERR_NODIRECTDRAWHW
;
301 ERR("DirectDrawCreate(%s,%p,%p): did not recognize requested GUID.\n",debugstr_guid(lpGUID
),lplpDD
,pUnkOuter
);
302 return DDERR_INVALIDDIRECTDRAWGUID
;
304 TRACE("using \"%s\" driver, calling %p\n",ddd
->name
,ddd
->createDDRAW
);
306 ret
= ddd
->createDDRAW(lplpDD
);
309 ddraw_drivers
[drvindex
] = NULL
; /* mark this one as unusable */
311 wc
.style
= CS_GLOBALCLASS
;
312 wc
.lpfnWndProc
= DDWndProc
;
316 /* We can be a child of the desktop since we're really important */
319 wc
.hCursor
= (HCURSOR
)IDC_ARROWA
;
320 wc
.hbrBackground
= NULL_BRUSH
;
322 wc
.lpszClassName
= "WINE_DirectDraw";
323 (*ilplpDD
)->d
.winclass
= RegisterClassA(&wc
);
327 /***********************************************************************
330 HRESULT WINAPI
DirectDrawCreateEx(
331 LPGUID lpGUID
, LPVOID
* lplpDD
, REFIID iid
, LPUNKNOWN pUnkOuter
333 FIXME(":semi stub\n");
334 /* I don't know about what functionality is unique to Ex */
335 return DirectDrawCreate(lpGUID
,(LPDIRECTDRAW
*)lplpDD
,pUnkOuter
);
338 /*******************************************************************************
339 * DirectDraw ClassFactory
341 * Heavily inspired (well, can you say completely copied :-) ) from DirectSound
345 /* IUnknown fields */
346 ICOM_VFIELD(IClassFactory
);
350 static HRESULT WINAPI
351 DDCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
352 ICOM_THIS(IClassFactoryImpl
,iface
);
354 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
355 return E_NOINTERFACE
;
359 DDCF_AddRef(LPCLASSFACTORY iface
) {
360 ICOM_THIS(IClassFactoryImpl
,iface
);
361 return ++(This
->ref
);
364 static ULONG WINAPI
DDCF_Release(LPCLASSFACTORY iface
) {
365 ICOM_THIS(IClassFactoryImpl
,iface
);
366 /* static class, won't be freed */
367 return --(This
->ref
);
370 static HRESULT WINAPI
DDCF_CreateInstance(
371 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
373 ICOM_THIS(IClassFactoryImpl
,iface
);
375 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
376 if ( ( IsEqualGUID( &IID_IDirectDraw
, riid
) ) ||
377 ( IsEqualGUID( &IID_IDirectDraw2
, riid
) ) ||
378 ( IsEqualGUID( &IID_IDirectDraw4
, riid
) ) ) {
379 /* FIXME: reuse already created DirectDraw if present? */
380 return DirectDrawCreate((LPGUID
) riid
,(LPDIRECTDRAW
*)ppobj
,pOuter
);
382 return CLASS_E_CLASSNOTAVAILABLE
;
385 static HRESULT WINAPI
DDCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
386 ICOM_THIS(IClassFactoryImpl
,iface
);
387 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
391 static ICOM_VTABLE(IClassFactory
) DDCF_Vtbl
=
393 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
400 static IClassFactoryImpl DDRAW_CF
= {&DDCF_Vtbl
, 1 };
402 /*******************************************************************************
403 * DllGetClassObject [DDRAW.13]
404 * Retrieves class object from a DLL object
407 * Docs say returns STDAPI
410 * rclsid [I] CLSID for the class object
411 * riid [I] Reference to identifier of interface for class object
412 * ppv [O] Address of variable to receive interface pointer for riid
416 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
419 DWORD WINAPI
DDRAW_DllGetClassObject(REFCLSID rclsid
,REFIID riid
,LPVOID
*ppv
)
421 TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
422 if ( IsEqualGUID( &IID_IClassFactory
, riid
) ) {
423 *ppv
= (LPVOID
)&DDRAW_CF
;
424 IClassFactory_AddRef((IClassFactory
*)*ppv
);
427 FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
428 return CLASS_E_CLASSNOTAVAILABLE
;
432 /*******************************************************************************
433 * DllCanUnloadNow [DDRAW.12] Determines whether the DLL is in use.
439 DWORD WINAPI
DDRAW_DllCanUnloadNow(void) {
440 FIXME("(void): stub\n");