I use [] instead of angle brackets to enclose templates below.
The stack trace comes from one dump:
0:007> kb 100
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0181f9c8 02a5952c 0745e6d8 02a59568 00000000 0x1f
0181f9d0 02a59568 00000000 02a5949b 00000001 IFtpSrvAPI!ATL::CComObject[CFTPLicense]
0181f9d8 02a5949b 00000001 022a16b8 77d04239 IFtpSrvAPI!ATL::CComObject
0181f9e4 77d04239 0745e6d8 022a16b8 022a16b8 IFtpSrvAPI!ATL::CComObject
0181f9f8 76f9f619 022a16b8 030f96d0 76f9b7e6 oleaut32!VariantClear+0xb1
0181fa04 76f9b7e6 030f96d0 0229c880 022a41e0 jscript!VAR::Clear+0x5d
0181fa1c 76f94058 00000000 022a41e0 02291eb0 jscript!GcAlloc::ReclaimAll+0x40
0181fa38 76f9b74b 00000001 02291d1c 02291cb0 jscript!GcContext::Reclaim+0x89
0181fa50 76f98753 0181fa80 76f9b0d3 00000000 jscript!IScavengerBase::UnlinkFromGc+0x5b
0181fa58 76f9b0d3 00000000 00000000 00000010 jscript!ScavVarList::Init+0x2d
0181fa80 76f9b57d 0181fadc 0181fb08 008ca390 jscript!CSession::Close+0xb5
0181faa0 6400189b 022c3d18 f7bb5dd5 0181fadc jscript!COleScript::Close+0x7c
0181fac8 003635c5 0181fae0 0181fb08 0181fbb4 Core!CActiveScriptEngine::~CActiveScriptEngine+0x5b [d:\fts\ws_ftp web server\core\activescriptengine.cpp @ 41]
0181fad8 0036fd70 f7b10f15 0181fc40 0181fbcc WSFTPWebServer!CWebActiveScriptEngine::~CWebActiveScriptEngine+0x85 [d:\fts\ws_ftp web server\nmwebserver\webactivescriptengine.cpp @ 29]
0181fbb4 003713d7 0181fc88 0732e910 06d2b390 WSFTPWebServer!CWebTcp::_ProcessScript+0x270 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1752]
0181fc4c 003710b4 0181fc88 0732e910 06d2b390 WSFTPWebServer!CWebTcp::_ProcessFile+0x1e7 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1932]
0181fca8 0036f94a 0181fd6c 0732e910 06d2b390 WSFTPWebServer!CWebTcp::ProcessFile+0x64 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1888]
0181fd08 003696b5 0181fd6c 0732e910 0204f1c8 WSFTPWebServer!CWebTcp::_ProcessRequest+0x30a [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1696]
0181ff10 6404cd10 f7bb5829 00000000 008ca368 WSFTPWebServer!CWebTcp::DoTask+0x6e5 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 220]
0181ff4c 6405b17e f7bb581d 00000000 00000000 Core!CThreadPoolThread::_Run+0x80 [d:\fts\ws_ftp web server\core\threadpool.cpp @ 404]
0181ff78 781329bb 008ca368 f7d07408 00000000 Core!CWorkerThread::_ThreadProc+0x3e [d:\fts\ws_ftp web server\core\workerthread.cpp @ 100]
0181ffb0 78132a47 00000000 77e64829 008ca390 msvcr80!_endthreadex+0x3b
0181ffb8 77e64829 008ca390 00000000 00000000 msvcr80!_endthreadex+0xc7
0181ffec 00000000 781329e1 008ca390 00000000 kernel32!BaseThreadStart+0x34
The stack trace comes from the other dump:
0:007> kb 100
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0171d7e4 02a5952c 03035ab8 02a59568 00000000 0x46005f
0171d7ec 02a59568 00000000 02a5949b 00000001 IFtpSrvAPI!ATL::CComObject
0171d7f4 02a5949b 00000001 02285000 77d04239 IFtpSrvAPI!ATL::CComObject
0171d800 77d04239 03035ab8 003fd950 02285000 IFtpSrvAPI!ATL::CComObject
0171d814 76f9f619 02285000 02285000 76f9f361 oleaut32!VariantClear+0xb1
0171d820 76f9f361 003fd950 02229c50 003fc658 jscript!VAR::Clear+0x5d
0171d84c 76fc633a 02229c70 00000000 02229c50 jscript!GcAlloc::ReclaimGarbage+0x74
0171d868 76f9f4f6 00000002 0171de04 0171da68 jscript!GcContext::Reclaim+0x82
0171d87c 76f9f6bb 0171de04 02266988 02266988 jscript!GcContext::Collect+0xa5
0171da54 76fa5996 0171de04 00000000 0171db70 jscript!CScriptRuntime::Run+0xfd
0171db18 76fa6e7e 0171de04 00000001 030f9960 jscript!ScrFncObj::Call+0x69
0171dbac 76fa5f15 003f8178 00000000 00000003 jscript!NameTbl::InvokeInternal+0x218
0171dbd8 76fa7bb8 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xfb
0171dc1c 76fa64ea 003f8178 0171dc3c 00000003 jscript!VAR::InvokeByName+0x164
0171dc5c 76fa6aa3 003f8178 00000003 0171de04 jscript!VAR::InvokeDispName+0x43
0171dc80 76fa7abe 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xb9
0171de74 76fa5996 0171e224 00000000 0171df90 jscript!CScriptRuntime::Run+0x18fb
0171df38 76fa6e7e 0171e224 00000003 030f99d0 jscript!ScrFncObj::Call+0x69
0171dfcc 76fa5f15 003f8178 00000000 00000003 jscript!NameTbl::InvokeInternal+0x218
0171dff8 76fa7bb8 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xfb
0171e03c 76fa64ea 003f8178 0171e05c 00000003 jscript!VAR::InvokeByName+0x164
0171e07c 76fa6aa3 003f8178 00000003 0171e224 jscript!VAR::InvokeDispName+0x43
0171e0a0 76fa7abe 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xb9
0171e294 76fa5996 0171e644 00000000 0171e3b0 jscript!CScriptRuntime::Run+0x18fb
0171e358 76fa6e7e 0171e644 00000001 030f9ae0 jscript!ScrFncObj::Call+0x69
0171e3ec 76fa5f15 003f8178 00000000 00000003 jscript!NameTbl::InvokeInternal+0x218
0171e418 76fa7bb8 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xfb
0171e45c 76fa64ea 003f8178 0171e47c 00000003 jscript!VAR::InvokeByName+0x164
0171e49c 76fa6aa3 003f8178 00000003 0171e644 jscript!VAR::InvokeDispName+0x43
0171e4c0 76fa7abe 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xb9
0171e6b4 76fa5996 0171ea64 00000000 0171e7d0 jscript!CScriptRuntime::Run+0x18fb
0171e778 76fa6e7e 0171ea64 00000000 022228d8 jscript!ScrFncObj::Call+0x69
0171e80c 76fa5f15 003f8178 00000000 00000001 jscript!NameTbl::InvokeInternal+0x218
0171e838 76fa7bb8 003f8178 00000000 00000001 jscript!VAR::InvokeByDispID+0xfb
0171e87c 76fa64ea 003f8178 0171e89c 00000001 jscript!VAR::InvokeByName+0x164
0171e8bc 76fa6aa3 003f8178 00000001 0171ea64 jscript!VAR::InvokeDispName+0x43
0171e8e0 76fa7abe 003f8178 00000000 00000001 jscript!VAR::InvokeByDispID+0xb9
0171ead4 76fa5996 0171ee90 0171ebec 00000000 jscript!CScriptRuntime::Run+0x18fb
0171eb98 76fbb951 0171ee90 00000000 00000000 jscript!ScrFncObj::Call+0x69
0171ec14 76fa7b7e 003f8178 0171eca4 0171ee90 jscript!JsEval+0x10b
0171ec4c 76fa7316 0171ee90 00000001 02222908 jscript!NatFncObj::Call+0x41
0171ece0 76fa5f15 003f8178 0227be50 00000003 jscript!NameTbl::InvokeInternal+0xd5
0171ed0c 76fa7abe 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xfb
0171ef00 76fa5996 0171f2b0 00000000 0171f01c jscript!CScriptRuntime::Run+0x18fb
0171efc4 76fa6e7e 0171f2b0 00000000 022229f8 jscript!ScrFncObj::Call+0x69
0171f058 76fa5f15 003f8178 00000000 00000001 jscript!NameTbl::InvokeInternal+0x218
0171f084 76fa7bb8 003f8178 00000000 00000001 jscript!VAR::InvokeByDispID+0xfb
0171f0c8 76fa64ea 003f8178 0171f0e8 00000001 jscript!VAR::InvokeByName+0x164
0171f108 76fa6aa3 003f8178 00000001 0171f2b0 jscript!VAR::InvokeDispName+0x43
0171f12c 76fa7abe 003f8178 00000000 00000001 jscript!VAR::InvokeByDispID+0xb9
0171f320 76fa5996 0171f6d0 00000000 0171f43c jscript!CScriptRuntime::Run+0x18fb
0171f3e4 76fa6e7e 0171f6d0 00000001 02222b58 jscript!ScrFncObj::Call+0x69
0171f478 76fa5f15 003f8178 00000000 00000003 jscript!NameTbl::InvokeInternal+0x218
0171f4a4 76fa7bb8 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xfb
0171f4e8 76fa64ea 003f8178 0171f508 00000003 jscript!VAR::InvokeByName+0x164
0171f528 76fa6aa3 003f8178 00000003 0171f6d0 jscript!VAR::InvokeDispName+0x43
0171f54c 76fa7abe 003f8178 00000000 00000003 jscript!VAR::InvokeByDispID+0xb9
0171f740 76fa5996 00000000 76f9ff88 00000000 jscript!CScriptRuntime::Run+0x18fb
0171f804 76fa57e5 00000000 00000000 00000000 jscript!ScrFncObj::Call+0x69
0171f87c 76f9bd59 02295eb8 00000000 00000000 jscript!CSession::Execute+0xb8
0171f8cc 76f9bf89 00000000 0171f998 0171f9cc jscript!COleScript::ExecutePendingScripts+0x141
0171f92c 76f9bdec 05700030 00000000 00000000 jscript!COleScript::ParseScriptTextCore+0x221
0171f958 640017f7 003f7e7c 05700030 00000000 jscript!COleScript::ParseScriptText+0x2b
0171f9cc 0036e56b 05c1a018 00000001 73052595 Core!CActiveScriptEngine::ParseScript+0xf7 [d:\fts\ws_ftp web server\core\activescriptengine.cpp @ 273]
0171fac8 0036fc76 0171faf8 01f2ada0 05c1a018 WSFTPWebServer!CWebTcp::_ProcessScriptEx+0x61b [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1430]
0171fbb4 003713d7 0171fc88 01f2ada0 03034ed8 WSFTPWebServer!CWebTcp::_ProcessScript+0x176 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1746]
0171fc4c 003710b4 0171fc88 01f2ada0 03034ed8 WSFTPWebServer!CWebTcp::_ProcessFile+0x1e7 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1932]
0171fca8 0036f94a 0171fd6c 01f2ada0 03034ed8 WSFTPWebServer!CWebTcp::ProcessFile+0x64 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1888]
0171fd08 003696b5 0171fd6c 01f2ada0 0216d620 WSFTPWebServer!CWebTcp::_ProcessRequest+0x30a [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1696]
0171ff10 6404cd10 73053b25 00000000 008ca120 WSFTPWebServer!CWebTcp::DoTask+0x6e5 [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 220]
0171ff4c 6405b17e 73053b11 00000000 00000000 Core!CThreadPoolThread::_Run+0x80 [d:\fts\ws_ftp web server\core\threadpool.cpp @ 404]
0171ff78 781329bb 008ca120 73102f5d 00000000 Core!CWorkerThread::_ThreadProc+0x3e [d:\fts\ws_ftp web server\core\workerthread.cpp @ 100]
0171ffb0 78132a47 00000000 77e64829 008ca148 msvcr80!_endthreadex+0x3b
0171ffb8 77e64829 008ca148 00000000 00000000 msvcr80!_endthreadex+0xc7
0171ffec 00000000 781329e1 008ca148 00000000 kernel32!BaseThreadStart+0x34
The top instruction pointers from both dump files are obviously invalid. And WinDBG displays the warning: Frame IP not in any known module. Following frames may be wrong.
Due to the warning from WinDBG, I made a quick check to ensure the stack traces are indeed correct.
0:007> ub 02a5952c
IFtpSrvAPI!ATL::CComObject
02a59508 c7069c71a902 mov dword ptr [esi],offset IFtpSrvAPI!ATL::CComObject
02a5950e c746088871a902 mov dword ptr [esi+8],offset IFtpSrvAPI!ATL::CComObject
02a59515 c7460c7071a902 mov dword ptr [esi+0Ch],offset IFtpSrvAPI!ATL::CComObject
02a5951c c74614010000c0 mov dword ptr [esi+14h],0C0000001h
02a59523 7407 je IFtpSrvAPI!ATL::CComObject
02a59525 8b01 mov eax,dword ptr [ecx]
02a59527 8b5004 mov edx,dword ptr [eax+4]
02a5952a ffd2 call edx
0:007> ub 02a59568
IFtpSrvAPI!ATL::CComObject
02a5955b cc int 3
02a5955c cc int 3
02a5955d cc int 3
02a5955e cc int 3
02a5955f cc int 3
IFtpSrvAPI!ATL::CComObject
02a59560 56 push esi
02a59561 8bf1 mov esi,ecx
02a59563 e898ffffff call IFtpSrvAPI!ATL::CComObject
...
Since each unassembled code from ub command ends up with call instruction, it seems that the stack trace is correct and the warning is due to the invalid instruction pointer. Next, I tried to figure out where the correct instruction pointer should be.
I displayed the stack trace again with the calling convention.
0:007> kv
ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
0181f9c8 02a5952c 0745e6d8 02a59568 00000000 0x1f
0181f9d0 02a59568 00000000 02a5949b 00000001 IFtpSrvAPI!ATL::CComObject
0181f9d8 02a5949b 00000001 022a16b8 77d04239 IFtpSrvAPI!ATL::CComObject
0181f9e4 77d04239 0745e6d8 022a16b8 022a16b8 IFtpSrvAPI!ATL::CComObject
0181f9f8 76f9f619 022a16b8 030f96d0 76f9b7e6 oleaut32!VariantClear+0xb1 (FPO: [1,0,0])
0181fa04 76f9b7e6 030f96d0 0229c880 022a41e0 jscript!VAR::Clear+0x5d (FPO: [0,0,0])
0181fa1c 76f94058 00000000 022a41e0 02291eb0 jscript!GcAlloc::ReclaimAll+0x40 (FPO: [0,1,0])
0181fa38 76f9b74b 00000001 02291d1c 02291cb0 jscript!GcContext::Reclaim+0x89 (FPO: [1,2,0])
0181fa50 76f98753 0181fa80 76f9b0d3 00000000 jscript!IScavengerBase::UnlinkFromGc+0x5b (FPO: [0,1,0])
0181fa58 76f9b0d3 00000000 00000000 00000010 jscript!ScavVarList::Init+0x2d (FPO: [4,0,0])
0181fa80 76f9b57d 0181fadc 0181fb08 008ca390 jscript!CSession::Close+0xb5 (FPO: [0,1,4])
0181faa0 6400189b 022c3d18 f7bb5dd5 0181fadc jscript!COleScript::Close+0x7c (FPO: [1,3,4])
0181fac8 003635c5 0181fae0 0181fb08 0181fbb4 Core!CActiveScriptEngine::~CActiveScriptEngine+0x5b (FPO: [0,4,0]) (CONV: thiscall) [d:\fts\ws_ftp web server\core\activescriptengine.cpp @ 41]
0181fad8 0036fd70 f7b10f15 0181fc40 0181fbcc WSFTPWebServer!CWebActiveScriptEngine::~CWebActiveScriptEngine+0x85 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webactivescriptengine.cpp @ 29]
0181fbb4 003713d7 0181fc88 0732e910 06d2b390 WSFTPWebServer!CWebTcp::_ProcessScript+0x270 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1752]
0181fc4c 003710b4 0181fc88 0732e910 06d2b390 WSFTPWebServer!CWebTcp::_ProcessFile+0x1e7 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1932]
0181fca8 0036f94a 0181fd6c 0732e910 06d2b390 WSFTPWebServer!CWebTcp::ProcessFile+0x64 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1888]
0181fd08 003696b5 0181fd6c 0732e910 0204f1c8 WSFTPWebServer!CWebTcp::_ProcessRequest+0x30a (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 1696]
0181ff10 6404cd10 f7bb5829 00000000 008ca368 WSFTPWebServer!CWebTcp::DoTask+0x6e5 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\nmwebserver\webserver.cpp @ 220]
0181ff4c 6405b17e f7bb581d 00000000 00000000 Core!CThreadPoolThread::_Run+0x80 (FPO: [Non-Fpo]) (CONV: thiscall) [d:\fts\ws_ftp web server\core\threadpool.cpp @ 404]
Since I had the return address, I unassembled it backward.
0:007> ub 02a5952c L10
IFtpSrvAPI![thunk]:ATL::CComObject
02a594fc cc int 3
02a594fd cc int 3
02a594fe cc int 3
02a594ff cc int 3
IFtpSrvAPI!ATL::CComObject
02a59500 56 push esi
02a59501 8bf1 mov esi,ecx ; move this from ecx to esi
02a59503 8b4e18 mov ecx,dword ptr [esi+18h] ; move object at offset 18h
02a59506 85c9 test ecx,ecx
02a59508 c7069c71a902 mov dword ptr [esi],offset IFtpSrvAPI!ATL::CComObject
02a5950e c746088871a902 mov dword ptr [esi+8],offset IFtpSrvAPI!ATL::CComObject
02a59515 c7460c7071a902 mov dword ptr [esi+0Ch],offset IFtpSrvAPI!ATL::CComObject
02a5951c c74614010000c0 mov dword ptr [esi+14h],0C0000001h
02a59523 7407 je IFtpSrvAPI!ATL::CComObject
02a59525 8b01 mov eax,dword ptr [ecx] ; move vtable to eax
02a59527 8b5004 mov edx,dword ptr [eax+4] ; move function at offset 4
02a5952a ffd2 call edx ; call function
Since the calling convention for the destructor of ATL::CComObject
From the above code, at the very beginning of the function, esi register is used to store this pointer from ecx register. Even though esi register has not been modified before the call instruction, it is possible that it would be modified inside the invoked virtual function. To check whether esi register indeed stores this pointer, I check the frame 3 with the following line of stack trace,
0181f9e4 77d04239 0745e6d8 022a16b8 022a16b8 IFtpSrvAPI!ATL::CComObject
Since the calling convention is stdcall, the first parameter would be the implicit this pointer. Since it matches to the value in esi register (see below). esi register has not been modified.
eax=04362bd8 ebx=022a1928 ecx=0633a580 edx=0000001f esi=0745e6d8 edi=00000009
eip=0000001f esp=0181f9cc ebp=0181f9f8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010202
0000001f ?? ???
Then I display the information for this object.
IFtpSrvAPI!ATL::CComObject
+0x014 m_pOuterUnknown : 0xc0000001 IUnknown
+0x000 __VFN_table : 0x02a9719c
+0x004 m_pSD : ATL::CComPtr
=02ab94c0 ATL::IDispatchImpl
+0x008 __VFN_table : 0x02a97188
+0x00c __VFN_table : 0x02a97170
+0x010 m_dwCurrentSafety : 0
+0x018 m_pLicense : 0x0633a580 FTP::IFTPLicense
However, when I deferenced ecx register to retrieve the vtable and then retrieved the virtual function, I had the following result,
0:007> dd 0633a580 l1
0633a580 073c6bb0
The value does not match to that in eax register.
0:007> dps 073c6bb0+0x4 l1
073c6bb4 00000020
The value does not match to the instruction pointer at the top.
Then I used u command to unassemble the code forward. Combining the output from both ub and u commands, I had the following code,
IFtpSrvAPI!ATL::CComObject
02a59500 56 push esi
02a59501 8bf1 mov esi,ecx
02a59503 8b4e18 mov ecx,dword ptr [esi+18h]
02a59506 85c9 test ecx,ecx ;
02a59508 c7069c71a902 mov dword ptr [esi],offset IFtpSrvAPI!ATL::CComObject
02a5950e c746088871a902 mov dword ptr [esi+8],offset IFtpSrvAPI!ATL::CComObject
02a59515 c7460c7071a902 mov dword ptr [esi+0Ch],offset IFtpSrvAPI!ATL::CComObject
02a5951c c74614010000c0 mov dword ptr [esi+14h],0C0000001h ;
02a59523 7407 je IFtpSrvAPI!ATL::CComObject
02a59525 8b01 mov eax,dword ptr [ecx]
02a59527 8b5004 mov edx,dword ptr [eax+4]
02a5952a ffd2 call edx ;
02a5952c c7461800000000 mov dword ptr [esi+18h],0 ; m_pLicense = NULL
02a59533 8b0d5cfcab02 mov ecx,dword ptr [IFtpSrvAPI!ATL::_pAtlModule (02abfc5c)]
02a59539 8b01 mov eax,dword ptr [ecx]
02a5953b 8b5008 mov edx,dword ptr [eax+8]
02a5953e ffd2 call edx ; _pAtlModule->Unlock()
02a59540 8b7604 mov esi,dword ptr [esi+4]
02a59543 85f6 test esi,esi
02a59545 7408 je IFtpSrvAPI!ATL::CComObject
From ATL source code, we have
virtual ~CComObject() throw()
{
m_dwRef = -(LONG_MAX/2);
FinalRelease();
#ifdef _ATL_DEBUG_INTERFACES
_AtlDebugInterfacesModule.DeleteNonAddRefThunk(_GetRawUnknown());
#endif
_pAtlModule->Unlock();
}
From CFTPLicense sourc code, we have
void CFTPLicense::FinalRelease()
{
if (m_pLicense) m_pLicense->RELEASE();
m_pLicense = NULL;
}
It seems that the function FinalRelease has been inlined due to optimization. From this point, it seem that the last function invoked is m_pLicense->RELEASE().
Then I attached a debugger to the web server and found out IFTPLicense_Impl::Release was indeed at offset 4 of the vtable.
Then I unassembled the Release function as following,
0:007> u ftpaccess!IFTPLicense_Impl::Release
ftpaccess!IFTPLicense_Impl::Release [d:\fts\ftpaccess\src\ftplicense_impl.cpp @ 139]:
02b2a360 56 push esi
02b2a361 8bf1 mov esi,ecx
02b2a363 8d4604 lea eax,[esi+4]
02b2a366 50 push eax
02b2a367 ff158c00b302 call dword ptr [ftpaccess!_imp__InterlockedDecrement (02b3008c)]
02b2a36d 85c0 test eax,eax
02b2a36f 7f34 jg ftpaccess!IFTPLicense_Impl::Release+0x45 (02b2a3a5)
02b2a371 683c6bb302 push offset ftpaccess!g_sLicenseCS (02b36b3c)
From the unassembled code, esi register is used to store the value of ecx register at the very beginning of the function, so I concluded the last function call was IFTPLicense_Impl::Release and the instruction pointer could be right at the call instruction.
There is a per-process global license object, which is also stored at offset 0x18 of ATL::CComObject[CFTPLicense]
1 comments: