This section of the tutorial explains what is perhaps one of the least known Internet programming related topics, Server side programming. Until now, most of what we've taught you dealt with the client side. Things like ActiveX, Java, LiveConnect and most of the WinSock programs. However, we decided to take a slightly different tack here and talk about some server technology.
This is just the first draft of the tutorial so do keep coming back. We'll soon be updating this page with information on the Microsoft Internet Information ( or is it Information Internet ?!! ) Server. We'll be working on Windows NT Server 4.0 and using version 2.0 of the MIIS.
This section of the tutorial has been divided into two parts. The first one, about Server side programming, is for professional ( and not so professional ! ) programmers. The other part is for non-programmers and it will explain setting up some of the various SMTP servers around, along with how to install various popular search engines, with absolutely no programming around. We'll also be trying out every server and almost every server utility ever written, so watch out for them !
When we first started off, we thought one 1GB hard disk would be enough for both Windows NT and Windows 95. Now, we've got three 1GB disks and we're still short of space !!
( Rest assured, this page will look much better and be more learner friendly in a couple of days, so keep coming back to check up on our progress ! )
There is nothing permanent about being a client or a server. It just depends on what software you run on your machine. If you run server software, your machine becomes a server and if you run client software, your machine is transformed into a client. Ofcourse, commercial server machines are big brutes with gigs of hard disk space and loads of RAM, but by definition, if you were to run a server like the MIIS, your machine too will be called a server, no matter what it's configuration.
Before we proceed any further, I guess I should tell you a little about CGI programming and also about the most happening thing around, SSI ( Server Side Includes ).
Lets look at z.htm
z.htm <HTML> <Body> <H1>Sample Form to Test Extension DLLs </H1> <Form method=GET action="sampdll.dll"> <Input type=text name=a> <Input type=text name=b> <Input TYPE="submit" VALUE="OK, it's done."> </Form> </HTML>
These tags should be familiar to most HTML scripters, because what we have here is a form. This form has two text boxes imaginatively named a and b and an input button called submit.
When the form comes over to your browser, key in Microsoft in text box a and purveyor in text box b and click on the submit button. The browser will then go to the line that says ACTION and check the action to be taken. In this case, the browser is instructed to connect to the site it got the HTML page from and load the file called sampdll.dll. This information ( the file name ), is sent to the server, using the GET method. In the GET method, all the user information is sent as part of the URL. So after the URL of the site you've connected to, there will be a ?, no space, and then the data you've entered will be displayed along with the relevant variable names. For example, http://www.microsoft.com/default.htm?a=microsoft&b=purveyor. An & sign separates the name-value pairs of the two text boxes, a and b.
If you've got spaces in your answer, they will be replaced by plus signs (+) or by the hex values (%20). This information is then sent to the server. There are many ways of handing over the information sent by the client, to the server. The most common way is for the server to create a list of environment variables that can then be called and used by the relevant programs. The environmental variable which holds the user's response is called QueryString. If you used GET, you can now easily find out what the user wrote. If you used POST, which sends the information as information packets instead of as the URL, there will be no question marks and no ampersands to remove, so you must handle the data accordingly. In POST the answer is part of the Standard Input and in both methods, your reply is sent to the Standard Output.
Now in the ACTION tag we can have a .pl file (PERL), an .exe file or a .dll file.
So the URL would look like one of the following depending upon the method you have chosen. (GET)
The server has to be configured to handle the types of files you intend to put up. If an .exe file is requested, it will run the .exe file, if a .pl file is requested, it will load the PERL interpreter and then run the script and if a .dll is requested, it will load the .dll into memory. In all three cases, the server will then pass the information after the question mark to the relevant program.www.microsoft.com/default.htm /cgi-bin/a.exe?a=microsoft&b=purveyor www.microsoft.com/default.htm /cgi-bin/a.pl?a=microsoft&b=purveyor www.microsoft.com/default.htm /cgi-bin/a.dll?a=microsoft&b=purveyor
The problem with the .exe method is that you have to use Standard Input and Standard Output, which is a little inconvenient. Also, loading a program into memory for each and every request is time and resource consuming. These problems are even more acute when you're dealing with Perl. Since Perl is an interpreted language, the Interpreter has also to be loaded into memory. Being very UNIX oriented, Perl can only be fully utilized on a UNIX platform and not on a Windows 95/NT one. Without all those nifty UNIX utilities, using Perl makes no sense. Perhaps the best option of all, is to use a .dll, because once a dll loads into memory, it stays there and doesn't get loaded every time a client requests a function. To use a technical term, it occupies the same address space on the server, regardless of the number of requests. This makes .dll's much faster than any competing technology.
Now enough of all this, let's start running some actual code.
This HTML document creates a button on the screen. When you click on it, it will use the POST method and activates the file z1.dll. Pretty simple huh ?z.htm <HTML> <Body> <H1>Sample Form to Test Extension DLLs </H1> <Form method=POST action="z1.dll"> <Input TYPE="submit" VALUE="OK, it's done."> </Form> </HTML>
In your browser, write down http;//you_ip_address_goes_here/Scripts/extn_dll/z.htm. (e.g. http://202.54.1.18/ Scripts/extn_dll/z.htm or http://localhost/ Scripts/extn_dll/z.htm etc.). in our case, we ran both the server and the client on one machine to test out the software. Press enter and you get that little button on the screen. When you click on the button, the browser follows the ACTION specified and tells the server to load z1.dll into memory. As of now we don't have z1.dll so we don't click on the button. Instead we go to Visual C++ 4.0 and create a new project (z1) out there to give us a dll(z1.dll). The files in the project will be
z1.def
LIBRARY      Z1
EXPORTS
	HttpExtensionProc
	GetExtensionVersion
