VirtualBox

source: vbox/trunk/tools/win/vbscript/helpers.vbs@ 93115

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Id
File size: 54.6 KB
Line 
1' $Id: helpers.vbs 93115 2022-01-01 11:31:46Z vboxsync $
2'' @file
3' Common VBScript helpers used by configure.vbs and later others.
4'
5' Requires the script including it to define a LogPrint function.
6'
7
8'
9' Copyright (C) 2006-2022 Oracle Corporation
10'
11' This file is part of VirtualBox Open Source Edition (OSE), as
12' available from http://www.virtualbox.org. This file is free software;
13' you can redistribute it and/or modify it under the terms of the GNU
14' General Public License (GPL) as published by the Free Software
15' Foundation, in version 2 as it comes in the "COPYING" file of the
16' VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17' hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18'
19
20
21''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
22' Global Variables '
23''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
24dim g_objShell
25Set g_objShell = WScript.CreateObject("WScript.Shell")
26
27dim g_objFileSys
28Set g_objFileSys = WScript.CreateObject("Scripting.FileSystemObject")
29
30'' Whether to ignore (continue) on errors.
31dim g_blnContinueOnError
32g_blnContinueOnError = False
33
34'' The script's exit code (for ignored errors).
35dim g_rcScript
36g_rcScript = 0
37
38
39''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
40' Helpers: Paths '
41''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
42
43''
44' Converts to unix slashes
45function UnixSlashes(str)
46 UnixSlashes = replace(str, "\", "/")
47end function
48
49
50''
51' Converts to dos slashes
52function DosSlashes(str)
53 DosSlashes = replace(str, "/", "\")
54end function
55
56
57''
58' Get the path of the parent directory. Returns root if root was specified.
59' Expects abs path.
60function PathParent(str)
61 PathParent = g_objFileSys.GetParentFolderName(DosSlashes(str))
62end function
63
64
65''
66' Strips the filename from at path.
67function PathStripFilename(str)
68 PathStripFilename = g_objFileSys.GetParentFolderName(DosSlashes(str))
69end function
70
71
72''
73' Get the abs path, use the short version if necessary.
74function PathAbs(str)
75 strAbs = g_objFileSys.GetAbsolutePathName(DosSlashes(str))
76 strParent = g_objFileSys.GetParentFolderName(strAbs)
77 if strParent = "" then
78 PathAbs = strAbs
79 else
80 strParent = PathAbs(strParent) ' Recurse to resolve parent paths.
81 PathAbs = g_objFileSys.BuildPath(strParent, g_objFileSys.GetFileName(strAbs))
82
83 dim obj
84 set obj = Nothing
85 if FileExists(PathAbs) then
86 set obj = g_objFileSys.GetFile(PathAbs)
87 elseif DirExists(PathAbs) then
88 set obj = g_objFileSys.GetFolder(PathAbs)
89 end if
90
91 if not (obj is nothing) then
92 for each objSub in obj.ParentFolder.SubFolders
93 if obj.Name = objSub.Name or obj.ShortName = objSub.ShortName then
94 if InStr(1, objSub.Name, " ") > 0 _
95 Or InStr(1, objSub.Name, "&") > 0 _
96 Or InStr(1, objSub.Name, "$") > 0 _
97 then
98 PathAbs = g_objFileSys.BuildPath(strParent, objSub.ShortName)
99 if InStr(1, PathAbs, " ") > 0 _
100 Or InStr(1, PathAbs, "&") > 0 _
101 Or InStr(1, PathAbs, "$") > 0 _
102 then
103 MsgFatal "PathAbs(" & str & ") attempted to return filename with problematic " _
104 & "characters in it (" & PathAbs & "). The tool/sdk referenced will probably " _
105 & "need to be copied or reinstalled to a location without 'spaces', '$', ';' " _
106 & "or '&' in the path name. (Unless it's a problem with this script of course...)"
107 end if
108 else
109 PathAbs = g_objFileSys.BuildPath(strParent, objSub.Name)
110 end if
111 exit for
112 end if
113 next
114 end if
115 end if
116end function
117
118
119''
120' Get the abs path, use the long version.
121function PathAbsLong(str)
122 strAbs = g_objFileSys.GetAbsolutePathName(DosSlashes(str))
123 strParent = g_objFileSys.GetParentFolderName(strAbs)
124 if strParent = "" then
125 PathAbsLong = strAbs
126 else
127 strParent = PathAbsLong(strParent) ' Recurse to resolve parent paths.
128 PathAbsLong = g_objFileSys.BuildPath(strParent, g_objFileSys.GetFileName(strAbs))
129
130 dim obj
131 set obj = Nothing
132 if FileExists(PathAbsLong) then
133 set obj = g_objFileSys.GetFile(PathAbsLong)
134 elseif DirExists(PathAbsLong) then
135 set obj = g_objFileSys.GetFolder(PathAbsLong)
136 end if
137
138 if not (obj is nothing) then
139 for each objSub in obj.ParentFolder.SubFolders
140 if obj.Name = objSub.Name or obj.ShortName = objSub.ShortName then
141 PathAbsLong = g_objFileSys.BuildPath(strParent, objSub.Name)
142 exit for
143 end if
144 next
145 end if
146 end if
147end function
148
149
150''
151' Compare two paths w/o abspathing them.
152'
153' Ignores case, slash direction, multiple slashes and single dot components.
154'
155function PathMatch(strPath1, strPath2)
156 PathMatch = true
157 if StrComp(strPath1, strPath2, vbTextCompare) <> 0 then
158 strPath1 = DosSlashes(strPath1)
159 strPath2 = DosSlashes(strPath2)
160 if StrComp(strPath1, strPath2, vbTextCompare) <> 0 then
161 ' Compare character by character
162 dim off1 : off1 = 1
163 dim off2 : off2 = 1
164
165 ' Compare UNC prefix if any, because the code below cannot handle it. UNC has exactly two slashes.
166 if Mid(strPath1, 1, 2) = "\\" and Mid(strPath2, 1, 2) = "\\" then
167 if (Mid(strPath1, 3, 1) = "\") <> (Mid(strPath2, 3, 1) = "\") then
168 PathMatch = false
169 exit function
170 end if
171 off1 = off1 + 2
172 off2 = off2 + 2
173 if Mid(strPath1, 3, 1) = "\" then
174 off1 = PathMatchSkipSlashesAndSlashDotHelper(strPath1, off1)
175 off2 = PathMatchSkipSlashesAndSlashDotHelper(strPath2, off2)
176 end if
177 end if
178
179 ' Compare the rest.
180 dim ch1, ch2
181 do while off1 <= Len(strPath1) and off2 <= Len(strPath2)
182 ch1 = Mid(strPath1, off1, 1)
183 ch2 = Mid(strPath2, off2, 1)
184 if StrComp(ch1, ch2, vbTextCompare) = 0 then
185 off1 = off1 + 1
186 off2 = off2 + 1
187 if ch1 = "\" then
188 off1 = PathMatchSkipSlashesAndSlashDotHelper(strPath1, off1)
189 off2 = PathMatchSkipSlashesAndSlashDotHelper(strPath2, off2)
190 end if
191 else
192 PathMatch = False
193 exit function
194 end if
195 loop
196
197 ' One or both of the strings ran out. That's fine if we've only got slashes
198 ' and "." components left in the other.
199 if off1 <= Len(strPath1) and Mid(strPath1, off1, 1) = "\" then
200 off1 = PathMatchSkipSlashesAndSlashDotHelper(strPath1, off1 + 1)
201 end if
202 if off2 <= Len(strPath2) and Mid(strPath2, off2, 1) = "\" then
203 off2 = PathMatchSkipSlashesAndSlashDotHelper(strPath2, off2 + 1)
204 end if
205 PathMatch = off1 > Len(strPath1) and off2 > Len(strPath2)
206 end if
207 end if
208end function
209
210'' PathMatch helper
211function PathMatchSkipSlashesAndSlashDotHelper(strPath, off)
212 dim ch
213 do while off <= Len(strPath)
214 ch = Mid(strPath, off, 1)
215 if ch = "\" then
216 off = off + 1
217 elseif ch = "." and off = Len(strPath) then
218 off = off + 1
219 elseif ch = "." and Mid(strPath, off, 2) = ".\" then
220 off = off + 2
221 else
222 exit do
223 end if
224 loop
225 PathMatchSkipSlashesAndSlashDotHelper = off
226end function
227
228
229''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
230' Helpers: Files and Dirs '
231''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
232
233''
234' Read a file (typically the tmp file) into a string.
235function FileToString(strFilename)
236 const ForReading = 1, TristateFalse = 0
237 dim objLogFile, str
238
239 set objFile = g_objFileSys.OpenTextFile(DosSlashes(strFilename), ForReading, False, TristateFalse)
240 str = objFile.ReadAll()
241 objFile.Close()
242
243 FileToString = str
244end function
245
246
247''
248' Deletes a file
249sub FileDelete(strFilename)
250 if g_objFileSys.FileExists(DosSlashes(strFilename)) then
251 g_objFileSys.DeleteFile(DosSlashes(strFilename))
252 end if
253end sub
254
255
256''
257' Appends a line to an ascii file.
258sub FileAppendLine(strFilename, str)
259 const ForAppending = 8, TristateFalse = 0
260 dim objFile
261
262 set objFile = g_objFileSys.OpenTextFile(DosSlashes(strFilename), ForAppending, True, TristateFalse)
263 objFile.WriteLine(str)
264 objFile.Close()
265end sub
266
267
268''
269' Checks if the file exists.
270function FileExists(strFilename)
271 FileExists = g_objFileSys.FileExists(DosSlashes(strFilename))
272 DbgPrint "FileExists(" & strFilename & ") -> " & FileExists
273end function
274
275
276''
277' Checks if the directory exists.
278function DirExists(strDirectory)
279 DirExists = g_objFileSys.FolderExists(DosSlashes(strDirectory))
280 DbgPrint "DirExists(" & strDirectory & ") -> " & DirExists
281end function
282
283
284''
285' Returns true if there are subfolders starting with the given string.
286function HasSubdirsStartingWith(strFolder, strStartingWith)
287 HasSubdirsStartingWith = False
288 if DirExists(strFolder) then
289 dim obj
290 set obj = g_objFileSys.GetFolder(strFolder)
291 for each objSub in obj.SubFolders
292 if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
293 HasSubdirsStartingWith = True
294 LogPrint "# HasSubdirsStartingWith(" & strFolder & "," & strStartingWith & ") found " & objSub.Name
295 exit for
296 end if
297 next
298 end if
299end function
300
301
302''
303' Returns a sorted array of subfolder names that starts with the given string.
304function GetSubdirsStartingWith(strFolder, strStartingWith)
305 if DirExists(strFolder) then
306 dim obj, i
307 set obj = g_objFileSys.GetFolder(strFolder)
308 i = 0
309 for each objSub in obj.SubFolders
310 if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
311 i = i + 1
312 end if
313 next
314 if i > 0 then
315 redim arrResult(i - 1)
316 i = 0
317 for each objSub in obj.SubFolders
318 if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
319 arrResult(i) = objSub.Name
320 i = i + 1
321 end if
322 next
323 GetSubdirsStartingWith = arrResult
324 else
325 GetSubdirsStartingWith = Array()
326 end if
327 else
328 GetSubdirsStartingWith = Array()
329 end if
330end function
331
332
333''
334' Returns a sorted array of subfolder names that starts with the given string.
335function GetSubdirsStartingWithVerSorted(strFolder, strStartingWith)
336 GetSubdirsStartingWithVerSorted = ArrayVerSortStrings(GetSubdirsStartingWith(strFolder, strStartingWith))
337end function
338
339
340''
341' Returns a reverse version sorted array of subfolder names that starts with the given string.
342function GetSubdirsStartingWithRVerSorted(strFolder, strStartingWith)
343 GetSubdirsStartingWithRVerSorted = ArrayRVerSortStrings(GetSubdirsStartingWith(strFolder, strStartingWith))
344end function
345
346
347''
348' Try find the specified file in the specified path variable.
349function WhichEx(strEnvVar, strFile)
350 dim strPath, iStart, iEnd, str
351
352 ' the path
353 strPath = EnvGet(strEnvVar)
354 iStart = 1
355 do while iStart <= Len(strPath)
356 iEnd = InStr(iStart, strPath, ";")
357 if iEnd <= 0 then iEnd = Len(strPath) + 1
358 if iEnd > iStart then
359 str = Mid(strPath, iStart, iEnd - iStart) & "/" & strFile
360 if FileExists(str) then
361 WhichEx = str
362 exit function
363 end if
364 end if
365 iStart = iEnd + 1
366 loop
367
368 ' registry or somewhere?
369
370 WhichEx = ""
371end function
372
373
374''
375' Try find the specified file in the path.
376function Which(strFile)
377 Which = WhichEx("Path", strFile)
378end function
379
380
381''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
382' Helpers: Processes '
383''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
384
385''
386' Checks if this is a WOW64 process.
387function IsWow64()
388 if g_objShell.Environment("PROCESS")("PROCESSOR_ARCHITEW6432") <> "" then
389 IsWow64 = 1
390 else
391 IsWow64 = 0
392 end if
393end function
394
395
396''
397' Executes a command in the shell catching output in strOutput
398function Shell(strCommand, blnBoth, ByRef strOutput)
399 dim strShell, strCmdline, objExec, str
400
401 strShell = g_objShell.ExpandEnvironmentStrings("%ComSpec%")
402 if blnBoth = true then
403 strCmdline = strShell & " /c " & strCommand & " 2>&1"
404 else
405 strCmdline = strShell & " /c " & strCommand & " 2>nul"
406 end if
407
408 LogPrint "# Shell: " & strCmdline
409 Set objExec = g_objShell.Exec(strCmdLine)
410 strOutput = objExec.StdOut.ReadAll()
411 objExec.StdErr.ReadAll()
412 do while objExec.Status = 0
413 Wscript.Sleep 20
414 strOutput = strOutput & objExec.StdOut.ReadAll()
415 objExec.StdErr.ReadAll()
416 loop
417
418 LogPrint "# Status: " & objExec.ExitCode
419 LogPrint "# Start of Output"
420 LogPrint strOutput
421 LogPrint "# End of Output"
422
423 Shell = objExec.ExitCode
424end function
425
426
427''
428' Gets the SID of the current user.
429function GetSid()
430 dim objNet, strUser, strDomain, offSlash, objWmiUser
431 GetSid = ""
432
433 ' Figure the user + domain
434 set objNet = CreateObject("WScript.Network")
435 strUser = objNet.UserName
436 strDomain = objNet.UserDomain
437 offSlash = InStr(1, strUser, "\")
438 if offSlash > 0 then
439 strDomain = Left(strUser, offSlash - 1)
440 strUser = Right(strUser, Len(strUser) - offSlash)
441 end if
442
443 ' Lookup the user.
444 on error resume next
445 set objWmiUser = GetObject("winmgmts:{impersonationlevel=impersonate}!/root/cimv2:Win32_UserAccount." _
446 & "Domain='" & strDomain &"',Name='" & strUser & "'")
447 if err.number = 0 then
448 GetSid = objWmiUser.SID
449 end if
450end function
451
452
453''
454' Gets the commandline used to invoke the script.
455function GetCommandline()
456 dim str, i
457
458 '' @todo find an api for querying it instead of reconstructing it like this...
459 GetCommandline = "cscript configure.vbs"
460 for i = 1 to WScript.Arguments.Count
461 str = WScript.Arguments.Item(i - 1)
462 if str = "" then
463 str = """"""
464 elseif (InStr(1, str, " ")) then
465 str = """" & str & """"
466 end if
467 GetCommandline = GetCommandline & " " & str
468 next
469end function
470
471
472''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
473' Helpers: Environment '
474''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
475
476''
477' Gets an environment variable.
478function EnvGet(strName)
479 EnvGet = g_objShell.Environment("PROCESS")(strName)
480end function
481
482
483''
484' Gets an environment variable with default value if not found.
485function EnvGetDef(strName, strDefault)
486 dim strValue
487 strValue = g_objShell.Environment("PROCESS")(strName)
488 if strValue = "" or IsNull(strValue) or IsEmpty(strValue) then
489 EnvGetDef = strDefault
490 else
491 EnvGetDef = strValue
492 end if
493end function
494
495
496''
497' Gets an environment variable with default value if not found or not
498' in the array of valid values. Issue warning about invalid values.
499function EnvGetDefValid(strName, strDefault, arrValidValues)
500 dim strValue
501 strValue = g_objShell.Environment("PROCESS")(strName)
502 if strValue = "" or IsNull(strValue) or IsEmpty(strValue) then
503 EnvGetDefValid = strDefault
504 elseif not ArrayContainsString(arrValidValues, strValue) then
505 MsgWarning "Invalid value " & strName & " value '" & EnvGetDefValid & "', using '" & strDefault & "' instead."
506 EnvGetDefValid = strDefault
507 else
508 EnvGetDefValid = strValue
509 end if
510end function
511
512
513''
514' Sets an environment variable.
515sub EnvSet(strName, strValue)
516 g_objShell.Environment("PROCESS")(strName) = strValue
517 LogPrint "EnvSet: " & strName & "=" & strValue
518end sub
519
520
521''
522' Prepends a string to an Path-like environment variable.
523function EnvPrependItemEx(strName, strItem, strSep, blnKeepEmpty, ByRef fnItemMatcher)
524 dim strValue
525 strValue = EnvRemoveItemEx(strName, strItem, strSep, blnKeepEmpty, fnItemMatcher, "EnvPrependItemEx")
526 if strValue <> "" then
527 strValue = strItem & strSep & strValue
528 else
529 strValue = strItem
530 end if
531 g_objShell.Environment("PROCESS")(strName) = strValue
532 EnvPrependItemEx = strValue
533end function
534
535
536''
537' Appends a string to an Path-like environment variable,
538function EnvAppendItemEx(strName, strItem, strSep, blnKeepEmpty, ByRef fnItemMatcher)
539 dim strValue
540 strValue = EnvRemoveItemEx(strName, strItem, strSep, blnKeepEmpty, fnItemMatcher, "EnvAppendItemEx")
541 if strValue <> "" then
542 strValue = strValue & strSep & strItem
543 else
544 strValue = strItem
545 end if
546 g_objShell.Environment("PROCESS")(strName) = strValue
547 EnvAppendItemEx = strValue
548end function
549
550
551''
552' Generic item remover.
553'
554' fnItemMatcher(strItem1, strItem2)
555'
556function EnvRemoveItemEx(strName, strItem, strSep, blnKeepEmpty, ByRef fnItemMatcher, strCaller)
557 dim strValue, off
558 strValue = g_objShell.Environment("PROCESS")(strName)
559 EnvRemoveItemEx = strValue
560 if strValue <> "" then
561 ' Split it up into an array of items
562 dim arrItems : arrItems = Split(strValue, strSep, -1, vbTextCompare)
563
564 ' Create an array of matching indexes that we should remove.
565 dim cntToRemove : cntToRemove = 0
566 redim arrIdxToRemove(ArraySize(arrItems) - 1)
567 dim i, strCur
568 for i = LBound(arrItems) to UBound(arrItems)
569 strCur = arrItems(i)
570 if fnItemMatcher(strCur, strItem) or (not blnKeepEmpty and strCur = "") then
571 arrIdxToRemove(cntToRemove) = i
572 cntToRemove = cntToRemove + 1
573 end if
574 next
575
576 ' Did we find anthing to remove?
577 if cntToRemove > 0 then
578 ' Update the array and join it up again.
579 for i = cntToRemove - 1 to 0 step -1
580 arrItems = ArrayRemove(arrItems, arrIdxToRemove(i))
581 next
582 dim strNewValue : strNewValue = ArrayJoinString(arrItems, strSep)
583 EnvRemoveItemEx = strNewValue
584
585 ' Update the environment variable.
586 LogPrint strCaller &": " & strName & ": '" & strValue & "' --> '" & strNewValue & "'"
587 g_objShell.Environment("PROCESS")(strName) = strNewValue
588 end if
589 end if
590end function
591
592
593''
594' Generic case-insensitive item matcher.
595' See also PathMatch().
596function EnvItemMatch(strItem1, strItem2)
597 EnvItemMatch = (StrComp(strItem1, strItem2) = 0)
598end function
599
600
601''
602' Prepends an item to an environment variable, after first removing any
603' existing ones (case-insensitive, preserves empty elements).
604function EnvPrependItem(strName, strItem, strSep)
605 EnvPrependItem = EnvPrependItemEx(strName, strItem, strSep, true, GetRef("EnvItemMatch"))
606 LogPrint "EnvPrependItem: " & strName & "=" & EnvPrependPathItem
607end function
608
609
610''
611' Appends an item to an environment variable, after first removing any
612' existing ones (case-insensitive, preserves empty elements).
613function EnvAppendItem(strName, strItem, strSep)
614 EnvAppendItem = EnvAppendItemEx(strName, strItem, strSep, true, GetRef("EnvItemMatch"))
615 LogPrint "EnvAppendItem: " & strName & "=" & EnvPrependPathItem
616end function
617
618
619''
620' Removes a string element from an environment variable, case
621' insensitive but preserving empty elements.
622function EnvRemoveItem(strName, strItem, strSep)
623 EnvRemoveItem = EnvRemoveItemEx(strName, strIten, strSep, true, GetRef("EnvItemMatch"), "EnvRemoveItem")
624end function
625
626
627''
628' Appends a string to an Path-like environment variable,
629function EnvPrependPathItem(strName, strItem, strSep)
630 EnvPrependPathItem = EnvPrependItemEx(strName, strItem, strSep, false, GetRef("PathMatch"))
631 LogPrint "EnvPrependPathItem: " & strName & "=" & EnvPrependPathItem
632end function
633
634
635''
636' Appends a string to an Path-like environment variable,
637function EnvAppendPathItem(strName, strItem, strSep)
638 EnvAppendPathItem = EnvAppendItemEx(strName, strItem, strSep, false, GetRef("PathMatch"))
639 LogPrint "EnvAppendPathItem: " & strName & "=" & EnvAppendPathItem
640end function
641
642
643''
644' Removes a string element from an Path-like environment variable, case
645' insensitive and treating forward and backward slashes the same way.
646function EnvRemovePathItem(strName, strItem, strSep)
647 EnvRemovePathItem = EnvRemoveItemEx(strName, strIten, strSep, false, GetRef("PathMatch"), "EnvRemovePathItem")
648end function
649
650
651''
652' Prepends a string to an environment variable
653sub EnvUnset(strName)
654 g_objShell.Environment("PROCESS").Remove(strName)
655 LogPrint "EnvUnset: " & strName
656end sub
657
658
659''
660' Gets the first non-empty environment variable of the given two.
661function EnvGetFirst(strName1, strName2)
662 EnvGetFirst = g_objShell.Environment("PROCESS")(strName1)
663 if EnvGetFirst = "" then
664 EnvGetFirst = g_objShell.Environment("PROCESS")(strName2)
665 end if
666end function
667
668''
669' Checks if the given enviornment variable exists.
670function EnvExists(strName)
671 EnvExists = g_objShell.Environment("PROCESS")(strName) <> ""
672end function
673
674
675''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
676' Helpers: Strings '
677''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
678
679''
680' Right pads a string with spaces to the given length
681function RightPad(str, cch)
682 if Len(str) < cch then
683 RightPad = str & String(cch - Len(str), " ")
684 else
685 RightPad = str
686 end if
687end function
688
689
690''
691' Checks if the given character is a decimal digit
692function CharIsDigit(ch)
693 CharIsDigit = (InStr(1, "0123456789", ch) > 0)
694end function
695
696''
697' Worker for StrVersionCompare
698' The offset is updated to point to the first non-digit character.
699function CountDigitsIgnoreLeadingZeros(ByRef str, ByRef off)
700 dim cntDigits, blnLeadingZeros, ch, offInt
701 cntDigits = 0
702 if CharIsDigit(Mid(str, off, 1)) then
703 ' Rewind to start of digest sequence.
704 do while off > 1
705 if not CharIsDigit(Mid(str, off - 1, 1)) then exit do
706 off = off - 1
707 loop
708 ' Count digits, ignoring leading zeros.
709 blnLeadingZeros = True
710 for off = off to Len(str)
711 ch = Mid(str, off, 1)
712 if CharIsDigit(ch) then
713 if ch <> "0" or blnLeadingZeros = False then
714 cntDigits = cntDigits + 1
715 blnLeadingZeros = False
716 end if
717 else
718 exit for
719 end if
720 next
721 ' If all zeros, count one of them.
722 if cntDigits = 0 then cntDigits = 1
723 end if
724 CountDigitsIgnoreLeadingZeros = cntDigits
725end function
726
727''
728' Very simple version string compare function.
729' @returns < 0 if str1 is smaller than str2
730' @returns 0 if str1 and str2 are equal
731' @returns > 1 if str2 is larger than str1
732function StrVersionCompare(str1, str2)
733 ' Compare the strings. We can rely on StrComp if equal or one is empty.
734 'LogPrint "StrVersionCompare("&str1&","&str2&"):"
735 StrVersionCompare = StrComp(str2, str1)
736 if StrVersionCompare <> 0 then
737 dim cch1, cch2, off1, off2, ch1, ch2, chPrev1, chPrev2, intDiff, cchDigits
738 cch1 = Len(str1)
739 cch2 = Len(str2)
740 if cch1 > 0 and cch2 > 0 then
741 ' Compare the common portion
742 off1 = 1
743 off2 = 1
744 chPrev1 = "x"
745 chPrev2 = "x"
746 do while off1 <= cch1 and off2 <= cch2
747 ch1 = Mid(str1, off1, 1)
748 ch2 = Mid(str2, off2, 1)
749 if ch1 = ch2 then
750 off1 = off1 + 1
751 off2 = off2 + 1
752 chPrev1 = ch1
753 chPrev2 = ch2
754 else
755 ' Is there a digest sequence in play. This includes the scenario where one of the
756 ' string ran out of digests.
757 dim blnDigest1 : blnDigest1 = CharIsDigit(ch1)
758 dim blnDigest2 : blnDigest2 = CharIsDigit(ch2)
759 if (blnDigest1 = True or blnDigest2 = True) _
760 and (blnDigest1 = True or CharIsDigit(chPrev1) = True) _
761 and (blnDigest2 = True or CharIsDigit(chPrev2) = True) _
762 then
763 'LogPrint "StrVersionCompare: off1="&off1&" off2="&off2&" ch1="&ch1&" chPrev1="&chPrev1&" ch2="&ch2&" chPrev2="&chPrev2
764 if blnDigest1 = False then off1 = off1 - 1
765 if blnDigest2 = False then off2 = off2 - 1
766 ' The one with the fewer digits comes first.
767 ' Note! off1 and off2 are adjusted to next non-digit character in the strings.
768 cchDigits = CountDigitsIgnoreLeadingZeros(str1, off1)
769 intDiff = cchDigits - CountDigitsIgnoreLeadingZeros(str2, off2)
770 'LogPrint "StrVersionCompare: off1="&off1&" off2="&off2&" cchDigits="&cchDigits
771 if intDiff <> 0 then
772 StrVersionCompare = intDiff
773 'LogPrint "StrVersionCompare: --> "&intDiff&" #1"
774 exit function
775 end if
776
777 ' If the same number of digits, the smaller digit wins. However, because of
778 ' potential leading zeros, we must redo the compare. Assume ASCII-like stuff
779 ' and we can use StrComp for this.
780 intDiff = StrComp(Mid(str1, off1 - cchDigits, cchDigits), Mid(str2, off2 - cchDigits, cchDigits))
781 if intDiff <> 0 then
782 StrVersionCompare = intDiff
783 'LogPrint "StrVersionCompare: --> "&intDiff&" #2"
784 exit function
785 end if
786 chPrev1 = "x"
787 chPrev2 = "x"
788 else
789 if blnDigest1 then
790 StrVersionCompare = -1 ' Digits before characters
791 'LogPrint "StrVersionCompare: --> -1 (#3)"
792 elseif blnDigest2 then
793 StrVersionCompare = 1 ' Digits before characters
794 'LogPrint "StrVersionCompare: --> 1 (#4)"
795 else
796 StrVersionCompare = StrComp(ch1, ch2)
797 'LogPrint "StrVersionCompare: --> "&StrVersionCompare&" (#5)"
798 end if
799 exit function
800 end if
801 end if
802 loop
803
804 ' The common part matches up, so the shorter string 'wins'.
805 StrVersionCompare = (cch1 - off1) - (cch2 - off2)
806 end if
807 end if
808 'LogPrint "StrVersionCompare: --> "&StrVersionCompare&" (#6)"
809end function
810
811
812''
813' Returns the first list of the given string.
814function StrGetFirstLine(str)
815 dim off
816 off = InStr(1, str, Chr(10))
817 if off <= 0 then off = InStr(1, str, Chr(13))
818 if off > 0 then
819 StrGetFirstLine = Mid(str, 1, off)
820 else
821 StrGetFirstLine = str
822 end if
823end function
824
825
826''
827' Returns the first word in the given string.
828'
829' Only recognizes space, tab, newline and carriage return as word separators.
830'
831function StrGetFirstWord(str)
832 dim strSep, offWord, offEnd, offEnd2, strSeparators
833 strSeparators = " " & Chr(9) & Chr(10) & Chr(13)
834
835 ' Skip leading separators.
836 for offWord = 1 to Len(str)
837 if InStr(1, strSeparators, Mid(str, offWord, 1)) < 1 then exit for
838 next
839
840 ' Find the end.
841 offEnd = Len(str) + 1
842 for offSep = 1 to Len(strSeparators)
843 offEnd2 = InStr(offWord, str, Mid(strSeparators, offSep, 1))
844 if offEnd2 > 0 and offEnd2 < offEnd then offEnd = offEnd2
845 next
846
847 StrGetFirstWord = Mid(str, offWord, offEnd - offWord)
848end function
849
850
851''
852' Checks if the string starts with the given prefix (case sensitive).
853function StrStartsWith(str, strPrefix)
854 if len(str) >= Len(strPrefix) then
855 StrStartsWith = (StrComp(Left(str, Len(strPrefix)), strPrefix, vbBinaryCompare) = 0)
856 else
857 StrStartsWith = false
858 end if
859end function
860
861
862''
863' Checks if the string starts with the given prefix, case insenstive edition.
864function StrStartsWithI(str, strPrefix)
865 if len(str) >= Len(strPrefix) then
866 StrStartsWithI = (StrComp(Left(str, Len(strPrefix)), strPrefix, vbTextCompare) = 0)
867 else
868 StrStartsWithI = false
869 end if
870end function
871
872
873''
874' Checks if the string ends with the given suffix (case sensitive).
875function StrEndsWith(str, strSuffix)
876 if len(str) >= Len(strSuffix) then
877 StrEndsWith = (StrComp(Right(str, Len(strSuffix)), strSuffix, vbBinaryCompare) = 0)
878 else
879 StrEndsWith = false
880 end if
881end function
882
883
884''
885' Checks if the string ends with the given suffix, case insenstive edition.
886function StrEndsWithI(str, strSuffix)
887 if len(str) >= Len(strSuffix) then
888 StrEndsWithI = (StrComp(Right(str, Len(strSuffix)), strSuffix, vbTextCompare) = 0)
889 else
890 StrEndsWithI = false
891 end if
892end function
893
894
895''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
896' Helpers: Arrays '
897''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
898
899''
900' Returns a reverse array (copy).
901function ArrayReverse(arr)
902 dim cnt, i, j, iHalf, objTmp
903 cnt = UBound(arr) - LBound(arr) + 1
904 if cnt > 0 then
905 j = UBound(arr)
906 iHalf = Fix(LBound(arr) + cnt / 2)
907 for i = LBound(arr) to iHalf - 1
908 objTmp = arr(i)
909 arr(i) = arr(j)
910 arr(j) = objTmp
911 j = j - 1
912 next
913 end if
914 ArrayReverse = arr
915end function
916
917
918''
919' Returns a reverse sorted array (strings).
920function ArraySortStringsEx(arrStrings, ByRef fnCompare)
921 dim str1, str2, i, j
922 for i = LBound(arrStrings) to UBound(arrStrings)
923 str1 = arrStrings(i)
924 for j = i + 1 to UBound(arrStrings)
925 str2 = arrStrings(j)
926 if fnCompare(str2, str1) < 0 then
927 arrStrings(j) = str1
928 str1 = str2
929 end if
930 next
931 arrStrings(i) = str1
932 next
933 ArraySortStringsEx = arrStrings
934end function
935
936'' Wrapper for StrComp as GetRef("StrComp") fails.
937function WrapStrComp(str1, str2)
938 WrapStrComp = StrComp(str1, str2)
939end function
940
941''
942' Returns a reverse sorted array (strings).
943function ArraySortStrings(arrStrings)
944 ArraySortStrings = ArraySortStringsEx(arrStrings, GetRef("WrapStrComp"))
945end function
946
947
948''
949' Returns a reverse sorted array (strings).
950function ArrayVerSortStrings(arrStrings)
951 ArrayVerSortStrings = ArraySortStringsEx(arrStrings, GetRef("StrVersionCompare"))
952end function
953
954
955'' Wrapper for StrComp as GetRef("StrComp") fails.
956function WrapStrCompNeg(str1, str2)
957 WrapStrCompNeg = -StrComp(str1, str2)
958end function
959
960''
961' Returns a reverse sorted array (strings).
962function ArrayRSortStrings(arrStrings)
963 ArrayRSortStrings = ArraySortStringsEx(arrStrings, GetRef("WrapStrCompNeg"))
964end function
965
966
967''
968' Returns a reverse version sorted array (strings).
969function ArrayRVerSortStrings(arrStrings)
970 ArrayRVerSortStrings = ArrayReverse(ArraySortStringsEx(arrStrings, GetRef("StrVersionCompare")))
971end function
972
973
974''
975' Prints a string array.
976sub ArrayPrintStrings(arrStrings, strPrefix)
977 for i = LBound(arrStrings) to UBound(arrStrings)
978 Print strPrefix & "arrStrings(" & i & ") = '" & arrStrings(i) & "'"
979 next
980end sub
981
982
983''
984' Returns an Array() statement string
985function ArrayToString(arrStrings)
986 dim strRet, i
987 strRet = "Array("
988 for i = LBound(arrStrings) to UBound(arrStrings)
989 if i <> LBound(arrStrings) then strRet = strRet & ", "
990 strRet = strRet & """" & arrStrings(i) & """"
991 next
992 ArrayToString = strRet & ")"
993end function
994
995
996''
997' Joins the elements of an array into a string using the given item separator.
998' @remark this is the same as Join() really.
999function ArrayJoinString(arrStrings, strSep)
1000 if ArraySize(arrStrings) = 0 then
1001 ArrayJoinString = ""
1002 else
1003 dim i
1004 ArrayJoinString = "" & arrStrings(LBound(arrStrings))
1005 for i = LBound(arrStrings) + 1 to UBound(arrStrings)
1006 ArrayJoinString = ArrayJoinString & strSep & arrStrings(i)
1007 next
1008 end if
1009end function
1010
1011
1012''
1013' Returns the input array with the string appended.
1014' @note This works by reference
1015function ArrayAppend(ByRef arr, str)
1016 dim i
1017 redim preserve arr(UBound(arr) + 1)
1018 arr(UBound(arr)) = str
1019 ArrayAppend = arr
1020end function
1021
1022
1023''
1024' Returns the input array with the string prepended.
1025' @note This works by reference
1026function ArrayPrepend(ByRef arr, str)
1027 dim i
1028 redim preserve arr(UBound(arr) + 1)
1029 for i = UBound(arr) to (LBound(arr) + 1) step -1
1030 arr(i) = arr(i - 1)
1031 next
1032 arr(LBound(arr)) = str
1033 ArrayPrepend = arr
1034end function
1035
1036
1037''
1038' Returns the input array with the string prepended.
1039' @note This works by reference
1040function ArrayRemove(ByRef arr, idx)
1041 dim i
1042 for i = idx to (UBound(arr) - 1)
1043 arr(i) = arr(i + 1)
1044 next
1045 redim preserve arr(UBound(arr) - 1)
1046 ArrayRemove = arr
1047end function
1048
1049
1050''
1051' Checks if the array contains the given string (case sensitive).
1052function ArrayContainsString(ByRef arr, str)
1053 dim strCur
1054 ArrayContainsString = False
1055 for each strCur in arr
1056 if StrComp(strCur, str) = 0 then
1057 ArrayContainsString = True
1058 exit function
1059 end if
1060 next
1061end function
1062
1063
1064''
1065' Checks if the array contains the given string, using case insensitive compare.
1066function ArrayContainsStringI(ByRef arr, str)
1067 dim strCur
1068 ArrayContainsStringI = False
1069 for each strCur in arr
1070 if StrComp(strCur, str, vbTextCompare) = 0 then
1071 ArrayContainsStringI = True
1072 exit function
1073 end if
1074 next
1075end function
1076
1077
1078''
1079' Returns the index of the first occurance of the given string; -1 if not found.
1080function ArrayFindString(ByRef arr, str)
1081 dim i
1082 for i = LBound(arr) to UBound(arr)
1083 if StrComp(arr(i), str, vbBinaryCompare) = 0 then
1084 ArrayFindString = i
1085 exit function
1086 end if
1087 next
1088 ArrayFindString = LBound(arr) - 1
1089end function
1090
1091
1092''
1093' Returns the index of the first occurance of the given string, -1 if not found,
1094' case insensitive edition.
1095function ArrayFindStringI(ByRef arr, str)
1096 dim i
1097 for i = LBound(arr) to UBound(arr)
1098 if StrComp(arr(i), str, vbTextCompare) = 0 then
1099 ArrayFindStringI = i
1100 exit function
1101 end if
1102 next
1103 ArrayFindStringI = LBound(arr) - 1
1104end function
1105
1106
1107''
1108' Returns the number of entries in an array.
1109function ArraySize(ByRef arr)
1110 if (UBound(arr) >= 0) then
1111 ArraySize = UBound(arr) - LBound(arr) + 1
1112 else
1113 ArraySize = 0
1114 end if
1115end function
1116
1117
1118''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1119' Helpers: Registry '
1120''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1121
1122'' The registry globals
1123dim g_objReg, g_objRegCtx
1124dim g_blnRegistry
1125g_blnRegistry = false
1126
1127
1128''
1129' Init the register provider globals.
1130function RegInit()
1131 RegInit = false
1132 On Error Resume Next
1133 if g_blnRegistry = false then
1134 set g_objRegCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
1135 ' Comment out the following for lines if the cause trouble on your windows version.
1136 if IsWow64() then
1137 g_objRegCtx.Add "__ProviderArchitecture", 64
1138 g_objRegCtx.Add "__RequiredArchitecture", true
1139 LogPrint "RegInit: WoW64"
1140 end if
1141 set objLocator = CreateObject("Wbemscripting.SWbemLocator")
1142 set objServices = objLocator.ConnectServer("", "root\default", "", "", , , , g_objRegCtx)
1143 set g_objReg = objServices.Get("StdRegProv")
1144 g_blnRegistry = true
1145 end if
1146 RegInit = true
1147end function
1148
1149
1150''
1151' Translates a register root name to a value
1152' This will translate HKCU path to HKEY_USERS and fixing
1153function RegTransRoot(strRoot, ByRef sSubKeyName)
1154 const HKEY_LOCAL_MACHINE = &H80000002
1155 const HKEY_CURRENT_USER = &H80000001
1156 const HKEY_USERS = &H80000003
1157
1158 select case strRoot
1159 case "HKLM"
1160 RegTransRoot = HKEY_LOCAL_MACHINE
1161 case "HKUS"
1162 RegTransRoot = HKEY_USERS
1163 case "HKCU"
1164 dim strCurrentSid
1165 strCurrentSid = GetSid()
1166 if strCurrentSid <> "" then
1167 sSubKeyName = strCurrentSid & "\" & sSubKeyName
1168 RegTransRoot = HKEY_USERS
1169 'LogPrint "RegTransRoot: HKCU -> HKEY_USERS + " & sSubKeyName
1170 else
1171 RegTransRoot = HKEY_CURRENT_USER
1172 LogPrint "RegTransRoot: Warning! HKCU -> HKEY_USERS failed!"
1173 end if
1174 case else
1175 MsgFatal "RegTransRoot: Unknown root: '" & strRoot & "'"
1176 RegTransRoot = 0
1177 end select
1178end function
1179
1180
1181''
1182' Gets a value from the registry. Returns "" if string wasn't found / valid.
1183function RegGetString(strName)
1184 RegGetString = ""
1185 if RegInit() then
1186 dim strRoot, strKey, strValue
1187
1188 ' split up into root, key and value parts.
1189 strRoot = left(strName, instr(strName, "\") - 1)
1190 strKey = mid(strName, instr(strName, "\") + 1, instrrev(strName, "\") - instr(strName, "\"))
1191 strValue = mid(strName, instrrev(strName, "\") + 1)
1192
1193 ' Must use ExecMethod to call the GetStringValue method because of the context.
1194 Set InParms = g_objReg.Methods_("GetStringValue").Inparameters
1195 InParms.hDefKey = RegTransRoot(strRoot, strKey)
1196 InParms.sSubKeyName = strKey
1197 InParms.sValueName = strValue
1198 On Error Resume Next
1199 set OutParms = g_objReg.ExecMethod_("GetStringValue", InParms, , g_objRegCtx)
1200 if OutParms.ReturnValue = 0 then
1201 if not IsNull(OutParms.sValue) then
1202 RegGetString = OutParms.sValue
1203 end if
1204 end if
1205 else
1206 ' fallback mode
1207 On Error Resume Next
1208 RegGetString = g_objShell.RegRead(strName)
1209 end if
1210end function
1211
1212
1213''
1214' Gets a multi string value from the registry. Returns array of strings if found, otherwise empty array().
1215function RegGetMultiString(strName)
1216 RegGetMultiString = Array()
1217 if RegInit() then
1218 dim strRoot, strKey, strValue
1219
1220 ' split up into root, key and value parts.
1221 strRoot = left(strName, instr(strName, "\") - 1)
1222 strKey = mid(strName, instr(strName, "\") + 1, instrrev(strName, "\") - instr(strName, "\"))
1223 strValue = mid(strName, instrrev(strName, "\") + 1)
1224
1225 ' Must use ExecMethod to call the GetStringValue method because of the context.
1226 Set InParms = g_objReg.Methods_("GetMultiStringValue").Inparameters
1227 InParms.hDefKey = RegTransRoot(strRoot, strKey)
1228 InParms.sSubKeyName = strKey
1229 InParms.sValueName = strValue
1230 On Error Resume Next
1231 set OutParms = g_objReg.ExecMethod_("GetMultiStringValue", InParms, , g_objRegCtx)
1232 if OutParms.ReturnValue = 0 then
1233 if OutParms.sValue <> Null then
1234 RegGetMultiString = OutParms.sValue
1235 end if
1236 end if
1237 else
1238 ' fallback mode
1239 On Error Resume Next
1240 RegGetMultiString = g_objShell.RegRead(strName)
1241 end if
1242end function
1243
1244
1245''
1246' Returns an array of subkey strings.
1247function RegEnumSubKeys(strRoot, ByVal strKeyPath)
1248 RegEnumSubKeys = Array()
1249 if RegInit() then
1250 ' Must use ExecMethod to call the EnumKey method because of the context.
1251 Set InParms = g_objReg.Methods_("EnumKey").Inparameters
1252 InParms.hDefKey = RegTransRoot(strRoot, strKeyPath)
1253 InParms.sSubKeyName = strKeyPath
1254 On Error Resume Next
1255 set OutParms = g_objReg.ExecMethod_("EnumKey", InParms, , g_objRegCtx)
1256 'LogPrint "RegEnumSubKeys(" & Hex(InParms.hDefKey) & "," & InParms.sSubKeyName &") -> " & OutParms.GetText_(1)
1257 if OutParms.ReturnValue = 0 then
1258 if OutParms.sNames <> Null then
1259 RegEnumSubKeys = OutParms.sNames
1260 end if
1261 end if
1262 else
1263 ' fallback mode
1264 dim objReg, rc, arrSubKeys
1265 set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
1266 On Error Resume Next
1267 rc = objReg.EnumKey(RegTransRoot(strRoot, strKeyPath), strKeyPath, arrSubKeys)
1268 if rc = 0 then
1269 RegEnumSubKeys = arrSubKeys
1270 end if
1271 end if
1272end function
1273
1274
1275''
1276' Returns an array of full path subkey strings.
1277function RegEnumSubKeysFull(strRoot, strKeyPath)
1278 dim arrTmp
1279 arrTmp = RegEnumSubKeys(strRoot, strKeyPath)
1280 for i = LBound(arrTmp) to UBound(arrTmp)
1281 arrTmp(i) = strKeyPath & "\" & arrTmp(i)
1282 next
1283 RegEnumSubKeysFull = arrTmp
1284end function
1285
1286
1287''
1288' Returns an rsorted array of subkey strings.
1289function RegEnumSubKeysRVerSorted(strRoot, strKeyPath)
1290 RegEnumSubKeysRVerSorted = ArrayRVerSortStrings(RegEnumSubKeys(strRoot, strKeyPath))
1291end function
1292
1293
1294''
1295' Returns an rsorted array of subkey strings.
1296function RegEnumSubKeysFullRVerSorted(strRoot, strKeyPath)
1297 RegEnumSubKeysFullRVerSorted = ArrayRVerSortStrings(RegEnumSubKeysFull(strRoot, strKeyPath))
1298end function
1299
1300
1301''
1302' Returns an array of value name strings.
1303function RegEnumValueNames(strRoot, ByVal strKeyPath)
1304 RegEnumValueNames = Array()
1305 if RegInit() then
1306 ' Must use ExecMethod to call the EnumKey method because of the context.
1307 Set InParms = g_objReg.Methods_("EnumValues").Inparameters
1308 InParms.hDefKey = RegTransRoot(strRoot, strKeyPath)
1309 InParms.sSubKeyName = strKeyPath
1310 On Error Resume Next
1311 set OutParms = g_objReg.ExecMethod_("EnumValues", InParms, , g_objRegCtx)
1312 'LogPrint "RegEnumValueNames(" & Hex(InParms.hDefKey) & "," & InParms.sSubKeyName &") -> " & OutParms.GetText_(1)
1313 if OutParms.ReturnValue = 0 then
1314 if OutParms.sNames <> Null then
1315 RegEnumValueNames = OutParms.sNames
1316 end if
1317 end if
1318 else
1319 ' fallback mode
1320 dim objReg, rc, arrSubKeys
1321 set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
1322 On Error Resume Next
1323 rc = objReg.EnumValues(RegTransRoot(strRoot, strKeyPath), strKeyPath, arrSubKeys)
1324 if rc = 0 then
1325 RegEnumValueNames = arrSubKeys
1326 end if
1327 end if
1328end function
1329
1330
1331''
1332' Returns an array of full path value name strings.
1333function RegEnumValueNamesFull(strRoot, strKeyPath)
1334 dim arrTmp
1335 arrTmp = RegEnumValueNames(strRoot, strKeyPath)
1336 for i = LBound(arrTmp) to UBound(arrTmp)
1337 arrTmp(i) = strKeyPath & "\" & arrTmp(i)
1338 next
1339 RegEnumValueNamesFull = arrTmp
1340end function
1341
1342
1343''
1344' Extract relevant paths from program links using a callback function.
1345'
1346' Enumerates start menu program links from "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\UFH\SHC"
1347' and similar, using the given callback to examine each and return a path if relevant. The relevant
1348' paths are returned in reverse sorted order.
1349'
1350' The callback prototype is as follows fnCallback(ByRef arrStrings, cStrings, ByRef objUser).
1351' Any non-empty return strings are collected, reverse sorted uniquely and returned.
1352'
1353function CollectFromProgramItemLinks(ByRef fnCallback, ByRef objUser)
1354 dim arrValues, strValue, arrStrings, str, arrCandidates, iCandidates, cStrings
1355 CollectFromProgramItemLinks = Array()
1356
1357 arrValues = RegEnumValueNamesFull("HKCU", "SOFTWARE\Microsoft\Windows\CurrentVersion\UFH\SHC")
1358 redim arrCandidates(UBound(arrValues) - LBound(arrValues) + 1)
1359 iCandidates = 0
1360 for each strValue in arrValues
1361 arrStrings = RegGetMultiString("HKCU\" & strValue)
1362 if UBound(arrStrings) >= 0 then
1363 cStrings = UBound(arrStrings) + 1 - LBound(arrStrings)
1364 str = fnCallback(arrStrings, cStrings, objUser)
1365 if str <> "" then
1366 if not ArrayContainsStringI(arrCandidates, str) then
1367 arrCandidates(iCandidates) = str
1368 iCandidates = iCandidates + 1
1369 end if
1370 end if
1371 end if
1372 next
1373 if iCandidates > 0 then
1374 redim preserve arrCandidates(iCandidates - 1)
1375 arrCandidates = ArrayRVerSortStrings(arrCandidates)
1376 for iCandidates = LBound(arrCandidates) to UBound(arrCandidates)
1377 LogPrint "CollectFromProgramItemLinks: #" & iCandidates & ": " & arrCandidates(iCandidates)
1378 next
1379 CollectFromProgramItemLinks = arrCandidates
1380 end if
1381end function
1382
1383
1384''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1385' Helpers: Messaging and Output '
1386''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1387
1388''
1389' Append text to the log file and echo it to stdout
1390sub Print(str)
1391 LogPrint str
1392 Wscript.Echo str
1393end sub
1394
1395
1396''
1397' Prints a test header
1398sub PrintHdr(strTest)
1399 LogPrint "***** Checking for " & strTest & " *****"
1400 Wscript.Echo "Checking for " & StrTest & "..."
1401end sub
1402
1403
1404''
1405' Prints a success message
1406sub PrintResultMsg(strTest, strResult)
1407 dim cchPad
1408 LogPrint "** " & strTest & ": " & strResult
1409 Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPad & strResult
1410end sub
1411
1412
1413''
1414' Prints a successfully detected path
1415sub PrintResult(strTest, strPath)
1416 strLongPath = PathAbsLong(strPath)
1417 if PathAbs(strPath) <> strLongPath then
1418 LogPrint "** " & strTest & ": " & strPath & " (" & UnixSlashes(strLongPath) & ")"
1419 Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPath & " (" & UnixSlashes(strLongPath) & ")"
1420 else
1421 LogPrint "** " & strTest & ": " & strPath
1422 Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPath
1423 end if
1424end sub
1425
1426
1427''
1428' Info message.
1429sub MsgInfo(strMsg)
1430 Print "info: " & strMsg
1431end sub
1432
1433
1434''
1435' Warning message.
1436sub MsgWarning(strMsg)
1437 Print "warning: " & strMsg
1438end sub
1439
1440
1441''
1442' Fatal error.
1443sub MsgFatal(strMsg)
1444 Print "fatal error: " & strMsg
1445 Wscript.Quit(1)
1446end sub
1447
1448
1449''
1450' Error message, fatal unless flag to ignore errors is given.
1451sub MsgError(strMsg)
1452 Print "error: " & strMsg
1453 if g_blnContinueOnError = False then
1454 Wscript.Quit(1)
1455 end if
1456 g_rcScript = 1
1457end sub
1458
1459''
1460' Error message, fatal unless flag to ignore errors is given.
1461' @note does not return
1462sub MsgSyntaxError(strMsg)
1463 Print "syntax error: " & strMsg
1464 Wscript.Quit(2)
1465end sub
1466
1467
1468''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1469' Helpers: Misc '
1470''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1471
1472''
1473' Translate a kBuild / VBox architecture name to a windows one.
1474function XlateArchitectureToWin(strArch)
1475 strArch = LCase(strArch)
1476 XlateArchitectureToWin = strArch
1477 if strArch = "amd64" then XlateArchitectureToWin = "x64"
1478end function
1479
1480
1481''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1482' Testcases '
1483''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
1484
1485''
1486' Self test for some of the above routines.
1487'
1488sub SelfTest
1489 dim i, str
1490 str = "0123456789"
1491 for i = 1 to Len(str)
1492 if CharIsDigit(Mid(str, i, 1)) <> True then MsgFatal "SelfTest failed: CharIsDigit("&Mid(str, i, 1)&")"
1493 next
1494 str = "abcdefghijklmnopqrstuvwxyz~`!@#$%^&*()_+-=ABCDEFGHIJKLMNOPQRSTUVWXYZ/\[]{}"
1495 for i = 1 to Len(str)
1496 if CharIsDigit(Mid(str, i, 1)) <> False then MsgFatal "SelfTest failed: CharIsDigit("&Mid(str, i, 1)&")"
1497 next
1498
1499 if StrVersionCompare("1234", "1234") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #1"
1500 if StrVersionCompare("1", "1") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #2"
1501 if StrVersionCompare("2", "1") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #3"
1502 if StrVersionCompare("1", "2") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #4"
1503 if StrVersionCompare("01", "1") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #5"
1504 if StrVersionCompare("01", "001") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #6"
1505 if StrVersionCompare("12", "123") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #7"
1506 if StrVersionCompare("v123", "123") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #8"
1507 if StrVersionCompare("v1.2.3", "v1.3.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #9"
1508 if StrVersionCompare("v1.02.3", "v1.3.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #10"
1509 if StrVersionCompare("v1.2.3", "v1.03.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #11"
1510 if StrVersionCompare("v1.2.4", "v1.23.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #12"
1511 if StrVersionCompare("v10.0.17163", "v10.00.18363") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #13"
1512 if StrVersionCompare("n 2.15.0", "2.12.0") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #14"
1513
1514 if StrGetFirstWord("1") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #1"
1515 if StrGetFirstWord(" 1 ") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #2"
1516 if StrGetFirstWord(" 1 2 ") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #3"
1517 if StrGetFirstWord("1 2") <> "1" then MsgFatal "SelfTest: StrGetFirstWord #4"
1518 if StrGetFirstWord("1234 5") <> "1234" then MsgFatal "SelfTest: StrGetFirstWord #5"
1519 if StrGetFirstWord(" ") <> "" then MsgFatal "SelfTest: StrGetFirstWord #6"
1520
1521 dim arr
1522 arr = ArrayAppend(Array("0", "1"), "2")
1523 if ArraySize(arr) <> 3 then MsgFatal "SelfTest: Array #1: size:" & ArraySize(arr)
1524 if ArrayToString(arr) <> "Array(""0"", ""1"", ""2"")" then MsgFatal "SelfTest: Array #1: " & ArrayToString(arr)
1525
1526 arr = ArrayPrepend(arr, "-1")
1527 if ArraySize(arr) <> 4 then MsgFatal "SelfTest: Array #2: size:" & ArraySize(arr)
1528 if ArrayToString(arr) <> "Array(""-1"", ""0"", ""1"", ""2"")" then MsgFatal "SelfTest: Array #2: " & ArrayToString(arr)
1529
1530 ArrayPrepend arr, "-2"
1531 if ArraySize(arr) <> 5 then MsgFatal "SelfTest: Array #3: size:" & ArraySize(arr)
1532 if ArrayToString(arr) <> "Array(""-2"", ""-1"", ""0"", ""1"", ""2"")" then MsgFatal "SelfTest: Array #3: " & ArrayToString(arr)
1533
1534 ArrayRemove arr, 1
1535 if ArraySize(arr) <> 4 then MsgFatal "SelfTest: Array #4: size:" & ArraySize(arr)
1536 if ArrayToString(arr) <> "Array(""-2"", ""0"", ""1"", ""2"")" then MsgFatal "SelfTest: Array #4: " & ArrayToString(arr)
1537
1538 arr = ArrayRemove(arr, 2)
1539 if ArraySize(arr) <> 3 then MsgFatal "SelfTest: Array #5: size:" & ArraySize(arr)
1540 if ArrayToString(arr) <> "Array(""-2"", ""0"", ""2"")" then MsgFatal "SelfTest: Array #5: " & ArrayToString(arr)
1541
1542 arr = ArrayPrepend(arr, "42")
1543 arr = ArrayAppend(arr, "-42")
1544 if ArraySize(arr) <> 5 then MsgFatal "SelfTest: Array #6: size:" & ArraySize(arr)
1545 if ArrayToString(arr) <> "Array(""42"", ""-2"", ""0"", ""2"", ""-42"")" then MsgFatal "SelfTest: Array #6: " & ArrayToString(arr)
1546
1547 arr = ArraySortStrings(arr)
1548 if ArraySize(arr) <> 5 then MsgFatal "SelfTest: Array #7: size:" & ArraySize(arr)
1549 if ArrayToString(arr) <> "Array(""-2"", ""-42"", ""0"", ""2"", ""42"")" then MsgFatal "SelfTest: Array #7: " & ArrayToString(arr)
1550
1551 arr = ArrayRSortStrings(arr)
1552 if ArraySize(arr) <> 5 then MsgFatal "SelfTest: Array #7: size:" & ArraySize(arr)
1553 if ArrayToString(arr) <> "Array(""42"", ""2"", ""0"", ""-42"", ""-2"")" then MsgFatal "SelfTest: Array #8: " & ArrayToString(arr)
1554
1555 arr = ArrayVerSortStrings(Array("v10", "v1", "v0"))
1556 if ArrayToString(arr) <> "Array(""v0"", ""v1"", ""v10"")" then MsgFatal "SelfTest: Array #9: " & ArrayToString(arr)
1557
1558 arr = ArrayRVerSortStrings(arr)
1559 if ArrayToString(arr) <> "Array(""v10"", ""v1"", ""v0"")" then MsgFatal "SelfTest: Array #10: " & ArrayToString(arr)
1560
1561 if ArrayJoinString(arr, ":") <> "v10:v1:v0" then MsgFatal "SelfTest: Array #11: " & ArrayJoinString(arr, ":")
1562
1563 if PathMatch("c:\", "C:\") <> true then MsgFatal "SelfTest: PathMatch #1"
1564 if PathMatch("c:\\\winDows/sysTem32", "C:\WindowS\.\\.\System32\.") <> true then MsgFatal "SelfTest: PathMatch #2"
1565 if PathMatch("c:\\\winDows/sysTem32", "C:\WindowS\.\\..\System32\.") <> false then MsgFatal "SelfTest: PathMatch #3"
1566 if PathMatch("\\x\", "\\\x\") <> false then MsgFatal "SelfTest: PathMatch #4"
1567 if PathMatch("\\x\", "\\x\") <> true then MsgFatal "SelfTest: PathMatch #5"
1568 if PathMatch("\\", "\\") <> true then MsgFatal "SelfTest: PathMatch #6"
1569 if PathMatch("\\x", "\\x") <> true then MsgFatal "SelfTest: PathMatch #7"
1570
1571end sub
1572
1573'
1574' Run the self tests if we're executed directly.
1575'
1576if StrEndsWithI(Wscript.ScriptFullName, "\tools\win\vbscript\helpers.vbs") then
1577 Wscript.echo "helpers.vbs: Running self test..."
1578 SelfTest
1579 Wscript.echo "helpers.vbs: Self test complete."
1580end if
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette