package wincmd import ( "fmt" "strconv" "strings" "unsafe" "b612.me/win32api" "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) func StartProcessWithSYS(appPath, cmdLine, workDir string, runas bool) error { var ( sessionId win32api.HANDLE userToken win32api.TOKEN = 0 envInfo win32api.HANDLE impersonationToken win32api.HANDLE = 0 startupInfo win32api.StartupInfo processInfo win32api.ProcessInformation sessionInformation win32api.HANDLE = win32api.HANDLE(0) sessionCount int = 0 sessionList []*win32api.WTS_SESSION_INFO = make([]*win32api.WTS_SESSION_INFO, 0) err error ) if err := win32api.WTSEnumerateSessions(0, 0, 1, &sessionInformation, &sessionCount); err != nil { return err } structSize := unsafe.Sizeof(win32api.WTS_SESSION_INFO{}) current := uintptr(sessionInformation) for i := 0; i < sessionCount; i++ { sessionList = append(sessionList, (*win32api.WTS_SESSION_INFO)(unsafe.Pointer(current))) current += structSize } if sessionId, err = func() (win32api.HANDLE, error) { for i := range sessionList { if sessionList[i].State == win32api.WTSActive { return sessionList[i].SessionID, nil } } if sessionId, err := win32api.WTSGetActiveConsoleSessionId(); sessionId == 0xFFFFFFFF { return 0xFFFFFFFF, fmt.Errorf("get current user session token: call native WTSGetActiveConsoleSessionId: %s", err) } else { return win32api.HANDLE(sessionId), nil } }(); err != nil { return err } if err := win32api.WTSQueryUserToken(sessionId, &impersonationToken); err != nil { return err } if err := win32api.DuplicateTokenEx(impersonationToken, 0, 0, int(win32api.SecurityImpersonation), win32api.TokenPrimary, &userToken); err != nil { return fmt.Errorf("call native DuplicateTokenEx: %s", err) } if runas { var admin win32api.TOKEN_LINKED_TOKEN var dt uintptr = 0 if err := win32api.GetTokenInformation(impersonationToken, 19, uintptr(unsafe.Pointer(&admin)), uintptr(unsafe.Sizeof(admin)), &dt); err == nil { userToken = admin.LinkedToken } } if err := win32api.CloseHandle(impersonationToken); err != nil { return fmt.Errorf("close windows handle used for token duplication: %s", err) } if err := win32api.CreateEnvironmentBlock(&envInfo, userToken, 0); err != nil { return fmt.Errorf("create environment details for process: %s", err) } creationFlags := win32api.CREATE_UNICODE_ENVIRONMENT | win32api.CREATE_NEW_CONSOLE startupInfo.ShowWindow = win32api.SW_SHOW startupInfo.Desktop = windows.StringToUTF16Ptr("winsta0\\default") if err := win32api.CreateProcessAsUser(userToken, appPath, cmdLine, 0, 0, 0, creationFlags, envInfo, workDir, &startupInfo, &processInfo); err != nil { return fmt.Errorf("create process as user: %s", err) } return nil } func GetRunningProcess() ([]map[string]string, error) { result := []map[string]string{} pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0) if err != nil { return result, err } for { var proc win32api.PROCESSENTRY32 proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc)) if err := win32api.Process32Next(pHandle, &proc); err == nil { bytetmp := proc.SzExeFile[0:] var sakura []byte for _, v := range bytetmp { if v == byte(0) { break } sakura = append(sakura, v) } result = append(result, map[string]string{"name": string(sakura), "pid": strconv.Itoa(int(proc.Th32ProcessID))}) } else { break } } win32api.CloseHandle(pHandle) return result, nil } func IsProcessRunningByPID(pid int) bool { pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0) if err != nil { return false } for { var proc win32api.PROCESSENTRY32 proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc)) if err := win32api.Process32Next(pHandle, &proc); err == nil { bytetmp := int(proc.Th32ProcessID) if bytetmp == pid { return true } } else { break } } win32api.CloseHandle(pHandle) return false } func IsProcessRunning(name string) bool { pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0) if err != nil { return false } for { var proc win32api.PROCESSENTRY32 proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc)) if err := win32api.Process32Next(pHandle, &proc); err == nil { bytetmp := proc.SzExeFile[0:] var sakura []byte for _, v := range bytetmp { if v == byte(0) { break } sakura = append(sakura, v) } if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) { return true } } else { break } } win32api.CloseHandle(pHandle) return false } func GetProcessCount(name string) int { var res int = 0 pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0) if err != nil { return 0 } for { var proc win32api.PROCESSENTRY32 proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc)) if err := win32api.Process32Next(pHandle, &proc); err == nil { bytetmp := proc.SzExeFile[0:] var sakura []byte for _, v := range bytetmp { if v == byte(0) { break } sakura = append(sakura, v) } if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) { res++ } } else { break } } win32api.CloseHandle(pHandle) return res } func Isas() bool { _, errs := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM`, registry.ALL_ACCESS) if errs != nil { return false } return true } func StartProcess(appPath, cmdLine, wordDir string, runas bool, ShowWindow int) bool { var cst string if runas { cst = "runas" } else { cst = "open" } r := win32api.ShellExecute(0, cst, appPath, cmdLine, wordDir, ShowWindow) if r != nil { return false } return true } func StartProcessWithPID(appPath, cmdLine, workDir string, runas bool, ShowWindow int) int { var sakura win32api.SHELLEXECUTEINFOW sakura.Hwnd = 0 sakura.NShow = ShowWindow sakura.FMask = 0x00000040 sakura.LpFile = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(appPath))) sakura.LpDirectory = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(workDir))) if runas { sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("runas"))) } else { sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("open"))) } sakura.CbSize = win32api.DWORD(unsafe.Sizeof(sakura)) if err := win32api.ShellExecuteEx(&sakura); err != nil { return 0 } return int(win32api.GetProcessId(sakura.HProcess)) } func AutoRun(key, path string) (bool, error) { reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS) if errs != nil { return false, errs } if errs = reg.SetStringValue(key, path); errs != nil { return false, errs } return true, nil } func DeleteAutoRun(key string) (bool, error) { reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS) if errs != nil { return false, errs } if _, i, _ := reg.GetStringValue(key); i == 0 { return true, nil } if errs = reg.DeleteValue(key); errs != nil { return false, errs } return true, nil } func IsAutoRun(key, path string) bool { reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS) if errs != nil { return false } if sa, _, _ := reg.GetStringValue(key); sa == path { return true } return false }