z1.c
#include  <windows.h>
#include  "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
strcpy(aa,"Hello World");
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
Now lets understand the code.
In this .c file we have five headers which contain stuff like typdefs and #defines. Windows.h is distributed with Visual C++ and the files httpext.h and prvr_ext.h are in the Win32 CD-ROM, which usually installs itself into the directory, MSTools. The other two headers are not really necessary.
Whenever a dll is loaded into memory, the function DllMain gets called. Since we're not doing anything with DllMain, we just return 'TRUE'. After DllMain, the next function which gets called is GetExtensionVersion. The GetExtensionVersion gets called because it is mentioned in the .def file as an export function implying others can call it too. This function is passed a pointer to a structure which looks like HSE_VERSION_INFO, where we initialize two members to inform the program about the version of ISAPI we're working on. This is not something we really need to bother about, but it's compulsory, so we've got to do it.
Now on to the really juicy stuff.
Next we have the function HttpExtensionProc, which is also exported in the .def file . This crucial function is called by the server, who then creates a structure which looks like EXTENSION_CONTROL_BLOCK, and whose address is put up on the stack for use by HttpExtensionProc. So c now becomes a pointer to the structure EXTENSION_CONTROL_BLOCK.
Before we proceed any further, a bit about the structure of HTML files. A HTML file is made up of two parts, a header and the data. The headers contain details like the content type /mime type which tells the browser whether the file is a text / html document, or an image, or is it an audio file and depending on the mime type, the browser handles the file in different ways. Now I don't want to sit down and write the headers myself, so I use the structure EXTENSION_CONTROL_BLOCK ( Remember that c is a pointer to this structure ). This structure contains a large number of members, one of which is called ServerSupportFunction. To access this member, which is a pointer to a function, you use c-> ServerSupportFunction. Since this is a pointer to a function, displaying the value of ServerSupportFunction will be a waste of time as all it does is point to a function in memory. The function takes six parameters before it can begin it's work. The first one is a member of the sam! e st ructure called ConnID, which stands for Connection Identification. The second is a macro which stands for some number or the other. In this program, we've used the macro HSE_REQ_SEND_RESPONSE_HEADER, but later on we'll use others like HSE_REQ_SEND_URL. The other parameters don't really have to be explained.
What ServerSupportFunction does is tell the server that the dll is not going to go about creating headers. The headers will have to be created by the server and then handed over to the browser.
And finally, we also have a pointer to a function called WriteClient. To it is given the ConnID, a string containing "Hello World", and k which contains the length of the a string (k is passed by reference). So here, instead of mucking about with Standard Output, the dll gives the data directly to the server. So the server first sends the client the necessary headers and then an HTML page containing the text, Hello World.
Note : Create a new project for the new program . The def file in all the cases will remain the same. We have to do this because the server doesn't allow you to overwrite the original z1.dll, because it is present in memory . Therefore, in your html file, the ACTION tag should refer to the new dll, z2.dll.
z2.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
strcpy(aa,"<b>Hello World</b>");
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
The program here remains the same, the only change being that we've added some HTML tags. So now Hello World will be displayed in bold, proving once and for all, that this is an HTML file.
When you go to www.browserwatch.com, you see your IP address displayed by the server for all to see. At one time we used to wonder how they did that, but not anymore !! CGI has 24 environmental variables (so says Murari, an Indian programmer who wrote the samples for purveyor). One of these environmental variables gives you the IP address of the client connected to the server . If you want to know more about the environmental variable, check out the RFC, something we've neglected to do !!
Let us see how we can display the environmental variables here.
z3.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
k=100;
c->GetServerVariable(c->ConnID,"SERVER_NAME",aa,&k); 
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
In this program we see that there is another member in the structure called GetServerVariable. Here in double inverted commas we give the environmental variable we're looking for, the name of an array and it's length. The array will then contain the value, which in our case is name of the server and this name will be displayed on the screen.
This is definitely a better way of getting environmental variables, certainly better than doing it the perl way. Sorry about taking these digs at perl, but we believe we've atoned for them by writing some examples in perl too.
This next example is the largest of the lot. Here we've displayed all the 24 environmental variables, one after another. There was nothing to it, all we did was copy, cut and past !
z4.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];char bb[100];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
k=100;
c->GetServerVariable(c->ConnID,"SERVER_NAME",bb,&k); 
sprintf(aa,"SERVER_NAME %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Server_Protocol",bb,&k); 
sprintf(aa,"Server_Protocol %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Auth_Type",bb,&k); 
sprintf(aa,"Auth_Type %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Content_Length",bb,&k); 
sprintf(aa,"Content_Length %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Content_length_verbatim",bb,&k); 
sprintf(aa,"Content_length_verbatim %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Content_Type",bb,&k); 
sprintf(aa,"Content_Type %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Gateway_Interface",bb,&k); 
sprintf(aa,"Gateway_Interface %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Path_Info",bb,&k); 
sprintf(aa,"Path_Info %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Path_Translated",bb,&k); 
sprintf(aa,"Path_Translated %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Query_String",bb,&k); 
sprintf(aa,"Query_String %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Remote_Addr",bb,&k); 
sprintf(aa,"Remote_Addr %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Remote_Host",bb,&k); 
sprintf(aa,"Remote_Host %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Remote Ident",bb,&k); 
sprintf(aa,"Remote Ident %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Remote_User",bb,&k); 
sprintf(aa,"Remote_User %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Request_Method",bb,&k); 
sprintf(aa,"Request_Method %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Script_Name",bb,&k); 
sprintf(aa,"Script_Name %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Server_Port",bb,&k); 
sprintf(aa,"Server_Port %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Server_Software",bb,&k); 
sprintf(aa,"Server_Software %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Auth_Realm",bb,&k); 
sprintf(aa,"Auth_Realm %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Auth_Pass",bb,&k); 
sprintf(aa,"Auth_Pass %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Request_Line",bb,&k); 
sprintf(aa,"Request_Line %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"Header_count",bb,&k); 
sprintf(aa,"Header_count %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"User_Info",bb,&k); 
sprintf(aa,"User_Info %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
k=100;
c->GetServerVariable(c->ConnID,"HTTP_Accept",bb,&k); 
sprintf(aa,"HTTP_Accept %s<p>",bb);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
As you can see, there really isn't much to this program, just a series of environmental variables being displayed. Be warned though, some of these environmental variables do not return an answer, so perform some error checks and don't display then. In some cases, a couple of the answers may not apply or may be repeated. This is a hell of a lot simpler that splitting up environmental variables and stuff like that. I get all my variables in one, convenient shot.
z5.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];char bb[100];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
sprintf(aa,"c->lpszMethod %s<p>",c->lpszMethod);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->cbSize %ld<p>",c->cbSize );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->dwVersion %ld<p>",c->dwVersion );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->lpszMethod %s<p>",c->lpszMethod );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->lpszQueryString %s<p>",c->lpszQueryString);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->lpszPathInfo  %s<p>",c->lpszPathInfo );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->lpszPathTranslated   %s<p>",c->lpszPathTranslated );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->cbTotalBytes   %ld<p>",c->cbTotalBytes);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->cbAvailable    %ld<p>",c->cbAvailable );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
sprintf(aa,"c->lpszContentType     %s<p>",c->lpszContentType );
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
In this example here, we can say that we have a pointer to an EXTENSION_CONTROL_BLOCK structure. This is a structure which informs us about the members fo the structure.
The most important one of these is the one called lpszMethod. It's important because the dll, when called, can have the method set to GET or POST. This variable lpszMethod will display the method used. Another important one is lpszQuerystring, but we'll talk about that later.
On to the next one now...
z6.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int k;char aa[100];char bb[3000];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
k=3000;
c->GetServerVariable(c->ConnID,"ALL_HTTP",bb,&k );
k= strlen(bb);
c->WriteClient(c->ConnID,bb,&k,0);
k=3000;
c->GetServerVariable(c->ConnID,"Accept",bb,&k );
k= strlen(bb);
c->WriteClient(c->ConnID,bb,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
This program displays some important headers you should know about. These headers are sent form the browser to server.
z7.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int i,k;char aa[100];char bb[3000];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
strcpy(bb,"/default.htm");
k=strlen(bb);
i = 0;
c->ServerSupportFunction(c->ConnID, HSE_REQ_SEND_URL ,bb,&k,&i);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
Earlier on, when we used the ServerSupportFunction, the program asked the server to send the headers to the client , but now, this dll will tell the server to send a particular file to the client. This file has not been created by the .dll. So the server wil pick up the specified file and send the headers and then the file ( default.htm, present in the document root of purveyor ) to the client. The client doesn't know whether the .dll has sent the file or just the server.
z8.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int i,k;char aa[100];char bb[3000];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
strcpy(bb,"http://www.microsoft.com");
k=strlen( bb);
i=0;
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_URL_REDIRECT_RESP,bb,&k,&i);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
In this example, when the browser asks for a particular file, say default.htm, the server, ( since we've used HSE_REQ_SEND_URL_REDIRECT_RESP ) will redirect the user to another site on the Internet. The browser will then automatically go to the other site and get the specified page. In our case the server redirects the browser to the Microsoft site. This can be used if the site has shifted to another server. In the previous example, the .dll told the server to send a particular file, but here the browser is sent to another site and the server is not concerned about what it does there.
In this last example, when the user clicks on the button, he is sped off to another site on the 'net.
z9.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int i,k;char aa[100];char bb[3000];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
k=sizeof( bb);
c->GetServerVariable(c->ConnID,"SERVER_NAME",bb,&k); 
c->ServerSupportFunction(c->ConnID,HSE_GET_COUNTER_FOR_ALL_METHODS,bb,&k,&i);	    
sprintf(aa,"No of Hits %d<p>",i);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
c->ServerSupportFunction(c->ConnID,HSE_GET_COUNTER_FOR_GET_METHOD,bb,&k,&i);	    
sprintf(aa,"No of Gets %d<p>",i);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
c->ServerSupportFunction(c->ConnID,HSE_GET_COUNTER_FOR_POST_METHOD,bb,&k,&i);	    
sprintf(aa,"No of Posts %d<p>",i);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
c->ServerSupportFunction(c->ConnID,HSE_GET_COUNTER_FOR_HEAD_METHOD,bb,&k,&i);	    
sprintf(aa,"No of Head %d<p>",i);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
Now the very last example is z10.c
z10.c
#include   <windows.h>
#include   "httpext.h"
#include   <stdio.h>
#include   <fcntl.h>
#include   "prvr_ext.h"
int i,k;char aa[100];char bb[3000];
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO  *ver )
{
ver->dwExtensionVersion = HSE_VERSION_MAJOR;
ver->dwExtensionVersion = ( ver->dwExtensionVersion << 16 ) | HSE_VERSION_MINOR;
sprintf( ver->lpszExtensionDesc, "%s", "This is a Sample Extension DLL by Process Software Corp" );
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *c)
{
c->ServerSupportFunction(c->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,0,0,&k);
sprintf(aa,"Data %s<p>",c->lpbData);
k= strlen(aa);
c->WriteClient(c->ConnID,aa,&k,0);
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID ptr ){return TRUE;}
This is an exceedingly simple example which uses c->lpbData to give you the number of POST requests. If, for example, you write Microsoft in textbox a, click on submit and the method is set to POST, then c->lpbData will contain a=microsoft. If it is a GET, then QueryString will return the value of a and if there are multiple values, these will be separated by &'s.
Mr. Vijay Mukhi
Ms. Sonal Kotecha
Mr. Arsalan Zaidi 
Move back to the Vijay Mukhi's Technology Cornucopia Page to learn more about the other new Internet Technologies.