CopyFileEx and partially locked files - winapi

I have been using CopyFileEx since the beginning of times and it has been working great. If the file is not locked, it will copy the file. If the file is locked, it will not and GetLastError will report the error. All fine and dandy.
However, there are some files that are partially locked, PST outlook files being the best example. In that case, CopyFileEx begins to copy, and when it hits the part of the file that is locked, it will hang and never return back (on Windows 7, maybe on other systems too).
Is there any way to avoid this problem?

There is a way to avoid it, but there is no easy solution.
Please see my answer here.

You could do the copying yourself, starting with a call to LockFileEx. It has a flag to fail immediately if it can't lock what you've asked it to.

Related

What prevents windows from deleting a file that is in use?

Sometimes I try to delete a file with del /f filenameand it says "The process cannot access the file because it is being used by another process.". Out of curiosity, what exactly is preventing this from happening? Is it the way that the hardware is set up, or is it more on the software side? And if the only thing preventing this from happening is the software, is there a way to work around it (force windows to delete part of the memory that is being accessed, and if it causes an error in whatever process is using it, just let it crash and exit)? Tried to look online and couldn't find anything.
Thanks
If a software program is loading or reading the file you want to delete, then this error appears.
And the only thing you can do, is closing the program and then try to delete the file again..

Cannot delete EXE after stopping the application

It looks like some executables do not shut down correctly on Windows. After stopping the application, and deleting the corresponding exe file, it immediately pops up again in the folder. I have to wait for some time (sometimes even minutes) until I can really remove it. Is there any reason/solution for this strange behavior?
This is very annoying, because I'm creating a release directory with a batch script, which previously removes the release directory in case it already exists.
I finally found the reason, thanks to this post:
https://superuser.com/questions/338567/why-cant-i-delete-some-exe-files/521349#521349
For some really really crazy (Microsoft internal) reasons you must have the "Application Experience service" enabled!!! God knows why! On German installations the service is called "Anwendungserfahrung". On my machine it was disabled. As soon as I enabled it, I was able to delete executable files immediately after terminating the EXE/programm!
I hope this post prevents others from going crazy like I did! ;-)

File rename fails with access denied (sharing violation)

My program creates a file, writes to it, closes it, renames it to something else. For one customer, the rename often fails with a sharing violation and I have been unable to recreate this issue.
The program is asynchronous and multithreaded, where the create and write are guaranteed to have been completed at the time of close and rename, but the close and rename may happen in any order due to being in different threads.
The customer ensures me that there are no av or backup programs installed and we have tried with Windows Search disabled.
When the close happens before or after the rename everything works (the file is opened with shared read+write+delete flags). However, when they are happening very close in time it sometimes fails. When running with ProcessMonitor, the error does not occur.
I know that the rename is made up out of several file operations (open, set information, close at least), so I assume that it is possible for the file close to be interleaved with the file rename, which seems be at the heart of the problem.
I am going to be able to work around the issue by ensuring that the file is closed after the rename. But I don't understand exactly what causes the sharing violation and I would like to know more why this is an issue. Can anyone give me more information on what happens?

Avoid updating last-accessed date/time when reading a file

