home *** CD-ROM | disk | FTP | other *** search
- /*
- CODEDATA.C -- Demonstration of executable data
-
- From Chapter 5 of "Undocumented Windows" (Addison-Wesley 1992)
- by Andrew Schulman, Dave Maxey and Matt Pietrek
-
- Build using: WINIOBC CODEDATA (for Borland C++ v3.00)
- WINIOMS CODEDATA (for Microsoft C/SDK)
- */
-
- #define WINDOWS
-
- // Ignore MS warning about redefinition of NULL under Windows
- #include <stdlib.h>
- #ifdef WINDOWS
- #include <dos.h>
- #include "windows.h"
- #include "winio.h"
-
- /* undocumented functions */
- void (FAR PASCAL *PrestoChangoSelector)(WORD sel1, WORD sel2);
- DWORD FAR PASCAL GetSelectorBase(WORD sel);
- #else
- #include <stdio.h>
- #endif
-
- unsigned char data[] = {
- 0xb8, 0x00, 0x00, /* mov ax, 0000 */
- 0x00, 0x00, 0x00, /* oper ax, immed */
- 0xcb, /* retf */
- } ;
-
- #define OPER 3 /* offset in data of operation byte */
- #define AX_LO 1 /* ax operand lo byte */
- #define IMMED_LO 4 /* immediate operand lo byte */
-
- /* opcodes */
- #define ADD 0x05
- #define OR 0x0d
- #define AND 0x25
- #define SUB 0x2d
- #define XOR 0x35
- #define CMP 0x3d
-
- void (far *code)(void);
-
- short math(short oper, short op1, short op2)
- {
- /*
- Compile code on the fly. For example, math(AND, 1, 3)
- becomes:
-
- B8 01 00 mov ax, 0001
- 25 03 00 and ax, 0003
- CB retf
-
- Code is compiled by putting values in data[] array; it is
- then immediately executed by calling (*code)() function ptr.
- */
-
- *((short *) &data[AX_LO]) = op1;
- *((short *) &data[IMMED_LO]) = op2;
- data[OPER] = oper;
- (*code)();
- /* return result in AX */
- }
-
- main()
- {
- #ifdef WINDOWS
- WORD data_sel, code_sel;
- void far *fpdata = (void far *) data; // Microsoft C FP_SEG wants lvalue
- HANDLE hKernel;
-
- winio_about("CODEDATA"
- "\nDemonstration of executable data"
- "\n\nFrom Chapter 5 of"
- "\n\"Undocumented Windows\" (Addison-Wesley, 1992)"
- "\nby Andrew Schulman, David Maxey and Matt Pietrek"
- );
-
- hKernel = GetModuleHandle("KERNEL");
- PrestoChangoSelector = GetProcAddress(hKernel, "PRESTOCHANGOSELECTOR");
- if (! PrestoChangoSelector)
- PrestoChangoSelector = GetProcAddress(hKernel, "CHANGESELECTOR");
- if (! PrestoChangoSelector)
- fail("This program requires PrestoChangoSelector()");
-
- data_sel = FP_SEG(fpdata);
- GlobalPageLock(data_sel); // Windows will not track changes for aliases!!
- code_sel = AllocSelector(data_sel);
- PrestoChangoSelector(data_sel, code_sel);
- code = MK_FP(code_sel, FP_OFF(fpdata));
-
- /* Now try to shake code & data loose by moving memory */
- GlobalCompact(-1L);
-
- if (GetSelectorBase(FP_SEG(code)) !=
- GetSelectorBase(FP_SEG(fpdata)))
- fail("Selectors out of sync!");
- #else
- code = (void far *) data;
- #endif
-
- printf("1 && 3 ==> %d\n", math(AND, 1, 3));
- printf("1 || 3 ==> %d\n", math(OR, 1, 3));
- printf("1 ^ 3 ==> %d\n", math(XOR, 1, 3));
- printf("1 + 3 ==> %d\n", math(ADD, 1, 3));
- printf("1 - 3 ==> %d\n", math(SUB, 1, 3));
-
- #ifdef WINDOWS
- GlobalPageUnlock(data_sel);
- FreeSelector(code_sel);
- #endif
-
- return 0;
- }
-