Fixed some warnings.
[wine.git] / dlls / ddraw / main.c
blobffc878a3682672d4f71f36b52731951f4e828140
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 "dc.h"
19 #include "win.h"
20 #include "wine/exception.h"
21 #include "ddraw.h"
22 #include "d3d.h"
23 #include "debugtools.h"
24 #include "message.h"
25 #include "monitor.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 /**********************************************************************/
48 typedef struct {
49 LPVOID lpCallback;
50 LPVOID lpContext;
51 } DirectDrawEnumerateProcData;
53 /***********************************************************************
54 * DirectDrawEnumerateExA (DDRAW.*)
56 HRESULT WINAPI DirectDrawEnumerateExA(
57 LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
59 int i;
60 TRACE("(%p,%p, %08lx)\n", lpCallback, lpContext, dwFlags);
62 if (TRACE_ON(ddraw)) {
63 DPRINTF(" Flags : ");
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 ");
70 DPRINTF("\n");
73 /* Invoke callback for what flags we do support */
74 for (i=0;i<MAX_DDRAW_DRIVERS;i++) {
75 if (!ddraw_drivers[i])
76 continue;
77 if (ddraw_drivers[i]->createDDRAW(NULL)) /* !0 is failing */
78 continue;
79 TRACE("Enumerating %s/%s interface\n",ddraw_drivers[i]->name,ddraw_drivers[i]->type);
80 if (!lpCallback(
81 ddraw_drivers[i]->guid,
82 (LPSTR)ddraw_drivers[i]->name,
83 (LPSTR)ddraw_drivers[i]->type,
84 lpContext,
85 0 /* FIXME: flags not supported here */
87 return DD_OK;
89 if (nrof_ddraw_drivers) {
90 TRACE("Enumerating the default interface\n");
91 if (!lpCallback(NULL,"WINE (default)", "display", lpContext, 0))
92 return DD_OK;
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");
108 return DD_OK;
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);
130 return bResult;
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)
202 LRESULT ret;
203 IDirectDrawImpl* ddraw = NULL;
204 DWORD lastError;
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);
213 if( ddraw ) {
214 /* Perform any special direct draw functions */
215 if (msg==WM_PAINT)
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
229 * - Lionel
231 ret = DefWindowProcA( ddraw->d.mainWindow, msg, wParam, lParam );
233 if( !ret ) {
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);
241 return ret;
242 } /* else FALLTHROUGH */
243 } /* else FALLTHROUGH */
244 return DefWindowProcA(hwnd,msg,wParam,lParam);
247 /***********************************************************************
248 * DirectDrawCreate
250 HRESULT WINAPI DirectDrawCreate(
251 LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter
253 IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
254 WNDCLASSA wc;
255 HRESULT ret = 0;
256 int i,drvindex=0;
257 GUID zeroGUID;
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));
266 while (1) {
267 ddd = NULL;
268 if ( ( !lpGUID ) ||
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];
278 if (!xddd)
279 continue;
280 if (!ddd || (ddd->preference<xddd->preference)) {
281 drvindex = i;
282 ddd = xddd;
285 } else {
286 for (i=0;i<nrof_ddraw_drivers;i++) {
287 if (!ddraw_drivers[i])
288 continue;
289 if (IsEqualGUID(ddraw_drivers[i]->guid,lpGUID)) {
290 drvindex = i;
291 ddd = ddraw_drivers[i];
292 break;
296 if (!ddd) {
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);
307 if (!ret)
308 break;
309 ddraw_drivers[drvindex] = NULL; /* mark this one as unusable */
311 wc.style = CS_GLOBALCLASS;
312 wc.lpfnWndProc = DDWndProc;
313 wc.cbClsExtra = 0;
314 wc.cbWndExtra = 0;
316 /* We can be a child of the desktop since we're really important */
317 wc.hInstance= 0;
318 wc.hIcon = 0;
319 wc.hCursor = (HCURSOR)IDC_ARROWA;
320 wc.hbrBackground = NULL_BRUSH;
321 wc.lpszMenuName = 0;
322 wc.lpszClassName = "WINE_DirectDraw";
323 (*ilplpDD)->d.winclass = RegisterClassA(&wc);
324 return ret;
327 /***********************************************************************
328 * DirectDrawCreateEx
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
344 typedef struct {
345 /* IUnknown fields */
346 ICOM_VFIELD(IClassFactory);
347 DWORD ref;
348 } IClassFactoryImpl;
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;
358 static ULONG WINAPI
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);
388 return S_OK;
391 static ICOM_VTABLE(IClassFactory) DDCF_Vtbl =
393 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
394 DDCF_QueryInterface,
395 DDCF_AddRef,
396 DDCF_Release,
397 DDCF_CreateInstance,
398 DDCF_LockServer
400 static IClassFactoryImpl DDRAW_CF = {&DDCF_Vtbl, 1 };
402 /*******************************************************************************
403 * DllGetClassObject [DDRAW.13]
404 * Retrieves class object from a DLL object
406 * NOTES
407 * Docs say returns STDAPI
409 * PARAMS
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
414 * RETURNS
415 * Success: S_OK
416 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
417 * E_UNEXPECTED
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);
425 return S_OK;
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.
435 * RETURNS
436 * Success: S_OK
437 * Failure: S_FALSE
439 DWORD WINAPI DDRAW_DllCanUnloadNow(void) {
440 FIXME("(void): stub\n");
441 return S_FALSE;