Sign in to follow this  
Followers 0
Homes32

WIMGAPI UDF

29 posts in this topic

#1 ·  Posted (edited)

A UDF for manipulating Windows Image Files (.wim) without ImageX.exe

This UDF allows you to use the Windows Imaging API directly (wimgapi.dll) so you don't have to use a command line program such as ImageX. Benefits are wimgapi.dll is shipped with windows 7 so users don't have to download the 1gb+ AIK to manage wim files. The UDF also allows you to utilize callback functions so you can show detailed progress info to your users.

wimfltr.sys/wimmount.sys required for mount/unmount only.

working with both 32 and 64 bit builds.

its pretty well documented but you should still read the MS Imaging API documentation and be familiar how wimgapi.dll works to get the most out of this UDF.

functions marked with an (*) are only available with newer versions of wimgapi.dll

Functions Included:

_WIM_ApplyImage

_WIM_CaptureImage

_WIM_CloseHandle

_WIM_CreateFile

_WIM_DeleteImage

_WIM_DeleteImageMounts *

_WIM_ExportImage

_WIM_ExtractImagePath *

_WIM_GetImageAttributes

_WIM_GetImageCount

_WIM_GetImageInformation

_WIM_LoadImage

_WIM_MountImage

_WIM_RegisterLogFile *

_WIM_RegisterMessageCallback

_WIM_RemountImage *

_WIM_SetBootImage

_WIM_SetImageInformation

_WIM_SetReferenceFile

_WIM_SetTemporaryPath

_WIM_Shutdown

_WIM_Startup

_WIM_UnMountImage

_WIM_UnRegisterLogFile *

_WIM_UnregisterMessageCallback

have fun!

Homes32

Sample Usage

#include <Wimgapi.au3> ; functions for WIM

Global $swimfile, $hWim, $hImage, $filepath, $Percent, $rTime, $pCallBack
Global $gsWimDLL = @SystemDir & "wimgapi.dll" ; path to wimgapi.dll

$ProgramName = "WIM Demo"

; 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


; your code here
; ex.
; Capture("C:toolz", "c:test.wim", "My Test IMG", "Test Desc", 1)
; Cleanup()




; 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
;-----------------------------
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

        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('Capture', '', '', -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), 'Capture ' & $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

History

v1 3-30-2011
* 1st release

v2 4-4-2011
* cleaned up the documention
* added the following functions
_WIM_DeleteImage
_WIM_DeleteImageMounts
_WIM_ExportImage
_WIM_RemountImage
_WIM_SetReferenceFile

v3 9-19-2011
* Fixed Access Violation crash in _WIM_GetImageInformation

Previous Downloads: 312

WimgapiUDF.zip

Edited by Homes32
2 people like this

Share this post


Link to post
Share on other sites



