dev

ShellExecute Doesn’t

My oldest supported Windows application is a launcher app named SlickRun, and it’s ~24 years old this year. I haven’t done much to maintain it over the last few years, although it’s now available in 64-bit and runs great on Windows 10. (Thanks go to Embarcadero, who now offer a free “Community” edition of Delphi, the language/platform I ported SlickRun to circa 1994).

I still fix bugs in SlickRun from time to time, and as I was playing with Rust a few days ago I was reminded of one of the oldest limitations in my code– if you update your system’s %PATH% variable, those changes aren’t seen by applications/consoles spawned by SlickRun until you restart it. It’s particularly annoying because it’s so unexpected– users expect that command consoles launched by Win+R,cmd.exe,Enter will behave the same way as Win+Q,cmd,Enter, but the former consoles have the updated %PATH% while the latter do not.

While ShellExecute() sounds like it’s an API that causes the shell (aka Explorer) to execute something, in fact it does nothing of the sort.

Updating the Environment Block

The root cause of the “outdated path” problem is that processes launched via ShellExecute inherit the environment variables of their spawning process, and those environment variables (typically) are assigned as the process launches and never touched again. Because SlickRun starts with Windows, the %PATH% when it starts is the %PATH% that every process it launches inherits. (You can easily view a process’ environment block using the Properties > Environment tab in Process Explorer).

So, how does Explorer detect the change? That part I figured out ages ago– after updating an environment variable, the System Properties > Environment Variables Control Panel UI (or the SetX.exe console tool) broadcast a WM_SETTINGCHANGE message to all top-level windows with an lparam containing the string “Environment”. I could easily add code to SlickRun to detect that the variables had changed, but for decades I didn’t really know what to do next… I didn’t know how to read the updated variables (without doing something hacky like restarting the process) nor ensure that they were passed to the applications spawned by ShellExecute.

Yesterday, I got fed up and started Googling. A few posts on StackOverflow mentioned a promising-sounding function, RegenerateUserEnvironment. And while that function appears to be undocumented, there’s an amazing issue filed in an open-source tracker that explains exactly how Windows Explorer uses this function– basically, just wait for the WM_SETTINGCHANGE event, then call the API. The RegenerateUserEnvironment will replace the calling process’ current environment block with the latest values.

Launching at Medium Integrity

While we’re on the topic of executing applications “like the shell”, another scenario came up twelve years ago when Windows Vista was first introduced. The SlickRun installer, written in NSIS, launches SlickRun when installation completes. Unfortunately, the installer runs with Admin rights (High integrity), which means that, by default, all of the programs it launches inherit that integrity. For SlickRun, this is especially bad because it means that any programs that it, in turn, launches during that first session (e.g. your browser!) will run at High integrity too. Not good.

While you can easily use the “Runas” verb to ShellExecute to launch a High integrity application from a Medium integrity application, there (depressingly) isn’t a way to do the opposite. For years, the official recommendation was to do some fancy coding to clone Explorer’s tokens and use those. Unfortunately, this is quite complicated to implement, especially within a NSIS script.

As it turns out, however, there’s a trivial workaround which works quite well– while ShellExecute doesn’t run things as the shell, applications can easily get Explorer to launch anything they like at Explorer’s integrity. The trick is to simply invoke explorer.exe and pass the filename to be executed as the first command line argument:

While this approach isn’t technically supported, I expect it is likely to continue to work for the foreseeable future.

 

It’s depressing that together these tricks have taken me almost twenty years to discover, but I’m happy that I have. I hope they help you out.

-Eric

Standard
tech

Troubleshooting Windows 10 Bluescreens

I recently bought a Dell XPS 8900 desktop system with Windows 10. It ran okay for a while, but after enabling Hyper-V, every few minutes the system would freeze for a few seconds and then reboot with no explanation. Looking at the Event Viewer’s Windows Logs > System revealed that the system had bugchecked (blue screened):

Event Viewer - BugcheckBugcheck 0x1a indicates a problem with “Memory Management” .

Run WinDbg as Administrator. File > Open Crash Dump:

WinDBG open crash dump 

Open C:\Windows\memory.dmp. Wait for symbols to download:

Debuggee not connected; symbols downloading

If symbols aren’t downloaded automatically, try typing .symfix and then .reload in the command prompt at the bottom.

Use !analyze -v says WinDBG

Then, follow the tool’s advice and run !analyze -v to have the debugger analyze the crash. WinDBG presents a surprisingly readable explanation:

WinDBG notes driver memory corruption

So a driver’s at fault, but which one?

Stack trace points at WiFi

It looks like bcmwl63a, for which symbols aren’t loaded, one clue that this isn’t Microsoft’s code. Let’s find out more about it using lm vm bcmw163a:

 

Debugger points at Wifi driver

