Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с классами в DLL


Страницы:   1 2

Piter ©   (2004-11-28 13:08:00) 

Есть ли какие-нибудь ограничения на работу с классами в DLL? Обязательно нужны какие-нибудь модули?

Дело в том, что я пишу DLL и по ходу дела решил разработать класс для упрощения работы с общей для DLL памятью (через проецируемые в память файлы).
Но столкнулся с ошибкой работы DLL. В чем причина - просто загадка.

Данная DLL устанавливает хук, поэтому внедряется во многие процессы.
Если она внедряется в Delphi приложение - то все нормально. Экземпляр TGlobalDataManagerуспешно создается, выделяется глобальная память... Все это можно протрассировать из дебаггера - проблем нету.

Но если внедрение начинается в другие процессы - то библиотека их просто рушит (Explorer, Delphi, Диспетчер задач и т.д.).
Причем, судя по всему, дело не успевает дойти даже до DLLMain - процесс рушится еще на стадии внедрения библиотеки (возможно, происходит какая-то инициализация дельфового менеджера памяти или там еще чего - фиг знает).

Если не использовать TGlobalDataManager- то библиотека вполне себе успешно внедряется во все процессы, ничего не разрушая.

Вот юнит GlobalDataUtil, где и реализована работа с проецируемыми файлами (извините за объем, выкладываю все - я не знаю где ошибка, если она вообще есть):

unit GlobalDataUtil;

interface

uses Windows;

type
 TGlobalDataRecord = record
   MapHandle: THandle;
   Data: Pointer;
 end;

 TGlobalDataManager = class
 private
   FListDataRecord: array of TGlobalDataRecord;
   FCriticalSection: TRTLCriticalSection;
   procedure AddRecord(const AMaphandle:THandle; const AData: Pointer);
   procedure DeleteRecord(const Index: integer);
   function SearchIndexdByData(const AData: Pointer): integer;
   function CloseGlobalDataByIndex(const Index: integer): boolean;
 public
   constructor Create;
   destructor Destroy; override;
   function OpenGlobalData(const Size: integer; const UnicName: string): Pointer;
   function CloseGlobalData(const Data: Pointer): boolean;
 end;

implementation

{ TGlobalData }

constructor TGlobalDataManager.Create;
begin
 inherited;
 InitializeCriticalSection(FCriticalSection);
end;

destructor TGlobalDataManager.Destroy;
begin
 while Length(FListDataRecord)<>0 do
   CloseGlobalData(FListDataRecord[0].Data);
 DeleteCriticalSection(FCriticalSection);
 inherited;
end;

function TGlobalDataManager.OpenGlobalData(const Size: integer;
 const UnicName: string): Pointer;
var
 MapHandle: THandle;
begin
 EnterCriticalSection(FCriticalSection);
 try
   MapHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
       0, Size, PChar(UnicName));
   if GetLastError = ERROR_ALREADY_EXISTS then
     begin
       CloseHandle(MapHandle);
       Result := nil;
     end
   else
     begin
       Result := MapViewOfFile(MapHandle, FILE_MAP_ALL_ACCESS, 0, 0, Size);
       if Result <> nil then
         AddRecord(MapHandle, Result);
     end;
 finally
   LeaveCriticalSection(FCriticalSection);
 end;
end;

function TGlobalDataManager.CloseGlobalData(const Data: Pointer): boolean;
var
 i: integer;
begin
 EnterCriticalSection(FCriticalSection);
 Result := false;
 try
   i := SearchIndexdByData(Data);
   CloseGlobalDataByIndex(i);
 finally
   LeaveCriticalSection(FCriticalSection);
 end;
end;

procedure TGlobalDataManager.AddRecord(const AMaphandle: THandle;
 const  AData: Pointer);
begin
 SetLength(FListDataRecord, Length(FListDataRecord) + 1);
 with FListDataRecord[High(FListDataRecord)] do
   begin
     MapHandle := AMaphandle ;
     Data := AData;
   end;
end;

procedure TGlobalDataManager.DeleteRecord(const Index: integer);
var
 i: integer;
begin
 if ( index <= High(FListDataRecord) ) and ( index >= 0 ) then
   begin
     for i := index to High(FListDataRecord) - 1 do
       FListDataRecord[i] := FListDataRecord[i+1];
     SetLength(FListDataRecord, Length(FListDataRecord) - 1);
   end;
end;

function TGlobalDataManager.SearchIndexdByData(const AData: Pointer): integer;
var
 i: integer;
begin
 Result := -1;
 for i:=0 to High(FListDataRecord) do
   if FListDataRecord[i].Data = AData then
     begin
       Result := i;
       break;
     end;
end;

function TGlobalDataManager.CloseGlobalDataByIndex(
 const Index: integer): boolean;
begin
 Result := false;
 if ( Index >= 0 ) and ( Index <= High(FListDataRecord) )then
   with FListDataRecord[Index] do
   begin
     UnmapViewOfFile(Data);
     CloseHandle(MapHandle);
     DeleteRecord(Index);
     Result := true;
   end;
end;

end.


Piter   (2004-11-28 15:34:00) [21]

Piter ©   (28.11.04 15:05) [5]
В тоже время, если не использовать класс TGlobalDataManager - то все, даже если библиотека грузится по хуку.


В тоже время, если не использовать класс TGlobalDataManager - то все нормально, даже если библиотека грузится по хуку.


Piter   (2004-11-28 15:19:00) [22]

VMcL ©   (28.11.04 13:13) [1]
Не вижу uses ShareMem


дык string'и не импортируются и не экспортируются библиотекой

Сделайте все public методы виртуальными

не помогло...

VMcL ©   (28.11.04 13:18) [3]
Где и кем создается экземпляр TGlobalDataManager?


создается он библиоткой при приходе DLL_PROCESS_ATTACH. Уничтожается соответственно при DLL_PROCESS_DETACH


Piter   (2004-11-28 15:05:00) [23]

Информация о работе только с Delphi приложениями не верная.

Получается так, что эта библиотека работает нормально, если приложение само грузит эту библиотеку (например, библиотека в разделе импорта EXE'щника). Если же библиотека грузится по хуку, то происходит сбой.

Но почему происходит сбой? В тоже время, если не использовать класс TGlobalDataManager - то все, даже если библиотека грузится по хуку.

Ничего не могу понять...


jack128   (2004-11-28 15:03:00) [24]

VMcL ©   (28.11.04 13:13) [1]
зачем? Разве библиотека должна разделять строки с другими приложениями?


VMcL   (2004-11-28 13:18:00) [25]

Тороплюсь что-то.

Где и кем создается экземпляр TGlobalDataManager?


VMcL   (2004-11-28 13:15:00) [26]

Да. И еще один момент. Сделайте все public методы виртуальными.


VMcL   (2004-11-28 13:13:00) [27]

>> Piter ©  (28.11.04 13:08)

> function OpenGlobalData(const Size: integer; const UnicName: string): Pointer;

Не вижу uses ShareMem. Возможно проблема из-за этого. Попробуйте переделать вызовы с использованием String на PChar.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо