Jump to content

WIMGAPI UDF


Homes32
 Share

Recommended Posts

Do you have an example of the _WIM_ApplyImage() function. The code documentation seems to be a copy of the capture function.

its very similar to capture.

I have updated the example code in the first post with a basic Apply function.

Link to comment
Share on other sites

  • 1 year later...

First, thanks a lot for this UDF! Its Awesome and will help me a crazy amount. I was wondering if you could help me. I'm trying to call multiple functions in the same script such as Mount and then unmounts or create .wim and then mount but once I call one of the functions no more functions will work. Any ideas where I'm going wrong? Any help would be very appreciated.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=favicon.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Wimgapi.au3> ; functions for WIM
#include <GUIConstantsEx.au3>
Global $swimfile, $hWim, $hImage, $filepath, $Percent, $rTime, $pCallBack
Global $gsWimDLL = "x86\wimgapi.dll"
;Global $gsWimDLL = @SystemDir & "\wimgapi.dll" ; path to wimgapi.dll
$debug = 0;
$ProgramName = "Backup Manager"
MainMenu()
; Apply
;-----------------------------
Func Apply($sWimFile, $iImageIndex, $sTarget)
    ProgressOn('Apply', '', '', -1, -1, 19)
    ; Register callbacks so we get progress information for the capture process.
    ; WARNING: This does not work very well with Apply do to the way autoit handles callbacks.
    ; See the following post for more info:
    ; [url=http://www.autoitscript.com/forum/topic/127075-wimgapi-udf/page__view__findpost__p__917049]http://www.autoitscript.com/forum/topic/127075-wimgapi-udf/page__view__findpost__p__917049[/url]
    $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword')
    _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0)
    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf
    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, $sTarget)
    ; load the image index
    $hImage = _WIM_LoadImage($hWim, $iImageIndex)
    ; Apply the image
    $aResult = _WIM_ApplyImage($hImage, $sTarget)
    If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to apply image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")")
    Cleanup()
    ProgressOff()
EndFunc
; Mount
;-----------------------------
Func Mount($sMountPath, $sWimFile, $iImageIndex, $RW)
        $aResult = _WIM_MountImage($sMountPath, $sWimFile, $iImageIndex, $RW)
        If $aResult = 0 Then
            MsgBox(48, $ProgramName, "Mount Error: (" & $aResult & "," & @error & "," & @extended & ")")
            Cleanup()
            Exit (253) ; mount error
        EndIf
        Cleanup()
EndFunc
; UnMount
;-----------------------------
Func UnMount($sMountPath, $iCommit)
        $aResult = _WIM_UnMountImage($sMountPath, 0, 0, $iCommit)
        If $aResult = 0 Then
            MsgBox(48, $ProgramName, "UnMount Error: (" & $aResult & "," & @error & "," & @extended & ")")
            Cleanup()
            Exit (254) ; Unmount error
        EndIf
        Cleanup()
