pebakery / pebakery

PEBakery is a script engine that specializes in customizing the Windows Preinstalled Environment (WinPE/WinRE).
Other
254 stars 34 forks source link

Wim Split= argument issues #42

Closed homes32 closed 6 years ago

homes32 commented 6 years ago

I'm not having any success getting this argument to work.

Fixed a small bug in CodeParser for WimApply that was causing the Split= argument always fail.

For testing I'm using the BOOT.WIM image from Win10 Pro split into 50 MB parts using the following command: wimlib-imagex split boot.wim boot.swm 50

WimApply,"D:\Temp\boot.swm",1,"D:\Temp\Target\",Split=D:\Temp\boot*.swm,CHECK,NOACL

WimExtract,D:\Temp\boot.swm,1,D:\Temp\Target,Windows\regedit.exe,Split=D:\Temp\boot*.swm,NOACL

ReferenceResourceFile() always returns GLOB_HAD_NO_MATCHES

[Error] WimApply - [GLOB_HAD_NO_MATCHES] Tried to select an image that does not exist in the WIM (WimApply,"D:\Temp\boot.swm",1,"D:\Temp\Target\",Split=D:\Temp\boot*.swm,CHECK,NOACL) (Line 5)

I am able to Apply and Extract successfully using wimlib-imagex

wimlib-imagex extract boot.swm 1 Windows\regedit.exe --dest-dir=D:\Temp\target --no-attributes --ref=boot*.swm"

wimlib-imagex apply boot.swm 1 Target --no-attributes --ref=boot*.swm

ied206 commented 6 years ago

Problem fixed, it was caused by faulty marshalling native functions. Letting .Net to use UTF16 in string marshalling solved this issue.

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
internal delegate WimLibErrorCode wimlib_reference_resource_files(
    IntPtr wim,
    // Surprisingly, using this explicit MarshalAs throws SEHException.
    // [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
    string[] resource_wimfiles_or_globs,
    uint count,
    WimLibReferenceFlags ref_flags,
    WimLibOpenFlags open_flags);
internal static wimlib_reference_resource_files ReferenceResourceFiles;
homes32 commented 6 years ago

I'm still getting exceptions (Win10 Pro x64)

- [1] Error in Script [Test] (Win7PESE\CodeBox.txt)
[Error] WimExtract - System.Runtime.InteropServices.SEHException: External component has thrown an exception.
   at ManagedWimLib.Wim.ReferenceResourceFile(String resourceWimFile, WimLibReferenceFlags refFlags, WimLibOpenFlags openFlags) in D:\CODE\pebakery\ManagedWimLib\WimStruct.cs:line 840
   at PEBakery.Core.Commands.CommandWim.WimExtract(EngineState s, CodeCommand cmd) in D:\CODE\pebakery\PEBakery\Core\Commands\CommandWim.cs:line 588
   at PEBakery.Core.Engine.ExecuteCommand(EngineState s, CodeCommand cmd) in D:\CODE\pebakery\PEBakery\Core\Engine.cs:line 642
  (WimExtract,D:\Temp\boot.swm,1,D:\Temp\Target3,Windows\regedit.exe,Split=D:\Temp\boot*.swm,NOACL) (Line 7)

any thoughts?

ied206 commented 6 years ago

SEHException happens if something related to pinvoke goes wrong.

In my system I had to face SEHException if I set function signature like this:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate WimLibErrorCode wimlib_reference_resource_files(
    IntPtr wim,
    [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
    string[] resource_wimfiles_or_globs,
    uint count,
    WimLibReferenceFlags ref_flags,
    WimLibOpenFlags open_flags);
internal static wimlib_reference_resource_files ReferenceResourceFiles;

Alongside with the problem wimlib_iterate_dir_tree() not working in 32bit binary, I am thinking about asking professionals over Stack Overflow.

ied206 commented 6 years ago

Can you try a version of commit cb6ffac?

homes32 commented 6 years ago

no change.

- [1] Error in Script [Test] (Win7PESE\CodeBox.txt)
[Error] WimApply - System.Runtime.InteropServices.SEHException: External component has thrown an exception.
   at ManagedWimLib.Wim.ReferenceResourceFile(String resourceWimFile, WimLibReferenceFlags refFlags, WimLibOpenFlags openFlags) in D:\CODE\pebakery\ManagedWimLib\WimStruct.cs:line 840
   at PEBakery.Core.Commands.CommandWim.WimApply(EngineState s, CodeCommand cmd) in D:\CODE\pebakery\PEBakery\Core\Commands\CommandWim.cs:line 448
   at PEBakery.Core.Engine.ExecuteCommand(EngineState s, CodeCommand cmd) in D:\CODE\pebakery\PEBakery\Core\Engine.cs:line 639
  (WimApply,"D:\Temp\boot.swm",1,"D:\Temp\Target3\",Split=D:\Temp\boot*.swm,CHECK,NOACL) (Line 5)
ied206 commented 6 years ago

My system is also Windows 10 x64 v1709, so there should be no difference in theory. I guess we will have to disable support for split wim temporary in beta 3.

homes32 commented 6 years ago

Mine is 10 x64 v1607, so perhaps that's the difference. I'll try my wife's laptop and my win7 Pro machine and see if there are any issues with either of them.

ied206 commented 6 years ago

I tried another attempt, marshaling strings myself with Marshal.StringToHGlobalUni(). I faced similar issue when pivoking Wim.GetWimInfo(), and that was solved by same method.

ied206 commented 6 years ago

I got a clue about this. In C, functions expect the memory address of funtion parameter not being moved. In contrast, in C# address of object can always be moved by GC. So without pinning down the address of string[] resource_wimfiles_or_globs, ExtractPaths are prone to crash if GC is invoked while wimlib_extract_paths are called.

I had experienced this issue while writing a wrapper of zlib (Joveler.ZLibWrapper) but I did completely forget it. I will roll the fix soon as possible.

ied206 commented 6 years ago

After more investigation, wimlib_reference_resource_files() crashes only if wildcard (called glob by wimlib) is used. One workaround is convert wildcard to list of files before passing them into wimlib.

ied206 commented 6 years ago

Hack is applied, and in unit test it works well. Please test in real use cases, especially with debugger attached (As in prior version SEHException was only raised in debug mode, at least in my system).

homes32 commented 6 years ago

That seems to have taken care of the issue. No problems running the debugger and Extracting or Applying split wims now :)