Pop over to the listed path to examine the file’s properties, and see that it’s the WiFi driver:

Driver details

The Dell 1560 802.11ac card is the same type as found in my Dell XPS 13” notebook PC, where it was responsible for a flurry of bluescreens last year. The driver appears to have improved (the XPS 13 doesn’t crash anymore), but it looks like some corner cases got missed, likely related to the Hyper-V virtual networking code. Rather than waiting for an updated driver, the experts on Twitter suggested I simply upgrade to the Intel 7265 and install the latest Intel PROSet wireless driver. At $20 on Amazon, this seemed like a fine approach.

The upgrade was straightforward and would’ve taken less than 5 minutes to install except one of the nearly microscopic sockets broke off as I removed the Dell card’s antenna cables:

BrokenSocket

I used a needle to remove the broken pieces from the antenna’s connector before it would fit on the new card’s socket. After connecting the antenna, the new card easily slid into the slot and Windows recognized it on next boot. I used Device Manager to ensure the drivers loaded for the new card’s Bluetooth support, and installed the latest PROSet driver. Everything’s been working great since.

While WinDBG is one of the more inscrutable tools I use, it worked great in this situation and would point even a novice in the right direction.

 

-Eric

Standard
dev, security

Stupid (useful) Windows Shell Tricks

RunAsUser

Back in the Windows Vista timeframe, the existing RunAs verb for ShellExecute was changed. Instead of prompting the user to run the target as a different user (e.g. the experience you get when you Shift-Right-Click on an app) it instead would treat the call as “Run the target as an Elevated Administrator”. Well, what if you wanted the old experience, where the user was prompted for an account to use?

It turns out there’s another (as far as I can tell, undocumented) verb, RunAsUser that has the old behavior.

This trick has been integrated in SlickRun 4.3 and you can use it by hitting Ctrl+Alt+Shift+Enter when executing a command. The existing Ctrl+Shift+Enter shortcut for “Run as Administrator” remains unchanged. You can also configure any given MagicWord to always prompt for a user-account to use via the new checkbox at the bottom:

MagicWord UI

 

Launching Unelevated

A longstanding problem with SlickRun was that the Setup program launched it when installation was complete, and because the Setup program runs as Administrator, SlickRun itself ran as Administrator. And when SlickRun runs at Administrator, everything it runs launches at Administrator as well. This has horrific consequences for things like Internet Explorer, which disables its sandbox when run as Administrator. It’s just awful.

So, you’d expect that ShellExecute would’ve been updated to offer some sort of RunUnelevated verb that enabled an elevated application to run a target application without elevation. Sadly, it doesn’t; the Windows team considered this a really hard problem (the corner cases are ugly) so they punted on solving it. The problem with this approach, of course, is that leaves solving the problem to the poor ISV developers, who have even less understanding of how to solve it, and thus they typically don’t even bother trying, leaving their users at risk.

Fortunately, a while ago I discovered an ugly hack that works everywhere I’ve tried it. A kind developer on the Shell team confirmed that the fact that this works is basically a bug and they could remove it at any time. But they haven’t yet, and compared to the (absurd) alternatives, I think it’s the best option for most of us.

The trick is simple—just execute Explorer and pass in the path to your application. In a NullSoft Installer Script, it looks like this:

    exec '"$WINDIR\explorer.exe" "$INSTDIR\sr.exe"'

There are, of course, corner cases where this could fail (e.g. if the user isn’t using Explorer as their Windows shell) but in the last few years I’ve been using this trick there have been a total of zero complaints.

The famous Raymond Chen has provided a more robust approach that asks Explorer to launch your app for you, depending on COM rather than the “bug”, but that approach is only feasible if you can call arbitrary native code, which is rather complicated for NSIS scripts.

 

-Eric Lawrence

Standard
browsers

Microsoft Edge Bugs and Omissions

I tweet about the new Microsoft Edge browser quite a lot. I wanted to have a blog post to collect some of the feedback I’ve provided so I have it in one place and can update as needed.

Note: This post mostly focuses on the bad parts of Edge; there are plenty of good parts, including much improved standards support and a safer default security posture.

Last Update: November 2015 Update Most of the trivial issues are fixed; the bigger problems are mostly unfixed

Bugs

1. The “Should I trust this site” link in the HTTPS trust badge goes to page that doesn’t even attempt to answer that question. Update: Sorta fixed.

2. The hover “tooltip” on that site doesn’t do escaping of & properly and also has a text-truncation bug:

image Update: Fixed.

3. The RichText tests at www.browserscope.org hang the browser.

4. When Windows UAC is set to “Don’t dim my desktop”, launching a download (e.g. setup.exe) that requires elevation causes the consent window to appear behind the Edge window, effectively causing a denial-of-service condition that hangs the tab.

5. No, not that star, the other one!

image

