https://www.codeproject.com/Articles/1432/What-is-an-ISAPI-Extension

Introduction

Unless you have been a caveman, you have seen a number of web sites that whenever is browsed, the navigation ends up to a DLL file residing in a scripting directory of that dominium! Something like the following pseudo URL:

Hide   Copy Code
http://www.mydomain.com/script/example.dll?ID=p05874&Tx=870250AZT6

What does this DLL suppose to do and what does it have to do with today's paper?

These DLLs are created using the Internet Server API, or ISAPI for short. ISAPI is developed to provide a benefit or two, over the shortcomings of Common Gateway Interface, CGI. Although we surprisingly experience new web sites developed exclusively by CGI scripts nowadays, however, ISAPI DLLs have got something to offer that CGI could never bring us this way or that way.

I am going to start off this paper by describing the underlying details that any ISAPI programmer has to know, to be able to develop a better ISAPI extension. From then on, I will go through a development of a useful ISAPI extension step by step. The extension is supposed to validate a given credit card. Yeah! This is also my answer to those people who asked me the algorithm involved validating a credit card over and over again. Gotta go!

What is ISAPI?

Internet Server Application Programming Interface (ISAPI), is an API developed to provide the application developers with a powerful way to extend the functionality of Internet Information Server (IIS). Although ISAPI extensions by no means are limited to IIS, they are extensively used in conjunction with MS-IIS.

CGI vs. ISAPI

Developing a CGI program involves creating an EXE with C, C++, and/or Perl programming languages. This EXE file will be executed and terminated for every request received, causing an excessive memory usage, whenever users hit the same page over and over again!

This excessive memory usage that could bring the server completely down, has been solved under ISAPI extensions. An ISAPI extension is a regular DLL file that exposes 3 special functions that is called by the calling process (i.e., IIS) and therefore, will be loaded to memory once, no matter how many clients are going to use it at the same time. (It would be a good idea if you could take a look at a reference, to see how memory management is done under Windows 2000. The Visual C++ 6.0 Bible, Chapter 18, The Memory Management, describes it well!)

ISAPI fundamentals

Since the ISAPI extension and the calling process (IIS) live at the same address space, they could contact each other, directly. This means a great potential to bring the whole IIS down, and in some cases, the entire web server! Take a look at the following figure:

What is an ISAPI Extension?_sed

You see whatever problem your extension encounters, it could affect the entire web server process, if it's not handled properly. As illustrated above, communicating between the extension and IIS is done via a pointer to a structure of type ECB, or Extension Control Block that is declared as follows: 

 

Whatever information either the calling process or the extension wants to pass to the other, is done through this control block. We will shortly have a look at this ECB structure. For now, let's see how IIS works in conjunction with your extension, to serve the visitor of your web site.

Whenever an extension is accessed (e.g., http://www.mydomain.com/script/example.dll?ID=p05874 & Tx=870250AZT6), IIS checks to see whether the example.dll is loaded into memory. If it is not, then it initiates the loading process. Once the DLL is loaded into memory, a worker thread starts running to manage our extension, and thereafter the entry point (DLLMain function) is called. When the DLLMain finishes, the server makes a call to GetExtensionVersion function to perform two tasks:

  1. Exchange version information
  2. Get a short text description of the extension

The server then calls the HttpExtensionProc function passing a copy of the ECB's pointer to start the actual ISAPI extension. This is the function that makes writing data back to the client, possible! We will examine this, shortly.

The third and the last entry point in an ISAPI extension DLL is the TerminateExtension function that is called whenever the extension is going to be unloaded from the memory. All the cleanup code can be done in this function.

In brief, an ISAPI extension is a regular DLL that exposes 3 functions to interact with the server:

  1. GetExtensionVersion
  2. HttpExtensionProc
  3. TerminateExtension (optional)

Having this information in hand, let's start with the DLLMain, the entry point of any DLL!

DLLMain, the entry point

As indicated by Microsoft, "the DllMain function is an optional entry point into a dynamic-link library (DLL). If the function is used, it is called by the system when processes and threads are initialized and terminated, or upon calls to the LoadLibrary and FreeLibrary functions", that is prototyped as follows:

Hide   Copy Code
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwCallReason, 
                                            LPVOID lpReserved);

