CreateFile fails with error ERROR_SHARING_VIOLATION - c++

Im using the CreateFile api and some times it randomly fails with the error: ERROR_SHARING_VIOLATION.
I have googled and there is almost nothing about this error. The strange thing is next time it is quite happy to open the same file.
Here is my code:
void FileHandle::open(const char* fileName, FILE_MODE mode)
{
if (m_bIsOpen)
close();
HANDLE fh = NULL;
DWORD dwDesiredAccess = GENERIC_READ;
DWORD dwShareMode = FILE_SHARE_READ;
DWORD dwCreationDisposition = OPEN_EXISTING;
switch (mode)
{
case FILE_READ:
break;
case FILE_WRITE:
dwDesiredAccess = GENERIC_WRITE;
dwShareMode = 0;
dwCreationDisposition = CREATE_ALWAYS;
break;
case FILE_APPEND:
dwDesiredAccess = GENERIC_WRITE;
dwShareMode = 0;
dwCreationDisposition = OPEN_ALWAYS;
break;
default:
throw gcException(ERR_INVALID, "The mode was invalid");
break;
}
fh = CreateFile(fileName, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, 0, NULL);
if (!fh || fh == INVALID_HANDLE_VALUE)
throw gcException(ERR_INVALIDFILE, GetLastError(), gcString("Failed to open the file {0}", fileName));
m_hFileHandle = fh;
m_bIsOpen = true;
if (mode == FILE_APPEND)
{
DWORD high = 0;
DWORD low = GetFileSize(fh, &high);
uint64 pos = (((uint64)high)<<32) + (uint64)low;
seek(pos);
}
}
Am i doing something wrong or is there an issue with the api?
Edit:
Im using the full file name (i.e. C:\somefile.txt) and mode=FILE_WRITE

There is nothing wrong with CreateFile - a sharing violation means that something else has the same file open. Which could be your own program, if you have the file open with a share mode of 0, you won't be able to open it again.
When you get the error you can use Process Explorer to determine what processes have the file open.

Is there anti-virus on the machine? Sometimes an AV's (or other software that monitors files) operations and timing can cause sharing conflicts.
This is particularly true if you're opening an existing file for exclusive access (this would be the case for the FILE_WRITE and FILE_APPEND cases if the file already exists).

I mean no disrespect, but I just shot myself in the foot last week on something similar:
Are you sure nothing else has the file open in a way which would prevent the access being requested?
In my case, I had used ctrl-Z in a Linux command window to suspend a program which created a socket connection, then I went to bed. Next morning after a few simple changes, I kept getting "unable to create socket: service in use" messages when running the program. Sadly, I spent hours debugging what I had broken. Once I killed the offending suspended process, it worked fine.

Microsoft say here that this can happen and it up to the application to retry when it does. Horrid but there you go.

Related

How to access the file pointer of each blocks of a file from the $MFT file in NTFS?

