VirtualBox

Changeset 85809 in vbox


Ignore:
Timestamp:
Aug 18, 2020 8:56:54 AM (4 years ago)
Author:
vboxsync
Message:

configure.vbs: Split out the helpers into a separate file (tools/win/vbscript/helpers.vbs). Want to use this for a tools/envSub.cmd revamp.

Location:
trunk
Files:
2 added
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/configure.vbs

    r85807 r85809  
    2222
    2323
    24 '*****************************************************************************
    25 '* Global Variables                                                          *
    26 '*****************************************************************************
    27 dim g_strPath, g_strEnvFile, g_strLogFile, g_strCfgFile, g_strShellOutput
     24''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     25'  Header Files
     26''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     27
     28''
     29' Includes a vbscript file relative to the script.
     30sub IncludeFile(strFilename)
     31   dim objFile, objFileSys
     32   set objFileSys = WScript.CreateObject("Scripting.FileSystemObject")
     33   dim strPath : strPath = objFileSys.BuildPath(objFileSys.GetParentFolderName(Wscript.ScriptFullName), strFilename)
     34   set objFile = objFileSys.openTextFile(strPath)
     35   executeglobal objFile.readAll()
     36   objFile.close
     37   set objFileSys = nothing
     38end sub
     39
     40IncludeFile "tools\win\vbscript\helpers.vbs"
     41
     42
     43''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     44'  Global Variables                                                                                                              '
     45''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     46dim g_strPath, g_strEnvFile, g_strLogFile, g_strCfgFile
    2847g_strPath = Left(Wscript.ScriptFullName, Len(Wscript.ScriptFullName) - Len("\configure.vbs"))
    2948g_strEnvFile = g_strPath & "\env.bat"
     
    3251'g_strTmpFile = g_strPath & "\configure.tmp"
    3352
    34 dim g_objShell, g_objFileSys
    35 Set g_objShell = WScript.CreateObject("WScript.Shell")
    36 Set g_objFileSys = WScript.CreateObject("Scripting.FileSystemObject")
    3753
    3854' kBuild stuff.
     
    87103end if
    88104
    89 
    90 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    91 '  Helpers: Paths                                                                                                                '
    92 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    93 
    94 ''
    95 ' Converts to unix slashes
    96 function UnixSlashes(str)
    97    UnixSlashes = replace(str, "\", "/")
    98 end function
    99 
    100 
    101 ''
    102 ' Converts to dos slashes
    103 function DosSlashes(str)
    104    DosSlashes = replace(str, "/", "\")
    105 end function
    106 
    107 
    108 ''
    109 ' Get the path of the parent directory. Returns root if root was specified.
    110 ' Expects abs path.
    111 function PathParent(str)
    112    PathParent = g_objFileSys.GetParentFolderName(DosSlashes(str))
    113 end function
    114 
    115 
    116 ''
    117 ' Strips the filename from at path.
    118 function PathStripFilename(str)
    119    PathStripFilename = g_objFileSys.GetParentFolderName(DosSlashes(str))
    120 end function
    121 
    122 
    123 ''
    124 ' Get the abs path, use the short version if necessary.
    125 function PathAbs(str)
    126    strAbs    = g_objFileSys.GetAbsolutePathName(DosSlashes(str))
    127    strParent = g_objFileSys.GetParentFolderName(strAbs)
    128    if strParent = "" then
    129       PathAbs = strAbs
    130    else
    131       strParent = PathAbs(strParent)  ' Recurse to resolve parent paths.
    132       PathAbs   = g_objFileSys.BuildPath(strParent, g_objFileSys.GetFileName(strAbs))
    133 
    134       dim obj
    135       set obj = Nothing
    136       if FileExists(PathAbs) then
    137          set obj = g_objFileSys.GetFile(PathAbs)
    138       elseif DirExists(PathAbs) then
    139          set obj = g_objFileSys.GetFolder(PathAbs)
    140       end if
    141 
    142       if not (obj is nothing) then
    143          for each objSub in obj.ParentFolder.SubFolders
    144             if obj.Name = objSub.Name  or  obj.ShortName = objSub.ShortName then
    145                if  InStr(1, objSub.Name, " ") > 0 _
    146                 Or InStr(1, objSub.Name, "&") > 0 _
    147                 Or InStr(1, objSub.Name, "$") > 0 _
    148                   then
    149                   PathAbs = g_objFileSys.BuildPath(strParent, objSub.ShortName)
    150                   if  InStr(1, PathAbs, " ") > 0 _
    151                    Or InStr(1, PathAbs, "&") > 0 _
    152                    Or InStr(1, PathAbs, "$") > 0 _
    153                      then
    154                      MsgFatal "PathAbs(" & str & ") attempted to return filename with problematic " _
    155                       & "characters in it (" & PathAbs & "). The tool/sdk referenced will probably " _
    156                       & "need to be copied or reinstalled to a location without 'spaces', '$', ';' " _
    157                       & "or '&' in the path name. (Unless it's a problem with this script of course...)"
    158                   end if
    159                else
    160                   PathAbs = g_objFileSys.BuildPath(strParent, objSub.Name)
    161                end if
    162                exit for
    163             end if
    164          next
    165       end if
    166    end if
    167 end function
    168 
    169 
    170 ''
    171 ' Get the abs path, use the long version.
    172 function PathAbsLong(str)
    173    strAbs    = g_objFileSys.GetAbsolutePathName(DosSlashes(str))
    174    strParent = g_objFileSys.GetParentFolderName(strAbs)
    175    if strParent = "" then
    176       PathAbsLong = strAbs
    177    else
    178       strParent = PathAbsLong(strParent)  ' Recurse to resolve parent paths.
    179       PathAbsLong = g_objFileSys.BuildPath(strParent, g_objFileSys.GetFileName(strAbs))
    180 
    181       dim obj
    182       set obj = Nothing
    183       if FileExists(PathAbsLong) then
    184          set obj = g_objFileSys.GetFile(PathAbsLong)
    185       elseif DirExists(PathAbsLong) then
    186          set obj = g_objFileSys.GetFolder(PathAbsLong)
    187       end if
    188 
    189       if not (obj is nothing) then
    190          for each objSub in obj.ParentFolder.SubFolders
    191             if obj.Name = objSub.Name  or  obj.ShortName = objSub.ShortName then
    192                PathAbsLong = g_objFileSys.BuildPath(strParent, objSub.Name)
    193                exit for
    194             end if
    195          next
    196       end if
    197    end if
    198 end function
    199 
    200 
    201 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    202 '  Helpers: Files and Dirs                                                                                                       '
    203 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    204 
    205 ''
    206 ' Read a file (typically the tmp file) into a string.
    207 function FileToString(strFilename)
    208    const ForReading = 1, TristateFalse = 0
    209    dim objLogFile, str
    210 
    211    set objFile = g_objFileSys.OpenTextFile(DosSlashes(strFilename), ForReading, False, TristateFalse)
    212    str = objFile.ReadAll()
    213    objFile.Close()
    214 
    215    FileToString = str
    216 end function
    217 
    218 
    219 ''
    220 ' Deletes a file
    221 sub FileDelete(strFilename)
    222    if g_objFileSys.FileExists(DosSlashes(strFilename)) then
    223       g_objFileSys.DeleteFile(DosSlashes(strFilename))
    224    end if
    225 end sub
    226 
    227 
    228 ''
    229 ' Appends a line to an ascii file.
    230 sub FileAppendLine(strFilename, str)
    231    const ForAppending = 8, TristateFalse = 0
    232    dim objFile
    233 
    234    set objFile = g_objFileSys.OpenTextFile(DosSlashes(strFilename), ForAppending, True, TristateFalse)
    235    objFile.WriteLine(str)
    236    objFile.Close()
    237 end sub
    238 
    239 
    240 ''
    241 ' Checks if the file exists.
    242 function FileExists(strFilename)
    243    FileExists = g_objFileSys.FileExists(DosSlashes(strFilename))
    244 end function
    245 
    246 
    247 ''
    248 ' Checks if the directory exists.
    249 function DirExists(strDirectory)
    250    DirExists = g_objFileSys.FolderExists(DosSlashes(strDirectory))
    251 end function
    252 
    253 
    254 ''
    255 ' Returns true if there are subfolders starting with the given string.
    256 function HasSubdirsStartingWith(strFolder, strStartingWith)
    257    HasSubdirsStartingWith = False
    258    if DirExists(strFolder) then
    259       dim obj
    260       set obj = g_objFileSys.GetFolder(strFolder)
    261       for each objSub in obj.SubFolders
    262          if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
    263             HasSubdirsStartingWith = True
    264             LogPrint "# HasSubdirsStartingWith(" & strFolder & "," & strStartingWith & ") found " & objSub.Name
    265             exit for
    266          end if
    267       next
    268    end if
    269 end function
    270 
    271 
    272 ''
    273 ' Returns a sorted array of subfolder names that starts with the given string.
    274 function GetSubdirsStartingWith(strFolder, strStartingWith)
    275    if DirExists(strFolder) then
    276       dim obj, i
    277       set obj = g_objFileSys.GetFolder(strFolder)
    278       i = 0
    279       for each objSub in obj.SubFolders
    280          if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
    281             i = i + 1
    282          end if
    283       next
    284       if i > 0 then
    285          redim arrResult(i - 1)
    286          i = 0
    287          for each objSub in obj.SubFolders
    288             if StrComp(Left(objSub.Name, Len(strStartingWith)), strStartingWith) = 0 then
    289                arrResult(i) = objSub.Name
    290                i = i + 1
    291             end if
    292          next
    293          GetSubdirsStartingWith = arrResult
    294       else
    295          GetSubdirsStartingWith = Array()
    296       end if
    297    else
    298       GetSubdirsStartingWith = Array()
    299    end if
    300 end function
    301 
    302 
    303 ''
    304 ' Returns a sorted array of subfolder names that starts with the given string.
    305 function GetSubdirsStartingWithVerSorted(strFolder, strStartingWith)
    306    GetSubdirsStartingWithVerSorted = ArrayVerSortStrings(GetSubdirsStartingWith(strFolder, strStartingWith))
    307 end function
    308 
    309 
    310 ''
    311 ' Returns a reverse version sorted array of subfolder names that starts with the given string.
    312 function GetSubdirsStartingWithRVerSorted(strFolder, strStartingWith)
    313    GetSubdirsStartingWithRSortedVersion = ArrayRVerSortStrings(GetSubdirsStartingWith(strFolder, strStartingWith))
    314 end function
    315 
    316 
    317 ''
    318 ' Try find the specified file in the specified path variable.
    319 function WhichEx(strEnvVar, strFile)
    320    dim strPath, iStart, iEnd, str
    321 
    322    ' the path
    323    strPath = EnvGet(strEnvVar)
    324    iStart = 1
    325    do while iStart <= Len(strPath)
    326       iEnd = InStr(iStart, strPath, ";")
    327       if iEnd <= 0 then iEnd = Len(strPath) + 1
    328       if iEnd > iStart then
    329          str = Mid(strPath, iStart, iEnd - iStart) & "/" & strFile
    330          if FileExists(str) then
    331             WhichEx = str
    332             exit function
    333          end if
    334       end if
    335       iStart = iEnd + 1
    336    loop
    337 
    338    ' registry or somewhere?
    339 
    340    WhichEx = ""
    341 end function
    342 
    343 
    344 ''
    345 ' Try find the specified file in the path.
    346 function Which(strFile)
    347    Which = WhichEx("Path", strFile)
    348 end function
    349 
    350 
    351 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    352 '  Helpers: Processes                                                                                                            '
    353 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    354 
    355 ''
    356 ' Checks if this is a WOW64 process.
    357 function IsWow64()
    358    if g_objShell.Environment("PROCESS")("PROCESSOR_ARCHITEW6432") <> "" then
    359       IsWow64 = 1
    360    else
    361       IsWow64 = 0
    362    end if
    363 end function
    364 
    365 
    366 ''
    367 ' Executes a command in the shell catching output in g_strShellOutput
    368 function Shell(strCommand, blnBoth)
    369    dim strShell, strCmdline, objExec, str
    370 
    371    strShell = g_objShell.ExpandEnvironmentStrings("%ComSpec%")
    372    if blnBoth = true then
    373       strCmdline = strShell & " /c " & strCommand & " 2>&1"
    374    else
    375       strCmdline = strShell & " /c " & strCommand & " 2>nul"
    376    end if
    377 
    378    LogPrint "# Shell: " & strCmdline
    379    Set objExec = g_objShell.Exec(strCmdLine)
    380    g_strShellOutput = objExec.StdOut.ReadAll()
    381    objExec.StdErr.ReadAll()
    382    do while objExec.Status = 0
    383       Wscript.Sleep 20
    384       g_strShellOutput = g_strShellOutput & objExec.StdOut.ReadAll()
    385       objExec.StdErr.ReadAll()
    386    loop
    387 
    388    LogPrint "# Status: " & objExec.ExitCode
    389    LogPrint "# Start of Output"
    390    LogPrint g_strShellOutput
    391    LogPrint "# End of Output"
    392 
    393    Shell = objExec.ExitCode
    394 end function
    395 
    396 
    397 ''
    398 ' Gets the SID of the current user.
    399 function GetSid()
    400    dim objNet, strUser, strDomain, offSlash, objWmiUser
    401    GetSid = ""
    402 
    403    ' Figure the user + domain
    404    set objNet = CreateObject("WScript.Network")
    405    strUser   = objNet.UserName
    406    strDomain = objNet.UserDomain
    407    offSlash  = InStr(1, strUser, "\")
    408    if offSlash > 0 then
    409       strDomain = Left(strUser, offSlash - 1)
    410       strUser   = Right(strUser, Len(strUser) - offSlash)
    411    end if
    412 
    413    ' Lookup the user.
    414    on error resume next
    415    set objWmiUser = GetObject("winmgmts:{impersonationlevel=impersonate}!/root/cimv2:Win32_UserAccount." _
    416                               & "Domain='" & strDomain &"',Name='" & strUser & "'")
    417    if err.number = 0 then
    418       GetSid = objWmiUser.SID
    419    end if
    420 end function
    421 
    422 
    423 ''
    424 ' Gets the commandline used to invoke the script.
    425 function GetCommandline()
    426    dim str, i
    427 
    428    '' @todo find an api for querying it instead of reconstructing it like this...
    429    GetCommandline = "cscript configure.vbs"
    430    for i = 1 to WScript.Arguments.Count
    431       str = WScript.Arguments.Item(i - 1)
    432       if str = "" then
    433          str = """"""
    434       elseif (InStr(1, str, " ")) then
    435          str = """" & str & """"
    436       end if
    437       GetCommandline = GetCommandline & " " & str
    438    next
    439 end function
    440 
    441 
    442 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    443 '  Helpers: Environment                                                                                                          '
    444 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    445 
    446 ''
    447 ' Gets an environment variable.
    448 function EnvGet(strName)
    449    EnvGet = g_objShell.Environment("PROCESS")(strName)
    450 end function
    451 
    452 
    453 ''
    454 ' Sets an environment variable.
    455 sub EnvSet(strName, strValue)
    456    g_objShell.Environment("PROCESS")(strName) = strValue
    457    LogPrint "EnvSet: " & strName & "=" & strValue
    458 end sub
    459 
    460 
    461 ''
    462 ' Appends a string to an environment variable
    463 sub EnvAppend(strName, strValue)
    464    dim str
    465    str = g_objShell.Environment("PROCESS")(strName)
    466    g_objShell.Environment("PROCESS")(strName) =  str & strValue
    467    LogPrint "EnvAppend: " & strName & "=" & str & strValue
    468 end sub
    469 
    470 
    471 ''
    472 ' Prepends a string to an environment variable
    473 sub EnvPrepend(strName, strValue)
    474    dim str
    475    str = g_objShell.Environment("PROCESS")(strName)
    476    g_objShell.Environment("PROCESS")(strName) =  strValue & str
    477    LogPrint "EnvPrepend: " & strName & "=" & strValue & str
    478 end sub
    479 
    480 ''
    481 ' Gets the first non-empty environment variable of the given two.
    482 function EnvGetFirst(strName1, strName2)
    483    EnvGetFirst = g_objShell.Environment("PROCESS")(strName1)
    484    if EnvGetFirst = "" then
    485       EnvGetFirst = g_objShell.Environment("PROCESS")(strName2)
    486    end if
    487 end function
    488 
    489 
    490 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    491 '  Helpers: Strings                                                                                                              '
    492 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    493 
    494 ''
    495 ' Right pads a string with spaces to the given length
    496 function RightPad(str, cch)
    497    if Len(str) < cch then
    498       RightPad = str & String(cch - Len(str), " ")
    499    else
    500       RightPad = str
    501    end if
    502 end function
    503 
    504 
    505 ''
    506 ' Checks if the given character is a decimal digit
    507 function CharIsDigit(ch)
    508    CharIsDigit = (InStr(1, "0123456789", ch) > 0)
    509 end function
    510 
    511 ''
    512 ' Worker for StrVersionCompare
    513 ' The offset is updated to point to the first non-digit character.
    514 function CountDigitsIgnoreLeadingZeros(ByRef str, ByRef off)
    515    dim cntDigits, blnLeadingZeros, ch, offInt
    516    cntDigits = 0
    517    if CharIsDigit(Mid(str, off, 1)) then
    518       ' Rewind to start of digest sequence.
    519       do while off > 1
    520          if not CharIsDigit(Mid(str, off - 1, 1)) then exit do
    521          off = off - 1
    522       loop
    523       ' Count digits, ignoring leading zeros.
    524       blnLeadingZeros = True
    525       for off = off to Len(str)
    526          ch = Mid(str, off, 1)
    527          if CharIsDigit(ch) then
    528             if ch <> "0" or blnLeadingZeros = False then
    529                cntDigits = cntDigits + 1
    530                blnLeadingZeros = False
    531             end if
    532          else
    533             exit for
    534          end if
    535       next
    536       ' If all zeros, count one of them.
    537       if cntDigits = 0 then cntDigits = 1
    538    end if
    539    CountDigitsIgnoreLeadingZeros = cntDigits
    540 end function
    541 
    542 ''
    543 ' Very simple version string compare function.
    544 ' @returns < 0 if str1 is smaller than str2
    545 ' @returns 0   if str1 and str2 are equal
    546 ' @returns > 1 if str2 is larger than str1
    547 function StrVersionCompare(str1, str2)
    548    ' Compare the strings.  We can rely on StrComp if equal or one is empty.
    549    'LogPrint "StrVersionCompare("&str1&","&str2&"):"
    550    StrVersionCompare = StrComp(str2, str1)
    551    if StrVersionCompare <> 0 then
    552       dim cch1, cch2, off1, off2, ch1, ch2, chPrev1, chPrev2, intDiff, cchDigits
    553       cch1 = Len(str1)
    554       cch2 = Len(str2)
    555       if cch1 > 0 and cch2 > 0 then
    556          ' Compare the common portion
    557          off1 = 1
    558          off2 = 1
    559          chPrev1 = "x"
    560          chPrev2 = "x"
    561          do while off1 <= cch1 and off2 <= cch2
    562             ch1 = Mid(str1, off1, 1)
    563             ch2 = Mid(str2, off2, 1)
    564             if ch1 = ch2 then
    565                off1 = off1 + 1
    566                off2 = off2 + 1
    567                chPrev1 = ch1
    568                chPrev2 = ch2
    569             else
    570                ' Is there a digest sequence in play.  This includes the scenario where one of the
    571                ' string ran out of digests.
    572                dim blnDigest1 : blnDigest1 = CharIsDigit(ch1)
    573                dim blnDigest2 : blnDigest2 = CharIsDigit(ch2)
    574                if    (blnDigest1 = True or blnDigest2 = True) _
    575                  and (blnDigest1 = True or CharIsDigit(chPrev1) = True) _
    576                  and (blnDigest2 = True or CharIsDigit(chPrev2) = True) _
    577                then
    578                   'LogPrint "StrVersionCompare: off1="&off1&" off2="&off2&" ch1="&ch1&" chPrev1="&chPrev1&" ch2="&ch2&" chPrev2="&chPrev2
    579                   if blnDigest1 = False then off1 = off1 - 1
    580                   if blnDigest2 = False then off2 = off2 - 1
    581                   ' The one with the fewer digits comes first.
    582                   ' Note! off1 and off2 are adjusted to next non-digit character in the strings.
    583                   cchDigits = CountDigitsIgnoreLeadingZeros(str1, off1)
    584                   intDiff = cchDigits - CountDigitsIgnoreLeadingZeros(str2, off2)
    585                   'LogPrint "StrVersionCompare: off1="&off1&" off2="&off2&" cchDigits="&cchDigits
    586                   if intDiff <> 0 then
    587                      StrVersionCompare = intDiff
    588                      'LogPrint "StrVersionCompare: --> "&intDiff&" #1"
    589                      exit function
    590                   end if
    591 
    592                   ' If the same number of digits, the smaller digit wins. However, because of
    593                   ' potential leading zeros, we must redo the compare. Assume ASCII-like stuff
    594                   ' and we can use StrComp for this.
    595                   intDiff = StrComp(Mid(str1, off1 - cchDigits, cchDigits), Mid(str2, off2 - cchDigits, cchDigits))
    596                   if intDiff <> 0 then
    597                      StrVersionCompare = intDiff
    598                      'LogPrint "StrVersionCompare: --> "&intDiff&" #2"
    599                      exit function
    600                   end if
    601                   chPrev1 = "x"
    602                   chPrev2 = "x"
    603                else
    604                   if blnDigest1 then
    605                      StrVersionCompare = -1   ' Digits before characters
    606                      'LogPrint "StrVersionCompare: --> -1 (#3)"
    607                   elseif blnDigest2 then
    608                      StrVersionCompare = 1       ' Digits before characters
    609                      'LogPrint "StrVersionCompare: --> 1 (#4)"
    610                   else
    611                      StrVersionCompare = StrComp(ch1, ch2)
    612                      'LogPrint "StrVersionCompare: --> "&StrVersionCompare&" (#5)"
    613                   end if
    614                   exit function
    615                end if
    616             end if
    617          loop
    618 
    619          ' The common part matches up, so the shorter string 'wins'.
    620          StrVersionCompare = (cch1 - off1) - (cch2 - off2)
    621       end if
    622    end if
    623    'LogPrint "StrVersionCompare: --> "&StrVersionCompare&" (#6)"
    624 end function
    625 
    626 
    627 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    628 '  Helpers: Arrays                                                                                                               '
    629 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    630 
    631 ''
    632 ' Returns a reverse array (copy).
    633 function ArrayReverse(arr)
    634    dim cnt, i, j, iHalf, objTmp
    635    cnt = UBound(arr) - LBound(arr) + 1
    636    if cnt > 0 then
    637       j     = UBound(arr)
    638       iHalf = Fix(LBound(arr) + cnt / 2)
    639       for i = LBound(arr) to iHalf - 1
    640          objTmp = arr(i)
    641          arr(i) = arr(j)
    642          arr(j) = objTmp
    643          j = j - 1
    644       next
    645    end if
    646    ArrayReverse = arr
    647 end function
    648 
    649 
    650 ''
    651 ' Returns a reverse sorted array (strings).
    652 function ArraySortStringsEx(arrStrings, ByRef fnCompare)
    653    dim str1, str2, i, j
    654    for i = LBound(arrStrings) to UBound(arrStrings)
    655       str1 = arrStrings(i)
    656       for j = i + 1 to UBound(arrStrings)
    657          str2 = arrStrings(j)
    658          if fnCompare(str2, str1) < 0 then
    659             arrStrings(j) = str1
    660             str1 = str2
    661          end if
    662       next
    663       arrStrings(i) = str1
    664    next
    665    ArraySortStringsEx = arrStrings
    666 end function
    667 
    668 
    669 ''
    670 ' Returns a reverse sorted array (strings).
    671 function ArraySortStrings(arrStrings)
    672    ArraySortStrings = ArraySortStringsEx(arrStrings, GetRef("StrComp"))
    673 end function
    674 
    675 
    676 ''
    677 ' Returns a reverse sorted array (strings).
    678 function ArrayVerSortStrings(arrStrings)
    679    ArrayVerSortStrings = ArraySortStringsEx(arrStrings, GetRef("StrVersionCompare"))
    680 end function
    681 
    682 
    683 ''
    684 ' Returns a reverse sorted array (strings).
    685 function ArrayRSortStrings(arrStrings)
    686    ArrayRSortStrings = ArrayReverse(ArraySortStringsEx(arrStrings, GetRef("StrComp")))
    687 end function
    688 
    689 
    690 ''
    691 ' Returns a reverse version sorted array (strings).
    692 function ArrayRVerSortStrings(arrStrings)
    693    ArrayRVerSortStrings = ArrayReverse(ArraySortStringsEx(arrStrings, GetRef("StrVersionCompare")))
    694 end function
    695 
    696 
    697 ''
    698 ' Prints a string array.
    699 sub ArrayPrintStrings(arrStrings, strPrefix)
    700    for i = LBound(arrStrings) to UBound(arrStrings)
    701       Print strPrefix & "arrStrings(" & i & ") = '" & arrStrings(i) & "'"
    702    next
    703 end sub
    704 
    705 
    706 ''
    707 ' Returns the input array with the string appended.
    708 ' Note! There must be some better way of doing this...
    709 ' @todo Lots of copying here...
    710 function ArrayAppend(arr, str)
    711    dim i, cnt
    712    cnt = UBound(arr) - LBound(arr) + 1
    713    redim arrRet(cnt)
    714    for i = LBound(arr) to UBound(arr)
    715       arrRet(i) = arr(i)
    716    next
    717    arrRet(UBound(arr) + 1) = str
    718    ArrayAppend = arrRet
    719 end function
    720 
    721 
    722 ''
    723 ' Checks if the array contains the given string (case sensitive).
    724 function ArrayContainsString(ByRef arr, str)
    725    dim strCur
    726    ArrayContainsString = False
    727    for each strCur in arr
    728       if StrComp(strCur, str) = 0 then
    729          ArrayContainsString = True
    730          exit function
    731       end if
    732    next
    733 end function
    734 
    735 
    736 ''
    737 ' Checks if the array contains the given string, using case insensitive compare.
    738 function ArrayContainsStringI(ByRef arr, str)
    739    dim strCur
    740    ArrayContainsStringI = False
    741    for each strCur in arr
    742       if StrComp(strCur, str, vbTextCompare) = 0 then
    743          ArrayContainsStringI = True
    744          exit function
    745       end if
    746    next
    747 end function
    748 
    749 ''
    750 ' Returns the number of entries in an array.
    751 function ArraySize(ByRef arr)
    752    if (UBound(arr) >= 0) then
    753       ArraySize = UBound(arr) - LBound(arr) + 1
    754    else
    755       ArraySize = 0
    756    end if
    757 end function
    758 
    759 
    760 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    761 '  Helpers: Registry                                                                                                             '
    762 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    763 
    764 '' The registry globals
    765 dim g_objReg, g_objRegCtx
    766 dim g_blnRegistry
    767 g_blnRegistry = false
    768 
    769 
    770 ''
    771 ' Init the register provider globals.
    772 function RegInit()
    773    RegInit = false
    774    On Error Resume Next
    775    if g_blnRegistry = false then
    776       set g_objRegCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
    777       ' Comment out the following for lines if the cause trouble on your windows version.
    778       if IsWow64() then
    779          g_objRegCtx.Add "__ProviderArchitecture", 64
    780          g_objRegCtx.Add "__RequiredArchitecture", true
    781          LogPrint "RegInit: WoW64"
    782       end if
    783       set objLocator = CreateObject("Wbemscripting.SWbemLocator")
    784       set objServices = objLocator.ConnectServer("", "root\default", "", "", , , , g_objRegCtx)
    785       set g_objReg = objServices.Get("StdRegProv")
    786       g_blnRegistry = true
    787    end if
    788    RegInit = true
    789 end function
    790 
    791 
    792 ''
    793 ' Translates a register root name to a value
    794 ' This will translate HKCU path to HKEY_USERS and fixing
    795 function RegTransRoot(strRoot, ByRef sSubKeyName)
    796    const HKEY_LOCAL_MACHINE = &H80000002
    797    const HKEY_CURRENT_USER  = &H80000001
    798    const HKEY_USERS         = &H80000003
    799 
    800    select case strRoot
    801       case "HKLM"
    802          RegTransRoot = HKEY_LOCAL_MACHINE
    803       case "HKUS"
    804          RegTransRoot = HKEY_USERS
    805       case "HKCU"
    806          dim strCurrentSid
    807          strCurrentSid = GetSid()
    808          if strCurrentSid <> "" then
    809             sSubKeyName  = strCurrentSid & "\" & sSubKeyName
    810             RegTransRoot = HKEY_USERS
    811             'LogPrint "RegTransRoot: HKCU -> HKEY_USERS + " & sSubKeyName
    812          else
    813             RegTransRoot = HKEY_CURRENT_USER
    814             LogPrint "RegTransRoot: Warning! HKCU -> HKEY_USERS failed!"
    815          end if
    816       case else
    817          MsgFatal "RegTransRoot: Unknown root: '" & strRoot & "'"
    818          RegTransRoot = 0
    819    end select
    820 end function
    821 
    822 
    823 ''
    824 ' Gets a value from the registry. Returns "" if string wasn't found / valid.
    825 function RegGetString(strName)
    826    RegGetString = ""
    827    if RegInit() then
    828       dim strRoot, strKey, strValue
    829 
    830       ' split up into root, key and value parts.
    831       strRoot = left(strName, instr(strName, "\") - 1)
    832       strKey = mid(strName, instr(strName, "\") + 1, instrrev(strName, "\") - instr(strName, "\"))
    833       strValue = mid(strName, instrrev(strName, "\") + 1)
    834 
    835       ' Must use ExecMethod to call the GetStringValue method because of the context.
    836       Set InParms = g_objReg.Methods_("GetStringValue").Inparameters
    837       InParms.hDefKey     = RegTransRoot(strRoot, strKey)
    838       InParms.sSubKeyName = strKey
    839       InParms.sValueName  = strValue
    840       On Error Resume Next
    841       set OutParms = g_objReg.ExecMethod_("GetStringValue", InParms, , g_objRegCtx)
    842       if OutParms.ReturnValue = 0 then
    843          if OutParms.sValue <> Null then
    844             RegGetString = OutParms.sValue
    845          end if
    846       end if
    847    else
    848       ' fallback mode
    849       On Error Resume Next
    850       RegGetString = g_objShell.RegRead(strName)
    851    end if
    852 end function
    853 
    854 
    855 ''
    856 ' Gets a multi string value from the registry. Returns array of strings if found, otherwise empty array().
    857 function RegGetMultiString(strName)
    858    RegGetMultiString = Array()
    859    if RegInit() then
    860       dim strRoot, strKey, strValue
    861 
    862       ' split up into root, key and value parts.
    863       strRoot = left(strName, instr(strName, "\") - 1)
    864       strKey = mid(strName, instr(strName, "\") + 1, instrrev(strName, "\") - instr(strName, "\"))
    865       strValue = mid(strName, instrrev(strName, "\") + 1)
    866 
    867       ' Must use ExecMethod to call the GetStringValue method because of the context.
    868       Set InParms = g_objReg.Methods_("GetMultiStringValue").Inparameters
    869       InParms.hDefKey     = RegTransRoot(strRoot, strKey)
    870       InParms.sSubKeyName = strKey
    871       InParms.sValueName  = strValue
    872       On Error Resume Next
    873       set OutParms = g_objReg.ExecMethod_("GetMultiStringValue", InParms, , g_objRegCtx)
    874       if OutParms.ReturnValue = 0 then
    875          if OutParms.sValue <> Null then
    876             RegGetMultiString = OutParms.sValue
    877          end if
    878       end if
    879    else
    880       ' fallback mode
    881       On Error Resume Next
    882       RegGetMultiString = g_objShell.RegRead(strName)
    883    end if
    884 end function
    885 
    886 
    887 ''
    888 ' Returns an array of subkey strings.
    889 function RegEnumSubKeys(strRoot, ByVal strKeyPath)
    890    RegEnumSubKeys = Array()
    891    if RegInit() then
    892       ' Must use ExecMethod to call the EnumKey method because of the context.
    893       Set InParms = g_objReg.Methods_("EnumKey").Inparameters
    894       InParms.hDefKey     = RegTransRoot(strRoot, strKeyPath)
    895       InParms.sSubKeyName = strKeyPath
    896       On Error Resume Next
    897       set OutParms = g_objReg.ExecMethod_("EnumKey", InParms, , g_objRegCtx)
    898       'LogPrint "RegEnumSubKeys(" & Hex(InParms.hDefKey) & "," & InParms.sSubKeyName &") -> " & OutParms.GetText_(1)
    899       if OutParms.ReturnValue = 0 then
    900          if OutParms.sNames <> Null then
    901             RegEnumSubKeys = OutParms.sNames
    902          end if
    903       end if
    904    else
    905       ' fallback mode
    906       dim objReg, rc, arrSubKeys
    907       set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
    908       On Error Resume Next
    909       rc = objReg.EnumKey(RegTransRoot(strRoot, strKeyPath), strKeyPath, arrSubKeys)
    910       if rc = 0 then
    911          RegEnumSubKeys = arrSubKeys
    912       end if
    913    end if
    914 end function
    915 
    916 
    917 ''
    918 ' Returns an array of full path subkey strings.
    919 function RegEnumSubKeysFull(strRoot, strKeyPath)
    920    dim arrTmp
    921    arrTmp = RegEnumSubKeys(strRoot, strKeyPath)
    922    for i = LBound(arrTmp) to UBound(arrTmp)
    923       arrTmp(i) = strKeyPath & "\" & arrTmp(i)
    924    next
    925    RegEnumSubKeysFull = arrTmp
    926 end function
    927 
    928 
    929 ''
    930 ' Returns an rsorted array of subkey strings.
    931 function RegEnumSubKeysRVerSorted(strRoot, strKeyPath)
    932    RegEnumSubKeysRVerSorted = ArrayRVerSortStrings(RegEnumSubKeys(strRoot, strKeyPath))
    933 end function
    934 
    935 
    936 ''
    937 ' Returns an rsorted array of subkey strings.
    938 function RegEnumSubKeysFullRVerSorted(strRoot, strKeyPath)
    939    RegEnumSubKeysFullRVerSorted = ArrayRVerSortStrings(RegEnumSubKeysFull(strRoot, strKeyPath))
    940 end function
    941 
    942 
    943 ''
    944 ' Returns an array of value name strings.
    945 function RegEnumValueNames(strRoot, ByVal strKeyPath)
    946    RegEnumValueNames = Array()
    947    if RegInit() then
    948       ' Must use ExecMethod to call the EnumKey method because of the context.
    949       Set InParms = g_objReg.Methods_("EnumValues").Inparameters
    950       InParms.hDefKey     = RegTransRoot(strRoot, strKeyPath)
    951       InParms.sSubKeyName = strKeyPath
    952       On Error Resume Next
    953       set OutParms = g_objReg.ExecMethod_("EnumValues", InParms, , g_objRegCtx)
    954       'LogPrint "RegEnumValueNames(" & Hex(InParms.hDefKey) & "," & InParms.sSubKeyName &") -> " & OutParms.GetText_(1)
    955       if OutParms.ReturnValue = 0 then
    956          if OutParms.sNames <> Null then
    957             RegEnumValueNames = OutParms.sNames
    958          end if
    959       end if
    960    else
    961       ' fallback mode
    962       dim objReg, rc, arrSubKeys
    963       set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
    964       On Error Resume Next
    965       rc = objReg.EnumValues(RegTransRoot(strRoot, strKeyPath), strKeyPath, arrSubKeys)
    966       if rc = 0 then
    967          RegEnumValueNames = arrSubKeys
    968       end if
    969    end if
    970 end function
    971 
    972 
    973 ''
    974 ' Returns an array of full path value name strings.
    975 function RegEnumValueNamesFull(strRoot, strKeyPath)
    976    dim arrTmp
    977    arrTmp = RegEnumValueNames(strRoot, strKeyPath)
    978    for i = LBound(arrTmp) to UBound(arrTmp)
    979       arrTmp(i) = strKeyPath & "\" & arrTmp(i)
    980    next
    981    RegEnumValueNamesFull = arrTmp
    982 end function
    983 
    984 
    985 ''
    986 ' Extract relevant paths from program links using a callback function.
    987 '
    988 ' Enumerates start menu program links from "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\UFH\SHC"
    989 ' and similar, using the given callback to examine each and return a path if relevant.  The relevant
    990 ' paths are returned in reverse sorted order.
    991 '
    992 ' The callback prototype is as follows fnCallback(ByRef arrStrings, cStrings, ByRef objUser).
    993 ' Any non-empty return strings are collected, reverse sorted uniquely and returned.
    994 '
    995 function CollectFromProgramItemLinks(ByRef fnCallback, ByRef objUser)
    996    dim arrValues, strValue, arrStrings, str, arrCandidates, iCandidates, cStrings
    997    CollectFromProgramItemLinks = Array()
    998 
    999    arrValues = RegEnumValueNamesFull("HKCU", "SOFTWARE\Microsoft\Windows\CurrentVersion\UFH\SHC")
    1000    redim arrCandidates(UBound(arrValues) - LBound(arrValues) + 1)
    1001    iCandidates = 0
    1002    for each strValue in arrValues
    1003       arrStrings = RegGetMultiString("HKCU\" & strValue)
    1004       if UBound(arrStrings) >= 0 then
    1005          cStrings = UBound(arrStrings) + 1 - LBound(arrStrings)
    1006          str = fnCallback(arrStrings, cStrings, objUser)
    1007          if str <> "" then
    1008             if not ArrayContainsStringI(arrCandidates, str) then
    1009                arrCandidates(iCandidates) = str
    1010                iCandidates = iCandidates + 1
    1011             end if
    1012          end if
    1013       end if
    1014    next
    1015    if iCandidates > 0 then
    1016       redim preserve arrCandidates(iCandidates - 1)
    1017       arrCandidates = ArrayRVerSortStrings(arrCandidates)
    1018       for iCandidates = LBound(arrCandidates) to UBound(arrCandidates)
    1019          LogPrint "CollectFromProgramItemLinks: #" & iCandidates & ": " & arrCandidates(iCandidates)
    1020       next
    1021       CollectFromProgramItemLinks = arrCandidates
    1022    end if
    1023 end function
    1024 
    1025 
    1026 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1027 '  Helpers: Messaging and Output                                                                                                 '
    1028 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1029 
    1030 ''
    1031 ' Append text to the log file and echo it to stdout
    1032 sub Print(str)
    1033    LogPrint str
    1034    Wscript.Echo str
    1035 end sub
    1036 
    1037 
    1038 ''
    1039 ' Prints a test header
    1040 sub PrintHdr(strTest)
    1041    LogPrint "***** Checking for " & strTest & " *****"
    1042    Wscript.Echo "Checking for " & StrTest & "..."
    1043 end sub
    1044 
    1045 
    1046 ''
    1047 ' Prints a success message
    1048 sub PrintResultMsg(strTest, strResult)
    1049    dim cchPad
    1050    LogPrint "** " & strTest & ": " & strResult
    1051    Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPad & strResult
    1052 end sub
    1053 
    1054 
    1055 ''
    1056 ' Prints a successfully detected path
    1057 sub PrintResult(strTest, strPath)
    1058    strLongPath = PathAbsLong(strPath)
    1059    if PathAbs(strPath) <> strLongPath then
    1060       LogPrint         "** " & strTest & ": " & strPath & " (" & UnixSlashes(strLongPath) & ")"
    1061       Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPath & " (" & UnixSlashes(strLongPath) & ")"
    1062    else
    1063       LogPrint         "** " & strTest & ": " & strPath
    1064       Wscript.Echo " Found " & RightPad(strTest & ": ", 22) & strPath
    1065    end if
    1066 end sub
    1067 
    1068 
    1069 ''
    1070 ' Warning message.
    1071 sub MsgWarning(strMsg)
    1072    Print "warning: " & strMsg
    1073 end sub
    1074 
    1075 
    1076 ''
    1077 ' Fatal error.
    1078 sub MsgFatal(strMsg)
    1079    Print "fatal error: " & strMsg
    1080    Wscript.Quit(1)
    1081 end sub
    1082 
    1083 
    1084 ''
    1085 ' Error message, fatal unless flag to ignore errors is given.
    1086 sub MsgError(strMsg)
    1087    Print "error: " & strMsg
    1088    if g_blnContinueOnError = False then
    1089       Wscript.Quit(1)
    1090    end if
    1091    g_rcScript = 1
    1092 end sub
    1093105
    1094106
     
    1173185' If no file is found, log the failure.
    1174186function LogFindFile(strPath, strPattern)
    1175    dim str
     187   dim str, strOutput
    1176188
    1177189   '
     
    1180192   ' too much hassle. So, we'll do it the unix way...
    1181193   '
    1182    if Shell("dir /B """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True) = 0 _
    1183     And InStr(1, g_strShellOutput, Chr(13)) > 1 _
     194   if Shell("dir /B """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True, strOutput) = 0 _
     195    And InStr(1, strOutput, Chr(13)) > 1 _
    1184196      then
    1185197      ' return the first word.
    1186       LogFindFile = Left(g_strShellOutput, InStr(1, g_strShellOutput, Chr(13)) - 1)
     198      LogFindFile = Left(strOutput, InStr(1, strOutput, Chr(13)) - 1)
    1187199   else
    1188200      LogPrint "Testing '" & strPath & "': " & strPattern & " not found"
     
    1197209' else return the complete path to the found directory.
    1198210function LogFindDir(strPath, strPattern)
    1199    dim str
     211   dim str, strOutput
    1200212
    1201213   '
     
    1206218
    1207219   ' List the alphabetically last names as first entries (with /O-N).
    1208    if Shell("dir /B /AD /O-N """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True) = 0 _
    1209     And InStr(1, g_strShellOutput, Chr(13)) > 1 _
     220   if Shell("dir /B /AD /O-N """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True, strOutput) = 0 _
     221    And InStr(1, strOutput, Chr(13)) > 1 _
    1210222      then
    1211223      ' return the first word.
    1212       LogFindDir = strPath & "/" & Left(g_strShellOutput, InStr(1, g_strShellOutput, Chr(13)) - 1)
     224      LogFindDir = strPath & "/" & Left(strOutput, InStr(1, strOutput, Chr(13)) - 1)
    1213225   else
    1214226      LogPrint "Testing '" & strPath & "': " & strPattern & " not found"
     
    1217229end function
    1218230
     231
     232''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     233'  Helpers: Configuration and Batch Script Writers                                                                               '
     234''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1219235
    1220236''
     
    1311327   ' Do the setting.
    1312328   FileAppendLine g_strEnvFile, "set " & strEnv & "=%" & strEnv & "%" & strSep & strValue
    1313 end sub
    1314 
    1315 
    1316 ''
    1317 ' Self test for some of the above routines.
    1318 '
    1319 sub SelfTest
    1320    dim i, str
    1321    str = "0123456789"
    1322    for i = 1 to Len(str)
    1323       if CharIsDigit(Mid(str, i, 1)) <> True then MsgFatal "SelfTest failed: CharIsDigit("&Mid(str, i, 1)&")"
    1324    next
    1325    str = "abcdefghijklmnopqrstuvwxyz~`!@#$%^&*()_+-=ABCDEFGHIJKLMNOPQRSTUVWXYZ/\[]{}"
    1326    for i = 1 to Len(str)
    1327       if CharIsDigit(Mid(str, i, 1)) <> False then MsgFatal "SelfTest failed: CharIsDigit("&Mid(str, i, 1)&")"
    1328    next
    1329    if StrVersionCompare("1234", "1234") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #1"
    1330    if StrVersionCompare("1", "1") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #2"
    1331    if StrVersionCompare("2", "1") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #3"
    1332    if StrVersionCompare("1", "2") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #4"
    1333    if StrVersionCompare("01", "1") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #5"
    1334    if StrVersionCompare("01", "001") <> 0 then MsgFatal "SelfTest failed: StrVersionCompare #6"
    1335    if StrVersionCompare("12", "123") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #7"
    1336    if StrVersionCompare("v123", "123") <= 0 then MsgFatal "SelfTest failed: StrVersionCompare #8"
    1337    if StrVersionCompare("v1.2.3", "v1.3.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #9"
    1338    if StrVersionCompare("v1.02.3", "v1.3.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #10"
    1339    if StrVersionCompare("v1.2.3", "v1.03.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #11"
    1340    if StrVersionCompare("v1.2.4", "v1.23.4") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #12"
    1341    if StrVersionCompare("v10.0.17163", "v10.00.18363") >= 0 then MsgFatal "SelfTest failed: StrVersionCompare #13"
    1342329end sub
    1343330
     
    1420407'
    1421408sub CheckForkBuild(strOptkBuild)
     409   dim blnNeedEnvVars, strOutput
    1422410   PrintHdr "kBuild"
    1423411
     
    1432420    And (EnvGetFirst("KBUILD_PATH", "PATH_KBUILD") = "") _
    1433421    And (EnvGetFirst("KBUILD_BIN_PATH", "PATH_KBUILD_BIN") = "") _
    1434     And (Shell("kmk.exe --version", True) = 0) _
    1435     And (InStr(1,g_strShellOutput, "kBuild Make 0.1") > 0) _
    1436     And (InStr(1,g_strShellOutput, "KBUILD_PATH") > 0) _
    1437     And (InStr(1,g_strShellOutput, "KBUILD_BIN_PATH") > 0) then
     422    And (Shell("kmk.exe --version", True, strOutput) = 0) _
     423    And (InStr(1,strOutput, "kBuild Make 0.1") > 0) _
     424    And (InStr(1,strOutput, "KBUILD_PATH") > 0) _
     425    And (InStr(1,strOutput, "KBUILD_BIN_PATH") > 0) then
    1438426      '' @todo Need to parse out the KBUILD_PATH and KBUILD_BIN_PATH values to complete the other tests.
    1439427      'blnNeedEnvVars = False
     
    1586574   end if
    1587575
    1588    if (Shell(DosSlashes(g_strPathkBuildBin & "/kmk.exe") & " --version", True) <> 0) then
     576   if (Shell(DosSlashes(g_strPathkBuildBin & "/kmk.exe") & " --version", True, strOutput) <> 0) then
    1589577      MsgFatal "Can't execute '" & g_strPathkBuildBin & "/kmk.exe --version'. check configure.log for the out."
    1590578      exit sub
     
    1656644   public function checkClExe(strClExe)
    1657645      ' We'll have to make sure mspdbXX.dll is somewhere in the PATH.
    1658       dim strSavedPath, rcExit
     646      dim strSavedPath, rcExit, strOutput
    1659647
    1660648      strSavedPath = EnvGet("PATH")
     
    1662650         EnvAppend "PATH", ";" & m_strPathVCCommon & "/IDE"
    1663651      end if
    1664       rcExit = Shell(DosSlashes(strClExe), True)
     652      rcExit = Shell(DosSlashes(strClExe), True, strOutput)
    1665653      EnvSet "PATH", strSavedPath
    1666654
     
    1670658         dim offVer, offEol, strVer
    1671659         strVer = ""
    1672          offVer = InStr(1, g_strShellOutput, " Version ")
     660         offVer = InStr(1, strOutput, " Version ")
    1673661         if offVer > 0 then
    1674662            offVer = offVer + Len(" Version ")
    1675             offEol = InStr(offVer, g_strShellOutput, Chr(13))
     663            offEol = InStr(offVer, strOutput, Chr(13))
    1676664            if offEol > 0 then
    1677                strVer = Trim(Mid(g_strShellOutput, offVer, offEol - offVer))
     665               strVer = Trim(Mid(strOutput, offVer, offEol - offVer))
    1678666            end if
    1679667         end if
     
    1988976'' Checks if the specified path points to a usable PSDK.
    1989977function CheckForPlatformSDKSub(strPathPSDK)
     978   dim strOutput
    1990979   CheckForPlatformSDKSub = False
    1991980   LogPrint "trying: strPathPSDK=" & strPathPSDK
     
    1994983    And  LogFileExists(strPathPSDK, "lib/User32.Lib") _
    1995984    And  LogFileExists(strPathPSDK, "bin/rc.exe") _
    1996     And  Shell("""" & DosSlashes(strPathPSDK & "/bin/rc.exe") & """" , True) <> 0 _
     985    And  Shell("""" & DosSlashes(strPathPSDK & "/bin/rc.exe") & """" , True, strOutput) <> 0 _
    1997986      then
    1998       if InStr(1, g_strShellOutput, "Resource Compiler Version 6.2.") > 0 then
     987      if InStr(1, strOutput, "Resource Compiler Version 6.2.") > 0 then
    1999988         g_strVerPSDK = "80"
    2000989         CheckForPlatformSDKSub = True
    2001       elseif InStr(1, g_strShellOutput, "Resource Compiler Version 6.1.") > 0 then
     990      elseif InStr(1, strOutput, "Resource Compiler Version 6.1.") > 0 then
    2002991         g_strVerPSDK = "71"
    2003992         CheckForPlatformSDKSub = True
     
    21951184'' Quick check if the DDK is in the specified directory or not.
    21961185function CheckForWinDDKSub(strPathDDK, blnCheckBuild)
     1186   dim strOutput
    21971187   CheckForWinDDKSub = False
    21981188   LogPrint "trying: strPathDDK=" & strPathDDK & " blnCheckBuild=" & blnCheckBuild
     
    22081198         CheckForWinDDKSub = True
    22091199      '' @todo Find better build check.
    2210       elseif Shell("""" & DosSlashes(strPathDDK & "/bin/x86/rc.exe") & """" , True) <> 0 _
    2211          And InStr(1, g_strShellOutput, "Resource Compiler Version 6.1.") > 0 then
     1200      elseif Shell("""" & DosSlashes(strPathDDK & "/bin/x86/rc.exe") & """" , True, strOutput) <> 0 _
     1201         And InStr(1, strOutput, "Resource Compiler Version 6.1.") > 0 then
    22121202         CheckForWinDDKSub = True
    22131203      end if
     
    28801870'
    28811871function Main
     1872   dim strOutput
     1873
    28821874   '
    28831875   ' Write the log header and check that we're not using wscript.
     
    30252017   '
    30262018   g_objShell.Environment("PROCESS")("TESTING_ENVIRONMENT_INHERITANCE") = "This works"
    3027    if Shell("set TESTING_ENVIRONMENT_INHERITANC", False) <> 0 then ' The 'E' is missing on purpose (4nt).
     2019   if Shell("set TESTING_ENVIRONMENT_INHERITANC", False, strOutput) <> 0 then ' The 'E' is missing on purpose (4nt).
    30282020      MsgFatal "shell execution test failed!"
    30292021   end if
    3030    if g_strShellOutput <> "TESTING_ENVIRONMENT_INHERITANCE=This works" & CHR(13) & CHR(10)  then
    3031       Print "Shell test Test -> '" & g_strShellOutput & "'"
     2022   if strOutput <> "TESTING_ENVIRONMENT_INHERITANCE=This works" & CHR(13) & CHR(10)  then
     2023      Print "Shell test Test -> '" & strOutput & "'"
    30322024      MsgFatal "shell inheritance or shell execution isn't working right. Make sure you use cmd.exe."
    30332025   end if
     
    30392031   '
    30402032   if blnOptDisableCOM = True then
    3041       DisableCOM "--disable-com"
     2033      DisableCOM        "--disable-com"
    30422034   end if
    30432035   if blnOptDisableUDPTunnel = True then
    3044       DisableUDPTunnel "--disable-udptunnel"
     2036      DisableUDPTunnel  "--disable-udptunnel"
    30452037   end if
    30462038   CheckSourcePath
     
    30522044   CheckForMidl         strOptMidl
    30532045   CheckForOpenWatcom   strOptOpenWatcom
     2046   if blnOptDisableSDL = True then
     2047      DisableSDL "--disable-sdl"
     2048   else
     2049      CheckForlibSDL    strOptlibSDL
     2050   end if
     2051   CheckForXml2         strOptXml2
     2052   CheckForSsl          strOptSsl, False
     2053   if g_strTargetArch = "amd64" then
     2054       ' 32-bit openssl required as well
     2055      CheckForSsl       strOptSsl32, True
     2056   end if
     2057   CheckForCurl         strOptCurl, False
     2058   if g_strTargetArch = "amd64" then
     2059       ' 32-bit Curl required as well
     2060      CheckForCurl      strOptCurl32, True
     2061   end if
     2062   CheckForQt           strOptQt5, strOptQt5Infix
     2063   CheckForPython       strOptPython
     2064
    30542065   CfgPrintAssign "VBOX_WITH_LIBVPX",  "" '' @todo look for libvpx 1.1.0+
    30552066   CfgPrintAssign "VBOX_WITH_LIBOPUS", "" '' @todo look for libopus 1.2.1+
    3056 
    3057    EnvPrintAppend "PATH", DosSlashes(g_strPath & "\tools\win." & g_strHostArch & "\bin"), ";" '' @todo look for yasm
     2067                                          '' @todo look for yasm
     2068   EnvPrintAppend "PATH", DosSlashes(g_strPath & "\tools\win." & g_strHostArch & "\bin"), ";"
    30582069   if g_strHostArch = "amd64" then
    30592070      EnvPrintAppend "PATH", DosSlashes(g_strPath & "\tools\win.x86\bin"), ";"
     
    30612072      EnvPrintCleanup "PATH", DosSlashes(g_strPath & "\tools\win.amd64\bin"), ";"
    30622073   end if
    3063    if blnOptDisableSDL = True then
    3064       DisableSDL "--disable-sdl"
    3065    else
    3066       CheckForlibSDL    strOptlibSDL
    3067    end if
    3068    CheckForXml2         strOptXml2
    3069    CheckForSsl          strOptSsl, False
    3070    if g_strTargetArch = "amd64" then
    3071        ' 32-bit openssl required as well
    3072        CheckForSsl      strOptSsl32, True
    3073    end if
    3074    CheckForCurl         strOptCurl, False
    3075    if g_strTargetArch = "amd64" then
    3076        ' 32-bit Curl required as well
    3077        CheckForCurl     strOptCurl32, True
    3078    end if
    3079    CheckForQt           strOptQt5, strOptQt5Infix
    3080    CheckForPython       strOptPython
    30812074
    30822075   Print ""
  • trunk/tools/win/vbscript/helpers.vbs

    r85807 r85809  
    11' $Id$
    22'' @file
    3 ' The purpose of this script is to check for all external tools, headers, and
    4 ' libraries VBox OSE depends on.
     3' Common VBScript helpers used by configure.vbs and later others.
    54'
    6 ' The script generates the build configuration file 'AutoConfig.kmk' and the
    7 ' environment setup script 'env.bat'. A log of what has been done is
    8 ' written to 'configure.log'.
     5' Requires the script including it to define a LogPrint function.
    96'
    107
     
    2219
    2320
    24 '*****************************************************************************
    25 '* Global Variables                                                          *
    26 '*****************************************************************************
    27 dim g_strPath, g_strEnvFile, g_strLogFile, g_strCfgFile, g_strShellOutput
    28 g_strPath = Left(Wscript.ScriptFullName, Len(Wscript.ScriptFullName) - Len("\configure.vbs"))
    29 g_strEnvFile = g_strPath & "\env.bat"
    30 g_strCfgFile = g_strPath & "\AutoConfig.kmk"
    31 g_strLogFile = g_strPath & "\configure.log"
    32 'g_strTmpFile = g_strPath & "\configure.tmp"
    33 
    34 dim g_objShell, g_objFileSys
    35 Set g_objShell = WScript.CreateObject("WScript.Shell")
     21''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     22'  Global Variables                                                                                                              '
     23''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
     24dim g_objShell
     25Set g_objShell   = WScript.CreateObject("WScript.Shell")
     26
     27dim g_objFileSys
    3628Set g_objFileSys = WScript.CreateObject("Scripting.FileSystemObject")
    37 
    38 ' kBuild stuff.
    39 dim g_strPathkBuild, g_strPathkBuildBin, g_strPathDev
    40 g_strPathkBuild = ""
    41 g_strPathkBuildBin = ""
    42 g_strPathDev = ""
    43 
    44 dim g_strTargetArch, g_StrTargetArchWin
    45 g_strTargetArch = ""
    46 g_StrTargetArchWin = ""
    47 
    48 dim g_strHostArch, g_strHostArchWin
    49 g_strHostArch = ""
    50 g_strHostArchWin = ""
    51 
    52 ' Visual C++ info.
    53 dim g_strPathVCC, g_strVCCVersion
    54 g_strPathVCC = ""
    55 g_strVCCVersion = ""
    56 
    57 ' SDK and DDK.
    58 dim g_strPathSDK10, g_strPathPSDK, g_strVerPSDK, g_strPathDDK
    59 g_strPathSDK10 = ""
    60 g_strPathPSDK = ""
    61 g_strVerPSDK = ""
    62 g_strPathDDK = ""
    63 
    64 ' COM disabling.
    65 dim g_blnDisableCOM, g_strDisableCOM
    66 g_blnDisableCOM = False
    67 g_strDisableCOM = ""
    68 
    69 ' Whether to ignore (continue) on errors.
    70 dim g_blnContinueOnError, g_rcExit
    71 g_blnContinueOnError = False
    72 
    73 ' The script's exit code (for ignored errors).
    74 dim g_rcScript
    75 g_rcScript = 0
    76 
    77 ' Whether to try the internal stuff first or last.
    78 dim g_blnInternalFirst
    79 g_blnInternalFirst = True
    80 
    81 ' List of program files locations.
    82 dim g_arrProgramFiles
    83 if EnvGet("ProgramFiles(x86)") <> "" then
    84    g_arrProgramFiles = Array(EnvGet("ProgramFiles"), EnvGet("ProgramFiles(x86)"))
    85 else
    86    g_arrProgramFiles = Array(EnvGet("ProgramFiles"))
    87 end if
    8829
    8930
     
    365306
    366307''
    367 ' Executes a command in the shell catching output in g_strShellOutput
    368 function Shell(strCommand, blnBoth)
     308' Executes a command in the shell catching output in strOutput
     309function Shell(strCommand, blnBoth, ByRef strOutput)
    369310   dim strShell, strCmdline, objExec, str
    370311
     
    378319   LogPrint "# Shell: " & strCmdline
    379320   Set objExec = g_objShell.Exec(strCmdLine)
    380    g_strShellOutput = objExec.StdOut.ReadAll()
     321   strOutput = objExec.StdOut.ReadAll()
    381322   objExec.StdErr.ReadAll()
    382323   do while objExec.Status = 0
    383324      Wscript.Sleep 20
    384       g_strShellOutput = g_strShellOutput & objExec.StdOut.ReadAll()
     325      strOutput = strOutput & objExec.StdOut.ReadAll()
    385326      objExec.StdErr.ReadAll()
    386327   loop
     
    388329   LogPrint "# Status: " & objExec.ExitCode
    389330   LogPrint "# Start of Output"
    390    LogPrint g_strShellOutput
     331   LogPrint strOutput
    391332   LogPrint "# End of Output"
    392333
     
    10941035
    10951036''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1096 '  Helpers: Logging and Logged operations                                                                                        '
    1097 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1098 
    1099 ''
    1100 ' Write a log header with some basic info.
    1101 sub LogInit
    1102    FileDelete g_strLogFile
    1103    LogPrint "# Log file generated by " & Wscript.ScriptFullName
    1104    for i = 1 to WScript.Arguments.Count
    1105       LogPrint "# Arg #" & i & ": " & WScript.Arguments.Item(i - 1)
    1106    next
    1107    if Wscript.Arguments.Count = 0 then
    1108       LogPrint "# No arguments given"
    1109    end if
    1110    LogPrint "# Reconstructed command line: " & GetCommandline()
    1111 
    1112    ' some Wscript stuff
    1113    LogPrint "# Wscript properties:"
    1114    LogPrint "#   ScriptName: " & Wscript.ScriptName
    1115    LogPrint "#   Version:    " & Wscript.Version
    1116    LogPrint "#   Build:      " & Wscript.BuildVersion
    1117    LogPrint "#   Name:       " & Wscript.Name
    1118    LogPrint "#   Full Name:  " & Wscript.FullName
    1119    LogPrint "#   Path:       " & Wscript.Path
    1120    LogPrint "#"
    1121 
    1122 
    1123    ' the environment
    1124    LogPrint "# Environment:"
    1125    dim objEnv
    1126    for each strVar in g_objShell.Environment("PROCESS")
    1127       LogPrint "#   " & strVar
    1128    next
    1129    LogPrint "#"
    1130 end sub
    1131 
    1132 
    1133 ''
    1134 ' Append text to the log file.
    1135 sub LogPrint(str)
    1136    FileAppendLine g_strLogFile, str
    1137    'Wscript.Echo "dbg: " & str
    1138 end sub
    1139 
    1140 
    1141 ''
    1142 ' Checks if the file exists and logs failures.
    1143 function LogFileExists(strPath, strFilename)
    1144    LogFileExists = FileExists(strPath & "/" & strFilename)
    1145    if LogFileExists = False then
    1146       LogPrint "Testing '" & strPath & "': " & strFilename & " not found"
    1147    end if
    1148 end function
    1149 
    1150 
    1151 ''
    1152 ' Checks if the file exists and logs failures.
    1153 function LogFileExists1(strPath)
    1154    LogFileExists1 = FileExists(strPath)
    1155    if LogFileExists1 = False then
    1156       LogPrint "Testing '" & strPath & "': file not found"
    1157    end if
    1158 end function
    1159 
    1160 
    1161 ''
    1162 ' Checks if the directory exists and logs failures.
    1163 function LogDirExists(strPath)
    1164    LogDirExists = DirExists(strPath)
    1165    if LogDirExists = False then
    1166       LogPrint "Testing '" & strPath & "': not found (or not dir)"
    1167    end if
    1168 end function
    1169 
    1170 
    1171 ''
    1172 ' Finds the first file matching the pattern.
    1173 ' If no file is found, log the failure.
    1174 function LogFindFile(strPath, strPattern)
    1175    dim str
    1176 
    1177    '
    1178    ' Yes, there are some facy database kinda interface to the filesystem
    1179    ' however, breaking down the path and constructing a usable query is
    1180    ' too much hassle. So, we'll do it the unix way...
    1181    '
    1182    if Shell("dir /B """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True) = 0 _
    1183     And InStr(1, g_strShellOutput, Chr(13)) > 1 _
    1184       then
    1185       ' return the first word.
    1186       LogFindFile = Left(g_strShellOutput, InStr(1, g_strShellOutput, Chr(13)) - 1)
    1187    else
    1188       LogPrint "Testing '" & strPath & "': " & strPattern & " not found"
    1189       LogFindFile = ""
    1190    end if
    1191 end function
    1192 
    1193 
    1194 ''
    1195 ' Finds the first directory matching the pattern.
    1196 ' If no directory is found, log the failure,
    1197 ' else return the complete path to the found directory.
    1198 function LogFindDir(strPath, strPattern)
    1199    dim str
    1200 
    1201    '
    1202    ' Yes, there are some facy database kinda interface to the filesystem
    1203    ' however, breaking down the path and constructing a usable query is
    1204    ' too much hassle. So, we'll do it the unix way...
    1205    '
    1206 
    1207    ' List the alphabetically last names as first entries (with /O-N).
    1208    if Shell("dir /B /AD /O-N """ & DosSlashes(strPath) & "\" & DosSlashes(strPattern) & """", True) = 0 _
    1209     And InStr(1, g_strShellOutput, Chr(13)) > 1 _
    1210       then
    1211       ' return the first word.
    1212       LogFindDir = strPath & "/" & Left(g_strShellOutput, InStr(1, g_strShellOutput, Chr(13)) - 1)
    1213    else
    1214       LogPrint "Testing '" & strPath & "': " & strPattern & " not found"
    1215       LogFindDir = ""
    1216    end if
    1217 end function
    1218 
    1219 
    1220 ''
    1221 ' Initializes the config file.
    1222 sub CfgInit
    1223    FileDelete g_strCfgFile
    1224    CfgPrint "# -*- Makefile -*-"
    1225    CfgPrint "#"
    1226    CfgPrint "# Build configuration generated by " & GetCommandline()
    1227    CfgPrint "#"
    1228    CfgPrint "VBOX_OSE := 1"
    1229    CfgPrint "VBOX_VCC_WERR = $(NO_SUCH_VARIABLE)"
    1230 end sub
    1231 
    1232 
    1233 ''
    1234 ' Prints a string to the config file.
    1235 sub CfgPrint(str)
    1236    FileAppendLine g_strCfgFile, str
    1237 end sub
    1238 
    1239 ''
    1240 ' Prints a string to the config file.
    1241 sub CfgPrintAssign(strVar, strValue)
    1242    if strValue = "" then
    1243       FileAppendLine g_strCfgFile, RightPad(strVar, 17) & " :="
    1244    else
    1245       FileAppendLine g_strCfgFile, RightPad(strVar, 17) & " := " & strValue
    1246    end if
    1247 end sub
    1248 
    1249 
    1250 ''
    1251 ' Initializes the environment batch script.
    1252 sub EnvInit
    1253    FileDelete g_strEnvFile
    1254    EnvPrint "@echo off"
    1255    EnvPrint "rem"
    1256    EnvPrint "rem Environment setup script generated by " & GetCommandline()
    1257    EnvPrint "rem"
    1258 end sub
    1259 
    1260 
    1261 ''
    1262 ' Prints a string to the environment batch script.
    1263 sub EnvPrint(str)
    1264    FileAppendLine g_strEnvFile, str
    1265 end sub
    1266 
    1267 
    1268 ''
    1269 ' Helper for EnvPrintPrepend and EnvPrintAppend.
    1270 sub EnvPrintCleanup(strEnv, strValue, strSep)
    1271    dim cchValueAndSep
    1272    FileAppendLine g_strEnvFile, "set " & strEnv & "=%" & strEnv & ":" & strSep & strValue & strSep & "=" & strSep & "%"
    1273    cchValueAndSep = Len(strValue) + Len(strSep)
    1274    FileAppendLine g_strEnvFile, "if ""%" & strEnv & "%""==""" & strValue & """ set " & strEnv & "="
    1275    FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~0," & cchValueAndSep & "%""==""" & strValue & strSep & """ set " & strEnv & "=%" & strEnv & ":~" & cchValueAndSep & "%"
    1276    FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~-"  & cchValueAndSep & "%""==""" & strSep & strValue & """  set " & strEnv & "=%" & strEnv & ":~0,-" & cchValueAndSep & "%"
    1277 end sub
    1278 
    1279 
    1280 '' Use by EnvPrintPrepend to skip ';' stripping.
    1281 dim g_strPrependCleanEnvVars
    1282 
    1283 ''
    1284 ' Print a statement prepending strValue to strEnv, removing duplicate values.
    1285 sub EnvPrintPrepend(strEnv, strValue, strSep)
    1286    ' Remove old values and any leading separators.
    1287    EnvPrintCleanup strEnv, strValue, strSep
    1288    if InStr(1, g_strPrependCleanEnvVars, "|" & strEnv & "|") = 0 then
    1289       FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~0,1%""==""" & strSep & """ set " & strEnv & "=%" & strEnv & ":~1%"
    1290       FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~0,1%""==""" & strSep & """ set " & strEnv & "=%" & strEnv & ":~1%"
    1291       g_strPrependCleanEnvVars = g_strPrependCleanEnvVars & "|" & strEnv & "|"
    1292    end if
    1293    ' Do the setting
    1294    FileAppendLine g_strEnvFile, "set " & strEnv & "=" & strValue & strSep & "%" & strEnv & "%"
    1295 end sub
    1296 
    1297 
    1298 '' Use by EnvPrintPrepend to skip ';' stripping.
    1299 dim g_strAppendCleanEnvVars
    1300 
    1301 ''
    1302 ' Print a statement appending strValue to strEnv, removing duplicate values.
    1303 sub EnvPrintAppend(strEnv, strValue, strSep)
    1304    ' Remove old values and any trailing separators.
    1305    EnvPrintCleanup strEnv, strValue, strSep
    1306    if InStr(1, g_strAppendCleanEnvVars, "|" & strEnv & "|") = 0 then
    1307       FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~-1%""==""" & strSep & """ set " & strEnv & "=%" & strEnv & ":~0,-1%"
    1308       FileAppendLine g_strEnvFile, "if ""%" & strEnv & ":~-1%""==""" & strSep & """ set " & strEnv & "=%" & strEnv & ":~0,-1%"
    1309       g_strAppendCleanEnvVars = g_strAppendCleanEnvVars & "|" & strEnv & "|"
    1310    end if
    1311    ' Do the setting.
    1312    FileAppendLine g_strEnvFile, "set " & strEnv & "=%" & strEnv & "%" & strSep & strValue
    1313 end sub
    1314 
     1037'  Testcases                                                                                                                     '
     1038''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    13151039
    13161040''
     
    13421066end sub
    13431067
    1344 
    1345 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1346 '  Feature disabling                                                                                                             '
    1347 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1348 
    1349 ''
    1350 ' No COM
    1351 sub DisableCOM(strReason)
    1352    if g_blnDisableCOM = False then
    1353       LogPrint "Disabled COM components: " & strReason
    1354       g_blnDisableCOM = True
    1355       g_strDisableCOM = strReason
    1356       CfgPrintAssign "VBOX_WITH_MAIN", ""
    1357       CfgPrintAssign "VBOX_WITH_QTGUI", ""
    1358       CfgPrintAssign "VBOX_WITH_VBOXSDL", ""
    1359       CfgPrintAssign "VBOX_WITH_DEBUGGER_GUI", ""
    1360    end if
    1361 end sub
    1362 
    1363 
    1364 ''
    1365 ' No UDPTunnel
    1366 sub DisableUDPTunnel(strReason)
    1367    if g_blnDisableUDPTunnel = False then
    1368       LogPrint "Disabled UDPTunnel network transport: " & strReason
    1369       g_blnDisableUDPTunnel = True
    1370       g_strDisableUDPTunnel = strReason
    1371       CfgPrintAssign "VBOX_WITH_UDPTUNNEL", ""
    1372    end if
    1373 end sub
    1374 
    1375 
    1376 ''
    1377 ' No SDL
    1378 sub DisableSDL(strReason)
    1379    if g_blnDisableSDL = False then
    1380       LogPrint "Disabled SDL frontend: " & strReason
    1381       g_blnDisableSDL = True
    1382       g_strDisableSDL = strReason
    1383       CfgPrintAssign "VBOX_WITH_VBOXSDL", ""
    1384    end if
    1385 end sub
    1386 
    1387 
    1388 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1389 '  Tool/Library Locating and Checking                                                                                            '
    1390 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    1391 
    1392 ''
    1393 ' Checks the the path doesn't contain characters the tools cannot deal with.
    1394 '
    1395 sub CheckSourcePath
    1396    dim sPwd
    1397 
    1398    sPwd = PathAbsLong(g_strPath)    ' Must check the long version.
    1399    if InStr(1, sPwd, " ") > 0 then
    1400       MsgError "Source path contains spaces! Please move it. (" & sPwd & ")"
    1401    end if
    1402    if InStr(1, sPwd, "$") > 0 then
    1403       MsgError "Source path contains the '$' char! Please move it. (" & sPwd & ")"
    1404    end if
    1405    if InStr(1, sPwd, "%") > 0 then
    1406       MsgError "Source path contains the '%' char! Please move it. (" & sPwd & ")"
    1407    end if
    1408    if  InStr(1, sPwd, Chr(10)) > 0 _
    1409     or InStr(1, sPwd, Chr(13)) > 0 _
    1410     or InStr(1, sPwd, Chr(9)) > 0 _
    1411    then
    1412       MsgError "Source path contains control characters! Please move it. (" & sPwd & ")"
    1413    end if
    1414    Print "Source path: OK"
    1415 end sub
    1416 
    1417 
    1418 ''
    1419 ' Checks for kBuild - very simple :)
    1420 '
    1421 sub CheckForkBuild(strOptkBuild)
    1422    PrintHdr "kBuild"
    1423 
    1424    '
    1425    ' Check if there is a 'kmk' in the path somewhere without
    1426    ' any KBUILD_*PATH stuff around.
    1427    '
    1428    blnNeedEnvVars = True
    1429    g_strPathkBuild = strOptkBuild
    1430    g_strPathkBuildBin = ""
    1431    if   (g_strPathkBuild = "") _
    1432     And (EnvGetFirst("KBUILD_PATH", "PATH_KBUILD") = "") _
    1433     And (EnvGetFirst("KBUILD_BIN_PATH", "PATH_KBUILD_BIN") = "") _
    1434     And (Shell("kmk.exe --version", True) = 0) _
    1435     And (InStr(1,g_strShellOutput, "kBuild Make 0.1") > 0) _
    1436     And (InStr(1,g_strShellOutput, "KBUILD_PATH") > 0) _
    1437     And (InStr(1,g_strShellOutput, "KBUILD_BIN_PATH") > 0) then
    1438       '' @todo Need to parse out the KBUILD_PATH and KBUILD_BIN_PATH values to complete the other tests.
    1439       'blnNeedEnvVars = False
    1440       MsgWarning "You've installed kBuild it seems. configure.vbs hasn't been updated to " _
    1441          & "deal with that yet and will use the one it ships with. Sorry."
    1442    end if
    1443 
    1444    '
    1445    ' Check for the KBUILD_PATH env.var. and fall back on root/kBuild otherwise.
    1446    '
    1447    if g_strPathkBuild = "" then
    1448       g_strPathkBuild = EnvGetFirst("KBUILD_PATH", "PATH_KBUILD")
    1449       if (g_strPathkBuild <> "") and (FileExists(g_strPathkBuild & "/footer.kmk") = False) then
    1450          MsgWarning "Ignoring incorrect kBuild path (KBUILD_PATH=" & g_strPathkBuild & ")"
    1451          g_strPathkBuild = ""
    1452       end if
    1453 
    1454       if g_strPathkBuild = "" then
    1455          g_strPathkBuild = g_strPath & "/kBuild"
    1456       end if
    1457    end if
    1458 
    1459    g_strPathkBuild = UnixSlashes(PathAbs(g_strPathkBuild))
    1460 
    1461    '
    1462    ' Check for env.vars that kBuild uses (do this early to set g_strTargetArch).
    1463    '
    1464    str = EnvGetFirst("KBUILD_TYPE", "BUILD_TYPE")
    1465    if   (str <> "") _
    1466     And (InStr(1, "|release|debug|profile|kprofile", str) <= 0) then
    1467       EnvPrint "set KBUILD_TYPE=release"
    1468       EnvSet "KBUILD_TYPE", "release"
    1469       MsgWarning "Found unknown KBUILD_TYPE value '" & str &"' in your environment. Setting it to 'release'."
    1470    end if
    1471 
    1472    str = EnvGetFirst("KBUILD_TARGET", "BUILD_TARGET")
    1473    if   (str <> "") _
    1474     And (InStr(1, "win|win32|win64", str) <= 0) then '' @todo later only 'win' will be valid. remember to fix this check!
    1475       EnvPrint "set KBUILD_TARGET=win"
    1476       EnvSet "KBUILD_TARGET", "win"
    1477       MsgWarning "Found unknown KBUILD_TARGET value '" & str &"' in your environment. Setting it to 'win32'."
    1478    end if
    1479 
    1480    str = EnvGetFirst("KBUILD_TARGET_ARCH", "BUILD_TARGET_ARCH")
    1481    if   (str <> "") _
    1482     And (InStr(1, "x86|amd64", str) <= 0) then
    1483       EnvPrint "set KBUILD_TARGET_ARCH=x86"
    1484       EnvSet "KBUILD_TARGET_ARCH", "x86"
    1485       MsgWarning "Found unknown KBUILD_TARGET_ARCH value '" & str &"' in your environment. Setting it to 'x86'."
    1486       str = "x86"
    1487    end if
    1488    if g_strTargetArch = "" then '' command line parameter --target-arch=x86|amd64 has priority
    1489       if str <> "" then
    1490          g_strTargetArch = str
    1491       elseif (EnvGet("PROCESSOR_ARCHITEW6432") = "AMD64" ) _
    1492           Or (EnvGet("PROCESSOR_ARCHITECTURE") = "AMD64" ) then
    1493          g_strTargetArch = "amd64"
    1494       else
    1495          g_strTargetArch = "x86"
    1496       end if
    1497    else
    1498       if InStr(1, "x86|amd64", g_strTargetArch) <= 0 then
    1499          EnvPrint "set KBUILD_TARGET_ARCH=x86"
    1500          EnvSet "KBUILD_TARGET_ARCH", "x86"
    1501          MsgWarning "Unknown --target-arch=" & str &". Setting it to 'x86'."
    1502       end if
    1503    end if
    1504    LogPrint " Target architecture: " & g_strTargetArch & "."
    1505    Wscript.Echo " Target architecture: " & g_strTargetArch & "."
    1506    EnvPrint "set KBUILD_TARGET_ARCH=" & g_strTargetArch
    1507 
    1508    ' Windows variant of the arch name.
    1509    g_strTargetArchWin = g_strTargetArch
    1510    if g_strTargetArchWin = "amd64" then g_strTargetArchWin = "x64"
    1511 
    1512    str = EnvGetFirst("KBUILD_TARGET_CPU", "BUILD_TARGET_CPU")
    1513     ' perhaps a bit pedantic this since this isn't clearly define nor used much...
    1514    if   (str <> "") _
    1515     And (InStr(1, "i386|i486|i686|i786|i868|k5|k6|k7|k8", str) <= 0) then
    1516       EnvPrint "set BUILD_TARGET_CPU=i386"
    1517       EnvSet "KBUILD_TARGET_CPU", "i386"
    1518       MsgWarning "Found unknown KBUILD_TARGET_CPU value '" & str &"' in your environment. Setting it to 'i386'."
    1519    end if
    1520 
    1521    str = EnvGetFirst("KBUILD_HOST", "BUILD_PLATFORM")
    1522    if   (str <> "") _
    1523     And (InStr(1, "win|win32|win64", str) <= 0) then '' @todo later only 'win' will be valid. remember to fix this check!
    1524       EnvPrint "set KBUILD_HOST=win"
    1525       EnvSet "KBUILD_HOST", "win"
    1526       MsgWarning "Found unknown KBUILD_HOST value '" & str &"' in your environment. Setting it to 'win32'."
    1527    end if
    1528 
    1529    str = EnvGetFirst("KBUILD_HOST_ARCH", "BUILD_PLATFORM_ARCH")
    1530    if str <> "" then
    1531       if InStr(1, "x86|amd64", str) <= 0 then
    1532          str = "x86"
    1533          MsgWarning "Found unknown KBUILD_HOST_ARCH value '" & str &"' in your environment. Setting it to 'x86'."
    1534       end if
    1535    elseif (EnvGet("PROCESSOR_ARCHITEW6432") = "AMD64" ) _
    1536        Or (EnvGet("PROCESSOR_ARCHITECTURE") = "AMD64" ) then
    1537       str = "amd64"
    1538    else
    1539       str = "x86"
    1540    end if
    1541    LogPrint " Host architecture: " & str & "."
    1542    Wscript.Echo " Host architecture: " & str & "."
    1543    EnvPrint "set KBUILD_HOST_ARCH=" & str
    1544    g_strHostArch = str
    1545 
    1546    ' Windows variant of the arch name.
    1547    g_strHostArchWin = g_strHostArch
    1548    if g_strHostArchWin = "amd64" then g_strHostArchWin = "x64"
    1549 
    1550 
    1551    str = EnvGetFirst("KBUILD_HOST_CPU", "BUILD_PLATFORM_CPU")
    1552     ' perhaps a bit pedantic this since this isn't clearly define nor used much...
    1553    if   (str <> "") _
    1554     And (InStr(1, "i386|i486|i686|i786|i868|k5|k6|k7|k8", str) <= 0) then
    1555       EnvPrint "set KBUILD_HOST_CPU=i386"
    1556       EnvSet "KBUILD_HOST_CPU", "i386"
    1557       MsgWarning "Found unknown KBUILD_HOST_CPU value '" & str &"' in your environment. Setting it to 'i386'."
    1558    end if
    1559 
    1560    '
    1561    ' Determin the location of the kBuild binaries.
    1562    '
    1563    if g_strPathkBuildBin = "" then
    1564       g_strPathkBuildBin = g_strPathkBuild & "/bin/win." & g_strHostArch
    1565       if FileExists(g_strPathkBuildBin & "/kmk.exe") = False then
    1566          g_strPathkBuildBin = g_strPathkBuild & "/bin/win.x86"
    1567       end if
    1568    end if
    1569    g_strPathkBuildBin = UnixSlashes(PathAbs(g_strPathkBuildBin))
    1570 
    1571    '
    1572    ' Perform basic validations of the kBuild installation.
    1573    '
    1574    if  (FileExists(g_strPathkBuild & "/footer.kmk") = False) _
    1575     Or (FileExists(g_strPathkBuild & "/header.kmk") = False) _
    1576     Or (FileExists(g_strPathkBuild & "/rules.kmk") = False) then
    1577       MsgFatal "Can't find valid kBuild at '" & g_strPathkBuild & "'. Either there is an " _
    1578          & "incorrect KBUILD_PATH in the environment or the checkout didn't succeed."
    1579       exit sub
    1580    end if
    1581    if  (FileExists(g_strPathkBuildBin & "/kmk.exe") = False) _
    1582     Or (FileExists(g_strPathkBuildBin & "/kmk_ash.exe") = False) then
    1583       MsgFatal "Can't find valid kBuild binaries at '" & g_strPathkBuildBin & "'. Either there is an " _
    1584          & "incorrect KBUILD_PATH in the environment or the checkout didn't succeed."
    1585       exit sub
    1586    end if
    1587 
    1588    if (Shell(DosSlashes(g_strPathkBuildBin & "/kmk.exe") & " --version", True) <> 0) then
    1589       MsgFatal "Can't execute '" & g_strPathkBuildBin & "/kmk.exe --version'. check configure.log for the out."
    1590       exit sub
    1591    end if
    1592 
    1593    '
    1594    ' If KBUILD_DEVTOOLS is set, check that it's pointing to something useful.
    1595    '
    1596    str = UnixSlashes(EnvGet("KBUILD_DEVTOOLS"))
    1597    g_strPathDev = str
    1598    if   str <> "" _
    1599     and LogDirExists(str & "/bin") _
    1600     and LogDirExists(str & "/win.amd64/bin") _
    1601     and LogDirExists(str & "/win.x86/bin") _
    1602    then
    1603       LogPrint "Found KBUILD_DEVTOOLS='" & str & "'."
    1604    elseif str <> "" then
    1605       MsgWarning "Ignoring bogus KBUILD_DEVTOOLS='" & str &"' in your environment!"
    1606       g_strPathDev = strNew
    1607    end if
    1608    if g_strPathDev = "" then
    1609       g_strPathDev = UnixSlashes(g_strPath & "/tools")
    1610       LogPrint "Using KBUILD_DEVTOOLS='" & g_strPathDev & "'."
    1611       if str <> "" then
    1612          EnvPrint "set KBUILD_DEVTOOLS=" & g_strPathDev
    1613          EnvSet "KBUILD_DEVTOOLS", g_strPathDev
    1614       end if
    1615    end if
    1616 
    1617    '
    1618    ' Write KBUILD_PATH and updated PATH to the environment script if necessary.
    1619    '
    1620    if blnNeedEnvVars = True then
    1621       EnvPrint "set KBUILD_PATH=" & g_strPathkBuild
    1622       EnvSet "KBUILD_PATH", g_strPathkBuild
    1623 
    1624       if Right(g_strPathkBuildBin, 7) = "win.x86" then
    1625          EnvPrintCleanup "PATH", DosSlashes(Left(g_strPathkBuildBin, Len(g_strPathkBuildBin) - 7) & "win.amd64"), ";"
    1626       end if
    1627       if Right(g_strPathkBuildBin, 9) = "win.amd64" then
    1628          EnvPrintCleanup "PATH", DosSlashes(Left(g_strPathkBuildBin, Len(g_strPathkBuildBin) - 9) & "win.x86"), ";"
    1629       end if
    1630       EnvPrintPrepend "PATH", DosSlashes(g_strPathkBuildBin), ";"
    1631       EnvPrepend "PATH", g_strPathkBuildBin & ";"
    1632    end if
    1633 
    1634    PrintResult "kBuild", g_strPathkBuild
    1635    PrintResult "kBuild binaries", g_strPathkBuildBin
    1636 end sub
    1637 
    1638 '' Class we use for detecting VisualC++
    1639 class VisualCPPState
    1640    public m_blnFound
    1641    public m_strPathVC
    1642    public m_strPathVCCommon
    1643    public m_strVersion
    1644    public m_strClVersion
    1645    public m_blnNewLayout
    1646 
    1647    private sub Class_Initialize
    1648       m_blnFound        = False
    1649       m_strPathVC       = ""
    1650       m_strPathVCCommon = ""
    1651       m_strVersion      = ""
    1652       m_strClVersion    = ""
    1653       m_blnNewLayout    = false
    1654    end sub
    1655 
    1656    public function checkClExe(strClExe)
    1657       ' We'll have to make sure mspdbXX.dll is somewhere in the PATH.
    1658       dim strSavedPath, rcExit
    1659 
    1660       strSavedPath = EnvGet("PATH")
    1661       if (m_strPathVCCommon <> "") then
    1662          EnvAppend "PATH", ";" & m_strPathVCCommon & "/IDE"
    1663       end if
    1664       rcExit = Shell(DosSlashes(strClExe), True)
    1665       EnvSet "PATH", strSavedPath
    1666 
    1667       checkClExe = False
    1668       if rcExit = 0 then
    1669          ' Extract the ' Version xx.yy.build.zz for arch' bit.
    1670          dim offVer, offEol, strVer
    1671          strVer = ""
    1672          offVer = InStr(1, g_strShellOutput, " Version ")
    1673          if offVer > 0 then
    1674             offVer = offVer + Len(" Version ")
    1675             offEol = InStr(offVer, g_strShellOutput, Chr(13))
    1676             if offEol > 0 then
    1677                strVer = Trim(Mid(g_strShellOutput, offVer, offEol - offVer))
    1678             end if
    1679          end if
    1680 
    1681          ' Check that it's a supported version
    1682          checkClExe = True
    1683          if InStr(1, strVer, "16.") = 1 then
    1684             m_strVersion = "VCC110"
    1685          elseif InStr(1, strVer, "17.") = 1 then
    1686             m_strVersion = "VCC111"
    1687             LogPrint "The Visual C++ compiler ('" & strClExe & "') version isn't really supported, but may work: " & strVer
    1688          elseif InStr(1, strVer, "18.") = 1 then
    1689             m_strVersion = "VCC112"
    1690             LogPrint "The Visual C++ compiler ('" & strClExe & "') version isn't really supported, but may work: " & strVer
    1691          elseif InStr(1, strVer, "19.0") = 1 then
    1692             m_strVersion = "VCC140"
    1693             LogPrint "The Visual C++ compiler ('" & strClExe & "') version isn't really supported, but may work: " & strVer
    1694          elseif InStr(1, strVer, "19.1") = 1 then
    1695             m_strVersion = "VCC141"
    1696             LogPrint "The Visual C++ compiler ('" & strClExe & "') version isn't really supported, but may work: " & strVer
    1697          elseif InStr(1, strVer, "19.2") = 1 then
    1698             m_strVersion = "VCC142"
    1699          else
    1700             LogPrint "The Visual C++ compiler we found ('" & strClExe & "') isn't in the 10.0-19.2x range (" & strVer & ")."
    1701             LogPrint "Check the build requirements and select the appropriate compiler version."
    1702             checkClExe = False
    1703             exit function
    1704          end if
    1705          LogPrint "'" & strClExe & "' = " & m_strVersion & " (" & strVer & ")"
    1706       else
    1707          LogPrint "Executing '" & strClExe & "' (which we believe to be the Visual C++ compiler driver) failed (rcExit=" & rcExit & ")."
    1708       end if
    1709    end function
    1710 
    1711    public function checkInner(strPathVC) ' For the new layout only
    1712       if m_blnFound = False then
    1713          if   LogDirExists(strPathVC & "/bin") _
    1714           and LogDirExists(strPathVC & "/lib") _
    1715           and LogDirExists(strPathVC & "/include") _
    1716           and LogFileExists(strPathVC, "include/stdarg.h") _
    1717           and LogFileExists(strPathVC, "lib/x64/libcpmt.lib") _
    1718           and LogFileExists(strPathVC, "lib/x86/libcpmt.lib") _
    1719           and LogFileExists(strPathVC, "bin/Host" & g_strHostArchWin & "/" & g_strTargetArchWin & "/cl.exe") _
    1720           and LogFileExists(strPathVC, "bin/Host" & g_strHostArchWin & "/" & g_strHostArchWin & "/cl.exe") _
    1721          then
    1722             LogPrint " => seems okay. new layout."
    1723             m_blnFound = checkClExe(strPathVC & "/bin/Host" & g_strHostArchWin & "/" & g_strTargetArchWin & "/cl.exe")
    1724             if m_blnFound then
    1725                m_strPathVC = strPathVC
    1726             end if
    1727          end if
    1728       end if
    1729       checkInner = m_blnFound
    1730    end function
    1731 
    1732    public function check(strPathVC, strPathVCommon)
    1733       if (m_blnFound = False) and (strPathVC <> "") then
    1734          m_strPathVC       = UnixSlashes(PathAbs(strPathVC))
    1735          m_strPathVCCommon = strPathVCCommon
    1736          m_strVersion      = ""
    1737 
    1738          LogPrint "Trying: strPathVC=" & m_strPathVC & " strPathVCCommon=" & m_strPathVCCommon
    1739          if LogDirExists(m_strPathVC) then
    1740             ' 15.0+ layout?  This is fun because of the multiple CL versions (/tools/msvc/xx.yy.bbbbb/).
    1741             ' OTOH, the user may have pointed us directly to one of them.
    1742             if LogDirExists(m_strPathVC & "/Tools/MSVC") then
    1743                m_blnNewLayout = True
    1744                LogPrint " => seems okay. new layout."
    1745                dim arrFolders, i
    1746                arrFolders = GetSubdirsStartingWithVerSorted(m_strPathVC & "/Tools/MSVC", "14.2")
    1747                if UBound(arrFolders) < 0 then arrFolders = GetSubdirsStartingWithVerSorted(m_strPathVC & "/Tools/MSVC", "14.1")
    1748                if UBound(arrFolders) < 0 then arrFolders = GetSubdirsStartingWithVerSorted(m_strPathVC & "/Tools/MSVC", "1")
    1749                for i = UBound(arrFolders) to LBound(arrFolders) step -1
    1750                   if checkInner(m_strPathVC & "/Tools/MSVC/" & arrFolders(i)) then exit for ' modifies m_strPathVC on success
    1751                next
    1752             elseif LogDirExists(m_strPathVC & "/bin/HostX64") _
    1753                 or LogDirExists(m_strPathVC & "/bin/HostX86") then
    1754                checkInner(m_strPathVC)
    1755             ' 14.0 and older layout?
    1756             elseif LogFileExists(m_strPathVC, "/bin/cl.exe") then
    1757                m_blnNewLayout = False
    1758                if   LogFileExists(m_strPathVC, "bin/link.exe") _
    1759                 and LogFileExists(m_strPathVC, "include/string.h") _
    1760                 and LogFileExists(m_strPathVC, "lib/libcmt.lib") _
    1761                 and LogFileExists(m_strPathVC, "lib/msvcrt.lib") _
    1762                then
    1763                   LogPrint " => seems okay. old layout."
    1764                   m_blnFound = checkClExe(m_strPathVC & "/bin/cl.exe")
    1765                end if
    1766             end if
    1767          end if
    1768       end if
    1769       check = m_bldFound
    1770    end function
    1771 
    1772    public function checkProg(strProg)
    1773       if m_blnFound = False then
    1774          dim str, i, offNewLayout
    1775          str = Which(strProg)
    1776          if str <> "" then
    1777             LogPrint "checkProg: '" & strProg & "' -> '" & str & "'"
    1778             if FileExists(PathStripFilename(str) & "/build.exe") then
    1779                Warning "Ignoring DDK cl.exe (" & str & ")." ' don't know how to deal with this cl.
    1780             else
    1781                ' Assume we've got cl.exe from somewhere under the 'bin' directory..
    1782                m_strPathVC = PathParent(PathStripFilename(str))
    1783                for i = 1 To 5
    1784                   if LogDirExists(m_strPathVC & "/include") then
    1785                      m_strPathVCCommon = PathParent(m_strPathVC) & "/Common7"
    1786                      if DirExists(m_strPathVCCommon) = False then
    1787                         m_strPathVCCommon = ""
    1788                         ' New layout?
    1789                         offNewLayout = InStr(1, LCase(DosSlashes(m_strPathVC)), "\tools\msvc\")
    1790                         if offNewLayout > 0 then m_strPathVC = Left(m_strPathVC, offNewLayout)
    1791                      end if
    1792                      check m_strPathVC, m_strPathVCCommon
    1793                      exit for
    1794                   end if
    1795                   m_strPathVC = PathParent(m_strPathVC)
    1796                next
    1797             end if
    1798          end if
    1799       end if
    1800       checkProg = m_bldFound
    1801    end function
    1802 
    1803    public function checkProgFiles(strSubdir)
    1804       if m_blnFound = False then
    1805          dim strProgFiles
    1806          for each strProgFiles in g_arrProgramFiles
    1807             check strProgFiles & "/" & strSubdir, ""
    1808          next
    1809       end if
    1810       checkProgFiles = m_blnFound
    1811    end function
    1812 
    1813    public function checkRegistry(strValueNm, strVCSubdir, strVCommonSubdir)
    1814       if m_blnFound = False then
    1815          dim str, strPrefix, arrPrefixes
    1816          arrPrefixes = Array("HKLM\SOFTWARE\Wow6432Node\", "HKLM\SOFTWARE\", "HKCU\SOFTWARE\Wow6432Node\", "HKCU\SOFTWARE\")
    1817          for each strPrefix in arrPrefixes
    1818             str = RegGetString(strPrefix & strValueNm)
    1819             if str <> "" then
    1820                LogPrint "checkRegistry: '" & strPrefix & strValueNm & "' -> '" & str & "'"
    1821                if check(str & strVCSubdir, str & strVCommonSubdir) = True then
    1822                   exit for
    1823                end if
    1824             end if
    1825          next
    1826       end if
    1827       checkRegistry = m_bldFound
    1828    end function
    1829 
    1830    public function checkInternal
    1831       check g_strPathDev & "/win.amd64/vcc/v14.2",  ""
    1832       check g_strPathDev & "/win.amd64/vcc/v14.1",  ""
    1833       check g_strPathDev & "/win.amd64/vcc/v14.0",  ""
    1834       check g_strPathDev & "/win.amd64/vcc/v10sp1", ""
    1835       check g_strPathDev & "/win.x86/vcc/v10sp1",   ""
    1836       checkInternal = m_blnFound
    1837    end function
    1838 end class
    1839 
    1840 
    1841 ''
    1842 ' Checks for Visual C++ version 16 (2019), 15 (2017), 14 (2015), 12 (2013), 11 (2012) or 10 (2010).
    1843 '
    1844 sub CheckForVisualCPP(strOptVC, strOptVCCommon)
    1845    PrintHdr "Visual C++"
    1846 
    1847    '
    1848    ' Try find it...
    1849    '
    1850    dim objState, strProgFiles
    1851    set objState = new VisualCPPState
    1852    objState.check strOptVC, strOptVCCommon
    1853    if g_blnInternalFirst = True then objState.checkInternal
    1854    objState.checkProgFiles "Microsoft Visual Studio\2019\BuildTools\VC"
    1855    objState.checkProgFiles "Microsoft Visual Studio\2019\Professional\VC"
    1856    objState.checkProgFiles "Microsoft Visual Studio\2019\Community\VC"
    1857    objState.checkRegistry "Microsoft\VisualStudio\SxS\VS7\16.0",             "VC", ""        ' doesn't work.
    1858    objState.checkProgFiles "Microsoft Visual Studio\2017\BuildTools\VC"
    1859    objState.checkProgFiles "Microsoft Visual Studio\2017\Professional\VC"
    1860    objState.checkProgFiles "Microsoft Visual Studio\2017\Community\VC"
    1861    objState.checkProgFiles "Microsoft Visual Studio\2017\Express\VC"
    1862    objState.checkRegistry "Microsoft\VisualStudio\SxS\VS7\15.0",             "VC", ""
    1863    objState.checkRegistry "Microsoft\VisualStudio\SxS\VS7\14.0",             "VC", "Common7"
    1864    objState.checkRegistry "Microsoft\VisualStudio\SxS\VS7\12.0",             "VC", "Common7" '?
    1865    objState.checkRegistry "Microsoft\VisualStudio\SxS\VS7\11.0",             "VC", "Common7" '?
    1866    objState.checkProg "cl.exe"
    1867    objState.checkRegistry "Microsoft\VisualStudio\10.0\Setup\VS\ProductDir", "VC", "Common7"
    1868    if g_blnInternalFirst = False then objState.checkInternal
    1869 
    1870    if objState.m_blnFound = False then
    1871       MsgError "Cannot find cl.exe (Visual C++) anywhere on your system. Check the build requirements."
    1872       exit sub
    1873    end if
    1874    g_strPathVCC = objState.m_strPathVC
    1875    g_strVCCVersion = objState.m_strVersion
    1876 
    1877    '
    1878    ' Ok, emit build config variables.
    1879    '
    1880    CfgPrintAssign "VBOX_VCC_TOOL_STEM", objState.m_strVersion
    1881    CfgPrintAssign "PATH_TOOL_" & objState.m_strVersion, g_strPathVCC
    1882    CfgPrintAssign "PATH_TOOL_" & objState.m_strVersion & "X86",   "$(PATH_TOOL_" & objState.m_strVersion & ")"
    1883    CfgPrintAssign "PATH_TOOL_" & objState.m_strVersion & "AMD64", "$(PATH_TOOL_" & objState.m_strVersion & ")"
    1884 
    1885    if   objState.m_strVersion = "VCC100" _
    1886      or objState.m_strVersion = "VCC110" _
    1887      or objState.m_strVersion = "VCC120" _
    1888      or objState.m_strVersion = "VCC140" _
    1889    then
    1890       CfgPrintAssign "VBOX_WITH_NEW_VCC", "" '?? for VCC110+
    1891    else
    1892       CfgPrintAssign "VBOX_WITH_NEW_VCC", "1"
    1893    end if
    1894    PrintResult "Visual C++ " & objState.m_strVersion, g_strPathVCC
    1895 
    1896    ' And the env.bat path fix.
    1897    if objState.m_strPathVCCommon <> "" then
    1898       EnvPrintAppend "PATH", DosSlashes(objState.m_strPathVCCommon) & "\IDE", ";"
    1899    end if
    1900 end sub
    1901 
    1902 '' Checks for a platform SDK that works with the compiler
    1903 sub CheckForPlatformSDK(strOptSDK)
    1904    dim strPathPSDK, str
    1905    PrintHdr "Windows Platform SDK (recent)"
    1906 
    1907    strPathPSDK = ""
    1908 
    1909    ' Check the supplied argument first.
    1910    str = strOptSDK
    1911    if str <> "" then
    1912       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1913    end if
    1914 
    1915    ' The tools location (first).
    1916    if strPathPSDK = "" And g_blnInternalFirst then
    1917       str = g_strPathDev & "/win.x86/sdk/v7.1"
    1918       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1919    end if
    1920 
    1921    if strPathPSDK = "" And g_blnInternalFirst then
    1922       str = g_strPathDev & "/win.x86/sdk/v8.0"
    1923       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1924    end if
    1925 
    1926    ' Look for it in the environment
    1927    str = EnvGet("MSSdk")
    1928    if strPathPSDK = "" And str <> "" then
    1929       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1930    end if
    1931 
    1932    str = EnvGet("Mstools")
    1933    if strPathPSDK = "" And str <> "" then
    1934       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1935    end if
    1936 
    1937    ' Check if there is one installed with the compiler.
    1938    if strPathPSDK = "" And str <> "" then
    1939       str = g_strPathVCC & "/PlatformSDK"
    1940       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1941    end if
    1942 
    1943    ' Check the registry next (ASSUMES sorting).
    1944    arrSubKeys = RegEnumSubKeysRVerSorted("HKLM", "SOFTWARE\Microsoft\Microsoft SDKs\Windows")
    1945    for each strSubKey in arrSubKeys
    1946       str = RegGetString("HKLM\SOFTWARE\Microsoft\Microsoft SDKs\Windows\" & strSubKey & "\InstallationFolder")
    1947       if strPathPSDK = "" And str <> "" then
    1948          if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1949       end if
    1950    Next
    1951    arrSubKeys = RegEnumSubKeysRVerSorted("HKCU", "SOFTWARE\Microsoft\Microsoft SDKs\Windows")
    1952    for each strSubKey in arrSubKeys
    1953       str = RegGetString("HKCU\SOFTWARE\Microsoft\Microsoft SDKs\Windows\" & strSubKey & "\InstallationFolder")
    1954       if strPathPSDK = "" And str <> "" then
    1955          if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1956       end if
    1957    Next
    1958 
    1959    ' The tools location (post).
    1960    if (strPathPSDK = "") And (g_blnInternalFirst = False) then
    1961       str = g_strPathDev & "/win.x86/sdk/v7.1"
    1962       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1963    end if
    1964 
    1965    if (strPathPSDK = "") And (g_blnInternalFirst = False) then
    1966       str = g_strPathDev & "/win.x86/sdk/v8.0"
    1967       if CheckForPlatformSDKSub(str) then strPathPSDK = str
    1968    end if
    1969 
    1970    ' Give up.
    1971    if strPathPSDK = "" then
    1972       MsgError "Cannot find a suitable Platform SDK. Check configure.log and the build requirements."
    1973       exit sub
    1974    end if
    1975 
    1976    '
    1977    ' Emit the config.
    1978    '
    1979    strPathPSDK = UnixSlashes(PathAbs(strPathPSDK))
    1980    CfgPrintAssign "PATH_SDK_WINPSDK" & g_strVerPSDK, strPathPSDK
    1981    CfgPrintAssign "VBOX_WINPSDK",  "WINPSDK" & g_strVerPSDK
    1982 
    1983    PrintResult "Windows Platform SDK", strPathPSDK
    1984    PrintResultMsg "Windows Platform SDK version", g_strVerPSDK
    1985    g_strPathPSDK = strPathPSDK
    1986 end sub
    1987 
    1988 '' Checks if the specified path points to a usable PSDK.
    1989 function CheckForPlatformSDKSub(strPathPSDK)
    1990    CheckForPlatformSDKSub = False
    1991    LogPrint "trying: strPathPSDK=" & strPathPSDK
    1992    if    LogFileExists(strPathPSDK, "include/Windows.h") _
    1993     And  LogFileExists(strPathPSDK, "lib/Kernel32.Lib") _
    1994     And  LogFileExists(strPathPSDK, "lib/User32.Lib") _
    1995     And  LogFileExists(strPathPSDK, "bin/rc.exe") _
    1996     And  Shell("""" & DosSlashes(strPathPSDK & "/bin/rc.exe") & """" , True) <> 0 _
    1997       then
    1998       if InStr(1, g_strShellOutput, "Resource Compiler Version 6.2.") > 0 then
    1999          g_strVerPSDK = "80"
    2000          CheckForPlatformSDKSub = True
    2001       elseif InStr(1, g_strShellOutput, "Resource Compiler Version 6.1.") > 0 then
    2002          g_strVerPSDK = "71"
    2003          CheckForPlatformSDKSub = True
    2004       end if
    2005    end if
    2006 end function
    2007 
    2008 
    2009 ''
    2010 ' Checks for a windows 10 SDK (later also WDK).
    2011 '
    2012 sub CheckForSDK10(strOptSDK10, strOptSDK10Version)
    2013    dim strPathSDK10, strSDK10Version, str
    2014    PrintHdr "Windows 10 SDK/WDK"
    2015    '' @todo implement strOptSDK10Version
    2016 
    2017    '
    2018    ' Try find the Windows 10 kit.
    2019    '
    2020    strSDK10Version = ""
    2021    strPathSDK10 = CheckForSDK10Sub(strOptSDK10, strSDK10Version)
    2022    if strPathSDK10 = "" and g_blnInternalFirst = True  then strPathSDK10 = CheckForSDK10ToolsSub(strSDK10Version)
    2023    if strPathSDK10 = "" then
    2024       str = RegGetString("HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots\KitsRoot10")
    2025       strPathSDK10 = CheckForSDK10Sub(str, strSDK10Version)
    2026    end if
    2027    if strPathSDK10 = "" then
    2028       for each str in g_arrProgramFiles
    2029          strPathSDK10 = CheckForSDK10Sub(str & "/Windows Kits/10", strSDK10Version)
    2030          if strPathSDK10 <> "" then exit for
    2031       next
    2032    end if
    2033    if strPathSDK10 = "" and g_blnInternalFirst = False then strPathSDK10 = CheckForSDK10ToolsSub()
    2034 
    2035    if strPathSDK10 = "" then
    2036       MsgError "Cannot find a suitable Windows 10 SDK.  Check configure.log and the build requirements."
    2037       exit sub
    2038    end if
    2039 
    2040    '
    2041    ' Emit the config.
    2042    '
    2043    strPathSDK10 = UnixSlashes(PathAbs(strPathSDK10))
    2044    CfgPrintAssign "PATH_SDK_WINSDK10", strPathSDK10
    2045    CfgPrintAssign "SDK_WINSDK10_VERSION", strSDK10Version
    2046 
    2047    PrintResult "Windows 10 SDK", strPathSDK10
    2048    PrintResultMsg "Windows 10 SDK version", strSDK10Version
    2049    g_strPathSDK10 = strPathSDK10
    2050 end sub
    2051 
    2052 '' Checks the tools directory.
    2053 function CheckForSDK10ToolsSub(ByRef strSDK10Version)
    2054    dim arrToolsDirs, strToolsDir, arrDirs, strDir
    2055    CheckForSDK10ToolSub = ""
    2056    arrToolsDirs = Array(g_strPathDev & "/win." & g_strTargetArch & "/sdk", _
    2057                         g_strPathDev & "/win.x86/sdk", g_strPathDev & "/win.amd64/sdk")
    2058    for each strToolsDir in arrToolsDirs
    2059       arrDirs = GetSubdirsStartingWithRSortedVersion(strToolsDir, "v10.")
    2060       for each strDir in arrDirs
    2061          CheckForSDK10ToolsSub = CheckForSDK10Sub(strToolsDir & "/" & strDir, strSDK10Version)
    2062          if CheckForSDK10ToolsSub <> "" then
    2063             exit function
    2064          end if
    2065       next
    2066    next
    2067 
    2068 end function
    2069 
    2070 '' Checks if the specified path points to a usable Windows 10 SDK/WDK.
    2071 function CheckForSDK10Sub(strPathSDK10, ByRef strSDK10Version)
    2072    CheckForSDK10Sub = ""
    2073    if strPathSDK10 <> "" then
    2074       LogPrint "Trying: strPathSDK10=" & strPathSDK10
    2075       if LogDirExists(strPathSDK10) then
    2076          if   LogDirExists(strPathSDK10 & "/Bin") _
    2077           and LogDirExists(strPathSDK10 & "/Include") _
    2078           and LogDirExists(strPathSDK10 & "/Lib") _
    2079           and LogDirExists(strPathSDK10 & "/Redist") _
    2080          then
    2081             ' Only testing the highest one, for now. '' @todo incorporate strOptSDK10Version
    2082             dim arrVersions
    2083             arrVersions = GetSubdirsStartingWithVerSorted(strPathSDK10 & "/Include", "10.0.")
    2084             if UBound(arrVersions) >= 0 then
    2085                dim strVersion
    2086                strVersion = arrVersions(UBound(arrVersions))
    2087                LogPrint "Trying version: " & strVersion
    2088                if    LogFileExists(strPathSDK10, "include/" & strVersion & "/um/Windows.h") _
    2089                 and  LogFileExists(strPathSDK10, "include/" & strVersion & "/ucrt/malloc.h") _
    2090                 and  LogFileExists(strPathSDK10, "include/" & strVersion & "/ucrt/stdio.h") _
    2091                 and  LogFileExists(strPathSDK10, "lib/" & strVersion & "/um/"   & g_strTargetArchWin & "/kernel32.lib") _
    2092                 and  LogFileExists(strPathSDK10, "lib/" & strVersion & "/um/"   & g_strTargetArchWin & "/user32.lib") _
    2093                 and  LogFileExists(strPathSDK10, "lib/" & strVersion & "/ucrt/" & g_strTargetArchWin & "/libucrt.lib") _
    2094                 and  LogFileExists(strPathSDK10, "lib/" & strVersion & "/ucrt/" & g_strTargetArchWin & "/ucrt.lib") _
    2095                 and  LogFileExists(strPathSDK10, "bin/" & strVersion & "/" & g_strHostArchWin & "/rc.exe") _
    2096                 and  LogFileExists(strPathSDK10, "bin/" & strVersion & "/" & g_strHostArchWin & "/midl.exe") _
    2097                then
    2098                   if StrComp(strVersion, "10.0.17134.0") >= 0 then
    2099                      strSDK10Version  = strVersion
    2100                      CheckForSDK10Sub = strPathSDK10
    2101                   else
    2102                      LogPrint "Version " & strVersion & " is too low, minimum: 10.0.17134.0"
    2103                   end if
    2104                end if
    2105             else
    2106                LogPrint "Found no 10.0.* subdirectories under '" & strPathSDK10 & "/Include'!"
    2107             end if
    2108          end if
    2109       end if
    2110    end if
    2111 end function
    2112 
    2113 
    2114 ''
    2115 ' Locating a Windows 7 Driver Kit.
    2116 '
    2117 sub CheckForWinDDK(strOptDDK)
    2118    dim strPathDDK, str, strSubKeys
    2119    PrintHdr "Windows DDK v7.1"
    2120 
    2121    '
    2122    ' Find the DDK.
    2123    '
    2124    strPathDDK = ""
    2125    ' The specified path.
    2126    if strPathDDK = "" And strOptDDK <> "" then
    2127       if CheckForWinDDKSub(strOptDDK, True) then strPathDDK = strOptDDK
    2128    end if
    2129 
    2130    ' The tools location (first).
    2131    if strPathDDK = "" And g_blnInternalFirst then
    2132       str = g_strPathDev & "/win.x86/ddk/7600.16385.1"
    2133       if CheckForWinDDKSub(str, False) then strPathDDK = str
    2134    end if
    2135 
    2136    ' Check the environment
    2137    str = EnvGet("DDK_INC_PATH")
    2138    if strPathDDK = "" And str <> "" then
    2139       str = PathParent(PathParent(str))
    2140       if CheckForWinDDKSub(str, True) then strPathDDK = str
    2141    end if
    2142 
    2143    str = EnvGet("BASEDIR")
    2144    if strPathDDK = "" And str <> "" then
    2145       if CheckForWinDDKSub(str, True) then strPathDDK = str
    2146    end if
    2147 
    2148    ' Some array constants to ease the work.
    2149    arrSoftwareKeys = array("SOFTWARE", "SOFTWARE\Wow6432Node")
    2150    arrRoots        = array("HKLM", "HKCU")
    2151 
    2152    ' Windows 7 WDK.
    2153    arrLocations = array()
    2154    for each strSoftwareKey in arrSoftwareKeys
    2155       for each strSubKey in RegEnumSubKeysFull("HKLM", strSoftwareKey & "\Microsoft\KitSetup\configured-kits")
    2156          for each strSubKey2 in RegEnumSubKeysFull("HKLM", strSubKey)
    2157             str = RegGetString("HKLM\" & strSubKey2 & "\setup-install-location")
    2158             if str <> "" then
    2159                arrLocations = ArrayAppend(arrLocations, PathAbsLong(str))
    2160             end if
    2161          next
    2162       next
    2163    next
    2164    arrLocations = ArrayRVerSortStrings(arrLocations)
    2165 
    2166    ' Check the locations we've gathered.
    2167    for each str in arrLocations
    2168       if strPathDDK = "" then
    2169          if CheckForWinDDKSub(str, True) then strPathDDK = str
    2170       end if
    2171    next
    2172 
    2173    ' The tools location (post).
    2174    if (strPathDDK = "") And (g_blnInternalFirst = False) then
    2175       str = g_strPathDev & "/win.x86/ddk/7600.16385.1"
    2176       if CheckForWinDDKSub(str, False) then strPathDDK = str
    2177    end if
    2178 
    2179    ' Give up.
    2180    if strPathDDK = "" then
    2181       MsgError "Cannot find the Windows DDK v7.1. Check configure.log and the build requirements."
    2182       exit sub
    2183    end if
    2184 
    2185    '
    2186    ' Emit the config.
    2187    '
    2188    strPathDDK = UnixSlashes(PathAbs(strPathDDK))
    2189    CfgPrintAssign "PATH_SDK_WINDDK71", strPathDDK
    2190 
    2191    PrintResult "Windows DDK v7.1", strPathDDK
    2192    g_strPathDDK = strPathDDK
    2193 end sub
    2194 
    2195 '' Quick check if the DDK is in the specified directory or not.
    2196 function CheckForWinDDKSub(strPathDDK, blnCheckBuild)
    2197    CheckForWinDDKSub = False
    2198    LogPrint "trying: strPathDDK=" & strPathDDK & " blnCheckBuild=" & blnCheckBuild
    2199    if   LogFileExists(strPathDDK, "inc/api/ntdef.h") _
    2200     And LogFileExists(strPathDDK, "lib/win7/i386/int64.lib") _
    2201     And LogFileExists(strPathDDK, "lib/wlh/i386/int64.lib") _
    2202     And LogFileExists(strPathDDK, "lib/wnet/i386/int64.lib") _
    2203     And LogFileExists(strPathDDK, "lib/wxp/i386/int64.lib") _
    2204     And Not LogFileExists(strPathDDK, "lib/win8/i386/int64.lib") _
    2205     And LogFileExists(strPathDDK, "bin/x86/rc.exe") _
    2206       then
    2207       if Not blnCheckBuild then
    2208          CheckForWinDDKSub = True
    2209       '' @todo Find better build check.
    2210       elseif Shell("""" & DosSlashes(strPathDDK & "/bin/x86/rc.exe") & """" , True) <> 0 _
    2211          And InStr(1, g_strShellOutput, "Resource Compiler Version 6.1.") > 0 then
    2212          CheckForWinDDKSub = True
    2213       end if
    2214    end if
    2215 end function
    2216 
    2217 
    2218 ''
    2219 ' Locating midl.exe
    2220 '
    2221 sub CheckForMidl(strOptMidl)
    2222    dim strMidl
    2223    PrintHdr "Midl.exe"
    2224 
    2225    ' Skip if no COM/ATL.
    2226    if g_blnDisableCOM then
    2227       PrintResultMsg "Midl.exe", "Skipped (" & g_strDisableCOM & ")"
    2228       exit sub
    2229    end if
    2230 
    2231    strMidl = CheckForMidlSub(strOptMidl)
    2232    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathSDK10 & "/bin/" & g_strHostArchWin & "/Midl.exe")
    2233    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathSDK10 & "/bin/x86/Midl.exe")
    2234    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathPSDK  & "/bin/Midl.exe")
    2235    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathVCC   & "/Common7/Tools/Bin/Midl.exe")
    2236    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathDDK   & "/bin/" & g_strHostArchWin & "/Midl.exe")
    2237    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathDDK   & "/bin/x86/Midl.exe")
    2238    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathDDK   & "/bin/Midl.exe")
    2239    if strMidl = "" then strMidl = CheckForMidlSub(g_strPathDev   & "/win.x86/bin/Midl.exe")
    2240    if strMidl = "" then
    2241       PrintResultMsg "Midl.exe", "not found"
    2242       exit sub
    2243    end if
    2244 
    2245    CfgPrintAssign "VBOX_MAIN_IDL", strMidl
    2246    PrintResult "Midl.exe", strMidl
    2247 end sub
    2248 
    2249 function CheckForMidlSub(strMidl)
    2250    CheckForMidlSub = ""
    2251    if strMidl <> "" then
    2252       if LogFileExists1(strMidl) then
    2253          CheckForMidlSub = UnixSlashes(PathAbs(strMidl))
    2254       end if
    2255    end if
    2256 end function
    2257 
    2258 
    2259 ''
    2260 ' Locating OpenWatcom 1.9
    2261 '
    2262 sub CheckForOpenWatcom(strOptOpenWatcom)
    2263    dim strPathOpenWatcom
    2264    PrintHdr "OpenWatcom"
    2265 
    2266    strPathOpenWatcom = CheckForOpenWatcomSub(strOptOpenWatcom)
    2267    if strPathOpenWatcom = "" and g_blnInternalFirst = True then strPathOpenWatcom = CheckForOpenWatcomToolsSub()
    2268    if strPathOpenWatcom = "" then strPathOpenWatcom = CheckForOpenWatcomSub(EnvGet("WATCOM"))
    2269    if strPathOpenWatcom = "" then strPathOpenWatcom = CheckForOpenWatcomSub(PathParent(PathStripFilename(Which("wcc386.exe"))))
    2270    if strPathOpenWatcom = "" then
    2271       dim arrCandiates, strCandidate
    2272       arrCandidates = CollectFromProgramItemLinks(GetRef("OpenWatcomProgramItemCallback"), strPathOpenWatcom)
    2273       for each strCandidate in arrCandidates
    2274          if strPathOpenWatcom = "" then strPathOpenWatcom = CheckForOpenWatcomSub(strCandidate)
    2275       next
    2276    end if
    2277    if strPathOpenWatcom = "" and g_blnInternalFirst = False then strPathOpenWatcom = CheckForOpenWatcomToolsSub()
    2278 
    2279    if strPathOpenWatcom = "" then
    2280       PrintResultMsg "OpenWatcom", "not found"
    2281       CfgPrintAssign "VBOX_WITH_OPEN_WATCOM", ""
    2282       exit sub
    2283    end if
    2284 
    2285    CfgPrintAssign "VBOX_WITH_OPEN_WATCOM", "1"
    2286    CfgPrintAssign "PATH_TOOL_OPENWATCOM", strPathOpenWatcom
    2287    PrintResult "OpenWatcom", strPathOpenWatcom
    2288 end sub
    2289 
    2290 function CheckForOpenWatcomToolsSub()
    2291    dim arrToolsDirs, strToolsDir, arrDirs, strDir
    2292    arrToolsDirs = Array(g_strPathDev & "/common/openwatcom", _
    2293                         g_strPathDev & "/win." & g_strTargetArch & "/openwatcom", _
    2294                         g_strPathDev & "/win.x86/openwatcom", g_strPathDev & "/win.amd64/openwatcom")
    2295    for each strToolsDir in arrToolsDirs
    2296       arrDirs = GetSubdirsStartingWithRSortedVersion(strToolsDir, "v")
    2297       for each strDir in arrDirs
    2298          CheckForOpenWatcomToolsSub = CheckForOpenWatcomSub(strToolsDir & "/" & strDir)
    2299          if CheckForOpenWatcomToolsSub <> "" then
    2300             exit function
    2301          end if
    2302       next
    2303    next
    2304    CheckForOpenWatcomToolsSub = ""
    2305 end function
    2306 
    2307 function OpenWatcomProgramItemCallback(ByRef arrStrings, cStrings, ByRef strUnused)
    2308    dim str, off
    2309    OpenWatcomProgramItemCallback = ""
    2310    if cStrings > 1 then
    2311       str = arrStrings(1)
    2312       off = InStr(1, str, "\binnt\", vbTextCompare)
    2313       if off > 0 then
    2314          OpenWatcomProgramItemCallback = Left(str, off - 1)
    2315       end if
    2316    end if
    2317 end function
    2318 
    2319 function CheckForOpenWatcomSub(strPathOpenWatcom)
    2320    CheckForOpenWatcomSub = ""
    2321    if strPathOpenWatcom <> "" then
    2322       LogPrint "Trying: " & strPathOpenWatcom
    2323       if LogDirExists(strPathOpenWatcom) then
    2324          if   LogDirExists(strPathOpenWatcom & "/binnt") _
    2325           and LogDirExists(strPathOpenWatcom & "/h") _
    2326           and LogDirExists(strPathOpenWatcom & "/eddat") _
    2327           and LogFileExists(strPathOpenWatcom, "binnt/wcc386.exe") _
    2328           and LogFileExists(strPathOpenWatcom, "binnt/wcc.exe") _
    2329           and LogFileExists(strPathOpenWatcom, "binnt/wlink.exe") _
    2330           and LogFileExists(strPathOpenWatcom, "binnt/wcl386.exe") _
    2331           and LogFileExists(strPathOpenWatcom, "binnt/wcl.exe") _
    2332           and LogFileExists(strPathOpenWatcom, "binnt/wlib.exe") _
    2333           and LogFileExists(strPathOpenWatcom, "binnt/wasm.exe") _
    2334           and LogFileExists(strPathOpenWatcom, "h/stdarg.h") _
    2335          then
    2336             '' @todo check the version!
    2337             CheckForOpenWatcomSub = UnixSlashes(PathAbs(strPathOpenWatcom))
    2338          end if
    2339       end if
    2340    end if
    2341 end function
    2342 
    2343 
    2344 ''
    2345 ' Checks for any libSDL binaries.
    2346 '
    2347 sub CheckForlibSDL(strOptlibSDL)
    2348    dim strPathlibSDL, str
    2349    PrintHdr "libSDL"
    2350 
    2351    '
    2352    ' Try find some SDL library.
    2353    '
    2354 
    2355    ' First, the specific location.
    2356    strPathlibSDL = ""
    2357    if (strPathlibSDL = "") And (strOptlibSDL <> "") then
    2358       if CheckForlibSDLSub(strOptlibSDL) then strPathlibSDL = strOptlibSDL
    2359    end if
    2360 
    2361    ' The tools location (first).
    2362    if (strPathlibSDL = "") And (g_blnInternalFirst = True) then
    2363       str = g_strPathDev & "/win." & g_strTargetArch & "/libsdl"
    2364       if HasSubdirsStartingWith(str, "v") then
    2365          PrintResult "libSDL", str & "/v* (auto)"
    2366          exit sub
    2367       end if
    2368    end if
    2369 
    2370    ' Poke about in the path.
    2371    if strPathlibSDL = "" then
    2372       str = WhichEx("LIB", "SDLmain.lib")
    2373       if str = "" then str = Which("..\lib\SDLmain.lib")
    2374       if str = "" then str = Which("SDLmain.lib")
    2375       if str <> "" then
    2376          str = PathParent(PathStripFilename(str))
    2377          if CheckForlibSDLSub(str) then strPathlibSDL = str
    2378       end if
    2379    end if
    2380 
    2381    if strPathlibSDL = "" then
    2382       str = Which("SDL.dll")
    2383       if str <> "" then
    2384          str = PathParent(PathStripFilename(str))
    2385          if CheckForlibSDLSub(str) then strPathlibSDL = str
    2386       end if
    2387    end if
    2388 
    2389    ' The tools location (post).
    2390    if (strPathlibSDL = "") And (g_blnInternalFirst = False) then
    2391       str = g_strPathDev & "/win." & g_strTargetArch & "/libsdl"
    2392       if HasSubdirsStartingWith(str, "v") then
    2393          PrintResult "libSDL", str & "/v* (auto)"
    2394          exit sub
    2395       end if
    2396    end if
    2397 
    2398    ' Success?
    2399    if strPathlibSDL = "" then
    2400       if strOptlibSDL = "" then
    2401          MsgError "Can't locate libSDL. Try specify the path with the --with-libSDL=<path> argument. " _
    2402                 & "If still no luck, consult the configure.log and the build requirements."
    2403       else
    2404          MsgError "Can't locate libSDL. Please consult the configure.log and the build requirements."
    2405       end if
    2406       exit sub
    2407    end if
    2408 
    2409    strPathLibSDL = UnixSlashes(PathAbs(strPathLibSDL))
    2410    CfgPrintAssign "PATH_SDK_LIBSDL", strPathlibSDL
    2411 
    2412    PrintResult "libSDL", strPathlibSDL
    2413 end sub
    2414 
    2415 '' Checks if the specified path points to an usable libSDL or not.
    2416 function CheckForlibSDLSub(strPathlibSDL)
    2417    CheckForlibSDLSub = False
    2418    LogPrint "trying: strPathlibSDL=" & strPathlibSDL
    2419    if   LogFileExists(strPathlibSDL, "lib/SDL.lib") _
    2420     And LogFileExists(strPathlibSDL, "lib/SDLmain.lib") _
    2421     And LogFileExists(strPathlibSDL, "lib/SDL.dll") _
    2422     And LogFileExists(strPathlibSDL, "include/SDL.h") _
    2423     And LogFileExists(strPathlibSDL, "include/SDL_syswm.h") _
    2424     And LogFileExists(strPathlibSDL, "include/SDL_version.h") _
    2425       then
    2426       CheckForlibSDLSub = True
    2427    end if
    2428 end function
    2429 
    2430 
    2431 ''
    2432 ' Checks for libxml2.
    2433 '
    2434 sub CheckForXml2(strOptXml2)
    2435    dim strPathXml2, str
    2436    PrintHdr "libxml2"
    2437 
    2438    '
    2439    ' Part of tarball / svn, so we can exit immediately if no path was specified.
    2440    '
    2441    if (strOptXml2 = "") then
    2442       PrintResultMsg "libxml2", "src/lib/libxml2-*"
    2443       exit sub
    2444    end if
    2445 
    2446    ' Skip if no COM/ATL.
    2447    if g_blnDisableCOM then
    2448       PrintResultMsg "libxml2", "Skipped (" & g_strDisableCOM & ")"
    2449       exit sub
    2450    end if
    2451 
    2452    '
    2453    ' Try find some xml2 dll/lib.
    2454    '
    2455    strPathXml2 = ""
    2456    if (strPathXml2 = "") And (strOptXml2 <> "") then
    2457       if CheckForXml2Sub(strOptXml2) then strPathXml2 = strOptXml2
    2458    end if
    2459 
    2460    if strPathXml2 = "" then
    2461       str = Which("libxml2.lib")
    2462       if str <> "" then
    2463          str = PathParent(PathStripFilename(str))
    2464          if CheckForXml2Sub(str) then strPathXml2 = str
    2465       end if
    2466    end if
    2467 
    2468    ' Success?
    2469    if strPathXml2 = "" then
    2470       if strOptXml2 = "" then
    2471          MsgError "Can't locate libxml2. Try specify the path with the --with-libxml2=<path> argument. " _
    2472                 & "If still no luck, consult the configure.log and the build requirements."
    2473       else
    2474          MsgError "Can't locate libxml2. Please consult the configure.log and the build requirements."
    2475       end if
    2476       exit sub
    2477    end if
    2478 
    2479    strPathXml2 = UnixSlashes(PathAbs(strPathXml2))
    2480    CfgPrintAssign "SDK_VBOX_LIBXML2_DEFS", "_REENTRANT"
    2481    CfgPrintAssign "SDK_VBOX_LIBXML2_INCS", strPathXml2 & "/include"
    2482    CfgPrintAssign "SDK_VBOX_LIBXML2_LIBS", strPathXml2 & "/lib/libxml2.lib"
    2483 
    2484    PrintResult "libxml2", strPathXml2
    2485 end sub
    2486 
    2487 '' Checks if the specified path points to an usable libxml2 or not.
    2488 function CheckForXml2Sub(strPathXml2)
    2489    dim str
    2490 
    2491    CheckForXml2Sub = False
    2492    LogPrint "trying: strPathXml2=" & strPathXml2
    2493    if   LogFileExists(strPathXml2, "include/libxml/xmlexports.h") _
    2494     And LogFileExists(strPathXml2, "include/libxml/xmlreader.h") _
    2495       then
    2496       str = LogFindFile(strPathXml2, "bin/libxml2.dll")
    2497       if str <> "" then
    2498          if LogFindFile(strPathXml2, "lib/libxml2.lib") <> "" then
    2499             CheckForXml2Sub = True
    2500          end if
    2501       end if
    2502    end if
    2503 end function
    2504 
    2505 
    2506 '' Checks for openssl
    2507 sub CheckForSsl(strOptSsl, bln32Bit)
    2508    dim strPathSsl, str
    2509    PrintHdr "openssl"
    2510 
    2511    strOpenssl = "openssl"
    2512    if bln32Bit = True then
    2513        strOpenssl = "openssl32"
    2514    end if
    2515 
    2516    '
    2517    ' Part of tarball / svn, so we can exit immediately if no path was specified.
    2518    '
    2519    if (strOptSsl = "") then
    2520       PrintResult strOpenssl, "src/libs/openssl-*"
    2521       exit sub
    2522    end if
    2523 
    2524    '
    2525    ' Try find some openssl dll/lib.
    2526    '
    2527    strPathSsl = ""
    2528    if (strPathSsl = "") And (strOptSsl <> "") then
    2529       if CheckForSslSub(strOptSsl) then strPathSsl = strOptSsl
    2530    end if
    2531 
    2532    if strPathSsl = "" then
    2533       str = Which("libssl.lib")
    2534       if str <> "" then
    2535          str = PathParent(PathStripFilename(str))
    2536          if CheckForSslSub(str) then strPathSsl = str
    2537       end if
    2538    end if
    2539 
    2540    ' Success?
    2541    if strPathSsl = "" then
    2542       if strOptSsl = "" then
    2543          MsgError "Can't locate " & strOpenssl & ". " _
    2544                 & "Try specify the path with the --with-" & strOpenssl & "=<path> argument. " _
    2545                 & "If still no luck, consult the configure.log and the build requirements."
    2546       else
    2547          MsgError "Can't locate " & strOpenssl & ". " _
    2548                 & "Please consult the configure.log and the build requirements."
    2549       end if
    2550       exit sub
    2551    end if
    2552 
    2553    strPathSsl = UnixSlashes(PathAbs(strPathSsl))
    2554    if bln32Bit = True then
    2555       CfgPrintAssign "SDK_VBOX_OPENSSL-x86_INCS",     strPathSsl & "/include"
    2556       CfgPrintAssign "SDK_VBOX_OPENSSL-x86_LIBS",     strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
    2557       CfgPrintAssign "SDK_VBOX_BLD_OPENSSL-x86_LIBS", strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
    2558    else
    2559       CfgPrintAssign "SDK_VBOX_OPENSSL_INCS",         strPathSsl & "/include"
    2560       CfgPrintAssign "SDK_VBOX_OPENSSL_LIBS",         strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
    2561       CfgPrintAssign "SDK_VBOX_BLD_OPENSSL_LIBS",     strPathSsl & "/lib/libcrypto.lib" & " " & strPathSsl & "/lib/libssl.lib"
    2562    end if
    2563 
    2564    PrintResult strOpenssl, strPathSsl
    2565 end sub
    2566 
    2567 '' Checks if the specified path points to an usable openssl or not.
    2568 function CheckForSslSub(strPathSsl)
    2569 
    2570    CheckForSslSub = False
    2571    LogPrint "trying: strPathSsl=" & strPathSsl
    2572    if   LogFileExists(strPathSsl, "include/openssl/md5.h") _
    2573     And LogFindFile(strPathSsl, "lib/libssl.lib") <> "" _
    2574       then
    2575          CheckForSslSub = True
    2576       end if
    2577 end function
    2578 
    2579 
    2580 ''
    2581 ' Checks for libcurl
    2582 '
    2583 sub CheckForCurl(strOptCurl, bln32Bit)
    2584    dim strPathCurl, str
    2585    PrintHdr "libcurl"
    2586 
    2587    strCurl = "libcurl"
    2588    if bln32Bit = True then
    2589        strCurl = "libcurl32"
    2590    end if
    2591 
    2592    '
    2593    ' Part of tarball / svn, so we can exit immediately if no path was specified.
    2594    '
    2595    if (strOptCurl = "") then
    2596       PrintResult strCurl, "src/libs/curl-*"
    2597       exit sub
    2598    end if
    2599 
    2600    '
    2601    ' Try find some cURL dll/lib.
    2602    '
    2603    strPathCurl = ""
    2604    if (strPathCurl = "") And (strOptCurl <> "") then
    2605       if CheckForCurlSub(strOptCurl) then strPathCurl = strOptCurl
    2606    end if
    2607 
    2608    if strPathCurl = "" then
    2609       str = Which("libcurl.lib")
    2610       if str <> "" then
    2611          str = PathParent(PathStripFilename(str))
    2612          if CheckForCurlSub(str) then strPathCurl = str
    2613       end if
    2614    end if
    2615 
    2616    ' Success?
    2617    if strPathCurl = "" then
    2618       if strOptCurl = "" then
    2619          MsgError "Can't locate " & strCurl & ". " _
    2620                 & "Try specify the path with the --with-" & strCurl & "=<path> argument. " _
    2621                 & "If still no luck, consult the configure.log and the build requirements."
    2622       else
    2623          MsgError "Can't locate " & strCurl & ". " _
    2624                 & "Please consult the configure.log and the build requirements."
    2625       end if
    2626       exit sub
    2627    end if
    2628 
    2629    strPathCurl = UnixSlashes(PathAbs(strPathCurl))
    2630    if bln32Bit = True then
    2631       CfgPrintAssign "SDK_VBOX_LIBCURL-x86_INCS",     strPathCurl & "/include"
    2632       CfgPrintAssign "SDK_VBOX_LIBCURL-x86_LIBS.x86", strPathCurl & "/libcurl.lib"
    2633    else
    2634       CfgPrintAssign "SDK_VBOX_LIBCURL_INCS", strPathCurl & "/include"
    2635       CfgPrintAssign "SDK_VBOX_LIBCURL_LIBS", strPathCurl & "/libcurl.lib"
    2636    end if
    2637 
    2638    PrintResult strCurl, strPathCurl
    2639 end sub
    2640 
    2641 '' Checks if the specified path points to an usable libcurl or not.
    2642 function CheckForCurlSub(strPathCurl)
    2643 
    2644    CheckForCurlSub = False
    2645    LogPrint "trying: strPathCurl=" & strPathCurl
    2646    if   LogFileExists(strPathCurl, "include/curl/curl.h") _
    2647     And LogFindFile(strPathCurl, "libcurl.dll") <> "" _
    2648     And LogFindFile(strPathCurl, "libcurl.lib") <> "" _
    2649       then
    2650          CheckForCurlSub = True
    2651       end if
    2652 end function
    2653 
    2654 
    2655 ''
    2656 ' Checks for any Qt5 binaries.
    2657 '
    2658 sub CheckForQt(strOptQt5, strOptInfix)
    2659    dim strPathQt5, strInfixQt5, arrFolders, arrVccInfixes, strVccInfix
    2660    PrintHdr "Qt5"
    2661 
    2662    '
    2663    ' Try to find the Qt5 installation (user specified path with --with-qt5)
    2664    '
    2665    LogPrint "Checking for user specified path of Qt5 ... "
    2666    strPathQt5 = ""
    2667    if strOptQt5 <> "" then
    2668       strPathQt5 = CheckForQt5Sub(UnixSlashes(strOptQt5), strOptInfix, strInfixQt5)
    2669    end if
    2670 
    2671    if strPathQt = "" then
    2672       '
    2673       ' Collect links from "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\UFH\SHC"
    2674       '
    2675       ' Typical string list:
    2676       '   C:\Users\someuser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Qt\5.x.y\MSVC 20zz (64-bit)\Qt 5.x.y (MSVC 20zz 64-bit).lnk
    2677       '   C:\Windows\System32\cmd.exe
    2678       '   /A /Q /K E:\qt\installed\5.x.y\msvc20zz_64\bin\qtenv2.bat
    2679       '
    2680       dim arrCandidates, strCandidate
    2681       arrCandidates = CollectFromProgramItemLinks(GetRef("Qt5ProgramItemCallback"), strPathQt5)
    2682       LogPrint "Testing qtenv2.bat links (" & ArraySize(arrCandidates) & ") ..."
    2683 
    2684       ' VC infixes/subdir names to consider (ASSUMES 64bit)
    2685       if     g_strVCCVersion = "VCC142" or g_strVCCVersion = "" then
    2686          arrVccInfixes = Array("msvc2019_64", "msvc2017_64", "msvc2015_64")
    2687       elseif g_strVCCVersion = "VCC141" then
    2688          arrVccInfixes = Array("msvc2017_64", "msvc2015_64", "msvc2019_64")
    2689       elseif g_strVCCVersion = "VCC140" then
    2690          arrVccInfixes = Array("msvc2015_64", "msvc2017_64", "msvc2019_64")
    2691       elseif g_strVCCVersion = "VCC120" then
    2692          arrVccInfixes = Array("msvc2013_64")
    2693       elseif g_strVCCVersion = "VCC110" then
    2694          arrVccInfixes = Array("msvc2012_64")
    2695       elseif g_strVCCVersion = "VCC100" then
    2696          arrVccInfixes = Array("msvc2010_64")
    2697       else
    2698          MsgFatal "Unexpected VC version: " & g_strVCCVersion
    2699          arrVccInfixes = Array()
    2700       end if
    2701       for each strVccInfix in arrVccInfixes
    2702          for each strCandidate in arrCandidates
    2703             if InStr(1, LCase(strCandidate), strVccInfix) > 0 then
    2704                strPathQt5 = CheckForQt5Sub(strCandidate, strOptInfix, strInfixQt5)
    2705                if strPathQt5 <> "" then exit for
    2706             end if
    2707          next
    2708          if strPathQt5 <> "" then exit for
    2709       next
    2710    end if
    2711 
    2712    ' Check the dev tools - prefer ones matching the compiler.
    2713    if strPathQt5 = "" then
    2714       LogPrint "Testing tools dir (" & g_strPathDev & "/win." & g_strTargetArch & "/qt/v5*) ..."
    2715       arrFolders = GetSubdirsStartingWithVerSorted(g_strPathDev & "/win." & g_strTargetArch & "/qt", "v5")
    2716       arrVccInfixes = Array(LCase(g_strVCCVersion), Left(LCase(g_strVCCVersion), Len(g_strVCCVersion) - 1), "")
    2717       for each strVccInfix in arrVccInfixes
    2718          for i = UBound(arrFolders) to LBound(arrFolders) step -1
    2719             if strVccInfix = "" or InStr(1, LCase(arrFolders(i)), strVccInfix) > 0 then
    2720                strPathQt5 = CheckForQt5Sub(g_strPathDev & "/win." & g_strTargetArch & "/qt/" & arrFolders(i), strOptInfix, strInfixQt5)
    2721                if strPathQt5 <> "" then exit for
    2722             end if
    2723          next
    2724          if strPathQt5 <> "" then exit for
    2725       next
    2726    end if
    2727 
    2728    '
    2729    ' Display the result and output the config.
    2730    '
    2731    if strPathQt5 <> "" then
    2732       PrintResult "Qt5", strPathQt5
    2733       PrintResultMsg "Qt5 infix", strInfixQt5
    2734       CfgPrintAssign "PATH_SDK_QT5",          strPathQt5
    2735       CfgPrintAssign "PATH_TOOL_QT5",         "$(PATH_SDK_QT5)"
    2736       CfgPrintAssign "VBOX_PATH_QT",          "$(PATH_SDK_QT5)"
    2737       CfgPrintAssign "VBOX_QT_INFIX",         strInfixQt5
    2738       CfgPrintAssign "VBOX_WITH_QT_PAYLOAD",  "1"
    2739    else
    2740       PrintResultMsg "Qt5", "not found"
    2741       CfgPrintAssign "VBOX_WITH_QTGUI", ""
    2742    end if
    2743 end sub
    2744 
    2745 function Qt5ProgramItemCallback(ByRef arrStrings, cStrings, ByRef strUnused)
    2746    dim str, off
    2747    Qt5ProgramItemCallback = ""
    2748    if cStrings >= 3 then
    2749       str = Trim(arrStrings(UBound(arrStrings)))
    2750       if   LCase(Right(str, Len("\bin\qtenv2.bat"))) = "\bin\qtenv2.bat" _
    2751        and InStr(1, LCase(str), "\msvc20") > 0 _
    2752        and InStr(1, str, ":") > 0 _
    2753       then
    2754          off = InStr(1, str, ":") - 1
    2755          Qt5ProgramItemCallback = Mid(str, off, Len(str) - off - Len("\bin\qtenv2.bat") + 1)
    2756       end if
    2757    end if
    2758 end function
    2759 
    2760 function CheckForQt5Sub(strPathQt5, strOptInfix, ByRef strInfixQt5)
    2761    CheckForQt5Sub = ""
    2762    LogPrint "trying: strPathQt5=" & strPathQt5
    2763 
    2764    if   LogFileExists(strPathQt5, "bin/moc.exe") _
    2765     and LogFileExists(strPathQt5, "bin/uic.exe") _
    2766     and LogFileExists(strPathQt5, "include/QtWidgets/qwidget.h") _
    2767     and LogFileExists(strPathQt5, "include/QtWidgets/QApplication") _
    2768     and LogFileExists(strPathQt5, "include/QtGui/QImage") _
    2769     and LogFileExists(strPathQt5, "include/QtNetwork/QHostAddress") _
    2770    then
    2771       ' Infix testing.
    2772       if   LogFileExists(strPathQt5, "lib/Qt5Core.lib") _
    2773        and LogFileExists(strPathQt5, "lib/Qt5Network.lib") then
    2774          strInfixQt5 = ""
    2775          CheckForQt5Sub = UnixSlashes(PathAbs(strPathQt5))
    2776       elseif LogFileExists(strPathQt5, "lib/Qt5Core" & strOptInfix & ".lib") _
    2777          and LogFileExists(strPathQt5, "lib/Qt5Network" & strOptInfix & ".lib") then
    2778          strInfixQt5 = strOptInfix
    2779          CheckForQt5Sub = UnixSlashes(PathAbs(strPathQt5))
    2780       elseif LogFileExists(strPathQt5, "lib/Qt5CoreVBox.lib") _
    2781          and LogFileExists(strPathQt5, "lib/Qt5NetworkVBox.lib") then
    2782          strInfixQt5 = "VBox"
    2783          CheckForQt5Sub = UnixSlashes(PathAbs(strPathQt5))
    2784       end if
    2785    end if
    2786 end function
    2787 
    2788 
    2789 ''
    2790 ' Checks for python.
    2791 '
    2792 function CheckForPython(strOptPython)
    2793    dim strPathPython, arrVersions, strVer, str
    2794    PrintHdr "Python"
    2795    CheckForPython = False
    2796 
    2797    '
    2798    ' Locate it.
    2799    '
    2800    strPathPython = CheckForPythonSub(strOptPython)
    2801    if strPathPython = "" then
    2802       arrVersions = Array("3.12", "3.11", "3.10", "3.9", "3.8", "3.7", "3.6", "3.5", "2.7")
    2803       for each strVer in arrVersions
    2804          strPathPython = CheckForPythonSub(RegGetString("HKLM\SOFTWARE\Python\PythonCore\" & strVer & "\InstallPath\"))
    2805          if strPathPython <> "" then exit for
    2806       next
    2807    end if
    2808    if strPathPython = "" then strPathPython = CheckForPythonSub(PathStripFilename(Which("python.exe")))
    2809 
    2810    '
    2811    ' Output config & result.
    2812    '
    2813    CheckForPython = strPathPython <> ""
    2814    if CheckForPython then
    2815       CfgPrintAssign "VBOX_BLD_PYTHON", strPathPython
    2816       PrintResult "Python", strPathPython
    2817    else
    2818       PrintResultMsg "Python", "not found"
    2819    end if
    2820 end function
    2821 
    2822 function CheckForPythonSub(strPathPython)
    2823    CheckForPythonSub = ""
    2824    if strPathPython <> "" then
    2825       if   LogFileExists(strPathPython, "python.exe") _
    2826        and LogDirExists(strPathPython & "/DLLs") _
    2827       then
    2828          CheckForPythonSub = UnixSlashes(PathAbs(strPathPython & "/python.exe"))
    2829       end if
    2830    end if
    2831 end function
    2832 
    2833 
    2834 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    2835 '  Main function and usage                                                                                                       '
    2836 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    2837 
    2838 ''
    2839 ' Show usage.
    2840 '
    2841 sub usage
    2842    Print "Usage: cscript configure.vbs [options]"
    2843    Print ""
    2844    Print "Configuration:"
    2845    Print "  -h, --help              Display this."
    2846    Print "  --target-arch=x86|amd64 The target architecture."
    2847    Print "  --continue-on-error     Do not stop on errors."
    2848    Print "  --internal-last         Check internal tools (tools/win.*) last."
    2849    Print "  --internal-first        Check internal tools (tools/win.*) first (default)."
    2850    Print ""
    2851    Print "Components:"
    2852    Print "  --disable-COM           Disables all frontends and API."
    2853    Print "  --disable-SDL           Disables the SDL frontend."
    2854    Print "  --disable-UDPTunnel"
    2855    Print ""
    2856    Print "Locations:"
    2857    Print "  --with-kBuild=PATH      Where kBuild is to be found."
    2858    Print "  --with-libSDL=PATH      Where libSDL is to be found."
    2859    Print "  --with-Qt5=PATH         Where Qt5 is to be found."
    2860    Print "  --with-DDK=PATH         Where the WDK is to be found."
    2861    Print "  --with-SDK=PATH         Where the Windows SDK is to be found."
    2862    Print "  --with-SDK10=PATH       Where the Windows 10 SDK/WDK is to be found."
    2863    Print "  --with-VC=PATH          Where the Visual C++ compiler is to be found."
    2864    Print "                          (Expecting bin, include and lib subdirs.)"
    2865    Print "  --with-VC-Common=PATH   Maybe needed for 2015 and older to"
    2866    Print "                          locate the Common7 directory."
    2867    Print "  --with-midl=PATH        Where midl.exe is to be found."
    2868    Print "  --with-openwatcom=PATH  Where OpenWatcom 1.9 is to be found."
    2869    Print "  --with-python=PATH      The python to use."
    2870    Print "  --with-libxml2=PATH     To use a libxml2 other than the VBox one."
    2871    Print "  --with-openssl=PATH     To use an openssl other than the VBox one."
    2872    Print "  --with-openssl32=PATH   The 32-bit variant of openssl."
    2873    Print "  --with-libcurl=PATH     To use a cURL other than the VBox one."
    2874    Print "  --with-libcurl32=PATH   The 32-bit variant of cURL."
    2875 end sub
    2876 
    2877 
    2878 ''
    2879 ' The main() like function.
    2880 '
    2881 function Main
    2882    '
    2883    ' Write the log header and check that we're not using wscript.
    2884    '
    2885    LogInit
    2886    if UCase(Right(Wscript.FullName, 11)) = "WSCRIPT.EXE" then
    2887       Wscript.Echo "This script must be run under CScript."
    2888       Main = 1
    2889       exit function
    2890    end if
    2891    SelfTest
    2892 
    2893    '
    2894    ' Parse arguments.
    2895    '
    2896    strOptDDK = ""
    2897    strOptDXDDK = ""
    2898    strOptkBuild = ""
    2899    strOptlibSDL = ""
    2900    strOptQt5 = ""
    2901    strOptQt5Infix = ""
    2902    strOptSDK = ""
    2903    strOptSDK10 = ""
    2904    strOptSDK10Version = ""
    2905    strOptVC = ""
    2906    strOptVCCommon = ""
    2907    strOptMidl = ""
    2908    strOptOpenWatcom = ""
    2909    strOptXml2 = ""
    2910    strOptSsl = ""
    2911    strOptSsl32 = ""
    2912    strOptCurl = ""
    2913    strOptCurl32 = ""
    2914    strOptPython = ""
    2915    blnOptDisableCOM = False
    2916    blnOptDisableUDPTunnel = False
    2917    blnOptDisableSDL = False
    2918    for i = 1 to Wscript.Arguments.Count
    2919       dim str, strArg, strPath
    2920 
    2921       ' Separate argument and path value
    2922       str = Wscript.Arguments.item(i - 1)
    2923       if InStr(1, str, "=") > 0 then
    2924          strArg = Mid(str, 1, InStr(1, str, "=") - 1)
    2925          strPath = Mid(str, InStr(1, str, "=") + 1)
    2926          if strPath = "" then MsgFatal "Syntax error! Argument #" & i & " is missing the path."
    2927       else
    2928          strArg = str
    2929          strPath = ""
    2930       end if
    2931 
    2932       ' Process the argument
    2933       select case LCase(strArg)
    2934          ' --with-something:
    2935          case "--with-ddk"
    2936             strOptDDK = strPath
    2937          case "--with-dxsdk"
    2938             MsgWarning "Ignoring --with-dxsdk (the DirectX SDK is no longer required)."
    2939          case "--with-kbuild"
    2940             strOptkBuild = strPath
    2941          case "--with-libsdl"
    2942             strOptlibSDL = strPath
    2943          case "--with-mingw32"
    2944             ' ignore
    2945          case "--with-mingw-w64"
    2946             ' ignore
    2947          case "--with-qt5"
    2948             strOptQt5 = strPath
    2949          case "--with-qt5-infix"
    2950             strOptQt5Infix = strPath
    2951          case "--with-sdk"
    2952             strOptSDK = strPath
    2953          case "--with-sdk10"
    2954             strOptSDK10 = strPath
    2955          case "--with-sdk10-version"
    2956             strOptSDK10Version = strPath
    2957          case "--with-vc"
    2958             strOptVC = strPath
    2959          case "--with-vc-common"
    2960             strOptVCCommon = strPath
    2961          case "--with-vc-express-edition"
    2962             ' ignore
    2963          case "--with-w32api"
    2964             ' ignore
    2965          case "--with-midl"
    2966             strOptMidl = strPath
    2967          case "--with-openwatcom"
    2968             strOptOpenWatcom = strPath
    2969          case "--with-libxml2"
    2970             strOptXml2 = strPath
    2971          case "--with-openssl"
    2972             strOptSsl = strPath
    2973          case "--with-openssl32"
    2974             strOptSsl32 = strPath
    2975          case "--with-libcurl"
    2976             strOptCurl = strPath
    2977          case "--with-libcurl32"
    2978             strOptCurl32 = strPath
    2979          case "--with-python"
    2980             strOptPython = strPath
    2981 
    2982          ' --disable-something/--enable-something
    2983          case "--disable-com"
    2984             blnOptDisableCOM = True
    2985          case "--enable-com"
    2986             blnOptDisableCOM = False
    2987          case "--disable-udptunnel"
    2988             blnOptDisableUDPTunnel = True
    2989          case "--enable-udptunnel"
    2990             blnOptDisableUDPTunnel = False
    2991          case "--disable-sdl"
    2992             blnOptDisableSDL = True
    2993          case "--endable-sdl"
    2994             blnOptDisableSDL = False
    2995 
    2996          ' Other stuff.
    2997          case "--continue-on-error"
    2998             g_blnContinueOnError = True
    2999          case "--internal-first"
    3000             g_blnInternalFirst = True
    3001          case "--internal-last"
    3002             g_blnInternalFirst = False
    3003          case "--target-arch"
    3004             g_strTargetArch = strPath
    3005          case "-h", "--help", "-?"
    3006             usage
    3007             Main = 0
    3008             exit function
    3009          case else
    3010             Wscript.echo "syntax error: Unknown option '" & str &"'."
    3011             usage
    3012             Main = 2
    3013             exit function
    3014       end select
    3015    next
    3016 
    3017    '
    3018    ' Initialize output files.
    3019    '
    3020    CfgInit
    3021    EnvInit
    3022 
    3023    '
    3024    ' Check that the Shell function is sane.
    3025    '
    3026    g_objShell.Environment("PROCESS")("TESTING_ENVIRONMENT_INHERITANCE") = "This works"
    3027    if Shell("set TESTING_ENVIRONMENT_INHERITANC", False) <> 0 then ' The 'E' is missing on purpose (4nt).
    3028       MsgFatal "shell execution test failed!"
    3029    end if
    3030    if g_strShellOutput <> "TESTING_ENVIRONMENT_INHERITANCE=This works" & CHR(13) & CHR(10)  then
    3031       Print "Shell test Test -> '" & g_strShellOutput & "'"
    3032       MsgFatal "shell inheritance or shell execution isn't working right. Make sure you use cmd.exe."
    3033    end if
    3034    g_objShell.Environment("PROCESS")("TESTING_ENVIRONMENT_INHERITANCE") = ""
    3035    Print "Shell inheritance test: OK"
    3036 
    3037    '
    3038    ' Do the checks.
    3039    '
    3040    if blnOptDisableCOM = True then
    3041       DisableCOM "--disable-com"
    3042    end if
    3043    if blnOptDisableUDPTunnel = True then
    3044       DisableUDPTunnel "--disable-udptunnel"
    3045    end if
    3046    CheckSourcePath
    3047    CheckForkBuild       strOptkBuild
    3048    CheckForWinDDK       strOptDDK
    3049    CheckForVisualCPP    strOptVC, strOptVCCommon
    3050    CheckForPlatformSDK  strOptSDK
    3051    CheckForSDK10        strOptSDK10, strOptSDK10Version
    3052    CheckForMidl         strOptMidl
    3053    CheckForOpenWatcom   strOptOpenWatcom
    3054    CfgPrintAssign "VBOX_WITH_LIBVPX",  "" '' @todo look for libvpx 1.1.0+
    3055    CfgPrintAssign "VBOX_WITH_LIBOPUS", "" '' @todo look for libopus 1.2.1+
    3056 
    3057    EnvPrintAppend "PATH", DosSlashes(g_strPath & "\tools\win." & g_strHostArch & "\bin"), ";" '' @todo look for yasm
    3058    if g_strHostArch = "amd64" then
    3059       EnvPrintAppend "PATH", DosSlashes(g_strPath & "\tools\win.x86\bin"), ";"
    3060    else
    3061       EnvPrintCleanup "PATH", DosSlashes(g_strPath & "\tools\win.amd64\bin"), ";"
    3062    end if
    3063    if blnOptDisableSDL = True then
    3064       DisableSDL "--disable-sdl"
    3065    else
    3066       CheckForlibSDL    strOptlibSDL
    3067    end if
    3068    CheckForXml2         strOptXml2
    3069    CheckForSsl          strOptSsl, False
    3070    if g_strTargetArch = "amd64" then
    3071        ' 32-bit openssl required as well
    3072        CheckForSsl      strOptSsl32, True
    3073    end if
    3074    CheckForCurl         strOptCurl, False
    3075    if g_strTargetArch = "amd64" then
    3076        ' 32-bit Curl required as well
    3077        CheckForCurl     strOptCurl32, True
    3078    end if
    3079    CheckForQt           strOptQt5, strOptQt5Infix
    3080    CheckForPython       strOptPython
    3081 
    3082    Print ""
    3083    Print "Execute env.bat once before you start to build VBox:"
    3084    Print ""
    3085    Print "  env.bat"
    3086    Print "  kmk"
    3087    Print ""
    3088    if g_rcScript <> 0 then
    3089       Print "Warning: ignored errors. See above or in configure.log."
    3090    end if
    3091 
    3092    Main = g_rcScript
    3093 end function
    3094 
    3095 '
    3096 ' What crt0.o typically does:
    3097 '
    3098 WScript.Quit(Main())
    3099 
Note: See TracChangeset for help on using the changeset viewer.

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