Thread: fileHasBeenRead()

  1. #1
    Registered User
    Join Date
    Jul 2010
    Posts
    8

    fileHasBeenRead()

    I am working on a system file monitoring tool. I need to be able to tell what files have/are being read (keyword is READ not modified). Things I have tried:

    Code:
    bool isFileOpen(string inputFile){
    	fstream myfile;
    	try{
    		myfile.open (inputFile);//always true if file exists
    
    		}
    	}
    	catch (int i){
    		return true;//does not catch if file exists
    	}
    	return false;
    }
    does not work... So i tried fileinfo last access...
    Code:
    DateTime dtmFileLastModified = File.GetLastWriteTime("C:\blah\filename.csv");
    although the above code does work, it does not have instant notifcation of last access timestamp.
    I have also explored all the filters for FileSystemWatcher as well
    Code:
    watcher->NotifyFilter = static_cast<NotifyFilters>(NotifyFilters::LastAccess |
    			NotifyFilters::LastWrite | NotifyFilters::FileName |  NotifyFilters::DirectoryName | 
    			NotifyFilters::CreationTime);
    any ideas?

    Chris

    SDK - Visual Studio
    OS - Windows 7 64 bit

  2. #2
    Registered User
    Join Date
    Jul 2010
    Posts
    8

    Also

    I have also now tried:

    Code:
    	while(true)
    	{
    		struct stat stResult;
    		stat("c:\practiceFileRead.txt",&stResult);
    		Console::WriteLine("last time : {0}",stResult.st_atime);
    		Thread::Sleep(4000);
    	}
    this works but again does not have that instance notification.

    Chris

  3. #3
    Registered User
    Join Date
    Jul 2010
    Posts
    8
    no one has any ideas still? Anyone try File Filter Drivers?

    Chris

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    *shrug*
    Tried ReadDirectoryChanges?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Registered User
    Join Date
    Jul 2010
    Posts
    8
    Ill give it a shot. Right now im looking at NTFS.

    Chris

  6. #6
    Registered User
    Join Date
    Jul 2010
    Posts
    8

    RE:

    I gave ReadDirectoryChangesW() a shot to no avil. Here is the source code for the method. Although it does detect changes, it will NOT detect if a file has been opened.

    Code:
    wstring s2ws(const string& s)
    {
    	int len;
    	int slength = (int)s.length() + 1;
    	len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0); 
    	wchar_t* buf = new wchar_t[len];
    	MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    	std::wstring r(buf);
    	delete[] buf;
    	return r;
    }
    
    void CALLBACK ChDirCompletionRoutine( DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered,  LPOVERLAPPED lpOverlapped)
    {
    	Console::WriteLine("stylo");
    }
    
    void ripCord(){
    	//open the directory to watch....
    	std::wstring stemp = s2ws("c:\\");
    	LPCWSTR results = stemp.c_str();
    
    	HANDLE hDir = CreateFile(results,
    		FILE_LIST_DIRECTORY | GENERIC_READ | GENERIC_WRITE,
    		FILE_SHARE_READ | FILE_SHARE_WRITE ,NULL, //security attributes
    		OPEN_EXISTING,
    		FILE_FLAG_BACKUP_SEMANTICS,NULL);
    	if( hDir == INVALID_HANDLE_VALUE )
    	{
    		DWORD dwError = GetLastError();
    		Console::WriteLine("problem");
    
    	}
    
    	OVERLAPPED overlapped;
    	//overlapped.Internal =
    	//	overlapped.InternalHigh =
    	//	overlapped.Offset =
    		overlapped.OffsetHigh = 0;
    	overlapped.hEvent = NULL;
    
    	DWORD byteRerurned = 0;
    	DWORD dwRecSize = sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * 2;
    	DWORD dwCount = 32;
    	FILE_NOTIFY_INFORMATION* pNI =
    		(FILE_NOTIFY_INFORMATION*)malloc(dwRecSize * dwCount);
    	while(true) {
    		//LPCOMPETION cb = ChDirCompletionRoutine;
    		if( ReadDirectoryChangesW( hDir,
    			pNI,//<--FILE_NOTIFY_INFORMATION records are put into this buffer
    			dwRecSize * dwCount,
    			FALSE,
    			FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE   |
    			FILE_NOTIFY_CHANGE_LAST_ACCESS
    			| FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE |
    			FILE_NOTIFY_CHANGE_CREATION
    			| FILE_NOTIFY_CHANGE_FILE_NAME,
    			&byteRerurned,
    			&overlapped,
    			&ChDirCompletionRoutine) )
    			{
    			Console::WriteLine("Do something");
    			}
    		Sleep(3000);
    		Console::WriteLine("do nothing");
    	}
    }

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Just FYI, "pNI" has to be aligned to a DWORD boundary...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Quote Originally Posted by Sebastiani View Post
    Just FYI, "pNI" has to be aligned to a DWORD boundary...
    Quote Originally Posted by http://msdn.microsoft.com/en-us/library/ycsb6wwf.aspx
    malloc is required to return memory on a 16-byte boundary.
    As for the problem at hand, I don't think you can get read notifications. The best you could do was last access time, but updates for that have been disabled since Vista.

    Filemon and similar use filter drivers, if you haven't experience of them you're in for a rough time. It'd probably be easier to reverse filemon and use its driver to do the heavy lifting than to write one yourself. EDIT: Or you could just copy the MiniSpy example.
    Last edited by adeyblue; 07-20-2010 at 04:22 PM.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by adeyblue View Post
    malloc is required to return memory on a 16-byte boundary.
    AFAIK, the standard doesn't guarantee any such thing (although I'm sure most implementations do). Anyway, my point was really that it was a matter to keep in mind, considering that the structure could be allocated in a number of ways...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Registered User
    Join Date
    Jul 2010
    Posts
    8

    Re

    Yes I'm going through filemon now and hopefully get something good from that. I'll let you guys know when I find a solution.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > AFAIK, the standard doesn't guarantee any such thing
    The standard requires that malloc return a pointer that is aligned to the worst-case data type supported by the implementation. Simply declaring a variable of a type, or using an allocator to do the same always works without any additional programmer effort.

    It's only when you start messing about with some roll your own pointer arithmetic that you have to worry about such things.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Jul 2010
    Posts
    8
    I used a file system filter driver. Installed the driver minispy (had to disable windows signature enforcement), launched the .exe that talks to the driver which listens for all files being queried, log that data into a file and boom problem solved. Thanks a lot guys.

    Chris

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Any chance of sharing that? I could have uses for that, too.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Registered User
    Join Date
    Jul 2010
    Posts
    8

    Create driver

    Build a minispy driver.

    1. Download and install windows driver kit. WDK Windows Driver Kit | Overview for Driver Developers

    2. click START/ All Programs/Windows Driver Kit/ WDK../Build Environments/(your operating system)/(system bit)checked build environment. This launches command line.

    3. Inside your Build Environment Command Line program, navigate to "C:\WinDDK\7600.16385.0\src\filesys\miniFilter\min ispy".

    3. To build the program you go into "user" directory and type "build" and it automatically builds your .exe file in sub directory called "objchk_win7_amd64".

    4. To build the driver ".sys" you go into the "filter" directory and type "build -ceZ " and it automatically builds your .sys file in subdirectory called "objchk_win7_amd64".

    5. Copy your .exe file and .sys file in the top top directory with the file called minispy.inf

    6. It would be smart to back up your system at this point just in case you get the blue screen of death.

    6a if you have windows vista or above you will have to reboot while holding F8 and in the boot menu select "disable driver signature enforcement." This will allow your driver to work.

    7. right-click minispy.inf, and click Install. This puts it in the drivers directory

    8. In your build environment type "fltmc load minispy" or "net start minispy" Hopefully you can still read this and it told you it launched and is running. You can see it running by typing "fltmc"

    9. launch learn love and modify minispy.exe.

    source: minispy Minifilter Sample (Windows Driver Kit)

    Now comes the challenge of porting minispy.exe from c to c++

    Chris
    Last edited by xero976; 07-23-2010 at 09:56 AM.

Popular pages Recent additions subscribe to a feed