- Update address of Free Software Foundation.
[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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 PDRIVERS DriverInfo;
232 hImageHandle = (HANDLE)GdiDriverInfo.ImageAddress;
233 DriverInfo = ExAllocatePool(PagedPool, sizeof(DRIVERS));
234 DriverInfo->DriverName.MaximumLength = GdiDriverInfo.DriverName.MaximumLength;
235 DriverInfo->DriverName.Length = GdiDriverInfo.DriverName.Length;
236 DriverInfo->DriverName.Buffer = ExAllocatePool(PagedPool, GdiDriverInfo.DriverName.MaximumLength);
237 RtlCopyUnicodeString(&DriverInfo->DriverName, &GdiDriverInfo.DriverName);
238 DriverInfo->ImageHandle = hImageHandle;
239 InsertHeadList(&GlobalDriverListHead, &DriverInfo->ListEntry);
240 }
241 }
242
243 return hImageHandle;
244 }
245
246 VOID
247 APIENTRY
248 EngUnloadImage ( IN HANDLE hModule )
249 {
250 NTSTATUS Status;
251
252 DPRINT("hModule 0x%x\n", hModule);
253
254 Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
255 &hModule, sizeof(HANDLE));
256
257 if(!NT_SUCCESS(Status))
258 {
259 DPRINT1("ZwSetSystemInformation failed with status 0x%08X\n",
260 Status);
261 }
262 else
263 {
264 /* remove from the list */
265 if( !IsListEmpty(&GlobalDriverListHead) )
266 {
267 PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink;
268 PDRIVERS Current;
269 /* probably the driver was already loaded, let's try to find it out */
270 while( CurrentEntry != &GlobalDriverListHead )
271 {
272 Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry);
273
274 if( Current ) {
275 if(Current->ImageHandle == hModule) {
276 ExFreePool(Current->DriverName.Buffer);
277 RemoveEntryList(&Current->ListEntry);
278 ExFreePool(Current);
279 break;
280 }
281 }
282 CurrentEntry = CurrentEntry->Flink;
283 };
284 }
285 }
286 }
287
288 /* EOF */