Commit MetaInfo

Revisionf84ee88991395b75c50d07089809c52c38c68f71 (tree)
Time2011-01-24 03:44:15
AuthorFace
CommiterFace

Log Message

OrbiterExtensions: added lib functions for RecordEvent hooking

Change Summary

Incremental Difference

diff -r d2d1b6db855a -r f84ee8899139 Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.cpp
--- a/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.cpp Sat Jan 22 23:34:28 2011 +0100
+++ b/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.cpp Sun Jan 23 19:44:15 2011 +0100
@@ -13,6 +13,7 @@
1313 #define VESSELSTRUCTOFFSET_RECORDING 0x0D32
1414 #define ADDRESS_RECORDEVENT 0x00476FA0
1515 #define ADDRESS_INTERNALRECORDEVENT 0x00465FB0
16+#define HOOKS 2
1617
1718 // ==============================================================
1819 // Global variables
@@ -27,36 +28,49 @@
2728
2829 struct EventEntry
2930 {
30- double MJD;
31+ double mjd;
3132 char *event_type;
3233 char *event;
3334 };
3435
3536 struct EventQueue
36-{
37- CRITICAL_SECTION access;
37+{
3838 int backlog;
3939 std::queue<EventEntry> queue;
4040 };
4141
4242 std::map<VESSEL *, OBJHANDLE> g_DockLink;
4343 std::map<VESSEL *, EventQueue> g_Events;
44-std::map<VESSEL *, int> g_Handles;
44+std::map<int, std::map<VESSEL *, int> > g_Handles;
45+CRITICAL_SECTION g_EventsAccess;
4546
4647 DWORD g_Hook;
47-byte g_GetDockStatusOriginal[9]={0x8b,0x44,0x24,0x04,0x8b,0x40,0x48,0xc2,0x04};
48-byte g_RecordEventOriginal[9]={0x8B,0x09,0x80,0xB9,0x32,0x0D,0x00,0x00,0x00};
4948
50-//The following array is:
49+void *g_Addresses[HOOKS]=
50+{
51+ (void *)ADDRESS_GETDOCKSTATUS,
52+ (void *)ADDRESS_RECORDEVENT
53+};
54+
55+byte g_Original[HOOKS][9]=
56+{
57+ {0x8b,0x44,0x24,0x04,0x8b,0x40,0x48,0xc2,0x04},
58+ {0x8B,0x09,0x80,0xB9,0x32,0x0D,0x00,0x00,0x00}
59+};
60+
61+//The following arrays are:
5162 //_asm
5263 //{
53-// pop eax;
54-// push ecx;
55-// push eax;
56-// jmp dword ptr [GetDockStatus]; //Dynamically detected address
57-// nop;
64+// pop eax //reorder stack to inject ECX (object pointer)
65+// push ecx
66+// push eax
67+// jmp dword ptr [HOOKFUNCTION]; //jump to dynamically detected address
5868 //}
59-byte g_Code[9] = {0x58, 0x51, 0x50, 0xff, 0x25, 0, 0, 0, 0};
69+byte g_Code[HOOKS][9]=
70+{
71+ {0x58, 0x51, 0x50, 0xff, 0x25, 0, 0, 0, 0},
72+ {0x58, 0x51, 0x50, 0xff, 0x25, 0, 0, 0, 0}
73+};
6074
6175 OBJHANDLE _stdcall GetDockStatus(VESSEL *vessel, DOCKHANDLE dock)
6276 {
@@ -70,22 +84,25 @@
7084 void _stdcall RecordEvent(VESSEL *vessel, const char *event_type, const char *event)
7185 {
7286 //Do my own RecordEvent
87+ EnterCriticalSection(&g_EventsAccess);
7388 std::map<VESSEL *, EventQueue>::iterator el=g_Events.find(vessel);
7489 if (el!=g_Events.end())
75- {
76- EnterCriticalSection(&el->second.access);
77- if (el->second.queue.size()<el->second.backlog)
90+ {
91+ EventEntry entry;
92+ entry.mjd=oapiGetSimMJD();
93+ entry.event=new char[strlen(event)+1];
94+ strcpy(entry.event, event);
95+ entry.event_type=new char[strlen(event_type)+1];
96+ strcpy(entry.event_type, event_type);
97+ while(el->second.queue.size()>=el->second.backlog)
7898 {
79- EventEntry entry;
80- entry.MJD=oapiGetSimMJD();
81- entry.event=new char[strlen(event)+1];
82- strcpy(entry.event, event);
83- entry.event_type=new char[strlen(event_type)+1];
84- strcpy(entry.event_type, event_type);
85- el->second.queue.push(entry);
86- }
87- LeaveCriticalSection(&el->second.access);
99+ delete [] el->second.queue.front().event_type;
100+ delete [] el->second.queue.front().event;
101+ el->second.queue.pop();
102+ }
103+ el->second.queue.push(entry);
88104 }
105+ LeaveCriticalSection(&g_EventsAccess);
89106 //Original function content
90107 if (*(*(char **)vessel+VESSELSTRUCTOFFSET_RECORDING)==0) return;
91108 _asm
@@ -135,22 +152,25 @@
135152 extern "C"
136153 {
137154
138-// Initializes the virtual docking hook.
155+// Initializes specified hook. Default is docking status hook.
139156 // Returns 0 if hooked
140157 // 1 if already hooked
141158 // -1 if already initialized by handle
142159 // -2 if already hooked by some other system
143-__declspec(dllexport) int __cdecl Init(VESSEL *handle, int flags=0)
160+// -3 if hook is unknown
161+__declspec(dllexport) int __cdecl InitHook(VESSEL *handle, int hook)
144162 {
145- if (g_Handles.find(handle)!=g_Handles.end()) return -1;
146- g_Handles[handle]=1;
163+ if (hook>=HOOKS || hook<0) return -3;
147164
148- if (memcmp((void *)g_GetDockStatusOriginal, (void *)ADDRESS_GETDOCKSTATUS, 9)!=0 ||
149- memcmp((void *)g_RecordEventOriginal, (void *)ADDRESS_RECORDEVENT, 9)!=0)
165+ std::map<int, std::map<VESSEL *, int> >::iterator list=g_Handles.find(hook);
166+ if (list!=g_Handles.end())
150167 {
151- if (g_Handles.size()==1) return -2;
168+ //Hook already established by OrbiterExtensions
169+ if (list->second.find(handle)!=list->second.end()) return -1;
170+ list->second[handle]=0;
152171 return 1;
153172 }
173+ g_Handles[hook][handle]=0;
154174
155175 union
156176 {
@@ -159,34 +179,49 @@
159179 DWORD value;
160180 } p;
161181
162- g_Hook=(DWORD)(void *)GetDockStatus;
163- p.pointer=(void *)&g_Hook;
164- for(int i=0;i<4;i++) g_Code[5+i] = p.bytes[i];
165- WriteCode((void *)ADDRESS_GETDOCKSTATUS, (void *)g_Code, 9);
182+ switch(hook)
183+ {
184+ case 0: g_Hook=(DWORD)(void *)GetDockStatus; break;
185+ case 1:
186+ InitializeCriticalSection(&g_EventsAccess);
187+ g_Hook=(DWORD)(void *)RecordEvent;
188+ break;
189+ }
190+ p.pointer=(void *)&g_Hook;
166191
167- g_Hook=(DWORD)(void *)RecordEvent;
168- p.pointer=(void *)&g_Hook;
169- for(int i=0;i<4;i++) g_Code[5+i] = p.bytes[i];
170- WriteCode((void *)ADDRESS_RECORDEVENT, (void *)g_Code, 9);
192+ if (memcmp((void *)g_Original[hook], g_Addresses[hook], 9)!=0) return -2;
193+ for(int i=0;i<4;i++) g_Code[hook][5+i] = p.bytes[i];
194+ WriteCode(g_Addresses[hook], (void *)g_Code[hook], 9);
171195
172196 return 0;
173197 }
198+__declspec(dllexport) int __cdecl Init(VESSEL *handle){return InitHook(handle, 0);}
174199
175-// Removes the virtual docking hook.
200+// Removes the specified hook. Default is docking status hook.
176201 // Returns 0 if unhooked
177202 // 1 if still hooked, but handles unregistered
178203 // -1 if handle already unregistered
179204 // -2 if hook already released by some other system
180-__declspec(dllexport) int __cdecl Exit(VESSEL *handle)
205+// -3 if hook is unknown
206+__declspec(dllexport) int __cdecl ExitHook(VESSEL *handle, int hook)
181207 {
182- if (g_Handles.find(handle)==g_Handles.end()) return -1;
183- g_Handles.erase(handle);
184- if (g_Handles.size()>0) return 1;
185- if (memcmp((void *)g_Code, (void *)ADDRESS_RECORDEVENT, 10)!=0) return -2;
186- WriteCode((void *)ADDRESS_GETDOCKSTATUS, (void *)g_GetDockStatusOriginal, 10);
187- WriteCode((void *)ADDRESS_RECORDEVENT, (void *)g_RecordEventOriginal, 10);
208+ if (hook>=HOOKS || hook<0) return -3;
209+ std::map<int, std::map<VESSEL *, int> >::iterator list=g_Handles.find(hook);
210+ if (list==g_Handles.end()) return -1;
211+ if (list->second.find(handle)==list->second.end()) return -1;
212+ list->second.erase(handle);
213+ if (list->second.size()>0) return 1;
214+ if (memcmp((void *)g_Code[hook], g_Addresses[hook], 9)!=0) return -2;
215+ WriteCode(g_Addresses[hook], (void *)g_Original[hook], 9);
216+ switch(hook)
217+ {
218+ case 1:
219+ DeleteCriticalSection(&g_EventsAccess);
220+ break;
221+ }
188222 return 0;
189223 }
224+__declspec(dllexport) int __cdecl Exit(VESSEL *handle){return ExitHook(handle, 0);}
190225
191226 // Sets the docking state of the given vessel handle to the specified object.
192227 // If the object is NULL, a previous dock state is cleared.
@@ -205,6 +240,75 @@
205240 }
206241
207242 __declspec(dllexport) float __cdecl GetVersion(){return (float)0.2;}
243+
244+//*** Version 0.2 functions
245+
246+// Register the given vessel for RecordEvent hooking and/or sets the specified backlog.
247+// Returns 0
248+__declspec(dllexport) int __cdecl RecordVesselEvents(VESSEL *handle, int backlog)
249+{
250+ EnterCriticalSection(&g_EventsAccess);
251+ std::map<VESSEL *, EventQueue>::iterator el=g_Events.find(handle);
252+ if (el==g_Events.end())
253+ {
254+ g_Events[handle].backlog=backlog;
255+ LeaveCriticalSection(&g_EventsAccess);
256+ return 0;
257+ }
258+ el->second.backlog=backlog;
259+ LeaveCriticalSection(&g_EventsAccess);
260+ return 0;
208261 }
209262
210-}
\ No newline at end of file
263+// Unregister the given vessel for RecordEvent hooking and delete the queue.
264+// Returns 0 if successful
265+// -1 if vessel was not registered
266+__declspec(dllexport) int __cdecl DeleteVesselEvents(VESSEL *handle)
267+{
268+ EnterCriticalSection(&g_EventsAccess);
269+ std::map<VESSEL *, EventQueue>::iterator el=g_Events.find(handle);
270+ if (el!=g_Events.end())
271+ {
272+ LeaveCriticalSection(&g_EventsAccess);
273+ return -1;
274+ }
275+ while (!el->second.queue.empty())
276+ {
277+ delete [] el->second.queue.front().event_type;
278+ delete [] el->second.queue.front().event;
279+ el->second.queue.pop();
280+ }
281+ g_Events.erase(el);
282+ LeaveCriticalSection(&g_EventsAccess);
283+ return 0;
284+}
285+
286+// Gets the specified amount of recorded events for the given vessel.
287+// The arrays needs to be initialized with the appropriate count.
288+// Returns 0 if queue was empty
289+// >0 number of read events
290+// -1 if vessel was not registered
291+__declspec(dllexport) int __cdecl GetVesselEvents(VESSEL *handle, double *mjds, char **event_types, char **events, int size)
292+{
293+ EnterCriticalSection(&g_EventsAccess);
294+ std::map<VESSEL *, EventQueue>::iterator el=g_Events.find(handle);
295+ if (el!=g_Events.end())
296+ {
297+ LeaveCriticalSection(&g_EventsAccess);
298+ return -1;
299+ }
300+ int i=0;
301+ while (!el->second.queue.empty() && i<size)
302+ {
303+ mjds[i]=el->second.queue.front().mjd;
304+ event_types[i]=el->second.queue.front().event_type;
305+ events[i]=el->second.queue.front().event;
306+ el->second.queue.pop();
307+ i++;
308+ }
309+ LeaveCriticalSection(&g_EventsAccess);
310+ return i;
311+}
312+
313+}
314+}
diff -r d2d1b6db855a -r f84ee8899139 Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.h
--- a/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.h Sat Jan 22 23:34:28 2011 +0100
+++ b/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnel.h Sun Jan 23 19:44:15 2011 +0100
@@ -10,6 +10,9 @@
1010 // ==============================================================
1111 #include "orbitersdk.h"
1212
13+#define ORBITEREXTENSIONSHOOK_GETDOCKSTATUS 0
14+#define ORBITEREXTENSIONSHOOK_RECORDEVENT 1
15+
1316 namespace OrbiterExtensions
1417 {
1518
@@ -18,26 +21,49 @@
1821 // 1 if already hooked
1922 // -1 if already initialized by handle
2023 // -2 if already hooked by some other system
21-// -3 if library not found
22-// -4 internal error
23-int Init(VESSEL *handle);
24+// -3 if specified hook is unknown
25+// -4 if library not found
26+// -5 internal error
27+int Init(VESSEL *handle, int hook=ORBITEREXTENSIONSHOOK_GETDOCKSTATUS);
2428
2529 // Removes the virtual docking hook.
2630 // Returns 0 if unhooked
2731 // 1 if still hooked, but handles unregistered
2832 // -1 if handle already unregistered
2933 // -2 if hook already released by some other system
30-// -3 if library not found
31-int Exit(VESSEL *handle);
34+// -3 if specified hook is unknown
35+// -4 if library not found
36+int Exit(VESSEL *handle, int hook=ORBITEREXTENSIONSHOOK_GETDOCKSTATUS);
3237
3338 // Sets the docking state of the given vessel handle to the specified object.
3439 // If the object is NULL, a previous dock state is cleared.
3540 // Returns 0 if successful
3641 // -1 if clearing was not necessary
37-// -3 if library not found
42+// -4 if library not found
3843 int SetDockState(VESSEL *handle, OBJHANDLE obj);
3944
40-// Returns version of Orbiter extensions DLL or -3 if library was not found
45+// Returns version of Orbiter extensions DLL or -4 if library was not found
4146 float GetVersion();
4247
48+//*** Version 0.2 functions
49+
50+// Register the given vessel for RecordEvent hooking and/or sets the specified backlog.
51+// Returns 0 if successful
52+// -4 if library not found
53+int RecordVesselEvents(VESSEL *handle, int backlog);
54+
55+// Unregister the given vessel for RecordEvent hooking and delete the queue.
56+// Returns 0 if successful
57+// -1 if vessel was not registered
58+// -4 if library not found
59+int DeleteVesselEvents(VESSEL *handle);
60+
61+// Gets the specified amount of recorded events for the given vessel.
62+// The arrays needs to be initialized with the appropriate count.
63+// Returns 0 if queue was empty
64+// >0 number of read events
65+// -1 if vessel was not registered
66+// -4 if library not found
67+int GetVesselEvents(VESSEL *handle, double *mjds, char **event_types, char **events, int size);
68+
4369 }
\ No newline at end of file
diff -r d2d1b6db855a -r f84ee8899139 Orbitersdk/samples/AscensionUltra/VirtualDockingTunnelLibrary.cpp
--- a/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnelLibrary.cpp Sat Jan 22 23:34:28 2011 +0100
+++ b/Orbitersdk/samples/AscensionUltra/VirtualDockingTunnelLibrary.cpp Sun Jan 23 19:44:15 2011 +0100
@@ -11,9 +11,11 @@
1111
1212 #include "VirtualDockingTunnel.h"
1313
14-typedef int (* VESSELFUNC) (VESSEL *handle);
15-typedef int (* MAPFUNC) (VESSEL *handle, OBJHANDLE obj);
14+typedef int (* HOOKFUNC) (VESSEL *, int);
15+typedef int (* VESSELFUNC) (VESSEL *);
16+typedef int (* MAPFUNC) (VESSEL *, OBJHANDLE);
1617 typedef float (* FLOATGETTER) (void);
18+typedef int (* GETEVENTFUNC) (VESSEL *, double *, char **, char **, int);
1719
1820 // ==============================================================
1921 // Global variables
@@ -23,8 +25,13 @@
2325 HMODULE g_Module;
2426 VESSELFUNC g_Init;
2527 VESSELFUNC g_Exit;
28+HOOKFUNC g_InitHook;
29+HOOKFUNC g_ExitHook;
2630 MAPFUNC g_SetDockState;
2731 FLOATGETTER g_GetVersion;
32+HOOKFUNC g_RecordVesselEvents;
33+VESSELFUNC g_DeleteVesselEvents;
34+GETEVENTFUNC g_GetVesselEvents;
2835 }
2936
3037 // Initializes the virtual docking hook.
@@ -32,20 +39,38 @@
3239 // 1 if already hooked
3340 // -1 if already initialized by handle
3441 // -2 if already hooked by some other system
35-// -3 if library not found
36-// -4 internal error
37-int OrbiterExtensions::Init(VESSEL *handle)
42+// -3 if specified hook is unknown
43+// -4 if library not found
44+// -5 internal error
45+int OrbiterExtensions::Init(VESSEL *handle, int hook)
3846 {
3947 g_Module=LoadLibrary("Modules\\VirtualDockingTunnel.dll");
40- if (g_Module==NULL) return -3;
48+ if (g_Module==NULL) return -4;
4149 g_Init=(VESSELFUNC)GetProcAddress(g_Module, "Init");
4250 g_Exit=(VESSELFUNC)GetProcAddress(g_Module, "Exit");
51+ g_InitHook=(HOOKFUNC)GetProcAddress(g_Module, "InitHook");
52+ g_ExitHook=(HOOKFUNC)GetProcAddress(g_Module, "ExitHook");
4353 g_SetDockState=(MAPFUNC)GetProcAddress(g_Module, "SetDockState");
4454 g_GetVersion=(FLOATGETTER)GetProcAddress(g_Module, "GetVersion");
45- if (((DWORD)g_Init & (DWORD)g_Exit & (DWORD)g_SetDockState & (DWORD)g_GetVersion)==NULL)
55+ g_RecordVesselEvents=(HOOKFUNC)GetProcAddress(g_Module, "RecordVesselEvents");
56+ g_DeleteVesselEvents=(VESSELFUNC)GetProcAddress(g_Module, "DeleteVesselEvents");
57+ g_GetVesselEvents=(GETEVENTFUNC)GetProcAddress(g_Module, "GetVesselEvents");
58+ float version=GetVersion();
59+ if (((DWORD)g_Init & (DWORD)g_Exit & (DWORD)g_SetDockState & (DWORD)g_GetVersion)==NULL ||
60+ (((DWORD)g_InitHook & (DWORD)g_ExitHook & (DWORD)g_RecordVesselEvents & (DWORD)g_DeleteVesselEvents & (DWORD)g_GetVesselEvents)==NULL && version>0.1f))
4661 {
4762 FreeLibrary(g_Module);
48- return -4;
63+ g_GetVersion=(FLOATGETTER)NULL;
64+ g_Init=g_Exit=(VESSELFUNC)NULL;
65+ g_SetDockState=(MAPFUNC)NULL;
66+ g_InitHook=g_ExitHook=(HOOKFUNC)NULL;
67+ return -5;
68+ }
69+ if (version>=0.2f) return g_InitHook(handle, hook);
70+ if (hook!=0)
71+ {
72+ FreeLibrary(g_Module);
73+ return -3;
4974 }
5075 return g_Init(handle);
5176 }
@@ -55,12 +80,17 @@
5580 // 1 if still hooked, but handles unregistered
5681 // -1 if handle already unregistered
5782 // -2 if hook already released by some other system
58-// -3 if library not found
59-int OrbiterExtensions::Exit(VESSEL *handle)
83+// -3 if specified hook is unknown
84+// -4 if library not found
85+int OrbiterExtensions::Exit(VESSEL *handle, int hook)
6086 {
61- if (!g_Exit) return -3;
62- int result=g_Exit(handle);
63- FreeLibrary(g_Module);
87+ if (!g_Exit) return -4;
88+ float version=GetVersion();
89+ int result;
90+ if (version>=0.2f) result=g_ExitHook(handle, hook);
91+ else if (hook!=0) result=-3;
92+ else result=g_Exit(handle);
93+ if (result!=-3) FreeLibrary(g_Module);
6494 return result;
6595 }
6696
@@ -68,9 +98,30 @@
6898 // If the object is NULL, a previous dock state is cleared.
6999 // Returns 0 if successful
70100 // -1 if clearing was not necessary
71-// -3 if library not found
101+// -4 if library not found
72102 int OrbiterExtensions::SetDockState(VESSEL *handle, OBJHANDLE obj){if (!g_SetDockState) return -3; return g_SetDockState(handle, obj);}
73103
74104 // Returns the version of the loaded library if successful
75-// -3 if library not found
76-float OrbiterExtensions::GetVersion(){if (!g_GetVersion) return -3; return g_GetVersion();}
\ No newline at end of file
105+// -4 if library not found
106+float OrbiterExtensions::GetVersion(){if (!g_GetVersion) return -4; return g_GetVersion();}
107+
108+//*** Version 0.2 functions
109+
110+// Register the given vessel for RecordEvent hooking and/or sets the specified backlog.
111+// Returns 0 if successful
112+// -4 if library not found
113+int OrbiterExtensions::RecordVesselEvents(VESSEL *handle, int backlog){if (!g_RecordVesselEvents) return -4; return g_RecordVesselEvents(handle, backlog);}
114+
115+// Unregister the given vessel for RecordEvent hooking and delete the queue.
116+// Returns 0 if successful
117+// -1 if vessel was not registered
118+// -4 if library not found
119+int OrbiterExtensions::DeleteVesselEvents(VESSEL *handle){if (!g_DeleteVesselEvents) return -4; return g_DeleteVesselEvents(handle);}
120+
121+// Gets the specified amount of recorded events for the given vessel.
122+// The arrays needs to be initialized with the appropriate count.
123+// Returns 0 if queue was empty
124+// >0 number of read events
125+// -1 if vessel was not registered
126+// -4 if library not found
127+int OrbiterExtensions::GetVesselEvents(VESSEL *handle, double *mjds, char **event_types, char **events, int size){if (!g_GetVesselEvents) return -4; return g_GetVesselEvents(handle, mjds, event_types, events, size);}
\ No newline at end of file
Show on old repository browser