Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does SHLoadIndirectString() work internally?

I have been trying to get display names (user friendly name of an application) of all UWP applications installed on a system from a desktop application. I am trying to use SHLoadIndirectString() on the resource string obtained from the registry entry corresponding to those apps. Let us take the case of windows calculator.

SHLoadIndirectString() Usage

It's resource string can be obtained from HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\‌​Repository\Packages\‌​Microsoft.WindowsCal‌​culator_10.1705.1301‌​.0_x64__8wekyb3d8bbw‌​e\DisplayName registry entry. The resource string on my system for it is @{Microsoft.WindowsCalculator_10.1705.1301.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.WindowsCalculator/Resources/AppStoreName}

To get the display name I would do SHLoadIndirectString(@{Microsoft.WindowsCalculator_10.1705.1301.0_x64__8wekyb3d8bbwe?ms-resource://Microsoft.WindowsCalculator/Resources/AppStoreName}).

Experimental observation

  1. (Experiment 1) I used SHLoadIndirectString() for two different users (U1, and U2). U1's language was set to english, U2's language was set to french (FR-fr). When SHLoadIndirectString() was run from U1 it returned Windows Calculator, and for U2 I got Calculatrice Windows. Thus the value returned for the same resource string depends on language setting of current user.
  2. (Experiment 2) I installed a UWP app in U2, and did SHLoadIndirectString() to the resource string in DiplayName. I got error in U1, but in U2, it gave me the required string correctly.
  3. (Experiment 3) When I added path to resource file (resources.pri), to resource string, I got no error in U1. The resource string earlier was @{DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar_5.1.12.0_x64__3nf5xjt6s13jt?ms-resource://DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar/Resources/AppName}, which I later modified to @{C:\\Program Files\\WindowsApps\\DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar_5.1.12.0_x64__3nf5xjt6s13jt\\resources.pri?ms-resource://DJiT.edjing-DJmixerconsolestudio-PlayMixRecordShar/Resources/AppName} before passing to SHLoadIndirectString().

Finding solutions

  1. SHLoadIndirectString()'s documentation says that its returned value depends on Shell environment or ResourceContext, without giving much details for each.
  2. Two projects which try to re create windows NT API to run windows applications are ReactOS and wine. I looked through their source code to find implementation of SHLoadIndirectString(), but all that the codes seems to do is to do a LoadLibrary() on the resource string, after removing the @ symbol at the beginning. This doesn't make any sense, why would there be such a dll in a system, as the resource string for every app is different?

    • SHLoadIndirectString() implementation in ReactOS
    • SHLoadIndirectString() implementation in wine
like image 763
Sahil Singh Avatar asked Sep 01 '17 17:09

Sahil Singh


1 Answers

From Windows XP to Windows 7 SHLoadIndirectString only used LoadLibrary with the @filename.dll,resource syntax documented on MSDN. The MUIVerb entry for file type registrations is perhaps the most common usage seen in the wild.

In Windows 8 it was extended to support other sources, specifically .PRI files (Package Resource Index) used by WinRT/Modern/Store apps.

To find out exactly how it works you can single-step it in a debugger but these implementation details are not something you should depend on, you should only use the documented API.

On Windows 8 it uses various functions in MrmCoreR.dll (mrmcorer!Microsoft::Resources::Runtime::CResource*) to extract the package name, then it builds a path with KERNEL32!PackageIdFromFullName+KERNEL32!GetPackagePath+"\resources.pri" and then it calls Bcp47Langs!Windows::Internal::CLanguagesListFactory::GetUserLanguages to get a list of preferred languages. It then builds a string from the path (it converts \ to %5) so it can check if the resource string is cached under HKCU\Software\Classes\Local Settings\MrtCache. If not it reads the string with the resource manager. The exact details of how a ResourceContext works (language, DPI scale etc.) and how it finds the true source from the .pri file is probably out of scope for this question and a much larger topic in itself.

like image 133
Anders Avatar answered Oct 05 '22 23:10

Anders