
Overview
Well 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 lot's 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 lot's of way to achieve
something similar but still, I like this approach.
The ISAPI dll uses MFC and I noticed early on that I could serialize an CByteArray to the CHttpServerContext class. So basicaly 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 it's 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.