See what's going on with flipcode!

This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.


  Bitmap Resource Extraction
  Submitted by

As a result of searching for some good icons and bitmaps for use in buttons, I found some programs that could be used to extract the resources inside exe and dll files. Most of them, at least the ones that I have found, we're limited in functionality as they are shareware or whatever. Anyway, I just disliked it, and though that it couldn't be too hard to extract the bitmap resources from those modules, so I started up MSDEV and the MSDN libraries, and got me this piece of code after a few minutes... Saving of the HBITMAP is a complete copy-paste from the MSDN, and the rest is too difficult either. Anyway, it doesn't do good error handling, and also the destination of the ".bmp" files is fixed in the code: "c:\res"... just compile it, and run it at c:\ or something, and your complete harddrive will be searched for bitmap resources, in any file that can be loaded by the LoadLibraryEx(...) method. Depending on the number of files, this could take hours... (it took me 56minutes, not really worth the garbage, but oh well...) Also, after running this on my disk, one thing I noticed was that I have about 115MB of which nearly 50% contain the same icons over and over again. It's amazing to see how many developers just create their own collection, and use it as an internal resource, while most of them are inside the comctl32.dll, user32.dll, or shell32.dll. Tom van Dijck

Download Associated File: bitmapRip.cpp (7,224 bytes)

#include <windows.h>
#include <stdio.h>

static char staticDir[512]; static char moduleName[512]; static char progressText[] = "/-\\|"; static char progress = 0; static int time, lastTime;

#pragma comment(lib, "Winmm.lib")

bool CheckExt(char* a_Name, char* a_Extension) { int len = strlen(a_Name)-1; int extLen = strlen(a_Extension)-1; bool found = true;

while (len >= 0 && extLen >= 0 && found) { found = (a_Name[len] == a_Extension[extLen]); len--; extLen--; } return found; }

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp) { BITMAP bmp; PBITMAPINFO pbmi; WORD cClrBits; // Retrieve the bitmap's color format, width, and height. GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp); // Convert the color format to a count of bits. cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); if (cClrBits == 1) cClrBits = 1; else if (cClrBits <= 4) cClrBits = 4; else if (cClrBits <= 8) cClrBits = 8; else if (cClrBits <= 16) cClrBits = 16; else if (cClrBits <= 24) cClrBits = 24; else cClrBits = 32; // Allocate memory for the BITMAPINFO structure. (This structure // contains a BITMAPINFOHEADER structure and an array of RGBQUAD // data structures.) if (cClrBits != 24) pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits)); // There is no RGBQUAD array for the 24-bit-per-pixel format. else pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER)); // Initialize the fields in the BITMAPINFO structure. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1<<cClrBits); // If the bitmap is not compressed, set the BI_RGB flag. pbmi->bmiHeader.biCompression = BI_RGB; // Compute the number of bytes in the array of color // indices and store the result in biSizeImage. // For Windows NT/2000, the width must be DWORD aligned unless // the bitmap is RLE compressed. This example shows this. // For Windows 95/98, the width must be WORD aligned unless the // bitmap is RLE compressed. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0; return pbmi; }

int CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC) { HANDLE hf; // file handle BITMAPFILEHEADER hdr; // bitmap file-header PBITMAPINFOHEADER pbih; // bitmap info-header LPBYTE lpBits; // memory pointer DWORD dwTotal; // total count of bytes DWORD cb; // incremental count of bytes BYTE *hp; // byte pointer DWORD dwTmp; pbih = (PBITMAPINFOHEADER) pbi; lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage); if (!lpBits) { return -1; } // Retrieve the color table (RGBQUAD array) and the bits // (array of palette indices) from the DIB. if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)) { return -1; } // Create the .BMP file. hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); if (hf == INVALID_HANDLE_VALUE) { return -1; }

hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" // Compute the size of the entire file. hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage); hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; // Compute the offset to the array of color indices. hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD); // Copy the BITMAPFILEHEADER into the .BMP file. if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) { return -1; } // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. if (!WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof(RGBQUAD), (LPDWORD)&dwTmp, NULL)) { return -1; } // Copy the array of color indices into the .BMP file. dwTotal = cb = pbih->biSizeImage; hp = lpBits; if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) { return -1; } // Close the .BMP file. if (!CloseHandle(hf)) { return -1; } // Free memory. GlobalFree((HGLOBAL)lpBits); return 0; }

BOOL CALLBACK EnumResNameProc(HMODULE a_Module, LPCTSTR a_Type, LPTSTR a_Name, LONG_PTR a_Param) { HBITMAP bitmap = NULL;

char resName[512]; if ((DWORD)a_Name < 65536) { sprintf(resName, "c:/res/%s.%d.bmp", moduleName, a_Name); } else { sprintf(resName, "c:/res/%s.%d.bmp", moduleName, a_Name); } switch ((DWORD)a_Type) { case RT_BITMAP: bitmap = LoadBitmap(a_Module, a_Name); break; } if (bitmap != NULL) { HDC hdc = GetDC(NULL); PBITMAPINFO info = CreateBitmapInfoStruct(bitmap); CreateBMPFile(resName, info, bitmap, hdc); ReleaseDC(NULL, hdc); } return TRUE; }

BOOL CALLBACK EnumResTypeProc(HMODULE a_Module, LPTSTR a_Type, LONG_PTR a_Param) { EnumResourceNames(a_Module, a_Type, EnumResNameProc, a_Param); return TRUE; }

void SearchFiles() { HANDLE findHandle; WIN32_FIND_DATA findData;

findHandle = FindFirstFile("*.*", &findData); do { if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (stricmp(findData.cFileName, ".")!=0 && stricmp(findData.cFileName, "..")!=0) { SetCurrentDirectory(findData.cFileName); SearchFiles(); SetCurrentDirectory(".."); } } else if ((findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0) { //if (CheckExt(findData.cFileName, ".dll") || CheckExt(findData.cFileName, ".exe")) { GetCurrentDirectory(512, staticDir); HINSTANCE module = LoadLibraryEx(findData.cFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); if (module != NULL) { printf("%s\\%s\n", staticDir, findData.cFileName); strcpy(moduleName, findData.cFileName); EnumResourceTypes(module, EnumResTypeProc, 0); FreeLibrary(module); } } }

time = timeGetTime(); if (time - lastTime > 100) { progress = (progress+1)&3; printf("%c\r", progressText[progress]); lastTime = time; }

} while (FindNextFile(findHandle, &findData)); }

int main(void) { lastTime = timeGetTime(); SearchFiles(); return 0; }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.


Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.