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// asmman.cpp - manifest info handling (implementation of class AsmMan, see asmman.hpp)
6//
7
8//
9#include "ilasmpch.h"
10
11#include "assembler.h"
12#include "strongname.h"
13#include <limits.h>
14#include <fusion.h>
15
16extern WCHAR* pwzInputFiles[];
17
18BinStr* BinStrToUnicode(BinStr* pSource, bool Swap)
19{
20 if(pSource)
21 {
22 pSource->appendInt8(0);
23 BinStr* tmp = new BinStr();
24 char* pb = (char*)(pSource->ptr());
25 int l=pSource->length(), L = sizeof(WCHAR)*l;
26 if(tmp)
27 {
28 WCHAR* wz = (WCHAR*)(tmp->getBuff(L));
29 if(wz)
30 {
31 memset(wz,0,L);
32 WszMultiByteToWideChar(g_uCodePage,0,pb,-1,wz,l);
33 tmp->remove(L-(DWORD)wcslen(wz)*sizeof(WCHAR));
34#if BIGENDIAN
35 if (Swap)
36 SwapStringLength(wz, (DWORD)wcslen(wz));
37#endif
38 delete pSource;
39 }
40 else
41 {
42 delete tmp;
43 tmp = NULL;
44 fprintf(stderr,"\nOut of memory!\n");
45 }
46 }
47 else
48 fprintf(stderr,"\nOut of memory!\n");
49 return tmp;
50 }
51 return NULL;
52}
53
54AsmManFile* AsmMan::GetFileByName(__in __nullterminated char* szFileName)
55{
56 AsmManFile* ret = NULL;
57 if(szFileName)
58 {
59 //AsmManFile X;
60 //X.szName = szFileName;
61 //ret = m_FileLst.FIND(&X);
62 //X.szName = NULL;
63 for(int i=0; (ret = m_FileLst.PEEK(i))&&strcmp(ret->szName,szFileName); i++);
64 }
65 return ret;
66}
67
68mdToken AsmMan::GetFileTokByName(__in __nullterminated char* szFileName)
69{
70 AsmManFile* tmp = GetFileByName(szFileName);
71 return(tmp ? tmp->tkTok : mdFileNil);
72}
73
74AsmManComType* AsmMan::GetComTypeByName(__in_opt __nullterminated char* szComTypeName,
75 __in_opt __nullterminated char* szComEnclosingTypeName)
76{
77 AsmManComType* ret = NULL;
78 if(szComTypeName)
79 {
80 //AsmManComType X;
81 //X.szName = szComTypeName;
82 //ret = m_ComTypeLst.FIND(&X);
83 //X.szName = NULL;
84 for(int i=0; (ret = m_ComTypeLst.PEEK(i)) != NULL; i++)
85 {
86 if (strcmp(ret->szName, szComTypeName) == 0)
87 {
88 if (ret->szComTypeName == NULL && szComEnclosingTypeName == NULL)
89 {
90 break;
91 }
92
93 if (ret->szComTypeName != NULL && szComEnclosingTypeName != NULL)
94 {
95 if (strcmp(ret->szComTypeName, szComEnclosingTypeName) == 0)
96 {
97 break;
98 }
99 }
100 }
101 }
102 }
103 return ret;
104}
105
106mdToken AsmMan::GetComTypeTokByName(
107 __in_opt __nullterminated char* szComTypeName,
108 __in_opt __nullterminated char* szComEnclosingTypeName)
109{
110 AsmManComType* tmp = GetComTypeByName(szComTypeName, szComEnclosingTypeName);
111 return(tmp ? tmp->tkTok : mdExportedTypeNil);
112}
113
114AsmManAssembly* AsmMan::GetAsmRefByName(__in __nullterminated const char* szAsmRefName)
115{
116 AsmManAssembly* ret = NULL;
117 if(szAsmRefName)
118 {
119 //AsmManAssembly X;
120 //X.szAlias = szAsmRefName;
121 //ret = m_AsmRefLst.FIND(&X);
122 //X.szAlias = NULL;
123 DWORD L = (DWORD)strlen(szAsmRefName);
124 for(int i=0; (ret = m_AsmRefLst.PEEK(i))&&
125 ((ret->dwAlias != L)||strcmp(ret->szAlias,szAsmRefName)); i++);
126 }
127 return ret;
128}
129mdToken AsmMan::GetAsmRefTokByName(__in __nullterminated const char* szAsmRefName)
130{
131 AsmManAssembly* tmp = GetAsmRefByName(szAsmRefName);
132 return(tmp ? tmp->tkTok : mdAssemblyRefNil);
133}
134AsmManAssembly* AsmMan::GetAsmRefByAsmName(__in __nullterminated const char* szAsmName)
135{
136 AsmManAssembly* ret = NULL;
137 if(szAsmName)
138 {
139 for(int i=0; (ret = m_AsmRefLst.PEEK(i))&&
140 (strcmp(ret->szName,szAsmName)); i++);
141 }
142 return ret;
143}
144
145//==============================================================================================================
146void AsmMan::SetModuleName(__inout_opt __nullterminated char* szName)
147{
148 if(m_szScopeName == NULL) // ignore all duplicate declarations
149 {
150 if(szName && *szName)
151 {
152 ULONG L = (ULONG)strlen(szName);
153 if(L >= MAX_SCOPE_LENGTH)
154 {
155 ((Assembler*)m_pAssembler)->report->warn("Module name too long (%d chars, max.allowed: %d chars), truncated\n",L,MAX_SCOPE_LENGTH-1);
156 szName[MAX_SCOPE_LENGTH-1] = 0;
157 }
158 m_szScopeName = szName;
159 strcpy_s(((Assembler*)m_pAssembler)->m_szScopeName, MAX_SCOPE_LENGTH, szName);
160 }
161 }
162}
163//==============================================================================================================
164
165void AsmMan::AddFile(__in __nullterminated char* szName, DWORD dwAttr, BinStr* pHashBlob)
166{
167 AsmManFile* tmp = GetFileByName(szName);
168 Assembler* pAsm = (Assembler*)m_pAssembler;
169 if(tmp==NULL)
170 {
171 tmp = new AsmManFile;
172 if(tmp==NULL)
173 {
174 pAsm->report->error("\nOut of memory!\n");
175 return;
176 }
177 memset(tmp,0,sizeof(AsmManFile));
178 if((dwAttr & 0x80000000)!=0) pAsm->m_fEntryPointPresent = TRUE;
179 tmp->szName = szName;
180 tmp->dwAttr = dwAttr;
181 tmp->pHash = pHashBlob;
182 tmp->m_fNew = TRUE;
183 m_FileLst.PUSH(tmp);
184 tmp->tkTok = TokenFromRid(m_FileLst.COUNT(),mdtFile);
185 }
186 pAsm->m_tkCurrentCVOwner = 0;
187 if(tmp) pAsm->m_pCustomDescrList = &(tmp->m_CustomDescrList);
188}
189//==============================================================================================================
190
191void AsmMan::EmitFiles()
192{
193 AsmManFile* tmp;
194 Assembler* pAsm = (Assembler*)m_pAssembler;
195 int i;
196 HRESULT hr = S_OK;
197 mdToken tk;
198 for(i = 0; (tmp=m_FileLst.PEEK(i)) != NULL; i++)
199 {
200 BOOL fEntry = ((tmp->dwAttr & 0x80000000)!=0);
201
202 wzUniBuf[0] = 0;
203
204 BYTE* pHash=NULL;
205 DWORD cbHash= 0;
206
207 if(!tmp->m_fNew) continue;
208 tmp->m_fNew = FALSE;
209
210 WszMultiByteToWideChar(g_uCodePage,0,tmp->szName,-1,wzUniBuf,dwUniBuf);
211 if(tmp->pHash==NULL) // if hash not explicitly specified
212 {
213 if(m_pAssembly // and assembly is defined
214 && m_pAssembly->ulHashAlgorithm) // and hash algorithm is defined...
215 { // then try to compute it
216 {
217 pHash = NULL;
218 cbHash = 0;
219 }
220 }
221 }
222 else
223 {
224 pHash = tmp->pHash->ptr();
225 cbHash = tmp->pHash->length();
226 }
227
228 hr = m_pAsmEmitter->DefineFile(wzUniBuf,
229 (const void*)pHash,
230 cbHash,
231 tmp->dwAttr & 0x7FFFFFFF,
232 (mdFile*)&tk);
233 _ASSERTE(tk == tmp->tkTok);
234 if(FAILED(hr)) report->error("Failed to define file '%s': 0x%08X\n",tmp->szName,hr);
235 else
236 {
237 if(fEntry)
238 {
239 if (FAILED(pAsm->m_pCeeFileGen->SetEntryPoint(pAsm->m_pCeeFile, tmp->tkTok)))
240 {
241 pAsm->report->error("Failed to set external entry point for file '%s'\n",tmp->szName);
242 }
243 }
244 pAsm->EmitCustomAttributes(tmp->tkTok, &(tmp->m_CustomDescrList));
245 }
246 } //end for(i = 0; tmp=m_FileLst.PEEK(i); i++)
247}
248
249void AsmMan::StartAssembly(__in __nullterminated char* szName, __in_opt __nullterminated char* szAlias, DWORD dwAttr, BOOL isRef)
250{
251 if(!isRef && (0==strcmp(szName, "mscorlib"))) ((Assembler*)m_pAssembler)->m_fIsMscorlib = TRUE;
252 if(!isRef && (m_pAssembly != NULL))
253 {
254 if(strcmp(szName, m_pAssembly->szName))
255 report->error("Multiple assembly declarations\n");
256 // if name is the same, just ignore it
257 m_pCurAsmRef = NULL;
258 }
259 else
260 {
261 if((m_pCurAsmRef = new AsmManAssembly))
262 {
263 memset(m_pCurAsmRef,0,sizeof(AsmManAssembly));
264 m_pCurAsmRef->usVerMajor = (USHORT)0xFFFF;
265 m_pCurAsmRef->usVerMinor = (USHORT)0xFFFF;
266 m_pCurAsmRef->usBuild = (USHORT)0xFFFF;
267 m_pCurAsmRef->usRevision = (USHORT)0xFFFF;
268 m_pCurAsmRef->szName = szName;
269 m_pCurAsmRef->szAlias = szAlias ? szAlias : szName;
270 m_pCurAsmRef->dwAlias = (DWORD)strlen(m_pCurAsmRef->szAlias);
271 m_pCurAsmRef->dwAttr = dwAttr;
272 m_pCurAsmRef->isRef = isRef;
273 m_pCurAsmRef->isAutodetect = FALSE;
274 m_pCurAsmRef->m_fNew = TRUE;
275 if(!isRef) m_pAssembly = m_pCurAsmRef;
276 }
277 else
278 report->error("Failed to allocate AsmManAssembly structure\n");
279 }
280 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
281 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
282 ((Assembler*)m_pAssembler)->m_pCustomDescrList = m_pCurAsmRef ? &(m_pCurAsmRef->m_CustomDescrList) : NULL;
283
284}
285// copied from asmparse.y
286static void corEmitInt(BinStr* buff, unsigned data)
287{
288 unsigned cnt = CorSigCompressData(data, buff->getBuff(5));
289 buff->remove(5 - cnt);
290}
291
292void AsmMan::EmitDebuggableAttribute(mdToken tkOwner)
293{
294 mdToken tkCA;
295 Assembler* pAsm = (Assembler*)m_pAssembler;
296 mdToken tkTypeSpec, tkMscorlib, tkParamType;
297 BinStr *pbsSig = new BinStr();
298 BinStr* bsBytes = new BinStr();;
299 char* szName;
300 tkMscorlib = pAsm->m_fIsMscorlib ? 1 : pAsm->GetBaseAsmRef();
301 tkTypeSpec = pAsm->ResolveClassRef(tkMscorlib,"System.Diagnostics.DebuggableAttribute",NULL);
302
303 EmitAssemblyRefs(); // just in case we gained 'mscorlib' AsmRef in GetAsmRef above
304
305 BOOL fOldStyle = FALSE;
306 if(tkMscorlib == 1)
307 fOldStyle = (m_pAssembly->usVerMajor == 1);
308 else
309 {
310 AsmManAssembly *pAssembly = GetAsmRefByName("mscorlib");
311 if(pAssembly != NULL)
312 {
313 fOldStyle = (pAssembly->usVerMajor == 1);
314 }
315 }
316
317 bsBytes->appendInt8(1);
318 bsBytes->appendInt8(0);
319 if(fOldStyle)
320 {
321 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
322 corEmitInt(pbsSig,2);
323 pbsSig->appendInt8(ELEMENT_TYPE_VOID);
324 pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN);
325 pbsSig->appendInt8(ELEMENT_TYPE_BOOLEAN);
326
327 //New to old: 0x101->(true,true),0x03->(true,false),0x103->(true,true)+warning
328 bsBytes->appendInt8(1);
329 bsBytes->appendInt8((pAsm->m_dwIncludeDebugInfo==0x03 ? 0 : 1));
330 if(pAsm->m_dwIncludeDebugInfo == 0x103)
331 {
332 report->warn("\nOption /DEBUG=IMPL is invalid for legacy DebuggableAttribute, /DEBUG used.\n" );
333 }
334 }
335 else
336 {
337 BinStr bsSigArg;
338 char buffer[80];
339 sprintf_s(buffer,80,
340 "%s%c%s",
341 "System.Diagnostics.DebuggableAttribute",
342 NESTING_SEP,
343 "DebuggingModes"
344 );
345
346 tkParamType = pAsm->ResolveClassRef(tkMscorlib,buffer, NULL);
347
348 bsSigArg.appendInt8(ELEMENT_TYPE_VALUETYPE);
349
350 unsigned cnt = CorSigCompressToken(tkParamType, bsSigArg.getBuff(5));
351 bsSigArg.remove(5 - cnt);
352
353 pbsSig->appendInt8(IMAGE_CEE_CS_CALLCONV_HASTHIS);
354 corEmitInt(pbsSig,1);
355 pbsSig->appendInt8(ELEMENT_TYPE_VOID);
356 pbsSig->append(&bsSigArg);
357
358 bsBytes->appendInt32(pAsm->m_dwIncludeDebugInfo);
359 }
360 bsBytes->appendInt8(0);
361 bsBytes->appendInt8(0);
362
363 szName = new char[16];
364 strcpy_s(szName,16,".ctor");
365 tkCA = pAsm->MakeMemberRef(tkTypeSpec,szName,pbsSig);
366 pAsm->DefineCV(new CustomDescr(tkOwner,tkCA,bsBytes));
367}
368
369void AsmMan::EndAssembly()
370{
371 if(m_pCurAsmRef)
372 {
373 if(m_pCurAsmRef->isRef)
374 { // list the assembly ref
375 if(GetAsmRefByName(m_pCurAsmRef->szAlias))
376 {
377 //report->warn("Multiple declarations of Assembly Ref '%s', ignored except the 1st one\n",m_pCurAsmRef->szName);
378 delete m_pCurAsmRef;
379 m_pCurAsmRef = NULL;
380 return;
381 }
382 m_AsmRefLst.PUSH(m_pCurAsmRef);
383 m_pCurAsmRef->tkTok = TokenFromRid(m_AsmRefLst.COUNT(),mdtAssemblyRef);
384 }
385 else
386 {
387 HRESULT hr = S_OK;
388 m_pCurAsmRef->tkTok = TokenFromRid(1,mdtAssembly);
389
390 // Determine the strong name public key. This may have been set
391 // via a directive in the source or from the command line (which
392 // overrides the directive). From the command line we may have
393 // been provided with a file or the name of a CAPI key
394 // container. Either may contain a public key or a full key
395 // pair.
396 if (((Assembler*)m_pAssembler)->m_wzKeySourceName)
397 {
398 // Key file versus container is determined by the first
399 // character of the source ('@' for container).
400 if (*(((Assembler*)m_pAssembler)->m_wzKeySourceName) == L'@')
401 {
402 report->error("Error: ilasm on CoreCLR does not support getting public key from container.\n");
403 m_pCurAsmRef = NULL;
404 return;
405 }
406 else
407 {
408 // Read public key or key pair from file.
409 HANDLE hFile = WszCreateFile(((Assembler*)m_pAssembler)->m_wzKeySourceName,
410 GENERIC_READ,
411 FILE_SHARE_READ,
412 NULL,
413 OPEN_EXISTING,
414 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
415 NULL);
416 if(hFile == INVALID_HANDLE_VALUE)
417 {
418 hr = GetLastError();
419 report->error("Failed to open key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
420 m_pCurAsmRef = NULL;
421 return;
422 }
423
424 // Determine file size and allocate an appropriate buffer.
425 m_sStrongName.m_cbPublicKey = SafeGetFileSize(hFile, NULL);
426 if (m_sStrongName.m_cbPublicKey == 0xffffffff) {
427 report->error("File size too large\n");
428 m_pCurAsmRef = NULL;
429 CloseHandle(hFile);
430 return;
431 }
432
433 m_sStrongName.m_pbPublicKey = new BYTE[m_sStrongName.m_cbPublicKey];
434 if (m_sStrongName.m_pbPublicKey == NULL) {
435 report->error("Failed to allocate key buffer\n");
436 m_pCurAsmRef = NULL;
437 CloseHandle(hFile);
438 return;
439 }
440 m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::AllocatedByNew;
441
442 // Read the file into the buffer.
443 DWORD dwBytesRead;
444 if (!ReadFile(hFile, m_sStrongName.m_pbPublicKey, m_sStrongName.m_cbPublicKey, &dwBytesRead, NULL)) {
445 hr = GetLastError();
446 report->error("Failed to read key file '%S': 0x%08X\n",((Assembler*)m_pAssembler)->m_wzKeySourceName,hr);
447 m_pCurAsmRef = NULL;
448 CloseHandle(hFile);
449 return;
450 }
451
452 CloseHandle(hFile);
453
454 // Guess whether we're full or delay signing based on
455 // whether the blob passed to us looks like a public
456 // key. (I.e. we may just have copied a full key pair
457 // into the public key buffer).
458 if (m_sStrongName.m_cbPublicKey >= sizeof(PublicKeyBlob) &&
459 (offsetof(PublicKeyBlob, PublicKey) +
460 ((PublicKeyBlob*)m_sStrongName.m_pbPublicKey)->cbPublicKey) == m_sStrongName.m_cbPublicKey)
461 m_sStrongName.m_fFullSign = FALSE;
462 else
463 m_sStrongName.m_fFullSign = TRUE;
464
465 // If we really have a key pair, we'll move it into a
466 // key container so the signing code gets the key pair
467 // from a consistent place.
468 if (m_sStrongName.m_fFullSign)
469 {
470 report->error("Error: ilasm on CoreCLR does not support full sign.\n");
471 m_pCurAsmRef = NULL;
472 return;
473 }
474 }
475 }
476 else
477 {
478 if (m_pAssembly->pPublicKey)
479 {
480 m_sStrongName.m_pbPublicKey = m_pAssembly->pPublicKey->ptr();
481 m_sStrongName.m_cbPublicKey = m_pAssembly->pPublicKey->length();
482 }
483 else
484 {
485 m_sStrongName.m_pbPublicKey = NULL;
486 m_sStrongName.m_cbPublicKey = 0;
487 }
488
489 m_sStrongName.m_wzKeyContainer = NULL;
490 m_sStrongName.m_fFullSign = FALSE;
491 m_sStrongName.m_dwPublicKeyAllocated = AsmManStrongName::NotAllocated;
492 }
493 }
494 m_pCurAsmRef = NULL;
495 }
496 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
497}
498
499void FillAssemblyMetadata(AsmManAssembly *pAsm, ASSEMBLYMETADATA *pmd)
500{
501 pmd->usMajorVersion = pAsm->usVerMajor;
502 pmd->usMinorVersion = pAsm->usVerMinor;
503 pmd->usBuildNumber = pAsm->usBuild;
504 pmd->usRevisionNumber = pAsm->usRevision;
505 if(pmd->usMajorVersion == 0xFFFF) pmd->usMajorVersion = 0;
506 if(pmd->usMinorVersion == 0xFFFF) pmd->usMinorVersion = 0;
507 if(pmd->usBuildNumber == 0xFFFF) pmd->usBuildNumber = 0;
508 if(pmd->usRevisionNumber == 0xFFFF) pmd->usRevisionNumber = 0;
509
510 if(pAsm->pLocale != NULL)
511 {
512 pmd->szLocale = (LPWSTR)(pAsm->pLocale->ptr());
513 pmd->cbLocale = pAsm->pLocale->length()/((ULONG)sizeof(WCHAR));
514 }
515 else
516 {
517 pmd->szLocale = NULL;
518 pmd->cbLocale = 0;
519 }
520
521 pmd->rProcessor = NULL;
522 pmd->rOS = NULL;
523 pmd->ulProcessor = 0;
524 pmd->ulOS = 0;
525}
526
527void AsmMan::EmitAssemblyRefs()
528{
529 int i;
530 HRESULT hr = S_OK;
531 ASSEMBLYMETADATA md;
532 mdToken tk;
533
534 for(i=0; (m_pCurAsmRef=m_AsmRefLst.PEEK(i)) != NULL; i++)
535 {
536 if(!m_pCurAsmRef->m_fNew) continue;
537 m_pCurAsmRef->m_fNew = FALSE;
538
539 wzUniBuf[0] = 0;
540 FillAssemblyMetadata(m_pCurAsmRef,&md);
541
542 // See if we've got a full public key or the tokenized version (or neither).
543 BYTE *pbPublicKeyOrToken = NULL;
544 DWORD cbPublicKeyOrToken = 0;
545 DWORD dwFlags = m_pCurAsmRef->dwAttr;
546 if (m_pCurAsmRef->pPublicKeyToken)
547 {
548 pbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->ptr();
549 cbPublicKeyOrToken = m_pCurAsmRef->pPublicKeyToken->length();
550
551 }
552 else if (m_pCurAsmRef->pPublicKey)
553 {
554 pbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->ptr();
555 cbPublicKeyOrToken = m_pCurAsmRef->pPublicKey->length();
556 dwFlags |= afPublicKey;
557 }
558 // Convert name to Unicode
559 WszMultiByteToWideChar(g_uCodePage,0,m_pCurAsmRef->szName,-1,wzUniBuf,dwUniBuf);
560 hr = m_pAsmEmitter->DefineAssemblyRef( // S_OK or error.
561 pbPublicKeyOrToken, // [IN] Public key or token of the assembly.
562 cbPublicKeyOrToken, // [IN] Count of bytes in the key or token.
563 (LPCWSTR)wzUniBuf, // [IN] Name of the assembly being referenced.
564 (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData.
565 (m_pCurAsmRef->pHashBlob ? (const void*)(m_pCurAsmRef->pHashBlob->ptr()) : NULL), // [IN] Hash Blob.
566 (m_pCurAsmRef->pHashBlob ? m_pCurAsmRef->pHashBlob->length() : 0), // [IN] Count of bytes in the Hash Blob.
567 dwFlags, // [IN] Flags.
568 (mdAssemblyRef*)&tk); // [OUT] Returned AssemblyRef token.
569 if(m_pCurAsmRef->tkTok != tk)
570 {
571 report->error("AsmRef'%S' tok %8.8X -> %8.8X\n",wzUniBuf,m_pCurAsmRef->tkTok,tk);
572 }
573 if(FAILED(hr)) report->error("Failed to define assembly ref '%s': 0x%08X\n",m_pCurAsmRef->szName,hr);
574 else
575 {
576 ((Assembler*)m_pAssembler)->EmitCustomAttributes(m_pCurAsmRef->tkTok, &(m_pCurAsmRef->m_CustomDescrList));
577 }
578 } // end for(i=0; m_pCurAsmRef=m_AsmRefLst.PEEK(i); i++)
579}
580
581void AsmMan::EmitAssembly()
582{
583 HRESULT hr = S_OK;
584 ASSEMBLYMETADATA md;
585
586 wzUniBuf[0] = 0;
587 if(m_pAssembly == NULL) return;
588 if(!m_pAssembly->m_fNew) return;
589 m_pAssembly->m_fNew = FALSE;
590
591 FillAssemblyMetadata(m_pAssembly, &md);
592
593 // Convert name to Unicode
594 WszMultiByteToWideChar(g_uCodePage,0,m_pAssembly->szName,-1,wzUniBuf,dwUniBuf);
595
596 hr = m_pAsmEmitter->DefineAssembly( // S_OK or error.
597 (const void*)(m_sStrongName.m_pbPublicKey), // [IN] Public key of the assembly.
598 m_sStrongName.m_cbPublicKey, // [IN] Count of bytes in the public key.
599 m_pAssembly->ulHashAlgorithm, // [IN] Hash algorithm used to hash the files.
600 (LPCWSTR)wzUniBuf, // [IN] Name of the assembly.
601 (const ASSEMBLYMETADATA*)&md, // [IN] Assembly MetaData.
602 m_pAssembly->dwAttr, // [IN] Flags.
603 (mdAssembly*)&(m_pAssembly->tkTok)); // [OUT] Returned Assembly token.
604
605 if(FAILED(hr)) report->error("Failed to define assembly '%s': 0x%08X\n",m_pAssembly->szName,hr);
606 else
607 {
608 Assembler* pAsm = ((Assembler*)m_pAssembler);
609 pAsm->EmitSecurityInfo(m_pAssembly->tkTok,
610 m_pAssembly->m_pPermissions,
611 m_pAssembly->m_pPermissionSets);
612 if(pAsm->m_dwIncludeDebugInfo)
613 {
614 EmitDebuggableAttribute(m_pAssembly->tkTok);
615 }
616 pAsm->EmitCustomAttributes(m_pAssembly->tkTok, &(m_pAssembly->m_CustomDescrList));
617 }
618}
619
620void AsmMan::SetAssemblyPublicKey(BinStr* pPublicKey)
621{
622 if(m_pCurAsmRef)
623 {
624 m_pCurAsmRef->pPublicKey = pPublicKey;
625 }
626}
627
628void AsmMan::SetAssemblyPublicKeyToken(BinStr* pPublicKeyToken)
629{
630 if(m_pCurAsmRef)
631 {
632 m_pCurAsmRef->pPublicKeyToken = pPublicKeyToken;
633 }
634}
635
636void AsmMan::SetAssemblyHashAlg(ULONG ulAlgID)
637{
638 if(m_pCurAsmRef)
639 {
640 m_pCurAsmRef->ulHashAlgorithm = ulAlgID;
641 }
642}
643
644void AsmMan::SetAssemblyVer(USHORT usMajor, USHORT usMinor, USHORT usBuild, USHORT usRevision)
645{
646 if(m_pCurAsmRef)
647 {
648 m_pCurAsmRef->usVerMajor = usMajor;
649 m_pCurAsmRef->usVerMinor = usMinor;
650 m_pCurAsmRef->usBuild = usBuild;
651 m_pCurAsmRef->usRevision = usRevision;
652 }
653}
654
655void AsmMan::SetAssemblyLocale(BinStr* pLocale, BOOL bConvertToUnicode)
656{
657 if(m_pCurAsmRef)
658 {
659 m_pCurAsmRef->pLocale = bConvertToUnicode ? ::BinStrToUnicode(pLocale) : pLocale;
660 }
661}
662
663void AsmMan::SetAssemblyHashBlob(BinStr* pHashBlob)
664{
665 if(m_pCurAsmRef)
666 {
667 m_pCurAsmRef->pHashBlob = pHashBlob;
668 }
669}
670
671void AsmMan::SetAssemblyAutodetect()
672{
673 if(m_pCurAsmRef)
674 {
675 m_pCurAsmRef->isAutodetect = TRUE;
676 }
677}
678
679void AsmMan::StartComType(__in __nullterminated char* szName, DWORD dwAttr)
680{
681 if((m_pCurComType = new AsmManComType))
682 {
683 memset(m_pCurComType,0,sizeof(AsmManComType));
684 m_pCurComType->szName = szName;
685 m_pCurComType->dwAttr = dwAttr;
686 m_pCurComType->m_fNew = TRUE;
687 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
688 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
689 ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurComType->m_CustomDescrList);
690 }
691 else
692 report->error("Failed to allocate AsmManComType structure\n");
693}
694
695void AsmMan::EndComType()
696{
697 if(m_pCurComType)
698 {
699 if(m_pAssembler)
700 {
701 Class* pClass =((Assembler*)m_pAssembler)->m_pCurClass;
702 if(pClass)
703 {
704 m_pCurComType->tkClass = pClass->m_cl;
705 if(pClass->m_pEncloser)
706 {
707 mdTypeDef tkEncloser = pClass->m_pEncloser->m_cl;
708 AsmManComType* pCT;
709 for(unsigned i=0; (pCT=m_ComTypeLst.PEEK(i)); i++)
710 {
711 if(pCT->tkClass == tkEncloser)
712 {
713 m_pCurComType->szComTypeName = pCT->szName;
714 break;
715 }
716 }
717 }
718 }
719 }
720
721 if (IsTdNested(m_pCurComType->dwAttr) && GetComTypeByName(m_pCurComType->szName, m_pCurComType->szComTypeName) != NULL)
722 {
723 report->error("Invalid TypeDefID of exported type\n");
724 delete m_pCurComType;
725 }
726 else
727 {
728 m_ComTypeLst.PUSH(m_pCurComType);
729 }
730
731 m_pCurComType = NULL;
732 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
733 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
734 }
735}
736
737void AsmMan::SetComTypeFile(__in __nullterminated char* szFileName)
738{
739 if(m_pCurComType)
740 {
741 m_pCurComType->szFileName = szFileName;
742 }
743}
744
745void AsmMan::SetComTypeAsmRef(__in __nullterminated char* szAsmRefName)
746{
747 if(m_pCurComType)
748 {
749 m_pCurComType->szAsmRefName = szAsmRefName;
750 }
751}
752
753void AsmMan::SetComTypeComType(__in __nullterminated char* szComTypeName)
754{
755 if(m_pCurComType)
756 {
757 m_pCurComType->szComTypeName = szComTypeName;
758 }
759}
760BOOL AsmMan::SetComTypeImplementationTok(mdToken tk)
761{
762 if(m_pCurComType)
763 {
764 switch(TypeFromToken(tk))
765 {
766 case mdtAssemblyRef:
767 case mdtExportedType:
768 case mdtFile:
769 m_pCurComType->tkImpl = tk;
770 return TRUE;
771 }
772 }
773 return FALSE;
774}
775BOOL AsmMan::SetComTypeClassTok(mdToken tkClass)
776{
777 if((m_pCurComType)&&(TypeFromToken(tkClass)==mdtTypeDef))
778 {
779 m_pCurComType->tkClass = tkClass;
780 return TRUE;
781 }
782 return FALSE;
783}
784
785void AsmMan::StartManifestRes(__in __nullterminated char* szName, __in __nullterminated char* szAlias, DWORD dwAttr)
786{
787 if((m_pCurManRes = new AsmManRes))
788 {
789 m_pCurManRes->szName = szName;
790 m_pCurManRes->szAlias = szAlias;
791 m_pCurManRes->dwAttr = dwAttr;
792 m_pCurManRes->m_fNew = TRUE;
793 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
794 ((Assembler*)m_pAssembler)->m_CustomDescrListStack.PUSH(((Assembler*)m_pAssembler)->m_pCustomDescrList);
795 ((Assembler*)m_pAssembler)->m_pCustomDescrList = &(m_pCurManRes->m_CustomDescrList);
796 }
797 else
798 report->error("Failed to allocate AsmManRes structure\n");
799}
800
801void AsmMan::EndManifestRes()
802{
803 if(m_pCurManRes)
804 {
805 m_ManResLst.PUSH(m_pCurManRes);
806 m_pCurManRes = NULL;
807 ((Assembler*)m_pAssembler)->m_tkCurrentCVOwner = 0;
808 ((Assembler*)m_pAssembler)->m_pCustomDescrList = ((Assembler*)m_pAssembler)->m_CustomDescrListStack.POP();
809 }
810}
811
812
813void AsmMan::SetManifestResFile(__in __nullterminated char* szFileName, ULONG ulOffset)
814{
815 if(m_pCurManRes)
816 {
817 m_pCurManRes->szFileName = szFileName;
818 m_pCurManRes->ulOffset = ulOffset;
819 }
820}
821
822void AsmMan::SetManifestResAsmRef(__in __nullterminated char* szAsmRefName)
823{
824 if(m_pCurManRes)
825 {
826 m_pCurManRes->szAsmRefName = szAsmRefName;
827 }
828}
829
830HRESULT AsmMan::EmitManifest()
831{
832 //AsmManAssembly* pAsmRef;
833 AsmManComType* pComType;
834 AsmManRes* pManRes;
835 HRESULT hr = S_OK;
836
837 wzUniBuf[0] = 0;
838
839 if(m_pAsmEmitter==NULL)
840 hr=m_pEmitter->QueryInterface(IID_IMetaDataAssemblyEmit, (void**) &m_pAsmEmitter);
841
842 if(SUCCEEDED(hr))
843 {
844 EmitFiles();
845 EmitAssembly();
846
847 if((((Assembler*)m_pAssembler)->m_dwIncludeDebugInfo != 0) && (m_pAssembly == NULL)
848 && !(((Assembler*)m_pAssembler)->m_fENCMode))
849 {
850 mdToken tkOwner, tkMscorlib;
851 tkMscorlib = ((Assembler*)m_pAssembler)->GetAsmRef("mscorlib");
852 tkOwner = ((Assembler*)m_pAssembler)->ResolveClassRef(tkMscorlib,
853 "System.Runtime.CompilerServices.AssemblyAttributesGoHere",
854 NULL);
855 EmitDebuggableAttribute(tkOwner);
856 }
857
858 // Emit all com types
859 unsigned i;
860 for(i = 0; (pComType = m_ComTypeLst.PEEK(i)); i++)
861 {
862 if(!pComType->m_fNew) continue;
863 pComType->m_fNew = FALSE;
864
865 WszMultiByteToWideChar(g_uCodePage,0,pComType->szName,-1,wzUniBuf,dwUniBuf);
866 mdToken tkImplementation = mdTokenNil;
867 if(pComType->tkImpl) tkImplementation = pComType->tkImpl;
868 else if(pComType->szFileName)
869 {
870 tkImplementation = GetFileTokByName(pComType->szFileName);
871 if(tkImplementation==mdFileNil)
872 {
873 report->error("Undefined File '%s' in ExportedType '%s'\n",pComType->szFileName,pComType->szName);
874 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
875 }
876 }
877 else if(pComType->szAsmRefName)
878 {
879 tkImplementation = GetAsmRefTokByName(pComType->szAsmRefName);
880 if(RidFromToken(tkImplementation)==0)
881 {
882 report->error("Undefined AssemblyRef '%s' in ExportedType '%s'\n",pComType->szAsmRefName,pComType->szName);
883 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
884 }
885 }
886 else if(pComType->szComTypeName)
887 {
888 char* szLastName = strrchr(pComType->szComTypeName, NESTING_SEP);
889
890 if(szLastName)
891 {
892 *szLastName = 0;
893 szLastName ++;
894 tkImplementation = GetComTypeTokByName(szLastName, pComType->szComTypeName);
895 *(szLastName-1) = NESTING_SEP; // not really necessary
896 }
897
898 else
899 {
900 tkImplementation = GetComTypeTokByName(pComType->szComTypeName);
901 }
902
903 if(tkImplementation==mdExportedTypeNil)
904 {
905 report->error("Undefined ExportedType '%s' in ExportedType '%s'\n",pComType->szComTypeName,pComType->szName);
906 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
907 }
908 }
909 else
910 {
911 report->warn("Undefined implementation in ExportedType '%s' -- ExportType not emitted\n",pComType->szName);
912 if(!((Assembler*)m_pAssembler)->OnErrGo) continue;
913 }
914 hr = m_pAsmEmitter->DefineExportedType( // S_OK or error.
915 (LPCWSTR)wzUniBuf, // [IN] Name of the Com Type.
916 tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the ComType.
917 (mdTypeDef)pComType->tkClass, // [IN] TypeDef token within the file.
918 pComType->dwAttr, // [IN] Flags.
919 (mdExportedType*)&(pComType->tkTok)); // [OUT] Returned ComType token.
920 if(FAILED(hr)) report->error("Failed to define ExportedType '%s': 0x%08X\n",pComType->szName,hr);
921 else
922 {
923 ((Assembler*)m_pAssembler)->EmitCustomAttributes(pComType->tkTok, &(pComType->m_CustomDescrList));
924 }
925 }
926
927 // Emit all manifest resources
928 m_dwMResSizeTotal = 0;
929 m_dwMResNum = 0;
930 for(i = 0; (pManRes = m_ManResLst.PEEK(i)); i++)
931 {
932 BOOL fOK = TRUE;
933 mdToken tkImplementation = mdFileNil;
934
935 if(!pManRes->m_fNew) continue;
936 pManRes->m_fNew = FALSE;
937
938 WszMultiByteToWideChar(g_uCodePage,0,pManRes->szAlias,-1,wzUniBuf,dwUniBuf);
939 if(pManRes->szAsmRefName)
940 {
941 tkImplementation = GetAsmRefTokByName(pManRes->szAsmRefName);
942 if(RidFromToken(tkImplementation)==0)
943 {
944 report->error("Undefined AssemblyRef '%s' in MResource '%s'\n",pManRes->szAsmRefName,pManRes->szName);
945 fOK = FALSE;
946 }
947 }
948 else if(pManRes->szFileName)
949 {
950 tkImplementation = GetFileTokByName(pManRes->szFileName);
951 if(RidFromToken(tkImplementation)==0)
952 {
953 report->error("Undefined File '%s' in MResource '%s'\n",pManRes->szFileName,pManRes->szName);
954 fOK = FALSE;
955 }
956 }
957 else // embedded mgd.resource, go after the file
958 {
959 HANDLE hFile = INVALID_HANDLE_VALUE;
960 int j;
961 WCHAR wzFileName[2048];
962 WCHAR* pwz;
963
964 pManRes->ulOffset = m_dwMResSizeTotal;
965 for(j=0; (hFile == INVALID_HANDLE_VALUE)&&(pwzInputFiles[j] != NULL); j++)
966 {
967 wcscpy_s(wzFileName,2048,pwzInputFiles[j]);
968 pwz = wcsrchr(wzFileName,'\\');
969 if(pwz == NULL) pwz = wcsrchr(wzFileName,':');
970 if(pwz == NULL) pwz = &wzFileName[0];
971 else pwz++;
972 wcscpy_s(pwz,2048-(pwz-wzFileName),wzUniBuf);
973 hFile = WszCreateFile(wzFileName, GENERIC_READ, FILE_SHARE_READ,
974 0, OPEN_EXISTING, 0, 0);
975 }
976 if (hFile == INVALID_HANDLE_VALUE)
977 {
978 report->error("Failed to open managed resource file '%s'\n",pManRes->szAlias);
979 fOK = FALSE;
980 }
981 else
982 {
983 if (m_dwMResNum >= MAX_MANIFEST_RESOURCES)
984 {
985 report->error("Too many resources (implementation limit: %d); skipping file '%s'\n",MAX_MANIFEST_RESOURCES,pManRes->szAlias);
986 fOK = FALSE;
987 }
988 else
989 {
990 m_dwMResSize[m_dwMResNum] = SafeGetFileSize(hFile,NULL);
991 if(m_dwMResSize[m_dwMResNum] == 0xFFFFFFFF)
992 {
993 report->error("Failed to get size of managed resource file '%s'\n",pManRes->szAlias);
994 fOK = FALSE;
995 }
996 else
997 {
998 m_dwMResSizeTotal += m_dwMResSize[m_dwMResNum]+sizeof(DWORD);
999 m_wzMResName[m_dwMResNum] = new WCHAR[wcslen(wzFileName)+1];
1000 wcscpy_s(m_wzMResName[m_dwMResNum],wcslen(wzFileName)+1,wzFileName);
1001 m_fMResNew[m_dwMResNum] = TRUE;
1002 m_dwMResNum++;
1003 }
1004 CloseHandle(hFile);
1005 }
1006 }
1007 }
1008 if(fOK || ((Assembler*)m_pAssembler)->OnErrGo)
1009 {
1010 WszMultiByteToWideChar(g_uCodePage,0,pManRes->szName,-1,wzUniBuf,dwUniBuf);
1011 hr = m_pAsmEmitter->DefineManifestResource( // S_OK or error.
1012 (LPCWSTR)wzUniBuf, // [IN] Name of the resource.
1013 tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource.
1014 pManRes->ulOffset, // [IN] Offset to the beginning of the resource within the file.
1015 pManRes->dwAttr, // [IN] Flags.
1016 (mdManifestResource*)&(pManRes->tkTok)); // [OUT] Returned ManifestResource token.
1017 if(FAILED(hr))
1018 report->error("Failed to define manifest resource '%s': 0x%08X\n",pManRes->szName,hr);
1019 }
1020 }
1021
1022
1023 m_pAsmEmitter->Release();
1024 m_pAsmEmitter = NULL;
1025 }
1026 else
1027 report->error("Failed to obtain IMetaDataAssemblyEmit interface: 0x%08X\n",hr);
1028 return hr;
1029}
1030
1031