147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32filesystem.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h"
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <shellapi.h>
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <shlobj.h>
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <tchar.h>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/fileutils.h"
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/pathutils.h"
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/scoped_ptr.h"
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stream.h"
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringutils.h"
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// In several places in this file, we test the integrity level of the process
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// before calling GetLongPathName. We do this because calling GetLongPathName
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// when running under protected mode IE (a low integrity process) can result in
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// a virtualized path being returned, which is wrong if you only plan to read.
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO: Waiting to hear back from IE team on whether this is the
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// best approach; IEIsProtectedModeProcess is another possible solution.
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::CreateFolder(const Pathname &pathname) {
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (pathname.pathname().empty() || !pathname.filename().empty())
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::wstring path16;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!Utf8ToWindowsFilename(pathname.pathname(), &path16))
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD res = ::GetFileAttributes(path16.c_str());
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (res != INVALID_FILE_ATTRIBUTES) {
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Something exists at this location, check if it is a directory
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0);
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if ((GetLastError() != ERROR_FILE_NOT_FOUND)
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org              && (GetLastError() != ERROR_PATH_NOT_FOUND)) {
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Unexpected error
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Directory doesn't exist, look up one directory level
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!pathname.parent_folder().empty()) {
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Pathname parent(pathname);
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    parent.SetFolder(pathname.parent_folder());
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!CreateFolder(parent)) {
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (::CreateDirectory(path16.c_str(), NULL) != 0);
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgFileStream *Win32Filesystem::OpenFile(const Pathname &filename,
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      const std::string &mode) {
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FileStream *fs = new FileStream();
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str(), NULL)) {
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete fs;
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    fs = NULL;
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return fs;
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // To make the file private to the current user, we first must construct a
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // SECURITY_DESCRIPTOR specifying an ACL. This code is mostly based upon
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // http://msdn.microsoft.com/en-us/library/ms707085%28VS.85%29.aspx
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Get the current process token.
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HANDLE process_token = INVALID_HANDLE_VALUE;
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::OpenProcessToken(::GetCurrentProcess(),
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                          TOKEN_QUERY,
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                          &process_token)) {
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "OpenProcessToken() failed";
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Get the size of its TOKEN_USER structure. Return value is not checked
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // because we expect it to fail.
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD token_user_size = 0;
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  (void)::GetTokenInformation(process_token,
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              TokenUser,
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              NULL,
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              0,
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              &token_user_size);
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Get the TOKEN_USER structure.
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_ptr<char[]> token_user_bytes(new char[token_user_size]);
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      token_user_bytes.get());
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  memset(token_user, 0, token_user_size);
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  BOOL success = ::GetTokenInformation(process_token,
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                       TokenUser,
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                       token_user,
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                       token_user_size,
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                       &token_user_size);
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // We're now done with this.
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ::CloseHandle(process_token);
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!success) {
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "GetTokenInformation() failed";
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsValidSid(token_user->User.Sid)) {
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "Current process has invalid user SID";
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Compute size needed for an ACL that allows access to just this user.
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      GetLengthSid(token_user->User.Sid);
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Allocate it.
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_ptr<char[]> acl_bytes(new char[acl_size]);
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  memset(acl, 0, acl_size);
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "InitializeAcl() failed";
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Allow access to only the current user.
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::AddAccessAllowedAce(acl,
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             ACL_REVISION,
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL,
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                             token_user->User.Sid)) {
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "AddAccessAllowedAce() failed";
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Now make the security descriptor.
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SECURITY_DESCRIPTOR security_descriptor;
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::InitializeSecurityDescriptor(&security_descriptor,
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      SECURITY_DESCRIPTOR_REVISION)) {
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "InitializeSecurityDescriptor() failed";
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Put the ACL in it.
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::SetSecurityDescriptorDacl(&security_descriptor,
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   TRUE,
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   acl,
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                   FALSE)) {
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "SetSecurityDescriptorDacl() failed";
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Finally create the file.
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SECURITY_ATTRIBUTES security_attributes;
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  security_attributes.nLength = sizeof(security_attributes);
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  security_attributes.lpSecurityDescriptor = &security_descriptor;
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  security_attributes.bInheritHandle = FALSE;
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HANDLE handle = ::CreateFile(
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ToUtf16(filename.pathname()).c_str(),
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      GENERIC_READ | GENERIC_WRITE,
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      &security_attributes,
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      CREATE_NEW,
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      0,
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      NULL);
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (INVALID_HANDLE_VALUE == handle) {
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "CreateFile() failed";
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::CloseHandle(handle)) {
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_ERROR) << "CloseFile() failed";
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Continue.
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::DeleteFile(const Pathname &filename) {
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "Deleting file " << filename.pathname();
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsFile(filename)) {
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(IsFile(filename));
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0;
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::DeleteEmptyFolder(const Pathname &folder) {
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "Deleting folder " << folder.pathname();
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string no_slash(folder.pathname(), 0, folder.pathname().length()-1);
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ::RemoveDirectory(ToUtf16(no_slash).c_str()) != 0;
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetTemporaryFolder(Pathname &pathname, bool create,
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                         const std::string *append) {
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  wchar_t buffer[MAX_PATH + 1];
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsCurrentProcessLowIntegrity() &&
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t len = strlen(buffer);
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((len > 0) && (buffer[len-1] != '\\')) {
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, L"\\");
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (len >= ARRAY_SIZE(buffer) - 1)
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pathname.clear();
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pathname.SetFolder(ToUtf8(buffer));
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (append != NULL) {
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(!append->empty());
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    pathname.AppendFolder(*append);
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return !create || CreateFolder(pathname);
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string Win32Filesystem::TempFilename(const Pathname &dir,
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                          const std::string &prefix) {
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  wchar_t filename[MAX_PATH];
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (::GetTempFileName(ToUtf16(dir.pathname()).c_str(),
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                        ToUtf16(prefix).c_str(), 0, filename) != 0)
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ToUtf8(filename);
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(false);
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return "";
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::MoveFile(const Pathname &old_path,
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                               const Pathname &new_path) {
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsFile(old_path)) {
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(IsFile(old_path));
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "Moving " << old_path.pathname()
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               << " to " << new_path.pathname();
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ::MoveFile(ToUtf16(old_path.pathname()).c_str(),
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    ToUtf16(new_path.pathname()).c_str()) != 0;
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::MoveFolder(const Pathname &old_path,
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const Pathname &new_path) {
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsFolder(old_path)) {
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(IsFolder(old_path));
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_INFO) << "Moving " << old_path.pathname()
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               << " to " << new_path.pathname();
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (::MoveFile(ToUtf16(old_path.pathname()).c_str(),
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org               ToUtf16(new_path.pathname()).c_str()) == 0) {
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (::GetLastError() != ERROR_NOT_SAME_DEVICE) {
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_GLE(LS_ERROR) << "Failed to move file";
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!CopyFolder(old_path, new_path))
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!DeleteFolderAndContents(old_path))
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::IsFolder(const Pathname &path) {
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WIN32_FILE_ATTRIBUTE_DATA data = {0};
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 GetFileExInfoStandard, &data))
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      FILE_ATTRIBUTE_DIRECTORY;
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::IsFile(const Pathname &path) {
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WIN32_FILE_ATTRIBUTE_DATA data = {0};
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 GetFileExInfoStandard, &data))
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0;
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::IsAbsent(const Pathname& path) {
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WIN32_FILE_ATTRIBUTE_DATA data = {0};
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 != ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 GetFileExInfoStandard, &data))
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD err = ::GetLastError();
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (ERROR_FILE_NOT_FOUND == err || ERROR_PATH_NOT_FOUND == err);
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::CopyFile(const Pathname &old_path,
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                               const Pathname &new_path) {
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ::CopyFile(ToUtf16(old_path.pathname()).c_str(),
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                    ToUtf16(new_path.pathname()).c_str(), TRUE) != 0;
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::IsTemporaryPath(const Pathname& pathname) {
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TCHAR buffer[MAX_PATH + 1];
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::GetTempPath(ARRAY_SIZE(buffer), buffer))
29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsCurrentProcessLowIntegrity() &&
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (::strnicmp(ToUtf16(pathname.pathname()).c_str(),
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                     buffer, strlen(buffer)) == 0);
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetFileSize(const Pathname &pathname, size_t *size) {
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WIN32_FILE_ATTRIBUTE_DATA data = {0};
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (::GetFileAttributesEx(ToUtf16(pathname.pathname()).c_str(),
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                            GetFileExInfoStandard, &data) == 0)
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return false;
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *size = data.nFileSizeLow;
31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetFileTime(const Pathname& path, FileTimeType which,
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                  time_t* time) {
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WIN32_FILE_ATTRIBUTE_DATA data = {0};
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                            GetFileExInfoStandard, &data) == 0)
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  switch (which) {
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case FTT_CREATED:
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    FileTimeToUnixTime(data.ftCreationTime, time);
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case FTT_MODIFIED:
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    FileTimeToUnixTime(data.ftLastWriteTime, time);
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  case FTT_ACCESSED:
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    FileTimeToUnixTime(data.ftLastAccessTime, time);
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    break;
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  default:
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetAppPathname(Pathname* path) {
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TCHAR buffer[MAX_PATH + 1];
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 == ::GetModuleFileName(NULL, buffer, ARRAY_SIZE(buffer)))
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  path->SetPathname(ToUtf8(buffer));
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetAppDataFolder(Pathname* path, bool per_user) {
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(!organization_name_.empty());
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(!application_name_.empty());
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TCHAR buffer[MAX_PATH + 1];
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int csidl = per_user ? CSIDL_LOCAL_APPDATA : CSIDL_COMMON_APPDATA;
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!::SHGetSpecialFolderPath(NULL, buffer, csidl, TRUE))
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsCurrentProcessLowIntegrity() &&
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      !::GetLongPathName(buffer, buffer, ARRAY_SIZE(buffer)))
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t len = strcatn(buffer, ARRAY_SIZE(buffer), __T("\\"));
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                 ToUtf16(organization_name_).c_str());
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((len > 0) && (buffer[len-1] != __T('\\'))) {
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\"));
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len,
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                 ToUtf16(application_name_).c_str());
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ((len > 0) && (buffer[len-1] != __T('\\'))) {
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    len += strcpyn(buffer + len, ARRAY_SIZE(buffer) - len, __T("\\"));
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (len >= ARRAY_SIZE(buffer) - 1)
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  path->clear();
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  path->SetFolder(ToUtf8(buffer));
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return CreateFolder(*path);
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetAppTempFolder(Pathname* path) {
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!GetAppPathname(path))
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string filename(path->filename());
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return GetTemporaryFolder(*path, true, &filename);
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Win32Filesystem::GetDiskFreeSpace(const Pathname& path, int64 *freebytes) {
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!freebytes) {
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  char drive[4];
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::wstring drive16;
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  const wchar_t* target_drive = NULL;
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (path.GetDrive(drive, sizeof(drive))) {
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    drive16 = ToUtf16(drive);
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    target_drive = drive16.c_str();
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (path.folder().substr(0, 2) == "\\\\") {
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // UNC path, fail.
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // TODO: Handle UNC paths.
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // The path is probably relative.  GetDriveType and GetDiskFreeSpaceEx
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // use the current drive if NULL is passed as the drive name.
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // TODO: Add method to Pathname to determine if the path is relative.
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // TODO: Add method to Pathname to convert a path to absolute.
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  UINT driveType = ::GetDriveType(target_drive);
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if ( (driveType & DRIVE_REMOTE) || (driveType & DRIVE_UNKNOWN) ) {
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_VERBOSE) << " remove or unknown drive " << drive;
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int64 totalNumberOfBytes;  // receives the number of bytes on disk
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int64 totalNumberOfFreeBytes;  // receives the free bytes on disk
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // make sure things won't change in 64 bit machine
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO replace with compile time assert
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(sizeof(ULARGE_INTEGER) == sizeof(uint64));  //NOLINT
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (::GetDiskFreeSpaceEx(target_drive,
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                           (PULARGE_INTEGER)freebytes,
41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                           (PULARGE_INTEGER)&totalNumberOfBytes,
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                           (PULARGE_INTEGER)&totalNumberOfFreeBytes)) {
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_VERBOSE) << " GetDiskFreeSpaceEx returns error ";
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgPathname Win32Filesystem::GetCurrentDirectory() {
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Pathname cwd;
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int path_len = 0;
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scoped_ptr<wchar_t[]> path;
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  do {
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    int needed = ::GetCurrentDirectory(path_len, path.get());
42947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (needed == 0) {
43047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Error.
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_GLE(LS_ERROR) << "::GetCurrentDirectory() failed";
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return cwd;  // returns empty pathname
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (needed <= path_len) {
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // It wrote successfully.
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Else need to re-alloc for "needed".
43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    path.reset(new wchar_t[needed]);
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    path_len = needed;
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } while (true);
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  cwd.SetFolder(ToUtf8(path.get()));
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return cwd;
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// TODO: Consider overriding DeleteFolderAndContents for speed and potentially
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// better OS integration (recycle bin?)
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::wstring temp_path16 = ToUtf16(temp_path.pathname());
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  temp_path16.append(1, '*');
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  temp_path16.append(1, '\0');
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
45347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SHFILEOPSTRUCT file_op = { 0 };
45447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  file_op.wFunc = FO_DELETE;
45547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  file_op.pFrom = temp_path16.c_str();
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (0 == SHFileOperation(&file_op));
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org*/
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
461