⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch26.htm

📁 好书《C++ Builder高级编程技术》
💻 HTM
📖 第 1 页 / 共 5 页
字号:
</FONT></PRE>
<P>If you want to query the DLL, you would edit the preceding line so that it looks
like this:</P>
<PRE><FONT COLOR="#0066FF">&lt;A 
HREF=&quot;/scripts/mystuff/test1.dll?MyQuery&quot;&gt;Test One&lt;/A&gt;

</FONT></PRE>
<P>Given the second of the two HTML fragments listed here, your DLL would get called
with the string <TT>&quot;MyQuery&quot;</TT> in the <TT>lpszQueryString</TT> 
parameter.
Notice in particular the use of the question mark, followed by the query string itself.</P>
<P>You could, of course, change the query string at will. For example, you could
write</P>
<PRE><FONT COLOR="#0066FF">&lt;A 
HREF=&quot;/scripts/mystuff/test1.dll?ServerName&quot;&gt;Test One&lt;/A&gt;

</FONT></PRE>
<P>To this query, the DLL might reply with the name of the server. You have no limits
on what you can pass in this parameter, but the string after the question 
mark cannot
have any spaces in it. If you need to use spaces, replace them with a plus sign:
Instead of <TT>&quot;Server Name&quot;</TT>, write <TT>&quot;Server+Name&quot;</TT>.
The string can be anything you want, and it is up to you to parse the 
information
from inside the DLL as you like.</P>
<P>When you return information from the server back to the browser, you use the <TT>WriteClient</TT>
function pointer that is part of this record.</P>
<P>Writers of CGI applications will notice that the 
syntax for sending query strings
is familiar. Indeed, ISAPI follows many of the conventions of CGI, and most of the
fields in the <TT>EXTENSION_CONTROL_BLOCK</TT> are simply borrowed directly to initialize
this pointer; it is passed to you gratis by 
the Internet Information Server.</P>
<P>Another key field in the <TT>EXTENSION_CONTROL_BLOCK</TT> is the <TT>lpbData</TT>
field, which contains any additional information sent to you by the browser. In particular,
it is used to pass information 
associated with a Submit button. For example, if you
have an HTML form with a number of fields in it, the information from these fields
will be sent in the pointer called <TT>lpbData</TT> after the Submit button is clicked.
The section of this chapter 
called &quot;Getting Information from a Submit Button&quot;
focuses on how to handle this situation.</P>
<P>So far I have zeroed in on three key fields of the <TT>EXTENSION_CONTROL_BLOCK</TT>:

<UL>
	<LI><TT>WriteClient</TT>: A pointer to a function 
that allows you to send formatted
	HTML data back to the browser. This function uses the <TT>ConnID</TT> field of <TT>EXTENSION_CONTROL_BLOCK</TT>.
	<P>
	<LI><TT>lpszQueryString</TT>: The query passed to you from the browser.
	<P>
	
<LI><TT>lpbData</TT>: Any additional data being passed to you from the browser. This
	data is usually the contents of any fields on an HTML form. I discuss this field
	further in the section on the Submit button.
</UL>

<H3><A 
NAME="Heading13"></A><FONT COLOR="#000077">Mirroring the Fields of the EXTENSION_CONTROL_BLOCK</FONT></H3>
<P>The best way to get a feeling for how the rest of the fields of <TT>EXTENSION_CONTROL_BLOCK</TT>
work is simply to mirror them back to 
yourself in a browser. In other words, you
can create an HTML page that allows the user to call a custom ISAPI DLL. The purpose
of this ISAPI DLL is simply to snag the contents of each field of the <TT>EXTENSION_CONTROL_BLOCK</TT>,
format them in 
HTML, and send them back to the browser. This will turn your browser
into a rather jazzy debugger that shows each of the fields in the <TT>EXTENSION_CONTROL_BLOCK</TT>.
Listing 26.2 contains the source to a DLL called <TT>IsapiVars</TT> that performs

this task.<BR>
<BR>
<A NAME="Heading14"></A><FONT COLOR="#000077"><B>Listing 26.2. The IsapiVars code
that mirrors back the parameters sent in the EXTENSION_CONTROL_BLOCK.</B></FONT></P>
<PRE><FONT 
COLOR="#0066FF">///////////////////////////////////////

