Solved Global DPI Scaling Disable for Win8.1 for all files/users

aph

Member
Member
Messages
47
Get WinXP DPI Scaling (No More Blur) in Win8.1 w/ Registry

Update 1/19: This thread seems to live on, so to summarize: what “DPI Disable.reg” does is add a right click context menu entry to .exe files to "Disable DPI scaling", which is equivalent to clicking (Properties) -> (Compatibility) -> (Disable display scaling) on high DPI.

Relative to other methods, this is the least intrusive thing that always seems to work--the only case where it doesn't that I've seen is on some files flagged as protected in the Windows folder.

The result is to mark the app as DPI-capable and allow it to scale using its own WMF methods, as opposed to the 8.1 way which makes everything big but also often adds a blurry looking effect to the upscaled window. This marks the app as capable of doing its own scaling even if it is not marked that way in its application manifest (an internal list of specs and functions that are part of the app.)

Besides DPI Disable.reg, I’ve attached a more powerful, but less reliable method to this update named "DPI Fix.reg". It doesn't always work, but when it does it prevents from having to manually add files to the high-DPI-capable list. I've seen best results when using right after a fresh install, and apparently getting similar results after deleting the AppCache value under the AppCompat key. I didn't bother to track down the exact cause/effect relationship once apps started behaving the way I wanted.



Update 9/10:
Funny how this thread is getting responses 4 months later. I solved it and hadn't looked back, but the first part had mixed up the keys for environment variables and compatibility layers. Here's my all in one solution:

Code:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Environment]
"__COMPAT_LAYER"="HighDpiAware"


