1 #include <precomp.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
7
8 /*
9 * @implemented
10 */
11 HGDIOBJ
12 WINAPI
GetStockObject(INT fnObject)13 GetStockObject(
14 INT fnObject)
15 {
16 HGDIOBJ hobj;
17
18 if ((fnObject < 0) || (fnObject >= NB_STOCK_OBJECTS))
19 return NULL;
20
21 hobj = stock_objects[fnObject];
22 if (hobj == NULL)
23 {
24 hobj = NtGdiGetStockObject(fnObject);
25
26 if (!GdiValidateHandle(hobj))
27 {
28 return NULL;
29 }
30
31 stock_objects[fnObject] = hobj;
32 }
33
34 return hobj;
35 }
36
37
38 /*
39 * @implemented
40 */
41 DWORD
42 WINAPI
GetObjectType(HGDIOBJ h)43 GetObjectType(
44 HGDIOBJ h)
45 {
46 DWORD Ret = 0;
47
48 if (GdiValidateHandle(h))
49 {
50 LONG Type = GDI_HANDLE_GET_TYPE(h);
51 switch(Type)
52 {
53 case GDI_OBJECT_TYPE_PEN:
54 Ret = OBJ_PEN;
55 break;
56 case GDI_OBJECT_TYPE_BRUSH:
57 Ret = OBJ_BRUSH;
58 break;
59 case GDI_OBJECT_TYPE_BITMAP:
60 Ret = OBJ_BITMAP;
61 break;
62 case GDI_OBJECT_TYPE_FONT:
63 Ret = OBJ_FONT;
64 break;
65 case GDI_OBJECT_TYPE_PALETTE:
66 Ret = OBJ_PAL;
67 break;
68 case GDI_OBJECT_TYPE_REGION:
69 Ret = OBJ_REGION;
70 break;
71 case GDI_OBJECT_TYPE_DC:
72 if ( GetDCDWord( h, GdiGetIsMemDc, 0))
73 {
74 Ret = OBJ_MEMDC;
75 }
76 else
77 Ret = OBJ_DC;
78 break;
79 case GDI_OBJECT_TYPE_COLORSPACE:
80 Ret = OBJ_COLORSPACE;
81 break;
82 case GDI_OBJECT_TYPE_METAFILE:
83 Ret = OBJ_METAFILE;
84 break;
85 case GDI_OBJECT_TYPE_ENHMETAFILE:
86 Ret = OBJ_ENHMETAFILE;
87 break;
88 case GDI_OBJECT_TYPE_METADC:
89 Ret = OBJ_METADC;
90 break;
91 case GDI_OBJECT_TYPE_EXTPEN:
92 Ret = OBJ_EXTPEN;
93 break;
94
95 case GDILoObjType_LO_ALTDC_TYPE:
96 // FIXME: could be something else?
97 Ret = OBJ_ENHMETADC;
98 break;
99
100 default:
101 DPRINT1("GetObjectType: Magic 0x%08x not implemented\n", Type);
102 break;
103 }
104 }
105 else
106 /* From Wine: GetObjectType does SetLastError() on a null object */
107 SetLastError(ERROR_INVALID_HANDLE);
108 return Ret;
109 }
110
111 ULONG
112 WINAPI
GetFontObjectA(_In_ HGDIOBJ hfont,_In_ ULONG cbSize,_Out_ LPVOID lpBuffer)113 GetFontObjectA(
114 _In_ HGDIOBJ hfont,
115 _In_ ULONG cbSize,
116 _Out_ LPVOID lpBuffer)
117 {
118 ENUMLOGFONTEXDVW elfedvW;
119 ENUMLOGFONTEXDVA elfedvA;
120 ULONG cbResult;
121
122 /* Check if size only is requested */
123 if (!lpBuffer) return sizeof(LOGFONTA);
124
125 /* Check for size 0 */
126 if (cbSize == 0)
127 {
128 /* Windows does not SetLastError() */
129 return 0;
130 }
131
132 /* Windows does this ... */
133 if (cbSize == sizeof(LOGFONTW)) cbSize = sizeof(LOGFONTA);
134
135 /* Call win32k to get the logfont (widechar) */
136 cbResult = NtGdiExtGetObjectW(hfont, sizeof(ENUMLOGFONTEXDVW), &elfedvW);
137 if (cbResult == 0)
138 {
139 return 0;
140 }
141
142 /* Convert the logfont from widechar to ansi */
143 EnumLogFontExW2A(&elfedvA.elfEnumLogfontEx, &elfedvW.elfEnumLogfontEx);
144 elfedvA.elfDesignVector = elfedvW.elfDesignVector;
145
146 /* Don't copy more than maximum */
147 if (cbSize > sizeof(ENUMLOGFONTEXDVA)) cbSize = sizeof(ENUMLOGFONTEXDVA);
148
149 /* Copy the number of bytes requested */
150 memcpy(lpBuffer, &elfedvA, cbSize);
151
152 /* Return the number of bytes copied */
153 return cbSize;
154 }
155
156
157 /*
158 * @implemented
159 */
160 int
161 WINAPI
GetObjectA(_In_ HGDIOBJ hGdiObj,_In_ int cbSize,_Out_ LPVOID lpBuffer)162 GetObjectA(
163 _In_ HGDIOBJ hGdiObj,
164 _In_ int cbSize,
165 _Out_ LPVOID lpBuffer)
166 {
167 DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
168
169 /* Chjeck if this is anything else but a font */
170 if (dwType == GDI_OBJECT_TYPE_FONT)
171 {
172 return GetFontObjectA(hGdiObj, cbSize, lpBuffer);
173 }
174 else
175 {
176 /* Simply pass it to the widechar version */
177 return GetObjectW(hGdiObj, cbSize, lpBuffer);
178 }
179 }
180
181
182 /*
183 * @implemented
184 */
185 int
186 WINAPI
GetObjectW(_In_ HGDIOBJ hGdiObj,_In_ int cbSize,_Out_ LPVOID lpBuffer)187 GetObjectW(
188 _In_ HGDIOBJ hGdiObj,
189 _In_ int cbSize,
190 _Out_ LPVOID lpBuffer)
191 {
192 DWORD dwType;
193 INT cbResult = 0;
194
195 /* Fixup handles with upper 16 bits masked */
196 hGdiObj = GdiFixUpHandle(hGdiObj);
197
198 /* Get the object type */
199 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
200
201 /* Check what kind of object we have */
202 switch (dwType)
203 {
204 case GDI_OBJECT_TYPE_PEN:
205 if (!lpBuffer) return sizeof(LOGPEN);
206 break;
207
208 case GDI_OBJECT_TYPE_BRUSH:
209 if (!lpBuffer) return sizeof(LOGBRUSH);
210 break;
211
212 case GDI_OBJECT_TYPE_BITMAP:
213 if (!lpBuffer) return sizeof(BITMAP);
214 break;
215
216 case GDI_OBJECT_TYPE_PALETTE:
217 if (!lpBuffer) return sizeof(WORD);
218 break;
219
220 case GDI_OBJECT_TYPE_FONT:
221 if (!lpBuffer) return sizeof(LOGFONTW);
222 break;
223
224 case GDI_OBJECT_TYPE_EXTPEN:
225 /* we don't know the size, ask win32k */
226 break;
227
228 case GDI_OBJECT_TYPE_COLORSPACE:
229 if ((cbSize < 328) || !lpBuffer)
230 {
231 SetLastError(ERROR_INSUFFICIENT_BUFFER);
232 return 0;
233 }
234 break;
235
236 case GDI_OBJECT_TYPE_DC:
237 case GDI_OBJECT_TYPE_REGION:
238 case GDI_OBJECT_TYPE_EMF:
239 case GDI_OBJECT_TYPE_METAFILE:
240 case GDI_OBJECT_TYPE_ENHMETAFILE:
241 SetLastError(ERROR_INVALID_HANDLE);
242 default:
243 return 0;
244 }
245
246 /* Call win32k */
247 cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
248
249 /* Handle error */
250 if (cbResult == 0)
251 {
252 if (!GdiValidateHandle(hGdiObj))
253 {
254 if ((dwType == GDI_OBJECT_TYPE_PEN) ||
255 (dwType == GDI_OBJECT_TYPE_EXTPEN) ||
256 (dwType == GDI_OBJECT_TYPE_BRUSH) ||
257 (dwType == GDI_OBJECT_TYPE_COLORSPACE))
258 {
259 SetLastError(ERROR_INVALID_PARAMETER);
260 }
261 }
262 else
263 {
264 if ((dwType == GDI_OBJECT_TYPE_PEN) ||
265 (dwType == GDI_OBJECT_TYPE_BRUSH) ||
266 (dwType == GDI_OBJECT_TYPE_COLORSPACE) ||
267 ( (dwType == GDI_OBJECT_TYPE_EXTPEN) &&
268 ( (cbSize >= sizeof(EXTLOGPEN)))) ||
269 ( (dwType == GDI_OBJECT_TYPE_BITMAP) && (cbSize >= sizeof(BITMAP)) ))
270 {
271 if (cbSize)
272 SetLastError(ERROR_NOACCESS);
273 }
274 }
275 }
276
277 return cbResult;
278 }
279
280 static
281 BOOL
GdiDeleteBrushOrPen(HGDIOBJ hobj)282 GdiDeleteBrushOrPen(
283 HGDIOBJ hobj)
284 {
285 GDILOOBJTYPE eObjectType;
286 PBRUSH_ATTR pbrattr;
287 PTEB pTeb;
288 PGDIBSOBJECT pgO;
289
290 eObjectType = GDI_HANDLE_GET_TYPE(hobj);
291
292 if ((GdiGetHandleUserData(hobj, eObjectType, (PVOID*)&pbrattr)) &&
293 (pbrattr != NULL))
294 {
295 pTeb = NtCurrentTeb();
296 if (pTeb->Win32ThreadInfo != NULL)
297 {
298 pgO = GdiAllocBatchCommand(NULL, GdiBCDelObj);
299 if (pgO)
300 {
301 /// FIXME: we need to mark the object as deleted!
302 pgO->hgdiobj = hobj;
303 return TRUE;
304 }
305 }
306 }
307
308 return NtGdiDeleteObjectApp(hobj);
309 }
310
311 /*
312 * @implemented
313 */
314 BOOL
315 WINAPI
DeleteObject(HGDIOBJ hObject)316 DeleteObject(HGDIOBJ hObject)
317 {
318 /* Check if the handle is valid (FIXME: we need some special
319 sauce for the stock object flag) */
320 if (!GdiValidateHandle(hObject))
321 return FALSE;
322
323 /* Check if this is a stock object */
324 if (GDI_HANDLE_IS_STOCKOBJ(hObject))
325 {
326 /* Ignore the attempt to delete a stock object */
327 DPRINT1("Trying to delete system object 0x%p\n", hObject);
328 return TRUE;
329 }
330
331 /* If we have any METAFILE objects, we need to check them */
332 if (gcClientObj > 0)
333 {
334 DPRINT("Going Glue\n");
335 METADC_RosGlueDeleteObject(hObject);
336 }
337
338 /* Switch by object type */
339 switch (GDI_HANDLE_GET_TYPE(hObject))
340 {
341 case GDILoObjType_LO_METAFILE16_TYPE:
342 case GDILoObjType_LO_METAFILE_TYPE:
343 return FALSE;
344
345 case GDILoObjType_LO_DC_TYPE:
346 case GDILoObjType_LO_ALTDC_TYPE:
347 return DeleteDC(hObject);
348
349 case GDILoObjType_LO_ICMLCS_TYPE:
350 return NtGdiDeleteColorSpace(hObject);
351
352 case GDILoObjType_LO_REGION_TYPE:
353 return DeleteRegion(hObject);
354
355 case GDILoObjType_LO_BRUSH_TYPE:
356 case GDILoObjType_LO_PEN_TYPE:
357 case GDILoObjType_LO_EXTPEN_TYPE:
358 return GdiDeleteBrushOrPen(hObject);
359
360 case GDILoObjType_LO_FONT_TYPE:
361 case GDILoObjType_LO_BITMAP_TYPE:
362 default:
363 break;
364 }
365
366 return NtGdiDeleteObjectApp(hObject);
367 }
368
369
370