mirror of
https://github.com/golang/sys.git
synced 2026-02-08 11:46:04 +03:00
windows: add NtSetInformationFile
Added NtSetInformationFile and some const values related to it. The doc for the function and the values of the file information class can be found here: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntsetinformationfile The values of the flags in the individual FILE_INFORMATION_CLASS can be found here: FILE_RENAME_INFORMATION - https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_rename_information FILE_DISPOSITION_INFORMATION_EX - https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_file_disposition_information_ex FILE_CASE_SENSITIVE_INFORMATION - https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_case_sensitive_information FILE_LINK_INFORMATION - https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_link_information The other file information classes do not have flag values. Fixes golang/go#48933 Change-Id: I917ff4c8df132f8584fd6d924cf5a9626a065092 Reviewed-on: https://go-review.googlesource.com/c/sys/+/355495 Trust: Alex Brainman <alex.brainman@gmail.com> Trust: Emmanuel Odeke <emmanuel@orijtech.com> Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
@@ -423,6 +423,7 @@ func NewCallbackCDecl(fn interface{}) uintptr {
|
||||
//sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString
|
||||
//sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile
|
||||
//sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile
|
||||
//sys NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile
|
||||
//sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus
|
||||
//sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus
|
||||
//sys RtlDefaultNpAcl(acl **ACL) (ntstatus error) = ntdll.RtlDefaultNpAcl
|
||||
|
||||
@@ -858,3 +858,77 @@ func TestSystemModuleVersions(t *testing.T) {
|
||||
(fixedInfo.FileVersionLS>>0)&0xff)
|
||||
}
|
||||
}
|
||||
|
||||
type fileRenameInformation struct {
|
||||
ReplaceIfExists uint32
|
||||
RootDirectory windows.Handle
|
||||
FileNameLength uint32
|
||||
FileName [1]uint16
|
||||
}
|
||||
|
||||
func TestNtCreateFileAndNtSetInformationFile(t *testing.T) {
|
||||
var iosb windows.IO_STATUS_BLOCK
|
||||
var allocSize int64 = 0
|
||||
// Open test directory with NtCreateFile.
|
||||
testDirPath := t.TempDir()
|
||||
objectName, err := windows.NewNTUnicodeString("\\??\\" + testDirPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oa := &windows.OBJECT_ATTRIBUTES{
|
||||
ObjectName: objectName,
|
||||
}
|
||||
oa.Length = uint32(unsafe.Sizeof(*oa))
|
||||
var testDirHandle windows.Handle
|
||||
err = windows.NtCreateFile(&testDirHandle, windows.FILE_GENERIC_READ|windows.FILE_GENERIC_WRITE, oa, &iosb,
|
||||
&allocSize, 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, windows.FILE_OPEN,
|
||||
windows.FILE_DIRECTORY_FILE, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("NtCreateFile(%v) failed: %v", testDirPath, err)
|
||||
}
|
||||
defer windows.CloseHandle(testDirHandle)
|
||||
// Create a file in test directory with NtCreateFile.
|
||||
fileName := "filename"
|
||||
filePath := filepath.Join(testDirPath, fileName)
|
||||
objectName, err = windows.NewNTUnicodeString(fileName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oa.RootDirectory = testDirHandle
|
||||
oa.ObjectName = objectName
|
||||
var fileHandle windows.Handle
|
||||
err = windows.NtCreateFile(&fileHandle, windows.FILE_GENERIC_READ|windows.FILE_GENERIC_WRITE|windows.DELETE, oa, &iosb,
|
||||
&allocSize, 0, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, windows.FILE_CREATE,
|
||||
0, 0, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("NtCreateFile(%v) failed: %v", filePath, err)
|
||||
}
|
||||
defer windows.CloseHandle(fileHandle)
|
||||
_, err = os.Stat(filePath)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot stat file created with NtCreatefile: %v", err)
|
||||
}
|
||||
// Rename file with NtSetInformationFile.
|
||||
newName := "newname"
|
||||
newPath := filepath.Join(testDirPath, newName)
|
||||
newNameUTF16, err := windows.UTF16FromString(newName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fileNameLen := len(newNameUTF16)*2 - 2
|
||||
var dummyFileRenameInfo fileRenameInformation
|
||||
bufferSize := int(unsafe.Offsetof(dummyFileRenameInfo.FileName)) + fileNameLen
|
||||
buffer := make([]byte, bufferSize)
|
||||
typedBufferPtr := (*fileRenameInformation)(unsafe.Pointer(&buffer[0]))
|
||||
typedBufferPtr.ReplaceIfExists = windows.FILE_RENAME_REPLACE_IF_EXISTS | windows.FILE_RENAME_POSIX_SEMANTICS
|
||||
typedBufferPtr.FileNameLength = uint32(fileNameLen)
|
||||
copy((*[1 << 29]uint16)(unsafe.Pointer(&typedBufferPtr.FileName[0]))[:], newNameUTF16)
|
||||
err = windows.NtSetInformationFile(fileHandle, &iosb, &buffer[0], uint32(bufferSize), windows.FileRenameInformation)
|
||||
if err != nil {
|
||||
t.Fatalf("NtSetInformationFile(%v) failed: %v", newPath, err)
|
||||
}
|
||||
_, err = os.Stat(newPath)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot stat rename target %v: %v", newPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2562,6 +2562,60 @@ const (
|
||||
FILE_PIPE_SERVER_END = 0x00000001
|
||||
)
|
||||
|
||||
const (
|
||||
// FileInformationClass for NtSetInformationFile
|
||||
FileBasicInformation = 4
|
||||
FileRenameInformation = 10
|
||||
FileDispositionInformation = 13
|
||||
FilePositionInformation = 14
|
||||
FileEndOfFileInformation = 20
|
||||
FileValidDataLengthInformation = 39
|
||||
FileShortNameInformation = 40
|
||||
FileIoPriorityHintInformation = 43
|
||||
FileReplaceCompletionInformation = 61
|
||||
FileDispositionInformationEx = 64
|
||||
FileCaseSensitiveInformation = 71
|
||||
FileLinkInformation = 72
|
||||
FileCaseSensitiveInformationForceAccessCheck = 75
|
||||
FileKnownFolderInformation = 76
|
||||
|
||||
// Flags for FILE_RENAME_INFORMATION
|
||||
FILE_RENAME_REPLACE_IF_EXISTS = 0x00000001
|
||||
FILE_RENAME_POSIX_SEMANTICS = 0x00000002
|
||||
FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE = 0x00000004
|
||||
FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008
|
||||
FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE = 0x00000010
|
||||
FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE = 0x00000020
|
||||
FILE_RENAME_PRESERVE_AVAILABLE_SPACE = 0x00000030
|
||||
FILE_RENAME_IGNORE_READONLY_ATTRIBUTE = 0x00000040
|
||||
FILE_RENAME_FORCE_RESIZE_TARGET_SR = 0x00000080
|
||||
FILE_RENAME_FORCE_RESIZE_SOURCE_SR = 0x00000100
|
||||
FILE_RENAME_FORCE_RESIZE_SR = 0x00000180
|
||||
|
||||
// Flags for FILE_DISPOSITION_INFORMATION_EX
|
||||
FILE_DISPOSITION_DO_NOT_DELETE = 0x00000000
|
||||
FILE_DISPOSITION_DELETE = 0x00000001
|
||||
FILE_DISPOSITION_POSIX_SEMANTICS = 0x00000002
|
||||
FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK = 0x00000004
|
||||
FILE_DISPOSITION_ON_CLOSE = 0x00000008
|
||||
FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE = 0x00000010
|
||||
|
||||
// Flags for FILE_CASE_SENSITIVE_INFORMATION
|
||||
FILE_CS_FLAG_CASE_SENSITIVE_DIR = 0x00000001
|
||||
|
||||
// Flags for FILE_LINK_INFORMATION
|
||||
FILE_LINK_REPLACE_IF_EXISTS = 0x00000001
|
||||
FILE_LINK_POSIX_SEMANTICS = 0x00000002
|
||||
FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE = 0x00000008
|
||||
FILE_LINK_NO_INCREASE_AVAILABLE_SPACE = 0x00000010
|
||||
FILE_LINK_NO_DECREASE_AVAILABLE_SPACE = 0x00000020
|
||||
FILE_LINK_PRESERVE_AVAILABLE_SPACE = 0x00000030
|
||||
FILE_LINK_IGNORE_READONLY_ATTRIBUTE = 0x00000040
|
||||
FILE_LINK_FORCE_RESIZE_TARGET_SR = 0x00000080
|
||||
FILE_LINK_FORCE_RESIZE_SOURCE_SR = 0x00000100
|
||||
FILE_LINK_FORCE_RESIZE_SR = 0x00000180
|
||||
)
|
||||
|
||||
// ProcessInformationClasses for NtQueryInformationProcess and NtSetInformationProcess.
|
||||
const (
|
||||
ProcessBasicInformation = iota
|
||||
|
||||
@@ -366,6 +366,7 @@ var (
|
||||
procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo")
|
||||
procNtCreateFile = modntdll.NewProc("NtCreateFile")
|
||||
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
|
||||
procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile")
|
||||
procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess")
|
||||
procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
|
||||
procNtSetInformationProcess = modntdll.NewProc("NtSetInformationProcess")
|
||||
@@ -3170,6 +3171,14 @@ func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, i
|
||||
return
|
||||
}
|
||||
|
||||
func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) {
|
||||
r0, _, _ := syscall.Syscall6(procNtSetInformationFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class), 0)
|
||||
if r0 != 0 {
|
||||
ntstatus = NTStatus(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) {
|
||||
r0, _, _ := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen)), 0)
|
||||
if r0 != 0 {
|
||||
|
||||
Reference in New Issue
Block a user