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