Visual C++ in Short: Unblock downloaded applications

Raymond Chen published an article earlier this week about ShellExecute hooks and it reminded me of a shell hook of sorts that still exists in Windows Vista despite Raymond’s very good argument that shell hooks are often used for evil and certainly can’t be used to add security. Granted this hook is not a ShellExecute hook in the literal sense but it amounts to the same thing.

Since I’m long overdue for a Visual C++ in Short article I thought I’d talk about a security feature in Windows that isn’t, well, secure. I’ve previously written about User Account Control and cannot say enough about it being a major step forward in providing a more secure environment for normal users to work and surf the web (with Internet Explorer). But there is this little so called security feature that the Windows shell introduced prior to Windows Vista that somehow came along for the ride but never quite got the UAC makeover and that is the topic of this article.

Many applications are distributed simply as an executable without an installer. You can for example go to and get various great system tools by simply downloading the executable and running it. Similarly you can download the Window Clippings executable and run it without first going through an installer.

Downloading an application and then running it often results in the following dialog box appearing before the application starts:

There are so many things wrong with this dialog box that I don’t really know where to start. Perhaps the most glaring problem is that it is neither consistent nor integrated into the secure desktop prompt used by User Account Control. Granted, the UAC prompt is not used since the application does not need to be elevated but the inconsistency is still jarring for the user.

A more serious problem is that, unlike UAC, this security warning is not coming from the Windows kernel but merely from the ShellExecute function called by Windows Explorer. A simple way to demonstrate this is by using the command prompt instead of Windows Explorer to run the downloaded application:

Sure enough there’s no security warning and the application runs immediately.

What about some code?

Here’s the equivalent of what Windows Explorer does, hardcoded for this example:

::ShellExecute(0, 0, L"C:\\Data\\WindowClippings.exe", L"/options", 0, SW_SHOWNORMAL);

And here’s the equivalent of what the command prompt does:

WCHAR commandLine[] = L"C:\\Data\\WindowClippings.exe /options";
::CreateProcess(0, commandLine, 0, 0, FALSE, 0, 0, 0, &si, &pi);

In fact you can even use ShellExecute’s big brother and tell it to forgo the security warning:

SHELLEXECUTEINFO info = { sizeof(info) };
info.nShow = SW_SHOWNORMAL;
info.lpFile = L"C:\\Data\\WindowClippings.exe";
info.lpParameters = L"/options";


The magic flag in this case is SEE_MASK_NOZONECHECKS.

It might seem that developers should just avoid ShellExecute(Ex) but that is far from the truth. It does add valuable features such as initiating the UAC prompt if needed, whereas CreateProcess would simply fail with ERROR_ELEVATION_REQUIRED.

As the application developer you can’t control whether the user will run your application using the command prompt or by simply double clicking the executable. Arguably the latter is far more common. Short of providing an installer there isn’t much you can do to avoid this security warning. All is not lost however. Take another look at the security warning:

Most users when confronted with obstacles like this one seem to just do whatever they can to overcome them as quickly as possible so they can perform the task they originally intended to perform. It is then not surprising that they completely overlook the little check box in the corner. All they need to do is clear this check box and Windows will no longer prompt them for this application. This check box only exists to annoy the user further. Think about it. Once the user has run the application a single time there’s no reason to prompt the user again in the name of security since a malicious application would have already had the opportunity to cause any intended harm. In fact the application could even unblock itself once it has been given an opportunity to execute some code!

To understand how this is possible we need to take a look at how Windows Explorer knows to block an application from running directly. For starters, you can quickly determine whether an application is blocked by looking at its properties window:

Notice the security warning at the bottom. Clicking the Unblock button has the same effect as clearing the check box in the security warning dialog box. When the application was first downloaded, the browser created an alternate NTFS data stream where it stored zone information. You can view this information using the command prompt:

Unblocking the application simply involves removing this data stream. Although not foolproof, such as when the application does not have the file permission to delete the data stream, it works in most cases.

