Release 980614
[wine] / windows / driver.c
1 /*
2  * WINE Drivers functions
3  *
4  * Copyright 1994 Martin Ayotte
5  * Copyright 1998 Marcus Meissner
6  */
7
8 #include "windows.h"
9 #include "heap.h"
10 #include "win.h"
11 #include "callback.h"
12 #include "driver.h"
13 #include "module.h"
14 #include "debug.h"
15
16 LPDRIVERITEM lpDrvItemList = NULL;
17 LPDRIVERITEM32A lpDrvItemList32 = NULL;
18
19 /**************************************************************************
20  *      LoadStartupDrivers
21  */
22 static void LoadStartupDrivers(void)
23 {
24     HDRVR16 hDrv;
25     char  str[256];
26     LPSTR ptr;
27
28     if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str),
29                                  "SYSTEM.INI" ) < 2)
30     {
31         ERR( driver,"Can't find drivers section in system.ini\n" );
32         return;
33     }
34
35     ptr = str;
36     while (lstrlen32A( ptr ) != 0)
37     {
38         TRACE(driver, "str='%s'\n", ptr );
39         hDrv = OpenDriver16( ptr, "drivers", 0L );
40         TRACE(driver, "hDrv=%04x\n", hDrv );
41         ptr += lstrlen32A(ptr) + 1;
42     }
43     TRACE(driver, "end of list !\n" );
44     return;
45 }
46
47 /**************************************************************************
48  *                              SendDriverMessage               [USER.251]
49  */
50 LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
51                                    LPARAM lParam2)
52 {
53     LPDRIVERITEM lpdrv;
54     LRESULT retval;
55
56     TRACE(driver, "(%04x, %04X, %08lX, %08lX)\n",
57                     hDriver, msg, lParam1, lParam2 );
58
59     lpdrv = (LPDRIVERITEM)GlobalLock16( hDriver );
60     if (lpdrv == NULL || lpdrv->dis.hDriver != hDriver)
61     {
62         GlobalUnlock16( hDriver );
63         return 0;
64     }
65
66     retval = Callbacks->CallDriverProc( lpdrv->lpDrvProc, 0L /* FIXME */,
67                                         hDriver, msg, lParam1, lParam2 );
68
69     TRACE(driver, "retval = %ld\n", retval );
70
71     GlobalUnlock16( hDriver );
72     return retval;
73 }
74
75 /**************************************************************************
76  *                              SendDriverMessage               [WINMM.19]
77  */
78 LRESULT WINAPI SendDriverMessage32(HDRVR32 hDriver, UINT32 msg, LPARAM lParam1,
79                                    LPARAM lParam2)
80 {
81     LPDRIVERITEM32A lpdrv;
82     LRESULT retval;
83
84     TRACE(driver, "(%04x, %04X, %08lX, %08lX)\n",
85                     hDriver, msg, lParam1, lParam2 );
86
87     lpdrv = (LPDRIVERITEM32A)hDriver;
88     if (!lpdrv)
89         return 0;
90
91     retval = lpdrv->driverproc(lpdrv->dis.hDriver,hDriver,msg,lParam1,lParam2);
92
93     TRACE(driver, "retval = %ld\n", retval );
94
95     return retval;
96 }
97
98 /**************************************************************************
99  *                              OpenDriver                      [USER.252]
100  */
101 HDRVR16 WINAPI OpenDriver16(
102         LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam
103 ) {
104     HDRVR16 hDrvr;
105     LPDRIVERITEM lpdrv, lpnewdrv;
106     char DrvName[128];
107
108     TRACE(driver,"('%s', '%s', %08lX);\n",
109                     lpDriverName, lpSectionName, lParam );
110
111     if (lpSectionName == NULL) {
112         lstrcpyn32A(DrvName,lpDriverName,sizeof(DrvName));
113         FIXME(driver,"sectionname NULL, assuming directfilename (%s)\n",lpDriverName);
114     } else {
115         GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName,
116                                      sizeof(DrvName), "SYSTEM.INI" );
117     }
118     TRACE(driver,"DrvName='%s'\n", DrvName );
119     if (lstrlen32A(DrvName) < 1) return 0;
120
121     lpdrv = lpDrvItemList;
122     while (lpdrv)                       /* XXX find it... like this? */
123     {
124         if (!lstrcmpi32A( lpDriverName, lpdrv->dis.szAliasName ))
125         {
126             lpdrv->count++;
127             SendDriverMessage16( lpdrv->dis.hDriver, DRV_OPEN, 0L, lParam );
128             return lpdrv->dis.hDriver;
129         }
130         lpdrv = lpdrv->lpNextItem;
131     }
132
133     lpdrv = lpDrvItemList;      /* find end of list */
134     if (lpdrv != NULL)
135       while (lpdrv->lpNextItem != NULL)
136         lpdrv = lpdrv->lpNextItem;
137
138     hDrvr = GlobalAlloc16( GMEM_MOVEABLE, sizeof(DRIVERITEM) );
139     lpnewdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
140     if (lpnewdrv == NULL) return 0;
141     lpnewdrv->dis.length = sizeof( DRIVERINFOSTRUCT16 );
142     lpnewdrv->dis.hModule = LoadModule16( DrvName, (LPVOID)-1 );
143     if (!lpnewdrv->dis.hModule)
144     {
145         GlobalUnlock16( hDrvr );
146         GlobalFree16( hDrvr );
147         return 0;
148     }
149     lpnewdrv->dis.hDriver = hDrvr;
150     lstrcpy32A( lpnewdrv->dis.szAliasName, lpDriverName );
151     lpnewdrv->count = 1;
152     if (!(lpnewdrv->lpDrvProc = (DRIVERPROC16)WIN32_GetProcAddress16(lpnewdrv->dis.hModule, "DRIVERPROC" )))
153     {
154         FreeModule16( lpnewdrv->dis.hModule );
155         GlobalUnlock16( hDrvr );
156         GlobalFree16( hDrvr );
157         return 0;
158     }
159
160     lpnewdrv->lpNextItem = NULL;
161     if (lpDrvItemList == NULL)
162     {
163         lpDrvItemList = lpnewdrv;
164         lpnewdrv->lpPrevItem = NULL;
165     }
166     else
167     {
168         lpdrv->lpNextItem = lpnewdrv;
169         lpnewdrv->lpPrevItem = lpdrv;
170     }
171
172     SendDriverMessage16( hDrvr, DRV_LOAD, 0L, lParam );
173     SendDriverMessage16( hDrvr, DRV_ENABLE, 0L, lParam );
174     SendDriverMessage16( hDrvr, DRV_OPEN, 0L, lParam );
175
176     TRACE(driver, "hDrvr=%04x loaded !\n", hDrvr );
177     return hDrvr;
178 }
179
180 /**************************************************************************
181  *                              OpenDriver                      [WINMM.15]
182  * (0,1,DRV_LOAD  ,0       ,0)
183  * (0,1,DRV_ENABLE,0       ,0)
184  * (0,1,DRV_OPEN  ,buf[256],0)
185  */
186 HDRVR32 WINAPI OpenDriver32A(
187         LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam
188 ) {
189     HDRVR32 hDrvr;
190     LPDRIVERITEM32A lpdrv, lpnewdrv;
191     char DrvName[128],*tmpbuf;
192
193     TRACE(driver,"('%s', '%s', %08lX);\n",
194                     lpDriverName,lpSectionName,lParam );
195
196     if (lpSectionName == NULL) {
197         lstrcpyn32A(DrvName,lpDriverName,sizeof(DrvName));
198         FIXME(driver,"sectionname NULL, assuming directfilename (%s)\n",lpDriverName);
199     } else  {
200         GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName,
201                                  sizeof(DrvName), "system.ini" );
202     }
203     TRACE(driver,"DrvName='%s'\n", DrvName );
204     if (lstrlen32A(DrvName) < 1) return 0;
205
206     lpdrv = lpDrvItemList32;
207     while (lpdrv) {
208         if (!lstrcmpi32A( lpDriverName, lpdrv->dis.szAliasName )) {
209             lpdrv->count++;
210             lpdrv->dis.hDriver = SendDriverMessage32( lpdrv->dis.hDriver, DRV_OPEN, ""/*FIXME*/, 0L );
211             return (HDRVR32)lpdrv;
212         }
213         lpdrv = lpdrv->next;
214     }
215
216     hDrvr = (HDRVR32)HeapAlloc(SystemHeap,0, sizeof(DRIVERITEM32A) );
217     if (!hDrvr) {
218         ERR(driver,"out of memory");
219         return 0;
220     }
221     lpnewdrv = (DRIVERITEM32A*)hDrvr;
222     lpnewdrv->dis.length = sizeof( DRIVERINFOSTRUCT32A );
223     lpnewdrv->dis.hModule = LoadLibrary32A( DrvName );
224     if (!lpnewdrv->dis.hModule) {
225         FIXME(driver,"could not load library %s\n",DrvName);
226         HeapFree( SystemHeap,0,(LPVOID)hDrvr );
227         return 0;
228     }
229     lstrcpy32A( lpnewdrv->dis.szAliasName, lpDriverName );
230     lpnewdrv->count = 1;
231     if (!(lpnewdrv->driverproc = (DRIVERPROC32)GetProcAddress32(lpnewdrv->dis.hModule, "DriverProc" )))
232     {
233         FIXME(driver,"no 'DriverProc' found in %s\n",DrvName);
234         FreeModule32( lpnewdrv->dis.hModule );
235         HeapFree( SystemHeap,0, (LPVOID)hDrvr );
236         return 0;
237     }
238
239     lpnewdrv->next = lpDrvItemList32;
240     lpDrvItemList32 = lpnewdrv;
241
242     SendDriverMessage32( hDrvr, DRV_LOAD, 0L, lParam );
243     SendDriverMessage32( hDrvr, DRV_ENABLE, 0L, lParam );
244     tmpbuf = HeapAlloc(SystemHeap,0,256);
245     lpnewdrv->dis.hDriver=SendDriverMessage32(hDrvr,DRV_OPEN,tmpbuf,lParam);
246     HeapFree(SystemHeap,0,tmpbuf);
247     TRACE(driver, "hDrvr=%04x loaded !\n", hDrvr );
248     return hDrvr;
249 }
250
251 /**************************************************************************
252  *                              OpenDriver                      [WINMM.15]
253  */
254 HDRVR32 WINAPI OpenDriver32W(
255         LPCWSTR lpDriverName, LPCWSTR lpSectionName, LPARAM lParam
256 ) {
257         LPSTR dn = HEAP_strdupWtoA(GetProcessHeap(),0,lpDriverName);
258         LPSTR sn = HEAP_strdupWtoA(GetProcessHeap(),0,lpSectionName);
259         HDRVR32 ret = OpenDriver32A(dn,sn,lParam);
260
261         if (dn) HeapFree(GetProcessHeap(),0,dn);
262         if (sn) HeapFree(GetProcessHeap(),0,sn);
263         return ret;
264 }
265
266 /**************************************************************************
267  *                      CloseDriver                             [USER.253]
268  */
269 LRESULT WINAPI CloseDriver16(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
270 {
271     LPDRIVERITEM lpdrv;
272
273     TRACE(driver, "(%04x, %08lX, %08lX);\n",
274                     hDrvr, lParam1, lParam2 );
275
276     lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
277     if (lpdrv != NULL && lpdrv->dis.hDriver == hDrvr)
278     {
279         SendDriverMessage16( hDrvr, DRV_CLOSE, lParam1, lParam2 );
280         if (--lpdrv->count == 0)
281         {
282             SendDriverMessage16( hDrvr, DRV_DISABLE, lParam1, lParam2 );
283             SendDriverMessage16( hDrvr, DRV_FREE, lParam1, lParam2 );
284
285             if (lpdrv->lpPrevItem)
286               lpdrv->lpPrevItem->lpNextItem = lpdrv->lpNextItem;
287             else
288                 lpDrvItemList = lpdrv->lpNextItem;
289             if (lpdrv->lpNextItem)
290               lpdrv->lpNextItem->lpPrevItem = lpdrv->lpPrevItem;
291
292             FreeModule16( lpdrv->dis.hModule );
293             GlobalUnlock16( hDrvr );
294             GlobalFree16( hDrvr );
295         }
296
297         TRACE(driver, "hDrvr=%04x closed !\n",
298                         hDrvr );
299         return TRUE;
300     }
301     return FALSE;
302 }
303
304 /**************************************************************************
305  *                              GetDriverModuleHandle   [USER.254]
306  */
307 HMODULE16 WINAPI GetDriverModuleHandle16(HDRVR16 hDrvr)
308 {
309     LPDRIVERITEM lpdrv;
310     HMODULE16 hModule = 0;
311
312     TRACE(driver, "(%04x);\n", hDrvr);
313
314     lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
315     if (lpdrv != NULL && lpdrv->dis.hDriver == hDrvr)
316     {
317         hModule = lpdrv->dis.hModule;
318         GlobalUnlock16( hDrvr );
319     }
320     return hModule;
321 }
322
323 /**************************************************************************
324  *                              GetDriverModuleHandle   [USER.254]
325  */
326 HMODULE32 WINAPI GetDriverModuleHandle32(HDRVR32 hDrvr)
327 {
328     LPDRIVERITEM32A lpdrv = (LPDRIVERITEM32A)hDrvr;
329
330     TRACE(driver, "(%04x);\n", hDrvr);
331     if (!lpdrv)
332         return 0;
333     return lpdrv->dis.hModule;
334 }
335
336 /**************************************************************************
337  *                              DefDriverProc                   [USER.255]
338  */
339 LRESULT WINAPI DefDriverProc(DWORD dwDevID, HDRVR16 hDriv, UINT16 wMsg, 
340                              LPARAM lParam1, LPARAM lParam2)
341 {
342     switch(wMsg)
343     {
344       case DRV_LOAD:
345         return (LRESULT)0L;
346       case DRV_FREE:
347         return (LRESULT)0L;
348       case DRV_OPEN:
349         return (LRESULT)0L;
350       case DRV_CLOSE:
351         return (LRESULT)0L;
352       case DRV_ENABLE:
353         return (LRESULT)0L;
354       case DRV_DISABLE:
355         return (LRESULT)0L;
356       case DRV_QUERYCONFIGURE:
357         return (LRESULT)0L;
358
359       case DRV_CONFIGURE:
360         MessageBox16( 0, "Driver isn't configurable !", "Wine Driver", MB_OK );
361         return (LRESULT)0L;
362
363       case DRV_INSTALL:
364         return (LRESULT)DRVCNF_RESTART;
365
366       case DRV_REMOVE:
367         return (LRESULT)DRVCNF_RESTART;
368
369       default:
370         return (LRESULT)0L;
371     }
372 }
373
374 /**************************************************************************
375  *                              GetDriverInfo                   [USER.256]
376  */
377 BOOL16 WINAPI GetDriverInfo(HDRVR16 hDrvr, LPDRIVERINFOSTRUCT16 lpDrvInfo)
378 {
379     LPDRIVERITEM lpdrv;
380
381     TRACE(driver, "(%04x, %p);\n", hDrvr, lpDrvInfo );
382
383     if (lpDrvInfo == NULL) return FALSE;
384
385     lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
386     if (lpdrv == NULL) return FALSE;
387     memcpy( lpDrvInfo, &lpdrv->dis, sizeof(DRIVERINFOSTRUCT16) );
388     GlobalUnlock16( hDrvr );
389
390     return TRUE;
391 }
392
393 /**************************************************************************
394  *                              GetNextDriver                   [USER.257]
395  */
396 HDRVR16 WINAPI GetNextDriver(HDRVR16 hDrvr, DWORD dwFlags)
397 {
398     LPDRIVERITEM lpdrv;
399     HDRVR16 hRetDrv = 0;
400
401     TRACE(driver, "(%04x, %08lX);\n", hDrvr, dwFlags );
402
403     if (hDrvr == 0)
404     {
405         if (lpDrvItemList == NULL)
406         {
407             TRACE(driver, "drivers list empty !\n");
408             LoadStartupDrivers();
409             if (lpDrvItemList == NULL) return 0;
410         }
411         TRACE(driver,"return first %04x !\n",
412                         lpDrvItemList->dis.hDriver );
413         return lpDrvItemList->dis.hDriver;
414     }
415
416     lpdrv = (LPDRIVERITEM)GlobalLock16( hDrvr );
417     if (lpdrv != NULL)
418     {
419         if (dwFlags & GND_REVERSE)
420         {
421             if (lpdrv->lpPrevItem) 
422               hRetDrv = lpdrv->lpPrevItem->dis.hDriver;
423         }
424         else
425         {
426             if (lpdrv->lpNextItem) 
427               hRetDrv = lpdrv->lpNextItem->dis.hDriver;
428         }
429         GlobalUnlock16( hDrvr );
430     }
431
432     TRACE(driver, "return %04x !\n", hRetDrv );
433     return hRetDrv;
434 }