Added a first-cut version of MapVirtualKeyExW() that has the same
[wine] / windows / 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
11 #include <string.h>
12 #include "heap.h"
13 #include "windef.h"
14 #include "wine/winbase16.h"
15 #include "wingdi.h"
16 #include "winuser.h"
17 #include "ldt.h"
18 #include "mmddk.h"
19 #include "debugtools.h"
20
21 DEFAULT_DEBUG_CHANNEL(driver);
22
23 /* The following definitions are WINE internals */
24 /* FIXME: This is a WINE internal struct and should be moved in include/wine directory
25  * Please note that WINE shares 16 and 32 bit drivers on a single list...
26  * Basically, we maintain an external double view on drivers, so that a 16 bit drivers 
27  * can be loaded/used... by 32 functions transparently 
28  */
29
30 /* Who said goofy boy ? */
31 #define WINE_DI_MAGIC   0x900F1B01
32
33 typedef struct tagWINE_DRIVER
34 {
35     DWORD                       dwMagic;
36     char                        szAliasName[128];
37     /* as usual LPWINE_DRIVER == hDriver32 */
38     HDRVR16                     hDriver16;
39     union {
40        struct {
41           HMODULE16             hModule;
42           DRIVERPROC16          lpDrvProc;
43        } d16;
44        struct {
45           HMODULE               hModule;
46           DRIVERPROC            lpDrvProc;
47        } d32;
48     } d;
49     DWORD                       dwDriverID;
50     DWORD                       dwFlags;
51     struct tagWINE_DRIVER*      lpPrevItem;
52     struct tagWINE_DRIVER*      lpNextItem;
53 } WINE_DRIVER, *LPWINE_DRIVER;
54
55 LPWINE_DRIVER   DRIVER_RegisterDriver16(LPCSTR, HMODULE16, DRIVERPROC16, LPARAM, BOOL);
56 LPWINE_DRIVER   DRIVER_RegisterDriver32(LPCSTR, HMODULE,   DRIVERPROC,   LPARAM, BOOL);
57
58 static LPWINE_DRIVER    lpDrvItemList = NULL;
59
60 /* TODO list :
61  *      - LoadModule count and clean up is not handled correctly (it's not a 
62  *        problem as long as FreeLibrary is not working correctly)
63  *      - shoudln't the allocations be done on a per process basis ?
64  *      - split 16/32 bit functions between DLLs as windows do (16 bit in USER, 32 bit in WINMM)
65  */
66
67 /* ### start build ### */
68 extern LONG CALLBACK DRIVER_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
69 /* ### stop build ### */
70
71 /**************************************************************************
72  *                      LoadStartupDrivers                      [internal]
73  */
74 static void WINE_UNUSED DRIVER_LoadStartupDrivers(void)
75 {
76     char        str[256];
77     
78     if (GetPrivateProfileStringA("drivers", NULL, "", str, sizeof(str), "SYSTEM.INI") < 2) {
79         ERR("Can't find drivers section in system.ini\n");
80     } else {
81         HDRVR16 hDrv;
82         LPSTR   ptr;
83
84         for (ptr = str; *ptr; ptr += strlen(ptr) + 1) {
85             TRACE("str='%s'\n", ptr);
86             hDrv = OpenDriver16(ptr, "drivers", 0L);
87             TRACE("hDrv=%04x\n", hDrv);
88         }
89         TRACE("end of list !\n");
90     }
91 }
92
93 /**************************************************************************
94  *                      DRIVER_GetNumberOfModuleRefs            [internal]
95  *
96  * Returns the number of open drivers which share the same module.
97  */
98 static  WORD    DRIVER_GetNumberOfModuleRefs(LPWINE_DRIVER lpNewDrv)
99 {
100     LPWINE_DRIVER       lpDrv;
101     WORD                count = 0;
102     
103     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
104         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
105             if (lpDrv->d.d16.hModule == lpNewDrv->d.d16.hModule) {
106                 count++;
107             }
108         } else {
109             if (lpDrv->d.d32.hModule == lpNewDrv->d.d32.hModule) {
110                 count++;
111             }
112         }
113     }
114     return count;
115 }
116
117 /**************************************************************************
118  *                              DRIVER_FindFromHDrvr16          [internal]
119  *
120  * From a hDrvr being 16 bits, returns the WINE internal structure.
121  */
122 static  LPWINE_DRIVER   DRIVER_FindFromHDrvr16(HDRVR16 hDrvr)
123 {    
124     LPWINE_DRIVER       lpDrv;
125     
126     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
127         if (lpDrv->hDriver16 == hDrvr) {
128             break;
129         }
130     }
131     return lpDrv;
132 }
133
134 /**************************************************************************
135  *                              DRIVER_FindFromHDrvr            [internal]
136  * 
137  * From a hDrvr (being 16 or 32 bits), returns the WINE internal structure.
138  */
139 static  LPWINE_DRIVER   DRIVER_FindFromHDrvr(HDRVR hDrvr)
140 {    
141     if (!IsBadWritePtr((void*)hDrvr, sizeof(WINE_DRIVER)) && 
142         ((LPWINE_DRIVER)hDrvr)->dwMagic == WINE_DI_MAGIC) {
143         return (LPWINE_DRIVER)hDrvr;
144     }
145     return DRIVER_FindFromHDrvr16(hDrvr);
146 }
147
148 /**************************************************************************
149  *                              DRIVER_MapMsg16To32             [internal]
150  *
151  * Map a 16 bit driver message to a 32 bit driver message.
152  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg16To32
153  *  0 : ok, no memory allocated
154  * -1 : ko, unknown message
155  * -2 : ko, memory problem
156  */
157 static int DRIVER_MapMsg16To32(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
158 {
159     int ret = -1;
160     
161     switch (wMsg) {
162     case DRV_LOAD:
163     case DRV_ENABLE:
164     case DRV_DISABLE:
165     case DRV_FREE:
166     case DRV_QUERYCONFIGURE:
167     case DRV_REMOVE:
168     case DRV_EXITSESSION:
169     case DRV_EXITAPPLICATION:   
170     case DRV_POWER:
171         /* lParam1 and lParam2 are not used */
172         ret = 0;
173         break;
174     case DRV_OPEN:
175     case DRV_CLOSE:
176         /* lParam1 is a NULL terminated string */
177         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
178         if (*lParam1)
179             *lParam1 = (DWORD)PTR_SEG_TO_LIN(*lParam1);
180         if (*lParam2 && wMsg == DRV_OPEN) {
181             LPMCI_OPEN_DRIVER_PARMS16   modp16 = PTR_SEG_TO_LIN(*lParam2);
182             char*                       ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(LPMCI_OPEN_DRIVER_PARMS16) + sizeof(MCI_OPEN_DRIVER_PARMSA));
183             LPMCI_OPEN_DRIVER_PARMSA    modp32;
184             
185             if (ptr) {
186                 *(LPMCI_OPEN_DRIVER_PARMS16*)ptr = modp16;
187                 modp32 = (LPMCI_OPEN_DRIVER_PARMSA)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
188
189                 modp32->wDeviceID = modp16->wDeviceID;
190                 modp32->lpstrParams = PTR_SEG_TO_LIN(modp16->lpstrParams);
191             } else {
192                 return -2;
193             }
194             *lParam2 = (DWORD)modp32;
195         }
196         ret = 1;
197         break;
198     case DRV_CONFIGURE:
199     case DRV_INSTALL:
200         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
201         if (*lParam2) {
202             LPDRVCONFIGINFO     dci32 = HeapAlloc(GetProcessHeap(), 0, sizeof(DRVCONFIGINFO));
203             LPDRVCONFIGINFO16   dci16 = PTR_SEG_TO_LIN(*lParam2);
204             
205             if (dci32) {
206                 dci32->dwDCISize = sizeof(DRVCONFIGINFO);
207                 dci32->lpszDCISectionName = HEAP_strdupAtoW(GetProcessHeap(), 0, PTR_SEG_TO_LIN(dci16->lpszDCISectionName));
208                 dci32->lpszDCIAliasName   = HEAP_strdupAtoW(GetProcessHeap(), 0, PTR_SEG_TO_LIN(dci16->lpszDCIAliasName));
209                 if (dci32->lpszDCISectionName == NULL || dci32->lpszDCIAliasName == NULL)
210                     return -2;
211             } else {
212                 return -2;
213             }
214             *lParam2 = (DWORD)dci32;
215             ret = 1;
216         } else {
217             ret = 0;
218         }
219         break;
220     default:
221         if ((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100 )) {
222             /* FIXME: another hack to handle MCI and ICM messages... 
223              * should find a *NICE* way to integrate DRIVER_ and
224              * MCI_ mapping/unmapping functions
225              */
226             ret = 0;
227         } else {
228            FIXME("Unknown message 0x%04x\n", wMsg);
229         }
230     }
231     return ret;
232 }
233
234 /**************************************************************************
235  *                              DRIVER_MapMsg16To32             [internal]
236  *
237  * UnMap a 16 bit driver message to a 32 bit driver message.
238  *  0 : ok
239  * -1 : ko
240  * -2 : ko, memory problem
241  */
242 static int DRIVER_UnMapMsg16To32(WORD wMsg, DWORD lParam1, DWORD lParam2)
243 {
244     int ret = -1;
245     
246     switch (wMsg) {
247     case DRV_LOAD:
248     case DRV_ENABLE:
249     case DRV_DISABLE:
250     case DRV_FREE:
251     case DRV_QUERYCONFIGURE:
252     case DRV_REMOVE:
253     case DRV_EXITSESSION:
254     case DRV_EXITAPPLICATION:
255     case DRV_POWER:
256         /* lParam1 and lParam2 are not used */
257     case DRV_OPEN:
258     case DRV_CLOSE:
259         /* lParam1 is a NULL terminated string */
260         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
261         if (lParam2 && wMsg == DRV_OPEN) {
262             LPMCI_OPEN_DRIVER_PARMSA    modp32 = (LPMCI_OPEN_DRIVER_PARMSA)lParam2;
263             LPMCI_OPEN_DRIVER_PARMS16   modp16 = *(LPMCI_OPEN_DRIVER_PARMS16*)(lParam2 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
264
265             modp16->wCustomCommandTable = modp32->wCustomCommandTable;
266             modp16->wType = modp32->wType;
267             if (!HeapFree(GetProcessHeap(), 0, modp32))
268                 FIXME("bad free line=%d\n", __LINE__);
269         }
270         ret = 0;
271         break;
272     case DRV_CONFIGURE: 
273     case DRV_INSTALL:
274         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
275         if (lParam2) {
276             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)lParam2;
277             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)dci32->lpszDCISectionName))
278                 FIXME("bad free line=%d\n", __LINE__);
279             if (!HeapFree(GetProcessHeap(), 0, (LPVOID)dci32->lpszDCIAliasName))
280                 FIXME("bad free line=%d\n", __LINE__);
281             if (!HeapFree(GetProcessHeap(), 0, dci32))
282                 FIXME("bad free line=%d\n", __LINE__);
283         }
284         ret = 0;
285         break;
286     default:
287         if ((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100 )) {
288             /* FIXME: another hack to handle MCI and ICM messages... 
289              * should find a *NICE* way to integrate DRIVER_ and
290              * MCI_ mapping/unmapping functions
291              */
292             ret = 0;
293         } else {
294            FIXME("Unknown message 0x%04x\n", wMsg);
295         }       
296     }
297     return ret;
298 }
299
300 /**************************************************************************
301  *                              DRIVER_MapMsg32To16             [internal]
302  *
303  * Map a 32 bit driver message to a 16 bit driver message.
304  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg32To16
305  *  0 : ok, no memory allocated
306  * -1 : ko, unknown message
307  * -2 : ko, memory problem
308  */
309 static int DRIVER_MapMsg32To16(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
310 {
311     int ret = -1;
312     
313     switch (wMsg) {
314     case DRV_LOAD:
315     case DRV_ENABLE:
316     case DRV_DISABLE:
317     case DRV_FREE:
318     case DRV_QUERYCONFIGURE:
319     case DRV_REMOVE:
320     case DRV_EXITSESSION:
321     case DRV_EXITAPPLICATION:   
322     case DRV_POWER:
323         /* lParam1 and lParam2 are not used */
324         ret = 0;
325         break;
326     case DRV_OPEN:
327     case DRV_CLOSE:
328         /* lParam1 is a NULL terminated string */
329         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
330         if (*lParam1) {
331             LPSTR str = SEGPTR_STRDUP((LPSTR)*lParam1);
332             if (str) {
333                 *lParam1 = (LPARAM)SEGPTR_GET(str);
334                 ret = 0;
335             } else {
336                 ret = -2;
337             }
338         } else {
339             ret = 0;
340         }
341         if (*lParam2 && wMsg == DRV_OPEN) {
342             LPMCI_OPEN_DRIVER_PARMS16   modp16;
343             char*                       ptr = SEGPTR_ALLOC(sizeof(LPMCI_OPEN_DRIVER_PARMSA) + sizeof(MCI_OPEN_DRIVER_PARMS16));
344             LPMCI_OPEN_DRIVER_PARMSA    modp32 = (LPMCI_OPEN_DRIVER_PARMSA)(*lParam2);
345             
346             if (ptr) {
347                 *(LPMCI_OPEN_DRIVER_PARMSA*)ptr = modp32;
348                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
349
350                 modp16->wDeviceID = modp32->wDeviceID;
351                 modp16->lpstrParams = PTR_SEG_TO_LIN(modp32->lpstrParams);
352             } else {
353                 return -2;
354             }
355             *lParam2 = (DWORD)SEGPTR_GET(modp16);
356             ret = 1;
357         }
358         break;
359     case DRV_CONFIGURE:
360     case DRV_INSTALL:
361         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
362         if (*lParam2) {
363             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)SEGPTR_ALLOC(sizeof(DRVCONFIGINFO16));
364             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)(*lParam2);
365             
366             if (dci16) {
367                 LPSTR   str1, str2;
368                 
369                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
370                 
371                 if ((str1 = HEAP_strdupWtoA(GetProcessHeap(), 0, dci32->lpszDCISectionName)) != NULL &&
372                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
373                     dci16->lpszDCISectionName = (LPSTR)SEGPTR_GET(str2);
374                     if (!HeapFree(GetProcessHeap(), 0, str1))
375                         FIXME("bad free line=%d\n", __LINE__);
376                 } else {
377                     return -2;
378                 }
379                 if ((str1 = HEAP_strdupWtoA(GetProcessHeap(), 0, dci32->lpszDCIAliasName)) != NULL &&
380                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
381                     dci16->lpszDCIAliasName = (LPSTR)SEGPTR_GET(str2);
382                     if (!HeapFree(GetProcessHeap(), 0, str1))
383                         FIXME("bad free line=%d\n", __LINE__);
384                 } else {
385                     return -2;
386                 }
387             } else {
388                 return -2;
389             }
390             *lParam2 = (LPARAM)SEGPTR_GET(dci16);
391             ret = 1;
392         } else {
393             ret = 0;
394         }
395         break;
396     default:
397         if ((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100 )) {
398             /* FIXME: another hack to handle MCI and ICM messages... 
399              * should find a *NICE* way to integrate DRIVER_ and
400              * MCI_ mapping/unmapping functions
401              */
402             ret = 0;
403         } else {
404            FIXME("Unknown message 0x%04x\n", wMsg);
405         }       
406     }
407     return ret;
408 }
409
410 /**************************************************************************
411  *                              DRIVER_UnMapMsg32To16           [internal]
412  *
413  * UnMap a 32 bit driver message to a 16 bit driver message.
414  *  0 : ok
415  * -1 : ko
416  * -2 : ko, memory problem
417  */
418 static int DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
419 {
420     int ret = -1;
421     
422     switch (wMsg) {
423     case DRV_LOAD:
424     case DRV_ENABLE:
425     case DRV_DISABLE:
426     case DRV_FREE:
427     case DRV_QUERYCONFIGURE:
428     case DRV_REMOVE:
429     case DRV_EXITSESSION:
430     case DRV_EXITAPPLICATION:
431     case DRV_POWER:
432         /* lParam1 and lParam2 are not used */
433     case DRV_OPEN:
434     case DRV_CLOSE:
435         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
436         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
437         if (lParam1) if (!SEGPTR_FREE(PTR_SEG_TO_LIN(lParam1)))
438             FIXME("bad free line=%d\n", __LINE__);
439
440         if (lParam2 && wMsg == DRV_OPEN) {
441             LPMCI_OPEN_DRIVER_PARMS16   modp16 = (LPMCI_OPEN_DRIVER_PARMS16)PTR_SEG_TO_LIN(lParam2);
442             LPMCI_OPEN_DRIVER_PARMSA    modp32 = *(LPMCI_OPEN_DRIVER_PARMSA*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
443
444             modp32->wCustomCommandTable = modp16->wCustomCommandTable;
445             modp32->wType = modp16->wType;
446             if (!SEGPTR_FREE((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA)))
447                 FIXME("bad free line=%d\n", __LINE__);
448         }
449         ret = 0;
450         break;
451     case DRV_CONFIGURE: 
452     case DRV_INSTALL:
453         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
454         if (lParam2) {
455             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)PTR_SEG_TO_LIN(lParam2);
456             
457             if (!SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCISectionName)))
458                 FIXME("bad free line=%d\n", __LINE__);
459             if (!SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCIAliasName)))
460                 FIXME("bad free line=%d\n", __LINE__);
461             if (!SEGPTR_FREE(dci16))
462                 FIXME("bad free line=%d\n", __LINE__);
463         }
464         ret = 0;
465         break;
466     default:
467         if ((wMsg >= 0x800 && wMsg < 0x900) || (wMsg >= 0x4000 && wMsg < 0x4100 )) {
468             /* FIXME: another hack to handle MCI and ICM messages... 
469              * should find a *NICE* way to integrate DRIVER_ and
470              * MCI_ mapping/unmapping functions
471              */
472             ret = 0;
473         } else {
474            FIXME("Unknown message 0x%04x\n", wMsg);
475         }
476     }
477     return ret;
478 }
479
480 /**************************************************************************
481  *                              SendDriverMessage               [USER.251]
482  */
483 LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
484                                    LPARAM lParam2)
485 {
486     LPWINE_DRIVER       lpDrv;
487     LRESULT             retval = 0;
488     int                 mapRet;
489     
490     TRACE("(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
491     
492     lpDrv = DRIVER_FindFromHDrvr16(hDriver);
493     if (lpDrv != NULL && lpDrv->hDriver16 == hDriver) {
494         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
495             TRACE("Before CallDriverProc proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
496                   lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);             
497             retval = DRIVER_CallTo16_long_lwwll((FARPROC16)lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, 
498                                                 hDriver, msg, lParam1, lParam2);
499         } else {
500             mapRet = DRIVER_MapMsg16To32(msg, &lParam1, &lParam2);
501             if (mapRet >= 0) {
502                 TRACE("Before func32 call proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
503                       lpDrv->d.d32.lpDrvProc, lpDrv->dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);            
504                 retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);
505                 if (mapRet >= 1) {
506                     DRIVER_UnMapMsg16To32(msg, lParam1, lParam2);
507                 }
508             } else {
509                 retval = 0;
510             }
511         }
512     } else {
513         WARN("Bad driver handle %u\n", hDriver);
514     }
515     
516     TRACE("retval = %ld\n", retval);
517     return retval;
518 }
519
520 /**************************************************************************
521  *                              SendDriverMessage               [WINMM.19]
522  */
523 LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM lParam1,
524                                  LPARAM lParam2)
525 {
526     LPWINE_DRIVER       lpDrv;
527     LRESULT             retval = 0;
528     int                 mapRet;
529     
530     TRACE("(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
531     
532     lpDrv = DRIVER_FindFromHDrvr(hDriver);
533
534     if (lpDrv != NULL) {
535         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
536             mapRet = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2);
537             if (mapRet >= 0) {
538                 TRACE("Before CallDriverProc proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
539                       lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, lpDrv->hDriver16, msg, lParam1, lParam2);                
540                 retval = DRIVER_CallTo16_long_lwwll((FARPROC16)lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, 
541                                                     lpDrv->hDriver16, msg, lParam1, lParam2);
542                 if (mapRet >= 1) {
543                     DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
544                 }
545             } else {
546                 retval = 0;
547             }
548         } else {
549             TRACE("Before func32 call proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
550                   lpDrv->d.d32.lpDrvProc, lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);             
551             retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);
552         }
553     } else {
554         WARN("Bad driver handle %u\n", hDriver);
555     }
556     TRACE("retval = %ld\n", retval);
557     
558     return retval;
559 }
560
561 /**************************************************************************
562  *                              DRIVER_RemoveFromList           [internal]
563  *
564  * Generates all the logic to handle driver closure / deletion
565  * Removes a driver struct to the list of open drivers.
566  */
567 static  BOOL    DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
568 {
569     lpDrv->dwDriverID = 0;
570     if (DRIVER_GetNumberOfModuleRefs(lpDrv) == 1) {
571         SendDriverMessage((HDRVR)lpDrv, DRV_DISABLE, 0L, 0L);
572         SendDriverMessage((HDRVR)lpDrv, DRV_FREE,    0L, 0L);
573     }
574     
575     if (lpDrv->lpPrevItem)
576         lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem;
577     else
578         lpDrvItemList = lpDrv->lpNextItem;
579     if (lpDrv->lpNextItem)
580         lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
581
582     return TRUE;
583 }
584
585 /**************************************************************************
586  *                              DRIVER_AddToList                [internal]
587  *
588  * Adds a driver struct to the list of open drivers.
589  * Generates all the logic to handle driver creation / open.
590  */
591 static  BOOL    DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam, BOOL bCallFrom32)
592 {
593     lpNewDrv->dwMagic = WINE_DI_MAGIC;
594     /* First driver to be loaded for this module, need to load correctly the module */
595     if (DRIVER_GetNumberOfModuleRefs(lpNewDrv) == 0) {
596         if (SendDriverMessage((HDRVR)lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
597             TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
598             return FALSE;
599         }
600         if (SendDriverMessage((HDRVR)lpNewDrv, DRV_ENABLE, 0L, 0L) != DRV_SUCCESS) {
601             TRACE("DRV_ENABLE failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
602             return FALSE;
603         }
604     }
605
606     lpNewDrv->lpNextItem = NULL;
607     if (lpDrvItemList == NULL) {
608         lpDrvItemList = lpNewDrv;
609         lpNewDrv->lpPrevItem = NULL;
610     } else {
611         LPWINE_DRIVER   lpDrv = lpDrvItemList;  /* find end of list */
612         while (lpDrv->lpNextItem != NULL)
613             lpDrv = lpDrv->lpNextItem;
614         
615         lpDrv->lpNextItem = lpNewDrv;
616         lpNewDrv->lpPrevItem = lpDrv;
617     }
618     /* Now just open a new instance of a driver on this module */
619     if (bCallFrom32) {
620         lpNewDrv->dwDriverID = SendDriverMessage((HDRVR)lpNewDrv, DRV_OPEN, 0L, lParam);
621     } else {
622         lpNewDrv->dwDriverID = SendDriverMessage16(lpNewDrv->hDriver16, DRV_OPEN, 0L, lParam);
623     }
624     if (lpNewDrv->dwDriverID == 0) {
625         TRACE("DRV_OPEN failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
626         DRIVER_RemoveFromList(lpNewDrv);
627         return FALSE;
628     }
629     
630     return TRUE;
631 }
632
633 /**************************************************************************
634  *                              DRIVER_CreateDrvr16             [internal]
635  *
636  * Creates unique ID for 16 bit drivers.
637  */
638 static  HDRVR16 DRIVER_CreateDrvr16(void)
639 {
640     static      WORD    DRIVER_hDrvr16Counter = 0;
641     
642     while (DRIVER_FindFromHDrvr16(++DRIVER_hDrvr16Counter));
643     return DRIVER_hDrvr16Counter;
644 }
645
646 /**************************************************************************
647  *                              DRIVER_CloseDriver              [internal]
648  *
649  */
650 BOOL DRIVER_CloseDriver(LPWINE_DRIVER lpDrv, DWORD lParam1, DWORD lParam2)
651 {
652     if (lpDrv != NULL) {
653         SendDriverMessage((HDRVR)lpDrv, DRV_CLOSE, lParam1, lParam2);
654     
655         if (DRIVER_RemoveFromList(lpDrv)) {
656             HeapFree(GetProcessHeap(), 0, lpDrv);
657             return TRUE;
658         }
659     }
660     WARN("Failed to close driver\n");
661     return FALSE;
662 }
663
664 /**************************************************************************
665  *                              DRIVER_RegisterDriver16         [internal]
666  *
667  * Creates all the WINE internal representations for a 16 bit driver.
668  * The driver is also open by sending the correct messages.
669  */
670 LPWINE_DRIVER DRIVER_RegisterDriver16(LPCSTR lpName, HMODULE16 hModule, DRIVERPROC16 lpProc, 
671                                       LPARAM lParam, BOOL bCallFrom32)
672 {
673     LPWINE_DRIVER       lpDrv;
674     
675     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
676     if (lpDrv != NULL) {
677         lpDrv->dwFlags         = WINE_GDF_EXIST|WINE_GDF_16BIT;
678         lpDrv->dwDriverID      = 0;
679         lpDrv->hDriver16       = DRIVER_CreateDrvr16();
680         lstrcpynA(lpDrv->szAliasName, lpName, sizeof(lpDrv->szAliasName));
681         lpDrv->d.d16.hModule   = hModule;
682         lpDrv->d.d16.lpDrvProc = lpProc;
683         
684         if (!DRIVER_AddToList(lpDrv, lParam, bCallFrom32)) {
685             HeapFree(GetProcessHeap(), 0, lpDrv);
686             lpDrv = NULL;
687         }
688     }
689     return lpDrv;
690 }
691
692 /**************************************************************************
693  *                              DRIVER_RegisterDriver32         [internal]
694  *
695  * Creates all the WINE internal representations for a 32 bit driver.
696  * The driver is also open by sending the correct messages.
697  */
698 LPWINE_DRIVER DRIVER_RegisterDriver32(LPCSTR lpName, HMODULE hModule, DRIVERPROC lpProc, 
699                                       LPARAM lParam, BOOL bCallFrom32)
700 {
701     LPWINE_DRIVER       lpDrv;
702     
703     lpDrv = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_DRIVER));
704     if (lpDrv != NULL) {
705         lpDrv->dwFlags          = WINE_GDF_EXIST;
706         lpDrv->dwDriverID       = 0;
707         lpDrv->hDriver16        = DRIVER_CreateDrvr16();
708         lstrcpynA(lpDrv->szAliasName, lpName, sizeof(lpDrv->szAliasName));
709         lpDrv->d.d32.hModule    = hModule;
710         lpDrv->d.d32.lpDrvProc  = lpProc;
711         
712         if (!DRIVER_AddToList(lpDrv, lParam, bCallFrom32)) {
713             HeapFree(GetProcessHeap(), 0, lpDrv);
714             lpDrv = NULL;
715         }
716     }
717     return lpDrv;
718 }
719
720 /**************************************************************************
721  *                              DRIVER_TryOpenDriver16          [internal]
722  *
723  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
724  */
725 static  HDRVR16 DRIVER_TryOpenDriver16(LPCSTR lpFileName, LPARAM lParam, BOOL bCallFrom32)
726 {
727     LPWINE_DRIVER       lpDrv = NULL;
728     LPCSTR              lpSFN;
729     HMODULE16           hModule;
730     DRIVERPROC16        lpProc;
731     
732     TRACE("('%s', %08lX, %d);\n", lpFileName, lParam, bCallFrom32);
733     
734     if (strlen(lpFileName) < 1) 
735         return 0;
736     
737     lpSFN = strrchr(lpFileName, '\\');
738     lpSFN = (lpSFN) ? (lpSFN + 1) : lpFileName;
739     
740     if ((hModule = LoadModule16(lpFileName, (LPVOID)-1)) >= 32) {
741         if ((lpProc = (DRIVERPROC16)GetProcAddress16(hModule, "DRIVERPROC")) != NULL) {
742             lpDrv = DRIVER_RegisterDriver16(lpSFN, hModule, lpProc, lParam, bCallFrom32);
743         } else {
744             FreeLibrary16(hModule);
745             TRACE("No DriverProc found\n");
746             lpDrv = 0;
747         }
748     } else {
749         TRACE("Unable to load 16 bit module (%s): %d\n", lpFileName, hModule);
750     }
751     return lpDrv ? lpDrv->hDriver16 : 0;
752 }
753
754 /**************************************************************************
755  *                              DRIVER_TryOpenDriver32          [internal]
756  *
757  * Tries to load a 32 bit driver whose DLL's (module) name is lpFileName.
758  */
759 static  HDRVR   DRIVER_TryOpenDriver32(LPCSTR lpFileName, LPARAM lParam, BOOL bCallFrom32)
760 {
761     LPWINE_DRIVER       lpDrv = NULL;
762     LPCSTR              lpSFN;
763     HMODULE             hModule;
764     DRIVERPROC          lpProc;
765     
766     TRACE("('%s', %08lX, %d);\n", lpFileName, lParam, bCallFrom32);
767     
768     if (strlen(lpFileName) < 1) 
769         return 0;
770     
771     lpSFN = strrchr(lpFileName, '\\');
772     lpSFN = (lpSFN) ? (lpSFN + 1) : lpFileName;
773     
774     if ((hModule = LoadLibraryA(lpFileName)) != 0) {
775         if ((lpProc = GetProcAddress(hModule, "DriverProc")) != NULL) {
776             lpDrv = DRIVER_RegisterDriver32(lpSFN, hModule, lpProc, lParam, bCallFrom32);
777         } else {
778             FreeLibrary(hModule);
779             lpDrv = 0;
780             TRACE("No DriverProc found\n");
781         }
782     } else {
783         TRACE("Unable to load 32 bit module \"%s\"\n", lpFileName);
784     }
785     TRACE("=> %p\n", lpDrv);
786     return (HDRVR)lpDrv;
787 }
788
789 /**************************************************************************
790  *                              OpenDriver16                    [USER.252]
791  */
792 HDRVR16 WINAPI OpenDriver16(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam)
793 {
794     HDRVR16             hDriver = 0;
795     char                drvName[128];
796     
797     TRACE("('%s', '%s', %08lX);\n", lpDriverName, lpSectionName, lParam);
798     
799     if (lpSectionName == NULL) {
800         hDriver = DRIVER_TryOpenDriver16(lpDriverName, lParam, FALSE);
801         if (!hDriver) {
802             hDriver = DRIVER_TryOpenDriver32(lpDriverName, lParam, FALSE);
803         }
804         if (!hDriver) {
805             /* in case hDriver is NULL, search in Drivers32 section */
806             lpSectionName = "Drivers";
807         }
808     }
809     if (!hDriver && GetPrivateProfileStringA(lpSectionName, lpDriverName, "", 
810                                              drvName, sizeof(drvName), "SYSTEM.INI") > 0) {
811         hDriver = DRIVER_TryOpenDriver16(drvName, lParam, FALSE);
812     }
813     if (!hDriver)
814         ERR("Failed to open driver %s from system.ini file, section %s\n", lpDriverName, lpSectionName);
815     else 
816         TRACE("=> %08x\n", hDriver);
817     return hDriver;
818 }
819
820 /**************************************************************************
821  *                              OpenDriverA                     [WINMM.15]
822  * (0,1,DRV_LOAD  ,0       ,0)
823  * (0,1,DRV_ENABLE,0       ,0)
824  * (0,1,DRV_OPEN  ,buf[256],0)
825  */
826 HDRVR WINAPI OpenDriverA(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam) 
827 {
828     HDRVR               hDriver = 0;
829     char                drvName[128];
830
831     TRACE("(%s, %s, 0x%08lx);\n", debugstr_a(lpDriverName), debugstr_a(lpSectionName), lParam);
832     
833     if (lpSectionName == NULL) {
834         lstrcpynA(drvName, lpDriverName, sizeof(drvName));
835         hDriver = DRIVER_TryOpenDriver32(lpDriverName, lParam, TRUE);
836         if (!hDriver) {
837             hDriver = DRIVER_TryOpenDriver16(lpDriverName, lParam, TRUE);
838         }
839         if (!hDriver) {
840             if (GetPrivateProfileStringA("Drivers32", lpDriverName, "", drvName,
841                                          sizeof(drvName), "SYSTEM.INI")) {
842                 hDriver = DRIVER_TryOpenDriver32(drvName, lParam, TRUE);
843                 
844             }
845         }
846         if (!hDriver) {
847             if (GetPrivateProfileStringA("Drivers", lpDriverName, "", drvName,
848                                          sizeof(drvName), "SYSTEM.INI")) {
849                 hDriver = DRIVER_TryOpenDriver16(drvName, lParam, TRUE);
850                 
851             }
852         }
853     } else {
854         if (GetPrivateProfileStringA(lpSectionName, lpDriverName, "", drvName,
855                                      sizeof(drvName), "SYSTEM.INI")) {
856             hDriver = DRIVER_TryOpenDriver32(drvName, lParam, TRUE);
857             if (!hDriver) {
858                 hDriver = DRIVER_TryOpenDriver16(drvName, lParam, TRUE);
859             }
860         }
861     }
862     if (!hDriver)
863         ERR("Failed to open driver %s from system.ini file, section %s\n", lpDriverName, lpSectionName);
864     else 
865         TRACE("=> %08x\n", hDriver);
866     return hDriver;
867 }
868
869 /**************************************************************************
870  *                              OpenDriverW                     [WINMM.15]
871  */
872 HDRVR WINAPI OpenDriverW(LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lParam)
873 {
874     LPSTR               dn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpDriverName);
875     LPSTR               sn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpSectionName);
876     HDRVR               ret = OpenDriverA(dn, sn, lParam);
877     
878     if (dn) HeapFree(GetProcessHeap(), 0, dn);
879     if (sn) HeapFree(GetProcessHeap(), 0, sn);
880     return ret;
881 }
882
883 /**************************************************************************
884  *                      CloseDriver16                           [USER.253]
885  */
886 LRESULT WINAPI CloseDriver16(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
887 {
888     TRACE("(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
889     
890     return DRIVER_CloseDriver(DRIVER_FindFromHDrvr16(hDrvr), lParam1, lParam2);
891 }
892
893 /**************************************************************************
894  *                      CloseDriver                             [WINMM.4]
895  */
896 LRESULT WINAPI CloseDriver(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
897 {
898     TRACE("(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
899     
900     return DRIVER_CloseDriver(DRIVER_FindFromHDrvr(hDrvr), lParam1, lParam2);
901 }
902
903 /**************************************************************************
904  *                              GetDriverModuleHandle   [USER.254]
905  */
906 HMODULE16 WINAPI GetDriverModuleHandle16(HDRVR16 hDrvr)
907 {
908     LPWINE_DRIVER       lpDrv;
909     HMODULE16           hModule = 0;
910     
911     TRACE("(%04x);\n", hDrvr);
912     
913     lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
914     if (lpDrv != NULL && lpDrv->hDriver16 == hDrvr && (lpDrv->dwFlags & WINE_GDF_16BIT)) {
915         hModule = lpDrv->d.d16.hModule;
916     }
917     TRACE("=> %d\n", hModule);
918     return hModule;
919 }
920
921 /**************************************************************************
922  *                              GetDriverFlags          [WINMM.13]
923  * [in] hDrvr handle to the driver
924  *
925  * Returns:
926  *      0x00000000 if hDrvr is an invalid handle
927  *      0x80000000 if hDrvr is a valid 32 bit driver
928  *      0x90000000 if hDrvr is a valid 16 bit driver
929  */
930 DWORD   WINAPI GetDriverFlags(HDRVR hDrvr)
931 {
932     LPWINE_DRIVER       lpDrv;
933     DWORD               ret = 0;
934
935     TRACE("(%04x)\n", hDrvr);
936
937     if ((lpDrv = DRIVER_FindFromHDrvr(hDrvr)) != NULL) {
938         ret = lpDrv->dwFlags;
939     }
940     return ret;
941 }
942
943 /**************************************************************************
944  *                              GetDriverModuleHandle   [WINMM.14]
945  */
946 HMODULE WINAPI GetDriverModuleHandle(HDRVR hDrvr)
947 {
948     LPWINE_DRIVER       lpDrv;
949     HMODULE             hModule = 0;
950     
951     TRACE("(%04x);\n", hDrvr);
952     
953     lpDrv = DRIVER_FindFromHDrvr(hDrvr);
954     if (lpDrv != NULL && !(lpDrv->dwFlags & WINE_GDF_16BIT)) {
955         hModule = lpDrv->d.d32.hModule;
956     }
957     TRACE("=> %d\n", hModule);
958     return hModule;
959 }
960
961 /**************************************************************************
962  *                              DefDriverProc16                 [USER.255]
963  */
964 LRESULT WINAPI DefDriverProc16(DWORD dwDevID, HDRVR16 hDriv, UINT16 wMsg, 
965                                LPARAM lParam1, LPARAM lParam2)
966 {
967     TRACE("devID=0x%08lx hDrv=0x%04x wMsg=%04x lP1=0x%08lx lP2=0x%08lx\n",
968           dwDevID, hDriv, wMsg, lParam1, lParam2);
969
970     switch(wMsg) {
971     case DRV_LOAD:              
972     case DRV_FREE:              
973     case DRV_ENABLE:
974     case DRV_DISABLE:
975         return (LRESULT)1L;
976     case DRV_OPEN:              
977     case DRV_CLOSE:             
978     case DRV_QUERYCONFIGURE:
979         return (LRESULT)0L;
980     case DRV_CONFIGURE:         
981         MessageBoxA(0, "Driver isn't configurable !", "Wine Driver", MB_OK); 
982         return (LRESULT)0L;
983     case DRV_INSTALL:           
984     case DRV_REMOVE:            
985         return DRV_SUCCESS;
986     default:                    
987         return (LRESULT)0L;
988     }
989 }
990
991 /**************************************************************************
992  *                              GetDriverInfo                   [USER.256]
993  */
994 BOOL16 WINAPI GetDriverInfo16(HDRVR16 hDrvr, LPDRIVERINFOSTRUCT16 lpDrvInfo)
995 {
996     LPWINE_DRIVER       lpDrv;
997     BOOL16              ret = FALSE;
998     
999     TRACE("(%04x, %p);\n", hDrvr, lpDrvInfo);
1000     
1001     if (lpDrvInfo == NULL || lpDrvInfo->length != sizeof(DRIVERINFOSTRUCT16)) 
1002         return FALSE;
1003     
1004     lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
1005     if (lpDrv != NULL && lpDrv->hDriver16 == hDrvr && 
1006         (lpDrv->dwFlags & WINE_GDF_16BIT)) {
1007         lpDrvInfo->hDriver = lpDrv->hDriver16;
1008         lpDrvInfo->hModule = lpDrv->d.d16.hModule;
1009         lstrcpynA(lpDrvInfo->szAliasName, lpDrv->szAliasName, sizeof(lpDrvInfo->szAliasName));
1010         ret = TRUE;
1011     }
1012     
1013     return ret;
1014 }
1015
1016 /**************************************************************************
1017  *                              GetNextDriver                   [USER.257]
1018  */
1019 HDRVR16 WINAPI GetNextDriver16(HDRVR16 hDrvr, DWORD dwFlags)
1020 {
1021     HDRVR16             hRetDrv = 0;
1022     LPWINE_DRIVER       lpDrv;
1023     
1024     TRACE("(%04x, %08lX);\n", hDrvr, dwFlags);
1025     
1026     if (hDrvr == 0) {
1027         if (lpDrvItemList == NULL) {
1028             FIXME("drivers list empty !\n");
1029             /* FIXME: code was using DRIVER_LoadStartupDrivers(); before ? 
1030              * I (EPP) don't quite understand this 
1031              */
1032             if (lpDrvItemList == NULL) 
1033                 return 0;
1034         }
1035         lpDrv = lpDrvItemList;
1036         if (dwFlags & GND_REVERSE) {
1037             while (lpDrv->lpNextItem)
1038                 lpDrv = lpDrv->lpNextItem;
1039         }
1040     } else {
1041         lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
1042         if (lpDrv != NULL) {
1043             if (dwFlags & GND_REVERSE) {
1044                 lpDrv = (lpDrv->lpPrevItem) ? lpDrv->lpPrevItem : NULL;
1045             } else {
1046                 lpDrv = (lpDrv->lpNextItem) ? lpDrv->lpNextItem : NULL;
1047             }
1048         }
1049     }
1050     
1051     hRetDrv = (lpDrv) ? lpDrv->hDriver16 : (HDRVR16)0;
1052     TRACE("return %04x !\n", hRetDrv);
1053     return hRetDrv;
1054 }
1055