How to lock lock on specific drive till i perform some operation(read/write) on that drive.
When i have captured lock on drive, no other process should able to write on that drive unitl I release lock on that drive, I have found one API i.e. DeviceIoControl(),
but I want access on drive for my process only, but the above API 'MAY' block access of all the processes. I'm not quite sure how lockfile() and lockfileex() works. Please help me find some way / API/ Logic to do this!
...
...
UPDATED :-
with referrance to your answer i have tried this :-->
HANDLE hdest,hf;
DWORD b,write;
hdest = CreateFile("\\\\?\\E:",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
NULL,
NULL);
if (hdest == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("NOT OK"),TEXT("NOT OK"),0);
}
if (DeviceIoControl( hdest,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&b,NULL))
{
MessageBox(NULL,TEXT("OK"),TEXT("OK"),0);
hf = CreateFile(TEXT("E:\\M_lucky.txt"), GENERIC_WRITE, 0, NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hf == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("NOT OK AFTER LOCK I"),TEXT("NOT OK AFTRE LOCK"),0);
}
WriteFile(hf, TEXT("M very lucky"), 13, &write, NULL);
}
CloseHandle((HANDLE)hdest);
CloseHandle((HANDLE)hf);
DeviceIoControl( hdest,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&b,NULL);
hf = CreateFile(TEXT("E:\\MNOT_lucky.txt"), GENERIC_WRITE, 0, NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hf == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("NOT OK AFTER LOCK"),TEXT("NOT OK AFTRE LOCK"),0);
}
WriteFile(hf, TEXT("M lucky"), 8, &write, NULL);
CloseHandle((HANDLE)hf);
""but........""
after getting exclusive lock on E drive, i am unable to create file.
(i have read that : only hdest(HANDLE) gets exclusive lock on that drive. )
here..!!! i want to create M_LUCKY.txt file..!!
(I need EXLUSIVE access on drive with context to PROCESS)
plz help! thanks a lottt!!
is there any other method for doing this??
Use DeviceIoControl with FSCTL_LOCK_VOLUME control code.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364575(v=vs.85).aspx
Related
I am trying to read raw bytes from a pen drive 'E:', but it gives error code 32 when trying to open the drive using CreateFIle(). My code is as follows:
wchar_t wszDrive[7];
wszDrive[0] = '\\';
wszDrive[1] = '\\';
wszDrive[2] = '.';
wszDrive[3] = '\\';
wszDrive[4] = 'e';
wszDrive[5] = ':';
wszDrive[6] = '\0';
hDevice = CreateFile(wszDrive, //drive name to open
GENERIC_READ | GENERIC_WRITE, ////must be opened with exclusive access(No Sharing)
0, // no access to the drive
NULL, // default security attributes
OPEN_EXISTING, // disposition i.e. if file already exist
0, // file attributes
NULL); // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
printf("CreateFile() failed! from read with error %d.\n", GetLastError());// Program prints this line. with error code 32.
return (FALSE);
}
else
cout << "\nCreateFile() successful! in read";
Edit:
The CreateFile() runs fine without errors if I use FILE_SHARE_READ | FILE_SHARE_WRITE:
hDevice = CreateFile(wszDrive,
GENERIC_READ |
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
Why cannot I run with exclusive access?
Error 32 is ERROR_SHARING_VIOLATION.
The process cannot access the file because it is being used by another process.
It means there is already an open handle to the drive, and that handle is using access/sharing rights which are not compatible with the access/sharing rights you are requesting.
That is why you can't open the drive for exclusive access, but you can open it for read/write sharing - the drive is already open elsewhere for reading/writing.
If you want to know where exactly, you can use a tool like SysInternals Process Explorer to see which processes have open handles to which files/folders, devices, etc.
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.
I'm writing a program using C++ under Windows that needs to synchronize write access to a file via a local network. I was thinking to use the following approach:
//Create or open it using 0 for sharing mode
HANDLE hFile = CreateFile(L"\\\\server\\share\\path\\file", GENERIC_READ | GENERIC_WRITE, 0, , OPEN_ALWAYS, , ,);
if(hFile == INVALID_HANDLE_VALUE && ::GetLastError() == ERROR_SHARING_VIOLATION)
{
//Try again later
}
Can someone confirm that it's a workable solution?
I have a card reader ( no memory stick is inserted ).
When i insert into my compter it shows an empty drive in My Computer...
Is it possible to know whether a drive is having a media ( sorry i am not sure how to call it ) or not...
I find the suggestion of MSalters to use IOCTL_STORAGE_CHECK_VERIFY very good. There are a small trick in the usage of IOCTL_STORAGE_CHECK_VERIFY. Before the usage of IOCTL code in the function DeviceIoControl one need to open the corresponding device with respect of CreateFile function:
HANDLE hDevice = CreateFile (szDeviceName, // like "\\.\E:"
0, // no access to the drive
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, OPEN_EXISTING, 0, NULL);
For the usage of DeviceIoControl one can use 0 as a second parameter of CreateFile, because we will not use ReadFile, WriteFile etc functions to access the device. The implementation of IOCTL_STORAGE_CHECK_VERIFY do follow to some read of data requests. So to be able to use IOCTL_STORAGE_CHECK_VERIFY without having ERROR_ACCESS_DENIED (5) error we have to open the device as following
HANDLE hDevice = CreateFile (szDeviceName, // like "\\.\E:"
FILE_READ_DATA, // read access to the data
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, OPEN_EXISTING, 0, NULL);
There exist another version of IOCTL_STORAGE_CHECK_VERIFY - IOCTL_STORAGE_CHECK_VERIFY2 which works absolutely the same as IOCTL_STORAGE_CHECK_VERIFY but much more quickly (see http://msdn.microsoft.com/en-us/library/ff560538.aspx). To use IOCTL_STORAGE_CHECK_VERIFY2 one can open device with only FILE_READ_ATTRIBUTES access:
HANDLE hDevice = CreateFile (szDeviceName, // like "\\.\E:"
FILE_READ_ATTRIBUTES, // read access to the attributes
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, OPEN_EXISTING, 0, NULL);
The code which test the existence of the media in the drive can look like following
DWORD cbBytesReturned;
bSuccess = DeviceIoControl (hDevice, // device to be queried
IOCTL_STORAGE_CHECK_VERIFY2,
NULL, 0, // no input buffer
NULL, 0, // no output buffer
&cbBytesReturned, // # bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if (bSuccess)
_tprintf (TEXT("the device media are accessible\n"));
else if (GetLastError() == ERROR_NOT_READY)
_tprintf (TEXT("the device media are not accessible\n"));
The reason for this behavior is historical, and dates back to floppy drives and MS-DOS. The A: drive would still be the A: drive even if there was no floppy in it.
It is sometimes possible to check whether a drive with removable media is empty. Card readers and CD drives usually support this, floppy drives don't. You would send the drive a IOCTL_STORAGE_CHECK_VERIFY .