EndFunc
; GetInfo
; Modified to display info instead of writing to a file!
;-----------------------------
Func GetInfo($sWimFile)
    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf
    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)
    ; read wim attributes
    $aWimAttribs = _WIM_GetImageAttributes($hWim)
    ; read info from the image
    $aXML = _WIM_GetImageInformation($hWim)
    ; Cleanup any open handles
    Cleanup()
        ; make our output pretty
        Switch $aWimAttribs[4]
            Case $WIM_COMPRESS_NONE
                $aWimAttribs[4] = "NONE"
            Case $WIM_COMPRESS_XPRESS
                $aWimAttribs[4] = "XPRESS"
            Case $WIM_COMPRESS_LZX
                $aWimAttribs[4] = "LZX"
        EndSwitch
  MsgBox(0,"Backup Complete","Backup Information:" & @CRLF & _
                "----------------" & @CRLF & _
                "Backup Path:  : " & $aWimAttribs[1] & @CRLF & _
                "GUID      : " & $aWimAttribs[2] & @CRLF & _
                "Image Count: " & $aWimAttribs[3] & @CRLF & _
                "Compression: " & $aWimAttribs[4] & @CRLF & _
                "Part Number: " & $aWimAttribs[5] & "/" & $aWimAttribs[6] & @CRLF & _
                "Boot Index : " & $aWimAttribs[7] & @CRLF & _
                "Attributes : " & $aWimAttribs[8] & @CRLF & @CRLF & @CRLF & _
                "Available Image Choices:" & @CRLF & _
                "------------------------" & @CRLF & _
                $aXML[1])
        ;Local $outFile = @ScriptDir & "wiminfo.txt"
        ;If FileExists($outFile) Then FileDelete($outFile)
        ;FileWrite($outFile, @CRLF & $ProgramName & @CRLF & @CRLF & @CRLF & @CRLF & _
        ;        "WIM Information:" & @CRLF & _
        ;        "----------------" & @CRLF & _
        ;        "Wim Path:  : " & $aWimAttribs[1] & @CRLF & _
        ;        "GUID      : " & $aWimAttribs[2] & @CRLF & _
        ;        "Image Count: " & $aWimAttribs[3] & @CRLF & _
        ;        "Compression: " & $aWimAttribs[4] & @CRLF & _
        ;        "Part Number: " & $aWimAttribs[5] & "/" & $aWimAttribs[6] & @CRLF & _
        ;        "Boot Index : " & $aWimAttribs[7] & @CRLF & _
        ;        "Attributes : " & $aWimAttribs[8] & @CRLF & @CRLF & @CRLF & _
        ;        "Available Image Choices:" & @CRLF & _
        ;        "------------------------" & @CRLF & _
        ;        $aXML[1])
EndFunc   ;==>GetInfo
; Extract
;-----------------------------
Func Extract($sWimFile, $iImageIndex, $sFilePath, $sExtractTo)
    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf
    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)
    ; load the image index
    $hImage = _WIM_LoadImage($hWim, $iImageIndex)
    ; extract the file
    $aResult = _WIM_ExtractImagePath($hImage, $sFilePath, $sExtractTo)
    If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to extract from image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")")
    Cleanup()
EndFunc
; Capture
;-----------------------------
Func Capture($Path, $sWimFile, $sImageName, $sImageDesc, $Compress)
    ProgressOn('Backing up...', '', '', -1, -1, 19)
    ; Register callbacks so we get progress information for the capture process.
    $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword')
    _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0)
    ; first we need to create a blank .wim file with write access and our compression options
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_WRITE, $WIM_CREATE_ALWAYS, 0, $Compress, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to create image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252) ; image create failed
    EndIf
    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)
    ; start the image capture!!!
    $hImage = _WIM_CaptureImage($hWim, $Path, 0)
    If $hImage = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to capture image. (" & $hImage & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (251) ; image capture failed
    EndIf
    ; add our name and description to the XML data - ChrW(65279) is the BOM
    $sXML = ChrW(65279) & "<IMAGE><NAME>" & $sImageName & "</NAME><DESCRIPTION>" & $sImageDesc & "</DESCRIPTION></IMAGE>"
    _WIM_SetImageInformation($hImage, $sXML)
    _WIM_SetBootImage($hWim, 1)
    Cleanup() ; free resources
    ProgressOff()
EndFunc   ;==>Capture
; ==================================================================================================================
; Function: CallBack
; Description: Very Basic Sample Callback function for capture progress
; Usage:       CallBack($msgId, $param1, $param2, $B)
; Author:     Homes32
; ==================================================================================================================
Func CallBack($msgId, $param1, $param2, $unused)
    Switch $msgId
        Case $WIM_MSG_PROGRESS ; get progress % and time remaining
            $Percent = $param1
            If $param2 = 0 Then
                $rTime = ""
            Else
                $rTime = StringFormat('Remaining: %i sec.', $param2 / 1000)
            EndIf
        Case $WIM_MSG_PROCESS ; get the file name being processed
            $Struct = DllStructCreate("ushort[1024]", $param1)
            $sFilePath = ""
            $i = 1
            While 1
                $Tmp = DllStructGetData($Struct, 1, $i)
                If $Tmp = 0 Then ExitLoop
                $sFilePath &= ChrW($Tmp)
                $i += 1
            WEnd
    EndSwitch
    ProgressSet($Percent, StringFormat('%3i%% completed.      %snn   %s', $Percent, $rTime, $filePath), 'Backing up... ' & $sWimFile)
    Return $WIM_MSG_SUCCESS
EndFunc   ;==>CallBack
Func Cleanup()
    ; Cleanup any open handles
    If $hImage Then _WIM_CloseHandle($hImage)
    If $hWim Then _WIM_CloseHandle($hWim)
    If $pCallBack Then ; Cleanup our callbacks
        $aResult = _WIM_UnregisterMessageCallback(0, DllCallbackGetPtr($pCallBack))
        DllCallbackFree($pCallBack)
    EndIf
    _WIM_Shutdown() ; shutdown wimgapi.dll
EndFunc   ;==>Cleanup
;File Save Dialog but also appends file type
Func _FileSaveDialog ($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR (BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt,16), 3 ))
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile   = DllStructCreate ('char[' & $iFileLen & ']')
    Local $usExtn   = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetSaveFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        Return StringStripWS(DllStructGetData ($usFile, 1),3)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc
