Subversion Repositories Kolibri OS

Rev

Rev 6446 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "tok.h"
  2.  
  3. #include "coff.h"
  4.  
  5.  
  6.  
  7. #define _OUTPE_
  8.  
  9.  
  10.  
  11. /* -----------------------------------------------------------------------
  12.  
  13.  Создание PE формата
  14.  
  15.  ------------------------------------------------------------------------ */
  16.  
  17. #define SIZESTUB 96
  18.  
  19. #define STRVERS 0x20    //смещение текста с номером версии
  20.  
  21.  
  22.  
  23. char stub[]={0x4D,0x5A,0x50,0x00,0x02,0x00,0x00,0x00,
  24.  
  25.              0x04,0x00,0x0F,0x00,0xFF,0xFF,0x00,0x00,
  26.  
  27.                                                  0xB8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  28.  
  29.              0x40,0x00,0x1A,0x00,0x00,0x00,0x00,0x00,
  30.  
  31.  
  32.  
  33.                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  34.  
  35.                                                  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  36.  
  37.              0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  38.  
  39.                                                  0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
  40.  
  41.  
  42.  
  43.                                                  0xBA,0x0E,0x00,0x0E,0x1F,0xB4,0x09,0xCD,
  44.  
  45.              0x21,0xB8,0x01,0x4C,0xCD,0x21,0x46,0x6F,
  46.  
  47.                                                  0x72,0x20,0x57,0x69,0x6E,0x33,0x32,0x20,
  48.  
  49.                                                  0x6F,0x6E,0x6C,0x79,0x21,0x0D,0x0A,0x24};
  50.  
  51.  
  52.  
  53. #define SIZESTUB2 12
  54.  
  55. char stub2[]={0x4D,0x5A,0x53,0x50,0x48,0x49,0x4E,0x58,
  56.  
  57.               0x20,0x43,0x2D,0x2D};
  58.  
  59. unsigned int numdll,numapi;
  60.  
  61. unsigned char FixUpTable=FALSE; //запретить создание таблици Fix UP for Windows
  62.  
  63. unsigned char WinMonoBlock=TRUE;
  64.  
  65. int numexport=0;
  66.  
  67. unsigned long ImageBase=0x400000;
  68.  
  69. unsigned long vsizeheader=0x1000; //виртуальный размер заголовка.
  70.  
  71. unsigned long FILEALIGN=0;//512;        // выравнивание секций в файле
  72.  
  73. int filingzerope;
  74.  
  75.  
  76.  
  77. struct listexport *lexport=NULL;
  78.  
  79. static unsigned long sizestub;
  80.  
  81. static unsigned long numrs=1;
  82.  
  83.  
  84.  
  85. unsigned long  Align(unsigned long size,unsigned long val)
  86.  
  87. {
  88.  
  89.         if(val<2)return size;
  90.  
  91.         val--;
  92.  
  93.         return (size+val)&(~val);
  94.  
  95. }
  96.  
  97.  
  98.  
  99. /*
  100.  
  101. #include <conio.h>
  102.  
  103.  
  104.  
  105. void PrintMem(void *mem)
  106.  
  107. {
  108.  
  109. unsigned char *m,*n;
  110.  
  111. int i,j;
  112.  
  113.         m=(unsigned char *)mem;
  114.  
  115.         for(i=0;i<192;){
  116.  
  117.                 n=m;
  118.  
  119.                 for(j=0;j<16;j++,i++){
  120.  
  121.                         printf("%02X ",*m);
  122.  
  123.                         m++;
  124.  
  125.                 }
  126.  
  127.                 for(j=0;j<16;j++){
  128.  
  129.                         char c=*n;
  130.  
  131.                         n++;
  132.  
  133.                         if(c<0x20||c>0x7e)c='.';
  134.  
  135.                         putch(c);
  136.  
  137.                 }
  138.  
  139.                 puts("");
  140.  
  141.         }
  142.  
  143. }
  144.  
  145.  
  146.  
  147. void CheckMem()
  148.  
  149. {
  150.  
  151.         if(listdll!=NULL){      //есть api-проц
  152.  
  153. DLLLIST *newdll=listdll;        //начало списка DLL
  154.  
  155. APIPROC *listapi=newdll->list;
  156.  
  157. idrec *rec=listapi->recapi;
  158.  
  159.                 PrintMem(rec);
  160.  
  161.         }
  162.  
  163. } */
  164.  
  165.  
  166.  
  167. void AddJmpApi()
  168.  
  169. {
  170.  
  171. //поиск api процедур
  172.  
  173. //скорректировать адреса из таблицы перемещений
  174.  
  175.         alignersize+=AlignCD(CS,4);
  176.  
  177.         if(listdll!=NULL){      //есть api-проц
  178.  
  179.                 DLLLIST *newdll=listdll;        //начало списка DLL
  180.  
  181.                 numdll=numapi=0;
  182.  
  183.                 for(APIPROC *listapi=newdll->list;;){
  184.  
  185.                         unsigned short numapiprocdll=0; //число используемых в библиотеке процедур
  186.  
  187.                         for(short i=0;i<newdll->num;i++){       //проверить все процедуры
  188.  
  189.                                 idrec *rec=(listapi+i)->recapi;
  190.  
  191.                                 unsigned int idnum=rec->recnumber;      //идентификатор списка
  192.  
  193.                                 char useapi=FALSE;      //флаг использования
  194.  
  195.                                 for(unsigned int j=0;j<posts;j++){      //поиск использования процедуры
  196.  
  197.                                         if((postbuf+j)->num==idnum){
  198.  
  199.                                                 if((postbuf+j)->type==CALL_32){ //нашли
  200.  
  201.                                                         useapi=API_JMP; //флаг взведем
  202.  
  203.                                                         unsigned long hold=outptr-((postbuf+j)->loc+4); //растояние до вызова
  204.  
  205.                                                         *(long *)&output[(postbuf+j)->loc]=hold;        //исправить
  206.  
  207.                                                 }
  208.  
  209.                                                 else if((postbuf+j)->type==CALL_32I){
  210.  
  211.                                                         useapi=API_FAST;        //флаг взведем
  212.  
  213.                                                         numrel++;
  214.  
  215.                                                 }
  216.  
  217.                                         }
  218.  
  219.                                 }
  220.  
  221.                                 if(useapi==API_JMP){    // процедура вызывалась
  222.  
  223.                                         *(short *)&output[outptr]=0x25ff;       //генерация JMP
  224.  
  225.                                         outptr+=2;
  226.  
  227.                                         rec->recnumber=outptr;  //теперь вместо идент. точка входа
  228.  
  229.                                         AddReloc(CS);   //добавить ее в табл перемещений
  230.  
  231.                                         *(long *)&output[outptr]=0;     //адрес вызова
  232.  
  233.                                         outptr+=4;
  234.  
  235.                                         numapi++;       //общее число использованых api-процедур
  236.  
  237.                                         numapiprocdll++;        //число использованых процедур в этой DLL
  238.  
  239.                                 }
  240.  
  241.                                 else if(useapi==API_FAST){
  242.  
  243.                                         numapi++;       //общее число использованых api-процедур
  244.  
  245.                                         numapiprocdll++;        //число использованых процедур в этой DLL
  246.  
  247.                                 }
  248.  
  249.                                 rec->recrm=useapi;      //тип вызова api; 0 - not used
  250.  
  251.                                 if(rec->newid!=NULL){
  252.  
  253.                                         free(rec->newid);       //список параметров больше не нужен
  254.  
  255.                                         rec->newid=NULL;
  256.  
  257.                                 }
  258.  
  259.                         }
  260.  
  261.                         newdll->num=numapiprocdll;      //исправить число реально использ процедур
  262.  
  263.                         if(numapiprocdll==0){   //в этой библиотеке не использ ни один вызов
  264.  
  265.                                 free(newdll->list);     //удалить список процедур.
  266.  
  267.                         }
  268.  
  269.                         else numdll++;
  270.  
  271.                         if(newdll->next==NULL)break;    //конец списка
  272.  
  273.                         newdll=newdll->next;
  274.  
  275.                         listapi=newdll->list;
  276.  
  277.                 }
  278.  
  279.         }
  280.  
  281.         outptrdata=outptr;
  282.  
  283. }
  284.  
  285.  
  286.  
  287. int MakePE()
  288.  
  289. {
  290.  
  291. unsigned short numobj=1;
  292.  
  293. char *importblock=NULL;
  294.  
  295. char *relocblock=NULL;
  296.  
  297. char *exportblock=NULL;
  298.  
  299. unsigned long psize = 0,vsize=0,sizereloc=0,sizeReloc=0,sizeImport=0,sizeExport=0,
  300.  
  301.               sizebss=0,sizeRes=0;
  302.  
  303. unsigned long startsec=0,startsecr=0,startsece=0,startsecres=0;
  304.  
  305. unsigned int posrel=0,sizeimport=0,startimportname=0,sizeexport=0,sizeres=0,
  306.  
  307.              startexportname=0;
  308.  
  309. unsigned int sizehead;  //размер заголовка
  310.  
  311. unsigned int exportnum=0; //номер секции экспорта
  312.  
  313. unsigned int relocnum=0;        //номер секции перемещений
  314.  
  315. unsigned int importnum=0;       //номер секции импорта
  316.  
  317. unsigned int codenum=0; //номер секции кода
  318.  
  319. unsigned int resnum=0;  //номер секции ресурсов
  320.  
  321.         if(hout==NULL)return -1;
  322.  
  323.         if(WinMonoBlock==FALSE){
  324.  
  325.                 vsize=Align(outptr+(wbss==FALSE?postsize:0),OBJECTALIGN);//виртуальный размер секции кода
  326.  
  327.                 psize=Align(outptr,FILEALIGN);  //физический размер секции кода
  328.  
  329.         }
  330.  
  331.         else vsize=outptr;
  332.  
  333. //      sizehead=((postsize&&wbss)?2:1)*sizeof(OBJECT_ENTRY);
  334.  
  335.         sizehead=numrs*sizeof(OBJECT_ENTRY);
  336.  
  337.         OBJECT_ENTRY *objentry=(OBJECT_ENTRY *)MALLOC(sizehead);//тавлица объектов
  338.  
  339.         memset(objentry,0,sizehead);//очистить таблицу объектов
  340.  
  341. //секция .bss
  342.  
  343.         if(wbss){       //есть post переменные
  344.  
  345.                 numobj++;     //увеличиваем число объектов
  346.  
  347.                 codenum=1;      //номер секции кода
  348.  
  349.                 strcpy(objentry->name,".bss"); //имя секции
  350.  
  351.                 objentry->vsize=sizebss=Align(postsize,OBJECTALIGN);
  352.  
  353.                 objentry->pOffset=objentry->psize=0;
  354.  
  355.                 objentry->flags=0xC0000080;
  356.  
  357.                 objentry->sectionRVA=vsizeheader;
  358.  
  359.         }
  360.  
  361.         strcpy((objentry+codenum)->name,"CODE");        //ее имя
  362.  
  363.         (objentry+codenum)->vsize=vsize;          //размер секции в памяти
  364.  
  365.         (objentry+codenum)->psize=psize;          //размер секции в файле
  366.  
  367.         (objentry+codenum)->flags=0xe0000060;     //флаг секции
  368.  
  369.         (objentry+codenum)->sectionRVA=vsizeheader+sizebss;//виртуальный адрес секции в памяти
  370.  
  371. //секция импорта
  372.  
  373.         if(numapi!=0){  //есть вызовы api-процедур созд секцию импорта
  374.  
  375.                 if(!WinMonoBlock){      //если не единый блок
  376.  
  377.                         importnum=numobj;
  378.  
  379.                         numobj++;     //увеличиваем число объектов
  380.  
  381.                 }
  382.  
  383.                 startsec=vsizeheader+vsize+sizebss;     //начало секции в памяти
  384.  
  385.                         //реальный размер секции
  386.  
  387.                 startimportname=(numdll+1)*20+(numapi+numdll)*(shortimport==0?8:4);
  388.  
  389.                 sizeimport=Align(startimportname,FILEALIGN);    //размер секции в памяти
  390.  
  391.                 importblock=(char *)MALLOC(sizeimport); //память под нее
  392.  
  393.                 memset(importblock,0,sizeimport);       //очистить ее
  394.  
  395.                 DLLLIST *newdll=listdll;        //табличка dll с импортируемыми процедурами
  396.  
  397.                 unsigned long sn,sn1;
  398.  
  399.                 sn1=sn=(numdll+1)*20;
  400.  
  401.                 for(int i=0;;i++){
  402.  
  403.                         while(newdll->num==0)if((newdll=newdll->next)==NULL)break;//пропуск неиспользуемых
  404.  
  405.                         if(newdll==NULL)break;  //завершить цикл если список dll пуст
  406.  
  407.                         APIPROC *listapi=newdll->list;  //табличка процедур из текущей dll
  408.  
  409.                         *(long *)&importblock[i*20+12]=startsec+startimportname;
  410.  
  411.                         *(long *)&importblock[i*20]=(shortimport==0?startsec+sn:0);
  412.  
  413.                         *(long *)&importblock[i*20+16]=startsec+sn+(shortimport==0?(numdll+numapi)*4:0);
  414.  
  415.                         sn+=(newdll->num+1)*4;
  416.  
  417.                         unsigned int lenn=strlen(newdll->name)+1;
  418.  
  419.                         if((lenn+startimportname+1)>=sizeimport){
  420.  
  421.                                 sizeimport+=FILEALIGN;  //увеличить размер секции
  422.  
  423.                                 importblock=(char *)REALLOC(importblock,sizeimport);
  424.  
  425.                                 memset(importblock+sizeimport-FILEALIGN,0,FILEALIGN);
  426.  
  427.                         }
  428.  
  429.                         strcpy(&importblock[startimportname],newdll->name);
  430.  
  431.                         startimportname+=lenn;
  432.  
  433.                         for(int n=0,t=0;n<newdll->num;n++,t++){
  434.  
  435.                                 while((listapi+t)->recapi->recrm==0)t++;
  436.  
  437.                                 idrec *rec=(listapi+t)->recapi;
  438.  
  439.                                 unsigned long newadr;
  440.  
  441.                                 newadr=ImageBase+startsec+sn1+(shortimport==0?(numdll+numapi)*4:0);
  442.  
  443.                                 if(rec->recrm==API_JMP)*(long *)&output[rec->recnumber]=newadr;
  444.  
  445.                                 else{
  446.  
  447.                                         for(unsigned int j=0;j<posts;j++){      //поиск использования процедуры
  448.  
  449.                                                 if((postbuf+j)->num==(unsigned long)rec->recnumber&&(postbuf+j)->type==CALL_32I){
  450.  
  451.                                                         *(long *)&output[(postbuf+j)->loc]=newadr;      //исправить
  452.  
  453.                                                 }
  454.  
  455.                                         }
  456.  
  457.                                 }
  458.  
  459.                                 if(useordinal&&rec->recsib!=-1){
  460.  
  461.                                         *(long *)&importblock[sn1]=rec->recsib|0x80000000;
  462.  
  463.                                         if(shortimport==0)*(long *)&importblock[sn1+(numdll+numapi)*4]=rec->recsib|0x80000000;
  464.  
  465.                                 }
  466.  
  467.                                 else{
  468.  
  469.                                         if((startimportname%2)==1)importblock[startimportname++]=0;
  470.  
  471.                                         *(long *)&importblock[sn1]=startsec+startimportname;
  472.  
  473.                                         if(shortimport==0)*(long *)&importblock[sn1+(numdll+numapi)*4]=startsec+startimportname;
  474.  
  475.                                         if(rec->recsize!=-1)sprintf((char *)string2,"%s@%u",rec->recid,rec->recsize);
  476.  
  477.                                         else strcpy((char *)string2,rec->recid);
  478.  
  479.                                         lenn=strlen((char *)string2)+1;
  480.  
  481.                                         if((lenn+startimportname+4)>=sizeimport){
  482.  
  483.                                                 sizeimport+=FILEALIGN;
  484.  
  485.                                                 importblock=(char *)REALLOC(importblock,sizeimport);
  486.  
  487.                                                 memset(importblock+sizeimport-FILEALIGN,0,FILEALIGN);
  488.  
  489.                                         }
  490.  
  491.                                         *(short *)&importblock[startimportname]=0;
  492.  
  493.                                         startimportname+=2;
  494.  
  495.                                         strcpy(&importblock[startimportname],(char *)string2);
  496.  
  497.                                         startimportname+=lenn;
  498.  
  499.                                 }
  500.  
  501.                                 sn1+=4;
  502.  
  503.                         }
  504.  
  505.                         if(newdll->next==NULL)break;
  506.  
  507.                         newdll=newdll->next;
  508.  
  509.                         sn1+=4;
  510.  
  511.                 }
  512.  
  513.                 importblock[startimportname++]=0;
  514.  
  515.  
  516.  
  517.                 if(!WinMonoBlock){      //если не единый блок
  518.  
  519.                         strcpy((objentry+importnum)->name,".idata"); //имя секции
  520.  
  521.                         (objentry+importnum)->vsize=sizeImport=Align(sizeimport,OBJECTALIGN);
  522.  
  523.                         (objentry+importnum)->psize=sizeimport;
  524.  
  525.                         (objentry+importnum)->flags=0xC0000040;
  526.  
  527.                         (objentry+importnum)->sectionRVA=startsec;
  528.  
  529.                 }
  530.  
  531.                 else sizeImport=sizeimport=Align(startimportname,4);
  532.  
  533.         }
  534.  
  535. //секция экспорта
  536.  
  537.         if(numexport!=0){
  538.  
  539.                 if(!WinMonoBlock){      //если не единый блок
  540.  
  541.                         exportnum=numobj;
  542.  
  543.                         numobj++;     //увеличиваем число объектов
  544.  
  545.                 }
  546.  
  547.                 startsece=vsizeheader+vsize+sizeImport+sizebss;//начало секции в памяти
  548.  
  549.                 startexportname=sizeof(EXPORT_TABLE)+numexport*10;//реальный размер секции
  550.  
  551.                 sizeexport=Align(startexportname,FILEALIGN);    //размер секции в памяти
  552.  
  553.                 exportblock=(char *)MALLOC(sizeexport); //память под нее
  554.  
  555.                 memset(exportblock,0,sizeexport);       //очистить ее
  556.  
  557.                 *(long *)&exportblock[12]=startsece+startexportname;//адрес имени файла
  558.  
  559.                 *(long *)&exportblock[16]=1;    //Ordinal Base
  560.  
  561.                 *(long *)&exportblock[20]=numexport;    //Num of Functions
  562.  
  563.                 *(long *)&exportblock[24]=numexport;    //Num of Name Pointer
  564.  
  565.                 *(long *)&exportblock[28]=startsece+sizeof(EXPORT_TABLE);//Address Table RVA
  566.  
  567.                 *(long *)&exportblock[32]=startsece+sizeof(EXPORT_TABLE)+numexport*4;//Name Pointers RVA
  568.  
  569.                 *(long *)&exportblock[36]=startsece+sizeof(EXPORT_TABLE)+numexport*8;//Ordinal Table RVA
  570.  
  571.                 char *oname;
  572.  
  573.                 strcpy((char *)string2,(char *)rawfilename);
  574.  
  575.                 oname=strrchr((char *)string2,'\\');
  576.  
  577.                 if(oname==NULL)oname=(char *)string2;
  578.  
  579.                 else oname=oname+1;
  580.  
  581.                 sprintf((char *)string,"%s.%s",oname,outext);
  582.  
  583.                 unsigned int lenn=strlen((char *)string)+1;
  584.  
  585.                 if((lenn+startexportname+1)>=sizeexport){
  586.  
  587.                         sizeexport+=FILEALIGN;  //увеличить размер секции
  588.  
  589.                         exportblock=(char *)REALLOC(exportblock,sizeexport);
  590.  
  591.                         memset(exportblock+sizeexport-FILEALIGN,0,FILEALIGN);
  592.  
  593.                 }
  594.  
  595.                 strcpy(&exportblock[startexportname],(char *)string);
  596.  
  597.                 startexportname+=lenn;
  598.  
  599.                 for(int i=0;i<numexport;i++){
  600.  
  601.                         *(long *)&exportblock[sizeof(EXPORT_TABLE)+i*4]=(lexport+i)->address+vsizeheader+sizebss;       //адреса функций
  602.  
  603.                         *(long *)&exportblock[sizeof(EXPORT_TABLE)+(numexport+i)*4]=startsece+startexportname;  //адреса имен
  604.  
  605.                         *(short *)&exportblock[sizeof(EXPORT_TABLE)+numexport*8+i*2]=(short)i;  //ординалы имен
  606.  
  607.                         lenn=strlen((lexport+i)->name)+1;
  608.  
  609.                         if((lenn+startexportname+1)>=sizeexport){
  610.  
  611.                                 sizeexport+=FILEALIGN;  //увеличить размер секции
  612.  
  613.                                 exportblock=(char *)REALLOC(exportblock,sizeexport);
  614.  
  615.                                 memset(exportblock+sizeexport-FILEALIGN,0,FILEALIGN);
  616.  
  617.                         }
  618.  
  619.                         strcpy(&exportblock[startexportname],(lexport+i)->name);
  620.  
  621.                         startexportname+=lenn;
  622.  
  623.                 }
  624.  
  625.                 free(lexport);//освободим уже не нужный блок
  626.  
  627.                 if(!WinMonoBlock){      //если не единый блок
  628.  
  629.                         strcpy((objentry+exportnum)->name,".edata"); //имя секции
  630.  
  631.                         (objentry+exportnum)->vsize=sizeExport=Align(sizeexport,OBJECTALIGN);
  632.  
  633.                         (objentry+exportnum)->psize=sizeexport;
  634.  
  635.                         (objentry+exportnum)->flags=0x40000040;
  636.  
  637.                         (objentry+exportnum)->sectionRVA=startsece;
  638.  
  639.                 }
  640.  
  641.                 else sizeexport=sizeExport=Align(startexportname,4);
  642.  
  643.         }
  644.  
  645.  
  646.  
  647.         if(numres){     //секция ресурсов
  648.  
  649.                 if(WinMonoBlock==FALSE){        //если не единый блок
  650.  
  651.                         resnum=numobj;
  652.  
  653.                         numobj++;                     //увеличить число объектов
  654.  
  655.                 }
  656.  
  657.                 startsecres=vsizeheader+vsize+sizeImport+sizebss+sizeExport;//начало секции в памяти
  658.  
  659.                 LISTRELOC *resrel;
  660.  
  661.                 if(MakeRes(startsecres,&resrel))free(resrel);
  662.  
  663.                 if(!WinMonoBlock){      //если не единый блок
  664.  
  665.                         strcpy((objentry+resnum)->name,".rsrc"); //имя секции
  666.  
  667.                         (objentry+resnum)->vsize=sizeRes=Align(curposbuf,OBJECTALIGN);
  668.  
  669.                         (objentry+resnum)->psize=sizeres=Align(curposbuf,FILEALIGN);
  670.  
  671.                         (objentry+resnum)->flags=0x40000040;
  672.  
  673.                         (objentry+resnum)->sectionRVA=startsecres;
  674.  
  675.                 }
  676.  
  677.                 else sizeres=Align(curposbuf,4);
  678.  
  679.         }
  680.  
  681.  
  682.  
  683. //секция таблиц перемещения
  684.  
  685.         if((FixUpTable==TRUE&&numrel!=0)/*||numexport!=0*/){//создать секцию перемещения
  686.  
  687.                 if(WinMonoBlock==FALSE||dllflag==TRUE){ //если не единый блок и это DLL
  688.  
  689.                         relocnum=numobj;
  690.  
  691.                         numobj++;                     //увеличить число объектов
  692.  
  693.                 }
  694.  
  695.                 if(WinMonoBlock&&dllflag)startsecr=vsizeheader+
  696.  
  697.                         Align(sizeimport+sizeexport+outptr+(wbss==FALSE?postsize:0)+sizebss+sizeres,OBJECTALIGN);
  698.  
  699.                 else startsecr=vsizeheader+vsize+sizeImport+sizeExport+sizebss+sizeres; //виртуальный адрес секции в памяти
  700.  
  701.                 //физический размер секции таблицы перемещений
  702.  
  703.                 sizereloc=Align(numrel*2+(outptr/4096+1)*10,FILEALIGN);
  704.  
  705.                 sizeReloc=Align(sizereloc,OBJECTALIGN);//виртуальный размер этой секции
  706.  
  707.                 relocblock=(char *)MALLOC(sizereloc);   //память под эту секцию
  708.  
  709.                 memset(relocblock,0,sizereloc); //очистить ее
  710.  
  711.                 //заполняем секцию перемещения
  712.  
  713.                 unsigned int startrsec=0;       //адрес начала блока в секции перемещения
  714.  
  715.                 unsigned int startblc=0;        //адрес первого блока
  716.  
  717.                 posrel=8;
  718.  
  719.                 do{
  720.  
  721.                         unsigned char fr=FALSE; //флаг элемента
  722.  
  723.                         for(unsigned int i=0;i<posts;i++){      //обходим всю таблицу post
  724.  
  725.                                 if(
  726.  
  727.                                                 (
  728.  
  729.                                                   (postbuf+i)->type==CALL_32I||
  730.  
  731.                                                     ((postbuf+i)->type>=POST_VAR32&&(postbuf+i)->type<=FIX_CODE32))
  732.  
  733.                                                                 &&
  734.  
  735.                                         (postbuf+i)->loc>=startblc&&(postbuf+i)->loc<(startblc+4096)){
  736.  
  737.                                         *(short *)&relocblock[posrel]=(short)((postbuf+i)->loc%4096|0x3000);
  738.  
  739.                                         posrel+=2;
  740.  
  741.                                         fr=TRUE;
  742.  
  743.                                 }
  744.  
  745.                         }
  746.  
  747.                         if(fr!=FALSE){  //если были перемещаемые адреса
  748.  
  749.                                 posrel+=posrel%4;       //выравниваем
  750.  
  751.                                 *(long *)&relocblock[startrsec]=vsizeheader+sizebss+startblc;
  752.  
  753.                                 *(long *)&relocblock[startrsec+4]=posrel-startrsec;     //размер куска
  754.  
  755.                                 startrsec=posrel;
  756.  
  757.                                 posrel+=8;
  758.  
  759.                         }
  760.  
  761.                         startblc+=4096;
  762.  
  763.                 }while(startblc<vsize);
  764.  
  765.                 posrel-=8;
  766.  
  767.                 if(WinMonoBlock==FALSE||dllflag==TRUE){ //если не единый блок
  768.  
  769.                         strcpy((objentry+relocnum)->name,".reloc");     //имя секции
  770.  
  771.                         (objentry+relocnum)->vsize=sizeReloc;        //размер секции в памяти
  772.  
  773.                         (objentry+relocnum)->psize=sizereloc;        //размер секции в файле
  774.  
  775.                         (objentry+relocnum)->flags=0x52000040;       //флаг секции
  776.  
  777.                         (objentry+relocnum)->sectionRVA=startsecr;   //виртуальный адрес секции в памяти
  778.  
  779.                 }
  780.  
  781.                 else sizereloc=Align(posrel,4);
  782.  
  783.         }
  784.  
  785.         if(WinMonoBlock){
  786.  
  787.                 psize=sizeimport+sizeexport+(dllflag==FALSE?sizereloc:0)+sizeres;       //размер дополнительных данных
  788.  
  789.                 if(wbss==0){
  790.  
  791.                         for(unsigned int i=0;i<posts;i++){
  792.  
  793.                                 if((postbuf+i)->type==POST_VAR32)
  794.  
  795.                                                 *(long *)&output[(postbuf+i)->loc]+=psize;
  796.  
  797.                         }
  798.  
  799.                 }
  800.  
  801.                 psize+=outptr;
  802.  
  803.                 (objentry+codenum)->vsize=vsize=Align(psize+(wbss==FALSE?postsize:0),OBJECTALIGN);//виртуальный размер секции кода
  804.  
  805.                 filingzerope=(objentry+codenum)->psize=Align(psize,FILEALIGN);  //физический размер секции кода
  806.  
  807.                 filingzerope-=psize;
  808.  
  809.                 psize=(objentry+codenum)->psize;
  810.  
  811.                 sizeImport=sizeExport=0;
  812.  
  813.                 if(dllflag==FALSE)sizeReloc=0;
  814.  
  815.         }
  816.  
  817.         PE_HEADER *peheader=(PE_HEADER *)MALLOC(sizeof(PE_HEADER));
  818.  
  819.         memset(peheader,0,sizeof(PE_HEADER));
  820.  
  821.         sizehead=Align(sizeof(PE_HEADER)+sizestub+(numobj+(numres!=0?0:1))*sizeof(OBJECT_ENTRY),FILEALIGN);
  822.  
  823. #ifdef _WC_
  824.  
  825.         peheader->sign='EP';
  826.  
  827. #else
  828.  
  829.         peheader->sign='PE';
  830.  
  831. #endif
  832.  
  833.         peheader->cpu=0x14c;//(chip>=4?(chip>=5?0x14e:0x14D):0x14c);
  834.  
  835. //      peheader->date_time=0;
  836.  
  837.         peheader->DLLflag=dllflag;
  838.  
  839.         peheader->numobj=numobj;
  840.  
  841.         peheader->NTheadsize=0xe0;
  842.  
  843.         peheader->flags=(short)(0x818e|(dllflag==0?0:0x2000));
  844.  
  845.         peheader->Magic=0x10b;
  846.  
  847.         peheader->LinkVer=(short)((short)ver2*256+ver1);
  848.  
  849.         peheader->sizecode=psize;
  850.  
  851.         peheader->sizeuninitdata=postsize;
  852.  
  853.         {
  854.  
  855.                 unsigned int temp;
  856.  
  857.                 temp=EntryPoint();
  858.  
  859.                 if(temp==0xffffffff)peheader->EntryRVA=0;
  860.  
  861.                 else peheader->EntryRVA=vsizeheader+sizebss+temp;
  862.  
  863.         }
  864.  
  865.         peheader->basecode=vsizeheader+sizebss;
  866.  
  867.         peheader->objAlig=OBJECTALIGN;
  868.  
  869.         peheader->fileAlig=FILEALIGN;
  870.  
  871.         peheader->OSver=1;
  872.  
  873.         peheader->SubSysVer=4;
  874.  
  875.         peheader->ImageBase=ImageBase;
  876.  
  877.         peheader->headsize=sizehead;
  878.  
  879.         peheader->imagesize=vsizeheader+        //размер заголовка
  880.  
  881.                                         vsize+  //размер кода
  882.  
  883.                                                                                         sizebss+                //размер post блока
  884.  
  885.                                                                                         sizeReloc+      //размер таблицы перемещения
  886.  
  887.                                                                                         sizeImport+//размер таблицы импорта
  888.  
  889.                                                                                         sizeRes+        //размер таблицы ресурсов
  890.  
  891.                                                                                         sizeExport;//размер таблицы экспорта
  892.  
  893.         peheader->SubSys=(short)(2+wconsole);   //GUIWIN
  894.  
  895.         peheader->stackRezSize=stacksize*0x10;
  896.  
  897.         peheader->stackComSize=stacksize;
  898.  
  899.         peheader->heapRezSize=0x10000;
  900.  
  901.         peheader->heapComSize=0x1000;//postsize;        //????
  902.  
  903.         peheader->numRVA=0x10;
  904.  
  905.         if(!usestub){
  906.  
  907.                 peheader->basedata=12;
  908.  
  909.                 peheader->pCOFF=0x40;
  910.  
  911.         }
  912.  
  913.         (objentry+codenum)->pOffset=sizehead;
  914.  
  915.         if(numapi){
  916.  
  917.                 if(!WinMonoBlock)(objentry+importnum)->pOffset=sizehead+psize;
  918.  
  919.                 peheader->importRVA=startsec;
  920.  
  921.                 peheader->importSize=startimportname;
  922.  
  923.         }
  924.  
  925.         if(numexport){
  926.  
  927.                 if(!WinMonoBlock)(objentry+exportnum)->pOffset=sizehead+psize+sizeimport;
  928.  
  929.                 peheader->exportRVA=startsece;
  930.  
  931.                 peheader->exportSize=startexportname;
  932.  
  933.         }
  934.  
  935.         if(numres){
  936.  
  937.                 if(!WinMonoBlock)(objentry+resnum)->pOffset=sizehead+psize+sizeimport+sizeexport;
  938.  
  939.                 peheader->resourRVA=startsecres;
  940.  
  941.                 peheader->resourSize=curposbuf;
  942.  
  943.         }
  944.  
  945.         if(posrel){
  946.  
  947.                 if(!WinMonoBlock)(objentry+relocnum)->pOffset=sizehead+psize+sizeimport+sizeexport+sizeres;
  948.  
  949.                 else if(dllflag)(objentry+relocnum)->pOffset=sizehead+psize;
  950.  
  951.                 peheader->fixupRVA=startsecr;
  952.  
  953.                 peheader->fixupSize=posrel;
  954.  
  955.         }
  956.  
  957.         if(fwrite(peheader,sizeof(PE_HEADER),1,hout)!=1){
  958.  
  959. errwrite:
  960.  
  961.                 ErrWrite();
  962.  
  963.                 fclose(hout);
  964.  
  965.                 hout=NULL;
  966.  
  967.                 return(-1);
  968.  
  969.         }
  970.  
  971.         if(fwrite(objentry,sizeof(OBJECT_ENTRY)*numobj,1,hout)!=1)goto errwrite;
  972.  
  973.         ChSize(sizehead);
  974.  
  975.         runfilesize=sizehead+psize;
  976.  
  977.         outputcodestart=ftell(hout);
  978.  
  979.         if(fwrite(output,outptr,1,hout)!=1)goto errwrite;       //блок кода
  980.  
  981.         if(!WinMonoBlock){
  982.  
  983.                 filingzerope=psize-outptr;
  984.  
  985.                 ChSize(runfilesize);
  986.  
  987.         }
  988.  
  989.         if(numapi){
  990.  
  991.                 if(fwrite(importblock,sizeimport,1,hout)!=1)goto errwrite;
  992.  
  993.                 free(importblock);
  994.  
  995.         }
  996.  
  997.         if(numexport){
  998.  
  999.                 if(fwrite(exportblock,sizeexport,1,hout)!=1)goto errwrite;
  1000.  
  1001.                 free(exportblock);
  1002.  
  1003.         }
  1004.  
  1005.         if(numres){
  1006.  
  1007.                 if(fwrite(resbuf,sizeres,1,hout)!=1)goto errwrite;
  1008.  
  1009.                 free(resbuf);
  1010.  
  1011.         }
  1012.  
  1013.         if(posrel){
  1014.  
  1015.                 if(WinMonoBlock&&dllflag)ChSize(runfilesize);
  1016.  
  1017.                 if(fwrite(relocblock,sizereloc,1,hout)!=1)goto errwrite;
  1018.  
  1019.                 free(relocblock);
  1020.  
  1021.         }
  1022.  
  1023.         if(WinMonoBlock){
  1024.  
  1025.                 if(dllflag)runfilesize+=sizereloc;
  1026.  
  1027.         }
  1028.  
  1029.         else runfilesize+=sizereloc+sizeimport+sizeexport+sizeres;
  1030.  
  1031.         ChSize(runfilesize);
  1032.  
  1033.         free(peheader);
  1034.  
  1035.         free(objentry);
  1036.  
  1037.         fclose(hout);
  1038.  
  1039.         hout=NULL;
  1040.  
  1041.         ImageBase+=vsizeheader+sizebss; //изм размер для листинга
  1042.  
  1043.         return 0;
  1044.  
  1045. }
  1046.  
  1047.  
  1048.  
  1049. void ChSize(long size)
  1050.  
  1051. {
  1052.  
  1053. char buf[256];
  1054.  
  1055. long delta,ssave;
  1056.  
  1057.         memset(buf,0,256);
  1058.  
  1059.         delta=size-ftell(hout);
  1060.  
  1061.         while(delta>0){
  1062.  
  1063.                 ssave=256;
  1064.  
  1065.                 if(delta<256)ssave=delta;
  1066.  
  1067.                 fwrite(buf,ssave,1,hout);
  1068.  
  1069.                 delta-=ssave;
  1070.  
  1071.         }
  1072.  
  1073. }
  1074.  
  1075.  
  1076.  
  1077. int AlignCD(char segm,int val)  //выравнять данные или код
  1078.  
  1079. {
  1080.  
  1081. unsigned int a;
  1082.  
  1083.         a=(segm==DS?outptrdata:outptr)%val;
  1084.  
  1085.         if(a==0)val=0;
  1086.  
  1087.         else val-=a;
  1088.  
  1089.         a=0;
  1090.  
  1091.         while(val!=0){
  1092.  
  1093.                 segm==DS?opd(aligner):op(0x90);
  1094.  
  1095.                 val--;
  1096.  
  1097.                 a++;
  1098.  
  1099.         }
  1100.  
  1101.         return a;
  1102.  
  1103. }
  1104.  
  1105.  
  1106.  
  1107. void CreatWinStub()
  1108.  
  1109. {
  1110.  
  1111.         if(!usestub){
  1112.  
  1113.                 sizestub=SIZESTUB2;
  1114.  
  1115.                 hout=CreateOutPut(outext,"wb");
  1116.  
  1117.                 if(fwrite(stub2,SIZESTUB2,1,hout)!=1){
  1118.  
  1119.                         ErrWrite();
  1120.  
  1121.                         return;
  1122.  
  1123.                 }
  1124.  
  1125.         }
  1126.  
  1127.         else CreatStub(winstub);
  1128.  
  1129. //подсчитать число секций
  1130.  
  1131.         if(wbss){
  1132.  
  1133.                 if(postsize)numrs++;
  1134.  
  1135.                 else wbss=FALSE;
  1136.  
  1137.         }
  1138.  
  1139.         if(WinMonoBlock==FALSE){        //если не единый блок
  1140.  
  1141.                 if(numapi)numrs++;      //есть вызовы api-процедур
  1142.  
  1143.                 if(numexport)numrs++;   //создать секцию импорта
  1144.  
  1145.                 if((FixUpTable==TRUE&&posts)/*||numexport!=0*/)numrs++; //создать секцию перемещения
  1146.  
  1147.                 if(numres)numrs++;      //ресурсы
  1148.  
  1149.         }
  1150.  
  1151.         else if(dllflag&&FixUpTable==TRUE&&posts!=0)numrs++;    //создать секцию перемещения
  1152.  
  1153. //размер загрузочного образа
  1154.  
  1155.         vsizeheader=Align(numrs*sizeof(OBJECT_ENTRY)+sizeof(PE_HEADER)+sizestub,0x1000);
  1156.  
  1157. }
  1158.  
  1159.  
  1160.  
  1161. void ImportName(char *name)
  1162.  
  1163. {
  1164.  
  1165. FILE *infile;
  1166.  
  1167. union{
  1168.  
  1169.         PE_HEADER pe;
  1170.  
  1171.         OBJECT_ENTRY obj;
  1172.  
  1173. };
  1174.  
  1175. unsigned long temp;
  1176.  
  1177. unsigned long ulexport; //секция с експортом
  1178.  
  1179. unsigned long numobj;   //число объектов
  1180.  
  1181. unsigned long posdll;   //позиция секции в файле
  1182.  
  1183. unsigned long nameadr;  //таблица адресов имен
  1184.  
  1185. unsigned long startname;        //начало имени
  1186.  
  1187. unsigned long ordinallist,ordinalbase;
  1188.  
  1189. unsigned int i,j;
  1190.  
  1191. DLLLIST *newdll;
  1192.  
  1193. APIPROC *listapi;
  1194.  
  1195.         if((infile=fopen(name,"rb"))==NULL){
  1196.  
  1197.                 ErrOpenFile(name);
  1198.  
  1199.                 return;
  1200.  
  1201.         }
  1202.  
  1203.         fseek(infile,0x3C,SEEK_SET);
  1204.  
  1205.         if(fread(&temp,4,1,infile)!=1){
  1206.  
  1207. errread:
  1208.  
  1209.                 //fprintf(stderr,"Unable to read from file %s.\n",name);
  1210.                 printf("Unable to read from file %s.\n",name);
  1211.                 fclose(infile);
  1212.  
  1213.                 return;
  1214.  
  1215.         }
  1216.  
  1217.         fseek(infile,0,SEEK_END);
  1218.  
  1219.         if((unsigned long)ftell(infile)<=temp){
  1220.  
  1221.                 //fprintf(stderr,"Bad file %s.\n",name);
  1222.                 printf("Bad file %s.\n",name);
  1223.                 fclose(infile);
  1224.  
  1225.                 return;
  1226.  
  1227.         }
  1228.  
  1229.         fseek(infile,temp,SEEK_SET);
  1230.  
  1231.         if(fread(&pe,sizeof(PE_HEADER),1,infile)!=1)goto errread;
  1232.  
  1233.         if(pe.sign!=
  1234.  
  1235. #ifdef _WC_
  1236.  
  1237.                         'EP'
  1238.  
  1239. #else
  1240.  
  1241.       'PE'
  1242.  
  1243. #endif
  1244.  
  1245.                                         ){
  1246.  
  1247.                 //fprintf(stderr,"For DLL support only format PE.\n");
  1248.                 printf("For DLL support only format PE.\n");
  1249.                
  1250.                 fclose(infile);
  1251.  
  1252.                 return;
  1253.  
  1254.         }
  1255.  
  1256.         if((ulexport=pe.exportRVA)==0){
  1257.  
  1258.                 //fprintf(stderr,"No export directory on %s.\n",name);
  1259.                 printf("No export directory on %s.\n",name);
  1260.                 fclose(infile);
  1261.  
  1262.                 return;
  1263.  
  1264.         }
  1265.  
  1266.         numobj=pe.numobj;
  1267.  
  1268.         temp=pe.objAlig;
  1269.  
  1270.         while(numobj!=0){
  1271.  
  1272.                 if(fread(&obj,sizeof(OBJECT_ENTRY),1,infile)!=1)goto errread;
  1273.  
  1274.                 if((obj.sectionRVA+Align(obj.psize,temp))>ulexport)break;
  1275.  
  1276.                 numobj--;
  1277.  
  1278.         }
  1279.  
  1280.         if(numobj==0){
  1281.  
  1282.                 //fprintf(stderr,"Bad object table in %s.\n",name);
  1283.                 printf("Bad object table in %s.\n",name);
  1284.                 fclose(infile);
  1285.  
  1286.                 return;
  1287.  
  1288.         }
  1289.  
  1290.         posdll=obj.pOffset+ulexport-obj.sectionRVA;
  1291.  
  1292.         fseek(infile,posdll+24,SEEK_SET);
  1293.  
  1294.         if(fread(&numobj,4,1,infile)!=1)goto errread;
  1295.  
  1296.         fseek(infile,posdll+32,SEEK_SET);
  1297.  
  1298.         if(fread(&nameadr,4,1,infile)!=1)goto errread;
  1299.  
  1300.         if(fread(&ordinallist,4,1,infile)!=1)goto errread;
  1301.  
  1302.         nameadr-=ulexport;
  1303.  
  1304.         ordinallist-=ulexport;
  1305.  
  1306.         fseek(infile,posdll+12,SEEK_SET);
  1307.  
  1308.         if(fread(&startname,4,1,infile)!=1)goto errread;
  1309.  
  1310.         if(fread(&ordinalbase,4,1,infile)!=1)goto errread;
  1311.  
  1312.         fseek(infile,posdll+startname-ulexport,SEEK_SET);
  1313.  
  1314.         j=0;
  1315.  
  1316.         do{
  1317.  
  1318.                 if(fread(&string[j],1,1,infile)!=1)goto errread;
  1319.  
  1320.         }while(string[j++]!=0); //имя библиотеки
  1321.  
  1322.         newdll=FindDLL();
  1323.  
  1324.         listapi=newdll->list;
  1325.  
  1326.  
  1327.  
  1328.         for(i=0;i<numobj;i++){
  1329.  
  1330.                 fseek(infile,posdll+nameadr,SEEK_SET);
  1331.  
  1332.                 if(fread(&startname,4,1,infile)!=1)goto errread;
  1333.  
  1334.                 fseek(infile,posdll+startname-ulexport,SEEK_SET);
  1335.  
  1336.                 itok.size=-1;
  1337.  
  1338.                 j=0;
  1339.  
  1340.                 unsigned char c;
  1341.  
  1342.                 do{
  1343.  
  1344.                         if(fread(&c,1,1,infile)!=1)goto errread;
  1345.  
  1346.                         if(c=='@'){
  1347.  
  1348.                                 itok.name[j]=0;
  1349.  
  1350.                                 break;
  1351.  
  1352.                         }
  1353.  
  1354.                         itok.name[j]=c;
  1355.  
  1356.                         j++;
  1357.  
  1358.                 }while(j<=IDLENGTH&&c!=0);
  1359.  
  1360.                 if(c=='@'){
  1361.  
  1362.                         j=0;
  1363.  
  1364.                         do{
  1365.  
  1366.                                 if(fread(&c,1,1,infile)!=1)goto errread;
  1367.  
  1368.                                 string[j++]=c;
  1369.  
  1370.                         }while(isdigit(c));
  1371.  
  1372.                         itok.size=getnumber(string);
  1373.  
  1374.                 }
  1375.  
  1376.                 tok=tk_id;
  1377.  
  1378.                 searchvar(itok.name);
  1379.  
  1380.                 if(tok==tk_id){
  1381.  
  1382.                         fseek(infile,posdll+ordinallist,SEEK_SET);
  1383.  
  1384.                         itok.sib=0;
  1385.  
  1386.                         if(fread(&itok.sib,2,1,infile)!=1)goto errread;
  1387.  
  1388.                         itok.sib+=ordinalbase;
  1389.  
  1390.                         tok=tk_apiproc;
  1391.  
  1392.                         itok.number=secondcallnum++;
  1393.  
  1394.                         itok.segm=NOT_DYNAMIC;
  1395.  
  1396.                         string[0]=0;
  1397.  
  1398.                         if(newdll->num==0)listapi=(APIPROC *)MALLOC(sizeof(APIPROC));   //первая в списке
  1399.  
  1400.                         else listapi=(APIPROC *)REALLOC(listapi,sizeof(APIPROC)*(newdll->num+1));
  1401.  
  1402.                         (listapi+newdll->num)->recapi=addtotree(itok.name);
  1403.  
  1404.                         newdll->num++;
  1405.  
  1406.                 }
  1407.  
  1408.                 nameadr+=4;
  1409.  
  1410.                 ordinallist+=2;
  1411.  
  1412.         }
  1413.  
  1414.         newdll->list=listapi;
  1415.  
  1416.         fclose(infile);
  1417.  
  1418. }
  1419.  
  1420.  
  1421.  
  1422. void CreatStub(char *name)
  1423.  
  1424. {
  1425.  
  1426.         sizestub=SIZESTUB;
  1427.  
  1428.         hout=CreateOutPut(outext,"wb");
  1429.  
  1430.         sprintf(&stub[STRVERS],"%s%s",compilerstr,__DATE__);
  1431.  
  1432.         if(name==NULL){
  1433.  
  1434. stdstub:
  1435.  
  1436.                 if(fwrite(stub,SIZESTUB,1,hout)!=1){
  1437.  
  1438. errwrite:
  1439.  
  1440.                         ErrWrite();
  1441.  
  1442.                         return;
  1443.  
  1444.                 }
  1445.  
  1446.         }
  1447.  
  1448.         else{
  1449.  
  1450. EXE_DOS_HEADER exeheader;  // header for EXE format
  1451.  
  1452. FILE *stubin;
  1453.  
  1454.                 if((stubin=fopen(name,"rb"))==NULL){
  1455.  
  1456.                         ErrOpenFile(name);
  1457.  
  1458.                         goto stdstub;
  1459.  
  1460.                 }
  1461.  
  1462.                 if(fread(&exeheader,sizeof(EXE_DOS_HEADER),1,stubin)!=1){
  1463.  
  1464. errread:
  1465.  
  1466.                         ErrReadStub();
  1467.  
  1468.                         fclose(stubin);
  1469.  
  1470.                         goto stdstub;
  1471.  
  1472.                 }
  1473.  
  1474.                 if(exeheader.sign!=0x5A4D){
  1475.  
  1476. errstub:
  1477.  
  1478.                         //fprintf(stderr,"File %s can not be stub file.\n",name);
  1479.                         printf("File %s can not be stub file.\n",name);
  1480.                         fclose(stubin);
  1481.  
  1482.                         goto stdstub;
  1483.  
  1484.                 }
  1485.  
  1486.                 fseek(stubin,0,SEEK_END);
  1487.  
  1488.                 sizestub=ftell(stubin);
  1489.  
  1490.                 unsigned long temp;
  1491.  
  1492.                 if(exeheader.ofsreloc>=0x40){   //проверка что это не 32-битный файл
  1493.  
  1494.                         fseek(stubin,0x3c,SEEK_SET);
  1495.  
  1496.                         if(fread(&temp,4,1,stubin)!=1)goto errread;
  1497.  
  1498.                         if(temp<sizestub){
  1499.  
  1500.                                 fseek(stubin,temp,SEEK_SET);
  1501.  
  1502.                                 if(fread(&temp,4,1,stubin)!=1)goto errread;
  1503.  
  1504.                                 switch(temp){
  1505.  
  1506. #ifdef _WC_
  1507.  
  1508.                                         case 'EP':
  1509.  
  1510.                                         case 'EN':
  1511.  
  1512.                                         case 'EL':
  1513.  
  1514.                                         case 'XL':
  1515.  
  1516. #else
  1517.  
  1518.                                         case 'PE':
  1519.  
  1520.                                         case 'NE':
  1521.  
  1522.                                         case 'LE':
  1523.  
  1524.                                         case 'LX':
  1525.  
  1526. #endif
  1527.  
  1528.                                                 goto errstub;
  1529.  
  1530.                                 }
  1531.  
  1532.                         }
  1533.  
  1534.                         exeheader.ofsreloc+=(unsigned short)0x20;
  1535.  
  1536.                 }
  1537.  
  1538.                 else exeheader.ofsreloc=0x40;
  1539.  
  1540.                 //размер файла
  1541.  
  1542.                 sizestub=Align(sizestub+32,8);
  1543.  
  1544.                 fseek(stubin,0x20,SEEK_SET);
  1545.  
  1546.                 exeheader.headsize+=(unsigned short)2;
  1547.  
  1548.                 if(fwrite(&exeheader,sizeof(EXE_DOS_HEADER),1,hout)!=1)goto errwrite;
  1549.  
  1550.                 *(unsigned long *)&stub[STRVERS+28]=sizestub;
  1551.  
  1552.                 if(fwrite(&stub[STRVERS],32,1,hout)!=1)goto errwrite;
  1553.  
  1554.                 CopyFile(stubin,hout);
  1555.  
  1556.                 ChSize(sizestub);
  1557.  
  1558.         }
  1559.  
  1560. }
  1561.  
  1562.  
  1563.  
  1564. #define MAXLISTNAME 1024
  1565.  
  1566. #define MAXNUMSYMBOL 128
  1567.  
  1568. #define MAXSIZESYMBOL MAXNUMSYMBOL*sizeof(IMAGE_SYMBOL)
  1569.  
  1570. #define MAXNUMRELOC 256
  1571.  
  1572.  
  1573.  
  1574. char *ListName;
  1575.  
  1576. unsigned long sizelistName,maxsizelistname,textnum,bssnum;
  1577.  
  1578. IMAGE_SYMBOL *isymbol;
  1579.  
  1580. unsigned long numsymbol,maxnumsymbol,maxnumnameid,maxnumreloc,numreloc;
  1581.  
  1582. int segtext,segbss;
  1583.  
  1584. extern int numextern;
  1585.  
  1586. IMAGE_RELOCATION *treloc;
  1587.  
  1588.  
  1589.  
  1590. struct NAMEID{
  1591.  
  1592.         int num;
  1593.  
  1594.         int id;
  1595.  
  1596. }*NameId;
  1597.  
  1598.  
  1599.  
  1600. #define MAXSIZENAMEID MAXNUMSYMBOL*sizeof(NAMEID)
  1601.  
  1602.  
  1603.  
  1604. void AddName(char *name,unsigned long size)
  1605.  
  1606. {
  1607.  
  1608.         if(sizelistName+size+1>=maxsizelistname){
  1609.  
  1610.                 maxsizelistname+=MAXLISTNAME;
  1611.  
  1612.                 ListName=(char *)REALLOC(ListName,maxsizelistname);
  1613.  
  1614.         }
  1615.  
  1616.         strcpy(ListName+sizelistName,name);
  1617.  
  1618.         sizelistName+=size+1;
  1619.  
  1620. }
  1621.  
  1622.  
  1623.  
  1624. void CreatSymbolTable(idrec *ptr)
  1625.  
  1626. {
  1627.  
  1628. unsigned int i;
  1629.  
  1630.         if(ptr!=NULL){
  1631.  
  1632.                 CreatSymbolTable(ptr->right);
  1633.  
  1634.                 if(ptr->rectok==tk_apiproc){
  1635.  
  1636.                         for(unsigned int j=0;j<posts;j++){      //поиск использования процедуры
  1637.  
  1638.                                 if((postbuf+j)->num==(unsigned long)ptr->recnumber&&((postbuf+j)->type==CALL_32I||(postbuf+j)->type==CALL_32)){
  1639.  
  1640.                                         goto nameext;
  1641.  
  1642.                                 }
  1643.  
  1644.                         }
  1645.  
  1646.                 }
  1647.  
  1648.                 else if((externnum!=0&&ptr->rectok==tk_undefproc&&(ptr->flag&f_extern)!=0)||
  1649.  
  1650.                                 ((ptr->rectok==tk_proc||ptr->rectok==tk_interruptproc)&&ptr->recsegm>=NOT_DYNAMIC)||
  1651.  
  1652.                                 ((ptr->rectok>=tk_bits&&ptr->rectok<=tk_doublevar)||ptr->rectok==tk_structvar)){
  1653.  
  1654. nameext:
  1655.  
  1656.                         if(numsymbol+1>=maxnumsymbol){
  1657.  
  1658.                                 maxnumsymbol+=MAXNUMSYMBOL;
  1659.  
  1660.                                 isymbol=(IMAGE_SYMBOL *)REALLOC(isymbol,maxnumsymbol*sizeof(IMAGE_SYMBOL));
  1661.  
  1662.                                 memset(isymbol+maxnumsymbol*sizeof(IMAGE_SYMBOL)-MAXSIZESYMBOL,0,MAXSIZESYMBOL);        //очистить ее
  1663.  
  1664.                         }
  1665.  
  1666.                         if(ptr->rectok==tk_apiproc||ptr->rectok==tk_undefproc||
  1667.  
  1668.                                         ptr->rectok==tk_proc||ptr->rectok==tk_interruptproc)(isymbol+numsymbol)->Type=32;
  1669.  
  1670.                         i=strlen(ptr->recid);
  1671.  
  1672.                         if(i>8){
  1673.  
  1674.                                 (isymbol+numsymbol)->N.Name.Short=0;
  1675.  
  1676.                                 (isymbol+numsymbol)->N.Name.Long=sizelistName+4;
  1677.  
  1678.                                 AddName(ptr->recid,i);
  1679.  
  1680.                         }
  1681.  
  1682.                         else strncpy((isymbol+numsymbol)->N.sname,ptr->recid,i);
  1683.  
  1684.                         if(ptr->rectok!=tk_apiproc&&ptr->rectok!=tk_undefproc&&(ptr->flag&f_extern)==0){
  1685.  
  1686.                                 (isymbol+numsymbol)->Value=ptr->recnumber;
  1687.  
  1688.                                 if(ptr->rectok==tk_proc||ptr->rectok==tk_interruptproc)(isymbol+numsymbol)->SectionNumber=(short)(textnum+1);
  1689.  
  1690.                                 else (isymbol+numsymbol)->SectionNumber=(short)((ptr->recpost==0?textnum:bssnum)+1);
  1691.  
  1692.                         }
  1693.  
  1694.                         else{
  1695.  
  1696.                                 (NameId+numextern)->num=ptr->recnumber;
  1697.  
  1698.                                 (NameId+numextern)->id=numsymbol;
  1699.  
  1700.                                 numextern++;
  1701.  
  1702.                                 if(numextern>=maxnumnameid){
  1703.  
  1704.                                         maxnumnameid+=MAXNUMSYMBOL;
  1705.  
  1706.                                         NameId=(NAMEID *)REALLOC(NameId,maxnumnameid*sizeof(NAMEID));
  1707.  
  1708.                                 }
  1709.  
  1710.                         }
  1711.  
  1712.                         (isymbol+numsymbol)->StorageClass=2;
  1713.  
  1714.                         numsymbol++;
  1715.  
  1716.                 }
  1717.  
  1718.                 CreatSymbolTable(ptr->left);
  1719.  
  1720.         }
  1721.  
  1722. }
  1723.  
  1724.  
  1725.  
  1726. void FreeCoffBuf()
  1727.  
  1728. {
  1729.  
  1730.         free(ListName);
  1731.  
  1732.         free(isymbol);
  1733.  
  1734.         free(NameId);
  1735.  
  1736.         free(treloc);
  1737.  
  1738.         fclose(hout);
  1739.  
  1740.         hout=NULL;
  1741.  
  1742. }
  1743.  
  1744.  
  1745.  
  1746. void IncReloc()
  1747.  
  1748. {
  1749.  
  1750.         numreloc++;
  1751.  
  1752.         if(numreloc>=maxnumreloc){
  1753.  
  1754.                 maxnumreloc+=MAXNUMRELOC;
  1755.  
  1756.                 treloc=(IMAGE_RELOCATION *)REALLOC(treloc,maxnumreloc*sizeof(IMAGE_RELOCATION));
  1757.  
  1758.         }
  1759.  
  1760. }
  1761.  
  1762.  
  1763.  
  1764. void CreatRelocTable()
  1765.  
  1766. {
  1767.  
  1768.         for(int j=0;j<posts;j++){
  1769.  
  1770.                 (treloc+numreloc)->VirtualAddress=(postbuf+j)->loc-startptr;
  1771.  
  1772.                 if((postbuf+j)->type>=CALL_32I&&(postbuf+j)->type<=FIX_CODE32){
  1773.  
  1774.                         switch((postbuf+j)->type){
  1775.  
  1776.                                 case POST_VAR:
  1777.  
  1778.                                 case POST_VAR32:
  1779.  
  1780.                                         (treloc+numreloc)->Type=IMAGE_REL_I386_DIR32;
  1781.  
  1782.                                         (treloc+numreloc)->SymbolTableIndex=segbss;
  1783.  
  1784.                                         break;
  1785.  
  1786.                                 case FIX_VAR:
  1787.  
  1788.                                 case FIX_VAR32:
  1789.  
  1790.                                 case FIX_CODE:
  1791.  
  1792.                                 case FIX_CODE32:
  1793.  
  1794.                                         (treloc+numreloc)->Type=IMAGE_REL_I386_DIR32;
  1795.  
  1796.                                         (treloc+numreloc)->SymbolTableIndex=segtext;
  1797.  
  1798.                                         break;
  1799.  
  1800.                         }
  1801.  
  1802.                         IncReloc();
  1803.  
  1804.                 }
  1805.  
  1806.                 else{
  1807.  
  1808.                         for(int i=0;i<numextern;i++){
  1809.  
  1810.                                 if((NameId+i)->num==(postbuf+j)->num){
  1811.  
  1812.                                         if((postbuf+j)->type==EXT_VAR)(treloc+numreloc)->Type=IMAGE_REL_I386_DIR32;
  1813.  
  1814.                                         else (treloc+numreloc)->Type=IMAGE_REL_I386_REL32;
  1815.  
  1816.                                         (treloc+numreloc)->SymbolTableIndex=(NameId+i)->id;
  1817.  
  1818.                                         IncReloc();
  1819.  
  1820.                                         break;
  1821.  
  1822.                                 }
  1823.  
  1824.                         }
  1825.  
  1826.                 }
  1827.  
  1828.  
  1829.  
  1830.         }
  1831.  
  1832. }
  1833.  
  1834.  
  1835.  
  1836. int MakeCoff()
  1837.  
  1838. {
  1839.  
  1840. COFF_HEADER chead;
  1841.  
  1842. unsigned long sizehead,curobj,resnum,numresrel,segres,lastoffset,headernum;
  1843.  
  1844. OBJECT_ENTRY *objentry;
  1845.  
  1846. int i;
  1847.  
  1848. LISTRELOC *resrel=NULL;
  1849.  
  1850. char *codesecname;
  1851.  
  1852.         hout=CreateOutPut("obj","wb");
  1853.  
  1854.         chead.cpu=0x14c;
  1855.  
  1856.         chead.SizeOfOptionalHeader=0;
  1857.  
  1858.         chead.date_time=0;
  1859.  
  1860.         chead.Characteristics=0x100;
  1861.  
  1862.         /*if(header)*/numrs=2;
  1863.  
  1864. //подсчитать число секций
  1865.  
  1866.         if(wbss){
  1867.  
  1868.                 if(postsize)numrs++;
  1869.  
  1870.                 else wbss=FALSE;
  1871.  
  1872.         }
  1873.  
  1874.         if(numres)numrs++;      //ресурсы
  1875.  
  1876.         chead.numobj=numrs;
  1877.  
  1878.         sizehead=numrs*sizeof(OBJECT_ENTRY);
  1879.  
  1880.         objentry=(OBJECT_ENTRY *)MALLOC(sizehead);//тавлица объектов
  1881.  
  1882.         memset(objentry,0,sizehead);//очистить таблицу объектов
  1883.  
  1884.         curobj=0;
  1885.  
  1886.         lastoffset=sizehead+sizeof(COFF_HEADER);
  1887.  
  1888. //      if(header){
  1889.  
  1890.                 strcpy((objentry+curobj)->name,".version");
  1891.  
  1892.                 sprintf(&stub[STRVERS],"%s%s",compilerstr,__DATE__);
  1893.  
  1894.                 (objentry+curobj)->psize=strlen(&stub[STRVERS])+1;
  1895.  
  1896.                 (objentry+curobj)->pOffset=lastoffset;
  1897.  
  1898.                 (objentry+curobj)->flags=0x100A00;
  1899.  
  1900.                 headernum=curobj;
  1901.  
  1902.                 lastoffset+=(objentry+curobj)->psize;
  1903.  
  1904.                 curobj++;
  1905.  
  1906. //      }
  1907.  
  1908.         codesecname=".text";
  1909.  
  1910.         if(splitdata==FALSE)codesecname=".codedat";
  1911.  
  1912.         strcpy((objentry+curobj)->name,codesecname);
  1913.  
  1914.         (objentry+curobj)->psize=outptr;
  1915.  
  1916.         (objentry+curobj)->pOffset=lastoffset;
  1917.  
  1918.         (objentry+curobj)->flags=0xE0300060;
  1919.  
  1920.         lastoffset+=outptr;
  1921.  
  1922.         textnum=curobj;
  1923.  
  1924.         curobj++;
  1925.  
  1926.         if(wbss){
  1927.  
  1928.                 strcpy((objentry+curobj)->name,".bss");
  1929.  
  1930.                 (objentry+curobj)->psize=postsize;
  1931.  
  1932.                 (objentry+curobj)->flags=0xC0300080;
  1933.  
  1934.                 bssnum=curobj;
  1935.  
  1936.                 curobj++;
  1937.  
  1938.         }
  1939.  
  1940.         if(numres){
  1941.  
  1942.                 strcpy((objentry+curobj)->name,".rsrc$01");
  1943.  
  1944.                 numresrel=(objentry+curobj)->NumberOfRelocations=MakeRes(0,&resrel);
  1945.  
  1946.                 (objentry+curobj)->psize=curposbuf;
  1947.  
  1948.                 (objentry+curobj)->flags=0x40000040;
  1949.  
  1950.                 resnum=curobj;
  1951.  
  1952.         }
  1953.  
  1954.         sizelistName=0;numsymbol=0;
  1955.  
  1956.         ListName=(char *)MALLOC(MAXLISTNAME);
  1957.  
  1958.         isymbol=(IMAGE_SYMBOL *)MALLOC(MAXSIZESYMBOL);
  1959.  
  1960.         memset(isymbol,0,MAXSIZESYMBOL);        //очистить ее
  1961.  
  1962.         maxsizelistname=MAXLISTNAME;
  1963.  
  1964.         maxnumnameid=maxnumsymbol=MAXNUMSYMBOL;
  1965.  
  1966.         NameId=(NAMEID *)MALLOC(MAXSIZENAMEID);
  1967.  
  1968.         treloc=(IMAGE_RELOCATION *)MALLOC(sizeof(IMAGE_RELOCATION)*MAXNUMRELOC);
  1969.  
  1970.         maxnumreloc=MAXNUMRELOC;
  1971.  
  1972.         numreloc=0;
  1973.  
  1974.         strcpy(isymbol->N.sname,"@comp.id");
  1975.  
  1976.         isymbol->Value=0x141F8E;
  1977.  
  1978.         isymbol->SectionNumber=-1;
  1979.  
  1980.         isymbol->StorageClass=3;
  1981.  
  1982.         strcpy((isymbol+1)->N.sname,".file");
  1983.  
  1984.         (isymbol+1)->Value=1;
  1985.  
  1986.         (isymbol+1)->SectionNumber=-2;
  1987.  
  1988.         (isymbol+1)->StorageClass=0x67;
  1989.  
  1990.         i=(strlen(startfileinfo->filename)-1)/sizeof(IMAGE_SYMBOL)+1;
  1991.  
  1992.         (isymbol+1)->NumberOfAuxSymbols=i;
  1993.  
  1994.         strcpy((isymbol+2)->N.sname,startfileinfo->filename);
  1995.  
  1996.         numsymbol=i+2;
  1997.  
  1998.         segtext=numsymbol;
  1999.  
  2000.         strcpy((isymbol+numsymbol)->N.sname,codesecname);
  2001.  
  2002.         (isymbol+numsymbol)->SectionNumber=textnum+1;
  2003.  
  2004.         (isymbol+numsymbol)->StorageClass=3;
  2005.  
  2006.         (isymbol+numsymbol)->NumberOfAuxSymbols=1;
  2007.  
  2008.         numsymbol++;
  2009.  
  2010.         (isymbol+numsymbol)->N.Name.Short=outptr;
  2011.  
  2012.         numsymbol++;
  2013.  
  2014.         if(wbss){
  2015.  
  2016.                 segbss=numsymbol;
  2017.  
  2018.                 strcpy((isymbol+numsymbol)->N.sname,".bss");
  2019.  
  2020.                 (isymbol+numsymbol)->SectionNumber=bssnum+1;
  2021.  
  2022.                 (isymbol+numsymbol)->StorageClass=3;
  2023.  
  2024.                 (isymbol+numsymbol)->NumberOfAuxSymbols=1;
  2025.  
  2026.                 numsymbol++;
  2027.  
  2028.                 (isymbol+numsymbol)->N.Name.Short=postsize;
  2029.  
  2030.                 numsymbol++;
  2031.  
  2032.                 strcpy((isymbol+numsymbol)->N.sname,"DGROUP");
  2033.  
  2034.                 (isymbol+numsymbol)->SectionNumber=bssnum+1;
  2035.  
  2036.                 (isymbol+numsymbol)->StorageClass=3;
  2037.  
  2038.         }
  2039.  
  2040.         strcpy((isymbol+numsymbol)->N.sname,"FLAT");
  2041.  
  2042.         (isymbol+numsymbol)->SectionNumber=-1;
  2043.  
  2044.         (isymbol+numsymbol)->StorageClass=3;
  2045.  
  2046.         numsymbol++;
  2047.  
  2048.         if(numres){
  2049.  
  2050.                 segres=numsymbol;
  2051.  
  2052.                 strcpy((isymbol+numsymbol)->N.sname,".rsrc$01");
  2053.  
  2054.                 (isymbol+numsymbol)->StorageClass=3;
  2055.  
  2056.                 (isymbol+numsymbol)->SectionNumber=resnum+1;
  2057.  
  2058.                 numsymbol++;
  2059.  
  2060.         }
  2061.  
  2062. //      if(header){
  2063.  
  2064.                 strcpy((isymbol+numsymbol)->N.sname,".version");
  2065.  
  2066.                 (isymbol+numsymbol)->SectionNumber=headernum+1;
  2067.  
  2068.                 (isymbol+numsymbol)->StorageClass=3;
  2069.  
  2070.                 numsymbol++;
  2071.  
  2072. //      }
  2073.  
  2074.         CreatSymbolTable(treestart);
  2075.  
  2076.         CreatRelocTable();
  2077.  
  2078.         (isymbol+segtext+1)->N.Name.Long=numreloc;
  2079.  
  2080.         (objentry+textnum)->NumberOfRelocations=numreloc;
  2081.  
  2082.         if(numreloc){
  2083.  
  2084.                 (objentry+textnum)->PointerToRelocations=lastoffset;
  2085.  
  2086.                 lastoffset+=sizeof(IMAGE_RELOCATION)*numreloc;
  2087.  
  2088.         }
  2089.  
  2090.         if(numres){
  2091.  
  2092.                 (objentry+resnum)->pOffset=lastoffset;
  2093.  
  2094.                 lastoffset+=curposbuf;
  2095.  
  2096.                 if(numresrel){
  2097.  
  2098.                         (objentry+resnum)->PointerToRelocations=lastoffset;
  2099.  
  2100.                         lastoffset+=sizeof(IMAGE_RELOCATION)*numresrel;
  2101.  
  2102.                 }
  2103.  
  2104.         }
  2105.  
  2106.         chead.COFFsize=numsymbol;
  2107.  
  2108.         if(numsymbol){
  2109.  
  2110.                 chead.pCOFF=lastoffset;
  2111.  
  2112.         }
  2113.  
  2114.         if(fwrite(&chead,sizeof(COFF_HEADER),1,hout)!=1){
  2115.  
  2116. errwrite:
  2117.  
  2118.                 ErrWrite();
  2119.  
  2120.                 free(objentry);
  2121.  
  2122.                 if(resrel)free(resrel);
  2123.  
  2124.                 FreeCoffBuf();
  2125.  
  2126.                 return(-1);
  2127.  
  2128.         }
  2129.  
  2130.         if(fwrite(objentry,sizehead,1,hout)!=1)goto errwrite;
  2131.  
  2132. //      if(header){
  2133.  
  2134.                 if(fwrite(&stub[STRVERS],(objentry+headernum)->psize,1,hout)!=1)goto errwrite;
  2135.  
  2136. //      }
  2137.  
  2138.         if(fwrite(output,outptr,1,hout)!=1)goto errwrite;       //блок кода
  2139.  
  2140.         if(numreloc){
  2141.  
  2142.                 if(fwrite(treloc,numreloc*sizeof(IMAGE_RELOCATION),1,hout)!=1)goto errwrite;
  2143.  
  2144.         }
  2145.  
  2146.         if(numres){
  2147.  
  2148.                 if(fwrite(resbuf,curposbuf,1,hout)!=1)goto errwrite;
  2149.  
  2150.                 free(resbuf);
  2151.  
  2152.                 if(numresrel){
  2153.  
  2154.                         IMAGE_RELOCATION *rrel;
  2155.  
  2156.                         rrel=(IMAGE_RELOCATION *)MALLOC(sizeof(IMAGE_RELOCATION)*numresrel);
  2157.  
  2158.                         for(i=0;i<numresrel;i++){
  2159.  
  2160.                                 (rrel+i)->VirtualAddress=(resrel+i)->val;
  2161.  
  2162.                                 (rrel+i)->Type=IMAGE_REL_I386_DIR32NB;
  2163.  
  2164.                                 (rrel+i)->SymbolTableIndex=segres;
  2165.  
  2166.                         }
  2167.  
  2168.                         if(fwrite(rrel,sizeof(IMAGE_RELOCATION)*numresrel,1,hout)!=1)goto errwrite;
  2169.  
  2170.                         free(rrel);
  2171.  
  2172.                 }
  2173.  
  2174.         }
  2175.  
  2176.         if(numsymbol){
  2177.  
  2178.                 if(fwrite(isymbol,numsymbol*sizeof(IMAGE_SYMBOL),1,hout)!=1)goto errwrite;
  2179.  
  2180.                 if(sizelistName){
  2181.  
  2182.                         sizelistName+=4;
  2183.  
  2184.                         if(fwrite(&sizelistName,4,1,hout)!=1)goto errwrite;
  2185.  
  2186.                         if(fwrite(ListName,sizelistName-4,1,hout)!=1)goto errwrite;
  2187.  
  2188.                 }
  2189.  
  2190.                 else{
  2191.  
  2192.                         if(fwrite(&sizelistName,4,1,hout)!=1)goto errwrite;
  2193.  
  2194.                         sizelistName+=4;
  2195.  
  2196.                 }
  2197.  
  2198.         }
  2199.  
  2200.         runfilesize=lastoffset+sizelistName;
  2201.  
  2202.         free(objentry);
  2203.  
  2204.         if(resrel)free(resrel);
  2205.  
  2206.         FreeCoffBuf();
  2207.  
  2208.         return 0;
  2209.  
  2210. }
  2211.  
  2212.