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