[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
"__COMPAT_LAYER"="HighDpiAware"


[HKEY_USERS\.DEFAULT\Environment]
"__COMPAT_LAYER"="HighDpiAware"


[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
@="^ HIGHDPIAWARE"
"C:\\Windows\\explorer.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\userinit.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\wininit.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\winlogon.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\smss.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\cmd.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\csrss.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\runonce.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\services.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\mmc.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\svchost.exe"="^ HIGHDPIAWARE"


[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
@="^ HIGHDPIAWARE"
"C:\\Windows\\explorer.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\userinit.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\wininit.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\winlogon.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\smss.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\cmd.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\csrss.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\runonce.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\services.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\mmc.exe"="^ HIGHDPIAWARE"
"C:\\Windows\\System32\\svchost.exe"="^ HIGHDPIAWARE"
That's it! Stop reading here. :busted:

Now you did it. There's a whole bunch of reasons this works that spans acronyms long enough to build a bridge with. It's components, managed assemblies, common runtimes, manifest preference, policy merging, environment inheritance, process invocation.... or if you prefer your acronyms: COM, GAC, MSIL, NI's, CLR, DCOM, PCA, MSDT, EDB and all their struts like XML serializers that keep track of this stuff. This is a sledgehammer that puts them to rest.

This is really where you should stop reading. If you continue past this point and apply the settings to you graphics adapters, those will work, but you may get all sorts of out of range memory issues. Like hitting PrtScr and your computer freezing. I was desperate and crossed the line there, but am leaving the info for reference. The reg fix above is safe and works.

Update 5/18: Done and down to 2 keys that worked across a number of computers. There are a few tricks to make sure you don't have to do extra work or restore to get scaling unlocked if you don't follow them.

This is all from a clean install so if you have enabled "one size for all displays, roll that back first. If you've tweaked the settings a lot (ex: 200% with the slider, applied, then switched to checkbox and typed 200%), do each of those with logoff/on in between. When done, a restart/reboot is required to commit the changes.

After you're back in there are just 2 steps. If you don't reboot there is a higher risk of the set getting flagged for out of spec values. Windows does a sanity check as well as a bunch of recursion and cycle checks across many keys in the registry, but only does a full reparse on a restart. Then it prioritizes the last known good configuration over any other, even if it the values seem out of range.

Step 1. Make a new string in HKLM and set it to:

[HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"__COMPAT_FLAGS"="HighDpiAware"


Step 2. Change the key 00 (and 01 for monitor 2, etc.) to its current value, usually from 4 to 16 like so:
(I've only seen 4 but can vary according to msdn):

[HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\[ABC...]\00\0#]
"Scaling"="16"


There should only be one [ABC...] key representing your display adapter. I have 2 because I've been messing with the keys and Windows has been putting me back in my spot. But after many attempts I've got it nailed down:

Step 3. Make sure you log in/log out at least once before restarting.

That's to to commit the current control set as a known working one before Windows has a chance to evaluate it for compatibility. Wait a few minutes (the timer is 20000 but I'm not sure what that specifies, presumably it's around 5 min 20 sec) and log off/on it again just to make sure.

That should be it. After restarting and making sure everything sticks, you can change other keys as needed to adjust from the base of 150%. Changing other keys is not necessary in most cases, 200% is too big and themes/visual styles still adhere to the 120/144 ppi spec or 125%/150% scaling.

Also this gives you Win8-style scaling. That's the environment key at work in a backwards way, by applying the scaling outside of your user context and having it scale back up as though on another display. Hence the note to go back to defaults and reboot first.

If you get blurry desktop apps or any other results let me know. I have many other variables that may be getting cycled back into the environment but the session manager is the top level key of the internal undocumented variable passed internally, and it seems to do the trick. Let me know if you have trouble.

More screens when it's not 3am, but here's one I have with the key:

HKLM_Scaling.png

Ignore the 8 as this was a test, it should be 16. Here's key #2 from another test (X's here mean ignore, not remove/replace):

HKLM_Flags.png

Tried this on 3 fairly different computers, Acer laptop with Intel HD4000, custom desktop with ATI 5570 and Dell Inspiron with nVidia 8600M) so should not be hardware specific.

If you get throttled there are a few dozen registry keys waiting for you to clean up that even the system user (above administrator) can't access. I guess I could put to make a restore at the top but I'll come back to it since it could give the impression any of this is unsafe when it's just Windows winding back a hardware-level hack that can't hurt.

Follow-up: If it scales but blurry, this key overrides the override of the variable the other key set:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Windows\\explorer.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\explorer.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\runonce.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\mmc.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\cmd.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\conhost.exe"="~ HIGHDPIAWARE"
"C:\\Windows\\System32\\svchost.exe"="~ HIGHDPIAWARE"

That key is always parsed so it sticks as a HKLM reg key, and since also results in an env var being set, gets passed down to child processes in case they don't do their own parsing.

If needed it can also be added to HKCU (same subkey) and HKU\S-5-1-18 if you want HKCU's equivalent for the system user (if you use psexec or nircmd)
View attachment DPI Fix.reg

Update 5/12: Done! Before and after:

PrtScr capture_8.png
PrtScr capture_10.png

Non-8.1 users won't see a difference as they haven't been dealing with what is the norm in Win8.1, next screenshot. "Blurry" sounds like almost too nice a word:

Resource Hacker.png - Pictus_2.png

Fixes are available as far as I've found and gathered to this point, for individual files. They can be automated, but not a system-level fix that's a once-and-forget. That is what the goal is here, and it's without to any specific exe. Sorry wasn't taking too many when things were that hard to read. :)

Now I'll test this and pull out the parts that are needed and clean out the ones that aren't. It's been many tries but ended up i nthe same place I started, the PCW changing SMI settings applied to the CLR's...

Now that there is some room to work with I can put back the font rasterizer I was using and try out an auto hinting tool I just came across. I think MacType was mentioned once on this forum but without good examples you can't really see the difference. Here are some from a few months ago:

neue.png

That's Mactype (no DPI change here, getting rid of blur was with the REG script attached.)

I ran this really quick conversion on ttfautohint's default settings:

Helvetica Neue LT Com 45 Light (OpenType) _2.png

Big benefit from a 1-time change, as MacType is easy on the eyes but caches all those characters as bitmaps.

As far as DPI is concerned I'll put a new reg script together. For now moving everything old further down and just leaving the older script up until I've got the new one ready and ironed out.





Alternative REG script for Disable DPI Scaling option in right click context menu

Before this tweak I was using this script to make DPI management easier in Win8.1. I tried to make it as fast and clean as possible and it works pretty well. Unfortunately they did seem to snap back once in a while bcause eventually some parameter of the app would change and the flag would have to be set again.

However if you use an HTPC or have aQH+ display you might prefer this. Feel free to use it if you don't need a system wide change, otherwise global" one is probably what you're looking for. Here is the old script:

Code:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\exefile\shell\disabledpi]
@="Disable DP&I Scaling"

[HKEY_CLASSES_ROOT\exefile\shell\disabledpi\command]
@="cmd /c @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%1\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\">nul"
"IsolatedCommand"="cmd /c @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%1\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\">nul"

[HKEY_CLASSES_ROOT\Msi.Package\shell\disabledpi]
@="Disable DP&I Scaling"

[HKEY_CLASSES_ROOT\Msi.Package\shell\disabledpi\command]
@="cmd /c @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%1\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\">nul"
"IsolatedCommand"="cmd /c @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%1\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\">nul"

[HKEY_CLASSES_ROOT\Directory\shell\disabledpi]
@="Disable DP&I Scaling"
[HKEY_CLASSES_ROOT\Directory\shell\disabledpi\command]
@="cmd /c @start /min cmd /c for /f \"usebackq delims=\" %%i in (`dir /b /s \"%1\\*.exe\" \"%1\\*.msi\"`) do @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%%i\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\""
"IsolatedCommand"="cmd /c @start /min cmd /c for /f \"usebackq delims=\" %%i in (`dir /b /s \"%1\\*.exe\" \"%1\\*.msi\"`) do @reg add \"HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers\" /v \"%%i\" /f /t REG_SZ /d \"~ HIGHDPIAWARE\""

This was still annoying because I have symlinks/directory junctions that create several paths to a single file, often change folder names to organize apps especially in my Dropbox, and will sometimes first run a program in a sandbox to make sure it doesn't do anything bad to my computer, then run it again outside the sandbox.

In all those cases the app would snap back to being blurry and the script only helps by greatly reducing clicks and travel. The better solution will be posted soon, just so I don't mess up your systems :). In the meantime this reg should tide things over:
 

Attachments

  • Disable DPI.reg
    1.7 KB · Views: 766
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Everything below is old, leaving it up in case someone searches. I didn't come up with anything at the time

In hindsight the following rollback was likely caused by editing a reparse point directly and breaking the symlinks in the registry, unaware there was such a thing. Regedit doesn't know that data type, so it looks like a normal string (reg_sz)



EDIT 2: I haven't seen registry changes get rolled back on their own before without a Last Known Good recovery triggered by a bad boot so that may be what happened. The very first thing I noticed had changed was my WindowMetrics fonts, back to Arial which I haven't used in a long time. A RegScanner report shows those changes were pushed to all the accounts, even the service user accounts which were always on the default Segoe UI.

EDIT: Hold on, don't bother applying this yet. It went back to normal for me after a reboot. I'm working on finding out what happened and how to fix it.

Unfortunately I can't see which account made the change or if there were any before it, or even really sort chronologically in a meaningful sense since having only the latest timestamp on the key makes it impossible to correlate with the event log. I see some potential culprits like the RAC task running right around that time but it its only log entries are starting and stopping a few minutes apart. It has explicit HKLM access so it's possible but I don't know yet.

I'm about to try Registrar and Regalyzer to see if they offer more than RegScanner and I'll keep looking for another tool. If there are any tools you wouldn't mind sharing the names of that would be very helpful. I've made some attempts to replicate all the other steps I took trying to get this working until it finally did but so far I have nothing. Sorry.

I will keep trying and leave the thread up a few days at least in case someone else wants to take a whack at it, then I'll request it taken down until I make some progress so not to clutter the forum. Beyond that I will start digging into the shadow volume copies for a reg hive backup since I hadn't gotten around to scheduling regular ones but that's a worst case because I hadn't made a restore point in almost a week.

This doesn't remove or affect your desktop's DPI scaling, or change anything about the way that new DPI-aware apps apps) look. It only changes the default scaling level for DPI-unaware apps so they don't show up blurry when Win8.1 scales them up. You could disable the blurry upscaling by checking "WinXP style scaling" in Win 8.0 but that option was removed in 8.1.... until now!


What happens when you use this tweak:

No need to keep setting the compatibility DPI checkbox every time you download a new app,rename a parent folder, etc. as it's automatic. Also works on system apps where the old functionality would sometimes fail [post from the future: the one thing that kept me going was a blurry mmc.exe, in the end I got it clear again.]

MMC and any other system files, as well as MSI installers could never be sharp in 8.1 before. Microsoft made them that way claiming they had overlap issues. They look 50x better sharp! Not an app, just a tiny reg for 4 values hidden in the Registry

Up til now the best option I had to remove the blur was a script I worked on for a while to make the "Properties -> Compatibility -> Disable DPI scaling" checkbox easier to access and set because it had to be done all the time. Moving an app from one folder to another, right clicking to Run as admin, renaming the file it or any folder in its path,--all those things would make the app blurry again. Some apps, I couldn't get rid of the blur in admin mode no matter what I tried including setting the corresponding key in HKLM.

Now all that is no longer necessary because this tweaks makes the default setting to disable DPI Scaling above 100% for the older apps. This is the same setting that was enabled when the popular Win 8.0 option for WinXP style scaling was checked, and it just means there istat means Spotify is sharp , Comodo , Process Explorer, just too many looked apps that looked like crap are now sharp again


This also sharpens all the Microsoft Management Console dependent apps like Services.msc, Group Policy, Task Scheduler, etc. etc. That is not at all possible using only the native Win8.1 options because Compatibility tab is removed on system files. Same with MSI files that install programs, no way to make them sharp because the tab was missing. Now there's no need.

I hope that makes it clear. Here is the registry for the New Tweak that needs to be inserted after taking ownership (see next post for instructions) of the 4 keys:

Code:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{00021401-0000-0000-C000-000000000046}]
"DpiAware"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{000C101C-0000-0000-C000-000000000046}]
"DpiAware"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{0010890e-8789-413c-adbc-48f5b511b3af}]
"DpiAware"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\AppID\{01A39A4B-90E2-4EDF-8A1C-DD9E5F526568}]
"DpiAware"=dword:00000001

