Retrieving a long path from "\Device\HarddiskVolume1\Progra~1" - windows

I'm writing a ProcessExplorer-like tool that shows all open files in the system.
Calling the NtQueryObject(,ObjectNameInformation,,,) gives me a path that looks like \Device\HarddiskVolume1\Users\ADMINI~1\AppData\Local\Temp\FXSAPIDebugLogFile.txt, so it is an NT device path that sometimes has shortened segments (ADMINI~1 in this case).
I don't really need to convert this path to a "standard" one (like C:\Users), but I need to expand it to a long form, so it should look like \Device\HarddiskVolume1\Users\Administrator\AppData\Local\Temp\FXSAPIDebugLogFile.txt. Besides, converting a device path to a standard one won't even be possible if the volume doesn't have a mountpoint.
I need a solution that works from Windows XP onwards.
Unfortunately, the most obvious method - using the GetLongPathNameW function doesn't work with a path like this, it returns a ERROR_INVALID_NAME for a path like this.
I tried different path prefixes: \\?\, \\.\, \??\, \\.\GLOBALROOT\ - none of this helped.
FindFirstFileW also doesn't accept a path like this on Vista.
It's strange, because the CreateFile function works with a \Device\HarddiskVolume path just fine.
Also I found, that if I remove the Device word from the path, making it \\.\HarddiskVolume1\Users\ADMINI~1\AppData\Local\Temp\FXSAPIDebugLogFile.txt, the GetLongPathNameW actually returns a correct long path. Unfortunately, this doesn't work on Windows XP/Vista.
I'd like to know if there is another method, that will work on Windows XP too.

Related

Is it allowed to pass paths as URLs to Media Foundation?

Passing standard Windows file paths like C:\Foo\Bar.mp4 to methods like IMFSourceResolver::CreateObjectFromURL() works fine here but I'm wondering if this is allowed because, strictly speaking, C:\Foo\Bar.mp4 is not a URL. It would probably have to be translated into something like file:///C:/Foo/Bar.mp4 in order to qualify as a URL.
Still, for simplicity's sake, I'm wondering if simply passing a path name is ok as well or is this something that just happens to work but should rather be avoided?
I'm wondering if simply passing a path name is ok as well or is this
something that just happens to work but should rather be avoided?
No, this is not an accident.
From IMFSourceResolver::CreateObjectFromURL,
For local files, you can pass the file name in the pwszURL parameter; the file: scheme is not required.
Note : This method cannot be called remotely.

What does "\\?\" means before a path?

I'm having a look at the code of FastCopy, where I want to add a few features.
Internally, it seems that FastCopy stores its paths with a \\?\ before the path. eg. \\?\c:\Program Files\Adobe. These paths are passed on directly to Windows API functions like DeleteFile, RemoveDirectory, etc. so it seems Windows understands the format.
But what do these extra characters mean and why do FastCopy stores them that way?
The thing that's probably most relevant for FastCopy is that it allows you to work with file names more than ~256 characters long.
If memory serves, it also prevents Windows from parsing a file name looking for things like \\server\file to access a shared file (though you can still use \\?\UNC\whatever), but that's probably not what's really intended/relevant here.
You are referring to Long UNC paths : https://en.wikipedia.org/wiki/Path_%28computing%29 Hope that helps.
Generally that means it's supporting long file names - names up to about 32K in length.
It can also be used to specify UNC paths, e.g. \\?\UNC\server\share.
Without that support Fastcopy wouldn't be able to access all files properly.
More detail at http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx

Rename file in Win32 to name with only differences in capitalization

Does anyone know a pure Win32 solution for renaming a file and only changing its capitalization, that does not involve intermediate renaming to a different name or special privileges (e.g. backup, restore).
Since the Win32 subsystem generally regards two file names differing only in capitalization as the same, I haven't been able to find any solution to the problem.
A test program I made with the MoveFile API seems to work. So does the rename command in cmd.exe. What have you tried, and what error are you getting?
This isn't relevant, but further testing shows that renaming a long filename in this way works but will change the short filename (alternating between ~1 and ~2 for example), incidentally.
Just use the normal MoveFile API. That call probably just turns into ZwSetInformationFile(..., FileRenameInformation,...) The docs for FILE_RENAME_INFORMATION states that you need DELETE access and the file can't be locked etc, but those restrictions will probably apply to other solutions also.
I do not believe there is a way to expose two files with identical names that differ only in spelling to the Win32 subsystem. Even if some how you were able to create these files, the most likely result would be that only one file would be accessible - defeating the purpose of staying soley in Win32.
If you want to go into the Native layer, you can create a file with NtCreateFile and InitializeObjectAttributes w/o OBJ_CASE_INSENSITIVE or you can pad the end with extra spaces (if you pad with extra spaces, the file will not be accessible from Win32 dos paths). See here: http://www.osronline.com/ddkx/kmarch/k109_66uq.htm . I'm pretty sure you were already aware but I included it incase you did not know.
So long as your file is not immediately needed by another program, you can use my solution.
When you rename the file, capitalize, and delete the last letter. Then rename again and return the letter.
:)

Registry does not like long filename for shell commands or verbs

(if not applicable to SO, please refer to another appropriate place, thanks).
When using the registry to associate file extensions and application, I put in the full filename of my application, but that does not work well, only if I use the 8.3 filename.
for example ( taken from the registry) this works:
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\command]
#="C:\\my\\path\\bin\\Debug\\bin\\myexe_~1.EXE /dde"
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\ddeexec]
#="[myVerb(\"%1\")]"
but this does not work :
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\command]
#="C:\\my\\path\\bin\\Debug\\bin\\myexecutable.EXE /dde"
[HKEY_CLASSES_ROOT\Toto.Document\shell\myVerb\ddeexec]
#="[myVerb(\"%1\")]"
The action is called by right-clicking on the file in Explorer, I get the error :
"Windows cannot find 'c:\users\me\desktop\tata.toto'. Make sure you typed the name correctly, and then try again".
I'm creating the keys programatically with CRegKey and using GetModuleFileName to get the application path.
2 questions :
- I'm probably missing something in my registry entry ? (i've tried quoting the paths, but does not work)
- Can I get the "short" filename ? (searching a little bit seems that GetShortPath should work, but not always!)
Thanks.
Max.
(edit 22/03/2011)
I tried using quotes but it did not work (with /dde)
I decided to use normal parameters instead of /dde and it seems to work nicely with the normal path (not shortened like stated above).
I'm still not certain why when creating a simple MFC SDI project it will write out registry values with the old short name instead of the long name.
Thanks again.
Max.
Try creating the key with another couple of double-quotes (note between .EXE and /dde:
#="C:\\my\\path\\bin\\Debug\\bin\\myexecutable.EXE" "/dde"

Absolute path from window handle

I open a file in windows word and get a handle to the window. Can I get the absolute path of the file (the actual .doc file, not the winword.exe)?
Thanks a lot
You certainly won't be able to do this direct from the Windows API (where a program's document is stored and how it is manageded is not controlled / constrained by the Windows API)...
What you might be able to do is use the Word libraries to iterate through open documents and look for the document with a matching handle, but I doubt this will be simple - I'm not even sure if it will be possible...
Martin.

Resources