diff --git a/win32ss/user/user32/include/user32.h b/win32ss/user/user32/include/user32.h index 2615fb61549..0eb01deeb71 100644 --- a/win32ss/user/user32/include/user32.h +++ b/win32ss/user/user32/include/user32.h @@ -72,4 +72,36 @@ typedef struct _PATRECT HBRUSH hBrush; } PATRECT, * PPATRECT; +#include "pshpack1.h" + +typedef struct { + BYTE bWidth; + BYTE bHeight; + BYTE bColorCount; + BYTE bReserved; + WORD xHotspot; + WORD yHotspot; + DWORD dwDIBSize; + DWORD dwDIBOffset; +} CURSORICONFILEDIRENTRY; + +typedef struct +{ + WORD idReserved; + WORD idType; + WORD idCount; + CURSORICONFILEDIRENTRY idEntries[1]; +} CURSORICONFILEDIR; + +#include "poppack.h" + +const CURSORICONFILEDIRENTRY* +get_best_icon_file_entry( + _In_ const CURSORICONFILEDIR* dir, + _In_ DWORD dwFileSize, + _In_ int cxDesired, + _In_ int cyDesired, + _In_ BOOL bIcon, + _In_ DWORD fuLoad); + #endif /* _USER32_PCH_ */ diff --git a/win32ss/user/user32/misc/exticon.c b/win32ss/user/user32/misc/exticon.c index ba2bd6d6b2c..97eeb1fa754 100644 --- a/win32ss/user/user32/misc/exticon.c +++ b/win32ss/user/user32/misc/exticon.c @@ -249,6 +249,11 @@ static BYTE * ICO_GetIconDirectory( LPBYTE peimage, LPicoICONDIR* lplpiID, ULONG return 0; } +static int get_dib_image_size( int width, int height, int depth ) +{ + return (((width * depth + 31) / 8) & ~3) * abs( height ); +} + /************************************************************************* * ICO_ExtractIconExW [internal] * @@ -438,36 +443,70 @@ static UINT ICO_ExtractIconExW( { DWORD dataOffset; LPBYTE imageData; - POINT hotSpot; - LPICONIMAGE entry; - - dataOffset = get_best_icon_file_offset(peimage, fsizel, cx[index], cy[index], sig == 1, flags, sig == 1 ? NULL : &hotSpot); - - if (dataOffset) + const CURSORICONFILEDIR *dir; + const CURSORICONFILEDIRENTRY *entry; + LPBITMAPINFOHEADER pbi; + LPBITMAPCOREHEADER pbc; + + dir = (const CURSORICONFILEDIR*)peimage; + entry = get_best_icon_file_entry(dir, fsizel, cx[index], cy[index], sig == 1, flags); + dataOffset = entry->dwDIBOffset; + if (entry && dataOffset) { HICON icon; WORD *cursorData = NULL; + DWORD imageSize, index; + dataOffset = entry->dwDIBOffset; imageData = peimage + dataOffset; - entry = (LPICONIMAGE)(imageData); + pbi = (LPBITMAPINFOHEADER)imageData; + if (pbi->biSize == sizeof(BITMAPCOREHEADER)) + { + pbc = (LPBITMAPCOREHEADER)imageData; + imageSize = pbc->bcSize; + if (pbc->bcBitCount < 8) + imageSize += (1 << pbc->bcBitCount) * sizeof(RGBTRIPLE); + imageSize += get_dib_image_size(pbc->bcWidth, pbc->bcHeight / 2, pbc->bcBitCount); + imageSize += get_dib_image_size(pbc->bcWidth, pbc->bcHeight / 2, 1); + } + else + { + imageSize = pbi->biSize; + if (pbi->biBitCount < 8) + imageSize += (1 << pbi->biBitCount) * sizeof(RGBQUAD); + imageSize += get_dib_image_size(pbi->biWidth, pbi->biHeight / 2, pbi->biBitCount); + imageSize += get_dib_image_size(pbi->biWidth, pbi->biHeight / 2, 1); + } + ERR("imageSize: %08X\n", imageSize); + + if (imageSize != entry->dwDIBSize) + { + ERR("mismatch %08lX, %08lX\n", imageSize, entry->dwDIBSize); + } if(sig == 2) { /* we need to prepend the bitmap data with hot spots for CreateIconFromResourceEx */ - cursorData = HeapAlloc(GetProcessHeap(), 0, entry->icHeader.biSizeImage + 2 * sizeof(WORD)); + cursorData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, imageSize + 2 * sizeof(WORD)); if(!cursorData) continue; - cursorData[0] = hotSpot.x; - cursorData[1] = hotSpot.y; + cursorData[0] = entry->xHotspot; + cursorData[1] = entry->yHotspot; - memcpy(cursorData + 2, imageData, entry->icHeader.biSizeImage); + memcpy(cursorData + 2, imageData, entry->dwDIBSize); imageData = (LPBYTE)cursorData; + imageSize += 2 * sizeof(WORD); } + ERR("imageData: %p\n", imageData); - icon = CreateIconFromResourceEx(imageData, entry->icHeader.biSizeImage, sig == 1, 0x00030000, cx[index], cy[index], flags); + ERR("imageData: %02X %02X %02X %02X %02X %02X\n", + imageData[0], imageData[1], imageData[2], imageData[3], imageData[4], imageData[5]); + + /* Now imageData is a RT_ICON or RT_CURSOR */ + icon = CreateIconFromResourceEx(imageData, imageSize, sig == 1, 0x00030000, cx[index], cy[index], flags); HeapFree(GetProcessHeap(), 0, cursorData); @@ -481,6 +520,10 @@ static UINT ICO_ExtractIconExW( iconCount = 1; break; } + else + { + ERR("ERR1\n"); + } } } } diff --git a/win32ss/user/user32/windows/cursoricon.c b/win32ss/user/user32/windows/cursoricon.c index 6299c839006..540b81098d1 100644 --- a/win32ss/user/user32/windows/cursoricon.c +++ b/win32ss/user/user32/windows/cursoricon.c @@ -440,29 +440,6 @@ done: return alpha; } -#include "pshpack1.h" - -typedef struct { - BYTE bWidth; - BYTE bHeight; - BYTE bColorCount; - BYTE bReserved; - WORD xHotspot; - WORD yHotspot; - DWORD dwDIBSize; - DWORD dwDIBOffset; -} CURSORICONFILEDIRENTRY; - -typedef struct -{ - WORD idReserved; - WORD idType; - WORD idCount; - CURSORICONFILEDIRENTRY idEntries[1]; -} CURSORICONFILEDIR; - -#include "poppack.h" - const CURSORICONFILEDIRENTRY* get_best_icon_file_entry( _In_ const CURSORICONFILEDIR* dir, @@ -470,8 +447,7 @@ get_best_icon_file_entry( _In_ int cxDesired, _In_ int cyDesired, _In_ BOOL bIcon, - _In_ DWORD fuLoad -) + _In_ DWORD fuLoad) { CURSORICONDIR* fakeDir; CURSORICONDIRENTRY* fakeEntry; @@ -536,7 +512,8 @@ get_best_icon_file_entry( } /* Now call LookupIconIdFromResourceEx */ - i = LookupIconIdFromDirectoryEx((PBYTE)fakeDir, bIcon, cxDesired, cyDesired, fuLoad & LR_MONOCHROME); + ERR("get_best_icon_file_entry\n"); + i = LookupIconIdFromDirectoryEx((PBYTE)fakeDir, bIcon, cxDesired, cyDesired, fuLoad); /* We don't need this anymore */ HeapFree(GetProcessHeap(), 0, fakeDir); if(i == 0) @@ -600,7 +577,10 @@ static BOOL CURSORICON_GetCursorDataFromBMI( ibmpType = DIB_GetBitmapInfo(&pbmi->bmiHeader, &width, &height, &bpp, &compr); /* Invalid data */ if(ibmpType < 0) + { + ERR("ERR3\n"); return FALSE; + } /* No compression for icons */ if(compr != BI_RGB) @@ -1465,11 +1445,13 @@ CURSORICON_LoadImageW( if (!ustrModule.Buffer) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ERR("EE\n"); return NULL; } ret = GetModuleFileNameW(hinst, ustrModule.Buffer, size); if(ret == 0) { + ERR("eee\n"); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); return NULL; } @@ -1477,6 +1459,7 @@ CURSORICON_LoadImageW( /* This API is completely broken... */ if (ret == size) { + ERR("fff\n"); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); size *= 2; continue; @@ -1502,7 +1485,7 @@ CURSORICON_LoadImageW( if(hCurIcon) { /* Woohoo, got it! */ - TRACE("MATCH! %p\n",hCurIcon); + ERR("MATCH! %p\n",hCurIcon); HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); return hCurIcon; } @@ -1516,16 +1499,26 @@ CURSORICON_LoadImageW( /* We let FindResource, LoadResource, etc. call SetLastError */ if(!hrsrc) + { + ERR("&&&\n"); goto done; - + } + handle = LoadResource(hinst, hrsrc); if(!handle) + { + ERR("'''\n"); goto done; + } dir = LockResource(handle); if(!dir) + { + ERR("^^^^^\n"); goto done; + } + ERR("CURSORICON_LoadImageW\n"); wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad); FreeResource(handle); @@ -1535,15 +1528,22 @@ CURSORICON_LoadImageW( MAKEINTRESOURCEW(wResId), bIcon ? RT_ICON : RT_CURSOR); if(!hrsrc) + { + ERR("@@@@@\n"); goto done; + } handle = LoadResource(hinst, hrsrc); if(!handle) + { + ERR("$$$$$\n"); goto done; + } bits = LockResource(handle); if(!bits) { + ERR("!!!!!\n"); FreeResource(handle); goto done; } @@ -1573,12 +1573,16 @@ CURSORICON_LoadImageW( FreeResource( handle ); if(!bStatus) + { + ERR("===\n"); goto done; + } /* Create the handle */ hCurIcon = NtUserxCreateEmptyCurObject(FALSE); if(!hCurIcon) { + ERR("DDDD\n"); goto end_error; } @@ -1593,12 +1597,14 @@ CURSORICON_LoadImageW( if(!bStatus) { NtUserDestroyCursor(hCurIcon, TRUE); + ERR("HHHH\n"); goto end_error; } done: if(ustrModule.Buffer) HeapFree(GetProcessHeap(), 0, ustrModule.Buffer); + ERR("CCCCC\n"); return hCurIcon; end_error: @@ -1608,6 +1614,7 @@ end_error: if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); + ERR("BBBB\n"); return NULL; } @@ -2221,11 +2228,21 @@ int WINAPI LookupIconIdFromDirectoryEx( BOOL notPaletted = FALSE; ULONG bestScore = 0xFFFFFFFF, score; - TRACE("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired, Flags); + ERR("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired, Flags); - if(!(dir && !dir->idReserved && (dir->idType & 3))) + if (!dir || dir->idReserved || !dir->idCount) + { + ERR("Invalid resource.\n"); + return 0; + } + if (fIcon && dir->idType != 1) { - WARN("Invalid resource.\n"); + ERR("Invalid resource.\n"); + return 0; + } + if (!fIcon && dir->idType != 2) + { + ERR("Invalid resource.\n"); return 0; } @@ -2423,7 +2440,9 @@ HICON WINAPI CreateIconFromResourceEx( HICON hIcon; BOOL isAnimated; - TRACE("%p, %lu, %lu, %lu, %i, %i, %lu.\n", pbIconBits, cbIconBits, fIcon, dwVersion, cxDesired, cyDesired, uFlags); + ERR("%p, %lu, %lu, %lu, %i, %i, %lu.\n", pbIconBits, cbIconBits, fIcon, dwVersion, cxDesired, cyDesired, uFlags); + ERR("pbIconBits: %02X %02X %02X %02X %02X %02X %02X\n", + pbIconBits[0], pbIconBits[1], pbIconBits[2], pbIconBits[3], pbIconBits[4], pbIconBits[5], pbIconBits[6]); if(uFlags & LR_DEFAULTSIZE) { @@ -2448,6 +2467,9 @@ HICON WINAPI CreateIconFromResourceEx( } else { + { + ERR("CreateIconFromResourceEx\n"); + } /* It is possible to pass Icon Directories to this API */ int wResId = LookupIconIdFromDirectoryEx(pbIconBits, fIcon, cxDesired, cyDesired, uFlags); HANDLE ResHandle = NULL; @@ -2464,6 +2486,7 @@ HICON WINAPI CreateIconFromResourceEx( (LPCWSTR)pbIconBits, &hinst)) { + ERR("MMM\n"); return NULL; } @@ -2471,6 +2494,7 @@ HICON WINAPI CreateIconFromResourceEx( if((fIcon && pCurIconDir->idType == 2) || (!fIcon && pCurIconDir->idType == 1)) { WARN("Got a %s directory pointer, but called for a %s", fIcon ? "cursor" : "icon", fIcon ? "icon" : "cursor"); + ERR("NNN\n"); return NULL; } @@ -2480,15 +2504,21 @@ HICON WINAPI CreateIconFromResourceEx( MAKEINTRESOURCEW(wResId), fIcon ? RT_ICON : RT_CURSOR); if (!hrsrc) + { + ERR("OOO\n"); return NULL; + } ResHandle = LoadResource(hinst, hrsrc); if (!ResHandle) + { + ERR("PPP\n"); return NULL; - + } pbIconBits = LockResource(ResHandle); if (!pbIconBits) { + ERR("QQQ\n"); FreeResource(ResHandle); return NULL; } @@ -2518,7 +2548,10 @@ HICON WINAPI CreateIconFromResourceEx( hIcon = NtUserxCreateEmptyCurObject(isAnimated); if (!hIcon) + { + ERR("!hIcon\n"); goto end_error; + } if(!NtUserSetCursorIconData(hIcon, NULL, NULL, &cursorData)) { @@ -2530,6 +2563,7 @@ HICON WINAPI CreateIconFromResourceEx( if(isAnimated) HeapFree(GetProcessHeap(), 0, cursorData.aspcur); + ERR("KKK\n"); return hIcon; /* Clean up */ @@ -2539,7 +2573,7 @@ end_error: DeleteObject(cursorData.hbmMask); if(cursorData.hbmColor) DeleteObject(cursorData.hbmColor); if(cursorData.hbmAlpha) DeleteObject(cursorData.hbmAlpha); - + ERR("JJJ\n"); return NULL; }