![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Работа с классами в DLL
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.