Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 84 стр.

UptoLike

токенов, который соответствует типам, объявленным в сборке
(другими словами, получаем содержимое таблицы TypeDef):
mdTypeDef tmp;
mdTypeDef *tokens;
HCORENUM Enum = 0;
unsigned long tokenCount;
mdimp->EnumTypeDefs(&Enum,&tmp,1,&tokenCount);
mdimp->CountEnum(Enum,&tokenCount);
if (tokenCount > 0)
{
tokens = new mdTypeDef [tokenCount];
tokens[0] = tmp;
if (tokenCount > 1)
mdimp->EnumTypeDefs(
&Enum,tokens+1,tokenCount-1,
&tokenCount
);
mdimp->CloseEnum(Enum);
}
Первый вызов метода EnumTypeDefs создает дескриптор массива
токенов (он записывается в переменную Enum), а также возвра-
щает первый элемент этого массива (он сохраняется в перемен-
ной tmp).
Затем метод CountEnum записывает в переменную tokenCount раз-
мер массива токенов, после чего выделяется нужное количество
памяти (для массива tokens) и второй раз вызывается метод
EnumTypeDefs. Обратите внимание, что первому элементу масси-
ва tokens мы присваиваем значение переменной tmp.
2. Методы FindXXX предназначены для поиска элементов метадан-
ных, удовлетворяющих некоторым критериям. Например, поиск
типа по его имени («MyType1») проводится следующим образом:
mdTypeDef token;
mdimp->FindTypeByName(L”MyType1”,NULL,&token);
3. Методы GetXXX используются для получения свойств элементов
метаданных. Например, получение содержимого строки, токен
которой хранится в переменной strToken, выглядит так:
unsigned short s[1024];
unsigned long len;
mdimp->GetUserString(strToken,s,1024,&len);
Обратите внимание, что для хранения одного символа применяется
тип unsigned short. Причина в том, что для представления строко-
вых данных в .NET используется 16-разрядная кодировка Unicode.
Анализ кода на CIL
155
Работа с Metadata Unmanaged API начинается с инициализации сис-
темы COM и получения указателя на интерфейс IMetadataDispenserEx:
CoInitialize(NULL);
IMetaDataDispenser *dispenser;
HRESULT h = CoCreateInstance(
CLSID_CorMetaDataDispenser,
NULL,
CLSCTX_INPROC_SERVER,
IID_IMetaDataDispenserEx,
(void **)&dispenser
);
if (h)
printf(“Error”);
Затем можно с помощью метода OpenScope этого интерфейса загру-
зить существующую сборку в память или с помощью метода DefineScope
создать новую сборку. Оба метода возвращают указатель на интерфейс, че-
рез который можно в дальнейшем осуществлять чтение или генерацию
метаданных. В следующем фрагменте программы происходит вызов мето-
да OpenScope для чтения метаданных из сборки test.exe:
IMetaDataImport *mdimp;
HRESULT h = dispenser->OpenScope(
L”test.exe”,
0,
IID_IMetaDataImport,
(IUnknown**)&mdimp
);
if (h)
printf(“Error”);
При завершении работы с Metadata Unmanaged API необходимо ос-
вободить указатели на полученные интерфейсы:
mdimp->Release();
dispenser->Release();
Чтение метаданных из сборки осуществляется через методы интер-
фейса IMetadataImport, которые условно можно разделить на три основ-
ные группы:
1. Методы EnumXXX возвращают массивы токенов, описывающих
определенную категорию элементов метаданных. Ответствен-
ность за выделение достаточного количества памяти для хране-
ния возвращаемого массива токенов лежит на программисте,
использующем библиотеку, а так как количество токенов зара-
нее неизвестно, то приходится использовать прием, проиллюст-
рированный следующим примером. В нем мы получаем массив
154
CIL и системное программирование в Microsoft .NET
154                        CIL и системное программирование в Microsoft .NET   Анализ кода на CIL                                                     155


     Работа с Metadata Unmanaged API начинается с инициализации сис-                      токенов, который соответствует типам, объявленным в сборке
