Index: base/file_util_win.cc |
diff --git a/base/file_util_win.cc b/base/file_util_win.cc |
index 39317a3a932777a3a10f635ba9024f7a92a4746e..e4ad6401c6114423cdf48a1561140521cd0e2392 100644 |
--- a/base/file_util_win.cc |
+++ b/base/file_util_win.cc |
@@ -24,6 +24,7 @@ |
#include "base/strings/utf_string_conversions.h" |
#include "base/threading/thread_restrictions.h" |
#include "base/time/time.h" |
+#include "base/win/scoped_comptr.h" |
#include "base/win/scoped_handle.h" |
#include "base/win/windows_version.h" |
@@ -31,6 +32,12 @@ namespace base { |
namespace { |
+// This GUID is associated with any 'don't ask me again' settings that the |
+// user can select for different file types. |
+// {2676A9A2-D919-4fee-9187-152100393AB2} |
+const GUID kClientID = { 0x2676a9a2, 0xd919, 0x4fee, |
brettw
2013/08/05 23:22:18
I don't get what this is. Is this the GUID of the
Greg Billock
2013/08/06 15:10:24
Yeah, I'm not sure what to do with this. It was in
|
+ { 0x91, 0x87, 0x15, 0x21, 0x0, 0x39, 0x3a, 0xb2 } }; |
+ |
const DWORD kFileShareAll = |
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; |
@@ -72,6 +79,36 @@ bool ShellCopy(const FilePath& from_path, |
return (SHFileOperation(&file_operation) == 0); |
} |
+// Sets the Zone Identifier on the file to "Internet" (3). Returns true if the |
+// function succeeds, false otherwise. A failure is expected on system where |
+// the Zone Identifier is not supported, like a machine with a FAT32 filesystem. |
+// This function does not invoke Windows Attachment Execution Services. |
+// |
+// |full_path| is the path to the downloaded file. |
+bool SetInternetZoneIdentifierDirectly(const base::FilePath& full_path) { |
+ const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; |
+ std::wstring path = full_path.value() + L":Zone.Identifier"; |
+ HANDLE file = CreateFile(path.c_str(), GENERIC_WRITE, kShare, NULL, |
+ OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
+ if (INVALID_HANDLE_VALUE == file) |
+ return false; |
+ |
+ static const char kIdentifier[] = "[ZoneTransfer]\r\nZoneId=3\r\n"; |
+ // Don't include trailing null in data written. |
+ static const DWORD kIdentifierSize = arraysize(kIdentifier) - 1; |
+ DWORD written = 0; |
+ BOOL result = WriteFile(file, kIdentifier, kIdentifierSize, &written, NULL); |
+ BOOL flush_result = FlushFileBuffers(file); |
+ CloseHandle(file); |
+ |
+ if (!result || !flush_result || written != kIdentifierSize) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
} // namespace |
FilePath MakeAbsoluteFilePath(const FilePath& input) { |
@@ -147,6 +184,41 @@ bool DeleteFileAfterReboot(const FilePath& path) { |
MOVEFILE_REPLACE_EXISTING) != FALSE; |
} |
+HRESULT ScanAndSaveDownloadedFile(const base::FilePath& full_path, |
brettw
2013/08/05 23:22:18
Why is this file called "Save" downloaded file? It
Greg Billock
2013/08/06 15:10:24
This is copy-pasted from the code in content/. I'm
|
+ const std::string& source_url) { |
+ base::win::ScopedComPtr<IAttachmentExecute> attachment_services; |
+ HRESULT hr = attachment_services.CreateInstance(CLSID_AttachmentServices); |
+ |
+ if (FAILED(hr)) { |
+ // The thread must have COM initialized. |
+ DCHECK_NE(CO_E_NOTINITIALIZED, hr); |
+ |
+ // We don't have Attachment Execution Services, it must be a pre-XP.SP2 |
+ // Windows installation, or the thread does not have COM initialized. Try to |
+ // set the zone information directly. Failure is not considered an error. |
+ SetInternetZoneIdentifierDirectly(full_path); |
+ return hr; |
+ } |
+ |
+ hr = attachment_services->SetClientGuid(kClientID); |
+ if (FAILED(hr)) |
+ return hr; |
+ |
+ hr = attachment_services->SetLocalPath(full_path.value().c_str()); |
+ if (FAILED(hr)) |
+ return hr; |
+ |
+ if (!source_url.empty()) { |
+ hr = attachment_services->SetSource(UTF8ToWide(source_url).c_str()); |
+ if (FAILED(hr)) |
+ return hr; |
+ } |
+ |
+ // A failure in the Save() call below could result in the downloaded file |
+ // being deleted. |
+ return attachment_services->Save(); |
+} |
+ |
bool ReplaceFile(const FilePath& from_path, |
const FilePath& to_path, |
PlatformFileError* error) { |