0

Avoid windows.h in message_pump_win.h.

This was used to define OVERLAPPED. Instead, make a duplicate definition
and use it to create properly-sized/aligned storage, that a real obj can
be constructed in in the .cc file.

Bug: 364987728
Change-Id: I0bffb42304659cce29807ab8af6070f9653b32f6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6134189
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Reviewed-by: Nico Weber <thakis@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Owners-Override: Nico Weber <thakis@chromium.org>
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1401181}
This commit is contained in:
Peter Kasting
2024-12-31 18:08:02 -08:00
committed by Chromium LUCI CQ
parent 8b592906df
commit 47b48940fb
12 changed files with 73 additions and 24 deletions

@ -9,6 +9,7 @@
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <memory>
#include <type_traits>
#include "base/auto_reset.h"
@ -719,7 +720,18 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() {
// MessagePumpForIO public:
MessagePumpForIO::IOContext::IOContext() {
memset(&overlapped, 0, sizeof(overlapped));
std::construct_at(GetOverlapped());
std::memset(GetOverlapped(), 0, sizeof(OVERLAPPED));
}
MessagePumpForIO::IOContext::~IOContext() {
std::destroy_at(GetOverlapped());
}
OVERLAPPED* MessagePumpForIO::IOContext::GetOverlapped() {
static_assert(sizeof(OVERLAPPED) == sizeof(Sizer));
static_assert(alignof(OVERLAPPED) == alignof(Sizer));
return reinterpret_cast<OVERLAPPED*>(storage_);
}
MessagePumpForIO::IOHandler::IOHandler(const Location& from_here)

@ -5,8 +5,6 @@
#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_
#include <windows.h>
#include <atomic>
#include <memory>
#include <optional>
@ -22,6 +20,7 @@
#include "base/time/time.h"
#include "base/win/message_window.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_types.h"
namespace base {
@ -219,9 +218,35 @@ class BASE_EXPORT MessagePumpForUI : public MessagePumpWin {
//
class BASE_EXPORT MessagePumpForIO : public MessagePumpWin {
public:
struct BASE_EXPORT IOContext {
class BASE_EXPORT IOContext {
public:
IOContext();
OVERLAPPED overlapped;
~IOContext();
OVERLAPPED* GetOverlapped();
private:
// Hack: This header needs to be pulled in by files that should not
// `#include <windows.h>`, yet wants to store an `OVERLAPPED` inline.
// We can't simply define `OVERLAPPED` ourselves, or the compiler will
// complain about type redefinitions in files that _do_ see the real
// definition. Instead, define an identical struct, but use it only to
// align/size storage that we will construct a real `OVERLAPPED` in in the
// constructor.
struct Sizer {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
};
alignas(Sizer) unsigned char storage_[sizeof(Sizer)];
};
// Clients interested in receiving OS notifications when asynchronous IO

@ -411,7 +411,7 @@ class TestIOHandler : public MessagePumpForIO::IOHandler {
DWORD error) override;
void Init();
OVERLAPPED* context() { return &context_.overlapped; }
OVERLAPPED* context() { return context_.GetOverlapped(); }
DWORD size() { return sizeof(buffer_); }
private:

@ -28,6 +28,8 @@
#if BUILDFLAG(IS_APPLE)
#include "base/apple/scoped_nsautorelease_pool.h"
#elif BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
namespace wifi {

@ -306,7 +306,7 @@ class ChannelWin : public Channel,
BOOL ok =
::ReadFile(handle_.get(), buffer, static_cast<DWORD>(buffer_capacity),
NULL, &read_context_.overlapped);
NULL, read_context_.GetOverlapped());
if (ok || GetLastError() == ERROR_IO_PENDING) {
is_read_pending_ = true;
AddRef();
@ -336,7 +336,7 @@ class ChannelWin : public Channel,
DCHECK(handle_.is_valid());
BOOL ok = WriteFile(handle_.get(), message->data(),
static_cast<DWORD>(message->data_num_bytes()), NULL,
&write_context_.overlapped);
write_context_.GetOverlapped());
if (ok || GetLastError() == ERROR_IO_PENDING) {
is_write_pending_ = true;
AddRef();

@ -20,6 +20,10 @@
#include "net/base/apple/guarded_fd.h"
#endif // BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
namespace net {
namespace {

@ -72,7 +72,7 @@ int FileStream::Context::Read(IOBuffer* buf,
FROM_HERE,
base::BindOnce(&FileStream::Context::ReadAsync, base::Unretained(this),
file_.GetPlatformFile(), base::WrapRefCounted(buf),
buf_len, &io_context_.overlapped,
buf_len, io_context_.GetOverlapped(),
base::SingleThreadTaskRunner::GetCurrentDefault()));
return ERR_IO_PENDING;
}
@ -85,8 +85,8 @@ int FileStream::Context::Write(IOBuffer* buf,
result_ = 0;
DWORD bytes_written = 0;
if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len,
&bytes_written, &io_context_.overlapped)) {
if (!WriteFile(file_.GetPlatformFile(), buf->data(), buf_len, &bytes_written,
io_context_.GetOverlapped())) {
IOResult error = IOResult::FromOSError(GetLastError());
if (error.os_error == ERROR_IO_PENDING) {
IOCompletionIsPending(std::move(callback), buf);
@ -105,7 +105,7 @@ int FileStream::Context::ConnectNamedPipe(CompletionOnceCallback callback) {
result_ = 0;
// Always returns zero when making an asynchronous call.
::ConnectNamedPipe(file_.GetPlatformFile(), &io_context_.overlapped);
::ConnectNamedPipe(file_.GetPlatformFile(), io_context_.GetOverlapped());
const auto error = ::GetLastError();
if (error == ERROR_PIPE_CONNECTED) {
return OK; // The client has already connected; operation complete.
@ -124,7 +124,7 @@ FileStream::Context::IOResult FileStream::Context::SeekFileImpl(
int64_t offset) {
LARGE_INTEGER result;
result.QuadPart = offset;
SetOffset(&io_context_.overlapped, result);
SetOffset(io_context_.GetOverlapped(), result);
return IOResult(result.QuadPart, 0);
}
@ -173,7 +173,7 @@ void FileStream::Context::OnIOCompleted(
if (result_)
DCHECK_EQ(result_, static_cast<int>(bytes_read));
result_ = bytes_read;
IncrementOffset(&io_context_.overlapped, bytes_read);
IncrementOffset(io_context_.GetOverlapped(), bytes_read);
}
if (async_read_initiated_)

@ -47,6 +47,10 @@ using net::test::IsOk;
#if BUILDFLAG(IS_ANDROID)
#include "base/test/test_file_util.h"
#elif BUILDFLAG(IS_WIN)
#include <windows.h>
#include <namedpipeapi.h>
#endif
namespace net {

@ -4,6 +4,8 @@
#include "net/disk_cache/blockfile/file.h"
#include <windows.h>
#include <limits.h>
#include <utility>
@ -29,10 +31,8 @@ class CompletionHandler;
struct MyOverlapped {
MyOverlapped(disk_cache::File* file, size_t offset,
disk_cache::FileIOCallback* callback);
~MyOverlapped() {}
OVERLAPPED* overlapped() {
return &context_.overlapped;
}
~MyOverlapped() = default;
OVERLAPPED* overlapped() { return context_.GetOverlapped(); }
base::MessagePumpForIO::IOContext context_;
scoped_refptr<disk_cache::File> file_;
@ -90,7 +90,7 @@ void CompletionHandler::OnIOCompleted(
MyOverlapped::MyOverlapped(disk_cache::File* file, size_t offset,
disk_cache::FileIOCallback* callback) {
context_.overlapped.Offset = static_cast<DWORD>(offset);
context_.GetOverlapped()->Offset = static_cast<DWORD>(offset);
file_ = file;
callback_ = callback;
completion_handler_ = CompletionHandler::Get();

@ -298,7 +298,7 @@ int TcpSocketIoCompletionPortWin::Write(
const int rv =
::WSASend(socket_, &write_buffer, /*dwBufferCount=*/1, &bytes_sent,
/*dwFlags=*/0, &context->overlapped,
/*dwFlags=*/0, context->GetOverlapped(),
/*lpCompletionRoutine=*/nullptr);
// "Citations" below are from
@ -508,7 +508,7 @@ int TcpSocketIoCompletionPortWin::HandleReadRequest(
// whether zero-byte overlapped reads are allowed (for ReadIfReady).
auto rv = ::WSARecv(
socket_, &read_buffer, /*dwBufferCount=*/1, &bytes_read, &flags,
allow_zero_byte_overlapped_read ? nullptr : &context->overlapped,
allow_zero_byte_overlapped_read ? nullptr : context->GetOverlapped(),
nullptr);
// "Citations" below are from
@ -532,7 +532,7 @@ int TcpSocketIoCompletionPortWin::HandleReadRequest(
// value from WSARecv here in that case will be WSA_IO_PENDING.
read_buffer = {};
rv = ::WSARecv(socket_, &read_buffer, /*dwBufferCount=*/1, &bytes_read,
&flags, &context->overlapped, nullptr);
&flags, context->GetOverlapped(), nullptr);
if (rv == 0) {
// Immediate completion for zero-byte read. The contract for ReadIfReady
// explicitly states that on synchronous completion we need to return

@ -26,6 +26,8 @@
#include "remoting/host/desktop_session_agent.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "base/win/windows_version.h"
#endif // BUILDFLAG(IS_WIN)

@ -194,7 +194,7 @@ void SerialIoHandlerWin::ReadImpl() {
if (!ReadFile(file().GetPlatformFile(), pending_read_buffer().data(),
pending_read_buffer().size(), nullptr,
&read_context_->overlapped) &&
read_context_->GetOverlapped()) &&
GetLastError() != ERROR_IO_PENDING) {
OnIOCompleted(read_context_.get(), 0, GetLastError());
}
@ -206,7 +206,7 @@ void SerialIoHandlerWin::WriteImpl() {
if (!WriteFile(file().GetPlatformFile(), pending_write_buffer().data(),
pending_write_buffer().size(), nullptr,
&write_context_->overlapped) &&
write_context_->GetOverlapped()) &&
GetLastError() != ERROR_IO_PENDING) {
OnIOCompleted(write_context_.get(), 0, GetLastError());
}