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// File: RegMeta_IMetaDataTables.cpp
6//
7
8//
9// Methods of code:RegMeta class which implement public API interfaces code:IMetaDataTables:
10// * code:RegMeta::GetStringHeapSize
11// * code:RegMeta::GetBlobHeapSize
12// * code:RegMeta::GetGuidHeapSize
13// * code:RegMeta::GetUserStringHeapSize
14//
15// * code:RegMeta#GetString_IMetaDataTables
16// * code:RegMeta#GetBlob_IMetaDataTables
17// * code:RegMeta#GetGuid_IMetaDataTables
18// * code:RegMeta#GetUserString_IMetaDataTables
19//
20// * code:RegMeta::GetNextString
21// * code:RegMeta::GetNextBlob
22// * code:RegMeta::GetNextGuid
23// * code:RegMeta::GetNextUserString
24//
25// * code:RegMeta::GetNumTables
26// * code:RegMeta::GetTableIndex
27// * code:RegMeta::GetTableInfo
28// * code:RegMeta::GetColumnInfo
29// * code:RegMeta::GetCodedTokenInfo
30// * code:RegMeta::GetRow
31// * code:RegMeta::GetColumn
32//
33// Methods of code:RegMeta class which implement public API interfaces code:IMetaDataTables2:
34// * code:RegMeta::GetMetaDataStorage
35// * code:RegMeta::GetMetaDataStreamInfo
36//
37// ======================================================================================
38
39#include "stdafx.h"
40#include "regmeta.h"
41
42// --------------------------------------------------------------------------------------
43//
44// Fills size (*pcbStringsHeapSize) of internal strings heap (#String).
45// Returns S_OK or error code. Fills *pcbStringsHeapSize with 0 on error.
46// Implements public API code:IMetaDataTables::GetStringHeapSize.
47//
48HRESULT
49RegMeta::GetStringHeapSize(
50 __out ULONG *pcbStringsHeapSize) // [OUT] Size of the string heap.
51{
52 HRESULT hr = S_OK;
53 BEGIN_ENTRYPOINT_NOTHROW;
54
55 *pcbStringsHeapSize = m_pStgdb->m_MiniMd.m_StringHeap.GetUnalignedSize();
56
57 END_ENTRYPOINT_NOTHROW;
58 return hr;
59} // RegMeta::GetStringHeapSize
60
61// --------------------------------------------------------------------------------------
62//
63// Fills size (*pcbBlobsHeapSize) of blobs heap (#Blob).
64// Returns S_OK or error code. Fills *pcbBlobsHeapSize with 0 on error.
65// Implements public API code:IMetaDataTables::GetBlobHeapSize.
66//
67HRESULT
68RegMeta::GetBlobHeapSize(
69 __out ULONG *pcbBlobsHeapSize) // [OUT] Size of the blob heap.
70{
71 HRESULT hr = S_OK;
72 BEGIN_ENTRYPOINT_NOTHROW;
73
74 *pcbBlobsHeapSize = m_pStgdb->m_MiniMd.m_BlobHeap.GetUnalignedSize();
75
76 END_ENTRYPOINT_NOTHROW;
77 return hr;
78} // RegMeta::GetBlobHeapSize
79
80// --------------------------------------------------------------------------------------
81//
82// Fills size (*pcbGuidsHeapSize) of guids heap (#GUID).
83// Returns S_OK or error code. Fills *pcbGuidsHeapSize with 0 on error.
84// Implements public API code:IMetaDataTables::GetGuidHeapSize.
85//
86HRESULT
87RegMeta::GetGuidHeapSize(
88 __out ULONG *pcbGuidsHeapSize) // [OUT] Size of the Guid heap.
89{
90 HRESULT hr = S_OK;
91 BEGIN_ENTRYPOINT_NOTHROW;
92
93 *pcbGuidsHeapSize = m_pStgdb->m_MiniMd.m_GuidHeap.GetSize();
94
95 END_ENTRYPOINT_NOTHROW;
96 return hr;
97} // RegMeta::GetGuidHeapSize
98
99// --------------------------------------------------------------------------------------
100//
101// Fills size (*pcbUserStringsHeapSize) of user strings heap (#US) (referenced from IL).
102// Returns S_OK or error code. Fills *pcbUserStringsHeapSize with 0 on error.
103// Implements public API code:IMetaDataTables::GetUserStringHeapSize.
104//
105HRESULT
106RegMeta::GetUserStringHeapSize(
107 __out ULONG *pcbUserStringsHeapSize) // [OUT] Size of the user string heap.
108{
109 HRESULT hr = S_OK;
110 BEGIN_ENTRYPOINT_NOTHROW;
111
112 *pcbUserStringsHeapSize = m_pStgdb->m_MiniMd.m_UserStringHeap.GetUnalignedSize();
113
114 END_ENTRYPOINT_NOTHROW;
115 return hr;
116} // RegMeta::GetUserStringHeapSize
117
118// --------------------------------------------------------------------------------------
119//
120//#GetString_IMetaDataTables
121//
122// Fills internal null-terminated string (*pszString) at index ixString from string heap (#String).
123// Returns S_OK (even for index 0) or error code (if index is invalid, fills *pszString with NULL then).
124// Implements public API code:IMetaDataTables::GetString.
125//
126HRESULT RegMeta::GetString(
127 ULONG ixString, // [IN] Value from a string column.
128 const char **pszString) // [OUT] Put a pointer to the string here.
129{
130 HRESULT hr = S_OK;
131 BEGIN_ENTRYPOINT_NOTHROW;
132
133 IfFailGo(m_pStgdb->m_MiniMd.getString(
134 ixString,
135 pszString));
136
137 _ASSERTE(hr == S_OK);
138 goto Exit;
139ErrExit:
140 *pszString = NULL;
141Exit:
142 END_ENTRYPOINT_NOTHROW;
143 return hr;
144} // RegMeta::GetString
145
146// --------------------------------------------------------------------------------------
147//
148//#GetBlob_IMetaDataTables
149//
150// Fills blob entry (*ppvData of size *pcbDataSize) at index ixBlob from blob heap (#Blob).
151// Returns S_OK (even for index 0) or error code (if index is invalid, fills NULL and o then).
152// Implements public API code:IMetaDataTables::GetBlob.
153//
154HRESULT RegMeta::GetBlob(
155 ULONG ixBlob, // [IN] Value from a blob column.
156 __out ULONG *pcbDataSize, // [OUT] Put size of the blob here.
157 __deref_out const void **ppvData) // [OUT] Put a pointer to the blob here.
158{
159 HRESULT hr = S_OK;
160 BEGIN_ENTRYPOINT_NOTHROW;
161
162 MetaData::DataBlob dataBlob;
163 IfFailGo(m_pStgdb->m_MiniMd.getBlob(ixBlob, &dataBlob));
164
165 *ppvData = (const void *)dataBlob.GetDataPointer();
166 *pcbDataSize = dataBlob.GetSize();
167
168 _ASSERTE(hr == S_OK);
169 goto Exit;
170ErrExit:
171 *ppvData = NULL;
172 *pcbDataSize = 0;
173Exit:
174 END_ENTRYPOINT_NOTHROW;
175 return hr;
176} // RegMeta::GetBlob
177
178// --------------------------------------------------------------------------------------
179//
180//#GetGuid_IMetaDataTables
181//
182// Fills guid (*ppGuid) at index ixGuid from guid heap (#GUID).
183// Returns S_OK and fills *ppGuid. Returns S_OK even for (invalid) index 0 (fills *ppGuid with pointer to
184// zeros then).
185// Retruns error code (if index is invalid except 0, fills NULL and o then).
186// Implements public API code:IMetaDataTables::GetGuid.
187//
188// Backward compatibility: returns S_OK even if the index is 0 which is invalid as specified in CLI ECMA
189// specification. In that case returns pointer to GUID from zeros.
190//
191HRESULT RegMeta::GetGuid(
192 ULONG ixGuid, // [IN] Value from a guid column.
193 const GUID **ppGuid) // [OUT] Put a pointer to the GUID here.
194{
195 HRESULT hr = S_OK;
196 BEGIN_ENTRYPOINT_NOTHROW;
197
198 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
199
200 if (ixGuid == 0)
201 {
202 // Return zeros
203 *ppGuid = GetPublicApiCompatibilityZeros<const GUID>();
204 hr = S_OK;
205 }
206 else
207 {
208 IfFailGo(m_pStgdb->m_MiniMd.m_GuidHeap.GetGuid(
209 ixGuid,
210 ppGuid));
211 }
212
213ErrExit:
214 END_ENTRYPOINT_NOTHROW;
215 return hr;
216} // RegMeta::GetGuid
217
218// --------------------------------------------------------------------------------------
219//
220//#GetUserString_IMetaDataTables
221//
222// Fills user string (*ppvData of size *pcbDataSize) at index ixUserString.
223// Returns S_OK (even for index 0) or error code (if index is invalid, fills NULL and o then).
224// Implements public API code:IMetaDataTables::GetUserString.
225//
226HRESULT
227RegMeta::GetUserString(
228 ULONG ixUserString, // [IN] Value from a UserString column.
229 __out ULONG *pcbDataSize, // [OUT] Put size of the UserString here.
230 __deref_out_opt const void **ppvData) // [OUT] Put a pointer to the UserString here.
231{
232 HRESULT hr = S_OK;
233 BEGIN_ENTRYPOINT_NOTHROW;
234
235 MetaData::DataBlob userString;
236 IfFailGo(m_pStgdb->m_MiniMd.GetUserString(ixUserString, &userString));
237 _ASSERTE(hr == S_OK);
238
239 *ppvData = (const void *)userString.GetDataPointer();
240 *pcbDataSize = userString.GetSize();
241
242 goto Exit;
243ErrExit:
244 *ppvData = NULL;
245 *pcbDataSize = 0;
246Exit:
247 END_ENTRYPOINT_NOTHROW;
248 return hr;
249} // RegMeta::GetUserString
250
251// --------------------------------------------------------------------------------------
252//
253//#GetNextString_IMetaDataTables
254//
255// Fills index of string (*pixNextString) from the internal strings heap (#String) starting behind string
256// at index ixString.
257// Returns S_OK or S_FALSE (if either index is invalid). Fills *pixNextString with 0 on S_FALSE.
258// Implements public API code:IMetaDataTables::GetNextString.
259//
260HRESULT
261RegMeta::GetNextString(
262 ULONG ixString, // [IN] Value from a string column.
263 __out ULONG *pixNextString) // [OUT] Put the index of the next string here.
264{
265 HRESULT hr = S_OK;
266 BEGIN_ENTRYPOINT_NOTHROW;
267
268 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
269
270 // Get string at index ixString
271 LPCSTR szString;
272 IfFailGo(m_pStgdb->m_MiniMd.m_StringHeap.GetString(
273 ixString,
274 &szString));
275 _ASSERTE(hr == S_OK);
276
277 // Get index behind the string - doesn't overflow, because string heap was verified
278 UINT32 ixNextString;
279 ixNextString = ixString + (UINT32)(strlen(szString) + 1);
280
281 // Verify that the next index is in the string heap
282 if (!m_pStgdb->m_MiniMd.m_StringHeap.IsValidIndex(ixNextString))
283 { // The next index is invalid
284 goto ErrExit;
285 }
286 // The next index is valid
287 *pixNextString = ixNextString;
288 goto Exit;
289
290ErrExit:
291 // Fill output parameters on error
292 *pixNextString = 0;
293 // Return S_FALSE if either of the string indexes is invalid (backward API compatibility)
294 hr = S_FALSE;
295Exit:
296 END_ENTRYPOINT_NOTHROW;
297 return hr;
298} // RegMeta::GetNextString
299
300// --------------------------------------------------------------------------------------
301//
302//#GetNextBlob_IMetaDataTables
303//
304// Fills index of blob (*pixNextBlob) from the blobs heap (#Blob) starting behind blob at index ixBlob.
305// Returns S_OK or S_FALSE (if either index is invalid). Fills *pixNextBlob with 0 on S_FALSE.
306// Implements public API code:IMetaDataTables::GetNextString.
307//
308HRESULT
309RegMeta::GetNextBlob(
310 ULONG ixBlob, // [IN] Value from a blob column.
311 __out ULONG *pixNextBlob) // [OUT] Put the index of the next blob here.
312{
313 HRESULT hr = S_OK;
314 BEGIN_ENTRYPOINT_NOTHROW;
315
316 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
317
318 // Get blob at index ixBlob (verifies that the blob is in the blob heap)
319 MetaData::DataBlob blob;
320 IfFailGo(m_pStgdb->m_MiniMd.m_BlobHeap.GetBlobWithSizePrefix(
321 ixBlob,
322 &blob));
323 _ASSERTE(hr == S_OK);
324
325 // Get index behind the blob - doesn't overflow, because the blob is in the blob heap
326 UINT32 ixNextBlob;
327 ixNextBlob = ixBlob + blob.GetSize();
328
329 // Verify that the next index is in the blob heap
330 if (!m_pStgdb->m_MiniMd.m_BlobHeap.IsValidIndex(ixNextBlob))
331 { // The next index is invalid
332 goto ErrExit;
333 }
334 // The next index is valid
335 *pixNextBlob = ixNextBlob;
336 goto Exit;
337
338ErrExit:
339 // Fill output parameters on error
340 *pixNextBlob = 0;
341 // Return S_FALSE if either of the string indexes is invalid (backward API compatibility)
342 hr = S_FALSE;
343Exit:
344 END_ENTRYPOINT_NOTHROW;
345 return hr;
346} // RegMeta::GetNextBlob
347
348// --------------------------------------------------------------------------------------
349//
350//#GetNextGuid_IMetaDataTables
351//
352// Fills index of guid (*pixNextGuid) from the guids heap (#GUID) starting behind guid at index ixGuid.
353// Returns S_OK or S_FALSE (if the new index is invalid). Fills *pixNextGuid with 0 on S_FALSE.
354// Implements public API code:IMetaDataTables::GetNextGuid.
355//
356// Backward compatibility: returns S_OK even if the guid index (ixGuid) is 0 which is invalid as
357// specified in CLI ECMA specification.
358//
359HRESULT
360RegMeta::GetNextGuid(
361 ULONG ixGuid, // [IN] Value from a guid column.
362 __out ULONG *pixNextGuid) // [OUT] Put the index of the next guid here.
363{
364 HRESULT hr = S_OK;
365 BEGIN_ENTRYPOINT_NOTHROW;
366
367 S_UINT32 ixNextGuid = S_UINT32(ixGuid) + S_UINT32(1);
368 if (ixNextGuid.IsOverflow())
369 { // It's invalid index (UINT32_MAX)
370 goto ErrExit;
371 }
372 if (!m_pStgdb->m_MiniMd.m_GuidHeap.IsValidIndex(ixNextGuid.Value()))
373 { // The next index is invalid
374 goto ErrExit;
375 }
376 _ASSERTE(hr == S_OK);
377 // The next index is valid
378 *pixNextGuid = ixNextGuid.Value();
379 goto Exit;
380
381ErrExit:
382 // Fill output parameters on error
383 *pixNextGuid = 0;
384 // Return S_FALSE if next guid index is invalid (backward API compatibility)
385 hr = S_FALSE;
386Exit:
387 END_ENTRYPOINT_NOTHROW;
388 return hr;
389} // RegMeta::GetNextGuid
390
391// --------------------------------------------------------------------------------------
392//
393//#GetNextUserString_IMetaDataTables
394//
395// Fills index of user string (*pixNextUserString) from the user strings heap (#US) starting behind string
396// at index ixUserString.
397// Returns S_OK or S_FALSE (if either index is invalid). Fills *pixNextUserString with 0 on S_FALSE.
398// Implements public API code:IMetaDataTables::GetNextUserString.
399//
400// Backward compatibility: returns S_OK even if the string doesn't have odd number of bytes as specified
401// in CLI ECMA specification.
402//
403HRESULT
404RegMeta::GetNextUserString(
405 ULONG ixUserString, // [IN] Value from a UserString column.
406 __out ULONG *pixNextUserString) // [OUT] Put the index of the next user string here.
407{
408 HRESULT hr = S_OK;
409 BEGIN_ENTRYPOINT_NOTHROW;
410
411 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
412
413 // Get user string at index ixUserString (verifies that the user string is in the heap)
414 MetaData::DataBlob userString;
415 IfFailGo(m_pStgdb->m_MiniMd.m_UserStringHeap.GetBlobWithSizePrefix(
416 ixUserString,
417 &userString));
418 _ASSERTE(hr == S_OK);
419
420 // Get index behind the user string - doesn't overflow, because the user string is in the heap
421 UINT32 ixNextUserString;
422 ixNextUserString = ixUserString + userString.GetSize();
423
424 // Verify that the next index is in the user string heap
425 if (!m_pStgdb->m_MiniMd.m_UserStringHeap.IsValidIndex(ixNextUserString))
426 { // The next index is invalid
427 goto ErrExit;
428 }
429 // The next index is valid
430 *pixNextUserString = ixNextUserString;
431 goto Exit;
432
433ErrExit:
434 // Fill output parameters on error
435 *pixNextUserString = 0;
436 // Return S_FALSE if either of the string indexes is invalid (backward API compatibility)
437 hr = S_FALSE;
438Exit:
439 END_ENTRYPOINT_NOTHROW;
440 return hr;
441} // RegMeta::GetNextUserString
442
443// --------------------------------------------------------------------------------------
444//
445// Implements public API code:IMetaDataTables::GetNumTables.
446//
447HRESULT
448RegMeta::GetNumTables(
449 __out ULONG *pcTables) // [OUT] Count of tables.
450{
451 BEGIN_ENTRYPOINT_NOTHROW;
452
453 // These are for dumping metadata information.
454 // We probably don't need to do any lock here.
455
456 *pcTables = m_pStgdb->m_MiniMd.GetCountTables();
457 END_ENTRYPOINT_NOTHROW;
458
459 return S_OK;
460} // RegMeta::GetNumTables
461
462// --------------------------------------------------------------------------------------
463//
464// Implements public API code:IMetaDataTables::GetTableIndex.
465//
466HRESULT
467RegMeta::GetTableIndex(
468 ULONG token, // [IN] Token for which to get table index.
469 __out ULONG *pixTbl) // [OUT] Put table index here.
470{
471 BEGIN_ENTRYPOINT_NOTHROW;
472
473 // These are for dumping metadata information.
474 // We probably don't need to do any lock here.
475
476 *pixTbl = CMiniMdRW::GetTableForToken(token);
477 END_ENTRYPOINT_NOTHROW;
478
479 return S_OK;
480} // RegMeta::GetTableIndex
481
482// --------------------------------------------------------------------------------------
483//
484// Implements public API code:IMetaDataTables::GetTableInfo.
485//
486HRESULT
487RegMeta::GetTableInfo(
488 ULONG ixTbl, // [IN] Which table.
489 ULONG *pcbRow, // [OUT] Size of a row, bytes.
490 ULONG *pcRows, // [OUT] Number of rows.
491 ULONG *pcCols, // [OUT] Number of columns in each row.
492 ULONG *piKey, // [OUT] Key column, or -1 if none.
493 const char **ppName) // [OUT] Name of the table.
494{
495 HRESULT hr = S_OK;
496 CMiniTableDef *pTbl = NULL;
497
498 BEGIN_ENTRYPOINT_NOTHROW;
499
500 // These are for dumping metadata information.
501 // We probably don't need to do any lock here.
502
503 if (ixTbl >= m_pStgdb->m_MiniMd.GetCountTables())
504 IfFailGo(E_INVALIDARG);
505 pTbl = &m_pStgdb->m_MiniMd.m_TableDefs[ixTbl];
506 if (pcbRow != NULL)
507 *pcbRow = pTbl->m_cbRec;
508 if (pcRows != NULL)
509 *pcRows = m_pStgdb->m_MiniMd.GetCountRecs(ixTbl);
510 if (pcCols != NULL)
511 *pcCols = pTbl->m_cCols;
512 if (piKey != NULL)
513 *piKey = (pTbl->m_iKey == (BYTE) -1) ? -1 : pTbl->m_iKey;
514 if (ppName != NULL)
515 *ppName = g_Tables[ixTbl].m_pName;
516
517ErrExit:
518 END_ENTRYPOINT_NOTHROW;
519 return hr;
520} // RegMeta::GetTableInfo
521
522// --------------------------------------------------------------------------------------
523//
524// Implements public API code:IMetaDataTables::GetColumnInfo.
525//
526HRESULT
527RegMeta::GetColumnInfo(
528 ULONG ixTbl, // [IN] Which Table
529 ULONG ixCol, // [IN] Which Column in the table
530 ULONG *poCol, // [OUT] Offset of the column in the row.
531 ULONG *pcbCol, // [OUT] Size of a column, bytes.
532 ULONG *pType, // [OUT] Type of the column.
533 const char **ppName) // [OUT] Name of the Column.
534{
535 HRESULT hr = S_OK;
536 CMiniTableDef *pTbl = NULL;
537 CMiniColDef *pCol = NULL;
538
539 BEGIN_ENTRYPOINT_NOTHROW;
540
541 // These are for dumping metadata information.
542 // We probably don't need to do any lock here.
543
544 if (ixTbl >= m_pStgdb->m_MiniMd.GetCountTables())
545 IfFailGo(E_INVALIDARG);
546 pTbl = &m_pStgdb->m_MiniMd.m_TableDefs[ixTbl];
547 if (ixCol >= pTbl->m_cCols)
548 IfFailGo(E_INVALIDARG);
549 pCol = &pTbl->m_pColDefs[ixCol];
550 if (poCol != NULL)
551 *poCol = pCol->m_oColumn;
552 if (pcbCol != NULL)
553 *pcbCol = pCol->m_cbColumn;
554 if (pType != NULL)
555 *pType = pCol->m_Type;
556 if (ppName != NULL)
557 *ppName = g_Tables[ixTbl].m_pColNames[ixCol];
558
559ErrExit:
560 END_ENTRYPOINT_NOTHROW;
561 return hr;
562} // RegMeta::GetColumnInfo
563
564// --------------------------------------------------------------------------------------
565//
566// Implements public API code:IMetaDataTables::GetCodedTokenInfo.
567//
568HRESULT
569RegMeta::GetCodedTokenInfo(
570 ULONG ixCdTkn, // [IN] Which kind of coded token.
571 ULONG *pcTokens, // [OUT] Count of tokens.
572 ULONG **ppTokens, // [OUT] List of tokens.
573 const char **ppName) // [OUT] Name of the CodedToken.
574{
575 HRESULT hr = S_OK;
576
577 BEGIN_ENTRYPOINT_NOTHROW;
578
579 // These are for dumping metadata information.
580 // We probably don't need to do any lock here.
581
582 // Validate arguments.
583 if (ixCdTkn >= CDTKN_COUNT)
584 IfFailGo(E_INVALIDARG);
585
586 if (pcTokens != NULL)
587 *pcTokens = g_CodedTokens[ixCdTkn].m_cTokens;
588 if (ppTokens != NULL)
589 *ppTokens = (ULONG*)g_CodedTokens[ixCdTkn].m_pTokens;
590 if (ppName != NULL)
591 *ppName = g_CodedTokens[ixCdTkn].m_pName;
592
593ErrExit:
594 END_ENTRYPOINT_NOTHROW;
595 return hr;
596} // RegMeta::GetCodedTokenInfo
597
598// --------------------------------------------------------------------------------------
599//
600// Implements public API code:IMetaDataTables::GetRow.
601//
602HRESULT
603RegMeta::GetRow(
604 ULONG ixTbl, // [IN] Which table.
605 ULONG rid, // [IN] Which row.
606 void **ppRow) // [OUT] Put pointer to row here.
607{
608 HRESULT hr = S_OK;
609
610 BEGIN_ENTRYPOINT_NOTHROW;
611
612 // These are for dumping metadata information.
613 // We probably don't need to do any lock here.
614
615 // Validate arguments.
616 if (ixTbl >= m_pStgdb->m_MiniMd.GetCountTables())
617 IfFailGo(E_INVALIDARG);
618 if (rid == 0 || rid > m_pStgdb->m_MiniMd.m_Schema.m_cRecs[ixTbl])
619 IfFailGo(E_INVALIDARG);
620
621 // Get the row.
622 IfFailGo(m_pStgdb->m_MiniMd.getRow(ixTbl, rid, ppRow));
623
624ErrExit:
625 END_ENTRYPOINT_NOTHROW;
626 return hr;
627} // RegMeta::GetRow
628
629// --------------------------------------------------------------------------------------
630//
631// Implements public API code:IMetaDataTables::GetColumn.
632//
633HRESULT
634RegMeta::GetColumn(
635 ULONG ixTbl, // [IN] Which table.
636 ULONG ixCol, // [IN] Which column.
637 ULONG rid, // [IN] Which row.
638 ULONG *pVal) // [OUT] Put the column contents here.
639{
640 HRESULT hr = S_OK;
641 CMiniColDef *pCol = NULL;
642 CMiniTableDef *pTbl = NULL;
643
644 BEGIN_ENTRYPOINT_NOTHROW;
645
646 // These are for dumping metadata information.
647 // We probably don't need to do any lock here.
648
649 void *pRow = NULL; // Row with data.
650
651 // Validate arguments.
652 if (ixTbl >= m_pStgdb->m_MiniMd.GetCountTables())
653 IfFailGo(E_INVALIDARG);
654 pTbl = &m_pStgdb->m_MiniMd.m_TableDefs[ixTbl];
655 if (ixCol >= pTbl->m_cCols)
656 IfFailGo(E_INVALIDARG);
657 if (rid == 0 || rid > m_pStgdb->m_MiniMd.m_Schema.m_cRecs[ixTbl])
658 IfFailGo(E_INVALIDARG);
659
660 // Get the row.
661 IfFailGo(m_pStgdb->m_MiniMd.getRow(ixTbl, rid, &pRow));
662
663 // Is column a token column?
664 pCol = &pTbl->m_pColDefs[ixCol];
665 if (pCol->m_Type <= iCodedTokenMax)
666 {
667 *pVal = m_pStgdb->m_MiniMd.GetToken(ixTbl, ixCol, pRow);
668 }
669 else
670 {
671 *pVal = m_pStgdb->m_MiniMd.GetCol(ixTbl, ixCol, pRow);
672 }
673
674ErrExit:
675 END_ENTRYPOINT_NOTHROW;
676 return hr;
677} // RegMeta::GetColumn
678
679// --------------------------------------------------------------------------------------
680//
681// Implements public API code:IMetaDataTables2::GetMetaDataStorage.
682//
683HRESULT
684RegMeta::GetMetaDataStorage(
685 const void **ppvMd, // [OUT] put pointer to MD section here (aka, 'BSJB').
686 ULONG *pcbMd) // [OUT] put size of the stream here.
687{
688 HRESULT hr = S_OK;
689
690 BEGIN_ENTRYPOINT_NOTHROW;
691 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
692
693 hr = m_pStgdb->GetRawData(ppvMd, pcbMd);
694
695 END_ENTRYPOINT_NOTHROW;
696 return hr;
697} // RegMeta::GetMetaDataStorage
698
699// --------------------------------------------------------------------------------------
700//
701// Implements public API code:IMetaDataTables2::GetMetaDataStreamInfo.
702//
703HRESULT
704RegMeta::GetMetaDataStreamInfo(
705 ULONG ix, // [IN] Stream ordinal desired.
706 const char **ppchName, // [OUT] put pointer to stream name here.
707 const void **ppv, // [OUT] put pointer to MD stream here.
708 ULONG *pcb) // [OUT] put size of the stream here.
709{
710 HRESULT hr = S_OK;
711
712 BEGIN_ENTRYPOINT_NOTHROW;
713 REGMETA_POSSIBLE_INTERNAL_POINTER_EXPOSED();
714
715 hr = m_pStgdb->GetRawStreamInfo(ix, ppchName, ppv, pcb);
716
717 END_ENTRYPOINT_NOTHROW;
718 return hr;
719} // RegMeta::GetMetaDataStreamInfo
720