ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

main.c
Go to the documentation of this file.
00001 /*        DirectDraw Base Functions
00002  *
00003  * Copyright 1997-1999 Marcus Meissner
00004  * Copyright 1998 Lionel Ulmer
00005  * Copyright 2000-2001 TransGaming Technologies Inc.
00006  * Copyright 2006 Stefan Dösinger
00007  * Copyright 2008 Denver Gingerich
00008  *
00009  * This file contains the (internal) driver registration functions,
00010  * driver enumeration APIs and DirectDraw creation functions.
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2.1 of the License, or (at your option) any later version.
00016  *
00017  * This library is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00025  */
00026 
00027 #include "config.h"
00028 #include "wine/port.h"
00029 
00030 #define DDRAW_INIT_GUID
00031 #include "ddraw_private.h"
00032 #include "rpcproxy.h"
00033 
00034 #include "wine/exception.h"
00035 #include "winreg.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
00038 
00039 /* The configured default surface */
00040 WINED3DSURFTYPE DefaultSurfaceType = SURFACE_OPENGL;
00041 
00042 static struct list global_ddraw_list = LIST_INIT(global_ddraw_list);
00043 
00044 static HINSTANCE instance;
00045 
00046 /* value of ForceRefreshRate */
00047 DWORD force_refresh_rate = 0;
00048 
00049 /* Handle table functions */
00050 BOOL ddraw_handle_table_init(struct ddraw_handle_table *t, UINT initial_size)
00051 {
00052     t->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, initial_size * sizeof(*t->entries));
00053     if (!t->entries)
00054     {
00055         ERR("Failed to allocate handle table memory.\n");
00056         return FALSE;
00057     }
00058     t->free_entries = NULL;
00059     t->table_size = initial_size;
00060     t->entry_count = 0;
00061 
00062     return TRUE;
00063 }
00064 
00065 void ddraw_handle_table_destroy(struct ddraw_handle_table *t)
00066 {
00067     HeapFree(GetProcessHeap(), 0, t->entries);
00068     memset(t, 0, sizeof(*t));
00069 }
00070 
00071 DWORD ddraw_allocate_handle(struct ddraw_handle_table *t, void *object, enum ddraw_handle_type type)
00072 {
00073     struct ddraw_handle_entry *entry;
00074 
00075     if (t->free_entries)
00076     {
00077         DWORD idx = t->free_entries - t->entries;
00078         /* Use a free handle */
00079         entry = t->free_entries;
00080         if (entry->type != DDRAW_HANDLE_FREE)
00081         {
00082             ERR("Handle %#x (%p) is in the free list, but has type %#x.\n", idx, entry->object, entry->type);
00083             return DDRAW_INVALID_HANDLE;
00084         }
00085         t->free_entries = entry->object;
00086         entry->object = object;
00087         entry->type = type;
00088 
00089         return idx;
00090     }
00091 
00092     if (!(t->entry_count < t->table_size))
00093     {
00094         /* Grow the table */
00095         UINT new_size = t->table_size + (t->table_size >> 1);
00096         struct ddraw_handle_entry *new_entries = HeapReAlloc(GetProcessHeap(),
00097                 0, t->entries, new_size * sizeof(*t->entries));
00098         if (!new_entries)
00099         {
00100             ERR("Failed to grow the handle table.\n");
00101             return DDRAW_INVALID_HANDLE;
00102         }
00103         t->entries = new_entries;
00104         t->table_size = new_size;
00105     }
00106 
00107     entry = &t->entries[t->entry_count];
00108     entry->object = object;
00109     entry->type = type;
00110 
00111     return t->entry_count++;
00112 }
00113 
00114 void *ddraw_free_handle(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type)
00115 {
00116     struct ddraw_handle_entry *entry;
00117     void *object;
00118 
00119     if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count)
00120     {
00121         WARN("Invalid handle %#x passed.\n", handle);
00122         return NULL;
00123     }
00124 
00125     entry = &t->entries[handle];
00126     if (entry->type != type)
00127     {
00128         WARN("Handle %#x (%p) is not of type %#x.\n", handle, entry->object, type);
00129         return NULL;
00130     }
00131 
00132     object = entry->object;
00133     entry->object = t->free_entries;
00134     entry->type = DDRAW_HANDLE_FREE;
00135     t->free_entries = entry;
00136 
00137     return object;
00138 }
00139 
00140 void *ddraw_get_object(struct ddraw_handle_table *t, DWORD handle, enum ddraw_handle_type type)
00141 {
00142     struct ddraw_handle_entry *entry;
00143 
00144     if (handle == DDRAW_INVALID_HANDLE || handle >= t->entry_count)
00145     {
00146         WARN("Invalid handle %#x passed.\n", handle);
00147         return NULL;
00148     }
00149 
00150     entry = &t->entries[handle];
00151     if (entry->type != type)
00152     {
00153         WARN("Handle %#x (%p) is not of type %#x.\n", handle, entry->object, type);
00154         return NULL;
00155     }
00156 
00157     return entry->object;
00158 }
00159 
00160 /***********************************************************************
00161  *
00162  * Helper function for DirectDrawCreate and friends
00163  * Creates a new DDraw interface with the given REFIID
00164  *
00165  * Interfaces that can be created:
00166  *  IDirectDraw, IDirectDraw2, IDirectDraw4, IDirectDraw7
00167  *  IDirect3D, IDirect3D2, IDirect3D3, IDirect3D7. (Does Windows return
00168  *  IDirect3D interfaces?)
00169  *
00170  * Arguments:
00171  *  guid: ID of the requested driver, NULL for the default driver.
00172  *        The GUID can be queried with DirectDrawEnumerate(Ex)A/W
00173  *  DD: Used to return the pointer to the created object
00174  *  UnkOuter: For aggregation, which is unsupported. Must be NULL
00175  *  iid: requested version ID.
00176  *
00177  * Returns:
00178  *  DD_OK if the Interface was created successfully
00179  *  CLASS_E_NOAGGREGATION if UnkOuter is not NULL
00180  *  E_OUTOFMEMORY if some allocation failed
00181  *
00182  ***********************************************************************/
00183 static HRESULT
00184 DDRAW_Create(const GUID *guid,
00185              void **DD,
00186              IUnknown *UnkOuter,
00187              REFIID iid)
00188 {
00189     enum wined3d_device_type device_type;
00190     IDirectDrawImpl *This;
00191     HRESULT hr;
00192 
00193     TRACE("driver_guid %s, ddraw %p, outer_unknown %p, interface_iid %s.\n",
00194             debugstr_guid(guid), DD, UnkOuter, debugstr_guid(iid));
00195 
00196     *DD = NULL;
00197 
00198     /* We don't care about this guids. Well, there's no special guid anyway
00199      * OK, we could
00200      */
00201     if (guid == (GUID *) DDCREATE_EMULATIONONLY)
00202     {
00203         /* Use the reference device id. This doesn't actually change anything,
00204          * WineD3D always uses OpenGL for D3D rendering. One could make it request
00205          * indirect rendering
00206          */
00207         device_type = WINED3D_DEVICE_TYPE_REF;
00208     }
00209     else if(guid == (GUID *) DDCREATE_HARDWAREONLY)
00210     {
00211         device_type = WINED3D_DEVICE_TYPE_HAL;
00212     }
00213     else
00214     {
00215         device_type = 0;
00216     }
00217 
00218     /* DDraw doesn't support aggregation, according to msdn */
00219     if (UnkOuter != NULL)
00220         return CLASS_E_NOAGGREGATION;
00221 
00222     /* DirectDraw creation comes here */
00223     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectDrawImpl));
00224     if(!This)
00225     {
00226         ERR("Out of memory when creating DirectDraw\n");
00227         return E_OUTOFMEMORY;
00228     }
00229 
00230     hr = ddraw_init(This, device_type);
00231     if (FAILED(hr))
00232     {
00233         WARN("Failed to initialize ddraw object, hr %#x.\n", hr);
00234         HeapFree(GetProcessHeap(), 0, This);
00235         return hr;
00236     }
00237 
00238     hr = IDirectDraw7_QueryInterface(&This->IDirectDraw7_iface, iid, DD);
00239     IDirectDraw7_Release(&This->IDirectDraw7_iface);
00240     if (SUCCEEDED(hr)) list_add_head(&global_ddraw_list, &This->ddraw_list_entry);
00241     else WARN("Failed to query interface %s from ddraw object %p.\n", debugstr_guid(iid), This);
00242 
00243     return hr;
00244 }
00245 
00246 /***********************************************************************
00247  * DirectDrawCreate (DDRAW.@)
00248  *
00249  * Creates legacy DirectDraw Interfaces. Can't create IDirectDraw7
00250  * interfaces in theory
00251  *
00252  * Arguments, return values: See DDRAW_Create
00253  *
00254  ***********************************************************************/
00255 HRESULT WINAPI DECLSPEC_HOTPATCH
00256 DirectDrawCreate(GUID *GUID,
00257                  LPDIRECTDRAW *DD,
00258                  IUnknown *UnkOuter)
00259 {
00260     HRESULT hr;
00261 
00262     TRACE("driver_guid %s, ddraw %p, outer_unknown %p.\n",
00263             debugstr_guid(GUID), DD, UnkOuter);
00264 
00265     wined3d_mutex_lock();
00266     hr = DDRAW_Create(GUID, (void **) DD, UnkOuter, &IID_IDirectDraw);
00267     wined3d_mutex_unlock();
00268 
00269     if (SUCCEEDED(hr))
00270     {
00271         hr = IDirectDraw_Initialize(*DD, GUID);
00272         if (FAILED(hr))
00273             IDirectDraw_Release(*DD);
00274     }
00275 
00276     return hr;
00277 }
00278 
00279 /***********************************************************************
00280  * DirectDrawCreateEx (DDRAW.@)
00281  *
00282  * Only creates new IDirectDraw7 interfaces, supposed to fail if legacy
00283  * interfaces are requested.
00284  *
00285  * Arguments, return values: See DDRAW_Create
00286  *
00287  ***********************************************************************/
00288 HRESULT WINAPI DECLSPEC_HOTPATCH
00289 DirectDrawCreateEx(GUID *guid,
00290                    LPVOID *dd,
00291                    REFIID iid,
00292                    IUnknown *UnkOuter)
00293 {
00294     HRESULT hr;
00295 
00296     TRACE("driver_guid %s, ddraw %p, interface_iid %s, outer_unknown %p.\n",
00297             debugstr_guid(guid), dd, debugstr_guid(iid), UnkOuter);
00298 
00299     if (!IsEqualGUID(iid, &IID_IDirectDraw7))
00300         return DDERR_INVALIDPARAMS;
00301 
00302     wined3d_mutex_lock();
00303     hr = DDRAW_Create(guid, dd, UnkOuter, iid);
00304     wined3d_mutex_unlock();
00305 
00306     if (SUCCEEDED(hr))
00307     {
00308         IDirectDraw7 *ddraw7 = *(IDirectDraw7 **)dd;
00309         hr = IDirectDraw7_Initialize(ddraw7, guid);
00310         if (FAILED(hr))
00311             IDirectDraw7_Release(ddraw7);
00312     }
00313 
00314     return hr;
00315 }
00316 
00317 /***********************************************************************
00318  * DirectDrawEnumerateA (DDRAW.@)
00319  *
00320  * Enumerates legacy ddraw drivers, ascii version. We only have one
00321  * driver, which relays to WineD3D. If we were sufficiently cool,
00322  * we could offer various interfaces, which use a different default surface
00323  * implementation, but I think it's better to offer this choice in
00324  * winecfg, because some apps use the default driver, so we would need
00325  * a winecfg option anyway, and there shouldn't be 2 ways to set one setting
00326  *
00327  * Arguments:
00328  *  Callback: Callback function from the app
00329  *  Context: Argument to the call back.
00330  *
00331  * Returns:
00332  *  DD_OK on success
00333  *  E_INVALIDARG if the Callback caused a page fault
00334  *
00335  *
00336  ***********************************************************************/
00337 HRESULT WINAPI DirectDrawEnumerateA(LPDDENUMCALLBACKA Callback, void *Context)
00338 {
00339     TRACE("callback %p, context %p.\n", Callback, Context);
00340 
00341     TRACE(" Enumerating default DirectDraw HAL interface\n");
00342     /* We only have one driver */
00343     __TRY
00344     {
00345         static CHAR driver_desc[] = "DirectDraw HAL",
00346         driver_name[] = "display";
00347 
00348         Callback(NULL, driver_desc, driver_name, Context);
00349     }
00350     __EXCEPT_PAGE_FAULT
00351     {
00352         return DDERR_INVALIDPARAMS;
00353     }
00354     __ENDTRY
00355 
00356     TRACE(" End of enumeration\n");
00357     return DD_OK;
00358 }
00359 
00360 /***********************************************************************
00361  * DirectDrawEnumerateExA (DDRAW.@)
00362  *
00363  * Enumerates DirectDraw7 drivers, ascii version. See
00364  * the comments above DirectDrawEnumerateA for more details.
00365  *
00366  * The Flag member is not supported right now.
00367  *
00368  ***********************************************************************/
00369 HRESULT WINAPI DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA Callback, void *Context, DWORD Flags)
00370 {
00371     TRACE("callback %p, context %p, flags %#x.\n", Callback, Context, Flags);
00372 
00373     if (Flags & ~(DDENUM_ATTACHEDSECONDARYDEVICES |
00374                   DDENUM_DETACHEDSECONDARYDEVICES |
00375                   DDENUM_NONDISPLAYDEVICES))
00376         return DDERR_INVALIDPARAMS;
00377 
00378     if (Flags)
00379         FIXME("flags 0x%08x not handled\n", Flags);
00380 
00381     TRACE("Enumerating default DirectDraw HAL interface\n");
00382 
00383     /* We only have one driver by now */
00384     __TRY
00385     {
00386         static CHAR driver_desc[] = "DirectDraw HAL",
00387         driver_name[] = "display";
00388 
00389         /* QuickTime expects the description "DirectDraw HAL" */
00390         Callback(NULL, driver_desc, driver_name, Context, 0);
00391     }
00392     __EXCEPT_PAGE_FAULT
00393     {
00394         return DDERR_INVALIDPARAMS;
00395     }
00396     __ENDTRY;
00397 
00398     TRACE("End of enumeration\n");
00399     return DD_OK;
00400 }
00401 
00402 /***********************************************************************
00403  * DirectDrawEnumerateW (DDRAW.@)
00404  *
00405  * Enumerates legacy drivers, unicode version.
00406  * This function is not implemented on Windows.
00407  *
00408  ***********************************************************************/
00409 HRESULT WINAPI DirectDrawEnumerateW(LPDDENUMCALLBACKW callback, void *context)
00410 {
00411     TRACE("callback %p, context %p.\n", callback, context);
00412 
00413     if (!callback)
00414         return DDERR_INVALIDPARAMS;
00415     else
00416         return DDERR_UNSUPPORTED;
00417 }
00418 
00419 /***********************************************************************
00420  * DirectDrawEnumerateExW (DDRAW.@)
00421  *
00422  * Enumerates DirectDraw7 drivers, unicode version.
00423  * This function is not implemented on Windows.
00424  *
00425  ***********************************************************************/
00426 HRESULT WINAPI DirectDrawEnumerateExW(LPDDENUMCALLBACKEXW callback, void *context, DWORD flags)
00427 {
00428     TRACE("callback %p, context %p, flags %#x.\n", callback, context, flags);
00429 
00430     return DDERR_UNSUPPORTED;
00431 }
00432 
00433 /***********************************************************************
00434  * Classfactory implementation.
00435  ***********************************************************************/
00436 
00437 /***********************************************************************
00438  * CF_CreateDirectDraw
00439  *
00440  * DDraw creation function for the class factory
00441  *
00442  * Params:
00443  *  UnkOuter: Set to NULL
00444  *  iid: ID of the wanted interface
00445  *  obj: Address to pass the interface pointer back
00446  *
00447  * Returns
00448  *  DD_OK / DDERR*, see DDRAW_Create
00449  *
00450  ***********************************************************************/
00451 static HRESULT
00452 CF_CreateDirectDraw(IUnknown* UnkOuter, REFIID iid,
00453                     void **obj)
00454 {
00455     HRESULT hr;
00456 
00457     TRACE("outer_unknown %p, riid %s, object %p.\n", UnkOuter, debugstr_guid(iid), obj);
00458 
00459     wined3d_mutex_lock();
00460     hr = DDRAW_Create(NULL, obj, UnkOuter, iid);
00461     wined3d_mutex_unlock();
00462 
00463     return hr;
00464 }
00465 
00466 /***********************************************************************
00467  * CF_CreateDirectDraw
00468  *
00469  * Clipper creation function for the class factory
00470  *
00471  * Params:
00472  *  UnkOuter: Set to NULL
00473  *  iid: ID of the wanted interface
00474  *  obj: Address to pass the interface pointer back
00475  *
00476  * Returns
00477  *  DD_OK / DDERR*, see DDRAW_Create
00478  *
00479  ***********************************************************************/
00480 static HRESULT
00481 CF_CreateDirectDrawClipper(IUnknown* UnkOuter, REFIID riid,
00482                               void **obj)
00483 {
00484     HRESULT hr;
00485     IDirectDrawClipper *Clip;
00486 
00487     TRACE("outer_unknown %p, riid %s, object %p.\n", UnkOuter, debugstr_guid(riid), obj);
00488 
00489     wined3d_mutex_lock();
00490     hr = DirectDrawCreateClipper(0, &Clip, UnkOuter);
00491     if (hr != DD_OK)
00492     {
00493         wined3d_mutex_unlock();
00494         return hr;
00495     }
00496 
00497     hr = IDirectDrawClipper_QueryInterface(Clip, riid, obj);
00498     IDirectDrawClipper_Release(Clip);
00499 
00500     wined3d_mutex_unlock();
00501 
00502     return hr;
00503 }
00504 
00505 static const struct object_creation_info object_creation[] =
00506 {
00507     { &CLSID_DirectDraw,        CF_CreateDirectDraw },
00508     { &CLSID_DirectDraw7,       CF_CreateDirectDraw },
00509     { &CLSID_DirectDrawClipper, CF_CreateDirectDrawClipper }
00510 };
00511 
00512 
00513 /******************************************************************************
00514  * DirectDraw ClassFactory implementation
00515  ******************************************************************************/
00516 typedef struct
00517 {
00518     IClassFactory IClassFactory_iface;
00519 
00520     LONG ref;
00521     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, REFIID iid, LPVOID *ppObj);
00522 } IClassFactoryImpl;
00523 
00524 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
00525 {
00526     return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
00527 }
00528 
00529 /*******************************************************************************
00530  * IDirectDrawClassFactory::QueryInterface
00531  *
00532  * QueryInterface for the class factory
00533  *
00534  * PARAMS
00535  *    riid   Reference to identifier of queried interface
00536  *    ppv    Address to return the interface pointer at
00537  *
00538  * RETURNS
00539  *    Success: S_OK
00540  *    Failure: E_NOINTERFACE
00541  *
00542  *******************************************************************************/
00543 static HRESULT WINAPI IDirectDrawClassFactoryImpl_QueryInterface(IClassFactory *iface, REFIID riid,
00544         void **obj)
00545 {
00546     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
00547 
00548     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), obj);
00549 
00550     if (IsEqualGUID(riid, &IID_IUnknown)
00551         || IsEqualGUID(riid, &IID_IClassFactory))
00552     {
00553         IClassFactory_AddRef(iface);
00554         *obj = This;
00555         return S_OK;
00556     }
00557 
00558     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),obj);
00559     return E_NOINTERFACE;
00560 }
00561 
00562 /*******************************************************************************
00563  * IDirectDrawClassFactory::AddRef
00564  *
00565  * AddRef for the class factory
00566  *
00567  * RETURNS
00568  *  The new refcount
00569  *
00570  *******************************************************************************/
00571 static ULONG WINAPI IDirectDrawClassFactoryImpl_AddRef(IClassFactory *iface)
00572 {
00573     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
00574     ULONG ref = InterlockedIncrement(&This->ref);
00575 
00576     TRACE("%p increasing refcount to %u.\n", This, ref);
00577 
00578     return ref;
00579 }
00580 
00581 /*******************************************************************************
00582  * IDirectDrawClassFactory::Release
00583  *
00584  * Release for the class factory. If the refcount falls to 0, the object
00585  * is destroyed
00586  *
00587  * RETURNS
00588  *  The new refcount
00589  *
00590  *******************************************************************************/
00591 static ULONG WINAPI IDirectDrawClassFactoryImpl_Release(IClassFactory *iface)
00592 {
00593     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
00594     ULONG ref = InterlockedDecrement(&This->ref);
00595 
00596     TRACE("%p decreasing refcount to %u.\n", This, ref);
00597 
00598     if (ref == 0)
00599         HeapFree(GetProcessHeap(), 0, This);
00600 
00601     return ref;
00602 }
00603 
00604 
00605 /*******************************************************************************
00606  * IDirectDrawClassFactory::CreateInstance
00607  *
00608  * What is this? Seems to create DirectDraw objects...
00609  *
00610  * Params
00611  *  The usual things???
00612  *
00613  * RETURNS
00614  *  ???
00615  *
00616  *******************************************************************************/
00617 static HRESULT WINAPI IDirectDrawClassFactoryImpl_CreateInstance(IClassFactory *iface,
00618         IUnknown *UnkOuter, REFIID riid, void **obj)
00619 {
00620     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
00621 
00622     TRACE("iface %p, outer_unknown %p, riid %s, object %p.\n",
00623             iface, UnkOuter, debugstr_guid(riid), obj);
00624 
00625     return This->pfnCreateInstance(UnkOuter, riid, obj);
00626 }
00627 
00628 /*******************************************************************************
00629  * IDirectDrawClassFactory::LockServer
00630  *
00631  * What is this?
00632  *
00633  * Params
00634  *  ???
00635  *
00636  * RETURNS
00637  *  S_OK, because it's a stub
00638  *
00639  *******************************************************************************/
00640 static HRESULT WINAPI IDirectDrawClassFactoryImpl_LockServer(IClassFactory *iface, BOOL dolock)
00641 {
00642     FIXME("iface %p, dolock %#x stub!\n", iface, dolock);
00643 
00644     return S_OK;
00645 }
00646 
00647 /*******************************************************************************
00648  * The class factory VTable
00649  *******************************************************************************/
00650 static const IClassFactoryVtbl IClassFactory_Vtbl =
00651 {
00652     IDirectDrawClassFactoryImpl_QueryInterface,
00653     IDirectDrawClassFactoryImpl_AddRef,
00654     IDirectDrawClassFactoryImpl_Release,
00655     IDirectDrawClassFactoryImpl_CreateInstance,
00656     IDirectDrawClassFactoryImpl_LockServer
00657 };
00658 
00659 /*******************************************************************************
00660  * DllGetClassObject [DDRAW.@]
00661  * Retrieves class object from a DLL object
00662  *
00663  * NOTES
00664  *    Docs say returns STDAPI
00665  *
00666  * PARAMS
00667  *    rclsid [I] CLSID for the class object
00668  *    riid   [I] Reference to identifier of interface for class object
00669  *    ppv    [O] Address of variable to receive interface pointer for riid
00670  *
00671  * RETURNS
00672  *    Success: S_OK
00673  *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
00674  *             E_UNEXPECTED
00675  */
00676 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
00677 {
00678     unsigned int i;
00679     IClassFactoryImpl *factory;
00680 
00681     TRACE("rclsid %s, riid %s, object %p.\n",
00682             debugstr_guid(rclsid), debugstr_guid(riid), ppv);
00683 
00684     if (!IsEqualGUID(&IID_IClassFactory, riid)
00685             && !IsEqualGUID(&IID_IUnknown, riid))
00686         return E_NOINTERFACE;
00687 
00688     for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
00689     {
00690         if (IsEqualGUID(object_creation[i].clsid, rclsid))
00691             break;
00692     }
00693 
00694     if (i == sizeof(object_creation)/sizeof(object_creation[0]))
00695     {
00696         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
00697         return CLASS_E_CLASSNOTAVAILABLE;
00698     }
00699 
00700     factory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*factory));
00701     if (factory == NULL) return E_OUTOFMEMORY;
00702 
00703     factory->IClassFactory_iface.lpVtbl = &IClassFactory_Vtbl;
00704     factory->ref = 1;
00705 
00706     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
00707 
00708     *ppv = factory;
00709     return S_OK;
00710 }
00711 
00712 
00713 /*******************************************************************************
00714  * DllCanUnloadNow [DDRAW.@]  Determines whether the DLL is in use.
00715  *
00716  * RETURNS
00717  *    Success: S_OK
00718  *    Failure: S_FALSE
00719  */
00720 HRESULT WINAPI DllCanUnloadNow(void)
00721 {
00722     TRACE("\n");
00723 
00724     return S_FALSE;
00725 }
00726 
00727 
00728 /***********************************************************************
00729  *      DllRegisterServer (DDRAW.@)
00730  */
00731 HRESULT WINAPI DllRegisterServer(void)
00732 {
00733     return __wine_register_resources( instance );
00734 }
00735 
00736 /***********************************************************************
00737  *      DllUnregisterServer (DDRAW.@)
00738  */
00739 HRESULT WINAPI DllUnregisterServer(void)
00740 {
00741     return __wine_unregister_resources( instance );
00742 }
00743 
00744 /*******************************************************************************
00745  * DestroyCallback
00746  *
00747  * Callback function for the EnumSurfaces call in DllMain.
00748  * Dumps some surface info and releases the surface
00749  *
00750  * Params:
00751  *  surf: The enumerated surface
00752  *  desc: it's description
00753  *  context: Pointer to the ddraw impl
00754  *
00755  * Returns:
00756  *  DDENUMRET_OK;
00757  *******************************************************************************/
00758 static HRESULT WINAPI
00759 DestroyCallback(IDirectDrawSurface7 *surf,
00760                 DDSURFACEDESC2 *desc,
00761                 void *context)
00762 {
00763     IDirectDrawSurfaceImpl *Impl = impl_from_IDirectDrawSurface7(surf);
00764     ULONG ref7, ref4, ref3, ref2, ref1, gamma_count, iface_count;
00765 
00766     ref7 = IDirectDrawSurface7_Release(surf);  /* For the EnumSurfaces */
00767     ref4 = Impl->ref4;
00768     ref3 = Impl->ref3;
00769     ref2 = Impl->ref2;
00770     ref1 = Impl->ref1;
00771     gamma_count = Impl->gamma_count;
00772 
00773     WARN("Surface %p has an reference counts of 7: %u 4: %u 3: %u 2: %u 1: %u gamma: %u\n",
00774             Impl, ref7, ref4, ref3, ref2, ref1, gamma_count);
00775 
00776     /* Skip surfaces which are attached somewhere or which are
00777      * part of a complex compound. They will get released when destroying
00778      * the root
00779      */
00780     if( (!Impl->is_complex_root) || (Impl->first_attached != Impl) )
00781         return DDENUMRET_OK;
00782 
00783     /* Destroy the surface */
00784     iface_count = ddraw_surface_release_iface(Impl);
00785     while (iface_count) iface_count = ddraw_surface_release_iface(Impl);
00786 
00787     return DDENUMRET_OK;
00788 }
00789 
00790 /***********************************************************************
00791  * get_config_key
00792  *
00793  * Reads a config key from the registry. Taken from WineD3D
00794  *
00795  ***********************************************************************/
00796 static inline DWORD get_config_key(HKEY defkey, HKEY appkey, const char* name, char* buffer, DWORD size)
00797 {
00798     if (0 != appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
00799     if (0 != defkey && !RegQueryValueExA( defkey, name, 0, NULL, (LPBYTE) buffer, &size )) return 0;
00800     return ERROR_FILE_NOT_FOUND;
00801 }
00802 
00803 /***********************************************************************
00804  * DllMain (DDRAW.0)
00805  *
00806  * Could be used to register DirectDraw drivers, if we have more than
00807  * one. Also used to destroy any objects left at unload if the
00808  * app didn't release them properly(Gothic 2, Diablo 2, Moto racer, ...)
00809  *
00810  ***********************************************************************/
00811 BOOL WINAPI
00812 DllMain(HINSTANCE hInstDLL,
00813         DWORD Reason,
00814         LPVOID lpv)
00815 {
00816     TRACE("(%p,%x,%p)\n", hInstDLL, Reason, lpv);
00817     if (Reason == DLL_PROCESS_ATTACH)
00818     {
00819         char buffer[MAX_PATH+10];
00820         DWORD size = sizeof(buffer);
00821         HKEY hkey = 0;
00822         HKEY appkey = 0;
00823         WNDCLASSA wc;
00824         DWORD len;
00825 
00826         /* Register the window class. This is used to create a hidden window
00827          * for D3D rendering, if the application didn't pass one. It can also
00828          * be used for creating a device window from SetCooperativeLevel(). */
00829         wc.style = CS_HREDRAW | CS_VREDRAW;
00830         wc.lpfnWndProc = DefWindowProcA;
00831         wc.cbClsExtra = 0;
00832         wc.cbWndExtra = 0;
00833         wc.hInstance = hInstDLL;
00834         wc.hIcon = 0;
00835         wc.hCursor = 0;
00836         wc.hbrBackground = GetStockObject(BLACK_BRUSH);
00837         wc.lpszMenuName = NULL;
00838         wc.lpszClassName = DDRAW_WINDOW_CLASS_NAME;
00839         if (!RegisterClassA(&wc))
00840         {
00841             ERR("Failed to register ddraw window class, last error %#x.\n", GetLastError());
00842             return FALSE;
00843         }
00844 
00845        /* @@ Wine registry key: HKCU\Software\Wine\Direct3D */
00846        if ( RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Direct3D", &hkey ) ) hkey = 0;
00847 
00848        len = GetModuleFileNameA( 0, buffer, MAX_PATH );
00849        if (len && len < MAX_PATH)
00850        {
00851             HKEY tmpkey;
00852             /* @@ Wine registry key: HKCU\Software\Wine\AppDefaults\app.exe\Direct3D */
00853             if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\AppDefaults", &tmpkey ))
00854             {
00855                 char *p, *appname = buffer;
00856                 if ((p = strrchr( appname, '/' ))) appname = p + 1;
00857                 if ((p = strrchr( appname, '\\' ))) appname = p + 1;
00858                 strcat( appname, "\\Direct3D" );
00859                 TRACE("appname = [%s]\n", appname);
00860                 if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0;
00861                 RegCloseKey( tmpkey );
00862             }
00863        }
00864 
00865        if ( 0 != hkey || 0 != appkey )
00866        {
00867             if ( !get_config_key( hkey, appkey, "DirectDrawRenderer", buffer, size) )
00868             {
00869                 if (!strcmp(buffer,"gdi"))
00870                 {
00871                     TRACE("Defaulting to GDI surfaces\n");
00872                     DefaultSurfaceType = SURFACE_GDI;
00873                 }
00874                 else if (!strcmp(buffer,"opengl"))
00875                 {
00876                     TRACE("Defaulting to opengl surfaces\n");
00877                     DefaultSurfaceType = SURFACE_OPENGL;
00878                 }
00879                 else
00880                 {
00881                     ERR("Unknown default surface type. Supported are:\n gdi, opengl\n");
00882                 }
00883             }
00884         }
00885 
00886         /* On Windows one can force the refresh rate that DirectDraw uses by
00887          * setting an override value in dxdiag.  This is documented in KB315614
00888          * (main article), KB230002, and KB217348.  By comparing registry dumps
00889          * before and after setting the override, we see that the override value
00890          * is stored in HKLM\Software\Microsoft\DirectDraw\ForceRefreshRate as a
00891          * DWORD that represents the refresh rate to force.  We use this
00892          * registry entry to modify the behavior of SetDisplayMode so that Wine
00893          * users can override the refresh rate in a Windows-compatible way.
00894          *
00895          * dxdiag will not accept a refresh rate lower than 40 or higher than
00896          * 120 so this value should be within that range.  It is, of course,
00897          * possible for a user to set the registry entry value directly so that
00898          * assumption might not hold.
00899          *
00900          * There is no current mechanism for setting this value through the Wine
00901          * GUI.  It would be most appropriate to set this value through a dxdiag
00902          * clone, but it may be sufficient to use winecfg.
00903          *
00904          * TODO: Create a mechanism for setting this value through the Wine GUI.
00905          */
00906         if ( !RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\DirectDraw", &hkey ) )
00907         {
00908             DWORD type, data;
00909             size = sizeof(data);
00910             if (!RegQueryValueExA( hkey, "ForceRefreshRate", NULL, &type, (LPBYTE)&data, &size ) && type == REG_DWORD)
00911             {
00912                 TRACE("ForceRefreshRate set; overriding refresh rate to %d Hz\n", data);
00913                 force_refresh_rate = data;
00914             }
00915             RegCloseKey( hkey );
00916         }
00917 
00918         instance = hInstDLL;
00919         DisableThreadLibraryCalls(hInstDLL);
00920     }
00921     else if (Reason == DLL_PROCESS_DETACH)
00922     {
00923         if(!list_empty(&global_ddraw_list))
00924         {
00925             struct list *entry, *entry2;
00926             WARN("There are still existing DirectDraw interfaces. Wine bug or buggy application?\n");
00927 
00928             /* We remove elements from this loop */
00929             LIST_FOR_EACH_SAFE(entry, entry2, &global_ddraw_list)
00930             {
00931                 HRESULT hr;
00932                 DDSURFACEDESC2 desc;
00933                 int i;
00934                 IDirectDrawImpl *ddraw = LIST_ENTRY(entry, IDirectDrawImpl, ddraw_list_entry);
00935 
00936                 WARN("DDraw %p has a refcount of %d\n", ddraw, ddraw->ref7 + ddraw->ref4 + ddraw->ref3 + ddraw->ref2 + ddraw->ref1);
00937 
00938                 /* Add references to each interface to avoid freeing them unexpectedly */
00939                 IDirectDraw_AddRef(&ddraw->IDirectDraw_iface);
00940                 IDirectDraw2_AddRef(&ddraw->IDirectDraw2_iface);
00941                 IDirectDraw4_AddRef(&ddraw->IDirectDraw4_iface);
00942                 IDirectDraw7_AddRef(&ddraw->IDirectDraw7_iface);
00943 
00944                 /* Does a D3D device exist? Destroy it
00945                     * TODO: Destroy all Vertex buffers, Lights, Materials
00946                     * and execute buffers too
00947                     */
00948                 if(ddraw->d3ddevice)
00949                 {
00950                     WARN("DDraw %p has d3ddevice %p attached\n", ddraw, ddraw->d3ddevice);
00951                     while(IDirect3DDevice7_Release(&ddraw->d3ddevice->IDirect3DDevice7_iface));
00952                 }
00953 
00954                 /* Destroy the swapchain after any 3D device. The 3D device
00955                  * cleanup code needs a swapchain. Specifically, it tries to
00956                  * set the current render target to the front buffer. */
00957                 if (ddraw->wined3d_swapchain)
00958                     ddraw_destroy_swapchain(ddraw);
00959 
00960                 /* Try to release the objects
00961                     * Do an EnumSurfaces to find any hanging surfaces
00962                     */
00963                 memset(&desc, 0, sizeof(desc));
00964                 desc.dwSize = sizeof(desc);
00965                 for(i = 0; i <= 1; i++)
00966                 {
00967                     hr = IDirectDraw7_EnumSurfaces(&ddraw->IDirectDraw7_iface, DDENUMSURFACES_ALL,
00968                             &desc, ddraw, DestroyCallback);
00969                     if(hr != D3D_OK)
00970                         ERR("(%p) EnumSurfaces failed, prepare for trouble\n", ddraw);
00971                 }
00972 
00973                 if (!list_empty(&ddraw->surface_list))
00974                     ERR("DDraw %p still has surfaces attached.\n", ddraw);
00975 
00976                 /* Release all hanging references to destroy the objects. This
00977                     * restores the screen mode too
00978                     */
00979                 while(IDirectDraw_Release(&ddraw->IDirectDraw_iface));
00980                 while(IDirectDraw2_Release(&ddraw->IDirectDraw2_iface));
00981                 while(IDirectDraw4_Release(&ddraw->IDirectDraw4_iface));
00982                 while(IDirectDraw7_Release(&ddraw->IDirectDraw7_iface));
00983             }
00984         }
00985 
00986         /* Unregister the window class. */
00987         UnregisterClassA(DDRAW_WINDOW_CLASS_NAME, hInstDLL);
00988     }
00989 
00990     return TRUE;
00991 }

Generated on Sun May 27 2012 04:16:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.