Index: sdk/lib/pifio/CMakeLists.txt =================================================================== --- sdk/lib/pifio/CMakeLists.txt (nonexistent) +++ sdk/lib/pifio/CMakeLists.txt (working copy) @@ -0,0 +1,2 @@ +add_library(pifio pifio.c) +add_dependencies(pifio psdk) \ No newline at end of file Index: sdk/lib/pifio/pifio.c =================================================================== --- sdk/lib/pifio/pifio.c (nonexistent) +++ sdk/lib/pifio/pifio.c (working copy) @@ -0,0 +1,260 @@ +/* + * COPYRIGHT: See COPYING.LIB in the top level directory + * PROJECT: PIF I/O Library + * FILE: lib/pifio/pifio.c + * PURPOSE: Gives the ability to Save/Load DOS Shortcut Files + * PROGRAMMERS: Alexandre Julliard + * Lee Schroeder + */ +#include "pifio.h" + +#define NDEBUG +#include + +HRESULT ReadPifFile_NEW(HANDLE hFile, LPPIFSTRUCT lpPifStruct) +{ + DWORD nread; + LARGE_INTEGER filesize; + PIFRECORDHEAD rhead; + PIF386REC pif386rec; + PIFHEAD pifheader; + BOOL found386rec = FALSE; + + /* Make sure there's a file to actually work with */ + if (hFile == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + return E_HANDLE; + } + + /* Make sure the file is of the proper size before using it */ + if (!GetFileSizeEx(hFile, &filesize) || + filesize.QuadPart < (sizeof(PIFHEAD) + sizeof(PIFRECORDHEAD))) + { + DPRINT1("Invalid PIF file size error %d.", (int)filesize.QuadPart); + return E_FAIL; + } + + /* Set the file pointer to the beginning of the file so it + can be read properly */ + if (!SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) + return E_FAIL; + + if (!ReadFile(hFile, &pifheader, sizeof(PIFHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + DPRINT1("header: program %s title %s startdir %s params %s\n", + pifheader.program, pifheader.windowtitle, pifheader.startdir, + pifheader.optparams); + DPRINT1("header: memory req'd %d desr'd %d drive %d videomode %d\n", + pifheader.memmin, pifheader.memmax, pifheader.startdrive, + pifheader.videomode); + DPRINT1("header: flags 0x%x 0x%x 0x%x\n", pifheader.hdrflags1, + pifheader.hdrflags2, pifheader.hdrflags3); + + /* Opens the file for reading from */ + if (!ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + /* Ensure that this is actually a PIF file */ + if (strncmp(rhead.recordname, "MICROSOFT PIFEX", 15)) + { + DPRINT1("Invalid PIF file: magic string not found. Used instead: %S\n", rhead.recordname); + return E_FAIL; + } + + /* now process the following records */ + while(1) + { + WORD nextrecord = rhead.posofnextrecord; + + if ((nextrecord & 0x8000) || + filesize.QuadPart < (nextrecord + sizeof(PIFRECORDHEAD))) + break; + + if (!SetFilePointer(hFile, nextrecord, NULL, FILE_BEGIN) || + !ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to set the file pointer."); + return E_POINTER; + } + + /* deleted record */ + if (!rhead.recordname[0]) + continue; + + DPRINT1("reading record %s size %d next 0x%x\n", rhead.recordname, + rhead.sizeofdata, rhead.posofnextrecord ); + + if (!strncmp(rhead.recordname, "WINDOWS 386", 11)) + { + found386rec = TRUE; + + if (!ReadFile( hFile, &pif386rec, sizeof(PIF386REC), &nread, NULL)) + return E_FAIL; + + DPRINT1("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); + DPRINT1("386rec: option 0x%x memory 0x%x video 0x%x\n", pif386rec.optflags, + pif386rec.memflags, pif386rec.videoflags); + DPRINT1("386rec: optional parameters %s\n", pif386rec.optparams); + } + } + + /* prepare the return data */ + StringCchCopyA(lpPifStruct->ProgramName, sizeof(pifheader.program)+1, pifheader.program); + StringCchCopyA(lpPifStruct->Caption, sizeof(pifheader.windowtitle)+1, pifheader.windowtitle); + + //lpPifStruct->PifHeader = rhead; + + if (found386rec) + { + lpPifStruct->Pif386Record = &pif386rec; + StringCchCopyA(lpPifStruct->OptParams, sizeof(pif386rec.optparams)+1, pif386rec.optparams); + } + + else + StringCchCopyA(lpPifStruct->OptParams, sizeof(pifheader.optparams)+1, pifheader.optparams); + + StringCchCopyA(lpPifStruct->StartDir, sizeof(pifheader.startdir)+1, pifheader.startdir); + *lpPifStruct->CloseOnExit = pifheader.hdrflags1 & 0x10; + *lpPifStruct->TextMode = found386rec ? pif386rec.videoflags & 0x0010 + : pifheader.hdrflags1 & 0x0002; + + return S_OK; +} + +/* Code taken from winevdm */ +HRESULT ReadPifFile(HANDLE hFile, + LPSTR progname, + LPSTR title, + LPSTR optparams, + LPSTR startdir, + PINT closeonexit, + PINT textmode) +{ + DWORD nread; + LARGE_INTEGER filesize; + PIFRECORDHEAD rhead; + PIF386REC pif386rec; + PIFHEAD pifheader; + BOOL found386rec = FALSE; + + /* Make sure there's a file to actually work with */ + if (hFile == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + return E_HANDLE; + } + + /* Make sure the file is of the proper size before using it */ + if (!GetFileSizeEx(hFile, &filesize) || + filesize.QuadPart < (sizeof(PIFHEAD) + sizeof(PIFRECORDHEAD))) + { + DPRINT1("Invalid PIF file size error %d.", (int)filesize.QuadPart); + return E_FAIL; + } + + /* Set the file pointer to the beginning of the file so it + can be read properly */ + if (!SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) + return E_FAIL; + + if (!ReadFile(hFile, &pifheader, sizeof(PIFHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + DPRINT1("header: program %s title %s startdir %s params %s\n", + pifheader.program, pifheader.windowtitle, pifheader.startdir, + pifheader.optparams); + DPRINT1("header: memory req'd %d desr'd %d drive %d videomode %d\n", + pifheader.memmin, pifheader.memmax, pifheader.startdrive, + pifheader.videomode); + DPRINT1("header: flags 0x%x 0x%x 0x%x\n", pifheader.hdrflags1, + pifheader.hdrflags2, pifheader.hdrflags3); + + /* Opens the file for reading from */ + if (!ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + /* Ensure that this is actually a PIF file */ + if (strncmp(rhead.recordname, "MICROSOFT PIFEX", 15)) + { + DPRINT1("Invalid PIF file: magic string not found. Used instead: %S\n", rhead.recordname); + return E_FAIL; + } + + /* now process the following records */ + while(1) + { + WORD nextrecord = rhead.posofnextrecord; + + if ((nextrecord & 0x8000) || + filesize.QuadPart < (nextrecord + sizeof(PIFRECORDHEAD))) + break; + + if (!SetFilePointer(hFile, nextrecord, NULL, FILE_BEGIN) || + !ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to set the file pointer."); + return E_POINTER; + } + + /* deleted record */ + if (!rhead.recordname[0]) + continue; + + DPRINT1("reading record %s size %d next 0x%x\n", rhead.recordname, + rhead.sizeofdata, rhead.posofnextrecord ); + + if (!strncmp(rhead.recordname, "WINDOWS 386", 11)) + { + found386rec = TRUE; + + if (!ReadFile( hFile, &pif386rec, sizeof(PIF386REC), &nread, NULL)) + return E_FAIL; + + DPRINT1("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); + DPRINT1("386rec: option 0x%x memory 0x%x video 0x%x\n", pif386rec.optflags, + pif386rec.memflags, pif386rec.videoflags); + DPRINT1("386rec: optional parameters %s\n", pif386rec.optparams); + } + } + + /* prepare the return data */ + StringCchCopyA(progname, sizeof(pifheader.program)+1, pifheader.program); + StringCchCopyA(title, sizeof(pifheader.windowtitle)+1, pifheader.windowtitle); + + if(found386rec) + StringCchCopyA(optparams, sizeof(pif386rec.optparams)+1, pif386rec.optparams); + else + StringCchCopyA(optparams, sizeof(pifheader.optparams)+1, pifheader.optparams); + + StringCchCopyA(startdir, sizeof(pifheader.startdir)+1, pifheader.startdir); + *closeonexit = pifheader.hdrflags1 & 0x10; + *textmode = found386rec ? pif386rec.videoflags & 0x0010 + : pifheader.hdrflags1 & 0x0002; + +#if 0 + lpPifStruct.PifHeader = rhead; + + if (found386rec) + lpPifStruct.Pif386Record = pif386rec; +#endif + + return S_OK; +} Index: sdk/lib/pifio/pifio.h =================================================================== --- sdk/lib/pifio/pifio.h (nonexistent) +++ sdk/lib/pifio/pifio.h (working copy) @@ -0,0 +1,106 @@ +/* + * COPYRIGHT: See COPYING.LIB in the top level directory + * PROJECT: PIF I/O Library + * FILE: lib/pifio/pifio.h + * PURPOSE: Gives the ability to Save/Load DOS Shortcut Files + * PROGRAMMERS: Alexandre Julliard + * Lee Schroeder + */ +#ifndef PIFLIB_H +#define PIFLIB_H + +#include +#include +#include + +#include + +/* NOTES: + * - Code taken from WINE's winevdm. + * - http://www.smsoft.ru/en/pifdoc.htm + * - http://www.drdobbs.com/architecture-and-design/undocumented-corner/184409042 + */ +typedef struct { + BYTE checksum[2]; /* 0x00 never checked */ + 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: + * 01 directly modify memory + * 02 286: text mode selected + * 04 prevent program switch + * 08 no screen exchange + * 10 close window at exit + * 40 Direct interaction with COM1 + * 80 Direct interaction with COM2 + */ + BYTE startdrive; /* 0x64 */ + char startdir[64]; /* 0x65 */ + char optparams[64]; /* 0xa5 seems to be zero terminated */ + BYTE videomode; /* 0xe5 not used */ + BYTE videopagequantity; /* 0xe6 not used */ + BYTE irqlow; /* 0xe7 not used */ + BYTE irqhigh; /* 0xe8 not used */ + BYTE rows; /* 0xe9 not used */ + BYTE cols; /* 0xea not used */ + BYTE winY; /* 0xeb not used */ + BYTE winX; /* 0xec not used */ + WORD lastvideopage; /* 0xed */ + CHAR unkn1[64]; /* 0xef not used */ + CHAR unkn2[64]; /* 0x12f not used */ + BYTE hdrflags2; /* 0x16f */ + BYTE hdrflags3; /* 0x170 */ +} PIFHEAD, *LPPIFHEAD; + +/* 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 */ +} PIFRECORDHEAD, *LPPIFRECORDHEAD; + +/* 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, *LPPIF386REC; + +typedef struct { + LPSTR ProgramName; + LPSTR Caption; + LPSTR OptParams; + LPSTR StartDir; + PINT CloseOnExit; + PINT TextMode; + LPPIFHEAD PifHeader; + LPPIF386REC Pif386Record; +} *LPPIFSTRUCT; + +#include + +HRESULT ReadPifFile(HANDLE hFile, LPSTR progname, LPSTR title, LPSTR optparams, LPSTR startdir, PINT closeonexit, PINT textmode); +HRESULT ReadPifFile_NEW(HANDLE hFile, LPPIFSTRUCT lpPifStruct); + +#endif /* PIFLIB_H */ \ No newline at end of file Index: sdk/lib/pifio/CMakeLists.txt =================================================================== --- sdk/lib/pifio/CMakeLists.txt (nonexistent) +++ sdk/lib/pifio/CMakeLists.txt (working copy) @@ -0,0 +1,2 @@ +add_library(pifio pifio.c) +add_dependencies(pifio psdk) \ No newline at end of file Index: sdk/lib/pifio/pifio.c =================================================================== --- sdk/lib/pifio/pifio.c (nonexistent) +++ sdk/lib/pifio/pifio.c (working copy) @@ -0,0 +1,260 @@ +/* + * COPYRIGHT: See COPYING.LIB in the top level directory + * PROJECT: PIF I/O Library + * FILE: lib/pifio/pifio.c + * PURPOSE: Gives the ability to Save/Load DOS Shortcut Files + * PROGRAMMERS: Alexandre Julliard + * Lee Schroeder + */ +#include "pifio.h" + +#define NDEBUG +#include + +HRESULT ReadPifFile_NEW(HANDLE hFile, LPPIFSTRUCT lpPifStruct) +{ + DWORD nread; + LARGE_INTEGER filesize; + PIFRECORDHEAD rhead; + PIF386REC pif386rec; + PIFHEAD pifheader; + BOOL found386rec = FALSE; + + /* Make sure there's a file to actually work with */ + if (hFile == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + return E_HANDLE; + } + + /* Make sure the file is of the proper size before using it */ + if (!GetFileSizeEx(hFile, &filesize) || + filesize.QuadPart < (sizeof(PIFHEAD) + sizeof(PIFRECORDHEAD))) + { + DPRINT1("Invalid PIF file size error %d.", (int)filesize.QuadPart); + return E_FAIL; + } + + /* Set the file pointer to the beginning of the file so it + can be read properly */ + if (!SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) + return E_FAIL; + + if (!ReadFile(hFile, &pifheader, sizeof(PIFHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + DPRINT1("header: program %s title %s startdir %s params %s\n", + pifheader.program, pifheader.windowtitle, pifheader.startdir, + pifheader.optparams); + DPRINT1("header: memory req'd %d desr'd %d drive %d videomode %d\n", + pifheader.memmin, pifheader.memmax, pifheader.startdrive, + pifheader.videomode); + DPRINT1("header: flags 0x%x 0x%x 0x%x\n", pifheader.hdrflags1, + pifheader.hdrflags2, pifheader.hdrflags3); + + /* Opens the file for reading from */ + if (!ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + /* Ensure that this is actually a PIF file */ + if (strncmp(rhead.recordname, "MICROSOFT PIFEX", 15)) + { + DPRINT1("Invalid PIF file: magic string not found. Used instead: %S\n", rhead.recordname); + return E_FAIL; + } + + /* now process the following records */ + while(1) + { + WORD nextrecord = rhead.posofnextrecord; + + if ((nextrecord & 0x8000) || + filesize.QuadPart < (nextrecord + sizeof(PIFRECORDHEAD))) + break; + + if (!SetFilePointer(hFile, nextrecord, NULL, FILE_BEGIN) || + !ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to set the file pointer."); + return E_POINTER; + } + + /* deleted record */ + if (!rhead.recordname[0]) + continue; + + DPRINT1("reading record %s size %d next 0x%x\n", rhead.recordname, + rhead.sizeofdata, rhead.posofnextrecord ); + + if (!strncmp(rhead.recordname, "WINDOWS 386", 11)) + { + found386rec = TRUE; + + if (!ReadFile( hFile, &pif386rec, sizeof(PIF386REC), &nread, NULL)) + return E_FAIL; + + DPRINT1("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); + DPRINT1("386rec: option 0x%x memory 0x%x video 0x%x\n", pif386rec.optflags, + pif386rec.memflags, pif386rec.videoflags); + DPRINT1("386rec: optional parameters %s\n", pif386rec.optparams); + } + } + + /* prepare the return data */ + StringCchCopyA(lpPifStruct->ProgramName, sizeof(pifheader.program)+1, pifheader.program); + StringCchCopyA(lpPifStruct->Caption, sizeof(pifheader.windowtitle)+1, pifheader.windowtitle); + + //lpPifStruct->PifHeader = rhead; + + if (found386rec) + { + lpPifStruct->Pif386Record = &pif386rec; + StringCchCopyA(lpPifStruct->OptParams, sizeof(pif386rec.optparams)+1, pif386rec.optparams); + } + + else + StringCchCopyA(lpPifStruct->OptParams, sizeof(pifheader.optparams)+1, pifheader.optparams); + + StringCchCopyA(lpPifStruct->StartDir, sizeof(pifheader.startdir)+1, pifheader.startdir); + *lpPifStruct->CloseOnExit = pifheader.hdrflags1 & 0x10; + *lpPifStruct->TextMode = found386rec ? pif386rec.videoflags & 0x0010 + : pifheader.hdrflags1 & 0x0002; + + return S_OK; +} + +/* Code taken from winevdm */ +HRESULT ReadPifFile(HANDLE hFile, + LPSTR progname, + LPSTR title, + LPSTR optparams, + LPSTR startdir, + PINT closeonexit, + PINT textmode) +{ + DWORD nread; + LARGE_INTEGER filesize; + PIFRECORDHEAD rhead; + PIF386REC pif386rec; + PIFHEAD pifheader; + BOOL found386rec = FALSE; + + /* Make sure there's a file to actually work with */ + if (hFile == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + return E_HANDLE; + } + + /* Make sure the file is of the proper size before using it */ + if (!GetFileSizeEx(hFile, &filesize) || + filesize.QuadPart < (sizeof(PIFHEAD) + sizeof(PIFRECORDHEAD))) + { + DPRINT1("Invalid PIF file size error %d.", (int)filesize.QuadPart); + return E_FAIL; + } + + /* Set the file pointer to the beginning of the file so it + can be read properly */ + if (!SetFilePointer(hFile, 0, NULL, FILE_BEGIN)) + return E_FAIL; + + if (!ReadFile(hFile, &pifheader, sizeof(PIFHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + DPRINT1("header: program %s title %s startdir %s params %s\n", + pifheader.program, pifheader.windowtitle, pifheader.startdir, + pifheader.optparams); + DPRINT1("header: memory req'd %d desr'd %d drive %d videomode %d\n", + pifheader.memmin, pifheader.memmax, pifheader.startdrive, + pifheader.videomode); + DPRINT1("header: flags 0x%x 0x%x 0x%x\n", pifheader.hdrflags1, + pifheader.hdrflags2, pifheader.hdrflags3); + + /* Opens the file for reading from */ + if (!ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to read PIF file!"); + return E_FAIL; + } + + /* Ensure that this is actually a PIF file */ + if (strncmp(rhead.recordname, "MICROSOFT PIFEX", 15)) + { + DPRINT1("Invalid PIF file: magic string not found. Used instead: %S\n", rhead.recordname); + return E_FAIL; + } + + /* now process the following records */ + while(1) + { + WORD nextrecord = rhead.posofnextrecord; + + if ((nextrecord & 0x8000) || + filesize.QuadPart < (nextrecord + sizeof(PIFRECORDHEAD))) + break; + + if (!SetFilePointer(hFile, nextrecord, NULL, FILE_BEGIN) || + !ReadFile(hFile, &rhead, sizeof(PIFRECORDHEAD), &nread, NULL)) + { + DPRINT1("Unable to set the file pointer."); + return E_POINTER; + } + + /* deleted record */ + if (!rhead.recordname[0]) + continue; + + DPRINT1("reading record %s size %d next 0x%x\n", rhead.recordname, + rhead.sizeofdata, rhead.posofnextrecord ); + + if (!strncmp(rhead.recordname, "WINDOWS 386", 11)) + { + found386rec = TRUE; + + if (!ReadFile( hFile, &pif386rec, sizeof(PIF386REC), &nread, NULL)) + return E_FAIL; + + DPRINT1("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); + DPRINT1("386rec: option 0x%x memory 0x%x video 0x%x\n", pif386rec.optflags, + pif386rec.memflags, pif386rec.videoflags); + DPRINT1("386rec: optional parameters %s\n", pif386rec.optparams); + } + } + + /* prepare the return data */ + StringCchCopyA(progname, sizeof(pifheader.program)+1, pifheader.program); + StringCchCopyA(title, sizeof(pifheader.windowtitle)+1, pifheader.windowtitle); + + if(found386rec) + StringCchCopyA(optparams, sizeof(pif386rec.optparams)+1, pif386rec.optparams); + else + StringCchCopyA(optparams, sizeof(pifheader.optparams)+1, pifheader.optparams); + + StringCchCopyA(startdir, sizeof(pifheader.startdir)+1, pifheader.startdir); + *closeonexit = pifheader.hdrflags1 & 0x10; + *textmode = found386rec ? pif386rec.videoflags & 0x0010 + : pifheader.hdrflags1 & 0x0002; + +#if 0 + lpPifStruct.PifHeader = rhead; + + if (found386rec) + lpPifStruct.Pif386Record = pif386rec; +#endif + + return S_OK; +} Index: sdk/lib/pifio/pifio.h =================================================================== --- sdk/lib/pifio/pifio.h (nonexistent) +++ sdk/lib/pifio/pifio.h (working copy) @@ -0,0 +1,106 @@ +/* + * COPYRIGHT: See COPYING.LIB in the top level directory + * PROJECT: PIF I/O Library + * FILE: lib/pifio/pifio.h + * PURPOSE: Gives the ability to Save/Load DOS Shortcut Files + * PROGRAMMERS: Alexandre Julliard + * Lee Schroeder + */ +#ifndef PIFLIB_H +#define PIFLIB_H + +#include +#include +#include + +#include + +/* NOTES: + * - Code taken from WINE's winevdm. + * - http://www.smsoft.ru/en/pifdoc.htm + * - http://www.drdobbs.com/architecture-and-design/undocumented-corner/184409042 + */ +typedef struct { + BYTE checksum[2]; /* 0x00 never checked */ + 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: + * 01 directly modify memory + * 02 286: text mode selected + * 04 prevent program switch + * 08 no screen exchange + * 10 close window at exit + * 40 Direct interaction with COM1 + * 80 Direct interaction with COM2 + */ + BYTE startdrive; /* 0x64 */ + char startdir[64]; /* 0x65 */ + char optparams[64]; /* 0xa5 seems to be zero terminated */ + BYTE videomode; /* 0xe5 not used */ + BYTE videopagequantity; /* 0xe6 not used */ + BYTE irqlow; /* 0xe7 not used */ + BYTE irqhigh; /* 0xe8 not used */ + BYTE rows; /* 0xe9 not used */ + BYTE cols; /* 0xea not used */ + BYTE winY; /* 0xeb not used */ + BYTE winX; /* 0xec not used */ + WORD lastvideopage; /* 0xed */ + CHAR unkn1[64]; /* 0xef not used */ + CHAR unkn2[64]; /* 0x12f not used */ + BYTE hdrflags2; /* 0x16f */ + BYTE hdrflags3; /* 0x170 */ +} PIFHEAD, *LPPIFHEAD; + +/* 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 */ +} PIFRECORDHEAD, *LPPIFRECORDHEAD; + +/* 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, *LPPIF386REC; + +typedef struct { + LPSTR ProgramName; + LPSTR Caption; + LPSTR OptParams; + LPSTR StartDir; + PINT CloseOnExit; + PINT TextMode; + LPPIFHEAD PifHeader; + LPPIF386REC Pif386Record; +} *LPPIFSTRUCT; + +#include + +HRESULT ReadPifFile(HANDLE hFile, LPSTR progname, LPSTR title, LPSTR optparams, LPSTR startdir, PINT closeonexit, PINT textmode); +HRESULT ReadPifFile_NEW(HANDLE hFile, LPPIFSTRUCT lpPifStruct); + +#endif /* PIFLIB_H */ \ No newline at end of file Index: subsystems/mvdm/ntvdm/CMakeLists.txt =================================================================== --- subsystems/mvdm/ntvdm/CMakeLists.txt (revision 75338) +++ subsystems/mvdm/ntvdm/CMakeLists.txt (working copy) @@ -15,6 +15,7 @@ ##################################### include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/fast486) +include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/pifio) spec2def(ntvdm.exe ntvdm.spec ADD_IMPORTLIB) @@ -75,6 +76,6 @@ add_executable(ntvdm ${SOURCE} ntvdm.rc) add_pch(ntvdm ntvdm.h SOURCE) set_module_type(ntvdm win32cui UNICODE IMAGEBASE 0x0F000000) -target_link_libraries(ntvdm fast486 ${PSEH_LIB}) +target_link_libraries(ntvdm fast486 pifio ${PSEH_LIB}) add_importlibs(ntvdm user32 gdi32 advapi32 comdlg32 msvcrt kernel32 ntdll) add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all) Index: subsystems/mvdm/ntvdm/dos/dos32krnl/process.c =================================================================== --- subsystems/mvdm/ntvdm/dos/dos32krnl/process.c (revision 75338) +++ subsystems/mvdm/ntvdm/dos/dos32krnl/process.c (working copy) @@ -31,6 +31,8 @@ #include "vddsup.h" +#include + /* PRIVATE FUNCTIONS **********************************************************/ static VOID DosInitPsp(IN WORD Segment, @@ -794,6 +796,70 @@ switch (BinaryType) { /* Those are handled by NTVDM */ + case SCS_PIF_BINARY: + { + HANDLE hFile; + char progpath[MAX_PATH]; + char lpProgName[64], lpTitle[31], lpOptParams[65], lpStartDir[65]; + int closeonexit, textmode; + + /* Opens the PIF file */ + if ((hFile = CreateFileA(ProgramName, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + 0, 0)) == INVALID_HANDLE_VALUE) + { + DisplayMessage(L"Could not load DOS shortcut '%S'.\n" + L"Make sure the file exists or is valid.", + ProgramName); + return ERROR_FILE_NOT_FOUND; + } + + if (ReadPifFile(hFile, lpProgName, lpTitle, lpOptParams, lpStartDir, &closeonexit, &textmode) != S_OK) + { + DisplayMessage(L"Error reading DOS shortcut '%S'.", ProgramName); + CloseHandle(hFile); + // Fall through + } + + /* Close the file since it's not being used right now */ + CloseHandle(hFile); + + /* Make sure that the path of the program actually exists */ + if (lpStartDir[0] && !SetCurrentDirectoryA(lpStartDir)) + { + DisplayMessage(L"Error changing current directory '%S'.", lpStartDir); + return ERROR_PATH_NOT_FOUND; + } + + /* Make sure that the program the shortcut is pointing to actually exists */ + if (!SearchPathA(NULL, lpProgName, NULL, MAX_PATH, progpath, NULL )) + { + DisplayMessage(L"Error finding DOS program '%S'.", lpProgName); + return ERROR_PATH_NOT_FOUND; + } + + /* If the PIF file defines a window title, then use it */ + if (textmode) + if(AllocConsole()) + SetConsoleTitleA(lpTitle); + + /* Load the executable */ + Result = DosLoadExecutable(DOS_LOAD_AND_EXECUTE, + progpath, + Parameters, + NULL, + NULL, + ReturnAddress); + if (Result != ERROR_SUCCESS) + { + DisplayMessage(L"Could not load '%S'. Error: %u", ProgramName, Result); + } + + break; + } case SCS_WOW_BINARY: { DisplayMessage(L"Trying to load '%S'.\n" Index: subsystems/mvdm/ntvdm/dos/dos32krnl/process.h =================================================================== --- subsystems/mvdm/ntvdm/dos/dos32krnl/process.h (revision 75338) +++ subsystems/mvdm/ntvdm/dos/dos32krnl/process.h (working copy) @@ -15,6 +15,8 @@ #define SEGMENT_TO_PSP(seg) ((PDOS_PSP)SEG_OFF_TO_PTR((seg), 0)) +#include + typedef enum { DOS_LOAD_AND_EXECUTE = 0x00,