|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "MiniShmChild.h" |
|
8 |
|
9 #include <limits> |
|
10 #include <sstream> |
|
11 |
|
12 namespace mozilla { |
|
13 namespace plugins { |
|
14 |
|
15 MiniShmChild::MiniShmChild() |
|
16 : mParentEvent(nullptr), |
|
17 mParentGuard(nullptr), |
|
18 mChildEvent(nullptr), |
|
19 mChildGuard(nullptr), |
|
20 mFileMapping(nullptr), |
|
21 mRegWait(nullptr), |
|
22 mView(nullptr), |
|
23 mTimeout(INFINITE) |
|
24 {} |
|
25 |
|
26 MiniShmChild::~MiniShmChild() |
|
27 { |
|
28 if (mRegWait) { |
|
29 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE); |
|
30 } |
|
31 if (mParentGuard) { |
|
32 // Try to avoid shutting down while the parent's event handler is running. |
|
33 ::WaitForSingleObject(mParentGuard, mTimeout); |
|
34 ::CloseHandle(mParentGuard); |
|
35 } |
|
36 if (mParentEvent) { |
|
37 ::CloseHandle(mParentEvent); |
|
38 } |
|
39 if (mChildEvent) { |
|
40 ::CloseHandle(mChildEvent); |
|
41 } |
|
42 if (mChildGuard) { |
|
43 ::CloseHandle(mChildGuard); |
|
44 } |
|
45 if (mView) { |
|
46 ::UnmapViewOfFile(mView); |
|
47 } |
|
48 if (mFileMapping) { |
|
49 ::CloseHandle(mFileMapping); |
|
50 } |
|
51 } |
|
52 |
|
53 nsresult |
|
54 MiniShmChild::Init(MiniShmObserver* aObserver, const std::wstring& aCookie, |
|
55 const DWORD aTimeout) |
|
56 { |
|
57 if (aCookie.empty() || !aTimeout) { |
|
58 return NS_ERROR_ILLEGAL_VALUE; |
|
59 } |
|
60 if (mFileMapping) { |
|
61 return NS_ERROR_ALREADY_INITIALIZED; |
|
62 } |
|
63 std::wistringstream iss(aCookie); |
|
64 HANDLE mapHandle = nullptr; |
|
65 iss >> mapHandle; |
|
66 if (!iss) { |
|
67 return NS_ERROR_ILLEGAL_VALUE; |
|
68 } |
|
69 ScopedMappedFileView view(::MapViewOfFile(mapHandle, |
|
70 FILE_MAP_WRITE, |
|
71 0, 0, 0)); |
|
72 if (!view.IsValid()) { |
|
73 return NS_ERROR_FAILURE; |
|
74 } |
|
75 MEMORY_BASIC_INFORMATION memInfo = {0}; |
|
76 SIZE_T querySize = ::VirtualQuery(view, &memInfo, sizeof(memInfo)); |
|
77 unsigned int mappingSize = 0; |
|
78 if (querySize) { |
|
79 if (memInfo.RegionSize <= std::numeric_limits<unsigned int>::max()) { |
|
80 mappingSize = static_cast<unsigned int>(memInfo.RegionSize); |
|
81 } |
|
82 } |
|
83 if (!querySize || !mappingSize) { |
|
84 return NS_ERROR_FAILURE; |
|
85 } |
|
86 nsresult rv = SetView(view, mappingSize, true); |
|
87 if (NS_FAILED(rv)) { |
|
88 return rv; |
|
89 } |
|
90 |
|
91 const MiniShmInit* initStruct = nullptr; |
|
92 rv = GetReadPtr(initStruct); |
|
93 if (NS_FAILED(rv)) { |
|
94 return rv; |
|
95 } |
|
96 if (!initStruct->mParentEvent || !initStruct->mParentGuard || |
|
97 !initStruct->mChildEvent || !initStruct->mChildGuard) { |
|
98 return NS_ERROR_FAILURE; |
|
99 } |
|
100 rv = SetGuard(initStruct->mParentGuard, aTimeout); |
|
101 if (NS_FAILED(rv)) { |
|
102 return rv; |
|
103 } |
|
104 if (!::RegisterWaitForSingleObject(&mRegWait, |
|
105 initStruct->mChildEvent, |
|
106 &SOnEvent, |
|
107 this, |
|
108 INFINITE, |
|
109 WT_EXECUTEDEFAULT)) { |
|
110 return NS_ERROR_FAILURE; |
|
111 } |
|
112 |
|
113 MiniShmInitComplete* initCompleteStruct = nullptr; |
|
114 rv = GetWritePtrInternal(initCompleteStruct); |
|
115 if (NS_FAILED(rv)) { |
|
116 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE); |
|
117 mRegWait = nullptr; |
|
118 return NS_ERROR_FAILURE; |
|
119 } |
|
120 |
|
121 initCompleteStruct->mSucceeded = true; |
|
122 |
|
123 // We must set the member variables before we signal the event |
|
124 mFileMapping = mapHandle; |
|
125 mView = view.Take(); |
|
126 mParentEvent = initStruct->mParentEvent; |
|
127 mParentGuard = initStruct->mParentGuard; |
|
128 mChildEvent = initStruct->mChildEvent; |
|
129 mChildGuard = initStruct->mChildGuard; |
|
130 SetObserver(aObserver); |
|
131 mTimeout = aTimeout; |
|
132 |
|
133 rv = Send(); |
|
134 if (NS_FAILED(rv)) { |
|
135 initCompleteStruct->mSucceeded = false; |
|
136 mFileMapping = nullptr; |
|
137 view.Set(mView); |
|
138 mView = nullptr; |
|
139 mParentEvent = nullptr; |
|
140 mParentGuard = nullptr; |
|
141 mChildEvent = nullptr; |
|
142 mChildGuard = nullptr; |
|
143 ::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE); |
|
144 mRegWait = nullptr; |
|
145 return rv; |
|
146 } |
|
147 |
|
148 OnConnect(); |
|
149 return NS_OK; |
|
150 } |
|
151 |
|
152 nsresult |
|
153 MiniShmChild::Send() |
|
154 { |
|
155 if (!mParentEvent) { |
|
156 return NS_ERROR_NOT_INITIALIZED; |
|
157 } |
|
158 if (!::SetEvent(mParentEvent)) { |
|
159 return NS_ERROR_FAILURE; |
|
160 } |
|
161 return NS_OK; |
|
162 } |
|
163 |
|
164 void |
|
165 MiniShmChild::OnEvent() |
|
166 { |
|
167 MiniShmBase::OnEvent(); |
|
168 ::SetEvent(mChildGuard); |
|
169 } |
|
170 |
|
171 } // namespace plugins |
|
172 } // namespace mozilla |
|
173 |