Reading/Writing files using nothing but a handle - c++

A question came up at work where I am not sure of the answer. Suppose there is a handle, within a process, to a directory. The handle has RW set and lets say it points to the desktop. Is there a way to use nothing but the handle in order to read or write files to the desktop?
Thanks for any ideas!
Edit: To clarify, this is on Windows and is a File handle pointing at the desktop. Lets assume you already know the value of the handle and are looking to use it within the same process in order to read/write files to the desktop that it points at. Any code is allowed, including the Windows API.

You can use GetFinalPathNameByHandle() on the directory handle to obtain the pathname, append the file you want to write onto the end of it, then use CreateFile() as normal.

Standard C and C++ have no notion of a directory, and thus the strict answer is no.
To say anything more, we need more information. What do you mean by a handle? What are the platforms/libraries you are allowed work with?
Also, it's not clear what you mean by "nothing but the handle." Functions are not the handle; are you allowed to call functions?

Related

Are FindFirstFile, FindNextFile APIs unreliable?

For my purpose I was looking to optimize ways of recursively enumerating subfolders from a given folder on the NTFS file system on Windows, and I came across this little "gem" from the Microsoft's page for the FindFirstFile API:
Note In rare cases or on a heavily loaded system, file attribute
information on NTFS file systems may not be current at the time this
function is called. To be assured of getting the current NTFS file
system file attributes, call the GetFileInformationByHandle function.
So, let me try to understand it.
I do rely on the dwFileAttributes parameter returned in the WIN32_FIND_DATA struct to tell a file from a folder. So what this note suggests is that in some cases I might get some bogus result, right? If so, why not fix it in one of their updates instead of posting it here?
And also their suggested workaround of using GetFileInformationByHandle API. How exactly am I supposed to call it? It takes a file handle. So do they really want us to open each file that the FindNextFile returns and call GetFileInformationByHandle on it? Can you imagine "how far" my optimization would go with such approach?
Anyway, it'd be nice if someone could shed some light on this...
Distinguishing a file from a folder will be OK, because that information is likely to be constant. Files aren't being turned into folders or folders into files.
The documentation says "may not be current" because other processes may be changing attributes, and without a locking mechanism to synchronize the attributes are being written lazily. If your application requires absolutely current info, you retrieve it ...ByHandle which insures that the information is current.
This is the way every status-reporting function works. At best, it reports the status at some undefined point in-between when you called the function and when the function returned. But it doesn't "freeze the world" to ensure that the data is still valid later.
Rather than noting this on every single function, documentation typically only notes it on functions that tend to lead to severe problems, particularly security problems, when this is not taken into account.
If you open a file and get a handle to it, you are assured that all your operations using that handle will be to the same underlying file. But when you perform operations by name, there is no such assurance. Files can be created, deleted, and renamed. So the same name may not later refer to the same file.
dwFileAttributes is not something that is going to be unreliable when it comes to telling the difference between files and folders. I think that note is referring to information that might be cached for update by the file system (modified/accessed timestamps, etc) but whether an item is a file or a folder is not something that is going to change.

how to make sure that a file will be closed at the end of the run

Suppose someone wrote a method that opens a certain file and forgets to close it in some cases. Given this method, can I make sure that the file is closed without changing the code of the original method?
The only option I see is to write a method that wraps the original method, but this is only possible if the file is defined outside the original method, right? Otherwise it's lost forever...
Since this is C++, I would expect that the I/O streams library (std::ifstream and friends) would be used, not the legacy C I/O library. In that case, yes, the file will be closed because the stream is closed by the stream object's destructor.
If you are using the legacy C API, then no, you're out of luck.
In my opinion, the best answer to an interview question like this is to point out the real flaw in the code--managing resources manually--and to suggest the correct solution: use automatic resource management ("Resource Acquisition is Initialization" or "Scope-Bound Resource Management").
You are correct that if the wrapper doesn't somehow get a reference to the opened file, it may be difficult to close it. However, the operating system might provide a means to get a list of open files, and you could then find the one you need to close.
However, note that most (practically all) operating systems take care of closing files when the application exits, so you don't need to worry about a file being left open indefinitely after the program stops. (This may or may not be a reasonable answer to the question you were given, which seems incredibly vague and ambiguous.)
If you are using C function for file open, you can use _fcloseall function for closing all the opened files.
If you are using C++, Like James suggested, stream destructor should take care of it.
Which environment are you in? You can always check the file descriptors opened by the process and close them forcefully.
Under linux you can use the lsof command to list open files for a process. Do it once before the method and once after the method to detect newly opened files. Hopefully you aren't fighting some multithreaded legacy beast.