Any description on what is the purpose of this UDF (for those ho didn't heard about the WIMGAPI)?


 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Share this post


Link to post
Share on other sites

Any description on what is the purpose of this UDF (for those ho didn't heard about the WIMGAPI)?

added.

Share this post


Link to post
Share on other sites

added.

Thanks.


 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Share this post


Link to post
Share on other sites

I assume this is Vista and later as I cannot seem to find those DLLs on XP or 2k3?

correct. for xp you will still need to download the AIK from Microsoft.

Share this post


Link to post
Share on other sites

The primary purpose of Imaging APIs (Wimgapi.dll) is to programmatically capture, modify, and apply images for deployment in a manufacturing or corporate IT environment. Wimgapi.dll is now included by default in Windows 7. ImageX is an implementation of the Imaging APIs.

http://msdn.microsoft.com/en-us/library/dd851933.aspx


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

This is incredibly cool. I've been using GimageX for a while, and it works great. But this will help me to automate my imaging even more with my own custom scripts. Thank you very much for this UDF.

Share this post


Link to post
Share on other sites

This is incredibly cool. I've been using GimageX for a while, and it works great. But this will help me to automate my imaging even more with my own custom scripts. Thank you very much for this UDF.

Glad you find it useful. :) its always nice to be able to give something back to a community that has been so helpful.

UDF updated to v2. see 1st post.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

I've run into an issue with getting info from a wim image. Autoit will crash and the windows event log will always show

Exception code: 0xc0000005

which is a Access Violation error.

tracing the _WIM_GetImageInformation func it always crashes at this line

Func _WIM_GetImageInformation($hImage)

    Local $aReturn[2] ; array to hold the return data
    Local $ppvImageInfo = DllStructCreate("ptr") ; Buffer for XML Data
    Local $pcbImageInfo = DllStructCreate("int") ; Size of buffer in bytes

    Local $aResult = DllCall($ghwimgapi, "bool", "WIMGetImageInformation", _
            "handle", $hImage, _
            "ptr", DllStructGetPtr($ppvImageInfo), _
            "ptr", DllStructGetPtr($pcbImageInfo))
    If @error Then Return SetError(@error, @extended, 0)

    ; create a struct so we have access to the buffer where the XML data is stored
    Local $xml = DllStructCreate("wchar [" & DllStructGetData($pcbImageInfo, 1) & "]", DllStructGetData($ppvImageInfo, 1))
    $aReturn[0] = $aResult[0]
        $aReturn[1] = DllStructGetData($xml, 1) ; <-- ***CRASH OCCURES HERE***
    Return SetError(@error, _WinAPI_GetLastError(), $aReturn)
EndFunc   ;==>_WIM_GetImageInformation

according to the return codes the structs get created correctly and the size of $xml is always correct, yet quite regularly reading data from $xml fails miserably.

this doesn't happen every time the command is run but you can always reproduce by running the script several times in a row. the frequency seems random.

can anyone give me some insite as to what may be going wrong here?

some code to get everything up and running for anyone wanting to take a crack at this.

make sure to download the UDF from the above link.

thanks.

Homes32

Steps to Reproduce

If required change the path to the WIM file. In my tests the crashes were not specific to any particular WIM file.

Run the following code several times in a row using F5 from SCITE or compile the code and use a cmd/bat to run several times in a row.

It doesn't matter if you compile or use x68 vs x64, autoit will always have a hard crash at a seemingly random interval.

Test code:

#include <Wimgapi.au3> ; functions for WIM

Global $swimfile, $hWim, $hImage, $filepath, $rTime, $pCallBack
Global $gsWimDLL = @SystemDir & "\wimgapi.dll" ; path to wimgapi.dll

$ProgramName = "WIM Demo"

; 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

GetInfo("C:\Images\Win7_32_EN_DVD\SOURCES\BOOT.WIM") ; Change this path to your WIM file


; GetInfo
;-----------------------------
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

        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

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
Edited by Homes32

Share this post


Link to post
Share on other sites

* updated above post to hopefully provide more information for anybody willing to help figure this out. *

Share this post


Link to post
Share on other sites

Thanks a lot for this UDF.

can anyone give me some insite as to what may be going wrong here?

I second this question, could anyone help here?

Or more general question: Why could a DllStructGetData crash on a successfully created DllStruct?

Share this post


Link to post
Share on other sites

hmm, it seems works that way

Func _WIM_GetImageInformation($hImage)

    Local $aReturn[2] ; array to hold the return data
    Local $ppvImageInfo = DllStructCreate("ptr") ; Buffer for XML Data
    Local $pcbImageInfo = DllStructCreate("int") ; Size of buffer in bytes

    Local $aResult = DllCall($ghwimgapi, "bool", "WIMGetImageInformation", _
            "handle", $hImage, _
            "ptr", DllStructGetPtr($ppvImageInfo), _
            "ptr", DllStructGetPtr($pcbImageInfo))
    If @error Then Return SetError(@error, @extended, 0)

    ; create a struct so we have access to the buffer where the XML data is stored
    Local $xml = DllStructCreate("byte [" & DllStructGetData($pcbImageInfo, 1) & "]", DllStructGetData($ppvImageInfo, 1))
    $aReturn[0] = $aResult[0]
    $aReturn[1] = BinaryToString(DllStructGetData($xml, 1),2)
    Return SetError(@error, _WinAPI_GetLastError(), $aReturn)
EndFunc

The output file should be UTF 16, too.

$hFile = FileOpen($outFile, 32 + 9)

        FileWrite($hFile, @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])
        FileClose($hFile)

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I have a theory and this might be a stretch becuase I don't know much about Dll calls and this image stuff but MSDN says to free it with LocalFree. So it's worth trying:

Func _WIM_GetImageInformation($hImage)
    Local $aReturn[2] ; array to hold the return data
    Local $ppvImageInfo = DllStructCreate("ptr") ; Buffer for XML Data
    Local $pcbImageInfo = DllStructCreate("int") ; Size of buffer in bytes

    Local $aResult = DllCall($ghwimgapi, "bool", "WIMGetImageInformation", _
            "handle", $hImage, _
            "ptr", DllStructGetPtr($ppvImageInfo), _
            "ptr", DllStructGetPtr($pcbImageInfo))
    If @error Then Return SetError(@error, @extended, 0)

    ; create a struct so we have access to the buffer where the XML data is stored
    Local $xml = DllStructCreate("wchar [" & DllStructGetData($pcbImageInfo, 1) & "]", DllStructGetData($ppvImageInfo, 1))
    $aReturn[0] = $aResult[0]
    $aReturn[1] = DllStructGetData($xml, 1) ; <-- ***CRASH OCCURES HERE***
    local_free($xml)
    Return SetError(@error, _WinAPI_GetLastError(), $aReturn)
EndFunc   ;==>_WIM_GetImageInformation

Func local_free(ByRef $hMem)
    DllCall("Kernel32.dll", "handle", "LocalFree", "handle", $hMem)
EndFunc   ;==>local_free
Edited by LaCastiglione

Share this post


Link to post
Share on other sites

Homes32,

Great UDF! I'm having trouble with the callback routine to get an accurate progress percentage. When I try and run your sample script I get a variable used before declared error for $Percent. I was hoping maybe you could shed some light on it. Thanks.

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

I have a theory and this might be a stretch becuase I don't know much about Dll calls and this image stuff but MSDN says to free it with LocalFree. So it's worth trying:

Func _WIM_GetImageInformation($hImage)
    Local $aReturn[2] ; array to hold the return data
    Local $ppvImageInfo = DllStructCreate("ptr") ; Buffer for XML Data
    Local $pcbImageInfo = DllStructCreate("int") ; Size of buffer in bytes

    Local $aResult = DllCall($ghwimgapi, "bool", "WIMGetImageInformation", _
            "handle", $hImage, _
            "ptr", DllStructGetPtr($ppvImageInfo), _
            "ptr", DllStructGetPtr($pcbImageInfo))
    If @error Then Return SetError(@error, @extended, 0)

    ; create a struct so we have access to the buffer where the XML data is stored
    Local $xml = DllStructCreate("wchar [" & DllStructGetData($pcbImageInfo, 1) & "]", DllStructGetData($ppvImageInfo, 1))
    $aReturn[0] = $aResult[0]
    $aReturn[1] = DllStructGetData($xml, 1) ; <-- ***CRASH OCCURES HERE***
    local_free($xml)
    Return SetError(@error, _WinAPI_GetLastError(), $aReturn)
EndFunc   ;==>_WIM_GetImageInformation

Func local_free(ByRef $hMem)
    DllCall("Kernel32.dll", "handle", "LocalFree", "handle", $hMem)
EndFunc   ;==>local_free

Hi LaCastiglione,

thanks for replying.

I tried something like this already.

the Crash actually occurs During DllStructGetData($xml, 1)

so local_free($xml) will never be called.

Homes32,

Great UDF! I'm having trouble with the callback routine to get an accurate progress percentage. When I try and run your sample script I get a variable used before declared error for $Percent. I was hoping maybe you could shed some light on it. Thanks.

oops. my bad. just add $Percent as Global at the top.

I also updated the sample code to fix this.

thanks.

Homes32

Edited by Homes32

Share this post


Link to post
Share on other sites

Hi!

I try to catch $WIM_MSG_PROGRESS from _WIM_ApplyImage. But I can't. Can you provide example func Apply($sWimFile, $iImageIndex, $Path) with working progress bar?

Thank you!

Share this post


Link to post
Share on other sites

Hi!

I try to catch $WIM_MSG_PROGRESS from _WIM_ApplyImage. But I can't. Can you provide example func Apply($sWimFile, $iImageIndex, $Path) with working progress bar?

Thank you!

sorry. but currently the limitations of Autoit's callback implementation prevent this from working correctly. I'm sure it also doesn't help that the apply functions of wimgapi.dll are multi-threaded.

as far as I know nobody has every gotten the progress to work with /apply

Share this post


Link to post
Share on other sites

forgot to upload v3 with fixed _WIM_GetImageInformation

thanks JFX for helping figure this out! :D

Share this post


Link to post
Share on other sites

#20 ·  Posted

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

Share this post


Link to post
Share on other sites

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
Sign in to follow this  
Followers 0