xref: /reactos/dll/directx/ddraw/Ddraw/ddraw_main.c (revision 50cf16b3)
1 /*
2  * COPYRIGHT:            See COPYING in the top level directory
3  * PROJECT:              ReactOS DirectX
4  * FILE:                 dll/directx/ddraw/Ddraw/ddraw_main.c
5  * PURPOSE:              IDirectDraw7 Implementation
6  * PROGRAMMER:           Magnus Olsen, Maarten Bosma
7  *
8  */
9 
10 /* TODO
11  * add warper functions for dx 1 - 6
12  * map the  DirectDraw4_Vtable, DirectDraw2_Vtable, DirectDraw_Vtable
13  * table to right version of the functions
14  */
15 
16 
17 
18 #include "rosdraw.h"
19 
20 #include <string.h>
21 
22 LPDDRAWI_DIRECTDRAW_INT
23 internal_directdraw_int_alloc(LPDDRAWI_DIRECTDRAW_INT This)
24 {
25     LPDDRAWI_DIRECTDRAW_INT  newThis;
26     DxHeapMemAlloc(newThis, sizeof(DDRAWI_DIRECTDRAW_INT));
27     if (newThis)
28     {
29         newThis->lpLcl = This->lpLcl;
30         newThis->lpLink = This;
31     }
32 
33     return  newThis;
34 }
35 
36 HRESULT WINAPI
37 Main_DirectDraw_QueryInterface (LPDDRAWI_DIRECTDRAW_INT This,
38                                 REFIID id,
39                                 LPVOID *obj)
40 {
41     HRESULT retVal = DD_OK;
42 
43     DX_WINDBG_trace();
44 
45     _SEH2_TRY
46     {
47         /* FIXME
48             the D3D object can be obtained from here
49             Direct3D7
50         */
51         if (IsEqualGUID(&IID_IDirectDraw7, id))
52         {
53             if (This->lpVtbl != &DirectDraw7_Vtable)
54             {
55                 This = internal_directdraw_int_alloc(This);
56                 if (!This)
57                 {
58                     retVal = DDERR_OUTOFVIDEOMEMORY;
59                     _SEH2_LEAVE;
60                 }
61             }
62 
63             This->lpVtbl = &DirectDraw7_Vtable;
64             *obj = This;
65             Main_DirectDraw_AddRef(This);
66         }
67         else if (IsEqualGUID(&IID_IDirectDraw4, id))
68         {
69             if (This->lpVtbl != &DirectDraw4_Vtable)
70             {
71                 This = internal_directdraw_int_alloc(This);
72                 if (!This)
73                 {
74                     retVal = DDERR_OUTOFVIDEOMEMORY;
75                     _SEH2_LEAVE;
76                 }
77             }
78 
79             This->lpVtbl = &DirectDraw4_Vtable;
80             *obj = This;
81             Main_DirectDraw_AddRef(This);
82         }
83 
84         else if (IsEqualGUID(&IID_IDirectDraw2, id))
85         {
86             if (This->lpVtbl != &DirectDraw2_Vtable)
87             {
88                 This = internal_directdraw_int_alloc(This);
89                 if (!This)
90                 {
91                     retVal = DDERR_OUTOFVIDEOMEMORY;
92                     _SEH2_LEAVE;
93                 }
94             }
95 
96             This->lpVtbl = &DirectDraw2_Vtable;
97             *obj = This;
98             Main_DirectDraw_AddRef(This);
99         }
100         else if (IsEqualGUID(&IID_IDirectDraw, id))
101         {
102             if (This->lpVtbl != &DirectDraw_Vtable)
103             {
104                 This = internal_directdraw_int_alloc(This);
105                 if (!This)
106                 {
107                     retVal = DDERR_OUTOFVIDEOMEMORY;
108                     _SEH2_LEAVE;
109                 }
110             }
111 
112             This->lpVtbl = &DirectDraw_Vtable;
113             *obj = This;
114             Main_DirectDraw_AddRef(This);
115         }
116         else
117         {
118             *obj = NULL;
119             DX_STUB_str("E_NOINTERFACE");
120             retVal = E_NOINTERFACE;
121         }
122     }
123     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
124     {
125     }
126     _SEH2_END;
127 
128     return retVal;
129 }
130 
131 /*++
132 * @name DDraw->AddRef
133 * @implemented
134 *
135 * The function DDraw->AddRef manages all ref counters in the COM object DDraw->
136 
137 * @return
138 * Returns the local Ref counter value for the COM object
139 *
140 * @remarks.
141 * none
142 *
143 *--*/
144 ULONG WINAPI
145 Main_DirectDraw_AddRef (LPDDRAWI_DIRECTDRAW_INT This)
146 {
147     ULONG retValue = 0;
148 
149     DX_WINDBG_trace();
150 
151     /* Lock the thread */
152     AcquireDDThreadLock();
153 
154     _SEH2_TRY
155     {
156         /* Increment the internal ref counter */
157         This->dwIntRefCnt++;
158 
159         /* Increment the local internal ref counter */
160         This->lpLcl->dwLocalRefCnt++;
161 
162         if (This->lpLcl->lpGbl != NULL)
163         {
164             /* Increment the global internal ref counter */
165             This->lpLcl->lpGbl->dwRefCnt++;
166         }
167     }
168     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
169     {
170     }
171     _SEH2_END;
172 
173     _SEH2_TRY
174     {
175         retValue = This->dwIntRefCnt;
176     }
177     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
178     {
179         retValue = 0;
180     }
181     _SEH2_END;
182 
183     /* Release the thread lock */
184     ReleaseDDThreadLock();
185 
186     /* Return the local Ref counter */
187     return retValue;
188 }
189 
190 
191 
192 
193 ULONG WINAPI
194 Main_DirectDraw_Release (LPDDRAWI_DIRECTDRAW_INT This)
195 {
196     ULONG Counter = 0;
197 
198     DX_WINDBG_trace();
199 
200     /* Lock the thread */
201     AcquireDDThreadLock();
202 
203     _SEH2_TRY
204     {
205         if (This!=NULL)
206         {
207             This->lpLcl->dwLocalRefCnt--;
208             This->dwIntRefCnt--;
209 
210             if (This->lpLcl->lpGbl != NULL)
211             {
212                 This->lpLcl->lpGbl->dwRefCnt--;
213             }
214 
215             if ( This->lpLcl->lpGbl->dwRefCnt == 0)
216             {
217                 // set resolution back to the one in registry
218                 /*if(This->cooperative_level & DDSCL_EXCLUSIVE)
219                 {
220                     ChangeDisplaySettings(NULL, 0);
221                 }*/
222 
223                 Cleanup(This);
224             }
225 
226             /* FIXME cleanup being not call why ?? */
227             Counter = This->dwIntRefCnt;
228         }
229         else
230         {
231             Counter = This->dwIntRefCnt;
232         }
233     }
234     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
235     {
236     }
237     _SEH2_END;
238 
239     /* Release the thread lock */
240     ReleaseDDThreadLock();
241 
242     return Counter;
243 }
244 
245 
246 HRESULT WINAPI
247 Main_DirectDraw_Initialize (LPDDRAWI_DIRECTDRAW_INT This, LPGUID lpGUID)
248 {
249 	return DDERR_ALREADYINITIALIZED;
250 }
251 
252 
253 /*++
254 * @name DDraw->Compact
255 * @implemented
256 *
257 * In exclusive mode the function DDraw->Compact returns DERR_NOEXCLUSIVEMODE, otherwise it returns DD_OK
258 *
259 * @return
260 * Returns only error code DD_OK or DERR_NOEXCLUSIVEMODE
261 *
262 * @remarks.
263 *  Microsoft says Compact is not implemented in ddraw.dll, but it returns  DDERR_NOEXCLUSIVEMODE or DD_OK
264 *
265 *--*/
266 HRESULT WINAPI
267 Main_DirectDraw_Compact(LPDDRAWI_DIRECTDRAW_INT This)
268 {
269     HRESULT retVal = DD_OK;
270 
271     DX_WINDBG_trace();
272 
273     /* Lock the thread */
274     AcquireDDThreadLock();
275 
276     _SEH2_TRY
277     {
278         /* Check if Exclusive mode has been activated */
279         if (This->lpLcl->lpGbl->lpExclusiveOwner != This->lpLcl)
280         {
281             retVal = DDERR_NOEXCLUSIVEMODE;
282         }
283     }
284     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
285     {
286     }
287     _SEH2_END;
288 
289     /* Release the thread lock */
290     ReleaseDDThreadLock();
291 
292     return retVal;
293 }
294 
295 HRESULT WINAPI
296 Main_DirectDraw_GetAvailableVidMem(LPDDRAWI_DIRECTDRAW_INT This, LPDDSCAPS ddscaps, LPDWORD dwTotal, LPDWORD dwFree)
297 {
298     DDSCAPS2 myddscaps;
299     HRESULT retValue = DD_OK;
300 
301     ZeroMemory(&myddscaps, sizeof(DDSCAPS2));
302 
303     _SEH2_TRY
304     {
305         myddscaps.dwCaps =  ddscaps->dwCaps;
306         retValue = Main_DirectDraw_GetAvailableVidMem4(This, &myddscaps, dwTotal, dwFree);
307     }
308     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
309     {
310          retValue = DDERR_INVALIDPARAMS;
311     }
312     _SEH2_END;
313 
314     return retValue;
315 }
316 
317 HRESULT WINAPI
318 Main_DirectDraw_GetAvailableVidMem4(LPDDRAWI_DIRECTDRAW_INT This, LPDDSCAPS2 ddscaps,
319                    LPDWORD dwTotal, LPDWORD dwFree)
320 {
321     HRESULT retVal = DD_OK;
322     DDHAL_GETAVAILDRIVERMEMORYDATA  memdata;
323 
324     DX_WINDBG_trace();
325 
326     _SEH2_TRY
327     {
328         // There is no HEL implementation of this api
329         if (!(This->lpLcl->lpDDCB->HALDDMiscellaneous.dwFlags & DDHAL_MISCCB32_GETAVAILDRIVERMEMORY) ||
330             (This->lpLcl->lpGbl->dwFlags & DDRAWI_NOHARDWARE) )
331         {
332             retVal = DDERR_NODIRECTDRAWHW;
333         }
334         else
335         {
336             if ((!dwTotal && !dwFree) || !ddscaps)
337             {
338                 retVal = DDERR_INVALIDPARAMS;
339                 _SEH2_LEAVE;
340             }
341 
342             if ( ddscaps->dwCaps & (DDSCAPS_BACKBUFFER  | DDSCAPS_COMPLEX   | DDSCAPS_FLIP |
343                                     DDSCAPS_FRONTBUFFER | DDSCAPS_PALETTE   | DDSCAPS_SYSTEMMEMORY |
344                                     DDSCAPS_VISIBLE     | DDSCAPS_WRITEONLY | DDSCAPS_OWNDC))
345             {
346                 retVal = DDERR_INVALIDPARAMS;
347                 _SEH2_LEAVE;
348             }
349 
350 
351             /*   ddscaps->dwCaps2 & 0x01
352                 this flag is outdate and are
353                 set to 0 in ms dxsdk  the name of
354                 this flag is DDSCAPS2_HARDWAREDEINTERLACE
355             */
356 
357             if ( ddscaps->dwCaps2 & 0x01)
358             {
359                 retVal = DDERR_INVALIDCAPS;
360                 _SEH2_LEAVE;
361             }
362 
363             if ( ddscaps->dwCaps3 & ~( DDSCAPS3_MULTISAMPLE_QUALITY_MASK | DDSCAPS3_MULTISAMPLE_MASK |
364                                        DDSCAPS3_RESERVED1                | DDSCAPS3_RESERVED2        |
365                                        DDSCAPS3_LIGHTWEIGHTMIPMAP        | DDSCAPS3_AUTOGENMIPMAP    |
366                                        DDSCAPS3_DMAP))
367             {
368                 retVal = DDERR_INVALIDCAPS;
369                 _SEH2_LEAVE;
370             }
371 
372             if ( ddscaps->dwCaps4)
373             {
374                 retVal = DDERR_INVALIDCAPS;
375                 _SEH2_LEAVE;
376             }
377 
378             ZeroMemory(&memdata, sizeof(DDHAL_GETAVAILDRIVERMEMORYDATA));
379             memdata.lpDD = This->lpLcl->lpGbl;
380             memdata.ddRVal = DDERR_INVALIDPARAMS;
381 
382             memdata.ddsCapsEx.dwCaps2 = ddscaps->dwCaps2;
383             memdata.ddsCapsEx.dwCaps3 = ddscaps->dwCaps3;
384 
385             This->lpLcl->lpGbl->hDD = This->lpLcl->hDD;
386 
387             if (This->lpLcl->lpDDCB->HALDDMiscellaneous.GetAvailDriverMemory(&memdata) == DDHAL_DRIVER_NOTHANDLED)
388             {
389                 retVal = DDERR_NODIRECTDRAWHW;
390 
391                 if (dwTotal)
392                     *dwTotal = 0;
393 
394                 if (dwFree)
395                     *dwFree = 0;
396             }
397             else
398             {
399                 if (dwTotal)
400                     *dwTotal = memdata.dwTotal;
401 
402                 if (dwFree)
403                     *dwFree = memdata.dwFree;
404 
405                 retVal = memdata.ddRVal;
406             }
407         }
408     }
409     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
410     {
411     }
412     _SEH2_END;
413 
414     return retVal;
415 }
416 
417 HRESULT WINAPI
418 Main_DirectDraw_GetFourCCCodes(LPDDRAWI_DIRECTDRAW_INT This, LPDWORD lpNumCodes, LPDWORD lpCodes)
419 {
420     HRESULT retVal = DD_OK;
421 
422     DX_WINDBG_trace();
423 
424 
425      // EnterCriticalSection(&ddcs);
426 
427     _SEH2_TRY
428     {
429         if(IsBadWritePtr(lpNumCodes,sizeof(LPDWORD)))
430         {
431             retVal = DDERR_INVALIDPARAMS;
432         }
433         else
434         {
435             if(!(IsBadWritePtr(lpNumCodes,sizeof(LPDWORD))))
436             {
437                 DWORD size;
438 
439                 if (*lpNumCodes > This->lpLcl->lpGbl->dwNumFourCC)
440                 {
441                     *lpNumCodes = This->lpLcl->lpGbl->dwNumFourCC;
442                 }
443 
444                 size =  *lpNumCodes * sizeof(DWORD);
445 
446                 if(!IsBadWritePtr(lpCodes, size ))
447                 {
448                     memcpy(lpCodes, This->lpLcl->lpGbl->lpdwFourCC, size );
449                 }
450                 else
451                 {
452                     *lpNumCodes = This->lpLcl->lpGbl->dwNumFourCC;
453                 }
454             }
455         }
456     }
457     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
458     {
459     }
460     _SEH2_END;
461 
462     //LeaveCriticalSection(&ddcs);
463     return retVal;
464 }
465 
466 
467 /*
468  * We can obtain the version of the directdraw object by compare the
469  * vtl table pointer from iface we do not need pass which version
470  * we whant to use
471  *
472  * Main_DirectDraw_CreateSurface is dead at moment we do only support
473  * directdraw 7 at moment
474  */
475 
476 /* For DirectDraw 1 - 3 */
477 HRESULT WINAPI
478 Main_DirectDraw_CreateSurface (LPDDRAWI_DIRECTDRAW_INT This, LPDDSURFACEDESC pDDSD,
479                                LPDDRAWI_DDRAWSURFACE_INT *ppSurf, IUnknown *pUnkOuter)
480 {
481    HRESULT ret = DDERR_GENERIC;
482    DDSURFACEDESC2 dd_desc_v2;
483 
484    DX_WINDBG_trace();
485 
486     EnterCriticalSection(&ddcs);
487     *ppSurf = NULL;
488 
489     _SEH2_TRY
490     {
491         if (pDDSD->dwSize == sizeof(DDSURFACEDESC))
492         {
493             CopyDDSurfDescToDDSurfDesc2(&dd_desc_v2, (LPDDSURFACEDESC)pDDSD);
494             ret = Internal_CreateSurface(This,
495                                          &dd_desc_v2,
496                                          ppSurf,
497                                          pUnkOuter);
498         }
499         else
500         {
501             ret = DDERR_INVALIDPARAMS;
502         }
503     }
504     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
505     {
506         ret = DDERR_INVALIDPARAMS;
507     }
508     _SEH2_END;
509     LeaveCriticalSection(&ddcs);
510     return ret;
511 }
512 
513 
514 /* For DirectDraw 4 - 7 */
515 HRESULT WINAPI
516 Main_DirectDraw_CreateSurface4(LPDDRAWI_DIRECTDRAW_INT This, LPDDSURFACEDESC2 pDDSD,
517                                LPDDRAWI_DDRAWSURFACE_INT *ppSurf, IUnknown *pUnkOuter)
518 {
519     HRESULT ret = DD_OK;
520     DX_WINDBG_trace();
521 
522     EnterCriticalSection(&ddcs);
523     *ppSurf = NULL;
524 
525     _SEH2_TRY
526     {
527         ret = Internal_CreateSurface(This, pDDSD, ppSurf, pUnkOuter);
528     }
529     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
530     {
531         ret = DDERR_INVALIDPARAMS;
532     }
533     _SEH2_END;
534 
535     if(*ppSurf != NULL)
536         Main_DirectDraw_AddRef(This);
537 
538     LeaveCriticalSection(&ddcs);
539     return ret;
540 }
541 
542 /* 5 of 31 DirectDraw7_Vtable api are working similar to windows */
543 /* 8 of 31 DirectDraw7_Vtable api are under devloping / testing */
544 
545 HRESULT WINAPI Main_DirectDraw_CreatePalette(LPDDRAWI_DIRECTDRAW_INT This, DWORD dwFlags,
546                   LPPALETTEENTRY palent, LPDIRECTDRAWPALETTE* ppPalette, LPUNKNOWN pUnkOuter)
547 {
548 	HRESULT ret = DD_OK;
549     DX_WINDBG_trace();
550 
551     EnterCriticalSection(&ddcs);
552     *ppPalette = NULL;
553 
554     _SEH2_TRY
555     {
556         ret = Internal_CreatePalette(This, dwFlags, palent, ppPalette, pUnkOuter);
557     }
558     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
559     {
560         ret = DDERR_INVALIDPARAMS;
561     }
562     _SEH2_END;
563 
564     //Versions 7 and 4 are addref'ed
565     if((This->lpVtbl == &DirectDraw7_Vtable || This->lpVtbl == &DirectDraw4_Vtable) && *ppPalette != NULL)
566         Main_DirectDraw_AddRef(This) ;
567 
568     LeaveCriticalSection(&ddcs);
569     return ret;
570 }
571 
572 
573 
574 
575 
576 
577 
578