// IsapiVars.cpp

// Mirror back the information sent to an ISAPI DLL by the server

// Copyright (c) 1997 by Charlie Calvert

//

#include &lt;vcl\vcl.h&gt;

#pragma hdrstop

#include 
&quot;..\..\utils\Httpext.h&quot;



USERES(&quot;IsapiVars.res&quot;);



BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer)

{

  pVer-&gt;dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);

  
strcpy(pVer-&gt;lpszExtensionDesc, &quot;ISAPI Variables DLL&quot;);

  return (TRUE);

};



#define SIZE 2048



DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)

{

  char ResultString[SIZE * 2];

  char HtmlInfo[SIZE];

  char 
Buffer[SIZE];

  DWORD StrSize;

  DWORD resultLen;



  char *IsapiLogText = &quot;ISAPIVars from C++ Builder&quot;;

  strcpy(pECB-&gt;lpszLogData, IsapiLogText);

  pECB-&gt;dwHttpStatusCode = 200;



  sprintf(HtmlInfo,

    
&quot;&lt;HTML&gt;&lt;TITLE&gt;Fields of EXTENSION_CONTROL_BLOCK&lt;/TITLE&gt;&quot;

    &quot;&lt;H1&gt;Test server results&lt;/H1&gt;&lt;BODY&gt;&quot;

    &quot;Size = %d&lt;BR&gt;&quot;

    &quot;Version = %.8x&lt;BR&gt;&quot;

    &quot;ConnID 
= %.8x&lt;BR&gt;&quot;

    &quot;Method = %s&lt;BR&gt;&quot;

    &quot;Query = %s&lt;BR&gt;&quot;

    &quot;PathInfo = %s&lt;BR&gt;&quot;

    &quot;PathTranslated = %s&lt;BR&gt;&quot;

    &quot;TotalBytes = %d&lt;BR&gt;&quot;

    
&quot;AvailableBytes = %d&lt;BR&gt;&quot;

    &quot;ContentType = %s&lt;BR&gt;&lt;BR&gt;&quot;

    &quot;&lt;H1&gt;Calls to GetServerVariable&lt;/H1&gt;&quot;,

    pECB-&gt;cbSize, pECB-&gt;dwVersion, pECB-&gt;ConnID,

    pECB-&gt;lpszMethod, 
pECB-&gt;lpszQueryString,

    pECB-&gt;lpszPathInfo, pECB-&gt;lpszPathTranslated,

    pECB-&gt;cbTotalBytes, pECB-&gt;cbAvailable,

    pECB-&gt;lpszContentType);



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, 
&quot;REMOTE_ADDR&quot;, &amp;Buffer, &amp;StrSize);

  AnsiString VarString(&quot;REMOTE_ADDR = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;); 



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, 
&quot;REMOTE_HOST&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;REMOTE_HOST = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;REMOTE_USER&quot;, 
&amp;Buffer, &amp;StrSize);

  VarString += &quot;REMOTE_USER = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;SERVER_NAME&quot;, &amp;Buffer, &amp;StrSize);

  
VarString += &quot;SERVER_NAME = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;SERVER_PORT&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;SERVER_PORT 
= &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;SERVER_PROTOCOL&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;SERVER_PROTOCOL = &quot; + 
AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;SERVER_SOFTWARE&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;SERVER_SOFTWARE = &quot; + AnsiString(Buffer) + 
&quot;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;HTTP_ACCEPT&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;HTTP_ACCEPT = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;



  
StrSize = sizeof(Buffer);

  pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;URL&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;URL = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&quot;;



  StrSize = sizeof(Buffer);

  
pECB-&gt;GetServerVariable(pECB-&gt;ConnID, &quot;ALL_HTTP&quot;, &amp;Buffer, &amp;StrSize);

  VarString += &quot;ALL_HTTP = &quot; + AnsiString(Buffer) + &quot;&lt;BR&gt;&quot;;





  strcat(HtmlInfo, VarString.c_str());



  sprintf(ResultString,

    
&quot;HTTP/1.0 200 OK\nContent-Type: text/html\n&quot;

    &quot;Content-Length: %d\nContent:\n\n %s &lt;/HTML&gt;&quot;,

    SIZE, HtmlInfo);





  StrSize = strlen(ResultString);

  pECB-&gt;WriteClient(pECB-&gt;ConnID, ResultString, 
&amp;StrSize, 0);

  return (HSE_STATUS_SUCCESS);

}



