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