Those keys are the only ones that it should be changed in. I've been testing it for 8 hours and it's been rock solid. No gaps, everything is sharp everywhere, no special flags have to be set anymore.

It is possible the last key or 2 aren't needed but they can't hurt anything at that level in the inheritance chain. I will check that out asap and post if that's the case.
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Why using SYSTEM is better for taking ownership from TrustedInstaller

Besides being less of a disruption in the permissions (you can't run as TrustedInstaller as far as I know but you can as SYSTEM. I trust you know that's an extremely privileged account under which system services run and you should do absolutely nothing but precise system maintenance in a process invoked with that account token. That's why psexec and nircmd don't let you log in as SYSTEM but only urn processes, so you don't accidentally double click that new EXE file that just downloaded.

It's still possible of course if you use those tools to run explorer.exe so be mindful of what you're doing. Take the ownership, change the key, then give it right back (it's "NT SERVICE\TrustedInstaller" instead of "NT AUTHORITY" that SYSTEM is under.)

That being said there is a concept named Integrity under which all Windows processes operate. It is a sliding scale that augments the level of detail possible for different accounts on a system rather than just Regular (which is now medium - I think the number is 400) and Admin (which is now High or 300 but please correct me because they changed the numbering a few times.)

Changing ownership while running as admin on your regular is a weird thing, because you're actually running under an elevated token and not a real admin account. You can do all the things a regular admin account can, but when you take ownership it is given to your regular account, not the you-as-admin account, because there's no such thing and at present no way to link ownership to elevated token. So the mots popular way of taking ownership of system files leaves them with a very small amount of security equivalent to 400 or any standard user account.

All processes inherit 400 from the SDDL on your C drive, so they are immediately on the same level as you were when you took ownership and can change all the system keys you took over. I hope that explains why taking ownership with your regular user account is an incredibly poor choice with regard to keeping your system files safe.


Why bother?

Since I finished the old script I was always looking for a permanent solution and never found one. I also kept seeing people asking for something like this everywhere I looked for an answer. Finally tonight I finished some tracing I started last week after I noticed a key in my registry after a reboot caused by a crash, and through a little luck, experience and brute force arrived at this way to bring back WInXP style scaling and remove the blurry app scaling Win8.1 does by default.

There's no mention of the value that is being set anywhere in Microsoft's docs or online, but I saw it twice, and why define something as a string in the reg key that showed up after the crash and reboot and thought, why define a value if not setting it somewhere? I followed every {ClassID} I could find in the key and down to its descendants, then back down to every parent .


Post from the future: The "string in the reg key" I mentioned is just regedit's way of messing around. It's really a reparse point (symlink) I just edited directly. Downhill from here so I stopped posting at the top and continued below the rest, background info already posted (still relevant, as it turned out to be (potentially, as of this writing, partially) the method used at the end





How it works

The AppID keys being added to here seem to handle execution based on the app manifest, setting different DPI defaults based on manifest version. Setting all the old manifest schema descriptors to be overridden with the value "1" makes all the old apps DPI compatible. That's basically it.

This way of overriding the DPI awareness of apps by manifest version seems to be a mistake in the way Windows understands manifests. Since the keys never existed for the old manifests they can't possible be set to true or 1!

However due to a buggy implementation of the SMI model in Win8.1, what should be nonexistent properties are being applied. Basically, that means the DPIDisable default can be changed by setting that key and it will apply to all apps using that manifest version (there are 5 total, they just mean the apps were released at different times or built using certain versions of compilers), defaults for all apps can be set regardless of their actual DPI awareness. (DPI aware = No blur)

Besides that, there's a few more reasons this is probably a bug. Even if we were using this method on apps that are DPI aware, doing so in the registry is not documented anywhere that I can find. There are always hidden functions but this is particularly surprising because it also depends on upstream SMI properties explicitly being set up to look for the properties we are enabling just by defining strings. It's very convenient and easy to reverse.


Bit of a tangent: What's an SDDL?

Up until about a month ago I was having all sorts of weird problems with my computer, for example: many apps would just close, presumably crashing but no WER would run. Dropbox never loaded properly through Remote Desktop, complained about a permissions issue. Chrome couldn't update unless I ran the setup y itself s Admin. Every time Acrobat ran it would take ownership of my profiledata folder which brok. everything else there.

All these things pointed to permissions so I checked them over and over and they all loooked good (except when Acrobat messed them up on my profile folder so often I ended up uninstalling it).

As it turns out, an incorrect SDDL string set on my C drive was the root cause of all those issues. I didn't even know what an SDDL was so I was very confused how that could be possible. As it turns out an SDDL is a way of describing the whole enchilada of permissions and includes more properties than are avaiable to be set in the GUI of the Windows Permissions dialog box. Some of those are the integrity level and the write-ahead property which define inheritance in a reverse way. Those two were set incorrectly somehow, at some point, on my C drive and causing all those problems.

To fix it, I ran one chml -ss C:\ command first to see the SDDL. Then I went over to another computer and ran the same command. The SDDL's were different and chml describes what the string means. The computer with the problems was set to low integrity and to forward its low integrity to all child objects that don't have explicit integrity set (that's the write-ahead part).

I googled to make sure the other computer's SDDL was correct and it was. Then I juts ran one more chml command, this time setting it to the correct default chml -ws S:p(ML;OINPIO;NW;;;HI) and my computer was back to normal just like that. Obviously the strings are hard to decipher and reportedly that was an intention when they were designed, with the reasoning that evil hackers couldn't figure them out. What a joke. Anyway, these are clearly powerful tools that should be understood if you prefer to be aware of what's going on with your system and they can all be run in read-only mode to check things out and see how the security descriptors are structured.

Side note, there is an SDDL specified for most of the keys that are being changed in this tweak. I am not touching them because it's not needed in this case. However if you want to decode them from hex (they are called strings but actually stored as binary bit masks most of the time, and that binary is shown as hex in the registry to save space). The SDDL is the AccessPermission value. The only tool I know of that can read it is regil is the registry version of chml.
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
I'm still working on this trying to figure out how it all works. There are so many cross-references and inheritances that it can be quite confusing. I just came across something that illustrates just how weird things can get:

mmc.png

The MMC console only runs as admin which SHOULD eliminate discrepancies in DPI awareness specified in the two CompatLayer key flags in HKLM and HKCU. So something else I'm unfamiliar with is happening, and working on figuring out what it is. This is the kind of thing that keeps coming up and taking more time. Sorry.

While I still have these open I'll do a stack trace to figure out what they're accessing. The only information I got from Process Explorer is that they're both running under my account, yet somehow inheriting different environment variables. Those probably don't matter but finding the cause could reveal other differences that result in their DPI awareness.

According to Process Explorer they are identical in every respect, except one is fully aware of DPI, per monitor, and the other completely unaware:

procexp.png

:confused:
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
I finally have a GOOD update! It's working.

Or, well, it was, actually very well, and did as soon as I made the changes. Because they are made within the the dynamic subsystem they can take effect right away,

However as I soon found out, if you're not exactly careful and have just tried a thousand other htings, it's likely things will go wrong at some point. And they sure did when I rebooted.

The vars got read again at that point but by different programs, this time by the subsystem itself which sent itself into a spin cycle of doom showing me the login background color for half a second, then out and back forever.

I believe I've figured out why that is, it's sort of recursive inclusion used intentionally in one place but not another, and I used it in both since I was eager to get a result. Here's the output of a little batch file I wrote to illustrate the problem. It's jumping in a little deep but I'll come back to explain it as I have pressing things to do in the next few hours.

Code:
* setting __COMPAT_LAYER to %__COMPAT_LAYER%:

%__COMPAT_LAYER%        =          ~ HighDpiAware
~ HighDpiAware           =           ~ HighDpiAware
%__COMPAT_LAYER%        =          %__COMPAT_LAYER%

Stepping aside a sec, note middle line shows variable being set that has the name as the value of the other variable. That's how the System to User level transaction gets completed Continuing...

Code:
* setting __COMPAT_LAYER to %__COMPAT_LAYER% (again)
%__COMPAT_LAYER%        =          ~ HighDpiAware
~ HighDpiAware          =           ~ HighDpiAware
%__COMPAT_LAYER%        =          %__COMPAT_LAYER%

* setting __COMPAT_LAYER to %__COMPAT_LAYER% (and again):
~ HighDpiAware                 =  ~ HighDpiAware

 * Inside local scope, searching vars for "High":
__COMPAT_LAYER=~ HighDpiAware
~ HighDpiAware=%__COMPAT_LAYER%


* Searching vars for "COMPAT":
__COMPAT_LAYER=~ HighDpiAware
~ HighDpiAware=%__COMPAT_LAYER%

----------------------------------
Cleaning up our var total we start with
* we get without expansion:
total=~ RunAsAdmin HighDpiAware
* and the same with expansion:
total=~ RunAsAdmin HighDpiAware
----------------------------------

* then substitute it in the sub=with syntax
(CU takes precedence). currently at:
.
%total% is ~ RunAsAdmin HighDpiAware
~ RunAsAdmin HighDpiAwaretotal
HKCU is ~ HighDpiAware
HKCU is ~ HighDpiAware -- no difference expanded
HKLM is ~ RunAsAdmin HighDpiAware
HKLM is ~ RunAsAdmin HighDpiAware -- no difference expanded


subbing our by replacing LM's contents with CU gives us:


SET total=!hklmcl!!hkcucl!

locally that's ~ RunAsAdmin HighDpiAware~ HighDpiAware
same expanded: ~ RunAsAdmin HighDpiAware~ HighDpiAware

Resetting and going the other way around:


SET total=!hkcucl!!hklmcl!
locally that's ~ HighDpiAware~ RunAsAdmin HighDpiAware
same expanded: ~ HighDpiAware~ RunAsAdmin HighDpiAware


1. The CU over HK assumption looks correct given the way it's ordered
   by the GUII when written to the registry


2. Better get rid of that leading ~ before RunAsAdmin

The ~ is an expansion operator so when it's includeded in a variable as the first character of another variable it gets processed differently, in this case as a concantenation operator. Unless I misunderstood the documentation that specify that it's a ternary operator the usage of it with a space isn't documented.

Or it could just be that it doesn't do anything (certianly doesn't seem to expand in the normal sense a ~ does when followed by a character (for exmaple ~dp means drive and path and will give you the full path of the file you reference coming after it. In any case the nonexistent documentation isn't surprising because the var itself isn't mentioned anywhere either, fairly certain it's an internal one set dynamically by the WMI when a program requiring it is detected.

I made many many changes over the past few weeks but I think I've narowed it down to this, if anyone wants to give it a try.


  1. Regedit to HKCU\Control\Panel\Environment and make an EXPANDABLE string key (REG_EXPAND_SZ) called "__COMPAT_LAYER" with a value of "ABC" as a placeholder since vars aren't defined/technically don't exist if they're empty
    .
  2. EDIT: See the SYSTEM NOTE edit at the bottom as of this writing, the OS does it differently (its env vars are hidden, but the reg keys are visible so I would say it's best to stay safe and stick with the minimum demonstrated working solution and then escalate up to what's described in the following paragraph as needed. More info in that edit.
    .
    [del]Do the same in HKLM. I can't see exactly where because I'm working in a slightly different environment that lets me type this. just search for a key with the exact name "Environment" and you'll see it. Put the same value/data in there. Sorry I can't be more specific as I'm doing it right now[/del]
  3. .
  4. Run "systempropertiesadvanced" and click Environment Variables. You should see your new entries in there. If not come back in a few minutes or force a crash on explorer (we all know that's not too hard)
    .
  5. Now once you see them, and if you don't just go ahead and make them, then they will appear in the registry as REG_SZ and you will need to quickly swap them in with REG_EXPAND_SZ's of the same value and data as we're about to end up with in the next step
    .
  6. In SYSTEM vars put:
    .
    EDIT: changed admin to ~ and user to ^ as that's how the system does them on individual files, see right below
    .
    [DEL]__COMPAT_LAYER RunAsAdmin HighDpiAware
    __COMPAT_LAYER ~ HighDpiAware[/DEL]
    .
  7. [del]That's it![/del]

EDIT: So just to triple check I did the same old operation again with the GUI and noticed it set a caret for the user name. That's not what I had but it should certainly avoid any expansion since it's an escape character (in the command prompt at least) which is the opposite of an operator in the sense that it does nothing but make the things around it not "react" with each other, preventing joins, pipes, etc.

I tested this theory and the results speak for themselves:

It looks like I was wrong about the order and in fact CU gets taken up first judging by the output and comparing it to the env var seen by inspecting the process environment in a shimmed high-DPI app.

Code:
Resetting again to follow the nomenclature of the GUI params with the caret (^) (<--there's a caret in there, it doesn't even show up in tihs forum since it's a universal escape char) in front of the admin key

SET total=!hkcucl!!hklmcl!
locally that's  HighDpiAware~ RunAsAdmin HighDpiAware
same expanded:  HighDpiAware~ RunAsAdmin HighDpiAware

Reversing substitution order...

SET total=!hklmcl!!hkcucl!
locally that's ~ RunAsAdmin HighDpiAware HighDpiAware
same expanded: ~ RunAsAdmin HighDpiAware HighDpiAware

I believe that last one is what we want so the tilde doesn't mess things up by sticking itself in the middle of the substitution from admin to user. So I am setting the following in systempropertiesadvanced.exe:

For the user:
__COMPAT_LAYER
HighDpiAware

For the system:
__COMPAT_LAYER
~ RunAsAdmin HighDpiAware

(Not-really-an-EDIT: These will stay as-is, both in system and user, but without the ~ and ^ since obviously reg != cmd and the only ones I've observed profiling processes shimmed as DPI aware do not show these chars. Although ^ would be unlikely to show the ~ should since followed by a space it means nothing in cmd but concatenates in reg. Link to TechNet article in this post a little further down)

Also system and user have different meanings in registry and cmd, it means more of all users than system in the registry, I may come back to that if there is interest. The code above is fine.)

Now you have expandable variables which is required because the ~ creates the expansion allowing hte substitution, even though that may not be reflected in batch as it's most likely a poewrshell or derivative, I've seen those same symbols there and it's the same idea.. The reason it's done that way is so that one can overwrite the other selectively, so the setting is always place even if in an anonymous administrative session. Some programs run that way.

Thats the idea, and I'm trying it literally right now as I type this from Safe Mode with Networking :)

Now after you mke t kick some apps around and notice how they start launching sharp! And check back on this post before you reboot to make sure there are no changes so you don't get stuck in a boot loop.

EDIT: See below for the 2 reg entries too. This applies to the paragraph above and the second half of the one below, so there's still just a few more steps...

And if you want the cliff's notes and don't care about apps you need to run as admin, it's pretty impossible to mess up just by setting the HKCU part. You may still have to make it a REG_EXPAND_SZ data type for the OS to work with it properly, otherwise it will ignore it iwth no indication that it did that.

... Because it's shhhh!!!! Seriously though, I only found that variable by going through the stack of those two MMC sessions I posted the screenshots of above. Searching leads to a few matches for the compat layer but I don't think any at all (there were too many either/ors that I stopped looking) that relate it back to DPI

Back soon to report really quickly.

EDIT: Just remembered I also set this which is also very likely a factor:
In the normal DPI reg keys of:


  • HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
  • [del]HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers[/del]

Put this one entry in each of the @=(value not set). Just double click that and put in ^ HIGHDPIAWARE on the first one and ~ RUNASADMIN HIGHDPIAWARE on the second. Win8.1 sets the caret when you apply high DPI exclusions to a file, it's supposed to be an escape character but it's probably another undocumented operator so I'll look into that later. But it must cancel out the recursion and be safe. Definitely if that's all you're doing and not touching HKLM for amdin run apps. So yo uend up with:

Code:
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\@=^ HIGHDPIAWARE

[B]EDIT:[/B] See the SYSTEM NOTE edit for why this next one may not be necessary just yet...[del]HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers@=~ RUNASADMIN HIGHDPIAWARE[/del]

(Note there should always be a space after the caret, since it's an escape char the forum strips it out (see, I'm not lying!) and if I missed putting in 2 so that 1 shows up please put it in and post or pm and I'll make the change. Of course I'll review again when I have a minute.)

In this case I don't believe you need EXPAND_SZ's and certainly hope not because you would need to do it in hex to make a default (@) anything other than REG_SZ because it can't be deleted and types can't be changed on existing items. It definitely works for single files but remains to be seen for multiple. I'll try REG_SZ first and then REG_EXPAND_SZ if it doesn't work.

A caret followed by a space is supposed to do absolutely onthing but perhaps note that the space is not a delimiter if it's normally interpreted to be one, but in this case that's unlikely since there is a normal space between RunAsAdmin and HighDPIAware. I've given up trying to understand the logic behind it but intereested if anyone happens to know. Anyway back on topic, the reg expand would be along the lines of this in a .reg file:

Code:
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
@=hex(2):5e,00,20,00,48,00,49,00,47,00,48,00,44,00,50,00,49,00,41,00,57,\
  00,41,00,52,00,45,00,00,00

Those numbers are hex for getting an expandable string that says HighDpiAware with a caret in front of it. It may/should overwrit ethe default and allow you to change its type without deletiion.

So all this work for what? Well, it seems this is actually a superior fix to the individual DPI fixes. I was running Comodo super sharp instead of pixelated with this in place at 200% in the windows screen zoom settings. After I put a specific key in for the comodo tray exe it went down to the unusable tiny size it is on my 42" I have set to that zoom level.

Besides that huge benefit, technically it's much prefable to have it written once at the top than generating 1500 entries with the reg scripts I wrote for this stuff (and should have posted above if you want a safe, easy and messy solution ;-))

Feel free to post back how this all works out so we there is some validation and I will do the same with my results in a few mins.

I will also be circling back with a lot of answers to questions I have myself, like is the runasadmin going to make all apps without a manifest specfying asInvoker privileges request elevation? Don't know yet, it shouldn't... but I do know that if it's not there the system tosses away the entire key since it doesn't fit the profile it generated and figures it's either old invalid or in our case targeted for that.

Yikes, as I'm here trying to get rid of the invisible space below (it doesn't show up in the editor) I see the post was made over an hour ago... so it's type to stop typing and documenting, although that certainly helped me find a possible bug or two, and start doing. I'll try to pots back soon with results.

As far as condensing it into something concise once it's all figured out that will take until way later in the week as things are looking tight. Getting rid of this DPI nonsense once and for all (and getting an actually much better upscaled result in some apps I tried) hopefully is a step in the right direction.

SYSTEM NOTE EDIT: I ran the PCW on an app and saw it does not promote runasadmin to the HKLM. So I am not going to do that just yet because I am really behind schedule and can't do any more downtime... So this is what i am seeing having completed the compatibility steps:

Code:
Key: HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

Value: @
[SIZE=2][FONT=arial](Value was the filename but in our case we put it in the default
so the rule covers all files, leaving @ alone (do nothing on value))[/FONT][/SIZE]
 
Data: ^ RUNASADMIN HIGHDPIAWARE

I guess that about summrized what I'm about to reboot with and check. So that's the Cliff's notes if you cleverly skipped ahead. :)

Which brings me back to wondering if that will make the app always launch admin as that's not what I want, and the combined solution I mentioned above is the one I believe may work best in the end, so lots of things to be tried. Also don't forget the env vars, since those are the ones that really do the heavy lifting, but they get deleted by the system from what I've seen if the reg keys aren't there to support them.

As a super safe approach I'm going to set the HKCU key only, with the at-equals-caret-space RunAsAdmin HighDpiAware notation, and try a few environment variable notations staritng with caret-space HighDpiAware on user, then the same without a caret-space, then if iit gets tossed I'll try adding the RunAsAdmin, then promoting that to the system env vars, and so on... that is the testing strategy in this case but open to any suggestions

I'll run some apps I know are safe like the Nirsoft toolkit which is very well known in the security community and happens to show up supremely blurry at any dpi other than 96 (100%). I found them to be a good test subject since they were also the only ones that came up with no issues whatsoever in the recovery console and they can scan the registry in seconds to see where things stand.
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Separate post for registry related things that are just extra.

Info on this TechNet doc confirming exactly as I described it functioning, a concatenation operator when at the beginning of a string.

Found an MSDN blog mention of the caret with relation but not in the registry directly... It is indeed PowerShell as I thought and it seems to be a way of a forging the source of the entry or overwriting the previous one at that location, check it out and if you have feedback I may add some of mine
:huh:

Update: I undid all the DPI settings in the recovery console and didn't get my system back, but I was taking parallel tracks to finding a solution for this and one of them was combing through policy settings. It was when I followed some instructions to clean up after a failed WMI 3.0 (Windows Management Instrumentation) install, which it turned out wasn't. I haven for Win8.1 that I finally got on the login screen. Going to run through with just the DPI settings (there aren't any in either GPO, LSO or WMI) after I catch up.

<b>Not-too-informative iUpdate b994/8: Should have time to give these a whirl tonight. I The comodo thing was proably the new look they rolled out at the same time and it was just upscaling to 200% which is still vrey preferable, al though I d oremember the fonts looking very sharp (you can see from all my screengrabs and ther's not a trace of Segoe UI (except the login screen where I the result was some empty-square looking glyphs).

Also notiecd a setting made by the system in the Current_User key with a ~ in front of it, yet the very same setting set by notehr winprog was set with into the same value but ith a carete instead All my personal backups use ~ because thats what my reg scripts generate when on a target eexecutable installer or folder parsi to run through
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Lots of progress , here is a screenshot showing a non native DPI app running at 130% on my desktop machine:

PrtScr capture.png

Left is run as admin, right without elevation. Just need to figure out the inheritances.

Layers is ps1 style and Environment is cmd style. I'll get there.

In the meantime you can play with these to get WinXP style scaling in Win 8.1 update 1. I just found this so I have no idea if it works in 8.1 proper or 8:

- Set DWM\UseDpiScaling=1
- Desktop\LogicalDPIOverride=1
- new key \FontDPI\LogPixels\LogPixels(DWORD)=(something higher than 96 in dec)

That seems to scale everything if you set it to match your logical DPI in Desktop including fonts that people complain about, taskbar etc.

Also, login screen can be resized by setting LogicalDPIOverride on the the system user (1-5-20) = 1
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
I'm repeating this process from scratch on my ultrabook which I was using as an HTPC but now need as a regular notebook and trying to dissect better what worked on the desktop to give me the full resolution. It might take a while but it should be better than the hundreds of changes I made to get scaling off since starting the thread.

I'm stayig entirely out of the AppCompatFlags\Layers keys as they seem to only affect individual programs ad y only interest iis to replicate the global fix. I am already seeing some changes take palace and no scaling is happening on about half my apps. I just realized that when I tried to make Comodo scale up by removing the flag only to find the entry isn't there, and in fact the entire key is blank. So I guess that's progress.

I see a key I've not seen before thay may be doing a lot of this automatially, but I'm i the middle of setting up the system so I won't be tweaking DPI just yet. Heres the info if you want to give it a shot. There's not a single match or any mention of it on Google.

That hex comes out as a REG_EXPAND_SZ (expandable string) since the export doesn't have a way to indicat ethe difference between that and REG_SZ. It knows to epand because the ends with 00 in the hx, whereas a normal string just ends.

HHere;s the export from my registry:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags]
"MirrorCompatBinaryExtension"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,\
52,00,6f,00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,\
00,32,00,5c,00,4d,00,69,00,72,00,72,00,6f,00,72,00,44,00,72,00,76,00,43,00,\
6f,00,6d,00,70,00,61,00,74,00,2e,00,64,00,6c,00,6c,00,00,00

And it translates into
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\MirrorCompatBinaryExtension=%SystemRoot%\System32\MirrorDrvCompat.dll

I have no idea wha that does, but this setting and one other are the only ones in my registry and seem to be doing a pretty good job with almost all apps. The other one is the compatibility assistant, which I recommend leaving at its default state as it tends to get a sense of what your preference is as you move windows around and scale them and tun off dpi somehow other than the register after a whil. II'l find the ame of the process and set an audit flag on aything it does so I can review in the event logger.
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Still at dpi auto on admin only. User refuses to cooperate without explicit settings so I'm exploring other avenues. If there's any interest lok and I'll pill those together. Should be no more than 6 entries total
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Finally... success in user land. 99% of the way there.


The only process that refuses to take up the shim is svchost.exe, and evne then only sometimes.


From previously seeing that and dwm.exe (also one that won't take it up, but irrelevant since it has no child processes), I think this is likely due to using a temporary account with GUID of all zeroes. It report as System but it's really nonexistent.


I still have a few tricks up my sleeve to get that last bit working. It is only an issue if the flag under folder options "Launch Explorer windows in a separate process" is checked, AND explorer is launched separately, AND a program is run from double clicking it.


All other cases, done.

:dinesh::dinesh::dinesh:
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
So many methods to hook presumably easier than attempts to use something removed...

Easiest seems to be this one to spoof the manifest is Window.SetProcessDPIAware
Details of the effects on the manifest, titled Manifest Madness over at MSDN

There are also these, but also not exposed in the registry:

System.Windows.Forms.AutoScale
System.Drawing.Graphics.Dpi
GetDpiForMonito
Shell.GetScaleFactorForDevice

A few others (perhaps equivalent to the above) I dug up through stack traces:

comctl32.dll
:84a70 HighDpi
:84da0 DPI
:1d0398 ScaleFactor (I remember this one exposed to the API as ScaleF, but no registry)

Perhaps even possible via the registry in one place (per monitor), but too risky without a VM going for now: CurrentControlSet\Control\Video\{ID}\Defaultsettings.*

But trying to keep it clean since I don't want another persistent hook than anyone else. Just combing through the stack traces makes me icky at the wasted cycles of back and forth with Windows, and I've only got 2 of those going.

Another place I see the Compatibility Troubleshooter poking at, a possible potential: HKLM\SOFTWARE\Microsoft\Ole\AppCompat

DesktopDPIOverride is still the one I havne't touched, and probably should the more I read. If the docs are believed it's only good for incements of 25%:
DPI-related APIs and registry settings

Very good article right there I wish I had long ago. As is this one explaining the calculations and optimal picks besides the obvious 200%:
Writing DPI-Aware Desktop and Win32 Applications (Windows)

Speaking of good articles, that first one has a paragraph expressing the sentiments around this whole thing accurately:

If you do have one or more poorly-written application without any DPI awareness, you must enable DPI virtualization unless you’re willing to tolerate the application’s screwed-up GUI. Unfortunately, this results in a secondary problem because Microsoft designed this option the wrong way around. DPI virtualization is opt-out rather than opt-in: you can only enable it for the entire system, then you must selectively disable it for individual applications.

But for now, I believe the issue with svchost is resolved. The default DPI that the System user shares. It was still at 96, right there in WindowMetrics where I started months ago.

So barring any surprises, going to start cleaning this up and ask shortly for a closed thread or delete myself if I can. Then wrap it all up into a few lines of .reg and now hopefully it's for good.
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Finding it difficult to replicate. For example, does anyone know how to make symlinks in the registry?

registry symlink.png

smss does, but I sure don't (neither does regedit). Hardcoding is fine but not ideal.

Also working on another approach based on a technique I saw the troubleshooter using. External manifest with dpiAware=true/pm and setting a key to specify the preference for external over internal.

That would depend on the compatibility engine parsing the XML in a way that isn't currently implemented but should be possible given the ECMA standard. I'll need a .manifest at the key parts of the .NET common language runtimes and if necessary (like for mmc.exe) maybe even a .config for standalone assemblies.

At least that's getting me out of the black box registry tricks getting pulled here. If it works the end result would be a polite code injection without the background process
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Forgot to mention, there is already a fully working method in place. I'll put it on the first page. It's just a bunch of registry settings for environment variables. Unlike the regular Layers key entries, these get passed down into child processes. There are many ways of doing this that only Microsoft knows, certainly that environment variable is nowhere to be found... until now. :)
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Bypassed the restriction on running the PCW on system files and saw this

PrtScr capture_8.png

Here is procmon showing the PCW writing the same xsd:string=dpiAware except it's to the common runtime itself . Thta's as a last resort and seems to be the strongest override, as I don't see a sequence preference for an external manifest taking over the invocation policy protections around a file like that.

The scope obviously needs expansion beyond that file but since it's a common runtime that sounds very broad in name (SxS Settings\Windows Settings) that just might cover the entire 3.0 namespace (http://schemas.microsoft.com/SMI/2005/WindowsSettings)
 

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
EDIT 5/12: Getting messages about this thread, no one posts though. Remember this is all in testing. With that said, AppliedDPI cannot be set at the registry level, it's inherited at bootup/logon from LogicalDPI. Better implementation guide soon

Works exactly as expected. Before and after with nothing in the AppCompat\Layer keys...

resbefore.pngresafter.pngPrtScr capture_7.png

Resource Hacker is not related to MMC... a little different I guess. It's widely known to crash when embedding a manifest into it, so difficult to get sharp at times.

Fortunately this appears to be easier than the SMI method, basically just declaring the desktop at 72 dpi and establishing that as the main multiplier (.75), then saying to Explorer that somehow the window is showing at 125% and we need it back at 100% (via AppliedDPI=120), it comes delivered to the desktop with 120ppi detail but 96ppi Explorer mode.

I guess DesktopDPIOverride being responsible was the thinking here, but they are not read in that order IIRC. It's a factor that changes meaning, what the criteria is I'm still testing but this MSDN article mentions a "1" can mean an increase from 100% to 200%, not just 25%. Any in between need to be tested to see how effective lowering LogMetrics would be to DPIOverride, or if it will just scale down to a blurry smaller . would need to bet set as I haven't tried. You may get a slightly bigger or smaller app than 96 ppi but the idea is it should never virtualize into a glob of ugly.

If you want to change up the Start screen you can also use LogicalDPIOverride at negatives whole numbers to zoom out for more squares or positives to zoom in, both 25% increments as well. There's another, undocumented property exposed by the GUI for "Larger Buttons" (something similar.) It creates the FontDPI/LogPixels/Logpixels dword at x78 (120 ppi in dec) when checked on in Start Screen, but I'm sure you can use any value to tweak zoom to whatever intermediate size you want and Metro will compensate.

Some examples of the [DEL]working theory[/DEL] consumer preview:

Target PPILogPixel
dword (dec)
AppliedDPI
dword (dec)
DesktopDPIOverride
:reg_sz
Win8DpiScaling
:dword
100% - 96 ppi0x60 (96)(not set) treated
as == 0x60 (96)
(not set) == "0"(not set) == "0"
125% - 1200x78 (120)0x78 (120)"1""1"
150%i - 1440x90 (144)0x90 (144)"1""1"
175%"1" ?"1"
200%"1""1"
133%"1" ?"1"

  • FontDPI/LogPixels is not a real folder, it's a symlink and editing the dword inside it with the same name does nothing. It looks like it sticks until you restart, but no amount of permissions can make it stick. I'm not aware of Backup Operator or equivalent permissions available for the registry to allow visibility into its symlinks. Still out on this one, but I say delete the key since it's the symlink. If it hasn't recreated at the correct DPI level by restart go back into the Display control panel and it should be
  • Also DesktopDPIOverride only works with Win8Scaling=1. You may be able to keep Win8 off and scale per monitor with AppliedDPI. Not sure about not matching DPI, if higher will definitely blur, lower bound needs checking.
  • Highly recommend double checking any changes against this MSDN article on DPI Registry settings, the most informative on the topic. Includes full reg paths, no mention of the symlinks however :)

PPI aware apps behave as they normally always have. In the first screenshot regedit is dpiAware and procmon is not, yet both are scaled to the same amount. Essentially, applying this method is like a mandatory opt-out policy for non-PPI aware apps.

Will need to roll back the SMI config or just do this approach by itself on the laptop to rule out others, as both SMI and the environment variable approaches are capable of doing the same on their own based on where they were from that point. There is a key named "altitude" in the xml config, and it's used to access the more sensitive permissions, like launching early in boot before malware protection.

Given the relative ease and the uncertainty of the xml being read, parsed correctly, etc. I think this is a good approach. It's better than the env vars which sometimes go missing depending on the context the process was invoked in. Hesitant to put them all in for backup since they can hide other issues (the window will appear smaller instead of blurring if the vars above are set incorrectly but if the environment var is set, hiding a conflict that normally doesn't exist by itself)
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Update 5/18: [snip] moved to OP
 

Attachments

  • HKLM_Scaling.png
    HKLM_Scaling.png
    24.9 KB · Views: 235
  • HKLM_Flags.png
    HKLM_Flags.png
    26.1 KB · Views: 198
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
If it scales but blurry, this key overrides the override of the variable the other key set:

Code:
[FONT=courier new]Windows Registry Editor Version 5.00[/FONT]

[FONT=courier new][HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers][/FONT]
[FONT=courier new]"C:\\Windows\\explorer.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\explorer.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\runonce.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\mmc.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\cmd.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\conhost.exe"="~ HIGHDPIAWARE"[/FONT]
[FONT=courier new]"C:\\Windows\\System32\\svchost.exe"="~ HIGHDPIAWARE"[/FONT]

That key is always parsed so it sticks as a HKLM reg key, and since also results in an env var being set, gets passed down to child processes in case they don't do their own parsing.

If needed it can also be added to HKCU (same subkey) and HKU\S-5-1-18 if you want HKCU's equivalent for the system user (if you use psexec or nircmd)
 
Last edited:

My Computer

System One

  • OS
    Windows 8.1 Pro/Server 2012 R2 Datacenter
    System Manufacturer/Model
    Self-assembled
    CPU
    Core i7-920 @ 3.4 GHz
    Memory
    12 GB DDR3
    Hard Drives
    SSD RAID 0
    Mouse
    Razer Naga 2012
    Internet Speed
    100 Mbps
    Antivirus
    virustotal.com
Thanks alot for this! One question thou;

The line "[HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration\[ABC...]\00\0#]
"Scaling"="16"

If I set Hexadecimal 16, it results in (22)
And decimal 10 results in (16)

Which is correct?

Also, I have like 10 different entries under GraphicsDriver/Configuration. How to know which ones are active?
 

My Computer

System One

  • OS
    Windows 8
    System Manufacturer/Model
    -
    CPU
    i5 3570K
    Motherboard
    Asus P8Z77-M
    Memory
    Corsair 16GB
    Graphics Card(s)
    EVGA GTX670 FTW
Also, I have lots of different entries under graphicsdrivers/configuration. How to tell which ones are used and which ones are old?
 

My Computer

System One

  • OS
    Windows 8
    System Manufacturer/Model
    -
    CPU
    i5 3570K
    Motherboard
    Asus P8Z77-M
    Memory
    Corsair 16GB
    Graphics Card(s)
    EVGA GTX670 FTW
If all else fails, how do I restore default global scaling?
 

My Computer

System One

  • OS
    Windows 8
    System Manufacturer/Model
    -
    CPU
    i5 3570K
    Motherboard
    Asus P8Z77-M
    Memory
    Corsair 16GB
    Graphics Card(s)
    EVGA GTX670 FTW
Back
Top