Func MainMenu()
    ;Local $MESSAGE = "The following buttons have been clicked"
    Local $browseBackupOption, $makeBackupOption, $close, $msg, $backupLocationBrowse,$captureLocation
    GUICreate("Select",250,150) ; will create a dialog box that when displayed is centered
    $browseBackupOption = GUICtrlCreateButton("Browse Backup", 64, 30, 125, 25)
    $makeBackupOption = GUICtrlCreateButton("Make Backup", 64, 60, 125, 25)
    $close = GUICtrlCreateButton("Close", 64, 90, 125, 25)
    GUISetState()
    $msg = 0
    While $msg <> $GUI_EVENT_CLOSE
        $msg = GUIGetMsg()
        Select
   Case $msg = $browseBackupOption
    ; Fire up wimgapi.dll
    $aResult = _WIM_Startup()
    If @error = 2 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.")
     Exit (2)
    ElseIf @error = 1 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)")
     Exit (254)
    EndIf
    ;Save file dialog box to find out where to save the .wim
    $fileToOpen = FileOpenDialog("Image Location", "D:\Captures" & "", "Backups (*.wim)", 1 + 4)
    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Backup is stored in " &$fileToOpen)
    EndIf
    $sMountPath = "C:\mount"
    Mount($sMountPath, $fileToOpen, 1,0)
    Run("Explorer.exe " & $sMountPath)
    MsgBox (0, "Close Backup","Click Ok to close backup ")
    UnMount($sMountPath, 1)
    ;$aResult = _WIM_UnMountImage($sMountPath, 0, 0, 0)
    ;Unload .dll
    Cleanup()
            Case $msg = $makeBackupOption
    ; Fire up wimgapi.dll
    $aResult = _WIM_Startup()
    If @error = 2 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.")
     Exit (2)
    ElseIf @error = 1 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)")
     Exit (254)
    EndIf
    ;$placeToBackup = "C:"
    ;Open file open dialog box
    $placeToBackup = FileSelectFolder ( "Folder To Backup", "" )
    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Capture Location " & $placeToBackup)
    EndIf
    ;Save file dialog box to find out where to save the .wim
    $placeToBackupTo = _FileSaveDialog("Image Location", "D:\Captures" & "", "Backups (*.wim)", 1 + 4)
    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Backup is stored in " &$placeToBackupTo)
    EndIf
    ;Capture the folder or Drive
    Capture($placeToBackup, $placeToBackupTo, "My Backup IMG", "This is a backup", 1)
    MsgBox (0, "Backup Complete!","Backup Completed Successfully! " & $placeToBackupTo)
    ;Unload .dll
    Cleanup()
            Case $msg = $close
                ;MsgBox(0, "", "the closing button has been clicked", 2)
                Exit
        EndSelect
    WEnd
EndFunc   ;==>Example

 