int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)

{

  return 1;

} 

</FONT></PRE>
<P>To call this DLL, you should create an HTML script that contains the following

line:</P>
<PRE><FONT COLOR="#0066FF">&lt;A HREF=&quot;/scripts/mystuff/isapivars.dll&quot;&gt;Test One&lt;/A&gt; &lt;BR&gt;

</FONT></PRE>
<P>Of course, the actual path shown in your code may be somewhat different from what
I show here.</P>
<P>The 
<TT>HttpExtensionProc</TT> for this DLL is broken into two sections. The first
retrieves all the main fields from the <TT>EXTENSION_CONTROL_BLOCK</TT>, and the
second goes to town on one particular field, which is a function called 
<TT>GetServerVariable</TT>.</P>
<P>The code that parses the main fields of the <TT>EXTENSION_CONTROL_BLOCK</TT> is
fairly straightforward:</P>
<PRE><FONT COLOR="#0066FF">sprintf(HtmlInfo,

    &quot;&lt;HTML&gt;&lt;TITLE&gt;Fields of 
EXTENSION_CONTROL_BLOCK&lt;/TITLE&gt;&quot;

    &quot;&lt;H1&gt;Test server results&lt;/H1&gt;&lt;BODY&gt;&quot;

    &quot;Size = %d&lt;BR&gt;&quot;

    &quot;Version = %.8x&lt;BR&gt;&quot;

    &quot;ConnID = %.8x&lt;BR&gt;&quot;

    &quot;Method 
= %s&lt;BR&gt;&quot;

    &quot;Query = %s&lt;BR&gt;&quot;

    &quot;PathInfo = %s&lt;BR&gt;&quot;

    &quot;PathTranslated = %s&lt;BR&gt;&quot;

    &quot;TotalBytes = %d&lt;BR&gt;&quot;

    &quot;AvailableBytes = %d&lt;BR&gt;&quot;

    
&quot;ContentType = %s&lt;BR&gt;&lt;BR&gt;&quot;

    &quot;&lt;H1&gt;Calls to GetServerVariable&lt;/H1&gt;&quot;,

    pECB-&gt;cbSize, pECB-&gt;dwVersion, pECB-&gt;ConnID,

    pECB-&gt;lpszMethod, pECB-&gt;lpszQueryString,

    
pECB-&gt;lpszPathInfo, pECB-&gt;lpszPathTranslated,

    pECB-&gt;cbTotalBytes, pECB-&gt;cbAvailable,

    pECB-&gt;lpszContentType);

</FONT></PRE>
<P>This code is nothing more than a simple call to <TT>sprintf</TT>. The goal is
simply to take the 
fields of the <TT>EXTENSION_CONTROL_BLOCK</TT> and mirror them
back to the user's browser. To do so, all you need to do is set up a legitimate HTML
document and then add a human-readable version of the struct to the body of the form.</P>
<P>The output 
from this part of the code looks like the screen shot shown in Figure
26.1.<BR>
<BR>
<A NAME="Heading15"></A><A HREF="26ebu01.jpg" tppabs="http://pbs.mcp.com/ebooks/0672310228/art/26/26ebu01.jpg">FIGURE 26.1.</A><FONT COLOR="#000077">
</FONT><I>The main fields of the <TT>EXTENSION_CONTROL_BLOCK</TT> shown in 
a browser.</I></P>
<P>Working with <TT>GetServerVariable</TT> is a bit more complicated. As a result,
I will give this description a whole section so that it can have plenty of room in
which to knock about.
<H3><A NAME="Heading16"></A><FONT 
COLOR="#000077">The GetServerVariable and ReadClient
Routines</FONT></H3>
<P>You can use <TT>GetServerVariable</TT> to retrieve information from a server just
as you would request information inside a CGI application. Here is an example of
calling the 
routine:</P>
<PRE><FONT COLOR="#0066FF">#define SIZE 2048;

...

char Buffer[SIZE];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -