L17: Extract icon of the appropriate size from an executable (or compatible) file.
| 2558 | |
| 2559 | // L17: Extract icon of the appropriate size from an executable (or compatible) file. |
| 2560 | HICON ExtractIconFromExecutable(LPTSTR aFilespec, int aIconNumber, int aWidth, int aHeight, HMODULE *apModule) |
| 2561 | { |
| 2562 | HICON hicon = NULL; |
| 2563 | |
| 2564 | // If the module is already loaded as an executable, LoadLibraryEx returns its handle. |
| 2565 | // Otherwise each call will receive its own handle to a data file mapping. |
| 2566 | HMODULE hdatafile = aFilespec ? LoadLibraryEx(aFilespec, NULL, LOAD_LIBRARY_AS_DATAFILE) : g_hInstance; |
| 2567 | if (hdatafile) |
| 2568 | { |
| 2569 | LPTSTR group_icon_id = (aIconNumber < 0) |
| 2570 | ? MAKEINTRESOURCE(-aIconNumber) |
| 2571 | : ResourceIndexToId(hdatafile, (LPCTSTR)RT_GROUP_ICON, aIconNumber ? aIconNumber : 1); |
| 2572 | |
| 2573 | HRSRC hres; |
| 2574 | HGLOBAL hresdata; |
| 2575 | LPVOID presdata; |
| 2576 | |
| 2577 | // MSDN indicates resources are unloaded when the *process* exits, but also states |
| 2578 | // that the pointer returned by LockResource is valid until the *module* containing |
| 2579 | // the resource is unloaded. Testing seems to indicate that unloading a module indeed |
| 2580 | // unloads or invalidates any resources it contains. |
| 2581 | if (group_icon_id != RESOURCE_ID_NOT_FOUND |
| 2582 | && (hres = FindResource(hdatafile, group_icon_id, RT_GROUP_ICON)) |
| 2583 | && (hresdata = LoadResource(hdatafile, hres)) |
| 2584 | && (presdata = LockResource(hresdata))) |
| 2585 | { |
| 2586 | #pragma pack(push, 1) // For RESDIR, mainly. |
| 2587 | struct NEWHEADER { |
| 2588 | WORD Reserved; |
| 2589 | WORD ResType; |
| 2590 | WORD ResCount; |
| 2591 | }; |
| 2592 | struct ICONRESDIR { |
| 2593 | BYTE Width; |
| 2594 | BYTE Height; |
| 2595 | BYTE ColorCount; |
| 2596 | BYTE reserved; |
| 2597 | }; |
| 2598 | // Note that the definition of RESDIR at http://msdn.microsoft.com/en-us/library/ms648026 is |
| 2599 | // completely wrong as at 2015-01-10, but the correct definition is posted in the comments. |
| 2600 | struct RESDIR { |
| 2601 | ICONRESDIR Icon; |
| 2602 | WORD Planes; |
| 2603 | WORD BitCount; |
| 2604 | DWORD BytesInRes; |
| 2605 | WORD IconCursorId; |
| 2606 | }; |
| 2607 | #pragma pack(pop) |
| 2608 | |
| 2609 | if (aWidth == -1) |
| 2610 | aWidth = aHeight; |
| 2611 | if (aWidth == 0) |
| 2612 | aWidth = GetSystemMetrics(SM_CXICON); |
| 2613 | |
| 2614 | NEWHEADER *resHead = (NEWHEADER *)presdata; |
| 2615 | WORD resCount = resHead->ResCount; |
| 2616 | RESDIR *resDir = (RESDIR *)(resHead + 1), *chosen = NULL; |
| 2617 | int chosen_width = 0; |
no test coverage detected