Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 */
6 /*
7 * ChromeWorker Object subprocess.jsm on Windows to process stdin/stdout/stderr
8 * on separate threads.
9 *
10 */
12 // Being a ChromeWorker object, implicitly uses the following:
13 // Components.utils.import("resource://gre/modules/ctypes.jsm");
15 'use strict';
17 const BufferSize = 1024;
19 const BOOL = ctypes.bool;
20 const HANDLE = ctypes.size_t;
21 const DWORD = ctypes.uint32_t;
22 const LPDWORD = DWORD.ptr;
23 const PVOID = ctypes.voidptr_t;
24 const LPVOID = PVOID;
26 /*
27 typedef struct _OVERLAPPED {
28 ULONG_PTR Internal;
29 ULONG_PTR InternalHigh;
30 union {
31 struct {
32 DWORD Offset;
33 DWORD OffsetHigh;
34 };
35 PVOID Pointer;
36 };
37 HANDLE hEvent;
38 } OVERLAPPED, *LPOVERLAPPED;
39 */
40 const OVERLAPPED = new ctypes.StructType("OVERLAPPED");
42 var ReadFileBuffer = ctypes.char.array(BufferSize);
43 var WriteFileBuffer = ctypes.uint8_t.array(BufferSize);
45 var kernel32dll = null;
46 var libFunc = {};
48 function initLib(libName) {
49 if (ctypes.size_t.size == 8) {
50 var WinABI = ctypes.default_abi;
51 } else {
52 var WinABI = ctypes.winapi_abi;
53 }
55 kernel32dll = ctypes.open(libName);
57 /*
58 BOOL WINAPI WriteFile(
59 __in HANDLE hFile,
60 __in LPCVOID lpBuffer,
61 __in DWORD nNumberOfBytesToWrite,
62 __out_opt LPDWORD lpNumberOfBytesWritten,
63 __inout_opt LPOVERLAPPED lpOverlapped
64 );
66 NOTE: lpBuffer is declared as array of unsigned int8 instead of char to avoid
67 implicit charset conversion
68 */
69 libFunc.WriteFile = kernel32dll.declare("WriteFile",
70 WinABI,
71 BOOL,
72 HANDLE,
73 WriteFileBuffer,
74 DWORD,
75 LPDWORD,
76 OVERLAPPED.ptr
77 );
79 /*
80 BOOL WINAPI ReadFile(
81 __in HANDLE hFile,
82 __out LPVOID ReadFileBuffer,
83 __in DWORD nNumberOfBytesToRead,
84 __out_opt LPDWORD lpNumberOfBytesRead,
85 __inout_opt LPOVERLAPPED lpOverlapped
86 );
87 */
88 libFunc.ReadFile = kernel32dll.declare("ReadFile",
89 WinABI,
90 BOOL,
91 HANDLE,
92 ReadFileBuffer,
93 DWORD,
94 LPDWORD,
95 OVERLAPPED.ptr
96 );
98 /*
99 BOOL WINAPI CloseHandle(
100 __in HANDLE hObject
101 );
102 */
103 libFunc.CloseHandle = kernel32dll.declare("CloseHandle",
104 WinABI,
105 BOOL,
106 HANDLE
107 );
108 }
111 function writePipe(pipe, data) {
112 var bytesWritten = DWORD(0);
114 var pData = new WriteFileBuffer();
116 var numChunks = Math.floor(data.length / BufferSize);
117 for (var chunk = 0; chunk <= numChunks; chunk ++) {
118 var numBytes = chunk < numChunks ? BufferSize : data.length - chunk * BufferSize;
119 for (var i=0; i < numBytes; i++) {
120 pData[i] = data.charCodeAt(chunk * BufferSize + i) % 256;
121 }
123 var r = libFunc.WriteFile(pipe, pData, numBytes, bytesWritten.address(), null);
124 if (bytesWritten.value != numBytes)
125 throw("error: wrote "+bytesWritten.value+" instead of "+numBytes+" bytes");
126 }
127 postMessage("wrote "+data.length+" bytes of data");
128 }
130 function readString(data, length, charset) {
131 var string = '', bytes = [];
132 for(var i = 0;i < length; i++) {
133 if(data[i] == 0 && charset != "null") // stop on NULL character for non-binary data
134 break;
136 bytes.push(data[i]);
137 }
139 return bytes;
140 }
142 function readPipe(pipe, charset) {
143 while (true) {
144 var bytesRead = DWORD(0);
145 var line = new ReadFileBuffer();
146 var r = libFunc.ReadFile(pipe, line, BufferSize, bytesRead.address(), null);
148 if (!r) {
149 // stop if we get an error (such as EOF reached)
150 postMessage({msg: "info", data: "ReadFile failed"});
151 break;
152 }
154 if (bytesRead.value > 0) {
155 var c = readString(line, bytesRead.value, charset);
156 postMessage({msg: "data", data: c, count: c.length});
157 }
158 else {
159 break;
160 }
161 }
162 libFunc.CloseHandle(pipe);
163 postMessage({msg: "done"});
164 kernel32dll.close();
165 close();
166 }
168 onmessage = function (event) {
169 let pipePtr;
170 switch (event.data.msg) {
171 case "init":
172 initLib(event.data.libc);
173 break;
174 case "write":
175 // data contents:
176 // msg: 'write'
177 // data: the data (string) to write
178 // pipe: ptr to pipe
179 pipePtr = HANDLE.ptr(event.data.pipe);
180 writePipe(pipePtr.contents, event.data.data);
181 postMessage("WriteOK");
182 break;
183 case "read":
184 initLib(event.data.libc);
185 pipePtr = HANDLE.ptr(event.data.pipe);
186 readPipe(pipePtr.contents, event.data.charset);
187 break;
188 case "close":
189 pipePtr = HANDLE.ptr(event.data.pipe);
190 postMessage("closing stdin\n");
192 if (libFunc.CloseHandle(pipePtr.contents)) {
193 postMessage("ClosedOK");
194 }
195 else
196 postMessage("Could not close stdin handle");
197 break;
198 case "stop":
199 kernel32dll.close();
200 close();
201 break;
202 default:
203 throw("error: Unknown command"+event.data.msg+"\n");
204 }
205 return;
206 };