Now only storing thread id for mci tasks (16 bit htask is now gotten
[wine] / dlls / winmm / driver.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * WINE Drivers functions
5  *
6  * Copyright 1994 Martin Ayotte
7  * Copyright 1998 Marcus Meissner
8  * Copyright 1999 Eric Pouech
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include <string.h>
26 #include "heap.h"
27 #include "windef.h"
28 #include "mmddk.h"
29 #include "winemm.h"
30 #include "wine/winbase16.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(driver);
34
35 static LPWINE_DRIVER    lpDrvItemList = NULL;
36
37 WINE_MMTHREAD* (*pFnGetMMThread16)(HANDLE16 h) /* = NULL */;
38
39 /**************************************************************************
40  *                      DRIVER_GetNumberOfModuleRefs            [internal]
41  *
42  * Returns the number of open drivers which share the same module.
43  */
44 static  unsigned DRIVER_GetNumberOfModuleRefs(HMODULE hModule, WINE_DRIVER** found)
45 {
46     LPWINE_DRIVER       lpDrv;
47     unsigned            count = 0;
48
49     if (found) *found = NULL;
50     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem)
51     {
52         if (!(lpDrv->dwFlags & WINE_GDF_16BIT) && lpDrv->d.d32.hModule == hModule)
53         {
54             if (found && !*found) *found = lpDrv;
55             count++;
56         }
57     }
58     return count;
59 }
60
61 /**************************************************************************
62  *                              DRIVER_FindFromHDrvr            [internal]
63  *
64  * From a hDrvr being 32 bits, returns the WINE internal structure.
65  */
66 LPWINE_DRIVER   DRIVER_FindFromHDrvr(HDRVR hDrvr)
67 {
68     LPWINE_DRIVER       d = (LPWINE_DRIVER)hDrvr;
69
70     if (hDrvr && HeapValidate(GetProcessHeap(), 0, d) && d->dwMagic == WINE_DI_MAGIC) {
71         return d;
72     }
73     return NULL;
74 }
75
76 /**************************************************************************
77  *                              DRIVER_SendMessage              [internal]
78  */
79 static LRESULT inline DRIVER_SendMessage(LPWINE_DRIVER lpDrv, UINT msg,
80                                         LPARAM lParam1, LPARAM lParam2)
81 {
82     if (lpDrv->dwFlags & WINE_GDF_16BIT) {
83         LRESULT         ret;
84         int             map = 0;
85         TRACE("Before sdm16 call hDrv=%04x wMsg=%04x p1=%08lx p2=%08lx\n",
86               lpDrv->d.d16.hDriver16, msg, lParam1, lParam2);
87
88         if ((map = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2)) >= 0) {
89             ret = SendDriverMessage16(lpDrv->d.d16.hDriver16, msg, lParam1, lParam2);
90             if (map == 1)
91                 DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
92         } else {
93             ret = 0;
94         }
95         return ret;
96     }
97     TRACE("Before func32 call proc=%p driverID=%08lx hDrv=%08x wMsg=%04x p1=%08lx p2=%08lx\n",
98           lpDrv->d.d32.lpDrvProc, lpDrv->d.d32.dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);
99     return lpDrv->d.d32.lpDrvProc(lpDrv->d.d32.dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);
100 }
101
102 /**************************************************************************
103  *                              SendDriverMessage               [WINMM.@]
104  *                              DrvSendMessage                  [WINMM.@]
105  */
106 LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM lParam1,
107                                  LPARAM lParam2)
108 {
109     LPWINE_DRIVER       lpDrv;
110     LRESULT             retval = 0;
111
112     TRACE("(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
113
114     if ((lpDrv = DRIVER_FindFromHDrvr(hDriver)) != NULL) {
115         retval = DRIVER_SendMessage(lpDrv, msg, lParam1, lParam2);
116     } else {
117         WARN("Bad driver handle %u\n", hDriver);
118     }
119     TRACE("retval = %ld\n", retval);
120
121     return retval;
122 }
123
124 /**************************************************************************
125  *                              DRIVER_RemoveFromList           [internal]
126  *
127  * Generates all the logic to handle driver closure / deletion
128  * Removes a driver struct to the list of open drivers.
129  */
130 static  BOOL    DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
131 {
132     if (!(lpDrv->dwFlags & WINE_GDF_16BIT)) {
133         /* last of this driver in list ? */
134         if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, NULL) == 1) {
135             DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L);
136             DRIVER_SendMessage(lpDrv, DRV_FREE,    0L, 0L);
137         }
138     }
139
140     if (lpDrv->lpPrevItem)
141         lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem;
142     else
143         lpDrvItemList = lpDrv->lpNextItem;
144     if (lpDrv->lpNextItem)
145         lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
146     /* trash magic number */
147     lpDrv->dwMagic ^= 0xa5a5a5a5;
148
149     return TRUE;
150 }
151
152 /**************************************************************************
153  *                              DRIVER_AddToList                [internal]
154  *
155  * Adds a driver struct to the list of open drivers.
156  * Generates all the logic to handle driver creation / open.
157  */
158 static  BOOL    DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam1, LPARAM lParam2)
159 {
160     lpNewDrv->dwMagic = WINE_DI_MAGIC;
161     /* First driver to be loaded for this module, need to load correctly the module */
162     if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
163         /* first of this driver in list ? */
164         if (DRIVER_GetNumberOfModuleRefs(lpNewDrv->d.d32.hModule, NULL) == 0) {
165             if (DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
166                 TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
167                 return FALSE;
168             }
169             /* returned value is not checked */
170             DRIVER_SendMessage(lpNewDrv, DRV_ENABLE, 0L, 0L);
171         }
172     }
173
174     lpNewDrv->lpNextItem = NULL;
175     if (lpDrvItemList == NULL) {
176         lpDrvItemList = lpNewDrv;
177         lpNewDrv->lpPrevItem = NULL;
178     } else {
179         LPWINE_DRIVER   lpDrv = lpDrvItemList;  /* find end of list */
180         while (lpDrv->lpNextItem != NULL)
181             lpDrv = lpDrv->lpNextItem;
182
183         lpDrv->lpNextItem = lpNewDrv;
184         lpNewDrv->lpPrevItem = lpDrv;
185     }
186
187     if (!(lpNewDrv->dwFlags & WINE_GDF_16BIT)) {
188         /* Now just open a new instance of a driver on this module */
189         lpNewDrv->d.d32.dwDriverID = DRIVER_SendMessage(lpNewDrv, DRV_OPEN, lParam1, lParam2);
190
191         if (lpNewDrv->d.d32.dwDriverID == 0) {
192             TRACE("DRV_OPEN failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
193             DRIVER_RemoveFromList(lpNewDrv);
194             return FALSE;
195         }
196     }
197     return TRUE;
198 }
199
200 /**************************************************************************
201  *                              DRIVER_GetLibName               [internal]
202  *
203  */
204 BOOL    DRIVER_GetLibName(LPCSTR keyName, LPCSTR sectName, LPSTR buf, int sz)
205 {
206     /* should also do some registry diving */
207     return GetPrivateProfileStringA(sectName, keyName, "", buf, sz, "SYSTEM.INI");
208 }
209
210 /**************************************************************************
211  *                              DRIVER_TryOpenDriver32          [internal]
212  *
213  * Tries to load a 32 bit driver whose DLL's (module) name is fn
214  */
215 LPWINE_DRIVER   DRIVER_TryOpenDriver32(LPCSTR fn, LPARAM lParam2)
216 {
217     LPWINE_DRIVER       lpDrv = NULL;
218     HMODULE             hModule = 0;
219     LPSTR               ptr;
220     LPCSTR              cause = 0;
221
222     TRACE("(%s, %08lX);\n", debugstr_a(fn), lParam2);
223
224     if ((ptr = strchr(fn, ' ')) != NULL) {
225         *ptr++ = '\0';
226         while (*ptr == ' ') ptr++;
227         if (*ptr == '\0') ptr = NULL;
228     }
229
230     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
231     if (lpDrv == NULL) {cause = "OOM"; goto exit;}
232
233     if ((hModule = LoadLibraryA(fn)) == 0) {cause = "Not a 32 bit lib"; goto exit;}
234
235     lpDrv->d.d32.lpDrvProc = (DRIVERPROC)GetProcAddress(hModule, "DriverProc");
236     if (lpDrv->d.d32.lpDrvProc == NULL) {cause = "no DriverProc"; goto exit;}
237
238     lpDrv->dwFlags          = 0;
239     lpDrv->d.d32.hModule    = hModule;
240     lpDrv->d.d32.dwDriverID = 0;
241
242     /* Win32 installable drivers must support a two phase opening scheme:
243      * + first open with NULL as lParam2 (session instance),
244      * + then do a second open with the real non null lParam2)
245      */
246     if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, NULL) == 0 && lParam2)
247     {
248         LPWINE_DRIVER   ret;
249
250         if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, 0L))
251         {
252             cause = "load0 failed";
253             goto exit;
254         }
255         ret = DRIVER_TryOpenDriver32(fn, lParam2);
256         if (!ret)
257         {
258             CloseDriver((HDRVR)lpDrv, 0L, 0L);
259             cause = "load1 failed";
260             goto exit;
261         }
262         return ret;
263     }
264
265     if (!DRIVER_AddToList(lpDrv, (LPARAM)ptr, lParam2))
266     {cause = "load failed"; goto exit;}
267
268     TRACE("=> %p\n", lpDrv);
269     return lpDrv;
270  exit:
271     FreeLibrary(hModule);
272     HeapFree(GetProcessHeap(), 0, lpDrv);
273     TRACE("Unable to load 32 bit module %s: %s\n", debugstr_a(fn), cause);
274     return NULL;
275 }
276
277 /**************************************************************************
278  *                              DRIVER_TryOpenDriver16          [internal]
279  *
280  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
281  */
282 static  LPWINE_DRIVER   DRIVER_TryOpenDriver16(LPCSTR fn, LPCSTR sn, LPARAM lParam2)
283 {
284     LPWINE_DRIVER       lpDrv = NULL;
285     LPCSTR              cause = 0;
286
287     TRACE("(%s, %08lX);\n", debugstr_a(sn), lParam2);
288
289     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
290     if (lpDrv == NULL) {cause = "OOM"; goto exit;}
291
292     /* FIXME: shall we do some black magic here on sn ?
293      *  drivers32 => drivers
294      *  mci32 => mci
295      * ...
296      */
297     lpDrv->d.d16.hDriver16 = OpenDriver16(fn, sn, lParam2);
298     if (lpDrv->d.d16.hDriver16 == 0) {cause = "Not a 16 bit driver"; goto exit;}
299     lpDrv->dwFlags = WINE_GDF_16BIT;
300
301     if (!DRIVER_AddToList(lpDrv, 0, lParam2)) {cause = "load failed"; goto exit;}
302
303     TRACE("=> %p\n", lpDrv);
304     return lpDrv;
305  exit:
306     HeapFree(GetProcessHeap(), 0, lpDrv);
307     TRACE("Unable to load 32 bit module %s: %s\n", debugstr_a(fn), cause);
308     return NULL;
309 }
310
311 /**************************************************************************
312  *                              OpenDriverA                     [WINMM.@]
313  *                              DrvOpenA                        [WINMM.@]
314  * (0,1,DRV_LOAD  ,0       ,0)
315  * (0,1,DRV_ENABLE,0       ,0)
316  * (0,1,DRV_OPEN  ,buf[256],0)
317  */
318 HDRVR WINAPI OpenDriverA(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam2)
319 {
320     LPWINE_DRIVER       lpDrv = NULL;
321     char                libName[128];
322     LPCSTR              lsn = lpSectionName;
323
324     TRACE("(%s, %s, 0x%08lx);\n", debugstr_a(lpDriverName), debugstr_a(lpSectionName), lParam2);
325
326     if (lsn == NULL) {
327         lstrcpynA(libName, lpDriverName, sizeof(libName));
328
329         if ((lpDrv = DRIVER_TryOpenDriver32(libName, lParam2)))
330             goto the_end;
331         lsn = "Drivers32";
332     }
333     if (DRIVER_GetLibName(lpDriverName, lsn, libName, sizeof(libName)) &&
334         (lpDrv = DRIVER_TryOpenDriver32(libName, lParam2)))
335         goto the_end;
336
337     if (!(lpDrv = DRIVER_TryOpenDriver16(lpDriverName, lpSectionName, lParam2)))
338         TRACE("Failed to open driver %s from system.ini file, section %s\n", debugstr_a(lpDriverName), debugstr_a(lpSectionName));
339  the_end:
340     if (lpDrv)  TRACE("=> %08lx\n", (DWORD)lpDrv);
341     return (HDRVR)lpDrv;
342 }
343
344 /**************************************************************************
345  *                              OpenDriver                      [WINMM.@]
346  *                              DrvOpen                         [WINMM.@]
347  */
348 HDRVR WINAPI OpenDriverW(LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lParam)
349 {
350     LPSTR               dn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpDriverName);
351     LPSTR               sn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpSectionName);
352     HDRVR               ret = OpenDriverA(dn, sn, lParam);
353
354     if (dn) HeapFree(GetProcessHeap(), 0, dn);
355     if (sn) HeapFree(GetProcessHeap(), 0, sn);
356     return ret;
357 }
358
359 /**************************************************************************
360  *                      CloseDriver                             [WINMM.@]
361  *                      DrvClose                                [WINMM.@]
362  */
363 LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
364 {
365     LPWINE_DRIVER       lpDrv;
366
367     TRACE("(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
368
369     if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL)
370     {
371         if (lpDrv->dwFlags & WINE_GDF_16BIT)
372             CloseDriver16(lpDrv->d.d16.hDriver16, lParam1, lParam2);
373         else
374         {
375             DRIVER_SendMessage(lpDrv, DRV_CLOSE, lParam1, lParam2);
376             lpDrv->d.d32.dwDriverID = 0;
377         }
378         if (DRIVER_RemoveFromList(lpDrv)) {
379             if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
380             {
381                 LPWINE_DRIVER       lpDrv0;
382
383                 /* if driver has an opened session instance, we have to close it too */
384                 if (DRIVER_GetNumberOfModuleRefs(lpDrv->d.d32.hModule, &lpDrv0) == 1)
385                 {
386                     DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0L, 0L);
387                     lpDrv0->d.d32.dwDriverID = 0;
388                     DRIVER_RemoveFromList(lpDrv0);
389                     FreeLibrary(lpDrv->d.d32.hModule);
390                     HeapFree(GetProcessHeap(), 0, lpDrv0);
391                 }
392                 FreeLibrary(lpDrv->d.d32.hModule);
393             }
394             HeapFree(GetProcessHeap(), 0, lpDrv);
395             return TRUE;
396         }
397     }
398     WARN("Failed to close driver\n");
399     return FALSE;
400 }
401
402 /**************************************************************************
403  *                              GetDriverFlags          [WINMM.@]
404  * [in] hDrvr handle to the driver
405  *
406  * Returns:
407  *      0x00000000 if hDrvr is an invalid handle
408  *      0x80000000 if hDrvr is a valid 32 bit driver
409  *      0x90000000 if hDrvr is a valid 16 bit driver
410  *
411  * native WINMM doesn't return those flags
412  *      0x80000000 for a valid 32 bit driver and that's it
413  *      (I may have mixed up the two flags :-(
414  */
415 DWORD   WINAPI GetDriverFlags(HDRVR hDrvr)
416 {
417     LPWINE_DRIVER       lpDrv;
418     DWORD               ret = 0;
419
420     TRACE("(%04x)\n", hDrvr);
421
422     if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) {
423         ret = WINE_GDF_EXIST | lpDrv->dwFlags;
424     }
425     return ret;
426 }
427
428 /**************************************************************************
429  *                              GetDriverModuleHandle   [WINMM.@]
430  *                              DrvGetModuleHandle      [WINMM.@]
431  */
432 HMODULE WINAPI GetDriverModuleHandle(HDRVR hDrvr)
433 {
434     LPWINE_DRIVER       lpDrv;
435     HMODULE             hModule = 0;
436
437     TRACE("(%04x);\n", hDrvr);
438
439     if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) {
440         if (!(lpDrv->dwFlags & WINE_GDF_16BIT))
441             hModule = lpDrv->d.d32.hModule;
442     }
443     TRACE("=> %04x\n", hModule);
444     return hModule;
445 }
446
447 /**************************************************************************
448  *                              DefDriverProc                     [WINMM.@]
449  *                              DrvDefDriverProc                  [WINMM.@]
450  */
451 LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR hDrv,
452                              UINT Msg, LPARAM lParam1, LPARAM lParam2)
453 {
454     switch (Msg) {
455     case DRV_LOAD:
456     case DRV_FREE:
457     case DRV_ENABLE:
458     case DRV_DISABLE:
459         return 1;
460     case DRV_INSTALL:
461     case DRV_REMOVE:
462         return DRV_SUCCESS;
463     default:
464         return 0;
465     }
466 }