Source code of Windows XP (NT5)
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.

717 lines
20 KiB

  1. /* %W% %E% */
  2. /*
  3. * Copyright Microsoft Corporation, 1983-1987
  4. *
  5. * This Module contains Proprietary Information of Microsoft
  6. * Corporation and should be treated as Confidential.
  7. */
  8. /****************************************************************
  9. * *
  10. * LINKER INITIALIZATION *
  11. * *
  12. ****************************************************************/
  13. #include <minlit.h> /* Types and constants */
  14. #include <bndtrn.h> /* More of the same */
  15. #include <bndrel.h> /* More of the same */
  16. #include <lnkio.h> /* Linker I/O definitions */
  17. #include <newexe.h> /* DOS & 286 .EXE format definitions */
  18. #if EXE386
  19. #include <exe386.h> /* 386 .EXE format definitions */
  20. #endif
  21. #include <signal.h> /* Signal definitions */
  22. #if QCLINK
  23. #include <stdlib.h>
  24. #endif
  25. #include <lnkmsg.h> /* Error messages */
  26. #if OSMSDOS AND NOT (WIN_NT OR DOSEXTENDER OR DOSX32) AND NOT WIN_3
  27. #define INCL_BASE
  28. #define INCL_DOSMISC
  29. #include <os2.h> /* OS/2 system calls */
  30. #if defined(M_I86LM)
  31. #undef NEAR
  32. #define NEAR
  33. #endif
  34. #endif
  35. #include <extern.h> /* External declarations */
  36. #include <impexp.h>
  37. #include <direct.h>
  38. #if defined(DOSX32) OR defined(WIN_NT)
  39. extern char FAR * _stdcall GetCommandLineA(void);
  40. #endif
  41. /*
  42. * FUNCTION PROTOTYPES
  43. */
  44. LOCAL void NEAR InitLeadByte(void);
  45. LOCAL void NEAR SetupEnv(void);
  46. LOCAL int NEAR IsPrefix(BYTE *pszPrefix, BYTE *pszString);
  47. #if TCE
  48. extern SYMBOLUSELIST aEntryPoints; // List of program entry points
  49. #endif
  50. #if ECS
  51. /*
  52. * InitLeadByte
  53. *
  54. * Initialize lead byte table structures.
  55. * Returns no meaningful value.
  56. */
  57. LOCAL void NEAR InitLeadByte ()
  58. {
  59. struct lbrange
  60. {
  61. unsigned char low; /* minimum */
  62. unsigned char high; /* maximum */
  63. };
  64. static struct lbrange lbtab[5] = { { 0, 0 } };
  65. struct lbrange *ptab;
  66. WORD i; /* index */
  67. COUNTRYCODE cc; /* country code */
  68. cc.country = cc.codepage = 0;
  69. if (DosGetDBCSEv(sizeof(lbtab), &cc, (char FAR *)lbtab))
  70. return;
  71. // For each range, set corresponding entries in fLeadByte
  72. for (ptab = lbtab; ptab->low || ptab->high; ptab++)
  73. if (ptab->low >= 0x80)
  74. for (i = ptab->low; i <= ptab->high; i++)
  75. fLeadByte[i-0x80] = (FTYPE) TRUE;
  76. // Mark inclusive range true
  77. }
  78. #endif /* ECS */
  79. #if NOT (WIN_NT OR DOSX32)
  80. /*** _setenvp - stub for C run-time
  81. *
  82. * Purpose:
  83. * Call stub instead of real function, we don't want C run-time to
  84. * setup enviroment.
  85. *
  86. * Input:
  87. * None;
  88. *
  89. * Output:
  90. * None;
  91. *
  92. * Exceptions:
  93. * None.
  94. *
  95. * Notes:
  96. * None.
  97. *
  98. *************************************************************************/
  99. void cdecl _setenvp(void)
  100. {
  101. return;
  102. }
  103. /*** IsPrefix - self-explanatory
  104. *
  105. * Purpose:
  106. * Check if one string is a prefix of another.
  107. *
  108. * Input:
  109. * pszPrefix - pointer to prefix string
  110. * pszString - the string
  111. *
  112. * Output:
  113. * The function returns TRUE if the first string is a prefix of the
  114. * second; otherwise it returns FALSE.
  115. *
  116. * Exceptions:
  117. * None.
  118. *
  119. * Notes:
  120. * None.
  121. *
  122. *************************************************************************/
  123. LOCAL int NEAR IsPrefix(BYTE *pszPrefix, BYTE *pszString)
  124. {
  125. while(*pszPrefix) // While not at end of prefix
  126. {
  127. if (*pszPrefix != *pszString) return(FALSE);
  128. // Return zero if mismatch
  129. ++pszPrefix; // Increment pointer
  130. ++pszString; // Increment pointer
  131. }
  132. return(TRUE); // We have a prefix
  133. }
  134. #endif
  135. /*** SetupEnv - set up pointer to linker evironment variables
  136. *
  137. * Purpose:
  138. * Every byte in the DGROUP is to valuable to waste it to hold
  139. * information available elswere in the memory linker is not using
  140. * C run-time GETENV function, which accesses copy of the entire
  141. * environemt in the DGROUP placed there by the startup code.
  142. * Insted this function scans enviroment and set up pointers to
  143. * appropriate strings. Because initially enviroment is in the FAR
  144. * memory no space in DGROUP is used.
  145. *
  146. * Input:
  147. * No explicit parameters are passed.
  148. *
  149. * Output:
  150. * Four global pointer set to appropriate enviroment strings
  151. *
  152. * lpszLink - the LINK
  153. * lpszPath - the PATH
  154. * lpszTMP - the TMP
  155. * lpszLIB - the LIB
  156. * lpszQH - the QH for QuickHelp
  157. *
  158. * Exceptions:
  159. * None.
  160. *
  161. * Notes:
  162. * None.
  163. *
  164. *************************************************************************/
  165. LOCAL void NEAR SetupEnv(void)
  166. {
  167. #if WIN_NT OR DOSX32
  168. #if C8_IDE
  169. char * pIDE = getenv("_MSC_IDE_FLAGS");
  170. if(pIDE)
  171. {
  172. if(strstr(pIDE, "FEEDBACK"))
  173. {
  174. fC8IDE = TRUE;
  175. #if DEBUG_IDE
  176. fprintf(stdout, "\r\nIDE ACTIVE - FEEDBACK is ON");
  177. #endif
  178. }
  179. if(strstr(pIDE, "BATCH"))
  180. {
  181. // NOTE: The link response file will still be echoed in this case!
  182. // NOTE: this is different than if you specify /BATCH on the
  183. // NOTE: command line -- also, the banner is still displayed
  184. // NOTE: this is intentional as the IDE wants to BATCH to cause
  185. // NOTE: the linker not to prompt, but it does want the banner
  186. // NOTE: and response file echoed unless /NOLOGO is also specified
  187. // NOTE: see CAVIAR 2378 [rm]
  188. fNoprompt = (FTYPE) TRUE;
  189. fPauseRun = FALSE; /* Disable /PAUSE */
  190. #if DEBUG_IDE
  191. fprintf(stdout, "\r\nIDE ACTIVE - BATCH is ON");
  192. #endif
  193. }
  194. if(strstr(pIDE, "NOLOGO"))
  195. {
  196. fNoBanner = (FTYPE) TRUE;
  197. #if DEBUG_IDE
  198. fprintf(stdout, "\r\nIDE ACTIVE - LOGO is OFF");
  199. #endif
  200. }
  201. }
  202. #if DEBUG_IDE
  203. else
  204. fprintf(stdout, "\r\nIDE NOT ACTIVE");
  205. fflush(stdout);
  206. #endif
  207. #endif // C8_IDE
  208. lpszPath = getenv("PATH");
  209. lpszLink = getenv("LINK");
  210. lpszTMP = getenv("TMP");
  211. lpszLIB = getenv("LIB");
  212. lpszQH = getenv("QH");
  213. lpszHELPFILES = getenv("HELPFILES");
  214. lpszCmdLine = GetCommandLineA();
  215. while (*lpszCmdLine != ' ')
  216. lpszCmdLine++;
  217. #else
  218. WORD selEnv;
  219. WORD cmdOffset;
  220. register WORD offMac;
  221. char FAR *lpszEnv;
  222. char FAR *lpch;
  223. SBTYPE buf;
  224. register WORD ich;
  225. WORD fEOS;
  226. #if QCLINK OR CPU8086 OR DOSEXTENDER
  227. // Get the segment address of the environment block
  228. // and set the command line offset to infinity. We
  229. // stop scanning environment block at NULL string.
  230. lpszEnv = (char FAR *)
  231. (((long) _psp << 16)
  232. + 0x2c);
  233. selEnv = *((WORD FAR *) lpszEnv);
  234. lpszCmdLine = (char FAR *)(((long) _psp << 16) + 0x80);
  235. lpszCmdLine[lpszCmdLine[0] + 1] = '\0';
  236. lpszCmdLine++;
  237. cmdOffset = 0xffff;
  238. #else
  239. if (DosGetEnv((unsigned FAR *) &selEnv, (unsigned FAR *) &cmdOffset))
  240. return;
  241. #endif
  242. lpszEnv = (char FAR *)((long) selEnv << 16);
  243. #if NOT (QCLINK OR CPU8086 OR DOSEXTENDER)
  244. lpszCmdLine = lpszEnv + cmdOffset;
  245. // Skip LINK
  246. lpszCmdLine += _fstrlen(lpszCmdLine) + 1;
  247. #endif
  248. // Skip leading spaces in command line
  249. while (*lpszCmdLine == ' ')
  250. lpszCmdLine++;
  251. lpch = lpszEnv;
  252. for (offMac = 0; offMac < cmdOffset && *lpszEnv; )
  253. {
  254. // Copy the enviroment variable string into near buffer
  255. ich = 0;
  256. while (*lpch && ich < sizeof(buf) - 1)
  257. buf[ich++] = *lpch++;
  258. if (*lpch == '\0')
  259. {
  260. // Skip over terminating zero
  261. lpch++;
  262. fEOS = TRUE;
  263. }
  264. else
  265. fEOS = FALSE;
  266. buf[ich] = '\0';
  267. // Check what it is and setup appropriate pointer
  268. if (lpszPath == NULL && IsPrefix((BYTE *) "PATH=", buf))
  269. lpszPath = lpszEnv + 5;
  270. else if (lpszLink == NULL && IsPrefix((BYTE *) "LINK=", buf))
  271. lpszLink = lpszEnv + 5;
  272. else if (lpszTMP == NULL && IsPrefix((BYTE *) "TMP=", buf))
  273. lpszTMP = lpszEnv + 4;
  274. else if (lpszLIB == NULL && IsPrefix((BYTE *) "LIB=", buf))
  275. lpszLIB = lpszEnv + 4;
  276. else if (lpszQH == NULL && IsPrefix((BYTE *) "QH=", buf))
  277. lpszQH = lpszEnv + 3;
  278. else if (lpszHELPFILES == NULL && IsPrefix((BYTE *) "HELPFILES=", buf))
  279. lpszHELPFILES = lpszEnv + 10;
  280. // If everything setup don't bother to look father
  281. if (lpszPath && lpszLink && lpszTMP && lpszLIB && lpszQH && lpszHELPFILES)
  282. break;
  283. // Update enviroment pointer and offset in enviroment segment
  284. offMac += ich;
  285. if (!fEOS)
  286. {
  287. // Oops ! - enviroment variable longer then buffer
  288. // skip to its end
  289. while (*lpch && offMac < cmdOffset)
  290. {
  291. lpch++;
  292. offMac++;
  293. }
  294. // Skip over terminating zero
  295. lpch++;
  296. offMac++;
  297. }
  298. lpszEnv = lpch;
  299. }
  300. #endif
  301. }
  302. #if FALSE
  303. /*** Dos3SetMaxFH - set max file handle count for DOS
  304. *
  305. * Purpose:
  306. * Sets the maximum number of files that may be opened
  307. * simultaneously using handles by the linker.
  308. *
  309. * Input:
  310. * cFH - number of desired handles
  311. *
  312. * Output:
  313. * No explicit value is returned.
  314. *
  315. * Exceptions:
  316. * None.
  317. *
  318. * Notes:
  319. * This function uses the int 21h function 67h which available on
  320. * DOS 3.3 and higher. The function fails if the requested number of
  321. * handles is greater then 20 and there is not sufficient free memory
  322. * in the system to allocate a new block to hold the enlarged table.
  323. *
  324. * If the number of handles requested is larger the available
  325. * entries in the system's global table for file handles (controlled
  326. * by the FILES entry in CONFIG.SYS), no error is returned.
  327. * However, a subsequent attempt to open a file or create a new
  328. * file will fail if all entries in the system's global file table
  329. * are in use, even if the requesting process has not used up all
  330. * of its own handles
  331. *
  332. * We don't check for error, because we can't do much about it.
  333. * Linker will try to run with what is available.
  334. *
  335. *************************************************************************/
  336. LOCAL void NEAR Dos3SetMaxFH(WORD cFH)
  337. {
  338. if ((_osmajor >= 3) && (_osminor >= 30))
  339. {
  340. _asm
  341. {
  342. mov ax, 0x6700
  343. mov bx, cFH
  344. int 0x21
  345. }
  346. }
  347. }
  348. #endif
  349. /****************************************************************
  350. * *
  351. * InitializeWorld: *
  352. * *
  353. * This function takes no arguments and returns no meaningful *
  354. * value. It sets up virtual memory, the symbol table *
  355. * Handlers, and it initializes segment structures. *
  356. * *
  357. ****************************************************************/
  358. void InitializeWorld(void)
  359. {
  360. #if OSMSDOS
  361. BYTE buf[512]; /* Temporary buffer */
  362. char FAR *lpch; /* Temporary pointer */
  363. int i; /* Temporary index */
  364. #endif
  365. #if NOT (FIXEDSTACK OR CPU386)
  366. InitStack(); /* Initialize stack */
  367. #endif
  368. #if OSMSDOS
  369. DskCur = (BYTE) (_getdrive() - 1); /* Get current (default) disk drive */
  370. #if FALSE
  371. if(!isatty(fileno(stderr))) /* No prompts if output not console */
  372. fNoprompt = TRUE;
  373. #endif
  374. #if CRLF
  375. /* Default mode of stdout, stdin, stderr is text, change to binary. */
  376. _setmode(fileno(stdout),O_BINARY);
  377. if(stderr != stdout)
  378. _setmode(fileno(stderr),O_BINARY);
  379. _setmode(fileno(stdin),O_BINARY);
  380. #endif
  381. #endif
  382. InitSym(); /* Initialize symbol table handler */
  383. DeclareStdIds();
  384. // Install CTRL-C handler
  385. #if OSMSDOS AND NOT WIN_NT
  386. signal(SIGINT, (void (__cdecl *)(int)) UserKill);
  387. #endif /* OSMSDOS */
  388. #if OSXENIX
  389. if(signal(SIGINT,UserKill) == SIG_IGN) signal(SIGINT,SIG_IGN);
  390. /* Trap user interrupts */
  391. if(signal(SIGHUP,UserKill) == SIG_IGN) signal(SIGHUP,SIG_IGN);
  392. /* Trap hangup signal */
  393. if(signal(SIGTERM,UserKill) == SIG_IGN) signal(SIGTERM,SIG_IGN);
  394. /* Trap software termination */
  395. #endif
  396. #if SYMDEB
  397. InitDbRhte();
  398. #endif
  399. #if ECS
  400. InitLeadByte(); /* Initialize lead byte table */
  401. #endif
  402. #if OSMSDOS
  403. // Initialize LINK environment.
  404. // Do it yourself to save the memory.
  405. SetupEnv();
  406. /* Process switches from LINK environment variable */
  407. if (lpszLink != NULL)
  408. {
  409. lpch = lpszLink;
  410. /* Skip leading whitespace. */
  411. while(*lpch == ' ' || *lpch == '\t')
  412. lpch++;
  413. if(*lpch++ == CHSWITCH)
  414. {
  415. // If string begins with switchr
  416. // Copy string to buf, removing whitespace
  417. for (i = 1; *lpch && i < sizeof(buf); lpch++)
  418. if (*lpch != ' ' && *lpch != '\t')
  419. buf[i++] = *lpch;
  420. buf[0] = (BYTE) (i - 1); /* Set the length of buf */
  421. if(buf[0]) /* If any switches, process them */
  422. BreakLine(buf,ProcFlag,CHSWITCH);
  423. }
  424. }
  425. #endif
  426. #if CPU286
  427. if (_osmode == OS2_MODE)
  428. {
  429. DosSetMaxFH(128); /* This is the same as _NFILE in crt0dat.asm */
  430. DosError(EXCEPTION_DISABLE);
  431. }
  432. #if FALSE
  433. else
  434. Dos3SetMaxFH(40);
  435. #endif
  436. #endif
  437. #if FALSE AND CPU8086
  438. Dos3SetMaxFH(40);
  439. #endif
  440. // Initialize import/export tables
  441. InitByteArray(&ResidentName);
  442. InitByteArray(&NonResidentName);
  443. InitByteArray(&ImportedName);
  444. ImportedName.byteMac++; // Ensure non-zero offsets to imported names
  445. InitWordArray(&ModuleRefTable);
  446. InitByteArray(&EntryTable);
  447. #if TCE
  448. aEntryPoints.cMaxEntries = 64;
  449. aEntryPoints.pEntries = (RBTYPE*)GetMem(aEntryPoints.cMaxEntries * sizeof(RBTYPE*));
  450. #endif
  451. }
  452. #if (OSXENIX OR OSMSDOS OR OSPCDOS) AND NOT WIN_NT
  453. /****************************************************************
  454. * *
  455. * UserKill: *
  456. * *
  457. * Clean up if linker killed by user. *
  458. * *
  459. ****************************************************************/
  460. void cdecl UserKill()
  461. {
  462. signal(SIGINT, SIG_IGN); /* Disallow ctrl-c during handler */
  463. CtrlC();
  464. }
  465. #endif
  466. /*
  467. * InitTabs:
  468. *
  469. * Initialize tables required in Pass 1.
  470. */
  471. void InitTabs(void)
  472. {
  473. #if NOT FAR_SEG_TABLES
  474. char *tabs; /* Pointer to table space */
  475. unsigned cbtabs;
  476. #endif
  477. /* Initialize the following tables:
  478. *
  479. * NAME TYPE
  480. * ---- ----
  481. * mpsegraFirst RATYPE
  482. * mpgsnfCod FTYPE
  483. * mpgsndra RATYPE
  484. * mpgsnrprop RBTYPE
  485. * mplnamerhte RBTYPE
  486. */
  487. #if FAR_SEG_TABLES
  488. mplnamerhte = (RBTYPE FAR *) GetMem(lnameMax * sizeof(RBTYPE));
  489. mpsegraFirst = (RATYPE FAR *) GetMem(gsnMax * sizeof(RATYPE));
  490. mpgsnfCod = (FTYPE FAR *) mpsegraFirst; /* Use same space twice */
  491. mpgsndra = (RATYPE FAR *) GetMem(gsnMax * sizeof(RATYPE));
  492. mpgsnrprop = (RBTYPE FAR *) GetMem(gsnMax * sizeof(RBTYPE));
  493. #else
  494. mplnamerhte = (RBTYPE *) malloc(lnameMax * sizeof(RBTYPE));
  495. if (mplnamerhte == NULL)
  496. Fatal(ER_seglim);
  497. memset(mplnamerhte, 0, lnameMax * sizeof(RATYPE));
  498. cbtabs = gsnMax * (sizeof(RATYPE) + sizeof(RATYPE) + sizeof(RBTYPE));
  499. if((tabs = malloc(cbtabs)) == NULL)
  500. Fatal(ER_seglim);
  501. memset(tabs,0,cbtabs); /* Clear everything */
  502. mpsegraFirst = (RATYPE *) tabs; /* Initialize base */
  503. mpgsnfCod = (FTYPE *) mpsegraFirst; /* Use same space twice */
  504. mpgsndra = (RATYPE *) &mpsegraFirst[gsnMax];
  505. mpgsnrprop = (RBTYPE *) &mpgsndra[gsnMax];
  506. #endif
  507. }
  508. /*
  509. * InitP2Tabs:
  510. *
  511. * Initialize tables not needed until Pass 2.
  512. */
  513. void InitP2Tabs (void)
  514. {
  515. char FAR *tabs; /* Pointer to table space */
  516. unsigned cbtabs; /* Size of table space */
  517. unsigned TabSize;
  518. TabSize = gsnMac + iovMac + 1;
  519. /* Tables required regardless of exe format generated:
  520. * mpsegsa SATYPE
  521. * mpgsnseg SEGTYPE
  522. */
  523. #if FAR_SEG_TABLES
  524. cbtabs = 0;
  525. mpsegsa = (SATYPE FAR *) GetMem(TabSize * sizeof(SATYPE));
  526. mpgsnseg = (SEGTYPE FAR *) GetMem(TabSize * sizeof(SEGTYPE));
  527. mpseggsn = (SNTYPE FAR *) GetMem(TabSize * sizeof(SNTYPE));
  528. #else
  529. cbtabs = TabSize * (sizeof(RATYPE) + sizeof(SATYPE));
  530. #endif
  531. /* Tables required according to exe format generated:
  532. *
  533. * DOS 3:
  534. * mpsegcb[TabSize] long
  535. * mpsegFlags[TabSize] FTYPE
  536. * mpsegalign[TabSize] ALIGNTYPE
  537. * mpsegiov[TabSize] IOVTYPE
  538. * mpiovRlc[iovMac] RUNRLC
  539. * Seg. exe:
  540. * mpsacb[SAMAX] long
  541. * mpsadraDP[SAMAX] long; for O68K
  542. * mpsacbinit[SAMAX] long
  543. * mpsaRlc[SAMAX] HASHRLC FAR *
  544. * mpsaflags[SAMAX] WORD; DWORD for EXE386
  545. * htsaraep[HEPLEN] EPTYPE FAR *
  546. * X.out:
  547. * mpsegcb[TabSize] long
  548. * mpsegFlags[TabSize] FTYPE
  549. * mpstsa[TabSize] SATYPE
  550. */
  551. #if EXE386
  552. if(fNewExe)
  553. cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(DWORD)+
  554. sizeof(DWORD))) + (HEPLEN * sizeof(WORD));
  555. else
  556. #else
  557. if(fNewExe)
  558. #if O68K
  559. cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(long)+sizeof(WORD)+
  560. sizeof(WORD))) + (HEPLEN * sizeof(WORD));
  561. #else
  562. cbtabs += (SAMAX*(sizeof(long)+sizeof(long)+sizeof(RLCHASH FAR *) +
  563. sizeof(WORD))) + (HEPLEN * sizeof(EPTYPE FAR *));
  564. #endif
  565. else
  566. #endif
  567. #if OEXE
  568. cbtabs += TabSize * (sizeof(long) + sizeof(FTYPE) + sizeof(ALIGNTYPE));
  569. #else
  570. cbtabs += TabSize * (sizeof(long) + sizeof(FTYPE) + sizeof(SATYPE));
  571. #endif
  572. cbtabs += sizeof(WORD);
  573. tabs = GetMem(cbtabs);
  574. #if NOT FAR_SEG_TABLES
  575. mpgsnseg = (SEGTYPE *)tabs;
  576. mpsegsa = (SATYPE *)&mpgsnseg[TabSize];
  577. tabs = (char *)&mpsegsa[TabSize];
  578. #endif
  579. #if OSEGEXE
  580. if(fNewExe)
  581. {
  582. mpsacb = (DWORD FAR *) tabs;
  583. #if O68K
  584. mpsadraDP = (long *)&mpsacb[SAMAX];
  585. mpsacbinit = (long *)&mpsadraDP[SAMAX];
  586. #else
  587. mpsacbinit = (DWORD FAR *)&mpsacb[SAMAX];
  588. #endif
  589. #if EXE386
  590. mpsacrlc = (DWORD *)&mpsacbinit[SAMAX];
  591. mpsaflags = (DWORD *)&mpsacrlc[SAMAX];
  592. #else
  593. mpsaRlc = (RLCHASH FAR * FAR *) &mpsacbinit[SAMAX];
  594. mpsaflags = (WORD FAR *) &mpsaRlc[SAMAX];
  595. #endif
  596. htsaraep = (EPTYPE FAR * FAR *)&mpsaflags[SAMAX];
  597. }
  598. else
  599. #endif
  600. {
  601. #if ODOS3EXE OR OIAPX286
  602. mpsegcb = (long FAR *) tabs;
  603. mpsegFlags = (FTYPE FAR *)&mpsegcb[TabSize];
  604. #if OEXE
  605. mpsegalign = (ALIGNTYPE FAR *)&mpsegFlags[TabSize];
  606. #if OVERLAYS
  607. cbtabs = iovMac * sizeof(RUNRLC) + TabSize * sizeof(IOVTYPE) +
  608. (sizeof(DWORD) - 1); // leave room to align mpiovRlc
  609. mpsegiov = (IOVTYPE FAR*) GetMem(cbtabs);
  610. // align mpiovRlc on a DWORD, the alignment needed by struct _RUNRLC
  611. mpiovRlc = (RUNRLC FAR*) ( ( (__int64)&mpsegiov[TabSize] +
  612. (sizeof(DWORD) - 1)
  613. ) & ~(sizeof(DWORD) - 1)
  614. );
  615. #endif
  616. #endif
  617. #if OIAPX286
  618. mpstsa = (SATYPE *)&mpsegFlags[TabSize];
  619. #endif
  620. #endif /* ODOS3EXE OR OIAPX286 */
  621. }
  622. /* Attempt to allocate space for mpextprop. */
  623. cbtabs = extMax * sizeof(RBTYPE);
  624. mpextprop = (RBTYPE FAR *) GetMem(cbtabs);
  625. }