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