| 3171 | |
| 3172 | |
| 3173 | PBITMAPINFO CColorCopDlg::CreateBitmapInfoStruct(HWND /*hwnd*/, HBITMAP hBmp) { |
| 3174 | BITMAP bmp = {}; |
| 3175 | if (!GetObject(hBmp, sizeof(bmp), &bmp)) { |
| 3176 | AfxMessageBox(_T("Unable to receive bitmap information")); |
| 3177 | return nullptr; |
| 3178 | } |
| 3179 | |
| 3180 | // Compute effective color depth (clamped to standard buckets) |
| 3181 | WORD cClrBits = static_cast<WORD>(bmp.bmPlanes * bmp.bmBitsPixel); |
| 3182 | if (cClrBits <= 1) |
| 3183 | cClrBits = 1; |
| 3184 | else if (cClrBits <= 4) |
| 3185 | cClrBits = 4; |
| 3186 | else if (cClrBits <= 8) |
| 3187 | cClrBits = 8; |
| 3188 | else if (cClrBits <= 16) |
| 3189 | cClrBits = 16; |
| 3190 | else if (cClrBits <= 24) |
| 3191 | cClrBits = 24; |
| 3192 | else |
| 3193 | cClrBits = 32; |
| 3194 | |
| 3195 | // Compute palette size safely (avoid 1 << cClrBits overflow) |
| 3196 | DWORD clrUsed = 0; |
| 3197 | if (cClrBits < 24) { |
| 3198 | // max palette entries for <= 8bpp is 256; for 16/32bpp it's 0 |
| 3199 | clrUsed = (cClrBits <= 8) ? (1u << cClrBits) : 0u; |
| 3200 | } |
| 3201 | |
| 3202 | // Compute allocation size |
| 3203 | const SIZE_T headerSize = sizeof(BITMAPINFOHEADER); |
| 3204 | const SIZE_T paletteSize = clrUsed * sizeof(RGBQUAD); |
| 3205 | |
| 3206 | // Overflow check (defensive) |
| 3207 | if (paletteSize / sizeof(RGBQUAD) != clrUsed) { |
| 3208 | return nullptr; // overflow detected |
| 3209 | } |
| 3210 | |
| 3211 | const SIZE_T totalSize = headerSize + paletteSize; |
| 3212 | |
| 3213 | PBITMAPINFO pbmi = static_cast<PBITMAPINFO>(LocalAlloc(LPTR, totalSize)); |
| 3214 | if (!pbmi) { |
| 3215 | return nullptr; |
| 3216 | } |
| 3217 | |
| 3218 | // Initialize BITMAPINFOHEADER |
| 3219 | pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
| 3220 | pbmi->bmiHeader.biWidth = bmp.bmWidth; |
| 3221 | pbmi->bmiHeader.biHeight = bmp.bmHeight; |
| 3222 | pbmi->bmiHeader.biPlanes = bmp.bmPlanes; |
| 3223 | pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; |
| 3224 | pbmi->bmiHeader.biCompression = BI_RGB; |
| 3225 | pbmi->bmiHeader.biClrUsed = clrUsed; |
| 3226 | |
| 3227 | // Compute image size (DWORD-aligned scanlines) |
| 3228 | const DWORD bitsPerLine = bmp.bmWidth * cClrBits; |
| 3229 | const DWORD alignedBits = (bitsPerLine + 31u) & ~31u; |
| 3230 | pbmi->bmiHeader.biSizeImage = (alignedBits / 8u) * bmp.bmHeight; |
nothing calls this directly
no outgoing calls
no test coverage detected