Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Embed Resources in a Static Library

0.00/5 (No votes)
22 Jan 2019 1  
How can a Static Library embed resources and other data so any application (even a Console based one) can use them.

See also my GitHub Repo.

Introduction

It started with a need to release a Static library as a product and include some resources in it. That is usually impossible since a program that uses such Static library will use its own resources. I posted a question (which I answered after finding this solution). I realized that this solution deserves an article with source code. I have also posted a question about that possibility in Stack Overflow.

In another occasion I wanted my Static library to embed another file of any kind (can be an executable, DLL, photo, documents, etc.) and extract it during run-time.

Several Code Examples

The source consists of a Static Library project ("MH_EmbedDataLib") and a test Console application ("ConsoleApp"). Of course, if it works with a GUIless Console application, it will work with any other type, i.e., Win32, MFC, etc.

The MH_EmbedDataLib Library

The MH_EmbedDataLib library has 2 main functions:

Get Icon

HICON GetIcon()
{
    DWORD dwTmp;
    int offset;
    HANDLE hFile;
    HICON hIcon = NULL;

    offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR);

    if (offset != 0)
    {
        hIcon = CreateIconFromResourceEx
        (s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
    }

    return hIcon;
}

Provided that you converted an icon you wish to use into a static array of BYTE and named it s_byIconData, GetIcon loads the icon from this static data (s_byIconData).

The LookupIconIdFromDirectoryEx function is used to search through icon or cursor data for the icon or cursor that best fits the current display device.

Then CreateIconFromResourceEx is used to create the icon from resource bits describing it, generated by Bin2C.

DisplayMessageWithIcon

void DisplayMessageWithIcon(LPWSTR message)
{
    XMSGBOXPARAMS xmb;
    //xmb.hInstanceIcon = (HINSTANCE)GetIcon();
    xmb.dwOptions |= XMSGBOXPARAMS::RightJustifyButtons;
    xmb.crBackground = RGB(255, 255, 255);
    xmb.crText = RGB(10, 135, 180);
    xmb.nIdIcon = 101;
    xmb.nTimeoutSeconds = 5;
    XMessageBox(NULL,
        message,
        L"Code Project article by Michael Haephrati",
        MB_YESNO, &xmb);
}

This function displays a MessageBox showing the icon encapsulated in s_byIconData.

The Process

Select a photo you wish to use, or an image. A web site named ICO Convert provides the service of converting most image types into an .ico file. After you have an .ico file, open it to see that the conversion went well. Then convert it into an array of BYTE using Bin2C. Make sure you use the correct name for the static array. (in this case, we used s_byIconData). Then the MessageBox will display it. For the purpose of this article, I used a photo from the Nigara Falls (Canadian side of course...) shown below.

The result isn't great but demonstrate this concept.

XMessageBox

The fancy Message Box used in the code of the article was developed by Hans Dietrich.

Creating Ad-Hoc Files from an Array

Another example that serves the purpose of this article is using the same array created by Bin2C for Ad-Hoc generation of a file during run-time.
bool Array2TempFile(char *arr, size_t len,WCHAR *file)
{
	HANDLE hFile = CreateFile(file, GENERIC_WRITE, // open for writing
		FILE_SHARE_WRITE, // share for writing
		NULL, // default security
		CREATE_ALWAYS, // create new file only
		FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
		// normal file archive and impersonate client
		NULL); // no attr. template


	DWORD bytes;
	if (hFile != INVALID_HANDLE_VALUE)
	{
		WriteFile(hFile, &arr[0], len, &bytes, NULL);
		CloseHandle(hFile);
		return true;
	}

	return false;
}

I used this function to extract and install Kernel drivers from a Static library. Here is an example of such use.

INF_PATH
and
SYS_PATH
are predefined.
int len;
// Extract .inf file for x86 Win 10
len = (int)sizeof(sgdrv86_10_inf);
Array2TempFile((char *)&sgdrv64_10_inf[0], len, INF_PATH);
// Extract .sys file for x86 Win 10
len = (int)sizeof(sgdrv86_10_sys);
Array2TempFile((char *)&sgdrv86_10_sys[0], len, SYS_PATH);

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here