I am working on file virtualization and versioning project. For that, I need to access the logical blocks of file contents directly without copying into memory. Anyone could you help me with code snippets that works on my 64 bit windows?
I tried the following code to access the MFT file. But it responds like 'Access denied' even though I ran with administrator privileges.
#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
// Format the Win32 system error code to string
void ErrorMessage(DWORD dwCode);
int wmain(int argc, WCHAR **argv){
HANDLE hVolume;
WCHAR lpDrive[] = L"\\\\.\\C:";
PNTFS_VOLUME_DATA_BUFFER ntfsVolData = {0};
BOOL bDioControl = FALSE;
DWORD dwWritten = 0;
hVolume = CreateFile(lpDrive, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hVolume == INVALID_HANDLE_VALUE){
wprintf(L"CreateFile() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
else
wprintf(L"CreateFile() is pretty fine!\n");
ntfsVolData = (PNTFS_VOLUME_DATA_BUFFER)malloc(sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA));
bDioControl = DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, ntfsVolData,sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA), &dwWritten, NULL);
if(bDioControl == 0){
wprintf(L"DeviceIoControl() failed!\n");
ErrorMessage(GetLastError());
if(CloseHandle(hVolume) != 0)
wprintf(L"hVolume handle was closed successfully!\n");
else{
wprintf(L"Failed to close hVolume handle!\n");
ErrorMessage(GetLastError());
}
}
getchar();
}
void ErrorMessage(DWORD dwCode){
DWORD dwErrCode = dwCode;
DWORD dwNumChar;
LPWSTR szErrString = NULL; // will be allocated and filled by FormatMessage
dwNumChar = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM, 0, dwErrCode, 0, (LPWSTR)&szErrString, 0,0 ); // since getting message from system tables
if(dwNumChar == 0)wprintf(L"FormatMessage() failed, error %u\n", GetLastError());//else//wprintf(L"FormatMessage() should be fine!\n");
wprintf(L"Error code %u:\n %s\n", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
if(LocalFree(szErrString) != NULL)
wprintf(L"Failed to free up the buffer, error %u\n", GetLastError());//else//wprintf(L"Buffer has been freed\n");
}
CreateFile() failed!
Error code 5:
Access is denied.
hVolume handle was closed successfully!
DeviceIoControl() failed!
Error code 6:
The handle is invalid.
hVolume handle was closed successfully!
Thank you
Admin privileges aren't enough. What you need to do is request backup and restore privileges for your process. MSDN has sample code. Keep in mind that you probably need both SE_BACKUP_NAME and SE_RESTORE_NAME.
The process is a bit cumbersome:
Use OpenProcessToken on your process with TOKEN_ADJUST_PRIVILEGES
Use LookupPrivilegeValue to get the privilege based on the string constants (one for SE_BACKUP_NAME, one for SE_RESTORE_NAME)
Use AdjustTokenPrivileges to acquire the backup and restore privileges
If you do this properly, the rest of your code should work. To actually enumerate the MFT, you'll want to use the FSCTL_ENUM_USN_DATA variant of DeviceIOControl.

Named pipe sometimes doesn't work

So I wrote a C++ application that connects to an Unreal Engine 4 game through a named pipe. 95% of the time it works perfectly, but sometimes it doesn't seem to connect properly. It is very random so it is hard for me to find the problem that is causing this. The Server is created in my application and the Client is created in the UE4 game. And sometimes the UE4 game doesn't connect and displays error 121:
//
// MessageId: ERROR_SEM_TIMEOUT
//
// MessageText:
//
// The semaphore timeout period has expired.
//
#define ERROR_SEM_TIMEOUT 121L
As I said the problem occurs very randomly and I can't seem to find a specific reason that could cause the problem. The pipe is successfully created, I can see this in windows powershell (get-childitem \.\pipe).
I was thinking maybe it has something todo with the pipe settings I use?
This is my code for creating the pipe server:
DWORD erPipeServer::CreatePipeServer() {
// create a SECURITY_ATTRIBUTES structure.
if (!CreatePipeSecurity(&pSa))
{
dwError = GetLastError();
//wprintf(L"CreatePipeSecurity failed w/err 0x%08lx\n", dwError);
Cleanup();
return dwError;
}
// Create the named pipe.
hNamedPipe = CreateNamedPipe(
pipename, // Pipe name.
PIPE_ACCESS_DUPLEX, // The pipe is duplex; both server and
// client processes can read from and
// write to the pipe
PIPE_TYPE_MESSAGE | // Message type pipe
PIPE_READMODE_MESSAGE | // Message-read mode
PIPE_NOWAIT, // Blocking mode is enabled
PIPE_UNLIMITED_INSTANCES, // Max. instances
BUFFER_SIZE, // Output buffer size in bytes
BUFFER_SIZE, // Input buffer size in bytes
NMPWAIT_WAIT_FOREVER, // Time-out interval
pSa // Security attributes
);
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
//wprintf(L"Unable to create named pipe w/err 0x%08lx\n", dwError);
Cleanup();
return dwError;
}
//wprintf(L"The named pipe (%s) is created.\n", pipename);
return dwError;
}
And this is my code for creating the client in Unreal Engine 4:
// Try to open the named pipe identified by the pipe name.
while (true)
{
hPipe = CreateFile(
FULL_PIPE_NAME, // Pipe name
GENERIC_READ | GENERIC_WRITE, // Read and write access
0, // No sharing
NULL, // Default security attributes
OPEN_ALWAYS, // Opens existing pipe
0, // Default attributes
NULL // No template file
);
// If the pipe handle is opened successfully ...
if (hPipe != INVALID_HANDLE_VALUE)
{
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Green, FString::Printf(TEXT("The named pipe %d is connected."), FULL_PIPE_NAME));
break;
}
dwError = GetLastError();
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (ERROR_PIPE_BUSY != dwError)
{
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, FString::Printf(TEXT("Unable to open named pipe ------ %d"),dwError));
goto Cleanup;
}
// All pipe instances are busy, so wait for 5 seconds.
if (!WaitNamedPipe(FULL_PIPE_NAME, 5000))
{
dwError = GetLastError();
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, FString::Printf(TEXT("Could not open pipe: 5 second wait timed out. %d"),dwError));
**THE 121 ERROR OCCURED HERE^^**
goto Cleanup;
}
}
Could it be a problem with the pipe settings or something? I do not understand why it works almost all the time, but sometimes not with no clear reason why or when...
Thanks for any help in advance!
Ok, so I think I fixed the problem, maybe not in the best way but it seems to work good enough for my purpose.
After managing to reproduce the problem, I started working with the idea that the Handle could be open or busy ( Thanks to Karsten!!). I could bug the game into showing the 121 error by using windows powershell and running \.\pipe\name (where name is the pipes name). This would open the pipe and the game could not connect anymore, displaying error 121.
How I "fixed" it: Recreating the pipe when no connection is made after a second. Normally in my application when the server is connected the client is already ready. So connection should be immediately. When it isn't, now the pipe is recreated after a second and then it will work. Off-course this is not a clean fix, but I have no idea how the handle normally can open, because normally the only application trying to connect to the pipe is the game...
But anyway it is a decent work-around for the 1 in 30 times the problem occured for (still) some strange reason...
Any other ideas would be appreciated but this is working for now I think :)

