Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "SharedMemory.h"
     28 
     29 #include "ArgumentDecoder.h"
     30 #include "ArgumentEncoder.h"
     31 #include <wtf/RefPtr.h>
     32 
     33 namespace WebKit {
     34 
     35 SharedMemory::Handle::Handle()
     36     : m_handle(0)
     37     , m_size(0)
     38 {
     39 }
     40 
     41 SharedMemory::Handle::~Handle()
     42 {
     43     if (!m_handle)
     44         return;
     45 
     46     ::CloseHandle(m_handle);
     47 }
     48 
     49 bool SharedMemory::Handle::isNull() const
     50 {
     51     return !m_handle;
     52 }
     53 
     54 void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const
     55 {
     56     encoder->encodeUInt64(m_size);
     57 
     58     // Hand off ownership of our HANDLE to the receiving process. It will close it for us.
     59     // FIXME: If the receiving process crashes before it receives the memory, the memory will be
     60     // leaked. See <http://webkit.org/b/47502>.
     61     encoder->encodeUInt64(reinterpret_cast<uint64_t>(m_handle));
     62     m_handle = 0;
     63 
     64     // Send along our PID so that the receiving process can duplicate the HANDLE for its own use.
     65     encoder->encodeUInt32(::GetCurrentProcessId());
     66 }
     67 
     68 static bool getDuplicatedHandle(HANDLE sourceHandle, DWORD sourcePID, HANDLE& duplicatedHandle)
     69 {
     70     duplicatedHandle = 0;
     71     if (!sourceHandle)
     72         return true;
     73 
     74     HANDLE sourceProcess = ::OpenProcess(PROCESS_DUP_HANDLE, FALSE, sourcePID);
     75     if (!sourceProcess)
     76         return false;
     77 
     78     // Copy the handle into our process and close the handle that the sending process created for us.
     79     BOOL success = ::DuplicateHandle(sourceProcess, sourceHandle, ::GetCurrentProcess(), &duplicatedHandle, 0, FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
     80     ASSERT_WITH_MESSAGE(success, "::DuplicateHandle failed with error %lu", ::GetLastError());
     81 
     82     ::CloseHandle(sourceProcess);
     83 
     84     return success;
     85 }
     86 
     87 bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle)
     88 {
     89     ASSERT_ARG(handle, !handle.m_handle);
     90     ASSERT_ARG(handle, !handle.m_size);
     91 
     92     uint64_t size;
     93     if (!decoder->decodeUInt64(size))
     94         return false;
     95 
     96     uint64_t sourceHandle;
     97     if (!decoder->decodeUInt64(sourceHandle))
     98         return false;
     99 
    100     uint32_t sourcePID;
    101     if (!decoder->decodeUInt32(sourcePID))
    102         return false;
    103 
    104     HANDLE duplicatedHandle;
    105     if (!getDuplicatedHandle(reinterpret_cast<HANDLE>(sourceHandle), sourcePID, duplicatedHandle))
    106         return false;
    107 
    108     handle.m_handle = duplicatedHandle;
    109     handle.m_size = size;
    110     return true;
    111 }
    112 
    113 PassRefPtr<SharedMemory> SharedMemory::create(size_t size)
    114 {
    115     HANDLE handle = ::CreateFileMappingW(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, 0);
    116     if (!handle)
    117         return 0;
    118 
    119     void* baseAddress = ::MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, size);
    120     if (!baseAddress) {
    121         ::CloseHandle(handle);
    122         return 0;
    123     }
    124 
    125     RefPtr<SharedMemory> memory = adoptRef(new SharedMemory);
    126     memory->m_size = size;
    127     memory->m_data = baseAddress;
    128     memory->m_handle = handle;
    129 
    130     return memory.release();
    131 }
    132 
    133 static DWORD accessRights(SharedMemory::Protection protection)
    134 {
    135     switch (protection) {
    136     case SharedMemory::ReadOnly:
    137         return FILE_MAP_READ;
    138     case SharedMemory::ReadWrite:
    139         return FILE_MAP_READ | FILE_MAP_WRITE;
    140     }
    141 
    142     ASSERT_NOT_REACHED();
    143     return 0;
    144 }
    145 
    146 PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection)
    147 {
    148     RefPtr<SharedMemory> memory = adopt(handle.m_handle, handle.m_size, protection);
    149     if (!memory)
    150         return 0;
    151 
    152     // The SharedMemory object now owns the HANDLE.
    153     handle.m_handle = 0;
    154 
    155     return memory.release();
    156 }
    157 
    158 PassRefPtr<SharedMemory> SharedMemory::adopt(HANDLE handle, size_t size, Protection protection)
    159 {
    160     if (!handle)
    161         return 0;
    162 
    163     DWORD desiredAccess = accessRights(protection);
    164 
    165     void* baseAddress = ::MapViewOfFile(handle, desiredAccess, 0, 0, size);
    166     ASSERT_WITH_MESSAGE(baseAddress, "::MapViewOfFile failed with error %lu", ::GetLastError());
    167     if (!baseAddress)
    168         return 0;
    169 
    170     RefPtr<SharedMemory> memory = adoptRef(new SharedMemory);
    171     memory->m_size = size;
    172     memory->m_data = baseAddress;
    173     memory->m_handle = handle;
    174 
    175     return memory.release();
    176 }
    177 
    178 SharedMemory::~SharedMemory()
    179 {
    180     ASSERT(m_data);
    181     ASSERT(m_handle);
    182 
    183     ::UnmapViewOfFile(m_data);
    184     ::CloseHandle(m_handle);
    185 }
    186 
    187 bool SharedMemory::createHandle(Handle& handle, Protection protection)
    188 {
    189     ASSERT_ARG(handle, !handle.m_handle);
    190     ASSERT_ARG(handle, !handle.m_size);
    191 
    192     HANDLE processHandle = ::GetCurrentProcess();
    193 
    194     HANDLE duplicatedHandle;
    195     if (!::DuplicateHandle(processHandle, m_handle, processHandle, &duplicatedHandle, accessRights(protection), FALSE, 0))
    196         return false;
    197 
    198     handle.m_handle = duplicatedHandle;
    199     handle.m_size = m_size;
    200     return true;
    201 }
    202 
    203 unsigned SharedMemory::systemPageSize()
    204 {
    205     static unsigned pageSize = 0;
    206 
    207     if (!pageSize) {
    208         SYSTEM_INFO systemInfo;
    209         ::GetSystemInfo(&systemInfo);
    210         pageSize = systemInfo.dwPageSize;
    211     }
    212 
    213     return pageSize;
    214 }
    215 
    216 } // namespace WebKit
    217