update for HEAD-2003091401
[reactos.git] / 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 #undef WIN32_LEAN_AND_MEAN
27 #define WIN32_NO_PEHDR
28
29 #include <ddk/ntddk.h>
30 #include <windows.h>
31 #include <win32k/driver.h>
32 #include <win32k/misc.h>
33 #include <wchar.h>
34 #include <ddk/winddi.h>
35 #include <ddk/ntddvid.h>
36
37 #define NDEBUG
38 #include <debug.h>
39
40 #define DRIVER_TAG TAG('G', 'D', 'R', 'V')
41
42 typedef struct _GRAPHICS_DRIVER
43 {
44   PWSTR  Name;
45   PGD_ENABLEDRIVER  EnableDriver;
46   int  ReferenceCount;
47   struct _GRAPHICS_DRIVER  *Next;
48 } GRAPHICS_DRIVER, *PGRAPHICS_DRIVER;
49
50 static PGRAPHICS_DRIVER  DriverList;
51 static PGRAPHICS_DRIVER  GenericDriver = 0;
52
53 BOOL DRIVER_RegisterDriver(LPCWSTR  Name, PGD_ENABLEDRIVER  EnableDriver)
54 {
55   PGRAPHICS_DRIVER  Driver = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Driver), DRIVER_TAG);
56   DPRINT( "DRIVER_RegisterDriver( Name: %S )\n", Name );
57   if (!Driver)  return  FALSE;
58   Driver->ReferenceCount = 0;
59   Driver->EnableDriver = EnableDriver;
60   if (Name)
61   {
62     Driver->Name = ExAllocatePoolWithTag(PagedPool,
63                                          (wcslen(Name) + 1) * sizeof(WCHAR),
64                                          DRIVER_TAG);
65     wcscpy(Driver->Name, Name);
66     Driver->Next  = DriverList;
67     DriverList = Driver;
68     return  TRUE;
69   }
70   
71   if (GenericDriver != NULL)
72   {
73     ExFreePool(Driver);
74     return  FALSE;
75   }
76   
77   GenericDriver = Driver;
78   return  TRUE;
79 }
80
81 PGD_ENABLEDRIVER DRIVER_FindDDIDriver(LPCWSTR Name)
82 {
83   static WCHAR DefaultPath[] = L"\\SystemRoot\\System32\\";
84   static WCHAR DefaultExtension[] = L".DLL";
85   SYSTEM_LOAD_IMAGE GdiDriverInfo;
86   GRAPHICS_DRIVER *Driver = DriverList;
87   NTSTATUS Status;
88   WCHAR *FullName;
89   LPCWSTR p;
90   BOOL PathSeparatorFound;
91   BOOL DotFound;
92   UINT Size;
93
94   DotFound = FALSE;  
95   PathSeparatorFound = FALSE;
96   p = Name;
97   while (L'\0' != *p)
98   {
99     if (L'\\' == *p || L'/' == *p)
100     {
101       PathSeparatorFound = TRUE;
102       DotFound = FALSE;
103     }
104     else if (L'.' == *p)
105     {
106       DotFound = TRUE;
107     }
108     p++;
109   }
110
111   Size = (wcslen(Name) + 1) * sizeof(WCHAR);
112   if (! PathSeparatorFound)
113   {
114     Size += sizeof(DefaultPath) - sizeof(WCHAR);
115   }
116   if (! DotFound)
117   {
118     Size += sizeof(DefaultExtension) - sizeof(WCHAR);
119   }
120   FullName = ExAllocatePoolWithTag(PagedPool, Size, DRIVER_TAG);
121   if (NULL == FullName)
122   {
123     DPRINT1("Out of memory\n");
124     return NULL;
125   }
126   if (PathSeparatorFound)
127   {
128     FullName[0] = L'\0';
129   }
130   else
131   {
132     wcscpy(FullName, DefaultPath);
133   }
134   wcscat(FullName, Name);
135   if (! DotFound)
136   {
137     wcscat(FullName, DefaultExtension);
138   }
139
140   /* First see if the driver hasn't already been loaded */
141   while (Driver && FullName)
142   {
143     if (!_wcsicmp( Driver->Name, FullName)) 
144     {
145       return Driver->EnableDriver;
146     }
147     Driver = Driver->Next;
148   }
149
150   /* If not, then load it */
151   RtlInitUnicodeString (&GdiDriverInfo.ModuleName, (LPWSTR)FullName);
152   Status = ZwSetSystemInformation (SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE));
153   ExFreePool(FullName);
154   if (!NT_SUCCESS(Status)) return NULL;
155
156   DRIVER_RegisterDriver( L"DISPLAY", GdiDriverInfo.EntryPoint);
157   return (PGD_ENABLEDRIVER)GdiDriverInfo.EntryPoint;
158 }
159
160 BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA  DED, 
161                                PDRIVER_FUNCTIONS  DF)
162 {
163   ULONG i;
164
165   for (i=0; i<DED->c; i++)
166   {
167     if(DED->pdrvfn[i].iFunc == INDEX_DrvEnablePDEV)      DF->EnablePDev = (PGD_ENABLEPDEV)DED->pdrvfn[i].pfn;
168     if(DED->pdrvfn[i].iFunc == INDEX_DrvCompletePDEV)    DF->CompletePDev = (PGD_COMPLETEPDEV)DED->pdrvfn[i].pfn;
169     if(DED->pdrvfn[i].iFunc == INDEX_DrvDisablePDEV)     DF->DisablePDev = (PGD_DISABLEPDEV)DED->pdrvfn[i].pfn;
170     if(DED->pdrvfn[i].iFunc == INDEX_DrvEnableSurface)   DF->EnableSurface = (PGD_ENABLESURFACE)DED->pdrvfn[i].pfn;
171     if(DED->pdrvfn[i].iFunc == INDEX_DrvDisableSurface)  DF->DisableSurface = (PGD_DISABLESURFACE)DED->pdrvfn[i].pfn;
172     if(DED->pdrvfn[i].iFunc == INDEX_DrvAssertMode)      DF->AssertMode = (PGD_ASSERTMODE)DED->pdrvfn[i].pfn;
173     if(DED->pdrvfn[i].iFunc == INDEX_DrvResetPDEV)       DF->ResetPDev = (PGD_RESETPDEV)DED->pdrvfn[i].pfn;
174     if(DED->pdrvfn[i].iFunc == INDEX_DrvCreateDeviceBitmap)
175       DF->CreateDeviceBitmap = (PGD_CREATEDEVICEBITMAP)DED->pdrvfn[i].pfn;
176     if(DED->pdrvfn[i].iFunc == INDEX_DrvDeleteDeviceBitmap)
177       DF->DeleteDeviceBitmap = (PGD_DELETEDEVICEBITMAP)DED->pdrvfn[i].pfn;
178     if(DED->pdrvfn[i].iFunc == INDEX_DrvRealizeBrush)    DF->RealizeBrush = (PGD_REALIZEBRUSH)DED->pdrvfn[i].pfn;
179     if(DED->pdrvfn[i].iFunc == INDEX_DrvDitherColor)     DF->DitherColor = (PGD_DITHERCOLOR)DED->pdrvfn[i].pfn;
180     if(DED->pdrvfn[i].iFunc == INDEX_DrvStrokePath)      DF->StrokePath = (PGD_STROKEPATH)DED->pdrvfn[i].pfn;
181     if(DED->pdrvfn[i].iFunc == INDEX_DrvFillPath)        DF->FillPath = (PGD_FILLPATH)DED->pdrvfn[i].pfn;
182     if(DED->pdrvfn[i].iFunc == INDEX_DrvStrokeAndFillPath)
183       DF->StrokeAndFillPath = (PGD_STROKEANDFILLPATH)DED->pdrvfn[i].pfn;
184     if(DED->pdrvfn[i].iFunc == INDEX_DrvPaint)           DF->Paint = (PGD_PAINT)DED->pdrvfn[i].pfn;
185     if(DED->pdrvfn[i].iFunc == INDEX_DrvBitBlt)          DF->BitBlt = (PGD_BITBLT)DED->pdrvfn[i].pfn;
186     if(DED->pdrvfn[i].iFunc == INDEX_DrvTransparentBlt)  DF->TransparentBlt = (PGD_TRANSPARENTBLT)DED->pdrvfn[i].pfn;
187     if(DED->pdrvfn[i].iFunc == INDEX_DrvCopyBits)        DF->CopyBits = (PGD_COPYBITS)DED->pdrvfn[i].pfn;
188     if(DED->pdrvfn[i].iFunc == INDEX_DrvStretchBlt)      DF->StretchBlt = (PGD_STRETCHBLT)DED->pdrvfn[i].pfn;
189     if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPalette)      DF->SetPalette = (PGD_SETPALETTE)DED->pdrvfn[i].pfn;
190     if(DED->pdrvfn[i].iFunc == INDEX_DrvTextOut)         DF->TextOut = (PGD_TEXTOUT)DED->pdrvfn[i].pfn;
191     if(DED->pdrvfn[i].iFunc == INDEX_DrvEscape)          DF->Escape = (PGD_ESCAPE)DED->pdrvfn[i].pfn;
192     if(DED->pdrvfn[i].iFunc == INDEX_DrvDrawEscape)      DF->DrawEscape = (PGD_DRAWESCAPE)DED->pdrvfn[i].pfn;
193     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFont)       DF->QueryFont = (PGD_QUERYFONT)DED->pdrvfn[i].pfn;
194     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontTree)   DF->QueryFontTree = (PGD_QUERYFONTTREE)DED->pdrvfn[i].pfn;
195     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontData)   DF->QueryFontData = (PGD_QUERYFONTDATA)DED->pdrvfn[i].pfn;
196     if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPointerShape) DF->SetPointerShape = (PGD_SETPOINTERSHAPE)DED->pdrvfn[i].pfn;
197     if(DED->pdrvfn[i].iFunc == INDEX_DrvMovePointer)     DF->MovePointer = (PGD_MOVEPOINTER)DED->pdrvfn[i].pfn;
198     if(DED->pdrvfn[i].iFunc == INDEX_DrvLineTo)          DF->LineTo = (PGD_LINETO)DED->pdrvfn[i].pfn;
199     if(DED->pdrvfn[i].iFunc == INDEX_DrvSendPage)        DF->SendPage = (PGD_SENDPAGE)DED->pdrvfn[i].pfn;
200     if(DED->pdrvfn[i].iFunc == INDEX_DrvStartPage)       DF->StartPage = (PGD_STARTPAGE)DED->pdrvfn[i].pfn;
201     if(DED->pdrvfn[i].iFunc == INDEX_DrvEndDoc)          DF->EndDoc = (PGD_ENDDOC)DED->pdrvfn[i].pfn;
202     if(DED->pdrvfn[i].iFunc == INDEX_DrvStartDoc)        DF->StartDoc = (PGD_STARTDOC)DED->pdrvfn[i].pfn;
203     if(DED->pdrvfn[i].iFunc == INDEX_DrvGetGlyphMode)    DF->GetGlyphMode = (PGD_GETGLYPHMODE)DED->pdrvfn[i].pfn;
204     if(DED->pdrvfn[i].iFunc == INDEX_DrvSynchronize)     DF->Synchronize = (PGD_SYNCHRONIZE)DED->pdrvfn[i].pfn;
205     if(DED->pdrvfn[i].iFunc == INDEX_DrvSaveScreenBits)  DF->SaveScreenBits = (PGD_SAVESCREENBITS)DED->pdrvfn[i].pfn;
206     if(DED->pdrvfn[i].iFunc == INDEX_DrvGetModes)        DF->GetModes = (PGD_GETMODES)DED->pdrvfn[i].pfn;
207     if(DED->pdrvfn[i].iFunc == INDEX_DrvFree)            DF->Free = (PGD_FREE)DED->pdrvfn[i].pfn;
208     if(DED->pdrvfn[i].iFunc == INDEX_DrvDestroyFont)     DF->DestroyFont = (PGD_DESTROYFONT)DED->pdrvfn[i].pfn;
209     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontCaps)   DF->QueryFontCaps = (PGD_QUERYFONTCAPS)DED->pdrvfn[i].pfn;
210     if(DED->pdrvfn[i].iFunc == INDEX_DrvLoadFontFile)    DF->LoadFontFile = (PGD_LOADFONTFILE)DED->pdrvfn[i].pfn;
211     if(DED->pdrvfn[i].iFunc == INDEX_DrvUnloadFontFile)  DF->UnloadFontFile = (PGD_UNLOADFONTFILE)DED->pdrvfn[i].pfn;
212     if(DED->pdrvfn[i].iFunc == INDEX_DrvFontManagement)  DF->FontManagement = (PGD_FONTMANAGEMENT)DED->pdrvfn[i].pfn;
213     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryTrueTypeTable)
214       DF->QueryTrueTypeTable = (PGD_QUERYTRUETYPETABLE)DED->pdrvfn[i].pfn;
215     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryTrueTypeOutline)
216       DF->QueryTrueTypeOutline = (PGD_QUERYTRUETYPEOUTLINE)DED->pdrvfn[i].pfn;
217     if(DED->pdrvfn[i].iFunc == INDEX_DrvGetTrueTypeFile) DF->GetTrueTypeFile = (PGD_GETTRUETYPEFILE)DED->pdrvfn[i].pfn;
218     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryFontFile)   DF->QueryFontFile = (PGD_QUERYFONTFILE)DED->pdrvfn[i].pfn;
219     if(DED->pdrvfn[i].iFunc == INDEX_DrvQueryAdvanceWidths)
220       DF->QueryAdvanceWidths = (PGD_QUERYADVANCEWIDTHS)DED->pdrvfn[i].pfn;
221     if(DED->pdrvfn[i].iFunc == INDEX_DrvSetPixelFormat)  DF->SetPixelFormat = (PGD_SETPIXELFORMAT)DED->pdrvfn[i].pfn;
222     if(DED->pdrvfn[i].iFunc == INDEX_DrvDescribePixelFormat)
223       DF->DescribePixelFormat = (PGD_DESCRIBEPIXELFORMAT)DED->pdrvfn[i].pfn;
224     if(DED->pdrvfn[i].iFunc == INDEX_DrvSwapBuffers)     DF->SwapBuffers = (PGD_SWAPBUFFERS)DED->pdrvfn[i].pfn;
225     if(DED->pdrvfn[i].iFunc == INDEX_DrvStartBanding)    DF->StartBanding = (PGD_STARTBANDING)DED->pdrvfn[i].pfn;
226     if(DED->pdrvfn[i].iFunc == INDEX_DrvNextBand)        DF->NextBand = (PGD_NEXTBAND)DED->pdrvfn[i].pfn;
227 #if 0
228     if(DED->pdrvfn[i].iFunc == INDEX_DrvGetDirectDrawInfo) DF->GETDIRECTDRAWINFO = (PGD_)DED->pdrvfn[i].pfn;
229     if(DED->pdrvfn[i].iFunc == INDEX_DrvEnableDirectDraw)  DF->ENABLEDIRECTDRAW = (PGD_)DED->pdrvfn[i].pfn;
230     if(DED->pdrvfn[i].iFunc == INDEX_DrvDisableDirectDraw) DF->DISABLEDIRECTDRAW = (PGD_)DED->pdrvfn[i].pfn;
231 #endif
232     if(DED->pdrvfn[i].iFunc == INDEX_DrvQuerySpoolType)  DF->QuerySpoolType = (PGD_QUERYSPOOLTYPE)DED->pdrvfn[i].pfn;
233   }
234
235   return TRUE;
236 }
237
238 typedef VP_STATUS (*PMP_DRIVERENTRY)(PVOID, PVOID);
239
240 HANDLE DRIVER_FindMPDriver(LPCWSTR  Name)
241 {
242   OBJECT_ATTRIBUTES ObjectAttributes;
243   UNICODE_STRING DeviceName;
244   IO_STATUS_BLOCK Iosb;
245   HANDLE DisplayHandle;
246   NTSTATUS Status;
247   PEPROCESS CurrentProcess;
248
249   CurrentProcess = PsGetCurrentProcess();
250   if (CurrentProcess != Win32kDeviceProcess)
251     {
252       /* Switch to process context in which handle is to be valid */
253       KeAttachProcess(Win32kDeviceProcess);
254     }
255
256   RtlInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1");
257   InitializeObjectAttributes(&ObjectAttributes,
258                              &DeviceName,
259                              0,
260                              NULL,
261                              NULL);
262   Status = ZwOpenFile(&DisplayHandle,
263                       FILE_ALL_ACCESS,
264                       &ObjectAttributes,
265                       &Iosb,
266                       0,
267                       FILE_SYNCHRONOUS_IO_ALERT);
268
269   if (CurrentProcess != Win32kDeviceProcess)
270     {
271       KeDetachProcess();
272     }
273
274   if (!NT_SUCCESS(Status))
275     {
276       DPRINT("ZwOpenFile() failed (Status %lx)\n", Status);
277       return(NULL);
278     }
279
280   return(DisplayHandle);
281 }
282
283
284 BOOL DRIVER_UnregisterDriver(LPCWSTR  Name)
285 {
286   PGRAPHICS_DRIVER  Driver = NULL;
287   
288   if (Name)
289   {
290     if (DriverList != NULL)
291     {
292       if (!_wcsicmp(DriverList->Name, Name))
293       {
294         Driver = DriverList;
295         DriverList = DriverList->Next;
296       }
297       else
298       {
299         Driver = DriverList;
300         while (Driver->Next && _wcsicmp(Driver->Name, Name))
301         {
302           Driver = Driver->Next;
303         }
304       }
305     }
306   }
307   else
308   {    
309     if (GenericDriver != NULL)
310     {
311       Driver = GenericDriver;
312       GenericDriver = NULL;
313     }
314   }
315   
316   if (Driver != NULL)
317   {
318     ExFreePool(Driver->Name);
319     ExFreePool(Driver);
320       
321     return  TRUE;
322   }
323   else
324   {
325     return  FALSE;
326   }
327 }
328
329 INT DRIVER_ReferenceDriver (LPCWSTR  Name)
330 {
331   GRAPHICS_DRIVER *Driver = DriverList;
332   
333   while (Driver && Name)
334   {
335     DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
336     if (!_wcsicmp( Driver->Name, Name)) 
337     {
338       return ++Driver->ReferenceCount;
339     }
340     Driver = Driver->Next;
341   }
342   DPRINT( "Driver %S not found to reference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
343   assert( GenericDriver != 0 );
344   return ++GenericDriver->ReferenceCount;
345 }
346
347 INT DRIVER_UnreferenceDriver (LPCWSTR  Name)
348 {
349   GRAPHICS_DRIVER *Driver = DriverList;
350   
351   while (Driver && Name)
352   {
353     DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
354     if (!_wcsicmp( Driver->Name, Name)) 
355     {
356       return --Driver->ReferenceCount;
357     }
358     Driver = Driver->Next;
359   }
360   DPRINT( "Driver '%S' not found to dereference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
361   assert( GenericDriver != 0 );
362   return --GenericDriver->ReferenceCount;
363 }
364 /* EOF */