If you provide your extension with this function, it will be called upon the initialization and the termination process of your extension. The state is indicated by the dwCallReason parameter that could be one the following predefined values:

  • DLL_PROCESS_ATTACHED
  • DLL_THREAD_ATTACH
  • DLL_THREAD_DETACH
  • DLL_PROCESS_DETACH

Describing each of these parameters in detail is beyond the scope of this paper, so I simply refer you to Microsoft's Developer Network to read more about this function.

Anyhow, we could save the hModule parameter for later use in our extension (if this suites us) and simply return TRUE from this function. We usually do not have anything to do in this function, while developing an extension!

GetExtensionVersion, the actual entry point

This function is actually the first entry point that is called by IIS to determine the information about the extension. To understand this better, let's have a look at it's prototype:

Hide   Copy Code
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer);

Upon the activation of this function, we are supposed to fill out the extension information within the pVer parameter passed to the function. This pointer is of type HSE_VERSION_INFO that is declared as follows:

Hide   Copy Code
typedef struct _HSE_VERSION_INFO
{
   DWORD dwExtensionVersion;
   CHAR lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN];
}HSE_VERSION_INFO, *LPHSE_VERSION_INFO;

where dwExtensionVersion is the extension version and lpszExtensionDescription is the description of the extension. If we return TRUE from this function, we notify IIS that our extension is ready to be used. Otherwise, IIS will not use the extension.

HttpExtensionProc, the main entry point

The amazing part of any ISAPI extension starts when the extension procedure (HttpExtensionProc) is called. As far as you could remember, this is the procedure that makes writing data back to the client possible! To see how this happens, lets start by having a look at the prototype of HttpExtensionProc:

Hide   Copy Code
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB);

where pECB is a pointer to an extension control block, that makes the intercommunication between the server and the extension possible. You decide what the web page should contain and how to present it to the user in this entry point. But how?

Do you recall the members of the ECB's structure? ECB contains a method, prototyped as follows:

Hide   Copy Code
BOOL WriteClient(HCONN ConnID, LPVOID Buffer, LPDWORD lpdwBytes, 
                                                        DWORD dwSync);

Using this member function, you can send the data present in the given Buffer to the client that is identified by its ConnID, the one that made the request. For example, to send A BIG RED ROSE to a client, you could simply make the following calls:

Hide   Copy Code
char szBigRedRos[] = 
  "<font color='#FF0000' size='3'><b>A BIG RED ROSE</b></font>";
DWORD dwSize = strlen(szBigRedRos);
pECB->WriteClient(pECB->ConnID, szBigRedRose, dwSize, 0);

Neat, huh? I think you already have got the minimum underlying knowledge to develop your first ISAPI extension. So, let's start...

 

The final word

This is what ISAPI extensions are supposed to do. They extend the functionality of IIS. Through this article, I repeated the word extension over and over again. It's now time to say that ISAPI programs are divided into two categories: ISAPI extensions and ISAPI filters.

ISAPI filters, unlike the ISAPI extensions would be called for any hit made to the web server! In other words, they magnificently slow down the process, since they are called over and over again. However, they could be absolutely useful when creating a logging service, or doing some specific jobs. Since describing ISAPI filters in detail deserves another paper, let me leave it here to you to understand the subtle nuances of how they work.

Anyhow, this was the simplest ISAPI extension that we developed today, just to show you what the heck an extension is and how it works. It was a synchronous, single-threaded DLL that is the most easiest DLL to develop! Real-world applications are not this easy to implement though, since you have to face the multi-threaded issues, as well as connection pools and other advanced topics. It's all up to you to learn how to play them magnificently, though, and this paper is just a starting point! That's all, folks. Aloha!