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:
Hao Mou
2021-10-23 08:55:30 +00:00
committed by Alex Brainman
parent 8e5104632a
commit d6a326fbbf
4 changed files with 138 additions and 0 deletions
+74
View File
@@ -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)
}
}