Tthe problem is, you have to specify each drive, what if I have a..z drives.
So, is there a way to monitor file creation in all drives without specifying?
I did a proxy test with ZwCreateFile,ZwWriteFile,ZwOpenFile, but it does not detect with this command;
procedure TfMainform.Button1Click(Sender: TObject);
begin
copyfile(application.exename, 'copytest.exe', false);
end;
Probably I need I callback, but I don't know how.
But, if the problem is in the callback?
Thanks
I don't know which one is a callback.Is it the TrueZwCreateFile? or the NewZwCreateFile?function TrueZwCreateFile( OUT FileHandle:PHANDLE; const DesiredAccess:ACCESS_MASK; const ObjectAttributes:PObjectAttributes; OUT IoStatusBlock:PIO_STATUS_BLOCK; const AllocationSize : LARGE_INTEGER; const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: ULONG; EaBuffer : PVOID; const EaLength :ULONG):NTStatus; stdcall;var Written: dword;begin WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @OldZwq, SizeOf(OldCode), Written); Result := ZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize, FileAttributes, ShareAccess,CreateDisposition,CreateOptions, EaBuffer, EaLength); WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @JmpZwq, SizeOf(far_jmp), Written);end;function NewZwCreateFile( OUT FileHandle:PHANDLE; const DesiredAccess:ACCESS_MASK; const ObjectAttributes:PObjectAttributes; OUT IoStatusBlock:PIO_STATUS_BLOCK; const AllocationSize : LARGE_INTEGER; const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: ULONG; EaBuffer : PVOID; const EaLength :ULONG):NTStatus; stdcall;varfileName:string;beginfileName:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer);//access violation with thisif IoStatusBlock.Status = FILE_CREATED thenSendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar('New Created')));SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName)));Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer ,EaLength);end;Pep's the code is working, But it say's access violation when I click the Button1.Any ideas?Am I doing right?, with the callback? huh, I don't even know what's the callback name I've write.
I don't think you have to test for the AllocationSize. A file could be created with that parameter not specified or 0, that just means that the system is not reserving any space for it, it just create an entry in the file table
besides, Result is not a boolean, and your former code was doing an AND binary operation between Result and DesiredAccess , which was only then compared to 0. No chance of that working.
You should always put brackets around single comparisons before using And/Or boolean operators. Delphi does not have the same operator priority than C/C++/Java etc...
Then, have you tested the sendmessage separately (with another app for example) ?
function NewZwCreateFile( FileHandle:pHandle; const DesiredAccess:ACCESS_MASK; const ObjectAttributes:PObjectAttributes; IoStatusBlock:PIO_STATUS_BLOCK; const AllocationSize : PInt64; const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: Cardinal; EaBuffer : Pointer; const EaLength :Cardinal):NTStatus; stdcall;var Msg:string; Hnd:THandle;begin Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes, IoStatusBlock,AllocationSize,FileAttributes,ShareAccess, CreateDisposition,CreateOptions,EaBuffer ,EaLength); if (Result=STATUS_SUCCESS) And (IoStatusBlock^.Information=FILE_CREATED) then begin Msg:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer)+' created'; Hnd:=FindWindow('TForm1', nil); // you'll have to do better than that later if Hnd<>0 Then Hnd:=FindWindowEx(Hnd, 0, 'TListBox', nil); if Hnd<>0 Then SendMessage(Hnd,LB_INSERTSTRING, 0, Integer(PChar(Msg))); end;end;
There are many Directory Notify/Monitor components, they all work pretty much the same, and no, none can monitor all drives at once as they are based on the same Windows API that works on a specific path.
But nothing can prevent you to create dynamically one such component for each drive.
epasquier;
thank you for that link, i'll deal with that later.
I know you are also flexible in programming different modules, with your overall experience in delphi I know you can help me with this, even if you have a little? background of nt system programming.
So with that experience you are capable to help me with this.
First step;
Lets start with the callback, which one of them is the callback?
Is it the TrueZwCreateFile? or the NewZwCreateFile?
0
ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.
One of a set of tools we're offering as a way to say thank you for being a part of the community.
I'm not too familiar with your code, but if I'm correct :
the function that is called by Windows is NewZwCreateFile , which calls TrueZwCreateFile, which in turn calls ZwCreateFile (after removing the hook to avoid infinite loop)
>> Here's the procedure that call's NewZwCreateFile
No, it does not call it. It replace IN ntdll the first instruction of ZwCreateFile with a call to your own. So next time somewhere this function is called, it will be in fact yours.
one thing you need to understand is that when you are in NewZwCreateFile, you are WITHIN the API, not OUTSIDE it. Said otherwise, you have to reverse all the logic you might find in MSDN. When it says that a function will do this and that value can have this flag, that means that it is WHAT YOURS HAVE TO DO.
Or, in your case, since you are calling the real one, that you can only test the OUT parameters at the end of the function.
ALSO : Out reserved word in Delphi does not have the same meaning as in MSDN
"An out parameter, like a variable parameter, is passed by reference. With an out parameter, however, the initial value of the referenced variable is discarded by the routine it is passed to. The out parameter is for output only; that is, it tells the function or procedure where to store output, but doesn't provide any input."
Which means the value of the pointer is cleared and that is why you have an access violation.
epasquier;
I've analyze what you did, it's correct, declaring the options/flags after the callback but include the (Result),
however, I have another idea;
Step 2;
Im getting the Allocationsize, but I can't, error during runtime;
if ( Result and AllocationSize<>0) then
What's the correct assignment for AllocationSize if not equal to zero?
I don't understand your problem with AllocationSize. You simply pass it to the real ZwCreateFile, what else do you want to do with it ?
I think there is an error in your type definition for this parameter. First, it's a pointer. Second, here is the type from MSDN :
typedef union _LARGE_INTEGER {
struct {
DWORD LowPart;
LONG HighPart;
} ;
struct {
DWORD LowPart;
LONG HighPart;
} u;
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
but that is compatible with Int64, so your real definition should be PInt64
and when you want to use it, you must first see it it's assigned (<>nil)
if Assigned(AllocationSize) Then ShowMessageFmt('AllocationSize = %d', [ AllocationSize^ ] );
Thank you epasquier;
As you see I'm not really a delphi pro.
I test the AllocationSize, because, as I understand at CreateFile;
"
If AllocationSize is NULL, no allocation size is specified. If no file is created or overwritten, AllocationSize is ignored.
"
But it seems not working also, I don't know if I stop here, or just continue listening
Here's what I did in AllocationSize;function NewZwCreateFile( FileHandle:pHandle; const DesiredAccess:ACCESS_MASK; const ObjectAttributes:PObjectAttributes; IoStatusBlock:PIO_STATUS_BLOCK; const AllocationSize : PInt64; const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: Cardinal; EaBuffer : Pointer; const EaLength :Cardinal):NTStatus; stdcall;varfileName:string;beginfileName:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer);Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer ,EaLength);if ( Result and DesiredAccess <> 0) thenif Assigned(AllocationSize) thenbeginSendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName+' created')));end;end;
I also try this with NewZwOpenFile;
if ( Result and DesiredAccess = FILE_WRITE_ATTRIBUTES and SYNCHRONIZE and GENERIC_WRITE) then
if ( Result and OpenOptions = FILE_SYNCHRONOUS_IO_NONALERT and FILE_NON_DIRECTORY_FILE) then
SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName+' created')));
end;
All of a sudden, I think "ZwQueryVolumeInformationFile" is the answer here, but I can't fine a sample of the code snippet given to produce a NewZwQueryVolumeInformationFile.
Step 3;
I know came up with ""ZwQueryVolumeInformationFile" but it seems I doubt, so I go to step 4
The "ZwWriteFile" http://msdn.microsoft.com/en-us/library/ff567121%28v=VS.85%29.aspx
Buffer [in]
Pointer to a caller-allocated buffer that contains the data to write to the file.
The result of the filename cant be read, it's ascii, how am I going to see it?
>>So, I can get the application who has the buffer?
Actually I want either of them, the source file or the destination file created.
I hope there is one possible function to do this kind of job.
besides, Result is not a boolean, and your former code was doing an AND binary operation between Result and DesiredAccess , which was only then compared to 0. No chance of that working.
You should always put brackets around single comparisons before using And/Or boolean operators. Delphi does not have the same operator priority than C/C++/Java etc...
Then, have you tested the sendmessage separately (with another app for example) ?
Open in new window