Permission denied while taking a snapshot of running process using CreateToolhelp32Snapshot()

Today I was requested to turn my console app(eg:App.exe) into a service, just googled and found nssm then used its effective commands to turn my APP.exe to a service,My next job is to monitor the running process(APP.exe) and if its size exceeds >30MB restart it that's all.What I've learned previously from nssm is when I kill the APP.exe nssm automatically restart it, So now I only need to code for only monitoring and killing the APP.exe when it exceeds 30MB,finally I've created an app that does monitoring There comes the problem, In the monitoring app I have been using CreateToolhelp32Snapshot() to take a snapshot of all running processes and try to find my APP.exe by its name then get it's size by pmc.WorkingSetSize, Yet When I ran my monitoring app it can't find the APP.EXE though i see it exist in the task manager I even ran it as an administrator yet it remains the same can any one helpme rid of this issue.
The error I am getting while taking a snapshot is permission denied.
please see my code below:
int main()
{
LOG mon;
PROCESSENTRY32 pe32 = {0};
HANDLE hSnap;
HANDLE hprocess;
PROCESS_MEMORY_COUNTERS pmc;
int iDone;
int iTime = 60;
bool bProcessFound;
while(true) // go forever
{
cout<<"adjfhaljkehdfhwoefjiej";
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe32.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnap,&pe32); // Can throw away, never an actual app
bProcessFound = false; //init values
iDone = 1;
while(iDone) // go until out of Processes
{
iDone = Process32Next(hSnap,&pe32);
if (strcmp(pe32.szExeFile,"APP.exe") == 0) // Did we find our process?
{
DWORD processID = pe32.th32ProcessID;
hprocess= OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if (GetProcessMemoryInfo( hprocess, &pmc, sizeof(pmc)))
{
size_t procsize=pmc.WorkingSetSize;
cout<<procsize;
if(procsize>30MB)--mylogic
{
hprocess=OpenProcess(PROCESS_TERMINATE,0, processID);
TerminateProcess (hprocess, 0);
mon.RestartLog("Server Closed due to large size");
}
}
bProcessFound = true;
iDone = 0;
}
}
if(!bProcessFound) .
{
mon.RestartLog("Server Down ");
}
Sleep(iTime*50); // delay x amount of seconds.
}
return 0;
}
Run the above said monitor app as a system process. i.e, make it as a service.

