|
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 file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /** |
|
6 * This file can be used in the following contexts: |
|
7 * |
|
8 * 1. included from a non-osfile worker thread using importScript |
|
9 * (it serves to define a synchronous API for that worker thread) |
|
10 * (bug 707681) |
|
11 * |
|
12 * 2. included from the main thread using Components.utils.import |
|
13 * (it serves to define the asynchronous API, whose implementation |
|
14 * resides in the worker thread) |
|
15 * (bug 729057) |
|
16 * |
|
17 * 3. included from the osfile worker thread using importScript |
|
18 * (it serves to define the implementation of the asynchronous API) |
|
19 * (bug 729057) |
|
20 */ |
|
21 |
|
22 { |
|
23 if (typeof Components != "undefined") { |
|
24 // We do not wish osfile_win.jsm to be used directly as a main thread |
|
25 // module yet. When time comes, it will be loaded by a combination of |
|
26 // a main thread front-end/worker thread implementation that makes sure |
|
27 // that we are not executing synchronous IO code in the main thread. |
|
28 |
|
29 throw new Error("osfile_win.jsm cannot be used from the main thread yet"); |
|
30 } |
|
31 |
|
32 (function(exports) { |
|
33 "use strict"; |
|
34 if (exports.OS && exports.OS.Win && exports.OS.Win.File) { |
|
35 return; // Avoid double initialization |
|
36 } |
|
37 |
|
38 let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); |
|
39 let SysAll = require("resource://gre/modules/osfile/osfile_win_allthreads.jsm"); |
|
40 let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back"); |
|
41 let libc = SysAll.libc; |
|
42 let advapi32 = new SharedAll.Library("advapi32", "advapi32.dll"); |
|
43 let Const = SharedAll.Constants.Win; |
|
44 |
|
45 /** |
|
46 * Initialize the Windows module. |
|
47 * |
|
48 * @param {function=} declareFFI |
|
49 */ |
|
50 // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them |
|
51 let init = function init(aDeclareFFI) { |
|
52 let declareFFI; |
|
53 if (aDeclareFFI) { |
|
54 declareFFI = aDeclareFFI.bind(null, libc); |
|
55 } else { |
|
56 declareFFI = SysAll.declareFFI; |
|
57 } |
|
58 let declareLazyFFI = SharedAll.declareLazyFFI; |
|
59 |
|
60 // Initialize types that require additional OS-specific |
|
61 // support - either finalization or matching against |
|
62 // OS-specific constants. |
|
63 let Type = Object.create(SysAll.Type); |
|
64 let SysFile = exports.OS.Win.File = { Type: Type }; |
|
65 |
|
66 // Initialize types |
|
67 |
|
68 /** |
|
69 * A C integer holding INVALID_HANDLE_VALUE in case of error or |
|
70 * a file descriptor in case of success. |
|
71 */ |
|
72 Type.HANDLE = |
|
73 Type.voidptr_t.withName("HANDLE"); |
|
74 Type.HANDLE.importFromC = function importFromC(maybe) { |
|
75 if (Type.int.cast(maybe).value == INVALID_HANDLE) { |
|
76 // Ensure that API clients can effectively compare against |
|
77 // Const.INVALID_HANDLE_VALUE. Without this cast, |
|
78 // == would always return |false|. |
|
79 return INVALID_HANDLE; |
|
80 } |
|
81 return ctypes.CDataFinalizer(maybe, this.finalizeHANDLE); |
|
82 }; |
|
83 Type.HANDLE.finalizeHANDLE = function placeholder() { |
|
84 throw new Error("finalizeHANDLE should be implemented"); |
|
85 }; |
|
86 let INVALID_HANDLE = Const.INVALID_HANDLE_VALUE; |
|
87 |
|
88 Type.file_HANDLE = Type.HANDLE.withName("file HANDLE"); |
|
89 SharedAll.defineLazyGetter(Type.file_HANDLE, |
|
90 "finalizeHANDLE", |
|
91 function() { |
|
92 return SysFile._CloseHandle; |
|
93 }); |
|
94 |
|
95 Type.find_HANDLE = Type.HANDLE.withName("find HANDLE"); |
|
96 SharedAll.defineLazyGetter(Type.find_HANDLE, |
|
97 "finalizeHANDLE", |
|
98 function() { |
|
99 return SysFile._FindClose; |
|
100 }); |
|
101 |
|
102 Type.DWORD = Type.uint32_t.withName("DWORD"); |
|
103 |
|
104 /* A special type used to represent flags passed as DWORDs to a function. |
|
105 * In JavaScript, bitwise manipulation of numbers, such as or-ing flags, |
|
106 * can produce negative numbers. Since DWORD is unsigned, these negative |
|
107 * numbers simply cannot be converted to DWORD. For this reason, whenever |
|
108 * bit manipulation is called for, you should rather use DWORD_FLAGS, |
|
109 * which is represented as a signed integer, hence has the correct |
|
110 * semantics. |
|
111 */ |
|
112 Type.DWORD_FLAGS = Type.int32_t.withName("DWORD_FLAGS"); |
|
113 |
|
114 /** |
|
115 * A C integer holding 0 in case of error or a positive integer |
|
116 * in case of success. |
|
117 */ |
|
118 Type.zero_or_DWORD = |
|
119 Type.DWORD.withName("zero_or_DWORD"); |
|
120 |
|
121 /** |
|
122 * A C integer holding 0 in case of error, any other value in |
|
123 * case of success. |
|
124 */ |
|
125 Type.zero_or_nothing = |
|
126 Type.int.withName("zero_or_nothing"); |
|
127 |
|
128 /** |
|
129 * A C integer holding flags related to NTFS security. |
|
130 */ |
|
131 Type.SECURITY_ATTRIBUTES = |
|
132 Type.void_t.withName("SECURITY_ATTRIBUTES"); |
|
133 |
|
134 /** |
|
135 * A C integer holding pointers related to NTFS security. |
|
136 */ |
|
137 Type.PSID = |
|
138 Type.voidptr_t.withName("PSID"); |
|
139 |
|
140 Type.PACL = |
|
141 Type.voidptr_t.withName("PACL"); |
|
142 |
|
143 Type.PSECURITY_DESCRIPTOR = |
|
144 Type.voidptr_t.withName("PSECURITY_DESCRIPTOR"); |
|
145 |
|
146 /** |
|
147 * A C integer holding Win32 local memory handle. |
|
148 */ |
|
149 Type.HLOCAL = |
|
150 Type.voidptr_t.withName("HLOCAL"); |
|
151 |
|
152 Type.FILETIME = |
|
153 new SharedAll.Type("FILETIME", |
|
154 ctypes.StructType("FILETIME", [ |
|
155 { lo: Type.DWORD.implementation }, |
|
156 { hi: Type.DWORD.implementation }])); |
|
157 |
|
158 Type.FindData = |
|
159 new SharedAll.Type("FIND_DATA", |
|
160 ctypes.StructType("FIND_DATA", [ |
|
161 { dwFileAttributes: ctypes.uint32_t }, |
|
162 { ftCreationTime: Type.FILETIME.implementation }, |
|
163 { ftLastAccessTime: Type.FILETIME.implementation }, |
|
164 { ftLastWriteTime: Type.FILETIME.implementation }, |
|
165 { nFileSizeHigh: Type.DWORD.implementation }, |
|
166 { nFileSizeLow: Type.DWORD.implementation }, |
|
167 { dwReserved0: Type.DWORD.implementation }, |
|
168 { dwReserved1: Type.DWORD.implementation }, |
|
169 { cFileName: ctypes.ArrayType(ctypes.jschar, Const.MAX_PATH) }, |
|
170 { cAlternateFileName: ctypes.ArrayType(ctypes.jschar, 14) } |
|
171 ])); |
|
172 |
|
173 Type.FILE_INFORMATION = |
|
174 new SharedAll.Type("FILE_INFORMATION", |
|
175 ctypes.StructType("FILE_INFORMATION", [ |
|
176 { dwFileAttributes: ctypes.uint32_t }, |
|
177 { ftCreationTime: Type.FILETIME.implementation }, |
|
178 { ftLastAccessTime: Type.FILETIME.implementation }, |
|
179 { ftLastWriteTime: Type.FILETIME.implementation }, |
|
180 { dwVolumeSerialNumber: ctypes.uint32_t }, |
|
181 { nFileSizeHigh: Type.DWORD.implementation }, |
|
182 { nFileSizeLow: Type.DWORD.implementation }, |
|
183 { nNumberOfLinks: ctypes.uint32_t }, |
|
184 { nFileIndex: ctypes.uint64_t } |
|
185 ])); |
|
186 |
|
187 Type.SystemTime = |
|
188 new SharedAll.Type("SystemTime", |
|
189 ctypes.StructType("SystemTime", [ |
|
190 { wYear: ctypes.int16_t }, |
|
191 { wMonth: ctypes.int16_t }, |
|
192 { wDayOfWeek: ctypes.int16_t }, |
|
193 { wDay: ctypes.int16_t }, |
|
194 { wHour: ctypes.int16_t }, |
|
195 { wMinute: ctypes.int16_t }, |
|
196 { wSecond: ctypes.int16_t }, |
|
197 { wMilliSeconds: ctypes.int16_t } |
|
198 ])); |
|
199 |
|
200 // Special case: these functions are used by the |
|
201 // finalizer |
|
202 libc.declareLazy(SysFile, "_CloseHandle", |
|
203 "CloseHandle", ctypes.winapi_abi, |
|
204 /*return */ctypes.bool, |
|
205 /*handle*/ ctypes.voidptr_t); |
|
206 |
|
207 SysFile.CloseHandle = function(fd) { |
|
208 if (fd == INVALID_HANDLE) { |
|
209 return true; |
|
210 } else { |
|
211 return fd.dispose(); // Returns the value of |CloseHandle|. |
|
212 } |
|
213 }; |
|
214 |
|
215 libc.declareLazy(SysFile, "_FindClose", |
|
216 "FindClose", ctypes.winapi_abi, |
|
217 /*return */ctypes.bool, |
|
218 /*handle*/ ctypes.voidptr_t); |
|
219 |
|
220 SysFile.FindClose = function(handle) { |
|
221 if (handle == INVALID_HANDLE) { |
|
222 return true; |
|
223 } else { |
|
224 return handle.dispose(); // Returns the value of |FindClose|. |
|
225 } |
|
226 }; |
|
227 |
|
228 // Declare libc functions as functions of |OS.Win.File| |
|
229 |
|
230 libc.declareLazyFFI(SysFile, "CopyFile", |
|
231 "CopyFileW", ctypes.winapi_abi, |
|
232 /*return*/ Type.zero_or_nothing, |
|
233 /*sourcePath*/ Type.path, |
|
234 /*destPath*/ Type.path, |
|
235 /*bailIfExist*/Type.bool); |
|
236 |
|
237 libc.declareLazyFFI(SysFile, "CreateDirectory", |
|
238 "CreateDirectoryW", ctypes.winapi_abi, |
|
239 /*return*/ Type.zero_or_nothing, |
|
240 /*name*/ Type.jschar.in_ptr, |
|
241 /*security*/Type.SECURITY_ATTRIBUTES.in_ptr); |
|
242 |
|
243 libc.declareLazyFFI(SysFile, "CreateFile", |
|
244 "CreateFileW", ctypes.winapi_abi, |
|
245 /*return*/ Type.file_HANDLE, |
|
246 /*name*/ Type.path, |
|
247 /*access*/ Type.DWORD_FLAGS, |
|
248 /*share*/ Type.DWORD_FLAGS, |
|
249 /*security*/Type.SECURITY_ATTRIBUTES.in_ptr, |
|
250 /*creation*/Type.DWORD_FLAGS, |
|
251 /*flags*/ Type.DWORD_FLAGS, |
|
252 /*template*/Type.HANDLE); |
|
253 |
|
254 libc.declareLazyFFI(SysFile, "DeleteFile", |
|
255 "DeleteFileW", ctypes.winapi_abi, |
|
256 /*return*/ Type.zero_or_nothing, |
|
257 /*path*/ Type.path); |
|
258 |
|
259 libc.declareLazyFFI(SysFile, "FileTimeToSystemTime", |
|
260 "FileTimeToSystemTime", ctypes.winapi_abi, |
|
261 /*return*/ Type.zero_or_nothing, |
|
262 /*filetime*/Type.FILETIME.in_ptr, |
|
263 /*systime*/ Type.SystemTime.out_ptr); |
|
264 |
|
265 libc.declareLazyFFI(SysFile, "SystemTimeToFileTime", |
|
266 "SystemTimeToFileTime", ctypes.winapi_abi, |
|
267 /*return*/ Type.zero_or_nothing, |
|
268 /*systime*/ Type.SystemTime.in_ptr, |
|
269 /*filetime*/ Type.FILETIME.out_ptr); |
|
270 |
|
271 libc.declareLazyFFI(SysFile, "FindFirstFile", |
|
272 "FindFirstFileW", ctypes.winapi_abi, |
|
273 /*return*/ Type.find_HANDLE, |
|
274 /*pattern*/Type.path, |
|
275 /*data*/ Type.FindData.out_ptr); |
|
276 |
|
277 libc.declareLazyFFI(SysFile, "FindNextFile", |
|
278 "FindNextFileW", ctypes.winapi_abi, |
|
279 /*return*/ Type.zero_or_nothing, |
|
280 /*prev*/ Type.find_HANDLE, |
|
281 /*data*/ Type.FindData.out_ptr); |
|
282 |
|
283 libc.declareLazyFFI(SysFile, "FormatMessage", |
|
284 "FormatMessageW", ctypes.winapi_abi, |
|
285 /*return*/ Type.DWORD, |
|
286 /*flags*/ Type.DWORD_FLAGS, |
|
287 /*source*/ Type.void_t.in_ptr, |
|
288 /*msgid*/ Type.DWORD_FLAGS, |
|
289 /*langid*/ Type.DWORD_FLAGS, |
|
290 /*buf*/ Type.out_wstring, |
|
291 /*size*/ Type.DWORD, |
|
292 /*Arguments*/Type.void_t.in_ptr |
|
293 ); |
|
294 |
|
295 libc.declareLazyFFI(SysFile, "GetCurrentDirectory", |
|
296 "GetCurrentDirectoryW", ctypes.winapi_abi, |
|
297 /*return*/ Type.zero_or_DWORD, |
|
298 /*length*/ Type.DWORD, |
|
299 /*buf*/ Type.out_path |
|
300 ); |
|
301 |
|
302 libc.declareLazyFFI(SysFile, "GetDiskFreeSpaceEx", |
|
303 "GetDiskFreeSpaceExW", ctypes.winapi_abi, |
|
304 /*return*/ Type.zero_or_nothing, |
|
305 /*directoryName*/ Type.path, |
|
306 /*freeBytesForUser*/ Type.uint64_t.out_ptr, |
|
307 /*totalBytesForUser*/ Type.uint64_t.out_ptr, |
|
308 /*freeTotalBytesOnDrive*/ Type.uint64_t.out_ptr); |
|
309 |
|
310 libc.declareLazyFFI(SysFile, "GetFileInformationByHandle", |
|
311 "GetFileInformationByHandle", ctypes.winapi_abi, |
|
312 /*return*/ Type.zero_or_nothing, |
|
313 /*handle*/ Type.HANDLE, |
|
314 /*info*/ Type.FILE_INFORMATION.out_ptr); |
|
315 |
|
316 libc.declareLazyFFI(SysFile, "MoveFileEx", |
|
317 "MoveFileExW", ctypes.winapi_abi, |
|
318 /*return*/ Type.zero_or_nothing, |
|
319 /*sourcePath*/ Type.path, |
|
320 /*destPath*/ Type.path, |
|
321 /*flags*/ Type.DWORD |
|
322 ); |
|
323 |
|
324 libc.declareLazyFFI(SysFile, "ReadFile", |
|
325 "ReadFile", ctypes.winapi_abi, |
|
326 /*return*/ Type.zero_or_nothing, |
|
327 /*file*/ Type.HANDLE, |
|
328 /*buffer*/ Type.voidptr_t, |
|
329 /*nbytes*/ Type.DWORD, |
|
330 /*nbytes_read*/Type.DWORD.out_ptr, |
|
331 /*overlapped*/Type.void_t.inout_ptr // FIXME: Implement? |
|
332 ); |
|
333 |
|
334 libc.declareLazyFFI(SysFile, "RemoveDirectory", |
|
335 "RemoveDirectoryW", ctypes.winapi_abi, |
|
336 /*return*/ Type.zero_or_nothing, |
|
337 /*path*/ Type.path); |
|
338 |
|
339 libc.declareLazyFFI(SysFile, "SetCurrentDirectory", |
|
340 "SetCurrentDirectoryW", ctypes.winapi_abi, |
|
341 /*return*/ Type.zero_or_nothing, |
|
342 /*path*/ Type.path |
|
343 ); |
|
344 |
|
345 libc.declareLazyFFI(SysFile, "SetEndOfFile", |
|
346 "SetEndOfFile", ctypes.winapi_abi, |
|
347 /*return*/ Type.zero_or_nothing, |
|
348 /*file*/ Type.HANDLE); |
|
349 |
|
350 libc.declareLazyFFI(SysFile, "SetFilePointer", |
|
351 "SetFilePointer", ctypes.winapi_abi, |
|
352 /*return*/ Type.DWORD, |
|
353 /*file*/ Type.HANDLE, |
|
354 /*distlow*/Type.long, |
|
355 /*disthi*/ Type.long.in_ptr, |
|
356 /*method*/ Type.DWORD); |
|
357 |
|
358 libc.declareLazyFFI(SysFile, "SetFileTime", |
|
359 "SetFileTime", ctypes.winapi_abi, |
|
360 /*return*/ Type.zero_or_nothing, |
|
361 /*file*/ Type.HANDLE, |
|
362 /*creation*/ Type.FILETIME.in_ptr, |
|
363 /*access*/ Type.FILETIME.in_ptr, |
|
364 /*write*/ Type.FILETIME.in_ptr); |
|
365 |
|
366 |
|
367 libc.declareLazyFFI(SysFile, "WriteFile", |
|
368 "WriteFile", ctypes.winapi_abi, |
|
369 /*return*/ Type.zero_or_nothing, |
|
370 /*file*/ Type.HANDLE, |
|
371 /*buffer*/ Type.voidptr_t, |
|
372 /*nbytes*/ Type.DWORD, |
|
373 /*nbytes_wr*/Type.DWORD.out_ptr, |
|
374 /*overlapped*/Type.void_t.inout_ptr // FIXME: Implement? |
|
375 ); |
|
376 |
|
377 libc.declareLazyFFI(SysFile, "FlushFileBuffers", |
|
378 "FlushFileBuffers", ctypes.winapi_abi, |
|
379 /*return*/ Type.zero_or_nothing, |
|
380 /*file*/ Type.HANDLE); |
|
381 |
|
382 libc.declareLazyFFI(SysFile, "GetFileAttributes", |
|
383 "GetFileAttributesW", ctypes.winapi_abi, |
|
384 /*return*/ Type.DWORD_FLAGS, |
|
385 /*fileName*/ Type.path); |
|
386 |
|
387 libc.declareLazyFFI(SysFile, "SetFileAttributes", |
|
388 "SetFileAttributesW", ctypes.winapi_abi, |
|
389 /*return*/ Type.zero_or_nothing, |
|
390 /*fileName*/ Type.path, |
|
391 /*fileAttributes*/ Type.DWORD_FLAGS); |
|
392 |
|
393 advapi32.declareLazyFFI(SysFile, "GetNamedSecurityInfo", |
|
394 "GetNamedSecurityInfoW", ctypes.winapi_abi, |
|
395 /*return*/ Type.DWORD, |
|
396 /*objectName*/ Type.path, |
|
397 /*objectType*/ Type.DWORD, |
|
398 /*securityInfo*/ Type.DWORD, |
|
399 /*sidOwner*/ Type.PSID.out_ptr, |
|
400 /*sidGroup*/ Type.PSID.out_ptr, |
|
401 /*dacl*/ Type.PACL.out_ptr, |
|
402 /*sacl*/ Type.PACL.out_ptr, |
|
403 /*securityDesc*/ Type.PSECURITY_DESCRIPTOR.out_ptr); |
|
404 |
|
405 advapi32.declareLazyFFI(SysFile, "SetNamedSecurityInfo", |
|
406 "SetNamedSecurityInfoW", ctypes.winapi_abi, |
|
407 /*return*/ Type.DWORD, |
|
408 /*objectName*/ Type.path, |
|
409 /*objectType*/ Type.DWORD, |
|
410 /*securityInfo*/ Type.DWORD, |
|
411 /*sidOwner*/ Type.PSID, |
|
412 /*sidGroup*/ Type.PSID, |
|
413 /*dacl*/ Type.PACL, |
|
414 /*sacl*/ Type.PACL); |
|
415 |
|
416 libc.declareLazyFFI(SysFile, "LocalFree", |
|
417 "LocalFree", ctypes.winapi_abi, |
|
418 /*return*/ Type.HLOCAL, |
|
419 /*mem*/ Type.HLOCAL); |
|
420 }; |
|
421 |
|
422 exports.OS.Win = { |
|
423 File: { |
|
424 _init: init |
|
425 } |
|
426 }; |
|
427 })(this); |
|
428 } |