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 | //***************************************************************************** |
28 | STDMETHODIMP 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 | |
133 | ErrExit: |
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 | //***************************************************************************** |
146 | STDMETHODIMP 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)); |
200 | ErrExit: |
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 | //***************************************************************************** |
213 | STDMETHODIMP 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 | |
239 | ErrExit: |
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 | //***************************************************************************** |
250 | STDMETHODIMP 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 | |
300 | ErrExit: |
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 | //***************************************************************************** |
311 | HRESULT 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 | |
378 | ErrExit: |
379 | return hr; |
380 | #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER |
381 | } // RegMeta::_SetRVA |
382 | |
383 | //***************************************************************************** |
384 | // Given a name, create a TypeRef. |
385 | //***************************************************************************** |
386 | STDMETHODIMP 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 | |
409 | ErrExit: |
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 | //***************************************************************************** |
420 | STDMETHODIMP 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 | |
484 | ErrExit: |
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 | //***************************************************************************** |
500 | STDMETHODIMP 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 | |
581 | ErrExit: |
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 | //***************************************************************************** |
592 | STDMETHODIMP 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 | |
699 | ErrExit: |
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 | //***************************************************************************** |
710 | STDMETHODIMP 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)); |
750 | ErrExit: |
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 | //***************************************************************************** |
764 | STDMETHODIMP 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 | |
806 | ErrExit: |
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 | //***************************************************************************** |
817 | HRESULT 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 | |
854 | ErrExit: |
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 | //***************************************************************************** |
863 | HRESULT 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 | |
895 | ErrExit: |
896 | return hr; |
897 | #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER |
898 | } // RegMeta::_SetFieldOffset |
899 | |
900 | //***************************************************************************** |
901 | // Delete the ClassLayout information. |
902 | //***************************************************************************** |
903 | STDMETHODIMP 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 | } |
968 | ErrExit: |
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 | //***************************************************************************** |
980 | STDMETHODIMP 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 | |
1002 | ErrExit: |
1003 | STOP_MD_PERF(SetFieldMarshal); |
1004 | END_ENTRYPOINT_NOTHROW; |
1005 | return hr; |
1006 | #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER |
1007 | } // RegMeta::SetFieldMarshal |
1008 | |
1009 | HRESULT 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 | |
1059 | ErrExit: |
1060 | |
1061 | return hr; |
1062 | } // RegMeta::_SetFieldMarshal |
1063 | |
1064 | |
1065 | //***************************************************************************** |
1066 | // Delete the FieldMarshal record for the given token. |
1067 | //***************************************************************************** |
1068 | STDMETHODIMP 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 | |
1124 | ErrExit: |
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 | //***************************************************************************** |
1136 | STDMETHODIMP 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 | |
1157 | ErrExit: |
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 | //***************************************************************************** |
1170 | HRESULT 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)); |
1236 | ErrExit: |
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 | //***************************************************************************** |
1250 | STDMETHODIMP 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 | |
1270 | ErrExit: |
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 | //***************************************************************************** |
1283 | STDMETHODIMP 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 | |
1306 | ErrExit: |
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 | //***************************************************************************** |
1317 | STDMETHODIMP 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 | |
1336 | ErrExit: |
1337 | STOP_MD_PERF(DefineModuleRef); |
1338 | END_ENTRYPOINT_NOTHROW; |
1339 | return hr; |
1340 | #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER |
1341 | } // RegMeta::DefineModuleRef |
1342 | |
1343 | HRESULT 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 | |
1391 | ErrExit: |
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 | //***************************************************************************** |
1400 | STDMETHODIMP 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 | |
1435 | ErrExit: |
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 | //***************************************************************************** |
1446 | STDMETHODIMP 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 | |
1499 | ErrExit: |
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 | //***************************************************************************** |
1513 | STDMETHODIMP 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 | |
1579 | ErrExit: |
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 | |
1596 | STDMETHODIMP 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 | //***************************************************************************** |
1777 | STDMETHODIMP 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 | |
1799 | ErrExit: |
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 | //***************************************************************************** |
1811 | STDMETHODIMP 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 | |
1840 | ErrExit: |
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 | //***************************************************************************** |
1850 | STDMETHODIMP 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 | |
1935 | ErrExit: |
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 | //***************************************************************************** |
1950 | STDMETHODIMP 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 | |
1986 | ErrExit: |
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 | //***************************************************************************** |
1997 | HRESULT 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 | |
2060 | ErrExit: |
2061 | return hr; |
2062 | #endif //!FEATURE_METADATA_EMIT_IN_DEBUGGER |
2063 | } // RegMeta::_SetGenericParamProps |
2064 | |
2065 | //***************************************************************************** |
2066 | // Create and set a MethodSpec record. |
2067 | //***************************************************************************** |
2068 | STDMETHODIMP 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 | |
2147 | ErrExit: |
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 | //***************************************************************************** |
2158 | STDMETHODIMP 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 | |
2185 | ErrExit: |
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 | //***************************************************************************** |
2196 | STDMETHODIMP 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 | |
2222 | ErrExit: |
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 | //***************************************************************************** |
2233 | STDMETHODIMP 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)); |
2266 | ErrExit: |
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 | //***************************************************************************** |
2279 | STDMETHODIMP 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 | |
2301 | ErrExit: |
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 | //***************************************************************************** |
2312 | HRESULT 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 | |
2395 | ErrExit: |
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 | //***************************************************************************** |
2404 | STDMETHODIMP 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 | |
2449 | ErrExit: |
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 | //***************************************************************************** |
2460 | STDMETHODIMP 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 | |
2514 | ErrExit: |
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 | //***************************************************************************** |
2526 | HRESULT 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 | |
2635 | ErrExit: |
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 | //***************************************************************************** |
2649 | HRESULT 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 | |
2752 | ErrExit: |
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 | //***************************************************************************** |
2767 | HRESULT 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 | |
2836 | ErrExit: |
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 | //***************************************************************************** |
2849 | HRESULT 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 | |
2881 | ErrExit: |
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 | //***************************************************************************** |
2892 | HRESULT 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 | |
2920 | ErrExit: |
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 | //***************************************************************************** |
2932 | HRESULT 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 | |
2956 | ErrExit: |
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 | //***************************************************************************** |
2967 | STDMETHODIMP 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 | |
2991 | ErrExit: |
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 | |