// Close will release all of the objects and memory needed to process debug // messages from other processes. func (r *OutputDebugStringReceiver) Close() error { if nil == r.err { r.done <- struct{}{} <-r.completed } var result, err error result = r.dataReadyEvent.Close() err = r.bufferReadyEvent.Close() if nil != result { result = err } if 0 != r.view { err = windows.UnmapViewOfFile(r.view) if nil != result { result = err } } if windows.InvalidHandle != r.buffer { err = windows.CloseHandle(r.buffer) if nil != result { result = err } } return result }
func munmap(b []byte) (err error) { m := memoryMap(b) dh := m.header() addr := dh.Data length := uintptr(dh.Len) flush(addr, length) err = windows.UnmapViewOfFile(addr) if err != nil { return err } handleLock.Lock() defer handleLock.Unlock() handle, ok := handleMap[addr] if !ok { // should be impossible; we would've errored above return errors.New("unknown base address") } delete(handleMap, addr) e := windows.CloseHandle(windows.Handle(handle)) return os.NewSyscallError("CloseHandle", e) }
// Launch creates and begins debugging a new process. func Launch(cmd []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists. if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } if _, err := os.Stat(argv0Go); err != nil { return nil, err } // Duplicate the stdin/stdout/stderr handles files := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)} p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(files)) for i := range files { err := syscall.DuplicateHandle(p, syscall.Handle(files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, err } defer syscall.CloseHandle(syscall.Handle(fd[i])) } argv0, err := syscall.UTF16PtrFromString(argv0Go) if err != nil { return nil, err } // create suitable command line for CreateProcess // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L326 // adapted from standard library makeCmdLine // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L86 var cmdLineGo string if len(cmd) >= 1 { for _, v := range cmd { if cmdLineGo != "" { cmdLineGo += " " } cmdLineGo += syscall.EscapeArg(v) } } var cmdLine *uint16 if cmdLineGo != "" { if cmdLine, err = syscall.UTF16PtrFromString(cmdLineGo); err != nil { return nil, err } } // Initialize the startup info and create process si := new(sys.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES si.StdInput = sys.Handle(fd[0]) si.StdOutput = sys.Handle(fd[1]) si.StdErr = sys.Handle(fd[2]) pi := new(sys.ProcessInformation) err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, DEBUGONLYTHISPROCESS, nil, nil, si, pi) if err != nil { return nil, err } sys.CloseHandle(sys.Handle(pi.Process)) sys.CloseHandle(sys.Handle(pi.Thread)) dbp := New(int(pi.ProcessId)) switch runtime.GOARCH { case "amd64": dbp.arch = AMD64Arch() } // Note - it should not actually be possible for the // call to waitForDebugEvent to fail, since Windows // will always fire a CreateProcess event immediately // after launching under DEBUGONLYTHISPROCESS. var tid, exitCode int dbp.execPtraceFunc(func() { tid, exitCode, err = dbp.waitForDebugEvent() }) if err != nil { return nil, err } if tid == 0 { dbp.postExit() return nil, ProcessExitedError{Pid: dbp.Pid, Status: exitCode} } return initializeDebugProcess(dbp, argv0Go, false) }
func (e *windowsEvent) Close() error { return windows.CloseHandle(e.handle) }
func (e *event) Close() error { return windows.CloseHandle(e.h) }
func cl(fd int) (err error) { return windows.CloseHandle(windows.Handle(fd)) }
// Launch creates and begins debugging a new process. func Launch(cmd []string) (*Process, error) { argv0Go, err := filepath.Abs(cmd[0]) if err != nil { return nil, err } // Make sure the binary exists and is an executable file if filepath.Base(cmd[0]) == cmd[0] { if _, err := exec.LookPath(cmd[0]); err != nil { return nil, err } } peFile, err := openExecutablePath(argv0Go) if err != nil { return nil, NotExecutableErr } peFile.Close() // Duplicate the stdin/stdout/stderr handles files := []uintptr{uintptr(syscall.Stdin), uintptr(syscall.Stdout), uintptr(syscall.Stderr)} p, _ := syscall.GetCurrentProcess() fd := make([]syscall.Handle, len(files)) for i := range files { err := syscall.DuplicateHandle(p, syscall.Handle(files[i]), p, &fd[i], 0, true, syscall.DUPLICATE_SAME_ACCESS) if err != nil { return nil, err } defer syscall.CloseHandle(syscall.Handle(fd[i])) } argv0, err := syscall.UTF16PtrFromString(argv0Go) if err != nil { return nil, err } // create suitable command line for CreateProcess // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L326 // adapted from standard library makeCmdLine // see https://github.com/golang/go/blob/master/src/syscall/exec_windows.go#L86 var cmdLineGo string if len(cmd) >= 1 { for _, v := range cmd { if cmdLineGo != "" { cmdLineGo += " " } cmdLineGo += syscall.EscapeArg(v) } } var cmdLine *uint16 if cmdLineGo != "" { if cmdLine, err = syscall.UTF16PtrFromString(cmdLineGo); err != nil { return nil, err } } // Initialize the startup info and create process si := new(sys.StartupInfo) si.Cb = uint32(unsafe.Sizeof(*si)) si.Flags = syscall.STARTF_USESTDHANDLES si.StdInput = sys.Handle(fd[0]) si.StdOutput = sys.Handle(fd[1]) si.StdErr = sys.Handle(fd[2]) pi := new(sys.ProcessInformation) err = sys.CreateProcess(argv0, cmdLine, nil, nil, true, _DEBUG_ONLY_THIS_PROCESS, nil, nil, si, pi) if err != nil { return nil, err } sys.CloseHandle(sys.Handle(pi.Process)) sys.CloseHandle(sys.Handle(pi.Thread)) return newDebugProcess(int(pi.ProcessId), argv0Go) }