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