Merge pull request #24002 from sandreenko/fixDesktopFailure
[platform/upstream/coreclr.git] / src / ilasm / writer.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 //
5 // writer.cpp
6 //
7
8 #include "ilasmpch.h"
9
10 #include "assembler.h"
11
12 #include "ceefilegenwriter.h"
13
14 #ifndef _MSC_VER
15 //cloned definition from ntimage.h that is removed for non MSVC builds
16 typedef VOID
17 (NTAPI *PIMAGE_TLS_CALLBACK) (
18     PVOID DllHandle,
19     ULONG Reason,
20     PVOID Reserved
21     );
22 #endif //_MSC_VER
23
24
25 HRESULT Assembler::InitMetaData()
26 {
27     HRESULT             hr = E_FAIL;
28
29     if(m_fInitialisedMetaData) return S_OK;
30
31     if(bClock) bClock->cMDInitBegin = GetTickCount();
32
33     hr = metaDataGetDispenser(CLSID_CorMetaDataDispenser,
34         IID_IMetaDataDispenserEx, (void **)&m_pDisp);
35     if (FAILED(hr))
36         goto exit;
37
38     if(m_wzMetadataVersion)
39     {
40         VARIANT encOption;
41         BSTR    bstr;
42         V_VT(&encOption) = VT_BSTR;
43         V_BSTR(&encOption) = bstr = ::SysAllocString(m_wzMetadataVersion);
44         hr = m_pDisp->SetOption(MetaDataRuntimeVersion, &encOption);
45         ::SysFreeString(bstr);
46     }
47     hr = m_pDisp->DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataEmit2,
48                         (IUnknown **)&m_pEmitter);
49     if (FAILED(hr))
50         goto exit;
51
52     m_pManifest->SetEmitter(m_pEmitter);
53     if(FAILED(hr = m_pEmitter->QueryInterface(IID_IMetaDataImport2, (void**)&m_pImporter)))
54         goto exit;
55
56
57     //m_Parser = new AsmParse(m_pEmitter);
58     m_fInitialisedMetaData = TRUE;
59
60     hr = S_OK;
61
62 exit:
63     if(bClock) bClock->cMDInitEnd = GetTickCount();
64     return hr;
65 }
66 /*********************************************************************************/
67 /* if we have any Thread local store data, make the TLS directory record for it */
68
69 HRESULT Assembler::CreateTLSDirectory() {
70
71     ULONG tlsEnd;
72     HRESULT hr;
73     if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pTLSSection, &tlsEnd))) return(hr);
74
75     if (tlsEnd == 0)        // No TLS data, we are done
76         return(S_OK);
77
78         // place to put the TLS directory
79     HCEESECTION tlsDirSec = m_pGlobalDataSection;
80
81     if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE32)
82     {
83         DWORD sizeofptr = (DWORD)sizeof(DWORD);
84         DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY32);
85         DWORD offsetofStartAddressOfRawData  = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, StartAddressOfRawData);
86         DWORD offsetofEndAddressOfRawData    = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, EndAddressOfRawData);
87         DWORD offsetofAddressOfIndex         = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfIndex);
88         DWORD offsetofAddressOfCallBacks     = (DWORD)offsetof(IMAGE_TLS_DIRECTORY32, AddressOfCallBacks);
89
90             // Get memory for for the TLS directory block,as well as a spot for callback chain
91         IMAGE_TLS_DIRECTORY32* tlsDir;
92         if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr);
93         DWORD* callBackChain = (DWORD*) &tlsDir[1];
94         *callBackChain = 0;
95     
96             // Find out where the tls directory will end up
97         ULONG tlsDirOffset;
98         if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr);
99         tlsDirOffset -= (sizeofdir + sizeofptr);
100     
101             // Set the start of the TLS data (offset 0 of hte TLS section)
102         tlsDir->StartAddressOfRawData = 0;
103         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
104     
105             // Set the end of the TLS data
106         tlsDir->EndAddressOfRawData = VALPTR(tlsEnd);
107         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
108     
109             // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?)
110         DWORD* tlsIndex;
111         if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr);
112         *tlsIndex = 0xCCCCCCCC;     // Does't really matter, the OS will fill it in
113     
114             // Find out where tlsIndex index is
115         ULONG tlsIndexOffset;
116         if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr);
117         tlsIndexOffset -= sizeof(DWORD);
118     
119             // Set the address of the TLS index
120         tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset);
121         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr);
122     
123             // Set addres of callbacks chain
124         tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir));
125         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr);
126         
127             // Set the other fields.
128         tlsDir->SizeOfZeroFill = 0;
129         tlsDir->Characteristics = 0;
130     
131         hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS,
132             sizeofdir, tlsDirOffset);
133
134         if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
135             COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
136     }
137     else
138     {
139         DWORD sizeofptr = (DWORD)sizeof(__int64);
140         DWORD sizeofdir = (DWORD)sizeof(IMAGE_TLS_DIRECTORY64);
141         DWORD offsetofStartAddressOfRawData  = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, StartAddressOfRawData);
142         DWORD offsetofEndAddressOfRawData    = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, EndAddressOfRawData);
143         DWORD offsetofAddressOfIndex         = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfIndex);
144         DWORD offsetofAddressOfCallBacks     = (DWORD)offsetof(IMAGE_TLS_DIRECTORY64, AddressOfCallBacks);
145
146             // Get memory for for the TLS directory block,as well as a spot for callback chain
147         IMAGE_TLS_DIRECTORY64* tlsDir;
148         if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(tlsDirSec, sizeofdir + sizeofptr, sizeofptr, (void**) &tlsDir))) return(hr);
149         __int64* callBackChain = (__int64*) &tlsDir[1];
150         *callBackChain = 0;
151     
152             // Find out where the tls directory will end up
153         ULONG tlsDirOffset;
154         if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsDirOffset))) return(hr);
155         tlsDirOffset -= (sizeofdir + sizeofptr);
156     
157             // Set the start of the TLS data (offset 0 of hte TLS section)
158         tlsDir->StartAddressOfRawData = 0;
159         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofStartAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
160     
161             // Set the end of the TLS data
162         tlsDir->EndAddressOfRawData = VALPTR(tlsEnd);
163         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofEndAddressOfRawData, m_pTLSSection, srRelocHighLow))) return(hr);
164     
165             // Allocate space for the OS to put the TLS index for this PE file (needs to be Read/Write?)
166         DWORD* tlsIndex;
167         if(FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pGlobalDataSection, sizeof(DWORD), sizeof(DWORD), (void**) &tlsIndex))) return(hr);
168         *tlsIndex = 0xCCCCCCCC;     // Does't really matter, the OS will fill it in
169     
170             // Find out where tlsIndex index is
171         ULONG tlsIndexOffset;
172         if(FAILED(hr=m_pCeeFileGen->GetSectionDataLen(tlsDirSec, &tlsIndexOffset))) return(hr);
173         tlsIndexOffset -= sizeof(DWORD);
174     
175             // Set the address of the TLS index
176         tlsDir->AddressOfIndex = VALPTR(tlsIndexOffset);
177         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfIndex, m_pGlobalDataSection, srRelocHighLow))) return(hr);
178     
179             // Set address of callbacks chain
180         tlsDir->AddressOfCallBacks = VALPTR((DWORD)(DWORD_PTR)(PIMAGE_TLS_CALLBACK*)(size_t)(tlsDirOffset + sizeofdir));
181         if(FAILED(hr=m_pCeeFileGen->AddSectionReloc(tlsDirSec, tlsDirOffset + offsetofAddressOfCallBacks, tlsDirSec, srRelocHighLow))) return(hr);
182         
183             // Set the other fields.
184         tlsDir->SizeOfZeroFill = 0;
185         tlsDir->Characteristics = 0;
186     
187         hr=m_pCeeFileGen->SetDirectoryEntry (m_pCeeFile, tlsDirSec, IMAGE_DIRECTORY_ENTRY_TLS,
188             sizeofdir, tlsDirOffset);
189     }
190
191     if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
192     {
193         report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
194     }
195     m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
196
197     return(hr);
198 }
199
200 HRESULT Assembler::CreateDebugDirectory()
201 {
202     HRESULT hr = S_OK;
203     HCEESECTION sec = m_pILSection;
204     BYTE *de;
205     ULONG deOffset;
206
207     // Only emit this if we're also emitting debug info.
208     if (!(m_fGeneratePDB && m_pSymWriter))
209         return S_OK;
210
211     IMAGE_DEBUG_DIRECTORY  debugDirIDD;
212     struct Param
213     {
214     DWORD                  debugDirDataSize;
215         BYTE              *debugDirData;
216     } param;
217     param.debugDirData = NULL;
218
219     // Get the debug info from the symbol writer.
220     if (FAILED(hr=m_pSymWriter->GetDebugInfo(NULL, 0, &param.debugDirDataSize, NULL)))
221         return hr;
222
223     // Will there even be any?
224     if (param.debugDirDataSize == 0)
225         return S_OK;
226
227     // Make some room for the data.
228     PAL_TRY(Param *, pParam, &param) {
229         pParam->debugDirData = new BYTE[pParam->debugDirDataSize];
230     } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
231         hr = E_FAIL;
232     } PAL_ENDTRY
233
234     if(FAILED(hr)) return hr;
235     // Actually get the data now.
236     if (FAILED(hr = m_pSymWriter->GetDebugInfo(&debugDirIDD,
237                                                param.debugDirDataSize,
238                                                NULL,
239                                                param.debugDirData)))
240         goto ErrExit;
241
242     // Grab the timestamp of the PE file.
243     DWORD fileTimeStamp;
244
245     if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile,
246                                                     &fileTimeStamp)))
247         goto ErrExit;
248
249     // Fill in the directory entry.
250     debugDirIDD.TimeDateStamp = VAL32(fileTimeStamp);
251
252     // Grab memory in the section for our stuff.
253     // Note that UpdateResource doesn't work correctly if the debug directory is
254     // in the data section.  So instead we put it in the text section (same as
255     // cs compiler).
256     if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec,
257                                                    sizeof(debugDirIDD) +
258                                                    param.debugDirDataSize,
259                                                    4,
260                                                    (void**) &de)))
261         goto ErrExit;
262
263     // Where did we get that memory?
264     if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec,
265                                                      &deOffset)))
266         goto ErrExit;
267
268     deOffset -= (sizeof(debugDirIDD) + param.debugDirDataSize);
269
270     // Setup a reloc so that the address of the raw
271     // data is setup correctly.
272     debugDirIDD.PointerToRawData = VAL32(deOffset + sizeof(debugDirIDD));
273
274     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(
275                                           sec,
276                                           deOffset +
277                                           offsetof(IMAGE_DEBUG_DIRECTORY,
278                                                    PointerToRawData),
279                                           sec, srRelocFilePos)))
280         goto ErrExit;
281
282     debugDirIDD.AddressOfRawData = VAL32(deOffset + sizeof(debugDirIDD));
283
284     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(
285                                           sec,
286                                           deOffset +
287                                           offsetof(IMAGE_DEBUG_DIRECTORY,
288                                                    AddressOfRawData),
289                                           sec, srRelocAbsolute)))
290         goto ErrExit;
291     // Emit the directory entry.
292     if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile,
293                                                      sec,
294                                                      IMAGE_DIRECTORY_ENTRY_DEBUG,
295                                                      sizeof(debugDirIDD),
296                                                      deOffset)))
297         goto ErrExit;
298
299     // Copy the debug directory into the section.
300     memcpy(de, &debugDirIDD, sizeof(debugDirIDD));
301     memcpy(de + sizeof(debugDirIDD), param.debugDirData,
302            param.debugDirDataSize);
303
304     if (param.debugDirData)
305     {
306         delete [] param.debugDirData;
307     }
308     return S_OK;
309
310 ErrExit:
311     if (param.debugDirData)
312     {
313         delete [] param.debugDirData;
314     }
315     return hr;
316 }
317 //#ifdef EXPORT_DIR_ENABLED
318 HRESULT Assembler::CreateExportDirectory()
319 {
320     HRESULT hr = S_OK;
321     DWORD   Nentries = m_EATList.COUNT();
322     if(Nentries == 0) return S_OK;
323
324     IMAGE_EXPORT_DIRECTORY  exportDirIDD;
325     DWORD                   exportDirDataSize;
326     BYTE                   *exportDirData;
327     EATEntry               *pEATE;
328     unsigned                i, L, ordBase = 0xFFFFFFFF, Ldllname;
329     // get the DLL name from output file name
330     char*                   pszDllName;
331     Ldllname = (unsigned)wcslen(m_wzOutputFileName)*3+3;
332     char*                   szOutputFileName = new char[Ldllname];
333     memset(szOutputFileName,0,wcslen(m_wzOutputFileName)*3+3);
334     WszWideCharToMultiByte(CP_ACP,0,m_wzOutputFileName,-1,szOutputFileName,Ldllname,NULL,NULL);
335     pszDllName = strrchr(szOutputFileName,'\\');
336     if(pszDllName == NULL) pszDllName = strrchr(szOutputFileName,':');
337     if(pszDllName == NULL) pszDllName = szOutputFileName;
338     Ldllname = (unsigned)strlen(pszDllName)+1;
339
340     // Allocate buffer for tables
341     for(i = 0, L=0; i < Nentries; i++) L += 1+(unsigned)strlen(m_EATList.PEEK(i)->szAlias);
342     exportDirDataSize = Nentries*5*sizeof(WORD) + L + Ldllname;
343     exportDirData = new BYTE[exportDirDataSize];
344     memset(exportDirData,0,exportDirDataSize);
345
346     // Export address table
347     DWORD*  pEAT = (DWORD*)exportDirData;
348     // Name pointer table
349     DWORD*  pNPT = pEAT + Nentries;
350     // Ordinal table
351     WORD*   pOT = (WORD*)(pNPT + Nentries);
352     // Export name table
353     char*   pENT = (char*)(pOT + Nentries);
354     // DLL name
355     char*   pDLLName = pENT + L;
356
357     // sort the names/ordinals
358     char**  pAlias = new char*[Nentries];
359     for(i = 0; i < Nentries; i++)
360     {
361         pEATE = m_EATList.PEEK(i);
362         pOT[i] = (WORD)pEATE->dwOrdinal;
363         if(pOT[i] < ordBase) ordBase = pOT[i];
364         pAlias[i] = pEATE->szAlias;
365     }
366     bool swapped = true;
367     unsigned j;
368     char*    pch;
369     while(swapped)
370     {
371         swapped = false;
372         for(i=1; i < Nentries; i++)
373         {
374             if(strcmp(pAlias[i-1],pAlias[i]) > 0)
375             {
376                 swapped = true;
377                 pch = pAlias[i-1];
378                 pAlias[i-1] = pAlias[i];
379                 pAlias[i] = pch;
380                 j = pOT[i-1];
381                 pOT[i-1] = pOT[i];
382                 pOT[i] = j;
383             }
384         }
385     }
386     // normalize ordinals
387     for(i = 0; i < Nentries; i++) pOT[i] -= ordBase;
388     // fill the export address table
389 #ifdef _PREFAST_
390 #pragma warning(push)
391 #pragma warning(disable:22008) // "Suppress PREfast warnings about integer overflow"
392 #endif
393     for(i = 0; i < Nentries; i++)
394     {
395         pEATE = m_EATList.PEEK(i);
396         pEAT[pEATE->dwOrdinal - ordBase] = pEATE->dwStubRVA;
397     }
398 #ifdef _PREFAST_
399 #pragma warning(pop)
400 #endif
401     // fill the export names table
402     unsigned l;
403     for(i = 0, j = 0; i < Nentries; i++)
404     {
405         pNPT[i] = j; // relative offset in the table
406         l = (unsigned)strlen(pAlias[i])+1;
407         memcpy(&pENT[j],pAlias[i],l);
408         j+=l;
409     }
410     _ASSERTE(j==L);
411     // fill the DLL name
412     memcpy(pDLLName,pszDllName,Ldllname);
413
414     // Data blob is ready pending Name Pointer Table values offsetting
415
416     memset(&exportDirIDD,0,sizeof(IMAGE_EXPORT_DIRECTORY));
417     // Grab the timestamp of the PE file.
418     DWORD fileTimeStamp;
419     if (FAILED(hr = m_pCeeFileGen->GetFileTimeStamp(m_pCeeFile,&fileTimeStamp))) return hr;
420     // Fill in the directory entry.
421     // Characteristics, MajorVersion and MinorVersion play no role and stay 0
422     exportDirIDD.TimeDateStamp = VAL32(fileTimeStamp);
423     exportDirIDD.Name = VAL32(exportDirDataSize - Ldllname); // to be offset later
424     exportDirIDD.Base = VAL32(ordBase);
425     exportDirIDD.NumberOfFunctions = VAL32(Nentries);
426     exportDirIDD.NumberOfNames = VAL32(Nentries);
427     exportDirIDD.AddressOfFunctions = 0;    // to be offset later
428     exportDirIDD.AddressOfNames = VAL32(Nentries*sizeof(DWORD));   // to be offset later
429     exportDirIDD.AddressOfNameOrdinals = VAL32(Nentries*sizeof(DWORD)*2);  // to be offset later
430
431     // Grab memory in the section for our stuff.
432     HCEESECTION sec = m_pGlobalDataSection;
433     BYTE *de;
434     if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(sec,
435                                                    sizeof(IMAGE_EXPORT_DIRECTORY) + exportDirDataSize,
436                                                    4,
437                                                    (void**) &de))) return hr;
438     // Where did we get that memory?
439     ULONG deOffset, deDataOffset;
440     if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(sec, &deDataOffset))) return hr;
441
442     deDataOffset -= exportDirDataSize;
443     deOffset = deDataOffset - sizeof(IMAGE_EXPORT_DIRECTORY);
444
445     // Add offsets and set up relocs for header entries
446     exportDirIDD.Name = VAL32(VAL32(exportDirIDD.Name) + deDataOffset);
447     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,Name),
448                                           sec, srRelocAbsolute))) return hr;
449     exportDirIDD.AddressOfFunctions = VAL32(VAL32(exportDirIDD.AddressOfFunctions) + deDataOffset);
450     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfFunctions),
451                                           sec, srRelocAbsolute))) return hr;
452     exportDirIDD.AddressOfNames = VAL32(VAL32(exportDirIDD.AddressOfNames) + deDataOffset);
453     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNames),
454                                           sec, srRelocAbsolute))) return hr;
455     exportDirIDD.AddressOfNameOrdinals = VAL32(VAL32(exportDirIDD.AddressOfNameOrdinals) + deDataOffset);
456     if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,deOffset + offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNameOrdinals),
457                                           sec, srRelocAbsolute))) return hr;
458
459     // Add offsets and set up relocs for Name Pointer Table
460     j = deDataOffset + Nentries*5*sizeof(WORD); // EA, NP and O Tables come first
461     for(i = 0; i < Nentries; i++)
462     {
463         pNPT[i] += j;
464         if (FAILED(hr = m_pCeeFileGen->AddSectionReloc(sec,exportDirIDD.AddressOfNames+i*sizeof(DWORD),
465             sec, srRelocAbsolute))) return hr;
466     }
467
468
469     // Emit the directory entry.
470     if (FAILED(hr = m_pCeeFileGen->SetDirectoryEntry(m_pCeeFile, sec, IMAGE_DIRECTORY_ENTRY_EXPORT,
471                                                      sizeof(IMAGE_EXPORT_DIRECTORY), deOffset)))  return hr;
472
473     // Copy the debug directory into the section.
474     memcpy(de, &exportDirIDD, sizeof(IMAGE_EXPORT_DIRECTORY));
475     memcpy(de + sizeof(IMAGE_EXPORT_DIRECTORY), exportDirData, exportDirDataSize);
476     delete [] pAlias;
477     delete [] exportDirData;
478     return S_OK;
479 }
480
481 static const BYTE ExportStubAMD64Template[] = 
482 {
483         // Jump through VTFixup table 
484         0x48, 0xA1,                             // rex.w rex.b mov rax,[following address]
485     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,//address of VTFixup slot
486     0xFF, 0xE0              // jmp [rax]
487 };
488 static const BYTE ExportStubX86Template[] = 
489 {
490         // Jump through VTFixup table 
491         0xFF, 0x25,                             // jmp [following address]
492     0x00, 0x00, 0x00, 0x00  //address of VTFixup slot
493 };
494 static const WORD ExportStubARMTemplate[] = 
495 {
496         // Jump through VTFixup table
497     0xf8df, 0xf000,         // ldr pc, [pc, #0]
498     0x0000, 0x0000          //address of VTFixup slot
499 };
500
501 DWORD   Assembler::EmitExportStub(DWORD dwVTFSlotRVA)
502 {
503     DWORD EXPORT_STUB_SIZE = (DWORD)(sizeof(WORD)+sizeof(DWORD));
504     DWORD OFFSET_OF_ADDR = (DWORD)sizeof(WORD);
505     DWORD STUB_ALIGNMENT = 16;
506     BYTE* STUB_TEMPLATE = NULL;
507     DWORD PEFileOffset;
508     BYTE* outBuff;
509     DWORD*  pdwVTFSlotRVA;
510
511     if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_AMD64)
512     {
513         STUB_TEMPLATE = (BYTE*)&ExportStubAMD64Template[0];
514         EXPORT_STUB_SIZE = sizeof(ExportStubAMD64Template);
515         OFFSET_OF_ADDR = 2;
516         STUB_ALIGNMENT = 4;
517     }
518     else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
519     {
520         STUB_TEMPLATE = (BYTE*)&ExportStubX86Template[0];
521         EXPORT_STUB_SIZE = sizeof(ExportStubX86Template);
522         OFFSET_OF_ADDR = 2;
523     }
524     else if(m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM)
525     {
526         STUB_TEMPLATE = (BYTE*)&ExportStubARMTemplate[0];
527         EXPORT_STUB_SIZE = sizeof(ExportStubARMTemplate);
528         OFFSET_OF_ADDR = 4;
529         STUB_ALIGNMENT = 4;
530     }
531     else
532     {
533         report->error("Unmanaged exports are not implemented for unknown platform");
534         return NULL;
535     }
536     // Addr must be aligned, not the stub!
537     if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0;
538     if((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1))
539     {
540         ULONG L = STUB_ALIGNMENT - ((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1));
541         if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, L, 1, (void **) &outBuff))) return 0;
542         memset(outBuff,0,L);
543     }
544     
545     if (FAILED(m_pCeeFileGen->GetSectionBlock (m_pILSection, EXPORT_STUB_SIZE, 1, (void **) &outBuff))) return 0;
546     memcpy(outBuff,STUB_TEMPLATE,EXPORT_STUB_SIZE);
547     pdwVTFSlotRVA = (DWORD*)(&outBuff[OFFSET_OF_ADDR]);
548     *pdwVTFSlotRVA = VAL32(dwVTFSlotRVA);
549
550     // The offset where we start, (not where the alignment bytes start!)
551     if (FAILED(m_pCeeFileGen->GetSectionDataLen (m_pILSection, &PEFileOffset))) return 0;
552
553     PEFileOffset -= EXPORT_STUB_SIZE;
554     _ASSERTE(((PEFileOffset + OFFSET_OF_ADDR)&(STUB_ALIGNMENT-1))==0);
555     m_pCeeFileGen->AddSectionReloc(m_pILSection, PEFileOffset+OFFSET_OF_ADDR,m_pGlobalDataSection, srRelocHighLow);
556
557     if(m_dwCeeFileFlags & ICEE_CREATE_FILE_STRIP_RELOCS)
558     {
559         report->error("Base relocations are emitted, while /STRIPRELOC option has been specified");
560     }
561     m_pCeeFileGen->GetMethodRVA(m_pCeeFile, PEFileOffset,&PEFileOffset);
562     return PEFileOffset;
563 }
564 //#endif
565
566 HRESULT Assembler::GetCAName(mdToken tkCA, __out LPWSTR *ppszName)
567 {
568     HRESULT hr = S_OK;
569     DWORD cchName;
570     LPWSTR name;
571
572     *ppszName = NULL;
573
574     if (TypeFromToken(tkCA) == mdtMemberRef)
575     {
576         mdToken parent;
577         if (FAILED(hr = m_pImporter->GetMemberRefProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL)))
578             return hr;
579         tkCA = parent;
580     }
581     else if (TypeFromToken(tkCA) == mdtMethodDef)
582     {
583         mdToken parent;
584         if (FAILED(hr = m_pImporter->GetMemberProps( tkCA, &parent, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)))
585             return hr;
586         tkCA = parent;
587     }
588
589     if (TypeFromToken(tkCA) == mdtTypeRef)
590     {
591         // A TypeRef
592         if (FAILED(hr = m_pImporter->GetTypeRefProps(tkCA, NULL, NULL, 0, &cchName)))
593             return hr;
594         if ((name = new WCHAR[cchName + 1]) == NULL)
595             return E_OUTOFMEMORY;
596         hr = m_pImporter->GetTypeRefProps(tkCA, NULL, name, cchName, &cchName);
597     }
598     else
599     {
600         hr = m_pImporter->GetTypeDefProps(tkCA, NULL, 0, &cchName, NULL, NULL);
601         if (hr != S_OK)
602             return hr;
603         if ((name = new WCHAR[cchName + 1]) == NULL)
604             return E_OUTOFMEMORY;
605         hr = m_pImporter->GetTypeDefProps(tkCA, name, cchName, &cchName, NULL, NULL);
606     }
607     if (SUCCEEDED(hr))
608         *ppszName = name;
609     else
610         delete [] name;
611     return hr;
612 }
613
614 BYTE HexToByte (CHAR wc)
615 {
616     if (!iswxdigit(wc)) return (BYTE) 0xff;
617     if (iswdigit(wc)) return (BYTE) (wc - L'0');
618     if (iswupper(wc)) return (BYTE) (wc - L'A' + 10);
619     return (BYTE) (wc - L'a' + 10);
620 }
621
622
623 BOOL Assembler::EmitFieldsMethods(Class* pClass)
624 {
625     unsigned n;
626     BOOL ret = TRUE;
627     // emit all field definition metadata tokens
628     if((n = pClass->m_FieldDList.COUNT()))
629     {
630         FieldDescriptor*    pFD;
631         if(m_fReportProgress) printf("Fields: %d;\t",n);
632         for(int j=0; (pFD = pClass->m_FieldDList.PEEK(j)); j++) // can't use POP here: we'll need field list for props
633         {
634             if(!EmitField(pFD))
635             {
636                 if(!OnErrGo) return FALSE;
637                 ret = FALSE;
638             }
639             pFD->m_fNew = FALSE;
640         }
641     }
642     // Fields are emitted; emit the class layout
643     {
644         COR_FIELD_OFFSET *pOffsets = NULL;
645         ULONG ul = pClass->m_ulPack;
646         ULONG N = pClass->m_dwNumFieldsWithOffset;
647
648         EmitSecurityInfo(pClass->m_cl,
649                          pClass->m_pPermissions,
650                          pClass->m_pPermissionSets);
651         pClass->m_pPermissions = NULL;
652         pClass->m_pPermissionSets = NULL;
653         if((pClass->m_ulSize != 0xFFFFFFFF)||(ul != 0)||(N != 0))
654         {
655             if(IsTdAutoLayout(pClass->m_Attr)) report->warn("Layout specified for auto-layout class\n");
656             if((ul > 128)||((ul & (ul-1)) !=0 ))
657                 report->error("Invalid packing parameter (%d), must be 1,2,4,8...128\n",pClass->m_ulPack);
658             if(N)
659             {
660                 pOffsets = new COR_FIELD_OFFSET[N+1];
661                 ULONG i,j=0;
662                 FieldDescriptor *pFD;
663                 for(i=0; (pFD = pClass->m_FieldDList.PEEK(i)); i++)
664                 {
665                     if(pFD->m_ulOffset != 0xFFFFFFFF)
666                     {
667                         pOffsets[j].ridOfField = RidFromToken(pFD->m_fdFieldTok);
668                         pOffsets[j].ulOffset = pFD->m_ulOffset;
669                         j++;
670                     }
671                 }
672                 _ASSERTE(j == N);
673                 pOffsets[j].ridOfField = mdFieldDefNil;
674             }
675             m_pEmitter->SetClassLayout   (
676                         pClass->m_cl,       // [IN] typedef
677                         ul,                     // [IN] packing size specified as 1, 2, 4, 8, or 16
678                         pOffsets,               // [IN] array of layout specification
679                         pClass->m_ulSize); // [IN] size of the class
680             if(pOffsets) delete [] pOffsets;
681         }
682     }
683     // emit all method definition metadata tokens
684     if((n = pClass->m_MethodList.COUNT()))
685     {
686         Method* pMethod;
687
688         if(m_fReportProgress) printf("Methods: %d;\t",n);
689         for(int i=0; (pMethod = pClass->m_MethodList.PEEK(i));i++)
690         {
691             if(!EmitMethod(pMethod))
692             {
693                 if(!OnErrGo) return FALSE;
694                 ret = FALSE;
695             }
696             pMethod->m_fNew = FALSE;
697         }
698     }
699     if(m_fReportProgress) printf("\n");
700     return ret;
701 }
702
703 HRESULT Assembler::ResolveLocalMemberRefs()
704 {
705     unsigned ulTotal=0, ulDefs=0, ulRefs=0, ulUnres=0;
706     MemberRefDList* pList[2] = {&m_LocalMethodRefDList,&m_LocalFieldRefDList};
707
708     if(pList[0]->COUNT() + pList[1]->COUNT())
709     {
710         MemberRefDescriptor*    pMRD;
711         mdToken         tkMemberDef = 0;
712         int i,j,k;
713         Class   *pSearch;
714
715         if(m_fReportProgress) printf("Resolving local member refs: ");
716         for(k=0; k<2; k++)
717         {
718             for(i=0; (pMRD = pList[k]->PEEK(i)) != NULL; i++)
719             {
720                 if(pMRD->m_tkResolved) continue;
721
722                 tkMemberDef = 0;
723                 Method* pListMD;
724                 char*           pMRD_szName = pMRD->m_szName;
725                 DWORD           pMRD_dwName = pMRD->m_dwName;
726                 ULONG           pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0);
727                 PCOR_SIGNATURE  pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL);
728                 CQuickBytes     qbSig;
729
730                 ulTotal++;
731
732                 pSearch = NULL;
733                 if(pMRD->m_tdClass == mdTokenNil)
734                     pSearch = m_lstClass.PEEK(0);
735                 else if((TypeFromToken(pMRD->m_tdClass) != mdtTypeDef)
736                     ||((pSearch = m_lstClass.PEEK(RidFromToken(pMRD->m_tdClass)-1)) == NULL))
737                 {
738                     report->msg("Error: bad parent 0x%08X of local member ref '%s'\n",
739                         pMRD->m_tdClass,pMRD->m_szName);
740                 }
741                 if(pSearch)
742                 {
743                     // MemberRef may reference a method or a field
744                     if(k==0) //methods
745                     {
746                         if((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG)
747                         {
748                             ULONG L;
749                             qbSig.Shrink(0);
750                             _GetFixedSigOfVarArg(pMRD_pSig,pMRD_dwCSig,&qbSig,&L);
751                             pMRD_pSig = (PCOR_SIGNATURE)(qbSig.Ptr());
752                             pMRD_dwCSig = L;
753                         }
754                         for(j=0; (pListMD = pSearch->m_MethodList.PEEK(j)) != NULL; j++)
755                         {
756                             if(pListMD->m_dwName != pMRD_dwName) continue;
757                             if(strcmp(pListMD->m_szName,pMRD_szName)) continue;
758                             if(pListMD->m_dwMethodCSig  != pMRD_dwCSig)  continue;
759                             if(memcmp(pListMD->m_pMethodSig,pMRD_pSig,pMRD_dwCSig)) continue;
760                             tkMemberDef = pListMD->m_Tok;
761                             ulDefs++;
762                             break;
763                         }
764                         if(tkMemberDef && ((*pMRD_pSig & IMAGE_CEE_CS_CALLCONV_MASK)==IMAGE_CEE_CS_CALLCONV_VARARG))
765                         {
766                             WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf);
767
768                             if(IsMdPrivateScope(pListMD->m_Attr))
769                             {
770                                 WCHAR* p = wcsstr(wzUniBuf,W("$PST06"));
771                                 if(p) *p = 0;
772                             }
773
774                             m_pEmitter->DefineMemberRef(tkMemberDef, wzUniBuf,
775                                                              pMRD->m_pSigBinStr->ptr(),
776                                                              pMRD->m_pSigBinStr->length(),
777                                                              &tkMemberDef);
778                             ulDefs--;
779                             ulRefs++;
780                         }
781                     }
782                     else   // fields
783                     {
784                         FieldDescriptor* pListFD;
785                         for(j=0; (pListFD = pSearch->m_FieldDList.PEEK(j)) != NULL; j++)
786                         {
787                             if(pListFD->m_dwName != pMRD_dwName) continue;
788                             if(strcmp(pListFD->m_szName,pMRD_szName)) continue;
789                             if(pListFD->m_pbsSig)
790                             {
791                                 if(pListFD->m_pbsSig->length()  != pMRD_dwCSig)  continue;
792                                 if(memcmp(pListFD->m_pbsSig->ptr(),pMRD_pSig,pMRD_dwCSig)) continue;
793                             }
794                             else if(pMRD_dwCSig) continue;
795                             tkMemberDef = pListFD->m_fdFieldTok;
796                             ulDefs++;
797                             break;
798                         }
799                     }
800                 }
801                 if(tkMemberDef==0)
802                 { // could not resolve ref to def, make new ref and leave it this way
803                     if((pSearch = pMRD->m_pClass) != NULL)
804                     {
805                         mdToken tkRef = MakeTypeRef(1,pSearch->m_szFQN);
806
807                         if(RidFromToken(tkRef))
808                         {
809                             WszMultiByteToWideChar(g_uCodePage,0,pMRD_szName,-1,wzUniBuf,dwUniBuf);
810
811                             m_pEmitter->DefineMemberRef(tkRef, wzUniBuf, pMRD_pSig,
812                                 pMRD_dwCSig, &tkMemberDef);
813                             ulRefs++;
814                         }
815                         else
816                         {
817                             report->msg("Error: unresolved member ref '%s' of class 0x%08X\n",pMRD->m_szName,pMRD->m_tdClass);
818                             ulUnres++;
819                         }
820                     }
821                     else
822                     {
823                         report->msg("Error: unresolved global member ref '%s'\n",pMRD->m_szName);
824                         ulUnres++;
825                     }
826                 }
827                 pMRD->m_tkResolved = tkMemberDef;
828             }
829         }
830         for(i=0; (pMRD = m_MethodSpecList.PEEK(i)) != NULL; i++)
831         {
832             if(pMRD->m_tkResolved) continue;
833             tkMemberDef = pMRD->m_tdClass;
834             if(TypeFromToken(tkMemberDef)==0x99000000)
835             {
836                 tkMemberDef = m_LocalMethodRefDList.PEEK(RidFromToken(tkMemberDef)-1)->m_tkResolved;
837                 if((TypeFromToken(tkMemberDef)==mdtMethodDef)||(TypeFromToken(tkMemberDef)==mdtMemberRef))
838                 {
839                     ULONG           pMRD_dwCSig = (pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->length() : 0);
840                     PCOR_SIGNATURE  pMRD_pSig = (PCOR_SIGNATURE)(pMRD->m_pSigBinStr ? pMRD->m_pSigBinStr->ptr() : NULL);
841                     HRESULT hr = m_pEmitter->DefineMethodSpec(tkMemberDef, pMRD_pSig, pMRD_dwCSig, &(pMRD->m_tkResolved));
842                     if(FAILED(hr))
843                         report->error("Unable to define method instantiation");
844                 }
845             }
846             if(RidFromToken(pMRD->m_tkResolved)) ulDefs++;
847             else ulUnres++;
848         }
849         if(m_fReportProgress) printf("%d -> %d defs, %d refs, %d unresolved\n",ulTotal,ulDefs,ulRefs,ulUnres);
850     }
851     return (ulUnres ? E_FAIL : S_OK);
852 }
853
854 HRESULT Assembler::DoLocalMemberRefFixups()
855 {
856     MemberRefDList* pList;
857     unsigned    Nlmr = m_LocalMethodRefDList.COUNT() + m_LocalFieldRefDList.COUNT(),
858                 Nlmrf = m_LocalMemberRefFixupList.COUNT();
859     HRESULT     hr = S_OK;
860     if(Nlmr)
861     {
862         MemberRefDescriptor* pMRD;
863         LocalMemberRefFixup* pMRF;
864         int i;
865         for(i = 0; (pMRF = m_LocalMemberRefFixupList.PEEK(i)) != NULL; i++)
866         {
867             if(m_fENCMode && (!pMRF->m_fNew)) continue;
868
869             switch(TypeFromToken(pMRF->tk))
870             {
871                 case 0x99000000: pList = &m_LocalMethodRefDList; break;
872                 case 0x98000000: pList = &m_LocalFieldRefDList; break;
873                 case 0x9A000000: pList = &m_MethodSpecList; break;
874                 default: pList = NULL; break;
875             }
876             if(pList)
877             {
878                 if((pMRD = pList->PEEK(RidFromToken(pMRF->tk)-1)) != NULL)
879                     SET_UNALIGNED_VAL32((void *)(pMRF->offset), pMRD->m_tkResolved);
880                 else
881                 {
882                     report->msg("Error: bad local member ref token 0x%08X in LMR fixup\n",pMRF->tk);
883                     hr = E_FAIL;
884                 }
885             }
886             pMRF->m_fNew = FALSE;
887         }
888     }
889     else if(Nlmrf)
890     {
891         report->msg("Error: %d local member ref fixups, no local member refs\n",Nlmrf);
892         hr = E_FAIL;
893     }
894     return hr;
895 }
896 void Assembler::EmitUnresolvedCustomAttributes()
897 {
898     CustomDescr *pCD;
899     while((pCD = m_CustomDescrList.POP()) != NULL)
900     {
901         pCD->tkType = ResolveLocalMemberRef(pCD->tkType);
902         pCD->tkOwner = ResolveLocalMemberRef(pCD->tkOwner);
903         // Look for the class'es interfaceimpl if this CA is one of those
904         if (pCD->tkInterfacePair)
905             pCD->tkOwner = GetInterfaceImpl(pCD->tkOwner, pCD->tkInterfacePair);
906         DefineCV(new CustomDescr(pCD->tkOwner,pCD->tkType,pCD->pBlob));
907     }
908 }
909
910 BOOL Assembler::EmitEventsProps(Class* pClass)
911 {
912     unsigned n;
913     BOOL ret = TRUE;
914     // emit all event definition metadata tokens
915     if((n = pClass->m_EventDList.COUNT()))
916     {
917         if(m_fReportProgress) printf("Events: %d;\t",n);
918         EventDescriptor* pED;
919         for(int j=0; (pED = pClass->m_EventDList.PEEK(j)); j++) // can't use POP here: we'll need event list for props
920         {
921             if(!EmitEvent(pED))
922             {
923                 if(!OnErrGo) return FALSE;
924                 ret = FALSE;
925             }
926             pED->m_fNew = FALSE;
927         }
928     }
929     // emit all property definition metadata tokens
930     if((n = pClass->m_PropDList.COUNT()))
931     {
932         if(m_fReportProgress) printf("Props: %d;\t",n);
933         PropDescriptor* pPD;
934
935         for(int j=0; (pPD = pClass->m_PropDList.PEEK(j)); j++)
936         {
937             if(!EmitProp(pPD))
938             {
939                 if(!OnErrGo) return FALSE;
940                 ret = FALSE;
941             }
942             pPD->m_fNew = FALSE;
943         }
944     }
945     if(m_fReportProgress) printf("\n");
946     return ret;
947 }
948
949 HRESULT Assembler::AllocateStrongNameSignature()
950 {
951     HRESULT             hr = S_OK;
952     HCEESECTION         hSection;
953     DWORD               dwDataLength;
954     DWORD               dwDataOffset;
955     DWORD               dwDataRVA;
956     VOID               *pvBuffer;
957     AsmManStrongName   *pSN = &m_pManifest->m_sStrongName;
958
959     // pSN->m_cbPublicKey is the length of the m_pbPublicKey
960     dwDataLength = ((int)pSN->m_cbPublicKey < 128 + 32) ? 128 : (int)pSN->m_cbPublicKey - 32;
961
962     // Grab memory in the section for our stuff.
963     if (FAILED(hr = m_pCeeFileGen->GetIlSection(m_pCeeFile,
964                                                 &hSection)))
965     {
966         return hr;
967     }
968
969     if (FAILED(hr = m_pCeeFileGen->GetSectionBlock(hSection,
970                                                    dwDataLength,
971                                                    4,
972                                                    &pvBuffer)))
973     {
974         return hr;
975     }
976
977     // Where did we get that memory?
978     if (FAILED(hr = m_pCeeFileGen->GetSectionDataLen(hSection,
979                                                      &dwDataOffset)))
980     {
981         return hr;
982     }
983
984     dwDataOffset -= dwDataLength;
985
986     // Convert to an RVA.
987     if (FAILED(hr = m_pCeeFileGen->GetMethodRVA(m_pCeeFile,
988                                                 dwDataOffset,
989                                                 &dwDataRVA)))
990     {
991         return hr;
992     }
993
994     // Emit the directory entry.
995     if (FAILED(hr = m_pCeeFileGen->SetStrongNameEntry(m_pCeeFile,
996                                                       dwDataLength,
997                                                       dwDataRVA)))
998     {
999         return hr;
1000     }
1001
1002     return S_OK;
1003 }
1004
1005 #ifdef _PREFAST_
1006 #pragma warning(push)
1007 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1008 #endif
1009 HRESULT Assembler::CreatePEFile(__in __nullterminated WCHAR *pwzOutputFilename)
1010 {
1011     HRESULT             hr;
1012     DWORD               mresourceSize = 0;
1013     BYTE*               mresourceData = NULL;
1014     WCHAR*              wzScopeName = NULL;
1015
1016     if(bClock) bClock->cMDEmitBegin = GetTickCount();
1017     if(m_fReportProgress) printf("Creating PE file\n");
1018     if (!m_pEmitter)
1019     {
1020         printf("Error: Cannot create a PE file with no metadata\n");
1021         return E_FAIL;
1022     }
1023     if(!(m_fDLL || m_fEntryPointPresent))
1024     {
1025         printf("Error: No entry point declared for executable\n");
1026         if(!OnErrGo) return E_FAIL;
1027     }
1028
1029     if(bClock) bClock->cMDEmit1 = GetTickCount();
1030
1031     // Allocate space for a strong name signature if we're delay or full
1032     // signing the assembly.
1033     if (m_pManifest->m_sStrongName.m_pbPublicKey)
1034     {
1035         if (FAILED(hr = AllocateStrongNameSignature()))
1036         {
1037             goto exit;
1038         }
1039     }
1040
1041     if(bClock) bClock->cMDEmit2 = GetTickCount();
1042
1043     if(m_VTFList.COUNT()==0)
1044     {
1045         Method* pMD;
1046         Class* pClass;
1047         unsigned N=0, OrdBase=0xFFFFFFFF, i, j;
1048         for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++)
1049         {
1050             for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++)
1051             {
1052                 if(pMD->m_dwExportOrdinal != 0xFFFFFFFF)
1053                 {
1054                     N++;
1055                     if(pMD->m_dwExportOrdinal < OrdBase) OrdBase = pMD->m_dwExportOrdinal;
1056                 }
1057             }
1058         }
1059         if(N)
1060         {
1061             for(i=0; (pClass = m_lstClass.PEEK(i)) != NULL; i++)
1062             {
1063                 for(j = 0; (pMD = pClass->m_MethodList.PEEK(j)) != NULL; j++)
1064                 {
1065                     if(pMD->m_wVTSlot >= 0x8000)
1066                     {
1067                         pMD->m_wVTSlot -= 0x8000 + OrdBase - 1;
1068                     }
1069                 }
1070             }
1071             SetDataSection();
1072             char* sz = new char[20];
1073             strcpy_s(sz,20,"VTF_EAT_internal");
1074             EmitDataLabel(sz);
1075             sz = new char[20];
1076             strcpy_s(sz,20,"VTF_EAT_internal");
1077             if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1078             {
1079                 ULONGLONG *pdw = new ULONGLONG[N];
1080                 for(i=0; i<N; i++) pdw[i] = UI64(0xdeadbeefdeadbeef);
1081                 EmitData(pdw,sizeof(ULONGLONG)*N);
1082                 m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_64BIT|COR_VTABLE_FROM_UNMANAGED,sz));
1083                 delete [] pdw;
1084             }
1085             else
1086             {
1087                 unsigned *pdw = new unsigned[N];
1088                 for(i=0; i<N; i++) pdw[i] = 0xdeadbeef;
1089                 EmitData(pdw,sizeof(unsigned)*N);
1090                 m_VTFList.PUSH(new VTFEntry((USHORT)N,COR_VTABLE_32BIT|COR_VTABLE_FROM_UNMANAGED,sz));
1091                 delete [] pdw;
1092             }
1093         }
1094     }
1095     wzScopeName=&wzUniBuf[0];
1096     if(m_szScopeName[0]) // default: scope name = output file name
1097     {
1098         WszMultiByteToWideChar(g_uCodePage,0,m_szScopeName,-1,wzScopeName,MAX_SCOPE_LENGTH);
1099     }
1100     else
1101     {
1102         WCHAR* pwc;
1103         if ((pwc = wcsrchr(m_wzOutputFileName, '\\')) != NULL) pwc++;
1104         else if ((pwc = wcsrchr(m_wzOutputFileName, ':')) != NULL) pwc++;
1105         else pwc = m_wzOutputFileName;
1106
1107         wcsncpy_s(wzScopeName, MAX_SCOPE_LENGTH, pwc, _TRUNCATE);
1108     }
1109     hr = m_pEmitter->SetModuleProps(wzScopeName);
1110
1111     if (FAILED(hr))
1112         goto exit;
1113
1114     EmitImports();
1115     if(m_pManifest)
1116     {
1117         hr = S_OK;
1118         if(m_pManifest->m_pAsmEmitter==NULL)
1119             hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &(m_pManifest->m_pAsmEmitter));
1120
1121         if(SUCCEEDED(hr))
1122         {
1123             m_pManifest->EmitAssemblyRefs();
1124         }
1125     }
1126     // Emit classes, class members and globals:
1127     {
1128         Class *pSearch;
1129         int i;
1130         BOOL    bIsUndefClass = FALSE;
1131         if(m_fReportProgress)   printf("\nEmitting classes:\n");
1132         for (i=1; (pSearch = m_lstClass.PEEK(i)); i++)   // 0 is <Module>
1133         {
1134             if(m_fReportProgress)
1135                 printf("Class %d:\t%s\n",i,pSearch->m_szFQN);
1136
1137             if(pSearch->m_bIsMaster)
1138             {
1139                 report->msg("Error: Reference to undefined class '%s'\n",pSearch->m_szFQN);
1140                 bIsUndefClass = TRUE;
1141             }
1142             if(!EmitClass(pSearch))
1143             {
1144                 if(!OnErrGo) return E_FAIL;
1145             }
1146             pSearch->m_fNew = FALSE;
1147         }
1148         if(bIsUndefClass && !OnErrGo) return E_FAIL;
1149
1150         if(m_fReportProgress)   printf("\nEmitting fields and methods:\n");
1151         for (i=0; (pSearch = m_lstClass.PEEK(i)) != NULL; i++)
1152         {
1153             if(m_fReportProgress)
1154             {
1155                 if(i == 0)  printf("Global \t");
1156                 else        printf("Class %d\t",i);
1157             }
1158             if(!EmitFieldsMethods(pSearch))
1159             {
1160                 if(!OnErrGo) return E_FAIL;
1161             }
1162         }
1163     }
1164
1165     // All ref'ed items def'ed in this file are emitted, resolve member refs to member defs:
1166     if(bClock) bClock->cRef2DefBegin = GetTickCount();
1167     hr = ResolveLocalMemberRefs();
1168     if(bClock) bClock->cRef2DefEnd = GetTickCount();
1169     if(FAILED(hr) &&(!OnErrGo)) goto exit;
1170
1171     // Local member refs resolved, emit events, props and method impls
1172     {
1173         Class *pSearch;
1174         int i;
1175
1176         if(m_fReportProgress)   printf("\nEmitting events and properties:\n");
1177         for (i=0; (pSearch = m_lstClass.PEEK(i)); i++)
1178         {
1179             if(m_fReportProgress)
1180             {
1181                 if(i == 0)  printf("Global \t");
1182                 else        printf("Class %d\t",i);
1183             }
1184             if(!EmitEventsProps(pSearch))
1185             {
1186                 if(!OnErrGo) return E_FAIL;
1187             }
1188             pSearch->m_fNewMembers = FALSE;
1189         }
1190     }
1191     if(bClock) bClock->cMDEmit3 = GetTickCount();
1192     if(m_MethodImplDList.COUNT())
1193     {
1194         if(m_fReportProgress) report->msg("Method Implementations (total): %d\n",m_MethodImplDList.COUNT());
1195         if(!EmitMethodImpls())
1196         {
1197             if(!OnErrGo) return E_FAIL;
1198         }
1199     }
1200     // Emit the rest of the metadata
1201     if(bClock) bClock->cMDEmit4 = GetTickCount();
1202     hr = S_OK;
1203     if(m_pManifest)
1204     {
1205         if (FAILED(hr = m_pManifest->EmitManifest())) goto exit;
1206     }
1207     ResolveLocalMemberRefs(); // in case CAs added some
1208     EmitUnresolvedCustomAttributes();
1209     // Emit typedefs as special TypeSpecs
1210     {
1211 #define ELEMENT_TYPE_TYPEDEF ELEMENT_TYPE_MAX+1
1212         TypeDefDescr* pTDD;
1213         unsigned __int8* pb;
1214         unsigned namesize;
1215         while((pTDD = m_TypeDefDList.POP()))
1216         {
1217             BinStr* pbs = new BinStr();
1218             if(pbs)
1219             {
1220                 namesize = 1 + (unsigned)strlen(pTDD->m_szName);
1221                 pb = pbs->getBuff(namesize + 1 + sizeof(mdToken));
1222                 *pb = ELEMENT_TYPE_TYPEDEF;
1223                 memcpy(++pb,pTDD->m_szName,namesize);
1224                 pTDD->m_tkTypeSpec = ResolveLocalMemberRef(pTDD->m_tkTypeSpec);
1225                 memcpy(pb+namesize,&(pTDD->m_tkTypeSpec),sizeof(mdToken));
1226                 if(TypeFromToken(pTDD->m_tkTypeSpec)==mdtCustomAttribute)
1227                 {
1228                     CustomDescr* pCA = pTDD->m_pCA;
1229                     pbs->appendInt32(pCA->tkType);
1230                     pbs->appendInt32(pCA->tkOwner);
1231                     if(pCA->pBlob) pbs->append(pCA->pBlob);
1232                 }
1233                 ResolveTypeSpec(pbs);
1234                 delete pbs;
1235             }
1236             delete pTDD;
1237         }
1238     }
1239     if(bClock) bClock->cMDEmitEnd = GetTickCount();
1240
1241     hr = DoLocalMemberRefFixups();
1242     if(FAILED(hr) &&(!OnErrGo)) goto exit;
1243     // Local member refs resolved and fixed up in BinStr method bodies. Emit the bodies.
1244     {
1245         Class* pClass;
1246         Method* pMethod;
1247         for (int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1248         {
1249             for(int j=0; (pMethod = pClass->m_MethodList.PEEK(j)); j++)
1250             {
1251                 if(!EmitMethodBody(pMethod,NULL))
1252                 {
1253                     report->msg("Error: failed to emit body of '%s'\n",pMethod->m_szName);
1254                     hr = E_FAIL;
1255                     if(!OnErrGo) goto exit;
1256                 }
1257                 pMethod->m_fNewBody = FALSE;
1258             }
1259         }
1260         //while(MethodBody* pMB = m_MethodBodyList.POP()) delete pMB;
1261     }
1262
1263     if (DoGlobalFixups() == FALSE)
1264         return E_FAIL;
1265
1266     if(m_wzResourceFile)
1267     {
1268 #ifdef FEATURE_PAL
1269         report->msg("Warning: The Win32 resource file '%S' is ignored and not emitted on xPlatform.\n", m_wzResourceFile);
1270 #else
1271         if (FAILED(hr=m_pCeeFileGen->SetResourceFileName(m_pCeeFile, m_wzResourceFile)))
1272         {
1273             report->msg("Warning: failed to set Win32 resource file name '%S', hr=0x%8.8X\n         The Win32 resource is not emitted.\n",
1274                         m_wzResourceFile, hr);
1275         }
1276 #endif
1277     }
1278
1279     if (FAILED(hr=CreateTLSDirectory())) goto exit;
1280
1281     if (FAILED(hr=CreateDebugDirectory())) goto exit;
1282
1283     if (FAILED(hr=m_pCeeFileGen->SetOutputFileName(m_pCeeFile, pwzOutputFilename))) goto exit;
1284
1285         // Reserve a buffer for the meta-data
1286     DWORD metaDataSize;
1287     if (FAILED(hr=m_pEmitter->GetSaveSize(cssAccurate, &metaDataSize))) goto exit;
1288     BYTE* metaData;
1289     if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, metaDataSize, sizeof(DWORD), (void**) &metaData))) goto exit;
1290     ULONG metaDataOffset;
1291     if (FAILED(hr=m_pCeeFileGen->GetSectionDataLen(m_pILSection, &metaDataOffset))) goto exit;
1292     metaDataOffset -= metaDataSize;
1293     // set managed resource entry, if any
1294     if(m_pManifest && m_pManifest->m_dwMResSizeTotal)
1295     {
1296         mresourceSize = m_pManifest->m_dwMResSizeTotal;
1297
1298         if (FAILED(hr=m_pCeeFileGen->GetSectionBlock(m_pILSection, mresourceSize,
1299                                             sizeof(DWORD), (void**) &mresourceData))) goto exit;
1300         if (FAILED(hr=m_pCeeFileGen->SetManifestEntry(m_pCeeFile, mresourceSize, 0))) goto exit;
1301     }
1302     if(m_VTFList.COUNT())
1303     {
1304         GlobalLabel *pGlobalLabel;
1305         VTFEntry*   pVTFEntry;
1306
1307         if(m_pVTable) delete m_pVTable; // can't have both; list takes precedence
1308         m_pVTable = new BinStr();
1309         hr = S_OK;
1310         for(WORD k=0; (pVTFEntry = m_VTFList.POP()); k++)
1311         {
1312             if((pGlobalLabel = FindGlobalLabel(pVTFEntry->m_szLabel)))
1313             {
1314                 Method* pMD;
1315                 Class* pClass;
1316                 m_pVTable->appendInt32(pGlobalLabel->m_GlobalOffset);
1317                 m_pVTable->appendInt16(pVTFEntry->m_wCount);
1318                 m_pVTable->appendInt16(pVTFEntry->m_wType);
1319                 for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1320                 {
1321                     for(WORD j = 0; (pMD = pClass->m_MethodList.PEEK(j)); j++)
1322                     {
1323                         if(pMD->m_wVTEntry == k+1)
1324                         {
1325                             char*   ptr;
1326                             if(SUCCEEDED(hr = m_pCeeFileGen->ComputeSectionPointer(m_pGlobalDataSection,pGlobalLabel->m_GlobalOffset,&ptr)))
1327                             {
1328                                 DWORD dwDelta;
1329                                 if((pVTFEntry->m_wType & COR_VTABLE_32BIT))
1330                                 {
1331                                     dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(DWORD);
1332                                     ptr += dwDelta;
1333                                     DWORD* mptr = (DWORD*)ptr;
1334                                     *mptr = (DWORD)(pMD->m_Tok);
1335                                 }
1336                                 else
1337                                 {
1338                                     dwDelta = (pMD->m_wVTSlot-1)*(DWORD)sizeof(ULONGLONG);
1339                                     ptr += dwDelta;
1340                                     ULONGLONG* mptr = (ULONGLONG*)ptr;
1341                                     *mptr = (ULONGLONG)(pMD->m_Tok);
1342                                 }
1343                                 if(pMD->m_dwExportOrdinal != 0xFFFFFFFF)
1344                                 {
1345                                     EATEntry*   pEATE = new EATEntry;
1346                                     pEATE->dwOrdinal = pMD->m_dwExportOrdinal;
1347                                     pEATE->szAlias = pMD->m_szExportAlias ? pMD->m_szExportAlias : pMD->m_szName;
1348                                     pEATE->dwStubRVA = EmitExportStub(pGlobalLabel->m_GlobalOffset+dwDelta);
1349                                     m_EATList.PUSH(pEATE);
1350                                 }
1351                             }
1352                             else
1353                                 report->msg("Error: Failed to get pointer to label '%s' inVTable fixup\n",pVTFEntry->m_szLabel);
1354                         }
1355                     }
1356                 }
1357             }
1358             else
1359             {
1360                 report->msg("Error: Unresolved label '%s' in VTable fixup\n",pVTFEntry->m_szLabel);
1361                 hr = E_FAIL;
1362             }
1363             delete pVTFEntry;
1364         }
1365         if(FAILED(hr)) goto exit;
1366     }
1367     if(m_pVTable)
1368     {
1369         ULONG i, N = m_pVTable->length()/sizeof(DWORD);
1370         ULONG ulVTableOffset;
1371         m_pCeeFileGen->GetSectionDataLen (m_pILSection, &ulVTableOffset);
1372         // SetVTableEntry will align VTable on DWORD
1373         ulVTableOffset = (ulVTableOffset + (ULONG)sizeof(DWORD) - 1) & ~((ULONG)sizeof(DWORD) - 1);
1374         if (FAILED(hr=m_pCeeFileGen->SetVTableEntry64(m_pCeeFile, m_pVTable->length(),(void*)(m_pVTable->ptr())))) goto exit; // @WARNING: casting down from pointer-size to DWORD
1375         for(i = 0; i < N; i+=2)
1376         {
1377             m_pCeeFileGen->AddSectionReloc(m_pILSection,
1378                                             ulVTableOffset+(i*sizeof(DWORD)),
1379                                             m_pGlobalDataSection,
1380                                             srRelocAbsolute);
1381         }
1382     }
1383     if(m_EATList.COUNT())
1384     {
1385         if(FAILED(CreateExportDirectory())) goto exit;
1386         m_dwComImageFlags &= ~COMIMAGE_FLAGS_ILONLY;
1387         if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_I386)
1388             COR_SET_32BIT_REQUIRED(m_dwComImageFlags);
1389     }
1390     if (m_fWindowsCE)
1391     {
1392         if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, 2, 10))) goto exit;
1393
1394         if (FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, 0x10000))) goto exit;
1395     }
1396     else
1397     {
1398         if (m_dwCeeFileFlags & ICEE_CREATE_MACHINE_ARM || m_fAppContainer)
1399         {
1400             // For AppContainer and ARM, you must have a minimum subsystem version of 6.02
1401             m_wSSVersionMajor = (m_wSSVersionMajor < 6) ? 6 : m_wSSVersionMajor;
1402             m_wSSVersionMinor = (m_wSSVersionMinor < 2 && m_wSSVersionMajor <= 6) ? 2 : m_wSSVersionMinor;
1403
1404         }
1405
1406         // Default the subsystem, instead the user doesn't set it to GUI or CUI
1407         if (m_dwSubsystem == (DWORD)-1)
1408             // The default for ILAsm previously was CUI, so that should be the default behavior...
1409             m_dwSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
1410
1411         if (FAILED(hr=m_pCeeFileGen->SetSubsystem(m_pCeeFile, m_dwSubsystem, m_wSSVersionMajor, m_wSSVersionMinor))) goto exit;
1412     }
1413
1414     if (FAILED(hr=m_pCeeFileGen->ClearComImageFlags(m_pCeeFile, COMIMAGE_FLAGS_ILONLY))) goto exit;
1415     if (FAILED(hr=m_pCeeFileGen->SetComImageFlags(m_pCeeFile, m_dwComImageFlags & ~COMIMAGE_FLAGS_STRONGNAMESIGNED))) goto exit;
1416
1417     if(m_dwFileAlignment)
1418     {
1419         if(FAILED(hr=m_pCeeFileGen->SetFileAlignment(m_pCeeFile, m_dwFileAlignment))) goto exit;
1420     }
1421     if(m_stBaseAddress)
1422     {
1423
1424         if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1425         {
1426             if(FAILED(hr=m_pCeeFileGen->SetImageBase64(m_pCeeFile, m_stBaseAddress))) goto exit;
1427         }
1428         else
1429         {
1430             if(FAILED(hr=m_pCeeFileGen->SetImageBase(m_pCeeFile, (size_t)m_stBaseAddress))) goto exit;
1431         }
1432     }
1433     if(m_stSizeOfStackReserve || m_fAppContainer || m_fHighEntropyVA)
1434     {
1435         PIMAGE_NT_HEADERS   pNT;
1436         PIMAGE_SECTION_HEADER   pSect;
1437         ULONG   ulNumSect;
1438         if(FAILED(hr=m_pCeeFileGen->GetHeaderInfo(m_pCeeFile,&pNT,&pSect,&ulNumSect))) goto exit;
1439         if(m_dwCeeFileFlags & ICEE_CREATE_FILE_PE64)
1440         {
1441             PIMAGE_OPTIONAL_HEADER64 pOpt = (PIMAGE_OPTIONAL_HEADER64)(&pNT->OptionalHeader);
1442             if (m_stSizeOfStackReserve)
1443                 pOpt->SizeOfStackReserve = VAL64(m_stSizeOfStackReserve); 
1444             if (m_fAppContainer)
1445                 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER;
1446             if (m_fHighEntropyVA)
1447                 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA;
1448         }
1449         else
1450         {
1451             PIMAGE_OPTIONAL_HEADER32 pOpt = (PIMAGE_OPTIONAL_HEADER32)(&pNT->OptionalHeader);
1452             if (m_stSizeOfStackReserve)
1453                 pOpt->SizeOfStackReserve = (DWORD)VAL32(m_stSizeOfStackReserve);
1454             if (m_fAppContainer)
1455                 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_APPCONTAINER;
1456             if (m_fHighEntropyVA)
1457                 pOpt->DllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA;
1458         }
1459     }
1460         //Compute all the RVAs
1461     if (FAILED(hr=m_pCeeFileGen->LinkCeeFile(m_pCeeFile))) goto exit;
1462
1463         // Fix up any fields that have RVA associated with them
1464     if (m_fHaveFieldsWithRvas) {
1465         hr = S_OK;
1466         ULONG dataSectionRVA;
1467         if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pGlobalDataSection, &dataSectionRVA))) goto exit;
1468
1469         ULONG tlsSectionRVA;
1470         if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pTLSSection, &tlsSectionRVA))) goto exit;
1471
1472         ULONG ilSectionRVA;
1473         if (FAILED(hr=m_pCeeFileGen->GetSectionRVA(m_pILSection, &ilSectionRVA))) goto exit;
1474
1475         FieldDescriptor* pListFD;
1476         Class* pClass;
1477         for(int i=0; (pClass = m_lstClass.PEEK(i)); i++)
1478         {
1479             for(int j=0; (pListFD = pClass->m_FieldDList.PEEK(j)); j++)
1480             {
1481                 if (pListFD->m_rvaLabel != 0)
1482                 {
1483                     DWORD rva;
1484                     if(*(pListFD->m_rvaLabel)=='@')
1485                     {
1486                         rva = (DWORD)atoi(pListFD->m_rvaLabel + 1);
1487                     }
1488                     else
1489                     {
1490                         GlobalLabel *pLabel = FindGlobalLabel(pListFD->m_rvaLabel);
1491                         if (pLabel == 0)
1492                         {
1493                             report->msg("Error:Could not find label '%s' for the field '%s'\n", pListFD->m_rvaLabel, pListFD->m_szName);
1494                             hr = E_FAIL;
1495                             continue;
1496                         }
1497
1498                         rva = pLabel->m_GlobalOffset;
1499                         if (pLabel->m_Section == m_pTLSSection)
1500                             rva += tlsSectionRVA;
1501                         else if (pLabel->m_Section == m_pILSection)
1502                             rva += ilSectionRVA;
1503                         else {
1504                             _ASSERTE(pLabel->m_Section == m_pGlobalDataSection);
1505                             rva += dataSectionRVA;
1506                         }
1507                     }
1508                     if (FAILED(m_pEmitter->SetFieldRVA(pListFD->m_fdFieldTok, rva))) goto exit;
1509                 }
1510             }
1511         }
1512         if (FAILED(hr)) goto exit;
1513     }
1514
1515     if(bClock) bClock->cFilegenBegin = GetTickCount();
1516     // actually output the meta-data
1517     if (FAILED(hr=m_pCeeFileGen->EmitMetaDataAt(m_pCeeFile, m_pEmitter, m_pILSection, metaDataOffset, metaData, metaDataSize))) goto exit;
1518     
1519     if((m_wMSVmajor < 0xFF)&&(m_wMSVminor < 0xFF))
1520     {
1521         STORAGESIGNATURE *pSSig = (STORAGESIGNATURE *)metaData;
1522         BYTE* pb = metaData;
1523         pb += 3*sizeof(DWORD)+2*sizeof(WORD)+VAL32(pSSig->iVersionString);
1524         pb = (BYTE*)(((size_t)pb + 3) & ~3);
1525         PSTORAGEHEADER pSHdr = (PSTORAGEHEADER)pb;
1526         PSTORAGESTREAM pStr = (PSTORAGESTREAM)(pSHdr+1);
1527         for(short iStr = 1; iStr <= VAL16(pSHdr->iStreams); iStr++)
1528         {
1529             if((strcmp(pStr->rcName,"#-")==0)||(strcmp(pStr->rcName,"#~")==0))
1530             {
1531                 pb = metaData + VAL32(pStr->iOffset); // start of the stream header
1532                 pb += sizeof(DWORD); // skip Reserved
1533                 *pb = VAL16(m_wMSVmajor)&0xFF;
1534                 *(pb+1) = VAL16(m_wMSVminor)&0xFF;
1535                 break;
1536             }
1537             pb = (BYTE*)pStr;
1538             pb += 2*sizeof(DWORD)+strlen(pStr->rcName)+1;
1539             pb = (BYTE*)(((size_t)pb + 3) & ~3);
1540             pStr = (PSTORAGESTREAM)pb;
1541         }
1542     }
1543
1544     if(m_fTolerateDupMethods) // means that there are /ENC files
1545     {
1546         if(m_pbsMD) delete m_pbsMD;
1547         m_pbsMD = new BinStr();
1548         memcpy(m_pbsMD->getBuff(metaDataSize),metaData,metaDataSize);
1549     }
1550     // actually output the resources
1551     if(mresourceSize && mresourceData)
1552     {
1553         size_t i, N = m_pManifest->m_dwMResNum, sizeread, L;
1554         BYTE    *ptr = (BYTE*)mresourceData;
1555         BOOL    mrfail = FALSE;
1556         FILE*   pFile = NULL;
1557         char sz[2048];
1558         for(i=0; i < N; i++)
1559         {
1560             m_pManifest->m_fMResNew[i] = FALSE;
1561             memset(sz,0,2048);
1562             WszWideCharToMultiByte(CP_ACP,0,m_pManifest->m_wzMResName[i],-1,sz,2047,NULL,NULL);
1563             L = m_pManifest->m_dwMResSize[i];
1564             sizeread = 0;
1565             memcpy(ptr,&L,sizeof(DWORD));
1566             ptr += sizeof(DWORD);
1567             if(fopen_s(&pFile,sz,"rb") == 0)
1568             {
1569                 sizeread = fread((void *)ptr,1,L,pFile);
1570                 fclose(pFile);
1571                 ptr += sizeread;
1572             }
1573             else
1574             {
1575                 report->msg("Error: failed to open mgd resource file '%ls'\n",m_pManifest->m_wzMResName[i]);
1576                 mrfail = TRUE;
1577             }
1578             if(sizeread < L)
1579             {
1580                 report->msg("Error: failed to read expected %d bytes from mgd resource file '%ls'\n",L,m_pManifest->m_wzMResName[i]);
1581                 mrfail = TRUE;
1582                 L -= sizeread;
1583                 memset(ptr,0,L);
1584                 ptr += L;
1585             }
1586         }
1587         if(mrfail)
1588         {
1589             hr = E_FAIL;
1590             goto exit;
1591         }
1592     }
1593     /*
1594     if((m_wRTVmajor < 0xFFFF)&&(m_wRTVminor < 0xFFFF))
1595     {
1596         IMAGE_COR20_HEADER* pCorH;
1597         if(FAILED(hr=m_pCeeFileGen->GetCorHeader(m_pCeeFile,&pCorH))) goto exit;
1598         pCorH->MajorRuntimeVersion = VAL16(m_wRTVmajor);
1599         pCorH->MinorRuntimeVersion = VAL16(m_wRTVminor);
1600     }
1601     */
1602     // Generate the file -- moved to main
1603     //if (FAILED(hr=m_pCeeFileGen->GenerateCeeFile(m_pCeeFile))) goto exit;
1604
1605
1606     hr = S_OK;
1607
1608 exit:
1609     return hr;
1610 }
1611 #ifdef _PREFAST_
1612 #pragma warning(pop)
1613 #endif