» » » Алекс Jenter - Программирование на Visual C++. Архив рассылки


Авторские права

Алекс Jenter - Программирование на Visual C++. Архив рассылки

Здесь можно скачать бесплатно "Алекс Jenter - Программирование на Visual C++. Архив рассылки" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Рейтинг:
Название:
Программирование на Visual C++. Архив рассылки
Автор:
Издательство:
неизвестно
Год:
неизвестен
ISBN:
нет данных
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "Программирование на Visual C++. Архив рассылки"

Описание и краткое содержание "Программирование на Visual C++. Архив рассылки" читать бесплатно онлайн.



РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.






 [PreserveSig()]

 int IsClassOfCategories([In] ref Guid rclsid,

  [In] uint cImplemented,

  [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Guid[] rgcatidImpl,

  [In] uint cRequired,

  [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] rgcatidReq);

 [PreserveSig()]

 int RemoteIsClassOfCategories([In] ref Guid rclsid,

  [In] uint cImplemented,

  [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] Guid[] rgcatidImpl,

  [In] uint cRequired,

  [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] Guid[] rgcatidReq);

 [return : MarshalAs(UnmanagedType.Interface)]

 IEnumGUID EnumImplCategoriesOfClass([In] ref Guid rclsid);

 [return : MarshalAs(UnmanagedType.Interface)]

 IEnumGUID EnumReqCategoriesOfClass([In] ref Guid rclsid);

}; 

Описание классов

Для описания классов также используются атрибуты ComImport и Guid. Классы с атрибутом ComImport не могут иметь никаких данных и методов.

Пример описания класса

IDL

Описание отсутствует 

C#

[ComImport, Guid("0002E005-0000-0000-C000-000000000046")]

public class StdComponentCategoriesMgr{}; 

Пример использования класса

C#

using System;

using System.ComponentModel;

using System.Runtime.InteropServices;

using ComCatWrapper;


public class Test {

 static void Main() {

  StdComponentCategoriesMgr mgr = new StdComponentCategoriesMgr();

  ICatInformation catInfoItf = (ICatInformation)mgr;

  IEnumCATEGORYINFO enumCInfoItf = сatInfoItf.EnumCategories(0);

  // и т.д.

 }

Из этого примера видна еще одна особенность работы с COM-объектами в .NET: вместо привычного CoCreateInstance используется оператор new, а вместо QueryInterface используется приведение типов.

Демонстрационное приложение

Демонстрационное приложение, демонстрирующее работу с COM-интерфейсами, написано на C#. Проект состоит из двух модулей: модуля, обеспечивающего интерфейс пользователя (файл MainForm.cs) и модуля, содержащего обертки COM-объекта (файл ComCatWrapper.cs).

Как уже упоминалось, в файле ComCatWrapper.cs содержатся описания структуры CATEGORYINFO и интерфейсов IEnumGUID, IEnumCATEGORYINFO и ICatInformation, а также кокласса StdComponentCategoriesMgr.

Файл MainForm.cs содержит код, необходимый для построения простейшего пользовательского интерфейса и использует интерфейсы из ComCatWrapper.cs.

Первоначально список категорий пуст, он заполняется при нажатии кнопки «Заполнить». Так сделано из-за того, что заполнение идет достаточно долго, а использование, например, дополнительных потоков усложнило бы логику программы.

Вся работа с COM-интерфейсами ведется в двух функциях: FillBtn_Click и FillNodes. Эти функции просты и достаточно подробно прокомментированы.

Визуально категории компонентов представляются в виде дерева следующего вида: описание категории, соответствующий ей идентификатор (CATID) и идентификаторы классов (CLSID), реализующих данную категорию. 

Ниже приведен пример работы тестового приложения, использующего обертки COM-интерфейсов. 

Заключение

Как видим, обеспечить взаимодействие COM и .NET довольно просто для программиста на C#. Нужно только знать, какие параметры и как передавать между управляемым и неуправляемым кодом.

К сожалению, во время подготовки статьи выяснилось, что ManagedC++ и VB.NET не позволяют писать обертки для COM-объектов без использования tlb. Задание атрибута ComImport в этих языках приводит к выбрасыванию исключений при попытке создания экземпляров классов во время выполнения программы, хотя компиляция проходит без проблем. Что это – ошибка или так было задумано, я не знаю. В то же время классы-обертки, написанные на C#, можно использовать и из ManagedC++ и VB.NET. 

ВОПРОС-ОТВЕТ 

Как подменить функцию API?

Автор: Павел Блудов

Демонстрационное приложение (WTL Dialog) HookAPI (100kb) Требует наличия звуковой карты. Методы 3, 4 и 5 не будут работать под windows9x/ME.

Демонстрационное приложение (WTL Dialog) HookAPI2 (20kb) Требует наличия WinSockets 1.0.

Переопределение с помощью препроцессора 

#include <windows.h>


WINUSERAPI BOOL WINAPI MyMessageBeep(IN UINT uType) {

 //Your code here

}

#define MessageBeep MyMessageBeep 

Теперь если в коде программы встретится MessageBeep препроцессор заменит ее на нашу MyMessageBeep. Очень просто.

Но что если хочется добавить немного своей логики в уже откомпилированный код, изменить работу чужой библиотеки, пересобрать которую нет никакой возможности? Иными словами, заставить уже откомпилированный код вызвать нашу функцию вместо стандартной. Это вполне реально. Давайте поближе рассмотрим, как под Windows процедуры одного модуля используют процедуры другого.

Модификация таблиц импорта/экспорта

Весь API, доступный из какого-либо модуля, описан в так называемой таблице экспорта этого модуля. С другой стороны, список API, необходимый для нормальной работы опять-таки, любого модуля, находится в его таблице импорта.

Код вызова процедуры из другого модуля выглядит примерно так:

call dword ptr [__imp__MessageBeep@4  (004404cc)]

И, если изменить значение по этому адресу, можно подменить оригинальнкю функцию своей. Для этого нам понадобится:

• Отыскать таблицу импорта функций для нужного нам модуля

• Отыскать там указатель на перехватываемую функцию

• Снять с этого участка памяти утрибут ReadOnly

• Записать указатель на нашу функцию

• Вернуть защиту обратно

HRESULT ApiHijackImports(HMODULE hModule, LPSTR szVictim, LPSTR szEntry, LPVOID pHijacker, LPVOID *ppOrig) {

 // Check args

 if (::IsBadStringPtrA(szVictim, –1) || (!IIS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) || ::IsBadCodePtr(FARPROC(pHijacker))) {

  return E_INVALIDARG;

 }

 PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);

