Removed some unnecessary #includes and dll dependencies.
[wine/multimedia.git] / dlls / ddraw / main.c
blob6c368de1fb88e5bff85fe33067e00c53929c7395
1 /* DirectDraw Base Functions
3 * Copyright 1997-1999 Marcus Meissner
4 * Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
5 */
7 #include "config.h"
9 #include <unistd.h>
10 #include <assert.h>
11 #include <fcntl.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
16 #include "winerror.h"
17 #include "heap.h"
18 #include "wine/exception.h"
19 #include "debugtools.h"
21 #include "initguid.h"
22 #include "ddraw.h"
23 #include "d3d.h"
25 /* This for all the enumeration and creation of D3D-related objects */
26 #include "ddraw_private.h"
28 #define MAX_DDRAW_DRIVERS 3
29 static ddraw_driver * ddraw_drivers[MAX_DDRAW_DRIVERS];
30 static int nrof_ddraw_drivers = 0;
32 DEFAULT_DEBUG_CHANNEL(ddraw);
34 /* register a direct draw driver. We better not use malloc for we are in
35 * the ELF startup initialisation at this point.
37 void ddraw_register_driver(ddraw_driver *driver) {
38 ddraw_drivers[nrof_ddraw_drivers++] = driver;
40 /* increase MAX_DDRAW_DRIVERS if the line below triggers */
41 assert(nrof_ddraw_drivers <= MAX_DDRAW_DRIVERS);
44 /**********************************************************************/
46 typedef struct {
47 LPVOID lpCallback;
48 LPVOID lpContext;
49 } DirectDrawEnumerateProcData;
51 /***********************************************************************
52 * DirectDrawEnumerateExA (DDRAW.*)
54 HRESULT WINAPI DirectDrawEnumerateExA(
55 LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
57 int i;
58 TRACE("(%p,%p, %08lx)\n", lpCallback, lpContext, dwFlags);
60 if (TRACE_ON(ddraw)) {
61 DPRINTF(" Flags : ");
62 if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES)
63 DPRINTF("DDENUM_ATTACHEDSECONDARYDEVICES ");
64 if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES)
65 DPRINTF("DDENUM_DETACHEDSECONDARYDEVICES ");
66 if (dwFlags & DDENUM_NONDISPLAYDEVICES)
67 DPRINTF("DDENUM_NONDISPLAYDEVICES ");
68 DPRINTF("\n");
71 /* Invoke callback for what flags we do support */
72 for (i=0;i<MAX_DDRAW_DRIVERS;i++) {
73 if (!ddraw_drivers[i])
74 continue;
75 if (ddraw_drivers[i]->createDDRAW(NULL)) /* !0 is failing */
76 continue;
77 TRACE("Enumerating %s/%s interface\n",ddraw_drivers[i]->name,ddraw_drivers[i]->type);
78 if (!lpCallback(
79 ddraw_drivers[i]->guid,
80 (LPSTR)ddraw_drivers[i]->name,
81 (LPSTR)ddraw_drivers[i]->type,
82 lpContext,
83 0 /* FIXME: flags not supported here */
85 return DD_OK;
87 if (nrof_ddraw_drivers) {
88 TRACE("Enumerating the default interface\n");
89 if (!lpCallback(NULL,"WINE (default)", "display", lpContext, 0))
90 return DD_OK;
93 /* Unsupported flags */
94 if (dwFlags & DDENUM_NONDISPLAYDEVICES) {
95 FIXME("no non-display devices supported.\n");
97 /* Hmm. Leave this out.
98 if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) {
99 FIXME("no attached secondary devices supported.\n");
102 if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES) {
103 FIXME("no detached secondary devices supported.\n");
106 return DD_OK;
109 /***********************************************************************
110 * DirectDrawEnumerateExW (DDRAW.*)
113 static BOOL CALLBACK DirectDrawEnumerateExProcW(
114 GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName,
115 LPVOID lpContext, HMONITOR hm)
117 DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext;
118 LPWSTR lpDriverDescriptionW =
119 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverDescription);
120 LPWSTR lpDriverNameW =
121 HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverName);
123 BOOL bResult = (*(LPDDENUMCALLBACKEXW *) pEPD->lpCallback)(
124 lpGUID, lpDriverDescriptionW, lpDriverNameW, pEPD->lpContext, hm);
126 HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW);
127 HeapFree(GetProcessHeap(), 0, lpDriverNameW);
128 return bResult;
131 /**********************************************************************/
133 HRESULT WINAPI DirectDrawEnumerateExW(
134 LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
136 DirectDrawEnumerateProcData epd;
137 epd.lpCallback = (LPVOID) lpCallback;
138 epd.lpContext = lpContext;
140 return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW, (LPVOID) &epd, 0);
143 /***********************************************************************
144 * DirectDrawEnumerateA (DDRAW.*)
147 static BOOL CALLBACK DirectDrawEnumerateProcA(
148 GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName,
149 LPVOID lpContext, HMONITOR hm)
151 DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext;
153 return ((LPDDENUMCALLBACKA) pEPD->lpCallback)(
154 lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
157 /**********************************************************************/
159 HRESULT WINAPI DirectDrawEnumerateA(
160 LPDDENUMCALLBACKA lpCallback, LPVOID lpContext)
162 DirectDrawEnumerateProcData epd;
163 epd.lpCallback = (LPVOID) lpCallback;
164 epd.lpContext = lpContext;
166 return DirectDrawEnumerateExA(DirectDrawEnumerateProcA, (LPVOID) &epd, 0);
169 /***********************************************************************
170 * DirectDrawEnumerateW (DDRAW.*)
173 static BOOL WINAPI DirectDrawEnumerateProcW(
174 GUID *lpGUID, LPWSTR lpDriverDescription, LPWSTR lpDriverName,
175 LPVOID lpContext, HMONITOR hm)
177 DirectDrawEnumerateProcData *pEPD = (DirectDrawEnumerateProcData*)lpContext;
179 return ((LPDDENUMCALLBACKW) pEPD->lpCallback)(
180 lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
183 /**********************************************************************/
185 HRESULT WINAPI DirectDrawEnumerateW(
186 LPDDENUMCALLBACKW lpCallback, LPVOID lpContext)
188 DirectDrawEnumerateProcData epd;
189 epd.lpCallback = (LPVOID) lpCallback;
190 epd.lpContext = lpContext;
192 return DirectDrawEnumerateExW(DirectDrawEnumerateProcW, (LPVOID) &epd, 0);
195 /******************************************************************************
196 * DirectDraw Window Procedure
198 static LRESULT WINAPI DDWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
200 LRESULT ret;
201 IDirectDrawImpl* ddraw = NULL;
202 DWORD lastError;
204 /* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
206 SetLastError( ERROR_SUCCESS );
207 ddraw = (IDirectDrawImpl*)GetPropA( hwnd, ddProp );
208 if( (!ddraw) && ( ( lastError = GetLastError() ) != ERROR_SUCCESS ))
209 ERR("Unable to retrieve this ptr from window. Error %08lx\n",lastError);
211 if( ddraw ) {
212 /* Perform any special direct draw functions */
213 if (msg==WM_PAINT)
214 ddraw->d->paintable = 1;
216 /* Now let the application deal with the rest of this */
217 if( ddraw->d->mainWindow ) {
219 /* Don't think that we actually need to call this but...
220 * might as well be on the safe side of things...
223 /* I changed hwnd to ddraw->d->mainWindow as I did not see why
224 * it should be the procedures of our fake window that gets called
225 * instead of those of the window provided by the application.
226 * And with this patch, mouse clicks work with Monkey Island III
227 * - Lionel
229 ret = DefWindowProcA( ddraw->d->mainWindow, msg, wParam, lParam );
231 if( !ret ) {
232 /* We didn't handle the message - give it to the application */
233 if (ddraw && ddraw->d->mainWindow)
235 WNDPROC winproc = (WNDPROC)GetWindowLongA( ddraw->d->mainWindow, GWL_WNDPROC );
236 ret = CallWindowProcA(winproc, ddraw->d->mainWindow, msg, wParam, lParam );
239 return ret;
240 } /* else FALLTHROUGH */
241 } /* else FALLTHROUGH */
242 return DefWindowProcA(hwnd,msg,wParam,lParam);
245 /***********************************************************************
246 * DirectDrawCreate
248 HRESULT WINAPI DirectDrawCreate(
249 LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter
251 IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
252 WNDCLASSA wc;
253 HRESULT ret = 0;
254 int i,drvindex=0;
255 GUID zeroGUID;
257 struct ddraw_driver *ddd = NULL;
259 if (!HIWORD(lpGUID)) lpGUID = NULL;
261 TRACE("(%s,%p,%p)\n",debugstr_guid(lpGUID),ilplpDD,pUnkOuter);
263 memset(&zeroGUID,0,sizeof(zeroGUID));
264 while (1) {
265 ddd = NULL;
266 if ( ( !lpGUID ) ||
267 ( IsEqualGUID( &zeroGUID, lpGUID ) ) ||
268 ( IsEqualGUID( &IID_IDirectDraw, lpGUID ) ) ||
269 ( IsEqualGUID( &IID_IDirectDraw2, lpGUID ) ) ||
270 ( IsEqualGUID( &IID_IDirectDraw4, lpGUID ) ) ||
271 ( IsEqualGUID( &IID_IDirectDraw7, lpGUID ) )
273 /* choose an interface out of the list */
274 for (i=0;i<nrof_ddraw_drivers;i++) {
275 ddraw_driver *xddd = ddraw_drivers[i];
276 if (!xddd)
277 continue;
278 if (!ddd || (ddd->preference<xddd->preference)) {
279 drvindex = i;
280 ddd = xddd;
283 } else {
284 for (i=0;i<nrof_ddraw_drivers;i++) {
285 if (!ddraw_drivers[i])
286 continue;
287 if (IsEqualGUID(ddraw_drivers[i]->guid,lpGUID)) {
288 drvindex = i;
289 ddd = ddraw_drivers[i];
290 break;
294 if (!ddd) {
295 if (!nrof_ddraw_drivers) {
296 ERR("DirectDrawCreate(%s,%p,%p): no DirectDraw drivers compiled in.\n",debugstr_guid(lpGUID),lplpDD,pUnkOuter);
297 return DDERR_NODIRECTDRAWHW;
299 ERR("DirectDrawCreate(%s,%p,%p): did not recognize requested GUID.\n",debugstr_guid(lpGUID),lplpDD,pUnkOuter);
300 return DDERR_INVALIDDIRECTDRAWGUID;
302 TRACE("using \"%s\" driver, calling %p\n",ddd->name,ddd->createDDRAW);
304 ret = ddd->createDDRAW(lplpDD);
305 if (!ret)
306 break;
307 ddraw_drivers[drvindex] = NULL; /* mark this one as unusable */
309 wc.style = CS_GLOBALCLASS;
310 wc.lpfnWndProc = DDWndProc;
311 wc.cbClsExtra = 0;
312 wc.cbWndExtra = 0;
314 /* We can be a child of the desktop since we're really important */
315 wc.hInstance= 0;
316 wc.hIcon = 0;
317 wc.hCursor = (HCURSOR)IDC_ARROWA;
318 wc.hbrBackground = NULL_BRUSH;
319 wc.lpszMenuName = 0;
320 wc.lpszClassName = "WINE_DirectDraw";
321 (*ilplpDD)->d->winclass = RegisterClassA(&wc);
322 return ret;
325 /***********************************************************************
326 * DirectDrawCreateEx
328 HRESULT WINAPI DirectDrawCreateEx(
329 LPGUID lpGUID, LPVOID* lplpDD, REFIID iid, LPUNKNOWN pUnkOuter
331 FIXME(":semi stub\n");
332 /* I don't know about what functionality is unique to Ex */
333 return DirectDrawCreate(lpGUID,(LPDIRECTDRAW*)lplpDD,pUnkOuter);
336 /*******************************************************************************
337 * DirectDraw ClassFactory
339 * Heavily inspired (well, can you say completely copied :-) ) from DirectSound
342 typedef struct {
343 /* IUnknown fields */
344 ICOM_VFIELD(IClassFactory);
345 DWORD ref;
346 } IClassFactoryImpl;
348 static HRESULT WINAPI
349 DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
350 ICOM_THIS(IClassFactoryImpl,iface);
352 FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
353 return E_NOINTERFACE;
356 static ULONG WINAPI
357 DDCF_AddRef(LPCLASSFACTORY iface) {
358 ICOM_THIS(IClassFactoryImpl,iface);
359 return ++(This->ref);
362 static ULONG WINAPI DDCF_Release(LPCLASSFACTORY iface) {
363 ICOM_THIS(IClassFactoryImpl,iface);
364 /* static class, won't be freed */
365 return --(This->ref);
368 static HRESULT WINAPI DDCF_CreateInstance(
369 LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
371 ICOM_THIS(IClassFactoryImpl,iface);
373 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
374 if ( ( IsEqualGUID( &IID_IDirectDraw, riid ) ) ||
375 ( IsEqualGUID( &IID_IDirectDraw2, riid ) ) ||
376 ( IsEqualGUID( &IID_IDirectDraw4, riid ) ) ) {
377 /* FIXME: reuse already created DirectDraw if present? */
378 return DirectDrawCreate((LPGUID) riid,(LPDIRECTDRAW*)ppobj,pOuter);
380 return CLASS_E_CLASSNOTAVAILABLE;
383 static HRESULT WINAPI DDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
384 ICOM_THIS(IClassFactoryImpl,iface);
385 FIXME("(%p)->(%d),stub!\n",This,dolock);
386 return S_OK;
389 static ICOM_VTABLE(IClassFactory) DDCF_Vtbl =
391 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
392 DDCF_QueryInterface,
393 DDCF_AddRef,
394 DDCF_Release,
395 DDCF_CreateInstance,
396 DDCF_LockServer
398 static IClassFactoryImpl DDRAW_CF = {&DDCF_Vtbl, 1 };
400 /*******************************************************************************
401 * DllGetClassObject [DDRAW.13]
402 * Retrieves class object from a DLL object
404 * NOTES
405 * Docs say returns STDAPI
407 * PARAMS
408 * rclsid [I] CLSID for the class object
409 * riid [I] Reference to identifier of interface for class object
410 * ppv [O] Address of variable to receive interface pointer for riid
412 * RETURNS
413 * Success: S_OK
414 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
415 * E_UNEXPECTED
417 DWORD WINAPI DDRAW_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
419 TRACE("(%p,%p,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
420 if ( IsEqualGUID( &IID_IClassFactory, riid ) ) {
421 *ppv = (LPVOID)&DDRAW_CF;
422 IClassFactory_AddRef((IClassFactory*)*ppv);
423 return S_OK;
425 FIXME("(%p,%p,%p): no interface found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
426 return CLASS_E_CLASSNOTAVAILABLE;
430 /*******************************************************************************
431 * DllCanUnloadNow [DDRAW.12] Determines whether the DLL is in use.
433 * RETURNS
434 * Success: S_OK
435 * Failure: S_FALSE
437 DWORD WINAPI DDRAW_DllCanUnloadNow(void) {
438 FIXME("(void): stub\n");
439 return S_FALSE;