home *** CD-ROM | disk | FTP | other *** search
/ Master 95 #1 / MASTER95_1.iso / microsof / vbasic4 / vb4-6.cab / common.bas < prev    next >
Encoding:
BASIC Source File  |  1995-07-26  |  44.4 KB  |  1,236 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. Global Const gstrSEP_DIR$ = "\"                         'Directory separator character
  10. Global Const gstrSEP_DIRALT$ = "/"                      'Alternate directory separator character
  11. Global Const gstrSEP_EXT$ = "."                         'Filename extension separator character
  12. Global Const gstrCOLON$ = ":"
  13. Global Const gstrSwitchPrefix1 = "-"
  14. Global Const gstrSwitchPrefix2 = "/"
  15. Global Const gstrCOMMA$ = ","
  16. Global Const gstrDECIMAL$ = "."
  17. Global Const gstrINI_PROTOCOL = "Protocol"
  18.  
  19. Global Const gintMAX_SIZE% = 255                        'Maximum buffer size
  20. Global Const gintMIN_BUTTONWIDTH% = 1200
  21. Global Const gsngBUTTON_BORDER! = 1.4
  22.  
  23. Global Const intDRIVE_REMOVABLE% = 2                    'Constants for GetDriveType
  24. Global Const intDRIVE_FIXED% = 3
  25. Global Const intDRIVE_REMOTE% = 4
  26.  
  27. Global Const gintNOVERINFO% = 32767                     'flag indicating no version info
  28.  
  29. 'File names
  30. Global Const gstrFILE_SETUP$ = "SETUP.LST"              'Name of setup information file
  31.  
  32. 'Share type macros for files
  33. Global Const mstrPRIVATEFILE = ""
  34. Global Const mstrSHAREDFILE = "$(Shared)"
  35.  
  36. 'INI File keys
  37. #If Win16 Then
  38. Global Const gstrINI_BTRIEVE$ = "Btrieve"
  39. #End If
  40. Global Const gstrINI_SETUP$ = "Setup"
  41. Global Const gstrINI_APPNAME$ = "Title"
  42. Global Const gstrINI_APPDIR$ = "DefaultDir"
  43. Global Const gstrINI_APPEXE$ = "AppExe"
  44. Global Const gstrINI_APPPATH$ = "AppPath"
  45. Global Const gstrINI_FORCEUSEDEFDEST = "ForceUseDefDir"
  46.  
  47. 'Setup information file macros
  48. Global Const gstrAPPDEST$ = "$(AppPath)"
  49. Global Const gstrWINDEST$ = "$(WinPath)"
  50. Global Const gstrWINSYSDEST$ = "$(WinSysPath)"
  51. Global Const gstrWINSYSDESTSYSFILE$ = "$(WinSysPathSysFile)"
  52. Global Const gstrPROGRAMFILES$ = "$(ProgramFiles)"
  53. Global Const gstrCOMMONFILES$ = "$(CommonFiles)"
  54. Global Const gstrCOMMONFILESSYS$ = "$(CommonFilesSys)"
  55. Global Const gstrDAODEST$ = "$(MSDAOPath)"
  56.  
  57. 'Mouse Pointer Constants
  58. Global Const gintMOUSE_DEFAULT% = 0
  59. Global Const gintMOUSE_HOURGLASS% = 11
  60.  
  61. 'MsgError() Constants
  62. Global Const MSGERR_ERROR = 1
  63. Global Const MSGERR_WARNING = 2
  64.  
  65. 'MsgBox Constants
  66. Global Const MB_OK = 0                                  'OK button only
  67. Global Const MB_OKCANCEL = 1                            'OK and Cancel buttons
  68. Global Const MB_ABORTRETRYIGNORE = 2                    'Abort, Retry, Ignore buttons
  69. Global Const MB_YESNO = 4                               'Yes and No buttons
  70. Global Const MB_RETRYCANCEL = 5                         'Retry and Cancel buttons
  71. Global Const MB_ICONSTOP = 16                           'Critical message
  72. Global Const MB_ICONQUESTION = 32                       'Warning query
  73. Global Const MB_ICONEXCLAMATION = 48                    'Warning message
  74. Global Const MB_ICONINFORMATION = 64                    'Information message
  75. Global Const MB_DEFBUTTON1 = 0                          'First button is default
  76. Global Const MB_DEFBUTTON2 = 256                        'Second button is default
  77. Global Const MB_DEFBUTTON3 = 512                        'Third button is default
  78.  
  79. 'MsgBox return values
  80. Global Const IDOK = 1                                   'OK button pressed
  81. Global Const IDCANCEL = 2                               'Cancel button pressed
  82. Global Const IDABORT = 3                                'Abort button pressed
  83. Global Const IDRETRY = 4                                'Retry button pressed
  84. Global Const IDIGNORE = 5                               'Ignore button pressed
  85. Global Const IDYES = 6                                  'Yes button pressed
  86. Global Const IDNO = 7                                   'No button pressed
  87.  
  88. '
  89. 'Type Definitions
  90. '
  91. Type OFSTRUCT
  92.     cBytes As Byte
  93.     fFixedDisk As Byte
  94.     nErrCode As Integer
  95.     nReserved1 As Integer
  96.     nReserved2 As Integer
  97.     szPathName As String * 256
  98. End Type
  99.  
  100. Type VERINFO                                            'Version FIXEDFILEINFO
  101.     strPad1 As Long                                     'Pad out struct version
  102.     strPad2 As Long                                     'Pad out struct signature
  103.     nMSLo As Integer                                    'Low word of ver # MS DWord
  104.     nMSHi As Integer                                    'High word of ver # MS DWord
  105.     nLSLo As Integer                                    'Low word of ver # LS DWord
  106.     nLSHi As Integer                                    'High word of ver # LS DWord
  107.     strPad3(1 To 36) As Byte                            'Pad out rest of VERINFO struct (36 bytes)
  108. End Type
  109.  
  110. Type PROTOCOL
  111.     strName As String
  112.     strFriendlyName As String
  113. End Type
  114.  
  115. Global Const OF_EXIST& = &H4000&
  116. Global Const OF_SEARCH& = &H400&
  117. Global Const HFILE_ERROR% = -1
  118.  
  119. '
  120. 'Global Variables
  121. '
  122. Global LF$                                              'single line break
  123. Global LS$                                              'double line break
  124.  
  125. 'List of available protocols
  126. Global gProtocol() As PROTOCOL
  127. Global gcProtocols As Integer
  128.  
  129.  
  130. #If Win16 Then
  131. '
  132. 'API/DLL Declarations for 16 bit SetupToolkit
  133. '
  134. Declare Function DiskSpaceFree Lib "STKIT416.DLL" () As Long
  135. Declare Function SetTime Lib "STKIT416.DLL" (ByVal strFileGetTime As String, ByVal strFileSetTime As String) As Integer
  136. Declare Function AllocUnit Lib "STKIT416.DLL" () As Long
  137. Declare Function GetWinPlatform Lib "STKIT416.DLL" () As Long
  138. Declare Function DLLSelfRegister Lib "STKIT416.DLL" (ByVal lpDllName As String) As Integer
  139. Declare Sub lmemcpy Lib "STKIT416.DLL" (strDest As Any, ByVal strSrc As Any, ByVal intBytes As Integer)
  140.  
  141. Declare Function OpenFile Lib "Kernel" (ByVal lpFileName As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Integer) As Integer
  142. Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
  143. Declare Function WritePrivateProfileString Lib "Kernel" (ByVal lpApplicationName As Any, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lplFileName As String) As Integer
  144. Declare Function GetWindowsDirectory Lib "Kernel" (ByVal lpBuffer As String, ByVal nSize As Integer) As Integer
  145. Declare Function GetSystemDirectory Lib "Kernel" (ByVal lpBuffer As String, ByVal nSize As Integer) As Integer
  146. Declare Function GetDriveType16 Lib "Kernel" Alias "GetDriveType" (ByVal intDriveNum As Integer) As Integer
  147. Declare Function GetTempFileName16 Lib "Kernel" Alias "GetTempFileName" (ByVal cDriveLetter As Integer, ByVal lpPrefixString As String, ByVal wUnique As Integer, ByVal lpTempFileName As String) As Integer
  148.  
  149. Declare Function VerInstallFile Lib "VER.DLL" (ByVal Flags%, ByVal SrcName$, ByVal DestName$, ByVal SrcDir$, ByVal DestDir$, ByVal CurrDir As Any, ByVal TmpName$, lpTmpFileLen&) As Long
  150. Declare Function GetFileVersionInfoSize Lib "VER.DLL" (ByVal strFileName As String, lVerHandle As Long) As Long
  151. Declare Function GetFileVersionInfo Lib "VER.DLL" (ByVal strFileName As String, ByVal lVerHandle As Long, ByVal lcbSize As Long, lpvData As Byte) As Integer
  152. Declare Function VerQueryValue Lib "VER.DLL" (lpvVerData As Byte, ByVal lpszSubBlock As String, lplpBuf As Long, lpcb As Long) As Integer
  153.  
  154. Declare Function GetModuleUsage Lib "Kernel" (ByVal hModule As Integer) As Integer
  155.  
  156. '-----------------------------------------------------------
  157. ' FUNCTION: FSyncShell
  158. '
  159. ' Executes an external program and waits for it to complete
  160.  
  161. ' Returns: True if the program was started OK, False otherwise
  162. '-----------------------------------------------------------
  163. '
  164. Function FSyncShell(ByVal strExeName As String, intCmdShow As Integer) As Integer
  165.     Const HINSTANCE_ERROR% = 32
  166.     
  167.     Dim hInstChild As Integer
  168.  
  169.     '
  170.     'Shell program, if Shell worked, enter loop
  171.     '
  172.     hInstChild = Shell(strExeName, intCmdShow)
  173.     If hInstChild >= HINSTANCE_ERROR Then
  174.         While GetModuleUsage(hInstChild)
  175.             DoEvents
  176.         Wend
  177.     End If
  178.  
  179.     FSyncShell = IIf(hInstChild < HINSTANCE_ERROR, False, True)
  180. End Function
  181.  
  182. #Else
  183.  
  184. '
  185. 'API/DLL Declarations for 32 bit SetupToolkit
  186. '
  187. Declare Function DiskSpaceFree Lib "STKIT432.DLL" Alias "DISKSPACEFREE" () As Long
  188. Declare Function SetTime Lib "STKIT432.DLL" (ByVal strFileGetTime As String, ByVal strFileSetTime As String) As Integer
  189. Declare Function AllocUnit Lib "STKIT432.DLL" () As Long
  190. Declare Function GetWinPlatform Lib "STKIT432.DLL" () As Long
  191. Declare Function fNTWithShell Lib "STKIT432.DLL" () As Boolean
  192. Declare Function FSyncShell Lib "STKIT432.DLL" Alias "SyncShell" (ByVal strCmdLine As String, ByVal intCmdShow As Long) As Long
  193. Declare Function DLLSelfRegister Lib "STKIT432.DLL" (ByVal lpDllName As String) As Integer
  194. Declare Sub lmemcpy Lib "STKIT432.DLL" (strDest As Any, ByVal strSrc As Any, ByVal lBytes As Long)
  195. Declare Function OSfCreateShellGroup Lib "STKIT432.DLL" Alias "fCreateShellFolder" (ByVal lpstrDirName As String) As Long
  196. Declare Function OSfCreateShellLink Lib "STKIT432.DLL" Alias "fCreateShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String, ByVal lpstrLinkPath As String, ByVal lpstrLinkArguments As String) As Long
  197. Declare Function OSfRemoveShellLink Lib "STKIT432.DLL" Alias "fRemoveShellLink" (ByVal lpstrFolderName As String, ByVal lpstrLinkName As String) As Long
  198. Private Declare Function OSGetLongPathName Lib "STKIT432.DLL" Alias "GetLongPathName" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
  199.  
  200. Declare Function OpenFile Lib "Kernel32" (ByVal lpFileName As String, lpReOpenBuff As OFSTRUCT, ByVal wStyle As Long) As Long
  201. 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
  202. 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
  203. Declare Function GetWindowsDirectory Lib "Kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  204. Declare Function GetSystemDirectory Lib "Kernel32" Alias "GetSystemDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
  205. Declare Function GetDriveType32 Lib "Kernel32" Alias "GetDriveTypeA" (ByVal strWhichDrive As String) As Long
  206. 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
  207.  
  208. 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
  209. Declare Function GetFileVersionInfoSize Lib "VERSION.DLL" Alias "GetFileVersionInfoSizeA" (ByVal strFileName As String, lVerHandle As Long) As Long
  210. 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
  211. Declare Function VerQueryValue Lib "VERSION.DLL" Alias "VerQueryValueA" (lpvVerData As Byte, ByVal lpszSubBlock As String, lplpBuf As Long, lpcb As Long) As Long
  212. Private Declare Function OSGetShortPathName Lib "Kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
  213. #End If
  214.  
  215. '-----------------------------------------------------------
  216. ' SUB: AddDirSep
  217. ' Add a trailing directory path separator (back slash) to the
  218. ' end of a pathname unless one already exists
  219. '
  220. ' IN/OUT: [strPathName] - path to add separator to
  221. '-----------------------------------------------------------
  222. '
  223. Sub AddDirSep(strPathName As String)
  224.     If Right$(RTrim$(strPathName), Len(gstrSEP_DIR)) <> gstrSEP_DIR Then
  225.         strPathName = RTrim$(strPathName) & gstrSEP_DIR
  226.     End If
  227. End Sub
  228.  
  229. '-----------------------------------------------------------
  230. ' FUNCTION: FileExists
  231. ' Determines whether the specified file exists
  232. '
  233. ' IN: [strPathName] - file to check for
  234. '
  235. ' Returns: True if file exists, False otherwise
  236. '-----------------------------------------------------------
  237. '
  238. Function FileExists(ByVal strPathName As String) As Integer
  239.     Dim intFileNum As Integer
  240.  
  241.     On Error Resume Next
  242.  
  243.     '
  244.     'Remove any trailing directory separator character
  245.     '
  246.     If Right$(strPathName, 1) = gstrSEP_DIR Then
  247.         strPathName = Left$(strPathName, Len(strPathName) - 1)
  248.     End If
  249.  
  250.     '
  251.     'Attempt to open the file, return value of this function is False
  252.     'if an error occurs on open, True otherwise
  253.     '
  254.     intFileNum = FreeFile
  255.     Open strPathName For Input As intFileNum
  256.  
  257.     FileExists = IIf(Err, False, True)
  258.  
  259.     Close intFileNum
  260.  
  261.     Err = 0
  262. End Function
  263.  
  264. '-----------------------------------------------------------
  265. ' FUNCTION: GetDriveType
  266. ' Determine whether a disk is fixed, removable, etc. by
  267. ' calling Windows GetDriveType()
  268. '-----------------------------------------------------------
  269. '
  270. Function GetDriveType(ByVal intDriveNum As Integer) As Integer
  271.     '
  272.     ' This function expects an integer drive number in Win16 or a string in Win32
  273.     '
  274. #If Win16 Then
  275.     GetDriveType = GetDriveType16(intDriveNum)
  276. #Else
  277.     Dim strDriveName As String
  278.     
  279.     strDriveName = Chr$(Asc("A") + intDriveNum) & gstrCOLON & gstrSEP_DIR
  280.     GetDriveType = CInt(GetDriveType32(strDriveName))
  281. #End If
  282. End Function
  283.  
  284. '-----------------------------------------------------------
  285. ' FUNCTION: ReadProtocols
  286. ' Reads the allowable protocols from the specified file.
  287. '
  288. ' IN: [strInputFilename] - INI filename from which to read the protocols
  289. '     [strINISection] - Name of the INI section
  290. '-----------------------------------------------------------
  291. Function ReadProtocols(ByVal strInputFilename As String, ByVal strINISection As String) As Boolean
  292.     Dim intIdx As Integer
  293.     Dim fOK As Boolean
  294.     Dim strInfo As String
  295.     Dim intOffset As Integer
  296.     
  297.     intIdx = 0
  298.     fOK = True
  299.     Erase gProtocol
  300.     gcProtocols = 0
  301.     
  302.     Do
  303.         strInfo = ReadIniFile(strInputFilename, strINISection, gstrINI_PROTOCOL & Format$(intIdx + 1))
  304.         If strInfo <> gstrNULL Then
  305.             intOffset = InStr(strInfo, gstrCOMMA)
  306.             If intOffset > 0 Then
  307.                 'The "ugly" name will be first on the line
  308.                 ReDim Preserve gProtocol(intIdx + 1)
  309.                 gcProtocols = intIdx + 1
  310.                 gProtocol(intIdx + 1).strName = Left$(strInfo, intOffset - 1)
  311.                 
  312.                 '... followed by the friendly name
  313.                 gProtocol(intIdx + 1).strFriendlyName = Mid$(strInfo, intOffset + 1)
  314.                 If (gProtocol(intIdx + 1).strName = "") Or (gProtocol(intIdx + 1).strFriendlyName = "") Then
  315.                     fOK = False
  316.                 End If
  317.             Else
  318.                 fOK = False
  319.             End If
  320.  
  321.             If Not fOK Then
  322.                 Exit Do
  323.             Else
  324.                 intIdx = intIdx + 1
  325.             End If
  326.         End If
  327.     Loop While strInfo <> gstrNULL
  328.     
  329.     ReadProtocols = fOK
  330. End Function
  331.  
  332. '-----------------------------------------------------------
  333. ' FUNCTION: ResolveResString
  334. ' Reads resource and replaces given macros with given values
  335. '
  336. ' Example, given a resource number 14:
  337. '    "Could not read '|1' in drive |2"
  338. '   The call
  339. '     ResolveResString(14, "|1", "TXTFILE.TXT", "|2", "A:")
  340. '   would return the string
  341. '     "Could not read 'TXTFILE.TXT' in drive A:"
  342. '
  343. ' IN: [resID] - resource identifier
  344. '     [varReplacements] - pairs of macro/replacement value
  345. '-----------------------------------------------------------
  346. '
  347. Function ResolveResString(ByVal resID As Integer, ParamArray varReplacements() As Variant) As String
  348.     Dim intMacro As Integer
  349.     Dim strResString As String
  350.     
  351.     strResString = LoadResString(resID)
  352.     
  353.     ' For each macro/value pair passed in...
  354.     For intMacro = LBound(varReplacements) To UBound(varReplacements) Step 2
  355.         Dim strMacro As String
  356.         Dim strValue As String
  357.         
  358.         strMacro = varReplacements(intMacro)
  359.         On Error GoTo MismatchedPairs
  360.         strValue = varReplacements(intMacro + 1)
  361.         On Error GoTo 0
  362.         
  363.         ' Replace all occurrences of strMacro with strValue
  364.         Dim intPos As Integer
  365.         Do
  366.             intPos = InStr(strResString, strMacro)
  367.             If intPos > 0 Then
  368.                 strResString = Left$(strResString, intPos - 1) & strValue & Right$(strResString, Len(strResString) - Len(strMacro) - intPos + 1)
  369.             End If
  370.         Loop Until intPos = 0
  371.     Next intMacro
  372.     
  373.     ResolveResString = strResString
  374.     
  375.     Exit Function
  376.     
  377. MismatchedPairs:
  378.     Resume Next
  379. End Function
  380.  
  381.  '-----------------------------------------------------------
  382.  ' FUNCTION GetLongPathName
  383.  '
  384.  ' Retrieve the long pathname version of a path possibly
  385.  '   containing short subdirectory and/or file names
  386.  '-----------------------------------------------------------
  387.  '
  388.  #If Win32 Then
  389.  Function GetLongPathName(ByVal strShortPath As String) As String
  390.      Const cchBuffer = 300
  391.      Dim strLongPath As String * cchBuffer
  392.      Dim lResult As Long
  393.  
  394.      On Error GoTo 0
  395.      lResult = OSGetLongPathName(strShortPath, strLongPath, cchBuffer)
  396.      If lResult = 0 Then
  397.          Error 53 ' File not found
  398.      Else
  399.          GetLongPathName = StripTerminator(strLongPath)
  400.      End If
  401.  End Function
  402.  #End If
  403.  
  404.  '-----------------------------------------------------------
  405.  ' FUNCTION GetShortPathName
  406.  '
  407.  ' Retrieve the short pathname version of a path possibly
  408.  '   containing long subdirectory and/or file names
  409.  '-----------------------------------------------------------
  410.  '
  411.  #If Win32 Then
  412.  Function GetShortPathName(ByVal strLongPath As String) As String
  413.      Const cchBuffer = 300
  414.      Dim strShortPath As String * cchBuffer
  415.      Dim lResult As Long
  416.  
  417.      On Error GoTo 0
  418.      lResult = OSGetShortPathName(strLongPath, strShortPath, cchBuffer)
  419.      If lResult = 0 Then
  420.          Error 53 ' File not found
  421.      Else
  422.          GetShortPathName = StripTerminator(strShortPath)
  423.      End If
  424.  End Function
  425.  #End If
  426.  
  427. '-----------------------------------------------------------
  428. ' FUNCTION: GetTempFileName
  429. ' Get a temporary filename for a specified drive and
  430. ' filename prefix
  431. '-----------------------------------------------------------
  432. '
  433. Function GetTempFileName(ByVal cDriveLetter As Integer, ByVal lpPrefixString As String, ByVal wUnique As Integer, lpTempFileName As String) As Integer
  434.     '
  435.     ' This function expects an integer drive number in Win16 or a string in Win32
  436.     '
  437. #If Win16 Then
  438.     GetTempFileName = GetTempFileName16(cDriveLetter, lpPrefixString, wUnique, lpTempFileName)
  439. #Else
  440.     Dim strDriveName As String
  441.     
  442.     strDriveName = Chr$(Asc("A") + cDriveLetter) & gstrCOLON & gstrSEP_DIR
  443.     GetTempFileName = CInt(GetTempFileName32(strDriveName, lpPrefixString, wUnique, lpTempFileName))
  444. #End If
  445. End Function
  446.  
  447. '-----------------------------------------------------------
  448. ' FUNCTION: GetDiskSpaceFree
  449. ' Get the amount of free disk space for the specified drive
  450. '
  451. ' IN: [strDrive] - drive to check space for
  452. '
  453. ' Returns: Amount of free disk space, or -1 if an error occurs
  454. '-----------------------------------------------------------
  455. '
  456. Function GetDiskSpaceFree(ByVal strDrive As String) As Long
  457.     Dim strCurDrive As String
  458.     Dim lDiskFree As Long
  459.  
  460.     On Error Resume Next
  461.  
  462.     '
  463.     'Save the current drive
  464.     '
  465.     strCurDrive = Left$(CurDir$, 2)
  466.  
  467.     '
  468.     'Fixup drive so it includes only a drive letter and a colon
  469.     '
  470.     If InStr(strDrive, gstrCOLON) = 0 Or Len(strDrive) > 2 Then
  471.         strDrive = Left$(strDrive, 1) & gstrCOLON
  472.     End If
  473.  
  474.     '
  475.     'Change to the drive we want to check space for.  The DiskSpaceFree() API
  476.     'works on the current drive only.
  477.     '
  478.     ChDrive strDrive
  479.  
  480.     '
  481.     'If we couldn't change to the request drive, it's an error, otherwise return
  482.     'the amount of disk space free
  483.     '
  484.     If Err <> 0 Or (strDrive <> Left$(CurDir$, 2)) Then
  485.         lDiskFree = -1
  486.     Else
  487.         lDiskFree = DiskSpaceFree()
  488.         If Err <> 0 Then    'If Setup Toolkit's DLL couldn't be found
  489.             lDiskFree = -1
  490.         End If
  491.     End If
  492.  
  493.     If lDiskFree = -1 Then
  494.         MsgError Error$ & LS$ & ResolveResString(resDISKSPCERR) & strDrive, MB_ICONEXCLAMATION, gstrTitle
  495.     End If
  496.  
  497.     GetDiskSpaceFree = lDiskFree
  498.  
  499.     '
  500.     'Cleanup by setting the current drive back to the original
  501.     '
  502.     ChDrive strCurDrive
  503.  
  504.     Err = 0
  505. End Function
  506.  
  507. '-----------------------------------------------------------
  508. ' FUNCTION: GetUNCShareName
  509. '
  510. ' Given a UNC names, returns the leftmost portion of the
  511. ' directory representing the machine name and share name.
  512. ' E.g., given "\\SCHWEIZ\PUBLIC\APPS\LISTING.TXT", returns
  513. ' the string "\\SCHWEIZ\PUBLIC"
  514. '
  515. ' Returns a string representing the machine and share name
  516. '   if the path is a valid pathname, else returns NULL
  517. '-----------------------------------------------------------
  518. '
  519. Function GetUNCShareName(ByVal strFN As String) As Variant
  520.     GetUNCShareName = Null
  521.     If IsUNCName(strFN) Then
  522.         Dim iFirstSeparator As Integer
  523.         iFirstSeparator = InStr(3, strFN, gstrSEP_DIR)
  524.         If iFirstSeparator > 0 Then
  525.             Dim iSecondSeparator As Integer
  526.             iSecondSeparator = InStr(iFirstSeparator + 1, strFN, gstrSEP_DIR)
  527.             If iSecondSeparator > 0 Then
  528.                 GetUNCShareName = Left$(strFN, iSecondSeparator - 1)
  529.             Else
  530.                 GetUNCShareName = strFN
  531.             End If
  532.         End If
  533.     End If
  534. End Function
  535.  
  536. '-----------------------------------------------------------
  537. ' FUNCTION: GetWindowsSysDir
  538. '
  539. ' Calls the windows API to get the windows\SYSTEM directory
  540. ' and ensures that a trailing dir separator is present
  541. '
  542. ' Returns: The windows\SYSTEM directory
  543. '-----------------------------------------------------------
  544. '
  545. Function GetWindowsSysDir() As String
  546.     Dim strBuf As String
  547.  
  548.     strBuf = Space$(gintMAX_SIZE)
  549.  
  550.     '
  551.     'Get the system directory and then trim the buffer to the exact length
  552.     'returned and add a dir sep (backslash) if the API didn't return one
  553.     '
  554.     If GetSystemDirectory(strBuf, gintMAX_SIZE) > 0 Then
  555.         strBuf = StripTerminator(strBuf)
  556.         AddDirSep strBuf
  557.         
  558.         GetWindowsSysDir = UCase16(strBuf)
  559.     Else
  560.         GetWindowsSysDir = gstrNULL
  561.     End If
  562. End Function
  563.  
  564. '-----------------------------------------------------------
  565. ' FUNCTION: IsWin32
  566. '
  567. ' Returns true if this program is running under Win32 (i.e.
  568. '   any 32-bit operating system)
  569. '-----------------------------------------------------------
  570. '
  571. Function IsWin32() As Boolean
  572.     IsWin32 = (IsWindows95() Or IsWindowsNT())
  573. End Function
  574.  
  575. '-----------------------------------------------------------
  576. ' FUNCTION: IsWindows95
  577. '
  578. ' Returns true if this program is running under Windows 95
  579. '   or successor
  580. '-----------------------------------------------------------
  581. '
  582. Function IsWindows95() As Boolean
  583.     Const dwMask95 = &H2&
  584.     If GetWinPlatform() And dwMask95 Then
  585.         IsWindows95 = True
  586.     Else
  587.         IsWindows95 = False
  588.     End If
  589. End Function
  590.  
  591. '-----------------------------------------------------------
  592. ' FUNCTION: IsWindowsNT
  593. '
  594. ' Returns true if this program is running under Windows NT
  595. '-----------------------------------------------------------
  596. '
  597. Function IsWindowsNT() As Boolean
  598.     Const dwMaskNT = &H1&
  599.     If GetWinPlatform() And dwMaskNT Then
  600.         IsWindowsNT = True
  601.     Else
  602.         IsWindowsNT = False
  603.     End If
  604. End Function
  605.  
  606. '-----------------------------------------------------------
  607. ' FUNCTION: IsUNCName
  608. '
  609. ' Determines whether the pathname specified is a UNC name.
  610. ' UNC (Universal Naming Convention) names are typically
  611. ' used to specify machine resources, such as remote network
  612. ' shares, named pipes, etc.  An example of a UNC name is
  613. ' "\\SERVER\SHARE\FILENAME.EXT".
  614. '
  615. ' IN: [strPathName] - pathname to check
  616. '
  617. ' Returns: True if pathname is a UNC name, False otherwise
  618. '-----------------------------------------------------------
  619. '
  620. Function IsUNCName(ByVal strPathName As String) As Integer
  621.     Const strUNCNAME$ = "\\//\"        'so can check for \\, //, \/, /\
  622.  
  623.     IsUNCName = IIf(InStr(strUNCNAME, Left$(strPathName, 2)) > 0, True, False)
  624. End Function
  625.  
  626. '-----------------------------------------------------------
  627. ' FUNCTION: MakePathAux
  628. '
  629. ' Creates the specified directory path.
  630. '
  631. ' No user interaction occurs if an error is encountered.
  632. ' If user interaction is desired, use the related
  633. '   MakePathAux() function.
  634. '
  635. ' IN: [strDirName] - name of the dir path to make
  636. '
  637. ' Returns: True if successful, False if error.
  638. '-----------------------------------------------------------
  639. '
  640. Function MakePathAux(ByVal strDirName As String) As Boolean
  641.     Dim strPath As String
  642.     Dim intOffset As Integer
  643.     Dim intAnchor As Integer
  644.     Dim strOldPath As String
  645.  
  646.     On Error Resume Next
  647.  
  648.     '
  649.     'Add trailing backslash
  650.     '
  651.     If Right$(strDirName, 1) <> gstrSEP_DIR Then
  652.         strDirName = strDirName & gstrSEP_DIR
  653.     End If
  654.  
  655.     strOldPath = CurDir$
  656.     MakePathAux = False
  657.     intAnchor = 0
  658.  
  659.     '
  660.     'Loop and make each subdir of the path separately.
  661.     '
  662.     '
  663.     intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  664.     intAnchor = intOffset 'Start with at least one backslash, i.e. "C:\FirstDir"
  665.     Do
  666.         intOffset = InStr(intAnchor + 1, strDirName, gstrSEP_DIR)
  667.         intAnchor = intOffset
  668.  
  669.         If intAnchor > 0 Then
  670.             strPath = Left$(strDirName, intOffset - 1)
  671.             ' Determine if this directory already exists
  672.             Err = 0
  673.             ChDir strPath
  674.             If Err Then
  675.                 ' We must create this directory
  676.                 Err = 0
  677.                 #If Win32 And LOGGING Then
  678.                     NewAction gstrKEY_CREATEDIR, """" & strPath & """"
  679.                 #End If
  680.                 MkDir strPath
  681.                 #If Win32 And LOGGING Then
  682.                     If Err Then
  683.                         LogError ResolveResString(resMAKEDIR) & " " & strPath
  684.                         AbortAction
  685.                         GoTo Done
  686.                     Else
  687.                         CommitAction
  688.                     End If
  689.                 #End If
  690.             End If
  691.         End If
  692.     Loop Until intAnchor = 0
  693.  
  694.     MakePathAux = True
  695. Done:
  696.     ChDir strOldPath
  697.  
  698.     Err = 0
  699. End Function
  700.  
  701. '-----------------------------------------------------------
  702. ' FUNCTION: MsgError
  703. '
  704. ' Forces mouse pointer to default, calls VB's MsgBox
  705. ' function, and logs this error and (32-bit only)
  706. ' writes the message and the user's response to the
  707. ' logfile (32-bit only)
  708. '
  709. ' IN: [strMsg] - message to display
  710. '     [intFlags] - MsgBox function type flags
  711. '     [strCaption] - caption to use for message box
  712. '     [intLogType] (optional) - The type of logfile entry to make.
  713. '                   By default, creates an error entry.  Use
  714. '                   the MsgWarning() function to create a warning.
  715. '                   Valid types as MSGERR_ERROR and MSGERR_WARNING
  716. '
  717. ' Returns: Result of MsgBox function
  718. '-----------------------------------------------------------
  719. '
  720. Function MsgError(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String, Optional ByVal intLogType As Variant) As Integer
  721.     Dim iRet As Integer
  722.     
  723.     iRet = MsgFunc(strMsg, intFlags, strCaption)
  724.     MsgError = iRet
  725.     
  726.     #If Win32 And LOGGING Then
  727.         ' We need to log this error and decode the user's response.
  728.         Dim strID As String
  729.         Dim strLogMsg As String
  730.  
  731.         Select Case iRet
  732.         Case IDOK
  733.             strID = ResolveResString(resLOG_IDOK)
  734.         Case IDCANCEL
  735.             strID = ResolveResString(resLOG_IDCANCEL)
  736.         Case IDABORT
  737.             strID = ResolveResString(resLOG_IDABORT)
  738.         Case IDRETRY
  739.             strID = ResolveResString(resLOG_IDRETRY)
  740.         Case IDIGNORE
  741.             strID = ResolveResString(resLOG_IDIGNORE)
  742.         Case IDYES
  743.             strID = ResolveResString(resLOG_IDYES)
  744.         Case IDNO
  745.             strID = ResolveResString(resLOG_IDNO)
  746.         Case Else
  747.             strID = ResolveResString(resLOG_IDUNKNOWN)
  748.         End Select
  749.  
  750.         strLogMsg = strMsg & LF$ & "(" & ResolveResString(resLOG_USERRESPONDEDWITH, "|1", strID) & ")"
  751.         If IsMissing(intLogType) Then
  752.             intLogType = MSGERR_ERROR
  753.         End If
  754.         Select Case intLogType
  755.         Case MSGERR_WARNING
  756.             LogWarning strLogMsg
  757.         Case MSGERR_ERROR
  758.             LogError strLogMsg
  759.         Case Else
  760.             LogError strLogMsg
  761.         End Select
  762.     #End If
  763. End Function
  764.  
  765. '-----------------------------------------------------------
  766. ' FUNCTION: MsgFunc
  767. '
  768. ' Forces mouse pointer to default and calls VB's MsgBox
  769. ' function
  770. '
  771. ' IN: [strMsg] - message to display
  772. '     [intFlags] - MsgBox function type flags
  773. '     [strCaption] - caption to use for message box
  774. '     [fLogAsError] - If present and True (MSGBOX_ERR), the 32-bit
  775. '                       version logs this message and the user's
  776. '                       response in the logfile as an error.
  777. '                       Otherwise it is presented to the user
  778. '                       only.  (It is easier to use the MsgError()
  779. '                       function.)
  780. ' Returns: Result of MsgBox function
  781. '-----------------------------------------------------------
  782. '
  783. Function MsgFunc(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  784.     Dim intOldPointer As Integer
  785.   
  786.     intOldPointer = Screen.MousePointer
  787.  
  788.     Screen.MousePointer = gintMOUSE_DEFAULT
  789.     MsgFunc = MsgBox(strMsg, intFlags, strCaption)
  790.     Screen.MousePointer = intOldPointer
  791. End Function
  792.  
  793. '-----------------------------------------------------------
  794. ' FUNCTION: MsgWarning
  795. '
  796. ' Forces mouse pointer to default, calls VB's MsgBox
  797. ' function, and logs this error and (32-bit only)
  798. ' writes the message and the user's response to the
  799. ' logfile (32-bit only)
  800. '
  801. ' IN: [strMsg] - message to display
  802. '     [intFlags] - MsgBox function type flags
  803. '     [strCaption] - caption to use for message box
  804. '
  805. ' Returns: Result of MsgBox function
  806. '-----------------------------------------------------------
  807. '
  808. Function MsgWarning(ByVal strMsg As String, ByVal intFlags As Integer, ByVal strCaption As String) As Integer
  809.     MsgWarning = MsgError(strMsg, intFlags, strCaption, MSGERR_WARNING)
  810. End Function
  811.  
  812. '-----------------------------------------------------------
  813. ' SUB: SetMousePtr
  814. '
  815. ' Provides a way to set the mouse pointer only when the
  816. ' pointer state changes.  For every HOURGLASS call, there
  817. ' should be a corresponding DEFAULT call.  Other types of
  818. ' mouse pointers are set explicitly.
  819. '
  820. ' IN: [intMousePtr] - type of mouse pointer desired
  821. '-----------------------------------------------------------
  822. '
  823. Sub SetMousePtr(intMousePtr As Integer)
  824.     Static intPtrState As Integer
  825.  
  826.     Select Case intMousePtr
  827.     Case gintMOUSE_HOURGLASS
  828.         intPtrState = intPtrState + 1
  829.     Case gintMOUSE_DEFAULT
  830.         intPtrState = intPtrState - 1
  831.         If intPtrState < 0 Then
  832.             intPtrState = 0
  833.         End If
  834.     Case Else
  835.         Screen.MousePointer = intMousePtr
  836.         Exit Sub
  837.     End Select
  838.  
  839.     Screen.MousePointer = IIf(intPtrState > 0, gintMOUSE_HOURGLASS, gintMOUSE_DEFAULT)
  840. End Sub
  841.  
  842. '-----------------------------------------------------------
  843. ' FUNCTION: StripTerminator
  844. '
  845. ' Returns a string without any zero terminator.  Typically,
  846. ' this was a string returned by a Windows API call.
  847. '
  848. ' IN: [strString] - String to remove terminator from
  849. '
  850. ' Returns: The value of the string passed in minus any
  851. '          terminating zero.
  852. '-----------------------------------------------------------
  853. '
  854. Function StripTerminator(ByVal strString As String) As String
  855.     Dim intZeroPos As Integer
  856.  
  857.     intZeroPos = InStr(strString, Chr$(0))
  858.     If intZeroPos > 0 Then
  859.         StripTerminator = Left$(strString, intZeroPos - 1)
  860.     Else
  861.         StripTerminator = strString
  862.     End If
  863. End Function
  864.  
  865. '-----------------------------------------------------------
  866. ' FUNCTION: GetFileVersion
  867. '
  868. ' Returns the internal file version number for the specified
  869. ' file.  This can be different than the 'display' version
  870. ' number shown in the File Manager File Properties dialog.
  871. ' It is the same number as shown in the VB4 SetupWizard's
  872. ' File Details screen.  This is the number used by the
  873. ' Windows VerInstallFile API when comparing file versions.
  874. '
  875. ' IN: [strFileName] - the file whose version # is desired
  876. '     [fIsRemoteServerSupportFile] - whether or not this file is
  877. '          a remote OLE automation server support file (.VBR)
  878. '          (Enterprise edition only).  If missing, False is assumed.
  879. '
  880. ' Returns: The Version number string if found, otherwise
  881. '          gstrNULL
  882. '-----------------------------------------------------------
  883. '
  884. Function GetFileVersion(ByVal strFileName As String, Optional ByVal fIsRemoteServerSupportFile) As String
  885.     Dim sVerInfo As VERINFO
  886.     Dim strVer As String
  887.  
  888.     On Error GoTo GFVError
  889.  
  890.     If IsMissing(fIsRemoteServerSupportFile) Then
  891.         fIsRemoteServerSupportFile = False
  892.     End If
  893.     
  894.     '
  895.     'Get the file version into a VERINFO struct, and then assemble a version string
  896.     'from the appropriate elements.
  897.     '
  898.     If GetFileVerStruct(strFileName, sVerInfo, fIsRemoteServerSupportFile) = True Then
  899.         strVer = Format$(sVerInfo.nMSHi) & gstrDECIMAL & Format$(sVerInfo.nMSLo) & gstrDECIMAL
  900.         strVer = strVer & Format$(sVerInfo.nLSHi) & gstrDECIMAL & Format$(sVerInfo.nLSLo)
  901.         GetFileVersion = strVer
  902.     Else
  903.         GetFileVersion = gstrNULL
  904.     End If
  905.     
  906.     Exit Function
  907.     
  908. GFVError:
  909.     GetFileVersion = gstrNULL
  910.     Err = 0
  911. End Function
  912.  
  913. '-----------------------------------------------------------
  914. ' FUNCTION: GetFileVerStruct
  915. '
  916. ' Gets the file version information into a VERINFO TYPE
  917. ' variable
  918. '
  919. ' IN: [strFileName] - name of file to get version info for
  920. '     [fIsRemoteServerSupportFile] - whether or not this file is
  921. '          a remote OLE automation server support file (.VBR)
  922. '          (Enterprise edition only).  If missing, False is assumed.
  923. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  924. '
  925. ' Returns: True if version info found, False otherwise
  926. '-----------------------------------------------------------
  927. '
  928. Function GetFileVerStruct(ByVal strFileName As String, sVerInfo As VERINFO, Optional ByVal fIsRemoteServerSupportFile) As Boolean
  929.     Const strFIXEDFILEINFO$ = "\"
  930.  
  931.     Dim lVerSize As Long
  932.     Dim lVerHandle As Long
  933.     Dim lpBufPtr As Long
  934.     Dim byteVerData() As Byte
  935.  
  936.     GetFileVerStruct = False
  937.  
  938.     If IsMissing(fIsRemoteServerSupportFile) Then
  939.         fIsRemoteServerSupportFile = False
  940.     End If
  941.  
  942.     If fIsRemoteServerSupportFile Then
  943.         GetFileVerStruct = GetRemoteSupportFileVerStruct(strFileName, sVerInfo)
  944.     Else
  945.         '
  946.         'Get the size of the file version info, allocate a buffer for it, and get the
  947.         'version info.  Next, we query the Fixed file info portion, where the internal
  948.         'file version used by the Windows VerInstallFile API is kept.  We then copy
  949.         'the fixed file info into a VERINFO structure.
  950.         '
  951.         lVerSize = GetFileVersionInfoSize(strFileName, lVerHandle)
  952.         If lVerSize > 0 Then
  953.             ReDim byteVerData(lVerSize)
  954.             If GetFileVersionInfo(strFileName, lVerHandle, lVerSize, byteVerData(0)) <> 0 Then ' (Pass byteVerData array via reference to first element)
  955.                 If VerQueryValue(byteVerData(0), strFIXEDFILEINFO & "", lpBufPtr, lVerSize) <> 0 Then
  956.                     lmemcpy sVerInfo, lpBufPtr, lVerSize
  957.                     GetFileVerStruct = True
  958.                 End If
  959.             End If
  960.         End If
  961.     End If
  962. End Function
  963.  
  964. '-----------------------------------------------------------
  965. ' FUNCTION: GetRemoteSupportFileVerStruct
  966. '
  967. ' Gets the file version information of a remote OLE server
  968. ' support file into a VERINFO TYPE variable (Enterprise
  969. ' Edition only).  Such files do not have a Windows version
  970. ' stamp, but they do have an internal version stamp that
  971. ' we can look for.
  972. '
  973. ' IN: [strFileName] - name of file to get version info for
  974. ' OUT: [sVerInfo] - VERINFO Type to fill with version info
  975. '
  976. ' Returns: True if version info found, False otherwise
  977. '-----------------------------------------------------------
  978. '
  979. Function GetRemoteSupportFileVerStruct(ByVal strFileName As String, sVerInfo As VERINFO, Optional ByVal fIsRemoteServerSupportFile) As Boolean
  980.     Const strVersionKey = "Version="
  981.     Dim cchVersionKey As Integer
  982.     Dim iFile As Integer
  983.  
  984.     cchVersionKey = Len(strVersionKey)
  985.     sVerInfo.nMSHi = gintNOVERINFO
  986.     
  987.     On Error GoTo Failed
  988.     
  989.     iFile = FreeFile
  990.  
  991.     Open strFileName For Input Access Read Lock Read Write As #iFile
  992.     
  993.     ' Loop through each line, looking for the key
  994.     While (Not EOF(iFile))
  995.         Dim strLine As String
  996.  
  997.         Line Input #iFile, strLine
  998.         If Left$(strLine, cchVersionKey) = strVersionKey Then
  999.             ' We've found the version key.  Copy everything after the equals sign
  1000.             Dim strVersion As String
  1001.             
  1002.             strVersion = Mid$(strLine, cchVersionKey + 1)
  1003.             
  1004.             'Parse and store the version information
  1005.             PackVerInfo strVersion, sVerInfo
  1006.  
  1007.             'Convert the format 1.2.3 from the .VBR into
  1008.             '1.2.0.3, which is really want we want
  1009.             sVerInfo.nLSLo = sVerInfo.nLSHi
  1010.             sVerInfo.nLSHi = 0
  1011.             
  1012.             GetRemoteSupportFileVerStruct = True
  1013.             Close iFile
  1014.             Exit Function
  1015.         End If
  1016.     Wend
  1017.     
  1018.     Close iFile
  1019.     Exit Function
  1020.  
  1021. Failed:
  1022.     GetRemoteSupportFileVerStruct = False
  1023. End Function
  1024. '-----------------------------------------------------------
  1025. ' FUNCTION: GetWindowsDir
  1026. '
  1027. ' Calls the windows API to get the windows directory and
  1028. ' ensures that a trailing dir separator is present
  1029. '
  1030. ' Returns: The windows directory
  1031. '-----------------------------------------------------------
  1032. '
  1033. Function GetWindowsDir() As String
  1034.     Dim strBuf As String
  1035.  
  1036.     strBuf = Space$(gintMAX_SIZE)
  1037.  
  1038.     '
  1039.     'Get the windows directory and then trim the buffer to the exact length
  1040.     'returned and add a dir sep (backslash) if the API didn't return one
  1041.     '
  1042.     If GetWindowsDirectory(strBuf, gintMAX_SIZE) > 0 Then
  1043.         strBuf = StripTerminator$(strBuf)
  1044.         AddDirSep strBuf
  1045.  
  1046.         GetWindowsDir = UCase16(strBuf)
  1047.     Else
  1048.         GetWindowsDir = gstrNULL
  1049.     End If
  1050. End Function
  1051.  
  1052. '-----------------------------------------------------------
  1053. ' FUNCTION: UCase16
  1054. '
  1055. ' Returns the upper-case conversion of a string
  1056. '   under 16 bits, or else returns an unmodified
  1057. '   copy of the string under 32 bits.
  1058. '
  1059. ' IN: [str] - String to copy/upper-case
  1060. '
  1061. '-----------------------------------------------------------
  1062. '
  1063. Function UCase16(ByVal str As String)
  1064. #If Win16 Then
  1065.     UCase16 = UCase$(str)
  1066. #Else
  1067.     UCase16 = str
  1068. #End If
  1069. End Function
  1070.  
  1071. '-----------------------------------------------------------
  1072. ' FUNCTION: ExtractFilenameItem
  1073. '
  1074. ' Extracts a quoted or unquoted filename from a string.
  1075. '
  1076. ' IN: [str] - string to parse for a filename.
  1077. '     [intAnchor] - index in str at which the filename begins.
  1078. '             The filename continues to the end of the string
  1079. '             or up to the next comma in the string, or, if
  1080. '             the filename is enclosed in quotes, until the
  1081. '             next double quote.
  1082. ' OUT: Returns the filename, without quotes.
  1083. '      [intAnchor] is set to the comma, or else one character
  1084. '             past the end of the string
  1085. '      [fErr] is set to True if a parsing error is discovered
  1086. '
  1087. '-----------------------------------------------------------
  1088. '
  1089. Function strExtractFilenameItem(ByVal str As String, intAnchor As Integer, fErr As Boolean) As String
  1090.     While Mid$(str, intAnchor, 1) = " "
  1091.         intAnchor = intAnchor + 1
  1092.     Wend
  1093.     
  1094.     Dim iEndFilenamePos As Integer
  1095.     Dim strFileName As String
  1096.     If Mid$(str, intAnchor, 1) = """" Then
  1097.         ' Filename is surrounded by quotes
  1098.         iEndFilenamePos = InStr(intAnchor + 1, str, """") ' Find matching quote
  1099.         If iEndFilenamePos > 0 Then
  1100.             strFileName = Mid$(str, intAnchor + 1, iEndFilenamePos - 1 - intAnchor)
  1101.             intAnchor = iEndFilenamePos + 1
  1102.             While Mid$(str, intAnchor, 1) = " "
  1103.                 intAnchor = intAnchor + 1
  1104.             Wend
  1105.             If (Mid$(str, intAnchor, 1) <> gstrCOMMA) And (Mid$(str, intAnchor, 1) <> "") Then
  1106.                 fErr = True
  1107.                 Exit Function
  1108.             End If
  1109.         Else
  1110.             fErr = True
  1111.             Exit Function
  1112.         End If
  1113.     Else
  1114.         ' Filename continues until next comma or end of string
  1115.         Dim iCommaPos As Integer
  1116.         
  1117.         iCommaPos = InStr(intAnchor, str, gstrCOMMA)
  1118.         If iCommaPos = 0 Then
  1119.             iCommaPos = Len(str) + 1
  1120.         End If
  1121.         iEndFilenamePos = iCommaPos
  1122.         
  1123.         strFileName = Mid$(str, intAnchor, iEndFilenamePos - intAnchor)
  1124.         intAnchor = iCommaPos
  1125.     End If
  1126.     
  1127.     strFileName = Trim$(strFileName)
  1128.     If strFileName = "" Then
  1129.         fErr = True
  1130.         Exit Function
  1131.     End If
  1132.     
  1133.     fErr = False
  1134.     strExtractFilenameItem = strFileName
  1135. End Function
  1136.  
  1137. '-----------------------------------------------------------
  1138. ' FUNCTION: Extension
  1139. '
  1140. ' Extracts the extension portion of a file/path name
  1141. '
  1142. ' IN: [strFileName] - file/path to get the extension of
  1143. '
  1144. ' Returns: The extension if one exists, else gstrNULL
  1145. '-----------------------------------------------------------
  1146. '
  1147. Function Extension(ByVal strFileName As String) As String
  1148.     Dim intPos As Integer
  1149.  
  1150.     Extension = gstrNULL
  1151.  
  1152.     intPos = Len(strFileName)
  1153.  
  1154.     Do While intPos > 0
  1155.         Select Case Mid$(strFileName, intPos, 1)
  1156.         Case gstrSEP_EXT
  1157.             Extension = Mid$(strFileName, intPos + 1)
  1158.             Exit Do
  1159.         Case gstrSEP_DIR, gstrSEP_DIRALT
  1160.             Exit Do
  1161.         End Select
  1162.  
  1163.         intPos = intPos - 1
  1164.     Loop
  1165. End Function
  1166.  
  1167. '-----------------------------------------------------------
  1168. ' SUB: PackVerInfo
  1169. '
  1170. ' Parses a file version number string of the form
  1171. ' x[.x[.x[.x]]] and assigns the extracted numbers to the
  1172. ' appropriate elements of a VERINFO type variable.
  1173. ' Examples of valid version strings are '3.11.0.102',
  1174. ' '3.11', '3', etc.
  1175. '
  1176. ' IN: [strVersion] - version number string
  1177. '
  1178. ' OUT: [sVerInfo] - VERINFO type variable whose elements
  1179. '                   are assigned the appropriate numbers
  1180. '                   from the version number string
  1181. '-----------------------------------------------------------
  1182. '
  1183. Sub PackVerInfo(ByVal strVersion As String, sVerInfo As VERINFO)
  1184.     Dim intOffset As Integer
  1185.     Dim intAnchor As Integer
  1186.  
  1187.     On Error GoTo PVIError
  1188.  
  1189.     intOffset = InStr(strVersion, gstrDECIMAL)
  1190.     If intOffset = 0 Then
  1191.         sVerInfo.nMSHi = Val(strVersion)
  1192.         GoTo PVIMSLo
  1193.     Else
  1194.         sVerInfo.nMSHi = Val(Left$(strVersion, intOffset - 1))
  1195.         intAnchor = intOffset + 1
  1196.     End If
  1197.  
  1198.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1199.     If intOffset = 0 Then
  1200.         sVerInfo.nMSLo = Val(Mid$(strVersion, intAnchor))
  1201.         GoTo PVILSHi
  1202.     Else
  1203.         sVerInfo.nMSLo = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1204.         intAnchor = intOffset + 1
  1205.     End If
  1206.  
  1207.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1208.     If intOffset = 0 Then
  1209.         sVerInfo.nLSHi = Val(Mid$(strVersion, intAnchor))
  1210.         GoTo PVILSLo
  1211.     Else
  1212.         sVerInfo.nLSHi = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1213.         intAnchor = intOffset + 1
  1214.     End If
  1215.  
  1216.     intOffset = InStr(intAnchor, strVersion, gstrDECIMAL)
  1217.     If intOffset = 0 Then
  1218.         sVerInfo.nLSLo = Val(Mid$(strVersion, intAnchor))
  1219.     Else
  1220.         sVerInfo.nLSLo = Val(Mid$(strVersion, intAnchor, intOffset - intAnchor))
  1221.     End If
  1222.  
  1223.     Exit Sub
  1224.  
  1225. PVIError:
  1226.     sVerInfo.nMSHi = 0
  1227. PVIMSLo:
  1228.     sVerInfo.nMSLo = 0
  1229. PVILSHi:
  1230.     sVerInfo.nLSHi = 0
  1231. PVILSLo:
  1232.     sVerInfo.nLSLo = 0
  1233. End Sub
  1234.  
  1235.  
  1236.