Use shell icon cache instead of an own IExtractIcon implementation.
[wine] / dlls / ddraw / ddraw_hal.c
1 /*      DirectDraw HAL driver
2  *
3  * Copyright 2001 TransGaming Technologies Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "config.h"
21
22 #include <assert.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25
26 #define CONST_VTABLE
27
28 #include "wine/debug.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "ddraw.h"
33 #include "ddrawi.h"
34 #include "d3dhal.h"
35
36 #include "ddraw_private.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39
40 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable;
41
42 static DDVERSIONDATA hal_version;
43 static DD32BITDRIVERDATA hal_driverdata;
44 static HINSTANCE hal_instance;
45
46 static const DDDEVICEIDENTIFIER2 hal_device =
47 {
48     "display",
49     "DirectDraw HAL",
50     { { 0x00010001, 0x00010001 } },
51     0, 0, 0, 0,
52     /* 40c1b248-9d7d-4a29-b7d7-4cd8109f3d5d */
53     {0x40c1b248,0x9d7d,0x4a29,{0xd7,0xb7,0x4c,0xd8,0x10,0x9f,0x3d,0x5d}},
54     0
55 };
56
57 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
58                               IUnknown* pUnkOuter, BOOL ex);
59 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl*, const GUID*);
60
61 static const ddraw_driver hal_driver =
62 {
63     &hal_device,
64     100, /* we prefer the HAL */
65     HAL_DirectDraw_Create,
66     HAL_DirectDraw_Initialize
67 };
68
69 static DDHAL_CALLBACKS dd_cbs;
70 static DDRAWI_DIRECTDRAW_GBL dd_gbl;
71
72 static D3DHAL_GLOBALDRIVERDATA d3d_hal_data;
73 static D3DHAL_D3DEXTENDEDCAPS d3d_hal_extcaps;
74 static D3DHAL_CALLBACKS d3d_hal_cbs1;
75 static D3DHAL_CALLBACKS2 d3d_hal_cbs2;
76
77 /* in real windoze, these entry points are 16-bit, but we can work in 32-bit */
78 static BOOL WINAPI set_hal_info(LPDDHALINFO lpDDHalInfo, BOOL reset)
79 {
80     dd_cbs.HALDD        = *lpDDHalInfo->lpDDCallbacks;
81     dd_cbs.HALDDSurface = *lpDDHalInfo->lpDDSurfaceCallbacks;
82     dd_cbs.HALDDPalette = *lpDDHalInfo->lpDDPaletteCallbacks;
83     if (lpDDHalInfo->lpDDExeBufCallbacks)
84         dd_cbs.HALDDExeBuf      = *lpDDHalInfo->lpDDExeBufCallbacks;
85
86     dd_gbl.lpDDCBtmp = &dd_cbs;
87
88     dd_gbl.ddCaps                = lpDDHalInfo->ddCaps;
89     dd_gbl.dwMonitorFrequency    = lpDDHalInfo->dwMonitorFrequency;
90     dd_gbl.vmiData               = lpDDHalInfo->vmiData;
91     dd_gbl.dwModeIndex           = lpDDHalInfo->dwModeIndex;
92     dd_gbl.dwNumFourCC           = lpDDHalInfo->ddCaps.dwNumFourCCCodes;
93     dd_gbl.lpdwFourCC            = lpDDHalInfo->lpdwFourCC;
94     dd_gbl.dwNumModes            = lpDDHalInfo->dwNumModes;
95     dd_gbl.lpModeInfo            = lpDDHalInfo->lpModeInfo;
96     /* FIXME: dwFlags */
97     dd_gbl.dwPDevice             = (DWORD)lpDDHalInfo->lpPDevice;
98     dd_gbl.hInstance             = lpDDHalInfo->hInstance;
99     /* DirectX 2 */
100     if (lpDDHalInfo->lpD3DGlobalDriverData)
101         memcpy(&d3d_hal_data, (LPVOID)lpDDHalInfo->lpD3DGlobalDriverData, sizeof(D3DDEVICEDESC_V1));
102     else
103         memset(&d3d_hal_data, 0, sizeof(D3DDEVICEDESC_V1));
104     dd_gbl.lpD3DGlobalDriverData = (ULONG_PTR)&d3d_hal_data;
105
106     if (lpDDHalInfo->lpD3DHALCallbacks)
107         memcpy(&d3d_hal_cbs1, (LPVOID)lpDDHalInfo->lpD3DHALCallbacks, sizeof(D3DHAL_CALLBACKS));
108     else
109         memset(&d3d_hal_cbs1, 0, sizeof(D3DHAL_CALLBACKS));
110     dd_gbl.lpD3DHALCallbacks     = (ULONG_PTR)&d3d_hal_cbs1;
111
112     if (lpDDHalInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) {
113         DDHAL_GETDRIVERINFODATA data;
114         data.dwSize = sizeof(DDHAL_GETDRIVERINFODATA);
115         data.dwFlags = 0; /* ? */
116         data.dwContext = hal_driverdata.dwContext; /* ? */
117
118         data.guidInfo = GUID_D3DExtendedCaps;
119         data.dwExpectedSize = sizeof(D3DHAL_D3DEXTENDEDCAPS);
120         data.lpvData = &d3d_hal_extcaps;
121         data.dwActualSize = 0;
122         data.ddRVal = 0;
123         lpDDHalInfo->GetDriverInfo(&data);
124         d3d_hal_extcaps.dwSize = data.dwActualSize;
125         dd_gbl.lpD3DExtendedCaps = (ULONG_PTR)&d3d_hal_extcaps;
126
127         data.guidInfo = GUID_D3DCallbacks2;
128         data.dwExpectedSize = sizeof(D3DHAL_CALLBACKS2);
129         data.lpvData = &d3d_hal_cbs2;
130         data.dwActualSize = 0;
131         data.ddRVal = 0;
132         lpDDHalInfo->GetDriverInfo(&data);
133         d3d_hal_cbs2.dwSize = data.dwActualSize;
134         dd_gbl.lpD3DHALCallbacks2 = (ULONG_PTR)&d3d_hal_cbs2;
135     }
136
137     if( opengl_initialized && 
138            (d3d_hal_data.hwCaps.dwFlags & D3DDD_WINE_OPENGL_DEVICE) ) {
139         /*GL_DirectDraw_Init(&dd_gbl);*/
140     }
141
142     return FALSE;
143 }
144
145 static DDHALDDRAWFNS hal_funcs = {
146     sizeof(DDHALDDRAWFNS),
147     set_hal_info,
148     NULL, /* VidMemAlloc */
149     NULL  /* VidMemFree */
150 };
151
152 /* Called from DllInit, which is synchronised so there are no threading
153  * concerns. */
154 static BOOL initialize(void)
155 {
156     DCICMD cmd;
157     INT ncmd = DCICOMMAND;
158     BOOL ret;
159     HDC dc = CreateDCA("DISPLAY", NULL, NULL, NULL);
160     INT ver = Escape(dc, QUERYESCSUPPORT, sizeof(ncmd), (LPVOID)&ncmd, NULL);
161     if (ver != DD_HAL_VERSION) {
162         DeleteDC(dc);
163         TRACE("DirectDraw HAL not available\n");
164         return FALSE;
165     }
166     cmd.dwVersion = DD_VERSION;
167     cmd.dwReserved = 0;
168
169     /* the DDNEWCALLBACKFNS is supposed to give the 16-bit driver entry points
170      * in ddraw16.dll, but since Wine doesn't have or use 16-bit display drivers,
171      * we'll just work in 32-bit, who'll notice... */
172     cmd.dwCommand = DDNEWCALLBACKFNS;
173     cmd.dwParam1 = (DWORD)&hal_funcs;
174     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, 0, NULL);
175
176     /* next, exchange version information */
177     cmd.dwCommand = DDVERSIONINFO;
178     cmd.dwParam1 = DD_RUNTIME_VERSION; /* not sure what should *really* go here */
179     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_version), (LPVOID)&hal_version);
180
181     /* get 32-bit driver data (dll name and entry point) */
182     cmd.dwCommand = DDGET32BITDRIVERNAME;
183     ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_driverdata), (LPVOID)&hal_driverdata);
184     /* we're supposed to load the DLL in hal_driverdata.szName, then GetProcAddress
185      * the hal_driverdata.szEntryPoint, and call it with hal_driverdata.dwContext
186      * as a parameter... but since this is only more remains from the 16-bit world,
187      * we'll ignore it */
188
189     /* finally, initialize the driver object */
190     cmd.dwCommand = DDCREATEDRIVEROBJECT;
191     ret = ExtEscape(dc, DCICOMMAND, sizeof(cmd), (LPVOID)&cmd, sizeof(hal_instance), (LPVOID)&hal_instance);
192     if (ret) {
193         /* the driver should have called our set_hal_info now */
194         if (!dd_gbl.lpDDCBtmp) ret = FALSE;
195     }
196
197     /* init done */
198     DeleteDC(dc);
199
200     TRACE("%s DirectDraw HAL\n", ret ? "enabling" : "disabling");
201
202     return ret;
203 }
204
205 static void cleanup(void)
206 {
207     DDHAL_DESTROYDRIVERDATA data;
208
209     if (!dd_cbs.HALDD.DestroyDriver) return;
210
211     data.lpDD = NULL;
212     data.ddRVal = 0;
213     data.DestroyDriver = dd_cbs.HALDD.DestroyDriver;
214     data.DestroyDriver(&data);
215 }
216
217 static DWORD choose_mode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP,
218                          DWORD dwRefreshRate, DWORD dwFlags)
219 {
220     int best = -1;
221     unsigned int i;
222
223     if (!dd_gbl.dwNumModes) return 0;
224
225 /* let's support HALs that cannot switch depths (XVidMode),
226  * these should return dwBPP == 0 for all their resolutions */
227 #define BPP_MATCH(dd, bpp) ((!(dd)) || ((dd) == bpp))
228
229 /* FIXME: we should try to match the refresh rate too */
230
231     /* Choose the smallest mode that is large enough. */
232     for (i=0; i < dd_gbl.dwNumModes; i++)
233     {
234         if (dd_gbl.lpModeInfo[i].dwWidth >= dwWidth &&
235             dd_gbl.lpModeInfo[i].dwHeight >= dwHeight &&
236             BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
237         {
238             if (best == -1) best = i;
239             else
240             {
241                 if (dd_gbl.lpModeInfo[i].dwWidth < dd_gbl.lpModeInfo[best].dwWidth ||
242                     dd_gbl.lpModeInfo[i].dwHeight < dd_gbl.lpModeInfo[best].dwHeight)
243                     best = i;
244             }
245         }
246     }
247
248     if (best == -1)
249     {
250         TRACE("all modes too small\n");
251         /* ok, let's use the largest */
252
253         for (i=0; i < dd_gbl.dwNumModes; i++)
254         {
255             if (BPP_MATCH(dd_gbl.lpModeInfo[i].dwBPP, dwBPP))
256             {
257                 if (best == -1) best = i;
258                 else
259                 {
260                     if (dd_gbl.lpModeInfo[i].dwWidth > dd_gbl.lpModeInfo[best].dwWidth ||
261                         dd_gbl.lpModeInfo[i].dwHeight > dd_gbl.lpModeInfo[best].dwHeight)
262                         best = i;
263                 }
264             }
265         }
266     }
267 #undef BPP_MATCH
268
269     if (best == -1)
270     {
271         ERR("requested color depth (%ld) not available, try reconfiguring X server\n", dwBPP);
272         return dd_gbl.dwModeIndex;
273     }
274
275     TRACE("using mode %d\n", best);
276
277     return best;
278 }
279
280 static HRESULT set_mode(IDirectDrawImpl *This, DWORD dwMode)
281 {
282     HRESULT hr = DD_OK;
283
284     if (dwMode != dd_gbl.dwModeIndex)
285     {
286         DDHAL_SETMODEDATA data;
287         data.lpDD = &dd_gbl;
288         data.dwModeIndex = dwMode;
289         data.ddRVal = 0;
290         data.SetMode = dd_cbs.HALDD.SetMode;
291         data.inexcl = 0;
292         data.useRefreshRate = FALSE;
293         if (data.SetMode)
294             data.SetMode(&data);
295         hr = data.ddRVal;
296         if (SUCCEEDED(hr))
297             dd_gbl.dwModeIndex = dwMode;
298     }
299     return hr;
300 }
301
302 static HRESULT set_exclusive_mode(IDirectDrawImpl *This, DWORD dwEnterExcl)
303 {
304     DDHAL_SETEXCLUSIVEMODEDATA data;
305
306     data.lpDD = &dd_gbl;
307     data.dwEnterExcl = dwEnterExcl;
308     data.dwReserved = 0;
309     data.ddRVal = 0;
310     data.SetExclusiveMode = dd_cbs.HALDD.SetExclusiveMode;
311     if (data.SetExclusiveMode)
312         data.SetExclusiveMode(&data);
313     return data.ddRVal;
314 }
315
316 BOOL DDRAW_HAL_Init(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
317 {
318     if (fdwReason == DLL_PROCESS_ATTACH)
319     {
320         if (initialize())
321             DDRAW_register_driver(&hal_driver);
322     }
323     else if (fdwReason == DLL_PROCESS_DETACH)
324     {
325         cleanup();
326     }
327
328     return TRUE;
329 }
330
331 /* Not called from the vtable. */
332 HRESULT HAL_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
333 {
334     HRESULT hr;
335
336     TRACE("(%p,%d)\n", This, ex);
337
338     hr = User_DirectDraw_Construct(This, ex);
339     if (FAILED(hr)) return hr;
340
341     This->local.lpGbl = &dd_gbl;
342
343     This->final_release = HAL_DirectDraw_final_release;
344     This->set_exclusive_mode = set_exclusive_mode;
345
346     This->create_palette = HAL_DirectDrawPalette_Create;
347
348     This->create_primary    = HAL_DirectDraw_create_primary;
349     This->create_backbuffer = HAL_DirectDraw_create_backbuffer;
350     This->create_texture    = HAL_DirectDraw_create_texture;
351
352     ICOM_INIT_INTERFACE(This, IDirectDraw7, HAL_DirectDraw_VTable);
353
354     /* merge HAL caps */
355     This->caps.dwCaps |= dd_gbl.ddCaps.dwCaps;
356     This->caps.dwCaps2 |= dd_gbl.ddCaps.dwCaps2;
357     This->caps.dwCKeyCaps |= dd_gbl.ddCaps.dwCKeyCaps;
358     This->caps.dwFXCaps |= dd_gbl.ddCaps.dwFXCaps;
359     This->caps.dwPalCaps |= dd_gbl.ddCaps.dwPalCaps;
360     /* FIXME: merge more caps */
361     This->caps.ddsCaps.dwCaps |= dd_gbl.ddCaps.ddsCaps.dwCaps;
362     This->caps.ddsCaps.dwCaps2 |= dd_gbl.ddsCapsMore.dwCaps2;
363     This->caps.ddsCaps.dwCaps3 |= dd_gbl.ddsCapsMore.dwCaps3;
364     This->caps.ddsCaps.dwCaps4 |= dd_gbl.ddsCapsMore.dwCaps4;
365     This->caps.ddsOldCaps.dwCaps = This->caps.ddsCaps.dwCaps;
366
367     return S_OK;
368 }
369
370 /* This function is called from DirectDrawCreate(Ex) on the most-derived
371  * class to start construction.
372  * Not called from the vtable. */
373 HRESULT HAL_DirectDraw_Create(const GUID* pGUID, LPDIRECTDRAW7* pIface,
374                               IUnknown* pUnkOuter, BOOL ex)
375 {
376     HRESULT hr;
377     IDirectDrawImpl* This;
378
379     TRACE("\n");
380
381     assert(pUnkOuter == NULL);
382
383     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
384                      sizeof(IDirectDrawImpl)
385                      + sizeof(HAL_DirectDrawImpl));
386     if (This == NULL) return E_OUTOFMEMORY;
387
388     /* Note that this relation does *not* hold true if the DD object was
389      * CoCreateInstanced then Initialized. */
390     This->private = (HAL_DirectDrawImpl *)(This+1);
391
392     /* Initialize the DDCAPS structure */
393     This->caps.dwSize = sizeof(This->caps);
394
395     hr = HAL_DirectDraw_Construct(This, ex);
396     if (FAILED(hr))
397         HeapFree(GetProcessHeap(), 0, This);
398     else
399         *pIface = ICOM_INTERFACE(This, IDirectDraw7);
400
401     return hr;
402 }
403
404 /* This function is called from Uninit_DirectDraw_Initialize on the
405  * most-derived-class to start initialization.
406  * Not called from the vtable. */
407 HRESULT HAL_DirectDraw_Initialize(IDirectDrawImpl *This, const GUID* guid)
408 {
409     HRESULT hr;
410
411     TRACE("\n");
412
413     This->private = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
414                               sizeof(HAL_DirectDrawImpl));
415     if (This->private == NULL) return E_OUTOFMEMORY;
416
417     /* Initialize the DDCAPS structure */
418     This->caps.dwSize = sizeof(This->caps);
419
420     hr = HAL_DirectDraw_Construct(This, TRUE); /* XXX ex? */
421     if (FAILED(hr))
422     {
423         HeapFree(GetProcessHeap(), 0, This->private);
424         return hr;
425     }
426
427     return DD_OK;
428 }
429
430 /* Called from an internal function pointer. */
431 void HAL_DirectDraw_final_release(IDirectDrawImpl *This)
432 {
433     if (dd_gbl.dwFlags & DDRAWI_MODECHANGED) set_mode(This, dd_gbl.dwModeIndexOrig);
434     User_DirectDraw_final_release(This);
435 }
436
437 HRESULT HAL_DirectDraw_create_primary(IDirectDrawImpl* This,
438                                       const DDSURFACEDESC2* pDDSD,
439                                       LPDIRECTDRAWSURFACE7* ppSurf,
440                                       IUnknown* pUnkOuter)
441 {
442     if (This->cooperative_level & DDSCL_EXCLUSIVE)
443         return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
444     else
445         return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
446 }
447
448 HRESULT HAL_DirectDraw_create_backbuffer(IDirectDrawImpl* This,
449                                          const DDSURFACEDESC2* pDDSD,
450                                          LPDIRECTDRAWSURFACE7* ppSurf,
451                                          IUnknown* pUnkOuter,
452                                          IDirectDrawSurfaceImpl* primary)
453 {
454     if (This->cooperative_level & DDSCL_EXCLUSIVE)
455         return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
456     else
457         return User_DirectDrawSurface_Create(This, pDDSD, ppSurf, pUnkOuter);
458 }
459
460 HRESULT HAL_DirectDraw_create_texture(IDirectDrawImpl* This,
461                                       const DDSURFACEDESC2* pDDSD,
462                                       LPDIRECTDRAWSURFACE7* ppSurf,
463                                       LPUNKNOWN pOuter,
464                                       DWORD dwMipMapLevel)
465 {
466     return HAL_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);
467 }
468
469 HRESULT WINAPI
470 HAL_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
471                                    LPDDDEVICEIDENTIFIER2 pDDDI,
472                                    DWORD dwFlags)
473 {
474     *pDDDI = hal_device;
475     return DD_OK;
476 }
477
478 HRESULT WINAPI
479 HAL_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
480 {
481     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
482     HRESULT hr;
483
484     TRACE("(%p)\n", iface);
485
486     if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) return DD_OK;
487
488     hr = Main_DirectDraw_RestoreDisplayMode(iface);
489     if (SUCCEEDED(hr)) {
490         hr = set_mode(This, dd_gbl.dwModeIndexOrig);
491         if (SUCCEEDED(hr)) dd_gbl.dwFlags &= ~DDRAWI_MODECHANGED;
492     }
493
494     return hr;
495 }
496
497 HRESULT WINAPI
498 HAL_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
499                               DWORD dwHeight, DWORD dwBPP,
500                               DWORD dwRefreshRate, DWORD dwFlags)
501 {
502     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
503
504     HRESULT hr;
505
506     TRACE("(%p)->(%ldx%ldx%ld,%ld Hz,%08lx)\n",This,dwWidth,dwHeight,dwBPP,dwRefreshRate,dwFlags);
507     hr = User_DirectDraw_SetDisplayMode(iface, dwWidth, dwHeight, dwBPP,
508                                         dwRefreshRate, dwFlags);
509
510     if (SUCCEEDED(hr)) {
511         if (!(dd_gbl.dwFlags & DDRAWI_MODECHANGED)) dd_gbl.dwModeIndexOrig = dd_gbl.dwModeIndex;
512         hr = set_mode(This, choose_mode(dwWidth, dwHeight, dwBPP, dwRefreshRate, dwFlags));
513         if (SUCCEEDED(hr)) dd_gbl.dwFlags |= DDRAWI_MODECHANGED;
514     }
515
516     return hr;
517 }
518
519 HRESULT WINAPI
520 HAL_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
521                                LPDWORD pCodes)
522 {
523     unsigned int i;
524     IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
525     if (*pNumCodes)
526         *pNumCodes=dd_gbl.dwNumFourCC;
527     if (pCodes && dd_gbl.dwNumFourCC)
528         memcpy(pCodes,dd_gbl.lpdwFourCC,sizeof(pCodes[0])*dd_gbl.dwNumFourCC);
529     FIXME("(%p,%p,%p)\n",This,pNumCodes,pCodes);
530     if (dd_gbl.dwNumFourCC) {
531         if (pCodes && FIXME_ON(ddraw)) {
532             FIXME("returning: ");
533             for (i=0;i<dd_gbl.dwNumFourCC;i++) {
534                 MESSAGE("%c%c%c%c,",
535                         ((LPBYTE)(pCodes+i))[0],
536                         ((LPBYTE)(pCodes+i))[1],
537                         ((LPBYTE)(pCodes+i))[2],
538                         ((LPBYTE)(pCodes+i))[3]
539                 );
540             }
541             MESSAGE("\n");
542         }
543     }
544     return DD_OK;
545 }
546
547
548 static const IDirectDraw7Vtbl HAL_DirectDraw_VTable =
549 {
550     Main_DirectDraw_QueryInterface,
551     Main_DirectDraw_AddRef,
552     Main_DirectDraw_Release,
553     Main_DirectDraw_Compact,
554     Main_DirectDraw_CreateClipper,
555     Main_DirectDraw_CreatePalette,
556     Main_DirectDraw_CreateSurface,
557     Main_DirectDraw_DuplicateSurface,
558     User_DirectDraw_EnumDisplayModes,
559     Main_DirectDraw_EnumSurfaces,
560     Main_DirectDraw_FlipToGDISurface,
561     Main_DirectDraw_GetCaps,
562     Main_DirectDraw_GetDisplayMode,
563     HAL_DirectDraw_GetFourCCCodes,
564     Main_DirectDraw_GetGDISurface,
565     Main_DirectDraw_GetMonitorFrequency,
566     Main_DirectDraw_GetScanLine,
567     Main_DirectDraw_GetVerticalBlankStatus,
568     Main_DirectDraw_Initialize,
569     HAL_DirectDraw_RestoreDisplayMode,
570     Main_DirectDraw_SetCooperativeLevel,
571     HAL_DirectDraw_SetDisplayMode,
572     Main_DirectDraw_WaitForVerticalBlank,
573     Main_DirectDraw_GetAvailableVidMem,
574     Main_DirectDraw_GetSurfaceFromDC,
575     Main_DirectDraw_RestoreAllSurfaces,
576     Main_DirectDraw_TestCooperativeLevel,
577     HAL_DirectDraw_GetDeviceIdentifier,
578     Main_DirectDraw_StartModeTest,
579     Main_DirectDraw_EvaluateMode
580 };