Overview
As my first contribution to CodeProject, I decided to do something really easy that is also pretty useful in a number of situations. I wrote most of this a couple of years ago when I was working on an internet application that needed to be easy to install and had to look like it was one "easy package". My problem was that my internet application had lots of graphics (buttons, etc.) and didn't want to include those separate files. One of the goals was also to make sure the user could not fiddle around with some of the graphics.
The solution?
Store our binary data in an ISAPI DLL and add code so it was easy to retrieve. All in all, it is very easy to do this. Most experienced ISAPI programmers can do this in no time. The nice thing is that, even in the .NET/COM era, it is a pretty useful ISAP DLL, that can make packaging your binary data easy. I could think of a number of other uses. I have since used it to provide a kind of "skin" support for some internet applications. Just send the user a new DLL and suddenly their whole application looks different (without them have to copy zillions of files to the correct directory). Yes, I know there are lots of ways to achieve something similar but still, I like this approach.
The ISAPI DLL uses MFC and I noticed earlier on that I could serialize an CByteArray
to the CHttpServerContext
class. So basically the only thing I had to do was make sure I could load the binary data into the CByteArray
.
That is really all that the following code does. What we need to do is find the correct resource, get its size and copy it to the CByteArray
. This is achieved by various calls to FindResource
and LoadResource
.
int iRAWSize = 0;
CByteArray caImage;
CString cImage(sImage);
cImage.Remove('\'');
HRSRC tSrc = ::FindResource(AfxGetResourceHandle() ,cImage,"BINARY");
if (tSrc == NULL) return;
iRAWSize = ::SizeofResource(AfxGetResourceHandle(),tSrc);
caImage.SetSize(iRAWSize);
HGLOBAL hImage;
hImage = ::LoadResource(AfxGetResourceHandle(),tSrc);
if (hImage == NULL) return;
BYTE* pImage = NULL;
pImage = (BYTE*) ::LockResource(hImage);
if (pImage == NULL) return;
for (int iCount = 0; iCount < iRAWSize; iCount++)
caImage.ElementAt(iCount) = pImage[iCount];
*pCtxt << caImage;
Note that the ISAPI DLL assumes that you store your binary data as type "BINARY
" as indicated in last parameter of the FindResource
call. Of course, you can use a different name or even make the name dynamic by changing the function parameters. Adding your data to your DLL is fairly easy, just use the import
command by right clicking on the resources.
Testing the ISAPI DLL is also pretty straightforward as indicated in the top introduction picture. You can add links like this in your own webpages or of course in other components and ISAPI DLLs.
<HTML>
You can add pictures using this dll to your webpages. This is a nce way to
implement "skins" by grouping all pictures in a ISAPI dll
<img src="http://localhost/Isapi/BinaryLib.dll?GetImage&Image=IDR_KITTY" border=0>
</HTML>
Note that these pictures are not cached locally by your browser so performance might be a bit slower. Then again, you might not want the images to be cached locally for some reason.
Don't ask where I got the picture, it is a long story... That's it for now, but I am sure you can think of other things to do with this approach. You don't have to store images of course. By adding new functions to the DLL, you can support different types of binary data. Just remember that your browser will not display everything without problems. You might have to write some HTML code to the CHttpServerContext
object to indicate what and how the browser should handle your data.
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.