This is an example of ReadDirectoryChangesW, written in go
kernel32dll := w32.NewKernel32DLL()
dirPath := "C://test_dir"
// Get the HANDLE of the target directory
hDir, _ := kernel32dll.CreateFile(dirPath,
w32.FILE_LIST_DIRECTORY,
w32.FILE_SHARE_READ|w32.FILE_SHARE_WRITE|w32.FILE_SHARE_DELETE,
0,
w32.OPEN_EXISTING,
w32.FILE_FLAG_BACKUP_SEMANTICS|w32.FILE_FLAG_OVERLAPPED,
0,
)
defer kernel32dll.CloseHandle(hDir) // close the handle when the program exit
var maxBufferSize uint32 = 96 // depend on you.
buffer := make([]uint8, maxBufferSize)
// a function for reset the data.
memset := func(a []uint8, v uint8) {
for i := range a {
a[i] = v
}
}
// a function for get the filename
getName := func(offset, fileNameLength uint32) string {
size := fileNameLength / 2
filename := make([]uint16, size)
var i uint32 = 0
for i = 0; i < size; i++ {
filename[i] = binary.LittleEndian.Uint16([]byte{buffer[offset+2*i], buffer[offset+2*i+1]})
}
return syscall.UTF16ToString(filename)
}
var record w32.FILE_NOTIFY_INFORMATION
for {
var dwBytes uint32 = 0
memset(buffer, 0) // clear the buffer for use again.
kernel32dll.ReadDirectoryChanges(hDir,
uintptr(unsafe.Pointer(&buffer[0])),
maxBufferSize,
true, // bWatchSubtree
w32.FILE_NOTIFY_CHANGE_LAST_WRITE|w32.FILE_NOTIFY_CHANGE_CREATION|w32.FILE_NOTIFY_CHANGE_FILE_NAME,
&dwBytes,
nil,
0,
)
if dwBytes == 0 { // if successful dwBytes is the number bytes used, or zero for Failed.
fmt.Printf("Buffer overflow! max-size:%d\n", maxBufferSize)
return
}
record = *(*w32.FILE_NOTIFY_INFORMATION)(unsafe.Pointer(&buffer[0]))
// There may be many FILE_NOTIFY_INFORMATION. For example, if you rename the file, it will trigger the FILE_ACTION_RENAMED_OLD_NAME and FILE_ACTION_RENAMED_NEW_NAM
var offsetFilename uint32 = 12 // The 12 is calculated from FILE_NOTIFY_INFORMATION.{NextEntryOffset, Action, FileName Length} => they are uint32 => 4*3=12
for {
switch record.Action {
case w32.FILE_ACTION_ADDED:
fmt.Println("FILE_ACTION_ADDED")
case w32.FILE_ACTION_REMOVED:
fmt.Println("FILE_ACTION_REMOVED")
return
case w32.FILE_ACTION_MODIFIED:
fmt.Println("FILE_ACTION_MODIFIED")
case w32.FILE_ACTION_RENAMED_OLD_NAME:
fmt.Println("FILE_ACTION_RENAMED_OLD_NAME")
case w32.FILE_ACTION_RENAMED_NEW_NAME:
fmt.Println("FILE_ACTION_RENAMED_NEW_NAME")
default:
break
}
fmt.Println(getName(offsetFilename, record.FileNameLength))
if record.NextEntryOffset == 0 {
break
}
offsetFilename = record.NextEntryOffset + 12
record = *(*w32.FILE_NOTIFY_INFORMATION)(unsafe.Pointer(uintptr(unsafe.Pointer(&buffer[0])) + uintptr(record.NextEntryOffset)))
}
}
You can go here to get the complete code.
https://github.com/CarsonSlovoka/go-pkg/blob/cf4a28372b05458d715ab118d4ce888b2727ac4d/v2/w32/kernel32_func_test.go#L465-L597