Edited by Melba23
Added tags
Link to comment
Share on other sites

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=favicon.ico
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Wimgapi.au3> ; functions for WIM
#include <GUIConstantsEx.au3>

Global $swimfile, $hWim, $hImage, $filepath, $Percent, $rTime, $pCallBack

Global $gsWimDLL = "x86\wimgapi.dll"
;Global $gsWimDLL = @SystemDir & "\wimgapi.dll" ; path to wimgapi.dll

$debug = 0;

$ProgramName = "Backup Manager"

MainMenu()

; Apply
;-----------------------------

Func Apply($sWimFile, $iImageIndex, $sTarget)

    ProgressOn('Apply', '', '', -1, -1, 19)

    ; Register callbacks so we get progress information for the capture process.
    ; WARNING: This does not work very well with Apply do to the way autoit handles callbacks.
    ; See the following post for more info:
    ; http://www.autoitscript.com/forum/topic/127075-wimgapi-udf/page__view__findpost__p__917049
    $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword')
    _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0)

    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)

    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf

    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, $sTarget)

    ; load the image index
    $hImage = _WIM_LoadImage($hWim, $iImageIndex)

    ; Apply the image
    $aResult = _WIM_ApplyImage($hImage, $sTarget)
    If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to apply image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")")

    ;Cleanup()
    ProgressOff()
EndFunc

; Mount
;-----------------------------
Func Mount($sMountPath, $sWimFile, $iImageIndex, $RW)

        $aResult = _WIM_MountImage($sMountPath, $sWimFile, $iImageIndex, $RW)

        If $aResult = 0 Then
            MsgBox(48, $ProgramName, "Mount Error: (" & $aResult & "," & @error & "," & @extended & ")")
            Cleanup()
            Exit (253) ; mount error
        EndIf

        Cleanup()
EndFunc

; UnMount
;-----------------------------
Func UnMount($sMountPath, $iCommit)

        $aResult = _WIM_UnMountImage($sMountPath, 0, 0, $iCommit)

        If $aResult = 0 Then
            MsgBox(48, $ProgramName, "UnMount Error: (" & $aResult & "," & @error & "," & @extended & ")")
            Cleanup()
            Exit (254) ; Unmount error
        EndIf

        Cleanup()

EndFunc

; GetInfo
; Modified to display info instead of writing to a file!
;-----------------------------
Func GetInfo($sWimFile)

    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf

    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)

    ; read wim attributes
    $aWimAttribs = _WIM_GetImageAttributes($hWim)

    ; read info from the image
    $aXML = _WIM_GetImageInformation($hWim)

    ;Cleanup any open handles
    Cleanup()

        ; make our output pretty
        Switch $aWimAttribs[4]
            Case $WIM_COMPRESS_NONE
                $aWimAttribs[4] = "NONE"
            Case $WIM_COMPRESS_XPRESS
                $aWimAttribs[4] = "XPRESS"
            Case $WIM_COMPRESS_LZX
                $aWimAttribs[4] = "LZX"
        EndSwitch

  MsgBox(0,"Backup Complete","Backup Information:" & @CRLF & _
                "----------------" & @CRLF & _
                "Backup Path:  : " & $aWimAttribs[1] & @CRLF & _
                "GUID      : " & $aWimAttribs[2] & @CRLF & _
                "Image Count: " & $aWimAttribs[3] & @CRLF & _
                "Compression: " & $aWimAttribs[4] & @CRLF & _
                "Part Number: " & $aWimAttribs[5] & "/" & $aWimAttribs[6] & @CRLF & _
                "Boot Index : " & $aWimAttribs[7] & @CRLF & _
                "Attributes : " & $aWimAttribs[8] & @CRLF & @CRLF & @CRLF & _
                "Available Image Choices:" & @CRLF & _
                "------------------------" & @CRLF & _
                $aXML[1])

EndFunc   ;==>GetInfo

; Extract
;-----------------------------