темы COM и получения указателя на интерфейс IMetadataDispenserEx:                         (другими словами, получаем содержимое таблицы TypeDef):
     CoInitialize(NULL);                                                                     mdTypeDef tmp;
     IMetaDataDispenser *dispenser;                                                          mdTypeDef *tokens;
     HRESULT h = CoCreateInstance(                                                           HCORENUM Enum = 0;
      CLSID_CorMetaDataDispenser,                                                            unsigned long tokenCount;
      NULL,                                                                                  mdimp->EnumTypeDefs(&Enum,&tmp,1,&tokenCount);
      CLSCTX_INPROC_SERVER,                                                                  mdimp->CountEnum(Enum,&tokenCount);
      IID_IMetaDataDispenserEx,                                                              if (tokenCount > 0)
      (void **)&dispenser                                                                    {
      );                                                                                       tokens = new mdTypeDef [tokenCount];
     if (h)                                                                                    tokens[0] = tmp;
      printf(“Error”);                                                                         if (tokenCount > 1)
     Затем можно с помощью метода OpenScope этого интерфейса загру-                                     mdimp->EnumTypeDefs(
зить существующую сборку в память или с помощью метода DefineScope                                      &Enum,tokens+1,tokenCount-1,
создать новую сборку. Оба метода возвращают указатель на интерфейс, че-                                 &tokenCount
рез который можно в дальнейшем осуществлять чтение или генерацию                                        );
метаданных. В следующем фрагменте программы происходит вызов мето-                             mdimp->CloseEnum(Enum);
да OpenScope для чтения метаданных из сборки test.exe:                                       }
     IMetaDataImport *mdimp;                                                              Первый вызов метода EnumTypeDefs создает дескриптор массива
     HRESULT h = dispenser->OpenScope(                                                    токенов (он записывается в переменную Enum), а также возвра-
      L”test.exe”,                                                                        щает первый элемент этого массива (он сохраняется в перемен-
      0,                                                                                  ной tmp).
      IID_IMetaDataImport,                                                                Затем метод CountEnum записывает в переменную tokenCount раз-
      (IUnknown**)&mdimp                                                                  мер массива токенов, после чего выделяется нужное количество
      );                                                                                  памяти (для массива tokens) и второй раз вызывается метод
     if (h)                                                                               EnumTypeDefs. Обратите внимание, что первому элементу масси-
      printf(“Error”);                                                                    ва tokens мы присваиваем значение переменной tmp.
     При завершении работы с Metadata Unmanaged API необходимо ос-                     2. Методы FindXXX предназначены для поиска элементов метадан-
вободить указатели на полученные интерфейсы:                                              ных, удовлетворяющих некоторым критериям. Например, поиск
     mdimp->Release();                                                                    типа по его имени («MyType1») проводится следующим образом:
     dispenser->Release();                                                                   mdTypeDef token;
     Чтение метаданных из сборки осуществляется через методы интер-                          mdimp->FindTypeByName(L”MyType1”,NULL,&token);
фейса IMetadataImport, которые условно можно разделить на три основ-                   3. Методы GetXXX используются для получения свойств элементов
ные группы:                                                                               метаданных. Например, получение содержимого строки, токен
        1. Методы EnumXXX возвращают массивы токенов, описывающих                         которой хранится в переменной strToken, выглядит так:
           определенную категорию элементов метаданных. Ответствен-                          unsigned short s[1024];
           ность за выделение достаточного количества памяти для хране-                      unsigned long len;
           ния возвращаемого массива токенов лежит на программисте,                          mdimp->GetUserString(strToken,s,1024,&len);
           использующем библиотеку, а так как количество токенов зара-                    Обратите внимание, что для хранения одного символа применяется
           нее неизвестно, то приходится использовать прием, проиллюст-                   тип unsigned short. Причина в том, что для представления строко-
           рированный следующим примером. В нем мы получаем массив                        вых данных в .NET используется 16-разрядная кодировка Unicode.