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 | // |
48 | HRESULT |
49 | RegMeta::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 | // |
67 | HRESULT |
68 | RegMeta::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 | // |
86 | HRESULT |
87 | RegMeta::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 | // |
105 | HRESULT |
106 | RegMeta::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 | // |
126 | HRESULT 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; |
139 | ErrExit: |
140 | *pszString = NULL; |
141 | Exit: |
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 | // |
154 | HRESULT 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; |
170 | ErrExit: |
171 | *ppvData = NULL; |
172 | *pcbDataSize = 0; |
173 | Exit: |
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 | // |
191 | HRESULT 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 | |
213 | ErrExit: |
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 | // |
226 | HRESULT |
227 | RegMeta::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; |
243 | ErrExit: |
244 | *ppvData = NULL; |
245 | *pcbDataSize = 0; |
246 | Exit: |
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 | // |
260 | HRESULT |
261 | RegMeta::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 | |
290 | ErrExit: |
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; |
295 | Exit: |
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 | // |
308 | HRESULT |
309 | RegMeta::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 | |
338 | ErrExit: |
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; |
343 | Exit: |
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 | // |
359 | HRESULT |
360 | RegMeta::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 | |
381 | ErrExit: |
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; |
386 | Exit: |
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 | // |
403 | HRESULT |
404 | RegMeta::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 | |
433 | ErrExit: |
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; |
438 | Exit: |
439 | END_ENTRYPOINT_NOTHROW; |
440 | return hr; |
441 | } // RegMeta::GetNextUserString |
442 | |
443 | // -------------------------------------------------------------------------------------- |
444 | // |
445 | // Implements public API code:IMetaDataTables::GetNumTables. |
446 | // |
447 | HRESULT |
448 | RegMeta::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 | // |
466 | HRESULT |
467 | RegMeta::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 | // |
486 | HRESULT |
487 | RegMeta::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 | |
517 | ErrExit: |
518 | END_ENTRYPOINT_NOTHROW; |
519 | return hr; |
520 | } // RegMeta::GetTableInfo |
521 | |
522 | // -------------------------------------------------------------------------------------- |
523 | // |
524 | // Implements public API code:IMetaDataTables::GetColumnInfo. |
525 | // |
526 | HRESULT |
527 | RegMeta::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 | |
559 | ErrExit: |
560 | END_ENTRYPOINT_NOTHROW; |
561 | return hr; |
562 | } // RegMeta::GetColumnInfo |
563 | |
564 | // -------------------------------------------------------------------------------------- |
565 | // |
566 | // Implements public API code:IMetaDataTables::GetCodedTokenInfo. |
567 | // |
568 | HRESULT |
569 | RegMeta::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 | |
593 | ErrExit: |
594 | END_ENTRYPOINT_NOTHROW; |
595 | return hr; |
596 | } // RegMeta::GetCodedTokenInfo |
597 | |
598 | // -------------------------------------------------------------------------------------- |
599 | // |
600 | // Implements public API code:IMetaDataTables::GetRow. |
601 | // |
602 | HRESULT |
603 | RegMeta::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 | |
624 | ErrExit: |
625 | END_ENTRYPOINT_NOTHROW; |
626 | return hr; |
627 | } // RegMeta::GetRow |
628 | |
629 | // -------------------------------------------------------------------------------------- |
630 | // |
631 | // Implements public API code:IMetaDataTables::GetColumn. |
632 | // |
633 | HRESULT |
634 | RegMeta::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 | |
674 | ErrExit: |
675 | END_ENTRYPOINT_NOTHROW; |
676 | return hr; |
677 | } // RegMeta::GetColumn |
678 | |
679 | // -------------------------------------------------------------------------------------- |
680 | // |
681 | // Implements public API code:IMetaDataTables2::GetMetaDataStorage. |
682 | // |
683 | HRESULT |
684 | RegMeta::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 | // |
703 | HRESULT |
704 | RegMeta::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 | |