github.com/sneal/packer@v0.5.2/builder/vmware/common/driver_workstation9_windows.go (about)

     1  // +build windows
     2  
     3  package common
     4  
     5  import (
     6  	"log"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  	"syscall"
    12  	"unsafe"
    13  )
    14  
    15  func workstationCheckLicense() error {
    16  	// Not implemented on Windows
    17  	return nil
    18  }
    19  
    20  func workstationFindVdiskManager() (string, error) {
    21  	path, err := exec.LookPath("vmware-vdiskmanager.exe")
    22  	if err == nil {
    23  		return path, nil
    24  	}
    25  
    26  	return findFile("vmware-vdiskmanager.exe", workstationProgramFilePaths()), nil
    27  }
    28  
    29  func workstationFindVMware() (string, error) {
    30  	path, err := exec.LookPath("vmware.exe")
    31  	if err == nil {
    32  		return path, nil
    33  	}
    34  
    35  	return findFile("vmware.exe", workstationProgramFilePaths()), nil
    36  }
    37  
    38  func workstationFindVmrun() (string, error) {
    39  	path, err := exec.LookPath("vmrun.exe")
    40  	if err == nil {
    41  		return path, nil
    42  	}
    43  
    44  	return findFile("vmrun.exe", workstationProgramFilePaths()), nil
    45  }
    46  
    47  func workstationToolsIsoPath(flavor string) string {
    48  	return findFile(flavor+".iso", workstationProgramFilePaths())
    49  }
    50  
    51  func workstationDhcpLeasesPath(device string) string {
    52  	path, err := workstationDhcpLeasesPathRegistry()
    53  	if err != nil {
    54  		log.Printf("Error finding leases in registry: %s", err)
    55  	} else if _, err := os.Stat(path); err == nil {
    56  		return path
    57  	}
    58  
    59  	return findFile("vmnetdhcp.leases", workstationDataFilePaths())
    60  }
    61  
    62  func workstationVmnetnatConfPath() string {
    63  	return findFile("vmnetnat.conf", workstationDataFilePaths())
    64  }
    65  
    66  // See http://blog.natefinch.com/2012/11/go-win-stuff.html
    67  //
    68  // This is used by workstationVMwareRoot in order to read some registry data.
    69  func readRegString(hive syscall.Handle, subKeyPath, valueName string) (value string, err error) {
    70  	var h syscall.Handle
    71  	err = syscall.RegOpenKeyEx(hive, syscall.StringToUTF16Ptr(subKeyPath), 0, syscall.KEY_READ, &h)
    72  	if err != nil {
    73  		return
    74  	}
    75  	defer syscall.RegCloseKey(h)
    76  
    77  	var typ uint32
    78  	var bufSize uint32
    79  	err = syscall.RegQueryValueEx(
    80  		h,
    81  		syscall.StringToUTF16Ptr(valueName),
    82  		nil,
    83  		&typ,
    84  		nil,
    85  		&bufSize)
    86  	if err != nil {
    87  		return
    88  	}
    89  
    90  	data := make([]uint16, bufSize/2+1)
    91  	err = syscall.RegQueryValueEx(
    92  		h,
    93  		syscall.StringToUTF16Ptr(valueName),
    94  		nil,
    95  		&typ,
    96  		(*byte)(unsafe.Pointer(&data[0])),
    97  		&bufSize)
    98  	if err != nil {
    99  		return
   100  	}
   101  
   102  	return syscall.UTF16ToString(data), nil
   103  }
   104  
   105  // This reads the VMware installation path from the Windows registry.
   106  func workstationVMwareRoot() (s string, err error) {
   107  	key := `SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\vmware.exe`
   108  	subkey := "Path"
   109  	s, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
   110  	if err != nil {
   111  		log.Printf(`Unable to read registry key %s\%s`, key, subkey)
   112  		return
   113  	}
   114  
   115  	return normalizePath(s), nil
   116  }
   117  
   118  // This reads the VMware DHCP leases path from the Windows registry.
   119  func workstationDhcpLeasesPathRegistry() (s string, err error) {
   120  	key := "SYSTEM\\CurrentControlSet\\services\\VMnetDHCP\\Parameters"
   121  	subkey := "LeaseFile"
   122  	s, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
   123  	if err != nil {
   124  		log.Printf(`Unable to read registry key %s\%s`, key, subkey)
   125  		return
   126  	}
   127  
   128  	return normalizePath(s), nil
   129  }
   130  
   131  func normalizePath(path string) string {
   132  	path = strings.Replace(path, "\\", "/", -1)
   133  	path = strings.Replace(path, "//", "/", -1)
   134  	path = strings.TrimRight(path, "/")
   135  	return path
   136  }
   137  
   138  func findFile(file string, paths []string) string {
   139  	for _, path := range paths {
   140  		path = filepath.Join(path, file)
   141  		path = normalizePath(path)
   142  		log.Printf("Searching for file '%s'", path)
   143  
   144  		if _, err := os.Stat(path); err == nil {
   145  			log.Printf("Found file '%s'", path)
   146  			return path
   147  		}
   148  	}
   149  
   150  	log.Printf("File not found: '%s'", file)
   151  	return ""
   152  }
   153  
   154  // workstationProgramFilesPaths returns a list of paths that are eligible
   155  // to contain program files we may want just as vmware.exe.
   156  func workstationProgramFilePaths() []string {
   157  	path, err := workstationVMwareRoot()
   158  	if err != nil {
   159  		log.Printf("Error finding VMware root: %s", err)
   160  	}
   161  
   162  	paths := make([]string, 0, 5)
   163  	if os.Getenv("VMWARE_HOME") != "" {
   164  		paths = append(paths, os.Getenv("VMWARE_HOME"))
   165  	}
   166  
   167  	if path != "" {
   168  		paths = append(paths, path)
   169  	}
   170  
   171  	if os.Getenv("ProgramFiles(x86)") != "" {
   172  		paths = append(paths,
   173  			filepath.Join(os.Getenv("ProgramFiles(x86)"), "/VMware/VMware Workstation"))
   174  	}
   175  
   176  	if os.Getenv("ProgramFiles") != "" {
   177  		paths = append(paths,
   178  			filepath.Join(os.Getenv("ProgramFiles"), "/VMware/VMware Workstation"))
   179  	}
   180  
   181  	return paths
   182  }
   183  
   184  // workstationDataFilePaths returns a list of paths that are eligible
   185  // to contain data files we may want such as vmnet NAT configuration files.
   186  func workstationDataFilePaths() []string {
   187  	leasesPath, err := workstationDhcpLeasesPathRegistry()
   188  	if err != nil {
   189  		log.Printf("Error getting DHCP leases path: %s", err)
   190  	}
   191  
   192  	if leasesPath != "" {
   193  		leasesPath = filepath.Dir(leasesPath)
   194  	}
   195  
   196  	paths := make([]string, 0, 5)
   197  	if os.Getenv("VMWARE_DATA") != "" {
   198  		paths = append(paths, os.Getenv("VMWARE_DATA"))
   199  	}
   200  
   201  	if leasesPath != "" {
   202  		paths = append(paths, leasesPath)
   203  	}
   204  
   205  	if os.Getenv("ProgramData") != "" {
   206  		paths = append(paths,
   207  			filepath.Join(os.Getenv("ProgramData"), "/VMware"))
   208  	}
   209  
   210  	if os.Getenv("ALLUSERSPROFILE") != "" {
   211  		paths = append(paths,
   212  			filepath.Join(os.Getenv("ALLUSERSPROFILE"), "/Application Data/VMware"))
   213  	}
   214  
   215  	return paths
   216  }