#include "precomp.h"
#pragma hdrstop
/* File: progcm.c */
/**************************************************************************/
/*	Install: Resource stamping
/**************************************************************************/


extern HWND hwndFrame;



#define wExeSignature		0x5A4D
#define lNewExeOffset		0x3CL
#define wNewExeSignature	0x454E
#define lResourceOffset		0x24L

#define FTypeNumeric(wType)	(wType & 0x8000)
#define FNameNumeric(wName) (wName & 0x8000)
#define WTypeActual(wType)  (WORD)(wType & 0x7FFF)
#define WNameActual(wName)  (WORD)(wName & 0x7FFF)

/* ReSource Group */
typedef struct _rsg
	{
	WORD wType;
	WORD crsd;
	LONG lReserved;
	} RSG;

#define cbRsg	(sizeof(RSG))

/* ReSource Descriptor */
typedef struct _rsd
	{
	WORD wOffset;
	WORD wLength;
	WORD wFlags;
	WORD wName;
	LONG lReserved;
	} RSD;

#define cbRsd	(sizeof(RSD))



/*
**	Purpose:
**		Write a string into an EXE resource
**	Arguments:
**		szSection	INF section containing EXE file descriptor
**		szKey		INF key of EXE file descriptor
**		szDst		Directory where the EXE file lives
**		wResType	Resource type
**		wResId		Resource ID
**		szData		String to write into the resource
**		cbData		Number of bytes to write
**	Notes:
**		Only numeric resource types and resource IDs are supported.
**		szData must contain the entire resource data, and must
**			be formatted correctly as a resource, including all tags,
**			byte counts, flags, etc, expected of the resource type.
**			FStampResource knows nothing of individual resource formats.
**		cbData must be less than or equal to the size of the
**			resource in the file.  If it is smaller than the actual
**			resource, the remainder of the resource is left intact.
**	Returns:
**		Returns fTrue if successful, fFalse otherwise.
**
**************************************************************************/
BOOL APIENTRY FStampResource(SZ szSection, SZ szKey, SZ szDst,
        WORD wResType, WORD wResId, SZ szData, CB cbData)
