Robert Baruch
2001-Dec-06 14:52 UTC
Problem report: SHRINKER.ERR, fix to DEVICE_Open/CreateFileA?
This was an error I got when running a self-installing executable, power-structure-demo.exe, available from www.write-brain.com (a demo for Power Structure). A error box appears with title SHRINKER.ERR and message: (path)\power-structure-demo.exe (3.4) (time&date) - Pager initialisation error 2 - File not found and then the program quits. Running with --debugmsg +all,+relay,+text,+string shows the following trace (only the part I think is significant): ----BEGIN TRACE---- 0806d388:Call kernel32.CreateFileA(40612b20 "\\\\.\\SHRINK34.LDR",00000000,00000000,00000000,00000003,04000000,00000000) ret=00761731 0806d388:trace:file:CreateFileA \\.\SHRINK34.LDR QUERY_ACCESS OPEN_EXISTING 0806d388:fixme:win32:DEVICE_Open Unknown/unsupported VxD SHRINK34.LDR. Try --winver nt40 or win31 ! 0806d388:Ret kernel32.CreateFileA() retval=ffffffff ret=00761731 0806d388:Call kernel32.GetWindowsDirectoryA(40616d3c,00000104) ret=0076180d 0806d388:trace:string:lstrcpynA (0x40616d3c, "C:\\WINDOWS", 260) 0806d388:Ret kernel32.GetWindowsDirectoryA() retval=0000000a ret=0076180d 0806d388:Call kernel32.GetTempFileNameA(40612b1c "C:\\WINDOWS\\",0075c538 "000",00000000,40616d3c) ret=007617b2 0806d388:trace:file:CreateFileA C:\WINDOWS\000cf6e.tmp GENERIC_WRITE CREATE_NEW 0806d388:trace:dosfs:DOSFS_GetFullName C:\WINDOWS\000cf6e.tmp (last=0) 0806d388:trace:string:lstrcpynA (0x406119ec, "/mnt/dos", 1024) 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos,WINDOWS\000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos,WINDOWS\000cf6e.tmp) -> windows (WINDOWS) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos/windows,000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:warn:dosfs:DOSFS_FindUnixName '000cf6e.tmp' not found in '/mnt/dos/windows' 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_GetFullName returning /mnt/dos/windows/000cf6e.tmp C:\WINDOWS\000cf6e.tmp 0806d388:trace:dosfs:GetDriveTypeA ("C:\\WINDOWS\\000cf6e.tmp") 0806d388: create_file( access=40000000, inherit=0, sharing=00000000, create=1, attrs=00000080, drive_type=3, filename="/mnt/dos/windows/000cf6e.tmp" ) 0806d388: create_file() = 0 { handle=52 } 0806d388:trace:file:FILE_GetTempFileName created C:\WINDOWS\000cf6e.tmp 0806d388: close_handle( handle=52 ) 0806d388: close_handle() = 0 { fd=-1 } 0806d388:trace:dosfs:DOSFS_GetFullName C:\WINDOWS\000cf6e.tmp (last=0) 0806d388:trace:string:lstrcpynA (0x40612234, "/mnt/dos", 1024) 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos,WINDOWS\000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos,WINDOWS\000cf6e.tmp) -> windows (WINDOWS) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos/windows,000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos/windows,000cf6e.tmp) -> 000cf6e.tmp (000CF6E.TMP) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_GetFullName returning /mnt/dos/windows/000cf6e.tmp C:\WINDOWS\000CF6E.TMP 0806d388:trace:file:FILE_GetTempFileName returning C:\WINDOWS\000cf6e.tmp 0806d388:Ret kernel32.GetTempFileNameA() retval=0000cf6e ret=007617b2 0806d388:Call kernel32.CreateFileA(40616d3c "C:\\WINDOWS\\000cf6e.tmp",40000000,00000000,00000000,00000002,00000080,00000000) ret=00761013 0806d388:trace:file:CreateFileA C:\WINDOWS\000cf6e.tmp GENERIC_WRITE CREATE_ALWAYS 0806d388:trace:dosfs:DOSFS_GetFullName C:\WINDOWS\000cf6e.tmp (last=0) 0806d388:trace:string:lstrcpynA (0x40612210, "/mnt/dos", 1024) 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos,WINDOWS\000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos,WINDOWS\000cf6e.tmp) -> windows (WINDOWS) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos/windows,000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos/windows,000cf6e.tmp) -> 000cf6e.tmp (000CF6E.TMP) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_GetFullName returning /mnt/dos/windows/000cf6e.tmp C:\WINDOWS\000CF6E.TMP 0806d388:trace:dosfs:GetDriveTypeA ("C:\\WINDOWS\\000CF6E.TMP") 0806d388: create_file( access=40000000, inherit=0, sharing=00000000, create=2, attrs=00000080, drive_type=3, filename="/mnt/dos/windows/000cf6e.tmp" ) 0806d388: create_file() = 0 { handle=52 } 0806d388:Ret kernel32.CreateFileA() retval=00000034 ret=00761013 0806d388:Call kernel32.WriteFile(00000034,40612c38,00003288,40612c04,00000000) ret=00761063 0806d388:trace:file:WriteFile 52 0x40612c38 12936 0x40612c04 (nil) 0806d388: get_handle_fd( handle=52, access=40000000 ) 0806d388: *fd* 52 -> 16 0806d388: get_handle_fd() = 0 { fd=-1, type=1 } 0806d388: set_handle_info( handle=52, flags=0, mask=0, fd=10 ) 0806d388: set_handle_info() = 0 { old_flags=0, cur_fd=10 } 0806d388:Ret kernel32.WriteFile() retval=00000001 ret=00761063 0806d388:Call kernel32.CloseHandle(00000034) ret=00760f0d 0806d388: close_handle( handle=52 ) 0806d388: close_handle() = 0 { fd=10 } 0806d388:Ret kernel32.CloseHandle() retval=00000001 ret=00760f0d 0806d388:Call kernel32.CreateFileA(40612b20 "\\\\.\\C:\\WINDOWS\\000cf6e.tmp",00000000,00000000,00000000,00000003,04000000,00000000) ret=00761731 0806d388:trace:file:CreateFileA \\.\C:\WINDOWS\000cf6e.tmp QUERY_ACCESS OPEN_EXISTING 0806d388:fixme:win32:DEVICE_Open Unknown/unsupported VxD C:\WINDOWS\000cf6e.tmp. Try --winver nt40 or win31 ! 0806d388:Ret kernel32.CreateFileA() retval=ffffffff ret=00761731 0806d388:Call kernel32.DeleteFileA(40616d3c "C:\\WINDOWS\\000cf6e.tmp") ret=00761911 0806d388:trace:file:DeleteFileA 'C:\WINDOWS\000cf6e.tmp' 0806d388:trace:dosfs:DOSFS_GetFullName C:\WINDOWS\000cf6e.tmp (last=1) 0806d388:trace:string:lstrcpynA (0x40612384, "/mnt/dos", 1024) 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos,WINDOWS\000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos,WINDOWS\000cf6e.tmp) -> windows (WINDOWS) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_FindUnixName /mnt/dos/windows,000cf6e.tmp 0806d388:trace:heap:HeapAlloc (403b0000,00000002,0000022c): returning 4042ef68 0806d388:trace:dosfs:DOSFS_FindUnixName (/mnt/dos/windows,000cf6e.tmp) -> 000cf6e.tmp (000CF6E.TMP) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:dosfs:DOSFS_GetFullName returning /mnt/dos/windows/000cf6e.tmp C:\WINDOWS\000CF6E.TMP 0806d388:Ret kernel32.DeleteFileA() retval=00000001 ret=00761911 0806d388:Call kernel32.GetLastError() ret=00760303 0806d388:Ret kernel32.GetLastError() retval=00000002 ret=00760303 0806d388:Call kernel32.GetLocalTime(40612bf8) ret=00761d66 0806d388:Ret kernel32.GetLocalTime() retval=00000000 ret=00761d66 0806d388:Call kernel32.GetLocalTime(40612bf8) ret=00761cd4 0806d388:Ret kernel32.GetLocalTime() retval=00000000 ret=00761cd4 0806d388:Call kernel32.FormatMessageA(00001000,00000000,00000002,00000400,0075d54b,000000c8,00000000) ret=00760493 0806d388:trace:resource:FormatMessageA (0x1000,(nil),2,0x400,0x75d54b,200,(nil))0806d388:trace:resource:load_messageA instance = 40667000, id = 00000002, buffer = (nil), length = 100 0806d388:trace:resource:RES_FindResource2 (40667000, 0000000b, 00000001, 0400, W, PE) 0806d388:trace:resource:RES_LoadResource (40667000, 406ac8c0, PE) 0806d388:trace:resource:LockResource (406974e0) 0806d388:trace:resource:load_messageA - strlen=20 0806d388:trace:heap:HeapAlloc (403b0000,00000002,00000018): returning 4042ef68 0806d388:trace:resource:load_messageA instance = 40667000, id = 00000002, buffer = 0x4042ef68, length = 21 0806d388:trace:resource:RES_FindResource2 (40667000, 0000000b, 00000001, 0400, W, PE) 0806d388:trace:resource:RES_LoadResource (40667000, 406ac8c0, PE) 0806d388:trace:resource:LockResource (406974e0) 0806d388:trace:resource:load_messageA - strlen=20 0806d388:trace:string:lstrcpynA (0x4042ef68, "File not found\n", 20) 0806d388:trace:resource:load_messageA 'File not found ' copied ! 0806d388:trace:heap:HeapAlloc (403b0000,0000000a,00000064): returning 4042ef8c 0806d388:trace:heap:HeapReAlloc (403b0000,0000000a,4042ef8c,000000c8): returning 4042ef8c 0806d388:trace:resource:FormatMessageA -- "File not found\r\n" 0806d388:trace:string:lstrcpynA (0x75d54b, "File not found\r\n", 200) 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef8c): returning TRUE 0806d388:trace:heap:HeapFree (403b0000,00000002,4042ef68): returning TRUE 0806d388:trace:resource:FormatMessageA -- returning 16 0806d388:Ret kernel32.FormatMessageA() retval=00000010 ret=00760493 0806d388:Call kernel32.GetModuleHandleA(40612bf4 "USER32") ret=0075fbdf 0806d388:Ret kernel32.GetModuleHandleA() retval=406e2000 ret=0075fbdf 0806d388:Call kernel32.GetProcAddress(406e2000,0075b05c "MessageBoxA") ret=0075fbfd 0806d388:trace:win32:MODULE_GetProcAddress (406e2000,MessageBoxA) 0806d388:trace:win32:PE_FindExportedFunction (MessageBoxA) 0806d388:Ret kernel32.GetProcAddress() retval=4077f8e0 ret=0075fbfd 0806d388:Call user32.MessageBoxA(00000000,0075d4e0 "C:\\My Documents\\installs\\power-structure-demo.exe (3.4) 12/06/01 15:05:02 - Page"...,0075b3e8 "SHRINKER.ERR",00002030) ret=0075fc1a 0806d388:warn:dialog:MessageBoxA Messagebox ----END TRACE---- The program apparently tries to open a file called \\.\SHRINK34.LDR, which fails because SHRINK34.LDR doesn't exist. The next thing the program does is create a temporary file (C:\WINDOWS\000cf6e.tmp here), write 0x3288 bytes of stuff to it (successfully), close it, and then try to re-open it with \\.\ prepended to the filename. That fails, resulting in the message box. CreateFileA (files/file.c) will handle filenames prepended with \\.\ specially. If the file begins with \\.\pipe\ then we open a pipe. If the filename is a DOS device, we open that. Otherwise we fall through to DEVICE_Open (win32/device.c) which checks to see if the file is a known VxD. In this trace, it fails. I've been looking through the Microsoft documentation. In the documentation for opening VxD's ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win32/devio_886c.asp) it says: "CreateFile checks for a filename extension to determine whether VxDName specifies a file. If a filename extension (such as .VXD) is present, the function looks for the file in the standard search path. In the following example, CreateFile looks for the SAMPLE.VXD file in the standard search path." (example: \\.\SAMPLE.VXD) In addition, under the documentation for CreateFile (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/filesio_7wmd.asp) it says: "There is no trailing backslash in a drive name. The string "\\.\c:\" refers to the root directory of drive C." So could it be that in DEVICE_Open or CreateFileA, opening a file prepended with \\.\ that starts with a drive letter and has a filename extension should just open the file? --Rob
Robert Baruch
2001-Dec-06 16:04 UTC
Problem report: SHRINKER.ERR, fix to DEVICE_Open/CreateFileA?
Well, I made the modification to the source code. This time the program got past opening the file after it was written to. The program then deleted the file, and then tried to do a DeviceIoControl on it: 0806b0a8:Ret kernel32.CreateFileA() retval=00000038 ret=00761731 0806b0a8:Call kernel32.DeleteFileA(40606d3c "C:\\WINDOWS\\000e914.tmp") ret=00761911 0806b0a8:trace:file:DeleteFileA 'C:\WINDOWS\000e914.tmp' 0806b0a8:trace:dosfs:DOSFS_GetFullName C:\WINDOWS\000e914.tmp (last=1) 0806b0a8:trace:string:lstrcpynA (0x40602380, "/mnt/dos", 1024) 0806b0a8:trace:dosfs:DOSFS_FindUnixName /mnt/dos,WINDOWS\000e914.tmp 0806b0a8:trace:heap:HeapAlloc (403a0000,00000002,0000022c): returning 4041ef38 0806b0a8:trace:dosfs:DOSFS_FindUnixName (/mnt/dos,WINDOWS\000e914.tmp) -> windows (WINDOWS) 0806b0a8:trace:heap:HeapFree (403a0000,00000002,4041ef38): returning TRUE 0806b0a8:trace:dosfs:DOSFS_FindUnixName /mnt/dos/windows,000e914.tmp 0806b0a8:trace:heap:HeapAlloc (403a0000,00000002,0000022c): returning 4041ef38 0806b0a8:trace:dosfs:DOSFS_FindUnixName (/mnt/dos/windows,000e914.tmp) -> 000e914.tmp (000E914.TMP) 0806b0a8:trace:heap:HeapFree (403a0000,00000002,4041ef38): returning TRUE 0806b0a8:trace:dosfs:DOSFS_GetFullName returning /mnt/dos/windows/000e914.tmp C:\WINDOWS\000E914.TMP 0806b0a8:Ret kernel32.DeleteFileA() retval=00000001 ret=00761911 0806b0a8:Call kernel32.DeviceIoControl(00000038,00000001,00000000,00000000,40606e40,00000010,40606e50,00000000) ret=00761943 0806b0a8:trace:win32:DeviceIoControl (56,1,(nil),0,0x40606e40,16,0x40606e50,(nil)) 0806b0a8: get_file_info( handle=56 ) 0806b0a8: get_file_info() = 0 { type=1, attr=32, access_time=1007675668, write_time=1007675668, size_high=0, size_low=12936, links=0, index_high=769, index_low=902562, serial=00000000 } 0806b0a8:Ret kernel32.DeviceIoControl() retval=00000000 ret=00761943 0806b0a8:Call kernel32.GetLastError() ret=00760303 0806b0a8:Ret kernel32.GetLastError() retval=00000057 ret=00760303 This last error means "Invalid Parameter". So I take back my thought that \\.\filename.ext should just open the file as a regular file. I think it should be opening the file as a VxD, installing it if it isn't already installed. How that's supposed to work is beyond me, but I'll see if I can learn about how it should be done. --Rob
Robert Baruch
2001-Dec-07 10:57 UTC
Problem report: SHRINKER.ERR, fix to DEVICE_Open/CreateFileA?
Hi Uwe, Thanks for the reply. I read your thread on VXD's from January 2001 and now I understand that Wine can't support just any VXD. Is "SHRINKER" some kind of decompressor? A long long time ago in a galaxy far far away I wrote a utility which would decompress an MSDOS self-decompressing-exe file that had been compressed by some utility I never got the name of. Would there be any interest in some kind of patch to Wine which would let this particular VXD's job be done within Wine? Something that would detect the shrinker VXD and immediately act to emulate it -- say, DEVICE_Open would look into the VXD to see if it's name was SHRINK34? I used winedbg to break the program just before it deletes the VXD, and then used IDA to look inside the VXD. It has no API's, and a single ioctl routine, which has five possible calls. Is there any interest in pursuing this further? --Rob