I googled a lot and I couldn't find any answer to this problem...
I have a C++ console application that reads a 1GB SD card that fixes improperly closed files and writes the FAT table accordingly. The SD card is written at the beginning by a firmware in a custom made device.
It worked OK up to Xp and stopped working in Win Vista/seven.
I tried elevating privileges: within an administrator account type, I launched a cmd window using the "run as administrator" method but no luck.
I also tried with a manifest asking for highestAvailable privileges but no luck.
I read in some post that “Windows Vista doesn't allow you to access the disks from user-mode processes at all. Does anybody know about any way of bypassing this behavior?
I’m working in a workaround however I would like to know if this is impossible or not
Edit:
This is my first post here so I don't quite understand about the linking issue... But I'm not reated to any spam at all... just asking in a comunity driven site :)
The code looks like
hDevice = CreateFile(buffer,GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING,0,NULL);
I then read the BTB information from the SD and look for and improperly closed file.
Finally when trying to write to the SD
WriteFile(hDevice,buffer,SD_SECTOR_SIZE, &temp, 0)
I get an Access denied (error #5)
The string on CreateFile() is \.\g: as the g letter correspond to the SD card on my machine. All that works ok and as I said before it woks on XP. I also tried using: DeviceIoControl with FSCTL_LOCK_VOLUME but that gives a mem fault error.
Hope this helps to understand and thanks for any help
I think this is due to the path string "buffer"; I ran into the same issue.
The path you are using to get device access needs to look lik this "\\.\PhysicalDrive%d"
%d is the decimal number of the drive.
From Vista on this string is CASE SENSITIVE.
Check the spelling. You also need admin rights, just as before in XP.
For Volumes,. the letter needs to CAPITALIZED
e.g. "\\.\G:"
Also note that it is much better to access the SD card as a device rathern than the volume, since if Windows mounts it, there might be a file system mounted with a write cache.
Furthermore: I forgot to mention that the buffer your read/write the data to/from should be page aligned and the read a multiple of the sector size.
VirtualAlloc() does this
You must dismount volume before writing raw data.
From MSDN:
A write on a volume handle will succeed if the volume does not have a mounted file system, or if one of the following conditions is true:
The sectors to be written to are boot sectors.
The sectors to be written to reside outside of file system space.
You have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The volume has no actual file system. (In other words, it has a RAW file system mounted.)
A write on a disk handle will succeed if one of the following conditions is true:
The sectors to be written to do not fall within a volume's extents.
The sectors to be written to fall within a mounted volume, but you have explicitly locked or dismounted the volume by using FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME.
The sectors to be written to fall within a volume that has no mounted file system other than RAW.
Sample code:
BOOL bResult = DeviceIoControl(hDevice, // device to be queried
FSCTL_DISMOUNT_VOLUME, // operation to perform
NULL, 0, // no input buffer
pdg, sizeof(*pdg), // output buffer
&junk, // # of bytes returned
(LPOVERLAPPED)NULL); // synchronous I/O
Related
I am writing a program that is using a database library. The library provides me access to the file handle it uses to access my table. I've found a windows API that allows me to retrieve information about the file by handle but I've yet to find any means of determining access mode / permissions of that file. At this point I'm sure I could likely live without knowing this information but being the stubborn cuss that I am I'm not ready to let this one go. Obviously Windows knows this info - so the question is how can coax the info out of it?
The API function that I've found is: GetFileInformationByHandleEx and it takes me close to the watering hole but doesn't let me drink the water.
The reason that the file mode information is useful is that I need to modify the table header information. If the file is already in a proper mode then I won't have to close the table open the file modify the file close the file then re-open the table.
And yes, before I'm told of all the options available to me to achieve my goal - I'm not interested in those. I'm only interesting in the original question - how do I determine the mode of an already opened file. I look forward to any responses and I thank you in advance.
Thanks,
Robert Milligan
I don't know if there is a corresponding Win32 API for this, but if you really need it you can call NtQueryObject(ObjectBasicInformation).
OK. So I finally got this part all figured out - thanks to your direction, a lot of MSDN study and a LOT of trial and error.
There were a couple of tricky points to getting this all figured out.
1) The ACCESS_MASK certainly did not reflect the access modes as I expected. The documentation led me to expect the upper 4 bits to reflect the "GENERIC" modes that I opened the file with - wrong! Those show up in the Specific Rights section. Heck - I still don't have a clue when those upper 4 bits actually get used, but for this exercise I don't need to.
2) Once I got THAT clear in my mind I had to stumble across documentation that let me know that when I opened with GENERIC_READ that was translated into:
FILE_GENERIC_READ
which is made up of:
STANDARD_RIGHTS_READ |
FILE_READ_DATA |
FILE_READ_ATTRIBUTES |
FILE_READ_EA |
SYNCHRONIZE
Understanding this concept made all the rest of it fall into place. Now my understanding correlated with the information that Process Hacker was telling me.
3) I also had a serious error going from my UI to the code (read one constant misplaced), which once figured out made the whole world lay down before my feet.
This is great because I can now figure out what Access Modes were used when the file was opened. Original question answered!
Now I would like to be able to determine the "share" mode the file is in - if possible. Any ideas?
Thanks again for your help
Figured it out maybe? From my reading of the docs, it seems you might be able to discern the original "share mode" of an open handle by calling ReOpenFile with dwDesiredAccess of 0 and dwShareMode for one (or more?) of the modes to query, i.e. FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE. If ReOpenFile returns a valid handle--which you can then close/dispose--then that sharing mode was present on the original file?
Source:
"If dwDesiredAccess is zero (0), the application can query device attributes without accessing the device. This is useful if an application wants to determine the size of a floppy disk drive and the formats it supports without requiring a floppy in the drive."https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-reopenfile
I have a Windows program coded in C++. To get the drive's serial number of the computer's drive, I run "wmic path win32_physicalmedia get SerialNumber" in the program with _popen().
However, the computers that run the program may have many drives, and USB drives also appear in the list.
How can I do to know which of the drives has the program I'm running? Thanks!
Assuming you still want to do it with WMI: first of all you need some code to read WMI properties in C++. No need to repeat here, you can find it in Getting CPU ID code from C# to be in C++.
When you have that code you can stat to work with disks. First of all you need to remember how Windows organize disks:
Each physical disk (Win32_DiskDrive) is made by partitions (Win32_DiskPartition).
Each partition (Win32_DiskPartition) is a logical disk (Win32_LogicalDisk).
Mapping between each other is done with Win32_DiskDriveToDiskPartition and Win32_LogicalDiskToPartition.
You already know where you're running then you can do this mapping:
Fetch from Win32_LogicalDisk the one where DeviceID property matches drive you're running on:
DeviceID=C:
Query Win32_LogicalDiskToPartition and pick Antecedent for which Dependent has ID you previously found:
\\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1" \\REPETTI\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
Now you should query partitions in Win32_DiskPartition to find the one where DeviceID is Disk #1, Partition #1 however also Win32_DiskDriveToDiskPartition uses DeviceID for this mapping then you can directly query Win32_DiskDriveToDiskPartition to match given ID:
\\REPETTI\root\cimv2:Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE1" \\REPETTI\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #1"
Now you just need to query Win32_DiskDrive searching for device ID \\.\PHYSICALDRIVE1:
WDC WDxxx ATA Device \\.\PHYSICALDRIVE1 WDC WDxxx ATA Device
And you can get its serial number (in this case same property is available both in Win32_PhysicalMedia and Win32_DiskDrive otherwise you should search by its Caption).
Without WMI
If you have to do it without WMI then it's little bit more tricky.
First of all you need to figure out which physical drive contains your logical drive_ you may follow How to list physical disks?.
When you have physical drive name easiest way is CreateFile() to open drive and get information with DeviceIoControl() sending S.M.A.R.T. commands. Don't think it's always so easy: with many drives it'll fail and you need administrative rights. Unfortunately there isn't a single perfect solution then you need to try different approaches. AFAIK best and most exhaustive code to handle this is written by Lynn McGuire for its DiskId32 utility.
I update the hard disk root directory, information like long filename, filesize , filedate etc, using VC++ writefile function. However, I note window explorer do not know about this until it is re-booted such as a refresh or reopen another window explorer. I have tried call to SHChangeNotify and SendMessageTimeout but fail. My next step would be to try a fake of removal and insert of an external disk. Please help. thanks
Do not attempt to modify a filesystem directly while it is mounted (and if explorer can see it, it's mounted). The OS will maintain various cached representations of the filesystem, and modifying it behind the OS's back will result in inconsistencies between the cached representation and the actual FS, potentially corrupting the filesystem and any data in said FS.
Take a look at this serverfault question for some hints on how to perform an unmount.
Try turning off the hard disk write cache, hopefully OS does not cache any file system data in RAM. This will affect IO performance but may help your experiment.
Background:
I have an application which plays video files from disc. When I play these files the first time the file reading sometimes lags. However, the second time it is played there is never any lag, I suspect this is because the file is put into the windows file cache the first time it is played.
The requirements of my application is that it should be able to play any video at any time (the same video is almost never played twice, thus making the cache unnecessary), this makes the current problem quite critical.
In order to debug this problem I would need to disable windows xp file caching.
Question
Is there a way to disable windows xp file caching?
EDIT/More Info
Im using ffmpeg, and have no access to the actual file read calls. The problem can occur even if several other files have been played previously (warm up).
In general, you can't just force FILE_FLAG_NO_BUFFERING. It requires aligned buffers, and typically these aren't provided. Besides, it's the wrong thing. You don't care whether Windows reads 32KB ahead.
The only thing that you'd like Windows to do is discard file contents from cache after you've read them. The correct flag for that is FILE_FLAG_SEQUENTIAL_SCAN. This hints Windows that you (probably) won't seek back, so there is no reason to keep those bytes in cache.
You can try passing FILE_FLAG_NO_BUFFERING to CreateFile() to avoid caching. This imposes some requirements on your buffers. Specifically, their size must be a multiple of the sector size and their addresses must be aligned on the sector size. See MSDN for more details.
Assuming you have access to the CreateFile call which ultimately opens your file, you can use FILE_FLAG_NO_BUFFERING when you open it:
http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
If you're not calling CreateFile directly yourself, but via some kind of library, you'll need to see if they provide a way to let you set this flag indirectly.
You might also find that the initial delay is caused by loading-up of the enormous number of DLLs which can make up the media stack in Windows, in which case altering the way the media file itself is opened won't help.
You could test this by making an extremely short media file, which you play at app startup, to 'warm-up' the stack.
Sometimes a network drive that is already mapped to a drive letter because "disconnected". Using the normal Windows functions to access files / folders on that drive fail. As soon as the user manually clicks on that drive it the Windows Explorer dialog, it's magically repaired.
Since my program is a batch program I'd like to start this "magic" from my program (C++) but I haven't found a Windows function for that. There's nothing in the usual WNet... functions...
NET USE V: /DELETE
NET USE V: "\\server1\videos"
NET USE L: /DELETE
NET USE L: "\\server2\archive"
When the path is inserted, you could check to see if it is a network resource and before opening files, use WNetGetConnection() to get the network resource.
You could also try to use WNetRestoreConnectionW(), which seems to have more spurious support, depending on the environment.
Try re-connecting to the share via net use:
net use \\server\folder [/user:[domain\]username] [password]
If that doesn't work, you can net use /delete it first, then re-connect.
Isn't this what WNetAddConnection and WNetAddConnection2 are for?
I suspect that is really the same thing, though. Explorer probably caches the connection info somewhere in the registry. When the user tries to go to that drive Explorer sees that the mapping is disconnected, reads the connection info from the registry, and re-creates the connection. Maybe you could try running regmon while you create a drive mapping and see if you can figure out where and how the connection information is cached.
I had trouble with this at a client of mine not long ago. I don't know if it's possible in your situation, but our fix was to tweak the Server's network settings to stop the timeouts and disconnects. See MSKB 297684 for details.
I agree with the comment from CMB, above. I've been down this path (excuse the pun) in the past and it caused me no end of trouble.
If the path is user configurable, they could use m:\pathonserver or they could use \server\c\pathonserver.
It shouldn't make any difference to your code, opening a file as m:\blahdeblah.dat or \server\c\blahdeblah.dat will be identical.
Using the UNC path is far more reliable, Windows will reconnect to that path automatically whether or not the mapped letter is there.
If you map a drive to a network
share, the mapped drive may be disconnected after a regular interval
of inactivity, and Windows Explorer may display a red "X" on the icon
of the mapped drive. However, if you try to access or browse the
mapped drive, it reconnects quickly.
To avoid this behavior use the following command:
net config server /autodisconnect:-1
Explanation of Microsoft on this topic:
https://support.microsoft.com/da-dk/help/297684/mapped-drive-connection-to-network-share-may-be-lost