 if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) {

  return E_INVALIDARG;

 }

 PIMAGE_NT_HEADERS pNTHeaders = MakePtr(PIMAGE_NT_HEADERS, hModule, pDosHeader->e_lfanew);

 if (::IsBadReadPtr(pNTHeaders, sizeof(IMAGE_NT_HEADERS)) || IMAGE_NT_SIGNATURE != pNTHeaders->Signature) {

  return E_INVALIDARG;

 }

 HRESULT hr = E_UNEXPECTED;

 // Locate the victim

 IMAGE_DATA_DIRECTORY& impDir =

  pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

 PIMAGE_IMPORT_DESCRIPTOR pImpDesc =

  MakePtr(PIMAGE_IMPORT_DESCRIPTOR, hModule, impDir.VirtualAddress),

  pEnd = pImpDesc + impDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR) - 1;

 while (pImpDesc < pEnd) {

  if (0 == ::lstrcmpiA(MakePtr(LPSTR, hModule, pImpDesc->Name), szVictim)) {

   if (0 == pImpDesc->OriginalFirstThunk) {

    // no import names table

    return E_UNEXPECTED;

   }

   // Locate the entry

   PIMAGE_THUNK_DATA pNamesTable =

    MakePtr(PIMAGE_THUNK_DATA, hModule, pImpDesc->OriginalFirstThunk);

   if (IS_INTRESOURCE(szEntry)) {

    // By ordinal

    while(pNamesTable->u1.AddressOfData) {

     if (IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal) && WORD(szEntry) == IMAGE_ORDINAL(pNamesTable->u1.Ordinal)) {

      hr = S_OK;

      break;

     }

     pNamesTable++;

    }

   } else {

    // By name

    while(pNamesTable->u1.AddressOfData) {

     if (!IMAGE_SNAP_BY_ORDINAL(pNamesTable->u1.Ordinal)) {

      PIMAGE_IMPORT_BY_NAME pName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pNamesTable->u1.AddressOfData);

      if (0 == ::lstrcmpiA(LPSTR(pName->Name), szEntry)) {

       hr = S_OK;

       break;

      }

     }

     pNamesTable++;

    }

   }

   if (SUCCEEDED(hr)) {

    // Get address

    LPVOID *pProc = MakePtr(LPVOID *, pNamesTable, pImpDesc->FirstThunk - pImpDesc->OriginalFirstThunk);

    // Save original handler

    if (ppOrig) *ppOrig = *pProc;

    // write to write-protected memory

    return WriteProtectedMemory(pProc, &pHijacker, sizeof(LPVOID));

   }

   break;

  }

  pImpDesc++;

 }

 return hr;

}


HRESULT WriteProtectedMemory(LPVOID pDest, LPCVOID pSrc, DWORD dwSize) {

 // Make it writable

 DWORD dwOldProtect = 0;

 if (::VirtualProtect(pDest, dwSize, PAGE_READWRITE, &dwOldProtect)) {

  ::MoveMemory(pDest, pSrc, dwSize);

  // Restore protection

  ::VirtualProtect(pDest, dwSize, dwOldProtect, &dwOldProtect);

  return S_OK;

 }

 return HRESULT_FROM_WIN32(GetLastError());

}

Впрочем, такой способ не будет работать если используется позднее связывание (delay load) или связывание во время исполнения (run-time load) с помощью ::GetProcAddress(). Это можно побороть если перехватить саму ::GetProcAddress(), и подменять возвращяемое значение при необходимости. А можно и подправить таблицу экспорта аналогичным способом:

HRESULT ApiHijackExports(HMODULE hModule, LPSTR szEntry, LPVOID pHijacker, LPVOID *ppOrig) {

 // Check args

 if ((!IS_INTRESOURCE(szEntry) && ::IsBadStringPtrA(szEntry, -1)) || ::IsBadCodePtr(FARPROC(pHijacker))) {

  return E_INVALIDARG;

 }

 PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(hModule);

 if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) || IMAGE_DOS_SIGNATURE != pDosHeader->e_magic) {


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Программирование на Visual C++. Архив рассылки"

Книги похожие на "Программирование на Visual C++. Архив рассылки" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Алекс Jenter

Алекс Jenter - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Алекс Jenter - Программирование на Visual C++. Архив рассылки"

Отзывы читателей о книге "Программирование на Visual C++. Архив рассылки", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.