Windows Event Viewer holds a lock on my EXE file

I'm curious about something. I'm developing a Windows service and log all the diagnostic events into the Windows Event Log. So when the service is running I open the Event Viewer (from Administrative tools) to view the results of my service's operation.
This works great except for the moment when I need to uninstall my program (again, for the testing purposes.) For some weird reason the Event Viewer holds a lock on the .exe image file for my service so the uninstaller fails to delete it with the error code ERROR_SHARING_VIOLATION:
The process cannot access the file because it is being used by another process.
This happens only on Vista and later OS and seems not to be an issue on XP.
Any idea how to make Event Viewer release the file lock? (I'm asking about programmatic approach. I can obviously close it manually, but that's not what I'm after.)
I released the lock this way:
Start -> Services
Locate Windows Event Log
Right click -> Restart
There's a less known feature introduced in Vista called Restart Manager that can help you release file locks via a user-mode code. Since you tagged it as C++, based on this article here's a small code sample to do that:
#include <RestartManager.h>
#pragma comment(lib ,"Rstrtmgr.lib")
BOOL ReleaseFileLock(LPCTSTR pFilePath)
{
BOOL bResult = FALSE;
DWORD dwSession;
WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = { 0 };
DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey);
if (dwError == ERROR_SUCCESS)
{
dwError = RmRegisterResources(dwSession, 1, &pFilePath,
0, NULL, 0, NULL);
if (dwError == ERROR_SUCCESS)
{
UINT nProcInfoNeeded = 0;
UINT nProcInfo = 0;
RM_PROCESS_INFO rgpi[1];
DWORD dwReason;
dwError = RmGetList(dwSession, &nProcInfoNeeded,
&nProcInfo, rgpi, &dwReason);
if (dwError == ERROR_SUCCESS ||
dwError == ERROR_MORE_DATA)
{
if(nProcInfoNeeded > 0)
{
//If current process does not have enough privileges to close one of
//the "offending" processes, you'll get ERROR_FAIL_NOACTION_REBOOT
dwError = RmShutdown(dwSession, RmForceShutdown, NULL);
if (dwError == ERROR_SUCCESS)
{
bResult = TRUE;
}
}
else
bResult = TRUE;
}
}
}
RmEndSession(dwSession);
SetLastError(dwError);
return bResult;
}
I just met same problem. The DLL was locked by svchost.exe process (Windows Audio, DHCP Client, Windows Event Log, TCP/IP NetBIOS Helper, Security Center, Task Scheduler)
Solution: close Event Viewer! :)

(Windows) Open the same file simultaneously

I am trying to open a file for writing and reading simultaneously, in windows.
I have one program which writes (every one second) to the file and one that reads from it. In unix it works prefectly but it doesn't work in windows (I can't open an already opened file).
I open the file with fopen().
How can I solve this problem?
EDIT2:
check out _fsopen it uses FILE *, and set the share flag accordingly.
EDIT:
First of all, some code: this is how I used to open the file
FILE* f = NULL;
int res = fopen_s(&f, "c:\\temp\\File1.txt", "w");
if (res != 0) return;
while (true) {
Sleep(1000);
fprintf_s(f , "Some data");
}
fclose(f);
The read was in other applicaiton, but it did fscanf instead.
The fixed code:
char d[] = "data";
HANDLE h = CreateFile("c:\\temp\\f.txt", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, /*FILE_ATTRIBUTE_NORMAL*/ FILE_FLAG_WRITE_THROUGH, NULL);
if (h == INVALID_HANDLE_VALUE) return 0;
DWORD bytesW;
while(true) {
Sleep(100);
WriteFile(h, d, strlen(d), &bytesW, NULL);
}
CloseHandle(h);
return 0;
Both Windows and Linux have a default way of opening a file, which fopen uses by default.
In Windows, that means blocking (only one process can open a file at a time).
In Linux, it means non-blocking.
fopen is a high-level API. To choose yourself the blocking policy on the file, for Windows you should use OpenFile from WinAPI. In particular, have a look at the OF_SHARE_* flags.