home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / software / pelne / optionp / iis4_07.cab / FORMDUMP.CPP < prev    next >
C/C++ Source or Header  |  1997-10-25  |  14KB  |  622 lines

  1. /*++
  2.  
  3. Copyright (c) 1997  Microsoft Corporation
  4.  
  5. Module Name:    formdump.cpp
  6.  
  7. Abstract:
  8.  
  9.     ISAPI Extension sample illustrating how to obtain data from a web browser
  10.     and how to build a reply to the form. 
  11.  
  12. --*/
  13.  
  14. #define WIN32_LEAN_AND_MEAN     // the bare essential Win32 API
  15. #include <windows.h>
  16. #include <ctype.h>              // for isprint()
  17. #include <httpext.h>
  18.  
  19. #include "keys.h"
  20. #include "html.h"
  21.  
  22. //
  23. // local prototypes
  24. // 
  25. void SendVariables( EXTENSION_CONTROL_BLOCK * pECB );
  26. void HexDumper( EXTENSION_CONTROL_BLOCK * pECB, LPBYTE lpbyBuf, DWORD dwLength );
  27. void WhoAmI( EXTENSION_CONTROL_BLOCK * pECB );
  28. BOOL SendHttpHeaders( EXTENSION_CONTROL_BLOCK *, LPCSTR, LPCSTR );
  29.  
  30.  
  31. BOOL WINAPI
  32. GetExtensionVersion(
  33.     OUT HSE_VERSION_INFO * pVer
  34.     )
  35. /*++
  36.  
  37. Purpose:
  38.  
  39.     This is required ISAPI Extension DLL entry point.
  40.  
  41. Arguments:
  42.  
  43.     pVer - poins to extension version info structure 
  44.  
  45. Returns:
  46.  
  47.     always returns TRUE
  48.  
  49. --*/
  50. {
  51.     //
  52.     // set version to httpext.h version constants
  53.     //
  54.     pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
  55.  
  56.     lstrcpyn((LPSTR) pVer->lpszExtensionDesc,
  57.         "FORMDUMP - A Form Decoder and Dumper",
  58.         HSE_MAX_EXT_DLL_NAME_LEN);
  59.  
  60.     return TRUE;
  61. }       
  62.  
  63.  
  64. DWORD WINAPI
  65. HttpExtensionProc(
  66.     IN EXTENSION_CONTROL_BLOCK * pECB
  67. )
  68. /*++
  69.  
  70. Purpose:
  71.  
  72.     Pull in all inbound data.  Build a reply page
  73.     so the user can see how forms appear in our key list.
  74.  
  75. Arguments:
  76.  
  77.     pECB - pointer to the extenstion control block 
  78.  
  79. Returns:
  80.  
  81.     HSE_STATUS_SUCCESS on successful completion
  82.     HSE_STATUS_ERROR on failure
  83.  
  84. --*/
  85. {
  86.     HKEYLIST hKeyList;
  87.     char szMsg[128];
  88.  
  89.     //
  90.     // Get the keys sent by the client
  91.     //
  92.     
  93.     hKeyList = GetKeyList( pECB );
  94.  
  95.     
  96.     //
  97.     // Send HTTP headers 
  98.     //
  99.     
  100.     SendHttpHeaders( pECB, "200 OK", "Content-type: text/html\r\n\r\n" );
  101.  
  102.     //
  103.     // Create a basic HTML page
  104.     //
  105.     
  106.     HtmlCreatePage( pECB, "FormDump.dll Reply" );
  107.     HtmlHeading( pECB, 1, "Data Available via ISAPI" );
  108.     HtmlHorizontalRule( pECB );
  109.  
  110.     // 
  111.     // Send each form field
  112.     // 
  113.  
  114.     HtmlHeading( pECB, 2, "Form Fields" );
  115.  
  116.     if ( !hKeyList ) {
  117.     
  118.         //
  119.         // Report no data/error
  120.         //
  121.         
  122.         HtmlBold( pECB, "No form fields sent" );
  123.         HtmlWriteText( pECB, " (or error decoding keys)" );
  124.         HtmlEndParagraph( pECB );
  125.         
  126.     } else {
  127.         HKEYLIST hKey;
  128.  
  129.         //
  130.         // Print a quick overview
  131.         //
  132.         
  133.         HtmlWriteTextLine( pECB, "The form you submitted data to just called" );
  134.         HtmlWriteTextLine( pECB, "the Internet Information Server extension" );
  135.         HtmlWriteTextLine( pECB, "FormDump.dll.  Here is a listing of what was" );
  136.         HtmlWriteTextLine( pECB, "received and what variables inside FormDump" );
  137.         HtmlWriteTextLine( pECB, "have the data." );
  138.         HtmlEndParagraph( pECB );
  139.  
  140.         //
  141.         // Loop through all of the keys
  142.         //
  143.         hKey = hKeyList;
  144.         while ( hKey ) {
  145.         
  146.             //
  147.             // Details about the key
  148.             //
  149.             
  150.             LPCTSTR lpszKeyName;
  151.             DWORD dwLength;
  152.             BOOL bHasCtrlChars;
  153.             int nInstance;
  154.             HKEYLIST hLastKey;
  155.  
  156.             //
  157.             // We get info, and hKey points to next key in list
  158.             //
  159.             
  160.             hLastKey = hKey;    // keep this for later
  161.  
  162.             hKey = GetKeyInfo( hKey, &lpszKeyName, &dwLength,
  163.                 &bHasCtrlChars, &nInstance );
  164.  
  165.             //
  166.             // Build web page
  167.             //
  168.             
  169.             HtmlBold( pECB, "Form Field Name (lpszKeyName): " );
  170.             HtmlWriteText( pECB, lpszKeyName );
  171.             HtmlLineBreak( pECB );
  172.  
  173.             HtmlBold( pECB, "Length of Data (dwLength): " );
  174.             wsprintf( szMsg, "%u", dwLength );
  175.             HtmlWriteText( pECB, szMsg );
  176.             HtmlLineBreak( pECB );
  177.  
  178.             HtmlBold( pECB, "Data Has Control Characters (bHasCtrlChars): " );
  179.             wsprintf( szMsg, "%u", bHasCtrlChars );
  180.             HtmlWriteText( pECB, szMsg );
  181.             HtmlLineBreak( pECB );
  182.  
  183.             HtmlBold( pECB, "Instance of Form Field (nInstance): " );
  184.             wsprintf( szMsg, "%u", nInstance );
  185.             HtmlWriteText( pECB, szMsg );
  186.  
  187.             if ( dwLength ) {
  188.                 HtmlLineBreak( pECB );
  189.                 HtmlBold( pECB, "Data Sent for Field:" );
  190.                 HtmlLineBreak( pECB );
  191.  
  192.                 HexDumper( pECB, GetKeyBuffer( hLastKey ), dwLength );
  193.             }
  194.             HtmlEndParagraph( pECB );
  195.         }
  196.     
  197.         //
  198.         // Clean up
  199.         //
  200.         
  201.         FreeKeyList( hKeyList );
  202.     }
  203.  
  204.     HtmlHorizontalRule( pECB );
  205.  
  206.  
  207.     // 
  208.     // Get user name from SID and return it in the page
  209.     // 
  210.  
  211.     HtmlHeading( pECB, 2, "Security Context for HttpExtensionProc Thread" );
  212.     WhoAmI( pECB );
  213.     HtmlHorizontalRule( pECB );
  214.  
  215.  
  216.     // 
  217.     // Display all server variables
  218.     // 
  219.  
  220.     HtmlHeading( pECB, 2, "Server Variables" );
  221.     HtmlWriteTextLine( pECB, 
  222.         "Below is a list of all variables available via" );
  223.     HtmlWriteTextLine( pECB, "GetServerVariable ISAPI API.  Much of this" );
  224.     HtmlWriteTextLine( pECB, 
  225.         "information comes from the browser HTTP header." );
  226.     HtmlEndParagraph( pECB );
  227.  
  228.     //
  229.     // Send server variables obtained from the HTTP header
  230.     //
  231.     
  232.     SendVariables( pECB );
  233.  
  234.  
  235.     //
  236.     // Finish up...
  237.     //
  238.     
  239.     HtmlEndPage( pECB );
  240.  
  241.     return HSE_STATUS_SUCCESS;
  242. }
  243.  
  244.  
  245. BOOL WINAPI
  246. TerminateExtension(
  247.     DWORD dwFlags
  248. )
  249. /*++
  250.  
  251. Purpose:
  252.  
  253.     This is optional ISAPI extension DLL entry point.
  254.     If present, it will be called before unloading the DLL,
  255.     giving it a chance to perform any shutdown procedures.
  256.     
  257. Arguments:
  258.     
  259.     dwFlags - specifies whether the DLL can refuse to unload or not
  260.     
  261. Returns:
  262.     
  263.     TRUE, if the DLL can be unloaded
  264.     
  265. --*/
  266. {
  267.     return TRUE;
  268. }
  269.  
  270.  
  271.  
  272.  
  273. void
  274. HexDumper(
  275.     IN EXTENSION_CONTROL_BLOCK * pECB,
  276.     IN LPBYTE lpbyBuf,
  277.     IN DWORD dwLength
  278. )
  279. /*++
  280.  
  281. Purpose:
  282.  
  283.     Put the inbound data in a hex dump format
  284.  
  285. Arguments:
  286.     
  287.     pECB - points to the extension control block
  288.     lpbyByf - bytes to dump
  289.     dwLength - specifies the number of bytes to dump
  290.     
  291. --*/
  292. {
  293.     DWORD dwSize;
  294.     char szLine[80];
  295.     char szHex[3];
  296.     DWORD i;
  297.     DWORD dwPos = 0;
  298.  
  299.     HtmlBeginPreformattedText( pECB );
  300.  
  301.     while (dwLength) {
  302.     
  303.         //
  304.         // Take min of 16 or dwLength
  305.         //
  306.         
  307.         dwSize = min(16, dwLength );
  308.  
  309.         //
  310.         // Build text line
  311.         //
  312.         
  313.         wsprintf(szLine, "  %04X ", dwPos );
  314.  
  315.         for (i = 0; i < dwSize; i++) {
  316.             wsprintf(szHex, "%02X", lpbyBuf[i] );
  317.             lstrcat(szLine, szHex );
  318.             lstrcat(szLine, " " );
  319.         }
  320.  
  321.         //
  322.         // Add spaces for short lines
  323.         //
  324.         
  325.         while (i < 16) {
  326.             lstrcat(szLine, "   " );
  327.             i++;
  328.         }
  329.  
  330.         //
  331.         // Add ASCII chars
  332.         //
  333.         
  334.         for (i = 0; i < dwSize; i++) {
  335.             if (isprint(lpbyBuf[i])) {
  336.                 wsprintf(szHex, "%c", lpbyBuf[i] );
  337.                 lstrcat(szLine, szHex );
  338.             } else {
  339.                 lstrcat(szLine, "." );
  340.             }
  341.         }
  342.  
  343.         //
  344.         // Write data to web page
  345.         //
  346.         
  347.         HtmlWriteTextLine( pECB, szLine );
  348.  
  349.         //
  350.         // Advance positions
  351.         //
  352.         
  353.         dwLength -= dwSize;
  354.         dwPos += dwSize;
  355.         lpbyBuf += dwSize;
  356.     }
  357.  
  358.     HtmlEndPreformattedText( pECB );
  359. }
  360.  
  361.  
  362. void
  363. DumpVariable(
  364.     IN EXTENSION_CONTROL_BLOCK * pECB,
  365.     IN LPCTSTR szName
  366. )
  367. /*++
  368.  
  369. Purpose:
  370.     
  371.     Dump a server variable
  372.  
  373. Arguments:
  374.  
  375.     pECB - points to the extension control block
  376.     lpbyByf - points to ASCIIZ name of the server variable to dump
  377.     
  378. --*/    
  379. {
  380.     DWORD dwBufferSize;
  381.     char szBuffer[4096];
  382.     BOOL bReturn;
  383.  
  384.     dwBufferSize = sizeof szBuffer;
  385.     bReturn = pECB->GetServerVariable( pECB->ConnID,
  386.         (LPSTR) szName,
  387.         szBuffer,
  388.         &dwBufferSize );
  389.  
  390.     if ( !bReturn || !szBuffer[0] )
  391.         return;
  392.  
  393.     HtmlWriteText( pECB, szName );
  394.     HtmlWriteText( pECB, "=" );
  395.     HtmlWriteText( pECB, szBuffer );
  396.     HtmlLineBreak( pECB );
  397. }
  398.  
  399.  
  400. BOOL 
  401. SendHttpHeaders( 
  402.     EXTENSION_CONTROL_BLOCK *pECB, 
  403.     LPCSTR pszStatus,
  404.     LPCSTR pszHeaders
  405. )
  406. /*++
  407.  
  408. Purpose:
  409.     Send specified HTTP status string and any additional header strings
  410.     using new ServerSupportFunction() request HSE_SEND_HEADER_EX_INFO
  411.  
  412. Arguments:
  413.  
  414.     pECB - pointer to the extension control block
  415.     pszStatus - HTTP status string (e.g. "200 OK")
  416.     pszHeaders - any additional headers, separated by CRLFs and 
  417.                  terminated by empty line
  418.  
  419. Returns:
  420.  
  421.     TRUE if headers were successfully sent
  422.     FALSE otherwise
  423.  
  424. --*/
  425. {
  426.     HSE_SEND_HEADER_EX_INFO header_ex_info;
  427.     BOOL success;
  428.  
  429.     header_ex_info.pszStatus = pszStatus;
  430.     header_ex_info.pszHeader = pszHeaders;
  431.     header_ex_info.cchStatus = strlen( pszStatus );
  432.     header_ex_info.cchHeader = strlen( pszHeaders );
  433.     header_ex_info.fKeepConn = FALSE;
  434.  
  435.  
  436.     success = pECB->ServerSupportFunction(
  437.                   pECB->ConnID,
  438.                   HSE_REQ_SEND_RESPONSE_HEADER_EX,
  439.                   &header_ex_info,
  440.                   NULL,
  441.                   NULL
  442.                   );
  443.  
  444.     return success;
  445. }
  446.  
  447.  
  448. void
  449. SendVariables(
  450.     IN EXTENSION_CONTROL_BLOCK * pECB
  451. )
  452. /*++
  453.  
  454. Purpose:
  455.  
  456.     Send all server variables (they came in the HTTP header)
  457.     
  458. Arguments:
  459.  
  460.     pECB - pointer to the extension control block
  461.     
  462. --*/    
  463. {
  464.     char *pChar, *pOpts, *pEnd;
  465.     DWORD dwBufferSize;
  466.     char szBuffer[4096];
  467.     BOOL bReturn;
  468.  
  469.     // 
  470.     // Dump the standard variables
  471.     // 
  472.  
  473.     DumpVariable( pECB, "AUTH_TYPE" );
  474.     DumpVariable( pECB, "CONTENT_LENGTH" );
  475.     DumpVariable( pECB, "CONTENT_TYPE" );
  476.     DumpVariable( pECB, "GATEWAY_INTERFACE" );
  477.     DumpVariable( pECB, "PATH_INFO" );
  478.     DumpVariable( pECB, "PATH_TRANSLATED" );
  479.     DumpVariable( pECB, "QUERY_STRING" );
  480.     DumpVariable( pECB, "REMOTE_ADDR" );
  481.     DumpVariable( pECB, "REMOTE_HOST" );
  482.     DumpVariable( pECB, "REMOTE_USER" );
  483.     DumpVariable( pECB, "REQUEST_METHOD" );
  484.     DumpVariable( pECB, "SCRIPT_NAME" );
  485.     DumpVariable( pECB, "SERVER_NAME" );
  486.     DumpVariable( pECB, "SERVER_PORT" );
  487.     DumpVariable( pECB, "SERVER_PROTOCOL" );
  488.     DumpVariable( pECB, "SERVER_SOFTWARE" );
  489.     DumpVariable( pECB, "AUTH_PASS" );
  490.  
  491.  
  492.     // 
  493.     // Dump any others (in ALL_HTTP)
  494.     // 
  495.  
  496.     dwBufferSize = sizeof szBuffer;
  497.     bReturn = pECB->GetServerVariable( pECB->ConnID,
  498.         "ALL_HTTP",
  499.         szBuffer,
  500.         &dwBufferSize );
  501.  
  502.     if ( bReturn ) {
  503.         // 
  504.         // Find lines, split key/data pair and write them as output
  505.         // 
  506.  
  507.         pChar = szBuffer;
  508.         while ( *pChar ) {
  509.             if ( *pChar == '\r' || *pChar == '\n' ) {
  510.                 pChar++;
  511.                 continue;
  512.             }
  513.             pOpts = strchr( pChar, ':' );   // look for separator
  514.  
  515.             if ( !pOpts )
  516.                 break;
  517.             if ( !*pOpts )
  518.                 break;
  519.  
  520.             pEnd = pOpts;
  521.             while ( *pEnd && *pEnd != '\r' && *pEnd != '\n' )
  522.                 pEnd++;
  523.  
  524.             *pOpts = 0;         // split strings
  525.  
  526.             *pEnd = 0;
  527.  
  528.             // 
  529.             // pChar points to variable name, pOpts + 1 points to variable
  530.             // val
  531.             // 
  532.  
  533.             HtmlWriteText( pECB, pChar );
  534.             HtmlWriteText( pECB, "=" );
  535.             HtmlWriteText( pECB, pOpts + 1 );
  536.             HtmlLineBreak( pECB );
  537.  
  538.             pChar = pEnd + 1;
  539.         }
  540.     }
  541.     HtmlEndParagraph( pECB );
  542.     HtmlHorizontalRule( pECB );
  543. }
  544.  
  545.  
  546. void
  547. WhoAmI(
  548.     IN EXTENSION_CONTROL_BLOCK * pECB
  549. )
  550. /*++
  551.  
  552. Purpose:
  553.     
  554.     Get the user SID, lookup the account name and display it
  555.  
  556. Arguments:
  557.  
  558.     pECB - pointer to the extension control block
  559.     
  560. --*/    
  561. {
  562.     HANDLE hToken;
  563.     PTOKEN_USER pTokenUser;
  564.     BYTE byBuf[1024];
  565.     DWORD dwLen;
  566.     char szName[256], szDomain[256];
  567.     DWORD dwNameLen, dwDomainLen;
  568.     SID_NAME_USE eUse;
  569.  
  570.     if ( !OpenThreadToken( 
  571.             GetCurrentThread( ), TOKEN_QUERY, TRUE, &hToken ) ) {
  572.             
  573.         DWORD dwError = GetLastError( );
  574.  
  575.         HtmlBold( pECB, "OpenThreadToken failed. " );
  576.         HtmlPrintf( pECB, "Error code=%u", dwError );
  577.         HtmlEndParagraph( pECB );
  578.         return;
  579.     }
  580.     
  581.     pTokenUser = (PTOKEN_USER) byBuf;
  582.     if ( !GetTokenInformation(
  583.             hToken, TokenUser, pTokenUser, sizeof byBuf, &dwLen ) ) {
  584.             
  585.         DWORD dwError = GetLastError( );
  586.  
  587.         CloseHandle( hToken );
  588.  
  589.         HtmlBold( pECB, "GetTokenInformation failed. " );
  590.         HtmlPrintf( pECB, "Error code=%u dwLen=%u", dwError, dwLen );
  591.         HtmlEndParagraph( pECB );
  592.         return;
  593.     }
  594.     
  595.     dwNameLen = sizeof szName;
  596.     dwDomainLen = sizeof szDomain;
  597.     if ( !LookupAccountSid( NULL, pTokenUser->User.Sid,
  598.             szName, &dwNameLen,
  599.             szDomain, &dwDomainLen, &eUse )) {
  600.             
  601.         DWORD dwError = GetLastError( );
  602.  
  603.         CloseHandle( hToken );
  604.  
  605.         HtmlBold( pECB, "LookupAccountSid failed. " );
  606.         HtmlPrintf( pECB, "Error code=%u dwNameLen=%u dwDomainLen=%u",
  607.             dwError, dwNameLen, dwDomainLen );
  608.         HtmlEndParagraph( pECB );
  609.         return;
  610.     }
  611.     
  612.     HtmlBold( pECB, "Domain: " );
  613.     HtmlWriteText( pECB, szDomain );
  614.     HtmlLineBreak( pECB );
  615.     HtmlBold( pECB, "User: " );
  616.     HtmlWriteText( pECB, szName );
  617.     HtmlEndParagraph( pECB );
  618.  
  619.     CloseHandle( hToken );
  620. }
  621.  
  622.