Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
9.5 KiB

  1. ' Windows Installer utility to report or update file versions, sizes, languages
  2. ' For use with Windows Scripting Host, CScript.exe or WScript.exe
  3. ' Copyright (c) 1999-2000, Microsoft Corporation
  4. ' Demonstrates the access to install engine and actions
  5. '
  6. Option Explicit
  7. ' FileSystemObject.CreateTextFile and FileSystemObject.OpenTextFile
  8. Const OpenAsASCII = 0
  9. Const OpenAsUnicode = -1
  10. ' FileSystemObject.CreateTextFile
  11. Const OverwriteIfExist = -1
  12. Const FailIfExist = 0
  13. ' FileSystemObject.OpenTextFile
  14. Const OpenAsDefault = -2
  15. Const CreateIfNotExist = -1
  16. Const FailIfNotExist = 0
  17. Const ForReading = 1
  18. Const ForWriting = 2
  19. Const ForAppending = 8
  20. Const msiOpenDatabaseModeReadOnly = 0
  21. Const msiOpenDatabaseModeTransact = 1
  22. Const msiViewModifyInsert = 1
  23. Const msiViewModifyUpdate = 2
  24. Const msiViewModifyAssign = 3
  25. Const msiViewModifyReplace = 4
  26. Const msiViewModifyDelete = 6
  27. Const msiUILevelNone = 2
  28. Const msiRunModeSourceShortNames = 9
  29. Const msidbFileAttributesNoncompressed = &h00002000
  30. Dim argCount:argCount = Wscript.Arguments.Count
  31. Dim iArg:iArg = 0
  32. If (argCount < 2) Then
  33. Wscript.Echo "Windows Installer utility to updata File table sizes and versions" &_
  34. vbNewLine & " The 1st argument is the path to MSI database, at the source file root" &_
  35. vbNewLine & " The 2nd argument specifies the source file directory" &_
  36. vbNewLine & " The following options may be specified at any point on the command line" &_
  37. vbNewLine & " /U to update the MSI database with the file sizes, versions, and languages" &_
  38. vbNewLine & " Notes:" &_
  39. vbNewLine & " If source type set to compressed, all files will be opened at the root" &_
  40. vbNewLine & " Using CSCRIPT.EXE without the /U option, the file info will be displayed" &_
  41. vbNewLine &_
  42. vbNewLine & "Copyright (C) Microsoft Corporation, 1999-2000. All rights reserved."
  43. Wscript.Quit 1
  44. End If
  45. ' Get argument values, processing any option flags
  46. Dim updateMsi : updateMsi = False
  47. Dim sequenceFile : sequenceFile = False
  48. Dim databasePath : databasePath = NextArgument
  49. Dim sourceFolder : sourceFolder = NextArgument
  50. If Not IsEmpty(NextArgument) Then Fail "More than 2 arguments supplied" ' process any trailing options
  51. If Not IsEmpty(sourceFolder) And Right(sourceFolder, 1) <> "\" Then sourceFolder = sourceFolder & "\"
  52. Dim console : If UCase(Mid(Wscript.FullName, Len(Wscript.Path) + 2, 1)) = "C" Then console = True
  53. ' Connect to Windows Installer object
  54. On Error Resume Next
  55. Dim installer : Set installer = Nothing
  56. Set installer = Wscript.CreateObject("WindowsInstaller.Installer") : CheckError
  57. ' Check if multiple language package, and force use of primary language
  58. REM Set sumInfo = database.SummaryInformation(3) : CheckError
  59. ' Open database
  60. Dim database, openMode, view, record, updateMode, sumInfo
  61. If updateMsi Then openMode = msiOpenDatabaseModeTransact Else openMode = msiOpenDatabaseModeReadOnly
  62. Set database = installer.OpenDatabase(databasePath, openMode) : CheckError
  63. ' Create an install session and execute actions in order to perform directory resolution
  64. installer.UILevel = msiUILevelNone
  65. Dim session : Set session = installer.OpenPackage(database,1) : If Err <> 0 Then Fail "Database: " & databasePath & ". Invalid installer package format"
  66. Dim shortNames : shortNames = session.Mode(msiRunModeSourceShortNames) : CheckError
  67. 'REM If Not IsEmpty(sourceFolder) Then session.Property("OriginalDatabase") = sourceFolder : CheckError
  68. Dim stat : stat = session.DoAction("CostInitialize") : CheckError
  69. If stat <> 1 Then Fail "CostInitialize failed, returned " & stat
  70. Set view = database.OpenView("SELECT File,FileSize,Version,Language,Sequence FROM File ORDER BY File") : CheckError
  71. view.Execute : CheckError
  72. wscript.echo "Updating File properties in the MSI"
  73. Dim objFS : Set objFS=WScript.CreateObject ("Scripting.FileSystemObject")
  74. Dim cabFileFolder : Set cabFileFolder=objFS.GetFolder(sourceFolder) : CheckError
  75. Dim g_cabFileList : Set g_cabFileList = cabFileFolder.Files : CheckError
  76. Dim objFile, nIndex
  77. Dim g_cabFileArray(600)
  78. If (g_cabFileList.Count > 600) Then Fail "Need to increase max file count constant beyond 600"
  79. nIndex = 1
  80. '
  81. ' Fill the array of files from the collection. The binary search for
  82. ' the files relies on the fact that this collection is alphabetized already.
  83. '
  84. For Each objFile In g_cabFileList
  85. Set g_cabFileArray(nIndex) = objFile
  86. nIndex = nIndex + 1
  87. Next
  88. ' Fetch each file and request the source path, then verify the source path, and get the file info if present
  89. Dim fileKey, sourcePath, fileSize, version, language, message, info, nFileCount, nLastIndex
  90. nLastIndex = Round(g_cabFileList.Count / 2)
  91. nFileCount = 0
  92. Do
  93. nFileCount = nFileCount + 1
  94. Set record = view.Fetch : CheckError
  95. If record Is Nothing Then Exit Do
  96. fileKey = record.StringData(1)
  97. REM fileSize = record.IntegerData(2)
  98. REM version = record.StringData(3)
  99. REM language = record.StringData(4)
  100. REM sequence = record.StringData(5)
  101. 'wscript.echo nFileCount & ": " & fileKey
  102. sourcePath = sourceFolder & fileKey
  103. If installer.FileAttributes(sourcePath) = -1 Then
  104. message = message & vbNewLine & sourcePath
  105. Else
  106. fileSize = installer.FileSize(sourcePath) : CheckError
  107. version = Empty : version = installer.FileVersion(sourcePath, False) : Err.Clear ' early MSI implementation fails if no version
  108. language = Empty : language = installer.FileVersion(sourcePath, True) : Err.Clear ' early MSI implementation doesn't support language
  109. If language = version Then language = Empty ' Temp check for MSI.DLL version without language support
  110. If Err <> 0 Then version = Empty : Err.Clear
  111. If updateMsi Then
  112. record.IntegerData(2) = fileSize
  113. If Len(version) > 0 Then record.StringData(3) = version
  114. If Len(language) > 0 Then record.StringData(4) = language
  115. nIndex = GetFileIndex(fileKey, nLastIndex)
  116. record.IntegerData(5) = nIndex
  117. view.Modify msiViewModifyUpdate, record : CheckError
  118. nLastIndex = nIndex + 1
  119. ElseIf console Then
  120. info = fileName : If Len(info) < 12 Then info = info & Space(12 - Len(info))
  121. info = info & " size=" & fileSize : If Len(info) < 26 Then info = info & Space(26 - Len(info))
  122. If Len(version) > 0 Then info = info & " vers=" & version : If Len(info) < 45 Then info = info & Space(45 - Len(info))
  123. If Len(language) > 0 Then info = info & " lang=" & language
  124. Wscript.Echo info
  125. End If
  126. End If
  127. Loop
  128. REM Wscript.Echo "SourceDir = " & session.Property("SourceDir")
  129. If Not IsEmpty(message) Then Fail "Error, the following files were not available:" & message
  130. ' Update SummaryInformation
  131. If updateMsi Then
  132. Set sumInfo = database.SummaryInformation(3) : CheckError
  133. sumInfo.Property(11) = Now
  134. sumInfo.Property(13) = Now
  135. sumInfo.Persist
  136. End If
  137. ' Commit database in case updates performed
  138. database.Commit : CheckError
  139. Wscript.Quit 0
  140. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  141. ' GetFileIndex
  142. '
  143. ' Description
  144. ' Performs a binary search for a file in an alphabetized list so that
  145. ' the sequence number can be changed to match the index of the file
  146. ' in the CAB.
  147. '
  148. ' Parameters
  149. ' strFilename Filename to search for
  150. ' nIndex A best guess of where to start looking
  151. ' in the array for the filename
  152. '
  153. ' Returns
  154. ' The index of the file in the list
  155. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  156. Function GetFileIndex(strFilename, nIndx)
  157. Dim nMin, nMax, nRound, nCompare
  158. '
  159. ' nMin and nMax are the inclusive boundaries where the file can be found
  160. ' in the array
  161. '
  162. nMin = 1
  163. nMax = g_cabFileList.Count
  164. If (nIndx > nMax) OR (nIndx < nMin) Then nIndx = Round(nMax / 2)
  165. nRound = 1
  166. Do
  167. 'wscript.echo "Entering loop: min=" & nMin & " max=" & nMax & " current=" & nIndx
  168. nCompare = StrComp(strFilename, g_cabFileArray(nIndx).Name, 1)
  169. If nCompare = 0 Then
  170. Exit Do 'Found the string
  171. ElseIf nCompare < 0 Then
  172. nMax = nIndx - 1 'The string is in the lower half of the bounds
  173. Else
  174. nMin = nIndx + 1 'The string is in the upper half of the bounds
  175. End If
  176. nIndx = Round((nMax + nMin) / 2)
  177. If nMax < nMin Then Fail "ERROR: Could not find file " & strFilename & " in CAB directory. Files may not be sorted properly"
  178. nRound = nRound + 1
  179. Loop
  180. 'wscript.echo "Index for " & strFilename & " is " & nIndx & " (" & nRound & " tries)"
  181. GetFileIndex = nIndx
  182. End Function
  183. ' Extract argument value from command line, processing any option flags
  184. Function NextArgument
  185. Dim arg
  186. Do ' loop to pull in option flags until an argument value is found
  187. If iArg >= argCount Then Exit Function
  188. arg = Wscript.Arguments(iArg)
  189. iArg = iArg + 1
  190. If (AscW(arg) <> AscW("/")) And (AscW(arg) <> AscW("-")) Then Exit Do
  191. Select Case UCase(Right(arg, Len(arg)-1))
  192. Case "U" : updateMsi = True
  193. Case Else: Wscript.Echo "Invalid option flag:", arg : Wscript.Quit 1
  194. End Select
  195. Loop
  196. NextArgument = arg
  197. End Function
  198. Sub CheckError
  199. Dim message, errRec
  200. If Err = 0 Then Exit Sub
  201. message = Err.Source & " " & Hex(Err) & ": " & Err.Description & ", " & Err.number
  202. If Not installer Is Nothing Then
  203. Set errRec = installer.LastErrorRecord
  204. If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
  205. End If
  206. Fail message
  207. End Sub
  208. Sub Fail(message)
  209. Wscript.Echo message
  210. Wscript.Quit 2
  211. End Sub