michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * This file can be used in the following contexts: michael@0: * michael@0: * 1. included from a non-osfile worker thread using importScript michael@0: * (it serves to define a synchronous API for that worker thread) michael@0: * (bug 707681) michael@0: * michael@0: * 2. included from the main thread using Components.utils.import michael@0: * (it serves to define the asynchronous API, whose implementation michael@0: * resides in the worker thread) michael@0: * (bug 729057) michael@0: * michael@0: * 3. included from the osfile worker thread using importScript michael@0: * (it serves to define the implementation of the asynchronous API) michael@0: * (bug 729057) michael@0: */ michael@0: michael@0: { michael@0: if (typeof Components != "undefined") { michael@0: // We do not wish osfile_win.jsm to be used directly as a main thread michael@0: // module yet. When time comes, it will be loaded by a combination of michael@0: // a main thread front-end/worker thread implementation that makes sure michael@0: // that we are not executing synchronous IO code in the main thread. michael@0: michael@0: throw new Error("osfile_win.jsm cannot be used from the main thread yet"); michael@0: } michael@0: michael@0: (function(exports) { michael@0: "use strict"; michael@0: if (exports.OS && exports.OS.Win && exports.OS.Win.File) { michael@0: return; // Avoid double initialization michael@0: } michael@0: michael@0: let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); michael@0: let SysAll = require("resource://gre/modules/osfile/osfile_win_allthreads.jsm"); michael@0: let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back"); michael@0: let libc = SysAll.libc; michael@0: let advapi32 = new SharedAll.Library("advapi32", "advapi32.dll"); michael@0: let Const = SharedAll.Constants.Win; michael@0: michael@0: /** michael@0: * Initialize the Windows module. michael@0: * michael@0: * @param {function=} declareFFI michael@0: */ michael@0: // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them michael@0: let init = function init(aDeclareFFI) { michael@0: let declareFFI; michael@0: if (aDeclareFFI) { michael@0: declareFFI = aDeclareFFI.bind(null, libc); michael@0: } else { michael@0: declareFFI = SysAll.declareFFI; michael@0: } michael@0: let declareLazyFFI = SharedAll.declareLazyFFI; michael@0: michael@0: // Initialize types that require additional OS-specific michael@0: // support - either finalization or matching against michael@0: // OS-specific constants. michael@0: let Type = Object.create(SysAll.Type); michael@0: let SysFile = exports.OS.Win.File = { Type: Type }; michael@0: michael@0: // Initialize types michael@0: michael@0: /** michael@0: * A C integer holding INVALID_HANDLE_VALUE in case of error or michael@0: * a file descriptor in case of success. michael@0: */ michael@0: Type.HANDLE = michael@0: Type.voidptr_t.withName("HANDLE"); michael@0: Type.HANDLE.importFromC = function importFromC(maybe) { michael@0: if (Type.int.cast(maybe).value == INVALID_HANDLE) { michael@0: // Ensure that API clients can effectively compare against michael@0: // Const.INVALID_HANDLE_VALUE. Without this cast, michael@0: // == would always return |false|. michael@0: return INVALID_HANDLE; michael@0: } michael@0: return ctypes.CDataFinalizer(maybe, this.finalizeHANDLE); michael@0: }; michael@0: Type.HANDLE.finalizeHANDLE = function placeholder() { michael@0: throw new Error("finalizeHANDLE should be implemented"); michael@0: }; michael@0: let INVALID_HANDLE = Const.INVALID_HANDLE_VALUE; michael@0: michael@0: Type.file_HANDLE = Type.HANDLE.withName("file HANDLE"); michael@0: SharedAll.defineLazyGetter(Type.file_HANDLE, michael@0: "finalizeHANDLE", michael@0: function() { michael@0: return SysFile._CloseHandle; michael@0: }); michael@0: michael@0: Type.find_HANDLE = Type.HANDLE.withName("find HANDLE"); michael@0: SharedAll.defineLazyGetter(Type.find_HANDLE, michael@0: "finalizeHANDLE", michael@0: function() { michael@0: return SysFile._FindClose; michael@0: }); michael@0: michael@0: Type.DWORD = Type.uint32_t.withName("DWORD"); michael@0: michael@0: /* A special type used to represent flags passed as DWORDs to a function. michael@0: * In JavaScript, bitwise manipulation of numbers, such as or-ing flags, michael@0: * can produce negative numbers. Since DWORD is unsigned, these negative michael@0: * numbers simply cannot be converted to DWORD. For this reason, whenever michael@0: * bit manipulation is called for, you should rather use DWORD_FLAGS, michael@0: * which is represented as a signed integer, hence has the correct michael@0: * semantics. michael@0: */ michael@0: Type.DWORD_FLAGS = Type.int32_t.withName("DWORD_FLAGS"); michael@0: michael@0: /** michael@0: * A C integer holding 0 in case of error or a positive integer michael@0: * in case of success. michael@0: */ michael@0: Type.zero_or_DWORD = michael@0: Type.DWORD.withName("zero_or_DWORD"); michael@0: michael@0: /** michael@0: * A C integer holding 0 in case of error, any other value in michael@0: * case of success. michael@0: */ michael@0: Type.zero_or_nothing = michael@0: Type.int.withName("zero_or_nothing"); michael@0: michael@0: /** michael@0: * A C integer holding flags related to NTFS security. michael@0: */ michael@0: Type.SECURITY_ATTRIBUTES = michael@0: Type.void_t.withName("SECURITY_ATTRIBUTES"); michael@0: michael@0: /** michael@0: * A C integer holding pointers related to NTFS security. michael@0: */ michael@0: Type.PSID = michael@0: Type.voidptr_t.withName("PSID"); michael@0: michael@0: Type.PACL = michael@0: Type.voidptr_t.withName("PACL"); michael@0: michael@0: Type.PSECURITY_DESCRIPTOR = michael@0: Type.voidptr_t.withName("PSECURITY_DESCRIPTOR"); michael@0: michael@0: /** michael@0: * A C integer holding Win32 local memory handle. michael@0: */ michael@0: Type.HLOCAL = michael@0: Type.voidptr_t.withName("HLOCAL"); michael@0: michael@0: Type.FILETIME = michael@0: new SharedAll.Type("FILETIME", michael@0: ctypes.StructType("FILETIME", [ michael@0: { lo: Type.DWORD.implementation }, michael@0: { hi: Type.DWORD.implementation }])); michael@0: michael@0: Type.FindData = michael@0: new SharedAll.Type("FIND_DATA", michael@0: ctypes.StructType("FIND_DATA", [ michael@0: { dwFileAttributes: ctypes.uint32_t }, michael@0: { ftCreationTime: Type.FILETIME.implementation }, michael@0: { ftLastAccessTime: Type.FILETIME.implementation }, michael@0: { ftLastWriteTime: Type.FILETIME.implementation }, michael@0: { nFileSizeHigh: Type.DWORD.implementation }, michael@0: { nFileSizeLow: Type.DWORD.implementation }, michael@0: { dwReserved0: Type.DWORD.implementation }, michael@0: { dwReserved1: Type.DWORD.implementation }, michael@0: { cFileName: ctypes.ArrayType(ctypes.jschar, Const.MAX_PATH) }, michael@0: { cAlternateFileName: ctypes.ArrayType(ctypes.jschar, 14) } michael@0: ])); michael@0: michael@0: Type.FILE_INFORMATION = michael@0: new SharedAll.Type("FILE_INFORMATION", michael@0: ctypes.StructType("FILE_INFORMATION", [ michael@0: { dwFileAttributes: ctypes.uint32_t }, michael@0: { ftCreationTime: Type.FILETIME.implementation }, michael@0: { ftLastAccessTime: Type.FILETIME.implementation }, michael@0: { ftLastWriteTime: Type.FILETIME.implementation }, michael@0: { dwVolumeSerialNumber: ctypes.uint32_t }, michael@0: { nFileSizeHigh: Type.DWORD.implementation }, michael@0: { nFileSizeLow: Type.DWORD.implementation }, michael@0: { nNumberOfLinks: ctypes.uint32_t }, michael@0: { nFileIndex: ctypes.uint64_t } michael@0: ])); michael@0: michael@0: Type.SystemTime = michael@0: new SharedAll.Type("SystemTime", michael@0: ctypes.StructType("SystemTime", [ michael@0: { wYear: ctypes.int16_t }, michael@0: { wMonth: ctypes.int16_t }, michael@0: { wDayOfWeek: ctypes.int16_t }, michael@0: { wDay: ctypes.int16_t }, michael@0: { wHour: ctypes.int16_t }, michael@0: { wMinute: ctypes.int16_t }, michael@0: { wSecond: ctypes.int16_t }, michael@0: { wMilliSeconds: ctypes.int16_t } michael@0: ])); michael@0: michael@0: // Special case: these functions are used by the michael@0: // finalizer michael@0: libc.declareLazy(SysFile, "_CloseHandle", michael@0: "CloseHandle", ctypes.winapi_abi, michael@0: /*return */ctypes.bool, michael@0: /*handle*/ ctypes.voidptr_t); michael@0: michael@0: SysFile.CloseHandle = function(fd) { michael@0: if (fd == INVALID_HANDLE) { michael@0: return true; michael@0: } else { michael@0: return fd.dispose(); // Returns the value of |CloseHandle|. michael@0: } michael@0: }; michael@0: michael@0: libc.declareLazy(SysFile, "_FindClose", michael@0: "FindClose", ctypes.winapi_abi, michael@0: /*return */ctypes.bool, michael@0: /*handle*/ ctypes.voidptr_t); michael@0: michael@0: SysFile.FindClose = function(handle) { michael@0: if (handle == INVALID_HANDLE) { michael@0: return true; michael@0: } else { michael@0: return handle.dispose(); // Returns the value of |FindClose|. michael@0: } michael@0: }; michael@0: michael@0: // Declare libc functions as functions of |OS.Win.File| michael@0: michael@0: libc.declareLazyFFI(SysFile, "CopyFile", michael@0: "CopyFileW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*sourcePath*/ Type.path, michael@0: /*destPath*/ Type.path, michael@0: /*bailIfExist*/Type.bool); michael@0: michael@0: libc.declareLazyFFI(SysFile, "CreateDirectory", michael@0: "CreateDirectoryW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*name*/ Type.jschar.in_ptr, michael@0: /*security*/Type.SECURITY_ATTRIBUTES.in_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "CreateFile", michael@0: "CreateFileW", ctypes.winapi_abi, michael@0: /*return*/ Type.file_HANDLE, michael@0: /*name*/ Type.path, michael@0: /*access*/ Type.DWORD_FLAGS, michael@0: /*share*/ Type.DWORD_FLAGS, michael@0: /*security*/Type.SECURITY_ATTRIBUTES.in_ptr, michael@0: /*creation*/Type.DWORD_FLAGS, michael@0: /*flags*/ Type.DWORD_FLAGS, michael@0: /*template*/Type.HANDLE); michael@0: michael@0: libc.declareLazyFFI(SysFile, "DeleteFile", michael@0: "DeleteFileW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*path*/ Type.path); michael@0: michael@0: libc.declareLazyFFI(SysFile, "FileTimeToSystemTime", michael@0: "FileTimeToSystemTime", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*filetime*/Type.FILETIME.in_ptr, michael@0: /*systime*/ Type.SystemTime.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SystemTimeToFileTime", michael@0: "SystemTimeToFileTime", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*systime*/ Type.SystemTime.in_ptr, michael@0: /*filetime*/ Type.FILETIME.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "FindFirstFile", michael@0: "FindFirstFileW", ctypes.winapi_abi, michael@0: /*return*/ Type.find_HANDLE, michael@0: /*pattern*/Type.path, michael@0: /*data*/ Type.FindData.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "FindNextFile", michael@0: "FindNextFileW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*prev*/ Type.find_HANDLE, michael@0: /*data*/ Type.FindData.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "FormatMessage", michael@0: "FormatMessageW", ctypes.winapi_abi, michael@0: /*return*/ Type.DWORD, michael@0: /*flags*/ Type.DWORD_FLAGS, michael@0: /*source*/ Type.void_t.in_ptr, michael@0: /*msgid*/ Type.DWORD_FLAGS, michael@0: /*langid*/ Type.DWORD_FLAGS, michael@0: /*buf*/ Type.out_wstring, michael@0: /*size*/ Type.DWORD, michael@0: /*Arguments*/Type.void_t.in_ptr michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "GetCurrentDirectory", michael@0: "GetCurrentDirectoryW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_DWORD, michael@0: /*length*/ Type.DWORD, michael@0: /*buf*/ Type.out_path michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "GetDiskFreeSpaceEx", michael@0: "GetDiskFreeSpaceExW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*directoryName*/ Type.path, michael@0: /*freeBytesForUser*/ Type.uint64_t.out_ptr, michael@0: /*totalBytesForUser*/ Type.uint64_t.out_ptr, michael@0: /*freeTotalBytesOnDrive*/ Type.uint64_t.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "GetFileInformationByHandle", michael@0: "GetFileInformationByHandle", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*handle*/ Type.HANDLE, michael@0: /*info*/ Type.FILE_INFORMATION.out_ptr); michael@0: michael@0: libc.declareLazyFFI(SysFile, "MoveFileEx", michael@0: "MoveFileExW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*sourcePath*/ Type.path, michael@0: /*destPath*/ Type.path, michael@0: /*flags*/ Type.DWORD michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "ReadFile", michael@0: "ReadFile", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*file*/ Type.HANDLE, michael@0: /*buffer*/ Type.voidptr_t, michael@0: /*nbytes*/ Type.DWORD, michael@0: /*nbytes_read*/Type.DWORD.out_ptr, michael@0: /*overlapped*/Type.void_t.inout_ptr // FIXME: Implement? michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "RemoveDirectory", michael@0: "RemoveDirectoryW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*path*/ Type.path); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SetCurrentDirectory", michael@0: "SetCurrentDirectoryW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*path*/ Type.path michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SetEndOfFile", michael@0: "SetEndOfFile", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*file*/ Type.HANDLE); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SetFilePointer", michael@0: "SetFilePointer", ctypes.winapi_abi, michael@0: /*return*/ Type.DWORD, michael@0: /*file*/ Type.HANDLE, michael@0: /*distlow*/Type.long, michael@0: /*disthi*/ Type.long.in_ptr, michael@0: /*method*/ Type.DWORD); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SetFileTime", michael@0: "SetFileTime", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*file*/ Type.HANDLE, michael@0: /*creation*/ Type.FILETIME.in_ptr, michael@0: /*access*/ Type.FILETIME.in_ptr, michael@0: /*write*/ Type.FILETIME.in_ptr); michael@0: michael@0: michael@0: libc.declareLazyFFI(SysFile, "WriteFile", michael@0: "WriteFile", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*file*/ Type.HANDLE, michael@0: /*buffer*/ Type.voidptr_t, michael@0: /*nbytes*/ Type.DWORD, michael@0: /*nbytes_wr*/Type.DWORD.out_ptr, michael@0: /*overlapped*/Type.void_t.inout_ptr // FIXME: Implement? michael@0: ); michael@0: michael@0: libc.declareLazyFFI(SysFile, "FlushFileBuffers", michael@0: "FlushFileBuffers", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*file*/ Type.HANDLE); michael@0: michael@0: libc.declareLazyFFI(SysFile, "GetFileAttributes", michael@0: "GetFileAttributesW", ctypes.winapi_abi, michael@0: /*return*/ Type.DWORD_FLAGS, michael@0: /*fileName*/ Type.path); michael@0: michael@0: libc.declareLazyFFI(SysFile, "SetFileAttributes", michael@0: "SetFileAttributesW", ctypes.winapi_abi, michael@0: /*return*/ Type.zero_or_nothing, michael@0: /*fileName*/ Type.path, michael@0: /*fileAttributes*/ Type.DWORD_FLAGS); michael@0: michael@0: advapi32.declareLazyFFI(SysFile, "GetNamedSecurityInfo", michael@0: "GetNamedSecurityInfoW", ctypes.winapi_abi, michael@0: /*return*/ Type.DWORD, michael@0: /*objectName*/ Type.path, michael@0: /*objectType*/ Type.DWORD, michael@0: /*securityInfo*/ Type.DWORD, michael@0: /*sidOwner*/ Type.PSID.out_ptr, michael@0: /*sidGroup*/ Type.PSID.out_ptr, michael@0: /*dacl*/ Type.PACL.out_ptr, michael@0: /*sacl*/ Type.PACL.out_ptr, michael@0: /*securityDesc*/ Type.PSECURITY_DESCRIPTOR.out_ptr); michael@0: michael@0: advapi32.declareLazyFFI(SysFile, "SetNamedSecurityInfo", michael@0: "SetNamedSecurityInfoW", ctypes.winapi_abi, michael@0: /*return*/ Type.DWORD, michael@0: /*objectName*/ Type.path, michael@0: /*objectType*/ Type.DWORD, michael@0: /*securityInfo*/ Type.DWORD, michael@0: /*sidOwner*/ Type.PSID, michael@0: /*sidGroup*/ Type.PSID, michael@0: /*dacl*/ Type.PACL, michael@0: /*sacl*/ Type.PACL); michael@0: michael@0: libc.declareLazyFFI(SysFile, "LocalFree", michael@0: "LocalFree", ctypes.winapi_abi, michael@0: /*return*/ Type.HLOCAL, michael@0: /*mem*/ Type.HLOCAL); michael@0: }; michael@0: michael@0: exports.OS.Win = { michael@0: File: { michael@0: _init: init michael@0: } michael@0: }; michael@0: })(this); michael@0: }