1 /* DirectDraw Base Functions
3 * Copyright 1997-1999 Marcus Meissner
4 * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
18 #include "wine/exception.h"
19 #include "debugtools.h"
21 /* This for all the enumeration and creation of D3D-related objects */
22 #include "ddraw_private.h"
24 #define MAX_DDRAW_DRIVERS 3
25 static ddraw_driver
* ddraw_drivers
[MAX_DDRAW_DRIVERS
];
26 static int nrof_ddraw_drivers
= 0;
28 DEFAULT_DEBUG_CHANNEL(ddraw
);
30 /* register a direct draw driver. We better not use malloc for we are in
31 * the ELF startup initialisation at this point.
33 void ddraw_register_driver(ddraw_driver
*driver
) {
34 ddraw_drivers
[nrof_ddraw_drivers
++] = driver
;
36 /* increase MAX_DDRAW_DRIVERS if the line below triggers */
37 assert(nrof_ddraw_drivers
<= MAX_DDRAW_DRIVERS
);
40 /**********************************************************************/
45 } DirectDrawEnumerateProcData
;
47 /***********************************************************************
48 * DirectDrawEnumerateExA (DDRAW.*)
50 HRESULT WINAPI
DirectDrawEnumerateExA(
51 LPDDENUMCALLBACKEXA lpCallback
, LPVOID lpContext
, DWORD dwFlags
)
55 TRACE("(%p,%p, %08lx)\n", lpCallback
, lpContext
, dwFlags
);
57 if (TRACE_ON(ddraw
)) {
59 if (dwFlags
& DDENUM_ATTACHEDSECONDARYDEVICES
)
60 DPRINTF("DDENUM_ATTACHEDSECONDARYDEVICES ");
61 if (dwFlags
& DDENUM_DETACHEDSECONDARYDEVICES
)
62 DPRINTF("DDENUM_DETACHEDSECONDARYDEVICES ");
63 if (dwFlags
& DDENUM_NONDISPLAYDEVICES
)
64 DPRINTF("DDENUM_NONDISPLAYDEVICES ");
67 if (dwFlags
& DDENUM_ATTACHEDSECONDARYDEVICES
) {
68 FIXME("no attached secondary devices supported.\n");
72 memset(&zeroGUID
,0,sizeof(zeroGUID
));
74 /* we have at least one DDRAW driver */
75 if (ddraw_drivers
[0]) {
77 &zeroGUID
, /* FIXME: or NULL? -MM */
81 0 /* FIXME: flags not supported here */
85 /* Invoke callback for what flags we do support */
86 for (i
=0;i
<MAX_DDRAW_DRIVERS
;i
++) {
87 if (!ddraw_drivers
[i
])
89 if (ddraw_drivers
[i
]->createDDRAW(NULL
)) /* !0 is failing */
91 TRACE("Enumerating %s/%s interface\n",ddraw_drivers
[i
]->name
,ddraw_drivers
[i
]->type
);
93 ddraw_drivers
[i
]->guid
,
94 (LPSTR
)ddraw_drivers
[i
]->name
,
95 (LPSTR
)ddraw_drivers
[i
]->type
,
97 0 /* FIXME: flags not supported here */
101 if (nrof_ddraw_drivers
) {
102 TRACE("Enumerating the default interface\n");
103 if (!lpCallback(NULL
,"WINE (default)", "display", lpContext
, 0))
107 /* Unsupported flags */
108 if (dwFlags
& DDENUM_NONDISPLAYDEVICES
) {
109 FIXME("no non-display devices supported.\n");
111 if (dwFlags
& DDENUM_DETACHEDSECONDARYDEVICES
) {
112 FIXME("no detached secondary devices supported.\n");
118 /***********************************************************************
119 * DirectDrawEnumerateExW (DDRAW.*)
122 static BOOL CALLBACK
DirectDrawEnumerateExProcW(
123 GUID
*lpGUID
, LPSTR lpDriverDescription
, LPSTR lpDriverName
,
124 LPVOID lpContext
, HMONITOR hm
)
126 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
127 LPWSTR lpDriverDescriptionW
=
128 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverDescription
);
129 LPWSTR lpDriverNameW
=
130 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverName
);
132 BOOL bResult
= (*(LPDDENUMCALLBACKEXW
*) pEPD
->lpCallback
)(
133 lpGUID
, lpDriverDescriptionW
, lpDriverNameW
, pEPD
->lpContext
, hm
);
135 HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW
);
136 HeapFree(GetProcessHeap(), 0, lpDriverNameW
);
140 /**********************************************************************/
142 HRESULT WINAPI
DirectDrawEnumerateExW(
143 LPDDENUMCALLBACKEXW lpCallback
, LPVOID lpContext
, DWORD dwFlags
)
145 DirectDrawEnumerateProcData epd
;
146 epd
.lpCallback
= (LPVOID
) lpCallback
;
147 epd
.lpContext
= lpContext
;
149 return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW
, (LPVOID
) &epd
, 0);
152 /***********************************************************************
153 * DirectDrawEnumerateA (DDRAW.*)
156 static BOOL CALLBACK
DirectDrawEnumerateProcA(
157 GUID
*lpGUID
, LPSTR lpDriverDescription
, LPSTR lpDriverName
,
158 LPVOID lpContext
, HMONITOR hm
)
160 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
162 return ((LPDDENUMCALLBACKA
) pEPD
->lpCallback
)(
163 lpGUID
, lpDriverDescription
, lpDriverName
, pEPD
->lpContext
);
166 /**********************************************************************/
168 HRESULT WINAPI
DirectDrawEnumerateA(
169 LPDDENUMCALLBACKA lpCallback
, LPVOID lpContext
)
171 DirectDrawEnumerateProcData epd
;
172 epd
.lpCallback
= (LPVOID
) lpCallback
;
173 epd
.lpContext
= lpContext
;
175 return DirectDrawEnumerateExA(DirectDrawEnumerateProcA
, (LPVOID
) &epd
, 0);
178 /***********************************************************************
179 * DirectDrawEnumerateW (DDRAW.*)
182 static BOOL WINAPI
DirectDrawEnumerateProcW(
183 GUID
*lpGUID
, LPWSTR lpDriverDescription
, LPWSTR lpDriverName
,
184 LPVOID lpContext
, HMONITOR hm
)
186 DirectDrawEnumerateProcData
*pEPD
= (DirectDrawEnumerateProcData
*)lpContext
;
188 return ((LPDDENUMCALLBACKW
) pEPD
->lpCallback
)(
189 lpGUID
, lpDriverDescription
, lpDriverName
, pEPD
->lpContext
);
192 /**********************************************************************/
194 HRESULT WINAPI
DirectDrawEnumerateW(
195 LPDDENUMCALLBACKW lpCallback
, LPVOID lpContext
)
197 DirectDrawEnumerateProcData epd
;
198 epd
.lpCallback
= (LPVOID
) lpCallback
;
199 epd
.lpContext
= lpContext
;
201 return DirectDrawEnumerateExW(DirectDrawEnumerateProcW
, (LPVOID
) &epd
, 0);
204 /******************************************************************************
205 * DirectDraw Window Procedure
207 static LRESULT WINAPI
DDWndProc(HWND hwnd
,UINT msg
,WPARAM wParam
,LPARAM lParam
)
210 IDirectDrawImpl
* ddraw
= NULL
;
213 /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
215 SetLastError( ERROR_SUCCESS
);
216 ddraw
= (IDirectDrawImpl
*)GetPropA( hwnd
, ddProp
);
217 if( (!ddraw
) && ( ( lastError
= GetLastError() ) != ERROR_SUCCESS
))
218 ERR("Unable to retrieve this ptr from window. Error %08lx\n",lastError
);
221 /* Perform any special direct draw functions */
223 ddraw
->d
->paintable
= 1;
225 /* Now let the application deal with the rest of this */
226 if( ddraw
->d
->mainWindow
) {
228 /* Don't think that we actually need to call this but...
229 * might as well be on the safe side of things...
232 /* I changed hwnd to ddraw->d->mainWindow as I did not see why
233 * it should be the procedures of our fake window that gets called
234 * instead of those of the window provided by the application.
235 * And with this patch, mouse clicks work with Monkey Island III
238 ret
= DefWindowProcA( ddraw
->d
->mainWindow
, msg
, wParam
, lParam
);
241 /* We didn't handle the message - give it to the application */
242 if (ddraw
&& ddraw
->d
->mainWindow
)
244 WNDPROC winproc
= (WNDPROC
)GetWindowLongA( ddraw
->d
->mainWindow
, GWL_WNDPROC
);
245 ret
= CallWindowProcA(winproc
, ddraw
->d
->mainWindow
, msg
, wParam
, lParam
);
249 } /* else FALLTHROUGH */
250 } /* else FALLTHROUGH */
251 return DefWindowProcA(hwnd
,msg
,wParam
,lParam
);
254 /***********************************************************************
257 HRESULT WINAPI
DirectDrawCreate(
258 LPGUID lpGUID
, LPDIRECTDRAW
*lplpDD
, LPUNKNOWN pUnkOuter
260 IDirectDrawImpl
** ilplpDD
=(IDirectDrawImpl
**)lplpDD
;
266 struct ddraw_driver
*ddd
= NULL
;
268 if (!HIWORD(lpGUID
)) lpGUID
= NULL
;
270 TRACE("(%s,%p,%p)\n",debugstr_guid(lpGUID
),ilplpDD
,pUnkOuter
);
272 memset(&zeroGUID
,0,sizeof(zeroGUID
));
276 ( IsEqualGUID( &zeroGUID
, lpGUID
) ) ||
277 ( IsEqualGUID( &IID_IDirectDraw
, lpGUID
) ) ||
278 ( IsEqualGUID( &IID_IDirectDraw2
, lpGUID
) ) ||
279 ( IsEqualGUID( &IID_IDirectDraw4
, lpGUID
) ) ||
280 ( IsEqualGUID( &IID_IDirectDraw7
, lpGUID
) )
282 /* choose an interface out of the list */
283 for (i
=0;i
<nrof_ddraw_drivers
;i
++) {
284 ddraw_driver
*xddd
= ddraw_drivers
[i
];
287 if (!ddd
|| (ddd
->preference
<xddd
->preference
)) {
293 for (i
=0;i
<nrof_ddraw_drivers
;i
++) {
294 if (!ddraw_drivers
[i
])
296 if (IsEqualGUID(ddraw_drivers
[i
]->guid
,lpGUID
)) {
298 ddd
= ddraw_drivers
[i
];
304 if (!nrof_ddraw_drivers
) {
305 ERR("DirectDrawCreate(%s,%p,%p): no DirectDraw drivers compiled in.\n",debugstr_guid(lpGUID
),lplpDD
,pUnkOuter
);
306 return DDERR_NODIRECTDRAWHW
;
308 ERR("DirectDrawCreate(%s,%p,%p): did not recognize requested GUID.\n",debugstr_guid(lpGUID
),lplpDD
,pUnkOuter
);
309 return DDERR_INVALIDDIRECTDRAWGUID
;
311 TRACE("using \"%s\" driver, calling %p\n",ddd
->name
,ddd
->createDDRAW
);
313 ret
= ddd
->createDDRAW(lplpDD
);
316 ddraw_drivers
[drvindex
] = NULL
; /* mark this one as unusable */
319 if (IsEqualGUID( &IID_IDirectDraw2
, lpGUID
) ||
320 IsEqualGUID( &IID_IDirectDraw4
, lpGUID
) ||
321 IsEqualGUID( &IID_IDirectDraw7
, lpGUID
)
324 ret
= IDirectDraw_QueryInterface(*lplpDD
,lpGUID
,&x
);
325 IDirectDraw_Release(*lplpDD
); /* either drop 1 refcount, or release */
331 wc
.style
= CS_GLOBALCLASS
;
332 wc
.lpfnWndProc
= DDWndProc
;
336 /* We can be a child of the desktop since we're really important */
339 wc
.hCursor
= (HCURSOR
)IDC_ARROWA
;
340 wc
.hbrBackground
= NULL_BRUSH
;
342 wc
.lpszClassName
= "WINE_DirectDraw";
343 (*ilplpDD
)->d
->winclass
= RegisterClassA(&wc
);
347 /***********************************************************************
350 HRESULT WINAPI
DirectDrawCreateEx(
351 LPGUID lpGUID
, LPVOID
* lplpDD
, REFIID iid
, LPUNKNOWN pUnkOuter
356 FIXME("(%p,%p,%s,%p), might be wrong.\n",lpGUID
,lplpDD
,debugstr_guid(iid
),pUnkOuter
);
358 hres
=DirectDrawCreate(lpGUID
,(LPDIRECTDRAW
*)&ddraw
,pUnkOuter
);
360 hres
=IDirectDraw_QueryInterface(ddraw
,iid
,lplpDD
);
361 IDirectDraw_Release(ddraw
);
366 /*******************************************************************************
367 * DirectDraw ClassFactory
369 * Heavily inspired (well, can you say completely copied :-) ) from DirectSound
373 /* IUnknown fields */
374 ICOM_VFIELD(IClassFactory
);
378 static HRESULT WINAPI
379 DDCF_QueryInterface(LPCLASSFACTORY iface
,REFIID riid
,LPVOID
*ppobj
) {
380 ICOM_THIS(IClassFactoryImpl
,iface
);
382 FIXME("(%p)->(%s,%p),stub!\n",This
,debugstr_guid(riid
),ppobj
);
383 return E_NOINTERFACE
;
387 DDCF_AddRef(LPCLASSFACTORY iface
) {
388 ICOM_THIS(IClassFactoryImpl
,iface
);
389 return ++(This
->ref
);
392 static ULONG WINAPI
DDCF_Release(LPCLASSFACTORY iface
) {
393 ICOM_THIS(IClassFactoryImpl
,iface
);
394 /* static class, won't be freed */
395 return --(This
->ref
);
398 static HRESULT WINAPI
DDCF_CreateInstance(
399 LPCLASSFACTORY iface
,LPUNKNOWN pOuter
,REFIID riid
,LPVOID
*ppobj
401 ICOM_THIS(IClassFactoryImpl
,iface
);
403 TRACE("(%p)->(%p,%s,%p)\n",This
,pOuter
,debugstr_guid(riid
),ppobj
);
404 if ( ( IsEqualGUID( &IID_IDirectDraw
, riid
) ) ||
405 ( IsEqualGUID( &IID_IDirectDraw2
, riid
) ) ||
406 ( IsEqualGUID( &IID_IDirectDraw4
, riid
) ) ) {
407 /* FIXME: reuse already created DirectDraw if present? */
408 return DirectDrawCreate((LPGUID
) riid
,(LPDIRECTDRAW
*)ppobj
,pOuter
);
410 return CLASS_E_CLASSNOTAVAILABLE
;
413 static HRESULT WINAPI
DDCF_LockServer(LPCLASSFACTORY iface
,BOOL dolock
) {
414 ICOM_THIS(IClassFactoryImpl
,iface
);
415 FIXME("(%p)->(%d),stub!\n",This
,dolock
);
419 static ICOM_VTABLE(IClassFactory
) DDCF_Vtbl
=
421 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
428 static IClassFactoryImpl DDRAW_CF
= {&DDCF_Vtbl
, 1 };
430 /*******************************************************************************
431 * DllGetClassObject [DDRAW.13]
432 * Retrieves class object from a DLL object
435 * Docs say returns STDAPI
438 * rclsid [I] CLSID for the class object
439 * riid [I] Reference to identifier of interface for class object
440 * ppv [O] Address of variable to receive interface pointer for riid
444 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
447 DWORD WINAPI
DDRAW_DllGetClassObject(REFCLSID rclsid
,REFIID riid
,LPVOID
*ppv
)
449 TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
450 if ( IsEqualGUID( &IID_IClassFactory
, riid
) ) {
451 *ppv
= (LPVOID
)&DDRAW_CF
;
452 IClassFactory_AddRef((IClassFactory
*)*ppv
);
455 FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid
), debugstr_guid(riid
), ppv
);
456 return CLASS_E_CLASSNOTAVAILABLE
;
460 /*******************************************************************************
461 * DllCanUnloadNow [DDRAW.12] Determines whether the DLL is in use.
467 DWORD WINAPI
DDRAW_DllCanUnloadNow(void) {
468 FIXME("(void): stub\n");