winutils.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package winutils
  15. import (
  16. "crypto/md5"
  17. "fmt"
  18. "io"
  19. "io/ioutil"
  20. "path"
  21. "regexp"
  22. "strconv"
  23. "strings"
  24. "time"
  25. "yunion.io/x/log"
  26. "yunion.io/x/pkg/utils"
  27. "yunion.io/x/onecloud/pkg/util/procutils"
  28. "yunion.io/x/onecloud/pkg/util/regutils2"
  29. )
  30. var _CHNTPW_PATH string
  31. func SetChntpwPath(spath string) {
  32. _CHNTPW_PATH = spath
  33. }
  34. func GetChntpwPath() string {
  35. if len(_CHNTPW_PATH) == 0 {
  36. _CHNTPW_PATH = "/usr/local/bin/chntpw.static"
  37. }
  38. return _CHNTPW_PATH
  39. }
  40. const (
  41. SYSTEM = "system"
  42. SOFTWARE = "software"
  43. SECURITY = "security"
  44. SAM = "sam"
  45. CONFIRM = "y"
  46. )
  47. func NewWinRegTool(spath string) *SWinRegTool {
  48. return &SWinRegTool{ConfigPath: spath}
  49. }
  50. func CheckTool(spath string) bool {
  51. return procutils.NewCommand(spath, "-h").Run() == nil
  52. }
  53. type SWinRegTool struct {
  54. ConfigPath string
  55. SystemPath string
  56. SoftwarePath string
  57. SamPath string
  58. SecurityPath string
  59. }
  60. func (w *SWinRegTool) CheckPath() bool {
  61. files, err := ioutil.ReadDir(w.ConfigPath)
  62. if err != nil {
  63. log.Errorln(err)
  64. return false
  65. }
  66. for _, file := range files {
  67. switch strings.ToLower(file.Name()) {
  68. case SYSTEM:
  69. w.SystemPath = path.Join(w.ConfigPath, file.Name())
  70. case SOFTWARE:
  71. w.SoftwarePath = path.Join(w.ConfigPath, file.Name())
  72. case SAM:
  73. w.SamPath = path.Join(w.ConfigPath, file.Name())
  74. case SECURITY:
  75. w.SecurityPath = path.Join(w.ConfigPath, file.Name())
  76. }
  77. }
  78. if len(w.SystemPath) > 0 && len(w.SoftwarePath) > 0 &&
  79. len(w.SamPath) > 0 && len(w.SecurityPath) > 0 {
  80. return true
  81. }
  82. return false
  83. }
  84. func (w *SWinRegTool) GetUsers() map[string]bool {
  85. output, err := procutils.NewCommand(GetChntpwPath(), "-l", w.SamPath).Output()
  86. if err != nil {
  87. log.Errorln(err)
  88. return nil
  89. }
  90. users := map[string]bool{}
  91. re := regexp.MustCompile(
  92. `\|\s*\w+\s*\|\s*(?P<user>\w+)\s*\|\s*(ADMIN)?\s*\|\s*(?P<lock>(dis/lock|\*BLANK\*)?)`)
  93. for _, line := range strings.Split(string(output), "\n") {
  94. m := regutils2.GetParams(re, line)
  95. if len(m) > 0 {
  96. user, _ := m["user"]
  97. if strings.ToLower(user) != "guest" {
  98. lock, _ := m["lock"]
  99. users[user] = lock != "dis/lock"
  100. }
  101. }
  102. }
  103. return users
  104. }
  105. func (w *SWinRegTool) samChange(user string, seq ...string) error {
  106. proc := procutils.NewCommand(GetChntpwPath(), "-u", user, w.SamPath, w.SystemPath, w.SecurityPath)
  107. stdin, err := proc.StdinPipe()
  108. if err != nil {
  109. return err
  110. }
  111. defer stdin.Close()
  112. outb, err := proc.StdoutPipe()
  113. if err != nil {
  114. return err
  115. }
  116. defer outb.Close()
  117. errb, err := proc.StderrPipe()
  118. if err != nil {
  119. return err
  120. }
  121. defer errb.Close()
  122. if err := proc.Start(); err != nil {
  123. return err
  124. }
  125. io.WriteString(stdin, "n\n")
  126. for _, s := range seq {
  127. io.WriteString(stdin, s+"\n")
  128. }
  129. io.WriteString(stdin, CONFIRM+"\n")
  130. stdoutPut, err := ioutil.ReadAll(outb)
  131. if err != nil {
  132. return err
  133. }
  134. stderrOutPut, err := ioutil.ReadAll(errb)
  135. if err != nil {
  136. return err
  137. }
  138. log.Debugf("Sam change %s %s", stdoutPut, stderrOutPut)
  139. done := make(chan error, 1)
  140. go func() {
  141. done <- proc.Wait()
  142. }()
  143. select {
  144. case <-time.After(time.Millisecond * 100):
  145. proc.Kill()
  146. return fmt.Errorf("Failed to change SAM password, not exit cleanly")
  147. case err := <-done:
  148. if err != nil {
  149. if exitStatus, ok := proc.GetExitStatus(err); ok {
  150. if exitStatus == 2 {
  151. return nil
  152. }
  153. }
  154. log.Errorf("Failed to change SAM password")
  155. return err
  156. } else {
  157. return nil
  158. }
  159. }
  160. }
  161. func (w *SWinRegTool) ChangePassword(user, password string) error {
  162. return w.samChange(user, "2", password)
  163. }
  164. func (w *SWinRegTool) RemovePassword(user string) error {
  165. return w.samChange(user, "2")
  166. }
  167. func (w *SWinRegTool) UnlockUser(user string) error {
  168. return w.samChange(user, "4")
  169. }
  170. func (w *SWinRegTool) GetRegFile(regPath string) (string, []string) {
  171. re := regexp.MustCompile(`\\`)
  172. vals := re.Split(regPath, -1)
  173. regSeg := []string{}
  174. for _, val := range vals {
  175. if len(val) > 0 {
  176. regSeg = append(regSeg, val)
  177. }
  178. }
  179. if regSeg[0] == "HKLM" {
  180. regSeg = regSeg[1:]
  181. }
  182. if strings.ToLower(regSeg[0]) == SOFTWARE {
  183. regSeg = regSeg[1:]
  184. return w.SoftwarePath, regSeg
  185. } else if strings.ToLower(regSeg[0]) == SYSTEM {
  186. regSeg = regSeg[1:]
  187. return w.SystemPath, regSeg
  188. } else {
  189. return "", nil
  190. }
  191. }
  192. func (w *SWinRegTool) showRegistry(spath string, keySeg []string, verb string) ([]string, error) {
  193. proc := procutils.NewCommand(GetChntpwPath(), spath)
  194. stdin, err := proc.StdinPipe()
  195. if err != nil {
  196. return nil, err
  197. }
  198. defer stdin.Close()
  199. outb, err := proc.StdoutPipe()
  200. if err != nil {
  201. return nil, err
  202. }
  203. defer outb.Close()
  204. // errb, err := proc.StderrPipe()
  205. // if err != nil {
  206. // return nil, err
  207. // }
  208. // defer errb.Close()
  209. if err := proc.Start(); err != nil {
  210. return nil, err
  211. }
  212. keypath := strings.Join(keySeg, "\\")
  213. io.WriteString(stdin, fmt.Sprintf("%s %s\n", verb, keypath))
  214. io.WriteString(stdin, "q\n")
  215. stdoutPut, err := ioutil.ReadAll(outb)
  216. if err != nil {
  217. return nil, err
  218. }
  219. time.Sleep(time.Millisecond * 100)
  220. done := make(chan error, 1)
  221. go func() {
  222. done <- proc.Wait()
  223. }()
  224. select {
  225. case <-time.After(time.Millisecond * 100):
  226. proc.Kill()
  227. case err := <-done:
  228. if err != nil {
  229. return nil, err
  230. }
  231. }
  232. return strings.Split(string(stdoutPut), "\n"), nil
  233. }
  234. func (w *SWinRegTool) getRegistry(spath string, keySeg []string) string {
  235. keyPath := strings.Join(keySeg, "\\")
  236. lines, err := w.showRegistry(spath, keySeg, "cat")
  237. if err != nil {
  238. log.Errorln(err)
  239. return ""
  240. }
  241. for i, line := range lines {
  242. if len(keyPath) > 85 {
  243. keyPath = keyPath[:85]
  244. }
  245. if strings.Contains(line, fmt.Sprintf("> Value <%s> of type REG_", keyPath)) {
  246. return lines[i+1]
  247. }
  248. }
  249. return ""
  250. }
  251. type sRegistry struct {
  252. Key string
  253. Type string
  254. Size string
  255. }
  256. func (w *SWinRegTool) listRegistry(spath string, keySeg []string) ([]string, []sRegistry, error) {
  257. lines, err := w.showRegistry(spath, keySeg, "ls")
  258. if err != nil {
  259. return nil, nil, err
  260. }
  261. keys := []string{}
  262. values := []sRegistry{}
  263. keyPattern := regexp.MustCompile("^<(?P<key>[^>]+)>$")
  264. valPattern := regexp.MustCompile(`^(?P<size>\d+)\s+(?P<type>REG\_\w+)\s+<(?P<key>[^>]+)>\s*`)
  265. for _, line := range lines {
  266. line = strings.TrimSpace(line)
  267. m := regutils2.GetParams(keyPattern, line)
  268. if len(m) > 0 {
  269. keys = append(keys, m["key"])
  270. }
  271. m = regutils2.GetParams(valPattern, line)
  272. if len(m) > 0 {
  273. values = append(values, sRegistry{m["key"], m["type"], m["size"]})
  274. }
  275. }
  276. return keys, values, nil
  277. }
  278. func (w *SWinRegTool) cmdRegistry(spath string, ops []string, retcode []int) bool {
  279. log.Infof("cmdRegistry %s -e %v", GetChntpwPath(), spath)
  280. proc := procutils.NewCommand(GetChntpwPath(), "-e", spath)
  281. stdin, err := proc.StdinPipe()
  282. if err != nil {
  283. log.Errorln(err)
  284. return false
  285. }
  286. defer stdin.Close()
  287. outb, err := proc.StdoutPipe()
  288. if err != nil {
  289. log.Errorln(err)
  290. return false
  291. }
  292. defer outb.Close()
  293. errb, err := proc.StderrPipe()
  294. if err != nil {
  295. log.Errorln(err)
  296. return false
  297. }
  298. defer errb.Close()
  299. if err := proc.Start(); err != nil {
  300. log.Errorln(err)
  301. return false
  302. }
  303. for _, op := range ops {
  304. log.Debugf("Input: %s", op)
  305. io.WriteString(stdin, op+"\n")
  306. }
  307. io.WriteString(stdin, "q\n")
  308. io.WriteString(stdin, CONFIRM+"\n")
  309. stdoutPut, err := ioutil.ReadAll(outb)
  310. if err != nil {
  311. log.Errorln(err)
  312. return false
  313. }
  314. stderrOutPut, err := ioutil.ReadAll(errb)
  315. if err != nil {
  316. log.Errorln(err)
  317. return false
  318. }
  319. log.Debugf("Cmd registry %s %s", stdoutPut, stderrOutPut)
  320. done := make(chan error, 1)
  321. go func() {
  322. done <- proc.Wait()
  323. }()
  324. select {
  325. case <-time.After(time.Millisecond * 1000):
  326. log.Errorf("Cmd registry timeout")
  327. if err := proc.Kill(); err != nil {
  328. log.Errorf("kill cmd registry process failed %s", err)
  329. }
  330. case err := <-done:
  331. if err != nil {
  332. if exitStatus, ok := proc.GetExitStatus(err); ok {
  333. log.Errorf("ops %v exit status: %d", ops, exitStatus)
  334. if in, _ := utils.InArray(exitStatus, retcode); in {
  335. return true
  336. }
  337. }
  338. } else {
  339. if in, _ := utils.InArray(0, retcode); in {
  340. return true
  341. }
  342. }
  343. }
  344. return false
  345. }
  346. func (w *SWinRegTool) setRegistry(spath string, keySeg []string, value string) bool {
  347. cmds := make([]string, 0)
  348. for i := range keySeg {
  349. if i < len(keySeg)-1 {
  350. cmds = append(cmds, fmt.Sprintf("cd %s", keySeg[i]))
  351. } else {
  352. cmds = append(cmds, fmt.Sprintf("ed %s", keySeg[i]))
  353. }
  354. }
  355. cmds = append(cmds, value)
  356. return w.cmdRegistry(spath, cmds, []int{0})
  357. }
  358. func (w *SWinRegTool) delRegistry(spath string, keySeg []string) bool {
  359. cmds := make([]string, 0)
  360. for i := range keySeg {
  361. if i < len(keySeg)-1 {
  362. cmds = append(cmds, fmt.Sprintf("cd %s", keySeg[i]))
  363. } else {
  364. cmds = append(cmds, fmt.Sprintf("rdel %s", keySeg[i]))
  365. }
  366. }
  367. return w.cmdRegistry(spath, cmds, []int{0})
  368. }
  369. func (w *SWinRegTool) mkdir(spath string, keySeg []string) bool {
  370. return w.cmdRegistry(spath,
  371. []string{
  372. fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
  373. fmt.Sprintf("nk %s", keySeg[len(keySeg)-1]),
  374. }, []int{0, 2})
  375. }
  376. func (w *SWinRegTool) keyExists(spath string, keySeg []string) bool {
  377. keys, _, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
  378. if err != nil {
  379. log.Errorln(err)
  380. return false
  381. }
  382. if utils.IsInStringArray(keySeg[len(keySeg)-1], keys) {
  383. return true
  384. }
  385. return false
  386. }
  387. func (w *SWinRegTool) valExists(spath string, keySeg []string) bool {
  388. _, vals, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
  389. if err != nil {
  390. log.Errorln(err)
  391. return false
  392. }
  393. for _, val := range vals {
  394. if val.Key == keySeg[len(keySeg)-1] {
  395. return true
  396. }
  397. }
  398. return false
  399. }
  400. func (w *SWinRegTool) mkdir_P(spath string, keySeg []string) bool {
  401. seg := []string{}
  402. for _, k := range keySeg {
  403. seg = append(seg, k)
  404. if !w.keyExists(spath, seg) {
  405. if !w.mkdir(spath, seg) {
  406. return false
  407. }
  408. }
  409. }
  410. return true
  411. }
  412. func (w *SWinRegTool) newValue(spath string, keySeg []string, regtype, val string) bool {
  413. REG_TYPE_TBL := []string{
  414. "REG_NONE",
  415. "REG_SZ",
  416. "REG_EXPAND_SZ",
  417. "REG_BINARY",
  418. "REG_DWORD",
  419. "REG_DWORD_BIG_ENDIAN",
  420. "REG_LINK",
  421. "REG_MULTI_SZ",
  422. "REG_RESOUCE_LIST",
  423. "REG_FULL_RES_DESC",
  424. "REG_RES_REQ",
  425. "REG_QWORD",
  426. }
  427. ok, idx := utils.InStringArray(regtype, REG_TYPE_TBL)
  428. if !ok {
  429. return false
  430. }
  431. cmds := []string{
  432. fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
  433. fmt.Sprintf("nv %x %s", idx, keySeg[len(keySeg)-1]),
  434. fmt.Sprintf("ed %s", keySeg[len(keySeg)-1]),
  435. }
  436. if regtype == "REG_QWORD" {
  437. cmds = append(cmds, "16", ": 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "s")
  438. } else {
  439. cmds = append(cmds, val)
  440. }
  441. return w.cmdRegistry(spath, cmds, []int{0})
  442. }
  443. func (w *SWinRegTool) GetRegistry(keyPath string) string {
  444. p1, p2s := w.GetRegFile(keyPath)
  445. if len(p1) == 0 && len(p2s) == 0 {
  446. return ""
  447. } else {
  448. return w.getRegistry(p1, p2s)
  449. }
  450. }
  451. func (w *SWinRegTool) ListRegistry(keyPath string) ([]string, []sRegistry) {
  452. p1, p2s := w.GetRegFile(keyPath)
  453. if len(p1) == 0 && len(p2s) == 0 {
  454. return nil, nil
  455. } else {
  456. v1, v2, err := w.listRegistry(p1, p2s)
  457. if err != nil {
  458. log.Errorln(err)
  459. return nil, nil
  460. }
  461. return v1, v2
  462. }
  463. }
  464. func (w *SWinRegTool) SetRegistry(keyPath, value, regtype string) bool {
  465. p1, p2s := w.GetRegFile(keyPath)
  466. if len(p1) == 0 && len(p2s) == 0 {
  467. return false
  468. } else {
  469. if w.valExists(p1, p2s) {
  470. return w.setRegistry(p1, p2s, value)
  471. } else {
  472. if !w.keyExists(p1, p2s[:len(p2s)-1]) {
  473. if !w.mkdir_P(p1, p2s[:len(p2s)-1]) {
  474. return false
  475. }
  476. }
  477. return w.newValue(p1, p2s, regtype, value)
  478. }
  479. }
  480. }
  481. func (w *SWinRegTool) DelRegistry(keyPath string) bool {
  482. p1, p2s := w.GetRegFile(keyPath)
  483. if len(p1) == 0 && len(p2s) == 0 {
  484. return false
  485. } else {
  486. if w.keyExists(p1, p2s) {
  487. ret := w.delRegistry(p1, p2s)
  488. log.Debugf("delete %s %s %v", p1, p2s, ret)
  489. return ret
  490. }
  491. return false
  492. }
  493. }
  494. func (w *SWinRegTool) KeyExists(keyPath string) bool {
  495. p1, p2s := w.GetRegFile(keyPath)
  496. if len(p1) == 0 && len(p2s) == 0 {
  497. return false
  498. } else {
  499. return w.keyExists(p1, p2s)
  500. }
  501. }
  502. func (w *SWinRegTool) MkdirP(keyPath string) bool {
  503. p1, p2s := w.GetRegFile(keyPath)
  504. if len(p1) == 0 && len(p2s) == 0 {
  505. return false
  506. } else {
  507. return w.mkdir_P(p1, p2s)
  508. }
  509. }
  510. func (w *SWinRegTool) GetCcsKey() string {
  511. ver := w.GetRegistry(`HKLM\SYSTEM\Select\Current`)
  512. log.Debugf("Current Control set %s", ver)
  513. return fmt.Sprintf("ControlSet%s", ver[len(ver)-3:])
  514. }
  515. func (w *SWinRegTool) GetCcsKeyPath() string {
  516. return fmt.Sprintf(`HKLM\SYSTEM\%s`, w.GetCcsKey())
  517. }
  518. func (w *SWinRegTool) getComputerNameKeyPath() string {
  519. key := w.GetCcsKey()
  520. return key + `\Control\ComputerName\ComputerName\ComputerName`
  521. }
  522. func (w *SWinRegTool) GetComputerName() string {
  523. key := w.getComputerNameKeyPath()
  524. return w.GetRegistry(key)
  525. }
  526. func (w *SWinRegTool) setComputerName(cn string) {
  527. MAX_COMPUTER_NAME_LEN := 15
  528. COMMON_PREFIX_LEN := 10
  529. if len(cn) > MAX_COMPUTER_NAME_LEN {
  530. suffix := cn[COMMON_PREFIX_LEN:]
  531. suffixlen := MAX_COMPUTER_NAME_LEN - COMMON_PREFIX_LEN
  532. md5sum := md5.Sum([]byte(suffix))
  533. cn = cn[:COMMON_PREFIX_LEN] + string(md5sum[:])[:suffixlen]
  534. }
  535. key := w.getComputerNameKeyPath()
  536. w.SetRegistry(key, cn, "")
  537. }
  538. func (w *SWinRegTool) SetHostname(hostname, domain string) {
  539. tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
  540. hnKey := tcpipKey + `\Hostname`
  541. dmKey := tcpipKey + `\Domain`
  542. nvHnKey := tcpipKey + `\NV Hostname`
  543. nvDmKey := tcpipKey + `\NV Domain`
  544. w.SetRegistry(hnKey, hostname, "REG_SZ")
  545. w.SetRegistry(dmKey, domain, "REG_SZ")
  546. w.SetRegistry(nvHnKey, hostname, "REG_SZ")
  547. w.SetRegistry(nvDmKey, domain, "REG_SZ")
  548. }
  549. func (w *SWinRegTool) SetDnsServer(nameserver, searchlist string) {
  550. tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
  551. ns_key := tcpipKey + `\NameServer`
  552. search_key := tcpipKey + `\SearchList`
  553. w.SetRegistry(ns_key, nameserver, "REG_SZ")
  554. w.SetRegistry(search_key, searchlist, "REG_SZ")
  555. }
  556. func (w *SWinRegTool) GetProductName() string {
  557. prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName`
  558. prodName := w.GetRegistry(prodKey)
  559. if strings.Contains(prodName, "Windows 10") {
  560. // check build number to determine whether it's actually Windows 11
  561. buildNumStr := w.GetCurrentBuildNumber()
  562. if buildNum, err := strconv.Atoi(strings.TrimSpace(buildNumStr)); err == nil && buildNum >= 22000 {
  563. prodName = strings.Replace(prodName, "Windows 10", "Windows 11", 1)
  564. }
  565. }
  566. return prodName
  567. }
  568. func (w *SWinRegTool) GetCurrentBuildNumber() string {
  569. prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuildNumber`
  570. return w.GetRegistry(prodKey)
  571. }
  572. func (w *SWinRegTool) GetVersion() string {
  573. prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
  574. return w.GetRegistry(prodKey)
  575. }
  576. func (w *SWinRegTool) GetInstallLanguage() string {
  577. nlsTbl := map[string]string{"0804": "zh_CN", "0404": "zh_TW", "0c04": "zh_HK",
  578. "1004": "zh_SG", "0409": "en_US", "0809": "en_UK"}
  579. key := w.GetCcsKeyPath()
  580. key += `\Control\Nls\Language\InstallLanguage`
  581. val := w.GetRegistry(key)
  582. if xval, ok := nlsTbl[key]; ok {
  583. return xval
  584. } else {
  585. return val
  586. }
  587. }
  588. func (w *SWinRegTool) LogontypePath() string {
  589. return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LogonType`
  590. }
  591. func (w *SWinRegTool) GetLogontype() string {
  592. return w.GetRegistry(w.LogontypePath())
  593. }
  594. func (w *SWinRegTool) SetLogontype(val string) {
  595. w.SetRegistry(w.LogontypePath(), val, "")
  596. }
  597. func (w *SWinRegTool) DefaultAccountPath() string {
  598. return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName`
  599. }
  600. func (w *SWinRegTool) GetDefaultAccount() string {
  601. return w.GetRegistry(w.DefaultAccountPath())
  602. }
  603. func (w *SWinRegTool) SetDefaultAccount(user string) {
  604. w.SetRegistry(w.DefaultAccountPath(), user, "")
  605. }
  606. func (w *SWinRegTool) GpeditScriptPath() string {
  607. return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts`
  608. }
  609. func (w *SWinRegTool) GpeditScriptStatePath() string {
  610. return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts`
  611. }
  612. func (w *SWinRegTool) GetGpeditStartScripts() []string {
  613. scriptKey := w.GpeditScriptPath() + `\Startup\0`
  614. keys, _ := w.ListRegistry(scriptKey)
  615. ret := []string{}
  616. for _, k := range keys {
  617. spath := scriptKey + (fmt.Sprintf(`\%s\Script`, k))
  618. val := w.GetRegistry(spath)
  619. ret = append(ret, val)
  620. }
  621. return ret
  622. }
  623. func (w *SWinRegTool) IsGpeditStartScriptInstalled(script string) bool {
  624. scripts := w.GetGpeditStartScripts()
  625. return utils.IsInStringArray(script, scripts)
  626. }
  627. func (w *SWinRegTool) InstallGpeditStartScript(script string) {
  628. if w.IsGpeditStartScriptInstalled(script) {
  629. return
  630. }
  631. w.installGpeditStartScript(script, w.GpeditScriptPath())
  632. w.installGpeditStartScript(script, w.GpeditScriptStatePath())
  633. }
  634. func (w *SWinRegTool) GetGpoDisplayname() string {
  635. spath := `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\GPO-List\0\DisplayName`
  636. return w.GetRegistry(spath)
  637. }
  638. func (w *SWinRegTool) installGpeditStartScript(script, scriptPath string) {
  639. idx := 0
  640. if !w.KeyExists(scriptPath + `\Startup`) {
  641. w.MkdirP(scriptPath + `\Startup`)
  642. w.MkdirP(scriptPath + `\Shutdown`)
  643. dsname := "Local Group Policy"
  644. kvts := [][3]string{
  645. {"GPO-ID", "LocalGPO", "REG_SZ"},
  646. {"SOM-ID", "Local", "REG_SZ"},
  647. {"FileSysPath", `C:\Windows\System32\GroupPolicy\Machine`, "REG_SZ"},
  648. {"DisplayName", dsname, "REG_SZ"},
  649. {"GPOName", dsname, "REG_SZ"},
  650. {"PSScriptOrder", "1", "REG_DWORD"},
  651. }
  652. for _, kvt := range kvts {
  653. w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%s`, scriptPath, kvt[0]), kvt[1], kvt[2])
  654. }
  655. } else {
  656. for w.KeyExists(scriptPath + (fmt.Sprintf(`\Startup\0\%d`, idx))) {
  657. idx += 1
  658. }
  659. }
  660. // `%WINDIR%\cloudboot.bat`
  661. kvts := [][3]string{
  662. {"Script", script, "REG_SZ"},
  663. {"Parameters", `%WINDIR%\cloudboot.bat`, "REG_SZ"},
  664. {"ExecTime", "", "REG_QWORD"},
  665. {"IsPowershell", "0", "REG_DWORD"},
  666. }
  667. for _, kvt := range kvts {
  668. w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%d\%s`, scriptPath, idx, kvt[0]), kvt[1], kvt[2])
  669. }
  670. }
  671. func (w *SWinRegTool) EnableRdp() {
  672. key := w.GetCcsKeyPath() + `\Control\Terminal Server\fDenyTSConnections`
  673. w.SetRegistry(key, "0", `REG_DWORD`)
  674. key = w.GetCcsKeyPath() + `\Services\MpsSvc\Start`
  675. w.SetRegistry(key, "3", `REG_DWORD`)
  676. // turn off Windows Firewall completely
  677. for _, prof := range []string{
  678. "StandardProfile", "PublicProfile", "DomainProfile",
  679. } {
  680. key = w.GetCcsKeyPath() + `\Services\SharedAccess\Parameters\FirewallPolicy\` + prof + `\EnableFirewall`
  681. w.SetRegistry(key, "0", `REG_DWORD`)
  682. }
  683. }
  684. func (w *SWinRegTool) ResetUSBProfile() {
  685. // https://www.kraxel.org/blog/2014/03/qemu-and-usb-tablet-cpu-consumtion/
  686. // reset USB registry
  687. key := w.GetCcsKeyPath() + `\Control\usbflags`
  688. w.DelRegistry(key)
  689. key = w.GetCcsKeyPath() + `\Enum\USB`
  690. w.DelRegistry(key)
  691. }