I noticed that writing to a file, closing it, and moving it to its destination randomly fails in Vista. In particular, MoveFileEx () will return ERROR_ACCESS_DENIED no apparent reason. This happens on Vista SP1 at least (32 bits). Doesn't happen on XP SP3.
I found this thread on the Internet about the exact same problem, without real solutions. It still looks like the error is caused by the Vista search index, see below.
The above code example is enough to reproduce the problem. I insert it here too:
#include <windows.h> #include <stdlib.h> #include <stdio.h> bool test() { unsigned char buf[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 }; HANDLE h; DWORD nbytes; LPCTSTR fn_tmp = "aaa"; LPCTSTR fn = "bbb"; h = CreateFile(fn_tmp, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 0, 0); if (h == INVALID_HANDLE_VALUE) return 0; if (!WriteFile(h, buf, sizeof buf, &nbytes, 0)) goto error; if (!FlushFileBuffers(h)) goto error; if (!CloseHandle(h)) goto error; if (!MoveFileEx(fn_tmp, fn, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH)) { printf("error=%d\n", GetLastError()); return 0; } return 1; error: CloseHandle(h); return 0; } int main(int argc, char** argv) { unsigned int i; for (i = 0;; ++i) { printf("*%u\n", i); if (!test()) return 1; } return 0; }
Create this as a console application using Visual Studio. The correct behavior will be an infinite loop that prints test numbers. In Vista SP1, a program will exit after a random number of iterations (usually up to 100 iterations).
This does not happen on Windows XP Service Pack 2 (SP2). There is no antivirus at all; and no other weird background processes (the machine is pretty much like installing Windows + Visual Studio).
Change We dig further through Process Monitor (thanks @sixlettervariables), I do not see anything particularly bad. Each test iteration results in 176 disk operations, most of which come from SearchProtocolHost.exe (search index). If the search indexing service is stopped, no errors occur, so it looks like a criminal.
At the time of the crash (when the application receives ERROR_ACCESS_DENIED ), SearchProtocolHost.exe has two CreateFile files for the release file (bbb) open with read / write / delete modes, so it should be in order. One of the discoveries is followed by an opportunistic castle ( FSCTL_REQUEST_FILTER_OPLOCK ), maybe the reason?
In any case, I found that I could avoid the problem by setting the FILE_ATTRIBUTE_TEMPORARY and FILE_ATTRIBUTE_NOT_CONTENT_INDEXED to a file. It seems that FILE_ATTRIBUTE_NOT_CONTENT_INDEXED enough in itself, but marking the file as temporary also dramatically reduces disk operations caused by the search index.
But this is not a real solution . I mean, if an application cannot count on the possibility of creating a file and renaming it, because some Vista search indexes are useless with it, it is absolutely crazy ! Should she try again? Yell at the user (which is very undesirable)? Do something else?