gpt4 book ai didi

delphi - 如何判断CoInitialize被调用了多少层?

转载 作者:行者123 更新时间:2023-12-03 14:45:30 29 4
gpt4 key购买 nike

我正在对一个困惑的项目进行一些调试,我发现以前的开发人员不知道他们在做什么,主要问题是尝试多线程应用程序失败。我现在正在清理困惑并试图找出问题出在哪里。问题之一是为了使用 ADO 组件而对 CoInitialize 的调用不一致。

继续我的previous question ,如何确定已调用多少层 CoInitialize

例如,考虑以下代码:

CoInitialize(nil);
try
CoInitialize(nil);
try
//2 levels have been called, how to programatically check this?
finally
CoUninitialize;
end;
finally
CoUninitialize;
end;

最佳答案

如果我必须解决这个问题,我会通过检测对 CoInitializeCoInitializeExCoUninitialize 的调用来解决它。我会将调用 Hook 到这些函数并使用线程局部变量来计算调用次数。

您可以通过将以下单元添加到您的项目中来实现此目的。

unit InstrumentCOMinit;

interface

uses
SysUtils, Windows, ComObj, ActiveX;

threadvar
COMinitCount: Integer;

implementation

function CoInitialize(pvReserved: Pointer): HResult; stdcall; external 'ole32.dll';
function CoInitializeEx(pvReserved: Pointer; coInit: Longint): HResult; stdcall; external 'ole32.dll';
procedure CoUninitialize; stdcall; external 'ole32.dll';

function InstrumentedCoInitialize(pvReserved: Pointer): HResult; stdcall;
begin
Result := CoInitialize(pvReserved);
if Succeeded(Result) then
inc(COMinitCount);
end;

function InstrumentedCoInitializeEx(pvReserved: Pointer; coInit: Longint): HResult; stdcall;
begin
Result := CoInitializeEx(pvReserved, coInit);
if Succeeded(Result) then
inc(COMinitCount);
end;

procedure InstrumentedCoUninitialize; stdcall;
begin
CoUninitialize;
dec(COMinitCount);
end;

procedure Fail;
begin
raise EAssertionFailed.Create('Fixup failed.');
end;

procedure PatchCode(Address: Pointer; const NewCode; Size: Integer);
var
OldProtect: DWORD;
begin
if not VirtualProtect(Address, Size, PAGE_EXECUTE_READWRITE, OldProtect) then begin
Fail;
end;
Move(NewCode, Address^, Size);
FlushInstructionCache(GetCurrentProcess, nil, 0);
if not VirtualProtect(Address, Size, OldProtect, @OldProtect) then begin
Fail;
end;
end;

type
PInstruction = ^TInstruction;
TInstruction = packed record
Opcode: Byte;
Offset: Integer;
end;

procedure RedirectProcedure(OldAddress, NewAddress: Pointer);
var
NewCode: TInstruction;
begin
NewCode.Opcode := $E9;//jump relative
NewCode.Offset := NativeInt(NewAddress)-NativeInt(OldAddress)-SizeOf(NewCode);
PatchCode(OldAddress, NewCode, SizeOf(NewCode));
end;

initialization
RedirectProcedure(@ActiveX.CoInitialize, @InstrumentedCoInitialize);
RedirectProcedure(@ActiveX.CoInitializeEx, @InstrumentedCoInitializeEx);
RedirectProcedure(@ActiveX.CoUninitialize, @InstrumentedCoUninitialize);
ComObj.CoInitializeEx := InstrumentedCoInitializeEx;

end.

与 Serg 的方法不同,此技术不会改变程序的语义。

关于delphi - 如何判断CoInitialize被调用了多少层?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14543496/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com