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// Emit.cpp
6//
7
8//
9// Implementation for the meta data emit code.
10//
11//*****************************************************************************
12#include "stdafx.h"
13#include "regmeta.h"
14#include "mdutil.h"
15#include "rwutil.h"
16#include "mdlog.h"
17#include "importhelper.h"
18
19#ifdef FEATURE_METADATA_EMIT
20
21#ifdef _MSC_VER
22#pragma warning(disable: 4102)
23#endif
24
25//*****************************************************************************
26// Create and set a new MethodDef record.
27//*****************************************************************************
28STDMETHODIMP RegMeta::DefineMethod( // S_OK or error.
29 mdTypeDef td, // Parent TypeDef
30 LPCWSTR szName, // Name of member
31 DWORD dwMethodFlags, // Member attributes
32 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
33 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
34 ULONG ulCodeRVA,
35 DWORD dwImplFlags,
36 mdMethodDef *pmd) // Put member token here
37{
38#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
39 return E_NOTIMPL;
40#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
41 HRESULT hr = S_OK;
42
43 BEGIN_ENTRYPOINT_NOTHROW;
44
45 MethodRec *pRecord = NULL; // The new record.
46 RID iRecord; // The new record's RID.
47 LPUTF8 szNameUtf8;
48 UTF8STR(szName, szNameUtf8);
49
50 LOG((LOGMD, "MD: RegMeta::DefineMethod(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
51 td, MDSTR(szName), dwMethodFlags, pvSigBlob, cbSigBlob, ulCodeRVA, dwImplFlags, pmd));
52 START_MD_PERF();
53
54 LOCKWRITE();
55
56 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
57
58 _ASSERTE(pmd);
59
60 // Make sure no one sets the reserved bits on the way in.
61 dwMethodFlags &= (~mdReservedMask);
62
63 IsGlobalMethodParent(&td);
64
65 // See if this method has already been defined.
66 if (CheckDups(MDDupMethodDef))
67 {
68 hr = ImportHelper::FindMethod(
69 &(m_pStgdb->m_MiniMd),
70 td,
71 szNameUtf8,
72 pvSigBlob,
73 cbSigBlob,
74 pmd);
75
76 if (SUCCEEDED(hr))
77 {
78 if (IsENCOn())
79 {
80 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(*pmd), &pRecord));
81 }
82 else
83 {
84 hr = META_S_DUPLICATE;
85 goto ErrExit;
86 }
87 }
88 else if (hr != CLDB_E_RECORD_NOTFOUND)
89 {
90 IfFailGo(hr);
91 }
92 }
93
94 // Create the new record.
95 if (pRecord == NULL)
96 {
97 IfFailGo(m_pStgdb->m_MiniMd.AddMethodRecord(&pRecord, &iRecord));
98
99 // Give token back to caller.
100 *pmd = TokenFromRid(iRecord, mdtMethodDef);
101
102 // Add to parent's list of child records.
103 IfFailGo(m_pStgdb->m_MiniMd.AddMethodToTypeDef(RidFromToken(td), iRecord));
104
105 IfFailGo(UpdateENCLog(td, CMiniMdRW::eDeltaMethodCreate));
106
107 // record the more defs are introduced.
108 SetMemberDefDirty(true);
109 }
110
111 // Set the method properties.
112 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Method, MethodRec::COL_Name, pRecord, szNameUtf8));
113 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_Method, MethodRec::COL_Signature, pRecord, pvSigBlob, cbSigBlob));
114
115 // <TODO>@FUTURE: possible performance improvement here to check _ first of all.</TODO>
116 // .ctor and .cctor below are defined in corhdr.h. However, corhdr.h does not have the
117 // the W() macro we need (since it's distributed to windows). We substitute the values of each
118 // macro in the code below to work around this issue.
119 // #define COR_CTOR_METHOD_NAME_W L".ctor"
120 // #define COR_CCTOR_METHOD_NAME_W L".cctor"
121
122 if (!wcscmp(szName, W(".ctor")) || // COR_CTOR_METHOD_NAME_W
123 !wcscmp(szName, W(".cctor")) || // COR_CCTOR_METHOD_NAME_W
124 !wcsncmp(szName, W("_VtblGap"), 8) )
125 {
126 dwMethodFlags |= mdRTSpecialName | mdSpecialName;
127 }
128 SetCallerDefine();
129 IfFailGo(_SetMethodProps(*pmd, dwMethodFlags, ulCodeRVA, dwImplFlags));
130
131 IfFailGo(m_pStgdb->m_MiniMd.AddMemberDefToHash(*pmd, td) );
132
133ErrExit:
134 SetCallerExternal();
135
136 STOP_MD_PERF(DefineMethod);
137 END_ENTRYPOINT_NOTHROW;
138
139 return hr;
140#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
141} // RegMeta::DefineMethod
142
143//*****************************************************************************
144// Create and set a MethodImpl Record.
145//*****************************************************************************
146STDMETHODIMP RegMeta::DefineMethodImpl( // S_OK or error.
147 mdTypeDef td, // [IN] The class implementing the method
148 mdToken tkBody, // [IN] Method body, MethodDef or MethodRef
149 mdToken tkDecl) // [IN] Method declaration, MethodDef or MethodRef
150{
151#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
152 return E_NOTIMPL;
153#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
154 HRESULT hr = S_OK;
155
156 BEGIN_ENTRYPOINT_NOTHROW;
157
158 MethodImplRec *pMethodImplRec = NULL;
159 RID iMethodImplRec;
160
161 LOG((LOGMD, "MD RegMeta::DefineMethodImpl(0x%08x, 0x%08x, 0x%08x)\n",
162 td, tkBody, tkDecl));
163 START_MD_PERF();
164 LOCKWRITE();
165
166 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
167
168 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
169 _ASSERTE(TypeFromToken(tkBody) == mdtMemberRef || TypeFromToken(tkBody) == mdtMethodDef);
170 _ASSERTE(TypeFromToken(tkDecl) == mdtMemberRef || TypeFromToken(tkDecl) == mdtMethodDef);
171 _ASSERTE(!IsNilToken(td) && !IsNilToken(tkBody) && !IsNilToken(tkDecl));
172
173 // Check for duplicates.
174 if (CheckDups(MDDupMethodDef))
175 {
176 hr = ImportHelper::FindMethodImpl(&m_pStgdb->m_MiniMd, td, tkBody, tkDecl, NULL);
177 if (SUCCEEDED(hr))
178 {
179 hr = META_S_DUPLICATE;
180 goto ErrExit;
181 }
182 else if (hr != CLDB_E_RECORD_NOTFOUND)
183 IfFailGo(hr);
184 }
185
186 // Create the MethodImpl record.
187 IfFailGo(m_pStgdb->m_MiniMd.AddMethodImplRecord(&pMethodImplRec, &iMethodImplRec));
188
189 // Set the values.
190 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MethodImpl, MethodImplRec::COL_Class,
191 pMethodImplRec, td));
192 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MethodImpl, MethodImplRec::COL_MethodBody,
193 pMethodImplRec, tkBody));
194 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MethodImpl, MethodImplRec::COL_MethodDeclaration,
195 pMethodImplRec, tkDecl));
196
197 IfFailGo( m_pStgdb->m_MiniMd.AddMethodImplToHash(iMethodImplRec) );
198
199 IfFailGo(UpdateENCLog2(TBL_MethodImpl, iMethodImplRec));
200ErrExit:
201
202 STOP_MD_PERF(DefineMethodImpl);
203 END_ENTRYPOINT_NOTHROW;
204
205 return hr;
206#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
207} // RegMeta::DefineMethodImpl
208
209
210//*****************************************************************************
211// Set or update RVA and ImplFlags for the given MethodDef or FieldDef record.
212//*****************************************************************************
213STDMETHODIMP RegMeta::SetMethodImplFlags( // [IN] S_OK or error.
214 mdMethodDef md, // [IN] Method for which to set impl flags
215 DWORD dwImplFlags)
216{
217#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
218 return E_NOTIMPL;
219#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
220 HRESULT hr = S_OK;
221
222 BEGIN_ENTRYPOINT_NOTHROW;
223
224 MethodRec *pMethodRec;
225
226 LOG((LOGMD, "MD RegMeta::SetMethodImplFlags(0x%08x, 0x%08x)\n",
227 md, dwImplFlags));
228 START_MD_PERF();
229 LOCKWRITE();
230
231 _ASSERTE(TypeFromToken(md) == mdtMethodDef && dwImplFlags != ULONG_MAX);
232
233 // Get the record.
234 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(md), &pMethodRec));
235 pMethodRec->SetImplFlags(static_cast<USHORT>(dwImplFlags));
236
237 IfFailGo(UpdateENCLog(md));
238
239ErrExit:
240 STOP_MD_PERF(SetMethodImplFlags);
241 END_ENTRYPOINT_NOTHROW;
242 return hr;
243#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
244} // RegMeta::SetMethodImplFlags
245
246
247//*****************************************************************************
248// Set or update RVA and ImplFlags for the given MethodDef or FieldDef record.
249//*****************************************************************************
250STDMETHODIMP RegMeta::SetFieldRVA( // [IN] S_OK or error.
251 mdFieldDef fd, // [IN] Field for which to set offset
252 ULONG ulRVA) // [IN] The offset
253{
254#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
255 return E_NOTIMPL;
256#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
257 HRESULT hr = S_OK;
258
259 BEGIN_ENTRYPOINT_NOTHROW;
260
261 FieldRVARec *pFieldRVARec;
262 RID iFieldRVA;
263 FieldRec *pFieldRec;
264
265 LOG((LOGMD, "MD RegMeta::SetFieldRVA(0x%08x, 0x%08x)\n",
266 fd, ulRVA));
267 START_MD_PERF();
268 LOCKWRITE();
269
270 _ASSERTE(TypeFromToken(fd) == mdtFieldDef);
271
272
273 IfFailGo(m_pStgdb->m_MiniMd.FindFieldRVAHelper(fd, &iFieldRVA));
274
275 if (InvalidRid(iFieldRVA))
276 {
277 // turn on the has field RVA bit
278 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(fd), &pFieldRec));
279 pFieldRec->AddFlags(fdHasFieldRVA);
280
281 // Create a new record.
282 IfFailGo(m_pStgdb->m_MiniMd.AddFieldRVARecord(&pFieldRVARec, &iFieldRVA));
283
284 // Set the data.
285 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldRVA, FieldRVARec::COL_Field,
286 pFieldRVARec, fd));
287 IfFailGo( m_pStgdb->m_MiniMd.AddFieldRVAToHash(iFieldRVA) );
288 }
289 else
290 {
291 // Get the record.
292 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRVARecord(iFieldRVA, &pFieldRVARec));
293 }
294
295 // Set the data.
296 pFieldRVARec->SetRVA(ulRVA);
297
298 IfFailGo(UpdateENCLog2(TBL_FieldRVA, iFieldRVA));
299
300ErrExit:
301 STOP_MD_PERF(SetFieldRVA);
302 END_ENTRYPOINT_NOTHROW;
303 return hr;
304#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
305} // RegMeta::SetFieldRVA
306
307
308//*****************************************************************************
309// Helper: Set or update RVA and ImplFlags for the given MethodDef or MethodImpl record.
310//*****************************************************************************
311HRESULT RegMeta::_SetRVA( // [IN] S_OK or error.
312 mdToken tk, // [IN] Member for which to set offset
313 ULONG ulCodeRVA, // [IN] The offset
314 DWORD dwImplFlags)
315{
316#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
317 return E_NOTIMPL;
318#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
319 HRESULT hr = S_OK;
320
321 _ASSERTE(TypeFromToken(tk) == mdtMethodDef || TypeFromToken(tk) == mdtFieldDef);
322 _ASSERTE(!IsNilToken(tk));
323
324 if (TypeFromToken(tk) == mdtMethodDef)
325 {
326 MethodRec *pMethodRec;
327
328 // Get the record.
329 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec));
330
331 // Set the data.
332 pMethodRec->SetRVA(ulCodeRVA);
333
334 // Do not set the flag value unless its valid.
335 if (dwImplFlags != ULONG_MAX)
336 pMethodRec->SetImplFlags(static_cast<USHORT>(dwImplFlags));
337
338 IfFailGo(UpdateENCLog(tk));
339 }
340 else // TypeFromToken(tk) == mdtFieldDef
341 {
342 _ASSERTE(dwImplFlags==0 || dwImplFlags==ULONG_MAX);
343
344 FieldRVARec *pFieldRVARec;
345 RID iFieldRVA;
346 FieldRec *pFieldRec;
347
348 IfFailGo(m_pStgdb->m_MiniMd.FindFieldRVAHelper(tk, &iFieldRVA));
349
350 if (InvalidRid(iFieldRVA))
351 {
352 // turn on the has field RVA bit
353 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tk), &pFieldRec));
354 pFieldRec->AddFlags(fdHasFieldRVA);
355
356 // Create a new record.
357 IfFailGo(m_pStgdb->m_MiniMd.AddFieldRVARecord(&pFieldRVARec, &iFieldRVA));
358
359 // Set the data.
360 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldRVA, FieldRVARec::COL_Field,
361 pFieldRVARec, tk));
362
363 IfFailGo( m_pStgdb->m_MiniMd.AddFieldRVAToHash(iFieldRVA) );
364
365 }
366 else
367 {
368 // Get the record.
369 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRVARecord(iFieldRVA, &pFieldRVARec));
370 }
371
372 // Set the data.
373 pFieldRVARec->SetRVA(ulCodeRVA);
374
375 IfFailGo(UpdateENCLog2(TBL_FieldRVA, iFieldRVA));
376 }
377
378ErrExit:
379 return hr;
380#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
381} // RegMeta::_SetRVA
382
383//*****************************************************************************
384// Given a name, create a TypeRef.
385//*****************************************************************************
386STDMETHODIMP RegMeta::DefineTypeRefByName( // S_OK or error.
387 mdToken tkResolutionScope, // [IN] ModuleRef or AssemblyRef.
388 LPCWSTR szName, // [IN] Name of the TypeRef.
389 mdTypeRef *ptr) // [OUT] Put TypeRef token here.
390{
391#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
392 return E_NOTIMPL;
393#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
394 HRESULT hr = S_OK;
395
396 BEGIN_ENTRYPOINT_NOTHROW;
397
398
399 LOG((LOGMD, "MD RegMeta::DefineTypeRefByName(0x%08x, %S, 0x%08x)\n",
400 tkResolutionScope, MDSTR(szName), ptr));
401 START_MD_PERF();
402 LOCKWRITE();
403
404 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
405
406 // Common helper function does all of the work.
407 IfFailGo(_DefineTypeRef(tkResolutionScope, szName, TRUE, ptr));
408
409ErrExit:
410 STOP_MD_PERF(DefineTypeRefByName);
411
412 END_ENTRYPOINT_NOTHROW;
413 return hr;
414#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
415} // RegMeta::DefineTypeRefByName
416
417//*****************************************************************************
418// Create a reference, in an emit scope, to a TypeDef in another scope.
419//*****************************************************************************
420STDMETHODIMP RegMeta::DefineImportType( // S_OK or error.
421 IMetaDataAssemblyImport *pAssemImport, // [IN] Assemby containing the TypeDef.
422 const void *pbHashValue, // [IN] Hash Blob for Assembly.
423 ULONG cbHashValue, // [IN] Count of bytes.
424 IMetaDataImport *pImport, // [IN] Scope containing the TypeDef.
425 mdTypeDef tdImport, // [IN] The imported TypeDef.
426 IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the TypeDef is imported.
427 mdTypeRef *ptr) // [OUT] Put TypeRef token here.
428{
429#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
430 return E_NOTIMPL;
431#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
432 HRESULT hr = S_OK;
433
434 BEGIN_ENTRYPOINT_NOTHROW;
435
436 IMetaDataImport2 *pImport2 = NULL;
437 IMDCommon *pImport2MDCommon = NULL;
438
439 IMDCommon *pAssemImportMDCommon = NULL;
440
441 RegMeta *pAssemEmitRM = NULL;
442 CMiniMdRW *pMiniMdAssemEmit = NULL;
443 CMiniMdRW *pMiniMdEmit = NULL;
444
445 IMetaModelCommon *pAssemImportMetaModelCommon;
446 IMetaModelCommon *pImport2MetaModelCommon;
447
448 LOG((LOGMD, "MD RegMeta::DefineImportType(0x%08x, 0x%08x, 0x%08x, 0x%08x, "
449 "0x%08x, 0x%08x, 0x%08x)\n",
450 pAssemImport, pbHashValue, cbHashValue,
451 pImport, tdImport, pAssemEmit, ptr));
452
453 START_MD_PERF();
454
455 LOCKWRITE();
456
457 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
458 IfFailGo(pImport->QueryInterface(IID_IMetaDataImport2, (void**)&pImport2));
459
460 if (pAssemImport)
461 {
462 IfFailGo(pAssemImport->QueryInterface(IID_IMDCommon, (void**)&pAssemImportMDCommon));
463 }
464
465 pAssemImportMetaModelCommon = pAssemImportMDCommon ? pAssemImportMDCommon->GetMetaModelCommon() : 0;
466
467 IfFailGo(pImport2->QueryInterface(IID_IMDCommon, (void**)&pImport2MDCommon));
468 pImport2MetaModelCommon = pImport2MDCommon->GetMetaModelCommon();
469
470 pAssemEmitRM = static_cast<RegMeta*>(pAssemEmit);
471 pMiniMdAssemEmit = pAssemEmitRM ? static_cast<CMiniMdRW*>(&pAssemEmitRM->m_pStgdb->m_MiniMd) : 0;
472 pMiniMdEmit = &m_pStgdb->m_MiniMd;
473
474 IfFailGo(ImportHelper::ImportTypeDef(
475 pMiniMdAssemEmit,
476 pMiniMdEmit,
477 pAssemImportMetaModelCommon,
478 pbHashValue, cbHashValue,
479 pImport2MetaModelCommon,
480 tdImport,
481 false, // Do not optimize to TypeDef if import and emit scopes are identical.
482 ptr));
483
484ErrExit:
485 if (pImport2)
486 pImport2->Release();
487 if (pImport2MDCommon)
488 pImport2MDCommon->Release();
489 if (pAssemImportMDCommon)
490 pAssemImportMDCommon->Release();
491 STOP_MD_PERF(DefineImportType);
492 END_ENTRYPOINT_NOTHROW;
493 return hr;
494#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
495} // RegMeta::DefineImportType
496
497//*****************************************************************************
498// Create and set a MemberRef record.
499//*****************************************************************************
500STDMETHODIMP RegMeta::DefineMemberRef( // S_OK or error
501 mdToken tkImport, // [IN] ClassRef or ClassDef importing a member.
502 LPCWSTR szName, // [IN] member's name
503 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
504 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
505 mdMemberRef *pmr) // [OUT] memberref token
506{
507#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
508 return E_NOTIMPL;
509#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
510 HRESULT hr = S_OK;
511
512 BEGIN_ENTRYPOINT_NOTHROW;
513
514 MemberRefRec *pRecord = 0; // The MemberRef record.
515 RID iRecord; // RID of new MemberRef record.
516 LPUTF8 szNameUtf8;
517 UTF8STR(szName, szNameUtf8);
518
519 LOG((LOGMD, "MD RegMeta::DefineMemberRef(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
520 tkImport, MDSTR(szName), pvSigBlob, cbSigBlob, pmr));
521 START_MD_PERF();
522 LOCKWRITE();
523
524 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
525
526 _ASSERTE(TypeFromToken(tkImport) == mdtTypeRef ||
527 TypeFromToken(tkImport) == mdtModuleRef ||
528 TypeFromToken(tkImport) == mdtMethodDef ||
529 TypeFromToken(tkImport) == mdtTypeSpec ||
530 (TypeFromToken(tkImport) == mdtTypeDef) ||
531 IsNilToken(tkImport));
532
533 _ASSERTE(szName && pvSigBlob && cbSigBlob && pmr);
534
535 // _ASSERTE(_IsValidToken(tkImport));
536
537 // Set token to m_tdModule if referring to a global function.
538 if (IsNilToken(tkImport))
539 tkImport = m_tdModule;
540
541 // If the MemberRef already exists, just return the token, else
542 // create a new record.
543 if (CheckDups(MDDupMemberRef))
544 {
545 hr = ImportHelper::FindMemberRef(&(m_pStgdb->m_MiniMd), tkImport, szNameUtf8, pvSigBlob, cbSigBlob, pmr);
546 if (SUCCEEDED(hr))
547 {
548 if (IsENCOn())
549 IfFailGo(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(*pmr), &pRecord));
550 else
551 {
552 hr = META_S_DUPLICATE;
553 goto ErrExit;
554 }
555 }
556 else if (hr != CLDB_E_RECORD_NOTFOUND) // MemberRef exists
557 IfFailGo(hr);
558 }
559
560 if (!pRecord)
561 { // Create the record.
562 IfFailGo(m_pStgdb->m_MiniMd.AddMemberRefRecord(&pRecord, &iRecord));
563
564 // record the more defs are introduced.
565 SetMemberDefDirty(true);
566
567 // Give token to caller.
568 *pmr = TokenFromRid(iRecord, mdtMemberRef);
569 }
570
571 // Save row data.
572 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_MemberRef, MemberRefRec::COL_Name, pRecord, szNameUtf8));
573 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MemberRef, MemberRefRec::COL_Class, pRecord, tkImport));
574 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_MemberRef, MemberRefRec::COL_Signature, pRecord,
575 pvSigBlob, cbSigBlob));
576
577 IfFailGo(m_pStgdb->m_MiniMd.AddMemberRefToHash(*pmr) );
578
579 IfFailGo(UpdateENCLog(*pmr));
580
581ErrExit:
582
583 STOP_MD_PERF(DefineMemberRef);
584 END_ENTRYPOINT_NOTHROW;
585 return hr;
586#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
587} // RegMeta::DefineMemberRef
588
589//*****************************************************************************
590// Create a MemberRef record based on a member in an import scope.
591//*****************************************************************************
592STDMETHODIMP RegMeta::DefineImportMember( // S_OK or error.
593 IMetaDataAssemblyImport *pAssemImport, // [IN] Assemby containing the Member.
594 const void *pbHashValue, // [IN] Hash Blob for Assembly.
595 ULONG cbHashValue, // [IN] Count of bytes.
596 IMetaDataImport *pImport, // [IN] Import scope, with member.
597 mdToken mbMember, // [IN] Member in import scope.
598 IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the Member is imported.
599 mdToken tkImport, // [IN] Classref or classdef in emit scope.
600 mdMemberRef *pmr) // [OUT] Put member ref here.
601{
602#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
603 return E_NOTIMPL;
604#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
605 HRESULT hr = S_OK;
606
607 BEGIN_ENTRYPOINT_NOTHROW;
608
609
610 LOG((LOGMD, "MD RegMeta::DefineImportMember("
611 "0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x,"
612 " 0x%08x, 0x%08x, 0x%08x)\n",
613 pAssemImport, pbHashValue, cbHashValue, pImport, mbMember,
614 pAssemEmit, tkImport, pmr));
615 START_MD_PERF();
616
617 // No need to lock this function. All the functions that it calls are public APIs.
618
619 _ASSERTE(pImport && pmr);
620 _ASSERTE(TypeFromToken(tkImport) == mdtTypeRef || TypeFromToken(tkImport) == mdtModuleRef ||
621 IsNilToken(tkImport) || TypeFromToken(tkImport) == mdtTypeSpec);
622 _ASSERTE((TypeFromToken(mbMember) == mdtMethodDef && mbMember != mdMethodDefNil) ||
623 (TypeFromToken(mbMember) == mdtFieldDef && mbMember != mdFieldDefNil));
624
625 CQuickArray<WCHAR> qbMemberName; // Name of the imported member.
626 CQuickArray<WCHAR> qbScopeName; // Name of the imported member's scope.
627 GUID mvidImport; // MVID of the import module.
628 GUID mvidEmit; // MVID of the emit module.
629 ULONG cchName; // Length of a name, in wide chars.
630 PCCOR_SIGNATURE pvSig; // Member's signature.
631 ULONG cbSig; // Length of member's signature.
632 CQuickBytes cqbTranslatedSig; // Buffer for signature translation.
633 ULONG cbTranslatedSig; // Length of translated signature.
634
635 if (TypeFromToken(mbMember) == mdtMethodDef)
636 {
637 do {
638 hr = pImport->GetMethodProps(mbMember, 0, qbMemberName.Ptr(),(DWORD)qbMemberName.MaxSize(),&cchName,
639 0, &pvSig,&cbSig, 0,0);
640 if (hr == CLDB_S_TRUNCATION)
641 {
642 IfFailGo(qbMemberName.ReSizeNoThrow(cchName));
643 continue;
644 }
645 break;
646 } while (1);
647 }
648 else // TypeFromToken(mbMember) == mdtFieldDef
649 {
650 do {
651 hr = pImport->GetFieldProps(mbMember, 0, qbMemberName.Ptr(),(DWORD)qbMemberName.MaxSize(),&cchName,
652 0, &pvSig,&cbSig, 0,0, 0);
653 if (hr == CLDB_S_TRUNCATION)
654 {
655 IfFailGo(qbMemberName.ReSizeNoThrow(cchName));
656 continue;
657 }
658 break;
659 } while (1);
660 }
661 IfFailGo(hr);
662
663 IfFailGo(cqbTranslatedSig.ReSizeNoThrow(cbSig * 3)); // Set size conservatively.
664
665 IfFailGo(TranslateSigWithScope(
666 pAssemImport,
667 pbHashValue,
668 cbHashValue,
669 pImport,
670 pvSig,
671 cbSig,
672 pAssemEmit,
673 static_cast<IMetaDataEmit*>(static_cast<IMetaDataEmit2*>(this)),
674 (COR_SIGNATURE *)cqbTranslatedSig.Ptr(),
675 cbSig * 3,
676 &cbTranslatedSig));
677
678 // Define ModuleRef for imported Member functions
679
680 // Check if the Member being imported is a global function.
681 IfFailGo(GetScopeProps(0, 0, 0, &mvidEmit));
682 IfFailGo(pImport->GetScopeProps(0, 0,&cchName, &mvidImport));
683 if (mvidEmit != mvidImport && IsNilToken(tkImport))
684 {
685 IfFailGo(qbScopeName.ReSizeNoThrow(cchName));
686 IfFailGo(pImport->GetScopeProps(qbScopeName.Ptr(),(DWORD)qbScopeName.MaxSize(),
687 0, 0));
688 IfFailGo(DefineModuleRef(qbScopeName.Ptr(), &tkImport));
689 }
690
691 // Define MemberRef base on the name, sig, and parent
692 IfFailGo(DefineMemberRef(
693 tkImport,
694 qbMemberName.Ptr(),
695 reinterpret_cast<PCCOR_SIGNATURE>(cqbTranslatedSig.Ptr()),
696 cbTranslatedSig,
697 pmr));
698
699ErrExit:
700 STOP_MD_PERF(DefineImportMember);
701 END_ENTRYPOINT_NOTHROW;
702
703 return hr;
704#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
705} // RegMeta::DefineImportMember
706
707//*****************************************************************************
708// Define and set a Event record.
709//*****************************************************************************
710STDMETHODIMP RegMeta::DefineEvent(
711 mdTypeDef td, // [IN] the class/interface on which the event is being defined
712 LPCWSTR szEvent, // [IN] Name of the event
713 DWORD dwEventFlags, // [IN] CorEventAttr
714 mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef(to the Event class
715 mdMethodDef mdAddOn, // [IN] required add method
716 mdMethodDef mdRemoveOn, // [IN] required remove method
717 mdMethodDef mdFire, // [IN] optional fire method
718 mdMethodDef rmdOtherMethods[], // [IN] optional array of other methods associate with the event
719 mdEvent *pmdEvent) // [OUT] output event token
720{
721#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
722 return E_NOTIMPL;
723#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
724 HRESULT hr = S_OK;
725
726 BEGIN_ENTRYPOINT_NOTHROW;
727
728
729 LOG((LOGMD, "MD RegMeta::DefineEvent(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
730 td, szEvent, dwEventFlags, tkEventType, mdAddOn, mdRemoveOn, mdFire, rmdOtherMethods, pmdEvent));
731 START_MD_PERF();
732 LOCKWRITE();
733
734 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
735
736 _ASSERTE(TypeFromToken(td) == mdtTypeDef && td != mdTypeDefNil);
737 _ASSERTE(IsNilToken(tkEventType) || TypeFromToken(tkEventType) == mdtTypeDef ||
738 TypeFromToken(tkEventType) == mdtTypeRef || TypeFromToken(tkEventType) == mdtTypeSpec);
739 _ASSERTE(TypeFromToken(mdAddOn) == mdtMethodDef && mdAddOn != mdMethodDefNil);
740 _ASSERTE(TypeFromToken(mdRemoveOn) == mdtMethodDef && mdRemoveOn != mdMethodDefNil);
741 _ASSERTE(IsNilToken(mdFire) || TypeFromToken(mdFire) == mdtMethodDef);
742 _ASSERTE(szEvent && pmdEvent);
743
744 hr = _DefineEvent(td, szEvent, dwEventFlags, tkEventType, pmdEvent);
745 if (hr != S_OK)
746 goto ErrExit;
747
748 IfFailGo(_SetEventProps2(*pmdEvent, mdAddOn, mdRemoveOn, mdFire, rmdOtherMethods, IsENCOn()));
749 IfFailGo(UpdateENCLog(*pmdEvent));
750ErrExit:
751
752 STOP_MD_PERF(DefineEvent);
753 END_ENTRYPOINT_NOTHROW;
754 return hr;
755#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
756} // RegMeta::DefineEvent
757
758//*****************************************************************************
759// Set the ClassLayout information.
760//
761// If a row already exists for this class in the layout table, the layout
762// information is overwritten.
763//*****************************************************************************
764STDMETHODIMP RegMeta::SetClassLayout(
765 mdTypeDef td, // [IN] typedef
766 DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16
767 COR_FIELD_OFFSET rFieldOffsets[], // [IN] array of layout specification
768 ULONG ulClassSize) // [IN] size of the class
769{
770#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
771 return E_NOTIMPL;
772#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
773 HRESULT hr = S_OK; // A result.
774
775 BEGIN_ENTRYPOINT_NOTHROW;
776
777 int index = 0; // Loop control.
778
779 LOG((LOGMD, "MD RegMeta::SetClassLayout(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
780 td, dwPackSize, rFieldOffsets, ulClassSize));
781 START_MD_PERF();
782 LOCKWRITE();
783
784 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
785
786 _ASSERTE(TypeFromToken(td) == mdtTypeDef);
787
788 // Create entries in the FieldLayout table.
789 if (rFieldOffsets)
790 {
791 mdFieldDef tkfd;
792 // Iterate the list of fields...
793 for (index = 0; rFieldOffsets[index].ridOfField != mdFieldDefNil; index++)
794 {
795 if (rFieldOffsets[index].ulOffset != ULONG_MAX)
796 {
797 tkfd = TokenFromRid(rFieldOffsets[index].ridOfField, mdtFieldDef);
798
799 IfFailGo(_SetFieldOffset(tkfd, rFieldOffsets[index].ulOffset));
800 }
801 }
802 }
803
804 IfFailGo(_SetClassLayout(td, dwPackSize, ulClassSize));
805
806ErrExit:
807
808 STOP_MD_PERF(SetClassLayout);
809 END_ENTRYPOINT_NOTHROW;
810 return hr;
811#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
812} // RegMeta::SetClassLayout
813
814//*****************************************************************************
815// Helper function to set a class layout for a given class.
816//*****************************************************************************
817HRESULT RegMeta::_SetClassLayout( // S_OK or error.
818 mdTypeDef td, // [IN] The class.
819 ULONG dwPackSize, // [IN] The packing size.
820 ULONG ulClassSize) // [IN, OPTIONAL] The class size.
821{
822#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
823 return E_NOTIMPL;
824#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
825 HRESULT hr = S_OK; // A result.
826 ClassLayoutRec *pClassLayout; // A classlayout record.
827 RID iClassLayout = 0; // RID of classlayout record.
828
829 // See if a ClassLayout record already exists for the given TypeDef.
830 IfFailGo(m_pStgdb->m_MiniMd.FindClassLayoutHelper(td, &iClassLayout));
831
832 if (InvalidRid(iClassLayout))
833 {
834 IfFailGo(m_pStgdb->m_MiniMd.AddClassLayoutRecord(&pClassLayout, &iClassLayout));
835 // Set the Parent entry.
836 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ClassLayout, ClassLayoutRec::COL_Parent,
837 pClassLayout, td));
838 IfFailGo( m_pStgdb->m_MiniMd.AddClassLayoutToHash(iClassLayout) );
839 }
840 else
841 {
842 IfFailGo(m_pStgdb->m_MiniMd.GetClassLayoutRecord(iClassLayout, &pClassLayout));
843 }
844
845 // Set the data.
846 if (dwPackSize != ULONG_MAX)
847 pClassLayout->SetPackingSize(static_cast<USHORT>(dwPackSize));
848 if (ulClassSize != ULONG_MAX)
849 pClassLayout->SetClassSize(ulClassSize);
850
851 // Create the log record for the non-token record.
852 IfFailGo(UpdateENCLog2(TBL_ClassLayout, iClassLayout));
853
854ErrExit:
855
856 return hr;
857#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
858} // RegMeta::_SetClassLayout
859
860//*****************************************************************************
861// Helper function to set a field offset for a given field def.
862//*****************************************************************************
863HRESULT RegMeta::_SetFieldOffset( // S_OK or error.
864 mdFieldDef fd, // [IN] The field.
865 ULONG ulOffset) // [IN] The offset of the field.
866{
867#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
868 return E_NOTIMPL;
869#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
870 HRESULT hr;
871 FieldLayoutRec * pFieldLayoutRec=0; // A FieldLayout record.
872 RID iFieldLayoutRec=0; // RID of a FieldLayout record.
873
874 // See if an entry already exists for the Field in the FieldLayout table.
875 IfFailGo(m_pStgdb->m_MiniMd.FindFieldLayoutHelper(fd, &iFieldLayoutRec));
876 if (InvalidRid(iFieldLayoutRec))
877 {
878 IfFailGo(m_pStgdb->m_MiniMd.AddFieldLayoutRecord(&pFieldLayoutRec, &iFieldLayoutRec));
879 // Set the Field entry.
880 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldLayout, FieldLayoutRec::COL_Field,
881 pFieldLayoutRec, fd));
882 IfFailGo( m_pStgdb->m_MiniMd.AddFieldLayoutToHash(iFieldLayoutRec) );
883 }
884 else
885 {
886 IfFailGo(m_pStgdb->m_MiniMd.GetFieldLayoutRecord(iFieldLayoutRec, &pFieldLayoutRec));
887 }
888
889 // Set the offset.
890 pFieldLayoutRec->SetOffSet(ulOffset);
891
892 // Create the log record for the non-token record.
893 IfFailGo(UpdateENCLog2(TBL_FieldLayout, iFieldLayoutRec));
894
895ErrExit:
896 return hr;
897#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
898} // RegMeta::_SetFieldOffset
899
900//*****************************************************************************
901// Delete the ClassLayout information.
902//*****************************************************************************
903STDMETHODIMP RegMeta::DeleteClassLayout(
904 mdTypeDef td) // [IN] typdef token
905{
906#ifdef FEATURE_METADATA_EMIT_ALL
907 HRESULT hr = S_OK;
908
909 BEGIN_ENTRYPOINT_NOTHROW;
910
911 ClassLayoutRec *pClassLayoutRec;
912 TypeDefRec *pTypeDefRec;
913 FieldLayoutRec *pFieldLayoutRec;
914 RID iClassLayoutRec;
915 RID iFieldLayoutRec;
916 RID ridStart;
917 RID ridEnd;
918 RID ridCur;
919 ULONG index;
920
921 LOG((LOGMD, "MD RegMeta::DeleteClassLayout(0x%08x)\n", td));
922 START_MD_PERF();
923 LOCKWRITE();
924
925 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
926
927 _ASSERTE(!m_bSaveOptimized && "Cannot change records after PreSave() and before Save().");
928 _ASSERTE(TypeFromToken(td) == mdtTypeDef && !IsNilToken(td));
929
930 // Get the ClassLayout record.
931 IfFailGo(m_pStgdb->m_MiniMd.FindClassLayoutHelper(td, &iClassLayoutRec));
932 if (InvalidRid(iClassLayoutRec))
933 {
934 hr = CLDB_E_RECORD_NOTFOUND;
935 goto ErrExit;
936 }
937 IfFailGo(m_pStgdb->m_MiniMd.GetClassLayoutRecord(iClassLayoutRec, &pClassLayoutRec));
938
939 // Clear the parent.
940 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ClassLayout,
941 ClassLayoutRec::COL_Parent,
942 pClassLayoutRec, mdTypeDefNil));
943
944 // Create the log record for the non-token record.
945 IfFailGo(UpdateENCLog2(TBL_ClassLayout, iClassLayoutRec));
946
947 // Delete all the corresponding FieldLayout records if there are any.
948 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(td), &pTypeDefRec));
949 ridStart = m_pStgdb->m_MiniMd.getFieldListOfTypeDef(pTypeDefRec);
950 IfFailGo(m_pStgdb->m_MiniMd.getEndFieldListOfTypeDef(RidFromToken(td), &ridEnd));
951
952 for (index = ridStart; index < ridEnd; index++)
953 {
954 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRid(index, &ridCur));
955 IfFailGo(m_pStgdb->m_MiniMd.FindFieldLayoutHelper(TokenFromRid(ridCur, mdtFieldDef), &iFieldLayoutRec));
956 if (InvalidRid(iFieldLayoutRec))
957 continue;
958 else
959 {
960 IfFailGo(m_pStgdb->m_MiniMd.GetFieldLayoutRecord(iFieldLayoutRec, &pFieldLayoutRec));
961 // Set the Field entry.
962 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldLayout, FieldLayoutRec::COL_Field,
963 pFieldLayoutRec, mdFieldDefNil));
964 // Create the log record for the non-token record.
965 IfFailGo(UpdateENCLog2(TBL_FieldLayout, iFieldLayoutRec));
966 }
967 }
968ErrExit:
969 STOP_MD_PERF(DeleteClassLayout);
970 END_ENTRYPOINT_NOTHROW;
971 return hr;
972#else //!FEATURE_METADATA_EMIT_ALL
973 return E_NOTIMPL;
974#endif //!FEATURE_METADATA_EMIT_ALL
975} // RegMeta::DeleteClassLayout
976
977//*****************************************************************************
978// Set the field's native type.
979//*****************************************************************************
980STDMETHODIMP RegMeta::SetFieldMarshal(
981 mdToken tk, // [IN] given a fieldDef or paramDef token
982 PCCOR_SIGNATURE pvNativeType, // [IN] native type specification
983 ULONG cbNativeType) // [IN] count of bytes of pvNativeType
984{
985#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
986 return E_NOTIMPL;
987#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
988 HRESULT hr = S_OK;
989
990 BEGIN_ENTRYPOINT_NOTHROW;
991
992
993 LOG((LOGMD, "MD RegMeta::SetFieldMarshal(0x%08x, 0x%08x, 0x%08x)\n",
994 tk, pvNativeType, cbNativeType));
995 START_MD_PERF();
996 LOCKWRITE();
997
998 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
999
1000 hr = _SetFieldMarshal(tk, pvNativeType, cbNativeType);
1001
1002ErrExit:
1003 STOP_MD_PERF(SetFieldMarshal);
1004 END_ENTRYPOINT_NOTHROW;
1005 return hr;
1006#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1007} // RegMeta::SetFieldMarshal
1008
1009HRESULT RegMeta::_SetFieldMarshal(
1010 mdToken tk, // [IN] given a fieldDef or paramDef token
1011 PCCOR_SIGNATURE pvNativeType, // [IN] native type specification
1012 ULONG cbNativeType) // [IN] count of bytes of pvNativeType
1013{
1014 HRESULT hr = S_OK;
1015 FieldMarshalRec *pFieldMarshRec;
1016 RID iFieldMarshRec = 0; // initialize to invalid rid
1017
1018 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1019
1020 _ASSERTE(TypeFromToken(tk) == mdtFieldDef || TypeFromToken(tk) == mdtParamDef);
1021 _ASSERTE(!IsNilToken(tk));
1022
1023 // turn on the HasFieldMarshal
1024 if (TypeFromToken(tk) == mdtFieldDef)
1025 {
1026 FieldRec *pFieldRec;
1027
1028 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tk), &pFieldRec));
1029 pFieldRec->AddFlags(fdHasFieldMarshal);
1030 }
1031 else // TypeFromToken(tk) == mdtParamDef
1032 {
1033 ParamRec *pParamRec;
1034
1035 IfFailGo(m_pStgdb->m_MiniMd.GetParamRecord(RidFromToken(tk), &pParamRec));
1036 pParamRec->AddFlags(pdHasFieldMarshal);
1037 }
1038 IfFailGo(UpdateENCLog(tk));
1039
1040 IfFailGo(m_pStgdb->m_MiniMd.FindFieldMarshalHelper(tk, &iFieldMarshRec));
1041 if (InvalidRid(iFieldMarshRec))
1042 {
1043 IfFailGo(m_pStgdb->m_MiniMd.AddFieldMarshalRecord(&pFieldMarshRec, &iFieldMarshRec));
1044 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldMarshal, FieldMarshalRec::COL_Parent, pFieldMarshRec, tk));
1045 IfFailGo( m_pStgdb->m_MiniMd.AddFieldMarshalToHash(iFieldMarshRec) );
1046 }
1047 else
1048 {
1049 IfFailGo(m_pStgdb->m_MiniMd.GetFieldMarshalRecord(iFieldMarshRec, &pFieldMarshRec));
1050 }
1051
1052 // Set data.
1053 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_FieldMarshal, FieldMarshalRec::COL_NativeType, pFieldMarshRec,
1054 pvNativeType, cbNativeType));
1055
1056 // Create the log record for the non-token record.
1057 IfFailGo(UpdateENCLog2(TBL_FieldMarshal, iFieldMarshRec));
1058
1059ErrExit:
1060
1061 return hr;
1062} // RegMeta::_SetFieldMarshal
1063
1064
1065//*****************************************************************************
1066// Delete the FieldMarshal record for the given token.
1067//*****************************************************************************
1068STDMETHODIMP RegMeta::DeleteFieldMarshal(
1069 mdToken tk) // [IN] fieldDef or paramDef token to be deleted.
1070{
1071#ifdef FEATURE_METADATA_EMIT_ALL
1072 HRESULT hr = S_OK;
1073
1074 BEGIN_ENTRYPOINT_NOTHROW;
1075
1076 FieldMarshalRec *pFieldMarshRec;
1077 RID iFieldMarshRec;
1078
1079
1080
1081 LOG((LOGMD, "MD RegMeta::DeleteFieldMarshal(0x%08x)\n", tk));
1082 START_MD_PERF();
1083 LOCKWRITE();
1084
1085 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1086
1087 _ASSERTE(TypeFromToken(tk) == mdtFieldDef || TypeFromToken(tk) == mdtParamDef);
1088 _ASSERTE(!IsNilToken(tk));
1089 _ASSERTE(!m_bSaveOptimized && "Cannot delete records after PreSave() and before Save().");
1090
1091 // Get the FieldMarshal record.
1092 IfFailGo(m_pStgdb->m_MiniMd.FindFieldMarshalHelper(tk, &iFieldMarshRec));
1093 if (InvalidRid(iFieldMarshRec))
1094 {
1095 hr = CLDB_E_RECORD_NOTFOUND;
1096 goto ErrExit;
1097 }
1098 IfFailGo(m_pStgdb->m_MiniMd.GetFieldMarshalRecord(iFieldMarshRec, &pFieldMarshRec));
1099 // Clear the parent token from the FieldMarshal record.
1100 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_FieldMarshal,
1101 FieldMarshalRec::COL_Parent, pFieldMarshRec, mdFieldDefNil));
1102
1103 // turn off the HasFieldMarshal
1104 if (TypeFromToken(tk) == mdtFieldDef)
1105 {
1106 FieldRec *pFieldRec;
1107
1108 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tk), &pFieldRec));
1109 pFieldRec->RemoveFlags(fdHasFieldMarshal);
1110 }
1111 else // TypeFromToken(tk) == mdtParamDef
1112 {
1113 ParamRec *pParamRec;
1114
1115 IfFailGo(m_pStgdb->m_MiniMd.GetParamRecord(RidFromToken(tk), &pParamRec));
1116 pParamRec->RemoveFlags(pdHasFieldMarshal);
1117 }
1118
1119 // Update the ENC log for the parent token.
1120 IfFailGo(UpdateENCLog(tk));
1121 // Create the log record for the non-token record.
1122 IfFailGo(UpdateENCLog2(TBL_FieldMarshal, iFieldMarshRec));
1123
1124ErrExit:
1125 STOP_MD_PERF(DeleteFieldMarshal);
1126 END_ENTRYPOINT_NOTHROW;
1127 return hr;
1128#else //!FEATURE_METADATA_EMIT_ALL
1129 return E_NOTIMPL;
1130#endif //!FEATURE_METADATA_EMIT_ALL
1131} // RegMeta::DeleteFieldMarshal
1132
1133//*****************************************************************************
1134// Define a new permission set for an object.
1135//*****************************************************************************
1136STDMETHODIMP RegMeta::DefinePermissionSet(
1137 mdToken tk, // [IN] the object to be decorated.
1138 DWORD dwAction, // [IN] CorDeclSecurity.
1139 void const *pvPermission, // [IN] permission blob.
1140 ULONG cbPermission, // [IN] count of bytes of pvPermission.
1141 mdPermission *ppm) // [OUT] returned permission token.
1142{
1143#ifdef FEATURE_METADATA_EMIT_ALL
1144 HRESULT hr = S_OK;
1145
1146 BEGIN_ENTRYPOINT_NOTHROW;
1147
1148 LOG((LOGMD, "MD RegMeta::DefinePermissionSet(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1149 tk, dwAction, pvPermission, cbPermission, ppm));
1150 START_MD_PERF();
1151 LOCKWRITE();
1152
1153 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1154
1155 IfFailGo(_DefinePermissionSet(tk, dwAction, pvPermission, cbPermission, ppm));
1156
1157ErrExit:
1158 STOP_MD_PERF(DefinePermissionSet);
1159 END_ENTRYPOINT_NOTHROW;
1160 return hr;
1161#else //!FEATURE_METADATA_EMIT_ALL
1162 return E_NOTIMPL;
1163#endif //!FEATURE_METADATA_EMIT_ALL
1164} // RegMeta::DefinePermissionSet
1165
1166
1167//*****************************************************************************
1168// Define a new permission set for an object.
1169//*****************************************************************************
1170HRESULT RegMeta::_DefinePermissionSet(
1171 mdToken tk, // [IN] the object to be decorated.
1172 DWORD dwAction, // [IN] CorDeclSecurity.
1173 void const *pvPermission, // [IN] permission blob.
1174 ULONG cbPermission, // [IN] count of bytes of pvPermission.
1175 mdPermission *ppm) // [OUT] returned permission token.
1176{
1177#ifdef FEATURE_METADATA_EMIT_ALL
1178 HRESULT hr = S_OK;
1179 DeclSecurityRec *pDeclSec = NULL;
1180 RID iDeclSec;
1181 short sAction = static_cast<short>(dwAction); // To match with the type in DeclSecurityRec.
1182 mdPermission tkPerm; // New permission token.
1183
1184 _ASSERTE(TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtMethodDef ||
1185 TypeFromToken(tk) == mdtAssembly);
1186
1187 // Check for valid Action.
1188 if (sAction == 0 || sAction > dclMaximumValue)
1189 IfFailGo(E_INVALIDARG);
1190
1191 if (CheckDups(MDDupPermission))
1192 {
1193 hr = ImportHelper::FindPermission(&(m_pStgdb->m_MiniMd), tk, sAction, &tkPerm);
1194
1195 if (SUCCEEDED(hr))
1196 {
1197 // Set output parameter.
1198 if (ppm)
1199 *ppm = tkPerm;
1200 if (IsENCOn())
1201 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(RidFromToken(tkPerm), &pDeclSec));
1202 else
1203 {
1204 hr = META_S_DUPLICATE;
1205 goto ErrExit;
1206 }
1207 }
1208 else if (hr != CLDB_E_RECORD_NOTFOUND)
1209 IfFailGo(hr);
1210 }
1211
1212 // Create a new record.
1213 if (!pDeclSec)
1214 {
1215 IfFailGo(m_pStgdb->m_MiniMd.AddDeclSecurityRecord(&pDeclSec, &iDeclSec));
1216 tkPerm = TokenFromRid(iDeclSec, mdtPermission);
1217
1218 // Set output parameter.
1219 if (ppm)
1220 *ppm = tkPerm;
1221
1222 // Save parent and action information.
1223 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_DeclSecurity, DeclSecurityRec::COL_Parent, pDeclSec, tk));
1224 pDeclSec->SetAction(sAction);
1225
1226 // Turn on the internal security flag on the parent.
1227 if (TypeFromToken(tk) == mdtTypeDef)
1228 IfFailGo(_TurnInternalFlagsOn(tk, tdHasSecurity));
1229 else if (TypeFromToken(tk) == mdtMethodDef)
1230 IfFailGo(_TurnInternalFlagsOn(tk, mdHasSecurity));
1231 IfFailGo(UpdateENCLog(tk));
1232 }
1233
1234 IfFailGo(_SetPermissionSetProps(tkPerm, sAction, pvPermission, cbPermission));
1235 IfFailGo(UpdateENCLog(tkPerm));
1236ErrExit:
1237
1238 STOP_MD_PERF(DefinePermissionSet);
1239 return hr;
1240#else //!FEATURE_METADATA_EMIT_ALL
1241 return E_NOTIMPL;
1242#endif //!FEATURE_METADATA_EMIT_ALL
1243} // RegMeta::_DefinePermissionSet
1244
1245
1246
1247//*****************************************************************************
1248// Set the RVA of a methoddef
1249//*****************************************************************************
1250STDMETHODIMP RegMeta::SetRVA( // [IN] S_OK or error.
1251 mdToken md, // [IN] Member for which to set offset
1252 ULONG ulRVA) // [IN] The offset#endif
1253{
1254#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1255 return E_NOTIMPL;
1256#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1257 HRESULT hr = S_OK;
1258
1259 BEGIN_ENTRYPOINT_NOTHROW;
1260
1261 LOG((LOGMD, "MD RegMeta::SetRVA(0x%08x, 0x%08x)\n",
1262 md, ulRVA));
1263 START_MD_PERF();
1264
1265 LOCKWRITE();
1266
1267 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1268 IfFailGo(_SetRVA(md, ulRVA, ULONG_MAX)); // 0xbaad
1269
1270ErrExit:
1271 STOP_MD_PERF(SetRVA);
1272 END_ENTRYPOINT_NOTHROW;
1273
1274 return hr;
1275#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1276} // RegMeta::SetRVA
1277
1278//*****************************************************************************
1279// Given a signature, return a token to the user. If there isn't an existing
1280// token, create a new record. This should more appropriately be called
1281// DefineSignature.
1282//*****************************************************************************
1283STDMETHODIMP RegMeta::GetTokenFromSig( // [IN] S_OK or error.
1284 PCCOR_SIGNATURE pvSig, // [IN] Signature to define.
1285 ULONG cbSig, // [IN] Size of signature data.
1286 mdSignature *pmsig) // [OUT] returned signature token.
1287{
1288#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1289 return E_NOTIMPL;
1290#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1291 HRESULT hr = S_OK;
1292
1293 BEGIN_ENTRYPOINT_NOTHROW;
1294
1295 LOG((LOGMD, "MD RegMeta::GetTokenFromSig(0x%08x, 0x%08x, 0x%08x)\n",
1296 pvSig, cbSig, pmsig));
1297 START_MD_PERF();
1298
1299 LOCKWRITE();
1300
1301 _ASSERTE(pmsig);
1302
1303 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1304 IfFailGo(_GetTokenFromSig(pvSig, cbSig, pmsig));
1305
1306ErrExit:
1307 STOP_MD_PERF(GetTokenFromSig);
1308 END_ENTRYPOINT_NOTHROW;
1309
1310 return hr;
1311#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1312} // RegMeta::GetTokenFromSig
1313
1314//*****************************************************************************
1315// Define and set a ModuleRef record.
1316//*****************************************************************************
1317STDMETHODIMP RegMeta::DefineModuleRef( // S_OK or error.
1318 LPCWSTR szName, // [IN] DLL name
1319 mdModuleRef *pmur) // [OUT] returned module ref token
1320{
1321#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1322 return E_NOTIMPL;
1323#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1324 HRESULT hr = S_OK;
1325
1326 BEGIN_ENTRYPOINT_NOTHROW;
1327
1328 LOG((LOGMD, "MD RegMeta::DefineModuleRef(%S, 0x%08x)\n", MDSTR(szName), pmur));
1329 START_MD_PERF();
1330 LOCKWRITE();
1331
1332 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1333
1334 hr = _DefineModuleRef(szName, pmur);
1335
1336ErrExit:
1337 STOP_MD_PERF(DefineModuleRef);
1338 END_ENTRYPOINT_NOTHROW;
1339 return hr;
1340#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1341} // RegMeta::DefineModuleRef
1342
1343HRESULT RegMeta::_DefineModuleRef( // S_OK or error.
1344 LPCWSTR szName, // [IN] DLL name
1345 mdModuleRef *pmur) // [OUT] returned module ref token
1346{
1347#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1348 return E_NOTIMPL;
1349#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1350 HRESULT hr = S_OK;
1351 ModuleRefRec *pModuleRef = 0; // The ModuleRef record.
1352 RID iModuleRef; // Rid of new ModuleRef record.
1353 LPUTF8 szUTF8Name;
1354 UTF8STR((LPCWSTR)szName, szUTF8Name);
1355
1356 _ASSERTE(szName && pmur);
1357
1358 // See if the given ModuleRef already exists. If it exists just return.
1359 // Else create a new record.
1360 if (CheckDups(MDDupModuleRef))
1361 {
1362 hr = ImportHelper::FindModuleRef(&(m_pStgdb->m_MiniMd), szUTF8Name, pmur);
1363 if (SUCCEEDED(hr))
1364 {
1365 if (IsENCOn())
1366 IfFailGo(m_pStgdb->m_MiniMd.GetModuleRefRecord(RidFromToken(*pmur), &pModuleRef));
1367 else
1368 {
1369 hr = META_S_DUPLICATE;
1370 goto ErrExit;
1371 }
1372 }
1373 else if (hr != CLDB_E_RECORD_NOTFOUND)
1374 IfFailGo(hr);
1375 }
1376
1377 if (!pModuleRef)
1378 {
1379 // Create new record and set the values.
1380 IfFailGo(m_pStgdb->m_MiniMd.AddModuleRefRecord(&pModuleRef, &iModuleRef));
1381
1382 // Set the output parameter.
1383 *pmur = TokenFromRid(iModuleRef, mdtModuleRef);
1384 }
1385
1386 // Save the data.
1387 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_ModuleRef, ModuleRefRec::COL_Name,
1388 pModuleRef, szUTF8Name));
1389 IfFailGo(UpdateENCLog(*pmur));
1390
1391ErrExit:
1392
1393 return hr;
1394#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1395} // RegMeta::_DefineModuleRef
1396
1397//*****************************************************************************
1398// Set the parent for the specified MemberRef.
1399//*****************************************************************************
1400STDMETHODIMP RegMeta::SetParent( // S_OK or error.
1401 mdMemberRef mr, // [IN] Token for the ref to be fixed up.
1402 mdToken tk) // [IN] The ref parent.
1403{
1404#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1405 return E_NOTIMPL;
1406#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1407 HRESULT hr = S_OK;
1408
1409 BEGIN_ENTRYPOINT_NOTHROW;
1410
1411 MemberRefRec *pMemberRef;
1412
1413 LOG((LOGMD, "MD RegMeta::SetParent(0x%08x, 0x%08x)\n",
1414 mr, tk));
1415 START_MD_PERF();
1416 LOCKWRITE();
1417
1418 _ASSERTE(TypeFromToken(mr) == mdtMemberRef);
1419 _ASSERTE(IsNilToken(tk) || TypeFromToken(tk) == mdtTypeRef || TypeFromToken(tk) == mdtTypeDef ||
1420 TypeFromToken(tk) == mdtModuleRef || TypeFromToken(tk) == mdtMethodDef);
1421
1422 IfFailGo(m_pStgdb->m_MiniMd.GetMemberRefRecord(RidFromToken(mr), &pMemberRef));
1423
1424 // If the token is nil set it to to m_tdModule.
1425 tk = IsNilToken(tk) ? m_tdModule : tk;
1426
1427 // Set the parent.
1428 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MemberRef, MemberRefRec::COL_Class, pMemberRef, tk));
1429
1430 // Add the updated MemberRef to the hash.
1431 IfFailGo(m_pStgdb->m_MiniMd.AddMemberRefToHash(mr) );
1432
1433 IfFailGo(UpdateENCLog(mr));
1434
1435ErrExit:
1436
1437 STOP_MD_PERF(SetParent);
1438 END_ENTRYPOINT_NOTHROW;
1439 return hr;
1440#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1441} // RegMeta::SetParent
1442
1443//*****************************************************************************
1444// Define an TypeSpec token given a type description.
1445//*****************************************************************************
1446STDMETHODIMP RegMeta::GetTokenFromTypeSpec( // [IN] S_OK or error.
1447 PCCOR_SIGNATURE pvSig, // [IN] Signature to define.
1448 ULONG cbSig, // [IN] Size of signature data.
1449 mdTypeSpec *ptypespec) // [OUT] returned signature token.
1450{
1451#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1452 return E_NOTIMPL;
1453#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1454 HRESULT hr = S_OK;
1455
1456 BEGIN_ENTRYPOINT_NOTHROW;
1457
1458 TypeSpecRec *pTypeSpecRec;
1459 RID iRec;
1460
1461 LOG((LOGMD, "MD RegMeta::GetTokenFromTypeSpec(0x%08x, 0x%08x, 0x%08x)\n",
1462 pvSig, cbSig, ptypespec));
1463 START_MD_PERF();
1464 LOCKWRITE();
1465
1466 _ASSERTE(ptypespec);
1467
1468 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1469
1470 if (CheckDups(MDDupTypeSpec))
1471 {
1472 hr = ImportHelper::FindTypeSpec(&(m_pStgdb->m_MiniMd), pvSig, cbSig, ptypespec);
1473 if (SUCCEEDED(hr))
1474 {
1475 //@GENERICS: Generalizing from similar code in this file, should we not set
1476 // hr = META_S_DUPLICATE;
1477 // here?
1478 goto ErrExit;
1479 }
1480 else if (hr != CLDB_E_RECORD_NOTFOUND)
1481 IfFailGo(hr);
1482 }
1483
1484 // Create a new record.
1485 IfFailGo(m_pStgdb->m_MiniMd.AddTypeSpecRecord(&pTypeSpecRec, &iRec));
1486
1487 // Set output parameter.
1488 *ptypespec = TokenFromRid(iRec, mdtTypeSpec);
1489
1490 // Set the signature field
1491 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(
1492 TBL_TypeSpec,
1493 TypeSpecRec::COL_Signature,
1494 pTypeSpecRec,
1495 pvSig,
1496 cbSig));
1497 IfFailGo(UpdateENCLog(*ptypespec));
1498
1499ErrExit:
1500
1501 STOP_MD_PERF(GetTokenFromTypeSpec);
1502 END_ENTRYPOINT_NOTHROW;
1503 return hr;
1504#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1505} // RegMeta::GetTokenFromTypeSpec
1506
1507//*****************************************************************************
1508// This API defines a user literal string to be stored in the MetaData section.
1509// The token for this string has embedded in it the offset into the BLOB pool
1510// where the string is stored in UNICODE format. An additional byte is padded
1511// at the end to indicate whether the string has any characters that are >= 0x80.
1512//*****************************************************************************
1513STDMETHODIMP RegMeta::DefineUserString( // S_OK or error.
1514 LPCWSTR szString, // [IN] User literal string.
1515 ULONG cchString, // [IN] Length of string.
1516 mdString *pstk) // [OUT] String token.
1517{
1518#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1519 return E_NOTIMPL;
1520#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1521 HRESULT hr = S_OK;
1522
1523 BEGIN_ENTRYPOINT_NOTHROW;
1524
1525 UINT32 nIndex; // Index into the user string heap.
1526 CQuickBytes qb; // For storing the string with the byte prefix.
1527 ULONG i; // Loop counter.
1528 BOOL bIs80Plus = false; // Is there an 80+ WCHAR.
1529 ULONG ulMemSize; // Size of memory taken by the string passed in.
1530 PBYTE pb; // Pointer into memory allocated by qb.
1531 WCHAR c; // Temporary used during comparison;
1532
1533
1534
1535 LOG((LOGMD, "MD RegMeta::DefineUserString(0x%08x, 0x%08x, 0x%08x)\n",
1536 szString, cchString, pstk));
1537 START_MD_PERF();
1538 LOCKWRITE();
1539
1540 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1541
1542 _ASSERTE(pstk && szString && cchString != ULONG_MAX);
1543
1544 //
1545 // Walk the entire string looking for characters that would block us from doing
1546 // a fast comparison of the string. These characters include anything greater than
1547 // 0x80 or an apostrophe or a hyphen. Apostrophe and hyphen are excluded because
1548 // they would prevent words like coop and co-op from sorting together in a culture-aware
1549 // comparison. We also need to exclude some set of the control characters. This check
1550 // is more restrictive
1551 //
1552 for (i=0; i<cchString; i++) {
1553 c = szString[i];
1554 if (c>=0x80 || HighCharHelper::IsHighChar((int)c)) {
1555 bIs80Plus = true;
1556 break;
1557 }
1558 }
1559
1560 // Copy over the string to memory.
1561 ulMemSize = cchString * sizeof(WCHAR);
1562 IfFailGo(qb.ReSizeNoThrow(ulMemSize + 1));
1563 pb = reinterpret_cast<PBYTE>(qb.Ptr());
1564 memcpy(pb, szString, ulMemSize);
1565 SwapStringLength((WCHAR *) pb, cchString);
1566 // Set the last byte of memory to indicate whether there is a 80+ character.
1567 *(pb + ulMemSize) = bIs80Plus ? 1 : 0;
1568
1569 IfFailGo(m_pStgdb->m_MiniMd.PutUserString(
1570 MetaData::DataBlob(pb, ulMemSize + 1),
1571 &nIndex));
1572
1573 // Fail if the offset requires the high byte which is reserved for the token ID.
1574 if (nIndex & 0xff000000)
1575 IfFailGo(META_E_STRINGSPACE_FULL);
1576 else
1577 *pstk = TokenFromRid(nIndex, mdtString);
1578
1579ErrExit:
1580 END_ENTRYPOINT_NOTHROW;
1581
1582 STOP_MD_PERF(DefineUserString);
1583 return hr;
1584#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1585} // RegMeta::DefineUserString
1586
1587//*****************************************************************************
1588// Delete a token.
1589// We only allow deleting a subset of tokens at this moment. These are TypeDef,
1590// MethodDef, FieldDef, Event, Property, and CustomAttribute. Except
1591// CustomAttribute, all the other tokens are named. We reserved a special
1592// name COR_DELETED_NAME_A to indicating a named record is deleted when
1593// xxRTSpecialName is set.
1594//*****************************************************************************
1595
1596STDMETHODIMP RegMeta::DeleteToken(
1597 mdToken tkObj) // [IN] The token to be deleted
1598{
1599#ifdef FEATURE_METADATA_EMIT_ALL
1600 HRESULT hr = NOERROR;
1601
1602 BEGIN_ENTRYPOINT_NOTHROW;
1603
1604 LOG((LOGMD, "MD RegMeta::DeleteToken(0x%08x)\n", tkObj));
1605 START_MD_PERF();
1606 LOCKWRITE();
1607
1608 if (!IsValidToken(tkObj))
1609 IfFailGo( E_INVALIDARG );
1610
1611 // make sure that MetaData scope is opened for incremental compilation
1612 if (!m_pStgdb->m_MiniMd.HasDelete())
1613 {
1614 _ASSERTE( !"You cannot call delete token when you did not open the scope with proper Update flags in the SetOption!");
1615 IfFailGo( E_INVALIDARG );
1616 }
1617
1618 _ASSERTE(!m_bSaveOptimized && "Cannot delete records after PreSave() and before Save().");
1619
1620 switch ( TypeFromToken(tkObj) )
1621 {
1622 case mdtTypeDef:
1623 {
1624 TypeDefRec *pRecord;
1625 IfFailGo(m_pStgdb->m_MiniMd.GetTypeDefRecord(RidFromToken(tkObj), &pRecord));
1626 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_TypeDef, TypeDefRec::COL_Name, pRecord, COR_DELETED_NAME_A));
1627 pRecord->AddFlags(tdSpecialName | tdRTSpecialName);
1628 break;
1629 }
1630 case mdtMethodDef:
1631 {
1632 MethodRec *pRecord;
1633 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tkObj), &pRecord));
1634 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Method, MethodRec::COL_Name, pRecord, COR_DELETED_NAME_A));
1635 pRecord->AddFlags(mdSpecialName | mdRTSpecialName);
1636 break;
1637 }
1638 case mdtFieldDef:
1639 {
1640 FieldRec *pRecord;
1641 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tkObj), &pRecord));
1642 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Field, FieldRec::COL_Name, pRecord, COR_DELETED_NAME_A));
1643 pRecord->AddFlags(fdSpecialName | fdRTSpecialName);
1644 break;
1645 }
1646 case mdtEvent:
1647 {
1648 EventRec *pRecord;
1649 IfFailGo(m_pStgdb->m_MiniMd.GetEventRecord(RidFromToken(tkObj), &pRecord));
1650 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Event, EventRec::COL_Name, pRecord, COR_DELETED_NAME_A));
1651 pRecord->AddEventFlags(evSpecialName | evRTSpecialName);
1652 break;
1653 }
1654 case mdtProperty:
1655 {
1656 PropertyRec *pRecord;
1657 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(RidFromToken(tkObj), &pRecord));
1658 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Property, PropertyRec::COL_Name, pRecord, COR_DELETED_NAME_A));
1659 pRecord->AddPropFlags(prSpecialName | prRTSpecialName);
1660 break;
1661 }
1662 case mdtExportedType:
1663 {
1664 ExportedTypeRec *pRecord;
1665 IfFailGo(m_pStgdb->m_MiniMd.GetExportedTypeRecord(RidFromToken(tkObj), &pRecord));
1666 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_ExportedType, ExportedTypeRec::COL_TypeName, pRecord, COR_DELETED_NAME_A));
1667 break;
1668 }
1669 case mdtCustomAttribute:
1670 {
1671 mdToken tkParent;
1672 CustomAttributeRec *pRecord;
1673 IfFailGo(m_pStgdb->m_MiniMd.GetCustomAttributeRecord(RidFromToken(tkObj), &pRecord));
1674
1675 // replace the parent column of the custom value record to a nil token.
1676 tkParent = m_pStgdb->m_MiniMd.getParentOfCustomAttribute(pRecord);
1677 tkParent = TokenFromRid( mdTokenNil, TypeFromToken(tkParent) );
1678 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_CustomAttribute, CustomAttributeRec::COL_Parent, pRecord, tkParent));
1679
1680 // now the CustomAttribute table is no longer sorted
1681 m_pStgdb->m_MiniMd.SetSorted(TBL_CustomAttribute, false);
1682 break;
1683 }
1684 case mdtGenericParam:
1685 {
1686 mdToken tkParent;
1687 GenericParamRec *pRecord;
1688 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamRecord(RidFromToken(tkObj), &pRecord));
1689
1690 // replace the Parent column of the GenericParam record with a nil token.
1691 tkParent = m_pStgdb->m_MiniMd.getOwnerOfGenericParam(pRecord);
1692 tkParent = TokenFromRid( mdTokenNil, TypeFromToken(tkParent) );
1693 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_GenericParam, GenericParamRec::COL_Owner,
1694 pRecord, tkParent));
1695
1696 // now the GenericParam table is no longer sorted
1697 m_pStgdb->m_MiniMd.SetSorted(TBL_GenericParam, false);
1698 break;
1699 }
1700 case mdtGenericParamConstraint:
1701 {
1702 GenericParamConstraintRec *pRecord;
1703 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamConstraintRecord(RidFromToken(tkObj), &pRecord));
1704
1705 // replace the Param column of the GenericParamConstraint record with zero RID.
1706 IfFailGo(m_pStgdb->m_MiniMd.PutCol(TBL_GenericParamConstraint,
1707 GenericParamConstraintRec::COL_Owner,pRecord, 0));
1708 // now the GenericParamConstraint table is no longer sorted
1709 m_pStgdb->m_MiniMd.SetSorted(TBL_GenericParamConstraint, false);
1710 break;
1711 }
1712 case mdtPermission:
1713 {
1714 mdToken tkParent;
1715 mdToken tkNil;
1716 DeclSecurityRec *pRecord;
1717 IfFailGo(m_pStgdb->m_MiniMd.GetDeclSecurityRecord(RidFromToken(tkObj), &pRecord));
1718
1719 // Replace the parent column of the permission record with a nil tokne.
1720 tkParent = m_pStgdb->m_MiniMd.getParentOfDeclSecurity(pRecord);
1721 tkNil = TokenFromRid( mdTokenNil, TypeFromToken(tkParent) );
1722 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_DeclSecurity, DeclSecurityRec::COL_Parent, pRecord, tkNil ));
1723
1724 // The table is no longer sorted.
1725 m_pStgdb->m_MiniMd.SetSorted(TBL_DeclSecurity, false);
1726
1727 // If the parent has no more security attributes, turn off the "has security" bit.
1728 HCORENUM hEnum = 0;
1729 mdPermission rPerms[1];
1730 ULONG cPerms = 0;
1731 EnumPermissionSets(&hEnum, tkParent, 0 /* all actions */, rPerms, 1, &cPerms);
1732 CloseEnum(hEnum);
1733 if (cPerms == 0)
1734 {
1735 void *pRow;
1736 ULONG ixTbl;
1737 // Get the row for the parent object.
1738 ixTbl = m_pStgdb->m_MiniMd.GetTblForToken(tkParent);
1739 _ASSERTE(ixTbl >= 0 && ixTbl <= m_pStgdb->m_MiniMd.GetCountTables());
1740 IfFailGo(m_pStgdb->m_MiniMd.getRow(ixTbl, RidFromToken(tkParent), &pRow));
1741
1742 switch (TypeFromToken(tkParent))
1743 {
1744 case mdtTypeDef:
1745 reinterpret_cast<TypeDefRec*>(pRow)->RemoveFlags(tdHasSecurity);
1746 break;
1747 case mdtMethodDef:
1748 reinterpret_cast<MethodRec*>(pRow)->RemoveFlags(mdHasSecurity);
1749 break;
1750 case mdtAssembly:
1751 // No security bit.
1752 break;
1753 }
1754 }
1755 break;
1756 }
1757 default:
1758 _ASSERTE(!"Bad token type!");
1759 IfFailGo( E_INVALIDARG );
1760 break;
1761 }
1762
1763 ErrExit:
1764
1765 STOP_MD_PERF(DeleteToken);
1766 END_ENTRYPOINT_NOTHROW;
1767
1768 return hr;
1769#else //!FEATURE_METADATA_EMIT_ALL
1770 return E_NOTIMPL;
1771#endif //!FEATURE_METADATA_EMIT_ALL
1772} // RegMeta::DeleteToken
1773
1774//*****************************************************************************
1775// Set the properties on the given TypeDef token.
1776//*****************************************************************************
1777STDMETHODIMP RegMeta::SetTypeDefProps( // S_OK or error.
1778 mdTypeDef td, // [IN] The TypeDef.
1779 DWORD dwTypeDefFlags, // [IN] TypeDef flags.
1780 mdToken tkExtends, // [IN] Base TypeDef or TypeRef.
1781 mdToken rtkImplements[]) // [IN] Implemented interfaces.
1782{
1783#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1784 return E_NOTIMPL;
1785#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1786 HRESULT hr = S_OK;
1787
1788 BEGIN_ENTRYPOINT_NOTHROW;
1789
1790 LOG((LOGMD, "RegMeta::SetTypeDefProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1791 td, dwTypeDefFlags, tkExtends, rtkImplements));
1792 START_MD_PERF();
1793 LOCKWRITE();
1794
1795 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1796
1797 hr = _SetTypeDefProps(td, dwTypeDefFlags, tkExtends, rtkImplements);
1798
1799ErrExit:
1800
1801 STOP_MD_PERF(SetTypeDefProps);
1802 END_ENTRYPOINT_NOTHROW;
1803 return hr;
1804#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1805} // RegMeta::SetTypeDefProps
1806
1807
1808//*****************************************************************************
1809// Define a Nested Type.
1810//*****************************************************************************
1811STDMETHODIMP RegMeta::DefineNestedType( // S_OK or error.
1812 LPCWSTR szTypeDef, // [IN] Name of TypeDef
1813 DWORD dwTypeDefFlags, // [IN] CustomAttribute flags
1814 mdToken tkExtends, // [IN] extends this TypeDef or typeref
1815 mdToken rtkImplements[], // [IN] Implements interfaces
1816 mdTypeDef tdEncloser, // [IN] TypeDef token of the enclosing type.
1817 mdTypeDef *ptd) // [OUT] Put TypeDef token here
1818{
1819#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1820 return E_NOTIMPL;
1821#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1822 HRESULT hr = S_OK;
1823
1824 BEGIN_ENTRYPOINT_NOTHROW;
1825
1826 LOG((LOGMD, "RegMeta::DefineNestedType(%S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
1827 MDSTR(szTypeDef), dwTypeDefFlags, tkExtends,
1828 rtkImplements, tdEncloser, ptd));
1829 START_MD_PERF();
1830 LOCKWRITE();
1831
1832 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1833
1834 _ASSERTE(TypeFromToken(tdEncloser) == mdtTypeDef && !IsNilToken(tdEncloser));
1835 _ASSERTE(IsTdNested(dwTypeDefFlags));
1836
1837 IfFailGo(_DefineTypeDef(szTypeDef, dwTypeDefFlags,
1838 tkExtends, rtkImplements, tdEncloser, ptd));
1839
1840ErrExit:
1841 STOP_MD_PERF(DefineNestedType);
1842 END_ENTRYPOINT_NOTHROW;
1843 return hr;
1844#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1845} // RegMeta::DefineNestedType
1846
1847//*****************************************************************************
1848// Define a formal type parameter for the given TypeDef or MethodDef token.
1849//*****************************************************************************
1850STDMETHODIMP RegMeta::DefineGenericParam( // S_OK or error.
1851 mdToken tkOwner, // [IN] TypeDef or MethodDef
1852 ULONG ulParamSeq, // [IN] Index of the type parameter
1853 DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance)
1854 LPCWSTR szName, // [IN] Name
1855 DWORD reserved, // [IN] For future use
1856 mdToken rtkConstraints[], // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec)
1857 mdGenericParam *pgp) // [OUT] Put GenericParam token here
1858{
1859#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1860 return E_NOTIMPL;
1861#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1862 HRESULT hr = S_OK;
1863
1864 BEGIN_ENTRYPOINT_NOTHROW;
1865
1866 mdToken tkRet = mdGenericParamNil;
1867 mdToken tkOwnerType = TypeFromToken(tkOwner);
1868
1869 LOG((LOGMD, "RegMeta::DefineGenericParam(0x%08x, %d, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
1870 tkOwner, ulParamSeq, dwParamFlags, szName, reserved, rtkConstraints, pgp));
1871 START_MD_PERF();
1872 LOCKWRITE();
1873
1874 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
1875
1876 if (reserved != 0)
1877 IfFailGo(META_E_BAD_INPUT_PARAMETER);
1878
1879 // See if this version of the metadata can do Generics
1880 if (!m_pStgdb->m_MiniMd.SupportsGenerics())
1881 IfFailGo(CLDB_E_INCOMPATIBLE);
1882
1883 if ((tkOwnerType == mdtTypeDef) || (tkOwnerType == mdtMethodDef))
1884 {
1885 // 1. Find/create GP (unique tkOwner+ulParamSeq) = tkRet
1886 GenericParamRec *pGenericParam = NULL;
1887 RID iGenericParam,rid;
1888 RID ridStart;
1889 RID ridEnd;
1890
1891 // See if this GenericParam has already been defined.
1892 if (CheckDups(MDDupGenericParam))
1893 {
1894 // Enumerate any GenericParams for the parent, looking for this sequence number.
1895 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamsForToken(tkOwner, &ridStart, &ridEnd));
1896 for (rid = ridStart; rid < ridEnd; rid++)
1897 {
1898 iGenericParam = m_pStgdb->m_MiniMd.GetGenericParamRid(rid);
1899 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamRecord(iGenericParam, &pGenericParam));
1900 // Is this the desired GenericParam #?
1901 if (pGenericParam->GetNumber() == (USHORT)ulParamSeq)
1902 {
1903 tkRet = TokenFromRid(iGenericParam,mdtGenericParam);
1904 // This is a duplicate. If not ENC, just return 'DUPLICATE'. If ENC, overwrite.
1905 if (!IsENCOn())
1906 {
1907 IfFailGo(META_S_DUPLICATE);
1908 }
1909 break;
1910 }
1911 }
1912 }
1913 else
1914 { // Clear rid, ridStart, ridEnd, so we no we didn't find one.
1915 rid = ridStart = ridEnd = 0;
1916 }
1917
1918 // If none was found, create one.
1919 if(rid >= ridEnd)
1920 {
1921 IfFailGo(m_pStgdb->m_MiniMd.AddGenericParamRecord(&pGenericParam, &iGenericParam));
1922 pGenericParam->SetNumber((USHORT)ulParamSeq);
1923 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_GenericParam, GenericParamRec::COL_Owner,
1924 pGenericParam, tkOwner));
1925 tkRet = TokenFromRid(iGenericParam,mdtGenericParam);
1926 }
1927
1928 // 2. Set its props
1929 IfFailGo(_SetGenericParamProps(tkRet, pGenericParam, dwParamFlags, szName, reserved ,rtkConstraints));
1930 IfFailGo(UpdateENCLog(tkRet));
1931 }
1932 else
1933 hr = META_E_BAD_INPUT_PARAMETER;
1934
1935ErrExit:
1936
1937 if(pgp != NULL)
1938 *pgp = tkRet;
1939 STOP_MD_PERF(DefineGenericParam);
1940
1941 END_ENTRYPOINT_NOTHROW;
1942
1943 return hr;
1944#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1945} // RegMeta::DefineGenericParam
1946
1947//*****************************************************************************
1948// Set props of a formal type parameter.
1949//*****************************************************************************
1950STDMETHODIMP RegMeta::SetGenericParamProps( // S_OK or error.
1951 mdGenericParam gp, // [IN] GenericParam
1952 DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance)
1953 LPCWSTR szName, // [IN] Optional name
1954 DWORD reserved, // [IN] For future use (e.g. non-type parameters)
1955 mdToken rtkConstraints[]) // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec)
1956{
1957#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
1958 return E_NOTIMPL;
1959#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1960 HRESULT hr = S_OK;
1961
1962 BEGIN_ENTRYPOINT_NOTHROW;
1963
1964 LOG((LOGMD, "RegMeta::SetGenericParamProps(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x)\n",
1965 gp, dwParamFlags,szName,reserved,rtkConstraints));
1966 START_MD_PERF();
1967
1968 if (reserved != 0)
1969 IfFailGo(META_E_BAD_INPUT_PARAMETER);
1970
1971 // See if this version of the metadata can do Generics
1972 if (!m_pStgdb->m_MiniMd.SupportsGenerics())
1973 IfFailGo(CLDB_E_INCOMPATIBLE);
1974
1975 if (TypeFromToken(gp) == mdtGenericParam)
1976 {
1977 GenericParamRec *pGenericParam;
1978
1979 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamRecord(RidFromToken(gp), &pGenericParam));
1980 IfFailGo(_SetGenericParamProps(gp,pGenericParam,dwParamFlags,szName,reserved,rtkConstraints));
1981 IfFailGo(UpdateENCLog(gp));
1982 }
1983 else
1984 hr = META_E_BAD_INPUT_PARAMETER;
1985
1986ErrExit:
1987 STOP_MD_PERF(SetGenericParamProps);
1988
1989 END_ENTRYPOINT_NOTHROW;
1990 return hr;
1991#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
1992} // RegMeta::SetGenericParamProps
1993
1994//*****************************************************************************
1995// Set props of a formal type parameter (internal).
1996//*****************************************************************************
1997HRESULT RegMeta::_SetGenericParamProps( // S_OK or error.
1998 mdGenericParam tkGP, // [IN] Formal parameter token
1999 GenericParamRec *pGenericParam, // [IN] GenericParam record ptr
2000 DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance)
2001 LPCWSTR szName, // [IN] Optional name
2002 DWORD reserved, // [IN] For future use (e.g. non-type parameters)
2003 mdToken rtkConstraints[]) // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec)
2004{
2005#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2006 return E_NOTIMPL;
2007#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2008 HRESULT hr = S_OK;
2009
2010 if (pGenericParam != NULL)
2011 {
2012 // If there is a name, set it.
2013 if ((szName != NULL) && (*szName != 0))
2014 IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_GenericParam, GenericParamRec::COL_Name,
2015 pGenericParam, szName));
2016
2017 // If there are new flags, set them.
2018 if (dwParamFlags != (DWORD) -1)
2019 pGenericParam->SetFlags((USHORT)dwParamFlags);
2020
2021 // If there is a new array of constraints, apply it.
2022 if (rtkConstraints != NULL)
2023 {
2024 //Clear existing constraints
2025 GenericParamConstraintRec* pGPCRec;
2026 RID ridGPC;
2027 RID rid;
2028 RID ridStart;
2029 RID ridEnd;
2030
2031 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamConstraintsForToken(tkGP, &ridStart, &ridEnd));
2032 for (rid = ridStart; rid < ridEnd; rid++)
2033 {
2034 ridGPC = m_pStgdb->m_MiniMd.GetGenericParamConstraintRid(rid);
2035 IfFailGo(m_pStgdb->m_MiniMd.GetGenericParamConstraintRecord(ridGPC, &pGPCRec));
2036 IfFailGo(m_pStgdb->m_MiniMd.PutCol(TBL_GenericParamConstraint,
2037 GenericParamConstraintRec::COL_Owner,
2038 pGPCRec, 0));
2039 IfFailGo(UpdateENCLog(TokenFromRid(ridGPC,mdtGenericParamConstraint)));
2040 }
2041
2042 //Emit new constraints
2043 mdToken* ptk;
2044 for (ptk = rtkConstraints; (ptk != NULL)&&(RidFromToken(*ptk)!=0); ptk++)
2045 {
2046 IfFailGo(m_pStgdb->m_MiniMd.AddGenericParamConstraintRecord(&pGPCRec, &ridGPC));
2047 IfFailGo(m_pStgdb->m_MiniMd.PutCol(TBL_GenericParamConstraint,
2048 GenericParamConstraintRec::COL_Owner,
2049 pGPCRec, RidFromToken(tkGP)));
2050 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_GenericParamConstraint,
2051 GenericParamConstraintRec::COL_Constraint,
2052 pGPCRec, *ptk));
2053 IfFailGo(UpdateENCLog(TokenFromRid(ridGPC,mdtGenericParamConstraint)));
2054 }
2055 }
2056 }
2057 else
2058 hr = META_E_BAD_INPUT_PARAMETER;
2059
2060ErrExit:
2061 return hr;
2062#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2063} // RegMeta::_SetGenericParamProps
2064
2065//*****************************************************************************
2066// Create and set a MethodSpec record.
2067//*****************************************************************************
2068STDMETHODIMP RegMeta::DefineMethodSpec( // S_OK or error
2069 mdToken tkImport, // [IN] MethodDef or MemberRef
2070 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
2071 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
2072 mdMethodSpec *pmi) // [OUT] method instantiation token
2073{
2074#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2075 return E_NOTIMPL;
2076#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2077 HRESULT hr = S_OK;
2078
2079 BEGIN_ENTRYPOINT_NOTHROW;
2080
2081 MethodSpecRec *pRecord = 0; // The MethodSpec record.
2082 RID iRecord; // RID of new MethodSpec record.
2083
2084
2085 LOG((LOGMD, "MD RegMeta::DefineMethodSpec(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2086 tkImport, pvSigBlob, cbSigBlob, pmi));
2087 START_MD_PERF();
2088 LOCKWRITE();
2089
2090 // See if this version of the metadata can do Generics
2091 if (!m_pStgdb->m_MiniMd.SupportsGenerics())
2092 IfFailGo(CLDB_E_INCOMPATIBLE);
2093
2094 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2095
2096 // Check that it is a method, or at least memberref.
2097 if ((TypeFromToken(tkImport) != mdtMethodDef) && (TypeFromToken(tkImport) != mdtMemberRef))
2098 IfFailGo(META_E_BAD_INPUT_PARAMETER);
2099
2100 // Must have a signature, and someplace to return the token.
2101 if ((pvSigBlob == NULL) || (cbSigBlob == 0) || (pmi == NULL))
2102 IfFailGo(META_E_BAD_INPUT_PARAMETER);
2103
2104 // If the MethodSpec already exists, just return the token, else
2105 // create a new record.
2106 if (CheckDups(MDDupMethodSpec))
2107 {
2108 hr = ImportHelper::FindMethodSpecByMethodAndInstantiation(&(m_pStgdb->m_MiniMd), tkImport,pvSigBlob, cbSigBlob, pmi);
2109 if (SUCCEEDED(hr))
2110 {
2111 if (IsENCOn()) //GENERICS: is this correct? Do we really want to support ENC of MethodSpecs?
2112 IfFailGo(m_pStgdb->m_MiniMd.GetMethodSpecRecord(RidFromToken(*pmi), &pRecord));
2113 else
2114 {
2115 hr = META_S_DUPLICATE;
2116 goto ErrExit;
2117 }
2118 }
2119 else if (hr != CLDB_E_RECORD_NOTFOUND) // MemberRef exists
2120 IfFailGo(hr);
2121 }
2122
2123
2124 if (!pRecord)
2125 { // Create the record.
2126 IfFailGo(m_pStgdb->m_MiniMd.AddMethodSpecRecord(&pRecord, &iRecord));
2127
2128 /*GENERICS: do we need to do anything like this?
2129 Probably not, since SetMemberDefDirty is for ref to def optimization, and there are no method spec "refs".
2130 // record the more defs are introduced.
2131 SetMemberDefDirty(true);
2132 */
2133
2134 // Give token to caller.
2135 *pmi = TokenFromRid(iRecord, mdtMethodSpec);
2136 }
2137
2138 // Save row data.
2139 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_MethodSpec, MethodSpecRec::COL_Method, pRecord, tkImport));
2140 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_MethodSpec, MethodSpecRec::COL_Instantiation, pRecord,
2141 pvSigBlob, cbSigBlob));
2142 /*@GENERICS: todo: update MethodSpec hash table */
2143 /* IfFailGo(m_pStgdb->m_MiniMd.AddMemberRefToHash(*pmi) ); */
2144
2145 IfFailGo(UpdateENCLog(*pmi));
2146
2147ErrExit:
2148
2149 STOP_MD_PERF(DefineMethodSpec);
2150 END_ENTRYPOINT_NOTHROW;
2151 return hr;
2152#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2153} // RegMeta::DefineMethodSpec
2154
2155//*****************************************************************************
2156// Set the properties on the given Method token.
2157//*****************************************************************************
2158STDMETHODIMP RegMeta::SetMethodProps( // S_OK or error.
2159 mdMethodDef md, // [IN] The MethodDef.
2160 DWORD dwMethodFlags, // [IN] Method attributes.
2161 ULONG ulCodeRVA, // [IN] Code RVA.
2162 DWORD dwImplFlags) // [IN] MethodImpl flags.
2163{
2164#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2165 return E_NOTIMPL;
2166#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2167 HRESULT hr = S_OK;
2168
2169 BEGIN_ENTRYPOINT_NOTHROW;
2170
2171 LOG((LOGMD, "RegMeta::SetMethodProps(0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2172 md, dwMethodFlags, ulCodeRVA, dwImplFlags));
2173 START_MD_PERF();
2174 LOCKWRITE();
2175
2176 if (dwMethodFlags != ULONG_MAX)
2177 {
2178 // Make sure no one sets the reserved bits on the way in.
2179 _ASSERTE((dwMethodFlags & (mdReservedMask&~mdRTSpecialName)) == 0);
2180 dwMethodFlags &= (~mdReservedMask);
2181 }
2182
2183 hr = _SetMethodProps(md, dwMethodFlags, ulCodeRVA, dwImplFlags);
2184
2185ErrExit:
2186
2187 STOP_MD_PERF(SetMethodProps);
2188 END_ENTRYPOINT_NOTHROW;
2189 return hr;
2190#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2191} // RegMeta::SetMethodProps
2192
2193//*****************************************************************************
2194// Set the properties on the given Event token.
2195//*****************************************************************************
2196STDMETHODIMP RegMeta::SetEventProps( // S_OK or error.
2197 mdEvent ev, // [IN] The event token.
2198 DWORD dwEventFlags, // [IN] CorEventAttr.
2199 mdToken tkEventType, // [IN] A reference (mdTypeRef or mdTypeRef) to the Event class.
2200 mdMethodDef mdAddOn, // [IN] Add method.
2201 mdMethodDef mdRemoveOn, // [IN] Remove method.
2202 mdMethodDef mdFire, // [IN] Fire method.
2203 mdMethodDef rmdOtherMethods[]) // [IN] Array of other methods associate with the event.
2204{
2205#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2206 return E_NOTIMPL;
2207#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2208 HRESULT hr = S_OK;
2209
2210 BEGIN_ENTRYPOINT_NOTHROW;
2211
2212 LOG((LOGMD, "MD RegMeta::SetEventProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2213 ev, dwEventFlags, tkEventType, mdAddOn, mdRemoveOn, mdFire, rmdOtherMethods));
2214 START_MD_PERF();
2215 LOCKWRITE();
2216
2217 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2218
2219 IfFailGo(_SetEventProps1(ev, dwEventFlags, tkEventType));
2220 IfFailGo(_SetEventProps2(ev, mdAddOn, mdRemoveOn, mdFire, rmdOtherMethods, true));
2221
2222ErrExit:
2223
2224 STOP_MD_PERF(SetEventProps);
2225 END_ENTRYPOINT_NOTHROW;
2226 return hr;
2227#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2228} // RegMeta::SetEventProps
2229
2230//*****************************************************************************
2231// Set the properties on the given Permission token.
2232//*****************************************************************************
2233STDMETHODIMP RegMeta::SetPermissionSetProps( // S_OK or error.
2234 mdToken tk, // [IN] The object to be decorated.
2235 DWORD dwAction, // [IN] CorDeclSecurity.
2236 void const *pvPermission, // [IN] Permission blob.
2237 ULONG cbPermission, // [IN] Count of bytes of pvPermission.
2238 mdPermission *ppm) // [OUT] Permission token.
2239{
2240#ifdef FEATURE_METADATA_EMIT_ALL
2241 HRESULT hr = S_OK;
2242
2243 BEGIN_ENTRYPOINT_NOTHROW;
2244
2245 USHORT sAction = static_cast<USHORT>(dwAction); // Corresponding DeclSec field is a USHORT.
2246 mdPermission tkPerm;
2247
2248 LOG((LOGMD, "MD RegMeta::SetPermissionSetProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2249 tk, dwAction, pvPermission, cbPermission, ppm));
2250 START_MD_PERF();
2251 LOCKWRITE();
2252
2253 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2254
2255 _ASSERTE(TypeFromToken(tk) == mdtTypeDef || TypeFromToken(tk) == mdtMethodDef ||
2256 TypeFromToken(tk) == mdtAssembly);
2257
2258 // Check for valid Action.
2259 if (dwAction == ULONG_MAX || dwAction == 0 || dwAction > dclMaximumValue)
2260 IfFailGo(E_INVALIDARG);
2261
2262 IfFailGo(ImportHelper::FindPermission(&(m_pStgdb->m_MiniMd), tk, sAction, &tkPerm));
2263 if (ppm)
2264 *ppm = tkPerm;
2265 IfFailGo(_SetPermissionSetProps(tkPerm, dwAction, pvPermission, cbPermission));
2266ErrExit:
2267
2268 STOP_MD_PERF(SetPermissionSetProps);
2269 END_ENTRYPOINT_NOTHROW;
2270 return hr;
2271#else //!FEATURE_METADATA_EMIT_ALL
2272 return E_NOTIMPL;
2273#endif //!FEATURE_METADATA_EMIT_ALL
2274} // RegMeta::SetPermissionSetProps
2275
2276//*****************************************************************************
2277// This routine sets the p-invoke information for the specified Field or Method.
2278//*****************************************************************************
2279STDMETHODIMP RegMeta::DefinePinvokeMap( // Return code.
2280 mdToken tk, // [IN] FieldDef or MethodDef.
2281 DWORD dwMappingFlags, // [IN] Flags used for mapping.
2282 LPCWSTR szImportName, // [IN] Import name.
2283 mdModuleRef mrImportDLL) // [IN] ModuleRef token for the target DLL.
2284{
2285#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2286 return E_NOTIMPL;
2287#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2288 HRESULT hr = S_OK;
2289
2290 BEGIN_ENTRYPOINT_NOTHROW;
2291
2292 LOG((LOGMD, "MD RegMeta::DefinePinvokeMap(0x%08x, 0x%08x, %S, 0x%08x)\n",
2293 tk, dwMappingFlags, MDSTR(szImportName), mrImportDLL));
2294 START_MD_PERF();
2295 LOCKWRITE();
2296
2297 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2298
2299 hr = _DefinePinvokeMap(tk, dwMappingFlags, szImportName, mrImportDLL);
2300
2301ErrExit:
2302
2303 STOP_MD_PERF(DefinePinvokeMap);
2304 END_ENTRYPOINT_NOTHROW;
2305 return hr;
2306#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2307} // RegMeta::DefinePinvokeMap
2308
2309//*****************************************************************************
2310// Internal worker function for setting p-invoke info.
2311//*****************************************************************************
2312HRESULT RegMeta::_DefinePinvokeMap( // Return hresult.
2313 mdToken tk, // [IN] FieldDef or MethodDef.
2314 DWORD dwMappingFlags, // [IN] Flags used for mapping.
2315 LPCWSTR szImportName, // [IN] Import name.
2316 mdModuleRef mrImportDLL) // [IN] ModuleRef token for the target DLL.
2317{
2318#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2319 return E_NOTIMPL;
2320#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2321 ImplMapRec *pRecord;
2322 ULONG iRecord;
2323 bool bDupFound = false;
2324 HRESULT hr = S_OK;
2325
2326 _ASSERTE(TypeFromToken(tk) == mdtFieldDef || TypeFromToken(tk) == mdtMethodDef);
2327 _ASSERTE(TypeFromToken(mrImportDLL) == mdtModuleRef);
2328 _ASSERTE(RidFromToken(tk) && RidFromToken(mrImportDLL) && szImportName);
2329
2330 // Turn on the quick lookup flag.
2331 if (TypeFromToken(tk) == mdtMethodDef)
2332 {
2333 if (CheckDups(MDDupMethodDef))
2334 {
2335 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
2336 if (! InvalidRid(iRecord))
2337 bDupFound = true;
2338 }
2339 MethodRec *pMethod;
2340 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethod));
2341 pMethod->AddFlags(mdPinvokeImpl);
2342 }
2343 else // TypeFromToken(tk) == mdtFieldDef
2344 {
2345 if (CheckDups(MDDupFieldDef))
2346 {
2347 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
2348 if (!InvalidRid(iRecord))
2349 bDupFound = true;
2350 }
2351 FieldRec *pField;
2352 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tk), &pField));
2353 pField->AddFlags(fdPinvokeImpl);
2354 }
2355
2356 // Create a new record.
2357 if (bDupFound)
2358 {
2359 if (IsENCOn())
2360 IfFailGo(m_pStgdb->m_MiniMd.GetImplMapRecord(RidFromToken(iRecord), &pRecord));
2361 else
2362 {
2363 hr = META_S_DUPLICATE;
2364 goto ErrExit;
2365 }
2366 }
2367 else
2368 {
2369 IfFailGo(UpdateENCLog(tk));
2370 IfFailGo(m_pStgdb->m_MiniMd.AddImplMapRecord(&pRecord, &iRecord));
2371 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ImplMap,
2372 ImplMapRec::COL_MemberForwarded, pRecord, tk));
2373 IfFailGo( m_pStgdb->m_MiniMd.AddImplMapToHash(iRecord) );
2374
2375 }
2376
2377 // If no module, create a dummy, empty module.
2378 if (IsNilToken(mrImportDLL))
2379 {
2380 hr = ImportHelper::FindModuleRef(&m_pStgdb->m_MiniMd, "", &mrImportDLL);
2381 if (hr == CLDB_E_RECORD_NOTFOUND)
2382 IfFailGo(_DefineModuleRef(W(""), &mrImportDLL));
2383 }
2384
2385 // Set the data.
2386 if (dwMappingFlags != ULONG_MAX)
2387 pRecord->SetMappingFlags(static_cast<USHORT>(dwMappingFlags));
2388 IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_ImplMap, ImplMapRec::COL_ImportName,
2389 pRecord, szImportName));
2390 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ImplMap,
2391 ImplMapRec::COL_ImportScope, pRecord, mrImportDLL));
2392
2393 IfFailGo(UpdateENCLog2(TBL_ImplMap, iRecord));
2394
2395ErrExit:
2396
2397 return hr;
2398#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2399} // RegMeta::DefinePinvokeMap
2400
2401//*****************************************************************************
2402// This routine sets the p-invoke information for the specified Field or Method.
2403//*****************************************************************************
2404STDMETHODIMP RegMeta::SetPinvokeMap( // Return code.
2405 mdToken tk, // [IN] FieldDef or MethodDef.
2406 DWORD dwMappingFlags, // [IN] Flags used for mapping.
2407 LPCWSTR szImportName, // [IN] Import name.
2408 mdModuleRef mrImportDLL) // [IN] ModuleRef token for the target DLL.
2409{
2410#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2411 return E_NOTIMPL;
2412#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2413 HRESULT hr = S_OK;
2414
2415 BEGIN_ENTRYPOINT_NOTHROW;
2416
2417 ImplMapRec *pRecord;
2418 ULONG iRecord;
2419
2420 LOG((LOGMD, "MD RegMeta::SetPinvokeMap(0x%08x, 0x%08x, %S, 0x%08x)\n",
2421 tk, dwMappingFlags, MDSTR(szImportName), mrImportDLL));
2422 START_MD_PERF();
2423 LOCKWRITE();
2424
2425 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2426
2427 _ASSERTE(TypeFromToken(tk) == mdtFieldDef || TypeFromToken(tk) == mdtMethodDef);
2428 _ASSERTE(RidFromToken(tk));
2429
2430 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
2431
2432 if (InvalidRid(iRecord))
2433 IfFailGo(CLDB_E_RECORD_NOTFOUND);
2434 else
2435 IfFailGo(m_pStgdb->m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
2436
2437 // Set the data.
2438 if (dwMappingFlags != ULONG_MAX)
2439 pRecord->SetMappingFlags(static_cast<USHORT>(dwMappingFlags));
2440 if (szImportName)
2441 IfFailGo(m_pStgdb->m_MiniMd.PutStringW(TBL_ImplMap, ImplMapRec::COL_ImportName,
2442 pRecord, szImportName));
2443 if (! IsNilToken(mrImportDLL))
2444 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ImplMap, ImplMapRec::COL_ImportScope,
2445 pRecord, mrImportDLL));
2446
2447 IfFailGo(UpdateENCLog2(TBL_ImplMap, iRecord));
2448
2449ErrExit:
2450
2451 STOP_MD_PERF(SetPinvokeMap);
2452 END_ENTRYPOINT_NOTHROW;
2453 return hr;
2454#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2455} // RegMeta::SetPinvokeMap
2456
2457//*****************************************************************************
2458// This routine deletes the p-invoke record for the specified Field or Method.
2459//*****************************************************************************
2460STDMETHODIMP RegMeta::DeletePinvokeMap( // Return code.
2461 mdToken tk) // [IN]FieldDef or MethodDef.
2462{
2463#ifdef FEATURE_METADATA_EMIT_ALL
2464 HRESULT hr = S_OK;
2465
2466 BEGIN_ENTRYPOINT_NOTHROW;
2467
2468 ImplMapRec *pRecord;
2469 RID iRecord;
2470
2471 LOG((LOGMD, "MD RegMeta::DeletePinvokeMap(0x%08x)\n", tk));
2472 START_MD_PERF();
2473 LOCKWRITE();
2474
2475 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2476
2477 _ASSERTE(TypeFromToken(tk) == mdtFieldDef || TypeFromToken(tk) == mdtMethodDef);
2478 _ASSERTE(!IsNilToken(tk));
2479 _ASSERTE(!m_bSaveOptimized && "Cannot delete records after PreSave() and before Save().");
2480
2481 // Get the PinvokeMap record.
2482 IfFailGo(m_pStgdb->m_MiniMd.FindImplMapHelper(tk, &iRecord));
2483 if (InvalidRid(iRecord))
2484 {
2485 IfFailGo(CLDB_E_RECORD_NOTFOUND);
2486 }
2487 IfFailGo(m_pStgdb->m_MiniMd.GetImplMapRecord(iRecord, &pRecord));
2488
2489 // Clear the MemberForwarded token from the PinvokeMap record.
2490 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_ImplMap,
2491 ImplMapRec::COL_MemberForwarded, pRecord, mdFieldDefNil));
2492
2493 // turn off the PinvokeImpl bit.
2494 if (TypeFromToken(tk) == mdtFieldDef)
2495 {
2496 FieldRec *pFieldRec;
2497
2498 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(tk), &pFieldRec));
2499 pFieldRec->RemoveFlags(fdPinvokeImpl);
2500 }
2501 else // TypeFromToken(tk) == mdtMethodDef
2502 {
2503 MethodRec *pMethodRec;
2504
2505 IfFailGo(m_pStgdb->m_MiniMd.GetMethodRecord(RidFromToken(tk), &pMethodRec));
2506 pMethodRec->RemoveFlags(mdPinvokeImpl);
2507 }
2508
2509 // Update the ENC log for the parent token.
2510 IfFailGo(UpdateENCLog(tk));
2511 // Create the log record for the non-token record.
2512 IfFailGo(UpdateENCLog2(TBL_ImplMap, iRecord));
2513
2514ErrExit:
2515 STOP_MD_PERF(DeletePinvokeMap);
2516 END_ENTRYPOINT_NOTHROW;
2517 return hr;
2518#else //!FEATURE_METADATA_EMIT_ALL
2519 return E_NOTIMPL;
2520#endif //!FEATURE_METADATA_EMIT_ALL
2521} // RegMeta::DeletePinvokeMap
2522
2523//*****************************************************************************
2524// Create and define a new FieldDef record.
2525//*****************************************************************************
2526HRESULT RegMeta::DefineField( // S_OK or error.
2527 mdTypeDef td, // Parent TypeDef
2528 LPCWSTR szName, // Name of member
2529 DWORD dwFieldFlags, // Member attributes
2530 PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature
2531 ULONG cbSigBlob, // [IN] count of bytes in the signature blob
2532 DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_*
2533 void const *pValue, // [IN] constant value
2534 ULONG cchValue, // [IN] size of constant value (string, in wide chars).
2535 mdFieldDef *pmd) // [OUT] Put member token here
2536{
2537#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2538 return E_NOTIMPL;
2539#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2540 HRESULT hr = S_OK;
2541
2542 BEGIN_ENTRYPOINT_NOTHROW;
2543
2544 FieldRec *pRecord = NULL; // The new record.
2545 RID iRecord; // RID of new record.
2546 LPUTF8 szNameUtf8;
2547 UTF8STR(szName, szNameUtf8);
2548
2549 LOG((LOGMD, "MD: RegMeta::DefineField(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2550 td, MDSTR(szName), dwFieldFlags, pvSigBlob, cbSigBlob, dwCPlusTypeFlag, pValue, cchValue, pmd));
2551
2552 START_MD_PERF();
2553 LOCKWRITE();
2554
2555 _ASSERTE(pmd);
2556
2557 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2558 IsGlobalMethodParent(&td);
2559
2560 // Validate flags.
2561 if (dwFieldFlags != ULONG_MAX)
2562 {
2563 // fdHasFieldRVA is settable, but not re-settable by applications.
2564 _ASSERTE((dwFieldFlags & (fdReservedMask&~(fdHasFieldRVA|fdRTSpecialName))) == 0);
2565 dwFieldFlags &= ~(fdReservedMask&~fdHasFieldRVA);
2566 }
2567
2568 // See if this field has already been defined as a forward reference
2569 // from a MemberRef. If so, then update the data to match what we know now.
2570 if (CheckDups(MDDupFieldDef))
2571 {
2572
2573 hr = ImportHelper::FindField(&(m_pStgdb->m_MiniMd),
2574 td,
2575 szNameUtf8,
2576 pvSigBlob,
2577 cbSigBlob,
2578 pmd);
2579 if (SUCCEEDED(hr))
2580 {
2581 if (IsENCOn())
2582 {
2583 IfFailGo(m_pStgdb->m_MiniMd.GetFieldRecord(RidFromToken(*pmd), &pRecord));
2584 }
2585 else
2586 {
2587 hr = META_S_DUPLICATE;
2588 goto ErrExit;
2589 }
2590 }
2591 else if (hr != CLDB_E_RECORD_NOTFOUND)
2592 {
2593 IfFailGo(hr);
2594 }
2595 }
2596
2597 // Create a new record.
2598 if (pRecord == NULL)
2599 {
2600 // Create the field record.
2601 IfFailGo(m_pStgdb->m_MiniMd.AddFieldRecord(&pRecord, &iRecord));
2602
2603 // Set output parameter pmd.
2604 *pmd = TokenFromRid(iRecord, mdtFieldDef);
2605
2606 // Add to parent's list of child records.
2607 IfFailGo(m_pStgdb->m_MiniMd.AddFieldToTypeDef(RidFromToken(td), iRecord));
2608
2609 IfFailGo(UpdateENCLog(td, CMiniMdRW::eDeltaFieldCreate));
2610
2611 // record the more defs are introduced.
2612 SetMemberDefDirty(true);
2613 }
2614
2615 // Set the Field properties.
2616 IfFailGo(m_pStgdb->m_MiniMd.PutString(TBL_Field, FieldRec::COL_Name, pRecord, szNameUtf8));
2617 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_Field, FieldRec::COL_Signature, pRecord,
2618 pvSigBlob, cbSigBlob));
2619
2620 // Check to see if it is value__ for enum type
2621 // <TODO>@FUTURE: shouldn't we have checked the type containing the field to be a Enum type first of all?</TODO>
2622 // value__ is defined in corhdr.h. However, corhdr.h does not have the
2623 // the W() macro we need (since it's distributed to windows). We substitute the values of the
2624 // macro in the code below to work around this issue.
2625 // #define COR_ENUM_FIELD_NAME_W L"value__"
2626
2627 if (!wcscmp(szName, W("value__")))
2628 {
2629 dwFieldFlags |= fdRTSpecialName | fdSpecialName;
2630 }
2631 SetCallerDefine();
2632 IfFailGo(_SetFieldProps(*pmd, dwFieldFlags, dwCPlusTypeFlag, pValue, cchValue));
2633 IfFailGo(m_pStgdb->m_MiniMd.AddMemberDefToHash(*pmd, td) );
2634
2635ErrExit:
2636 SetCallerExternal();
2637
2638 STOP_MD_PERF(DefineField);
2639
2640 END_ENTRYPOINT_NOTHROW;
2641
2642 return hr;
2643#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2644} // RegMeta::DefineField
2645
2646//*****************************************************************************
2647// Define and set a Property record.
2648//*****************************************************************************
2649HRESULT RegMeta::DefineProperty(
2650 mdTypeDef td, // [IN] the class/interface on which the property is being defined
2651 LPCWSTR szProperty, // [IN] Name of the property
2652 DWORD dwPropFlags, // [IN] CorPropertyAttr
2653 PCCOR_SIGNATURE pvSig, // [IN] the required type signature
2654 ULONG cbSig, // [IN] the size of the type signature blob
2655 DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_*
2656 void const *pValue, // [IN] constant value
2657 ULONG cchValue, // [IN] size of constant value (string, in wide chars).
2658 mdMethodDef mdSetter, // [IN] optional setter of the property
2659 mdMethodDef mdGetter, // [IN] optional getter of the property
2660 mdMethodDef rmdOtherMethods[], // [IN] an optional array of other methods
2661 mdProperty *pmdProp) // [OUT] output property token
2662{
2663#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2664 return E_NOTIMPL;
2665#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2666 HRESULT hr = S_OK;
2667
2668 BEGIN_ENTRYPOINT_NOTHROW;
2669
2670 PropertyRec *pPropRec = NULL;
2671 RID iPropRec;
2672 PropertyMapRec *pPropMap;
2673 RID iPropMap;
2674 LPUTF8 szUTF8Property;
2675 UTF8STR(szProperty, szUTF8Property);
2676
2677 LOG((LOGMD, "MD RegMeta::DefineProperty(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2678 td, szProperty, dwPropFlags, pvSig, cbSig, dwCPlusTypeFlag, pValue, cchValue, mdSetter, mdGetter,
2679 rmdOtherMethods, pmdProp));
2680
2681 START_MD_PERF();
2682 LOCKWRITE();
2683
2684 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2685
2686 _ASSERTE(TypeFromToken(td) == mdtTypeDef && td != mdTypeDefNil &&
2687 szProperty && pvSig && cbSig && pmdProp);
2688
2689 if (CheckDups(MDDupProperty))
2690 {
2691 hr = ImportHelper::FindProperty(&(m_pStgdb->m_MiniMd), td, szUTF8Property, pvSig, cbSig, pmdProp);
2692 if (SUCCEEDED(hr))
2693 {
2694 if (IsENCOn())
2695 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyRecord(RidFromToken(*pmdProp), &pPropRec));
2696 else
2697 {
2698 hr = META_S_DUPLICATE;
2699 goto ErrExit;
2700 }
2701 }
2702 else if (hr != CLDB_E_RECORD_NOTFOUND)
2703 IfFailGo(hr);
2704 }
2705
2706 if (! pPropRec)
2707 {
2708 // Create a new map if one doesn't exist already, else retrieve the existing one.
2709 // The property map must be created before the PropertyRecord, the new property
2710 // map will be pointing past the first property record.
2711 IfFailGo(m_pStgdb->m_MiniMd.FindPropertyMapFor(RidFromToken(td), &iPropMap));
2712 if (InvalidRid(iPropMap))
2713 {
2714 // Create new record.
2715 IfFailGo(m_pStgdb->m_MiniMd.AddPropertyMapRecord(&pPropMap, &iPropMap));
2716 // Set parent.
2717 IfFailGo(m_pStgdb->m_MiniMd.PutToken(TBL_PropertyMap,
2718 PropertyMapRec::COL_Parent, pPropMap, td));
2719 IfFailGo(UpdateENCLog2(TBL_PropertyMap, iPropMap));
2720 }
2721 else
2722 {
2723 IfFailGo(m_pStgdb->m_MiniMd.GetPropertyMapRecord(iPropMap, &pPropMap));
2724 }
2725
2726 // Create a new record.
2727 IfFailGo(m_pStgdb->m_MiniMd.AddPropertyRecord(&pPropRec, &iPropRec));
2728
2729 // Set output parameter.
2730 *pmdProp = TokenFromRid(iPropRec, mdtProperty);
2731
2732 // Add Property to the PropertyMap.
2733 IfFailGo(m_pStgdb->m_MiniMd.AddPropertyToPropertyMap(RidFromToken(iPropMap), iPropRec));
2734
2735 IfFailGo(UpdateENCLog2(TBL_PropertyMap, iPropMap, CMiniMdRW::eDeltaPropertyCreate));
2736 }
2737
2738 // Save the data.
2739 IfFailGo(m_pStgdb->m_MiniMd.PutBlob(TBL_Property, PropertyRec::COL_Type, pPropRec,
2740 pvSig, cbSig));
2741 IfFailGo( m_pStgdb->m_MiniMd.PutString(TBL_Property, PropertyRec::COL_Name,
2742 pPropRec, szUTF8Property) );
2743
2744 SetCallerDefine();
2745 IfFailGo(_SetPropertyProps(*pmdProp, dwPropFlags, dwCPlusTypeFlag, pValue, cchValue, mdSetter,
2746 mdGetter, rmdOtherMethods));
2747
2748 // Add the <property token, typedef token> to the lookup table
2749 if (m_pStgdb->m_MiniMd.HasIndirectTable(TBL_Property))
2750 IfFailGo( m_pStgdb->m_MiniMd.AddPropertyToLookUpTable(*pmdProp, td) );
2751
2752ErrExit:
2753 SetCallerExternal();
2754
2755 STOP_MD_PERF(DefineProperty);
2756
2757 END_ENTRYPOINT_NOTHROW;
2758
2759 return hr;
2760#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2761} // RegMeta::DefineProperty
2762
2763//*****************************************************************************
2764// Create a record in the Param table. Any set of name, flags, or default value
2765// may be set.
2766//*****************************************************************************
2767HRESULT RegMeta::DefineParam(
2768 mdMethodDef md, // [IN] Owning method
2769 ULONG ulParamSeq, // [IN] Which param
2770 LPCWSTR szName, // [IN] Optional param name
2771 DWORD dwParamFlags, // [IN] Optional param flags
2772 DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_*
2773 void const *pValue, // [IN] constant value
2774 ULONG cchValue, // [IN] size of constant value (string, in wide chars).
2775 mdParamDef *ppd) // [OUT] Put param token here
2776{
2777#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2778 return E_NOTIMPL;
2779#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2780 HRESULT hr = S_OK;
2781
2782 BEGIN_ENTRYPOINT_NOTHROW;
2783
2784 RID iRecord;
2785 ParamRec *pRecord = 0;
2786
2787 LOG((LOGMD, "MD RegMeta::DefineParam(0x%08x, 0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2788 md, ulParamSeq, MDSTR(szName), dwParamFlags, dwCPlusTypeFlag, pValue, cchValue, ppd));
2789 START_MD_PERF();
2790 LOCKWRITE();
2791
2792 _ASSERTE(TypeFromToken(md) == mdtMethodDef && md != mdMethodDefNil &&
2793 ulParamSeq != ULONG_MAX && ppd);
2794
2795 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2796
2797 // Retrieve or create the Param row.
2798 if (CheckDups(MDDupParamDef))
2799 {
2800 hr = _FindParamOfMethod(md, ulParamSeq, ppd);
2801 if (SUCCEEDED(hr))
2802 {
2803 if (IsENCOn())
2804 IfFailGo(m_pStgdb->m_MiniMd.GetParamRecord(RidFromToken(*ppd), &pRecord));
2805 else
2806 {
2807 hr = META_S_DUPLICATE;
2808 goto ErrExit;
2809 }
2810 }
2811 else if (hr != CLDB_E_RECORD_NOTFOUND)
2812 IfFailGo(hr);
2813 }
2814
2815 if (!pRecord)
2816 {
2817 // Create the Param record.
2818 IfFailGo(m_pStgdb->m_MiniMd.AddParamRecord(&pRecord, &iRecord));
2819
2820 // Set the output parameter.
2821 *ppd = TokenFromRid(iRecord, mdtParamDef);
2822
2823 // Set sequence number.
2824 pRecord->SetSequence(static_cast<USHORT>(ulParamSeq));
2825
2826 // Add to the parent's list of child records.
2827 IfFailGo(m_pStgdb->m_MiniMd.AddParamToMethod(RidFromToken(md), iRecord));
2828
2829 IfFailGo(UpdateENCLog(md, CMiniMdRW::eDeltaParamCreate));
2830 }
2831
2832 SetCallerDefine();
2833 // Set the properties.
2834 IfFailGo(_SetParamProps(*ppd, szName, dwParamFlags, dwCPlusTypeFlag, pValue, cchValue));
2835
2836ErrExit:
2837 ;
2838 END_ENTRYPOINT_NOTHROW;
2839 SetCallerExternal();
2840
2841 STOP_MD_PERF(DefineParam);
2842 return hr;
2843#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2844} // RegMeta::DefineParam
2845
2846//*****************************************************************************
2847// Set the properties on the given Field token.
2848//*****************************************************************************
2849HRESULT RegMeta::SetFieldProps( // S_OK or error.
2850 mdFieldDef fd, // [IN] The FieldDef.
2851 DWORD dwFieldFlags, // [IN] Field attributes.
2852 DWORD dwCPlusTypeFlag, // [IN] Flag for the value type, selected ELEMENT_TYPE_*
2853 void const *pValue, // [IN] Constant value.
2854 ULONG cchValue) // [IN] size of constant value (string, in wide chars).
2855{
2856#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2857 return E_NOTIMPL;
2858#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2859 HRESULT hr = S_OK;
2860
2861 BEGIN_ENTRYPOINT_NOTHROW;
2862
2863
2864 LOG((LOGMD, "MD: RegMeta::SetFieldProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2865 fd, dwFieldFlags, dwCPlusTypeFlag, pValue, cchValue));
2866 START_MD_PERF();
2867 LOCKWRITE();
2868
2869 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2870
2871 // Validate flags.
2872 if (dwFieldFlags != ULONG_MAX)
2873 {
2874 // fdHasFieldRVA is settable, but not re-settable by applications.
2875 _ASSERTE((dwFieldFlags & (fdReservedMask&~(fdHasFieldRVA|fdRTSpecialName))) == 0);
2876 dwFieldFlags &= ~(fdReservedMask&~fdHasFieldRVA);
2877 }
2878
2879 hr = _SetFieldProps(fd, dwFieldFlags, dwCPlusTypeFlag, pValue, cchValue);
2880
2881ErrExit:
2882
2883 STOP_MD_PERF(SetFieldProps);
2884 END_ENTRYPOINT_NOTHROW;
2885 return hr;
2886#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2887} // RegMeta::SetFieldProps
2888
2889//*****************************************************************************
2890// Set the properties on the given Property token.
2891//*****************************************************************************
2892HRESULT RegMeta::SetPropertyProps( // S_OK or error.
2893 mdProperty pr, // [IN] Property token.
2894 DWORD dwPropFlags, // [IN] CorPropertyAttr.
2895 DWORD dwCPlusTypeFlag, // [IN] Flag for value type, selected ELEMENT_TYPE_*
2896 void const *pValue, // [IN] Constant value.
2897 ULONG cchValue, // [IN] size of constant value (string, in wide chars).
2898 mdMethodDef mdSetter, // [IN] Setter of the property.
2899 mdMethodDef mdGetter, // [IN] Getter of the property.
2900 mdMethodDef rmdOtherMethods[]) // [IN] Array of other methods.
2901{
2902#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2903 return E_NOTIMPL;
2904#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2905 HRESULT hr = S_OK;
2906
2907 BEGIN_ENTRYPOINT_NOTHROW;
2908
2909
2910 LOG((LOGMD, "MD RegMeta::SetPropertyProps(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2911 pr, dwPropFlags, dwCPlusTypeFlag, pValue, cchValue, mdSetter, mdGetter,
2912 rmdOtherMethods));
2913 START_MD_PERF();
2914 LOCKWRITE();
2915
2916 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2917
2918 hr = _SetPropertyProps(pr, dwPropFlags, dwCPlusTypeFlag, pValue, cchValue, mdSetter, mdGetter, rmdOtherMethods);
2919
2920ErrExit:
2921
2922 STOP_MD_PERF(SetPropertyProps);
2923 END_ENTRYPOINT_NOTHROW;
2924 return hr;
2925#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2926} // RegMeta::SetPropertyProps
2927
2928
2929//*****************************************************************************
2930// This routine sets properties on the given Param token.
2931//*****************************************************************************
2932HRESULT RegMeta::SetParamProps( // Return code.
2933 mdParamDef pd, // [IN] Param token.
2934 LPCWSTR szName, // [IN] Param name.
2935 DWORD dwParamFlags, // [IN] Param flags.
2936 DWORD dwCPlusTypeFlag, // [IN] Flag for value type. selected ELEMENT_TYPE_*.
2937 void const *pValue, // [OUT] Constant value.
2938 ULONG cchValue) // [IN] size of constant value (string, in wide chars).
2939{
2940#ifdef FEATURE_METADATA_EMIT_IN_DEBUGGER
2941 return E_NOTIMPL;
2942#else //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2943 HRESULT hr = S_OK;
2944
2945 BEGIN_ENTRYPOINT_NOTHROW;
2946
2947 LOG((LOGMD, "MD RegMeta::SetParamProps(0x%08x, %S, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
2948 pd, MDSTR(szName), dwParamFlags, dwCPlusTypeFlag, pValue, cchValue));
2949 START_MD_PERF();
2950 LOCKWRITE();
2951
2952 IfFailGo(m_pStgdb->m_MiniMd.PreUpdate());
2953
2954 hr = _SetParamProps(pd, szName, dwParamFlags, dwCPlusTypeFlag, pValue, cchValue);
2955
2956ErrExit:
2957
2958 STOP_MD_PERF(SetParamProps);
2959 END_ENTRYPOINT_NOTHROW;
2960 return hr;
2961#endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER
2962} // RegMeta::SetParamProps
2963
2964//*****************************************************************************
2965// Apply edit and continue changes to this metadata.
2966//*****************************************************************************
2967STDMETHODIMP RegMeta::ApplyEditAndContinue( // S_OK or error.
2968 IUnknown *pUnk) // [IN] Metadata from the delta PE.
2969{
2970#ifdef FEATURE_METADATA_EMIT_ALL
2971 HRESULT hr;
2972
2973 BEGIN_ENTRYPOINT_NOTHROW;
2974
2975 IMetaDataImport2 *pImport=0; // Interface on the delta metadata.
2976 RegMeta *pDeltaMD=0; // The delta metadata.
2977 CMiniMdRW *mdDelta = NULL;
2978 CMiniMdRW *mdBase = NULL;
2979
2980 // Get the MiniMd on the delta.
2981 IfFailGo(pUnk->QueryInterface(IID_IMetaDataImport2, (void**)&pImport));
2982
2983 pDeltaMD = static_cast<RegMeta*>(pImport);
2984
2985 mdDelta = &(pDeltaMD->m_pStgdb->m_MiniMd);
2986 mdBase = &(m_pStgdb->m_MiniMd);
2987
2988 IfFailGo(mdBase->ConvertToRW());
2989 IfFailGo(mdBase->ApplyDelta(*mdDelta));
2990
2991ErrExit:
2992 if (pImport)
2993 pImport->Release();
2994 END_ENTRYPOINT_NOTHROW;
2995 return hr;
2996#else //!FEATURE_METADATA_EMIT_ALL
2997 return E_NOTIMPL;
2998#endif //!FEATURE_METADATA_EMIT_ALL
2999} // RegMeta::ApplyEditAndContinue
3000
3001#endif //FEATURE_METADATA_EMIT
3002