Func Extract($sWimFile, $iImageIndex, $sFilePath, $sExtractTo)
    ; load .wim file with read access
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_READ, $WIM_OPEN_EXISTING, 0, 0, 0)

    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to load image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252)
    EndIf

    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)

    ; load the image index
    $hImage = _WIM_LoadImage($hWim, $iImageIndex)

    ; extract the file
    $aResult = _WIM_ExtractImagePath($hImage, $sFilePath, $sExtractTo)
    If $aResult = 0 Then MsgBox(48, $ProgramName, "Error: Failed to extract from image. Make sure your path exists! (" & $aResult & "," & @error & "," & @extended & ")")

    Cleanup()
EndFunc

; Capture
;-----------------------------
Func Capture($Path, $sWimFile, $sImageName, $sImageDesc, $Compress)

    ProgressOn('Backing up...', '', '', -1, -1, 19)

    ; Register callbacks so we get progress information for the capture process.
    $pCallBack = DllCallbackRegister('CallBack', 'int', 'dword;WPARAM;LPARAM;dword')
    _WIM_RegisterMessageCallback(0, DllCallbackGetPtr($pCallBack), 0)

    ; first we need to create a blank .wim file with write access and our compression options
    $hWim = _WIM_CreateFile($sWimFile, $WIM_GENERIC_WRITE, $WIM_CREATE_ALWAYS, 0, $Compress, 0)
    If $hWim = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to create image. (" & $hWim & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (252) ; image create failed
    EndIf

    ; set our temp path
    $aResult = _WIM_SetTemporaryPath($hWim, @TempDir)

    ; start the image capture!!!
    $hImage = _WIM_CaptureImage($hWim, $Path, 0)

    If $hImage = 0 Then
        MsgBox(48, $ProgramName, "Error: Failed to capture image. (" & $hImage & "," & @error & "," & @extended & ")")
        Cleanup()
        Exit (251) ; image capture failed
    EndIf

    ; add our name and description to the XML data - ChrW(65279) is the BOM
    $sXML = ChrW(65279) & "<IMAGE><NAME>" & $sImageName & "</NAME><DESCRIPTION>" & $sImageDesc & "</DESCRIPTION></IMAGE>"

    _WIM_SetImageInformation($hImage, $sXML)
    _WIM_SetBootImage($hWim, 1)

    Cleanup() ; free resources
    ProgressOff()

EndFunc   ;==>Capture

; ==================================================================================================================
; Function: CallBack
; Description: Very Basic Sample Callback function for capture progress
; Usage:       CallBack($msgId, $param1, $param2, $
; Author:     Homes32
; ==================================================================================================================
Func CallBack($msgId, $param1, $param2, $unused)
    Switch $msgId
        Case $WIM_MSG_PROGRESS ; get progress % and time remaining
            $Percent = $param1

            If $param2 = 0 Then
                $rTime = ""
            Else
                $rTime = StringFormat('Remaining: %i sec.', $param2 / 1000)
            EndIf

        Case $WIM_MSG_PROCESS ; get the file name being processed

            $Struct = DllStructCreate("ushort[1024]", $param1)
            $sFilePath = ""
            $i = 1
            While 1
                $Tmp = DllStructGetData($Struct, 1, $i)
                If $Tmp = 0 Then ExitLoop
                $sFilePath &= ChrW($Tmp)
                $i += 1
            WEnd
    EndSwitch

    ProgressSet($Percent, StringFormat('%3i%% completed.      %s   %s', $Percent, $rTime, $filePath), 'Backing up... ' & $sWimFile)

    Return $WIM_MSG_SUCCESS

EndFunc   ;==>CallBack

Func Cleanup()
    ; Cleanup any open handles
    If $hImage Then _WIM_CloseHandle($hImage)

    If $hWim Then _WIM_CloseHandle($hWim)

    If $pCallBack Then ; Cleanup our callbacks
        $aResult = _WIM_UnregisterMessageCallback(0, DllCallbackGetPtr($pCallBack))
        DllCallbackFree($pCallBack)
    EndIf

 $swimfile = ""
 $filepath = ""
 $Percent = ""
 $rTime = ""
 $pCallBack = ""

EndFunc   ;==>Cleanup

Func CleanupMajor()
    ; Cleanup any open handles
    If $hImage Then _WIM_CloseHandle($hImage)

    If $hWim Then _WIM_CloseHandle($hWim)

    If $pCallBack Then ; Cleanup our callbacks
        $aResult = _WIM_UnregisterMessageCallback(0, DllCallbackGetPtr($pCallBack))
        DllCallbackFree($pCallBack)
    EndIf

 $swimfile = ""
 $filepath = ""
 $Percent = ""
 $rTime = ""
 $pCallBack = ""

    _WIM_Shutdown() ; shutdown wimgapi.dll

EndFunc   ;==>Cleanup

;File Save Dialog but also appends file type
Func _FileSaveDialog ($sTitle, $sInitDir, $sFilter = 'All (*.*)', $iOpt = 0, $sDefaultFile = "", $sDefaultExt = "", $mainGUI = 0)
    Local $iFileLen = 65536 ; Max chars in returned string
    ; API flags prepare
    Local $iFlag = BitOR (BitShift (BitAND ($iOpt, 2),-10), BitShift (BitAND ($iOpt,16), 3 ))
    ; Filter string to array convertion
    Local $asFLines = StringSplit ( $sFilter, '|'), $asFilter [$asFLines [0] *2+1]
    Local $i, $iStart, $iFinal, $suFilter = ''
    $asFilter [0] = $asFLines [0] *2
    For $i=1 To $asFLines [0]
        $iStart = StringInStr ($asFLines [$i], '(', 0, 1)
        $iFinal = StringInStr ($asFLines [$i], ')', 0,-1)
        $asFilter [$i*2-1] = StringStripWS (StringLeft ($asFLines [$i], $iStart-1), 3)
        $asFilter [$i*2] = StringStripWS (StringTrimRight (StringTrimLeft ($asFLines [$i], $iStart), StringLen ($asFLines [$i]) -$iFinal+1), 3)
        $suFilter = $suFilter & 'byte[' & StringLen ($asFilter [$i*2-1])+1 & '];byte[' & StringLen ($asFilter [$i*2])+1 & '];'
    Next
    ; Create API structures
    Local $uOFN = DllStructCreate ('dword;int;int;ptr;ptr;dword;dword;ptr;dword' & _
        ';ptr;int;ptr;ptr;dword;short;short;ptr;ptr;ptr;ptr;ptr;dword;dword' )
    Local $usTitle  = DllStructCreate ('byte[' & StringLen ($sTitle) +1 & ']')
    Local $usInitDir= DllStructCreate ('byte[' & StringLen ($sInitDir) +1 & ']')
    Local $usFilter = DllStructCreate ($suFilter & 'byte')
    Local $usFile   = DllStructCreate ('char[' & $iFileLen & ']')
    Local $usExtn   = DllStructCreate ('byte[' & StringLen ($sDefaultExt) +1 & ']')
    For $i=1 To $asFilter [0]
        DllStructSetData ($usFilter, $i, $asFilter [$i])
    Next
    ; Set Data of API structures
    DllStructSetData ($usTitle, 1, $sTitle)
    DllStructSetData ($usInitDir, 1, $sInitDir)
    DllStructSetData ($usFile, 1, $sDefaultFile)
    DllStructSetData ($usExtn, 1, $sDefaultExt)
    DllStructSetData ($uOFN,  1, DllStructGetSize($uOFN))
    DllStructSetData ($uOFN,  2, $mainGUI)
    DllStructSetData ($uOFN,  4, DllStructGetPtr ($usFilter))
    DllStructSetData ($uOFN,  7, 1)
    DllStructSetData ($uOFN,  8, DllStructGetPtr ($usFile))
    DllStructSetData ($uOFN,  9, $iFileLen)
    DllStructSetData ($uOFN, 12, DllStructGetPtr ($usInitDir))
    DllStructSetData ($uOFN, 13, DllStructGetPtr ($usTitle))
    DllStructSetData ($uOFN, 14, $iFlag)
    DllStructSetData ($uOFN, 17, DllStructGetPtr ($usExtn))
    DllStructSetData ($uOFN, 23, BitShift (BitAND ($iOpt, 32), 5))
    ; Call API function
    $ret = DllCall ('comdlg32.dll', 'int', 'GetSaveFileName', _
            'ptr', DllStructGetPtr ($uOFN) )
    If $ret [0] Then
        Return StringStripWS(DllStructGetData ($usFile, 1),3)
    Else
        SetError (1)
        Return ""
    EndIf
EndFunc

Func MainMenu()
    ;Local $MESSAGE = "The following buttons have been clicked"
    Local $browseBackupOption, $makeBackupOption, $close, $msg, $backupLocationBrowse,$captureLocation

    GUICreate("Select",250,150) ; will create a dialog box that when displayed is centered

    $browseBackupOption = GUICtrlCreateButton("Browse Backup", 64, 30, 125, 25)
    $makeBackupOption = GUICtrlCreateButton("Make Backup", 64, 60, 125, 25)
    $close = GUICtrlCreateButton("Close", 64, 90, 125, 25)

    GUISetState()

    $msg = 0
    While $msg <> $GUI_EVENT_CLOSE
        $msg = GUIGetMsg()

        Select
   Case $msg = $browseBackupOption

    ; Fire up wimgapi.dll
    $aResult = _WIM_Startup()
    If @error = 2 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.")
     Exit (2)
    ElseIf @error = 1 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)")
     Exit (254)
    EndIf

    ;Save file dialog box to find out where to save the .wim
    $fileToOpen = FileOpenDialog("Image Location", "D:\Captures" & "", "Backups (*.wim)", 1 + 4)

    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Backup is stored in " &$fileToOpen)
    EndIf

    $sMountPath = "C:\mount"
    Mount($sMountPath, $fileToOpen, 1,0)
    Run("Explorer.exe " & $sMountPath)

    MsgBox (0, "Close Backup","Click Ok to close backup ")

    UnMount($sMountPath, 1)

            Case $msg = $makeBackupOption

    ; Fire up wimgapi.dll
    $aResult = _WIM_Startup()
    If @error = 2 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "The file could not be found.")
     Exit (2)
    ElseIf @error = 1 Then
     MsgBox(16, $ProgramName, "Error loading library: " & "(" & $aResult & "," & @error & ", " & $gsWimDLL & ")" & @CRLF & @CRLF & "Wrong DLL. Make sure you are using the right arch (x86/x64)")
     Exit (254)
    EndIf

    ;$placeToBackup = "C:"
    ;Open file open dialog box
    $placeToBackup = FileSelectFolder ( "Folder To Backup", "" )

    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Capture Location " & $placeToBackup)
    EndIf

    ;Save file dialog box to find out where to save the .wim
    $placeToBackupTo = _FileSaveDialog("Image Location", "D:\Captures" & "", "Backups (*.wim)", 1 + 4)

    ;Debug messages
    If $debug = 1 Then
     MsgBox (0, "BackupFrom","Backup is stored in " &$placeToBackupTo)
    EndIf

    ;Capture the folder or Drive
    Capture($placeToBackup, $placeToBackupTo, "My Backup IMG", "This is a backup", 1)

    MsgBox (0, "Backup Complete!","Backup Completed Successfully! " & $placeToBackupTo)
    ;GetInfo($placeToBackupTo)

            Case $msg = $close
                CleanupMajor()
                Exit
        EndSelect
    WEnd
EndFunc   ;==>Example

Incase anyone is interested I found the problem. When a function is run the cleanup function is called which unloads the .dll. I changed the cleanup function to only clear the vars and I also created a major cleanup function that is called once on program shutdown to close the .dll. This is what I've got so far. I've created a small gui and I'm going to keep tweeking it. If anyone else is interested I could upload newer versions as I add features. Thanks again for this awesome udf!

Edited by Melba23
Added tags
Link to comment
Share on other sites

  • Moderators

Damian89,

When you post code please use Code tags - see here how to do it. Then you get a scrolling box and syntax colouring as you can see above now I have added the tags. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

  • 2 months later...
  • 1 year later...

Hi,

Have been using this UDF, and added another function to it for the people to use:  _WIM_GetMountedImageInfo

; #FUNCTION# ====================================================================================================================
; Name...........: _WIM_GetMountedImageInfo
; Description ...: Returns list of mounted images
; Syntax.........: _WIM_GetMountedImageInfo()
; Parameters ....:
; Return values .: Success - Returns Array where [0][0] holds number of mounted images, each subsequent row holds information to each image
;                  Failure - Returns 0 and Sets @Error:
;                  |0 - No DLLCall error.
;                  |1 - Unable to use the DLL file
;                  |2 - Unknown "return type"
;                  |3 - "function" not found in the DLL file
;                  |4 - Bad number of parameters.
;                  Both - Sets @Extended to _WinAPI_GetLastError()
; Author(s) .....: Herman van Drie (hvandrie)
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......;
;
; ===============================================================================================================================
Func _WIM_GetMountedImageInfo()

    Local $aReturn[2][4]
    Local $pWimMountList = DllStructCreate($tagWIM_MOUNT_LIST)
    Local $pWimMountInfoLevel1 = DllStructCreate($tagWIM_MOUNT_INFO_LEVEL1)
    Local $pWimMountImageCount = DllStructCreate("dword pdwImageCount;")
    Local $pWimMountListSize = DllStructCreate("dword pcbReturnLength;")
    Local $aResult

    $aResult = DllCall($ghwimgapi, "bool", "WIMGetMountedImageInfo", _
                "int", 1, _
                "ptr", DllStructGetPtr($pWimMountImageCount), _
                "ptr", DllStructGetPtr($pWimMountList), _
                "dword", DllStructGetSize($pWimMountList), _
                "ptr", DllStructGetPtr($pWimMountListSize))

    If _WinAPI_GetLastError() = 122 Then ; ERROR_INSUFFICIENT_BUFFER    122 (0x7A) : The data area passed to a system call is too small.

        ; Calculate required buffer / array size
        Local $iRequiredBufferSizeFactor = Int(DllStructGetData($pWimMountListSize, "pcbReturnLength"))/int(DllStructGetSize($pWimMountList))
        Local $tWimMountList

        ReDim $aReturn[UBound($aReturn,1)+$iRequiredBufferSizeFactor][4]
        For $i = 1 To $iRequiredBufferSizeFactor
            $tWimMountList &= $tagWIM_MOUNT_LIST & "; "
        Next
        $pWimMountList = DllStructCreate($tWimMountList)

        ; Retry the call
        $aResult = DllCall($ghwimgapi, "bool", "WIMGetMountedImageInfo", _
                "int", 1, _
                "ptr", DllStructGetPtr($pWimMountImageCount), _
                "ptr", DllStructGetPtr($pWimMountList), _
                "dword", DllStructGetSize($pWimMountList), _
                "ptr", DllStructGetPtr($pWimMountListSize))
    EndIf

    $aReturn[0][0]= DllStructGetData($pWimMountImageCount,"pdwImageCount") ; number of mounted images
    For $i = 0 To $aReturn[0][0] - 1
        $aReturn[$i+1][0] = DllStructGetData($pWimMountList, 4*$i+1 ) ; "WimPath"
        $aReturn[$i+1][1] = DllStructGetData($pWimMountList, 4*$i+2 ) ; "MountPath"
        $aReturn[$i+1][2] = DllStructGetData($pWimMountList, 4*$i+3 ) ; "ImageIndex")
        $aReturn[$i+1][3] = DllStructGetData($pWimMountList, 4*$i+4 ) ; "MountedForRW")
    Next
    Return SetError(@error, _WinAPI_GetLastError(), $aReturn)

EndFunc
;==>_WIM_GetMountedImageInfo

Have fun with it!

Edited by hvandrie
Link to comment
Share on other sites

  • 8 months later...

Looked interesting to try out :)

Couldn't see the correct syntax for apply

Apply($drive & "\sources\install.wim",4,"C:\")
Or
Apply($drive & "\sources\install.wim","4","C:") or "c"

nevertheless It already fails me at "load .wim file with read access" pass

Thanks

Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...