Introduction to the Protected Mode API

Protected Mode helps reduce the severity of threats to Windows Internet Explorer 7 and its extensions by eliminating the silent installation of malicious code through software vulnerabilities. Protected Mode accomplishes this goal using the integrity mechanisms of Windows Vista which restrict access to processes, files, and registry keys with higher integrity levels. The Protected Mode API enables software vendors to develop extensions and add-ons for Windows Internet Explorer that can interact with the file system and registry from a low integrity process, such as Protected Mode Internet Explorer.

This topic contains the following sections.

  • Finding Low Integrity Write Locations
  • Saving Files in Protected Mode
  • Related topics

Finding Low Integrity Write Locations

Extensions written for Internet Explorer 7 should write files and settings to a low integrity location, such as the Temporary Internet Files folder, by default. Low integrity locations enable write access for processes with a low privilege level. Writing to a low integrity location helps protect the system against potentially malicious data from the Internet.

To determine if Internet Explorer is running in Protected Mode, call the IEIsProtectedModeProcess function. To find a low integrity file or registry location that an in-process Internet Explorer extension can write to, call the IEGetWriteableFolderPath function or the IEGetWriteableHKCU function.

The following example uses the Protected Mode API to detect the integrity level of Internet Explorer and choose a low integrity write location for a registry setting.

#include iepmapi.h

HRESULT WriteSetting(LPCTSTR pszKey, LPCTSTR pszValue, LPCTSTR pszData)
{
   BOOL bIsProtected;
   HRESULT hr = IEIsProtectedModeProcess(&bIsProtected);
   
   if (SUCCEEDED(hr) && bIsProtected)
   {
      HKEY hKey;
      hr = IEGetWriteableHKCU(&hKey);
      if (SUCCEEDED(hr))
      {
         HKEY hMyKey;
         DWORD dwDisposition;
         LONG lRes = RegCreateKeyEx(
              hKey,         // Low integrity write location
              pszKey,       // Specified sub-key
              0L,           // Reserved
              NULL,         // Class
              REG_OPTION_NON_VOLATILE,
              KEY_SET_VALUE,
              NULL,         // Security Descriptor
              &hMyKey,      // NEW or EXISTING key
              &dwDisposition);
         
         if (ERROR_SUCCESS == lRes)
         {
            lRes = RegSetValueEx(hMyKey, pszValue, NULL, REG_SZ,
                      (CONST BYTE*)pszData, strlen(pszData) + 1));
            hr = HRESULT_FROM_WIN32(lRes);
            
            RegCloseKey(hMyKey);
         }
         else
            hr = HRESULT_FROM_WIN32(lRes);
         
         // Close the low integrity handle
         RegCloseKey(hKey);   
      }
   }
   else
   {
      // IE not in protected mode
   }

   return hr;
}

Saving Files in Protected Mode

When Microsoft ActiveX controls and other extensions are running in Protected Mode, they cannot directly download files outside the Temporary Internet Files, History, Cookies, and Temp folders. File operations that attempt to write to other locations are intercepted and redirected to a "virtualized" location in a low integrity area. To save a file outside the virtualized location, extensions can use the following two Protected Mode API functions.

  1. IEShowSaveFileDialog—Call this function with a target location of the file that you want the user to save to. The user is prompted with the Save As dialog box, and the function returns the destination file path that the user specified.
  2. IESaveFile—Call this function with the handle returned from the previous operation and the temporary file path to the download location. The Protected Mode User Broker process copies the file from the temporary location to the target location. To free the associated memory without saving the file, call IECancelSaveFile.

The following example shows how to use the Protect Mode API to perform an elevated privilege file save operation. In this example, the data is written to a temporary location prior to the save operation, which copies the file in a user-mode operation to a higher privileged area. If the file has already been downloaded to the Internet cache, this step is not necessary.

#include iepmapi.h

// NOTE: Caller must free *ppszDest with CoTaskMemFree
HRESULT SaveFileData(
         LPWSTR pszName,    // Desired file name and path
         BYTE* pbData,      // Data for save
         UINT cbBytes,      // Count of bytes in pbData
         LPWSTR* ppszDest)  // OUT: final save location
{
   LPWSTR pszTempPath;
   HRESULT hr;
   
   hr = IEGetWriteableFolderPath(
         FOLDERID_InternetCache,   // Temporary Internet Files
         &pszTempPath);
      
   if (S_OK == hr)  // S_FALSE means no access to folder
   {
      // Create a temporary file. 
      TCHAR szTempName[MAX_PATH];
      GetTempFileNameW(
             pszTempPath, // Directory for temp files 
             _T("tmp"),   // Temp file name prefix 
             0,           // Create unique name 
             szTempName); // Buffer for name 
      
      HANDLE hTempFile;
      hTempFile = CreateFile(
             (LPTSTR)szTempName,           // File name 
             GENERIC_READ | GENERIC_WRITE, // Open for read/write 
             0,                            // Do not share 
             NULL,                         // Default security 
             CREATE_ALWAYS,                // Overwrite existing file
             FILE_ATTRIBUTE_NORMAL,        // Normal file 
             NULL);                        // No template 
      
      if (INVALID_HANDLE_VALUE != hTempFile) 
      { 
         DWORD dwBytesWritten;
         
         // Save the file
         WriteFile(hTempFile, pbData, cbBytes, 
                   &dwBytesWritten, NULL); 
         ASSERT(dwBytesWritten == cbBytes);
         CloseHandle(hTempFile);
         
         // Show the SaveAs dialog
         hr = SaveFileProtected(pszName,
                   (LPWSTR)szTempName, ppszDest);
         
         DeleteFile((LPCTSTR)szTempName);
      }
      else
      {
         // Could not create temporary file
         hr = HRESULT_FROM_WIN32(GetLastError());
      }
      
      // Free memory
      CoTaskMemFree(pszTempPath);
   }
   
   return hr;
}
 
// RETURNS: S_OK, or S_FALSE if canceled.
// NOTE: Caller must free *ppszDest with CoTaskMemFree
HRESULT SaveFileProtected(
         LPWSTR pszName,     // Desired name and path
         LPWSTR pszSource,   // Current file location
         LPWSTR *ppszDest)   // OUT: path to saved file
{
   LPCWSTR pszExt = L"Text Files|*.txt|All Files|*.*|";
   LPCWSTR pszDefExt = L"txt";
   HANDLE  hState; // No need to call CloseHandle on this
   
   if (ppszDest) *ppszDest = NULL;
   
   HRESULT hr = IEShowSaveFileDialog(
          g_hwnd,       // Application window (global)
          pszName,      // Initial filename and path
          NULL,         // Use path from filename
          pszExt,       // Extension filter list
          pszDefExt,    // Default extension
          1,            // Filter index
          OFN_ENABLESIZING | OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT,
          ppszDest,     // Selected destination
          &hState);     // Used to complete the operation
         
   if (S_OK == hr)  // S_FALSE if user cancels the operation
   {
      hr = IESaveFile(hState, pszSource);
      hState = NULL;   // hState SHOULD NOT be used again; set to NULL
   }
   
   return hr;
}

Understanding and Working in Protected Mode Internet Explorer