Hi i want to translate the user scanner ( found in WDDK ) from C into Delphi :
Here is the C Version :
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;
assert(notification->BytesToScan <= SCANNER_READ_BUFFER_SIZE);
__analysis_assume(notification->BytesToScan <= SCANNER_READ_BUFFER_SIZE);
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;
and here is my Delphi conversion attempt :
program Project1;
{$APPTYPE CONSOLE}
uses
windows,
SysUtils,
NtDefs in 'NtDefs.pas',
rspFltUser in 'FltUser.pas',
scanuk_h in 'scanuk_h.pas';
const
SCANNER_DEFAULT_REQUEST_COUNT = 5;
SCANNER_DEFAULT_THREAD_COUNT = 2;
SCANNER_MAX_THREAD_COUNT = 64;
FoulString:String = 'foul';
type
_SCANNER_THREAD_CONTEXT = record
Port: THandle;
Completion: THandle;
end;
SCANNER_THREAD_CONTEXT = _SCANNER_THREAD_CONTEXT;
PSCANNER_THREAD_CONTEXT = ^_SCANNER_THREAD_CONTEXT;
//
type
_SCANNER_MESSAGE = packed record
MessageHeader: FILTER_MESSAGE_HEADER;
(**)
(* Required structure header.*)
(**)
(**)
(* Private scanner-specific fields begin here.*)
(**)
Notification: SCANNER_NOTIFICATION;
(**)
(* Overlapped structure: this is not really part of the message*)
(* However we embed it instead of using a separately allocated overlap structure*)
(**)
//
FOverlapped: TOverlapped;
FPOverlapped: POverlapped;
//
end;
SCANNER_MESSAGE = _SCANNER_MESSAGE;
PSCANNER_MESSAGE = ^_SCANNER_MESSAGE;
_SCANNER_REPLY_MESSAGE = packed record
ReplyHeader: FILTER_REPLY_HEADER;
(**)
(* Required structure header.*)
(**)
(**)
(* Private scanner-specific fields begin here.*)
(**)
Reply: SCANNER_REPLY;
end;
SCANNER_REPLY_MESSAGE = _SCANNER_REPLY_MESSAGE;
PSCANNER_REPLY_MESSAGE = ^_SCANNER_REPLY_MESSAGE;
//
procedure Usage();
begin
WriteLn('Connects to the scanner filter and scans buffers '#13#10'');
WriteLN('Usage: scanuser [requests per thread] [number of threads(1-64)]'#13#10'');
end;
function ScanBuffer( Buffer:PUCHAR;BufferSize:Cardinal): BOOL;
var
p: PUCHAR;
searchStringLength: ULONG;
begin
searchStringLength:=sizeof(FoulString)-sizeof(UCHAR);
// for{while} P:=Buffer to (Buffer+BufferSize-searchStringLength) {
// p++}
//do
begin
// if RtlEqualMemory(p,FoulString,searchStringLength)
//then
begin
WriteLN('Found a string'#13#10'');
(**)
(* Once we find our search string, we're not interested in seeing*)
(* whether it appears again.*)
(**)
begin
result:= LongBool(1);
exit;
end;
end;
end;
begin
result:= LongBool(0);
exit;
end;
end;
var
FOverlapped: TOverlapped;
FPOverlapped: POverlapped;
Ovlp: OVERLAPPED;
function ScannerWorker(Context:PSCANNER_THREAD_CONTEXT): DWORD;
var
notification: PSCANNER_NOTIFICATION;
replyMessage: SCANNER_REPLY_MESSAGE;
message: PSCANNER_MESSAGE;
pOvlp:LPOVERLAPPED;
cResult: BOOL;
outSize: DWORD;
hr: HRESULT;
key: DWORD;
begin
while LongBool(1)
do
begin
(**)
(* Poll for messages from the filter component to scan.*)
(**)
cResult:= GetQueuedCompletionStatus(Context^.Completion,outSize,key,FPOverlapped,INFINITE);
// message:= CONTAINING_RECORD(pOvlp,SCANNER_MESSAGE,Ovlp);
(**)
(* 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.*)
(**)
if ( not cResult)
then
begin
(**)
(* An error occured.*)
(**)
hr:=(GetLastError());
break; {<= !!!b possible in "switch" - then remove this line}
end;
writeLn('Received message, size %d'#13#10'',pOvlp.InternalHigh);
notification:= @message.Notification;
assert(notification.BytesToScan<=SCANNER_READ_BUFFER_SIZE);
// __analysis_assume(notification.BytesToScan<=SCANNER_READ_BUFFER_SIZE);
cResult:= ScanBuffer(@notification^.Contents, notification^.BytesToScan);
replyMessage.ReplyHeader.Status:= 0;
replyMessage.ReplyHeader.MessageId:= message.MessageHeader.MessageId;
replyMessage.Reply.SafeToOpen:=not cResult;
WriteLN('Replying message, SafeToOpen: %d'#13#10'',replyMessage.Reply.SafeToOpen);
(**)
(* Need to invert the boolean -- result is true if found*)
(* foul language, in which case SafeToOpen should be set to false.*)
(**)
hr:= FilterReplyMessage(Context.Port,@replyMessage,sizeof(replyMessage));
if SUCCEEDED(hr)
then
begin
WriteLN('Replied message'#13#10'');
end
else
begin
WriteLN('Scanner: Error replying message. Error = 0x%X'#13#10'',hr);
break; {<= !!!b possible in "switch" - then remove this line}
end;
ZeroMemory(@message.FPOverlapped,sizeof(OVERLAPPED));
hr:= FilterGetMessage(Context.Port,@message.MessageHeader,{(Ovlp)}600,@message.FPOverlapped);
if hr<>(ERROR_IO_PENDING)
then
begin
break; {<= !!!b possible in "switch" - then remove this line}
end;
end;
if ( not SUCCEEDED( hr ))
then
begin
if hr=(ERROR_INVALID_HANDLE)
then
begin
(**)
(* Scanner port disconncted.*)
(**)
WriteLN('Scanner: Port is disconnected, probably due to scanner filter unloading.'#13#10'');
end
else
begin
WriteLN('Scanner: Unknown error occured. Error = 0x%X'#13#10'',hr);
end;
end;
//free(message);
begin
result:= hr;
exit;
end;
end;
///
procedure main({argc: integer;argv:Integer } {!!!3 unknown typedef});
var
requestCount: DWORD;
threadCount: DWORD;
threads: array [0..Pred(SCANNER_MAX_THREAD_COUNT)] of THandle;
context: SCANNER_THREAD_CONTEXT;
port: THandle;
completion: THandle;
msg: PSCANNER_MESSAGE;
threadId: DWORD;
retVal: DWORD;
hr: HRESULT;
i: DWORD;
j: DWORD;
(**)
(* Check how many threads and per thread requests are desired.*)
(**)
label
main_cleanup;
begin
requestCount:=SCANNER_DEFAULT_REQUEST_COUNT;
threadCount:=SCANNER_DEFAULT_THREAD_COUNT;
retVal:=0;
if paramCount>1 then
// if argc>1
// then
begin
requestCount:=StrToInt(ParamStr(1));
if paramCount>1
// if argc>2
then
begin
threadCount:=StrToInt(ParamStr(2));
end;
if ((requestCount <= 0) or (threadCount <= 0 )or( threadCount > 64))
then
begin
Usage();
begin
// result:= 1;
exit;
end;
end;
end;
WriteLN('Scanner: Connecting to the filter ...'#13#10'');
(**)
(* Open a commuication channel to the filter*)
(**)
hr:= FilterConnectCommunicationPort(ScannerPortName,0,0{nil},0,0{nil},@port);
if (hr<>S_Ok)
then
begin
WriteLN('ERROR: Connecting to filter port: %d',hr);
begin
// result:= 2;
exit;
end;
end;
completion:= CreateIoCompletionPort(port,0{nil},0,threadCount);
(**)
(* Create a completion port to associate with this handle.*)
(**)
if completion=0{nil}
then
begin
WriteLN('ERROR: Creating completion port: %d',GetLastError());
CloseHandle(port);
begin
// result:= 3;
exit;
end;
end;
WriteLN('Scanner: Port = 0x%p Completion = 0x%p',port,completion);
context.Port:= port;
context.Completion:= completion;
(**)
(* Create specified number of threads.*)
(**)
for{while} i:=0 to Pred(threadCount) { i++}
do
begin
threads[i]:= CreateThread(nil,0,@ScannerWorker,POinter(context.port),0,threadId);
if threads[i]=0{nil}
then
begin
(**)
(* Couldn't create thread.*)
(**)
hr:= GetLastError();
WriteLN('ERROR: Couldn'#39't create thread: %d',hr);
goto main_cleanup;
end;
for{while} j:=0 to Pred(requestCount) { j++}
do
begin
(**)
(* Allocate the message.*)
(**)
msg:= AllocMem(sizeof(SCANNER_MESSAGE));
if msg=nil then
begin
hr:= ERROR_NOT_ENOUGH_MEMORY;
goto main_cleanup;
end;
ZeroMemory(@msg.FPOverlapped,sizeof(OVERLAPPED));
//Context.Port,@message.MessageHeader,{(Ovlp)}600,@message.FPOverlapped
hr:= FilterGetMessage(port,@msg.MessageHeader,{(Ovlp)}600,@msg.FPOverlapped);
(**)
(* Request messages from the filter driver.*)
(**)
if hr<>(ERROR_IO_PENDING)
then
begin
freeMem(msg);
goto main_cleanup;
end;
end;
end;
hr:= S_OK;
WaitForMultipleObjects(i, @threads, TRUE, INFINITE);
main_cleanup:
WriteLN('Scanner: All done. Result = 0x%08x'#13#10'',hr);
CloseHandle(port);
CloseHandle(completion);
begin
// result:= hr;
exit;
end;
end;
///
begin
{ TODO -oUser -cConsole Main : Insert code here }
main();
end.
But i always get the error : Connecting to filter port
please can any one help me in doing this .
many thanks
Здравствуйте, randydom, Вы писали:
R>I use and declare the function FilterConnectCommunicationPort as follows :
R>function FilterConnectCommunicationPort(lpPortName: pWideChar; dwOptions: DWORD;
R> lpContect: pBYTE; wSizeOfContext: WORD; lpSecurityAttributes: PSECURITY_ATTRIBUTES; hPort: PHANDLE): HRESULT;stdcall; external 'FLTLIB.dll';
from MSDN:
HRESULT
WINAPI
FilterConnectCommunicationPort(
IN LPCWSTR lpPortName,
IN DWORD dwOptions,
IN LPVOID lpContext OPTIONAL,
IN DWORD dwSizeOfContext, // <== DWORD
IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
OUT HANDLE *hPort
);
Здравствуйте, wallaby, Вы писали:
W>Здравствуйте, randydom, Вы писали:
R>>I use and declare the function FilterConnectCommunicationPort as follows :
R>>function FilterConnectCommunicationPort(lpPortName: pWideChar; dwOptions: DWORD;
R>> lpContect: pBYTE; wSizeOfContext: WORD; lpSecurityAttributes: PSECURITY_ATTRIBUTES; hPort: PHANDLE): HRESULT;stdcall; external 'FLTLIB.dll';
W>from MSDN:
W>W>HRESULT
W>WINAPI
W> FilterConnectCommunicationPort(
W> IN LPCWSTR lpPortName,
W> IN DWORD dwOptions,
W> IN LPVOID lpContext OPTIONAL,
W> IN DWORD dwSizeOfContext, // <== DWORD
W> IN LPSECURITY_ATTRIBUTES lpSecurityAttributes OPTIONAL,
W> OUT HANDLE *hPort
W> );
W>
I DID it but i get an Exception :
Scanner : Error replying message .Error = 0x800703E6
Here's my Code :
function ScannerWorker(Context:PSCANNER_THREAD_CONTEXT): DWORD;
var
notification: PSCANNER_NOTIFICATION;
replyMessage: SCANNER_REPLY_MESSAGE;
msg: PSCANNER_MESSAGE;
pOvlp:POVERLAPPED;
bResult: BOOL;
outSize: DWORD;
hr: HRESULT;
key: DWORD;
begin
While True Do
begin
bResult := GetQueuedCompletionStatus(Context^.Completion,OutSize,Key,pOvlp,INFINITE);
Msg := PSCANNER_MESSAGE(@PSCANNER_MESSAGE(pOvlp)^.Ovlp);
If Not(bResult) Then
begin
HR := HRESULT_FROM_WIN32(GetLastError());
Break;
end;
WriteLN(Format('Received message: %d',[pOvlp.InternalHigh]));
notification := @msg.Notification;
assert(notification.BytesToScan<=SCANNER_READ_BUFFER_SIZE);
// result := ScanBuffer( notification^.Contents, notification.BytesToScan );
replyMessage.ReplyHeader.Status:= 0;
replyMessage.ReplyHeader.MessageId:= msg.MessageHeader.MessageId;
replyMessage.Reply.SafeToOpen:=not bResult;
WriteLN(Format('Replying message, SafeToOpen: %d',[ReplyMessage.Reply.SafeToOpen]));
HR := FilterReplyMessage(Context^.Port,PFILTER_REPLY_HEADER(@ReplyMessage),SizeOf(ReplyMessage));
If SUCCEEDED(HR) Then
begin
WriteLN('Replied message');
end
Else
begin
WriteLN(('Scanner: Error replying message. Error = 0x'+inttoHex(HR,2)));//EXCEPTION:0x800703E6
Break;
end;
FillChar(Msg^.FOverlapped,0,SizeOf(OVERLAPPED));
//#define FIELD_OFFSET(t, f) ((unsigned int)(unsigned long)&(((t *)0)->f))
HR := FilterGetMessage(Context^.Port,@Msg^.MessageHeader,DWORD(@PSCANNER_MESSAGE(0)^.FOverlapped),@Msg^.FOverlapped);
If HR <> HRESULT_FROM_WIN32(ERROR_IO_PENDING) Then Break;
end;
If Not(SUCCEEDED(HR)) Then
begin
If HR = HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) Then
begin
WriteLN('Scanner: Port is disconnected, probably due to scanner filter unloading.');
end
Else
begin
WriteLN(Format('Scanner: Unknown error occured. Error = 0x%x',<hr>));
end;
end;
FreeMem(Msg);
Result := HR;
end;
Please where's the Error ?
Здравствуйте, randydom, Вы писали:
R>I DID it but i get an Exception :
R>Scanner : Error replying message .Error = 0x800703E6
That is not an exception, that is function return error value:
Invalid access to memory location.
Maybe wrong function prototype again, eg. check FilterReplyMessage argument dwReplyBufferSize (must be DWORD):
HRESULT
WINAPI
FilterReplyMessage(
__in HANDLE hPort,
__in PFILTER_REPLY_HEADER lpReplyBuffer,
__in DWORD dwReplyBufferSize
);
Здравствуйте, wallaby, Вы писали:
W>Здравствуйте, randydom, Вы писали:
R>>I DID it but i get an Exception :
R>>Scanner : Error replying message .Error = 0x800703E6
W>That is not an exception, that is function return error value: Invalid access to memory location.
W>Maybe wrong function prototype again, eg. check FilterReplyMessage argument dwReplyBufferSize (must be DWORD):
W>W>HRESULT
W>WINAPI
W> FilterReplyMessage(
W> __in HANDLE hPort,
W> __in PFILTER_REPLY_HEADER lpReplyBuffer,
W> __in DWORD dwReplyBufferSize
W> );
W>
Yes Sir wallaby the Declaration is as follows :
function FilterReplyMessage(hPort: THandle; lpReplyBuffer: PFILTER_REPLY_HEADER; dwReplyBufferSize: DWORD): HRESULT;
stdcall; external 'FLTLIB.dll';
Could i have you email and i will send you the Full Project
thank you for your help
Здравствуйте, randydom, Вы писали:
R>Здравствуйте, wallaby, Вы писали:
W>>Здравствуйте, randydom, Вы писали:
R>>>I DID it but i get an Exception :
R>>>Scanner : Error replying message .Error = 0x800703E6
W>>That is not an exception, that is function return error value: Invalid access to memory location.
W>>Maybe wrong function prototype again, eg. check FilterReplyMessage argument dwReplyBufferSize (must be DWORD):
W>>W>>HRESULT
W>>WINAPI
W>> FilterReplyMessage(
W>> __in HANDLE hPort,
W>> __in PFILTER_REPLY_HEADER lpReplyBuffer,
W>> __in DWORD dwReplyBufferSize
W>> );
W>>
R> Yes Sir wallaby the Declaration is as follows :
R>R>function FilterReplyMessage(hPort: THandle; lpReplyBuffer: PFILTER_REPLY_HEADER; dwReplyBufferSize: DWORD): HRESULT;
R> stdcall; external 'FLTLIB.dll';
R>
R>Could i have you email and i will send you the Full Project
R>thank you for your help
Sir wallaby i sent the full project to your 2nd Email .
many thanks again for your help