github.com/mitchellh/packer@v1.3.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 workstationDhcpConfPath(device string) string {
    63  	// device isn't used on a windows host
    64  	return findFile("vmnetdhcp.conf", workstationDataFilePaths())
    65  }
    66  
    67  func workstationVmnetnatConfPath(device string) string {
    68  	// device isn't used on a windows host
    69  	return findFile("vmnetnat.conf", workstationDataFilePaths())
    70  }
    71  
    72  func workstationNetmapConfPath() string {
    73  	return findFile("netmap.conf", workstationDataFilePaths())
    74  }
    75  
    76  // See http://blog.natefinch.com/2012/11/go-win-stuff.html
    77  //
    78  // This is used by workstationVMwareRoot in order to read some registry data.
    79  func readRegString(hive syscall.Handle, subKeyPath, valueName string) (value string, err error) {
    80  	var h syscall.Handle
    81  	err = syscall.RegOpenKeyEx(hive, syscall.StringToUTF16Ptr(subKeyPath), 0, syscall.KEY_READ, &h)
    82  	if err != nil {
    83  		return
    84  	}
    85  	defer syscall.RegCloseKey(h)
    86  
    87  	var typ uint32
    88  	var bufSize uint32
    89  	err = syscall.RegQueryValueEx(
    90  		h,
    91  		syscall.StringToUTF16Ptr(valueName),
    92  		nil,
    93  		&typ,
    94  		nil,
    95  		&bufSize)
    96  	if err != nil {
    97  		return
    98  	}
    99  
   100  	data := make([]uint16, bufSize/2+1)
   101  	err = syscall.RegQueryValueEx(
   102  		h,
   103  		syscall.StringToUTF16Ptr(valueName),
   104  		nil,
   105  		&typ,
   106  		(*byte)(unsafe.Pointer(&data[0])),
   107  		&bufSize)
   108  	if err != nil {
   109  		return
   110  	}
   111  
   112  	return syscall.UTF16ToString(data), nil
   113  }
   114  
   115  // This reads the VMware installation path from the Windows registry.
   116  func workstationVMwareRoot() (s string, err error) {
   117  	key := `SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\vmware.exe`
   118  	subkey := "Path"
   119  	s, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
   120  	if err != nil {
   121  		log.Printf(`Unable to read registry key %s\%s`, key, subkey)
   122  		return
   123  	}
   124  
   125  	return normalizePath(s), nil
   126  }
   127  
   128  // This reads the VMware DHCP leases path from the Windows registry.
   129  func workstationDhcpLeasesPathRegistry() (s string, err error) {
   130  	key := "SYSTEM\\CurrentControlSet\\services\\VMnetDHCP\\Parameters"
   131  	subkey := "LeaseFile"
   132  	s, err = readRegString(syscall.HKEY_LOCAL_MACHINE, key, subkey)
   133  	if err != nil {
   134  		log.Printf(`Unable to read registry key %s\%s`, key, subkey)
   135  		return
   136  	}
   137  
   138  	return normalizePath(s), nil
   139  }
   140  
   141  func normalizePath(path string) string {
   142  	path = strings.Replace(path, "\\", "/", -1)
   143  	path = strings.Replace(path, "//", "/", -1)
   144  	path = strings.TrimRight(path, "/")
   145  	return path
   146  }
   147  
   148  func findFile(file string, paths []string) string {
   149  	for _, path := range paths {
   150  		path = filepath.Join(path, file)
   151  		path = normalizePath(path)
   152  		log.Printf("Searching for file '%s'", path)
   153  
   154  		if _, err := os.Stat(path); err == nil {
   155  			log.Printf("Found file '%s'", path)
   156  			return path
   157  		}
   158  	}
   159  
   160  	log.Printf("File not found: '%s'", file)
   161  	return ""
   162  }
   163  
   164  // workstationProgramFilesPaths returns a list of paths that are eligible
   165  // to contain program files we may want just as vmware.exe.
   166  func workstationProgramFilePaths() []string {
   167  	path, err := workstationVMwareRoot()
   168  	if err != nil {
   169  		log.Printf("Error finding VMware root: %s", err)
   170  	}
   171  
   172  	paths := make([]string, 0, 5)
   173  	if os.Getenv("VMWARE_HOME") != "" {
   174  		paths = append(paths, os.Getenv("VMWARE_HOME"))
   175  	}
   176  
   177  	if path != "" {
   178  		paths = append(paths, path)
   179  	}
   180  
   181  	if os.Getenv("ProgramFiles(x86)") != "" {
   182  		paths = append(paths,
   183  			filepath.Join(os.Getenv("ProgramFiles(x86)"), "/VMware/VMware Workstation"))
   184  	}
   185  
   186  	if os.Getenv("ProgramFiles") != "" {
   187  		paths = append(paths,
   188  			filepath.Join(os.Getenv("ProgramFiles"), "/VMware/VMware Workstation"))
   189  	}
   190  
   191  	return paths
   192  }
   193  
   194  // workstationDataFilePaths returns a list of paths that are eligible
   195  // to contain data files we may want such as vmnet NAT configuration files.
   196  func workstationDataFilePaths() []string {
   197  	leasesPath, err := workstationDhcpLeasesPathRegistry()
   198  	if err != nil {
   199  		log.Printf("Error getting DHCP leases path: %s", err)
   200  	}
   201  
   202  	if leasesPath != "" {
   203  		leasesPath = filepath.Dir(leasesPath)
   204  	}
   205  
   206  	paths := make([]string, 0, 5)
   207  	if os.Getenv("VMWARE_DATA") != "" {
   208  		paths = append(paths, os.Getenv("VMWARE_DATA"))
   209  	}
   210  
   211  	if leasesPath != "" {
   212  		paths = append(paths, leasesPath)
   213  	}
   214  
   215  	if os.Getenv("ProgramData") != "" {
   216  		paths = append(paths,
   217  			filepath.Join(os.Getenv("ProgramData"), "/VMware"))
   218  	}
   219  
   220  	if os.Getenv("ALLUSERSPROFILE") != "" {
   221  		paths = append(paths,
   222  			filepath.Join(os.Getenv("ALLUSERSPROFILE"), "/Application Data/VMware"))
   223  	}
   224  
   225  	return paths
   226  }