@@ -7,10 +7,13 @@ import (
7
7
"fmt"
8
8
"io"
9
9
"net"
10
+ "os"
11
+ "os/exec"
10
12
"strings"
11
13
12
14
"github.com/Microsoft/go-winio"
13
15
"github.com/containers/podman/v5/pkg/machine/sockets"
16
+ "github.com/containers/podman/v5/pkg/machine/wsl/wutil"
14
17
"github.com/containers/podman/v5/utils"
15
18
"github.com/sirupsen/logrus"
16
19
"golang.org/x/sys/windows/registry"
@@ -83,7 +86,7 @@ type HVSockRegistryEntry struct {
83
86
}
84
87
85
88
// Add creates a new Windows registry entry with string values from the
86
- // HVSockRegistryEntry.
89
+ // HVSockRegistryEntry. Must have elevated rights.
87
90
func (hv * HVSockRegistryEntry ) Add () error {
88
91
if err := hv .validate (); err != nil {
89
92
return err
@@ -186,9 +189,9 @@ func findOpenHVSockPort() (uint64, error) {
186
189
return 0 , errors .New ("unable to find a free port for hvsock use" )
187
190
}
188
191
189
- // NewHVSockRegistryEntry is a constructor to make a new registry entry in Windows. After making the new
190
- // object, you must call the add() method to *actually* add it to the Windows registry.
191
- func NewHVSockRegistryEntry (machineName string , purpose HVSockPurpose ) (* HVSockRegistryEntry , error ) {
192
+ // CreateHVSockRegistryEntry is a constructor to make an instance of a registry entry in Windows. After making the new
193
+ // object, you must call the add() method or AddHVSockRegistryEntries(...) to *actually* add it to the Windows registry.
194
+ func CreateHVSockRegistryEntry (machineName string , purpose HVSockPurpose ) (* HVSockRegistryEntry , error ) {
192
195
// a so-called wildcard entry ... everything from FACB -> 6D3 is MS special sauce
193
196
// for a " linux vm". this first segment is hexi for the hvsock port number
194
197
// 00000400-FACB-11E6-BD58-64006A7986D3
@@ -202,10 +205,96 @@ func NewHVSockRegistryEntry(machineName string, purpose HVSockPurpose) (*HVSockR
202
205
Port : port ,
203
206
MachineName : machineName ,
204
207
}
208
+
209
+ return & r , nil
210
+ }
211
+
212
+ // NewHVSockRegistryEntry is a constructor to make a new registry entry in Windows. After making the new
213
+ // object, it calls the add() method to *actually* add it to the Windows registry.
214
+ func NewHVSockRegistryEntry (machineName string , purpose HVSockPurpose ) (* HVSockRegistryEntry , error ) {
215
+ r , err := CreateHVSockRegistryEntry (machineName , purpose )
216
+ if err != nil {
217
+ return nil , err
218
+ }
219
+
205
220
if err := r .Add (); err != nil {
206
221
return nil , err
207
222
}
208
- return & r , nil
223
+
224
+ return r , nil
225
+ }
226
+
227
+ // AddHVSockRegistryEntries allows to *actually* add multiple registry entries to the Windows registry
228
+ // As adding an entry to the HKLM path in the Registry requires elevated privileges, this func can be used for bulk insertion so to
229
+ // ask the user for elevated rights only once
230
+ func AddHVSockRegistryEntries (entries []HVSockRegistryEntry ) error {
231
+ // create a script which will be executed with elevated rights
232
+ script := ""
233
+ for _ , entry := range entries {
234
+ if err := entry .validate (); err != nil {
235
+ return err
236
+ }
237
+ exists , err := entry .exists ()
238
+ if err != nil {
239
+ return err
240
+ }
241
+ if exists {
242
+ return fmt .Errorf ("%q: %s" , ErrVSockRegistryEntryExists , entry .KeyName )
243
+ }
244
+ parentKey , err := registry .OpenKey (registry .LOCAL_MACHINE , VsockRegistryPath , registry .QUERY_VALUE )
245
+ defer func () {
246
+ if err := parentKey .Close (); err != nil {
247
+ logrus .Error (err )
248
+ }
249
+ }()
250
+ if err != nil {
251
+ return err
252
+ }
253
+
254
+ // for each entry it adds a purpose and machineName property
255
+ registryPath := fmt .Sprintf ("HKLM:\\ %s" , VsockRegistryPath )
256
+ keyPath := fmt .Sprintf ("%s\\ %s" , registryPath , entry .KeyName )
257
+
258
+ createRegistryKeyCmd := fmt .Sprintf ("New-Item -Path '%s' -Name '%s'" , registryPath , entry .KeyName )
259
+ addPurposePropertyCmd := fmt .Sprintf ("New-ItemProperty -Path '%s' -Name '%s' -Value '%s' -PropertyType String" , keyPath , HvsockPurpose , entry .Purpose .string ())
260
+ addMachinePropertyCmd := fmt .Sprintf ("New-ItemProperty -Path '%s' -Name '%s' -Value '%s' -PropertyType String" , keyPath , HvsockMachineName , entry .MachineName )
261
+
262
+ script += fmt .Sprintf ("%s; %s; %s;" , createRegistryKeyCmd , addPurposePropertyCmd , addMachinePropertyCmd )
263
+ }
264
+
265
+ // launch the script in elevated mode
266
+ return launchElevated (script )
267
+ }
268
+
269
+ // RemoveHVSockRegistryEntries allows to *actually* remove multiple registry entries from the Windows registry
270
+ // As removing an entry from the HKLM path in the Registry requires elevated privileges, this func can be used for bulk deletion so to
271
+ // ask the user for elevated rights only once
272
+ func RemoveHVSockRegistryEntries (entries []HVSockRegistryEntry ) error {
273
+ // create a script which will be executed with elevated rights
274
+ script := ""
275
+ for _ , entry := range entries {
276
+ // for each entry it calculate the path and the script to remove it
277
+ registryPath := fmt .Sprintf ("HKLM:\\ %s" , VsockRegistryPath )
278
+ keyPath := fmt .Sprintf ("%s\\ %s" , registryPath , entry .KeyName )
279
+
280
+ removeRegistryKeyCmd := fmt .Sprintf ("Remove-Item -Path '%s' -Force -Recurse" , keyPath )
281
+
282
+ script += fmt .Sprintf ("%s;" , removeRegistryKeyCmd )
283
+ }
284
+
285
+ // launch the script in elevated mode
286
+ return launchElevated (script )
287
+ }
288
+
289
+ func launchElevated (args string ) error {
290
+ psPath , err := exec .LookPath ("powershell.exe" )
291
+ if err != nil {
292
+ return err
293
+ }
294
+
295
+ d , _ := os .Getwd ()
296
+
297
+ return wutil .LaunchElevatedWait (psPath , d , args )
209
298
}
210
299
211
300
func portToKeyName (port uint64 ) string {
0 commit comments