120 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			120 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // +build windows
 | |
| 
 | |
| package ps
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"syscall"
 | |
| 	"unsafe"
 | |
| )
 | |
| 
 | |
| // Windows API functions
 | |
| var (
 | |
| 	modKernel32                  = syscall.NewLazyDLL("kernel32.dll")
 | |
| 	procCloseHandle              = modKernel32.NewProc("CloseHandle")
 | |
| 	procCreateToolhelp32Snapshot = modKernel32.NewProc("CreateToolhelp32Snapshot")
 | |
| 	procProcess32First           = modKernel32.NewProc("Process32FirstW")
 | |
| 	procProcess32Next            = modKernel32.NewProc("Process32NextW")
 | |
| )
 | |
| 
 | |
| // Some constants from the Windows API
 | |
| const (
 | |
| 	ERROR_NO_MORE_FILES = 0x12
 | |
| 	MAX_PATH            = 260
 | |
| )
 | |
| 
 | |
| // PROCESSENTRY32 is the Windows API structure that contains a process's
 | |
| // information.
 | |
| type PROCESSENTRY32 struct {
 | |
| 	Size              uint32
 | |
| 	CntUsage          uint32
 | |
| 	ProcessID         uint32
 | |
| 	DefaultHeapID     uintptr
 | |
| 	ModuleID          uint32
 | |
| 	CntThreads        uint32
 | |
| 	ParentProcessID   uint32
 | |
| 	PriorityClassBase int32
 | |
| 	Flags             uint32
 | |
| 	ExeFile           [MAX_PATH]uint16
 | |
| }
 | |
| 
 | |
| // WindowsProcess is an implementation of Process for Windows.
 | |
| type WindowsProcess struct {
 | |
| 	pid  int
 | |
| 	ppid int
 | |
| 	exe  string
 | |
| }
 | |
| 
 | |
| func (p *WindowsProcess) Pid() int {
 | |
| 	return p.pid
 | |
| }
 | |
| 
 | |
| func (p *WindowsProcess) PPid() int {
 | |
| 	return p.ppid
 | |
| }
 | |
| 
 | |
| func (p *WindowsProcess) Executable() string {
 | |
| 	return p.exe
 | |
| }
 | |
| 
 | |
| func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess {
 | |
| 	// Find when the string ends for decoding
 | |
| 	end := 0
 | |
| 	for {
 | |
| 		if e.ExeFile[end] == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 		end++
 | |
| 	}
 | |
| 
 | |
| 	return &WindowsProcess{
 | |
| 		pid:  int(e.ProcessID),
 | |
| 		ppid: int(e.ParentProcessID),
 | |
| 		exe:  syscall.UTF16ToString(e.ExeFile[:end]),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func findProcess(pid int) (Process, error) {
 | |
| 	ps, err := processes()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	for _, p := range ps {
 | |
| 		if p.Pid() == pid {
 | |
| 			return p, nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil, nil
 | |
| }
 | |
| 
 | |
| func processes() ([]Process, error) {
 | |
| 	handle, _, _ := procCreateToolhelp32Snapshot.Call(
 | |
| 		0x00000002,
 | |
| 		0)
 | |
| 	if handle < 0 {
 | |
| 		return nil, syscall.GetLastError()
 | |
| 	}
 | |
| 	defer procCloseHandle.Call(handle)
 | |
| 
 | |
| 	var entry PROCESSENTRY32
 | |
| 	entry.Size = uint32(unsafe.Sizeof(entry))
 | |
| 	ret, _, _ := procProcess32First.Call(handle, uintptr(unsafe.Pointer(&entry)))
 | |
| 	if ret == 0 {
 | |
| 		return nil, fmt.Errorf("Error retrieving process info.")
 | |
| 	}
 | |
| 
 | |
| 	results := make([]Process, 0, 50)
 | |
| 	for {
 | |
| 		results = append(results, newWindowsProcess(&entry))
 | |
| 
 | |
| 		ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
 | |
| 		if ret == 0 {
 | |
| 			break
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return results, nil
 | |
| }
 |