6. Remember focus rectangles that show which button is active? Yeah, I miss those.

7. Adding a folder silently fails if the name chosen contains any “special filesystem characters” like ?, :, *, etc.

image

8. HTML5 Drag/Drop — You can’t drag/drop files into the browser (e.g. on OneDrive.com). Update: Fixed.

9. Microsoft Edge fixed the longstanding (and amusing, due to its root cause) bug whereby it exported HTTP Archive (HAR) files as XML instead of JSON. Unfortunately, the new JSON exporter omits the required encoding=”base64″ attribute when including binary bodies. Also unfortunate, F12 doesn’t write the creator version field in the JSON; a proper version number here would allow tools like Fiddler to better accommodate the buggy output.

10. CSS Animations that have been offloaded to the GPU (“independent animations”) cannot be stopped. The only workaround is to prevent them from being independently animated.

Omitted

1. Windows 7 Support – After strongly hinting that IE11’s successor would run on Windows 7, the team changed course and said that Edge wouldn’t appear on Windows 7 at release but they’d promise to “watch customer demand” for a Windows 7 version. From both mind-share and market-share perspectives, I think this is a very risky move.

2. Extensions – Edge was expected to contain a new Chrome-like extension model, but this slipped from the original release. There’s currently no ETA for its arrival. Update: Delayed to 2016.

3. Tracking Protection Lists –  A Tweet from an IE engineer implies that these will not be coming back to Edge and the future extension model is expected to serve as a replacement. This is unfortunate, as a good TPL dramatically improves the speed at which pages load and significantly reduces the number of pages that can cause the browser to hang or crash.

4. AddSearchProvider – Edge makes it quite cumbersome to add search providers, having removed the AddSearchProvider API supported by IE7-IE11, Chrome and Firefox.

5. Click-to-Play – There’s no way to configure the built-in Flash object to operate in a “click-to-play” manner.

6. Report Phishing – The old “SmartScreen > Report this Site” experience has been removed and replaced with a “Feedback and Reporting” widget that accepts all sorts of feedback about both the browser and the site. It is likely that this experience does not collect the same level of data as the old experience, meaning that some reported phish may escape.

7. Menus & Chords – When Microsoft Office dumped the menus in favor of the ribbon system, they ensured that the old accelerator keys and keyboard chords (e.g. Alt+F,C to “Close tab”) continued to work. Edge makes no such attempt, and thus my muscle memory built up for over a decade now fails.

8. JavaScript Uncontrollable — Unlike nearly every browser, Edge offers no way to disable JavaScript on a per-site or global basis, even to test <noscript> tags.

9. Certificate Inspection — There’s no way to inspect the certificate presented by a HTTPS site.

Bonus Gripes: Windows 10 Issues

1. At 125% Zoom, the Window Title bar is one pixel too short. (Fixed in August)

Embedded image permalink

2. There’s no visual distinction between the title bar and the menu bar in some apps (like Notepad). As a consequence there’s no way to tell whether click & drag will drag the window or do nothing at all.

3. A background licensing service frequently crashes when resuming from sleep; it takes down the WiFi service which runs in the same service host which means you can’t access WiFi after resume. Update: fixed by the July 20th update.

4. The experience for making applications default has changed again in Windows 10. While the Windows 8/8.1 experience wasn’t awesome, the Windows 10 experience is a slap in the face to the user. Mozilla is complaining, justifiably.

5. Win10/.NET4.6 carries over the Shell/.NET bug whereby double-clicking any label control copies its text to the clipboard. The behavior change in the comctl32 label control was checked in during Windows Vista by a rogue dev without a spec or an explanation.

6. Windows 10 carries over the Windows 8 regression whereby proxy-change calls are ignored during shutdown.

-Eric

Standard
tech

On Chromebooks

I spent the summer of 1994 working minimum wage (a princely $4.25/hour), testing electronics, saving all of my pay to buy a beast of a computer. That September, I entered my sophomore year of high school and plunked down my saved ~$3000 to become the proud owner of my first Windows PC, a Comtrade Pentium 90 with 8 megabytes of RAM, a 730mb hard disk, and a quad-speed CD drive. My parents threw in a few hundred dollars to get me an upgrade to a 17” monitor (snicker… 15.7” visible). I split my time between DOS and Windows for Workgroups 3.11.

Suffice it to say, I’ve been a Windows user for a long time.

In 1999, I started as an intern on the team that became the SharePoint team, and in 2001 I joined Microsoft full-time to work on Microsoft Office, and later Internet Explorer.

Since 2012, I’ve dabbled with Macs and Linux VMs, but spent nearly all of my time on Windows.

That’s starting to change.

Why?

Confession: I love Chromebooks.

