1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2006, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32filesystem.h" 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/win32.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <shellapi.h> 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <shlobj.h> 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <tchar.h> 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/fileutils.h" 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/pathutils.h" 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/scoped_ptr.h" 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/stream.h" 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/stringutils.h" 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// In several places in this file, we test the integrity level of the process 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// before calling GetLongPathName. We do this because calling GetLongPathName 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// when running under protected mode IE (a low integrity process) can result in 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// a virtualized path being returned, which is wrong if you only plan to read. 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// TODO: Waiting to hear back from IE team on whether this is the 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// best approach; IEIsProtectedModeProcess is another possible solution. 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::CreateFolder(const Pathname &pathname) { 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pathname.pathname().empty() || !pathname.filename().empty()) 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::wstring path16; 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!Utf8ToWindowsFilename(pathname.pathname(), &path16)) 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD res = ::GetFileAttributes(path16.c_str()); 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (res != INVALID_FILE_ATTRIBUTES) { 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Something exists at this location, check if it is a directory 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0); 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if ((GetLastError() != ERROR_FILE_NOT_FOUND) 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch && (GetLastError() != ERROR_PATH_NOT_FOUND)) { 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Unexpected error 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Directory doesn't exist, look up one directory level 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!pathname.parent_folder().empty()) { 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Pathname parent(pathname); 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch parent.SetFolder(pathname.parent_folder()); 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!CreateFolder(parent)) { 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (::CreateDirectory(path16.c_str(), NULL) != 0); 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochFileStream *Win32Filesystem::OpenFile(const Pathname &filename, 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::string &mode) { 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FileStream *fs = new FileStream(); 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str())) { 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete fs; 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch fs = NULL; 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return fs; 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Win32Filesystem::CreatePrivateFile(const Pathname &filename) { 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // To make the file private to the current user, we first must construct a 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // SECURITY_DESCRIPTOR specifying an ACL. This code is mostly based upon 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // http://msdn.microsoft.com/en-us/library/ms707085%28VS.85%29.aspx 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Get the current process token. 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HANDLE process_token = INVALID_HANDLE_VALUE; 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::OpenProcessToken(GetCurrentProcess(), 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TOKEN_QUERY, 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &process_token)) { 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "OpenProcessToken() failed"; 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Get the size of its TOKEN_USER structure. Return value is not checked 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // because we expect it to fail. 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DWORD token_user_size = 0; 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick (void)::GetTokenInformation(process_token, 1083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TokenUser, 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL, 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &token_user_size); 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Get the TOKEN_USER structure. 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_array<char> token_user_bytes(new char[token_user_size]); 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>( 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick token_user_bytes.get()); 1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memset(token_user, 0, token_user_size); 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick BOOL success = ::GetTokenInformation(process_token, 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TokenUser, 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick token_user, 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick token_user_size, 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &token_user_size); 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We're now done with this. 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ::CloseHandle(process_token); 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!success) { 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "GetTokenInformation() failed"; 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!IsValidSid(token_user->User.Sid)) { 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "Current process has invalid user SID"; 1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Compute size needed for an ACL that allows access to just this user. 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GetLengthSid(token_user->User.Sid); 1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Allocate it. 1403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_array<char> acl_bytes(new char[acl_size]); 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PACL acl = reinterpret_cast<PACL>(acl_bytes.get()); 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick memset(acl, 0, acl_size); 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) { 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "InitializeAcl() failed"; 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Allow access to only the current user. 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::AddAccessAllowedAce(acl, 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ACL_REVISION, 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL, 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick token_user->User.Sid)) { 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "AddAccessAllowedAce() failed"; 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Now make the security descriptor. 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECURITY_DESCRIPTOR security_descriptor; 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::InitializeSecurityDescriptor(&security_descriptor, 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECURITY_DESCRIPTOR_REVISION)) { 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "InitializeSecurityDescriptor() failed"; 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Put the ACL in it. 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::SetSecurityDescriptorDacl(&security_descriptor, 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick TRUE, 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick acl, 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FALSE)) { 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "SetSecurityDescriptorDacl() failed"; 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Finally create the file. 1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECURITY_ATTRIBUTES security_attributes; 1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick security_attributes.nLength = sizeof(security_attributes); 1773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick security_attributes.lpSecurityDescriptor = &security_descriptor; 1783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick security_attributes.bInheritHandle = FALSE; 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HANDLE handle = ::CreateFile( 1803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ToUtf16(filename.pathname()).c_str(), 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GENERIC_READ | GENERIC_WRITE, 1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &security_attributes, 1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CREATE_NEW, 1853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 0, 1863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NULL); 1873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (INVALID_HANDLE_VALUE == handle) { 1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "CreateFile() failed"; 1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!::CloseHandle(handle)) { 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG_ERR(LS_ERROR) << "CloseFile() failed"; 1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Continue. 1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::DeleteFile(const Pathname &filename) { 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Deleting file " << filename.pathname(); 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsFile(filename)) { 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(IsFile(filename)); 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0; 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::DeleteEmptyFolder(const Pathname &folder) { 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Deleting folder " << folder.pathname(); 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string no_slash(folder.pathname(), 0, folder.pathname().length()-1); 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::RemoveDirectory(ToUtf16(no_slash).c_str()) != 0; 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetTemporaryFolder(Pathname &pathname, bool create, 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::string *append) { 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wchar_t buffer[MAX_PATH + 1]; 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!::GetTempPath(ARRAY_SIZE(buffer), buffer)) 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsCurrentProcessLowIntegrity() && 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer))) 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t len = strlen(buffer); 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((len > 0) && (buffer[len-1] != '\\')) { 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, L"\\"); 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (len >= ARRAY_SIZE(buffer) - 1) 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pathname.clear(); 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pathname.SetFolder(ToUtf8(buffer)); 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (append != NULL) { 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!append->empty()); 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pathname.AppendFolder(*append); 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return !create || CreateFolder(pathname); 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstd::string Win32Filesystem::TempFilename(const Pathname &dir, 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const std::string &prefix) { 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch wchar_t filename[MAX_PATH]; 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::GetTempFileName(ToUtf16(dir.pathname()).c_str(), 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(prefix).c_str(), 0, filename) != 0) 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ToUtf8(filename); 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(false); 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ""; 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::MoveFile(const Pathname &old_path, 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const Pathname &new_path) { 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsFile(old_path)) { 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(IsFile(old_path)); 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Moving " << old_path.pathname() 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " to " << new_path.pathname(); 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::MoveFile(ToUtf16(old_path.pathname()).c_str(), 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(new_path.pathname()).c_str()) != 0; 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::MoveFolder(const Pathname &old_path, 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const Pathname &new_path) { 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsFolder(old_path)) { 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(IsFolder(old_path)); 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_INFO) << "Moving " << old_path.pathname() 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch << " to " << new_path.pathname(); 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::MoveFile(ToUtf16(old_path.pathname()).c_str(), 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(new_path.pathname()).c_str()) == 0) { 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::GetLastError() != ERROR_NOT_SAME_DEVICE) { 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_GLE(LS_ERROR) << "Failed to move file"; 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!CopyFolder(old_path, new_path)) 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!DeleteFolderAndContents(old_path)) 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::IsFolder(const Pathname &path) { 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WIN32_FILE_ATTRIBUTE_DATA data = {0}; 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetFileExInfoStandard, &data)) 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FILE_ATTRIBUTE_DIRECTORY; 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::IsFile(const Pathname &path) { 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WIN32_FILE_ATTRIBUTE_DATA data = {0}; 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetFileExInfoStandard, &data)) 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::IsAbsent(const Pathname& path) { 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WIN32_FILE_ATTRIBUTE_DATA data = {0}; 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 != ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetFileExInfoStandard, &data)) 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD err = ::GetLastError(); 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (ERROR_FILE_NOT_FOUND == err || ERROR_PATH_NOT_FOUND == err); 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::CopyFile(const Pathname &old_path, 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const Pathname &new_path) { 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return ::CopyFile(ToUtf16(old_path.pathname()).c_str(), 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(new_path.pathname()).c_str(), TRUE) != 0; 311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::IsTemporaryPath(const Pathname& pathname) { 314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TCHAR buffer[MAX_PATH + 1]; 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!::GetTempPath(ARRAY_SIZE(buffer), buffer)) 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsCurrentProcessLowIntegrity() && 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer))) 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (::strnicmp(ToUtf16(pathname.pathname()).c_str(), 321f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch buffer, strlen(buffer)) == 0); 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 323f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 324f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetFileSize(const Pathname &pathname, size_t *size) { 325f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WIN32_FILE_ATTRIBUTE_DATA data = {0}; 326f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::GetFileAttributesEx(ToUtf16(pathname.pathname()).c_str(), 327f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetFileExInfoStandard, &data) == 0) 328f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 329f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *size = data.nFileSizeLow; 330f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 332f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetFileTime(const Pathname& path, FileTimeType which, 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch time_t* time) { 335f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WIN32_FILE_ATTRIBUTE_DATA data = {0}; 336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), 337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch GetFileExInfoStandard, &data) == 0) 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch switch (which) { 340f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FTT_CREATED: 341f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FileTimeToUnixTime(data.ftCreationTime, time); 342f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 343f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FTT_MODIFIED: 344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FileTimeToUnixTime(data.ftLastWriteTime, time); 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch case FTT_ACCESSED: 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch FileTimeToUnixTime(data.ftLastAccessTime, time); 348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch default: 350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetAppPathname(Pathname* path) { 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TCHAR buffer[MAX_PATH + 1]; 357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 == ::GetModuleFileName(NULL, buffer, ARRAY_SIZE(buffer))) 358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch path->SetPathname(ToUtf8(buffer)); 360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetAppDataFolder(Pathname* path, bool per_user) { 364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!organization_name_.empty()); 365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!application_name_.empty()); 366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TCHAR buffer[MAX_PATH + 1]; 367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int csidl = per_user ? CSIDL_LOCAL_APPDATA : CSIDL_COMMON_APPDATA; 368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!::SHGetSpecialFolderPath(NULL, buffer, csidl, TRUE)) 369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!IsCurrentProcessLowIntegrity() && 371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer))) 372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch size_t len = strcatn(buffer, ARRAY_SIZE(buffer), __T("\\")); 374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, 375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(organization_name_).c_str()); 376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((len > 0) && (buffer[len-1] != __T('\\'))) { 377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\")); 378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, 380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ToUtf16(application_name_).c_str()); 381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ((len > 0) && (buffer[len-1] != __T('\\'))) { 382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\")); 383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (len >= ARRAY_SIZE(buffer) - 1) 385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch path->clear(); 387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch path->SetFolder(ToUtf8(buffer)); 388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return CreateFolder(*path); 389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetAppTempFolder(Pathname* path) { 392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!GetAppPathname(path)) 393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::string filename(path->filename()); 395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return GetTemporaryFolder(*path, true, &filename); 396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) { 399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!freebytes) { 400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch char drive[4]; 403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::wstring drive16; 404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch const wchar_t* target_drive = NULL; 405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (path.GetDrive(drive, sizeof(drive))) { 406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch drive16 = ToUtf16(drive); 407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch target_drive = drive16.c_str(); 408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (path.folder().substr(0, 2) == "\\\\") { 409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // UNC path, fail. 410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // TODO: Handle UNC paths. 411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // The path is probably relative. GetDriveType and GetDiskFreeSpaceEx 414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // use the current drive if NULL is passed as the drive name. 415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // TODO: Add method to Pathname to determine if the path is relative. 416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // TODO: Add method to Pathname to convert a path to absolute. 417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UINT driveType = ::GetDriveType(target_drive); 419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if ( (driveType & DRIVE_REMOTE) || (driveType & DRIVE_UNKNOWN) ) { 420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_VERBOSE) << " remove or unknown drive " << drive; 421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 totalNumberOfBytes; // receives the number of bytes on disk 425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 totalNumberOfFreeBytes; // receives the free bytes on disk 426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // make sure things won't change in 64 bit machine 427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // TODO replace with compile time assert 428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(sizeof(ULARGE_INTEGER) == sizeof(uint64)); //NOLINT 429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (::GetDiskFreeSpaceEx(target_drive, 430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (PULARGE_INTEGER)freebytes, 431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (PULARGE_INTEGER)&totalNumberOfBytes, 432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (PULARGE_INTEGER)&totalNumberOfFreeBytes)) { 433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_VERBOSE) << " GetDiskFreeSpaceEx returns error "; 436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochPathname Win32Filesystem::GetCurrentDirectory() { 441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Pathname cwd; 442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int path_len = 0; 443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch scoped_array<wchar_t> path; 444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch do { 445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int needed = ::GetCurrentDirectory(path_len, path.get()); 446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (needed == 0) { 447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Error. 448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_GLE(LS_ERROR) << "::GetCurrentDirectory() failed"; 449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return cwd; // returns empty pathname 450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (needed <= path_len) { 452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // It wrote successfully. 453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch break; 454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Else need to re-alloc for "needed". 456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch path.reset(new wchar_t[needed]); 457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch path_len = needed; 458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } while (true); 459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cwd.SetFolder(ToUtf8(path.get())); 460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return cwd; 461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// TODO: Consider overriding DeleteFolderAndContents for speed and potentially 464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// better OS integration (recycle bin?) 465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::wstring temp_path16 = ToUtf16(temp_path.pathname()); 467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch temp_path16.append(1, '*'); 468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch temp_path16.append(1, '\0'); 469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SHFILEOPSTRUCT file_op = { 0 }; 471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch file_op.wFunc = FO_DELETE; 472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch file_op.pFrom = temp_path16.c_str(); 473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT; 474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return (0 == SHFileOperation(&file_op)); 475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch*/ 476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 478