home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* Copyright (C) 1986-1990 Phar Lap Software, Inc. */
- /* Unpublished - rights reserved under the Copyright Laws of the */
- /* United States. Use, duplication, or disclosure by the */
- /* Government is subject to restrictions as set forth in */
- /* subparagraph (c)(1)(ii) of the Rights in Technical Data and */
- /* Computer Software clause at 252.227-7013. */
- /* Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138 */
- /************************************************************************/
-
- /* INCLUDES */
-
- #include <stdio.h>
- #include <dos.h>
- #include <pharlap.h>
- #include <hw386.h>
- #include <pldos32.h>
-
- void load_err(UCHAR *namep, int errv, UINT info, UINT dosinfo);
- int call_child(LDEXP_BLK *ldblkp, ULONG ndword_params, ...);
-
- /*
- This example program is run as:
- load <.EXE filename>
-
- It loads the specified file, and does a FAR call to its entry point. The
- loaded program terminates by executing a FAR return.
-
- NOTE: If you are loading a program built with a high level language, you
- MUST build the program to be loaded with a modified version of the
- initializer that comes with the compiler. You have to modify the
- initializer to:
- (1) make sure the program terminates with a FAR RET, instead of
- DOS system call INT 21h func 4Ch, and
- (2) the heap initialization modifies the size of the correct segment
- (i.e., doesn't assume hardwired segments 000Ch and 0014h),
- and calculates the desired segment size correctly (i.e., does
- NOT pull program size values out of the PSP, which applies
- to this program not the loaded program, instead it uses
- size values returned in the load parameter block by the
- load program system call).
- */
- int main (argc,argv)
- int argc;
- char **argv;
- {
- UCHAR *namep; /* ptr to pgm name string */
- LDEXP_BLK ldblk; /* Load parameter block */
- CONFIG_INF cbuf; /* config info */
- BOOL unprivf; /* T ==> if this pgm runs unprivileged*/
- int errv; /* Error value */
- UINT vmhandle; /* 386|VMM handle */
- UINT einfo; /* Error information */
- UINT doseinfo; /* DOS error information */
- USHORT code_sel; /* child's code segment selector */
- USHORT data_sel; /* child's data segment selector */
-
- /*
- * Get program name from command line
- */
- if (argc < 2)
- {
- printf("Usage: load filename");
- return TRUE;
- }
- namep = (UCHAR *) *(argv + 1);
-
- /*
- * Get config info so we have CS for this program; then look at the
- * RPL bits in CS to see if we are running at privilege level 0 (-PRIV) or
- * unprivileged (-UNPRIV). All we use this for is checking to see if child
- * privilege selection is the same as ours.
- */
- _dx_config_inf(&cbuf, (UCHAR *) &cbuf);
- unprivf = (cbuf.c_cs_sel & SEL_RPL) != 0;
-
- /*
- * Make DOS-X system call to load the program. If the child privilege
- * level selection (-PRIV or -UNPRIV) is different from ours, print out
- * a warning message to that effect. A program linked with -UNPRIV should
- * normally be capable of running at privilege level 0 (-PRIV), but a
- * program linked with -PRIV may not run unprivileged if it performs
- * operations (such as accessing the GDT or IDT directly) that are not
- * possible when running unprivileged.
- */
- errv = _dx_ld_flat(namep, &ldblk, FALSE, &vmhandle, &einfo,&doseinfo);
- if (errv != _DOSE_NONE)
- {
- load_err(namep, errv, einfo, doseinfo);
- return TRUE;
- }
- if (ldblk.flags & LD_UNPRIV)
- {
- if (!unprivf)
- printf("Warning: loader is running privileged,\n\
- child program %s is linked with -UNPRIV\n", namep);
- }
- else if (unprivf)
- printf("Warning: loader is running unprivileged,\n\
- child program %s is linked with -PRIV\n", namep);
-
- /*
- * Call assembly language routine to load regs and do FAR call to
- * loaded child pgm. First save child's code and data segment selectors,
- * which we need to free up the child later.
- */
- printf("Calling loaded program: <<%s>>\n", namep);
- fflush(stdout);
- code_sel = ldblk.cs;
- data_sel = ldblk.ds;
- call_child(&ldblk, 0);
-
- /*
- * Program terminated, now free up the segments for it in the LDT, and
- * if we have a VMM handle make a system call to release the handle.
- *
- * We have to free both the code & data segment to make the allocated memory
- * get freed; freeing just one removes the segment aliasing but leaves the
- * other still allocated.
- */
- errv = (int) _dos_freemem(code_sel);
- if (errv != _DOSE_NONE)
- goto FREE_ERR;
- errv = (int) _dos_freemem(data_sel);
- if (errv != _DOSE_NONE)
- {
- FREE_ERR:
- printf("Unexpected err freeing segment: %d\n", errv);
- return TRUE;
- }
- if (vmhandle != (UINT) -1)
- {
- errv = _dx_vmm_close(vmhandle);
- if (errv != _DOSE_NONE)
- {
- printf("Unexpected err releasing 386|VMM handle: %d\n",
- errv);
- return TRUE;
- }
- }
-
- /*
- * Successful terminate
- */
- return FALSE;
- }
-
- /* <load_err> - Print error message after load error */
-
- void load_err(UCHAR *namep, int errv, UINT info, UINT dosinfo)
-
- /*
- Description:
- This routine takes the error information returned by the load
- program system call and prints out an appropriate error message.
-
- Calling arguments:
- namep ptr to file name string
- errv error code returned by load pgm system call
- info sub-error code ret'd for file error or memory error
- dosinfo DOS error code ret'd for DOS file error
-
- Returned values:
- - none
- */
- {
- if (errv == 2)
- {
- printf("File related error loading %s\n", namep);
- switch(info)
- {
- case 1:
- printf(" DOS error opening file\n");
- break;
- case 2:
- printf(" DOS error seeking in file\n");
- break;
- case 3:
- printf(" DOS error reading file\n");
- break;
- case 4:
- printf(" Not flat model EXP or REX file\n");
- break;
- case 5:
- printf(" Invalid file format\n");
- break;
- case 6:
- printf(" Program linked with -OFFSET not \
- multiple of 4k\n");
- break;
- case 7:
- printf(" -NOPAGE in effect and program was \
- linked with -REALBREAK or -OFFSET\n");
- break;
- default:
- printf(" Unexpected file error code: %d\n",
- info);
- break;
- }
- if (info == 1 || info == 2 || info == 3)
- {
- switch(dosinfo)
- {
- case 2:
- printf(" File not found\n");
- break;
- case 3:
- printf(" Path not found\n");
- break;
- case 4:
- printf(" Too many open files\n");
- break;
- case 5:
- printf(" Access denied\n");
- break;
- case 6:
- printf(" Invalid file handle\n");
- break;
- case 12:
- printf(" Invalid file access code\n");
- break;
- default:
- printf(" Unexpected DOS err code: %d\n",
- dosinfo);
- break;
- }
- }
- }
-
- else if (errv == 8)
- {
- printf("Memory related error loading %s\n", namep);
- switch(info){
- case 1:
- printf(" Out of physical memory\n");
- break;
- case 2:
- printf(" Out of swap space\n");
- break;
- case 3:
- printf(" Unable to grow LDT\n");
- break;
- case 4:
- printf(" Unable to change extended \
- memory allocation mark\n");
- break;
- case 5:
- printf(" Maximum virtual size (from \
- -MAXPGMMEM switch) exceeded\n");
- break;
- case 6:
- printf(" Insuff. conv memory to satisfy \
- -REALBREAK switch setting\n");
- break;
- case 7:
- printf(" No conv memory available for \
- program PSP and environment\n");
- break;
- default:
- printf(" Unexpected mem err code: %d\n",
- info);
- break;
- }
- }
-
- else
- {
- printf("Unexpected error code from load pgm: %d\n", errv);
- return;
- }
-
- return;
- }
-