2025-04-27 07:49:33 -04:00

378 lines
9.4 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994-1996 Microsoft Corporation
Module Name:
binsrv.cxx
Abstract:
Main module for binary object server ISAPI application.
It uses Async TransmitFile for achieving the same.
Author:
Murali R. Krishnan ( MuraliK ) 30-Oct-1996
Revision History:
--*/
#include <windows.h>
#include <iisext.h>
# include "dbgutil.h"
/************************************************************
* Global Data
************************************************************/
CRITICAL_SECTION g_csWorkItems;
# define USE_WORK_QUEUE (0)
DWORD
SendHeaderToClient( IN EXTENSION_CONTROL_BLOCK * pecb, IN LPCSTR pszErrorMsg);
DWORD
SendFileToClient( IN EXTENSION_CONTROL_BLOCK * pecb);
DWORD
SendFileOver( IN EXTENSION_CONTROL_BLOCK * pecb,
IN HANDLE hFile,
IN LPCSTR pszFile);
DWORD
GenerateBinaryUrlName( IN EXTENSION_CONTROL_BLOCK * pecb,
OUT CHAR * pszNewUrl,
OUT LPCSTR * ppszError
);
DECLARE_DEBUG_PRINTS_OBJECT();
DECLARE_DEBUG_VARIABLE();
/************************************************************
* Functions
************************************************************/
BOOL WINAPI
DllLibMain(
IN HINSTANCE hinstDll,
IN DWORD fdwReason,
IN LPVOID lpvContext OPTIONAL)
/*++
Routine Description:
This function DllLibMain() is the main initialization function for
this DLL. It initializes local variables and prepares it to be invoked
subsequently.
Arguments:
hinstDll Instance Handle of the DLL
fdwReason Reason why NT called this DLL
lpvReserved Reserved parameter for future use.
Return Value:
Returns TRUE is successful; otherwise FALSE is returned.
--*/
{
BOOL fReturn = TRUE;
switch (fdwReason ) {
case DLL_PROCESS_ATTACH:
{
OutputDebugString( " Initializing the global data\n");
//
// Initialize various data and modules.
//
InitializeCriticalSection(&g_csWorkItems);
break;
} /* case DLL_PROCESS_ATTACH */
case DLL_PROCESS_DETACH:
{
//
// Only cleanup when we are called because of a FreeLibrary().
// i.e., when lpvContext == NULL
// If we are called because of a process termination,
// dont free anything. System will free resources and memory for us.
//
if ( lpvContext != NULL) {
DeleteCriticalSection(&g_csWorkItems);
}
break;
} /* case DLL_PROCESS_DETACH */
default:
break;
} /* switch */
return ( fReturn);
} /* DllLibMain() */
DWORD WINAPI
HttpExtensionProc(
EXTENSION_CONTROL_BLOCK * pecb
)
/*++
Routine Description:
This function performs the necessary action to send response for the
request received from the client. It picks up the name of a file from
the pecb->lpszQueryString and transmits that file to the client.
Arguments:
pecb pointer to ECB containing parameters related to the request.
Return Value:
Returns HSE_* status codes
--*/
{
char buff[2048];
DWORD hseStatus;
IF_DEBUG( API_ENTRY) {
DBGPRINTF(( DBG_CONTEXT, "HttpExtensionProc( %08x) QS: %s. PI: %s\n",
pecb,
(pecb->lpszQueryString) ? pecb->lpszQueryString : "null",
(pecb->lpszPathInfo) ? pecb->lpszPathInfo : "null"
));
}
hseStatus = SendFileToClient( pecb);
return ( hseStatus);
} // HttpExtensionProc()
BOOL WINAPI
GetExtensionVersion(
HSE_VERSION_INFO * pver
)
{
CREATE_DEBUG_PRINT_OBJECT( "binsrv");
SET_DEBUG_FLAGS( DEBUG_ERROR | DEBUG_API_ENTRY | DEBUG_API_EXIT);
pver->dwExtensionVersion = MAKELONG( HSE_VERSION_MAJOR, HSE_VERSION_MINOR);
strcpy( pver->lpszExtensionDesc,
"Binary Object Server ISAPI application" );
return TRUE;
}
BOOL WINAPI
TerminateExtension( IN DWORD dwFlags)
{
DELETE_DEBUG_PRINT_OBJECT();
return ( TRUE);
} // TerminateExtension()
DWORD
SendHeaderToClient( IN EXTENSION_CONTROL_BLOCK * pecb, IN LPCSTR pszErrorMsg)
{
CHAR buff[600];
//
// Note the HTTP header block is terminated by a blank '\r\n' pair,
// followed by the document body
//
wsprintf( buff,
"Content-Type: text/html\r\n"
"\r\n"
"<head><title>Simple File Transfer</title></head>\n"
"<body><h1>%s</h1>\n"
,
pszErrorMsg );
if ( !pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"200 OK",
NULL,
(LPDWORD) buff )
) {
return HSE_STATUS_ERROR;
}
return ( HSE_STATUS_SUCCESS);
} // SendHeaderToClient()
DWORD
SendFileToClient( IN EXTENSION_CONTROL_BLOCK * pecb)
{
CHAR rgszNewUrl[1024];
DWORD hseStatus = HSE_STATUS_SUCCESS;
LPCSTR pszError = "File Not Found";
// 1. Munge the incoming URL based no client CPU
hseStatus = GenerateBinaryUrlName( pecb, rgszNewUrl, &pszError);
if ( hseStatus != HSE_STATUS_SUCCESS) {
hseStatus = ( SendHeaderToClient( pecb, pszError));
} else {
DBGPRINTF(( DBG_CONTEXT, " New URL is: %s\n",
rgszNewUrl));
// 2. Use SEND_URL to reprocess URL for transmission
if ( !pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_SEND_URL,
rgszNewUrl,
NULL,
(LPDWORD) NULL )
) {
IF_DEBUG( ERROR ) {
DBGPRINTF(( DBG_CONTEXT, "SendURL(%s) failed with Error = %d\n",
rgszNewUrl, GetLastError()));
}
hseStatus = ( HSE_STATUS_ERROR);
}
}
return ( hseStatus);
} // SendFileToClient()
# define MAX_PROCESSOR_TYPE_LEN (40)
const char * g_rgchProcTypes[] = {
"x86",
"alpha",
"ppc",
"mips"
};
const char * g_rgchUpcaseProcTypes[] = {
"X86",
"ALPHA",
"PPC",
"MIPS"
};
DWORD g_rgLenProcTypes[] = {
3, 5, 4, 3
};
# define NUM_PROC_TYPES ( sizeof(g_rgchProcTypes) / sizeof( g_rgchProcTypes[0]))
DWORD
GenerateBinaryUrlName( IN EXTENSION_CONTROL_BLOCK * pecb,
OUT CHAR * pszNewUrl,
OUT LPCSTR * ppszError
)
{
LPCSTR pszOriginalUrl = pecb->lpszPathInfo;
CHAR rgchProcessorType[ MAX_PROCESSOR_TYPE_LEN];
DWORD cbProcessorType = MAX_PROCESSOR_TYPE_LEN;
// 1. find the path for the file.
// Intelligently enough IIS does not send the path info for request in the
// lpszPathInfo. Let us choose Query String if lpszPathInfo is empty.
if ( (pszOriginalUrl == NULL) || (*pszOriginalUrl == '\0')) {
pszOriginalUrl = pecb->lpszQueryString;
}
// 2. find the UA_CPU value for client
// 3. Encode file_path & UA_CPU to form the path for proper binary
// 4. store the new name in pszNewUrl
// TBD: Verify if such a file exists
if ( !pecb->GetServerVariable( pecb->ConnID,
"HTTP_UA_CPU",
rgchProcessorType,
&cbProcessorType
)
) {
DBGPRINTF(( DBG_CONTEXT, " GSV( HTTP_UA_CPU) failed with error = %d\n",
GetLastError()));
*ppszError = " No CPU Type specified ";
return ( HSE_STATUS_ERROR);
}
// now rgchProcessorType has the type -> form the proper binary path.
for ( DWORD i = 0; i < NUM_PROC_TYPES; i++) {
if ( (rgchProcessorType[0] == g_rgchProcTypes[i][0]) &&
!strcmp( rgchProcessorType + 1, g_rgchProcTypes[i] + 1)
) {
break;
} else {
if ((rgchProcessorType[0] == g_rgchUpcaseProcTypes[i][0]) &&
!strcmp( rgchProcessorType + 1, g_rgchUpcaseProcTypes[i] + 1)
) {
break;
}
}
} // for
if ( i == NUM_PROC_TYPES) {
DBGPRINTF(( DBG_CONTEXT, " Unknown Processor Type %s\n",
rgchProcessorType));
*ppszError = "Unknown Processor Type";
return ( HSE_STATUS_ERROR); // avoid cascading errors
}
// form the new URL name
// New URL = <oldURL> + <processorType>
DWORD cbLen;
cbLen = strlen(pszOriginalUrl);
DBG_ASSERT( ( cbLen + g_rgLenProcTypes[i])
< 1024);
DBGPRINTF(( DBG_CONTEXT, " old = [%s] Proc = [%s] \n",
pszOriginalUrl, rgchProcessorType));
strcpy( pszNewUrl, pszOriginalUrl);
strcat( pszNewUrl + cbLen, ".");
strcat( pszNewUrl + cbLen + 1, g_rgchProcTypes[i]);
return ( HSE_STATUS_SUCCESS);
} // GenerateBinaryUrlName()