We're building a Windows-based application that traverses a directory structure recursively, looking for files that meet certain criteria and then doing some processing on them. In order to decide whether or not to process a particular file, we have to open that file and read some of its contents.
This approach seems great in principle, but some customers testing an early version of the application have reported that it's changing the last-accessed time of large numbers of their files (not surprisingly, as it is in fact accessing the files). This is a problem for these customers because they have archive policies based on the last-accessed times of files (e.g. they archive files that have not been accessed in the past 12 months). Because our application is scheduled to run more frequently than the archive "window", we're effectively preventing any of these files from ever being archived.
We tried adding some code to save each file's last-accessed time before reading it, then write it back afterwards (hideous, I know) but that caused problems for another customer who was doing incremental backups based on a file system transaction log. Our explicit setting of the last-accessed time on files was causing those files to be included in every incremental backup, even though they hadn't actually changed.
So here's the question: is there any way whatsoever in a Windows environment that we can read a file without the last-accessed time being updated?
Thanks in advance!
EDIT: Despite the "ntfs" tag, we actually can't rely on the filesystem being NTFS. Many of our customers run our application over a network, so it could be just about anything on the other end.
The documentation indicates you can do this, though I've never tried it myself.
To preserve the existing last access time for a file even after accessing a file, call SetFileTime immediately after opening the file handle with this parameter's FILETIME structure members initialized to 0xFFFFFFFF.
From Vista onwards NTFS does not update the last access time by default. To enable this see http://technet.microsoft.com/en-us/library/cc959914.aspx
Starting NTFS transaction and rolling back is very bad, and the performance will be terrible.
You can also do
FSUTIL behavior set disablelastaccess 0
I don't know what your client minimum requirements are, but have you tried NTFS Transactions? On the desktop the first OS to support it was Vista and on the server it was Windows Server 2008. But, it may be worth a look at.
Start an NTFS transaction, read your file, rollback the transaction. Simple! :-). I actually don't know if it will rollback the Last Access Date though. You will have to test it for yourself.
Here is a link to a MSDN Magazine article on NTFS transactions which includes other links. http://msdn.microsoft.com/en-us/magazine/cc163388.aspx
Hope it helps.

How to prevent a file being copied or cut in windows file system?

I want that an exe file can't be copied or cut from the Windows file system to paste somewhere.
The exe is made in C#. which must have to be in only one PC.
I have worked with FileSystemWatcher, NSIS, Clipboard. but for all I need to detect whether that file is being copied.
I also have seen 'Prevent'(http www free-download-blog.com disable-cut-paste-copy-delete-rename-functions-using-prevent ), but I need to prevent only that particular exe from being copied or cut.
Any pointer or idea will help.
As others have suggested you won't be able to disable the copy/cut behaviour so easily.
An alternative would be to disable the execution of the copied versions. In your executable you could check many things like :
The path of the present executable is explicitly your_path
The name of the machine and user is the one you authorise
You could even prevent the file of being executed more than once using Windows register entries (if already 1 don't launch). It won't be perfect since any experimented user could tweak that out, assuming they are seeking for that. But depending on your users profile it might be sufficient.
If you need the exe to be executable, you need to permit loading it into memory.
As soon as you do, anyone can read it to memory using ReadFile and then write to an arbitrary location using WriteFile. No shell-detectable copying involved.
A good reading: Raymond's post and its comments on preventing copying.
Well, this is a hard problem. Even if you get explorer.exe to disable cut&paste, what prevents a user from using the command window? Or writing their own exe to do it? Booting up in linux and reading it?
Still, you have a few options (there will be more, most likely) which you could try:
Use the right permissions: Set the
permissions such that the users who
you don't want to cut&paste cannot
read the file.
Write a device driver which can hook
onto the filesystem calls and do that
for you.
Encrypt the file.
And some hacky options like:
Use the APPINIT_DLLS regkey to put your own dll to be loaded into each process ( I am not sure if this will work with console process though). Then on your dll load, do IAT hooking to replace the kernel32.dll file calls.
Replace kernel32.dll with your own version. Might have to do some messing around with the PE format etc.
There are no guarantees though. If for instance, you expect them to be able to execute it, but not copy it, you are probably stuck.
Any local admin will be able to undo anything you do to prevent copying. I can pretty much guarantee the program on that page you mention relies on a service or background process to prevent copy-and-paste, and therefore is easily circumventable. If your users are in a closed environment where none of them are admins and they have very limited rights to their PCs, then you have a chance.
if you could completly block explorer from copying or moving files, then all u need is a 3rd party software for copying files (but make sure it can filter file extensions) for example Copy Handler
Set up an ENVIRONMENT variable in your machine
In your code add a check
if (ENVIRONMENT Variable=='Same as defined')
//Execute code
else
//Suspend execution

Resources