Support execution of pif files - RESEND
Rein Klazes
wijn at wanadoo.nl
Sun Mar 6 02:55:17 CST 2005
Hi,
Submitted on 19 Jan. Not applied, no comments...
=================================================
Hi,
This is for an old windows installer that does:
WinExec16( "LHA.PIF e FILES.LZH");
to extract a bunch a files.
Changelog:
dlls/kernel : ne_module.c, process.c
programs/winevdm : winevdm.c
Support execution of pif files.
Rein.
-------------- next part --------------
--- wine/dlls/kernel/ne_module.c 2004-12-29 12:09:48.000000000 +0100
+++ mywine/dlls/kernel/ne_module.c 2005-01-19 09:25:03.000000000 +0100
@@ -1827,7 +1827,7 @@ HINSTANCE16 WINAPI WinExec16( LPCSTR lpC
HeapFree( GetProcessHeap(), 0, cmdline );
if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
- if (ret == 21) /* 32-bit module */
+ if (ret == 21 || ret == 11) /* 32-bit module or unknown executable*/
{
DWORD count;
ReleaseThunkLock( &count );
--- wine/dlls/kernel/process.c 2004-12-29 12:09:48.000000000 +0100
+++ mywine/dlls/kernel/process.c 2005-01-19 09:31:45.000000000 +0100
@@ -82,6 +82,7 @@ const WCHAR *DIR_System = NULL;
static const WCHAR comW[] = {'.','c','o','m',0};
static const WCHAR batW[] = {'.','b','a','t',0};
+static const WCHAR pifW[] = {'.','p','i','f',0};
static const WCHAR winevdmW[] = {'w','i','n','e','v','d','m','.','e','x','e',0};
extern void SHELL_LoadRegistry(void);
@@ -1952,7 +1953,7 @@ BOOL WINAPI CreateProcessW( LPCWSTR app_
/* check for .com or .bat extension */
if ((p = strrchrW( name, '.' )))
{
- if (!strcmpiW( p, comW ))
+ if (!strcmpiW( p, comW ) || !strcmpiW( p, pifW ))
{
TRACE( "starting %s as DOS binary\n", debugstr_w(name) );
retv = create_vdm_process( name, tidy_cmdline, envW, cur_dir, process_attr, thread_attr,
--- wine/programs/winevdm/winevdm.c 2003-09-27 04:34:07.000000000 +0200
+++ mywine/programs/winevdm/winevdm.c 2005-01-18 18:56:38.000000000 +0100
@@ -19,11 +19,13 @@
*/
#include <stdarg.h>
+#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "wine/winbase16.h"
#include "winuser.h"
+#include "wincon.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(winevdm);
@@ -31,6 +33,223 @@ WINE_DEFAULT_DEBUG_CHANNEL(winevdm);
extern void WINAPI wine_load_dos_exe( LPCSTR filename, LPCSTR cmdline );
+/*** PIF file structures ***/
+#include "pshpack1.h"
+
+/* header of a PIF file */
+typedef struct {
+ BYTE unk1[2]; /* 0x00 */
+ CHAR windowtitle[ 30 ]; /* 0x02 seems to be padded with blanks*/
+ WORD memmax; /* 0x20 */
+ WORD memmin; /* 0x22 */
+ CHAR program[63]; /* 0x24 seems to be zero terminated */
+ BYTE hdrflags1; /* 0x63 various flags:
+ * 02 286: text mode selected
+ * 10 close window at exit
+ */
+ BYTE startdrive; /* 0x64 */
+ char startdir[64]; /* 0x65 */
+ char optparams[64]; /* 0xa5 seems to be zero terminated */
+ BYTE videomode; /* 0xe5 */
+ BYTE unkn2; /* 0xe6 ?*/
+ BYTE irqlow; /* 0xe7 */
+ BYTE irqhigh; /* 0xe8 */
+ BYTE rows; /* 0xe9 */
+ BYTE cols; /* 0xea */
+ BYTE winY; /* 0xeb */
+ BYTE winX; /* 0xec */
+ WORD unkn3; /* 0xed 7??? */
+ CHAR unkn4[64]; /* 0xef */
+ CHAR unkn5[64]; /* 0x12f */
+ BYTE hdrflags2; /* 0x16f */
+ BYTE hdrflags3; /* 0x170 */
+ } pifhead_t;
+
+/* record header: present on every record */
+typedef struct {
+ CHAR recordname[16]; /* zero terminated */
+ WORD posofnextrecord; /* file offset, 0xffff if last */
+ WORD startofdata; /* file offset */
+ WORD sizeofdata; /* data is expected to follow directly */
+} recordhead_t;
+
+/* 386 -enhanced mode- record */
+typedef struct {
+ WORD memmax; /* memory desired, overrides the pif header*/
+ WORD memmin; /* memory required, overrides the pif header*/
+ WORD prifg; /* foreground priority */
+ WORD pribg; /* background priority */
+ WORD emsmax; /* EMS memory limit */
+ WORD emsmin; /* EMS memory required */
+ WORD xmsmax; /* XMS memory limit */
+ WORD xmsmin; /* XMS memory required */
+ WORD optflags; /* option flags:
+ * 0008 full screen
+ * 0004 exclusive
+ * 0002 background
+ * 0001 close when active
+ */
+ WORD memflags; /* various memory flags*/
+ WORD videoflags; /* video flags:
+ * 0010 text
+ * 0020 med. res. graphics
+ * 0040 hi. res. graphics
+ */
+ WORD hotkey[9]; /* Hot key info */
+ CHAR optparams[64]; /* optional params, replaces those in the pif header */
+} pif386rec_t;
+
+#include "poppack.h"
+
+/***********************************************************************
+ * read_pif_file
+ *pif386rec_tu
+ * Read a pif file and return the header and possibly the 286 (real mode)
+ * record or 386 (enhanced mode) record. Returns FALSE if the file is
+ * invalid otherwise TRUE.
+ */
+static BOOL read_pif_file( HANDLE hFile, char *progname, char *title,
+ char *optparams, char *startdir, int *closeonexit, int *textmode)
+{
+ DWORD nread;
+ LARGE_INTEGER filesize;
+ recordhead_t rhead;
+ BOOL found386rec = FALSE;
+ pif386rec_t pif386rec;
+ pifhead_t pifheader;
+ if( !GetFileSizeEx( hFile, &filesize) ||
+ filesize.QuadPart < (sizeof(pifhead_t) + sizeof(recordhead_t))) {
+ WINE_ERR("Invalid pif file: size error %d must be >= %d\n",
+ (int)filesize.QuadPart,
+ (sizeof(pifhead_t) + sizeof(recordhead_t)));
+ return FALSE;
+ }
+ SetFilePointer( hFile, 0, NULL, FILE_BEGIN);
+ if( !ReadFile( hFile, &pifheader, sizeof(pifhead_t), &nread, NULL))
+ return FALSE;
+ WINE_TRACE("header: program %s title %s startdir %s params %s\n",
+ wine_dbgstr_a(pifheader.program),
+ wine_dbgstr_an(pifheader.windowtitle, sizeof(pifheader.windowtitle)),
+ wine_dbgstr_a(pifheader.startdir),
+ wine_dbgstr_a(pifheader.optparams));
+ WINE_TRACE("header: memory req'd %d desr'd %d drive %d videomode %d\n",
+ pifheader.memmin, pifheader.memmax, pifheader.startdrive,
+ pifheader.videomode);
+ WINE_TRACE("header: flags 0x%x 0x%x 0x%x\n",
+ pifheader.hdrflags1, pifheader.hdrflags2, pifheader.hdrflags3);
+ ReadFile( hFile, &rhead, sizeof(recordhead_t), &nread, NULL);
+ if( strncmp( rhead.recordname, "MICROSOFT PIFEX", 15)) {
+ WINE_ERR("Invalid pif file: magic string not found\n");
+ return FALSE;
+ }
+ /* now process the following records */
+ while( 1) {
+ WORD nextrecord = rhead.posofnextrecord;
+ if( (nextrecord & 0x8000) ||
+ filesize.QuadPart <( nextrecord + sizeof(recordhead_t))) break;
+ if( !SetFilePointer( hFile, nextrecord, NULL, FILE_BEGIN) ||
+ !ReadFile( hFile, &rhead, sizeof(recordhead_t), &nread, NULL))
+ return FALSE;
+ if( !rhead.recordname[0]) continue; /* deleted record */
+ WINE_TRACE("reading record %s size %d next 0x%x\n",
+ wine_dbgstr_a(rhead.recordname), rhead.sizeofdata,
+ rhead.posofnextrecord );
+ if( !strncmp( rhead.recordname, "WINDOWS 386", 11)) {
+ found386rec = TRUE;
+ ReadFile( hFile, &pif386rec, sizeof(pif386rec_t), &nread, NULL);
+ WINE_TRACE("386rec: memory req'd %d des'd %d EMS req'd %d des'd %d XMS req'd %d des'd %d\n",
+ pif386rec.memmin, pif386rec.memmax,
+ pif386rec.emsmin, pif386rec.emsmax,
+ pif386rec.xmsmin, pif386rec.xmsmax);
+ WINE_TRACE("386rec: option 0x%x memory 0x%x video 0x%x \n",
+ pif386rec.optflags, pif386rec.memflags,
+ pif386rec.videoflags);
+ WINE_TRACE("386rec: optional parameters %s\n",
+ wine_dbgstr_a(pif386rec.optparams));
+ }
+ }
+ /* prepare the return data */
+ strncpy( progname, pifheader.program, sizeof(pifheader.program));
+ memcpy( title, pifheader.windowtitle, sizeof(pifheader.windowtitle));
+ title[ sizeof(pifheader.windowtitle) ] = '\0';
+ if( found386rec)
+ strncpy( optparams, pif386rec.optparams, sizeof( pif386rec.optparams));
+ else
+ strncpy( optparams, pifheader.optparams, sizeof(pifheader.optparams));
+ strncpy( startdir, pifheader.startdir, sizeof(pifheader.startdir));
+ *closeonexit = pifheader.hdrflags1 & 0x10;
+ *textmode = found386rec ? pif386rec.videoflags & 0x0010
+ : pifheader.hdrflags1 & 0x0002;
+ return TRUE;
+}
+
+/***********************************************************************
+ * pif_cmd
+ *
+ * execute a pif file.
+ */
+static VOID pif_cmd( char *filename, char *cmdline)
+{
+ HANDLE hFile;
+ char progpath[MAX_PATH];
+ char buf[128];
+ char progname[64];
+ char title[31];
+ char optparams[64];
+ char startdir[64];
+ char *p;
+ int closeonexit;
+ int textmode;
+ if( (hFile = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
+ {
+ WINE_ERR("open file %s failed\n", wine_dbgstr_a(filename));
+ return;
+ }
+ if( !read_pif_file( hFile, progname, title, optparams, startdir,
+ &closeonexit, &textmode)) {
+ WINE_ERR( "failed to read %s\n", wine_dbgstr_a(filename));
+ CloseHandle( hFile);
+ sprintf( buf, "%s\nInvalid file format. Check your pif file.",
+ filename);
+ MessageBoxA( NULL, buf, "16 bit DOS subsystem", MB_OK|MB_ICONWARNING);
+ SetLastError( ERROR_BAD_FORMAT);
+ return;
+ }
+ CloseHandle( hFile);
+ if( (p = strrchr( progname, '.')) && !strcasecmp( p, ".bat"))
+ WINE_FIXME(".bat programs in pif files are not supported.\n");
+ /* first change dir, so the search below can start from there */
+ if( startdir[0] && !SetCurrentDirectory( startdir)) {
+ WINE_ERR("Cannot change directory %s\n", wine_dbgstr_a( startdir));
+ sprintf( buf, "%s\nInvalid startup directory. Check your pif file.",
+ filename);
+ MessageBoxA( NULL, buf, "16 bit DOS subsystem", MB_OK|MB_ICONWARNING);
+ }
+ /* search for the program */
+ if( !SearchPathA( NULL, progname, NULL, MAX_PATH, progpath, NULL )) {
+ sprintf( buf, "%s\nInvalid program file name. Check your pif file.",
+ filename);
+ MessageBoxA( NULL, buf, "16 bit DOS subsystem", MB_OK|MB_ICONERROR);
+ SetLastError( ERROR_FILE_NOT_FOUND);
+ return;
+ }
+ if( textmode)
+ if( AllocConsole())
+ SetConsoleTitleA( title) ;
+ /* if no arguments on the commandline, use them from the pif file */
+ if( !cmdline[0] && optparams[0])
+ cmdline = optparams;
+ /* FIXME: do something with:
+ * - close on exit
+ * - graphic modes
+ * - hot key's
+ * - etc.
+ */
+ wine_load_dos_exe( progpath, cmdline );
+ return;
+}
+
/***********************************************************************
* build_command_line
*
@@ -164,6 +383,7 @@ int main( int argc, char *argv[] )
char buffer[MAX_PATH];
STARTUPINFOA info;
char *cmdline, *appname, **first_arg;
+ char *p;
if (!argv[1]) usage();
@@ -217,10 +437,15 @@ int main( int argc, char *argv[] )
if ((instance = LoadModule16( appname, ¶ms )) < 32)
{
- if (instance == 11) /* try DOS format */
+ if (instance == 11)
{
- /* loader expects arguments to be regular C strings */
- wine_load_dos_exe( appname, cmdline + 1 );
+ /* first see if it is a .pif file */
+ if( ( p = strrchr( appname, '.' )) && !strcasecmp( p, ".pif"))
+ pif_cmd( appname, cmdline + 1);
+ else
+ /* try DOS format */
+ /* loader expects arguments to be regular C strings */
+ wine_load_dos_exe( appname, cmdline + 1 );
/* if we get back here it failed */
instance = GetLastError();
}
@@ -229,7 +454,7 @@ int main( int argc, char *argv[] )
switch (instance)
{
case 2: WINE_MESSAGE("file not found\n" ); break;
- case 11: WINE_MESSAGE("invalid exe file\n" ); break;
+ case 11: WINE_MESSAGE("invalid program file\n" ); break;
default: WINE_MESSAGE("error=%d\n", instance ); break;
}
ExitProcess(instance);
More information about the wine-patches
mailing list