...

Source file src/github.com/Microsoft/hcsshim/internal/winobjdir/object_dir.go

Documentation: github.com/Microsoft/hcsshim/internal/winobjdir

     1  //go:build windows
     2  
     3  package winobjdir
     4  
     5  import (
     6  	"path/filepath"
     7  	"syscall"
     8  	"unsafe"
     9  
    10  	"github.com/Microsoft/hcsshim/internal/winapi"
    11  )
    12  
    13  const bufferSize = 1024
    14  
    15  // EnumerateNTObjectDirectory queries for all entires in the object
    16  // directory at `ntObjDirPath`. returns the resulting entry names as a string slice.
    17  func EnumerateNTObjectDirectory(ntObjDirPath string) ([]string, error) {
    18  	var (
    19  		handle uintptr
    20  		oa     winapi.ObjectAttributes
    21  
    22  		context      uint32
    23  		returnLength uint32
    24  		buffer       [bufferSize]byte
    25  		result       []string
    26  	)
    27  
    28  	path := filepath.Clean(ntObjDirPath)
    29  	fsNtPath := filepath.FromSlash(path)
    30  
    31  	pathUnicode, err := winapi.NewUnicodeString(fsNtPath)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	oa.Length = unsafe.Sizeof(oa)
    37  	oa.ObjectName = pathUnicode
    38  
    39  	// open `ntObjDirPath` directory
    40  	status := winapi.NtOpenDirectoryObject(
    41  		&handle,
    42  		winapi.FILE_LIST_DIRECTORY,
    43  		&oa,
    44  	)
    45  
    46  	if !winapi.NTSuccess(status) {
    47  		return nil, winapi.RtlNtStatusToDosError(status)
    48  	}
    49  
    50  	defer syscall.Close(syscall.Handle(handle))
    51  
    52  	for {
    53  		// Query opened `globalNTPath` for entries. This call takes in a
    54  		// set length buffer, so to ensure we find all entires, we make
    55  		// successive calls until no more entires exist or an error is seen.
    56  		status = winapi.NtQueryDirectoryObject(
    57  			handle,
    58  			&buffer[0],
    59  			bufferSize,
    60  			false,
    61  			false,
    62  			&context,
    63  			&returnLength,
    64  		)
    65  
    66  		if !winapi.NTSuccess(status) && status != winapi.STATUS_MORE_ENTRIES {
    67  			if status == winapi.STATUS_NO_MORE_ENTRIES {
    68  				break
    69  			}
    70  			return nil, winapi.RtlNtStatusToDosError(status)
    71  		}
    72  		dirInfo := (*winapi.ObjectDirectoryInformation)(unsafe.Pointer(&buffer[0]))
    73  		index := 1
    74  		for {
    75  			if dirInfo == nil || dirInfo.Name.Length == 0 {
    76  				break
    77  			}
    78  			result = append(result, dirInfo.Name.String())
    79  			size := unsafe.Sizeof(winapi.ObjectDirectoryInformation{}) * uintptr(index)
    80  			dirInfo = (*winapi.ObjectDirectoryInformation)(unsafe.Pointer(&buffer[size]))
    81  			index++
    82  		}
    83  	}
    84  
    85  	return result, nil
    86  }
    87  

View as plain text