Source code of Windows XP (NT5)
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.

783 lines
28 KiB

  1. <job id='wi_link'>
  2. <!-- includes for constants definitions -->
  3. <script language='VBScript' src='.\vbsconst.inc'></script>
  4. <script language='VBScript' src='.\wiconst.inc'></script>
  5. <!-- includes for function declarations -->
  6. <script language='VBScript' src='.\widir.inc'></script>
  7. <script language='VBScript' src='.\wixerror.inc'></script>
  8. <!-- main -->
  9. <script Language='VBScript'>
  10. Option Explicit
  11. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  12. ' main
  13. Public installer 'As Installer
  14. Public database 'As Database
  15. Public fso 'As FileSystemObject
  16. Public dictVars 'As Dictionary
  17. Public dictFiles 'As Dictionary
  18. Public dictModules 'As Dictionary
  19. Public dictSequences 'As Dictionary
  20. Public sTempDir 'As String
  21. Public vInstallerVer
  22. Public fHelp, fNoOnError, fNoCab, fNoRedist, fNoTidy, fVerbose
  23. Public sOriginalManifest
  24. Public fModule ' if linking a Merge Module
  25. Public fMediaFinal ' assumes Media information is final
  26. Public sDatabasePath, sOutputPath, sTempDb
  27. Public g_sBaseDir ' base directory used for update and CAB'ing
  28. Public aSumInfo(19), i
  29. Dim openMode
  30. Dim si
  31. ' connect to Windows Installer, create dictionaries for modules and files
  32. Set installer = Nothing
  33. Set installer = WScript.CreateObject("WindowsInstaller.Installer")
  34. Set fso = WScript.CreateObject("Scripting.FileSystemObject") : CheckError
  35. Set dictVars = WScript.CreateObject("Scripting.Dictionary") : CheckError
  36. Set dictFiles = WScript.CreateObject("Scripting.Dictionary")
  37. Set dictModules = WScript.CreateObject("Scripting.Dictionary")
  38. Set dictSequences = WScript.CreateObject("Scripting.Dictionary")
  39. Dim sInstallerVer : sInstallerVer = installer.Version
  40. Dim nDot : nDot = InStr(sInstallerVer, ".")
  41. vInstallerVer = CInt(Left(sInstallerVer, nDot - 1)) * 100
  42. vInstallerVer = vInstallerVer + CInt(Mid(sInstallerVer, nDot + 1, InStr(nDot + 1, sInstallerVer, ".") - nDot))
  43. sTempDir = installer.Environment("TMP")
  44. If Len(sTempDir) = 0 Then sTempDir = installer.Environment("TEMP")
  45. sTempDb = sTempDir & "\" & fso.GetTempName
  46. ParseCommandLine
  47. If Not fNoOnError Then On Error Resume Next
  48. If fHelp Or IsEmpty(sDatabasePath) Then
  49. ShowHelp
  50. WScript.Quit 1
  51. End If
  52. ' open the object file
  53. Set database = installer.OpenDatabase(sDatabasePath, sTempDb) : CheckError
  54. ' remember summary information for later
  55. Set si = database.SummaryInformation(0)
  56. For i = 0 To 19
  57. aSumInfo(i) = si.Property(i)
  58. Next
  59. Set si = Nothing
  60. If Not fMediaFinal Then
  61. ReadLinkerInfo
  62. ProcessFilesAndModules
  63. End If
  64. ' close the database and merge all the modules into the temp db
  65. database.Commit
  66. Set database = Nothing
  67. If Not fModule Then MergeModules sTempDb
  68. ' if an output path wasn't provided generate one
  69. If IsEmpty(sOutputPath) Then
  70. If ".wixobj" = Right(sDatabasePath, 7) Then
  71. ' put on the correct extension
  72. sOutputPath = Left(sDatabasePath, Len(sDatabasePath) - 7)
  73. If fModule Then sOutputPath = sOutputPath & ".msm" Else sOutputPath = sOutputPath & ".msi"
  74. Else
  75. sOutputPath = sDatabasePath
  76. End If
  77. End If
  78. ' reopen the temp db to the targetdb
  79. Set database = installer.OpenDatabase(sTempDb, sOutputPath) : CheckError
  80. If Not fNoCab Then
  81. If fModule Then
  82. CABFiles "MergeModule.CABinet", 0, 0, True
  83. Else
  84. ProcessMediaTable
  85. End If
  86. End If
  87. ' write the redist information
  88. If Not fNoRedist Then ProcessRedistInfo sOutputPath & ".redist"
  89. ' clean up the final MSI/MSM
  90. If Not fNoTidy Then
  91. If 1 = database.TablePersistent("candle_Info") Then database.OpenView("DROP TABLE `candle_Info`").Execute
  92. If 1 = database.TablePersistent("candle_DiskInfo") Then database.OpenView("DROP TABLE `candle_DiskInfo`").Execute
  93. If 1 = database.TablePersistent("candle_Files") Then database.OpenView("DROP TABLE `candle_Files`").Execute
  94. If 1 = database.TablePersistent("candle_Modules") Then database.OpenView("DROP TABLE `candle_Modules`").Execute
  95. If 1 = database.TablePersistent("redist_Info") Then database.OpenView("DROP TABLE `redist_Info`").Execute
  96. If 1 = database.TablePersistent("redist_Keywords") Then database.OpenView("DROP TABLE `redist_Keywords`").Execute
  97. If 1 = database.TablePersistent("redist_Contacts") Then database.OpenView("DROP TABLE `redist_Contacts`").Execute
  98. If 1 = database.TablePersistent("redist_Perminssions") Then database.OpenView("DROP TABLE `redist_Perminssions`").Execute
  99. If 1 = database.TablePersistent("redist_Os") Then database.OpenView("DROP TABLE `redist_Os`").Execute
  100. End If
  101. database.Commit
  102. Set database = Nothing
  103. ' write summary information back
  104. Set si = installer.SummaryInformation(sOutputPath, 20)
  105. For i = 1 To 19
  106. If Not IsEmpty(aSumInfo(i)) Then si.Property(i) = aSumInfo(i)
  107. Next
  108. si.Persist
  109. Set si = Nothing
  110. Set installer = Nothing
  111. fso.DeleteFile sTempDb ' clean
  112. WScript.Quit 0
  113. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  114. ' Error handling and command-line parsing routines
  115. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' robmen ''
  116. ' ParseCommandLine
  117. Function ParseCommandLine()
  118. Dim arg, argIndex
  119. Dim chFlag
  120. If 0 = WScript.Arguments.Count Then fHelp = True : Exit Function
  121. For argIndex = 0 To WScript.Arguments.Count - 1
  122. arg = WScript.Arguments(argIndex)
  123. chFlag = AscW(arg)
  124. ' if this a variable
  125. If InStr(arg, "=") Then
  126. Dim expr : expr = Split(arg, "=")
  127. If IsNumeric(expr(1)) Then expr(1) = CLng(expr(1))
  128. dictVars.Item(expr(0)) = expr(1)
  129. ' command line parameter
  130. ElseIf (chFlag = AscW("/")) Or (chFlag = AscW("-")) Then
  131. chFlag = LCase(Mid(arg, 2))
  132. Select Case chFlag
  133. Case "b" ' base directory
  134. argIndex = argIndex + 1
  135. g_sBaseDir = WScript.Arguments(argIndex)
  136. Case "o" ' database to create
  137. argIndex = argIndex + 1
  138. sOutputPath = WScript.Arguments(argIndex)
  139. If fso.FileExists(sOutputPath) Then WScript.Echo "Warning, overwriting database: " & sOutputPath
  140. Case "m" : fMediaFinal = True
  141. Case "sc" : fNoCab = True
  142. Case "sr" : fNoRedist = True
  143. Case "st" : fNoTidy = True
  144. Case "v" : fVerbose = True
  145. Case "e" : fNoOnError = True
  146. Case "?" : fHelp = True
  147. Case Else : Fail "Invalid option flag: " & arg
  148. End Select
  149. ' must be the database to link
  150. Else
  151. If Not IsEmpty(sDatabasePath) Then Fail "Cannot specify two databases to link"
  152. sDatabasePath = arg
  153. End If
  154. Next
  155. End Function ' ParseCommandLine
  156. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''' robmen ''
  157. ' ShowHelp
  158. Sub ShowHelp()
  159. Dim sHelp
  160. sHelp = "light - 'links' Files and Merge Modules in a Windows Installer Database created" & vbCrLf & _
  161. " by candle.wsf" & vbCrLf & _
  162. vbCrLf & _
  163. "light.wsf [-?] [-sc] [-sr] [-st] [-b basedir] [-m] [-o destfile] [-v] [-e] linkme.wixobj" & vbCrLf & _
  164. vbCrLf & _
  165. " -b base directory to locate Files" & vbCrLf & _
  166. " -e errors crash linker, useful for debugging compiler" & vbCrLf & _
  167. " -i include paths to search (not yet implemented!)" & vbCrLf & _
  168. " -l log all operations, useful for debugging" & vbCrLf & _
  169. " -m assumes Media information is final" & vbCrLf & _
  170. " -o output to new database instead of updating this one [will overwrite]" & vbCrLf & _
  171. " -sb suppress processing of Binary-encoded data" & vbCrLf & _
  172. " -sc suppress CAB'ing process" & vbCrLf & _
  173. " -sr suppress .redist generation" & vbCrLf & _
  174. " -st suppress tidy'ing [leave linker tables]" & vbCrLf & _
  175. " -v verbose output, useful for debugging" & vbCrLf & _
  176. " -? this help information" & vbCrLf & _
  177. vbCrLf & _
  178. "For more information see: http://compcat/wix"
  179. WScript.Echo sHelp
  180. End Sub ' ShowHelp
  181. Sub CheckError
  182. Dim message, errRec
  183. If Err = 0 Then Exit Sub
  184. message = Err.Source & " " & Hex(Err) & ": " & Err.Description
  185. If Not installer Is Nothing Then
  186. Set errRec = installer.LastErrorRecord
  187. If Not errRec Is Nothing Then message = message & vbNewLine & errRec.FormatText
  188. End If
  189. Fail message
  190. End Sub
  191. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  192. ' BaseDir
  193. Function BaseDir(sPath)
  194. If IsEmpty(g_sBaseDir) Then g_sBaseDir = "."
  195. If "sourcedir\" = LCase(Left(sPath, 10)) Then
  196. BaseDir = g_sBaseDir & Mid(sPath, 10)
  197. Else
  198. BaseDir = sPath
  199. End If
  200. End Function ' BaseDir
  201. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  202. ' Linker information routines
  203. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  204. ' ReadLinkerInfo
  205. Sub ReadLinkerInfo
  206. Dim vw, rec
  207. If 2 = database.TablePersistent("candle_Info") Then Exit Sub
  208. Set vw = database.OpenView("SELECT `LinkProperty`, `Value` FROM `candle_Info`")
  209. vw.Execute
  210. Do
  211. Set rec = vw.Fetch
  212. If Not rec Is Nothing Then
  213. Select Case rec.StringData(1)
  214. Case "SourceFile" : sOriginalManifest = rec.StringData(2)
  215. Case "IsModule" : fModule = CBool(rec.IntegerData(2))
  216. Case Else : dictVars.Add rec.StringData(1), rec.StringData(2)
  217. End Select
  218. End If
  219. Loop Until rec Is Nothing
  220. ReadFileInfo
  221. ReadModuleInfo
  222. End Sub
  223. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  224. ' ReadFileInfo
  225. Sub ReadFileInfo
  226. Dim vw, rec
  227. If 2 = database.TablePersistent("candle_Files") Then Exit Sub
  228. Set vw = database.OpenView("SELECT `File_`, `Path` FROM `candle_Files`")
  229. vw.Execute
  230. Do
  231. Set rec = vw.Fetch
  232. If Not rec Is Nothing Then
  233. dictFiles.Add rec.StringData(1), rec.StringData(2)
  234. End If
  235. Loop Until rec Is Nothing
  236. End Sub ' ReadFileInfo
  237. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  238. ' ReadModuleInfo
  239. Sub ReadModuleInfo
  240. Dim vw, rec
  241. Dim aData(4)
  242. If 2 = database.TablePersistent("candle_Modules") Then Exit Sub
  243. Set vw = database.OpenView("SELECT `Module`, `Path`, `Language`, `PrimaryFeature_`, `ConnectFeatures_`, `RedirectDirectory_` FROM `candle_Modules`")
  244. vw.Execute
  245. Do
  246. Set rec = vw.Fetch
  247. If Not rec Is Nothing Then
  248. aData(0) = rec.StringData(2)
  249. aData(1) = rec.IntegerData(3)
  250. aData(2) = rec.StringData(4)
  251. aData(3) = rec.StringData(5)
  252. aData(4) = rec.StringData(6)
  253. dictModules.Add rec.StringData(1), aData
  254. End If
  255. Loop Until rec Is Nothing
  256. End Sub ' ReadModuleInfo
  257. ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  258. ' Linker work routines
  259. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  260. ' ProcessFilesAndModules
  261. Sub ProcessFilesAndModules
  262. Dim vwFiles, vwModules
  263. Dim recFile, recModule
  264. Dim vwDisk, recDisk
  265. Dim vwFileUpdate, vwMediaUpdate, vwFileHash
  266. Dim recFileUpdate, recMediaUpdate, recFileHash
  267. Dim nDiskId, fIsModule, nLastSequence
  268. Dim sPath
  269. ' Dim merge, getFiles
  270. ' Set merge = WScript.CreateObject("Msm.Merge")
  271. ' Set getFiles = WScript.CreateObject("{7041AE26-2D78-11D2-888A-00A0C981B015}")
  272. Dim module, vw, rec
  273. nDiskId = 0
  274. nLastSequence = 0
  275. ' bail if disk information wasn't provided
  276. If 1 <> database.TablePersistent("candle_DiskInfo") Then Exit Sub
  277. Set vwDisk = database.OpenView("SELECT `Identifier`, `DiskId`, `IsModule` FROM `candle_DiskInfo` ORDER BY `DiskId`, `IsModule`")
  278. vwDisk.Execute
  279. If 1 = database.TablePersistent("File") Then
  280. Set vwFileUpdate = database.OpenView("SELECT `FileSize`, `Language`, `Version` FROM `File` WHERE `File`=?")
  281. Set recFileUpdate = installer.CreateRecord(4)
  282. End If
  283. If 1 = database.TablePersistent("Media") Then
  284. If fModule Then Fail "Modules cannot have a Media table"
  285. Set vwMediaUpdate = database.OpenView("SELECT `LastSequence` FROM `Media` WHERE `DiskId`=?")
  286. Set recMediaUpdate = installer.CreateRecord(1)
  287. End If
  288. If 1 = database.TablePersistent("MsiFileHash") Then
  289. Set vwFileHash = database.OpenView("SELECT `File_`, `Options`, `HashPart1`, `HashPart2`, `HashPart3`, `HashPart4` FROM `MsiFileHash`")
  290. Set recFileHash = installer.CreateRecord(6)
  291. End If
  292. Set recFile = Nothing
  293. Set recModule = Nothing
  294. Do
  295. Set recDisk = vwDisk.Fetch
  296. If Not recDisk Is Nothing Then
  297. fIsModule = recDisk.IntegerData(3)
  298. ' if the disk id has changed, update the Media table
  299. If 0 < nDiskId And nDiskId <> recDisk.IntegerData(2) Then
  300. recMediaUpdate.IntegerData(1) = nDiskId
  301. vwMediaUpdate.Execute recMediaUpdate
  302. Set recMediaUpdate = vwMediaUpdate.Fetch
  303. recMediaUpdate.IntegerData(1) = nLastSequence
  304. vwMediaUpdate.Modify msiViewModifyUpdate, recMediaUpdate
  305. nDiskId = recDisk.IntegerData(2) ' on to the next Media disk
  306. Else
  307. nDiskId = recDisk.IntegerData(2)
  308. End If
  309. If fModule and fIsModule Then Fail "Cannot merge a Merge Module into another Merge Module"
  310. If fIsModule Then ' merge the module
  311. Dim aData
  312. aData = dictModules.Item(recDisk.StringData(1))
  313. sPath = BaseDir(aData(0))
  314. If fso.FileExists(sPath) Then
  315. ' merge.OpenModule sPath, aData(1)
  316. Set module = installer.OpenDatabase(sPath, msiOpenDatabaseModeReadOnly)
  317. If 1 = module.TablePersistent("File") Then
  318. Set vw = module.OpenView("SELECT `File` FROM `File`")
  319. vw.Execute
  320. Do
  321. Set rec = vw.Fetch
  322. If Not rec Is Nothing Then
  323. ' Set sList = merge.ModuleFiles
  324. ' For Each s in sList
  325. nLastSequence = nLastSequence + 1
  326. dictSequences.Add rec.StringData(1), nLastSequence
  327. ' Next
  328. End If
  329. Loop Until rec Is Nothing
  330. End If
  331. Else
  332. WScript.Echo "Link could not locate module: " & sPath
  333. End If
  334. Else ' update the file
  335. sPath = dictFiles.Item(recDisk.StringData(1))
  336. sPath = BaseDir(sPath)
  337. If fso.FileExists(sPath) Then
  338. vwFileUpdate.Execute recDisk
  339. Set recFileUpdate = vwFileUpdate.Fetch
  340. recFileUpdate.IntegerData(1) = installer.FileSize(sPath)
  341. recFileUpdate.StringData(2) = installer.FileVersion(sPath, True) ' version
  342. recFileUpdate.StringData(3) = installer.FileVersion(sPath, False) ' language
  343. vwFileUpdate.Modify msiViewModifyUpdate, recFileUpdate
  344. ' if the file has no version information add it to the hash table if Windows Installer 1.5 or better is on the machine
  345. If Not IsEmpty(vwFileHash) And "" = recFileUpdate.StringData(2) And vInstallerVer > 120 Then
  346. Dim recHash : Set recHash = installer.FileHash(sPath, 0)
  347. recFileHash.StringData(1) = recDisk.StringData(1) ' file id
  348. recFileHash.IntegerData(2) = 0 ' options are always 0
  349. recFileHash.IntegerData(3) = recHash.IntegerData(1)
  350. recFileHash.IntegerData(4) = recHash.IntegerData(2)
  351. recFileHash.IntegerData(5) = recHash.IntegerData(3)
  352. recFileHash.IntegerData(6) = recHash.IntegerData(4)
  353. vwFileHash.Modify msiViewModifyInsert, recFileHash
  354. End If
  355. nLastSequence = nLastSequence + 1
  356. dictSequences.Add recDisk.StringData(1), nLastSequence
  357. Else
  358. WScript.Echo "Link could not locate file: " & sPath
  359. End If
  360. End If
  361. End If
  362. Loop Until recDisk Is Nothing
  363. ' update the last Media entry
  364. If Not fModule Then
  365. recMediaUpdate.IntegerData(1) = nDiskId
  366. vwMediaUpdate.Execute recMediaUpdate
  367. Set recMediaUpdate = vwMediaUpdate.Fetch
  368. recMediaUpdate.IntegerData(1) = nLastSequence
  369. vwMediaUpdate.Modify msiViewModifyUpdate, recMediaUpdate
  370. End If
  371. End Sub ' ProcessFilesAndModules
  372. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  373. ' MergeModules
  374. Sub MergeModules(sDb)
  375. Dim merge
  376. Dim sModule, aData, sPath
  377. Dim aFeatures, i
  378. If 0 = dictModules.Count Then Exit Sub
  379. Set merge = WScript.CreateObject("Msm.Merge")
  380. merge.OpenLog "temp.log"
  381. merge.OpenDatabase sDb
  382. For Each sModule In dictModules
  383. aData = dictModules.Item(sModule)
  384. sPath = BaseDir(aData(0))
  385. merge.OpenModule sPath, aData(1)
  386. merge.Merge aData(2), aData(4)
  387. aFeatures = Split(aData(3), ":")
  388. For i = 0 To UBound(aFeatures)
  389. merge.Connect aFeatures(i)
  390. Next
  391. If IsEmpty(g_sBaseDir) Then g_sBaseDir = "."
  392. merge.ExtractFiles g_sBaseDir
  393. merge.CloseModule
  394. Next
  395. merge.CloseDatabase True
  396. merge.CloseLog
  397. End Sub
  398. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  399. ' ProcessFileSequences ??? (robmen) - why does this function exist if it isn't used?
  400. Sub ProcessFileSequences
  401. Dim vw, rec
  402. Dim sFile, nSequence
  403. If 1 <> database.TablePersistent("File") Then Exit Sub
  404. Set vw = database.OpenView("SELECT `File`, `Sequence` FROM `File`")
  405. vw.Execute
  406. Do
  407. Set rec = vw.Fetch
  408. If Not rec Is Nothing Then
  409. sFile = rec.StringData(1)
  410. If dictSequences.Exists(sFile) Then
  411. nSequence = dictSequences.Item(sFile)
  412. rec.IntegerData(2) = CInt(nSequence) ' update the sequence
  413. vw.Modify msiViewModifyUpdate, rec
  414. Else
  415. WScript.Echo "Warning, unexpected file '" & sFile & "' has sequence: " & nSequence
  416. End If
  417. End If
  418. Loop Until rec Is Nothing
  419. End Sub ' ProcessFileSequences
  420. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  421. ' ProcessMediaTable
  422. Sub ProcessMediaTable
  423. Dim vw, rec
  424. Dim sCabinet, fEmbed
  425. Dim nBeginSequence, nEndSequence
  426. nBeginSequence = 0
  427. Set vw = database.OpenView("SELECT `LastSequence`, `Cabinet` FROM `Media` ORDER BY `LastSequence`")
  428. vw.Execute
  429. Do
  430. Set rec = vw.Fetch
  431. If Not rec Is Nothing Then
  432. nEndSequence = rec.IntegerData(1)
  433. sCabinet = rec.StringData(2)
  434. If 0 < Len(sCabinet) Then
  435. If "#" = Left(sCabinet, 1) Then
  436. sCabinet = Mid(sCabinet, 2)
  437. fEmbed = True
  438. Else
  439. fEmbed = False
  440. End If
  441. CABFiles sCabinet, nBeginSequence, nEndSequence, fEmbed
  442. End If
  443. nBeginSequence = nEndSequence + 1
  444. End If
  445. Loop Until rec Is Nothing
  446. End Sub ' ProcessMediaTable
  447. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  448. ' CABFiles
  449. Sub CABFiles(sCabName, nMinSequence, nMaxSequence, fAsStream)
  450. Const sDDF = "$_candle.ddf"
  451. Const sCAB = "$_candle.cab"
  452. Const sINF = "$_candle.inf"
  453. Const sRPT = "$_candle.rpt"
  454. ' bail if there are no files
  455. If 1 <> database.TablePersistent("File") Then Exit Sub
  456. Dim sKey, sPath
  457. Dim sSql, vw, rec
  458. Dim tsDDF : Set tsDDF = fso.CreateTextFile(sDDF, OverwriteIfExist, OpenAsASCII) : CheckError
  459. Dim shell, cabStat
  460. tsDDF.WriteLine "; Generated from " & sDatabasePath & " on " & Now
  461. tsDDF.WriteLine ".Set CabinetNameTemplate=candle*.CAB"
  462. tsDDF.WriteLine ".Set CabinetName1=" & sCAB
  463. tsDDF.WriteLine ".Set ReservePerCabinetSize=8"
  464. tsDDF.WriteLine ".Set MaxDiskSize=CDROM"
  465. tsDDF.WriteLine ".Set CompressionType=MSZIP"
  466. tsDDF.WriteLine ".Set InfFileLineFormat=(*disk#*) *file#*: *file* = *Size*"
  467. tsDDF.WriteLine ".Set InfFileName=" & sINF
  468. tsDDF.WriteLine ".Set RptFileName=" & sRPT
  469. tsDDF.WriteLine ".Set InfHeader="
  470. tsDDF.WriteLine ".Set InfFooter="
  471. tsDDF.WriteLine ".Set DiskDirectoryTemplate=."
  472. tsDDF.WriteLine ".Set Compress=ON"
  473. tsDDF.WriteLine ".Set Cabinet=ON"
  474. sSql = "SELECT `File` FROM `File`"
  475. If nMaxSequence > 0 Then
  476. sSql = sSql & " WHERE `Sequence`>=" & nMinSequence & " AND`Sequence`<=" & nMaxSequence
  477. End If
  478. sSql = sSql & " ORDER BY `Sequence`" ' ORDER BY must be at the end of the query
  479. If fVerbose Then WScript.Echo "Update Sql: " & sSql
  480. Set vw = database.OpenView(sSql)
  481. vw.Execute
  482. Do
  483. Set rec = vw.Fetch
  484. If rec Is Nothing Then Exit Do
  485. sKey = rec.StringData(1)
  486. If dictFiles.Exists(sKey) Then
  487. sPath = dictFiles.Item(sKey)
  488. Else ' file came from a merge module so resolve it in the source
  489. sPath = ResolveFileSourcePath(database, sKey, False)
  490. End If
  491. sPath = BaseDir(sPath)
  492. If fVerbose Then WScript.Echo "CAB'ing " & sPath & " for File key: " & sKey
  493. If fso.FileExists(sPath) Then
  494. tsDDF.WriteLine chr(34) & sPath & chr(34) & " " & sKey
  495. Else
  496. Fail "CAB'ing could not locate file: " & sPath
  497. End If
  498. Loop
  499. Set vw = Nothing
  500. tsDDF.Close
  501. Set shell = WScript.CreateObject("Wscript.Shell")
  502. cabStat = shell.Run("MakeCab.exe /f " & sDDF, 1, True)
  503. If cabStat <> 0 Then Fail "MAKECAB.EXE failed, possibly could not find source files, or invalid DDF format, see: " & sDDF
  504. ' add the stream to the database
  505. If fAsStream Then
  506. Set vw = database.OpenView("SELECT `Name`,`Data` FROM _Streams")
  507. vw.Execute
  508. Set rec = Installer.CreateRecord(2)
  509. rec.StringData(1) = sCabName
  510. rec.SetStream 2, sCAB : CheckError
  511. vw.Modify msiViewModifyAssign, rec 'replace any existing stream of that name
  512. Set vw = Nothing
  513. Set rec = Nothing
  514. Else
  515. If fso.FileExists(sCabName) Then fso.DeleteFile sCabName
  516. If fVerbose Then WScript.Echo "Renaming temp cab: " & sCAB & " to real cab: " & sCabName
  517. fso.MoveFile sCAB, sCabName ' rename the cab to whatever the user wanted
  518. End If
  519. ' clean up
  520. fso.DeleteFile sDDF
  521. If fAsStream Then fso.DeleteFile sCAB ' only delete if added to MSI
  522. fso.DeleteFile sINF
  523. fso.DeleteFile sRPT
  524. End Sub ' CABFiles
  525. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  526. ' ProcessRedistInfo
  527. Sub ProcessRedistInfo(sOutputPath)
  528. Dim vw, rec, n, sFormat, sLanguage, sDescription, sDistribution, sType
  529. If 2 = database.TablePersistent("redist_Info") Then Exit Sub
  530. If fModule Then sFormat = "msm" Else sFormat = "msi"
  531. sLanguage = aSumInfo(7)
  532. n = InStr(sLanguage, ";")
  533. If -1 <> n Then sLanguage = Mid(sLanguage, n + 1)
  534. If 0 = Len(LTrim(sLanguage)) Then sLanguage = 0
  535. Set vw = database.OpenView("SELECT `Description`, `Distribution`, `Type` FROM `redist_Info`")
  536. vw.Execute
  537. Set rec = vw.Fetch
  538. If Not rec Is Nothing Then
  539. sDescription = EscapeXml(rec.StringData(1), False)
  540. If 0 = rec.IntegerData(2) Then sDistribution = "internal" else sDistribution = "external"
  541. If 0 = rec.IntegerData(3) Then sType = "debug" else sType = "retail"
  542. Else
  543. Fail "redist_Info is malformed"
  544. End If
  545. Dim tsRedist
  546. Set tsRedist = fso.CreateTextFile(sOutputPath, OverwriteIfExist, OpenAsASCII)
  547. CheckError
  548. tsRedist.WriteLine "<RedistPack Format='" & sFormat & "' Type='" & sType & "' Language='" & sLanguage & "' Distribution='" & sDistribution & "'>"
  549. If 0 < Len(sDescription) Then tsRedist.WriteLine " <Description>" & sDescription & "</Description>"
  550. ProcessRedistKeywords(tsRedist)
  551. ProcessRedistContacts(tsRedist)
  552. ProcessRedistPermissions(tsRedist)
  553. ProcessRedistOs(tsRedist)
  554. tsRedist.WriteLine "</RedistPack>"
  555. End Sub
  556. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  557. ' ProcessRedistKeywords
  558. Sub ProcessRedistKeywords(tsRedist)
  559. Dim vw, rec, n, sKeyword, aKeywords
  560. aKeywords = Split(aSumInfo(5), ",")
  561. For n = 0 To UBound(aKeywords)
  562. sKeyword = EscapeXml(Trim(aKeywords(n)), False)
  563. tsRedist.WriteLine " <Keyword>" & sKeyword & "</Keyword>"
  564. Next
  565. ' If 2 = database.TablePersistent("redist_Keywords") Then Exit Sub
  566. ' Set vw = database.OpenView("SELECT `Keyword`FROM `redist_Keywords`")
  567. ' vw.Execute
  568. ' Do
  569. ' Set rec = vw.Fetch
  570. '
  571. ' If Not rec Is Nothing Then
  572. ' sKeyword = EscapeXml(rec.StringData(1), False)
  573. ' tsRedist.WriteLine " <Keyword>" & sKeyword & "</Keyword>"
  574. ' End If
  575. ' Loop Until rec Is Nothing
  576. End Sub
  577. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  578. ' ProcessRedistContacts
  579. Sub ProcessRedistContacts(tsRedist)
  580. Dim vw, rec, sContact
  581. If 2 = database.TablePersistent("redist_Contacts") Then Exit Sub
  582. Set vw = database.OpenView("SELECT `Contact`FROM `redist_Contacts`")
  583. vw.Execute
  584. Do
  585. Set rec = vw.Fetch
  586. If Not rec Is Nothing Then
  587. sContact = EscapeXml(rec.StringData(1), False)
  588. tsRedist.WriteLine " <Contact>" & sContact & "</Contact>"
  589. End If
  590. Loop Until rec Is Nothing
  591. End Sub
  592. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  593. ' ProcessRedistPermissions
  594. Sub ProcessRedistPermissions(tsRedist)
  595. Dim vw, rec, sDomain, sAlias
  596. If 2 = database.TablePersistent("redist_Permissions") Then Exit Sub
  597. Set vw = database.OpenView("SELECT `Domain`, `Alias` FROM `redist_Permissions`")
  598. vw.Execute
  599. Do
  600. Set rec = vw.Fetch
  601. If Not rec Is Nothing Then
  602. sDomain = EscapeXml(rec.StringData(1), True)
  603. sAlias = EscapeXml(rec.StringData(2), True)
  604. tsRedist.WriteLine " <Permission Domain='" & sDomain & "' Alias='" & sAlias &"'/>"
  605. End If
  606. Loop Until rec Is Nothing
  607. End Sub
  608. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
  609. ' ProcessRedistOs
  610. Sub ProcessRedistOs(tsRedist)
  611. Dim vw, rec, n, sProc, sType, sFlavor, sLanguage, sMin, sMax
  612. If 2 = database.TablePersistent("redist_Os") Then Exit Sub
  613. sProc = aSumInfo(7)
  614. n = InStr(sProc, ";")
  615. If -1 <> n Then sProc = Left(sProc, n - 1) Else sProc = Empty
  616. If "Intel" = sProc Then sProc = "x86"
  617. If "Intel64" = sProc Then sProc = "ia64"
  618. If "Alpha" = sProc Then sProc = "axp64"
  619. Set vw = database.OpenView("SELECT `Type`, `Flavor`, `Language`, `MinVersion`, `MaxVersion` FROM `redist_Os`")
  620. vw.Execute
  621. Do
  622. Set rec = vw.Fetch
  623. If Not rec Is Nothing Then
  624. sType = rec.StringData(1)
  625. sFlavor = rec.StringData(2)
  626. sLanguage = rec.StringData(3)
  627. sMin = rec.StringData(4)
  628. sMax = rec.StringData(5)
  629. tsRedist.Write " <" & sType
  630. If 0 < Len(sProc) Then tsRedist.Write " Processor='" & sProc & "'"
  631. If 0 < Len(sFlavor) Then tsRedist.Write " Flavor='" & sFlavor & "'"
  632. If 0 < Len(sLanguage) Then tsRedist.Write " Language='" & sLanguage & "'"
  633. If 0 < Len(sMin) Then tsRedist.Write " MinVersion='" & sMin & "'"
  634. If 0 < Len(sMax) Then tsRedist.Write " MaxVersion='" & sMax & "'"
  635. tsRedist.WriteLine "/>"
  636. End If
  637. Loop Until rec Is Nothing
  638. End Sub
  639. Function EscapeXml(s, fStrict)
  640. s = Replace(s, "&", "&amp;")
  641. s = Replace(s, "<", "&gt;")
  642. s = Replace(s, ">", "&lt;")
  643. If fStrict Then
  644. s = Replace(s, "'", "&apos;")
  645. s = Replace(s, """", "&quot;")
  646. End If
  647. EscapeXml = s
  648. End Function
  649. </script>
  650. </job>