Some more recursive include fixes/optimizations.
[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 "wine/winuser16.h"
12 #include "heap.h"
13 #include "callback.h"
14 #include "driver.h"
15 #include "ldt.h"
16 #include "module.h"
17 #include "debug.h"
18 #include <string.h>
19
20 static LPWINE_DRIVER    lpDrvItemList = NULL;
21
22 /* TODO list :
23  *      - LoadModule count and clean up is not handled correctly (it's not a problem as 
24  *        long as FreeLibrary is not working correctly 
25  *      - msacm has some FIXME related to new code here...
26  */
27
28 /**************************************************************************
29  *                      LoadStartupDrivers                      [internal]
30  */
31 static void DRIVER_LoadStartupDrivers(void)
32 {
33     HDRVR16     hDrv;
34     char        str[256];
35     LPSTR       ptr;
36
37     if (GetPrivateProfileString32A("drivers", NULL, "", str, sizeof(str), "SYSTEM.INI") < 2) {
38         ERR(driver,"Can't find drivers section in system.ini\n");
39         return;
40     }
41
42     for (ptr = str; lstrlen32A(ptr) != 0; ptr += lstrlen32A(ptr) + 1) {
43         TRACE(driver, "str='%s'\n", ptr);
44         hDrv = OpenDriver16(ptr, "drivers", 0L);
45         TRACE(driver, "hDrv=%04x\n", hDrv);
46     }
47     TRACE(driver, "end of list !\n");
48     return;
49 }
50
51 /**************************************************************************
52  *                      DRIVER_GetNumberOfModuleRefs            [internal]
53  *
54  * Returns the number of open drivers which share the same module.
55  */
56 static  WORD    DRIVER_GetNumberOfModuleRefs(LPWINE_DRIVER lpNewDrv)
57 {
58     LPWINE_DRIVER       lpDrv;
59     DWORD               type = lpNewDrv->dwFlags & WINE_DI_TYPE_MASK;
60     WORD                count = 0;
61     
62     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
63         if ((lpDrv->dwFlags & WINE_DI_TYPE_MASK) == type) {
64             switch (type) {
65             case WINE_DI_TYPE_16:
66                 if (lpDrv->d.d16.hModule == lpNewDrv->d.d16.hModule)
67                     count++;
68                 break;
69             case WINE_DI_TYPE_32:
70                 if (lpDrv->d.d32.hModule == lpNewDrv->d.d32.hModule)
71                     count++;
72                 break;
73             default:
74                 FIXME(driver, "Unsupported driver type: %ld\n", type);
75                 break;
76             }
77         }
78     }
79     return count;
80 }
81
82 static  LPWINE_DRIVER   DRIVER_FindFromHDrvr16(HDRVR16 hDrvr)
83 {    
84     LPWINE_DRIVER       lpDrv;
85     
86     for (lpDrv = lpDrvItemList; lpDrv; lpDrv = lpDrv->lpNextItem) {
87         if (lpDrv->hDriver16 == hDrvr) {
88             return lpDrv;
89         }
90     }
91     return NULL;
92 }
93
94 /**************************************************************************
95  *                              DRIVER_MapMsg16To32             [internal]
96  *
97  * Map a 16 bit driver message to a 32 bit driver message.
98  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg16To32
99  *  0 : ok, no memory allocated
100  * -1 : ko, unknown message
101  * -2 : ko, memory problem
102  */
103 int     DRIVER_MapMsg16To32(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
104 {
105     int ret = -1;
106
107     switch (wMsg) {
108     case DRV_LOAD:
109     case DRV_ENABLE:
110     case DRV_DISABLE:
111     case DRV_FREE:
112     case DRV_QUERYCONFIGURE:
113     case DRV_REMOVE:
114     case DRV_EXITSESSION:
115     case DRV_EXITAPPLICATION:   
116     case DRV_POWER:
117         /* lParam1 and lParam2 are not used */
118         ret = 0;
119         break;
120     case DRV_OPEN:
121     case DRV_CLOSE:
122         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
123         if (*lParam1)
124             *lParam1 = (DWORD)PTR_SEG_TO_LIN(*lParam1);
125         ret = 0;
126         break;
127     case DRV_CONFIGURE:
128     case DRV_INSTALL:
129         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
130         if (*lParam2) {
131             LPDRVCONFIGINFO32   dci32 = HeapAlloc(SystemHeap, 0, sizeof(DRVCONFIGINFO32));
132             LPDRVCONFIGINFO16   dci16 = PTR_SEG_TO_LIN(*lParam2);
133
134             if (dci32) {
135                 dci32->dwDCISize = sizeof(DRVCONFIGINFO32);
136                 dci32->lpszDCISectionName = HEAP_strdupAtoW(SystemHeap, 0, PTR_SEG_TO_LIN(dci16->lpszDCISectionName));
137                 dci32->lpszDCIAliasName   = HEAP_strdupAtoW(SystemHeap, 0, PTR_SEG_TO_LIN(dci16->lpszDCIAliasName));
138                 if (dci32->lpszDCISectionName == NULL || dci32->lpszDCIAliasName == NULL)
139                     return -2;
140             } else {
141                 return -2;
142             }
143             *lParam2 = (DWORD)dci32;
144             ret = 1;
145         } else {
146             ret = 0;
147         }
148         break;
149     default:
150         FIXME(driver, "Unknown message 0x%04x\n", wMsg);
151     }
152     return ret;
153 }
154
155 /**************************************************************************
156  *                              DRIVER_MapMsg16To32             [internal]
157  *
158  * UnMap a 16 bit driver message to a 32 bit driver message.
159  *  0 : ok
160  * -1 : ko
161  * -2 : ko, memory problem
162  */
163 int     DRIVER_UnMapMsg16To32(WORD wMsg, DWORD lParam1, DWORD lParam2)
164 {
165     int ret = -1;
166
167     switch (wMsg) {
168     case DRV_LOAD:
169     case DRV_ENABLE:
170     case DRV_DISABLE:
171     case DRV_FREE:
172     case DRV_QUERYCONFIGURE:
173     case DRV_REMOVE:
174     case DRV_EXITSESSION:
175     case DRV_EXITAPPLICATION:
176     case DRV_POWER:
177         /* lParam1 and lParam2 are not used */
178     case DRV_OPEN:
179     case DRV_CLOSE:
180         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
181         ret = 0;
182         break;
183     case DRV_CONFIGURE: 
184     case DRV_INSTALL:
185         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
186         if (lParam2) {
187             LPDRVCONFIGINFO32   dci32 = (LPDRVCONFIGINFO32)lParam2;
188             HeapFree(SystemHeap, 0, (LPVOID)dci32->lpszDCISectionName);
189             HeapFree(SystemHeap, 0, (LPVOID)dci32->lpszDCIAliasName);
190             HeapFree(SystemHeap, 0, dci32);
191         }
192         ret = 0;
193         break;
194     default:
195         FIXME(driver, "Unknown message 0x%04x\n", wMsg);
196     }
197     return ret;
198 }
199
200 /**************************************************************************
201  *                              DRIVER_MapMsg32To16             [internal]
202  *
203  * Map a 32 bit driver message to a 16 bit driver message.
204  *  1 : ok, some memory allocated, need to call DRIVER_UnMapMsg32To16
205  *  0 : ok, no memory allocated
206  * -1 : ko, unknown message
207  * -2 : ko, memory problem
208  */
209 int     DRIVER_MapMsg32To16(WORD wMsg, DWORD* lParam1, DWORD* lParam2)
210 {
211     int ret = -1;
212
213     switch (wMsg) {
214     case DRV_LOAD:
215     case DRV_ENABLE:
216     case DRV_DISABLE:
217     case DRV_FREE:
218     case DRV_QUERYCONFIGURE:
219     case DRV_REMOVE:
220     case DRV_EXITSESSION:
221     case DRV_EXITAPPLICATION:   
222     case DRV_POWER:
223         /* lParam1 and lParam2 are not used */
224         ret = 0;
225         break;
226     case DRV_OPEN:
227     case DRV_CLOSE:
228         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
229         if (*lParam1) {
230             LPSTR str = SEGPTR_STRDUP((LPSTR)*lParam1);
231             if (str) {
232                 *lParam1 = (LPARAM)SEGPTR_GET(str);
233                 ret = 0;
234             } else {
235                 ret = -2;
236             }
237         } else {
238             ret = 0;
239         }
240         break;
241     case DRV_CONFIGURE:
242     case DRV_INSTALL:
243         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO */
244         if (*lParam2) {
245             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)SEGPTR_ALLOC(sizeof(DRVCONFIGINFO16));
246             LPDRVCONFIGINFO32   dci32 = (LPDRVCONFIGINFO32)lParam2;
247
248             if (dci16) {
249                 LPSTR   str1, str2;
250
251                 dci16->dwDCISize = sizeof(DRVCONFIGINFO16);
252
253                 if ((str1 = HEAP_strdupWtoA(SystemHeap, 0, dci32->lpszDCISectionName)) != NULL &&
254                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
255                     dci16->lpszDCISectionName = (LPSTR)SEGPTR_GET(str2);
256                     HeapFree(SystemHeap, 0, str1);
257                 } else {
258                     return -2;
259                 }
260                 if ((str1 = HEAP_strdupWtoA(SystemHeap, 0, dci32->lpszDCIAliasName)) != NULL &&
261                     (str2 = SEGPTR_STRDUP(str1)) != NULL) {
262                     dci16->lpszDCIAliasName = (LPSTR)SEGPTR_GET(str2);
263                     HeapFree(SystemHeap, 0, str1);
264                 } else {
265                     return -2;
266                 }
267             } else {
268                 return -2;
269             }
270             *lParam2 = (LPARAM)SEGPTR_GET(dci16);
271             ret = 1;
272         } else {
273             ret = 0;
274         }
275         break;
276     default:
277         FIXME(driver, "Unknown message 0x%04x\n", wMsg);
278     }
279     return ret;
280 }
281
282 /**************************************************************************
283  *                              DRIVER_MapMsg32To16             [internal]
284  *
285  * UnMap a 32 bit driver message to a 16 bit driver message.
286  *  0 : ok
287  * -1 : ko
288  * -2 : ko, memory problem
289  */
290 int     DRIVER_UnMapMsg32To16(WORD wMsg, DWORD lParam1, DWORD lParam2)
291 {
292     int ret = -1;
293
294     switch (wMsg) {
295     case DRV_LOAD:
296     case DRV_ENABLE:
297     case DRV_DISABLE:
298     case DRV_FREE:
299     case DRV_QUERYCONFIGURE:
300     case DRV_REMOVE:
301     case DRV_EXITSESSION:
302     case DRV_EXITAPPLICATION:
303     case DRV_POWER:
304         /* lParam1 and lParam2 are not used */
305     case DRV_OPEN:
306     case DRV_CLOSE:
307         /* lParam1 is a NULL terminated string, lParam2 is unknown => may lead to some problem */
308         if (lParam1) SEGPTR_FREE(PTR_SEG_TO_LIN(lParam1));
309         ret = 0;
310         break;
311     case DRV_CONFIGURE: 
312     case DRV_INSTALL:
313         /* lParam1 is a handle to a window (or not used), lParam2 is a pointer to DRVCONFIGINFO, lParam2 */
314         if (lParam2) {
315             LPDRVCONFIGINFO16   dci16 = (LPDRVCONFIGINFO16)PTR_SEG_TO_LIN(lParam2);
316
317             SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCISectionName));
318             SEGPTR_FREE(PTR_SEG_TO_LIN(dci16->lpszDCIAliasName));
319             SEGPTR_FREE(dci16);
320         }
321         ret = 0;
322         break;
323     default:
324         FIXME(driver, "Unknown message 0x%04x\n", wMsg);
325     }
326     return ret;
327 }
328
329 /**************************************************************************
330  *                              SendDriverMessage               [USER.251]
331  */
332 LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
333                                    LPARAM lParam2)
334 {
335     LPWINE_DRIVER       lpDrv;
336     LRESULT             retval = 0;
337     int                 mapRet;
338
339     TRACE(driver, "(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
340
341     lpDrv = (LPWINE_DRIVER)DRIVER_FindFromHDrvr16(hDriver);
342     if (lpDrv != NULL && lpDrv->hDriver16 == hDriver) {
343         switch (lpDrv->dwFlags & WINE_DI_TYPE_MASK) {
344         case WINE_DI_TYPE_16:
345             retval = Callbacks->CallDriverProc(lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, hDriver, 
346                                                msg, lParam1, lParam2);
347             break;
348         case WINE_DI_TYPE_32:
349             mapRet = DRIVER_MapMsg16To32(msg, &lParam1, &lParam2);
350             if (mapRet >= 0) {
351                 retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);
352                 if (mapRet > 1) {
353                     DRIVER_UnMapMsg16To32(msg, lParam1, lParam2);
354                 }
355             } else {
356                 retval = 0;
357             }
358             break;
359         default:
360             FIXME(driver, "Unknown driver type %08lx\n", lpDrv->dwFlags);
361             break;
362         }
363     }
364
365     TRACE(driver, "retval = %ld\n", retval);
366     return retval;
367 }
368
369 /**************************************************************************
370  *                              SendDriverMessage               [WINMM.19]
371  */
372 LRESULT WINAPI SendDriverMessage32(HDRVR32 hDriver, UINT32 msg, LPARAM lParam1,
373                                    LPARAM lParam2)
374 {
375     LPWINE_DRIVER       lpDrv = (LPWINE_DRIVER)hDriver;
376     LRESULT             retval = 0;
377     int                 mapRet;
378
379     TRACE(driver, "(%04x, %04X, %08lX, %08lX)\n", hDriver, msg, lParam1, lParam2);
380
381     if (lpDrv != NULL) {
382         switch (lpDrv->dwFlags & WINE_DI_TYPE_MASK) {
383         case WINE_DI_TYPE_16:
384             mapRet = DRIVER_MapMsg32To16(msg, &lParam1, &lParam2);
385             if (mapRet >= 0) {
386                 retval = Callbacks->CallDriverProc(lpDrv->d.d16.lpDrvProc, lpDrv->dwDriverID, hDriver, 
387                                                    msg, lParam1, lParam2);
388                 if (mapRet > 1) {
389                     DRIVER_UnMapMsg32To16(msg, lParam1, lParam2);
390                 }
391             } else {
392                 retval = 0;
393             }
394             break;
395         case WINE_DI_TYPE_32:
396             retval = lpDrv->d.d32.lpDrvProc(lpDrv->dwDriverID, hDriver, msg, lParam1, lParam2);
397             break;
398         default:
399             FIXME(driver, "Unknown driver type %08lx\n", lpDrv->dwFlags);
400             break;
401         }
402     }
403     TRACE(driver, "retval = %ld\n", retval);
404
405     return retval;
406 }
407
408 /**************************************************************************
409  *                              DRIVER_AddToList                [internal]
410  *
411  * Adds a driver struct to the list of open drivers.
412  * Generates all the logic to handle driver creation / open.
413  */
414 static  BOOL32  DRIVER_AddToList(LPWINE_DRIVER lpNewDrv, LPARAM lParam)
415 {
416     /* First driver to be loaded for this module, need to load correctly the module */
417     if (DRIVER_GetNumberOfModuleRefs(lpNewDrv) == 0) {
418         if (SendDriverMessage32((HDRVR32)lpNewDrv, DRV_LOAD,   0L, 0L) != DRV_SUCCESS) {
419             TRACE(driver, "DRV_LOAD failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
420             return FALSE;
421         }
422         if (SendDriverMessage32((HDRVR32)lpNewDrv, DRV_ENABLE, 0L, 0L) != DRV_SUCCESS) {
423             TRACE(driver, "DRV_ENABLE failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
424             return FALSE;
425         }
426     }
427     /* Now just open a new instance of a driver on this module */
428     /* Handle of this lParam is rather touchy :
429      * + we know here if it comes from 16 or 32 bit from lpDrv->dwFlags
430      * + but we don't know its content...
431      * + and we send it through SendDriverMessage32 as a 32 bit value...
432      * => so we might have trouble with this little guy (FIXME ???)
433      */
434     lpNewDrv->dwDriverID = SendDriverMessage32((HDRVR32)lpNewDrv, DRV_OPEN, (DWORD)lpNewDrv->szAliasName, lParam);
435     if (lpNewDrv->dwDriverID == 0) {
436         TRACE(driver, "DRV_OPEN failed on driver 0x%08lx\n", (DWORD)lpNewDrv);
437         return FALSE;
438     }
439
440     lpNewDrv->lpNextItem = NULL;
441     if (lpDrvItemList == NULL) {
442         lpDrvItemList = lpNewDrv;
443         lpNewDrv->lpPrevItem = NULL;
444     } else {
445         LPWINE_DRIVER   lpDrv = lpDrvItemList;  /* find end of list */
446         while (lpDrv->lpNextItem != NULL)
447             lpDrv = lpDrv->lpNextItem;
448
449         lpDrv->lpNextItem = lpNewDrv;
450         lpNewDrv->lpPrevItem = lpDrv;
451     }
452     return TRUE;
453 }
454
455 /**************************************************************************
456  *                              DRIVER_RemoveFromList           [internal]
457  *
458  * Generates all the logic to handle driver closure / deletion
459  * Removes a driver struct to the list of open drivers.
460  */
461 static  BOOL32  DRIVER_RemoveFromList(LPWINE_DRIVER lpDrv, LPARAM lParam1, LPARAM lParam2)
462 {
463     SendDriverMessage32((HDRVR32)lpDrv, DRV_CLOSE, lParam1, lParam2);
464
465     lpDrv->dwDriverID = 0;
466     if (DRIVER_GetNumberOfModuleRefs(lpDrv) == 1) {
467         SendDriverMessage16((HDRVR32)lpDrv, DRV_DISABLE, 0L, 0L);
468         SendDriverMessage16((HDRVR32)lpDrv, DRV_FREE,    0L, 0L);
469
470         if (lpDrv->lpPrevItem)
471             lpDrv->lpPrevItem->lpNextItem = lpDrv->lpNextItem;
472         else
473             lpDrvItemList = lpDrv->lpNextItem;
474         if (lpDrv->lpNextItem)
475             lpDrv->lpNextItem->lpPrevItem = lpDrv->lpPrevItem;
476     }
477     return TRUE;
478 }
479
480 static  HDRVR16 DRIVER_CreateDrvr16()
481 {
482     static      WORD    DRIVER_hDrvr16Counter = 0;
483
484     while (DRIVER_FindFromHDrvr16(++DRIVER_hDrvr16Counter));
485     return DRIVER_hDrvr16Counter;
486 }
487
488 /**************************************************************************
489  *                              DRIVER_RegisterDriver16         [internal]
490  *
491  * Creates all the WINE internal representations for a 16 bit driver.
492  * The driver is also open by sending the correct messages.
493  */
494 LPWINE_DRIVER DRIVER_RegisterDriver16(LPCSTR lpName, HMODULE16 hModule, DRIVERPROC16 lpProc, LPARAM lParam)
495 {
496     LPWINE_DRIVER       lpDrv;
497
498     lpDrv = HeapAlloc(SystemHeap, 0, sizeof(WINE_DRIVER));
499     if (lpDrv != NULL) {
500         lpDrv->dwFlags         = WINE_DI_TYPE_16;
501         lpDrv->dwDriverID      = 0;
502         lpDrv->hDriver16       = DRIVER_CreateDrvr16();
503         strncpy(lpDrv->szAliasName, lpName, sizeof(lpDrv->szAliasName));
504         lpDrv->d.d16.hModule   = hModule;
505         lpDrv->d.d16.lpDrvProc = lpProc;
506         
507         if (!DRIVER_AddToList(lpDrv, lParam)) {
508             HeapFree(SystemHeap, 0, lpDrv);
509             lpDrv = NULL;
510         }
511     }
512     return lpDrv;
513 }
514
515 /**************************************************************************
516  *                              DRIVER_RegisterDriver32         [internal]
517  *
518  * Creates all the WINE internal representations for a 32 bit driver.
519  * The driver is also open by sending the correct messages.
520  */
521 LPWINE_DRIVER DRIVER_RegisterDriver32(LPCSTR lpName, HMODULE32 hModule, DRIVERPROC32 lpProc, LPARAM lParam)
522 {
523     LPWINE_DRIVER       lpDrv;
524
525     lpDrv = HeapAlloc(SystemHeap, 0, sizeof(WINE_DRIVER));
526     if (lpDrv != NULL) {
527         lpDrv->dwFlags          = WINE_DI_TYPE_32;
528         lpDrv->dwDriverID       = 0;
529         lpDrv->hDriver16        = DRIVER_CreateDrvr16();
530         strncpy(lpDrv->szAliasName, lpName, sizeof(lpDrv->szAliasName));
531         lpDrv->d.d32.hModule    = hModule;
532         lpDrv->d.d32.lpDrvProc  = lpProc;
533         
534         if (!DRIVER_AddToList(lpDrv, lParam)) {
535             HeapFree(SystemHeap, 0, lpDrv);
536             lpDrv = NULL;
537         }
538     }
539     return lpDrv;
540 }
541
542 /**************************************************************************
543  *                              DRIVER_TryOpenDriver32          [internal]
544  *
545  * Tries to load a 16 bit driver whose DLL's (module) name is lpFileName.
546  */
547 static  HDRVR16 DRIVER_TryOpenDriver16(LPCSTR lpFileName, LPARAM lParam)
548 {
549     LPWINE_DRIVER       lpDrv = NULL;
550     LPCSTR              lpSFN;
551     HMODULE16           hModule;
552     DRIVERPROC16        lpProc;
553
554     TRACE(driver,"('%s', %08lX);\n", lpFileName, lParam);
555
556     if (lstrlen32A(lpFileName) < 1) 
557         return 0;
558
559     lpSFN = strrchr(lpFileName, '\\');
560     lpSFN = (lpSFN) ? (lpSFN + 1) : lpFileName;
561
562     if ((hModule = LoadModule16(lpFileName, (LPVOID)-1)) != 0) {
563         if ((lpProc = (DRIVERPROC16)WIN32_GetProcAddress16(hModule, "DRIVERPROC")) != NULL) {
564             lpDrv = DRIVER_RegisterDriver16(lpSFN, hModule, lpProc, lParam);
565         } else {
566             TRACE(driver, "No DriverProc found\n");
567         }
568     } else {
569         TRACE(driver, "Unable to load module (%s)\n", lpFileName);
570     }
571     return lpDrv ? lpDrv->hDriver16 : 0;
572 }
573
574 /**************************************************************************
575  *                              DRIVER_TryOpenDriver32          [internal]
576  *
577  * Tries to load a 32 bit driver whose DLL's (module) name is lpFileName.
578  */
579 static  HDRVR32 DRIVER_TryOpenDriver32(LPCSTR lpFileName, LPARAM lParam)
580 {
581     LPWINE_DRIVER       lpDrv = NULL;
582     LPCSTR              lpSFN;
583     HMODULE32           hModule;
584     DRIVERPROC32        lpProc;
585
586     TRACE(driver,"('%s', %08lX);\n", lpFileName, lParam);
587
588     if (lstrlen32A(lpFileName) < 1) 
589         return 0;
590
591     lpSFN = strrchr(lpFileName, '\\');
592     lpSFN = (lpSFN) ? (lpSFN + 1) : lpFileName;
593
594     if ((hModule = LoadLibrary32A(lpFileName)) != 0) {
595         if ((lpProc = GetProcAddress32(hModule, "DriverProc")) != NULL) {
596             lpDrv = DRIVER_RegisterDriver32(lpSFN, hModule, lpProc, lParam);
597         } else {
598             TRACE(driver, "No DriverProc found\n");
599         }
600     } else {
601         TRACE(driver, "Unable to load module (%s)\n", lpFileName);
602     }
603     return (HDRVR32)lpDrv;
604 }
605
606 /**************************************************************************
607  *                              OpenDriver16                    [USER.252]
608  */
609 HDRVR16 WINAPI OpenDriver16(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam)
610 {
611     HDRVR16             hDriver = 0;
612     char                drvName[128];
613
614     TRACE(driver,"('%s', '%s', %08lX);\n", lpDriverName, lpSectionName, lParam);
615
616     if (lpSectionName == NULL) {
617         hDriver = DRIVER_TryOpenDriver16(lpDriverName, lParam);
618         if (!hDriver) {
619             /* in case hDriver is NULL, search in Drivers32 section */
620             lpSectionName = "Drivers";
621         }
622     }
623     if (!hDriver && GetPrivateProfileString32A(lpSectionName, lpDriverName, "", 
624                                                drvName, sizeof(drvName), "SYSTEM.INI") > 0) {
625         hDriver = DRIVER_TryOpenDriver16(drvName, lParam);
626     }
627     return hDriver;
628 }
629
630 /**************************************************************************
631  *                              OpenDriver32A                   [WINMM.15]
632  * (0,1,DRV_LOAD  ,0       ,0)
633  * (0,1,DRV_ENABLE,0       ,0)
634  * (0,1,DRV_OPEN  ,buf[256],0)
635  */
636 HDRVR32 WINAPI OpenDriver32A(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam) 
637 {
638     HDRVR32             hDriver = 0;
639     char                drvName[128];
640
641     TRACE(driver,"('%s', '%s', %08lX);\n", lpDriverName, lpSectionName, lParam);
642  
643     if (lpSectionName == NULL) {
644         strncpy(drvName, lpDriverName, sizeof(drvName));
645         hDriver = DRIVER_TryOpenDriver32(lpDriverName, lParam);
646         if (!hDriver) {
647             /* FIXME what has to be done on lParam ?? */
648             hDriver = DRIVER_TryOpenDriver16(lpDriverName, lParam);
649         }
650         if (!hDriver) {
651             if (GetPrivateProfileString32A("Drivers32", lpDriverName, "", drvName,
652                                            sizeof(drvName), "SYSTEM.INI")) {
653                 hDriver = DRIVER_TryOpenDriver32(drvName, lParam);
654                 
655             }
656         }
657         if (!hDriver) {
658             if (GetPrivateProfileString32A("Drivers", lpDriverName, "", drvName,
659                                            sizeof(drvName), "SYSTEM.INI")) {
660                 hDriver = DRIVER_TryOpenDriver16(drvName, lParam);
661                 
662             }
663         }
664     } else {
665         if (GetPrivateProfileString32A(lpSectionName, lpDriverName, "", drvName,
666                                        sizeof(drvName), "SYSTEM.INI")) {
667             hDriver = DRIVER_TryOpenDriver32(drvName, lParam);
668         }
669     }
670
671     TRACE(driver, "retval='%08x'\n", hDriver);
672     return hDriver;
673 }
674
675 /**************************************************************************
676  *                              OpenDriver32W                   [WINMM.15]
677  */
678 HDRVR32 WINAPI OpenDriver32W(LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lParam)
679 {
680     LPSTR       dn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpDriverName);
681     LPSTR       sn = HEAP_strdupWtoA(GetProcessHeap(), 0, lpSectionName);
682     HDRVR32     ret = OpenDriver32A(dn, sn, lParam);
683
684     if (dn) HeapFree(GetProcessHeap(), 0, dn);
685     if (sn) HeapFree(GetProcessHeap(), 0, sn);
686     return ret;
687 }
688
689 /**************************************************************************
690  *                      CloseDriver                             [USER.253]
691  */
692 LRESULT WINAPI CloseDriver16(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
693 {
694     LPWINE_DRIVER lpDrv;
695
696     TRACE(driver, "(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
697
698     lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
699     if (lpDrv != NULL && lpDrv->hDriver16 == hDrvr) {
700         if (DRIVER_RemoveFromList(lpDrv, lParam1, lParam2)) {
701             TRACE(driver, "hDrvr=%04x closed !\n", hDrvr);
702             return TRUE;
703         }
704     }
705     return FALSE;
706 }
707 /**************************************************************************
708  *                      CloseDriver32                           [WINMM.4]
709  */
710 LRESULT WINAPI CloseDriver32(HDRVR32 hDrvr, LPARAM lParam1, LPARAM lParam2)
711 {
712     LPWINE_DRIVER lpDrv;
713
714     TRACE(driver, "(%04x, %08lX, %08lX);\n", hDrvr, lParam1, lParam2);
715
716     lpDrv = (LPWINE_DRIVER)hDrvr;
717     if (lpDrv != NULL) {
718         if (DRIVER_RemoveFromList(lpDrv, lParam1, lParam2)) {
719             TRACE(driver, "hDrvr=%08x closed !\n", hDrvr);
720             return TRUE;
721         }
722     }
723     return FALSE;
724 }
725
726 /**************************************************************************
727  *                              GetDriverModuleHandle   [USER.254]
728  */
729 HMODULE16 WINAPI GetDriverModuleHandle16(HDRVR16 hDrvr)
730 {
731     LPWINE_DRIVER       lpDrv;
732     HMODULE16           hModule = 0;
733
734     TRACE(driver, "(%04x);\n", hDrvr);
735
736     lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
737     if (lpDrv != NULL && lpDrv->hDriver16 == hDrvr && 
738         (lpDrv->dwFlags & WINE_DI_TYPE_MASK) == WINE_DI_TYPE_16) {
739         hModule = lpDrv->d.d16.hModule;
740     }
741     return hModule;
742 }
743
744 /**************************************************************************
745  *                              GetDriverModuleHandle   [USER.254]
746  */
747 HMODULE32 WINAPI GetDriverModuleHandle32(HDRVR32 hDrvr)
748 {
749     LPWINE_DRIVER       lpDrv = (LPWINE_DRIVER)hDrvr;
750     HMODULE32           hModule = 0;
751
752     TRACE(driver, "(%04x);\n", hDrvr);
753
754     if (lpDrv != NULL && (lpDrv->dwFlags & WINE_DI_TYPE_MASK) == WINE_DI_TYPE_32) {
755         hModule = lpDrv->d.d32.hModule;
756     }
757     return hModule;
758 }
759
760 /**************************************************************************
761  *                              DefDriverProc16                 [USER.255]
762  */
763 LRESULT WINAPI DefDriverProc16(DWORD dwDevID, HDRVR16 hDriv, UINT16 wMsg, 
764                                LPARAM lParam1, LPARAM lParam2)
765 {
766     switch(wMsg) {
767     case DRV_LOAD:              return (LRESULT)0L;
768     case DRV_FREE:              return (LRESULT)0L;
769     case DRV_OPEN:              return (LRESULT)0L;
770     case DRV_CLOSE:             return (LRESULT)0L;
771     case DRV_ENABLE:            return (LRESULT)0L;
772     case DRV_DISABLE:           return (LRESULT)0L;
773     case DRV_QUERYCONFIGURE:    return (LRESULT)0L;
774     case DRV_CONFIGURE:         MessageBox32A(0, "Driver isn't configurable !", "Wine Driver", MB_OK); return (LRESULT)0L;
775     case DRV_INSTALL:           return (LRESULT)DRVCNF_RESTART;
776     case DRV_REMOVE:            return (LRESULT)DRVCNF_RESTART;
777     default:                    return (LRESULT)0L;
778     }
779 }
780
781 /**************************************************************************
782  *                              GetDriverInfo                   [USER.256]
783  */
784 BOOL16 WINAPI GetDriverInfo(HDRVR16 hDrvr, LPDRIVERINFOSTRUCT16 lpDrvInfo)
785 {
786     LPWINE_DRIVER       lpDrv;
787     BOOL16              ret = FALSE;
788
789     TRACE(driver, "(%04x, %p);\n", hDrvr, lpDrvInfo);
790
791     if (lpDrvInfo == NULL ||
792         lpDrvInfo->length != sizeof(DRIVERINFOSTRUCT16)) return FALSE;
793
794     lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
795     if (lpDrv != NULL && lpDrv->hDriver16 == hDrvr && 
796         (lpDrv->dwFlags & WINE_DI_TYPE_MASK) == WINE_DI_TYPE_16) {
797         lpDrvInfo->hDriver = lpDrv->hDriver16;
798         lpDrvInfo->hModule = lpDrv->d.d16.hModule;
799         strncpy(lpDrvInfo->szAliasName, lpDrv->szAliasName, sizeof(lpDrvInfo->szAliasName));
800         ret = TRUE;
801     }
802
803     return ret;
804 }
805
806 /**************************************************************************
807  *                              GetNextDriver                   [USER.257]
808  */
809 HDRVR16 WINAPI GetNextDriver(HDRVR16 hDrvr, DWORD dwFlags)
810 {
811     HDRVR16             hRetDrv = 0;
812     LPWINE_DRIVER       lpDrv;
813
814     TRACE(driver, "(%04x, %08lX);\n", hDrvr, dwFlags);
815
816     if (hDrvr == 0) {
817         if (lpDrvItemList == NULL) {
818             FIXME(driver, "drivers list empty !\n");
819             /* FIXME: code was using DRIVER_LoadStartupDrivers(); before ? 
820              * I (EPP) don't quite understand this 
821              */
822             if (lpDrvItemList == NULL) return 0;
823         }
824         lpDrv = lpDrvItemList;
825         if (dwFlags & GND_REVERSE) {
826             while (lpDrv->lpNextItem)
827                 lpDrv = lpDrv->lpNextItem;
828         }
829     } else {
830         lpDrv = DRIVER_FindFromHDrvr16(hDrvr);
831         if (lpDrv != NULL) {
832             if (dwFlags & GND_REVERSE) {
833                 lpDrv = (lpDrv->lpPrevItem) ? lpDrv->lpPrevItem : NULL;
834             } else {
835                 lpDrv = (lpDrv->lpNextItem) ? lpDrv->lpNextItem : NULL;
836             }
837         }
838     }
839
840     hRetDrv = (lpDrv) ? lpDrv->hDriver16 : (HDRVR16)0;
841     TRACE(driver, "return %04x !\n", hRetDrv);
842     return hRetDrv;
843 }
844