file_win.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/file.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h"
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/lazy_instance.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/disk_cache/disk_cache.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Structure used for asynchronous operations.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct MyOverlapped {
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped(disk_cache::File* file, size_t offset,
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               disk_cache::FileIOCallback* callback);
183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ~MyOverlapped() {}
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  OVERLAPPED* overlapped() {
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return &context_.overlapped;
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO::IOContext context_;
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<disk_cache::File> file_;
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  disk_cache::FileIOCallback* callback_;
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(!offsetof(MyOverlapped, context_), starts_with_overlapped);
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Helper class to handle the IO completion notifications from the message loop.
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass CompletionHandler : public MessageLoopForIO::IOHandler {
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             DWORD actual_bytes, DWORD error);
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic base::LazyInstance<CompletionHandler> g_completion_handler(
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    base::LINKER_INITIALIZED);
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CompletionHandler::OnIOCompleted(MessageLoopForIO::IOContext* context,
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      DWORD actual_bytes, DWORD error) {
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = reinterpret_cast<MyOverlapped*>(context);
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (error) {
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!actual_bytes);
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    actual_bytes = static_cast<DWORD>(-1);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED();
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (data->callback_)
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    data->callback_->OnFileIOComplete(static_cast<int>(actual_bytes));
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  delete data;
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           disk_cache::FileIOCallback* callback) {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(this, 0, sizeof(*this));
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  context_.handler = g_completion_handler.Pointer();
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  context_.overlapped.Offset = static_cast<DWORD>(offset);
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  file_ = file;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  callback_ = callback;
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace disk_cache {
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile::File(base::PlatformFile file)
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : init_(true), mixed_(true), platform_file_(INVALID_HANDLE_VALUE),
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sync_platform_file_(file) {
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Init(const FilePath& name) {
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!init_);
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (init_)
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DWORD sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DWORD access = GENERIC_READ | GENERIC_WRITE | DELETE;
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  platform_file_ = CreateFile(name.value().c_str(), access, sharing, NULL,
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                              OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE == platform_file_)
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoopForIO::current()->RegisterIOHandler(
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      platform_file_, g_completion_handler.Pointer());
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  init_ = true;
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  sync_platform_file_  = CreateFile(name.value().c_str(), access, sharing, NULL,
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    OPEN_EXISTING, 0, NULL);
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE == sync_platform_file_)
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFile::~File() {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_)
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE != platform_file_)
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandle(platform_file_);
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_HANDLE_VALUE != sync_platform_file_)
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    CloseHandle(sync_platform_file_);
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbase::PlatformFile File::platform_file() const {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (INVALID_HANDLE_VALUE == platform_file_) ? sync_platform_file_ :
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                    platform_file_;
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::IsValid() const {
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!init_)
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (INVALID_HANDLE_VALUE != platform_file_ ||
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          INVALID_HANDLE_VALUE != sync_platform_file_);
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Read(void* buffer, size_t buffer_len, size_t offset) {
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > LONG_MAX)
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD ret = SetFilePointer(sync_platform_file_, static_cast<LONG>(offset),
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             NULL, FILE_BEGIN);
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == ret)
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ReadFile(sync_platform_file_, buffer, size, &actual, NULL))
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return actual == size;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD ret = SetFilePointer(sync_platform_file_, static_cast<LONG>(offset),
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             NULL, FILE_BEGIN);
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == ret)
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!WriteFile(sync_platform_file_, buffer, size, &actual, NULL))
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return actual == size;
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We have to increase the ref counter of the file before performing the IO to
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// prevent the completion to happen with an invalid handle (if the file is
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// closed while the IO is in flight).
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Read(void* buffer, size_t buffer_len, size_t offset,
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                FileIOCallback* callback, bool* completed) {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!callback) {
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (completed)
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *completed = true;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return Read(buffer, buffer_len, offset);
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = new MyOverlapped(this, offset, callback);
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ReadFile(platform_file_, buffer, size, &actual, data->overlapped())) {
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *completed = false;
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GetLastError() == ERROR_IO_PENDING)
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete data;
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The operation completed already. We'll be called back anyway.
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *completed = (actual == size);
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(actual == size);
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->callback_ = NULL;
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->file_ = NULL;  // There is no reason to hold on to this anymore.
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return *completed;
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::Write(const void* buffer, size_t buffer_len, size_t offset,
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 FileIOCallback* callback, bool* completed) {
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!callback) {
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (completed)
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *completed = true;
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return Write(buffer, buffer_len, offset);
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return AsyncWrite(buffer, buffer_len, offset, callback, completed);
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                      FileIOCallback* callback, bool* completed) {
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(callback);
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(completed);
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MyOverlapped* data = new MyOverlapped(this, offset, callback);
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(buffer_len);
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD actual;
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!WriteFile(platform_file_, buffer, size, &actual, data->overlapped())) {
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *completed = false;
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GetLastError() == ERROR_IO_PENDING)
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete data;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The operation completed already. We'll be called back anyway.
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *completed = (actual == size);
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(actual == size);
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->callback_ = NULL;
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  data->file_ = NULL;  // There is no reason to hold on to this anymore.
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return *completed;
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool File::SetLength(size_t length) {
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (length > ULONG_MAX)
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DWORD size = static_cast<DWORD>(length);
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HANDLE file = platform_file();
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (INVALID_SET_FILE_POINTER == SetFilePointer(file, size, NULL, FILE_BEGIN))
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return TRUE == SetEndOfFile(file);
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t File::GetLength() {
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(init_);
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  LARGE_INTEGER size;
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HANDLE file = platform_file();
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!GetFileSizeEx(file, &size))
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return 0;
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (size.HighPart)
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return ULONG_MAX;
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return static_cast<size_t>(size.LowPart);
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Static.
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid File::WaitForPendingIO(int* num_pending_io) {
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (*num_pending_io) {
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Asynchronous IO operations may be in flight and the completion may end
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // up calling us back so let's wait for them.
26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    MessageLoopForIO::IOHandler* handler = g_completion_handler.Pointer();
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    MessageLoopForIO::current()->WaitForIOCompletion(100, handler);
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace disk_cache
267