diff --git a/core/includes/file.inc b/core/includes/file.inc
index 36204b0..54956a1 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -432,7 +432,7 @@ function file_ensure_htaccess() {
 }
 
 /**
- * Creates a .htaccess file in the given directory.
+ * Creates a .htaccess file for Apache or web.config file for IIS in the given directory.
  *
  * @param string $directory
  *   The directory.
@@ -440,31 +440,40 @@ function file_ensure_htaccess() {
  *   (Optional) FALSE indicates that $directory should be a web-accessible
  *   directory. Defaults to TRUE which indicates a private directory.
  * @param bool $force_overwrite
- *   (Optional) Set to TRUE to attempt to overwrite the existing .htaccess file
+ *   (Optional) Set to TRUE to attempt to overwrite the existing file
  *   if one is already present. Defaults to FALSE.
  */
 function file_save_htaccess($directory, $private = TRUE, $force_overwrite = FALSE) {
+  if (strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')) {
+    $server_is_iis = TRUE;
+    $htaccess_filename = 'web.config';
+  }
+  else {
+    $server_is_iis = FALSE;
+    $htaccess_filename = '.htaccess';
+  }
+
   if (file_uri_scheme($directory)) {
-    $htaccess_path = file_stream_wrapper_uri_normalize($directory . '/.htaccess');
+    $htaccess_path = file_stream_wrapper_uri_normalize($directory . DIRECTORY_SEPARATOR . $htaccess_filename);
   }
   else {
     $directory = rtrim($directory, '/\\');
-    $htaccess_path = $directory . '/.htaccess';
+    $htaccess_path = $directory . DIRECTORY_SEPARATOR . $htaccess_filename;
   }
 
   if (file_exists($htaccess_path) && !$force_overwrite) {
-    // Short circuit if the .htaccess file already exists.
+    // Short circuit if the .htaccess or web.config file already exists.
     return TRUE;
   }
-  $htaccess_lines = FileStorage::htaccessLines($private);
+  $htaccess_lines = ($server_is_iis) ? FileStorage::webconfigLines($private) : FileStorage::htaccessLines($private);
 
-  // Write the .htaccess file.
+  // Write the .htaccess or web.config file.
   if (file_exists($directory) && is_writable($directory) && file_put_contents($htaccess_path, $htaccess_lines)) {
     return drupal_chmod($htaccess_path, 0444);
   }
   else {
-    $variables = array('%directory' => $directory, '!htaccess' => '<br />' . nl2br(String::checkPlain($htaccess_lines)));
-    \Drupal::logger('security')->error("Security warning: Couldn't write .htaccess file. Please create a .htaccess file in your %directory directory which contains the following lines: <code>!htaccess</code>", $variables);
+    $variables = array('%directory' => $directory, '!htaccess' => '<br />' . nl2br(String::checkPlain($htaccess_lines)), '%filename' => $htaccess_filename);
+    \Drupal::logger('security')->error("Security warning: Couldn't write %filename file. Please create a %filename file in your %directory directory which contains the following lines: <code>!htaccess</code>", $variables);
     return FALSE;
   }
 }
diff --git a/core/lib/Drupal/Component/PhpStorage/FileStorage.php b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
index 71ff3f2..1ac4219 100644
--- a/core/lib/Drupal/Component/PhpStorage/FileStorage.php
+++ b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
@@ -54,9 +54,17 @@ public function load($name) {
   public function save($name, $code) {
     $path = $this->getFullPath($name);
     $directory = dirname($path);
+    if (strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')) {
+      $server_is_iis = TRUE;
+      $htaccess_filename = 'web.config';
+    }
+    else {
+      $server_is_iis = FALSE;
+      $htaccess_filename = '.htaccess';
+    }
     if ($this->ensureDirectory($directory)) {
-      $htaccess_path =  $directory . '/.htaccess';
-      if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, static::htaccessLines())) {
+      $htaccess_path =  $directory . DIRECTORY_SEPARATOR . $htaccess_filename;
+      if (!file_exists($htaccess_path) && file_put_contents($htaccess_path, ($server_is_iis) ? static::webconfigLines() : static::htaccessLines())) {
         @chmod($htaccess_path, 0444);
       }
     }
@@ -114,6 +122,59 @@ public static function htaccessLines($private = TRUE) {
   }
 
   /**
+   * Returns the standard web.config lines that Drupal writes to file directories
+   * on Microsoft IIS web servers.
+   *
+   * @param bool $private
+   *   (optional) Set to FALSE to return the .htaccess lines for an open and
+   *   public directory. The default is TRUE, which returns the web.config lines
+   *   for a private and protected directory.
+   *
+   * @return string
+   *   The desired contents of the web.config file.
+   *
+   * @see file_create_htaccess()
+   */
+  public static function webconfigLines($private = TRUE) {
+    if ($private) {
+      // Deny ALL access.
+      // See: https://msdn.microsoft.com/en-us/library/8aeskccd%28v=vs.85%29.aspx
+      $lines = <<<EOF
+<configuration>
+  <system.web>
+    <authorization>
+      <deny users="*"/>
+    </authorization>
+  </system.web>
+</configuration>
+EOF;
+    }
+    else {
+      // Clear the handlers for script execution. Only allow serving of flat files.
+      // See: https://groups.drupal.org/node/226059
+      $lines = <<<EOF
+<configuration>
+  <system.webServer>
+        <handlers>
+          <clear />
+          <add
+            name="StaticFile"
+            path="*"
+            verb="*"
+            modules="StaticFileModule"
+            resourceType="Either"
+            requireAccess="Read"
+          />
+        </handlers>
+  </system.webServer>
+</configuration>
+EOF;
+    }
+
+    return $lines;
+  }
+
+  /**
    * Ensures the directory exists, has the right permissions, and a .htaccess.
    *
    * For compatibility with open_basedir, the requested directory is created
