Replaced Wine specific DRIVER_GetType by a correct implementation of
[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 "winuser.h"
14 #include "driver.h"
15 #include "ldt.h"
16 #include "module.h"
17 #include "mmddk.h"
18 #include "debugtools.h"
19
20 DEFAULT_DEBUG_CHANNEL(driver)
21
22 /* The following definitions are WINE internals */
23 /* FIXME: This is a WINE internal struct and should be moved in include/wine directory
24  * Please note that WINE shares 16 and 32 bit drivers on a single list...
25  * Basically, we maintain an external double view on drivers, so that a 16 bit drivers 
26  * can be loaded/used... by 32 functions transparently 
27  */
28
29 /* Who said goofy boy ? */
30 #define WINE_DI_MAGIC   0x900F1B01
31
32 typedef struct tagWINE_DRIVER
33 {
34     DWORD                       dwMagic;
35     char                        szAliasName[128];
36     /* as usual LPWINE_DRIVER == hDriver32 */
37     HDRVR16                     hDriver16;
38     union {
39        struct {
40           HMODULE16             hModule;
41           DRIVERPROC16          lpDrvProc;
42        } d16;
43        struct {
44           HMODULE               hModule;
45           DRIVERPROC            lpDrvProc;
46        } d32;
47     } d;
48     DWORD                       dwDriverID;
49     DWORD                       dwFlags;
50     struct tagWINE_DRIVER*      lpPrevItem;
51     struct tagWINE_DRIVER*      lpNextItem;
52 } WINE_DRIVER, *LPWINE_DRIVER;
53
54 LPWINE_DRIVER   DRIVER_RegisterDriver16(LPCSTR, HMODULE16, DRIVERPROC16, LPARAM, BOOL);
55 LPWINE_DRIVER   DRIVER_RegisterDriver32(LPCSTR, HMODULE,   DRIVERPROC,   LPARAM, BOOL);
56
57 static LPWINE_DRIVER    lpDrvItemList = NULL;
58
59 /* TODO list :
60  *      - LoadModule count and clean up is not handled correctly (it's not a 
61  *        problem as long as FreeLibrary is not working correctly)
62  *      - shoudln't the allocations be done on a per process basis ?
63  *      - split 16/32 bit functions between DLLs as windows do (16 bit in USER, 32 bit in WINMM)
64  */
65
66 /* ### start build ### */
67 extern LONG CALLBACK DRIVER_CallTo16_long_lwwll(FARPROC16,LONG,WORD,WORD,LONG,LONG);
68 /* ### stop build ### */
69
70 /**************************************************************************
71  *                      LoadStartupDrivers                      [internal]
72  */
73 static void WINE_UNUSED DRIVER_LoadStartupDrivers(void)
74 {
75     char        str[256];
76     
77     if (GetPrivateProfileStringA("drivers", NULL, "", str, sizeof(str), "SYSTEM.INI") < 2) {
78         ERR("Can't find drivers section in system.ini\n");
79     } else {
80         HDRVR16 hDrv;
81         LPSTR   ptr;
82
83         for (ptr = str; lstrlenA(ptr) != 0; ptr += lstrlenA(ptr) + 1) {
84             TRACE("str='%s'\n", ptr);
85             hDrv = OpenDriver16(ptr, "drivers", 0L);
86             TRACE("hDrv=%04x\n", hDrv);
87         }
88         TRACE("end of list !\n");
89     }
90 }
91
92 /**************************************************************************
93  *                      DRIVER_GetNumberOfModuleRefs            [internal]
94  *
95  * Returns the number of open drivers which share the same module.
96  */
97 static  WORD    DRIVER_GetNumberOfModuleRefs(LPWINE_DRIVER lpNewDrv)
98 {
99     LPWINE_DRIVER       lpDrv;
100     WORD                count = 0;
101     
102     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
103         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
104             if (lpDrv->d.d16.hModule == lpNewDrv->d.d16.hModule) {
105                 count++;
106             }
107         } else {
108             if (lpDrv->d.d32.hModule == lpNewDrv->d.d32.hModule) {
109                 count++;
110             }
111         }
112     }
113     return count;
114 }
115
116 /**************************************************************************
117  *                              DRIVER_FindFromHDrvr16          [internal]
118  *
119  * From a hDrvr being 16 bits, returns the WINE internal structure.
120  */
121 static  LPWINE_DRIVER   DRIVER_FindFromHDrvr16(HDRVR16 hDrvr)
122 {    
123     LPWINE_DRIVER       lpDrv;
124     
125     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
126         if (lpDrv->hDriver16 == hDrvr) {
127             break;
128         }
129     }
130     return lpDrv;
131 }
132
133 /**************************************************************************
134  *                              DRIVER_FindFromHDrvr            [internal]
135  * 
136  * From a hDrvr (being 16 or 32 bits), returns the WINE internal structure.
137  */
138 static  LPWINE_DRIVER   DRIVER_FindFromHDrvr(HDRVR hDrvr)
139 {    
140     if (!IsBadWritePtr((void*)hDrvr, sizeof(WINE_DRIVER)) && 
141         ((LPWINE_DRIVER)hDrvr)->dwMagic == WINE_DI_MAGIC) {
142         return (LPWINE_DRIVER)hDrvr;
143     }
144     return DRIVER_FindFromHDrvr16(hDrvr);
145 }
146
147 /**************************************************************************
148  *                              DRIVER_MapMsg16To32             [internal]
149  *
150  * Map a 16 bit driver message to a 32 bit driver message.
151  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg16To32
152  *  0 : ok, no memory allocated
153  * -1 : ko, unknown message
154  * -2 : ko, memory problem
155  */
156 static int DRIVER_MapMsg16To32(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
157 {
158     int ret = -1;
159     
160     switch (wMsg) {
161     case DRV_LOAD:
162     case DRV_ENABLE:
163     case DRV_DISABLE:
164     case DRV_FREE:
165     case DRV_QUERYCONFIGURE:
166     case DRV_REMOVE:
167     case DRV_EXITSESSION:
168     case DRV_EXITAPPLICATION:   
169     case DRV_POWER:
170         /* lParam1 and lParam2 are not used */
171         ret = 0;
172         break;
173     case DRV_OPEN:
174     case DRV_CLOSE:
175         /* lParam1 is a NULL terminated string */
176         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
177         if (*lParam1)
178             *lParam1 = (DWORD)PTR_SEG_TO_LIN(*lParam1);
179         if (*lParam2 && wMsg == DRV_OPEN) {
180             LPMCI_OPEN_DRIVER_PARMS16   modp16 = PTR_SEG_TO_LIN(*lParam2);
181             char*                       ptr = HeapAlloc(SystemHeap, 0, sizeof(LPMCI_OPEN_DRIVER_PARMS16) + sizeof(MCI_OPEN_DRIVER_PARMSA));
182             LPMCI_OPEN_DRIVER_PARMSA    modp32;
183             
184             if (ptr) {
185                 *(LPMCI_OPEN_DRIVER_PARMS16*)ptr = modp16;
186                 modp32 = (LPMCI_OPEN_DRIVER_PARMSA)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
187
188                 modp32->wDeviceID = modp16->wDeviceID;
189                 modp32->lpstrParams = PTR_SEG_TO_LIN(modp16->lpstrParams);
190             } else {
191                 return -2;
192             }
193             *lParam2 = (DWORD)modp32;
194         }
195         ret = 1;
196         break;
197     case DRV_CONFIGURE:
198     case DRV_INSTALL:
199         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
200         if (*lParam2) {
201             LPDRVCONFIGINFO     dci32 = HeapAlloc(SystemHeap, 0, sizeof(DRVCONFIGINFO));
202             LPDRVCONFIGINFO16   dci16 = PTR_SEG_TO_LIN(*lParam2);
203             
204             if (dci32) {
205                 dci32->dwDCISize = sizeof(DRVCONFIGINFO);
206                 dci32->lpszDCISectionName = HEAP_strdupAtoW(SystemHeap, 0, PTR_SEG_TO_LIN(dci16->lpszDCISectionName));
207                 dci32->lpszDCIAliasName   = HEAP_strdupAtoW(SystemHeap, 0, PTR_SEG_TO_LIN(dci16->lpszDCIAliasName));
208                 if (dci32->lpszDCISectionName == NULL || dci32->lpszDCIAliasName == NULL)
209                     return -2;
210             } else {
211                 return -2;
212             }
213             *lParam2 = (DWORD)dci32;
214             ret = 1;
215         } else {
216             ret = 0;
217         }
218         break;
219     default:
220         if (wMsg >= 0x800 && wMsg < 0x900) {
221             /* FIXME: another hack to handle MCI messages... 
222              * should find a *NICE* way to integrate DRIVER_ and
223              * MCI_ mapping/unmapping functions
224              */
225             ret = 0;
226         } else {
227            FIXME("Unknown message 0x%04x\n", wMsg);
228         }
229     }
230     return ret;
231 }
232
233 /**************************************************************************
234  *                              DRIVER_MapMsg16To32             [internal]
235  *
236  * UnMap a 16 bit driver message to a 32 bit driver message.
237  *  0 : ok
238  * -1 : ko
239  * -2 : ko, memory problem
240  */
241 static int DRIVER_UnMapMsg16To32(WORD wMsg, DWORD lParam1, DWORD lParam2)
242 {
243     int ret = -1;
244     
245     switch (wMsg) {
246     case DRV_LOAD:
247     case DRV_ENABLE:
248     case DRV_DISABLE:
249     case DRV_FREE:
250     case DRV_QUERYCONFIGURE:
251     case DRV_REMOVE:
252     case DRV_EXITSESSION:
253     case DRV_EXITAPPLICATION:
254     case DRV_POWER:
255         /* lParam1 and lParam2 are not used */
256     case DRV_OPEN:
257     case DRV_CLOSE:
258         /* lParam1 is a NULL terminated string */
259         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
260         if (lParam2 && wMsg == DRV_OPEN) {
261             LPMCI_OPEN_DRIVER_PARMSA    modp32 = (LPMCI_OPEN_DRIVER_PARMSA)lParam2;
262             LPMCI_OPEN_DRIVER_PARMS16   modp16 = *(LPMCI_OPEN_DRIVER_PARMS16*)(lParam2 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
263
264             modp16->wCustomCommandTable = modp32->wCustomCommandTable;
265             modp16->wType = modp32->wType;
266             if (!HeapFree(SystemHeap, 0, modp32))
267                 FIXME("bad free line=%d\n", __LINE__);
268         }
269         ret = 0;
270         break;
271     case DRV_CONFIGURE: 
272     case DRV_INSTALL:
273         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
274         if (lParam2) {
275             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)lParam2;
276             if (!HeapFree(SystemHeap, 0, (LPVOID)dci32->lpszDCISectionName))
277                 FIXME("bad free line=%d\n", __LINE__);
278             if (!HeapFree(SystemHeap, 0, (LPVOID)dci32->lpszDCIAliasName))
279                 FIXME("bad free line=%d\n", __LINE__);
280             if (!HeapFree(SystemHeap, 0, dci32))
281                 FIXME("bad free line=%d\n", __LINE__);
282         }
283         ret = 0;
284         break;
285     default:
286         if (wMsg >= 0x800 && wMsg < 0x900) {
287             /* FIXME: another hack to handle MCI messages... 
288              * should find a *NICE* way to integrate DRIVER_ and
289              * MCI_ mapping/unmapping functions
290              */
291             ret = 0;
292         } else {
293            FIXME("Unknown message 0x%04x\n", wMsg);
294         }       
295     }
296     return ret;
297 }
298
299 /**************************************************************************
300  *                              DRIVER_MapMsg32To16             [internal]
301  *
302  * Map a 32 bit driver message to a 16 bit driver message.
303  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg32To16
304  *  0 : ok, no memory allocated
305  * -1 : ko, unknown message
306  * -2 : ko, memory problem
307  */
308 static int DRIVER_MapMsg32To16(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
309 {
310     int ret = -1;
311     
312     switch (wMsg) {
313     case DRV_LOAD:
314     case DRV_ENABLE:
315     case DRV_DISABLE:
316     case DRV_FREE:
317     case DRV_QUERYCONFIGURE:
318     case DRV_REMOVE:
319     case DRV_EXITSESSION:
320     case DRV_EXITAPPLICATION:   
321     case DRV_POWER:
322         /* lParam1 and lParam2 are not used */
323         ret = 0;
324         break;
325     case DRV_OPEN:
326     case DRV_CLOSE:
327         /* lParam1 is a NULL terminated string */
328         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
329         if (*lParam1) {
330             LPSTR str = SEGPTR_STRDUP((LPSTR)*lParam1);
331             if (str) {
332                 *lParam1 = (LPARAM)SEGPTR_GET(str);
333                 ret = 0;
334             } else {
335                 ret = -2;
336             }
337         } else {
338             ret = 0;
339         }
340         if (*lParam2 && wMsg == DRV_OPEN) {
341             LPMCI_OPEN_DRIVER_PARMS16   modp16;
342             char*                       ptr = SEGPTR_ALLOC(sizeof(LPMCI_OPEN_DRIVER_PARMSA) + sizeof(MCI_OPEN_DRIVER_PARMS16));
343             LPMCI_OPEN_DRIVER_PARMSA    modp32 = (LPMCI_OPEN_DRIVER_PARMSA)(*lParam2);
344             
345             if (ptr) {
346                 *(LPMCI_OPEN_DRIVER_PARMSA*)ptr = modp32;
347                 modp16 = (LPMCI_OPEN_DRIVER_PARMS16)(ptr + sizeof(LPMCI_OPEN_DRIVER_PARMSA));
348
349                 modp16->wDeviceID = modp32->wDeviceID;
350                 modp16->lpstrParams = PTR_SEG_TO_LIN(modp32->lpstrParams);
351             } else {
352                 return -2;
353             }
354             *lParam2 = (DWORD)SEGPTR_GET(modp16);
355             ret = 1;
356         }
357         break;
358     case DRV_CONFIGURE:
359     case DRV_INSTALL:
360         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
361         if (*lParam2) {
362             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)SEGPTR_ALLOC(sizeof(DRVCONFIGINFO16));
363             LPDRVCONFIGINFO     dci32 = (LPDRVCONFIGINFO)(*lParam2);
364             
365             if (dci16) {
366                 LPSTR   str1, str2;
367                 
368                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
369                 
370                 if ((str1 = HEAP_strdupWtoA(SystemHeap, 0, dci32->lpszDCISectionName)) != NULL &&
371                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
372                     dci16->lpszDCISectionName = (LPSTR)SEGPTR_GET(str2);
373                     if (!HeapFree(SystemHeap, 0, str1))
374                         FIXME("bad free line=%d\n", __LINE__);
375                 } else {
376                     return -2;
377                 }
378                 if ((str1 = HEAP_strdupWtoA(SystemHeap, 0, dci32->lpszDCIAliasName)) != NULL &&
379                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
380                     dci16->lpszDCIAliasName = (LPSTR)SEGPTR_GET(str2);
381                     if (!HeapFree(SystemHeap, 0, str1))
382                         FIXME("bad free line=%d\n", __LINE__);
383                 } else {
384                     return -2;
385                 }
386             } else {
387                 return -2;
388             }
389             *lParam2 = (LPARAM)SEGPTR_GET(dci16);
390             ret = 1;
391         } else {
392             ret = 0;
393         }
394         break;
395     default:
396         if (wMsg >= 0x800 && wMsg < 0x900) {
397             /* FIXME: another hack to handle MCI messages... 
398              * should find a *NICE* way to integrate DRIVER_ and
399              * MCI_ mapping/unmapping functions
400              */
401             ret = 0;
402         } else {
403            FIXME("Unknown message 0x%04x\n", wMsg);
404         }       
405     }
406     return ret;
407 }
408
409 /**************************************************************************
410  *                              DRIVER_UnMapMsg32To16           [internal]
411  *
412  * UnMap a 32 bit driver message to a 16 bit driver message.
413  *  0 : ok
414  * -1 : ko
415  * -2 : ko, memory problem
416  */
417 static int DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
418 {
419     int ret = -1;
420     
421     switch (wMsg) {
422     case DRV_LOAD:
423     case DRV_ENABLE:
424     case DRV_DISABLE:
425     case DRV_FREE:
426     case DRV_QUERYCONFIGURE:
427     case DRV_REMOVE:
428     case DRV_EXITSESSION:
429     case DRV_EXITAPPLICATION:
430     case DRV_POWER:
431         /* lParam1 and lParam2 are not used */
432     case DRV_OPEN:
433     case DRV_CLOSE:
434         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
435         /* lParam2 is a pointer to an MCI_OPEN_DRIVER_PARMS for an MCI device */
436         if (lParam1) if (!SEGPTR_FREE(PTR_SEG_TO_LIN(lParam1)))
437             FIXME("bad free line=%d\n", __LINE__);
438
439         if (lParam2 && wMsg == DRV_OPEN) {
440             LPMCI_OPEN_DRIVER_PARMS16   modp16 = (LPMCI_OPEN_DRIVER_PARMS16)PTR_SEG_TO_LIN(lParam2);
441             LPMCI_OPEN_DRIVER_PARMSA    modp32 = *(LPMCI_OPEN_DRIVER_PARMSA*)((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA));
442
443             modp32->wCustomCommandTable = modp16->wCustomCommandTable;
444             modp32->wType = modp16->wType;
445             if (!SEGPTR_FREE((char*)modp16 - sizeof(LPMCI_OPEN_DRIVER_PARMSA)))
446                 FIXME("bad free line=%d\n", __LINE__);
447         }
448         ret = 0;
449         break;
450     case DRV_CONFIGURE: 
451     case DRV_INSTALL:
452         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
453         if (lParam2) {
454             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)PTR_SEG_TO_LIN(lParam2);
455             
456             if (!SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCISectionName)))
457                 FIXME("bad free line=%d\n", __LINE__);
458             if (!SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCIAliasName)))
459                 FIXME("bad free line=%d\n", __LINE__);
460             if (!SEGPTR_FREE(dci16))
461                 FIXME("bad free line=%d\n", __LINE__);
462         }
463         ret = 0;
464         break;
465     default:
466         if (wMsg >= 0x800 && wMsg < 0x900) {
467             /* FIXME: another hack to handle MCI messages... 
468              * should find a *NICE* way to integrate DRIVER_ and
469              * MCI_ mapping/unmapping functions
470              */
471             ret = 0;
472         } else {
473            FIXME("Unknown message 0x%04x\n", wMsg);
474         }
475     }
476     return ret;
477 }
478
479 /**************************************************************************
480  *                              SendDriverMessage               [USER.251]
481  */
482 LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
483                                    LPARAM lParam2)
484 {
485     LPWINE_DRIVER       lpDrv;
486     LRESULT             retval = 0;
487     int                 mapRet;
488     
489     TRACE("(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
490     
491     lpDrv = DRIVER_FindFromHDrvr16(hDriver);
492     if (lpDrv != NULL && lpDrv->hDriver16 == hDriver) {
493         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
494             TRACE("Before CallDriverProc proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
495                   lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);             
496             retval = DRIVER_CallTo16_long_lwwll((FARPROC16)lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, 
497                                                 hDriver, msg, lParam1, lParam2);
498         } else {
499             mapRet = DRIVER_MapMsg16To32(msg, &lParam1, &lParam2);
500             if (mapRet >= 0) {
501                 TRACE("Before func32 call proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
502                       lpDrv->d.d32.lpDrvProc, lpDrv->dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);            
503                 retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, (HDRVR)lpDrv, msg, lParam1, lParam2);
504                 if (mapRet >= 1) {
505                     DRIVER_UnMapMsg16To32(msg, lParam1, lParam2);
506                 }
507             } else {
508                 retval = 0;
509             }
510         }
511     } else {
512         WARN("Bad driver handle %u\n", hDriver);
513     }
514     
515     TRACE("retval = %ld\n", retval);
516     return retval;
517 }
518
519 /**************************************************************************
520  *                              SendDriverMessage               [WINMM.19]
521  */
522 LRESULT WINAPI SendDriverMessage(HDRVR hDriver, UINT msg, LPARAM lParam1,
523                                  LPARAM lParam2)
524 {
525     LPWINE_DRIVER       lpDrv;
526     LRESULT             retval = 0;
527     int                 mapRet;
528     
529     TRACE("(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
530     
531     lpDrv = DRIVER_FindFromHDrvr(hDriver);
532
533     if (lpDrv != NULL) {
534         if (lpDrv->dwFlags & WINE_GDF_16BIT) {
535             mapRet = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2);
536             if (mapRet >= 0) {
537                 TRACE("Before CallDriverProc proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
538                       lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, lpDrv->hDriver16, msg, lParam1, lParam2);                
539                 retval = DRIVER_CallTo16_long_lwwll((FARPROC16)lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, 
540                                                     lpDrv->hDriver16, msg, lParam1, lParam2);
541                 if (mapRet >= 1) {
542                     DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
543                 }
544             } else {
545                 retval = 0;
546             }
547         } else {
548             TRACE("Before func32 call proc=%p driverID=%08lx hDrv=%u wMsg=%04x p1=%08lx p2=%08lx\n", 
549                   lpDrv->d.d32.lpDrvProc, lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);             
550             retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);
551         }
552     } else {
553         WARN("Bad driver handle %u\n", hDriver);
554     }
555     TRACE("retval = %ld\n", retval);
556     
557     return retval;
558 }
559
560 /**************************************************************************
561  *                              DRIVER_RemoveFromList           [internal]
562  *
563  * Generates all the logic to handle driver closure / deletion
564  * Removes a driver struct to the list of open drivers.
565  */
566 static  BOOL    DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv)
567 {
568     lpDrv->dwDriverID = 0;
569     if (DRIVER_GetNumberOfModuleRefs(lpDrv) == 1) {
570         SendDriverMessage((HDRVR)lpDrv, DRV_DISABLE, 0L, 0L);
571         SendDriverMessage((HDRVR)lpDrv, DRV_FREE,    0L, 0L);
572     }
573     
574     if (lpDrv->lpPrevItem)
575         lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem;
576     else
577         lpDrvItemList = lpDrv->lpNextItem;
578     if (lpDrv->lpNextItem)
579         lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
580
581     return TRUE;
582 }
583
584 /**************************************************************************
585  *                              DRIVER_AddToList                [internal]
586  *
587  * Adds a driver struct to the list of open drivers.
588  * Generates all the logic to handle driver creation / open.
589  */
590 static  BOOL    DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam, BOOL bCallFrom32)
591 {
592     lpNewDrv->dwMagic = WINE_DI_MAGIC;
593     /* First driver to be loaded for this module, need to load correctly the module */
594     if (DRIVER_GetNumberOfModuleRefs(lpNewDrv) == 0) {
595         if (SendDriverMessage((HDRVR)lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
596             TRACE("DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
597             return FALSE;
598         }
599         if (SendDriverMessage((HDRVR)lpNewDrv, DRV_ENABLE, 0L, 0L) != DRV_SUCCESS) {
600             TRACE("DRV_ENABLE failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
601             return FALSE;
602         }
603     }
604
605     lpNewDrv->lpNextItem = NULL;
606     if (lpDrvItemList == NULL) {
607         lpDrvItemList = lpNewDrv;
608         lpNewDrv->lpPrevItem = NULL;
609     } else {
610         LPWINE_DRIVER   lpDrv = lpDrvItemList;  /* find end of list */
611         while (lpDrv->lpNextItem != NULL)
612             lpDrv = lpDrv->lpNextItem;
613         
614         lpDrv->lpNextItem = lpNewDrv;
615         lpNewDrv->lpPrevItem = lpDrv;
616     }
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()
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(SystemHeap, 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(SystemHeap, 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(SystemHeap, 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(SystemHeap, 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(SystemHeap, 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 (lstrlenA(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)WIN32_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 (lstrlenA(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 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', %08lX);\n", lpDriverName, 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 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