xref: /reactos/win32ss/gdi/gdi32/objects/gdiobj.c (revision c2c66aff)
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 || !cbSize) 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)) || (cbSize == 0) ) ) ||
269                 ( (dwType == GDI_OBJECT_TYPE_BITMAP) && (cbSize >= sizeof(BITMAP)) ))
270             {
271                 SetLastError(ERROR_NOACCESS);
272             }
273         }
274     }
275 
276     return cbResult;
277 }
278 
279 static
280 BOOL
281 GdiDeleteBrushOrPen(
282     HGDIOBJ hobj)
283 {
284     GDILOOBJTYPE eObjectType;
285     PBRUSH_ATTR pbrattr;
286     PTEB pTeb;
287     PGDIBSOBJECT pgO;
288 
289     eObjectType = GDI_HANDLE_GET_TYPE(hobj);
290 
291     if ((GdiGetHandleUserData(hobj, eObjectType, (PVOID*)&pbrattr)) &&
292         (pbrattr != NULL))
293     {
294         pTeb = NtCurrentTeb();
295         if (pTeb->Win32ThreadInfo != NULL)
296         {
297             pgO = GdiAllocBatchCommand(NULL, GdiBCDelObj);
298             if (pgO)
299             {
300                 /// FIXME: we need to mark the object as deleted!
301                 pgO->hgdiobj = hobj;
302                 return TRUE;
303             }
304         }
305     }
306 
307     return NtGdiDeleteObjectApp(hobj);
308 }
309 
310 /*
311  * @implemented
312  */
313 BOOL
314 WINAPI
315 DeleteObject(HGDIOBJ hObject)
316 {
317     /* Check if the handle is valid (FIXME: we need some special
318        sauce for the stock object flag) */
319     if (!GdiValidateHandle(hObject))
320         return FALSE;
321 
322     /* Check if this is a stock object */
323     if ((DWORD_PTR)hObject & GDI_HANDLE_STOCK_MASK)
324     {
325         /* Ignore the attempt to delete a stock object */
326         DPRINT("Trying to delete system object 0x%p\n", hObject);
327         return TRUE;
328     }
329 
330     /* If we have any METAFILE objects, we need to check them */
331     if (gcClientObj > 0)
332     {
333         METADC_DeleteObject(hObject);
334     }
335 
336     /* Switch by object type */
337     switch (GDI_HANDLE_GET_TYPE(hObject))
338     {
339         case GDILoObjType_LO_METAFILE16_TYPE:
340         case GDILoObjType_LO_METAFILE_TYPE:
341             return FALSE;
342 
343         case GDILoObjType_LO_DC_TYPE:
344         case GDILoObjType_LO_ALTDC_TYPE:
345             return DeleteDC(hObject);
346 
347         case GDILoObjType_LO_ICMLCS_TYPE:
348             return NtGdiDeleteColorSpace(hObject);
349 
350         case GDILoObjType_LO_REGION_TYPE:
351             return DeleteRegion(hObject);
352 #if 0
353         case GDI_OBJECT_TYPE_METADC:
354             return MFDRV_DeleteObject( hObject );
355         case GDI_OBJECT_TYPE_EMF:
356         {
357             PLDC pLDC = GdiGetLDC(hObject);
358             if ( !pLDC ) return FALSE;
359             return EMFDRV_DeleteObject( hObject );
360         }
361 #endif
362         case GDILoObjType_LO_BRUSH_TYPE:
363         case GDILoObjType_LO_PEN_TYPE:
364         case GDILoObjType_LO_EXTPEN_TYPE:
365             return GdiDeleteBrushOrPen(hObject);
366 
367         case GDILoObjType_LO_FONT_TYPE:
368         case GDILoObjType_LO_BITMAP_TYPE:
369         default:
370             break;
371     }
372 
373     return NtGdiDeleteObjectApp(hObject);
374 }
375 
376 
377