In January of 2013, I bought my first Chromebook, the $249 11.6” Samsung Chromebook. It was a underpowered little machine with a decent keyboard, a good battery, and not much else. But the long battery life meant it was almost always ready to go, and the tiny form factor made it an easy choice when I wanted portability but a better keyboard than the tablet.

Within a few months, my wife took over the machine; it was perfect for her scenarios: it booted quickly, rarely ran out of juice, and didn’t bother her with incessant demands that she install updates and reboot, a constant hassle with her Lenovo x200. Updates on the Chromebook are incredibly painless (just click an icon every few weeks) and make both Mac OS and Windows look primitive by comparison.

In March of 2014, I sent my parents a $160 ASUS Chromebox to replace their old Windows XP computer. The new box is about a twentieth of the size and probably four times as fast, but the real reason I sent it was that I was tired of doing remote tech support for browser-borne malware, and I was increasingly terrified of letting my parents do online banking from Windows.

In October of 2014, we upgraded my wife to the $329 Toshiba Chromebook2; it has a much faster CPU than the old Samsung, a dramatically nicer screen, and a respectable battery. It’s a bit heavier and bulkier than the Samsung, but it’s still much more pleasant than the Lenovo. The Samsung Chromebook became a hand-me-down to our two year old son (who loves pounding the keyboard) but alas, the screen was recently broken… not by the boy, but by our cat, who knocked it off a table. Still, for a $249 machine, we definitely got our money’s worth.

My favorite Chromebook is the Pixel. I had a 2013 model which was a beautiful machine with a fatal flaw—an inefficient CPU and a smallish battery that meant it wouldn’t last for five hours on a charge. As much as I wanted to love the Pixel, it let me down too many times; I’d pick it up and it’d be dead. The 2015 Chromebook Pixel solves this problem—it gets much longer battery life (10 hours or more), can live on standby for a very long time, charges rapidly over USB-C, and has a faster CPU. Build quality is generally very good (awesome touch screen, strong hinge, good keyboard). The only worrying issue is that I recently noticed that when the fan comes on (pretty rare) there’s a bit of an audible whine if the base isn’t horizontally level—a problem which may or may not be unique to mine, as I haven’t found anyone else with the next Pixel yet. Update: a friend reports his 2015 Pixel doesn’t have this problem.

I have the $1300 “LS” edition which has an i7, 64gb SSD and 16GB of memory but I’d recommend the $1000 regular edition (i5, 32gb SSD, 8gb RAM) to almost everyone, as there are more useful ways to spend the $300 price difference. (I bought the higher-end model with the idea that I’d eventually put Crouton on mine and run Linux beside ChromeOS… but thus far I’m too afraid to “break” it.)

I currently have a wide range of other devices to choose from (2015 XPS13, 2013 Mac Air, Lenovo T420s, Retina IPad 3, Nexus 7) but I find myself picking up the Pixel more often than not—it’s just a fundamentally pleasant machine for doing things on the web. I’ve also started redeeming the “free HD version on Google Play” codes that come with the HBO shows I’ve bought on DVD and Blu-ray and the Pixel is a great device for watching these as well, although the beta branch of Chrome OS seems to have a number of minor annoyances in the Google Play app.

My 2015 XPS13 which is an awesome form factor (light and fast) but it is currently running Windows 10 which is not ready. Prior to upgrading to Windows 10, the XPS13’s real problems were the awkwardness of the Metro UI paired with the hassle of constant Windows Updates. Another key consideration is that you can’t get (performance destroying) antivirus for a Chromebook, and most IT departments don’t know how to screw them up. Previously this beneficial ignorance was an advantage for Macs as well, but our IT department at least has started “enhancing” Macs and making them awful too.

Despite its many benefits, the Pixel isn’t a perfect machine and it’s probably not for everyone. Apps are sadly sparse, and web-based replacements aren’t getting new features as fast as I’d hope. There have been a few promising developments recently, like Skype making its way to Chromebook. I’m not a gamer, but Chromebooks are very limited in this department– while many browser-based games will work great, those based on Java don’t, and none of the major PC games available for Windows (and increasingly, for Mac) will run on Chromebooks.

The biggest disappointment so far is in printing—it’s not a super-common scenario for us, but we do a ton of online shopping and need to print a return label a few times per month. At home, we have a Brother DCP 7065DN printer and you basically can’t print to it from Chromebooks without expensive workarounds like the Lantronix xPrintServer Cloud Print. It’s goofy that I have to buy a little box to run a print server just so ChromeOS can print, while presumably the exact same print daemon could be run directly on the ChromeOS machine. While frustrating, this limitation will probably continue to fade in importance as new printers come with the Google Cloud Print code built in; for instance, the slightly newer Brother DCP L2520DW supports Cloud Print, and it’d be cheaper to buy that than the xPrintServer box.

Unlike most of my PCs, I feel like my Chromebook works for me, rather than the other way around.

-Eric

Standard