257431bbad5fb2373808d20ac1b1a442450a7760
[reactos.git] / reactos / subsys / win32k / misc / driver.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * GDI Driver support routines
22 * (mostly swiped from Wine)
23 *
24 */
25
26 #include <w32k.h>
27
28 #define NDEBUG
29 #include <debug.h>
30
31 /* #define TRACE_DRV_CALLS to get a log of all calls into the display driver. */
32 #undef TRACE_DRV_CALLS
33
34 typedef struct _GRAPHICS_DRIVER
35 {
36 PWSTR Name;
37 PGD_ENABLEDRIVER EnableDriver;
38 int ReferenceCount;
39 struct _GRAPHICS_DRIVER *Next;
40 } GRAPHICS_DRIVER, *PGRAPHICS_DRIVER;
41
42 static PGRAPHICS_DRIVER DriverList;
43 static PGRAPHICS_DRIVER GenericDriver = 0;
44
45 BOOL DRIVER_RegisterDriver(LPCWSTR Name, PGD_ENABLEDRIVER EnableDriver)
46 {
47 PGRAPHICS_DRIVER Driver = ExAllocatePoolWithTag(PagedPool, sizeof(*Driver), TAG_DRIVER);
48 DPRINT( "DRIVER_RegisterDriver( Name: %S )\n", Name );
49 if (!Driver) return FALSE;
50 Driver->ReferenceCount = 0;
51 Driver->EnableDriver = EnableDriver;
52 if (Name)
53 {
54 Driver->Name = ExAllocatePoolWithTag(PagedPool,
55 (wcslen(Name) + 1) * sizeof(WCHAR),
56 TAG_DRIVER);
57 wcscpy(Driver->Name, Name);
58 Driver->Next = DriverList;
59 DriverList = Driver;
60 return TRUE;
61 }
62
63 if (GenericDriver != NULL)
64 {
65 ExFreePool(Driver);
66 return FALSE;
67 }
68
69 GenericDriver = Driver;
70 return TRUE;
71 }
72
73 PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name)
74 {
75 static WCHAR DefaultPath[] = L"\\SystemRoot\\System32\\";
76 static WCHAR DefaultExtension[] = L".DLL";
77 SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
78 GRAPHICS_DRIVER *Driver = DriverList;
79 NTSTATUS Status;
80 WCHAR *FullName;
81 LPCWSTR p;
82 BOOL PathSeparatorFound;
83 BOOL DotFound;
84 UINT Size;
85
86 DotFound = FALSE;
87 PathSeparatorFound = FALSE;
88 p = Name;
89 while (L'\0' != *p)
90 {
91 if (L'\\' == *p || L'/' == *p)
92 {
93 PathSeparatorFound = TRUE;
94 DotFound = FALSE;
95 }
96 else if (L'.' == *p)
97 {
98 DotFound = TRUE;
99 }
100 p++;
101 }
102
103 Size = (wcslen(Name) + 1) * sizeof(WCHAR);
104 if (! PathSeparatorFound)
105 {
106 Size += sizeof(DefaultPath) - sizeof(WCHAR);
107 }
108 if (! DotFound)
109 {
110 Size += sizeof(DefaultExtension) - sizeof(WCHAR);
111 }
112 FullName = ExAllocatePoolWithTag(PagedPool, Size, TAG_DRIVER);
113 if (NULL == FullName)
114 {
115 DPRINT1("Out of memory\n");
116 return NULL;
117 }
118 if (PathSeparatorFound)
119 {
120 FullName[0] = L'\0';
121 }
122 else
123 {
124 wcscpy(FullName, DefaultPath);
125 }
126 wcscat(FullName, Name);
127 if (! DotFound)
128 {
129 wcscat(FullName, DefaultExtension);
130 }
131
132 /* First see if the driver hasn't already been loaded */
133 while (Driver && FullName)
134 {
135 if (!_wcsicmp( Driver->Name, FullName))
136 {
137 return Driver->EnableDriver;
138 }
139 Driver = Driver->Next;
140 }
141
142 /* If not, then load it */
143 RtlInitUnicodeString (&GdiDriverInfo.DriverName, (LPWSTR)FullName);
144 Status = ZwSetSystemInformation (SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
145 ExFreePool(FullName);
146 if (!NT_SUCCESS(Status)) return NULL;
147
148 DRIVER_RegisterDriver( L"DISPLAY", GdiDriverInfo.EntryPoint);
149 return (PGD_ENABLEDRIVER)GdiDriverInfo.EntryPoint;
150 }
151
152 #define BEGIN_FUNCTION_MAP() \
153 ULONG i; \
154 for (i = 0; i < DED->c; i++) \
155 { \
156 switch(DED->pdrvfn[i].iFunc) \
157 {
158
159 #define END_FUNCTION_MAP() \
160 default: \
161 DPRINT1("Unsupported DDI function 0x%x\n", DED->pdrvfn[i].iFunc); \
162 break; \
163 } \
164 }
165
166 #ifdef TRACE_DRV_CALLS
167
168 typedef struct _TRACEDRVINFO
169 {
170 unsigned Index;
171 char *Name;
172 PVOID DrvRoutine;
173 }
174 TRACEDRVINFO, *PTRACEDRVINFO;
175
176 __asm__(
177 " .text\n"
178 "TraceDrv:\n"
179 " pushl %eax\n"
180 " call _FindTraceInfo\n"
181 " add $4,%esp\n"
182 " pushl %eax\n"
183 " pushl 4(%eax)\n"
184 " call _DbgPrint\n"
185 " addl $4,%esp\n"
186 " popl %eax\n"
187 " mov 8(%eax),%eax\n"
188 " jmp *%eax\n"
189 );
190
191 #define TRACEDRV_ROUTINE(function) \
192 unsigned TraceDrvIndex##function = INDEX_Drv##function; \
193 __asm__ ( \
194 " .text\n" \
195 "_Trace" #function ":\n" \
196 " movl _TraceDrvIndex" #function ",%eax\n" \
197 " jmp TraceDrv\n" \
198 ); \
199 extern PVOID Trace##function;
200
201 TRACEDRV_ROUTINE(EnablePDEV)
202 TRACEDRV_ROUTINE(CompletePDEV)
203 TRACEDRV_ROUTINE(DisablePDEV)
204 TRACEDRV_ROUTINE(EnableSurface)
205 TRACEDRV_ROUTINE(DisableSurface)
206 TRACEDRV_ROUTINE(AssertMode)
207 TRACEDRV_ROUTINE(Offset)
208 TRACEDRV_ROUTINE(ResetPDEV)
209 TRACEDRV_ROUTINE(DisableDriver)
210 TRACEDRV_ROUTINE(CreateDeviceBitmap)
211 TRACEDRV_ROUTINE(DeleteDeviceBitmap)
212 TRACEDRV_ROUTINE(RealizeBrush)
213 TRACEDRV_ROUTINE(DitherColor)
214 TRACEDRV_ROUTINE(StrokePath)
215 TRACEDRV_ROUTINE(FillPath)
216 TRACEDRV_ROUTINE(StrokeAndFillPath)
217 TRACEDRV_ROUTINE(Paint)
218 TRACEDRV_ROUTINE(BitBlt)
219 TRACEDRV_ROUTINE(TransparentBlt)
220 TRACEDRV_ROUTINE(CopyBits)
221 TRACEDRV_ROUTINE(StretchBlt)
222 TRACEDRV_ROUTINE(StretchBltROP)
223 TRACEDRV_ROUTINE(SetPalette)
224 TRACEDRV_ROUTINE(TextOut)
225 TRACEDRV_ROUTINE(Escape)
226 TRACEDRV_ROUTINE(DrawEscape)
227 TRACEDRV_ROUTINE(QueryFont)
228 TRACEDRV_ROUTINE(QueryFontTree)
229 TRACEDRV_ROUTINE(QueryFontData)
230 TRACEDRV_ROUTINE(SetPointerShape)
231 TRACEDRV_ROUTINE(MovePointer)
232 TRACEDRV_ROUTINE(LineTo)
233 TRACEDRV_ROUTINE(SendPage)
234 TRACEDRV_ROUTINE(StartPage)
235 TRACEDRV_ROUTINE(EndDoc)
236 TRACEDRV_ROUTINE(StartDoc)
237 TRACEDRV_ROUTINE(GetGlyphMode)
238 TRACEDRV_ROUTINE(Synchronize)
239 TRACEDRV_ROUTINE(SaveScreenBits)
240 TRACEDRV_ROUTINE(GetModes)
241 TRACEDRV_ROUTINE(Free)
242 TRACEDRV_ROUTINE(DestroyFont)
243 TRACEDRV_ROUTINE(QueryFontCaps)
244 TRACEDRV_ROUTINE(LoadFontFile)
245 TRACEDRV_ROUTINE(UnloadFontFile)
246 TRACEDRV_ROUTINE(FontManagement)
247 TRACEDRV_ROUTINE(QueryTrueTypeTable)
248 TRACEDRV_ROUTINE(QueryTrueTypeOutline)
249 TRACEDRV_ROUTINE(GetTrueTypeFile)
250 TRACEDRV_ROUTINE(QueryFontFile)
251 TRACEDRV_ROUTINE(QueryAdvanceWidths)
252 TRACEDRV_ROUTINE(SetPixelFormat)
253 TRACEDRV_ROUTINE(DescribePixelFormat)
254 TRACEDRV_ROUTINE(SwapBuffers)
255 TRACEDRV_ROUTINE(StartBanding)
256 TRACEDRV_ROUTINE(NextBand)
257 TRACEDRV_ROUTINE(GetDirectDrawInfo)
258 TRACEDRV_ROUTINE(EnableDirectDraw)
259 TRACEDRV_ROUTINE(DisableDirectDraw)
260 TRACEDRV_ROUTINE(QuerySpoolType)
261 TRACEDRV_ROUTINE(GradientFill)
262 TRACEDRV_ROUTINE(SynchronizeSurface)
263 TRACEDRV_ROUTINE(AlphaBlend)
264
265 #define TRACEDRVINFO_ENTRY(function) \
266 { INDEX_Drv##function, "Drv" #function "\n", NULL }
267 static TRACEDRVINFO TraceDrvInfo[] =
268 {
269 TRACEDRVINFO_ENTRY(EnablePDEV),
270 TRACEDRVINFO_ENTRY(CompletePDEV),
271 TRACEDRVINFO_ENTRY(DisablePDEV),
272 TRACEDRVINFO_ENTRY(EnableSurface),
273 TRACEDRVINFO_ENTRY(DisableSurface),
274 TRACEDRVINFO_ENTRY(AssertMode),
275 TRACEDRVINFO_ENTRY(Offset),
276 TRACEDRVINFO_ENTRY(ResetPDEV),
277 TRACEDRVINFO_ENTRY(DisableDriver),
278 TRACEDRVINFO_ENTRY(CreateDeviceBitmap),
279 TRACEDRVINFO_ENTRY(DeleteDeviceBitmap),
280 TRACEDRVINFO_ENTRY(RealizeBrush),
281 TRACEDRVINFO_ENTRY(DitherColor),
282 TRACEDRVINFO_ENTRY(StrokePath),
283 TRACEDRVINFO_ENTRY(FillPath),
284 TRACEDRVINFO_ENTRY(StrokeAndFillPath),
285 TRACEDRVINFO_ENTRY(Paint),
286 TRACEDRVINFO_ENTRY(BitBlt),
287 TRACEDRVINFO_ENTRY(TransparentBlt),
288 TRACEDRVINFO_ENTRY(CopyBits),
289 TRACEDRVINFO_ENTRY(StretchBlt),
290 TRACEDRVINFO_ENTRY(StretchBltROP),
291 TRACEDRVINFO_ENTRY(SetPalette),
292 TRACEDRVINFO_ENTRY(TextOut),
293 TRACEDRVINFO_ENTRY(Escape),
294 TRACEDRVINFO_ENTRY(DrawEscape),
295 TRACEDRVINFO_ENTRY(QueryFont),
296 TRACEDRVINFO_ENTRY(QueryFontTree),
297 TRACEDRVINFO_ENTRY(QueryFontData),
298 TRACEDRVINFO_ENTRY(SetPointerShape),
299 TRACEDRVINFO_ENTRY(MovePointer),
300 TRACEDRVINFO_ENTRY(LineTo),
301 TRACEDRVINFO_ENTRY(SendPage),
302 TRACEDRVINFO_ENTRY(StartPage),
303 TRACEDRVINFO_ENTRY(EndDoc),
304 TRACEDRVINFO_ENTRY(StartDoc),
305 TRACEDRVINFO_ENTRY(GetGlyphMode),
306 TRACEDRVINFO_ENTRY(Synchronize),
307 TRACEDRVINFO_ENTRY(SaveScreenBits),
308 TRACEDRVINFO_ENTRY(GetModes),
309 TRACEDRVINFO_ENTRY(Free),
310 TRACEDRVINFO_ENTRY(DestroyFont),
311 TRACEDRVINFO_ENTRY(QueryFontCaps),
312 TRACEDRVINFO_ENTRY(LoadFontFile),
313 TRACEDRVINFO_ENTRY(UnloadFontFile),
314 TRACEDRVINFO_ENTRY(FontManagement),
315 TRACEDRVINFO_ENTRY(QueryTrueTypeTable),
316 TRACEDRVINFO_ENTRY(QueryTrueTypeOutline),
317 TRACEDRVINFO_ENTRY(GetTrueTypeFile),
318 TRACEDRVINFO_ENTRY(QueryFontFile),
319 TRACEDRVINFO_ENTRY(QueryAdvanceWidths),
320 TRACEDRVINFO_ENTRY(SetPixelFormat),
321 TRACEDRVINFO_ENTRY(DescribePixelFormat),
322 TRACEDRVINFO_ENTRY(SwapBuffers),
323 TRACEDRVINFO_ENTRY(StartBanding),
324 TRACEDRVINFO_ENTRY(NextBand),
325 TRACEDRVINFO_ENTRY(GetDirectDrawInfo),
326 TRACEDRVINFO_ENTRY(EnableDirectDraw),
327 TRACEDRVINFO_ENTRY(DisableDirectDraw),
328 TRACEDRVINFO_ENTRY(QuerySpoolType),
329 TRACEDRVINFO_ENTRY(GradientFill),
330 TRACEDRVINFO_ENTRY(SynchronizeSurface),
331 TRACEDRVINFO_ENTRY(AlphaBlend)
332 };
333
334 PTRACEDRVINFO
335 FindTraceInfo(unsigned Index)
336 {
337 unsigned i;
338
339 for (i = 0; i < sizeof(TraceDrvInfo) / sizeof(TRACEDRVINFO); i++)
340 {
341 if (TraceDrvInfo[i].Index == Index)
342 {
343 return TraceDrvInfo + i;
344 }
345 }
346
347 return NULL;
348 }
349
350 #define DRIVER_FUNCTION(function) \
351 case INDEX_Drv##function: \
352 FindTraceInfo(INDEX_Drv##function)->DrvRoutine = DED->pdrvfn[i].pfn; \
353 *(PVOID*)&DF->function = &Trace##function; \
354 break
355 #else
356 #define DRIVER_FUNCTION(function) \
357 case INDEX_Drv##function: \
358 *(PVOID*)&DF->function = DED->pdrvfn[i].pfn; \
359 break
360 #endif
361
362 BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA DED,
363 PDRIVER_FUNCTIONS DF)
364 {
365 BEGIN_FUNCTION_MAP();
366
367 DRIVER_FUNCTION(EnablePDEV);
368 DRIVER_FUNCTION(CompletePDEV);
369 DRIVER_FUNCTION(DisablePDEV);
370 DRIVER_FUNCTION(EnableSurface);
371 DRIVER_FUNCTION(DisableSurface);
372 DRIVER_FUNCTION(AssertMode);
373 DRIVER_FUNCTION(Offset);
374 DRIVER_FUNCTION(ResetPDEV);
375 DRIVER_FUNCTION(DisableDriver);
376 DRIVER_FUNCTION(CreateDeviceBitmap);
377 DRIVER_FUNCTION(DeleteDeviceBitmap);
378 DRIVER_FUNCTION(RealizeBrush);
379 DRIVER_FUNCTION(DitherColor);
380 DRIVER_FUNCTION(StrokePath);
381 DRIVER_FUNCTION(FillPath);
382 DRIVER_FUNCTION(StrokeAndFillPath);
383 DRIVER_FUNCTION(Paint);
384 DRIVER_FUNCTION(BitBlt);
385 DRIVER_FUNCTION(TransparentBlt);
386 DRIVER_FUNCTION(CopyBits);
387 DRIVER_FUNCTION(StretchBlt);
388 DRIVER_FUNCTION(StretchBltROP);
389 DRIVER_FUNCTION(SetPalette);
390 DRIVER_FUNCTION(TextOut);
391 DRIVER_FUNCTION(Escape);
392 DRIVER_FUNCTION(DrawEscape);
393 DRIVER_FUNCTION(QueryFont);
394 DRIVER_FUNCTION(QueryFontTree);
395 DRIVER_FUNCTION(QueryFontData);
396 DRIVER_FUNCTION(SetPointerShape);
397 DRIVER_FUNCTION(MovePointer);
398 DRIVER_FUNCTION(LineTo);
399 DRIVER_FUNCTION(SendPage);
400 DRIVER_FUNCTION(StartPage);
401 DRIVER_FUNCTION(EndDoc);
402 DRIVER_FUNCTION(StartDoc);
403 DRIVER_FUNCTION(GetGlyphMode);
404 DRIVER_FUNCTION(Synchronize);
405 DRIVER_FUNCTION(SaveScreenBits);
406 DRIVER_FUNCTION(GetModes);
407 DRIVER_FUNCTION(Free);
408 DRIVER_FUNCTION(DestroyFont);
409 DRIVER_FUNCTION(QueryFontCaps);
410 DRIVER_FUNCTION(LoadFontFile);
411 DRIVER_FUNCTION(UnloadFontFile);
412 DRIVER_FUNCTION(FontManagement);
413 DRIVER_FUNCTION(QueryTrueTypeTable);
414 DRIVER_FUNCTION(QueryTrueTypeOutline);
415 DRIVER_FUNCTION(GetTrueTypeFile);
416 DRIVER_FUNCTION(QueryFontFile);
417 DRIVER_FUNCTION(QueryAdvanceWidths);
418 DRIVER_FUNCTION(SetPixelFormat);
419 DRIVER_FUNCTION(DescribePixelFormat);
420 DRIVER_FUNCTION(SwapBuffers);
421 DRIVER_FUNCTION(StartBanding);
422 DRIVER_FUNCTION(NextBand);
423 DRIVER_FUNCTION(GetDirectDrawInfo);
424 DRIVER_FUNCTION(EnableDirectDraw);
425 DRIVER_FUNCTION(DisableDirectDraw);
426 DRIVER_FUNCTION(QuerySpoolType);
427 DRIVER_FUNCTION(GradientFill);
428 DRIVER_FUNCTION(SynchronizeSurface);
429 DRIVER_FUNCTION(AlphaBlend);
430
431 END_FUNCTION_MAP();
432
433 return TRUE;
434 }
435
436 typedef LONG VP_STATUS;
437 typedef VP_STATUS (STDCALL *PMP_DRIVERENTRY)(PVOID, PVOID);
438
439 PFILE_OBJECT DRIVER_FindMPDriver(ULONG DisplayNumber)
440 {
441 OBJECT_ATTRIBUTES ObjectAttributes;
442 WCHAR DeviceNameBuffer[20];
443 UNICODE_STRING DeviceName;
444 IO_STATUS_BLOCK Iosb;
445 HANDLE DisplayHandle;
446 NTSTATUS Status;
447 PFILE_OBJECT VideoFileObject;
448
449 swprintf(DeviceNameBuffer, L"\\??\\DISPLAY%d", DisplayNumber + 1);
450 RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
451 InitializeObjectAttributes(&ObjectAttributes,
452 &DeviceName,
453 0,
454 NULL,
455 NULL);
456 Status = ZwOpenFile(&DisplayHandle,
457 FILE_ALL_ACCESS,
458 &ObjectAttributes,
459 &Iosb,
460 0,
461 FILE_SYNCHRONOUS_IO_ALERT);
462 if (NT_SUCCESS(Status))
463 {
464 Status = ObReferenceObjectByHandle(DisplayHandle,
465 FILE_READ_DATA | FILE_WRITE_DATA,
466 IoFileObjectType,
467 KernelMode,
468 (PVOID *)&VideoFileObject,
469 NULL);
470 ZwClose(DisplayHandle);
471 }
472
473 if (!NT_SUCCESS(Status))
474 {
475 DPRINT1("Unable to connect to miniport (Status %lx)\n", Status);
476 DPRINT1("Perhaps the miniport wasn't loaded?\n");
477 return(NULL);
478 }
479
480 return VideoFileObject;
481 }
482
483
484 BOOL DRIVER_UnregisterDriver(LPCWSTR Name)
485 {
486 PGRAPHICS_DRIVER Driver = NULL;
487
488 if (Name)
489 {
490 if (DriverList != NULL)
491 {
492 if (!_wcsicmp(DriverList->Name, Name))
493 {
494 Driver = DriverList;
495 DriverList = DriverList->Next;
496 }
497 else
498 {
499 Driver = DriverList;
500 while (Driver->Next && _wcsicmp(Driver->Name, Name))
501 {
502 Driver = Driver->Next;
503 }
504 }
505 }
506 }
507 else
508 {
509 if (GenericDriver != NULL)
510 {
511 Driver = GenericDriver;
512 GenericDriver = NULL;
513 }
514 }
515
516 if (Driver != NULL)
517 {
518 ExFreePool(Driver->Name);
519 ExFreePool(Driver);
520
521 return TRUE;
522 }
523 else
524 {
525 return FALSE;
526 }
527 }
528
529 INT DRIVER_ReferenceDriver (LPCWSTR Name)
530 {
531 GRAPHICS_DRIVER *Driver = DriverList;
532
533 while (Driver && Name)
534 {
535 DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
536 if (!_wcsicmp( Driver->Name, Name))
537 {
538 return ++Driver->ReferenceCount;
539 }
540 Driver = Driver->Next;
541 }
542 DPRINT( "Driver %S not found to reference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
543 assert( GenericDriver != 0 );
544 return ++GenericDriver->ReferenceCount;
545 }
546
547 INT DRIVER_UnreferenceDriver (LPCWSTR Name)
548 {
549 GRAPHICS_DRIVER *Driver = DriverList;
550
551 while (Driver && Name)
552 {
553 DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
554 if (!_wcsicmp( Driver->Name, Name))
555 {
556 return --Driver->ReferenceCount;
557 }
558 Driver = Driver->Next;
559 }
560 DPRINT( "Driver '%S' not found to dereference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
561 assert( GenericDriver != 0 );
562 return --GenericDriver->ReferenceCount;
563 }
564 /* EOF */