Start by getting the full path to the executable. You can do this with the QueryFullProcessImageName function that was introduced with Windows Vista. If needed, you can fall back to the slightly less reliable GetModuleFileNameEx function for previous versions of Windows. Now simply append ":Zone.Identifier" to the path and call the DeleteFile function to get rid of it. Here is a complete example. The UnblockProcessImage function returns S_OK if the file was unblocked, S_FALSE if it wasn’t blocked to begin with, or another HRESULT describing what went wrong.

HRESULT UnblockProcessImage()
   static const WCHAR streamName[] = L":Zone.Identifier";

   WCHAR fileName[MAX_PATH + _countof(streamName)] = { 0 };
   DWORD length = MAX_PATH; // Deliberately not the actual size

#if _WIN32_WINNT >= 0x0600

   // QueryFullProcessImageName updates the length parameter.
   if (!::QueryFullProcessImageName(::GetCurrentProcess(),
                                    0, // flags
       return HRESULT_FROM_WIN32(::GetLastError());


   // GetModuleFileNameEx returns the length.
   length = ::GetModuleFileNameEx(::GetCurrentProcess(),
                                  0, // module

   if (0 == length)
       return HRESULT_FROM_WIN32(::GetLastError());


   wcscpy_s(fileName + length, _countof(fileName) - length, streamName);

   if (!::DeleteFile(fileName))
       const DWORD error = ::GetLastError();

       if (ERROR_FILE_NOT_FOUND == error)
           return S_FALSE;
           return HRESULT_FROM_WIN32(error);

   return S_OK;

Please understand that I’m not advising developers to do this. I’m merely demonstrating that it is possible. A better solution is to simply ship your product with an installer, which is exactly what the next version of Window Clippings will provide.

Produce the highest quality screenshots! Use Window Clippings.


  • I feel you are missing the point here, someone starting the process from cmd.exe (or some other app that uses CreateProcess) is not the target of this dialog.

  • asf: you may have missed my point. :)

    I guess if I had to sum it up I’d say: its not secure, its a bad user experience, we can make the user experience slightly less painful by using something like UnblockProcessImage, and we should just use an installer.

    To put it into perspective, this dialog box causes the majority of the support emails I receive for Window Clippings.

  • Also frustrating is that when you are crazy enough to create a folder in the programs folders without an installer, it seems to be almost impossible to get that sucker to unblock. You can unclick and unclick again that checkbox. No warnings - just no results. The only work around that I've found is to move it to your desktop (or anywhere that you'll have rights to) and unblock from there, and then move it back.

    That makes sense now that you've shown what's going on behind the scenes, but I figured it'd at least popup the UAC stuff for me when I click the unblock button if I don't have permissions to do so.

  • Phil Scott: yeah it’s very unreliable.

  • Hello,

    The article is indeed very interesting, it's nice to find out about the inner working of this warning prompt, and its limitations, however I still think it's valuable to have it in place, sometimes I have an unknown executable that I don't want to actually run for some reasons, and the prompt prevented a few mistakes.


  • Kenny: but is not about security, its just one final chance for a noob to stop and think about what they are about to run (Not that they do, but hey) Opera for example does not set the "mark of the internet" on files it downloads.

  • asf: I see what you’re saying. I still don't like it.

  • Kenny: will the version with the installer, really require an installer? Can I still put the Windows Clippings executable in my SVN repo so that I can get it from all my machines?

  • Brian: an installer will be provided with version 3 as that is a popular request and will reduce the support overhead from most users. The program itself does not however require a complex installation and I’m happy to continue offering it in binary form for XCOPY deployment if that is desired.

  • How about using IZoneIdentifier to inspect and to modify the zone identifier instead of unsupported stream modification?

  • patria: Nice. I wasn’t aware of that interface.

  • Thanks for info about streams.

    Besides that chibi-checkbox, what most people actually miss is the fact what one can disable ALL these useless dialogs. To do this, one should go to Security Settings of "Internet" zone, goto Miscellaneous -> Launching applications and unsafe files.
    [ ] Disable
    [x] Enable // Ta-da!
    [ ] Prompt

    (It says "Not secure" there, but how is that insecure, huh?)

Comments have been disabled for this content.