xref: /reactos/win32ss/gdi/gdi32/objects/gdiobj.c (revision 84344399)
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
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
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
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
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
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
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
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