SHILCreateFromPath substitution in Win7? - winapi

The shell.SHILCreateFromPath function creates a pointer to an item identifier list (PIDL) from a path.
As noted in the MSDN Dev Center, the function is deprecated and the support ends with Windows XP.
What is the substitution in Windows 7?

Use the SHParseDisplayName function.

Related

Detect Windows version on Delphi 2007 with no APIs

Simple question : how to detect Windows version in a reliable way using Delphi 2007 ? Is there a way to do it without APIs ie, checking only some folder or files in system directory ?
Thanks in advance !
You cannot check a file or registry value without calling a Windows API function!
The only way to check the version without calling any API is to read from the PEB but most of the fields there are undocumented and could in theory change from version to version. It is also affected by the compatibility shims. I don't recommend that you do this but if you insist then this code might be a good starting point, just read the OSMajorVersion and OSMinorVersion members (Teb from GetTeb and Peb := Teb.Peb from Teb).
Microsoft recommends that you check if the feature you need exists instead of checking the version. The recommended way to check the version is with VerifyVersionInfo but you can still continue to use the deprecated GetVersionEx if you need the version number for display purposes. Both of these functions require a manifest to get the correct version on Windows 8.1 and 10.
In theory you can parse EXPLORER.EXE for its version details and then speculate on the Windows version. But every Delphi version uses for Pascal's blockread() implementation the WinApi again. And wanting tofind the Windows-directory (which can have any name on any drive) also leads to WinApi calls again.

What happens when "file_with_invalid_chars:<?>.txt" is passed to the MFC CFile class?

Note: Needed to edit the title and question, as initially I thought the problem is with ::CreateFile[W] - but it turns out, the error only happens on XP when I use MFC's Cfile class.
I am slightly confused by the behaviour of CFile::Open(...) (on Win7/64bit) when I pass the filename file_with_invalid_chars:<?>.txt to this function to request creation of the file.
On my Windows XP box, the call fails.
On my Win7/64 box, the call succeeds, creating a file named file_with_invalid_chars.
What's happening?
I'm guessing it's creating an alternate data stream. Seems odd that it would fail on XP, though. The documentation says that characters legal for a file name are also legal for a stream name, though I guess that doesn't necessarily mean the inverse is true. Maybe Windows 7 supports < and > in stream names and Windows XP doesn't.
It turns out that this is due to a bugfix(?) in shlwapi.dll -
MFC's CFile class does some internal processing on the filename, and happens to call the PathStripToRoot Function.
This function resides in Shlwapi.dll and Win7 is shipped with a newer version than Windows XP.
The Version in Windows XP apparently does not work correctly with file-paths containing ADS colon separated stream names.
Example:
On XP PathStripToRoot(L"C:\\temp\\file.txt:stream");yields the string C:\temp\file.txt: which is incorrect and leads to an error return from CFile::Open
On Win7, the same call yields the actual root C:\.

IShellExecuteHook.Execute

Can someone show me how to use "IShellExecuteHook.Execute" in Delphi please?
info: IShellExecuteHook::Execute Method
Description:
This method is called any time the ShellExecute or ShellExecuteEx functions are
called. This happens when a file is double-clicked in Explorer or when the Run dialog
box is used.
Thanks.
The following EDN link looks like it will give you what you need: How to hook ShellExecute calls (IShellExecuteHook)
Be aware that it won't work in 64 bit Windows because that requires 64 bit shell extensions and because Delphi only produces 32 bit images you would need to use a different language. I also note that IShellExecuteHook is deprecated as of Vista.

how to call different Win API based on Windows version?

The specific problem is, the support of condition variable on Windows begins from Vista, for early version of Windows (Windows XP), I have a emulated condition variable code sort of solved the problem. However, I'd like to have the ability to call native condition variable API when the system supported and fallback to my version only on XP and earlier version. I tried to detect windows version with GetVersionInfo API, but it still gives me error on start time (cannot find API entry of InitializeConditionVariable sort of).
I am not familiar with Windows programming, how do you solve the gentle fallback problem nicely?
if you want to call a function that may or may not exist depending on platform version then use dynamic loading
LoadLibrary and GetProcAddress
These will tell you if the entry point exists and then let you call it if it does

How can I get a list of all open named pipes in Windows?

Is there an easy way to test whether your named pipe is working correctly? I want to make sure that the data I'm sending from my app is actually being sent. Is there a quick and easy way to get a list of all the named pipes?
In the Windows Powershell console, type
[System.IO.Directory]::GetFiles("\\.\\pipe\\")
If your OS version is greater than Windows 7, you can also type
get-childitem \\.\pipe\
This returns a list of objects. If you want the name only:
(get-childitem \\.\pipe\).FullName
In Powershell 7, the second example \\.\pipe\ does not work (see this known bug), so you will have to stick to the first syntax.
You can view these with Process Explorer from sysinternals. Use the "Find -> Find Handle or DLL..." option and enter the pattern "\Device\NamedPipe\". It will show you which processes have which pipes open.
Try the following instead:
String[] listOfPipes = System.IO.Directory.GetFiles(#"\\.\pipe\");
Use pipelist.exe from Sysinternals.
I stumbled across a feature in Chrome that will list out all open named pipes by navigating to "file://.//pipe//"
Since I can't seem to find any reference to this and it has been very helpful to me, I thought I might share.
C#:
String[] listOfPipes = System.IO.Directory.GetFiles(#"\\.\pipe\");
At CMD prompt:
>ver
Microsoft Windows [Version 10.0.18362.476]
>dir \\.\pipe\\
The second pipe was interpreted by this web site when submitted... You need two backslashes at the beginning. So make sure to use System.IO.Directory.GetFiles(#"\\.\pipe\").
Note that I have seen this function call throw an 'illegal characters in path.' exception when one of the pipes on my machine had invalid characters. PipleList.exe worked ok though, so it seems like a bug in MS's .NET code.

Resources