📄 scanuser.c
字号:
/*++
Copyright (c) 1999-2002 Microsoft Corporation
Module Name:
scanUser.c
Abstract:
This file contains the implementation for the main function of the
user application piece of scanner. This function is responsible for
actually scanning file contents.
Environment:
User mode
--*/
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <winioctl.h>
#include <string.h>
#include <crtdbg.h>
#include <fltuser.h>
#include "scanuk.h"
#include "scanuser.h"
#include <dontuse.h>
//
// Default and Maximum number of threads.
//
#define SCANNER_DEFAULT_REQUEST_COUNT 5
#define SCANNER_DEFAULT_THREAD_COUNT 2
#define SCANNER_MAX_THREAD_COUNT 64
UCHAR FoulString[] = "foul";
//
// Context passed to worker threads
//
typedef struct _SCANNER_THREAD_CONTEXT {
HANDLE Port;
HANDLE Completion;
} SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;
VOID
Usage (
VOID
)
/*++
Routine Description
Prints usage
Arguments
None
Return Value
None
--*/
{
printf( "Connects to the scanner filter and scans buffers \n" );
printf( "Usage: scanuser [requests per thread] [number of threads(1-64)]\n" );
}
BOOL
ScanBuffer (
__in_bcount(BufferSize) PUCHAR Buffer,
__in ULONG BufferSize
)
/*++
Routine Description
Scans the supplied buffer for an instance of FoulString.
Note: Pattern matching algorithm used here is just for illustration purposes,
there are many better algorithms available for real world filters
Arguments
Buffer - Pointer to buffer
BufferSize - Size of passed in buffer
Return Value
TRUE - Found an occurrence of the appropriate FoulString
FALSE - Buffer is ok
--*/
{
PUCHAR p;
ULONG searchStringLength = sizeof(FoulString) - sizeof(UCHAR);
for (p = Buffer;
p <= (Buffer + BufferSize - searchStringLength);
p++) {
if (RtlEqualMemory( p, FoulString, searchStringLength )) {
printf( "Found a string\n" );
//
// Once we find our search string, we're not interested in seeing
// whether it appears again.
//
return TRUE;
}
}
return FALSE;
}
DWORD
ScannerWorker(
__in PSCANNER_THREAD_CONTEXT Context
)
/*++
Routine Description
This is a worker thread that
Arguments
Context - This thread context has a pointer to the port handle we use to send/receive messages,
and a completion port handle that was already associated with the comm. port by the caller
Return Value
HRESULT indicating the status of thread exit.
--*/
{
PSCANNER_NOTIFICATION notification;
SCANNER_REPLY_MESSAGE replyMessage;
PSCANNER_MESSAGE message;
LPOVERLAPPED pOvlp;
BOOL result;
DWORD outSize;
HRESULT hr;
ULONG_PTR key;
while (TRUE) {
//
// Poll for messages from the filter component to scan.
//
result = GetQueuedCompletionStatus( Context->Completion, &outSize, &key, &pOvlp, INFINITE );
//
// Obtain the message: note that the message we sent down via FltGetMessage() may NOT be
// the one dequeued off the completion queue: this is solely because there are multiple
// threads per single port handle. Any of the FilterGetMessage() issued messages can be
// completed in random order - and we will just dequeue a random one.
//
message = CONTAINING_RECORD( pOvlp, SCANNER_MESSAGE, Ovlp );
if (!result) {
//
// An error occured.
//
hr = HRESULT_FROM_WIN32( GetLastError() );
break;
}
printf( "Received message, size %d\n", pOvlp->InternalHigh );
notification = &message->Notification;
result = ScanBuffer( notification->Contents, notification->BytesToScan );
replyMessage.ReplyHeader.Status = 0;
replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;
//
// Need to invert the boolean -- result is true if found
// foul language, in which case SafeToOpen should be set to false.
//
replyMessage.Reply.SafeToOpen = !result;
printf( "Replying message, SafeToOpen: %d\n", replyMessage.Reply.SafeToOpen );
hr = FilterReplyMessage( Context->Port,
(PFILTER_REPLY_HEADER) &replyMessage,
sizeof( replyMessage ) );
if (SUCCEEDED( hr )) {
printf( "Replied message\n" );
} else {
printf( "Scanner: Error replying message. Error = 0x%X\n", hr );
break;
}
memset( &message->Ovlp, 0, sizeof( OVERLAPPED ) );
hr = FilterGetMessage( Context->Port,
&message->MessageHeader,
FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
&message->Ovlp );
if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {
break;
}
}
if (!SUCCEEDED( hr )) {
if (hr == HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE )) {
//
// Scanner port disconncted.
//
printf( "Scanner: Port is disconnected, probably due to scanner filter unloading.\n" );
} else {
printf( "Scanner: Unknown error occured. Error = 0x%X\n", hr );
}
}
free( message );
return hr;
}
int _cdecl
main (
__in int argc,
__in_ecount(argc) char *argv[]
)
{
DWORD requestCount = SCANNER_DEFAULT_REQUEST_COUNT;
DWORD threadCount = SCANNER_DEFAULT_THREAD_COUNT;
HANDLE threads[SCANNER_MAX_THREAD_COUNT];
SCANNER_THREAD_CONTEXT context;
HANDLE port, completion;
PSCANNER_MESSAGE msg;
DWORD threadId;
DWORD retVal = 0;
HRESULT hr;
DWORD i, j;
//
// Check how many threads and per thread requests are desired.
//
if (argc > 1) {
requestCount = atoi( argv[1] );
if (argc > 2) {
threadCount = atoi( argv[2] );
}
if (requestCount <= 0 || threadCount <= 0 || threadCount > 64) {
Usage();
return 1;
}
}
//
// Open a commuication channel to the filter
//
printf( "Scanner: Connecting to the filter ...\n" );
hr = FilterConnectCommunicationPort( ScannerPortName,
0,
NULL,
0,
NULL,
&port );
if (IS_ERROR( hr )) {
printf( "ERROR: Connecting to filter port: 0x%08x\n", hr );
return 2;
}
//
// Create a completion port to associate with this handle.
//
completion = CreateIoCompletionPort( port,
NULL,
0,
threadCount );
if (completion == NULL) {
printf( "ERROR: Creating completion port: %d\n", GetLastError() );
CloseHandle( port );
return 3;
}
printf( "Scanner: Port = 0x%p Completion = 0x%p\n", port, completion );
context.Port = port;
context.Completion = completion;
//
// Create specified number of threads.
//
for (i = 0; i < threadCount; i++) {
threads[i] = CreateThread( NULL,
0,
ScannerWorker,
&context,
0,
&threadId );
if (threads[i] == NULL) {
//
// Couldn't create thread.
//
hr = GetLastError();
printf( "ERROR: Couldn't create thread: %d\n", hr );
goto main_cleanup;
}
for (j = 0; j < requestCount; j++) {
//
// Allocate the message.
//
msg = malloc( sizeof( SCANNER_MESSAGE ) );
if (msg == NULL) {
hr = ERROR_NOT_ENOUGH_MEMORY;
goto main_cleanup;
}
memset( &msg->Ovlp, 0, sizeof( OVERLAPPED ) );
//
// Request messages from the filter driver.
//
hr = FilterGetMessage( port,
&msg->MessageHeader,
FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
&msg->Ovlp );
if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {
free( msg );
goto main_cleanup;
}
}
}
hr = S_OK;
WaitForMultipleObjects( i, threads, TRUE, INFINITE );
main_cleanup:
printf( "Scanner: All done. Result = 0x%08x\n", hr );
CloseHandle( port );
CloseHandle( completion );
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -