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