This is from some old code that worked well for several years, but in our new project it got error. I have replaced all function arguments to constants, and tried using both wide-char and ASCII version and all got same result:
// compile with UNICODE=1
HANDLE handle = CreateFile( L"\\\\.\\C", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
// or
HANDLE handle = CreateFileW( L"\\\\.\\C", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
// or
HANDLE handle = CreateFileA( "\\\\.\\C", 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
The returned handle is 0xffffffff that is INVALID_HANDLE_VALUE, and GetLastError() return 2 which means no file found.
Running program with administrator privilege got same result.
Related
I have a Parent process which creates a file using CreateFile() and locks it. below is the code:
m_hWriterLockFile = ::CreateFile("C:\\Test.txt",
GENERIC_READ | GENERIC_WRITE,
0, // exclusive
NULL, // default security
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
Now, I want only the child process to access this locked file. I do not want any other process to read this file.
I have created a child process. Below is the sample code:
// Initialize a security attributes structure.
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = TRUE;
if (!CreateProcess("FileReader.exe", // I want to invoke this exe
"C:\\Test.txt",
&sa,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi))
{
std::cout << "Create Process Faild (%d) " << GetLastError() << '\n';
}
Unfortunately, I am not able to achieve my goal, is there anyone who can help me? Is there any other way to achieve this? I will share more information(code) if needed.
Note: I didn't share the complete code to make the post shorter.
Here is the answer of of my question :
create the file with an inheritable handle and pass that handle to the child process. A simple way to do this is to pass it as a command line parameter. We must pass a SECURITY_ATTRIBUTES structure that specifies TRUE for bInheritHandle to CreateFile and also pass TRUE to the bInheritHandles parameter of the call to CreateProcess.
Create File
Ex:
SECURITY_ATTRIBUTES sa{ sizeof sa, nullptr, TRUE };
HANDLE hFile = CreateFileA("C:\\Test.txt",
GENERIC_READ | GENERIC_WRITE,
0,
&sa,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
Child Process:
UINT_PTR uiHandle = reinterpret_cast<UINT_PTR>(hFile);
sprintf_s(szCmdLine, "\"%s\" %Iu", szExePath, uiHandle);
if (CreateProcessA(nullptr,
szCmdLine,
nullptr,
nullptr,
TRUE,
CREATE_NEW_CONSOLE,
nullptr,
nullptr,
&si,
&pi))
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
I am using the following code to memory-map a file for reading in windows (Windows 10):
HANDLE windowsFileHdl = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (windowsFileHdl == INVALID_HANDLE_VALUE)
{
return false;
}
HANDLE fileMappedHdl = CreateFileMappingA(windowsFileHdl, 0, PAGE_READONLY, 0, 0, nullptr);
char* baseFileData = (char*)MapViewOfFile(fileMapedHdl, FILE_MAP_READ, 0, 0, 0);
I would still like others to write to this file while I am reading it. Is this possible?
Currently, I get an error like this:
The process cannot access the file because it is being used by another process.
The above error was received by trying to open the file in a separate program (Notepad) while I had it memory mapped.
Is this a limitation with how the OS maps the file to memory or am I missing some flag?
EDIT:
#zett42 pointed out that I am missing FILE_SHARE_READ adding this makes the code:
HANDLE windowsFileHdl = CreateFileA(filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (windowsFileHdl == INVALID_HANDLE_VALUE)
{
return false;
}
HANDLE fileMappedHdl = CreateFileMappingA(windowsFileHdl, 0, PAGE_READONLY, 0, 0, nullptr);
char* baseFileData = (char*)MapViewOfFile(fileMapedHdl, FILE_MAP_READ, 0, 0, 0);
Now, notepad is able to open and write to the file!
However other programs like Visual Studio, Notepad++, or Emacs still have errors when writing to the file.
Visual Studio error:
The process cannot access the file because it is being used by another process.
Notepad++ error:
The file cannot be saved and it may be protected. Do you want to launch Notepad++ in Administrator mode?
I would like to ask for help with WINAPI function CreateFileMapping (), which returns constantly NULL. After GetLastError() I get 5 - "ERROR_ACCESS_DENIED 5 (0x5) Access is denied". The file has been created after CreateFile with no problem, but following CreateFileMapping never has bee succesful.
int MapDestFile(LPCWSTR fPath)
{
hDestFile = CreateFile(
fPath,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hSourceFile == NULL)
{
printf("%d\n", GetLastError());
}
hDestMapFile = CreateFileMapping(
hDestFile,
NULL,
PAGE_READWRITE,
0,
10,
NULL
);
if (hDestMapFile == NULL)
{
// here always tell error number 5
printf("%d\n", GetLastError());
}
lpMapAddressDestFile = MapViewOfFile(
hDestMapFile,
FILE_MAP_WRITE,
0,
0,
0);
if (lpMapAddressDestFile == NULL)
{
printf("%d\n", GetLastError());
}
return 1;
}
I would appreciate any suggestions.
Thanks
You need to create the file with GENERIC_WRITE | GENERIC_READ to match PAGE_READWRITE.
That seems self-evident when you think about it. How can you have memory that you can read from backed by a file that you cannot read from? The documentation does call this out explicitly in any case:
PAGE_READWRITE
The file handle that the hFile parameter specifies must be created with the GENERIC_READ and GENERIC_WRITE access rights.
On top of that your error checking on the call to CreateFile is wrong. Take another look at the documentations. Error is indicated by a return value of INVALID_FILE_HANDLE.
Createfile fails while reading mbr on WinXP. Returns -1 i.e INVALID_DEVICE_HANDLE
HANDLE hDisk = CreateFile((LPCWSTR)"\\\\.\\PhysicalDrive0", GENERIC_READ| GENERIC_WRITE, FILE_SHARE_READ| FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,NULL );
Any idea why???
You forgot to add 'L' to the string constant "\\.\PhysicalDrive0".
HANDLE hDisk = CreateFile(L"\\.\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
This is right only when you are using the unicode version of the API, i.e. CreateFileW().
Use this:
HANDLE hDisk = CreateFile(L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
It's working for me.
I try create file in visual studio c++.
But it now work, what is wrong?
CreateFile("1",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
If you try to create a file (not open it), you should not specify the OPEN_EXISTING flag. Instead, pass the CREATE_NEW constant:
CreateFile("1",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_FLAG_OVERLAPPED,
NULL);
This code tries to open existing file: OPEN_EXISTING. Replace it with CREATE_NEW to create new file.