I'm opening a file for a video I'm creating and writing to disk with fopen in C++, I'm able to write to disk. But when I try to read it as I'm writing it, it will throw errors saying that it doesn't have permission to read the file as soon as I close the file or stop the program, I can suddenly read from it.
Not an issue with not finishing writing the write as if I crash the program, can still read it. Also, VLC's logs tell me it's a permission issue.
Any idea how to change that permission?
Response to William asking for code snippets or if open happened before the file existed:
Thanks William, here's what I've got. I waited a few minutes and could see the file with windows explorer by that point and waited until after I'd flushed and data was there, couldn't open with VLC or Notepad++ or Notepad or Windows Media Player
Notepad says cannot access because it is being used by another process, others too.
Here is the VLC log while it tries to open this:
http://snippi.com/s/g4cbu23
Here is where I create the file with fopen:
http://snippi.com/s/cyajw4h
At the very end is where I write to the file using fwrite and flush:
http://snippi.com/s/oz27m0g
You need to use _fsopen with _SH_DENYNO if you want the file to be shareable.
C++ In Windows 7.
When writing to my log file, i sometimes set a breakpoint, or the program gets stuck at something. When i try too peek in my logfile from another program it says "The file cannot be opened because it is in use by another process". Well thats true, however I've worked with other programs that still allows reading from a logfile while they are writing to it, so I know it should be possible. Tried the _fsopen and unlocking the file but without success.
FILE* logFile;
//fopen_s(&logFile, "log.log", "w");
logFile = _fsopen("log.log", "w", _SH_DENYNO);
if (!logFile)
throw "fopen";
_unlock_file(logFile);
If you have the log-file open with full sharing-mode, others are still stopped from opening for exclusive access, or with deny-write.
Seems the second program wants more access than would be compatible.
Also, I guess you only want to append to the log, use mode "a" instead of "w".
Last, do not call _unlock_file unless you called _lock_file on the same file previously.
There is a way to do what you want though:
Open your file without any access, and then use Opportunistic Locks.
Raymond Chen's blog The Old New Thing also has a nice example: https://devblogs.microsoft.com/oldnewthing/20130415-00/?p=4663
Any idea how to read data from a file that is locked by another process?
When I try fopen() or CreateFile() or OpenFile() I get sharing violation.
Yet if I go to command prompt and do a "c:> more blah.h" I can see the file. So "more" somehow can read the file. Any idea how it accomplishes that?
Thanks!
I am trying to open it as "read-only". ie. "r" in fopen() and GENERIC_READ, FILE_SHARE_READ in create file
Clearly the file is not locked from reading, otherwise the more command could not have worked. So the process did specify read sharing when it created the file. The mistake is only specifying FILE_SHARE_READ in your own attempt to open the file. That denies write sharing. That cannot work, the process has already acquired write access to the file, you cannot deny it. Instead you'll be denied access with the sharing violation. You must also specify FILE_SHARE_WRITE to gain access to the file.
That will fix your problem. Only other wrinkle is that you'll be reading from a file that's being written to. So data in the file changes entirely unpredictably.
fopen is deprecated and msdn recommends fopen_s but sharing isnt enabled for that .
Files opened by fopen_s and _wfopen_s are not sharable. If you require
that a file be sharable, use _fsopen, _wfsopen with the appropriate
sharing mode constant (for example, _SH_DENYNO for read/write
sharing).
use _fsopen to open the file and enable a flag to share ( _SH_DENYNO ) to give sharing access.
fsopen
One way is to copy the file to a new temporary one and read that.
Please read this - http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
When you say , "access violations", do you mean a Win32 0xc000005 error, or something else?
There is a static library I use in my program which can only take filenames as its input, not actual file contents. There is nothing I can do about the library's source code. So I want to: create a brand-new file, store data to being processed into it, flush it onto the disk(?), pass its name to the library, then delete it.
But I also want this process to be rather secure:
1) the file must be created anew, without any bogus data (maybe it's not critical, but whatever);
2) anyone but my process must not be able read or write from/to this file (I want the library to process my actual data, not bogus data some wiseguy managed to plug in);
3) after I'm done with this file, it must be deleted (okay, if someone TerminateProcess() me, I guess there is nothing much can be done, but still).
The library seems to use non-Unicode fopen() to open the given file though, so I am not quite sure how to handle all this, since the program is intended to run on Windows. Any suggestions?
You have a lot of suggestions already, but another option that I don't think has been mentioned is using named pipes. It will depend on the library in question as to whether it works or not, but it might be worth a try. You can create a named pipe in your application using the CreateNamedPipe function, and pass the name of the pipe to the library to operate on (the filename you would pass would be \\.\pipe\PipeName). Whether the library accepts a filename like that or not is something you would have to try, but if it works the advantage is your file never has to actually be written to disk.
This can be achieved using the CreateFile and GetTempFileName functions (if you don't know if you can write to the current working directory, you may also want to use , GetTempPath).
Determine a directory to store your temporary file in; the current directory (".") or the result of GetTempPath would be good candidates.
Use GetTempFileName to create a temporary file name.
Finally, call CreateFile to create the temporary file.
For the last step, there are a few things to consider:
The dwFlagsAndAttributes parameter of CreateFile should probably include FILE_ATTRIBUTE_TEMPORARY.
The dwFlagsAndAttributes parameter should probably also include FILE_FLAG_DELETE_ON_CLOSE to make sure that the file gets deleted no matter what (this probably also works if your process crashes, in which case the system closes all handles for you).
The dwShareMode parameter of CreateFile should probably be FILE_SHARE_READ so that other attempts to open the file will succeed, but only for reading. This means that your library code will be able to read the file, but nobody will be able to write to it.
This article should give you some good guidelines on the issue.
The gist of the matter is this:
The POSIX mkstemp() function is the secure and preferred solution where available. Unfortunately, it is not available in Windows, so you would need to find a wrapper that properly implements this functionality using Windows API calls.
On Windows, the tmpfile_s() function is the only one that actually opens the temporary file atomically (instead of simply generating a filename), protecting you from a race condition. Unfortunately, this function does not allow you to specify which directory the file will be created in, which is a potential security issue.
Primarily, you can create file in user's temporary folder (eg. C:\Users\\AppData\Local\Temp) - it is a perfect place for such files. Secondly, when creating a file, you can specify, what kind of access sharing do you provide.
Fragment of CreateFile help page on MSDN:
dwShareMode
0 Prevents other processes from opening a file or device
if they request delete, read, or write access.
FILE_SHARE_DELETE Enables subsequent open operations on a file or device to
request delete access. Otherwise, other processes cannot open the file or device if they
request delete access. If this flag is not specified, but the file or device has been opened for delete access, the function fails. Note: Delete access allows both delete and rename operations.
FILE_SHARE_READ Enables subsequent open operations on a
file or device to request read access. Otherwise, other processes cannot open the file or device if they request read access. If this flag is not specified, but the file or device has been opened for read access, the function fails.
FILE_SHARE_WRITE Enables subsequent open operations on a file or device to request
write access.
Otherwise, other processes cannot open the file or device if they
request write access.
If this flag is not specified, but the file or device has been opened
for write access or has a file mapping with write access, the function
fails.
Whilst suggestions given are good, such as using FILE_SHARE_READ, FILE_DELETE_ON_CLOSE, etc, I don't think there is a completely safe way to do thist.
I have used Process Explorer to close files that are meant to prevent a second process starting - I did this because the first process got stuck and was "not killable and not dead, but not responding", so I had a valid reason to do this - and I didn't want to reboot the machine at that particular point due to other processes running on the system.
If someone uses a debugger of some sort [including something non-commercial, written specifically for this purpose], attaches to your running process, sets a breakpoint and stops the code, then closes the file you have open, it can write to the file you just created.
You can make it harder, but you can't stop someone with sufficient privileges/skills/capabilities from intercepting your program and manipulating the data.
Note that file/folder protection only works if you reliably know that users don't have privileged accounts on the machine - typical Windows users are either admins right away, or have another account for admin purposes - and I have access to sudo/root on nearly all of the Linux boxes I use at work - there are some fileservers that I don't [and shouldn't] have root access. But all the boxes I use myself or can borrow of testing purposes, I can get to a root environment. This is not very unusual.
A solution I can think of is to find a different library that uses a different interface [or get the sources of the library and modify it so that it]. Not that this prevents a "stop, modify and go" attack using the debugger approach described above.
Create your file in your executable's folder using CreateFile API, You can give the file name some UUID, each time its created, so that no other process can guess the file name to open it. and set its attribute to hidden. After using it, just delete the file .Is it enough?
Under Windows is there a way to modify a file/executable opened by another process using c++?
Is there a way to modify an open executable in windows?
No.
Is there a way to modify an open file in windows using c++?
Yes. If it has been opened with the proper share permissions. See http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx FILE_SHARE_WRITE
It may be possible but perhaps not easy to achieve. You need inject thread in destination process and know PE format for correctly edit opened file and modify it.
All information is on web.
Good Luck.
I find this freeware tool, it proposes to unlock files and folders.
The OS holds the executable file open for read-only sharing as long as it's running, so there's no way to modify it directly. You can, however, open it for reading (if you specify read-sharing in your CreateFile call), and make a modified copy of it, while it's running.
I don't know if that's what you had in mind, but if it's your own program you're doing this to, you can start the new copy and have it pick up where the previous one left off... not straightforward, but not all that difficult either.