The old contents are not being wiped out.
Instead the data is being written over, so I still see old contents.
What did I not do?
hFile = CreateFile(fname, // open testfile.txt
GENERIC_WRITE, // open for reading
0, // do not share
NULL, // default security
OPEN_ALWAYS, //
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attribute template
dwBytesToWrite = buff.GetLength();
WriteFile(hFile, buff.GetBuffer(100), dwBytesToWrite, &dwBytesWritten, NULL);
You have specified the wrong value for dwCreationDisposition. You need to specify CREATE_ALWAYS.
Creates a new file, always.
If the specified file exists and is writable, the function overwrites the file, the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183).
If the specified file does not exist and is a valid path, a new file is created, the function succeeds, and the last-error code is set to zero.
In dwCreationDisposition you need to specify CREATE_ALWAYS.
You need dwCreationDisposition = TRUNCATE_EXISTING. This however:
Opens a file and truncates it so that its size is zero bytes, only if
it exists. If the specified file does not exist, the function fails
and the last-error code is set to ERROR_FILE_NOT_FOUND (2). The
calling process must open the file with the GENERIC_WRITE bit set as
part of the dwDesiredAccess parameter.
So I would try and open it first with TRUNCATE_EXISTING. If it fails with ERROR_FILE_NOT_FOUND, then open it with CREATE_NEW.
hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, TRUNCATE_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile == NULL) && (GetLastError() == ERROR_FILE_NOT_FOUND))
{
hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
}
EDIT: This is not the best way to do this. CREATE_ALWAYS is the dwCreationDisposition you want to use. See David Heffernan's answer.
Related
I am trying to get a number from a HANDLE file, store it in an int, and possibly replace it in the same file. My code right now looks like this
HANDLE numFile = INVALID_HANDLE_VALUE; //Just in case file not found
numFile = CreateFile("numFile.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
ReadFile(numFile, input, sizeof(char), &bytesRead, NULL);
int myNumber = input[0];
I know that there exists a WriteFile method in the API, but it looks like it will append the file as opposed to overwriting the contents. I have briefly considered deleting and recreating the file each time, but this seems unnecessarily complex for this problem. Any ideas out there?
Use the function SetFilePointer prior WriteFile for moving back to the begin
SetFilePointer(numFile, 0, NULL, FILE_BEGIN);
I was under the assumption that if you use CreateFileW requesting exclusive access, that if it was already opened I should receive a sharing violation. However, I've come across an example where this is not the case. If LoadLibraryEx is called to load a DLL with the LOAD_LIBRARY_AS_DATAFILE flag set, then CreateFileW returns successfully. However there are operations that will be rejected (such as setting attributes like end of file). Is there a better way to detect if these files are open? Am I using CreateFileW incorrectly? Loading a DLL without the LOAD_LIBRARY_AS_DATAFILE flag does result in CreateFileW failing indicating it can not access the file because it is in use by another process.
HMODULE hModule = LoadLibraryEx(L"\\Pathto\\module.dll", NULL, NULL);
DWORD access = GENERIC_READ | GENERIC_WRITE | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY;
DWORD creation = OPEN_EXISTING;
DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
HANDLE file = CreateFileW(L"\\Pathto\\module.dll", access, 0, NULL, creation, flags, 0);
The above will result in CreateFileW failing with error code 32 (can't access cause it is in use by another process) which is the expected result. If I add the flag to LoadLibraryEx:
HMODULE hModule = LoadLibraryEx(name, NULL, LOAD_LIBRARY_AS_DATAFILE);
And use the exact same call to CreateFileW then I'm told it's successful, although I will run into problems later when attempting to set end of file (as an example). Additionally, deleting the file will fail with an access denied error (without the application or any other having an open handle).
Other odd behavior involves hard links with loaded libraries. If I generate a new hard link to the loaded module, and try to delete the alternate newly created hard link, it also fails (NO open file handles, just loaded module). Why? Shouldn't it just remove the link and dereference the link count, or schedule deletion on module close since I could have obtained exclusive access previously?
Also of note, the process itself runs in a privileged user account with the following additional privileges enabled:
SE_SECURITY_NAME, SE_BACKUP_NAME, SE_RESTORE_NAME, SE_TAKE_OWNERSHIP_NAME
How would one determine if you truly have exclusive access to a file when libraries are loaded?
Edit: Just to doubly check, I verified no other open handles besides loading the module via the SysInternals tool "handle".
your case can be more clear shown in next test
ULONG TestImageAccess(PCWSTR name, BOOL bImage, BOOL bRequestWriteAccess)
{
SetLastError(0);
HANDLE hFile = CreateFileW(name, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hSection = CreateFileMappingW(hFile, 0,
bImage ? PAGE_READONLY|SEC_IMAGE : PAGE_READONLY|SEC_COMMIT, 0, 0, 0);
CloseHandle(hFile);
if (hSection)
{
hFile = CreateFileW(name,
bRequestWriteAccess ? GENERIC_WRITE : GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
CloseHandle(hSection);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
}
}
}
return GetLastError();
}
void TestImageAccess(PCWSTR filename)
{
TestImageAccess(filename, TRUE, TRUE); // ERROR_SHARING_VIOLATION
TestImageAccess(filename, FALSE, TRUE); // NOERROR
TestImageAccess(filename, TRUE, FALSE); // NOERROR
TestImageAccess(filename, FALSE, FALSE);// NOERROR
}
we got ERROR_SHARING_VIOLATION when we request write access to file and file mapped as image
this case is described in Executable Images:
If the user wants write access to the file, make sure there is not a
process mapping this file as an image
the call to MmFlushImageSection with MmFlushForWrite fail and you got STATUS_SHARING_VIOLATION - exactly at this line.
LoadLibraryEx with flag LOAD_LIBRARY_AS_DATAFILE create section on file with SEC_COMMIT when with 0 in flag - with SEC_IMAGE - so as image section
the privileges here absolute not related
How would one determine if you truly have exclusive access to a file
when libraries are loaded?
simply open file with access which you need and do what you need. and yes, you can got error ERROR_USER_MAPPED_FILE when you try truncate mapped file. but here nothing can be done. example 2
ULONG TestImage2(PCWSTR name)
{
HANDLE hFile = CreateFileW(name, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hSection = CreateFileMappingW(hFile, 0, PAGE_READONLY|SEC_COMMIT, 0, 0, 0);
CloseHandle(hFile);
if (hSection)
{
PVOID pv = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
CloseHandle(hSection);
if (pv)
{
hFile = CreateFileW(name,GENERIC_WRITE|GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
FILE_END_OF_FILE_INFO eof = { };
// ERROR_USER_MAPPED_FILE will be here
SetFileInformationByHandle(hFile, FileEndOfFileInfo, &eof, sizeof(eof));
CloseHandle(hFile);
}
UnmapViewOfFile(pv);
}
}
}
return GetLastError();
}
I'm using IWICImagingFactory::CreateDecoderFromFilename() for reading only. Is there a way I can pass something like the FILE_SHARE_READ flag? The file stays open from the function call above until the program terminates.
During another operation within the same program, I attempted to use CFile::Open(), but I got error 32 ("The process cannot access the file because it is being used by another process").
What I ended up doing was using
pImagePoolEntry->hFileHandle = CreateFile(
path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
before the call to CreateDecoderFromFilename().
Since I was already using an Image Pool keeping track of opened, shared images I just added the initial file handle and added code to use CloseHandle() when the image was not longer in use.
I'm not sure what the IWICBitmapDecoder does with the file, but it seems to be keeping it opened past the Release() call on it. It might have a bug where the handle isn't closed, who knows. I couldn't find any information on that behaviour. Actually, apart from this question, nobody seems to have noticed (or nobody cares).
In any case, the solution, as hinted by Tony, is to open the file manually and use CreateDecoderFromFileHandle() instead of CreateDecoderFromFilename(). Note that "the file handle must remain alive during the lifetime of the decoder."
So this:
void f(IWICImagingFactory* factory, const wchar_t* path)
{
IWICBitmapDecoder* decoder = nullptr;
factory->CreateDecoderFromFilename(
path, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &decoder);
// ...
decoder->Release();
}
becomes this:
void f(IWICImagingFactory* factory, const wchar_t* path)
{
auto h = CreateFileW(
path, GENERIC_READ, FILE_SHARE_READ,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
IWICBitmapDecoder* decoder = nullptr;
factory->CreateDecoderFromFileHandle(
reinterpret_cast<ULONG_PTR>(h), nullptr,
WICDecodeMetadataCacheOnLoad, &decoder);
// ...
decoder->Release();
CloseHandle(h);
}
Here's my code in which I've got on an infinite loop (to my knowledge)
while(true) {
DWORD TitleID = XamGetCurrentTitleId();
std::ostringstream titleMessageSS;
titleMessageSS << "Here's the current title we're on : " << TitleID << "\n\n";
std::string titleMessage = titleMessageSS.str(); // get the string from the stream
DWORD dwBytesToWrite = (DWORD)titleMessage.size();
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
bErrorFlag = WriteFile(logFile, titleMessage.c_str(), dwBytesToWrite, &dwBytesWritten, NULL);
CloseHandle(logFile);
Sleep(30000);
}
return NULL;
Does anyone see a reason as to why this only writes just once? I've waited over 5 minutes to see if it does anything in the end to no avail.
The Flag CREATE_NEW in CreateFile prevents the update of the file because CreateFile fail with ERROR_FILE_EXISTS. Use OPEN_ALWAYS instead.
Also it will always truncate. Replace GENERIC_WRITE with FILE_APPEND_DATA if you want to add a new line at the end of your logfile.
The whole CreateFile line should be:
HANDLE logFile = CreateFile( "Hdd:\\LOGFile.txt", FILE_APPEND_DATA , 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
Read CreateFile documentation carefully, it worth it, because it has a central role in the windows IO universe:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx
look also add:
https://stackoverflow.com/a/9891875/1922748
As Martin James mentioned, from MSDN:
CREATE_NEW
Creates a new file, only if it does not already exist.
If the specified file exists, the function fails and the last-error
code is set to ERROR_FILE_EXISTS (80).
If the specified file does not exist and is a valid path to a writable
location, a new file is created.
So it seems that the handle is invalid after the first call, and hence WriteFile() fails.
I'm trying to create a process on another machine that deletes itself when its done. I'm using the DELETE_ON_CLOSE flag with CreateFile. This method is a bit popular but I'm having trouble because I can't execute it while it's open(expected but that's what some solutions do). To work around this I tried opening the file with read permissions. The DELETE_ON_CLOSE flag says that it should only delete a file when all pointers to it are gone. I have a pointer to it with the read, I close the write handle and the file deletes leaving my open handle unreadable. Any other way around this would be gladly appreciated.
I also have considered the possibility that since this is a remote file system there's something funky going on with the handles.
I cannot modify the code of the execuatble I'm sending over so a self-deleting executable is the last thing I want to do.
Making my program wait around to clean up the service will cause it to hang for an unacceptably long time because of how long it can take to destroy a service on the remote box.
//Open remote file for reading and set the delete flag
HANDLE remote_fh = CreateFile(&remote_file_location[0],
GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
NULL);
if(!remote_fh)
{
debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
RevertToSelf();
return dead_return;
}
//File to read from
HANDLE local_fh = CreateFile(&local_file_location[0],
GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(!local_fh)
{
debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
RevertToSelf();
return dead_return;
}
byte buf[256];
DWORD bytesRead;
DWORD bytesWritten;
//Copy the file
while(ReadFile(local_fh, buf, 256, &bytesRead, NULL) && bytesRead > 0)
{
WriteFile(remote_fh, buf, bytesRead, &bytesWritten, NULL);
}
CloseHandle(local_fh);
//Create a file retainer to hold the pointer so the file doesn't get deleted before the service starts
HANDLE remote_retain_fh = CreateFile(&remote_file_location[0],
GENERIC_READ,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (!remote_retain_fh)
{
debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
RevertToSelf();
return dead_return;
}
CloseHandle(remote_fh);
//if(!CopyFile(&local_file_location[0], &remote_file_location[0], false))
//{
// debug.DebugMessage(Error::GetErrorMessageW(GetLastError()));
// RevertToSelf();
// return dead_return;
//}
remote_service.Create(Service::GetServiceName().c_str());
//In the words of my daughter: "OH, OH, FILE ALL GONE!"
Pipe pipe(L"\\\\" + *hostname + L"\\pipe\\dbg");
CloseHandle(remote_fh);
FILE_FLAG_DELETE_ON_CLOSE requires FILE_SHARE_DELETE permission. The problem with that is that when a process starts up, the operating system opens a file handle to the executable and requires NOT sharing the FILE_SHARE_DELETE permission so that you can't delete the executable file while the process is open.
Consider: you open a handle to an executable file without exclusive FILE_SHARE_DELETE, but say just FILE_GENERIC_READ. Someone else (you, later, or indeed another thread or process) then launches that executable. No problem because nobody's trying to delete the executable. But if you were then to try to gain FILE_SHARE_DELETE permission, you'd fail because the executable is already running with exclusive file delete permission.