d90f76ad2b8ae056473c73a3fa879f24a5b82cda
[reactos.git] / reactos / subsystems / win32 / win32k / ldr / loader.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 */
22
23 #include <w32k.h>
24
25 #define NDEBUG
26 #include <debug.h>
27
28
29 typedef struct _DRIVERS
30 {
31 LIST_ENTRY ListEntry;
32 HANDLE ImageHandle;
33 UNICODE_STRING DriverName;
34 }DRIVERS, *PDRIVERS;
35
36 extern LIST_ENTRY GlobalDriverListHead;
37
38 /*
39 * Blatantly stolen from ldr/utils.c in ntdll. I can't link ntdll from
40 * here, though.
41 */
42 NTSTATUS APIENTRY
43 LdrGetProcedureAddress (IN PVOID BaseAddress,
44 IN PANSI_STRING Name,
45 IN ULONG Ordinal,
46 OUT PVOID *ProcedureAddress)
47 {
48 PIMAGE_EXPORT_DIRECTORY ExportDir;
49 PUSHORT OrdinalPtr;
50 PULONG NamePtr;
51 PULONG AddressPtr;
52 ULONG i = 0;
53
54 DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n",
55 BaseAddress, Name, Ordinal, ProcedureAddress);
56
57 /* Get the pointer to the export directory */
58 ExportDir = (PIMAGE_EXPORT_DIRECTORY)
59 RtlImageDirectoryEntryToData (BaseAddress,
60 TRUE,
61 IMAGE_DIRECTORY_ENTRY_EXPORT,
62 &i);
63
64 DPRINT("ExportDir %x i %lu\n", ExportDir, i);
65
66 if (!ExportDir || !i || !ProcedureAddress)
67 {
68 return STATUS_INVALID_PARAMETER;
69 }
70
71 AddressPtr = (PULONG)((ULONG_PTR)BaseAddress + (ULONG)ExportDir->AddressOfFunctions);
72 if (Name && Name->Length)
73 {
74 /* by name */
75 OrdinalPtr = (PUSHORT)((ULONG_PTR)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals);
76 NamePtr = (PULONG)((ULONG_PTR)BaseAddress + (ULONG)ExportDir->AddressOfNames);
77 for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
78 {
79 if (!strcmp(Name->Buffer, (char*)((ULONG_PTR)BaseAddress + *NamePtr)))
80 {
81 *ProcedureAddress = (PVOID)((ULONG_PTR)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]);
82 return STATUS_SUCCESS;
83 }
84 }
85 DPRINT1("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
86 }
87 else
88 {
89 /* by ordinal */
90 Ordinal &= 0x0000FFFF;
91 if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
92 {
93 *ProcedureAddress = (PVOID)((ULONG_PTR)BaseAddress + (ULONG_PTR)AddressPtr[Ordinal - ExportDir->Base]);
94 return STATUS_SUCCESS;
95 }
96 DPRINT1("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
97 }
98
99 return STATUS_PROCEDURE_NOT_FOUND;
100 }
101
102 PVOID APIENTRY
103 EngFindImageProcAddress(IN HANDLE Module,
104 IN LPSTR ProcName)
105 {
106 PVOID Function;
107 NTSTATUS Status;
108 ANSI_STRING ProcNameString;
109 unsigned i;
110 static struct
111 {
112 PCSTR ProcName;
113 PVOID ProcAddress;
114 }
115 Win32kExports[] =
116 {
117 { "BRUSHOBJ_hGetColorTransform", BRUSHOBJ_hGetColorTransform },
118 { "EngAlphaBlend", EngAlphaBlend },
119 { "EngClearEvent", EngClearEvent },
120 { "EngControlSprites", EngControlSprites },
121 { "EngCreateEvent", EngCreateEvent },
122 { "EngDeleteEvent", EngDeleteEvent },
123 { "EngDeleteFile", EngDeleteFile },
124 { "EngDeleteSafeSemaphore", EngDeleteSafeSemaphore },
125 { "EngDeleteWnd", EngDeleteWnd },
126 { "EngDitherColor", EngDitherColor },
127 { "EngGetPrinterDriver", EngGetPrinterDriver },
128 { "EngGradientFill", EngGradientFill },
129 { "EngHangNotification", EngHangNotification },
130 { "EngInitializeSafeSemaphore", EngInitializeSafeSemaphore },
131 { "EngLockDirectDrawSurface", EngLockDirectDrawSurface },
132 { "EngLpkInstalled", EngLpkInstalled },
133 { "EngMapEvent", EngMapEvent },
134 { "EngMapFile", EngMapFile },
135 { "EngMapFontFileFD", EngMapFontFileFD },
136 { "EngModifySurface", EngModifySurface },
137 { "EngMovePointer", EngMovePointer },
138 { "EngPlgBlt", EngPlgBlt },
139 { "EngQueryDeviceAttribute", EngQueryDeviceAttribute },
140 { "EngQueryPalette", EngQueryPalette },
141 { "EngQuerySystemAttribute", EngQuerySystemAttribute },
142 { "EngReadStateEvent", EngReadStateEvent },
143 { "EngRestoreFloatingPointState", EngRestoreFloatingPointState },
144 { "EngSaveFloatingPointState", EngSaveFloatingPointState },
145 { "EngSetEvent", EngSetEvent },
146 { "EngSetPointerShape", EngSetPointerShape },
147 { "EngSetPointerTag", EngSetPointerTag },
148 { "EngStretchBltROP", EngStretchBltROP },
149 { "EngTransparentBlt", EngTransparentBlt },
150 { "EngUnlockDirectDrawSurface", EngUnlockDirectDrawSurface },
151 { "EngUnmapEvent", EngUnmapEvent },
152 { "EngUnmapFile", EngUnmapFile },
153 { "EngUnmapFontFileFD", EngUnmapFontFileFD },
154 { "EngWaitForSingleObject", EngWaitForSingleObject },
155 { "FONTOBJ_pfdg", FONTOBJ_pfdg },
156 { "FONTOBJ_pjOpenTypeTablePointer", FONTOBJ_pjOpenTypeTablePointer },
157 { "FONTOBJ_pQueryGlyphAttrs", FONTOBJ_pQueryGlyphAttrs },
158 { "FONTOBJ_pwszFontFilePaths", FONTOBJ_pwszFontFilePaths },
159 { "HeapVidMemAllocAligned", HeapVidMemAllocAligned },
160 { "HT_Get8BPPMaskPalette", HT_Get8BPPMaskPalette },
161 { "STROBJ_bEnumPositionsOnly", STROBJ_bEnumPositionsOnly },
162 { "STROBJ_bGetAdvanceWidths", STROBJ_bGetAdvanceWidths },
163 { "STROBJ_fxBreakExtra", STROBJ_fxBreakExtra },
164 { "STROBJ_fxCharacterExtra", STROBJ_fxCharacterExtra },
165 { "VidMemFree", VidMemFree },
166 { "XLATEOBJ_hGetColorTransform", XLATEOBJ_hGetColorTransform }
167 };
168
169 if (NULL == Module)
170 {
171 DPRINT("Looking for win32k export %s\n", ProcName);
172 for (i = 0; i < sizeof(Win32kExports) / sizeof(Win32kExports[0]); i++)
173 {
174 if (0 == strcmp(ProcName, Win32kExports[i].ProcName))
175 {
176 DPRINT("Found it index %u address %p\n", i, Win32kExports[i].ProcName);
177 return Win32kExports[i].ProcAddress;
178 }
179 }
180 return NULL;
181 }
182 RtlInitAnsiString(&ProcNameString, ProcName);
183 Status = LdrGetProcedureAddress(Module,
184 &ProcNameString,
185 0,
186 &Function);
187 if (!NT_SUCCESS(Status))
188 {
189 return(NULL);
190 }
191 return(Function);
192 }
193
194
195 /*
196 * @implemented
197 */
198 HANDLE
199 APIENTRY
200 EngLoadImage (LPWSTR DriverName)
201 {
202 HANDLE hImageHandle = NULL;
203 SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
204 NTSTATUS Status;
205
206 RtlInitUnicodeString(&GdiDriverInfo.DriverName, DriverName);
207 if( !IsListEmpty(&GlobalDriverListHead) )
208 {
209 PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink;
210 PDRIVERS Current;
211 /* probably the driver was already loaded, let's try to find it out */
212 while( CurrentEntry != &GlobalDriverListHead )
213 {
214 Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry);
215 if( Current && (0 == RtlCompareUnicodeString(&GdiDriverInfo.DriverName, &Current->DriverName, FALSE)) ) {
216 hImageHandle = Current->ImageHandle;
217 break;
218 }
219 CurrentEntry = CurrentEntry->Flink;
220 };
221 }
222
223 if( !hImageHandle )
224 {
225 /* the driver was not loaded before, so let's do that */
226 Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
227 if (!NT_SUCCESS(Status)) {
228 DPRINT1("ZwSetSystemInformation failed with Status 0x%lx\n", Status);
229 }
230 else {
231 hImageHandle = (HANDLE)GdiDriverInfo.ImageAddress;
232 PDRIVERS DriverInfo = ExAllocatePool(PagedPool, sizeof(DRIVERS));
233 DriverInfo->DriverName.MaximumLength = GdiDriverInfo.DriverName.MaximumLength;
234 DriverInfo->DriverName.Length = GdiDriverInfo.DriverName.Length;
235 DriverInfo->DriverName.Buffer = ExAllocatePool(PagedPool, GdiDriverInfo.DriverName.MaximumLength);
236 RtlCopyUnicodeString(&DriverInfo->DriverName, &GdiDriverInfo.DriverName);
237 DriverInfo->ImageHandle = hImageHandle;
238 InsertHeadList(&GlobalDriverListHead, &DriverInfo->ListEntry);
239 }
240 }
241
242 return hImageHandle;
243 }
244
245
246 /*
247 * @unimplemented
248 */
249 HANDLE
250 APIENTRY
251 EngLoadModule(LPWSTR ModuleName)
252 {
253 SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
254 NTSTATUS Status;
255
256 // FIXME: should load as readonly
257
258 RtlInitUnicodeString (&GdiDriverInfo.DriverName, ModuleName);
259 Status = ZwSetSystemInformation (SystemLoadGdiDriverInformation,
260 &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
261 if (!NT_SUCCESS(Status)) return NULL;
262
263 return (HANDLE)GdiDriverInfo.ImageAddress;
264 }
265
266 VOID
267 APIENTRY
268 EngUnloadImage ( IN HANDLE hModule )
269 {
270 NTSTATUS Status;
271
272 DPRINT("hModule 0x%x\n", hModule);
273
274 Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
275 &hModule, sizeof(HANDLE));
276
277 if(!NT_SUCCESS(Status))
278 {
279 DPRINT1("ZwSetSystemInformation failed with status 0x%08X\n",
280 Status);
281 }
282 else
283 {
284 /* remove from the list */
285 if( !IsListEmpty(&GlobalDriverListHead) )
286 {
287 PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink;
288 PDRIVERS Current;
289 /* probably the driver was already loaded, let's try to find it out */
290 while( CurrentEntry != &GlobalDriverListHead )
291 {
292 Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry);
293
294 if( Current ) {
295 if(Current->ImageHandle == hModule) {
296 ExFreePool(Current->DriverName.Buffer);
297 RemoveEntryList(&Current->ListEntry);
298 ExFreePool(Current);
299 break;
300 }
301 }
302 CurrentEntry = CurrentEntry->Flink;
303 };
304 }
305 }
306 }
307
308 /* EOF */