How to create a virtual file?

I'd like to simulate a file without writing it on disk. I have a file at the end of my executable and I would like to give its path to a dll. Of course since it doesn't have a real path, I have to fake it.
I first tried using named pipes under Windows to do it. That would allow for a path like \\.\pipe\mymemoryfile but I can't make it works, and I'm not sure the dll would support a path like this.
Second, I found CreateFileMapping and GetMappedFileName. Can they be used to simulate a file in a fragment of another ? I'm not sure this is what this API does.
What I'm trying to do seems similar to boxedapp. Any ideas about how they do it ? I suppose it's something like API interception (Like Detour ), but that would be a lot of work. Is there another way to do it ?
Why ? I'm interested in this specific solution because I'd like to hide the data and for the benefit of distributing only one file but also for geeky reasons of making it works that way ;)
I agree that copying data to a temporary file would work and be a much easier solution.
Use BoxedApp and do not worry.
You can store the data in an NTFS stream. That way you can get a real path pointing to your data that you can give to your dll in the form of
x:\myfile.exe:mystreamname
This works precisely like a normal file, however it only works if the file system used is NTFS. This is standard under Windows nowadays, but is of course not an option if you want to support older systems or would like to be able to run this from a usb-stick or similar. Note that any streams present in a file will be lost if the file is sent as an attachment in mail or simply copied from a NTFS partition to a FAT32 partition.
I'd say that the most compatible way would be to write your data to an actual file, but you can of course do it one way on NTFS systems and another on FAT systems. I do recommend against it because of the added complexity. The appropriate way would be to distribute your files separately of course, but since you've indicated that you don't want this, you should in that case write it to a temporary file and give the dll the path to that file. Make sure you write the temporary file to the users' temp directory (you can find the path using GetTempPath in C/C++).
Your other option would be to write a filesystem filter driver, but that is a road that I strongly advise against. That sort of defeats the purpose of using a single file as well...
Also, in case you want only a single file for distribution, how about using a zip file or an installer?
Pipes are for communication between processes running concurrently. They don't store data for later access, and they don't have the same semantics as files (you can't seek or rewind a pipe, for instance).
If you're after file-like behaviour, your best bet will always be to use a file. Under Windows, you can pass FILE_ATTRIBUTE_TEMPORARY to CreateFile as a hint to the system to avoid flushing data to disk if there's sufficient memory.
If you're worried about the performance hit of writing to disk, the above should be sufficient to avoid the performance impact in most cases. (If the system is low enough on memory to force the file data out to disk, it's probably also swapping heavily anyway -- you've already got a performance problem.)
If you're trying to avoid writing to disk for some other reason, can you explain why? In general, it's quite hard to stop data from ever hitting the disk -- the user can always hibernate the machine, for instance.
Since you don't have control over the DLL you have to assume that the DLL expects an actual file. It probably at some point makes that assumption which is why named pipes are failing on you.
The simplest solution is to create a temporary file in the temp directory, write the data from your EXE to the temp file and then delete the temporary file.
Is there a reason you are embedding this "pseudo-file" at the end of your EXE instead of just distributing it with our application? You are obviously already distributing this third party DLL with your application so one more file doesn't seem like it is going to hurt you?
Another question, will this data be changing? That is are you expecting to write back data this "pseudo-file" in your EXE? I don't think that will work well. Standard users may not have write access to the EXE and that would probably drive anti-virus nuts.
And no CreateFileMapping and GetMappedFileName definitely won't work since they don't give you a file name that can be passed to CreateFile. If you could somehow get this DLL to accept a HANDLE then that would work.
And I wouldn't even bother with API interception. Just hand the DLL a path to an acutal file.
Reading your question made me think: if you can pretend an area of memory is a file and have kind of "virtual path" to it, then this would allow loading a DLL directly from memory which is what LoadLibrary forbids by design by asking for a path name. And this is why people write their own PE loader when they want to achieve that.
I would say you can't achieve what you want with file mapping: the purpose of file mapping is to treat a portion of a file as if it was physical memory, and you're wanting the reciprocal.
Using Detours implies that you would have to replicate everything the intercepted DLL function does except from obtaining data from a real file; hence it's not generic. Or, even more intricate, let's pretend the DLL uses fopen; then you provide your own fopen that detects a special pattern in the path and you mimmic the C runtime internals... Hmm is it really worth all the pain? :D
Please explain why you can't extract the data from your EXE and write it to a temporary file. Many applications do this -- it's the classic solution to this problem.
If you really must provide a "virtual file", the cleanest solution is probably a filesystem filter driver. "clean" doesn't mean "good" -- a filter is a fully documented and supported solution, so it's cleaner than API hooking, injection, etc. However, filesystem filters are not easy.
OSR Online is the best place to find Windows filesystem information. The NTFSD mailing list is where filesystem developers hang out.
How about using a some sort of RamDisk and writing the file to this disk? I have tried some ramdisks myself, though never found a good one, tell me if you are successful.
Well, if you need to have the virtual file allocated in your exe, you will need to create a vector, stream or char array big enough to hold all of the virtual data you want to write.
that is the only solution I can think of without doing any I/O to disk (even if you don't write to file).
If you need to keep a file like path syntax, just write a class that mimics that behaviour and instead of writing to a file write to your memory buffer. It's as simple as it gets. Remember KISS.
Cheers
Open the file called "NUL:" for writing. It's writable, but the data are silently discarded. Kinda like /dev/null of *nix fame.
You cannot memory-map it though. Memory-mapping implies read/write access, and NUL is write-only.
I'm guessing that this dll cant take a stream? Its almost to simple to ask BUT if it can you could just use that.
Have you tried using the \?\ prefix when using named pipes? Many APIs support using \?\ to pass the remainder of the path directly through without any parsing/modification.
http://msdn.microsoft.com/en-us/library/aa365247(VS.85,lightweight).aspx
Why not just add it as a resource - http://msdn.microsoft.com/en-us/library/7k989cfy(VS.80).aspx - the same way you would add an icon.

Implementing a File Object (C++)

I've been looking over the Doom 3 SDK code, specifically their File System implementation.
The system works (the code I have access to at least) by passing around an 'idFile' object and I've noticed that this class provides read and write methods as well as maintaining a FILE* member.
This suggests to me that either the FILE* is 'opened' with read and write access or the file is closed and reopened (with the appropriate access) between calls to Read() and Write().
Does this sound correct or am I over simplifying it?
If this isn't the case (which part of me suspects it isn't - due to speed etc.) does anyone have any suggestions as to how they would achieve this elegant interface?
Please bare in mind that I am fairly new to both C++ and stdio (which I'm pretty sure iD favours).
You can open a FILE* in read-write mode.
If you do that, you should flush and seek to a known location when changing between reading and writing, but you don't have to reopen the file.
Without ever having looked at the Doom code (I'm guessing you can specify a mode when you create the object), you can use freopen() to re-open a file (in a different mode, if you want) without closing it first.

Shell Extension - Virtual File Creation

I want to create a file that only resides in memory... In looking through some documentation I saw a recommendation to use a shell extension as a virtual file. Im not sure that is a workable solution but I would like to know
Is it a good approach (or should I be using a ramdisk instead)
Where is a good place to start to read up on it
Note: This is on the Windows platform
As I understand, you want your program to create a "file", which resides only in memory and that you can pass on to another external program (say, Microsoft Word).
AFAIK this is not possible, short of a ramdrive. I'd suggest using a temporary folder. You will however have to come up with a strategy for deleting the file when it's not needed anymore.
Added: On second though, you might want to check out Reparse points. I'm not familiar with them myself, and they will only work for NTFS formatted disks, but perhaps they can provide you with what you want. It will be a lot of coding though.
You don't say on which plateform you are but I'm guessing Windows. Is mmap() available? If not, I think BerkeleyDB has been ported to Windows so you should be able to use that. Win32 API may have something akin to mmap() but I don't know it.
If you want a file that resides only in memory, use a named pipe or something, though I question your scenario - can you go up a level and describe what you want to do?