215 lines
6.0 KiB
C++
215 lines
6.0 KiB
C++
|
/*
|
||
|
* exe.c Get info from a EXEHDR
|
||
|
*
|
||
|
* Modification History:
|
||
|
*
|
||
|
* 4/03/89 ToddLa Wrote it
|
||
|
* 4/09/90 T-JackD modification such that the type of error is reflected...
|
||
|
* 4/17/90 t-jackd modification such that notification of error can be set...
|
||
|
* 4/20/2001 BryanSt improved the error checking to bring the code into the 21st centry.
|
||
|
*/
|
||
|
|
||
|
#include "priv.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <newexe.h>
|
||
|
#include "exe.h"
|
||
|
|
||
|
static DWORD dwDummy;
|
||
|
#define FOPEN(sz) CreateFile(sz, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )
|
||
|
#define FCLOSE(fh) CloseHandle(fh)
|
||
|
#define FREAD(fh,buf,len) (ReadFile(fh,buf,len, &dwDummy, NULL) ? dwDummy : HFILE_ERROR)
|
||
|
#define FSEEK(fh,off,i) SetFilePointer(fh,(DWORD)off, NULL, i)
|
||
|
#define F_SEEK_SET FILE_BEGIN
|
||
|
|
||
|
BOOL NEAR PASCAL IsFAPI(int fh, struct new_exe FAR *pne, long off);
|
||
|
|
||
|
/*
|
||
|
* Function will return a specific piece of information from a new EXEHDR
|
||
|
*
|
||
|
* szFile - Path Name a new exe
|
||
|
* pBuf - Buffer to place returned info
|
||
|
* nBuf - Size of buffer in BYTES
|
||
|
* fInfo - What info to get?
|
||
|
*
|
||
|
* GEI_MODNAME - Get module name
|
||
|
* GEI_DESCRIPTION - Get description
|
||
|
* GEI_FLAGS - Get EXEHDR flags
|
||
|
*
|
||
|
* returns: LOWORD = ne_magic, HIWORD = ne_exever
|
||
|
* 0 if error
|
||
|
*/
|
||
|
|
||
|
DWORD FAR PASCAL GetExeInfo(LPTSTR szFile, void FAR *pBuf, int nBuf, UINT fInfo)
|
||
|
{
|
||
|
HANDLE fh;
|
||
|
DWORD off;
|
||
|
DWORD dw;
|
||
|
BYTE len;
|
||
|
struct exe_hdr exehdr;
|
||
|
struct new_exe newexe;
|
||
|
|
||
|
fh = FOPEN(szFile);
|
||
|
|
||
|
if (fh == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FREAD(fh, &exehdr, sizeof(exehdr)) != sizeof(exehdr) ||
|
||
|
exehdr.e_magic != EMAGIC ||
|
||
|
exehdr.e_lfanew == 0L)
|
||
|
{
|
||
|
goto error; /* Abort("Not an exe",h); */
|
||
|
}
|
||
|
|
||
|
FSEEK(fh, exehdr.e_lfanew, F_SEEK_SET);
|
||
|
|
||
|
if (FREAD(fh, &newexe, sizeof(newexe)) != sizeof(newexe))
|
||
|
{
|
||
|
goto error; // Read error
|
||
|
}
|
||
|
|
||
|
if (newexe.ne_magic == PEMAGIC)
|
||
|
{
|
||
|
if (fInfo != GEI_DESCRIPTION &&
|
||
|
fInfo != GEI_EXPVER)
|
||
|
goto error;
|
||
|
|
||
|
// make the file name the description
|
||
|
lstrcpy((LPTSTR) pBuf, szFile);
|
||
|
|
||
|
// read the SubsystemVersion
|
||
|
|
||
|
FSEEK(fh,exehdr.e_lfanew+18*4,F_SEEK_SET);
|
||
|
FREAD(fh,&dw,4);
|
||
|
|
||
|
newexe.ne_expver = LOBYTE(LOWORD(dw)) << 8 | LOBYTE(HIWORD(dw));
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
if (newexe.ne_magic != NEMAGIC)
|
||
|
{
|
||
|
goto error; // Invalid NEWEXE
|
||
|
}
|
||
|
|
||
|
switch (fInfo)
|
||
|
{
|
||
|
case GEI_EXEHDR:
|
||
|
*(struct new_exe FAR *)pBuf = newexe;
|
||
|
break;
|
||
|
|
||
|
case GEI_FLAGS:
|
||
|
*(WORD FAR *)pBuf = newexe.ne_flags;
|
||
|
break;
|
||
|
|
||
|
/* module name is the first entry in the medident name table */
|
||
|
case GEI_MODNAME:
|
||
|
off = exehdr.e_lfanew + newexe.ne_restab;
|
||
|
goto readstr;
|
||
|
break;
|
||
|
|
||
|
/* module name is the first entry in the non-medident name table */
|
||
|
case GEI_DESCRIPTION:
|
||
|
off = newexe.ne_nrestab;
|
||
|
readstr:
|
||
|
FSEEK(fh, off, F_SEEK_SET);
|
||
|
FREAD(fh, &len, sizeof(BYTE));
|
||
|
|
||
|
nBuf--; // leave room for a \0
|
||
|
|
||
|
if (len > (BYTE)nBuf)
|
||
|
len = (BYTE)nBuf;
|
||
|
|
||
|
{
|
||
|
LPSTR pbTmp;
|
||
|
pbTmp = (LPSTR) LocalAlloc(LMEM_FIXED, len);
|
||
|
|
||
|
if (pbTmp)
|
||
|
{
|
||
|
FREAD(fh, pbTmp, len);
|
||
|
|
||
|
len = (BYTE)MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pbTmp, len,
|
||
|
(LPWSTR)pBuf, nBuf / SIZEOF(WCHAR));
|
||
|
|
||
|
LocalFree(pbTmp);
|
||
|
}
|
||
|
}
|
||
|
((LPTSTR)pBuf)[len] = 0;
|
||
|
break;
|
||
|
|
||
|
case GEI_EXPVER:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
goto error;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
exit:
|
||
|
FCLOSE(fh);
|
||
|
return MAKELONG(newexe.ne_magic, newexe.ne_expver);
|
||
|
|
||
|
error:
|
||
|
FCLOSE(fh);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Code taken from kernel32.dll
|
||
|
#define DEFAULT_WAIT_FOR_INPUT_IDLE_TIMEOUT 30000
|
||
|
|
||
|
UINT WinExecN(LPCTSTR pszPath, LPTSTR pszPathAndArgs, UINT uCmdShow)
|
||
|
{
|
||
|
STARTUPINFO StartupInfo;
|
||
|
PROCESS_INFORMATION ProcessInformation;
|
||
|
BOOL CreateProcessStatus;
|
||
|
DWORD ErrorCode;
|
||
|
|
||
|
ZeroMemory(&StartupInfo,sizeof(StartupInfo));
|
||
|
StartupInfo.cb = sizeof(StartupInfo);
|
||
|
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
|
||
|
StartupInfo.wShowWindow = (WORD)uCmdShow;
|
||
|
CreateProcessStatus = CreateProcess(
|
||
|
pszPath,
|
||
|
pszPathAndArgs,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
FALSE,
|
||
|
0,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&StartupInfo,
|
||
|
&ProcessInformation
|
||
|
);
|
||
|
|
||
|
if ( CreateProcessStatus )
|
||
|
{
|
||
|
// Wait for the started process to go idle. If it doesn't go idle in
|
||
|
// 10 seconds, return anyway.
|
||
|
WaitForInputIdle(ProcessInformation.hProcess, DEFAULT_WAIT_FOR_INPUT_IDLE_TIMEOUT);
|
||
|
CloseHandle(ProcessInformation.hProcess);
|
||
|
CloseHandle(ProcessInformation.hThread);
|
||
|
return 33;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If CreateProcess failed, then look at GetLastError to determine
|
||
|
// appropriate return code.
|
||
|
ErrorCode = GetLastError();
|
||
|
switch ( ErrorCode )
|
||
|
{
|
||
|
case ERROR_FILE_NOT_FOUND:
|
||
|
return 2;
|
||
|
|
||
|
case ERROR_PATH_NOT_FOUND:
|
||
|
return 3;
|
||
|
|
||
|
case ERROR_BAD_EXE_FORMAT:
|
||
|
return 11;
|
||
|
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|