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