|
|
/*****************************************************************************\
* MODULE: inetinfo.cxx * * * PURPOSE: Handles the data pumping to the client via IIS * * Copyright (C) 1996-1997 Microsoft Corporation * * History: * 01/16/96 eriksn Created based on ISAPI sample DLL * 07/15/96 babakj Moved to a separate file * 05/12/97 weihaic ASP template support * \*****************************************************************************/
#include "pch.h"
#include "printers.h"
static char c_szRemoteHost[] = "REMOTE_HOST"; static char c_szServerName[] = "SERVER_NAME";
/* AnsiToUnicodeString
* * Parameters: * * pAnsi - A valid source ANSI string. * * pUnicode - A pointer to a buffer large enough to accommodate * the converted string. * * StringLength - The length of the source ANSI string. * If 0 , the string is assumed to be * null-terminated. * * Return: * * The return value from MultiByteToWideChar, the number of * wide characters returned. * * */ INT AnsiToUnicodeString( LPSTR pAnsi, LPWSTR pUnicode, UINT StringLength ) { INT iReturn;
if( StringLength == 0 ) StringLength = strlen( pAnsi );
iReturn = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pAnsi, StringLength + 1, pUnicode, StringLength + 1 );
//
// Ensure NULL termination.
//
pUnicode[StringLength] = 0;
return iReturn; }
/* UnicodeToAnsiString
* * Parameters: * * pUnicode - A valid source Unicode string. * * pANSI - A pointer to a buffer large enough to accommodate * the converted string. * * StringLength - The length of the source Unicode string. * If 0 , the string is assumed to be * null-terminated. * * * Notes: * Added the #ifdef DBCS directive for MS-KK, if compiled * with DBCS enabled, we will allocate twice the size of the * buffer including the null terminator to take care of double * byte character strings - KrishnaG * * pUnicode is truncated to StringLength characters. * * Return: * * The return value from WideCharToMultiByte, the number of * multi-byte characters returned. * * */ INT UnicodeToAnsiString( LPWSTR pUnicode, LPSTR pAnsi, UINT StringLength) { LPSTR pTempBuf = NULL; INT rc = 0;
if( !StringLength ) {
//
// StringLength is just the
// number of characters in the string
//
StringLength = wcslen( pUnicode ); }
//
// WideCharToMultiByte doesn't NULL terminate if we're copying
// just part of the string, so terminate here.
//
//if (pUnicode[StringLength])
// pUnicode[StringLength] = 0;
//
// Include one for the NULL
//
StringLength++;
//
// Unfortunately, WideCharToMultiByte doesn't do conversion in place,
// so allocate a temporary buffer, which we can then copy:
//
if( pAnsi == (LPSTR)pUnicode ) { // Allocate enough memory anyway (in case of the far easten language
// the conversion needs that much
pTempBuf = (LPSTR) LocalAlloc( LPTR, (1 + StringLength) * 2 );
if (!pTempBuf) { return 0; }
pAnsi = pTempBuf; }
if( pAnsi ) { rc = WideCharToMultiByte( CP_ACP, 0, pUnicode, StringLength, pAnsi, StringLength * 2, NULL, NULL ); }
/* If pTempBuf is non-null, we must copy the resulting string
* so that it looks as if we did it in place: */ if( pTempBuf && ( rc > 0 ) ) { pAnsi = (LPSTR)pUnicode; strcpy( pAnsi, pTempBuf ); LocalFree( pTempBuf ); }
return rc; }
LPWSTR AllocateUnicodeString( LPSTR pAnsiString ) { LPWSTR pUnicodeString;
if (!pAnsiString) return NULL;
pUnicodeString = (LPWSTR) LocalAlloc(LPTR, strlen(pAnsiString) * sizeof(WCHAR) + sizeof(WCHAR));
if (pUnicodeString) AnsiToUnicodeString(pAnsiString, pUnicodeString, 0);
return pUnicodeString; }
//======================================================================
// HTML HELPER FUNCTIONS
//======================================================================
///////////////////////////////////////////////////////////////////////////////////////
//
// Server communications: First we send a HSE_REQ_SEND_RESPONSE_HEADER.
// Then we do WriteClient if we have leftover data.
//
// This routune allows a string to be written to the client using printf syntax.
//
///////////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
Name: htmlSendRedirect
Description:
Send a redirect to the client to let the client request the server again
Arguments:
pAllInfo: Pointer to the ALLINFO structure lpszURL: The redirect URL. It is the unicode version of the URL. Its content will be modified!!!
Return Value: TRUE if succeed, FASE otherwise.
********************************************************************************/
BOOL htmlSendRedirect(PALLINFO pAllInfo, LPTSTR lpszURL) { DWORD dwLen;
if (lpszURL && (dwLen = UnicodeToAnsiString (lpszURL, (LPSTR) lpszURL, NULL))) { return pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID, HSE_REQ_SEND_URL_REDIRECT_RESP, (LPVOID) lpszURL, &dwLen, NULL); } else return FALSE; }
unsigned long GetIPAddr (LPSTR lpName) { struct hostent * hp; struct sockaddr_in dest,from;
if (! (hp = gethostbyname(lpName))) { return inet_addr(lpName); }
memcpy (&(dest.sin_addr),hp->h_addr,hp->h_length); return dest.sin_addr.S_un.S_addr; }
#if 0
BOOL IsClientSameAsServer(EXTENSION_CONTROL_BLOCK *pECB) { LPSTR lpServer = NULL; LPSTR lpClient = NULL; DWORD dwSize = 32; BOOL bRet = FALSE; DWORD dwClient; DWORD dwServer;
if (! (lpClient = (LPSTR) LocalAlloc (LPTR, dwSize))) goto Cleanup;
if (!pECB->GetServerVariable (pECB->ConnID, c_szRemoteHost, lpClient, &dwSize)) if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) { LocalFree (lpClient); lpClient = NULL; if ( !(lpClient = (LPSTR) LocalAlloc (LPTR, dwSize)) || !pECB->GetServerVariable (pECB->ConnID, c_szRemoteHost, lpClient, &dwSize)) goto Cleanup;; } else goto Cleanup;
if (! (lpServer = (LPSTR) LocalAlloc (LPTR, dwSize))) goto Cleanup;
if (!pECB->GetServerVariable (pECB->ConnID, c_szServerName, lpServer, &dwSize)) if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) { LocalFree (lpServer); lpServer = NULL; if (!(lpServer = (LPSTR) LocalAlloc (LPTR, dwSize)) || !pECB->GetServerVariable (pECB->ConnID, c_szServerName, lpServer, &dwSize)) goto Cleanup; } else goto Cleanup;
bRet = GetIPAddr (lpClient) == GetIPAddr (lpServer);
Cleanup: LocalFree (lpClient); LocalFree (lpServer); return bRet;
} #endif
/********************************************************************************
Name: EncodeFriendlyName
Description:
Encode the friendly name to avoid special characters
Arguments:
lpText: the normal text string
Return Value:
Pointer to the HTML string. The caller is responsible to free the pointer. NULL is returned if no enougth memory ********************************************************************************/ LPTSTR EncodeFriendlyName (LPCTSTR lpText) { DWORD dwLen; LPTSTR lpHTMLStr = NULL;
dwLen = 0; if (!EncodePrinterName (lpText, NULL, &dwLen) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (lpHTMLStr = (LPTSTR) LocalAlloc (LPTR, dwLen * sizeof (TCHAR))) && EncodePrinterName (lpText, lpHTMLStr, &dwLen)) return lpHTMLStr; else { LocalFree (lpHTMLStr); return NULL; } }
/********************************************************************************
Name: DecodeFriendlyName
Description:
Decode the frienly name to get rid of %xx pattern.
Arguments:
lpText: the encoded printer friendly name
Return Value:
Pointer to the decoded friendly name.
********************************************************************************/ LPTSTR DecodeFriendlyName (LPTSTR lpStr) { LPTSTR lpParsedStr = lpStr; LPTSTR lpUnparsedStr = lpStr; TCHAR d1, d2;
if (!lpStr) return lpStr;
while (*lpUnparsedStr) { switch (*lpUnparsedStr) { case '~': // To take care the case when the DecodeString ends with %
if (! (d1 = *++lpUnparsedStr) || (! (d2 = *++lpUnparsedStr))) break; lpUnparsedStr++; *lpParsedStr++ = AscToHex (d1) * 16 + AscToHex (d2); break; default: *lpParsedStr++ = *lpUnparsedStr++; } } *lpParsedStr = NULL; return lpStr; }
BOOL IsClientHttpProvider (PALLINFO pAllInfo) { EXTENSION_CONTROL_BLOCK *pECB; DWORD dwVersion = 0; char buf[64]; DWORD dwSize = sizeof (buf); // This string is copied from ../inetpp/globals.c
const char c_szUserAgent[] = "Internet Print Provider";
pECB = pAllInfo->pECB;
// Check the UserAgent variable at first to see the IE version
if (pECB->GetServerVariable (pECB->ConnID, "HTTP_USER_AGENT", buf, &dwSize)) return !strcmp (buf, c_szUserAgent); else return FALSE; }
BOOL htmlSendHeader(PALLINFO pAllInfo, LPTSTR lpszHeader, LPTSTR lpszContent) { LPSTR lpszAnsiHeader = NULL; LPSTR lpszAnsiContent = NULL; BOOL bRet = FALSE; DWORD dwSize = 0;
lpszAnsiHeader = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszHeader)) * sizeof (TCHAR)); if (lpszContent) lpszAnsiContent = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszContent)) * sizeof (TCHAR));
if (!lpszAnsiHeader || !lpszAnsiContent) { goto Cleanup; }
UnicodeToAnsiString(lpszHeader, lpszAnsiHeader, 0); if (lpszContent) dwSize = UnicodeToAnsiString(lpszContent, lpszAnsiContent, 0);
bRet = pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (LPVOID) lpszAnsiHeader, &dwSize, (LPDWORD) lpszAnsiContent); Cleanup: LocalFree (lpszAnsiHeader); LocalFree (lpszAnsiContent);
return bRet;
}
BOOL htmlSend500Header(PALLINFO pAllInfo, DWORD dwError) { TCHAR szStatusPattern [] = TEXT ("500 %d"); LPTSTR lpszHeader = NULL; DWORD bRet = FALSE; LPTSTR pszErrorContent = GetString(pAllInfo, IDS_ERROR_500CONTENT);
if (! (lpszHeader = (LPTSTR) LocalAlloc (LPTR, sizeof (szStatusPattern) + sizeof (TCHAR) * 40))) goto Cleanup; else { wsprintf (lpszHeader, szStatusPattern, dwError); bRet = htmlSendHeader(pAllInfo, lpszHeader, pszErrorContent); }
Cleanup: if (lpszHeader) { LocalFree (lpszHeader); }
return bRet;
}
/********************************************************************************
Name: ProcessErrorMessage
Description:
Do the authentication if the error is Permission denied, show the error meesage otherwise
Arguments:
pAllInfo: Pointer to the infor struction dwError(optional): Error code, if not provided, dwError in the pAllInfo is used
Return Value:
HSE_STATUS_SUCCESS if ok.
********************************************************************************/ DWORD ProcessErrorMessage (PALLINFO pAllInfo, DWORD dwError) { DWORD dwRet = HSE_STATUS_ERROR;
if (!pAllInfo) { return dwRet; }
if (dwError != ERROR_SUCCESS) pAllInfo->dwError = dwError;
SetLastError (pAllInfo->dwError);
if (pAllInfo->dwError == ERROR_ACCESS_DENIED || pAllInfo->dwError == ERROR_INVALID_OWNER) { if (AuthenticateUser(pAllInfo)) dwRet = HSE_STATUS_SUCCESS; } else {
#if 0
if (IsClientHttpProvider (pAllInfo)) { // This piece will not be needed when IPP port validation (OpenPrinter) is done by Chris.
LPTSTR pszErrorContent = GetString(pAllInfo, IDS_ERROR_501CONTENT); return htmlSendHeader (pAllInfo, TEXT ("501 Function not supported"), pszErrorContent); } else { #endif
if (htmlSend500Header(pAllInfo, dwError)) dwRet = HSE_STATUS_SUCCESS; }
return dwRet;
}
LPTSTR AllocStr( LPCTSTR pStr ) {
LPTSTR pMem = NULL; DWORD cbStr;
if( !pStr ) return NULL;
cbStr = lstrlen( pStr )*sizeof(TCHAR) + sizeof(TCHAR);
if( pMem = (LPTSTR)LocalAlloc( LPTR, cbStr )) CopyMemory( pMem, pStr, cbStr );
return pMem; }
|