Spelling stuff.
[wine] / dlls / dinput / dinput_main.c
1 /*              DirectInput
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998,1999 Lionel Ulmer
5  *
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 /* Status:
22  *
23  * - Tomb Raider 2 Demo:
24  *   Playable using keyboard only.
25  * - WingCommander Prophecy Demo:
26  *   Doesn't get Input Focus.
27  * 
28  * - Fallout : works great in X and DGA mode
29  *
30  * FIXME: The keyboard handling needs to (and will) be merged into keyboard.c
31  *        (The current implementation is currently only a proof of concept and
32  *         an utter mess.)
33  */
34
35 #include "config.h"
36 #include <assert.h>
37 #include <string.h>
38
39 #include "wine/debug.h"
40 #include "winbase.h"
41 #include "winuser.h"
42 #include "winerror.h"
43 #include "windef.h"
44 #include "dinput_private.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
47
48 static ICOM_VTABLE(IDirectInputA) ddiavt;
49 static ICOM_VTABLE(IDirectInput7A) ddi7avt;
50
51 /* This array will be filled a dinput.so loading */
52 #define MAX_WINE_DINPUT_DEVICES 4
53 static dinput_device * dinput_devices[MAX_WINE_DINPUT_DEVICES];
54 static int nrof_dinput_devices = 0;
55
56 BOOL WINAPI Init( HINSTANCE inst, DWORD reason, LPVOID reserv)
57 {
58     switch(reason)
59     {
60       case DLL_PROCESS_ATTACH:
61         keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, 0, 0 );
62         break;
63       case DLL_PROCESS_DETACH:
64         UnhookWindowsHookEx(keyboard_hook);
65         break;
66     }
67     return TRUE;
68 }
69
70
71 /* register a direct draw driver. We better not use malloc for we are in 
72  * the ELF startup initialisation at this point.
73  */
74 void dinput_register_device(dinput_device *device) {
75     int i;
76
77     /* insert according to priority */
78     for (i=0;i<nrof_dinput_devices;i++) {
79         if (dinput_devices[i]->pref <= device->pref) {
80             memcpy(dinput_devices+i+1,dinput_devices+i,sizeof(dinput_devices[0])*(nrof_dinput_devices-i));
81             dinput_devices[i] = device;
82             break;
83         }
84     }
85     if (i==nrof_dinput_devices) /* not found, or too low priority */
86         dinput_devices[nrof_dinput_devices] = device;
87
88     nrof_dinput_devices++;
89
90     /* increase MAX_DDRAW_DRIVERS if the line below triggers */
91     assert(nrof_dinput_devices <= MAX_WINE_DINPUT_DEVICES);
92 }
93
94 /******************************************************************************
95  *      DirectInputCreateEx (DINPUT.@)
96  */
97 HRESULT WINAPI DirectInputCreateEx(
98         HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
99         LPUNKNOWN punkOuter
100 ) {
101         IDirectInputAImpl* This;
102
103         TRACE("(0x%08lx,%04lx,%s,%p,%p)\n",
104                 (DWORD)hinst,dwVersion,debugstr_guid(riid),ppDI,punkOuter
105         );
106         if (IsEqualGUID(&IID_IDirectInputA,riid)) {
107           This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
108           This->ref = 1;
109           ICOM_VTBL(This) = &ddiavt;
110           *ppDI = This;
111           
112           return DI_OK;
113         }
114         
115         if (IsEqualGUID(&IID_IDirectInput7A,riid)) {
116           This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
117           This->ref = 1;
118           ICOM_VTBL(This) = (ICOM_VTABLE(IDirectInputA) *) &ddi7avt;
119           *ppDI = This;
120           
121           return DI_OK;
122         }
123
124         return DIERR_OLDDIRECTINPUTVERSION;
125 }
126
127 /******************************************************************************
128  *      DirectInputCreateA (DINPUT.@)
129  */
130 HRESULT WINAPI DirectInputCreateA(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA *ppDI, LPUNKNOWN punkOuter)
131 {
132         IDirectInputAImpl* This;
133         TRACE("(0x%08lx,%04lx,%p,%p)\n",
134                 (DWORD)hinst,dwVersion,ppDI,punkOuter
135         );
136         This = (IDirectInputAImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDirectInputAImpl));
137         This->ref = 1;
138         ICOM_VTBL(This) = &ddiavt;
139         *ppDI=(IDirectInputA*)This;
140         return 0;
141 }
142 /******************************************************************************
143  *      IDirectInputA_EnumDevices
144  */
145 static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
146         LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
147         LPVOID pvRef, DWORD dwFlags
148 )
149 {
150         ICOM_THIS(IDirectInputAImpl,iface);
151         DIDEVICEINSTANCEA devInstance;
152         int i;
153
154         TRACE("(this=%p,0x%04lx,%p,%p,%04lx)\n", This, dwDevType, lpCallback, pvRef, dwFlags);
155
156         for (i = 0; i < nrof_dinput_devices; i++) {
157           if (dinput_devices[i]->enum_device(dwDevType, dwFlags, &devInstance)) {
158             if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
159               return 0;
160           }
161         }
162         
163         return 0;
164 }
165
166 static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
167 {
168         ICOM_THIS(IDirectInputAImpl,iface);
169         return ++(This->ref);
170 }
171
172 static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
173 {
174         ICOM_THIS(IDirectInputAImpl,iface);
175         if (!(--This->ref)) {
176                 HeapFree(GetProcessHeap(),0,This);
177                 return 0;
178         }
179         return This->ref;
180 }
181
182 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(
183         LPDIRECTINPUT7A iface,REFGUID rguid,LPDIRECTINPUTDEVICEA* pdev,
184         LPUNKNOWN punk
185 ) {
186         ICOM_THIS(IDirectInputAImpl,iface);
187         HRESULT ret_value = DIERR_DEVICENOTREG;
188         int i;
189         
190         TRACE("(this=%p,%s,%p,%p)\n",This,debugstr_guid(rguid),pdev,punk);
191
192         /* Loop on all the devices to see if anyone matches the given GUID */
193         for (i = 0; i < nrof_dinput_devices; i++) {
194           HRESULT ret;
195           if ((ret = dinput_devices[i]->create_device(This, rguid, NULL, pdev)) == DI_OK)
196             return DI_OK;
197
198           if (ret == DIERR_NOINTERFACE)
199             ret_value = DIERR_NOINTERFACE;
200         }
201
202         return ret_value;
203 }
204
205 static HRESULT WINAPI IDirectInputAImpl_QueryInterface(
206         LPDIRECTINPUT7A iface,REFIID riid,LPVOID *ppobj
207 ) {
208         ICOM_THIS(IDirectInputAImpl,iface);
209
210         TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
211         if (IsEqualGUID(&IID_IUnknown,riid)) {
212                 IDirectInputA_AddRef(iface);
213                 *ppobj = This;
214                 return 0;
215         }
216         if (IsEqualGUID(&IID_IDirectInputA,riid)) {
217                 IDirectInputA_AddRef(iface);
218                 *ppobj = This;
219                 return 0;
220         }
221         TRACE("Unsupported interface !\n");
222         return E_FAIL;
223 }
224
225 static HRESULT WINAPI IDirectInputAImpl_Initialize(
226         LPDIRECTINPUT7A iface,HINSTANCE hinst,DWORD x
227 ) {
228         return DIERR_ALREADYINITIALIZED;
229 }
230
231 static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface,
232                                                         REFGUID rguid) {
233   ICOM_THIS(IDirectInputAImpl,iface);
234   
235   FIXME("(%p)->(%s): stub\n",This,debugstr_guid(rguid));
236   
237   return DI_OK;
238 }
239
240 static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
241                                                         HWND hwndOwner,
242                                                         DWORD dwFlags) {
243   ICOM_THIS(IDirectInputAImpl,iface);
244   FIXME("(%p)->(%08lx,%08lx): stub\n",This, (DWORD) hwndOwner, dwFlags);
245   
246   return DI_OK;
247 }
248
249 static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT2A iface, REFGUID rguid,
250                                                     LPCSTR pszName, LPGUID pguidInstance) {
251   ICOM_THIS(IDirectInputAImpl,iface);
252   FIXME("(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance);
253   
254   return DI_OK;
255 }
256
257 static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
258                                                         REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
259 {
260   ICOM_THIS(IDirectInputAImpl,iface);
261   HRESULT ret_value = DIERR_DEVICENOTREG;
262   int i;
263         
264   TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
265
266   /* Loop on all the devices to see if anyone matches the given GUID */
267   for (i = 0; i < nrof_dinput_devices; i++) {
268     HRESULT ret;
269     if ((ret = dinput_devices[i]->create_device(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
270       return DI_OK;
271     
272     if (ret == DIERR_NOINTERFACE)
273       ret_value = DIERR_NOINTERFACE;
274   }
275   
276   return ret_value;
277 }
278
279 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
280 # define XCAST(fun)     (typeof(ddiavt.fun))
281 #else
282 # define XCAST(fun)     (void*)
283 #endif
284
285 static ICOM_VTABLE(IDirectInputA) ddiavt = 
286 {
287         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
288         XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,
289         XCAST(AddRef)IDirectInputAImpl_AddRef,
290         XCAST(Release)IDirectInputAImpl_Release,
291         XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
292         XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
293         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
294         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
295         XCAST(Initialize)IDirectInputAImpl_Initialize
296 };
297 #undef XCAST
298
299 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
300 # define XCAST(fun)     (typeof(ddi7avt.fun))
301 #else
302 # define XCAST(fun)     (void*)
303 #endif
304
305 static ICOM_VTABLE(IDirectInput7A) ddi7avt = {
306         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
307         XCAST(QueryInterface)IDirectInputAImpl_QueryInterface,
308         XCAST(AddRef)IDirectInputAImpl_AddRef,
309         XCAST(Release)IDirectInputAImpl_Release,
310         XCAST(CreateDevice)IDirectInputAImpl_CreateDevice,
311         XCAST(EnumDevices)IDirectInputAImpl_EnumDevices,
312         XCAST(GetDeviceStatus)IDirectInputAImpl_GetDeviceStatus,
313         XCAST(RunControlPanel)IDirectInputAImpl_RunControlPanel,
314         XCAST(Initialize)IDirectInputAImpl_Initialize,
315         XCAST(FindDevice)IDirectInput2AImpl_FindDevice,
316         IDirectInput7AImpl_CreateDeviceEx
317 };
318 #undef XCAST
319
320 /***********************************************************************
321  *              DllCanUnloadNow (DINPUT.@)
322  */
323 HRESULT WINAPI DINPUT_DllCanUnloadNow(void)
324 {
325     FIXME("(void): stub\n");
326
327     return S_FALSE;
328 }
329
330 /***********************************************************************
331  *              DllGetClassObject (DINPUT.@)
332  */
333 HRESULT WINAPI DINPUT_DllGetClassObject(REFCLSID rclsid, REFIID riid,
334                                         LPVOID *ppv)
335 {
336     FIXME("(%p, %p, %p): stub\n", debugstr_guid(rclsid), 
337           debugstr_guid(riid), ppv);
338
339     return CLASS_E_CLASSNOTAVAILABLE;
340 }
341
342 /***********************************************************************
343  *              DllRegisterServer (DINPUT.@)
344  */
345 HRESULT WINAPI DINPUT_DllRegisterServer(void)
346 {
347     FIXME("(void): stub\n");
348
349     return S_OK;
350 }
351
352 /***********************************************************************
353  *              DllUnregisterServer (DINPUT.@)
354  */
355 HRESULT WINAPI DINPUT_DllUnregisterServer(void)
356 {
357     FIXME("(void): stub\n");
358
359     return S_OK;
360 }