mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
7.5 KiB
305 lines
7.5 KiB
/*
|
|
* 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...
|
|
*/
|
|
#include <windows.h>
|
|
#include "desk.h"
|
|
#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(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)
|
|
{
|
|
#ifdef FAPI
|
|
case GEI_FAPI:
|
|
*(BOOL FAR *)pBuf = IsFAPI(fh,(struct new_exe FAR *)&newexe,
|
|
exehdr.e_lfanew);
|
|
break;
|
|
#endif
|
|
|
|
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;
|
|
|
|
#ifdef UNICODE
|
|
{
|
|
LPSTR pbTmp;
|
|
pbTmp = LocalAlloc(LMEM_FIXED, len);
|
|
|
|
FREAD(fh, pbTmp, len);
|
|
|
|
len = MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pbTmp, len,
|
|
(LPWSTR)pBuf, nBuf / SIZEOF(WCHAR));
|
|
|
|
LocalFree(pbTmp);
|
|
|
|
}
|
|
#else
|
|
FREAD(fh, pBuf, len);
|
|
#endif
|
|
((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;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
|
|
/*
|
|
* Code taken from kernel32.dll
|
|
*/
|
|
#define DEFAULT_WAIT_FOR_INPUT_IDLE_TIMEOUT 30000
|
|
|
|
UINT WinExecN( LPCTSTR lpCmdLine, 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(
|
|
NULL,
|
|
(LPTSTR)lpCmdLine,
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef FAPI
|
|
|
|
#pragma error(THIS CODE HAS NOT BEEN PORTED TO NT)
|
|
|
|
|
|
#include <ctype.h>
|
|
#define UP_CASE(f) toupper(f)
|
|
|
|
int NEAR PASCAL lstrncmpi(LPSTR pch1, LPSTR pch2, int n)
|
|
{
|
|
while (*pch1 && --n > 0 && UP_CASE(*pch1) == UP_CASE(*pch2))
|
|
*pch1++,*pch2++;
|
|
return UP_CASE(*pch1) != UP_CASE(*pch2);
|
|
}
|
|
|
|
char szDOSCALLS[] = "DOSCALLS";
|
|
#define lenDOSCALLS 8
|
|
|
|
/* BOOL NEAR PASCAL IsFAPI(fh,off)
|
|
*
|
|
* Function will return whether a exe is a FAPI exe
|
|
*
|
|
* fh - Open file handle to NEW EXE
|
|
* off - Base of module table
|
|
*
|
|
* returns: TRUE if FAPI, FALSE otherwise.
|
|
*/
|
|
BOOL NEAR PASCAL IsFAPI(int fh, struct new_exe FAR * pne, long off)
|
|
{
|
|
char buf[256];
|
|
char FAR *pch;
|
|
WORD FAR *pw;
|
|
int n;
|
|
UINT i;
|
|
BOOL f = FALSE;
|
|
|
|
/*
|
|
* look through the imported module table for the name "DOSCALLS" if
|
|
* found the EXE is a FAPI app.
|
|
*
|
|
* NOTE! assumes module table will fit in a 256 byte buffer
|
|
*/
|
|
|
|
// make sure this doesn't point off the end of the buffer we will use
|
|
|
|
if (pne->ne_modtab > sizeof(buf))
|
|
return FALSE;
|
|
|
|
FSEEK(fh,off,F_SEEK_SET);
|
|
FREAD(fh,buf,sizeof(buf));
|
|
|
|
pw = (WORD FAR *)(buf + pne->ne_modtab);
|
|
|
|
for (i = 0; i < pne->ne_cmod; i++)
|
|
{
|
|
pch = (LPSTR)buf + pne->ne_imptab + *pw++;
|
|
|
|
if (pch > (LPSTR)(buf + sizeof(buf))) // be sure we don't go off the end
|
|
break;
|
|
|
|
n = (int)*pch++;
|
|
|
|
if (n == 0)
|
|
break;
|
|
|
|
if (n == lenDOSCALLS && !lstrncmpi(szDOSCALLS, pch, lenDOSCALLS))
|
|
{
|
|
f = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
#endif
|