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

  1. /*++
  2.  
  3. Copyright (c) 1997  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     AReadCli.c
  8.  
  9. Abstract:
  10.  
  11.     This module demonstrates using asynchronous ReadClient call
  12.     to read data sent from client. On return, this sends the 
  13.     followings back to client:
  14.     
  15.     1) the number of bytes intended to send
  16.     2) the number of bytes actually read.
  17.     3) data content 
  18.  
  19. Author:
  20.  
  21.     Stanley Tam (stanleyt)   4-June 1997
  22.     
  23. Revision History:
  24.   
  25. --*/
  26. #include <windows.h>
  27. #include <stdio.h>
  28. #include <httpext.h>
  29.  
  30.  
  31. #define MAX_BUF_SIZE        (49152)                 // Max number of bytes for each read - 48K
  32. #define MEM_ALLOC_THRESHOLD (1024 * 1024)           // Default heap size is 1M
  33.  
  34.  
  35. typedef struct _IO_WORK_ITEM {
  36.  
  37.     PBYTE                       pbDATAFromClient;   // Grand read data holder
  38.     DWORD                       cbReadSoFar;        // Number of bytes read so far, 
  39.                                                     // and is used as index for pbDATAFromClient
  40.     EXTENSION_CONTROL_BLOCK *   pecb;
  41.  
  42. }  IO_WORK_ITEM, * PIOWI;
  43.  
  44.  
  45. //
  46. //  Sample Form for doing a POST method
  47. //
  48.  
  49. static CHAR             g_szPostForm[] =
  50.                         "<h2>Asychronous ReadClient Sample Post Form</h2><p>\r\n\r\n"
  51.                         "This demonstrates a post request being sent by this form to the sample ISAPI - AReadCli.dll<p>\r\n\r\n"
  52.                         "AReadCli.dll reads data posted by this form and send it back to the browser.<p>\r\n"
  53.                         "<h3>Post Form</h3>\r\n"
  54.                         "Please enter data below:<br>\r\n"
  55.                         "<form method=POST action=\"areadcli.dll\">\r\n"
  56.                         "<textarea name=\"Data\" cols=48 rows=4></textarea>\r\n\r\n"
  57.                         "<input type=submit> <input type=reset>\r\n"
  58.                         "</form>";
  59.  
  60. //
  61. //  Report read data
  62. //
  63.  
  64. static CHAR             g_szReport[] = 
  65.                         "Bytes count including \"Data=\"  \r\n"
  66.                         "ECB Total Bytes:    %d.\r\n"
  67.                         "Actual Read Bytes:  %d.\r\n";
  68.                 
  69. DWORD
  70. DoInit(IN OUT PIOWI piowi);
  71.  
  72. VOID
  73. DoCleanUp(IN PIOWI piowi);
  74.  
  75. DWORD
  76. DoAsyncReadClient(IN PIOWI piowi);
  77.              
  78. VOID WINAPI
  79. AsyncReadClientIoCompletion(IN LPEXTENSION_CONTROL_BLOCK pecb, 
  80.                             IN PVOID pContext,
  81.                             IN DWORD cbIO,
  82.                             IN DWORD dwError);
  83.  
  84. DWORD
  85. SendMSGToClient(IN LPEXTENSION_CONTROL_BLOCK pecb, 
  86.                 IN LPCSTR pszErrorMsg);
  87.  
  88. LPVOID 
  89. AR_Allocate(IN LPEXTENSION_CONTROL_BLOCK pecb, IN DWORD dwSize);
  90.  
  91. BOOL 
  92. AR_Free(IN LPEXTENSION_CONTROL_BLOCK pecb, IN LPVOID pvData);
  93.  
  94.  
  95.  
  96. DllMain(
  97.      IN HINSTANCE hinstDll,
  98.      IN DWORD     fdwReason,
  99.      IN LPVOID    lpvContext OPTIONAL)
  100. /*++
  101.  
  102.  Routine Description:
  103.  
  104.    This function DllLibMain() is the main initialization function for
  105.     this DLL. It initializes local variables and prepares it to be invoked
  106.     subsequently.
  107.  
  108.  Arguments:
  109.  
  110.    hinstDll          Instance Handle of the DLL
  111.    fdwReason         Reason why NT called this DLL
  112.    lpvReserved       Reserved parameter for future use.
  113.  
  114.  fReturn Value:
  115.  
  116.     fReturns TRUE if successful; otherwise FALSE is fReturned.
  117.  
  118. --*/
  119. {
  120.   BOOL    fReturn = TRUE;
  121.  
  122.  
  123.   switch ( fdwReason) {
  124.  
  125.     case DLL_PROCESS_ATTACH:
  126.       {
  127.           OutputDebugString( "Initializing the global data for areadcli.dll\n");
  128.  
  129.           //
  130.           // Prevent the system from calling DllMain
  131.           // when threads are created or destroyed.
  132.           //
  133.  
  134.           DisableThreadLibraryCalls( hinstDll);
  135.  
  136.           //
  137.           // Initialize various data and modules.
  138.           //
  139.  
  140.           break;
  141.  
  142.       } // case DLL_PROCESS_ATTACH
  143.  
  144.     case DLL_PROCESS_DETACH:
  145.       {
  146.  
  147.           if ( lpvContext != NULL) { }
  148.  
  149.           break;
  150.       } // case DLL_PROCESS_DETACH
  151.  
  152.     default:
  153.       break;
  154.   }   // switch
  155.  
  156.   return (fReturn);
  157. }  // DllLibMain()
  158.  
  159.  
  160.  
  161.  
  162. BOOL WINAPI
  163. GetExtensionVersion(HSE_VERSION_INFO * Version)
  164. /*++
  165.  
  166. Routine Description:
  167.  
  168.     Sets the ISAPI extension version information.
  169.  
  170. Arguments:
  171.  
  172.     Version     pointer to HSE_VERSION_INFO structure
  173.  
  174. Return Value:
  175.  
  176.     TRUE
  177.  
  178. --*/
  179. {
  180.     Version->dwExtensionVersion = 
  181.     MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
  182.  
  183.     strcpy(Version->lpszExtensionDesc, "Asynchronous Read Client Sample ISAPI DLL");
  184.  
  185.     return TRUE;
  186. }
  187.  
  188.  
  189.  
  190.  
  191. DWORD WINAPI
  192. HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK pecb)
  193. /*++
  194.  
  195. Routine Description:
  196.  
  197.     This is the main routine for any ISAPI application. Inside DoASyncReadClient,
  198.     proper action will be performed to read data from client asynchronously. Any data 
  199.     read from client will be sent back to the client by using synchronous WriteClient.
  200.  
  201. Arguments:
  202.  
  203.     pecb        pointer to ECB containing parameters related to the request.
  204.  
  205. Return Value:
  206.  
  207.     HSE_STATUS_SUCCESS  or
  208.     HSE_STATUS_PENDING  or 
  209.     HSE_STATUS_ERROR
  210.  
  211. --*/
  212. {
  213.     PIOWI   piowi;
  214.     DWORD   hseStatus = HSE_STATUS_SUCCESS;
  215.     
  216.     //
  217.     // The string length of textarea name "Data=" is 5. 
  218.     // Available bytes <= 5 indicates that no user-
  219.     // entered data has been sent, and the post form 
  220.     // is shown.
  221.     //
  222.  
  223.     if ( pecb->cbAvailable <= 5) {  
  224.  
  225.         hseStatus = SendMSGToClient(pecb, g_szPostForm);
  226.     
  227.     } else {
  228.  
  229.         piowi  = (PIOWI ) LocalAlloc( LMEM_FIXED, sizeof( IO_WORK_ITEM));
  230.  
  231.         if ( NULL == piowi) {
  232.  
  233.             SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  234.             return (HSE_STATUS_ERROR);
  235.         }
  236.  
  237.         piowi->pecb = pecb;
  238.  
  239.         //
  240.         // Init Grand data holder, assign the first chunk(read-ahead chunk)
  241.         // and update the index (cbRreadSoFar) of the grand data holder.
  242.         //
  243.  
  244.         hseStatus = DoInit( piowi);
  245.         
  246.         if ( HSE_STATUS_ERROR != hseStatus) {
  247.             
  248.             //
  249.             // Now we are ready to do asynchronous readclient here
  250.             //
  251.  
  252.             hseStatus = DoAsyncReadClient( piowi);
  253.         
  254.             if (hseStatus != HSE_STATUS_PENDING) {
  255.  
  256.                 //
  257.                 //  When IO finishes, tell IIS we will end the
  258.                 //  session. Also clean up other resources here
  259.                 //
  260.  
  261.                 DoCleanUp( piowi);
  262.  
  263.             }
  264.         
  265.         }
  266.  
  267.     }
  268.        
  269.     return (hseStatus);
  270. }
  271.  
  272.  
  273.  
  274.  
  275. BOOL WINAPI
  276. TerminateExtension(DWORD dwFlags)
  277. /*++
  278.  
  279. Routine Description:
  280.  
  281.     This function is called when the WWW service is shutdown
  282.  
  283. Arguments:
  284.  
  285.     dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
  286.  
  287. Return Value:
  288.  
  289.     TRUE
  290.  
  291. --*/
  292. {
  293.     return TRUE;
  294. }
  295.  
  296.  
  297.  
  298.  
  299. DWORD
  300. SendMSGToClient(IN LPEXTENSION_CONTROL_BLOCK  pecb, IN LPCSTR pszMsg)
  301. /*++
  302.  
  303. Routine Description:
  304.  
  305.     Prepare header, SendHeaderExInfo struct and write whatever
  306.     message is intended to send to the client.
  307.  
  308. Arguments:
  309.  
  310.     pecb        - pointer to ECB containing parameters related to the request.
  311.     pszMsg      - pointer to the body of the message that is sent to the content.
  312.  
  313. Return Value:
  314.  
  315.     HSE_STATUS_SUCCESS  or HSE_STATUS_ERROR
  316.  
  317. --*/
  318. {
  319.     HSE_SEND_HEADER_EX_INFO    SHEI;
  320.  
  321.     BOOL    fReturn;
  322.     DWORD   cbText;
  323.     DWORD   hseStatus = HSE_STATUS_SUCCESS;
  324.     CHAR    *pszText = NULL;
  325.     
  326.     CHAR    szStatus[] = "200 OK";
  327.     CHAR    szHeaderBase[] = "Content-type: text/html\r\n\r\n";
  328.     
  329.     //
  330.     //  Populate SendHeaderExInfo struct
  331.     //
  332.     //  NOTE we must send Content-Length header with correct 
  333.     //  byte count in order for keep-alive to work.
  334.     //
  335.     //
  336.  
  337.     SHEI.pszStatus = szStatus;
  338.     SHEI.pszHeader = szHeaderBase;
  339.     SHEI.cchStatus = lstrlen(szStatus);
  340.     SHEI.cchHeader = lstrlen(szHeaderBase);
  341.     SHEI.fKeepConn = FALSE;
  342.     
  343.     //
  344.     //  Build page 
  345.     //
  346.     
  347.     cbText = strlen("<head><title>Simple Async Read Client Sample</title></head>\n<body></body>\n")
  348.              + strlen(pszMsg)
  349.              + 1;
  350.  
  351.     pszText = (PCHAR) AR_Allocate(pecb, cbText);
  352.  
  353.     if ( NULL == pszText) {
  354.  
  355.         SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  356.         return (HSE_STATUS_ERROR);
  357.     }
  358.     
  359.     strcpy(pszText, "<head><title>Simple Async Read Client Sample</title></head>\n");
  360.     strcat(pszText, "<body>");
  361.     strcat(pszText, pszMsg);
  362.     strcat(pszText, "</body>\n");
  363.     cbText = (DWORD)strlen(pszText); 
  364.         
  365.     //
  366.     // Send header and body text to client
  367.     //
  368.  
  369.     fReturn = 
  370.     pecb->ServerSupportFunction( pecb->ConnID,
  371.                                  HSE_REQ_SEND_RESPONSE_HEADER_EX,  
  372.                                  &SHEI,
  373.                                  NULL,
  374.                                  NULL) 
  375.                                             
  376.                                  &&
  377.  
  378.     pecb->WriteClient( pecb->ConnID,
  379.                        pszText,
  380.                        &cbText,
  381.                        0 );
  382.  
  383.     if ( !fReturn)  {
  384.         hseStatus = HSE_STATUS_ERROR;
  385.     }
  386.  
  387.     
  388.     AR_Free( pecb, pszText);
  389.     
  390.     return ( hseStatus);
  391.  
  392.  
  393.  
  394.  
  395. DWORD
  396. DoAsyncReadClient(IN PIOWI piowi)
  397. /*++
  398.  
  399. Routine Description:
  400.  
  401.     The caller of the asynchrnous read client.
  402.  
  403. Arguments:
  404.  
  405.     piowi       pointer to the work item
  406.     
  407. Return Value:
  408.  
  409.     HSE_STATUS_SUCCESS  or
  410.     HSE_STATUS_PENDING  or 
  411.     HSE_STATUS_ERROR
  412.  
  413. --*/
  414. {   
  415.     BOOL    fReturn;
  416.     BYTE    *pbData = NULL;
  417.     CHAR    szTmp[MAX_BUF_SIZE];
  418.     DWORD   dwFlags;
  419.     DWORD   cbTotalToRead = MAX_BUF_SIZE;
  420.     DWORD   hseStatus =  HSE_STATUS_PENDING;
  421.     
  422.     //
  423.     // Check if cbTotalBytes == cbAvailable
  424.     // if so lpbData contains all the data sent by 
  425.     // the client, and complete the session. 
  426.     //
  427.  
  428.     if (piowi->pecb->cbTotalBytes == piowi->pecb->cbAvailable) {
  429.         
  430.         //
  431.         // Construct the report and write it to client
  432.         //
  433.  
  434.         pbData = (PBYTE) AR_Allocate(piowi->pecb, piowi->pecb->cbAvailable + MAX_BUF_SIZE);
  435.             
  436.         if ( NULL == pbData) {
  437.  
  438.             SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  439.             return (HSE_STATUS_ERROR);
  440.         }
  441.  
  442.         wsprintf ( pbData,
  443.                    g_szReport,
  444.                    piowi->pecb->cbTotalBytes,
  445.                    piowi->pecb->cbAvailable );
  446.                     
  447.         strcat( pbData, piowi->pecb->lpbData);  
  448.  
  449.         hseStatus = SendMSGToClient( piowi->pecb, pbData);
  450.  
  451.  
  452.         AR_Free( piowi->pecb, pbData);
  453.         DoCleanUp( piowi);
  454.         
  455.         return ( hseStatus); // HSE_STATUS_SUCCESS or HSE_STATUS_ERROR;
  456.     }
  457.  
  458.     //
  459.     //  More to read...
  460.     //
  461.  
  462.     //
  463.     //  Set a call back function and context that will 
  464.     //  be used for handling asynchrnous IO operations.
  465.     //  This only needs to set up once.
  466.     //
  467.  
  468.     fReturn =
  469.     piowi->pecb->ServerSupportFunction(
  470.                     piowi->pecb->ConnID,
  471.                     HSE_REQ_IO_COMPLETION,
  472.                     AsyncReadClientIoCompletion,
  473.                     0,
  474.                     (LPDWORD)piowi );  
  475.     
  476.     if ( !fReturn) {
  477.  
  478.         wsprintf ( szTmp, "Problem occurred at ServerSupportFunction() sending HSE_REQ_IO_COMPLETION request.");
  479.         SendMSGToClient( piowi->pecb, szTmp);
  480.         
  481.         return ( HSE_STATUS_ERROR);
  482.     }
  483.     
  484.  
  485.     //
  486.     //  Fire off the call to perform an asynchronus read from the client. 
  487.     //
  488.     
  489.     // 
  490.     // We need to first check if the size of the remaining chunk 
  491.     // is less than MAX_BUF_SIZE, if so just read what is available, 
  492.     // otherwise read MAX_BUF_SIZE bytes of data.
  493.     // 
  494.  
  495.     cbTotalToRead = piowi->pecb->cbTotalBytes - piowi->cbReadSoFar;
  496.     if ( cbTotalToRead > MAX_BUF_SIZE )  {
  497.  
  498.         cbTotalToRead = MAX_BUF_SIZE;
  499.     }
  500.  
  501.     dwFlags = HSE_IO_ASYNC;
  502.     fReturn = 
  503.     piowi->pecb->ServerSupportFunction(
  504.                         piowi->pecb->ConnID
  505.                       , HSE_REQ_ASYNC_READ_CLIENT
  506.                       , piowi->pbDATAFromClient + // append the new chunk to buffer, cbReadSoFar indexes
  507.                         piowi->cbReadSoFar        // the byte right after the last written byte in the buffer
  508.                       , &cbTotalToRead
  509.                       , &dwFlags);
  510.  
  511.     if (!fReturn) {
  512.         
  513.         wsprintf ( szTmp, "Problem occurred at ServerSupportFunction() sending HSE_REQ_ASYNC_READ_CLIENT request.");
  514.         SendMSGToClient( piowi->pecb, szTmp);
  515.         
  516.         hseStatus = HSE_STATUS_ERROR;
  517.     }
  518.  
  519.     return ( hseStatus); // HSE_STATUS_PENDING or HSE_STATUS_ERROR;
  520.     
  521. }
  522.  
  523.  
  524.  
  525.  
  526. VOID WINAPI
  527. AsyncReadClientIoCompletion(
  528.             IN LPEXTENSION_CONTROL_BLOCK pECB,
  529.             IN PVOID pContext,
  530.             IN DWORD cbIO,
  531.             IN DWORD dwError)
  532. /*++
  533.  
  534. Routine Description:
  535.  
  536.     This is the callback function for handling completions of asynchronous ReadClient.
  537.     This function resubmits additional IO to read the next chunk of data from the 
  538.     client. If there is no more data to read or problem during operation, this function 
  539.     will inform IIS that it is about to end the request session.
  540.     
  541.  
  542. Arguments:
  543.  
  544.     pecb        - extension control block
  545.     pContext    - this is a IO_WORK_ITEM
  546.     cbIO        - bytes just read
  547.     dwError     - Win32 error status code
  548.  
  549. fReturn Value:
  550.  
  551.     None
  552.  
  553. --*/
  554. {
  555.     BOOL    fReturn;
  556.     BYTE    *pbData = NULL;
  557.     CHAR    szTmp[MAX_BUF_SIZE];
  558.     DWORD   dwFlags;
  559.     DWORD   cbTotalToRead;
  560.     
  561.     PIOWI   piowi = ( PIOWI) pContext;
  562.     EXTENSION_CONTROL_BLOCK   * pecb = piowi->pecb;
  563.     
  564.  
  565.     if (ERROR_SUCCESS == dwError) {
  566.  
  567.         //
  568.         // Read successfully, so update current 
  569.         // total bytes read (aka index of grand data holder)
  570.         //
  571.  
  572.         piowi->cbReadSoFar += cbIO;     
  573.                                
  574.         //
  575.         // If they are equal, we finish reading all bytes from client
  576.         //
  577.         
  578.         if ( piowi->cbReadSoFar == pecb->cbTotalBytes ) { 
  579.  
  580.             //
  581.             // Construct the report and write it to client
  582.             //
  583.  
  584.             pbData = (PBYTE) AR_Allocate( pecb, piowi->cbReadSoFar + MAX_BUF_SIZE);
  585.                 
  586.             if ( NULL == pbData) {
  587.  
  588.                 SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  589.                 wsprintf ( szTmp, "Failed to allocate memory inside AsyncReadClientIoCompletion().");
  590.                 SendMSGToClient( pecb, szTmp);
  591.                 
  592.                 DoCleanUp( piowi);
  593.  
  594.                 return;
  595.             }
  596.             
  597.             wsprintf ( pbData, g_szReport, pecb->cbTotalBytes, piowi->cbReadSoFar );
  598.             piowi->pbDATAFromClient[piowi->cbReadSoFar] = 0; 
  599.             strcat( pbData, piowi->pbDATAFromClient);
  600.             SendMSGToClient( pecb, pbData);
  601.             
  602.  
  603.             AR_Free( piowi->pecb, pbData);
  604.             DoCleanUp( piowi);
  605.             
  606.             return;
  607.             
  608.         } else {
  609.  
  610.             // 
  611.             // Still have more data to read... 
  612.             // 
  613.             // We need to first check if the size of the remaining chunk 
  614.             // is less than MAX_BUF_SIZE, if so just read what is available, 
  615.             // otherwise read MAX_BUF_SIZE bytes of data.
  616.             // 
  617.  
  618.             cbTotalToRead = pecb->cbTotalBytes - piowi->cbReadSoFar;
  619.             if ( cbTotalToRead > MAX_BUF_SIZE )  {
  620.  
  621.                 cbTotalToRead = MAX_BUF_SIZE;
  622.             }
  623.             
  624.             // 
  625.             // Fire off another call to perform an asynchronus read from the client. 
  626.             //
  627.  
  628.             dwFlags = HSE_IO_ASYNC;
  629.             fReturn = 
  630.             pecb->ServerSupportFunction(
  631.                           pecb->ConnID
  632.                         , HSE_REQ_ASYNC_READ_CLIENT
  633.                         , piowi->pbDATAFromClient + // append the new chunk to buffer, cbReadSoFar indexes
  634.                           piowi->cbReadSoFar        // the byte right after the last written byte in the buffer
  635.                         , &cbTotalToRead
  636.                         , &dwFlags);
  637.  
  638.             if ( !fReturn) {
  639.                 wsprintf ( szTmp, "Problem occurred at ServerSupportFunction() sending HSE_REQ_ASYNC_READ_CLIENT request.");
  640.                 SendMSGToClient( pecb, szTmp);
  641.  
  642.                 DoCleanUp( piowi);
  643.                 
  644.                 return;
  645.             }
  646.  
  647.         }
  648.     
  649.     } else {
  650.  
  651.         //
  652.         // Error on read
  653.         //
  654.  
  655.         SetLastError(dwError);
  656.         
  657.         DoCleanUp( piowi);
  658.     }
  659.         
  660.     return;
  661.         
  662. } // AsyncReadClientIoCompletion
  663.  
  664.  
  665.  
  666.  
  667. DWORD
  668. DoInit(IN OUT PIOWI piowi)
  669. /*++
  670.  
  671. Routine Description:
  672.  
  673.     Initialize the  Grand data holder, assign the first chunk(read-ahead chunk)
  674.     and update the index (cbRreadSoFar) of the grand data holder.
  675.     
  676. Arguments:
  677.  
  678.     piowi       pointer to the work item
  679.  
  680. fReturn Value:
  681.  
  682.     HSE_STATUS_SUCCESS or HSE_STATUS_ERROR
  683.  
  684. --*/
  685. {
  686.  
  687.     piowi->pbDATAFromClient = 
  688.     (PBYTE) AR_Allocate( piowi->pecb, piowi->pecb->cbTotalBytes + MAX_BUF_SIZE);
  689.     
  690.     if ( NULL == piowi->pbDATAFromClient) {
  691.  
  692.         SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  693.         return (HSE_STATUS_ERROR);
  694.     }
  695.  
  696.     //
  697.     // The first chunk (read-ahead chunk) has arrived.  
  698.     //
  699.     
  700.     strcpy ( piowi->pbDATAFromClient, piowi->pecb->lpbData);
  701.     piowi->cbReadSoFar = piowi->pecb->cbAvailable;
  702.  
  703.     return (HSE_STATUS_SUCCESS);
  704. }
  705.  
  706.  
  707.  
  708.  
  709. VOID
  710. DoCleanUp(IN PIOWI piowi)
  711. /*++
  712.  
  713. Routine Description:
  714.  
  715.     End the session with IIS and clean up other previous allocated resources.
  716.     
  717. Arguments:
  718.  
  719.     piowi       pointer to the work item
  720.  
  721. fReturn Value:
  722.  
  723.     None
  724.  
  725. --*/
  726. {
  727.     
  728.     
  729.     if ( piowi->pbDATAFromClient != NULL) {
  730.  
  731.         AR_Free( piowi->pecb, piowi->pbDATAFromClient);
  732.  
  733.     }
  734.  
  735.     piowi->pecb->ServerSupportFunction( piowi->pecb->ConnID,
  736.                                         HSE_REQ_DONE_WITH_SESSION,
  737.                                         NULL,
  738.                                         NULL,
  739.                                         NULL);
  740.  
  741.     LocalFree( piowi);
  742.  
  743.     return;
  744.  
  745. }
  746.  
  747.  
  748.  
  749.  
  750. LPVOID 
  751. AR_Allocate(IN LPEXTENSION_CONTROL_BLOCK pecb, IN DWORD dwSize)
  752. /*++
  753.  
  754. Routine Description:
  755.  
  756.     Memory allocation routine. Two different Win32 API's to allocate
  757.     bytes in memory, which is based on the number of bytes coming from 
  758.     the client. If the size is greater than 1 M bytes VirtualAllocate is 
  759.     used, otherwise HeapAllocate is used.
  760.     
  761. Arguments:
  762.  
  763.     pecb        - pointer to ECB containing parameters related to the request.
  764.     dwSize      - number of bytes to allocate
  765.  
  766. fReturn Value:
  767.  
  768.     Pointer to void
  769.  
  770. --*/
  771. {
  772.     LPVOID pvData = NULL;
  773.     
  774.  
  775.     if ( pecb->cbTotalBytes > MEM_ALLOC_THRESHOLD) {
  776.  
  777.         pvData = 
  778.         VirtualAlloc( NULL, 
  779.                       dwSize,
  780.                       MEM_RESERVE | MEM_COMMIT, 
  781.                       PAGE_READWRITE);
  782.  
  783.     } else {
  784.  
  785.         pvData = 
  786.         HeapAlloc( GetProcessHeap(), 
  787.                    HEAP_ZERO_MEMORY,
  788.                    dwSize);
  789.                            
  790.     }
  791.  
  792.     return ( pvData);
  793.  
  794. }
  795.  
  796.  
  797.  
  798.  
  799. BOOL
  800. AR_Free( IN LPEXTENSION_CONTROL_BLOCK pecb, IN LPVOID pvData)
  801. /*++
  802.  
  803. Routine Description:
  804.  
  805.     Freeing memory routine, a complementary routine to AR_Allocate. 
  806.     Two different Win32 API's will be used to free up bytes in memory,
  807.     which is based on the number of bytes coming from the client. If 
  808.     the size is greater than 1 M bytes VirtualFree is used. Otherwise, 
  809.     HeapFree is used.
  810.     
  811. Arguments:
  812.  
  813.     pecb        - pointer to ECB containing parameters related to the request.
  814.     pvData      - pointer to the data to be freed.
  815.  
  816. fReturn Value:
  817.  
  818.     TRUE or FALSE
  819.  
  820. --*/
  821. {
  822.     BOOL fReturn = FALSE;
  823.  
  824.  
  825.     if ( pecb->cbTotalBytes > MEM_ALLOC_THRESHOLD) {
  826.         
  827.         fReturn = VirtualFree( pvData, 0, MEM_RELEASE);
  828.  
  829.     } else {
  830.  
  831.         fReturn = HeapFree( GetProcessHeap(), 0, pvData);
  832.     }
  833.  
  834.     return (fReturn);
  835. }
  836.