/* REVIEW need fVital? */
{
#if defined(WIN16)
	PSFD   psfd = (PSFD)NULL;
	OER    oer;
	CHP    szExe[cchpFullPathBuf];
	PFH    pfh;
	LONG   lData, lNewHeader;
	WORD   wResShift;
	USHORT date, time;
    GRC    grc;
    INT    Line;

	while ((grc = GrcFillPoerFromSymTab(&oer)) != grcOkay)
		if (EercErrorHandler(hwndFrame, grc, fTrue, 0, 0, 0) != eercRetry)
			return(fFalse);

    if ((Line = FindLineFromInfSectionKey(szSection, szKey)) == -1)
		{
        EvalAssert(EercErrorHandler(hwndFrame, grcINFMissingLine, fTrue, szSection, pLocalInfPermInfo()->szName,
				0) == eercAbort);
		return(fFalse);
		}

    while ((grc = GrcGetSectionFileLine(&psfd, &oer)) != grcOkay) {
        SZ szParam1 = NULL, szParam2 = NULL;
        switch ( grc ) {
        case grcINFBadFDLine:
            szParam1 = pLocalInfPermInfo()->szName;
            szParam2 = szSection;
            break;
        default:
            break;
        }

        if (EercErrorHandler(hwndFrame, grc, fTrue, szParam1, szParam2, 0) != eercRetry) {
			return(fFalse);
        }

    }

	Assert(psfd != NULL);

    if (!FBuildFullDstPath(szExe, szDst, psfd, fFalse))
		{
		EvalAssert(FFreePsfd(psfd));
		EvalAssert(EercErrorHandler(hwndFrame, grcInvalidPathErr, fTrue,
				szDst, psfd->szFile, 0) == eercAbort);
		return(fFalse);
		}

	EvalAssert(FFreePsfd(psfd));

	while ((pfh = PfhOpenFile(szExe, ofmReadWrite)) == (PFH)NULL)
		if (EercErrorHandler(hwndFrame, grcOpenFileErr, fTrue, szExe, 0, 0)
				!= eercRetry)
			return(fFalse);

	while (_dos_getftime(pfh->iDosfh, &date, &time))
		if (EercErrorHandler(hwndFrame, grcReadFileErr, fTrue, szExe, 0, 0)
				!= eercRetry)
			goto LCloseExit;

	while (CbReadFile(pfh, (PB)&lData, 2) != 2)
		if (EercErrorHandler(hwndFrame, grcReadFileErr, fTrue, szExe, 0, 0)
				!= eercRetry)
			goto LCloseExit;

	if (LOWORD(lData) != 0x5A4D)		//'MZ'
		goto LBadExe;
	if (LfaSeekFile(pfh, 0x3CL, sfmSet) == lfaSeekError)
		goto LBadExe;
	if (CbReadFile(pfh, (PB)&lNewHeader, 4) != 4)
		goto LBadExe;
	if (LfaSeekFile(pfh, lNewHeader, sfmSet) == lfaSeekError)
		goto LBadExe;
	if (CbReadFile(pfh, (PB)&lData, 2) != 2)
		goto LBadExe;
	if (LOWORD(lData) != 0x454E)		//'NE'
		goto LBadExe;
	if (LfaSeekFile(pfh, lNewHeader + 0x24, sfmSet) == lfaSeekError)
		goto LBadExe;
	if (CbReadFile(pfh, (PB)&lData, 2) != 2)
		goto LBadExe;
	if (LfaSeekFile(pfh, lNewHeader + LOWORD(lData), sfmSet) == lfaSeekError)
		goto LBadExe;
	if (CbReadFile(pfh, (PB)&wResShift, 2) != 2)
		goto LBadExe;

	for (;;)
		{
		RSG rsg;

		if (CbReadFile(pfh, (PB)&rsg, cbRsg) != cbRsg)
			goto LBadExe;
		if (rsg.wType == 0)
			goto LMissingResource;

		while (rsg.crsd)
			{
			RSD rsd;

			if (CbReadFile(pfh, (PB)&rsd, cbRsd) != cbRsd)
				goto LBadExe;
			if (FTypeNumeric(rsg.wType) &&
                    WTypeActual(rsg.wType) == wResType &&
					FNameNumeric(rsd.wName) &&
					WNameActual(rsd.wName) == wResId)
				{
				LONG lOffset = ((LONG)rsd.wOffset) << wResShift;
				LONG lLength = ((LONG)rsd.wLength) << wResShift;

				if (LfaSeekFile(pfh, lOffset, sfmSet) == lfaSeekError)
					goto LMissingResource;
				if ((LONG)cbData > lLength)
					{
					EvalAssert(EercErrorHandler(hwndFrame,
							grcResourceTooLongErr, fTrue, 0, 0,0) == eercAbort);
					goto LCloseExit;
					}
				if (CbWriteFile(pfh, szData, cbData) != cbData)
					{
                    EvalAssert(EercErrorHandler(hwndFrame, grcWriteFileErr,
							fTrue, szExe, 0,0) == eercAbort);
					goto LCloseExit;
					}

				while (_dos_setftime(pfh->iDosfh, date, time))
					if (EercErrorHandler(hwndFrame, grcWriteFileErr, fTrue,
							szExe, 0, 0) != eercRetry)
						goto LCloseExit;

				EvalAssert(FCloseFile(pfh));
				return(fTrue);
				}
			rsg.crsd--;
			}
		}

LMissingResource:
	EvalAssert(EercErrorHandler(hwndFrame, grcMissingResourceErr, fTrue, szExe,
			0, 0) == eercAbort);
	goto LCloseExit;

LBadExe:
	EvalAssert(EercErrorHandler(hwndFrame, grcBadWinExeFileFormatErr, fTrue,
			szExe, 0, 0) == eercAbort);

LCloseExit:
	EvalAssert(FCloseFile(pfh));
    return(fFalse);

#else           // 1632BUG -- eliminate this func altogether?

    Unused(szSection);
    Unused(szKey);
    Unused(szDst);
    Unused(wResType);
    Unused(wResId);
    Unused(szData);
    Unused(cbData);

    MessBoxSzSz("FStampResource","IGNORED (Unsupported in 32-bit version)");

    return(fTrue);
#endif
}