gecko-dev/toolkit/components/osfile/osfile_win_back.jsm

343 lines
13 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* This file can be used in the following contexts:
*
* 1. included from a non-osfile worker thread using importScript
* (it serves to define a synchronous API for that worker thread)
* (bug 707681)
*
* 2. included from the main thread using Components.utils.import
* (it serves to define the asynchronous API, whose implementation
* resides in the worker thread)
* (bug 729057)
*
* 3. included from the osfile worker thread using importScript
* (it serves to define the implementation of the asynchronous API)
* (bug 729057)
*/
{
if (typeof Components != "undefined") {
// We do not wish osfile_win.jsm to be used directly as a main thread
// module yet. When time comes, it will be loaded by a combination of
// a main thread front-end/worker thread implementation that makes sure
// that we are not executing synchronous IO code in the main thread.
throw new Error("osfile_win.jsm cannot be used from the main thread yet");
}
(function(exports) {
"use strict";
if (!exports.OS) {
exports.OS = {};
}
if (!exports.OS.Win) {
exports.OS.Win = {};
}
if (exports.OS.Win.File) {
return; // Avoid double-initialization
}
exports.OS.Win.File = {};
let LOG = OS.Shared.LOG.bind(OS.Shared, "Win", "back");
let libc = exports.OS.Shared.Win.libc;
/**
* Initialize the Windows module.
*
* @param {function=} declareFFI
*/
// FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
let init = function init(aDeclareFFI) {
let declareFFI;
if (aDeclareFFI) {
declareFFI = aDeclareFFI.bind(null, libc);
} else {
declareFFI = exports.OS.Shared.Win.declareFFI;
}
// Shorthands
let OSWin = exports.OS.Win;
let WinFile = exports.OS.Win.File;
if (!exports.OS.Types) {
exports.OS.Types = {};
}
let Type = exports.OS.Shared.Type;
let Types = Type;
// Initialize types
/**
* A C integer holding INVALID_HANDLE_VALUE in case of error or
* a file descriptor in case of success.
*/
Types.HANDLE =
Types.voidptr_t.withName("HANDLE");
Types.HANDLE.importFromC = function importFromC(maybe) {
if (Types.int.cast(maybe).value == INVALID_HANDLE) {
// Ensure that API clients can effectively compare against
// Const.INVALID_HANDLE_VALUE. Without this cast,
// == would always return |false|.
return INVALID_HANDLE;
}
return ctypes.CDataFinalizer(maybe, this.finalizeHANDLE);
};
Types.HANDLE.finalizeHANDLE = function placeholder() {
throw new Error("finalizeHANDLE should be implemented");
};
let INVALID_HANDLE = exports.OS.Constants.Win.INVALID_HANDLE_VALUE;
Types.file_HANDLE = Types.HANDLE.withName("file HANDLE");
exports.OS.Shared.defineLazyGetter(Types.file_HANDLE,
"finalizeHANDLE",
function() {
return _CloseHandle;
});
Types.find_HANDLE = Types.HANDLE.withName("find HANDLE");
exports.OS.Shared.defineLazyGetter(Types.find_HANDLE,
"finalizeHANDLE",
function() {
return _FindClose;
});
Types.DWORD = Types.int32_t.withName("DWORD");
/**
* A C integer holding -1 in case of error or a positive integer
* in case of success.
*/
Types.negative_or_DWORD =
Types.DWORD.withName("negative_or_DWORD");
/**
* A C integer holding 0 in case of error or a positive integer
* in case of success.
*/
Types.zero_or_DWORD =
Types.DWORD.withName("zero_or_DWORD");
/**
* A C integer holding 0 in case of error, any other value in
* case of success.
*/
Types.zero_or_nothing =
Types.int.withName("zero_or_nothing");
Types.SECURITY_ATTRIBUTES =
Types.void_t.withName("SECURITY_ATTRIBUTES");
Types.FILETIME =
new Type("FILETIME",
ctypes.StructType("FILETIME", [
{ lo: Types.DWORD.implementation },
{ hi: Types.DWORD.implementation }]));
Types.FindData =
new Type("FIND_DATA",
ctypes.StructType("FIND_DATA", [
{ dwFileAttributes: ctypes.uint32_t },
{ ftCreationTime: Types.FILETIME.implementation },
{ ftLastAccessTime: Types.FILETIME.implementation },
{ ftLastWriteTime: Types.FILETIME.implementation },
{ nFileSizeHigh: Types.DWORD.implementation },
{ nFileSizeLow: Types.DWORD.implementation },
{ dwReserved0: Types.DWORD.implementation },
{ dwReserved1: Types.DWORD.implementation },
{ cFileName: ctypes.ArrayType(ctypes.jschar, exports.OS.Constants.Win.MAX_PATH) },
{ cAlternateFileName: ctypes.ArrayType(ctypes.jschar, 14) }
]));
Types.FILE_INFORMATION =
new Type("FILE_INFORMATION",
ctypes.StructType("FILE_INFORMATION", [
{ dwFileAttributes: ctypes.uint32_t },
{ ftCreationTime: Types.FILETIME.implementation },
{ ftLastAccessTime: Types.FILETIME.implementation },
{ ftLastWriteTime: Types.FILETIME.implementation },
{ dwVolumeSerialNumber: ctypes.uint32_t },
{ nFileSizeHigh: Types.DWORD.implementation },
{ nFileSizeLow: Types.DWORD.implementation },
{ nNumberOfLinks: ctypes.uint32_t },
{ nFileIndex: ctypes.uint64_t }
]));
Types.SystemTime =
new Type("SystemTime",
ctypes.StructType("SystemTime", [
{ wYear: ctypes.int16_t },
{ wMonth: ctypes.int16_t },
{ wDayOfWeek: ctypes.int16_t },
{ wDay: ctypes.int16_t },
{ wHour: ctypes.int16_t },
{ wMinute: ctypes.int16_t },
{ wSecond: ctypes.int16_t },
{ wMilliSeconds: ctypes.int16_t }
]));
// Special case: these functions are used by the
// finalizer
let _CloseHandle = WinFile._CloseHandle =
libc.declare("CloseHandle", ctypes.winapi_abi,
/*return */ctypes.bool,
/*handle*/ ctypes.voidptr_t);
WinFile.CloseHandle = function(fd) {
if (fd == INVALID_HANDLE) {
return true;
} else {
return fd.dispose(); // Returns the value of |CloseHandle|.
}
};
let _FindClose =
libc.declare("FindClose", ctypes.winapi_abi,
/*return */ctypes.bool,
/*handle*/ ctypes.voidptr_t);
WinFile.FindClose = function(handle) {
if (handle == INVALID_HANDLE) {
return true;
} else {
return handle.dispose(); // Returns the value of |FindClose|.
}
};
// Declare libc functions as functions of |OS.Win.File|
WinFile.CopyFile =
declareFFI("CopyFileW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*sourcePath*/ Types.path,
/*destPath*/ Types.path,
/*bailIfExist*/Types.bool);
WinFile.CreateDirectory =
declareFFI("CreateDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*name*/ Types.jschar.in_ptr,
/*security*/Types.SECURITY_ATTRIBUTES.in_ptr);
WinFile.CreateFile =
declareFFI("CreateFileW", ctypes.winapi_abi,
/*return*/ Types.file_HANDLE,
/*name*/ Types.path,
/*access*/ Types.DWORD,
/*share*/ Types.DWORD,
/*security*/Types.SECURITY_ATTRIBUTES.in_ptr,
/*creation*/Types.DWORD,
/*flags*/ Types.DWORD,
/*template*/Types.HANDLE);
WinFile.DeleteFile =
declareFFI("DeleteFileW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*path*/ Types.path);
WinFile.FileTimeToSystemTime =
declareFFI("FileTimeToSystemTime", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*filetime*/Types.FILETIME.in_ptr,
/*systime*/ Types.SystemTime.out_ptr);
WinFile.FindFirstFile =
declareFFI("FindFirstFileW", ctypes.winapi_abi,
/*return*/ Types.find_HANDLE,
/*pattern*/Types.path,
/*data*/ Types.FindData.out_ptr);
WinFile.FindNextFile =
declareFFI("FindNextFileW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*prev*/ Types.find_HANDLE,
/*data*/ Types.FindData.out_ptr);
WinFile.FormatMessage =
declareFFI("FormatMessageW", ctypes.winapi_abi,
/*return*/ Types.DWORD,
/*flags*/ Types.DWORD,
/*source*/ Types.void_t.in_ptr,
/*msgid*/ Types.DWORD,
/*langid*/ Types.DWORD,
/*buf*/ Types.out_wstring,
/*size*/ Types.DWORD,
/*Arguments*/Types.void_t.in_ptr
);
WinFile.GetCurrentDirectory =
declareFFI("GetCurrentDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_DWORD,
/*length*/ Types.DWORD,
/*buf*/ Types.out_path
);
WinFile.GetFileInformationByHandle =
declareFFI("GetFileInformationByHandle", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*handle*/ Types.HANDLE,
/*info*/ Types.FILE_INFORMATION.out_ptr);
WinFile.MoveFileEx =
declareFFI("MoveFileExW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*sourcePath*/ Types.path,
/*destPath*/ Types.path,
/*flags*/ Types.DWORD
);
WinFile.ReadFile =
declareFFI("ReadFile", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*file*/ Types.HANDLE,
/*buffer*/ Types.voidptr_t,
/*nbytes*/ Types.DWORD,
/*nbytes_read*/Types.DWORD.out_ptr,
/*overlapped*/Types.void_t.inout_ptr // FIXME: Implement?
);
WinFile.RemoveDirectory =
declareFFI("RemoveDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*path*/ Types.path);
WinFile.SetCurrentDirectory =
declareFFI("SetCurrentDirectoryW", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*path*/ Types.path
);
WinFile.SetEndOfFile =
declareFFI("SetEndOfFile", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*file*/ Types.HANDLE);
WinFile.SetFilePointer =
declareFFI("SetFilePointer", ctypes.winapi_abi,
/*return*/ Types.negative_or_DWORD,
/*file*/ Types.HANDLE,
/*distlow*/Types.long,
/*disthi*/ Types.long.in_ptr,
/*method*/ Types.DWORD);
WinFile.WriteFile =
declareFFI("WriteFile", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*file*/ Types.HANDLE,
/*buffer*/ Types.voidptr_t,
/*nbytes*/ Types.DWORD,
/*nbytes_wr*/Types.DWORD.out_ptr,
/*overlapped*/Types.void_t.inout_ptr // FIXME: Implement?
);
WinFile.FlushFileBuffers =
declareFFI("FlushFileBuffers", ctypes.winapi_abi,
/*return*/ Types.zero_or_nothing,
/*file*/ Types.HANDLE);
};
exports.OS.Win.File._init = init;
})(this);
}