home *** CD-ROM | disk | FTP | other *** search
/ Programmer Plus 2007 / Programmer-Plus-2007.iso / Programming / Microsoft Plateform / Visual Basic 5.0 / Msvb50.ace / msvb50 / MSVB50 / VB / SETUPKIT / SETUP1 / COMMON.BAS < prev    next >
Encoding:
BASIC Source File  |  1997-02-04  |  66.4 KB  |  1,862 lines

  1. Attribute VB_Name = "basCommon"
  2. Option Explicit
  3. Option Compare Text
  4.  
  5. '
  6. ' Global Constants
  7. '
  8. Global Const gstrNULL$ = ""                             'Empty string
  9.  
  10. Global Const gstrSEP_DIR$ = "\"                         ' Directory separator character
  11. Public Const gstrSEP_REGKEY$ = "\"                      ' Registration key separator character.
  12. Global Const gstrSEP_DRIVE$ = ":"                       ' Driver separater character, e.g., C:\
  13. Global Const gstrSEP_DIRALT$ = "/"                      ' Alternate directory separator character
  14. Global Const gstrSEP_EXT$ = "."                         ' Filename extension separator character
  15. Public Const gstrSEP_PROGID = "."
  16. Public Const gstrSEP_FILE$ = "|"                        ' Use the character for delimiting filename lists because it is not a valid character in a filename.
  17. Public Const gstrSEP_LIST = "|"
  18. Public Const gstrSEP_URL$ = "://"                       ' Separator that follows HPPT in URL address
  19. Public Const gstrSEP_URLDIR$ = "/"                      ' Separator for dividing directories in URL addresses.
  20.  
  21. Global Const gstrUNC$ = "\\"                            'UNC specifier \\
  22. Global Const gstrCOLON$ = ":"
  23. Global Const gstrSwitchPrefix1 = "-"
  24. Global Const gstrSwitchPrefix2 = "/"
  25. Global Const gstrCOMMA$ = ","
  26. Global Const gstrDECIMAL$ = "."
  27. Global Const gstrQUOTE$ = """"
  28. Public Const gstrCCOMMENT$ = "//"                       ' Comment specifier used in C, etc.
  29. Public Const gstrASSIGN$ = "="
  30. Global Const gstrINI_PROTOCOL = "Protocol"
  31. Public Const gstrREMOTEAUTO = "RA"
  32. Public Const gstrDCOM = "DCOM"
  33.  
  34. Global Const gintMAX_SIZE% = 255                        'Maximum buffer size
  35. Global Const gintMAX_PATH_LEN% = 260                    ' Maximum allowed path length including path, filename,
  36.                                                         ' and command line arguments for NT (Intel) and Win95.
  37. Global Const gintMAX_GROUPNAME_LEN% = 30                ' Maximum length that we allow for an NT 3.51 group name.
  38. Global Const gintMIN_BUTTONWIDTH% = 1200
  39. Global Const gsngBUTTON_BORDER! = 1.4
  40.  
  41. Global Const intDRIVE_REMOVABLE% = 2                    'Constants for GetDriveType
  42. Global Const intDRIVE_FIXED% = 3
  43. Global Const intDRIVE_REMOTE% = 4
  44. Global Const intDRIVE_CDROM% = 5
  45. Global Const intDRIVE_RAMDISK% = 6
  46.  
  47. Global Const gintNOVERINFO% = 32767                     'flag indicating no version info
  48.  
  49. 'File names
  50. Global Const gstrFILE_SETUP$ = "SETUP.LST"              'Name of setup information file
  51. Public Const gstrTEMP_DIR$ = "TEMP"
  52. Public Const gstrTMP_DIR$ = "TMP"
  53.  
  54. 'Share type macros for files
  55. Global Const mstrPRIVATEFILE = ""
  56. Global Const mstrSHAREDFILE = "$(Shared)"
  57.  
  58. 'INI File keys
  59. Global Const gstrINI_SETUP$ = "Setup"
  60. Global Const gstrINI_APPNAME$ = "Title"
  61. Global Const gstrINI_APPDIR$ = "DefaultDir"
  62. Global Const gstrINI_APPEXE$ = "AppExe"
  63. Public Const gstrINI_APPTOUNINSTALL = "AppToUninstall"
  64. Global Const gstrINI_APPPATH$ = "AppPath"
  65. Global Const gstrINI_FORCEUSEDEFDEST = "ForceUseDefDir"
  66. Global Const gstrINI_DEFGROUP$ = "DefProgramGroup"
  67.  
  68. Public Const gstrEXT_DEP$ = "DEP"
  69.  
  70. 'Setup information file macros
  71. Global Const gstrAPPDEST$ = "$(AppPath)"
  72. Global Const gstrWINDEST$ = "$(WinPath)"
  73. Global Const gstrWINSYSDEST$ = "$(WinSysPath)"
  74. Global Const gstrWINSYSDESTSYSFILE$ = "$(WinSysPathSysFile)"
  75. Global Const gstrPROGRAMFILES$ = "$(ProgramFiles)"
  76. Global Const gstrCOMMONFILES$ = "$(CommonFiles)"
  77. Global Const gstrCOMMONFILESSYS$ = "$(CommonFilesSys)"
  78. Global Const gstrDAODEST$ = "$(MSDAOPath)"
  79. Public Const gstrDONOTINSTALL$ = "$(DoNotInstall)"
  80.  
  81. 'Mouse Pointer Constants
  82. Global Const gintMOUSE_DEFAULT% = 0
  83. Global Const gintMOUSE_HOURGLASS% = 11
  84.  
  85. 'MsgError() Constants
  86. Global Const MSGERR_ERROR = 1
  87. Global Const MSGERR_WARNING = 2
  88.  
  89. 'MsgBox Constants
  90. Global Const MB_OK = 0                                  'OK button only
  91. Global Const MB_OKCANCEL = 1                            'OK and Cancel buttons
  92. Global Const MB_ABORTRETRYIGNORE = 2                    'Abort, Retry, Ignore buttons
  93. Global Const MB_YESNO = 4                               'Yes and No buttons
  94. Global Const MB_RETRYCANCEL = 5                         'Retry and Cancel buttons
  95. Global Const MB_ICONSTOP = 16                           'Critical message
  96. Global Const MB_ICONQUESTION = 32                       'Warning query
  97. Global Const MB_ICONEXCLAMATION = 48                    'Warning message
  98. Global Const MB_ICONINFORMATION = 64                    'Information message
  99. Global Const MB_DEFBUTTON1 = 0                          'First button is default
  100. Global Const MB_DEFBUTTON2 = 256                        'Second button is default
  101. Global Const MB_DEFBUTTON3 = 512                        'Third button is default
  102.  
  103. 'MsgBox return values
  104. Global Const IDOK = 1                                   'OK button pressed
  105. Global Const IDCANCEL = 2                               'Cancel button pressed
  106. Global Const IDABORT = 3                                'Abort button pressed
  107. Global Const IDRETRY = 4                                'Retry button pressed
  108. Global Const IDIGNORE = 5                               'Ignore button pressed
  109. Global Const IDYES = 6                                  'Yes button pressed
  110. Global Const IDNO = 7                                   'No button pressed
  111.  
  112. '
  113. 'Type Definitions
  114. '
  115. Type OFSTRUCT
  116.     cBytes As Byte
  117.     fFixedDisk As Byte
  118.     nErrCode As Integer
  119.     nReserved1 As Integer
  120.     nReserved2 As Integer
  121.     szPathName As String * 256
  122. End Type
  123.  
  124. Type VERINFO                                            'Version FIXEDFILEINFO
  125.     strPad1 As Long                                     'Pad out struct version
  126.     strPad2 As Long                                     'Pad out struct signature
  127.     nMSLo As Integer                                    'Low word of ver # MS DWord
  128.     nMSHi As Integer                                    'High word of ver # MS DWord
  129.     nLSLo As Integer                                    'Low word of ver # LS DWord
  130.     nLSHi As Integer                                    'High word of ver # LS DWord
  131.     strPad3(1 To 16) As Byte                            'Skip some of VERINFO struct (16 bytes)
  132.     FileOS As Long                                      'Information about the OS this file is targeted for.
  133.     strPad4(1 To 16) As Byte                            'Pad out the resto of VERINFO struct (16 bytes)
  134. End Type
  135.  
  136. Type PROTOCOL
  137.     strName As String
  138.     strFriendlyName As String
  139. End Type
  140.  
  141. Type OSVERSIONINFO 'for GetVersionEx API call
  142.     dwOSVersionInfoSize As Long
  143.     dwMajorVersion As Long
  144.     dwMinorVersion As Long
  145.     dwBuildNumber As Long
  146.     dwPlatformId As Long
  147.     szCSDVersion As String * 128
  148. End Type
  149.  
  150. Global Const OF_EXIST& = &H4000&
  151. Global Const OF_SEARCH& = &H400&
  152. Global Const HFILE_ERROR% = -1
  153.  
  154. '
  155. 'Global Variables
  156. '
  157. Global LF$                                              'single line break
  158. Global LS$                                              'double line break
  159. Public CRLF As String                                   ' Carriage Return/Line Feed
  160. '
  161. ' Global variables used for silent and SMS installation
  162. '
  163. Public gfSilent As Boolean                              ' Whether or not we are doing a silent install
  164. Public gstrSilentLog As String                          ' filename for output during silent install.
  165. Public gfSMS As Boolean                                 ' Whether or not we are doing an SMS silent install
  166. Public gstrMIFFile As String                            ' status output file for SMS
  167. Public gfSMSStatus As Boolean                           ' status of SMS installation
  168. Public gstrSMSDescription As String                     ' description string written to MIF file for SMS installation
  169. Public gfNoUserInput As Boolean                         ' True if either gfSMS or gfSilent is True
  170. Public gfDontLogSMS As Boolean                          ' Prevents MsgFunc from being logged to SMS (e.g., for confirmation messasges)
  171. Public Const MAX_SMS_DESCRIP = 255                      ' SMS does not allow description strings longer than 255 chars.
  172. '
  173. 'List of available protocols
  174. '
  175. Global gProtocol() As PROTOCOL
  176. Global gcProtocols As Integer
  177. '
  178. ' AXDist.exe and wint351.exe needed.  These are self extracting exes
  179. ' that install other files not installed by setup1.
  180. '
  181. Public gfAXDist As Boolean
  182. Public Const gstrFILE_AXDIST = "AXDIST.EXE"
  183. Public gstrAXDISTInstallPath As String
  184. Public gfAXDistChecked As Boolean
  185. Public gfWINt351 As Boolean
  186. Public Const gstrFILE_WINT351 = "WINt351.EXE"
  187. Public gstrWINt351InstallPath As String
  188. Public gfWINt351Checked As Boolean
  189. '
  190. 'API/DLL Declarations for 32 bit SetupToolkit
  191. '
  192. Declare Function DiskSpaceFree Lib "VB5STKIT.DLL" Alias "DISKSPACEFREE" () As Long
  193. Declare Function SetTime Lib "VB5STKIT.DLL" (ByVal strFileGetTime As String, ByVal strFileSetTime As String) As Integer
  194. Declare Function AllocUnit Lib "VB5STKIT.DLL" () As Long
  195. Declare Function GetWinPlatform Lib "VB5STKIT.DLL" () As Long
  196. Declare Function fNTWithShell Lib "VB5STKIT.DLL" () As Boolean
  197. Declare Function FSyncShell Lib "VB5STKIT.DLL" Alias "SyncShell" (ByVal strCmdLine As String, ByVal intCmdShow As Long) As Long
  198. Declare Function DLLSelfRegister Lib "VB5STKIT.DLL" (ByVal lpDllName As String) As Integer
  199. Declare Function GetClsidFromActXFile Lib "VB5STKIT.DLL" (ByVal pszFilename As String, ByVal pszProgID As String, ByVal pszClsid As String) As Long
  200. Declare Function RegisterTLB Lib "VB5STKIT.DLL" (ByVal lpTLBName As String) As Integer
  201. Declare Sub lmemcpy Lib "VB5STKIT.DLL" (strDest As Any, ByVal strSrc As Any, ByVal lBytes As Long)
  202. Declare Function OSfCreateShellGroup Lib "VB5STKIT.DLL" Alias "fCreateShellFolder" (ByVal lpstrDirName As String) As Long
  203. Declare Function OSfCreateShellLink Lib "VB5STKIT.DLL" Alias "fCreateShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String, ByVal lpstrLinkPath As String, ByVal lpstrLinkArguments As String) As Long
  204. Declare Function OSfRemoveShellLink Lib "VB5STKIT.DLL" Alias "fRemoveShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String) As Long
  205. Private Declare Function OSGetLongPathName Lib "VB5STKIT.DLL" Alias "GetLongPathName" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
  206.  
  207. Declare Function OpenFile Lib "kernel32" (ByVal lpFilename As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long
  208. Declare Function GetFullPathName Lib "kernel32" Alias "GetFullPathNameA" (ByVal lpFilename As String, ByVal nBufferLength As Long, ByVal lpBuffer As String, ByVal lpFilePart As String) As Long
  209. Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal lSize As Long, ByVal lpFilename As String) As Long
  210. Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As Any, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lplFilename As String) As Long
  211. Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFilename As String) As Long
  212. Declare Function GetPrivateProfileSectionNames Lib "kernel32" Alias "GetPrivateProfileSectionNamesA" (ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFilename As String) As Long
  213. Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  214. Declare Function GetSystemDirectory Lib "kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  215. Declare Function GetDriveType32 Lib "kernel32" Alias "GetDriveTypeA" (ByVal strWhichDrive As String) As Long
  216. Declare Function GetTempFilename32 Lib "kernel32" Alias "GetTempFileNameA" (ByVal strWhichDrive As String, ByVal lpPrefixString As String, ByVal wUnique As Integer, ByVal lpTempFilename As String) As Long
  217. Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
  218. Declare Function SendMessageString Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long
  219. Public Const LB_FINDSTRINGEXACT = &H1A2
  220. Public Const LB_ERR = (-1)
  221.  
  222. Declare Function VerInstallFile Lib "VERSION.DLL" Alias "VerInstallFileA" (ByVal Flags&, ByVal SrcName$, ByVal DestName$, ByVal SrcDir$, ByVal DestDir$, ByVal CurrDir As Any, ByVal TmpName$, lpTmpFileLen&) As Long
  223. Declare Function GetFileVersionInfoSize Lib "VERSION.DLL" Alias "GetFileVersionInfoSizeA" (ByVal strFilename As String, lVerHandle As Long) As Long
  224. Declare Function GetFileVersionInfo Lib "VERSION.DLL" Alias "GetFileVersionInfoA" (ByVal strFilename As String, ByVal lVerHandle As Long, ByVal lcbSize As Long, lpvData As Byte) As Long
  225. Declare Function VerQueryValue Lib "VERSION.DLL" Alias "VerQueryValueA" (lpvVerData As Byte, ByVal lpszSubBlock As String, lplpBuf As Long, lpcb As Long) As Long
  226. Private Declare Function OSGetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
  227. Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation As OSVERSIONINFO) As Long
  228.  
  229. '-----------------------------------------------------------
  230. ' SUB: AddDirSep
  231. ' Add a trailing directory path separator (back slash) to the
  232. ' end of a pathname unless one already exists
  233. '
  234. ' IN/OUT: [strPathName] - path to add separator to
  235. '-----------------------------------------------------------
  236. '
  237. Sub AddDirSep(strPathName As String)
  238.     If Right(Trim(strPathName), Len(gstrSEP_URLDIR)) <> gstrSEP_URLDIR And _
  239.        Right(Trim(strPathName), Len(gstrSEP_DIR)) <> gstrSEP_DIR Then
  240.         strPathName = RTrim$(strPathName) & gstrSEP_DIR
  241.     End If
  242. End Sub
  243. '-----------------------------------------------------------
  244. ' SUB: AddURLDirSep
  245. ' Add a trailing URL path separator (forward slash) to the
  246. ' end of a URL unless one (or a back slash) already exists
  247. '
  248. ' IN/OUT: [strPathName] - path to add separator to
  249. '-----------------------------------------------------------
  250. '
  251. Sub AddURLDirSep(strPathName As String)
  252.     If Right(Trim(strPathName), Len(gstrSEP_URLDIR)) <> gstrSEP_URLDIR And _
  253.        Right(Trim(strPathName), Len(gstrSEP_DIR)) <> gstrSEP_DIR Then
  254.         strPathName = Trim(strPathName) & gstrSEP_URLDIR
  255.     End If
  256. End Sub
  257.  
  258. '-----------------------------------------------------------
  259. ' FUNCTION: FileExists
  260. ' Determines whether the specified file exists
  261. '
  262. ' IN: [strPathName] - file to check for
  263. '
  264. ' Returns: True if file exists, False otherwise
  265. '-----------------------------------------------------------
  266. '
  267. Function FileExists(ByVal strPathName As String) As Integer
  268.     Dim intFileNum As Integer
  269.  
  270.     On Error Resume Next
  271.  
  272.     '
  273.     ' If the string is quoted, remove the quotes.
  274.     '
  275.     strPathName = strUnQuoteString(strPathName)
  276.     '
  277.     'Remove any trailing directory separator character
  278.     '
  279.     If Right$(strPathName, 1) = gstrSEP_DIR Then
  280.         strPathName = Left$(strPathName, Len(strPathName) - 1)
  281.     End If
  282.  
  283.     '
  284.     'Attempt to open the file, return value of this function is False
  285.     'if an error occurs on open, True otherwise
  286.     '
  287.     intFileNum = FreeFile
  288.     Open strPathName For Input As intFileNum
  289.  
  290.     FileExists = IIf(Err = 0, True, False)
  291.  
  292.     Close intFileNum
  293.  
  294.     Err = 0
  295. End Function
  296.  
  297. '-----------------------------------------------------------
  298. ' FUNCTION: DirExists
  299. '
  300. ' Determines whether the specified directory name exists.
  301. ' This function is used (for example) to determine whether
  302. ' an installation floppy is in the drive by passing in
  303. ' something like 'A:\'.
  304. '
  305. ' IN: [strDirName] - name of directory to check for
  306. '
  307. ' Returns: True if the directory exists, False otherwise
  308. '-----------------------------------------------------------
  309. '
  310. Public Function DirExists(ByVal strDirName As String) As Integer
  311.     Const strWILDCARD$ = "*.*"
  312.  
  313.     Dim strDummy As String
  314.  
  315.     On Error Resume Next
  316.  
  317.     AddDirSep strDirName
  318.     strDummy = Dir$(strDirName & strWILDCARD, vbDirectory)
  319.     DirExists = Not (strDummy = gstrNULL)
  320.  
  321.     Err = 0
  322. End Function
  323.  
  324. '-----------------------------------------------------------
  325. ' FUNCTION: GetDriveType
  326. ' Determine whether a disk is fixed, removable, etc. by
  327. ' calling Windows GetDriveType()
  328. '-----------------------------------------------------------
  329. '
  330. Function GetDriveType(ByVal intDriveNum As Integer) As Integer
  331.     '
  332.     ' This function expects an integer drive number in Win16 or a string in Win32
  333.     '
  334.     Dim strDriveName As String
  335.     
  336.     strDriveName = Chr$(Asc("A") + intDriveNum) & gstrSEP_DRIVE & gstrSEP_DIR
  337.     GetDriveType = CInt(GetDriveType32(strDriveName))
  338. End Function
  339.  
  340. '-----------------------------------------------------------
  341. ' FUNCTION: ReadProtocols
  342. ' Reads the allowable protocols from the specified file.
  343. '
  344. ' IN: [strInputFilename] - INI filename from which to read the protocols
  345. '     [strINISection] - Name of the INI section
  346. '-----------------------------------------------------------
  347. Function ReadProtocols(ByVal strInputFilename As String, ByVal strINISection As String) As Boolean
  348.     Dim intIdx As Integer
  349.     Dim fOk As Boolean
  350.     Dim strInfo As String
  351.     Dim intOffset As Integer
  352.     
  353.     intIdx = 0
  354.     fOk = True
  355.     Erase gProtocol
  356.     gcProtocols = 0
  357.     
  358.     Do
  359.         strInfo = ReadIniFile(strInputFilename, strINISection, gstrINI_PROTOCOL & Format$(intIdx + 1))
  360.         If strInfo <> gstrNULL Then
  361.             intOffset = InStr(strInfo, gstrCOMMA)
  362.             If intOffset > 0 Then
  363.                 'The "ugly" name will be first on the line
  364.                 ReDim Preserve gProtocol(intIdx + 1)
  365.                 gcProtocols = intIdx + 1
  366.                 gProtocol(intIdx + 1).strName = Left$(strInfo, intOffset - 1)
  367.                 
  368.                 '... followed by the friendly name
  369.                 gProtocol(intIdx + 1).strFriendlyName = Mid$(strInfo, intOffset + 1)
  370.                 If (gProtocol(intIdx + 1).strName = "") Or (gProtocol(intIdx + 1).strFriendlyName = "") Then
  371.                     fOk = False
  372.                 End If
  373.             Else
  374.                 fOk = False
  375.             End If
  376.  
  377.             If Not fOk Then
  378.                 Exit Do
  379.             Else
  380.                 intIdx = intIdx + 1
  381.             End If
  382.         End If
  383.     Loop While strInfo <> gstrNULL
  384.     
  385.     ReadProtocols = fOk
  386. End Function
  387.  
  388. '-----------------------------------------------------------
  389. ' FUNCTION: ResolveResString
  390. ' Reads resource and replaces given macros with given values
  391. '
  392. ' Example, given a resource number 14:
  393. '    "Could not read '|1' in drive |2"
  394. '   The call
  395. '     ResolveResString(14, "|1", "TXTFILE.TXT", "|2", "A:")
  396. '   would return the string
  397. '     "Could not read 'TXTFILE.TXT' in drive A:"
  398. '
  399. ' IN: [resID] - resource identifier
  400. '     [varReplacements] - pairs of macro/replacement value
  401. '-----------------------------------------------------------
  402. '
  403. Public Function ResolveResString(ByVal resID As Integer, ParamArray varReplacements() As Variant) As String
  404.     Dim intMacro As Integer
  405.     Dim strResString As String
  406.     
  407.     strResString = LoadResString(resID)
  408.     
  409.     ' For each macro/value pair passed in...
  410.     For intMacro = LBound(varReplacements) To UBound(varReplacements) Step 2
  411.         Dim strMacro As String
  412.         Dim strValue As String
  413.         
  414.         strMacro = varReplacements(intMacro)
  415.         On Error GoTo MismatchedPairs
  416.         strValue = varReplacements(intMacro + 1)
  417.         On Error GoTo 0
  418.         
  419.         ' Replace all occurrences of strMacro with strValue
  420.         Dim intPos As Integer
  421.         Do
  422.             intPos = InStr(strResString, strMacro)
  423.             If intPos > 0 Then
  424.                 strResString = Left$(strResString, intPos - 1) & strValue & Right$(strResString, Len(strResString) - Len(strMacro) - intPos + 1)
  425.             End If
  426.         Loop Until intPos = 0
  427.     Next intMacro
  428.     
  429.     ResolveResString = strResString
  430.     
  431.     Exit Function
  432.     
  433. MismatchedPairs:
  434.     Resume Next
  435. End Function
  436. '-----------------------------------------------------------
  437. ' SUB: GetLicInfoFromVBL
  438. ' Parses a VBL file name and extracts the license key for
  439. ' the registry and license information.
  440. '
  441. ' IN: [strVBLFile] - must be a valid VBL.
  442. '
  443. ' OUT: [strLicKey] - registry key to write license info to.
  444. '                    This key will be added to
  445. '                    HKEY_CLASSES_ROOT\Licenses.  It is a
  446. '                    guid.
  447. ' OUT: [strLicVal] - license information.  Usually in the
  448. '                    form of a string of cryptic characters.
  449. '-----------------------------------------------------------
  450. '
  451. Public Sub GetLicInfoFromVBL(strVBLFile As String, strLicKey As String, strLicVal As String)
  452.     Dim fn As Integer
  453.     Const strREGEDIT = "REGEDIT"
  454.     Const strLICKEYBASE = "HKEY_CLASSES_ROOT\Licenses\"
  455.     Dim strTemp As String
  456.     Dim posEqual As Integer
  457.     Dim fLicFound As Boolean
  458.     
  459.     fn = FreeFile
  460.     Open strVBLFile For Input Access Read Lock Read Write As #fn
  461.     '
  462.     ' Read through the file until we find a line that starts with strLICKEYBASE
  463.     '
  464.     fLicFound = False
  465.     Do While Not EOF(fn)
  466.         Line Input #fn, strTemp
  467.         strTemp = Trim(strTemp)
  468.         If Left$(strTemp, Len(strLICKEYBASE)) = strLICKEYBASE Then
  469.             '
  470.             ' We've got the line we want.
  471.             '
  472.             fLicFound = True
  473.             Exit Do
  474.         End If
  475.     Loop
  476.  
  477.     Close fn
  478.     
  479.     If fLicFound Then
  480.         '
  481.         ' Parse the data on this line to split out the
  482.         ' key and the license info.  The line should be
  483.         ' the form of:
  484.         ' "HKEY_CLASSES_ROOT\Licenses\<lickey> = <licval>"
  485.         '
  486.         posEqual = InStr(strTemp, gstrASSIGN)
  487.         If posEqual > 0 Then
  488.             strLicKey = Mid$(Trim(Left$(strTemp, posEqual - 1)), Len(strLICKEYBASE) + 1)
  489.             strLicVal = Trim(Mid$(strTemp, posEqual + 1))
  490.         End If
  491.     Else
  492.         strLicKey = gstrNULL
  493.         strLicVal = gstrNULL
  494.     End If
  495. End Sub
  496.  
  497.  '-----------------------------------------------------------
  498.  ' FUNCTION GetLongPathName
  499.  '
  500.  ' Retrieve the long pathname version of a path possibly
  501.  '   containing short subdirectory and/or file names
  502.  '-----------------------------------------------------------
  503.  '
  504.  Function GetLongPathName(ByVal strShortPath As String) As String
  505.     Const cchBuffer = 300
  506.     Dim strLongPath As String
  507.     Dim lResult As Long
  508.     
  509.     On Error GoTo 0
  510.     
  511.     strLongPath = String(cchBuffer, Chr$(0))
  512.     lResult = OSGetLongPathName(strShortPath, strLongPath, cchBuffer)
  513.     If lResult = 0 Then
  514.         Error 53 ' File not found
  515.     Else
  516.         GetLongPathName = StripTerminator(strLongPath)
  517.     End If
  518.  End Function
  519.  
  520.  '-----------------------------------------------------------
  521.  ' FUNCTION GetShortPathName
  522.  '
  523.  ' Retrieve the short pathname version of a path possibly
  524.  '   containing long subdirectory and/or file names
  525.  '-----------------------------------------------------------
  526.  '
  527.  Function GetShortPathName(ByVal strLongPath As String) As String
  528.      Const cchBuffer = 300
  529.      Dim strShortPath As String
  530.      Dim lResult As Long
  531.  
  532.      On Error GoTo 0
  533.      strShortPath = String(cchBuffer, Chr$(0))
  534.      lResult = OSGetShortPathName(strLongPath, strShortPath, cchBuffer)
  535.      If lResult = 0 Then
  536.          Error 53 ' File not found
  537.      Else
  538.          GetShortPathName = StripTerminator(strShortPath)
  539.      End If
  540.  End Function
  541.  
  542. '-----------------------------------------------------------
  543. ' FUNCTION: GetTempFilename
  544. ' Get a temporary filename for a specified drive and
  545. ' filename prefix
  546. ' PARAMETERS:
  547. '   strDestPath - Location where temporary file will be created.  If this
  548. '                 is an empty string, then the location specified by the
  549. '                 tmp or temp environment variable is used.
  550. '   lpPrefixString - First three characters of this string will be part of
  551. '                    temporary file name returned.
  552. '   wUnique - Set to 0 to create unique filename.  Can also set to integer,
  553. '             in which case temp file name is returned with that integer
  554. '             as part of the name.
  555. '   lpTempFilename - Temporary file name is returned as this variable.
  556. ' RETURN:
  557. '   True if function succeeds; false otherwise
  558. '-----------------------------------------------------------
  559. '
  560. Function GetTempFilename(ByVal strDestPath As String, ByVal lpPrefixString As String, ByVal wUnique As Integer, lpTempFilename As String) As Boolean
  561.     If strDestPath = gstrNULL Then
  562.         '
  563.         ' No destination was specified, use the temp directory.
  564.         '
  565.         strDestPath = String(gintMAX_PATH_LEN, vbNullChar)
  566.         If GetTempPath(gintMAX_PATH_LEN, strDestPath) = 0 Then
  567.             GetTempFilename = False
  568.             Exit Function
  569.         End If
  570.     End If
  571.     lpTempFilename = String(gintMAX_PATH_LEN, vbNullChar)
  572.     GetTempFilename = GetTempFilename32(strDestPath, lpPrefixString, wUnique, lpTempFilename) > 0
  573.     lpTempFilename = StripTerminator(lpTempFilename)
  574. End Function
  575. '-----------------------------------------------------------
  576. ' FUNCTION: GetDefMsgBoxButton
  577. ' Decode the flags passed to the MsgBox function to
  578. ' determine what the default button is.  Use this
  579. ' for silent installs.
  580. '
  581. ' IN: [intFlags] - Flags passed to MsgBox
  582. '
  583. ' Returns: VB defined number for button
  584. '               vbOK        1   OK button pressed.
  585. '               vbCancel    2   Cancel button pressed.
  586. '               vbAbort     3   Abort button pressed.
  587. '               vbRetry     4   Retry button pressed.
  588. '               vbIgnore    5   Ignore button pressed.
  589. '               vbYes       6   Yes button pressed.
  590. '               vbNo        7   No button pressed.
  591. '-----------------------------------------------------------
  592. '
  593. Function GetDefMsgBoxButton(intFlags) As Integer
  594.     '
  595.     ' First determine the ordinal of the default
  596.     ' button on the message box.
  597.     '
  598.     Dim intButtonNum As Integer
  599.     Dim intDefButton As Integer
  600.     
  601.     If (intFlags And vbDefaultButton2) = vbDefaultButton2 Then
  602.         intButtonNum = 2
  603.     ElseIf (intFlags And vbDefaultButton3) = vbDefaultButton3 Then
  604.         intButtonNum = 3
  605.     Else
  606.         intButtonNum = 1
  607.     End If
  608.     '
  609.     ' Now determine the type of message box we are dealing
  610.     ' with and return the default button.
  611.     '
  612.     If (intFlags And vbRetryCancel) = vbRetryCancel Then
  613.         intDefButton = IIf(intButtonNum = 1, vbRetry, vbCancel)
  614.     ElseIf (intFlags And vbYesNoCancel) = vbYesNoCancel Then
  615.         Select Case intButtonNum
  616.             Case 1
  617.                 intDefButton = vbYes
  618.             Case 2
  619.                 intDefButton = vbNo
  620.             Case 3
  621.                 intDefButton = vbCancel
  622.             'End Case
  623.         End Select
  624.     ElseIf (intFlags And vbOKCancel) = vbOKCancel Then
  625.         intDefButton = IIf(intButtonNum = 1, vbOK, vbCancel)
  626.     ElseIf (intFlags And vbAbortRetryIgnore) = vbAbortRetryIgnore Then
  627.         Select Case intButtonNum
  628.             Case 1
  629.                 intDefButton = vbAbort
  630.             Case 2
  631.                 intDefButton = vbRetry
  632.             Case 3
  633.                 intDefButton = vbIgnore
  634.             'End Case
  635.         End Select
  636.     ElseIf (intFlags And vbYesNo) = vbYesNo Then
  637.         intDefButton = IIf(intButtonNum = 1, vbYes, vbNo)
  638.     Else
  639.         intDefButton = vbOK
  640.     End If
  641.     
  642.     GetDefMsgBoxButton = intDefButton
  643.     
  644. End Function
  645. '-----------------------------------------------------------
  646. ' FUNCTION: GetDiskSpaceFree
  647. ' Get the amount of free disk space for the specified drive
  648. '
  649. ' IN: [strDrive] - drive to check space for
  650. '
  651. ' Returns: Amount of free disk space, or -1 if an error occurs
  652. '-----------------------------------------------------------
  653. '
  654. Function GetDiskSpaceFree(ByVal strDrive As String) As Long
  655.     Dim strCurDrive As String
  656.     Dim lDiskFree As Long
  657.  
  658.     On Error Resume Next
  659.  
  660.     '
  661.     'Save the current drive
  662.     '
  663.     strCurDrive = Left$(CurDir$, 2)
  664.  
  665.     '
  666.     'Fixup drive so it includes only a drive letter and a colon
  667.     '
  668.     If InStr(strDrive, gstrSEP_DRIVE) = 0 Or Len(strDrive) > 2 Then
  669.         strDrive = Left$(strDrive, 1) & gstrSEP_DRIVE
  670.     End If
  671.  
  672.     '
  673.     'Change to the drive we want to check space for.  The DiskSpaceFree() API
  674.     'works on the current drive only.
  675.     '
  676.     ChDrive strDrive
  677.  
  678.     '
  679.     'If we couldn't change to the request drive, it's an error, otherwise return
  680.     'the amount of disk space free
  681.     '
  682.     If Err <> 0 Or (strDrive <> Left$(CurDir$, 2)) Then
  683.         lDiskFree = -1
  684.     Else
  685.         lDiskFree = DiskSpaceFree()
  686.         If Err <> 0 Then    'If Setup Toolkit's DLL couldn't be found
  687.             lDiskFree = -1
  688.         End If
  689.     End If
  690.  
  691.     If lDiskFree = -1 Then
  692.         MsgError Error$ & LS$ & ResolveResString(resDISKSPCERR) & strDrive, MB_ICONEXCLAMATION, gstrTitle
  693.     End If
  694.  
  695.     GetDiskSpaceFree = lDiskFree
  696.  
  697.     '
  698.     'Cleanup by setting the current drive back to the original
  699.     '
  700.     ChDrive strCurDrive
  701.  
  702.     Err = 0
  703. End Function
  704.  
  705. '-----------------------------------------------------------
  706. ' FUNCTION: GetUNCShareName
  707. '
  708. ' Given a UNC names, returns the leftmost portion of the
  709. ' directory representing the machine name and share name.
  710. ' E.g., given "\\SCHWEIZ\PUBLIC\APPS\LISTING.TXT", returns
  711. ' the string "\\SCHWEIZ\PUBLIC"
  712. '
  713. ' Returns a string representing the machine and share name
  714. '   if the path is a valid pathname, else returns NULL
  715. '-----------------------------------------------------------
  716. '
  717. Function GetUNCShareName(ByVal strFN As String) As Variant
  718.     GetUNCShareName = Null
  719.     If IsUNCName(strFN) Then
  720.         Dim iFirstSeparator As Integer
  721.         iFirstSeparator = InStr(3, strFN, gstrSEP_DIR)
  722.         If iFirstSeparator > 0 Then
  723.             Dim iSecondSeparator As Integer
  724.             iSecondSeparator = InStr(iFirstSeparator + 1, strFN, gstrSEP_DIR)
  725.             If iSecondSeparator > 0 Then
  726.                 GetUNCShareName = Left$(strFN, iSecondSeparator - 1)
  727.             Else
  728.                 GetUNCShareName = strFN
  729.             End If
  730.         End If
  731.     End If
  732. End Function
  733.  
  734. '-----------------------------------------------------------
  735. ' FUNCTION: GetWindowsSysDir
  736. '
  737. ' Calls the windows API to get the windows\SYSTEM directory
  738. ' and ensures that a trailing dir separator is present
  739. '
  740. ' Returns: The windows\SYSTEM directory
  741. '-----------------------------------------------------------
  742. '
  743. Function GetWindowsSysDir() As String
  744.     Dim strBuf As String
  745.  
  746.     strBuf = Space$(gintMAX_SIZE)
  747.  
  748.     '
  749.     'Get the system directory and then trim the buffer to the exact length
  750.     'returned and add a dir sep (backslash) if the API didn't return one
  751.     '
  752.     If GetSystemDirectory(strBuf, gintMAX_SIZE) > 0 Then
  753.         strBuf = StripTerminator(strBuf)
  754.         AddDirSep strBuf
  755.         
  756.         GetWindowsSysDir = strBuf
  757.     Else
  758.         GetWindowsSysDir = gstrNULL
  759.     End If
  760. End Function
  761. '-----------------------------------------------------------
  762. ' SUB: TreatAsWin95
  763. '
  764. ' Returns True iff either we're running under Windows 95
  765. ' or we are treating this version of NT as if it were
  766. ' Windows 95 for registry and application loggin and
  767. ' removal purposes.
  768. '-----------------------------------------------------------
  769. '
  770. Function TreatAsWin95() As Boolean
  771.     If IsWindows95() Then
  772.         TreatAsWin95 = True
  773.     ElseIf fNTWithShell() Then
  774.         TreatAsWin95 = True
  775.     Else
  776.         TreatAsWin95 = False
  777.     End If
  778. End Function
  779. '-----------------------------------------------------------
  780. ' FUNCTION: IsDepFile
  781. '
  782. ' Returns true if the file passed to this routine is a
  783. ' dependency (*.dep) file.  We make this determination
  784. ' by verifying that the extension is .dep and that it
  785. ' contains version information.
  786. '-----------------------------------------------------------
  787. '
  788. Function fIsDepFile(strFilename As String) As Boolean
  789.     Const strEXT_DEP = "DEP"
  790.     
  791.     fIsDepFile = False
  792.     
  793.     If UCase(Extension(strFilename)) = strEXT_DEP Then
  794.         If GetFileVersion(strFilename) <> gstrNULL Then
  795.             fIsDepFile = True
  796.         End If
  797.     End If
  798. End Function
  799.  
  800. '-----------------------------------------------------------
  801. ' FUNCTION: IsWin32
  802. '
  803. ' Returns true if this program is running under Win32 (i.e.
  804. '   any 32-bit operating system)
  805. '-----------------------------------------------------------
  806. '
  807. Function IsWin32() As Boolean
  808.     IsWin32 = (IsWindows95() Or IsWindowsNT())
  809. End Function
  810.  
  811. '-----------------------------------------------------------
  812. ' FUNCTION: IsWindows95
  813. '
  814. ' Returns true if this program is running under Windows 95
  815. '   or successor
  816. '-----------------------------------------------------------
  817. '
  818. Function IsWindows95() As Boolean
  819.     Const dwMask95 = &H2&
  820.     If GetWinPlatform() And dwMask95 Then
  821.         IsWindows95 = True
  822.     Else
  823.         IsWindows95 = False
  824.     End If
  825. End Function
  826.  
  827. '-----------------------------------------------------------
  828. ' FUNCTION: IsWindowsNT
  829. '
  830. ' Returns true if this program is running under Windows NT
  831. '-----------------------------------------------------------
  832. '
  833. Function IsWindowsNT() As Boolean
  834.     Const dwMaskNT = &H1&
  835.     If GetWinPlatform() And dwMaskNT Then
  836.         IsWindowsNT = True
  837.     Else
  838.         IsWindowsNT = False
  839.     End If
  840. End Function
  841.  
  842. '-----------------------------------------------------------
  843. ' FUNCTION: IsWindowsNT4WithoutSP2
  844. '
  845. ' Determines if the user is running under Windows NT 4.0
  846. ' but without Service Pack 2 (SP2).  If running under any
  847. ' other platform, returns False.
  848. '
  849. ' IN: [none]
  850. '
  851. ' Returns: True if and only if running under Windows NT 4.0
  852. ' without at least Service Pack 2 installed.
  853. '-----------------------------------------------------------
  854. '
  855. Function IsWindowsNT4WithoutSP2() As Boolean
  856.     IsWindowsNT4WithoutSP2 = False
  857.     
  858.     If Not IsWindowsNT() Then
  859.         Exit Function
  860.     End If
  861.     
  862.     Dim osvi As OSVERSIONINFO
  863.     Dim strCSDVersion As String
  864.     osvi.dwOSVersionInfoSize = Len(osvi)
  865.     If GetVersionEx(osvi) = 0 Then
  866.         Exit Function
  867.     End If
  868.     strCSDVersion = StripTerminator(osvi.szCSDVersion)
  869.     
  870.     'Is this Windows NT 4.0?
  871.     Const NT4MajorVersion = 4
  872.     Const NT4MinorVersion = 0
  873.     If (osvi.dwMajorVersion <> NT4MajorVersion) Or (osvi.dwMinorVersion <> NT4MinorVersion) Then
  874.         'No.  Return False.
  875.         Exit Function
  876.     End If
  877.     
  878.     'If no service pack is installed, or if Service Pack 1 is
  879.     'installed, then return True.
  880.     Const strSP1 = "SERVICE PACK 1"
  881.     If strCSDVersion = "" Then
  882.         IsWindowsNT4WithoutSP2 = True 'No service pack installed
  883.     ElseIf strCSDVersion = strSP1 Then
  884.         IsWindowsNT4WithoutSP2 = True 'Only SP1 installed
  885.     End If
  886. End Function
  887.  
  888. '-----------------------------------------------------------
  889. ' FUNCTION: IsUNCName
  890. '
  891. ' Determines whether the pathname specified is a UNC name.
  892. ' UNC (Universal Naming Convention) names are typically
  893. ' used to specify machine resources, such as remote network
  894. ' shares, named pipes, etc.  An example of a UNC name is
  895. ' "\\SERVER\SHARE\FILENAME.EXT".
  896. '
  897. ' IN: [strPathName] - pathname to check
  898. '
  899. ' Returns: True if pathname is a UNC name, False otherwise
  900. '-----------------------------------------------------------
  901. '
  902. Function IsUNCName(ByVal strPathName As String) As Integer
  903.     Const strUNCNAME$ = "\\//\"        'so can check for \\, //, \/, /\
  904.  
  905.     IsUNCName = ((InStr(strUNCNAME, Left$(strPathName, 2)) > 0) And _
  906.                  (Len(strPathName) > 1))
  907. End Function
  908. '-----------------------------------------------------------
  909. ' FUNCTION: LogSilentMsg
  910. '
  911. ' If this is a silent install, this routine writes
  912. ' a message to the gstrSilentLog file.
  913. '
  914. ' IN: [strMsg] - The message
  915. '
  916. ' Normally, this routine is called inlieu of displaying
  917. ' a MsgBox and strMsg is the same message that would
  918. ' have appeared in the MsgBox
  919. ' (Note: Are we still supporting silent mode?  Rick Andrews)
  920.  
  921. '-----------------------------------------------------------
  922. '
  923. Sub LogSilentMsg(strMsg As String)
  924.     If Not gfSilent Then Exit Sub
  925.     
  926.     Dim fn As Integer
  927.     
  928.     On Error Resume Next
  929.     
  930.     fn = FreeFile
  931.     
  932.     Open gstrSilentLog For Append As fn
  933.     Print #fn, strMsg
  934.     Close fn
  935.     Exit Sub
  936. End Sub
  937. '-----------------------------------------------------------
  938. ' FUNCTION: LogSMSMsg
  939. '
  940. ' If this is a SMS install, this routine appends
  941. ' a message to the gstrSMSDescription string.  This
  942. ' string will later be written to the SMS status
  943. ' file (*.MIF) when the installation completes (success
  944. ' or failure).
  945. '
  946. ' Note that if gfSMS = False, not message will be logged.
  947. ' Therefore, to prevent some messages from being logged
  948. ' (e.g., confirmation only messages), temporarily set
  949. ' gfSMS = False.
  950. '
  951. ' IN: [strMsg] - The message
  952. '
  953. ' Normally, this routine is called inlieu of displaying
  954. ' a MsgBox and strMsg is the same message that would
  955. ' have appeared in the MsgBox
  956. '-----------------------------------------------------------
  957. '
  958. Sub LogSMSMsg(strMsg As String)
  959.     If Not gfSMS Then Exit Sub
  960.     '
  961.     ' Append the message.  Note that the total
  962.     ' length cannot be more than 255 characters, so
  963.     ' truncate anything after that.
  964.     '
  965.     gstrSMSDescription = Left(gstrSMSDescription & strMsg, MAX_SMS_DESCRIP)
  966. End Sub
  967.  
  968. '-----------------------------------------------------------
  969. ' FUNCTION: MakePathAux
  970. '
  971. ' Creates the specified directory path.
  972. '
  973. ' No user interaction occurs if an error is encountered.
  974. ' If user interaction is desired, use the related
  975. '   MakePathAux() function.
  976. '
  977. ' IN: [strDirName] - name of the dir path to make
  978. '
  979. ' Returns: True if successful, False if error.
  980. '-----------------------------------------------------------
  981. '
  982. Function MakePathAux(ByVal strDirName As String) As Boolean
  983.     Dim strPath As String
  984.     Dim intOffset As Integer
  985.     Dim intAnchor As Integer
  986.     Dim strOldPath As String
  987.  
  988.     On Error Resume Next
  989.  
  990.     '
  991.     'Add trailing backslash
  992.     '
  993.     If Right$(strDirName, 1) <> gstrSEP_DIR Then
  994.         strDirName = strDirName & gstrSEP_DIR
  995.     End If
  996.  
  997.     strOldPath = CurDir$
  998.     MakePathAux = False
  999.     intAnchor = 0
  1000.  
  1001.     '
  1002.     'Loop and make each subdir of the path separately.
  1003.     '
  1004.     intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  1005.     intAnchor = intOffset 'Start with at least one backslash, i.e. "C:\FirstDir"
  1006.     Do
  1007.         intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  1008.         intAnchor = intOffset
  1009.  
  1010.         If intAnchor > 0 Then
  1011.             strPath = Left$(strDirName, intOffset - 1)
  1012.             ' Determine if this directory already exists
  1013.             Err = 0
  1014.             ChDir strPath
  1015.             If Err Then
  1016.                 ' We must create this directory
  1017.                 Err = 0
  1018. #If LOGGING Then
  1019.                 NewAction gstrKEY_CREATEDIR, """" & strPath & """"
  1020. #End If
  1021.                 MkDir strPath
  1022. #If LOGGING Then
  1023.                 If Err Then
  1024.                     LogError ResolveResString(resMAKEDIR) & " " & strPath
  1025.                     AbortAction
  1026.                     GoTo Done
  1027.                 Else
  1028.                     CommitAction
  1029.                 End If
  1030. #End If
  1031.             End If
  1032.         End If
  1033.     Loop Until intAnchor = 0
  1034.  
  1035.     MakePathAux = True
  1036. Done:
  1037.     ChDir strOldPath
  1038.  
  1039.     Err = 0
  1040. End Function
  1041.  
  1042. '-----------------------------------------------------------
  1043. ' FUNCTION: MsgError
  1044. '
  1045. ' Forces mouse pointer to default, calls VB's MsgBox
  1046. ' function, and logs this error and (32-bit only)
  1047. ' writes the message and the user's response to the
  1048. ' logfile (32-bit only)
  1049. '
  1050. ' IN: [strMsg] - message to display
  1051. '     [intFlags] - MsgBox function type flags
  1052. '     [strCaption] - caption to use for message box
  1053. '     [intLogType] (optional) - The type of logfile entry to make.
  1054. '                   By default, creates an error entry.  Use
  1055. '                   the MsgWarning() function to create a warning.
  1056. '                   Valid types as MSGERR_ERROR and MSGERR_WARNING
  1057. '
  1058. ' Returns: Result of MsgBox function
  1059. '-----------------------------------------------------------
  1060. '
  1061. Function MsgError(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String, Optional ByVal intLogType As Variant) As Integer
  1062.     Dim iRet As Integer
  1063.     
  1064.     iRet = MsgFunc(strMsg, intFlags, strCaption)
  1065.     MsgError = iRet
  1066. #If LOGGING Then
  1067.     ' We need to log this error and decode the user's response.
  1068.     Dim strID As String
  1069.     Dim strLogMsg As String
  1070.  
  1071.     Select Case iRet
  1072.         Case IDOK
  1073.             strID = ResolveResString(resLOG_IDOK)
  1074.         Case IDCANCEL
  1075.             strID = ResolveResString(resLOG_IDCANCEL)
  1076.         Case IDABORT
  1077.             strID = ResolveResString(resLOG_IDABORT)
  1078.         Case IDRETRY
  1079.             strID = ResolveResString(resLOG_IDRETRY)
  1080.         Case IDIGNORE
  1081.             strID = ResolveResString(resLOG_IDIGNORE)
  1082.         Case IDYES
  1083.             strID = ResolveResString(resLOG_IDYES)
  1084.         Case IDNO
  1085.             strID = ResolveResString(resLOG_IDNO)
  1086.         Case Else
  1087.             strID = ResolveResString(resLOG_IDUNKNOWN)
  1088.         'End Case
  1089.     End Select
  1090.  
  1091.     strLogMsg = strMsg & LF$ & "(" & ResolveResString(resLOG_USERRESPONDEDWITH, "|1", strID) & ")"
  1092.     If IsMissing(intLogType) Then
  1093.         intLogType = MSGERR_ERROR
  1094.     End If
  1095.     Select Case intLogType
  1096.         Case MSGERR_WARNING
  1097.             LogWarning strLogMsg
  1098.         Case MSGERR_ERROR
  1099.             LogError strLogMsg
  1100.         Case Else
  1101.             LogError strLogMsg
  1102.         'End Case
  1103.     End Select
  1104. #End If
  1105. End Function
  1106.  
  1107. '-----------------------------------------------------------
  1108. ' FUNCTION: MsgFunc
  1109. '
  1110. ' Forces mouse pointer to default and calls VB's MsgBox
  1111. ' function.  See also MsgError.
  1112. '
  1113. ' IN: [strMsg] - message to display
  1114. '     [intFlags] - MsgBox function type flags
  1115. '     [strCaption] - caption to use for message box
  1116. ' Returns: Result of MsgBox function
  1117. '-----------------------------------------------------------
  1118. '
  1119. Function MsgFunc(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  1120.     Dim intOldPointer As Integer
  1121.   
  1122.     intOldPointer = Screen.MousePointer
  1123.     If gfNoUserInput Then
  1124.         MsgFunc = GetDefMsgBoxButton(intFlags)
  1125.         If gfSilent = True Then
  1126.             LogSilentMsg strMsg
  1127.         End If
  1128.         If gfSMS = True Then
  1129.             LogSMSMsg strMsg
  1130.             gfDontLogSMS = False
  1131.         End If
  1132.     Else
  1133.         Screen.MousePointer = gintMOUSE_DEFAULT
  1134.         MsgFunc = MsgBox(strMsg, intFlags, strCaption)
  1135.         Screen.MousePointer = intOldPointer
  1136.     End If
  1137. End Function
  1138.  
  1139. '-----------------------------------------------------------
  1140. ' FUNCTION: MsgWarning
  1141. '
  1142. ' Forces mouse pointer to default, calls VB's MsgBox
  1143. ' function, and logs this error and (32-bit only)
  1144. ' writes the message and the user's response to the
  1145. ' logfile (32-bit only)
  1146. '
  1147. ' IN: [strMsg] - message to display
  1148. '     [intFlags] - MsgBox function type flags
  1149. '     [strCaption] - caption to use for message box
  1150. '
  1151. ' Returns: Result of MsgBox function
  1152. '-----------------------------------------------------------
  1153. '
  1154. Function MsgWarning(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  1155.     MsgWarning = MsgError(strMsg, intFlags, strCaption, MSGERR_WARNING)
  1156. End Function
  1157. '-----------------------------------------------------------
  1158. ' SUB: SetFormFont
  1159. '
  1160. ' Walks through all controls on specified form and
  1161. ' sets Font to properties set in the Resource file.
  1162. '
  1163. ' IN: [frm] - Form whose control fonts need to be set.
  1164. '-----------------------------------------------------------
  1165. '
  1166. Public Sub SetFormFont(frm As Form)
  1167.     Dim ctl As Control
  1168.     Dim fntSize As Integer
  1169.     Dim fntName As String
  1170.     Dim fntBold As Boolean
  1171.     '
  1172.     ' this procedure will set the font of every control to
  1173.     ' a font listed in the resource file
  1174.     '
  1175.     ' some controls may fail, so we will do a resume next...
  1176.     '
  1177.     On Error Resume Next
  1178.     '
  1179.     ' get the font name and size from the resource file
  1180.     '
  1181.     fntSize = CInt(LoadResString(resFONTSIZE))
  1182.     fntBold = (LoadResString(resFONTBOLD) = Format(True))
  1183.     fntName = LoadResString(resFONTNAME)
  1184.     '
  1185.     ' set the form's fontname (don't set the size and bold until later)
  1186.     '
  1187.     frm.FontName = fntName
  1188.     If Err.Number <> 0 Then
  1189.         '
  1190.         ' Setting the font failed.  Probably because
  1191.         ' the font wasn't installed.  There are two
  1192.         ' alternate fontnames stored in the resource
  1193.         ' file.  Try these.
  1194.         '
  1195.         Err.Number = 0
  1196.         fntName = LoadResString(resFONTNAMEBACKUP1)
  1197.         frm.FontName = fntName
  1198.         If Err.Number <> 0 Then
  1199.             '
  1200.             ' Still didn't work.  One last chance, try
  1201.             ' the second backup font.  If it fails this
  1202.             ' time, we just continue and use the default
  1203.             ' font.
  1204.             '
  1205.             Err.Number = 0
  1206.             fntName = LoadResString(resFONTNAMEBACKUP2)
  1207.             frm.FontName = fntName
  1208.             Err.Number = 0
  1209.         End If
  1210.     End If
  1211.     '
  1212.     ' Now set the FontSize and FontBold.  This needs to be set
  1213.     ' after the FontName has been set because not all fonts
  1214.     ' support all sizes, etc.
  1215.     '
  1216.     frm.FontSize = fntSize
  1217.     frm.FontBold = fntBold
  1218.     '
  1219.     ' loop through each control and try to set its font property
  1220.     ' this may fail, but our error handling is shut off
  1221.     '
  1222.     For Each ctl In frm.Controls
  1223.         ctl.FontName = fntName
  1224.         ctl.FontSize = fntSize
  1225.         ctl.FontBold = fntBold
  1226.     Next
  1227.     '
  1228.     ' get out, reset error handling
  1229.     '
  1230.     Set ctl = Nothing
  1231.     On Error GoTo 0
  1232.     Exit Sub
  1233.        
  1234. End Sub
  1235.  
  1236. '-----------------------------------------------------------
  1237. ' SUB: SetMousePtr
  1238. '
  1239. ' Provides a way to set the mouse pointer only when the
  1240. ' pointer state changes.  For every HOURGLASS call, there
  1241. ' should be a corresponding DEFAULT call.  Other types of
  1242. ' mouse pointers are set explicitly.
  1243. '
  1244. ' IN: [intMousePtr] - type of mouse pointer desired
  1245. '-----------------------------------------------------------
  1246. '
  1247. Sub SetMousePtr(intMousePtr As Integer)
  1248.     Static intPtrState As Integer
  1249.  
  1250.     Select Case intMousePtr
  1251.         Case gintMOUSE_HOURGLASS
  1252.             intPtrState = intPtrState + 1
  1253.         Case gintMOUSE_DEFAULT
  1254.             intPtrState = intPtrState - 1
  1255.             If intPtrState < 0 Then
  1256.                 intPtrState = 0
  1257.             End If
  1258.         Case Else
  1259.             Screen.MousePointer = intMousePtr
  1260.             Exit Sub
  1261.         'End Case
  1262.     End Select
  1263.  
  1264.     Screen.MousePointer = IIf(intPtrState > 0, gintMOUSE_HOURGLASS, gintMOUSE_DEFAULT)
  1265. End Sub
  1266.  
  1267. '-----------------------------------------------------------
  1268. ' FUNCTION: StripTerminator
  1269. '
  1270. ' Returns a string without any zero terminator.  Typically,
  1271. ' this was a string returned by a Windows API call.
  1272. '
  1273. ' IN: [strString] - String to remove terminator from
  1274. '
  1275. ' Returns: The value of the string passed in minus any
  1276. '          terminating zero.
  1277. '-----------------------------------------------------------
  1278. '
  1279. Function StripTerminator(ByVal strString As String) As String
  1280.     Dim intZeroPos As Integer
  1281.  
  1282.     intZeroPos = InStr(strString, Chr$(0))
  1283.     If intZeroPos > 0 Then
  1284.         StripTerminator = Left$(strString, intZeroPos - 1)
  1285.     Else
  1286.         StripTerminator = strString
  1287.     End If
  1288. End Function
  1289.  
  1290. '-----------------------------------------------------------
  1291. ' FUNCTION: GetFileVersion
  1292. '
  1293. ' Returns the internal file version number for the specified
  1294. ' file.  This can be different than the 'display' version
  1295. ' number shown in the File Manager File Properties dialog.
  1296. ' It is the same number as shown in the VB5 SetupWizard's
  1297. ' File Details screen.  This is the number used by the
  1298. ' Windows VerInstallFile API when comparing file versions.
  1299. '
  1300. ' IN: [strFilename] - the file whose version # is desired
  1301. '     [fIsRemoteServerSupportFile] - whether or not this file is
  1302. '          a remote ActiveX component support file (.VBR)
  1303. '          (Enterprise edition only).  If missing, False is assumed.
  1304. '
  1305. ' Returns: The Version number string if found, otherwise
  1306. '          gstrNULL
  1307. '-----------------------------------------------------------
  1308. '
  1309. Function GetFileVersion(ByVal strFilename As String, Optional ByVal fIsRemoteServerSupportFile) As String
  1310.     Dim sVerInfo As VERINFO
  1311.     Dim strVer As String
  1312.  
  1313.     On Error GoTo GFVError
  1314.  
  1315.     If IsMissing(fIsRemoteServerSupportFile) Then
  1316.         fIsRemoteServerSupportFile = False
  1317.     End If
  1318.     
  1319.     '
  1320.     'Get the file version into a VERINFO struct, and then assemble a version string
  1321.     'from the appropriate elements.
  1322.     '
  1323.     If GetFileVerStruct(strFilename, sVerInfo, fIsRemoteServerSupportFile) = True Then
  1324.         strVer = Format$(sVerInfo.nMSHi) & gstrDECIMAL & Format$(sVerInfo.nMSLo) & gstrDECIMAL
  1325.         strVer = strVer & Format$(sVerInfo.nLSHi) & gstrDECIMAL & Format$(sVerInfo.nLSLo)
  1326.         GetFileVersion = strVer
  1327.     Else
  1328.         GetFileVersion = gstrNULL
  1329.     End If
  1330.     
  1331.     Exit Function
  1332.     
  1333. GFVError:
  1334.     GetFileVersion = gstrNULL
  1335.     Err = 0
  1336. End Function
  1337.  
  1338. '-----------------------------------------------------------
  1339. ' FUNCTION: GetFileVerStruct
  1340. '
  1341. ' Gets the file version information into a VERINFO TYPE
  1342. ' variable
  1343. '
  1344. ' IN: [strFilename] - name of file to get version info for
  1345. '     [fIsRemoteServerSupportFile] - whether or not this file is
  1346. '          a remote ActiveX component support file (.VBR)
  1347. '          (Enterprise edition only).  If missing, False is assumed.
  1348. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1349. '
  1350. ' Returns: True if version info found, False otherwise
  1351. '-----------------------------------------------------------
  1352. '
  1353. Function GetFileVerStruct(ByVal strFilename As String, sVerInfo As VERINFO, Optional ByVal fIsRemoteServerSupportFile) As Boolean
  1354.     Const strFIXEDFILEINFO$ = "\"
  1355.  
  1356.     Dim lVerSize As Long
  1357.     Dim lVerHandle As Long
  1358.     Dim lpBufPtr As Long
  1359.     Dim byteVerData() As Byte
  1360.     Dim fFoundVer As Boolean
  1361.  
  1362.     GetFileVerStruct = False
  1363.     fFoundVer = False
  1364.  
  1365.     If IsMissing(fIsRemoteServerSupportFile) Then
  1366.         fIsRemoteServerSupportFile = False
  1367.     End If
  1368.     
  1369.     If fIsRemoteServerSupportFile Then
  1370.         GetFileVerStruct = GetRemoteSupportFileVerStruct(strFilename, sVerInfo)
  1371.         fFoundVer = True
  1372.     Else
  1373.         '
  1374.         'Get the size of the file version info, allocate a buffer for it, and get the
  1375.         'version info.  Next, we query the Fixed file info portion, where the internal
  1376.         'file version used by the Windows VerInstallFile API is kept.  We then copy
  1377.         'the fixed file info into a VERINFO structure.
  1378.         '
  1379.         lVerSize = GetFileVersionInfoSize(strFilename, lVerHandle)
  1380.         If lVerSize > 0 Then
  1381.             ReDim byteVerData(lVerSize)
  1382.             If GetFileVersionInfo(strFilename, lVerHandle, lVerSize, byteVerData(0)) <> 0 Then ' (Pass byteVerData array via reference to first element)
  1383.                 If VerQueryValue(byteVerData(0), strFIXEDFILEINFO & "", lpBufPtr, lVerSize) <> 0 Then
  1384.                     lmemcpy sVerInfo, lpBufPtr, lVerSize
  1385.                     fFoundVer = True
  1386.                     GetFileVerStruct = True
  1387.                 End If
  1388.             End If
  1389.         End If
  1390.     End If
  1391.     
  1392.     If Not fFoundVer Then
  1393.         '
  1394.         ' We were unsuccessful in finding the version info from the file.
  1395.         ' One possibility is that this is a dependency file.
  1396.         '
  1397.         If UCase(Extension(strFilename)) = gstrEXT_DEP Then
  1398.             GetFileVerStruct = GetDepFileVerStruct(strFilename, sVerInfo)
  1399.         End If
  1400.     End If
  1401. End Function
  1402. '-----------------------------------------------------------
  1403. ' FUNCTION: GetDepFileVerStruct
  1404. '
  1405. ' Gets the file version information from a dependency
  1406. ' file (*.dep).  Such files do not have a Windows version
  1407. ' stamp, but they do have an internal version stamp that
  1408. ' we can look for.
  1409. '
  1410. ' IN: [strFilename] - name of dep file to get version info for
  1411. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1412. '
  1413. ' Returns: True if version info found, False otherwise
  1414. '-----------------------------------------------------------
  1415. '
  1416. Function GetDepFileVerStruct(ByVal strFilename As String, sVerInfo As VERINFO) As Boolean
  1417.     Const strVersionKey = "Version="
  1418.     Dim cchVersionKey As Integer
  1419.     Dim iFile As Integer
  1420.  
  1421.     GetDepFileVerStruct = False
  1422.     
  1423.     cchVersionKey = Len(strVersionKey)
  1424.     sVerInfo.nMSHi = gintNOVERINFO
  1425.     
  1426.     On Error GoTo Failed
  1427.     
  1428.     iFile = FreeFile
  1429.  
  1430.     Open strFilename For Input Access Read Lock Read Write As #iFile
  1431.     
  1432.     ' Loop through each line, looking for the key
  1433.     While (Not EOF(iFile))
  1434.         Dim strLine As String
  1435.  
  1436.         Line Input #iFile, strLine
  1437.         If Left$(strLine, cchVersionKey) = strVersionKey Then
  1438.             ' We've found the version key.  Copy everything after the equals sign
  1439.             Dim strVersion As String
  1440.             
  1441.             strVersion = Mid$(strLine, cchVersionKey + 1)
  1442.             
  1443.             'Parse and store the version information
  1444.             PackVerInfo strVersion, sVerInfo
  1445.  
  1446.             GetDepFileVerStruct = True
  1447.             Close iFile
  1448.             Exit Function
  1449.         End If
  1450.     Wend
  1451.     
  1452.     Close iFile
  1453.     Exit Function
  1454.  
  1455. Failed:
  1456.     GetDepFileVerStruct = False
  1457. End Function
  1458.  
  1459. '-----------------------------------------------------------
  1460. ' FUNCTION: GetRemoteSupportFileVerStruct
  1461. '
  1462. ' Gets the file version information of a remote ActiveX component
  1463. ' support file into a VERINFO TYPE variable (Enterprise
  1464. ' Edition only).  Such files do not have a Windows version
  1465. ' stamp, but they do have an internal version stamp that
  1466. ' we can look for.
  1467. '
  1468. ' IN: [strFilename] - name of file to get version info for
  1469. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  1470. '
  1471. ' Returns: True if version info found, False otherwise
  1472. '-----------------------------------------------------------
  1473. '
  1474. Function GetRemoteSupportFileVerStruct(ByVal strFilename As String, sVerInfo As VERINFO) As Boolean
  1475.     Const strVersionKey = "Version="
  1476.     Dim cchVersionKey As Integer
  1477.     Dim iFile As Integer
  1478.  
  1479.     cchVersionKey = Len(strVersionKey)
  1480.     sVerInfo.nMSHi = gintNOVERINFO
  1481.     
  1482.     On Error GoTo Failed
  1483.     
  1484.     iFile = FreeFile
  1485.  
  1486.     Open strFilename For Input Access Read Lock Read Write As #iFile
  1487.     
  1488.     ' Loop through each line, looking for the key
  1489.     While (Not EOF(iFile))
  1490.         Dim strLine As String
  1491.  
  1492.         Line Input #iFile, strLine
  1493.         If Left$(strLine, cchVersionKey) = strVersionKey Then
  1494.             ' We've found the version key.  Copy everything after the equals sign
  1495.             Dim strVersion As String
  1496.             
  1497.             strVersion = Mid$(strLine, cchVersionKey + 1)
  1498.             
  1499.             'Parse and store the version information
  1500.             PackVerInfo strVersion, sVerInfo
  1501.  
  1502.             'Convert the format 1.2.3 from the .VBR into
  1503.             '1.2.0.3, which is really want we want
  1504.             sVerInfo.nLSLo = sVerInfo.nLSHi
  1505.             sVerInfo.nLSHi = 0
  1506.             
  1507.             GetRemoteSupportFileVerStruct = True
  1508.             Close iFile
  1509.             Exit Function
  1510.         End If
  1511.     Wend
  1512.     
  1513.     Close iFile
  1514.     Exit Function
  1515.  
  1516. Failed:
  1517.     GetRemoteSupportFileVerStruct = False
  1518. End Function
  1519. '-----------------------------------------------------------
  1520. ' FUNCTION: GetWindowsDir
  1521. '
  1522. ' Calls the windows API to get the windows directory and
  1523. ' ensures that a trailing dir separator is present
  1524. '
  1525. ' Returns: The windows directory
  1526. '-----------------------------------------------------------
  1527. '
  1528. Function GetWindowsDir() As String
  1529.     Dim strBuf As String
  1530.  
  1531.     strBuf = Space$(gintMAX_SIZE)
  1532.  
  1533.     '
  1534.     'Get the windows directory and then trim the buffer to the exact length
  1535.     'returned and add a dir sep (backslash) if the API didn't return one
  1536.     '
  1537.     If GetWindowsDirectory(strBuf, gintMAX_SIZE) > 0 Then
  1538.         strBuf = StripTerminator$(strBuf)
  1539.         AddDirSep strBuf
  1540.  
  1541.         GetWindowsDir = strBuf
  1542.     Else
  1543.         GetWindowsDir = gstrNULL
  1544.     End If
  1545. End Function
  1546.  
  1547. '-----------------------------------------------------------
  1548. ' FUNCTION: UCase16
  1549. '
  1550. ' Returns the upper-case conversion of a string
  1551. '   under 16 bits, or else returns an unmodified
  1552. '   copy of the string under 32 bits.
  1553. '
  1554. ' IN: [str] - String to copy/upper-case
  1555. '
  1556. '-----------------------------------------------------------
  1557. '
  1558. Function UCase16(ByVal str As String)
  1559.     UCase16 = str
  1560. End Function
  1561.  
  1562. '-----------------------------------------------------------
  1563. ' FUNCTION: ExtractFilenameItem
  1564. '
  1565. ' Extracts a quoted or unquoted filename from a string.
  1566. '
  1567. ' IN: [str] - string to parse for a filename.
  1568. '     [intAnchor] - index in str at which the filename begins.
  1569. '             The filename continues to the end of the string
  1570. '             or up to the next comma in the string, or, if
  1571. '             the filename is enclosed in quotes, until the
  1572. '             next double quote.
  1573. ' OUT: Returns the filename, without quotes.
  1574. '      [intAnchor] is set to the comma, or else one character
  1575. '             past the end of the string
  1576. '      [fErr] is set to True if a parsing error is discovered
  1577. '
  1578. '-----------------------------------------------------------
  1579. '
  1580. Function strExtractFilenameItem(ByVal str As String, intAnchor As Integer, fErr As Boolean) As String
  1581.     While Mid$(str, intAnchor, 1) = " "
  1582.         intAnchor = intAnchor + 1
  1583.     Wend
  1584.     
  1585.     Dim iEndFilenamePos As Integer
  1586.     Dim strFilename As String
  1587.     If Mid$(str, intAnchor, 1) = """" Then
  1588.         ' Filename is surrounded by quotes
  1589.         iEndFilenamePos = InStr(intAnchor + 1, str, """") ' Find matching quote
  1590.         If iEndFilenamePos > 0 Then
  1591.             strFilename = Mid$(str, intAnchor + 1, iEndFilenamePos - 1 - intAnchor)
  1592.             intAnchor = iEndFilenamePos + 1
  1593.             While Mid$(str, intAnchor, 1) = " "
  1594.                 intAnchor = intAnchor + 1
  1595.             Wend
  1596.             If (Mid$(str, intAnchor, 1) <> gstrCOMMA) And (Mid$(str, intAnchor, 1) <> "") Then
  1597.                 fErr = True
  1598.                 Exit Function
  1599.             End If
  1600.         Else
  1601.             fErr = True
  1602.             Exit Function
  1603.         End If
  1604.     Else
  1605.         ' Filename continues until next comma or end of string
  1606.         Dim iCommaPos As Integer
  1607.         
  1608.         iCommaPos = InStr(intAnchor, str, gstrCOMMA)
  1609.         If iCommaPos = 0 Then
  1610.             iCommaPos = Len(str) + 1
  1611.         End If
  1612.         iEndFilenamePos = iCommaPos
  1613.         
  1614.         strFilename = Mid$(str, intAnchor, iEndFilenamePos - intAnchor)
  1615.         intAnchor = iCommaPos
  1616.     End If
  1617.     
  1618.     strFilename = Trim$(strFilename)
  1619.     If strFilename = "" Then
  1620.         fErr = True
  1621.         Exit Function
  1622.     End If
  1623.     
  1624.     fErr = False
  1625.     strExtractFilenameItem = strFilename
  1626. End Function
  1627.  
  1628. '-----------------------------------------------------------
  1629. ' FUNCTION: Extension
  1630. '
  1631. ' Extracts the extension portion of a file/path name
  1632. '
  1633. ' IN: [strFilename] - file/path to get the extension of
  1634. '
  1635. ' Returns: The extension if one exists, else gstrNULL
  1636. '-----------------------------------------------------------
  1637. '
  1638. Function Extension(ByVal strFilename As String) As String
  1639.     Dim intPos As Integer
  1640.  
  1641.     Extension = gstrNULL
  1642.  
  1643.     intPos = Len(strFilename)
  1644.  
  1645.     Do While intPos > 0
  1646.         Select Case Mid$(strFilename, intPos, 1)
  1647.             Case gstrSEP_EXT
  1648.                 Extension = Mid$(strFilename, intPos + 1)
  1649.                 Exit Do
  1650.             Case gstrSEP_DIR, gstrSEP_DIRALT
  1651.                 Exit Do
  1652.             'End Case
  1653.         End Select
  1654.  
  1655.         intPos = intPos - 1
  1656.     Loop
  1657. End Function
  1658.  
  1659. '-----------------------------------------------------------
  1660. ' SUB: PackVerInfo
  1661. '
  1662. ' Parses a file version number string of the form
  1663. ' x[.x[.x[.x]]] and assigns the extracted numbers to the
  1664. ' appropriate elements of a VERINFO type variable.
  1665. ' Examples of valid version strings are '3.11.0.102',
  1666. ' '3.11', '3', etc.
  1667. '
  1668. ' IN: [strVersion] - version number string
  1669. '
  1670. ' OUT: [sVerInfo] - VERINFO type variable whose elements
  1671. '                   are assigned the appropriate numbers
  1672. '                   from the version number string
  1673. '-----------------------------------------------------------
  1674. '
  1675. Sub PackVerInfo(ByVal strVersion As String, sVerInfo As VERINFO)
  1676.     Dim intOffset As Integer
  1677.     Dim intAnchor As Integer
  1678.  
  1679.     On Error GoTo PVIError
  1680.  
  1681.     intOffset = InStr(strVersion, gstrDECIMAL)
  1682.     If intOffset = 0 Then
  1683.         sVerInfo.nMSHi = Val(strVersion)
  1684.         GoTo PVIMSLo
  1685.     Else
  1686.         sVerInfo.nMSHi = Val(Left$(strVersion, intOffset - 1))
  1687.         intAnchor = intOffset + 1
  1688.     End If
  1689.  
  1690.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1691.     If intOffset = 0 Then
  1692.         sVerInfo.nMSLo = Val(Mid$(strVersion, intAnchor))
  1693.         GoTo PVILSHi
  1694.     Else
  1695.         sVerInfo.nMSLo = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1696.         intAnchor = intOffset + 1
  1697.     End If
  1698.  
  1699.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1700.     If intOffset = 0 Then
  1701.         sVerInfo.nLSHi = Val(Mid$(strVersion, intAnchor))
  1702.         GoTo PVILSLo
  1703.     Else
  1704.         sVerInfo.nLSHi = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1705.         intAnchor = intOffset + 1
  1706.     End If
  1707.  
  1708.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1709.     If intOffset = 0 Then
  1710.         sVerInfo.nLSLo = Val(Mid$(strVersion, intAnchor))
  1711.     Else
  1712.         sVerInfo.nLSLo = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1713.     End If
  1714.  
  1715.     Exit Sub
  1716.  
  1717. PVIError:
  1718.     sVerInfo.nMSHi = 0
  1719. PVIMSLo:
  1720.     sVerInfo.nMSLo = 0
  1721. PVILSHi:
  1722.     sVerInfo.nLSHi = 0
  1723. PVILSLo:
  1724.     sVerInfo.nLSLo = 0
  1725. End Sub
  1726.  
  1727. Public Function strQuoteString(strUnQuotedString As String, Optional vForce As Variant, Optional vTrim As Variant)
  1728. '
  1729. ' This routine adds quotation marks around an unquoted string, by default.  If the string is already quoted
  1730. ' it returns without making any changes unless vForce is set to True (vForce defaults to False) except that white
  1731. ' space before and after the quotes will be removed unless vTrim is False.  If the string contains leading or
  1732. ' trailing white space it is trimmed unless vTrim is set to False (vTrim defaults to True).
  1733. '
  1734.     Dim strQuotedString As String
  1735.     
  1736.     If IsMissing(vForce) Then
  1737.         vForce = False
  1738.     End If
  1739.     If IsMissing(vTrim) Then
  1740.         vTrim = True
  1741.     End If
  1742.     
  1743.     strQuotedString = strUnQuotedString
  1744.     '
  1745.     ' Trim the string if necessary
  1746.     '
  1747.     If vTrim = True Then
  1748.         strQuotedString = Trim(strQuotedString)
  1749.     End If
  1750.     '
  1751.     ' See if the string is already quoted
  1752.     '
  1753.     If vForce = False Then
  1754.         If (Left(strQuotedString, 1) = gstrQUOTE) And (Right(strQuotedString, 1) = gstrQUOTE) Then
  1755.             '
  1756.             ' String is already quoted.  We are done.
  1757.             '
  1758.             GoTo DoneQuoteString
  1759.         End If
  1760.     End If
  1761.     '
  1762.     ' Add the quotes
  1763.     '
  1764.     strQuotedString = gstrQUOTE & strQuotedString & gstrQUOTE
  1765. DoneQuoteString:
  1766.     strQuoteString = strQuotedString
  1767. End Function
  1768. Public Function strUnQuoteString(ByVal strQuotedString As String)
  1769. '
  1770. ' This routine tests to see if strQuotedString is wrapped in quotation
  1771. ' marks, and, if so, remove them.
  1772. '
  1773.     strQuotedString = Trim(strQuotedString)
  1774.  
  1775.     If Mid$(strQuotedString, 1, 1) = gstrQUOTE And Right$(strQuotedString, 1) = gstrQUOTE Then
  1776.         '
  1777.         ' It's quoted.  Get rid of the quotes.
  1778.         '
  1779.         strQuotedString = Mid$(strQuotedString, 2, Len(strQuotedString) - 2)
  1780.     End If
  1781.     strUnQuoteString = strQuotedString
  1782. End Function
  1783. Public Function fCheckFNLength(strFilename As String) As Boolean
  1784. '
  1785. ' This routine verifies that the length of the filename strFilename is valid.
  1786. ' Under NT (Intel) and Win95 it can be up to 259 (gintMAX_PATH_LEN-1) characters
  1787. ' long.  This length must include the drive, path, filename, commandline
  1788. ' arguments and quotes (if the string is quoted).
  1789. '
  1790.     fCheckFNLength = (Len(strFilename) < gintMAX_PATH_LEN)
  1791. End Function
  1792. Public Function intGetNextFldOffset(ByVal intAnchor As Integer, strList As String, strDelimit As String, Optional CompareType As Variant) As Integer
  1793. '
  1794. ' This routine reads from a strDelimit separated list, strList, and locates the next
  1795. ' item in the list following intAnchor.  Basically it finds the next
  1796. ' occurance of strDelimit that is not inside quotes.  If strDelimit is not
  1797. ' found the routine returns 0.  Note intAnchor must be outside of quotes
  1798. ' or this routine will return incorrect results.
  1799. '
  1800. ' strDelimit is typically a comma.
  1801. '
  1802. ' If there is an error this routine returns -1.
  1803. '
  1804.     Dim intQuote As Integer
  1805.     Dim intDelimit As Integer
  1806.     
  1807.     Const CompareBinary = 0
  1808.     Const CompareText = 1
  1809.  
  1810.     If IsMissing(CompareType) Then
  1811.         CompareType = CompareText
  1812.     End If
  1813.     
  1814.     If intAnchor = 0 Then intAnchor = 1
  1815.     
  1816.     intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  1817.     intDelimit = InStr(intAnchor, strList, strDelimit, CompareType)
  1818.     
  1819.     If (intQuote > intDelimit) Or (intQuote = 0) Then
  1820.         '
  1821.         ' The next delimiter is not within quotes.  Therefore,
  1822.         ' we have found what we are looking for.  Note that the
  1823.         ' case where there are no delimiters is also handled here.
  1824.         '
  1825.         GoTo DoneGetNextFldOffset
  1826.     ElseIf intQuote < intDelimit Then
  1827.         '
  1828.         ' A quote appeared before the next delimiter.  This
  1829.         ' means we might be inside quotes.  We still need to check
  1830.         ' if the closing quote comes after the delmiter or not.
  1831.         '
  1832.         intAnchor = intQuote + 1
  1833.         intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  1834.         If (intQuote > intDelimit) Then
  1835.             '
  1836.             ' The delimiter was inside quotes.  Therefore, ignore it.
  1837.             ' The next delimiter after the closing quote must be outside
  1838.             ' of quotes or else we have a corrupt file.
  1839.             '
  1840.             intAnchor = intQuote + 1
  1841.             intDelimit = InStr(intAnchor, strList, strDelimit, CompareType)
  1842.             '
  1843.             ' Sanity check.  Make sure there is not another quote before
  1844.             ' the delimiter we just found.
  1845.             '
  1846.             If intDelimit > 0 Then
  1847.                 intQuote = InStr(intAnchor, strList, gstrQUOTE, CompareType)
  1848.                 If (intQuote > 0) And (intQuote < intDelimit) Then
  1849.                     '
  1850.                     ' Something is wrong.  We've encountered a stray
  1851.                     ' quote.  Means the string is probably corrupt.
  1852.                     '
  1853.                     intDelimit = -1 ' Error
  1854.                 End If
  1855.             End If
  1856.         End If
  1857.     End If
  1858. DoneGetNextFldOffset:
  1859.     intGetNextFldOffset = intDelimit
  1860. End Function
  1861.  
  1862.