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