windows-nt/Source/XPSP1/NT/printscan/fax/web/faxisapi/faxisapi.c
2020-09-26 16:20:57 +08:00

625 lines
11 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
faxisapi.c
Abstract:
This module implements an isapi dll for the
ms fax server. The HttpExtensionProc() supports
the following syntax:
dir= directory browser
status= fax status display
Author:
Wesley Witt (wesw) 01-May-1996
Revision History:
--*/
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "httpext.h"
#include "faxutil.h"
#include "winfax.h"
BOOL WINAPI
GetExtensionVersion(
HSE_VERSION_INFO *pVer
)
/*++
Routine Description:
Provides version information for this dll.
Arguments:
pVer - HTTP version structure
Return Value:
TRUE - Success
FALSE - Failure
--*/
{
pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
strncpy(
pVer->lpszExtensionDesc,
"FAX Server ISAPI Support DLL",
HSE_MAX_EXT_DLL_NAME_LEN
);
return TRUE;
}
LPSTR
AddString(
LPSTR Buffer,
LPSTR String,
...
)
/*++
Routine Description:
Adds a string to end of a buffer.
Arguments:
Buffer - Buffer to receive the string
String - The string to be added to the buffer
... - varargs data
Return Value:
Pointer to the end of the buffer.
--*/
{
DWORD len;
va_list arg_ptr;
va_start(arg_ptr, String);
vsprintf( Buffer, String, arg_ptr);
va_end(arg_ptr);
return Buffer + strlen(Buffer);
}
LPSTR
AppendNode(
LPSTR Directory,
LPSTR Node
)
/*++
Routine Description:
Appends a node to the end of a path.
Arguments:
Directory - Current directory.
Node - Node to be added to the directory.
Return Value:
Pointer to a newly allocated directory.
--*/
{
LPSTR s,dir;
s = Directory + strlen(Directory);
while (*s != '\\') s--;
s[0] = 0;
dir = MemAlloc( strlen(Directory) + 128 );
if (!dir) {
return NULL;
}
sprintf( dir, "%s\\%s\\*", Directory, Node );
s[0] = '\\';
return dir;
}
LPSTR
ResolvePath(
LPSTR Directory
)
/*++
Routine Description:
Obtains a complete path for a directory.
Arguments:
Directory - Current directory.
Return Value:
Pointer to a newly allocated complete directory.
--*/
{
LPSTR dir;
DWORD len;
LPSTR fname;
len = strlen(Directory) + 128;
dir = MemAlloc( len );
if (!dir) {
return NULL;
}
if (!GetFullPathName( Directory, len, dir, &fname )) {
MemFree( dir );
return NULL;
}
return dir;
}
LPSTR
PrintFileInfo(
LPSTR Buffer,
LPSTR Link,
LPWIN32_FIND_DATA FindData
)
/*++
Routine Description:
Generates a single HTML source line for a file name.
Arguments:
Buffer - Buffer to put the HTML source into
Link - TRUE=generate href, FALSE=no href
FindData - File information
Return Value:
Pointer to the end of the buffer.
--*/
{
FILETIME LocalTime;
SYSTEMTIME SystemTime;
FileTimeToLocalFileTime( &FindData->ftCreationTime, &LocalTime );
FileTimeToSystemTime( &LocalTime, &SystemTime );
Buffer = AddString(
Buffer,
"%02d-%02d-%04d %02d:%02d:%02d ",
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wYear,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond
);
if (Link) {
Buffer = AddString(
Buffer,
"<a href=\"/scripts/faxisapi.dll?%s\">%s</a>\n",
Link,
FindData->cFileName
);
} else {
Buffer = AddString( Buffer, "%s\n", FindData->cFileName );
}
return Buffer;
}
BOOL
HtmlDirectory(
LPSTR Directory,
LPBYTE Buffer
)
/*++
Routine Description:
Generates a page of HTML source for a directory.
This function implements a directory browser that
allows an HTML client to browse the directories
on the server's disks.
Arguments:
Directory - Directory from which to generate HTML source.
Buffer - Buffer to put the HTML source into.
Return Value:
TRUE - HTML generation is successful
FALSE - NTML generation failed
--*/
{
LPBYTE p;
LPSTR dir;
HANDLE hFind;
WIN32_FIND_DATA FindData;
p = Buffer;
hFind = FindFirstFile( Directory, &FindData );
if (hFind == INVALID_HANDLE_VALUE) {
return FALSE;
}
p = AddString( p, "Content-type: text/html\r\n\r\n" );
p = AddString( p, "<html>\r\n" );
p = AddString( p, "<head><title>Tornado FAX Server Project</title></head>\r\n" );
p = AddString( p, "<body>\r\n" );
p = AddString( p, "<h1>Directory Listing:<br>%s</h1><hr>\r\n", Directory );
p = AddString( p, "<p><pre>\n" );
do {
if (FindData.cFileName[0] == '.') {
if (FindData.cFileName[1] == '.') {
dir = AppendNode( Directory, ".." );
if (dir) {
LPSTR NewDir = ResolvePath( dir );
if (NewDir) {
MemFree( dir );
dir = NewDir;
}
p = AddString(
p,
"<a href=\"/scripts/faxisapi.dll?%s\"><img src=\"/images/b_arrow.gif\" border=0 >Parent Directory</a>\n",
dir
);
p = AddString( p, "<br>" );
MemFree( dir );
}
}
} else {
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
dir = AppendNode( Directory, FindData.cFileName );
if (dir) {
p = PrintFileInfo( p, dir, &FindData );
MemFree( dir );
}
} else {
p = PrintFileInfo( p, NULL, &FindData );
}
}
} while( FindNextFile( hFind, &FindData ) );
p = AddString( p, "</pre></body></html>\r\n" );
FindClose( hFind );
return TRUE;
}
BOOL
HtmlFaxStatus(
LPBYTE Buffer
)
/*++
Routine Description:
Generates a page of HTML source that shows
a status display for a ms fax server.
Arguments:
Buffer - Buffer to put the HTML source into.
Return Value:
TRUE - HTML generation is successful
FALSE - NTML generation failed
--*/
{
LPBYTE p;
PFAX_STATUS FaxStatus = NULL;
DWORD BytesNeeded;
DWORD i;
HFAX FaxHandle = NULL;
p = Buffer;
p = AddString( p, "Content-type: text/html\r\n\r\n" );
p = AddString( p, "<html>\r\n" );
p = AddString( p, "<head><title>Tornado FAX Server Project</title></head>\r\n" );
p = AddString( p, "<body>\r\n" );
p = AddString( p, "<h1>FAX Server Status</h1><hr>\n" );
p = AddString( p, "<p>\n" );
p = AddString( p, "<body background=\"/images/softgrid.gif\">" );
p = AddString( p, "<table border=5 cellpadding=5 cellspacing=10>\n" );
p = AddString( p, "<tr>\n" );
p = AddString( p, " <th>Port Name</th>\n" );
p = AddString( p, " <th>Port Number</th>\n" );
p = AddString( p, " <th>Status</th>\n" );
p = AddString( p, "</tr>\n" );
FaxStatus = (PFAX_STATUS) MemAlloc( 4096 );
if (!FaxStatus) {
return FALSE;
}
if (!FaxConnectFaxServer( NULL, &FaxHandle )) {
return FALSE;
}
if (!FaxGetDeviceStatus( FaxHandle, 0, (LPBYTE) FaxStatus, 4096, &BytesNeeded )) {
FaxDisconnectFaxServer( FaxHandle );
return FALSE;
}
for (i=0; i<FaxStatus->DeviceCount; i++) {
p = AddString( p, "<tr>\n" );
p = AddString( p, " <td>%s</td>\n", FaxStatus->DeviceStatus[i].DeviceName );
p = AddString( p, " <td>%d</td>\n", FaxStatus->DeviceStatus[i].DeviceId );
if (FaxStatus->DeviceStatus[i].Status & FPS_SENDING) {
p = AddString( p, " <td>Sending</td>\n" );
} else if (FaxStatus->DeviceStatus[i].Status & FPS_RECEIVING) {
p = AddString( p, " <td>Receiving</td>\n" );
} else if (FaxStatus->DeviceStatus[i].Status & FPS_AVAILABLE) {
p = AddString( p, " <td>Idle</td>\n" );
} else if (FaxStatus->DeviceStatus[i].Status & FPS_ABORTING) {
p = AddString( p, " <td>Aborting</td>\n" );
} else if (FaxStatus->DeviceStatus[i].Status & FPS_ROUTING) {
p = AddString( p, " <td>Routing</td>\n" );
} else if (FaxStatus->DeviceStatus[i].Status & FPS_UNAVAILABLE) {
p = AddString( p, " <td>Unavailable</td>\n" );
} else {
p = AddString( p, " <td>*Unknown Status*</td>\n" );
}
p = AddString( p, "</tr>\n" );
}
MemFree( FaxStatus );
FaxDisconnectFaxServer( FaxHandle );
p = AddString( p, "</table>" );
p = AddString( p, "</body></html>\n" );
return TRUE;
}
DWORD WINAPI
HttpExtensionProc(
EXTENSION_CONTROL_BLOCK *pECB
)
/*++
Routine Description:
Function that is called by the HTTP server.
Arguments:
pECB - HTTP extension control block
Return Value:
HSE_STATUS_ERROR - failure
HSE_STATUS_SUCCESS - success
--*/
{
#define MAX_BUFFER_SIZE (1024*1024)
LPBYTE Buffer;
DWORD Length;
LPSTR s;
pECB->dwHttpStatusCode = 0;
s = strchr( pECB->lpszQueryString, '=' );
if (!s) {
return HSE_STATUS_ERROR;
}
*s++ = 0;
if (_stricmp( pECB->lpszQueryString, "dir" ) == 0) {
Buffer = (LPBYTE) VirtualAlloc( NULL, MAX_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE );
if (!Buffer) {
return HSE_STATUS_ERROR;
}
if (!HtmlDirectory( s, Buffer )) {
return HSE_STATUS_ERROR;
}
} else if (_stricmp( pECB->lpszQueryString, "status" ) == 0) {
Buffer = (LPBYTE) VirtualAlloc( NULL, MAX_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE );
if (!Buffer) {
return HSE_STATUS_ERROR;
}
if (!HtmlFaxStatus( Buffer )) {
return HSE_STATUS_ERROR;
}
} else {
return HSE_STATUS_ERROR;
}
if (Buffer) {
Length = strlen( Buffer );
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
&Length,
(LPDWORD) Buffer
);
pECB->dwHttpStatusCode = 200;
VirtualFree( Buffer, MAX_BUFFER_SIZE, MEM_DECOMMIT );
} else {
return HSE_STATUS_ERROR;
}
return HSE_STATUS_SUCCESS;
}
DWORD
FaxIsapiDllEntry(
HINSTANCE hInstance,
DWORD Reason,
LPVOID Context
)
/*++
Routine Description:
DLL initialization function.
Arguments:
hInstance - Instance handle
Reason - Reason for the entrypoint being called
Context - Context record
Return Value:
TRUE - Initialization succeeded
FALSE - Initialization failed
--*/
{
if (Reason == DLL_PROCESS_ATTACH) {
DisableThreadLibraryCalls( hInstance );
HeapInitialize();
}
if (Reason == DLL_PROCESS_DETACH) {
HeapCleanup();
}
return TRUE;
}