├── packages.config
├── ProjectInstaller.cs
├── util
└── KernelSymbolLookup.ps1
├── SystemCallService.sln
├── SystemCallServiceSettings.cs
├── Properties
├── SystemCallServiceSettings.cs
├── AssemblyInfo.cs
├── SystemCallServiceSettings.settings
└── SystemCallServiceSettings.Designer.cs
├── SystemCallService.Designer.cs
├── README.md
├── ProjectInstaller.Designer.cs
├── .gitignore
├── App.config
├── SystemCallService.resx
├── ProjectInstaller.resx
├── SystemCallServiceMain.cs
├── ntsensors.txt
├── SystemCallService.csproj
├── LICENSE
└── SystemCallService.cs
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ProjectInstaller.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2014 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 | using System.ComponentModel;
22 | using System.Configuration.Install;
23 |
24 | namespace SystemCallService
25 | {
26 | [RunInstaller(true)]
27 | public partial class ProjectInstaller : Installer
28 | {
29 | public ProjectInstaller()
30 | {
31 | InitializeComponent();
32 | }
33 |
34 | private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
35 | {
36 |
37 | }
38 |
39 | private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
40 | {
41 |
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/util/KernelSymbolLookup.ps1:
--------------------------------------------------------------------------------
1 | # Copyright 2015 Ray Canzanese
2 | # email: rcanzanese@gmail.com
3 | # url: www.canzanese.com
4 | #
5 | # This file is part of SystemCallService.
6 | #
7 | # SystemCallService is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 2 of the License, or
10 | # (at your option) any later version.
11 | #
12 | # SystemCallService is distributed in the hope that it will be useful,
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | # GNU General Public License for more details.
16 | #
17 | # You should have received a copy of the GNU General Public License
18 | # along with SystemCallService. If not, see .
19 |
20 | # Accepts a single command line argument that is the path to a kernel for
21 | # which to lookup the symbols.
22 |
23 | # Check for command line argument
24 | if($args.count -lt 1){
25 | echo "Input the *.binary file output by the SyscallCounterService and get a *.symbol file in return."
26 | return
27 | }
28 |
29 | # Makes sure the debug tools are in the path.
30 | $env:Path += ";C:\Program Files (x86)\Windows Kits\8.1\bin\x64\"
31 |
32 | $inputfile = $args[0];
33 |
34 | # Chekc to see if it is a binary file.
35 | if(-not $inputfile -match "\.binary$")
36 | {
37 | echo "Probably not a binary file. Make sure you are inputting the binary file SyscallCounterService died on."
38 | return
39 | }
40 |
41 | $outputfile = $inputfile -replace "\.binary$", ".symbols"
42 |
43 | dbh.exe $inputfile enum | out-file $outputfile -Encoding ASCII
44 |
--------------------------------------------------------------------------------
/SystemCallService.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SystemCallService", "SystemCallService.csproj", "{7D3C3B13-8911-48C6-9B42-95DE79B34716}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|Any CPU = Release|Any CPU
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x64.ActiveCfg = Debug|x64
21 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x64.Build.0 = Debug|x64
22 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x86.ActiveCfg = Debug|x86
23 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Debug|x86.Build.0 = Debug|x86
24 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x64.ActiveCfg = Release|x64
27 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x64.Build.0 = Release|x64
28 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x86.ActiveCfg = Release|x86
29 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}.Release|x86.Build.0 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | EndGlobal
35 |
--------------------------------------------------------------------------------
/SystemCallServiceSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 | using System.ComponentModel;
22 | using System.Configuration;
23 |
24 | namespace SystemCallService {
25 |
26 | // This class allows you to handle specific events on the settings class:
27 | // The SettingChanging event is raised before a setting's value is changed.
28 | // The PropertyChanged event is raised after a setting's value is changed.
29 | // The SettingsLoaded event is raised after the setting values are loaded.
30 | // The SettingsSaving event is raised before the setting values are saved.
31 | internal sealed class SystemCallServiceSettings {
32 | private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) {
33 | // Add code to handle the SettingChangingEvent event here.
34 | }
35 |
36 | private void SettingsSavingEventHandler(object sender, CancelEventArgs e) {
37 | // Add code to handle the SettingsSaving event here.
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Properties/SystemCallServiceSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 |
22 | using System.ComponentModel;
23 | using System.Configuration;
24 |
25 | namespace SystemCallService.Properties {
26 |
27 |
28 | // This class allows you to handle specific events on the settings class:
29 | // The SettingChanging event is raised before a setting's value is changed.
30 | // The PropertyChanged event is raised after a setting's value is changed.
31 | // The SettingsLoaded event is raised after the setting values are loaded.
32 | // The SettingsSaving event is raised before the setting values are saved.
33 | internal sealed partial class SystemCallServiceSettings {
34 | private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) {
35 | // Add code to handle the SettingChangingEvent event here.
36 | }
37 |
38 | private void SettingsSavingEventHandler(object sender, CancelEventArgs e) {
39 | // Add code to handle the SettingsSaving event here.
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/SystemCallService.Designer.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 |
22 | using System.ComponentModel;
23 |
24 | namespace SystemCallService
25 | {
26 | partial class SystemCallService
27 | {
28 | ///
29 | /// Required designer variable.
30 | ///
31 | private IContainer components = null;
32 |
33 | ///
34 | /// Clean up any resources being used.
35 | ///
36 | /// true if managed resources should be disposed; otherwise, false.
37 | protected override void Dispose(bool disposing)
38 | {
39 | if (disposing && (components != null))
40 | {
41 | components.Dispose();
42 | }
43 | base.Dispose(disposing);
44 | }
45 |
46 | #region Component Designer generated code
47 |
48 | ///
49 | /// Required method for Designer support - do not modify
50 | /// the contents of this method with the code editor.
51 | ///
52 | private void InitializeComponent()
53 | {
54 | //
55 | // SystemCallService
56 | //
57 | this.ServiceName = "Service1";
58 |
59 | }
60 |
61 | #endregion
62 |
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 |
22 | using System.Reflection;
23 | using System.Runtime.InteropServices;
24 |
25 | // General Information about an assembly is controlled through the following
26 | // set of attributes. Change these attribute values to modify the information
27 | // associated with an assembly.
28 | [assembly: AssemblyTitle("SystemCallService")]
29 | [assembly: AssemblyDescription("Performs system call tracing for research purposes. ")]
30 | [assembly: AssemblyConfiguration("")]
31 | [assembly: AssemblyCompany("")]
32 | [assembly: AssemblyProduct("SystemCallService")]
33 | [assembly: AssemblyCopyright("Copyright © Ray Canzanese 2015")]
34 | [assembly: AssemblyTrademark("")]
35 | [assembly: AssemblyCulture("")]
36 |
37 | // Setting ComVisible to false makes the types in this assembly not visible
38 | // to COM components. If you need to access a type in this assembly from
39 | // COM, set the ComVisible attribute to true on that type.
40 | [assembly: ComVisible(false)]
41 |
42 | // The following GUID is for the ID of the typelib if this project is exposed to COM
43 | [assembly: Guid("2d0ef725-105b-4981-b4ec-dd3ecd4c7017")]
44 |
45 | // Version information for an assembly consists of the following four values:
46 | //
47 | // Major Version
48 | // Minor Version
49 | // Build Number
50 | // Revision
51 | //
52 | // You can specify all the values or you can default the Build and Revision Numbers
53 | // by using the '*' as shown below:
54 | // [assembly: AssemblyVersion("1.0.*")]
55 | [assembly: AssemblyVersion("2014.01.0.0")]
56 | [assembly: AssemblyFileVersion("2014.01.0.0")]
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SystemCallService
2 |
3 | Host / process / thread-level system call tracer for Windows 7 / 8 / 2008 / 2012
4 |
5 | ## Prerequisites
6 | * Requires .NET Framework 4.5 or newer
7 | * Windows 7 / 2008 / 2008 R2 / 8 / 8.1 / 2012 / 2012 R2
8 | * TraceEvent 1.0.29 (can be installed using Nuget)
9 | * System.Data.SQLite 1.0.96.0 (can be installed using Nuget)
10 |
11 | ## Symbol tables
12 | Symbol tables change when new kernel versions are released.
13 | The current update process is manual and requires the Windows Debugging Tools.
14 | There is a tool in the utils/ directory to facilitate symbol lookup.
15 |
16 | ```
17 | dbh.exe "kernel_file" enum | out-file "output symbols" -Encoding ASCII
18 | ```
19 |
20 | ## Quick start instructions
21 |
22 | * Open an elevated command prompt or powershell by right clicking the icon and choosing "Run as Administrator"
23 | * Change to the folder where SystemCallService.exe is located
24 | * Install the service by running:
25 | ```
26 | SystemCallService.exe -install
27 | ```
28 | * To uninstall the service, run:
29 | ```
30 | SystemCallService.exe -uninstall
31 | ```
32 |
33 | ## Overview
34 |
35 | ### Data storage
36 |
37 | Data are stored in C:\Windows\Temp\SystemCallServiceData\
38 | * database.sqlite is a sqlite database containing all of the logged data.
39 | * debug_log.txt is a log file containing information useful for debugging.
40 | * host_data_trace is a binary file containing the host data
41 | * the *_trace files are the process and thread traces, with GUIDs specified in the database.sqlite
42 |
43 | Major error messages are also logged to the Application Event Log.
44 |
45 | ### Usage
46 | There are three ways to control the service. All must be executed using "Run as Administrator":
47 | * sc.exe
48 | * SystemCallService.exe
49 | * net.exe ()for stopping and starting the service only)
50 |
51 | ####Installation
52 | ```
53 | sc.exe create SystemCallService binPath= "C:\Full\Path\To\SystemCallService.exe" start= auto
54 | ```
55 | or
56 | ```
57 | SystemCallService.exe -install
58 | ```
59 |
60 | ####Uninstallation
61 | ```sc.exe delete SystemCallService```
62 | or
63 | ```SystemCallService.exe -uninstall ```
64 |
65 | ####Start Logging
66 |
67 | ```sc.exe start SystemCallService```
68 |
69 | or
70 |
71 | ```SystemCallService.exe -start ```
72 |
73 | or
74 |
75 | ```net start SystemCallService```
76 |
77 | ####Stop Logging
78 | ```sc.exe stop SystemCallService```
79 |
80 | or
81 |
82 | ```SystemCallService.exe -stop ```
83 |
84 | or
85 |
86 | ```net stop SystemCallService```
--------------------------------------------------------------------------------
/ProjectInstaller.Designer.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2014 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 |
22 | using System.ComponentModel;
23 | using System.ServiceProcess;
24 |
25 | namespace SystemCallService
26 | {
27 | partial class ProjectInstaller
28 | {
29 | ///
30 | /// Required designer variable.
31 | ///
32 | private IContainer components = null;
33 |
34 | ///
35 | /// Clean up any resources being used.
36 | ///
37 | /// true if managed resources should be disposed; otherwise, false.
38 | protected override void Dispose(bool disposing)
39 | {
40 | if (disposing && (components != null))
41 | {
42 | components.Dispose();
43 | }
44 | base.Dispose(disposing);
45 | }
46 |
47 | #region Component Designer generated code
48 |
49 | ///
50 | /// Required method for Designer support - do not modify
51 | /// the contents of this method with the code editor.
52 | ///
53 | private void InitializeComponent()
54 | {
55 | this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
56 | this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
57 | //
58 | // serviceProcessInstaller1
59 | //
60 | this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
61 | this.serviceProcessInstaller1.Password = null;
62 | this.serviceProcessInstaller1.Username = null;
63 | this.serviceProcessInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceProcessInstaller1_AfterInstall);
64 | //
65 | // serviceInstaller1
66 | //
67 | this.serviceInstaller1.Description = "Collects system call traces for research purposes. Contact Ray Canzanese -- rcanzanese@gmail.com";
68 | this.serviceInstaller1.DisplayName = "System Call Service";
69 | this.serviceInstaller1.ServiceName = "SystemCallService";
70 | this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
71 | this.serviceInstaller1.AfterInstall += new System.Configuration.Install.InstallEventHandler(this.serviceInstaller1_AfterInstall);
72 | this.serviceInstaller1.ServicesDependedOn = new string[] {"LanmanServer"};
73 | //
74 | // ProjectInstaller
75 | //
76 | this.Installers.AddRange(new System.Configuration.Install.Installer[] {
77 | this.serviceProcessInstaller1,
78 | this.serviceInstaller1});
79 |
80 | }
81 |
82 | #endregion
83 |
84 | private ServiceProcessInstaller serviceProcessInstaller1;
85 | private ServiceInstaller serviceInstaller1;
86 | }
87 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 |
--------------------------------------------------------------------------------
/Properties/SystemCallServiceSettings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | SystemCallServiceData
7 |
8 |
9 | debug_log.txt
10 |
11 |
12 | Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, CommandLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey INTEGER, Md5 TEXT
13 |
14 |
15 | Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT
16 |
17 |
18 | NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DOUBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace INT, ThreadTrace INT
19 |
20 |
21 | 0
22 |
23 |
24 | 3600000
25 |
26 |
27 | symbols
28 |
29 |
30 | ntsensors.txt
31 |
32 |
33 | 120000
34 |
35 |
36 | 30000
37 |
38 |
39 | 30000
40 |
41 |
42 | 100
43 |
44 |
45 | True
46 |
47 |
48 | 10000
49 |
50 |
51 | None
52 |
53 |
54 | False
55 |
56 |
57 | True
58 |
59 |
60 | True
61 |
62 |
63 | True
64 |
65 |
66 | False
67 |
68 |
69 |
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | None
15 |
16 |
17 |
18 |
19 |
20 |
21 | SystemCallServiceData
22 |
23 |
24 | debug_log.txt
25 |
26 |
27 | Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, CommandLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey INTEGER, Md5 TEXT
28 |
29 |
30 | Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT
31 |
32 |
33 | NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DOUBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace INT, ThreadTrace INT
34 |
35 |
36 | 0
37 |
38 |
39 | 3600000
40 |
41 |
42 | symbols
43 |
44 |
45 | ntsensors.txt
46 |
47 |
48 | 120000
49 |
50 |
51 | 30000
52 |
53 |
54 | 30000
55 |
56 |
57 | 100
58 |
59 |
60 | True
61 |
62 |
63 | 10000
64 |
65 |
66 | False
67 |
68 |
69 | True
70 |
71 |
72 | True
73 |
74 |
75 | True
76 |
77 |
78 | False
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/SystemCallService.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | False
122 |
123 |
--------------------------------------------------------------------------------
/ProjectInstaller.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 56
122 |
123 |
124 | 196, 17
125 |
126 |
127 | False
128 |
129 |
--------------------------------------------------------------------------------
/SystemCallServiceMain.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 | // TODO: Cleanup this code and provide feedback to the terminal
22 |
23 | using System;
24 | using System.Collections;
25 | using System.Configuration.Install;
26 | using System.ServiceProcess;
27 |
28 | namespace SystemCallService
29 | {
30 | static class SyscallCounterMain
31 | {
32 | private static readonly String _serviceName = "SystemCallService";
33 | ///
34 | /// The main entry point for the application.
35 | ///
36 | static void Main(string[] args)
37 | {
38 | if (args.Length == 0)
39 | {
40 | ServiceBase[] servicesToRun;
41 | servicesToRun = new ServiceBase[]
42 | {
43 | new SystemCallService()
44 | };
45 | ServiceBase.Run(servicesToRun);
46 | }
47 | else if (args.Length == 1)
48 | {
49 | switch (args[0])
50 | {
51 | case "-install":
52 | InstallService();
53 | StartService();
54 | break;
55 | case "-uninstall":
56 | StopService();
57 | UninstallService();
58 | break;
59 | case "-start":
60 | StartService();
61 | break;
62 | case "-stop":
63 | StopService();
64 | break;
65 | default:
66 | Console.WriteLine("This is a service executable. Read the documentation or try one of the following command line options: -install -uninstall -start -stop");
67 | break;
68 | }
69 | }
70 | }
71 |
72 | private static bool IsInstalled()
73 | {
74 | using (ServiceController controller =
75 | new ServiceController(_serviceName))
76 | {
77 | try
78 | {
79 | ServiceControllerStatus status = controller.Status;
80 | }
81 | catch
82 | {
83 | return false;
84 | }
85 | return true;
86 | }
87 | }
88 |
89 | private static bool IsRunning()
90 | {
91 | using (ServiceController controller =
92 | new ServiceController(_serviceName))
93 | {
94 | if (!IsInstalled()) return false;
95 | return (controller.Status == ServiceControllerStatus.Running);
96 | }
97 | }
98 |
99 | private static AssemblyInstaller GetInstaller()
100 | {
101 | AssemblyInstaller installer = new AssemblyInstaller(
102 | typeof(ProjectInstaller).Assembly, null);
103 | installer.UseNewContext = true;
104 | return installer;
105 | }
106 |
107 | private static void InstallService()
108 | {
109 | if (IsInstalled()) return;
110 |
111 | try
112 | {
113 | using (AssemblyInstaller installer = GetInstaller())
114 | {
115 | IDictionary state = new Hashtable();
116 | try
117 | {
118 | installer.Install(state);
119 | installer.Commit(state);
120 | }
121 | catch
122 | {
123 | try
124 | {
125 | installer.Rollback(state);
126 | }
127 | catch
128 | {
129 |
130 | }
131 | throw;
132 | }
133 | }
134 | }
135 | catch
136 | {
137 | throw;
138 | }
139 | }
140 |
141 | private static void UninstallService()
142 | {
143 | if (!IsInstalled()) return;
144 | try
145 | {
146 | using (AssemblyInstaller installer = GetInstaller())
147 | {
148 | IDictionary state = new Hashtable();
149 | try
150 | {
151 | installer.Uninstall(state);
152 | }
153 | catch
154 | {
155 | throw;
156 | }
157 | }
158 | }
159 | catch
160 | {
161 | throw;
162 | }
163 | }
164 |
165 | private static void StartService()
166 | {
167 | if (!IsInstalled()) return;
168 |
169 | using (ServiceController controller =
170 | new ServiceController(_serviceName))
171 | {
172 | try
173 | {
174 | if (controller.Status != ServiceControllerStatus.Running)
175 | {
176 | controller.Start();
177 | controller.WaitForStatus(ServiceControllerStatus.Running,
178 | TimeSpan.FromSeconds(10));
179 | }
180 | }
181 | catch
182 | {
183 | throw;
184 | }
185 | }
186 | }
187 |
188 | private static void StopService()
189 | {
190 | if (!IsInstalled()) return;
191 | using (ServiceController controller =
192 | new ServiceController(_serviceName))
193 | {
194 | try
195 | {
196 | if (controller.Status != ServiceControllerStatus.Stopped)
197 | {
198 | controller.Stop();
199 | controller.WaitForStatus(ServiceControllerStatus.Stopped,
200 | TimeSpan.FromSeconds(10));
201 | }
202 | }
203 | catch
204 | {
205 | throw;
206 | }
207 | }
208 | }
209 | }
210 |
211 | }
212 |
--------------------------------------------------------------------------------
/Properties/SystemCallServiceSettings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.34209
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SystemCallService.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
16 | internal sealed partial class SystemCallServiceSettings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static SystemCallServiceSettings defaultInstance = ((SystemCallServiceSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new SystemCallServiceSettings())));
19 |
20 | public static SystemCallServiceSettings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("SystemCallServiceData")]
29 | public string DataDirectory {
30 | get {
31 | return ((string)(this["DataDirectory"]));
32 | }
33 | }
34 |
35 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
36 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
37 | [global::System.Configuration.DefaultSettingValueAttribute("debug_log.txt")]
38 | public string DebugLogFilename {
39 | get {
40 | return ((string)(this["DebugLogFilename"]));
41 | }
42 | }
43 |
44 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
45 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
46 | [global::System.Configuration.DefaultSettingValueAttribute("Pid int, Start DATETIME, StartRelativeMSec DOUBLE, StopRelativeMSec DOUBLE, Comma" +
47 | "ndLine TEXT, ImageFileName TEXT, ParentID int, Guid TEXT PRIMARY KEY, ProcessKey" +
48 | " INTEGER, Md5 TEXT")]
49 | public string ProcessTableStructure {
50 | get {
51 | return ((string)(this["ProcessTableStructure"]));
52 | }
53 | }
54 |
55 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
56 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
57 | [global::System.Configuration.DefaultSettingValueAttribute("Pid int, PidStartRelativeMSec DOUBLE, Tid int, Start DateTime, StartRelativeMSec " +
58 | "DOUBLE, StopRelativeMSec DOUBLE, Guid TEXT PRIMARY KEY, ProcessGuid TEXT ")]
59 | public string ThreadTableStructure {
60 | get {
61 | return ((string)(this["ThreadTableStructure"]));
62 | }
63 | }
64 |
65 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
66 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
67 | [global::System.Configuration.DefaultSettingValueAttribute("NtoskrnlVersion TEXT, NtoskrnlMD5 TEXT, Cores int, Hostname TEXT, HostSampling DO" +
68 | "UBLE, ProcessSampling DOUBLE, ThreadSampling DOUBLE, HostTrace INT, ProcessTrace" +
69 | " INT, ThreadTrace INT")]
70 | public string SystemInfoTableStructure {
71 | get {
72 | return ((string)(this["SystemInfoTableStructure"]));
73 | }
74 | }
75 |
76 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
77 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
78 | [global::System.Configuration.DefaultSettingValueAttribute("0")]
79 | public int Verbosity {
80 | get {
81 | return ((int)(this["Verbosity"]));
82 | }
83 | }
84 |
85 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
86 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
87 | [global::System.Configuration.DefaultSettingValueAttribute("3600000")]
88 | public double AutoResetMs {
89 | get {
90 | return ((double)(this["AutoResetMs"]));
91 | }
92 | }
93 |
94 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
95 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
96 | [global::System.Configuration.DefaultSettingValueAttribute("symbols")]
97 | public string SymbolSubfolder {
98 | get {
99 | return ((string)(this["SymbolSubfolder"]));
100 | }
101 | }
102 |
103 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
104 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
105 | [global::System.Configuration.DefaultSettingValueAttribute("ntsensors.txt")]
106 | public string NtSensorList {
107 | get {
108 | return ((string)(this["NtSensorList"]));
109 | }
110 | }
111 |
112 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
113 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
114 | [global::System.Configuration.DefaultSettingValueAttribute("120000")]
115 | public float CommitInterval {
116 | get {
117 | return ((float)(this["CommitInterval"]));
118 | }
119 | }
120 |
121 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
122 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
123 | [global::System.Configuration.DefaultSettingValueAttribute("30000")]
124 | public double ThreadDeletionDelay {
125 | get {
126 | return ((double)(this["ThreadDeletionDelay"]));
127 | }
128 | }
129 |
130 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
131 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
132 | [global::System.Configuration.DefaultSettingValueAttribute("30000")]
133 | public double ProcessDeletionDelay {
134 | get {
135 | return ((double)(this["ProcessDeletionDelay"]));
136 | }
137 | }
138 |
139 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
140 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
141 | [global::System.Configuration.DefaultSettingValueAttribute("100")]
142 | public double MinBackoff {
143 | get {
144 | return ((double)(this["MinBackoff"]));
145 | }
146 | }
147 |
148 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
149 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
150 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
151 | public bool TracePerProcess {
152 | get {
153 | return ((bool)(this["TracePerProcess"]));
154 | }
155 | }
156 |
157 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
158 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
159 | [global::System.Configuration.DefaultSettingValueAttribute("10000")]
160 | public long MaxTraceSyscalls {
161 | get {
162 | return ((long)(this["MaxTraceSyscalls"]));
163 | }
164 | }
165 |
166 | [global::System.Configuration.UserScopedSettingAttribute()]
167 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
168 | [global::System.Configuration.DefaultSettingValueAttribute("None")]
169 | public string HostIdentifier {
170 | get {
171 | return ((string)(this["HostIdentifier"]));
172 | }
173 | set {
174 | this["HostIdentifier"] = value;
175 | }
176 | }
177 |
178 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
179 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
180 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
181 | public bool AnonymizeHostname {
182 | get {
183 | return ((bool)(this["AnonymizeHostname"]));
184 | }
185 | }
186 |
187 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
188 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
189 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
190 | public bool ScrubCommandLine {
191 | get {
192 | return ((bool)(this["ScrubCommandLine"]));
193 | }
194 | }
195 |
196 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
197 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
198 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
199 | public bool TraceHostLevel {
200 | get {
201 | return ((bool)(this["TraceHostLevel"]));
202 | }
203 | }
204 |
205 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
206 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
207 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
208 | public bool TracePerThread {
209 | get {
210 | return ((bool)(this["TracePerThread"]));
211 | }
212 | }
213 |
214 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
215 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
216 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
217 | public bool ProfileCode {
218 | get {
219 | return ((bool)(this["ProfileCode"]));
220 | }
221 | }
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/ntsensors.txt:
--------------------------------------------------------------------------------
1 | NtGetContextThread
2 | NtDeleteValueKey
3 | NtCreateProcessEx
4 | NtSystemRoot
5 | NtFilterBootOption
6 | NtQueryEaFile
7 | NtCreateIRTimer
8 | NtCancelWaitCompletionPacket
9 | NtFlushBuffersFileEx
10 | NtQuerySemaphore
11 | NtLockRegistryKey
12 | NtSetCachedSigningLevel
13 | NtFlushBuffersFile
14 | NtQueryMultipleValueKey
15 | NtUmsThreadYield
16 | NtAlpcCreateResourceReserve
17 | NtSetIoCompletionEx
18 | NtAccessCheckByTypeResultList
19 | NtRaiseException
20 | NtSetSystemInformation
21 | NtWaitForWorkViaWorkerFactory
22 | NtSuspendProcess
23 | NtCommitTransaction
24 | NtdllExports
25 | NtCreateTimer
26 | NtContinue
27 | NtWaitForDebugEvent
28 | NtQueryDebugFilterState
29 | NtProtectVirtualMemory
30 | NtCreateKeyedEvent
31 | NtOpenTimer
32 | NtFlushProcessWriteBuffers
33 | NtQueryVirtualMemory
34 | NtCreateFile
35 | NtAllocateVirtualMemory
36 | NtCreateSymbolicLinkObject
37 | NtImpersonateAnonymousToken
38 | NtCreatePrivateNamespace
39 | NtSetDebugFilterState
40 | NtInitialUserProcessBuffer
41 | NtDeleteWnfStateName
42 | NtGlobalFlag
43 | NtCreateKey
44 | NtSetSystemTime
45 | NtPrivilegeCheck
46 | NtQueryInformationTransaction
47 | NtSetEvent
48 | NtAlpcOpenSenderThread
49 | NtGetCachedSigningLevel
50 | NtDeleteKey
51 | NtPropagationComplete
52 | NtRollbackEnlistment
53 | NtCreateWnfStateName
54 | NtSetThreadExecutionState
55 | NtFreezeRegistry
56 | NtDeletePrivateNamespace
57 | NtSaveKey
58 | NtQueryDirectoryFile
59 | NtPowerInformation
60 | NtCreateSection
61 | NtSetContextThread
62 | NtAlpcCancelMessage
63 | NtAlpcCreatePort
64 | NtUnloadKey
65 | NtDeleteFile
66 | NtCreateTokenEx
67 | NtSetIntervalProfile
68 | NtQueryIntervalProfile
69 | NtCreateTransaction
70 | NtReplaceKey
71 | NtReadRequestData
72 | NtClearEvent
73 | NtCreateDebugObject
74 | NtCreateDirectoryObject
75 | NtRenameTransactionManager
76 | NtCreateTimer2
77 | NtCreateNamedPipeFile
78 | NtAlpcRevokeSecurityContext
79 | NtDeleteBootEntry
80 | NtWriteVirtualMemory
81 | NtAlpcDeleteResourceReserve
82 | NtIsProcessInJob
83 | NtAlertThread
84 | NtQuerySystemInformationEx
85 | NtDebugActiveProcess
86 | NtQueueApcThreadEx
87 | NtOpenFile
88 | NtGetNotificationResourceManager
89 | NtAcceptConnectPort
90 | NtListenPort
91 | NtTerminateJobObject
92 | NtDisableLastKnownGood
93 | NtOpenPrivateNamespace
94 | NtDeviceIoControlFile
95 | NtFlushInstructionCache
96 | NtQuerySystemEnvironmentValue
97 | NtFlushInstallUILanguage
98 | NtMapCMFModule
99 | NtGetCompleteWnfStateSubscription
100 | NtSubscribeWnfStateChange
101 | NtMakePermanentObject
102 | NtAlertResumeThread
103 | NtCreateEvent
104 | NtOpenKeyTransactedEx
105 | NtWriteRequestData
106 | NtDelayExecution
107 | NtSaveMergedKeys
108 | NtAlpcAcceptConnectPort
109 | NtSetInformationJobObject
110 | NtImpersonateThread
111 | NtQueryKey
112 | NtGetWriteWatch
113 | NtQueryLicenseValue
114 | NtSetValueKey
115 | NtAllocateLocallyUniqueId
116 | NtReleaseSemaphore
117 | NtRollbackTransaction
118 | NtGetNlsSectionPtr
119 | NtFindAtom
120 | NtLoadDriver
121 | NtCreateMailslotFile
122 | NtAccessCheck
123 | NtDeleteObjectAuditAlarm
124 | NtSetBootEntryOrder
125 | NtShutdownWorkerFactory
126 | NtOpenEventPair
127 | NtWaitHighEventPair
128 | NtIsSystemResumeAutomatic
129 | NtThawRegistry
130 | NtAccessCheckByTypeResultListAndAuditAlarmByHandle
131 | NtAlpcCreatePortSection
132 | NtCreateJobSet
133 | NtSetQuotaInformationFile
134 | NtStopProfile
135 | NtCreateProfile
136 | NtCreateTransactionManager
137 | NtEnumerateDriverEntries
138 | NtPrepareComplete
139 | NtOpenObjectAuditAlarm
140 | NtRequestWaitReplyPort
141 | NtSetDefaultUILanguage
142 | NtYieldExecution
143 | NtCommitEnlistment
144 | NtCreateEventPair
145 | NtPrePrepareComplete
146 | NtSetSystemEnvironmentValueEx
147 | NtVhdBootFile
148 | NtQueryInformationWorkerFactory
149 | NtCancelIoFile
150 | NtRemoveIoCompletion
151 | NtFsControlFile
152 | NtCancelIoFileEx
153 | NtQueryTimer
154 | NtRollbackComplete
155 | NtCompareTokens
156 | NtCreatePort
157 | NtRemoveProcessDebug
158 | NtSetVolumeInformationFile
159 | NtPlugPlayGetDeviceRelatedDevice
160 | NtAllocateUserPhysicalPages
161 | NtQueryWnfStateData
162 | NtRecoverEnlistment
163 | NtQueryInformationThread
164 | NtQuerySecurityAttributesToken
165 | NtModifyDriverEntry
166 | NtUpdateWnfStateData
167 | NtResumeThread
168 | NtSetIoCompletion
169 | NtQueryPortInformationProcess
170 | NtEnableLastKnownGood
171 | NtSetInformationProcess
172 | NtQueryDefaultLocale
173 | NtReplacePartitionUnit
174 | NtWaitForKeyedEvent
175 | NtQueryWnfStateNameInformation
176 | NtDrawText
177 | NtWaitForSingleObject
178 | NtAddDriverEntry
179 | NtSecureConnectPort
180 | NtQueryInformationJobObject
181 | NtCreateEnlistment
182 | NtCompactKeys
183 | NtQueryValueKey
184 | NtCreateUserProcess
185 | NtSetSecurityObject
186 | NtIsUILanguageComitted
187 | NtPlugPlayGetDeviceStatus
188 | NtDeleteWnfStateData
189 | NtFlushWriteBuffer
190 | NtQuerySystemEnvironmentValueEx
191 | NtTerminateThread
192 | NtRollforwardTransactionManager
193 | NtSaveKeyEx
194 | NtOpenProcess
195 | NtCreateWaitablePort
196 | NtCompressKey
197 | NtCreateThreadEx
198 | NtAlpcDeletePortSection
199 | NtInitiatePowerAction
200 | NtQueryInformationTransactionManager
201 | NtCreateResourceManager
202 | NtPropagationFailed
203 | NtSetUuidSeed
204 | NtSetWnfProcessNotificationEvent
205 | NtInitialUserProcessBufferType
206 | NtUnmapViewOfSectionEx
207 | NtQueryIoCompletion
208 | NtOpenEvent
209 | NtBuildLabEx
210 | NtQueryInformationEnlistment
211 | NtClose
212 | NtCreatePagingFile
213 | NtBuildLab
214 | NtOpenMutant
215 | NtQueryInformationResourceManager
216 | NtCompleteConnectPort
217 | NtPrivilegeObjectAuditAlarm
218 | NtQueryQuotaInformationFile
219 | NtBuildNumber
220 | NtCreateToken
221 | NtSuspendThread
222 | NtPlugPlayGetDeviceProperty
223 | NtSetInformationWorkerFactory
224 | NtRegisterProtocolAddressInformation
225 | NtBuildGUID
226 | NtRenameKey
227 | NtCreateThread
228 | NtSetInformationObject
229 | NtDeleteAtom
230 | NtAlpcDeleteSecurityContext
231 | NtReplyWaitReceivePort
232 | NtTerminateProcess
233 | Ntdll32Exports
234 | NtSetEaFile
235 | NtOpenTransaction
236 | NtPlugPlayControl
237 | NtSinglePhaseReject
238 | NtSetInformationFile
239 | NtPrepareEnlistment
240 | NtAccessCheckAndAuditAlarm
241 | NtInitialUserProcessBufferLength
242 | NtMapViewOfSection
243 | NtPlugPlayGetDeviceRelationsList
244 | NtSetSystemEnvironmentValue
245 | NtOpenDirectoryObject
246 | NtSetInformationKey
247 | NtAddAtom
248 | NtQueryObject
249 | NtReplyWaitReceivePortEx
250 | NtCreateProfileEx
251 | NtUnloadDriver
252 | NtLockFile
253 | NtFilterTokenEx
254 | NtNotifyChangeKey
255 | NtFreeVirtualMemory
256 | NtAlpcQueryInformation
257 | NtThawTransactions
258 | NtGetDevicePowerState
259 | NtCancelTimer2
260 | NtGetMUIRegistryInfo
261 | NtCallbackReturn
262 | NtAddBootEntry
263 | NtfsStructLock
264 | NtWaitForMultipleObjects32
265 | NtQueryMutant
266 | NtAssociateWaitCompletionPacket
267 | NtConnectPort
268 | NtPulseEvent
269 | NtOpenSymbolicLinkObject
270 | NtOpenSemaphore
271 | NtSetEventBoostPriority
272 | NtSetInformationVirtualMemory
273 | NtSetLowWaitHighEventPair
274 | NtResetWriteWatch
275 | NtSystemDebugControl
276 | NtAlpcQueryInformationMessage
277 | NtAdjustTokenClaimsAndDeviceGroups
278 | NtWriteFileGather
279 | NtQueryAttributesFile
280 | NtFlushVirtualMemory
281 | NtCreateKeyTransacted
282 | NtAccessCheckByType
283 | NtDuplicateObject
284 | NtImpersonateClientOfPort
285 | NtQuerySystemTime
286 | NtOpenKeyTransacted
287 | NtRestoreKey
288 | NtOpenThreadTokenEx
289 | NtAdjustGroupsToken
290 | NtQueryFullAttributesFile
291 | NtdllExportInformation
292 | NtRequestPort
293 | NtModifyBootEntry
294 | NtCreateWaitCompletionPacket
295 | NtRegisterThreadTerminatePort
296 | NtAdjustPrivilegesToken
297 | NtReplyPort
298 | NtAlpcDisconnectPort
299 | NtGetNextProcess
300 | NtCreateKeyTransacted_Stub
301 | NtAssignProcessToJobObject
302 | NtRecoverTransactionManager
303 | NtAlpcSetInformation
304 | NtTraceControl
305 | NtTranslateFilePath
306 | NtAlpcOpenSenderProcess
307 | NtOpenSection
308 | NtQueryInformationFile
309 | NtSetDriverEntryOrder
310 | NtCreateSemaphore
311 | NtAlpcConnectPortEx
312 | NtQueryInstallUILanguage
313 | NtQuerySystemInformation
314 | NtQueryOpenSubKeysEx
315 | NtQueueApcThread
316 | NtCancelTimer
317 | NtEnumerateBootEntries
318 | NtWaitForMultipleObjects
319 | NtQueryPerformanceCounter
320 | NtLockVirtualMemory
321 | NtPrePrepareEnlistment
322 | NtCommitComplete
323 | NtInitializeNlsFiles
324 | NtWorkerFactoryWorkerReady
325 | NtCreateLowBoxToken
326 | NtQuerySymbolicLinkObject
327 | NtUnloadKey2
328 | NtLockProductActivationKeys
329 | NtSetInformationTransaction
330 | NtOpenKeyedEvent
331 | NtQuerySection
332 | NtOpenKey
333 | NtQueryEvent
334 | NtLoadKeyEx
335 | NtSetInformationDebugObject
336 | NtEnumerateSystemEnvironmentValuesEx
337 | NtAlpcCreateSecurityContext
338 | NtQueryOpenSubKeys
339 | NtDebugContinue
340 | NtQueryDriverEntryOrder
341 | NtSetInformationTransactionManager
342 | NtQueryBootEntryOrder
343 | NtPrivilegedServiceAuditAlarm
344 | NtMapUserPhysicalPagesScatter
345 | NtSetLowEventPair
346 | NtOpenThread
347 | NtFilterToken
348 | NtSetHighWaitLowEventPair
349 | NtPlugPlayGetDeviceInterfaceEnabled
350 | NtAccessCheckByTypeResultListAndAuditAlarm
351 | NtSetLdtEntries
352 | NtAlpcDeleteSectionView
353 | NtAlertThreadByThreadId
354 | NtDeleteDriverEntry
355 | NtFlushKey
356 | NtDisplayString
357 | NtGetCurrentProcessorNumber
358 | NtQueryVolumeInformationFile
359 | NtReadOnlyEnlistment
360 | NtLoadKey2
361 | NtUnlockVirtualMemory
362 | NtCreateDirectoryObjectEx
363 | NtReleaseMutant
364 | NtRecoverResourceManager
365 | NtCloseObjectAuditAlarm
366 | NtAllocateUuids
367 | NtUnloadKeyEx
368 | NtResetEvent
369 | NtResumeProcess
370 | NtSetTimer
371 | NtEnumerateValueKey
372 | NtQueryTimerResolution
373 | NtFreezeTransactions
374 | NtSetTimer2
375 | NtReadFileScatter
376 | NtSetSystemPowerState
377 | NtShutdownSystem
378 | NtCreateJobObject
379 | NtGetNextThread
380 | NtFreeUserPhysicalPages
381 | NtUnlockFile
382 | NtStartProfile
383 | NtAlpcSendWaitReceivePort
384 | NtAreMappedFilesTheSame
385 | NtAccessCheckByTypeAndAuditAlarm
386 | NtReadVirtualMemory
387 | NtAddAtomEx
388 | NtQueryDefaultUILanguage
389 | NtTestAlert
390 | NtSignalAndWaitForSingleObject
391 | NtVdmControl
392 | NtRemoveIoCompletionEx
393 | NtSetTimerEx
394 | NtOpenSession
395 | NtCancelSynchronousIoFile
396 | NtQueryDirectoryObject
397 | NtQueryEnvironmentVariableInfoEx
398 | NtSerializeBoot
399 | NtOpenResourceManager
400 | NtExtendSection
401 | NtMakeTemporaryObject
402 | NtCreateMutant
403 | NtSetInformationResourceManager
404 | NtWriteFile
405 | NtAlpcConnectPort
406 | NtSetDefaultLocale
407 | NtEnumerateTransactionObject
408 | NtOpenKeyEx
409 | NtNotifyChangeMultipleKeys
410 | NtRaiseHardError
411 | NtGetEnvironmentVariableEx
412 | NtWaitForAlertByThreadId
413 | NtQueryInformationProcess
414 | NtOpenTransactionManager
415 | NtLoadKey
416 | NtDuplicateToken
417 | NtSetHighEventPair
418 | NtMapUserPhysicalPages
419 | NtCreateWorkerFactory
420 | NtSetInformationToken
421 | NtAlpcImpersonateClientOfPort
422 | NtWaitLowEventPair
423 | NtTraceEvent
424 | NtSetDefaultHardErrorPort
425 | NtQueryInformationToken
426 | NtCreateIoCompletion
427 | NtSetInformationThread
428 | NtNotifyChangeDirectoryFile
429 | NtOpenEnlistment
430 | NtOpenProcessTokenEx
431 | NtUnmapViewOfSection
432 | NtReleaseWorkerFactoryWorker
433 | NtQueryInformationAtom
434 | NtAllocateReserveObject
435 | NtCreateProcess
436 | NtReplyWaitReplyPort
437 | NtNotifyChangeSession
438 | NtUnsubscribeWnfStateChange
439 | NtQueryInformationPort
440 | NtSetBootOptions
441 | NtReleaseKeyedEvent
442 | NtAlpcCreateSectionView
443 | NtQuerySecurityObject
444 | NtOpenThreadToken
445 | NtSetTimerResolution
446 | NtSetInformationEnlistment
447 | NtSetIRTimer
448 | NtOpenIoCompletion
449 | NtApphelpCacheControl
450 | NtReadFile
451 | NtQueryBootOptions
452 | NtInitializeRegistry
453 | NtOpenProcessToken
454 | NtEnumerateKey
455 | NtOpenJobObject
456 | xHalIommuInitialize
457 | NtWaitForWnfNotifications
458 | NtMajorVersion
459 | NtMinorVersion
460 | NtGetPlugPlayEvent
461 | NtCancelDeviceWakeupRequest
462 | NtRequestDeviceWakeup
463 | NtReleaseCMFViewOwnership
464 | NtAcquireCMFViewOwnership
465 | NtRequestWakeupLatency
466 |
--------------------------------------------------------------------------------
/SystemCallService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7D3C3B13-8911-48C6-9B42-95DE79B34716}
8 | WinExe
9 | Properties
10 | SystemCallService
11 | SystemCallService
12 | v4.5
13 | 512
14 | false
15 | publish\
16 | true
17 | Disk
18 | false
19 | Foreground
20 | 7
21 | Days
22 | false
23 | false
24 | true
25 | 1
26 | 2014.01.0.%2a
27 | false
28 | true
29 | true
30 | 30789494
31 |
32 |
33 | x64
34 | true
35 | full
36 | false
37 | bin\Debug\
38 | DEBUG;TRACE
39 | prompt
40 | 4
41 | false
42 |
43 |
44 | x64
45 | pdbonly
46 | true
47 | bin\Release\
48 | TRACE
49 | prompt
50 | 4
51 | true
52 |
53 |
54 | D30FE9BA74CC0F70A30EE2AA7208104008340109
55 |
56 |
57 | true
58 |
59 |
60 | true
61 |
62 |
63 | true
64 | bin\x64\Debug\
65 | DEBUG;TRACE
66 | full
67 | x64
68 | prompt
69 | MinimumRecommendedRules.ruleset
70 | true
71 |
72 |
73 | bin\x64\Release\
74 |
75 |
76 | false
77 | true
78 | pdbonly
79 | x64
80 | prompt
81 | MinimumRecommendedRules.ruleset
82 | true
83 | false
84 | 0
85 |
86 |
87 | true
88 | bin\x86\Debug\
89 | DEBUG;TRACE
90 | full
91 | x86
92 | prompt
93 | MinimumRecommendedRules.ruleset
94 | true
95 |
96 |
97 | bin\x86\Release\
98 | true
99 | 1
100 | pdbonly
101 | x86
102 | prompt
103 | MinimumRecommendedRules.ruleset
104 | true
105 | false
106 |
107 |
108 |
109 | Component
110 |
111 |
112 | ProjectInstaller.cs
113 |
114 |
115 | True
116 | True
117 | SystemCallServiceSettings.settings
118 |
119 |
120 |
121 | Component
122 |
123 |
124 | SystemCallService.cs
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | SettingsSingleFileGenerator
135 | SystemCallServiceSettings.Designer.cs
136 |
137 |
138 | PreserveNewest
139 |
140 |
141 | PreserveNewest
142 |
143 |
144 | PreserveNewest
145 |
146 |
147 | PreserveNewest
148 |
149 |
150 | PreserveNewest
151 |
152 |
153 | PreserveNewest
154 |
155 |
156 | PreserveNewest
157 |
158 |
159 | PreserveNewest
160 |
161 |
162 | PreserveNewest
163 |
164 |
165 | PreserveNewest
166 |
167 |
168 | PreserveNewest
169 |
170 |
171 | PreserveNewest
172 |
173 |
174 | PreserveNewest
175 |
176 |
177 | PreserveNewest
178 |
179 |
180 | PreserveNewest
181 |
182 |
183 | PreserveNewest
184 |
185 |
186 | PreserveNewest
187 |
188 |
189 | PreserveNewest
190 |
191 |
192 | PreserveNewest
193 |
194 |
195 | PreserveNewest
196 |
197 |
198 | PreserveNewest
199 |
200 |
201 | PreserveNewest
202 |
203 |
204 | PreserveNewest
205 |
206 |
207 | PreserveNewest
208 |
209 |
210 | PreserveNewest
211 |
212 |
213 |
214 |
215 | False
216 | Microsoft .NET Framework 4.5 %28x86 and x64%29
217 | true
218 |
219 |
220 | False
221 | .NET Framework 3.5 SP1 Client Profile
222 | false
223 |
224 |
225 | False
226 | .NET Framework 3.5 SP1
227 | false
228 |
229 |
230 |
231 |
232 | ProjectInstaller.cs
233 |
234 |
235 | SystemCallService.cs
236 |
237 |
238 |
239 |
240 | PreserveNewest
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 | packages\EntityFramework.6.1.2\lib\net45\EntityFramework.dll
249 | True
250 |
251 |
252 | packages\EntityFramework.6.1.2\lib\net45\EntityFramework.SqlServer.dll
253 | True
254 |
255 |
256 | packages\Microsoft.Diagnostics.Tracing.TraceEvent.1.0.29\lib\net40\Microsoft.Diagnostics.Tracing.TraceEvent.dll
257 | True
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 | packages\System.Data.SQLite.Core.1.0.96.0\lib\net45\System.Data.SQLite.dll
266 | True
267 |
268 |
269 | packages\System.Data.SQLite.EF6.1.0.96.0\lib\net45\System.Data.SQLite.EF6.dll
270 | True
271 |
272 |
273 | packages\System.Data.SQLite.Linq.1.0.96.0\lib\net45\System.Data.SQLite.Linq.dll
274 | True
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
286 |
287 |
288 |
289 |
296 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/SystemCallService.cs:
--------------------------------------------------------------------------------
1 | /* Copyright 2015 Ray Canzanese
2 | * email: rcanzanese@gmail.com
3 | * url: www.canzanese.com
4 | *
5 | * This file is part of SystemCallService.
6 | *
7 | * SystemCallService is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * SystemCallService is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with SystemCallService. If not, see .
19 | */
20 |
21 | // TODO items
22 | // - break more functions out of the main class
23 | // - figure out if there is a easy way to incorporate symbol lookup
24 |
25 |
26 | // NOTE: You must manually set / unset this variable for 32 / 64 bit builds
27 | //#define X86
28 |
29 |
30 | using System;
31 | using System.Collections.Generic;
32 | using System.Configuration;
33 | using System.Data.SQLite;
34 | using System.Diagnostics;
35 | using System.Globalization;
36 | using System.IO;
37 | using System.Linq;
38 | using System.Reflection;
39 | using System.Runtime.CompilerServices;
40 | using System.Runtime.InteropServices;
41 | using System.Security.Cryptography;
42 | using System.ServiceProcess;
43 | using System.Text;
44 | using System.Text.RegularExpressions;
45 | using System.Threading;
46 | using System.Timers;
47 | using Microsoft.Diagnostics.Tracing;
48 | using Microsoft.Diagnostics.Tracing.Parsers;
49 | using Microsoft.Diagnostics.Tracing.Parsers.Kernel;
50 | using Microsoft.Diagnostics.Tracing.Session;
51 |
52 | namespace SystemCallService
53 | {
54 | ///
55 | /// Class for the service, extends the base service class. No actual functionality is here other than handling requests.
56 | ///
57 | public partial class SystemCallService : ServiceBase
58 | {
59 | private Thread _thread; // Worker thread for running the service
60 | private SystemCallServiceLoop _scc; // System call counter object
61 | private bool _isRunning; // Keeps track of whether it is running to handle power events
62 |
63 | ///
64 | /// Initialization and establishes that the SCS handles power events
65 | ///
66 | public SystemCallService()
67 | {
68 | InitializeComponent();
69 | CanHandlePowerEvent = true;
70 | }
71 |
72 | ///
73 | /// Handles hibernation events.
74 | ///
75 | /// Powerstatus passed in by SC
76 | /// true
77 | protected override bool OnPowerEvent(PowerBroadcastStatus powerStatus)
78 | {
79 | EventLog.WriteEntry("Power Status Change -- " + powerStatus, EventLogEntryType.Warning);
80 |
81 | if (PowerBroadcastStatus.Suspend == powerStatus)
82 | {
83 | if (_isRunning)
84 | {
85 | EventLog.WriteEntry("Stopping for suspend.", EventLogEntryType.Warning);
86 | OnStop();
87 | }
88 | else
89 | {
90 | EventLog.WriteEntry("Tried suspending but it was already stopped.", EventLogEntryType.Warning);
91 | }
92 | }
93 |
94 | // Start on resume.
95 | else if (PowerBroadcastStatus.ResumeSuspend == powerStatus ||
96 | PowerBroadcastStatus.ResumeAutomatic == powerStatus)
97 | {
98 | if (_isRunning)
99 | {
100 | EventLog.WriteEntry("Tried resuming, but already running.", EventLogEntryType.Warning);
101 | }
102 | else
103 | {
104 | EventLog.WriteEntry("Resuming.", EventLogEntryType.Warning);
105 | OnStart(null);
106 | }
107 | }
108 | return true;
109 | }
110 |
111 |
112 | ///
113 | /// Called by SC when the service is started. Must return immediately.
114 | ///
115 | /// Passed by SC
116 | protected override void OnStart(string[] args)
117 | {
118 | _isRunning = true;
119 |
120 | // Sets the event log source so we can find us the in the application log
121 | EventLog.Source = "SystemCallService";
122 |
123 | // Starts the worker thread that actually performs all the useful tasks
124 | _thread = new Thread(WorkerThreadFunc)
125 | {
126 | Name = "Main SystemCallService Worker Thread",
127 | IsBackground = true
128 | };
129 | _thread.Start();
130 |
131 | // Prints the path to the local configuration to the app event log.
132 | EventLog.WriteEntry(
133 | "Local Configuration Location:" +
134 | ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath,
135 | EventLogEntryType.Information);
136 | }
137 |
138 | ///
139 | /// Called by SC when service is stopped
140 | ///
141 | protected override void OnStop()
142 | {
143 | _isRunning = false;
144 |
145 | // Signal the thread to stop collecting data
146 | _scc.Stop(true);
147 |
148 | // Give the thread 10 seconds to stop gracefully. It does a lot of processing, so we are conservative with this etimate for now.
149 | if (_thread.Join(10000)) return;
150 |
151 | EventLog.WriteEntry("Internal error Stopping Service", EventLogEntryType.Error);
152 | _thread.Abort();
153 | }
154 |
155 | ///
156 | /// Worker thread responsible for kicking off the data collection. Exits when the data collection is signalled by OnStop to stop.
157 | ///
158 | private void WorkerThreadFunc()
159 | {
160 | // Create a new SyscallCounter object with sampling periods from settings
161 | _scc = new SystemCallServiceLoop(EventLog);
162 |
163 | // Continuously restart the service until IsRunning is set to false
164 | while (_isRunning)
165 | {
166 | _scc.Start();
167 | }
168 | }
169 | }
170 |
171 | ///
172 | /// Put host, process, and thread metadata in a SQLite database
173 | ///
174 | public class DatabaseInterface
175 | {
176 | //EventLog object for logging to the Application Event Log
177 | private readonly StreamWriter _debugLog;
178 |
179 | // Database connection
180 | private readonly SQLiteConnection _connection;
181 |
182 | // Everything is in one transaction
183 | private SQLiteTransaction _transaction;
184 |
185 | // Queries for adding processes and threads and a list of the column titles to expedite the query building.
186 | private readonly SQLiteCommand _processAdd;
187 | private readonly List _processColumns;
188 | private readonly SQLiteCommand _threadAdd;
189 | private readonly List _threadColumns;
190 | private readonly SQLiteCommand _processEnd;
191 | private readonly SQLiteCommand _threadEnd;
192 |
193 | ///
194 | /// Constructor
195 | ///
196 | /// Absolute path to the database file
197 | /// Handle to debug log
198 | public DatabaseInterface(string path, StreamWriter debugLog)
199 | {
200 | _debugLog = debugLog;
201 |
202 | // Create file
203 | SQLiteConnection.CreateFile(path);
204 |
205 | //Connect and open handle
206 | _connection = new SQLiteConnection("Data Source=" + path + ";Version=3;");
207 | _connection.Open();
208 |
209 | _transaction = _connection.BeginTransaction();
210 |
211 | // Create table for processes
212 | using (SQLiteCommand genericCommand = _connection.CreateCommand())
213 | {
214 | // Create process Table
215 | genericCommand.CommandText = "CREATE TABLE Processes (" +
216 | Properties.SystemCallServiceSettings.Default.ProcessTableStructure + ")";
217 | genericCommand.ExecuteNonQuery();
218 | _processAdd = SetupObjectQuery(typeof (ProcessInfo), "Processes", out _processColumns);
219 |
220 | // Create table for threads
221 | genericCommand.CommandText = "CREATE TABLE Threads (" +
222 | Properties.SystemCallServiceSettings.Default.ThreadTableStructure + ")";
223 | genericCommand.ExecuteNonQuery();
224 | genericCommand.Dispose();
225 | }
226 |
227 | // Create command for thread and process endings
228 | _threadEnd = _connection.CreateCommand();
229 | _threadEnd.CommandText = "UPDATE threads SET StopRelativeMsec=@StopRelativeMsec WHERE Guid=@Guid";
230 | _threadEnd.Parameters.AddWithValue("@StopRelativeMsec", "");
231 | _threadEnd.Parameters.AddWithValue("@Guid", "");
232 |
233 | _processEnd = _connection.CreateCommand();
234 | _processEnd.CommandText = "UPDATE processes SET StopRelativeMsec=@StopRelativeMsec WHERE Guid=@Guid";
235 | _processEnd.Parameters.AddWithValue("@StopRelativeMsec", "");
236 | _processEnd.Parameters.AddWithValue("@Guid", "");
237 |
238 | _threadAdd = SetupObjectQuery(typeof (ThreadInfo), "Threads", out _threadColumns);
239 |
240 | // Commit all the table creations and starts a new transaction
241 | _transaction.Commit();
242 | _transaction.Dispose();
243 | _transaction = _connection.BeginTransaction();
244 | }
245 |
246 |
247 | ///
248 | /// Update the thread end time.
249 | ///
250 | /// end time in ms
251 | /// thread guid
252 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
253 | public void UpdateThreadEnd(double mSec, string guid)
254 | {
255 | _threadEnd.Parameters["@StopRelativeMsec"].Value = mSec;
256 | _threadEnd.Parameters["@Guid"].Value = guid;
257 | _threadEnd.ExecuteNonQuery();
258 | }
259 |
260 | ///
261 | /// Update the process end time.
262 | ///
263 | /// end time in ms
264 | /// process guid
265 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
266 | public void UpdateProcessEnd(double mSec, string guid)
267 | {
268 | _processEnd.Parameters["@StopRelativeMsec"].Value = mSec;
269 | _processEnd.Parameters["@Guid"].Value = guid;
270 | _processEnd.ExecuteNonQuery();
271 | }
272 |
273 | ///
274 | /// Construct a query to use for adding properties of an object to the database.
275 | ///
276 | /// The object type that will be added
277 | /// The name of the table
278 | /// Output the names of the columns so we don't have to look them up every time.
279 | /// The sqlite command
280 | public SQLiteCommand SetupObjectQuery(Type type, string table, out List columns)
281 | {
282 | columns = new List();
283 | foreach (var field in type.GetProperties())
284 | {
285 | if (!field.Name.Contains("Flag") && !field.Name.Contains("InsertCommand"))
286 | // I have flags in the data structures that are only used internally and not added to database
287 | {
288 | columns.Add(field.Name);
289 | }
290 | }
291 |
292 | SQLiteCommand command = _connection.CreateCommand();
293 | command.CommandText = "INSERT INTO " + table + "(" + String.Join(",", columns) + ") VALUES(@" +
294 | String.Join(",@", columns) + ")";
295 |
296 | foreach (var column in columns)
297 | {
298 | command.Parameters.AddWithValue("@" + column, "");
299 | }
300 |
301 | return command;
302 | }
303 |
304 | ///
305 | /// Add the properties of an object as a new entry into the table.
306 | ///
307 | /// The object containing data to add
308 | /// The name of the table
309 | /// The command prepared by SetupObjectQuery
310 | /// The name of the columns prepared by SetupObjectQuery
311 | /// True
312 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
313 | public bool AddObject(Object data, string table, SQLiteCommand command, List columns)
314 | {
315 | foreach (var column in columns)
316 | {
317 | command.Parameters["@" + column].Value = data.GetType().GetProperty(column).GetValue(data, null);
318 | }
319 | command.ExecuteNonQuery();
320 | return true;
321 | }
322 |
323 | ///
324 | /// Add a thread to the thread table.
325 | ///
326 | ///
327 | ///
328 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
329 | public bool AddThread(ThreadInfo thread)
330 | {
331 | AddObject(thread, "Threads", _threadAdd, _threadColumns);
332 | return true;
333 | }
334 |
335 | ///
336 | /// Add a process to the process table.
337 | ///
338 | ///
339 | ///
340 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
341 | public bool AddProcess(ProcessInfo process)
342 | {
343 | AddObject(process, "Processes", _processAdd, _processColumns);
344 | return true;
345 | }
346 |
347 | ///
348 | /// Add system information
349 | ///
350 | /// System information structure
351 | ///
352 | public bool AddSystemInformation(SystemInformation sysinfo)
353 | {
354 | using (var localCommand = _connection.CreateCommand())
355 | {
356 | //Create table
357 | localCommand.CommandText = "CREATE TABLE SystemInfo (" +
358 | Properties.SystemCallServiceSettings.Default.SystemInfoTableStructure + ")";
359 | localCommand.ExecuteNonQuery();
360 |
361 | // Setup Query
362 | List systemInfoColumns;
363 | SQLiteCommand systemInfoAdd = SetupObjectQuery(typeof (SystemInformation), "SystemInfo",
364 | out systemInfoColumns);
365 |
366 | // Execute query
367 | AddObject(sysinfo, "SystemInfo", systemInfoAdd, systemInfoColumns);
368 | }
369 | return true;
370 | }
371 |
372 |
373 | ///
374 | /// Commit the current transaction and create a new one.
375 | ///
376 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
377 | public void Commit()
378 | {
379 | try
380 | {
381 | _transaction.Commit();
382 | _transaction.Dispose();
383 | _transaction = _connection.BeginTransaction();
384 | }
385 | catch (Exception e)
386 | {
387 | _debugLog.WriteLine("Commit error: " + e);
388 | }
389 | }
390 |
391 | ///
392 | /// Commit transaction, dispose all commands, and close the connection to the database
393 | ///
394 | public void CloseConnection()
395 | {
396 | Commit();
397 |
398 | _processAdd.Dispose();
399 | _threadAdd.Dispose();
400 | _processEnd.Dispose();
401 | _threadEnd.Dispose();
402 |
403 | try
404 | {
405 | _transaction.Dispose();
406 | }
407 | catch (Exception e)
408 | {
409 | _debugLog.WriteLine("CloseError: " + e);
410 | }
411 | try
412 | {
413 | _connection.Close();
414 | _connection.Dispose();
415 | }
416 | catch (Exception e)
417 | {
418 | _debugLog.WriteLine("CloseError: " + e);
419 | }
420 | }
421 | }
422 |
423 | ///
424 | /// Generic class for storing information about a process or thread
425 | ///
426 | public class Info
427 | {
428 | public String Guid { get; set; } // GUID to identify the data table.
429 | public double DeletionFlag; // Indicates when object was flagged for deletion
430 | public bool Deleted; // Indicates that that it has been deleted
431 | public double StartRelativeMSec { get; set; } // Time the process started as RelativeMSec count
432 | public DateTime Start { get; set; } // Time the process was started
433 | public double StopRelativeMSec { get; set; } // Time the process started as RelativeMSec count
434 | public SystemCallTracer Counter; // Where the tracing and counting occurs
435 | }
436 |
437 | ///
438 | /// Information about active processes
439 | ///
440 | public class ProcessInfo : Info
441 | {
442 | public string Name; // Just the executable name
443 | public int Pid { get; set; }
444 | public long ProcessKey; // I don't know whether this is unique -- currently unused
445 | public string CommandLine { get; set; } // Full path used to launch the process
446 | public string ImageFileName { get; set; } // Same as executable name?
447 | public string KernelImageFileName; // Same as executable name?
448 | public int ParentId { get; set; } // Parent PID
449 | public uint TotalThreads; // Total number of child threads
450 | public uint ActiveThreads; // Number of threads currently executing
451 | public double LastActive; // Time it was last CSWITCHED off a core.
452 | public string Md5 { get; set; }
453 | }
454 |
455 | ///
456 | /// Information about the host
457 | ///
458 | public class SystemInformation
459 | {
460 | public string NtoskrnlVersion { get; set; } // ntoskrnl.exe file version
461 | public string NtoskrnlMd5 { get; set; } // ntoskrnl.exe file version
462 | public int Cores { get; set; } // Number of logical processor cores
463 | public string Hostname { get; set; } // hostname
464 | public double HostSampling { get; set; } // System sampling period
465 | public double ProcessSampling { get; set; } // Process sampling period
466 | public double ThreadSampling { get; set; } // Thread Sampling period
467 | public long HostTrace { get; set; } // System sampling period
468 | public long ProcessTrace { get; set; } // Process sampling period
469 | public long ThreadTrace { get; set; } // Thread Sampling period
470 | }
471 |
472 | ///
473 | /// Information about active threads
474 | ///
475 | public class ThreadInfo : Info
476 | {
477 | public int Pid { get; set; } // PID to which the thread belongs
478 | public double PidStartRelativeMSec { get; set; } // Process start time as RelativeMSec
479 | public int Tid { get; set; }
480 | public String ProcessGuid { get; set; } // Process GUID so we can do joins
481 | public double LastActive; // Last time it was CSWITCHed out
482 | public bool IsActive; // Whether it is currently active on a core
483 | }
484 |
485 | ///
486 | /// Perform system call traces at the host, process, and thread levels
487 | ///
488 | public class SystemCallTracer
489 | {
490 | private readonly string _filename;
491 |
492 | // TODO: Implement these or remove them.
493 | private double _startTimeMs;
494 | private StreamWriter _debugLog;
495 |
496 | // For saving raw traces
497 | private long _maxTrace = -1;
498 | private FileStream _traceOutputFile;
499 | private BinaryWriter _traceWriter;
500 | private bool _fullTrace;
501 | private long _traceLength;
502 | private bool _traceFinished = true;
503 |
504 | ///
505 | /// Create the tracer.
506 | ///
507 | /// Filename to store the trace
508 | /// Debug logger
509 | public SystemCallTracer(string filename, StreamWriter debugLog)
510 | {
511 | _filename = filename;
512 | _debugLog = debugLog;
513 | }
514 |
515 |
516 |
517 | ///
518 | /// Initialize a trace
519 | ///
520 | /// Maximum number of system calls. Negative number indicates no limit.
521 | /// Start time of trace in ms.
522 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
523 | public void InitializeFullTrace(long maxTrace, double timeMs)
524 | {
525 | _traceOutputFile = File.Open(_filename + "_trace", FileMode.Create);
526 | _traceWriter = new BinaryWriter(_traceOutputFile);
527 | _maxTrace = maxTrace;
528 | _traceFinished = false;
529 | _fullTrace = true;
530 | _startTimeMs = timeMs;
531 | }
532 |
533 | ///
534 | /// Add a system call to the trace
535 | ///
536 | /// system call index
537 | /// time of the call
538 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
539 | public void Add(ushort syscall, double timeMs)
540 | {
541 | if (!_fullTrace) return;
542 |
543 | if (_maxTrace >= 0 && _traceLength >= _maxTrace)
544 | {
545 | if (_traceFinished) return;
546 | _traceFinished = true;
547 | _traceWriter.Flush();
548 | _traceWriter.Close();
549 | _traceOutputFile.Close();
550 | //DebugLog.WriteLine("TOTAL_TRACE_TIME=" + (time - StartTimeMs));
551 | return;
552 | }
553 | _traceWriter.Write(syscall);
554 | _traceLength += 1;
555 | }
556 |
557 | ///
558 | /// End the trace and close the file.
559 | ///
560 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
561 | public void Close()
562 | {
563 | if (_traceFinished) return;
564 | _traceFinished = true;
565 | _traceWriter.Flush();
566 | _traceWriter.Close();
567 | _traceOutputFile.Close();
568 | }
569 | }
570 |
571 | ///
572 | /// Service loop and primary interface with ETW
573 | ///
574 | public class SystemCallServiceLoop
575 | {
576 | // Regex for sanitizing the command line -- either it is quoted, contains spaces and ends with exe, or contains no spaces. This covers all cases seen on the development machine.
577 | private readonly Regex _pathRegex = new Regex("(\"[^\"]*\"|.*?\\.exe|[^ ]*)");
578 |
579 | // List of settings we want to print out in debug log / get from web
580 | private readonly string[] _properties =
581 | {
582 | "AutoResetMs", "TracePerProcess", "TracePerThread", "MaxTraceSyscalls",
583 | "Verbosity", "ScrubCommandLine", "AnonymizeHostname"
584 | };
585 |
586 | // Private copies of settings for speed. I don't know whether these are actually faster.
587 | private readonly bool _traceHostLevel = Properties.SystemCallServiceSettings.Default.TraceHostLevel;
588 | private readonly bool _tracePerThread = Properties.SystemCallServiceSettings.Default.TracePerThread;
589 | private readonly bool _tracePerProcess = Properties.SystemCallServiceSettings.Default.TracePerProcess;
590 | private readonly long _maxTraceSyscalls = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls;
591 | private readonly int _verbosity = Properties.SystemCallServiceSettings.Default.Verbosity;
592 | private readonly double _commitInterval = Properties.SystemCallServiceSettings.Default.CommitInterval;
593 | private readonly bool _scrubCommandLine = Properties.SystemCallServiceSettings.Default.ScrubCommandLine;
594 | private readonly string _dataDirectory = Properties.SystemCallServiceSettings.Default.DataDirectory;
595 | private readonly double _processDeletionDelay = Properties.SystemCallServiceSettings.Default.ProcessDeletionDelay; //ms
596 | private readonly double _minBackoff = Properties.SystemCallServiceSettings.Default.MinBackoff;
597 | private double _threadDeletionDelay = Properties.SystemCallServiceSettings.Default.ThreadDeletionDelay; //ms
598 |
599 | // Counting system call tuples
600 | private SystemCallTracer _systemWideCounter;
601 |
602 | // System call list
603 | private List _syscallNameList;
604 |
605 | //Code profiling
606 | private readonly bool _profileCode = Properties.SystemCallServiceSettings.Default.ProfileCode;
607 | private readonly Dictionary _codeProfileTimers = new Dictionary();
608 | private readonly Dictionary _codeProfileCounters = new Dictionary();
609 |
610 | private readonly string[] _codeProfileKeys =
611 | {
612 | "Commit", "Syscall", "ProcessStartTable", "WriteProcessData", "ProcessDeletionQueue", "ThreadDeletionQueue",
613 | "ContextSwitch", "ContextSwitch1", "ContextSwitch2", "ContextSwitch3", "Database.Commit",
614 | "WriteProcessDataInsert", "CreateTable", "WriteSystemData", "ProcessStart", "ProcessStop", "ThreadStart",
615 | "ThreadStop", "CreateCommand", "InsertCommandClone", "InsertCommandNew"
616 | };
617 |
618 | // Last time we checked for thread and process deletion
619 | private double _lastDeletionCheck;
620 |
621 | // System information
622 | private SystemInformation _systemInfo;
623 |
624 | // End service flag
625 | private bool _endService;
626 |
627 | // Timer to trigger automatic restarts
628 | private readonly System.Timers.Timer _resetTimer;
629 |
630 | // Database connection
631 | private DatabaseInterface _database;
632 |
633 | // For timing the code
634 | private readonly Stopwatch _timer = new Stopwatch(); // Keeps track of processing lag.
635 |
636 | // For keeping track of how much time each thread has been active since last cswitch
637 | private double[] _lastCSwitch;
638 |
639 | // Dict for active threads, indexed by PID then TID
640 | private class ThreadDict : Dictionary{}
641 | private class ProcessThreadDict : Dictionary{};
642 |
643 | //Queue for creating tables
644 | private readonly Queue _tableCreations = new Queue();
645 |
646 | // Queue for deleting processes and threads
647 | private readonly List _processesToDelete = new List();
648 | private readonly List _threadsToDelete = new List();
649 |
650 | // A Dictionary of active threads by process [PID][TID]
651 | private readonly ProcessThreadDict _activeThreadsByProcess = new ProcessThreadDict();
652 |
653 | // Dict for unknown threads, indexed by TID
654 | private readonly ThreadDict _unkownThreads = new ThreadDict();
655 |
656 | // Dict for active processes, indexed by PID
657 | private readonly Dictionary _activeProcesses = new Dictionary();
658 |
659 | //EventLog object for logging to the Application Event Log
660 | private readonly EventLog _eventLog;
661 |
662 | // Data directory location, used for generating paths to various files
663 | private readonly string _rootPath;
664 | private readonly string _tempPath;
665 | private string _dataSubFolder;
666 |
667 | // Maps from the addresses to some set of integers so we can do array indexing quickly and easily
668 | private int[] _ntMap;
669 | private ulong _ntLowestAddress;
670 | private ulong _ntMaxAddress;
671 |
672 | // Number of logical processors
673 | private int _logicalProcessorCount;
674 |
675 | // File to store all of our debug messages
676 | private StreamWriter _debugLog;
677 |
678 | // Event tracing session
679 | private TraceEventSession _eventTracingSession;
680 |
681 | // Place to keep track of what process and thread on each processor core
682 | private int[] _processorActiveThreads;
683 | private int[] _processorActiveProcesses;
684 |
685 | // Default values for processors. Used for convenience
686 | private const int DefaultProcessorValue = -2;
687 | private const int UnknownPid = -1;
688 | private const int IdlePid = 0;
689 |
690 | // Address of the Kenrel
691 | private UInt64 _ntKernelAddress;
692 | private String _ntKernelImageName;
693 |
694 | // Track the last time the database changes were committed
695 | private double _lastCommit = -100;
696 |
697 | // DLL imports for the functions that we use to get the base addresses of the kernel modules.
698 | // The precompiler directives handle the 32 bit vs. 64 distinction
699 | [DllImport("psapi")]
700 | private static extern bool EnumDeviceDrivers(
701 | #if X86
702 | [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] UInt32[] ddAddresses,
703 | #else
704 | [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In] [Out] UInt64[] ddAddresses,
705 | #endif
706 | UInt32 arraySizeBytes,
707 | [MarshalAs(UnmanagedType.U4)] out UInt32 bytesNeeded
708 | );
709 |
710 | [DllImport("psapi")]
711 | private static extern int GetDeviceDriverBaseName(
712 | #if X86
713 | UInt32 ddAddress,
714 | #else
715 | UInt64 ddAddress,
716 | #endif
717 | StringBuilder ddBaseName,
718 | int baseNameStringSizeChars
719 | );
720 |
721 | ///
722 | /// Set the tracer parameters.
723 | ///
724 | /// EventLog object
725 | public SystemCallServiceLoop(EventLog el)
726 | {
727 | // Keep an instance variable of the event log -- used for crash logging
728 | _eventLog = el;
729 |
730 | // Keep track of where this is executing from and where we store the data
731 | _rootPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
732 | _tempPath = Path.GetTempPath();
733 |
734 | // Setup a timer to automatically restart logging
735 | _resetTimer = new System.Timers.Timer {AutoReset = false};
736 | _resetTimer.Elapsed += ResetTimerEvent;
737 | }
738 |
739 | ///
740 | /// Compute the MD5 of the kernel.
741 | ///
742 | /// Filename of kernel (varies for different versions of wWndows).
743 | ///
744 | private string ComputeMd5(string kernelFileName)
745 | {
746 | string md5Sum;
747 |
748 | // Debug print MD5sum of the kernel
749 | using (var md5 = MD5.Create())
750 | {
751 | using (
752 | var stream =
753 | File.OpenRead(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
754 | kernelFileName)))
755 | {
756 | md5Sum = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
757 | }
758 | }
759 | return md5Sum;
760 | }
761 |
762 | ///
763 | /// Load the system call addresses.
764 | ///
765 | /// Filename of the kernel
766 | /// Kernel version
767 | /// Filename that lists desired system calls to trace
768 | /// List of the system calls (out)
769 | /// Base address of kernel (out)
770 | /// Max address of system call (out)
771 | /// Used as offset for GDI tracing to prevent index collisions with multiple kernel files.
772 | /// Base address of the kernel.
773 | /// The map from addresses to indices
774 | private int[] LoadAddressMaps(String kernelFileName, String version, String sensorFileName,
775 | out List sensorList, out ulong baseAddress, out ulong maxAddress, int indexBase, ulong kernelBase)
776 | {
777 | // Load the symbol table and build a dict, where the sensor names are the keys
778 | string[] lines;
779 | string md5Sum = ComputeMd5(kernelFileName);
780 | _debugLog.WriteLine("KERNEL MD5: " + md5Sum);
781 |
782 | // This is an abuse of naming, but because they are identified by version and MD5, I am not going to differentiate among different kernel image file names
783 | string subdirectory = "ntoskrnl.exe";
784 | string localFilename = Path.Combine(_rootPath, Properties.SystemCallServiceSettings.Default.SymbolSubfolder,
785 | subdirectory, version + "_" + md5Sum + ".symbols");
786 |
787 | try
788 | {
789 | lines = File.ReadAllLines(localFilename);
790 | }
791 | catch
792 | {
793 | _debugLog.WriteLine("Kernel symbols not held locally. Checking online");
794 | _debugLog.WriteLine("NtVersion: " + _systemInfo.NtoskrnlVersion);
795 | _debugLog.WriteLine("Local Filename: " + localFilename);
796 | _debugLog.Flush();
797 |
798 | File.Copy(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), kernelFileName),
799 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory,
800 | _dataSubFolder, version + "_" + md5Sum + ".binary"));
801 | maxAddress = 0;
802 | baseAddress = 0;
803 | sensorList = null;
804 | return null;
805 | }
806 |
807 | Dictionary symbolTable = new Dictionary();
808 |
809 | // First group is the address, second group is the name;
810 | Regex re = new Regex(@"[ ]+[0-9a-f]+[ ]+([0-9a-f]+)[ ]+:+[ ]+(.*)");
811 |
812 | foreach (string line in lines)
813 | {
814 | Match match = re.Match(line);
815 |
816 | if (match.Success)
817 | {
818 | symbolTable[match.Groups[2].Value] = UInt64.Parse(match.Groups[1].Value, NumberStyles.HexNumber) -
819 | UInt64.Parse("1000000", NumberStyles.HexNumber);
820 | // corrects dbh.exe offset default.
821 | }
822 | }
823 |
824 | // Load the sensor list to figure out the offsets
825 | lines = File.ReadAllLines(Path.Combine(_rootPath, sensorFileName));
826 |
827 | // Creates a list of the sensor names as a list of strings and the map from the addresses to the indices
828 | sensorList = new List();
829 |
830 | List temp = new List();
831 |
832 | // Convert the list of addresses to a map.
833 | foreach (string line in lines)
834 | {
835 | sensorList.Add(line);
836 | try
837 | {
838 | var offset = symbolTable[line];
839 | temp.Add(offset);
840 | }
841 | catch
842 | {
843 | _debugLog.WriteLine("Sensor not found in symbol table: " + line);
844 | }
845 | }
846 |
847 | baseAddress = temp.Min() + kernelBase;
848 | maxAddress = temp.Max() + kernelBase;
849 | int[] sensorMap = new int[1 + (temp.Max() - temp.Min())];
850 |
851 | for (int i = 0; i < sensorMap.Count(); i++)
852 | {
853 | sensorMap[i] = -1;
854 | }
855 |
856 | for (int i = 0; i < temp.Count; i++)
857 | {
858 | sensorMap[(temp[i] - temp.Min())] = i + indexBase;
859 | }
860 |
861 | // Debugging information
862 | _debugLog.WriteLine("Base: {0:X}", kernelBase);
863 | _debugLog.WriteLine("Min: {0:X}", temp.Min());
864 | _debugLog.WriteLine("Max: {0:X}", temp.Max());
865 | _debugLog.WriteLine("baseAddress: {0:X}", baseAddress);
866 | _debugLog.WriteLine("maxAddress: {0:X}", maxAddress);
867 |
868 | return sensorMap;
869 | }
870 |
871 | ///
872 | /// Get the hostname or the anonymized identifier.
873 | ///
874 | /// hostname or anonymized identifier
875 | private string GetHostname()
876 | {
877 | string hostname;
878 | if (Properties.SystemCallServiceSettings.Default.AnonymizeHostname)
879 | {
880 | if (Properties.SystemCallServiceSettings.Default.HostIdentifier == "None")
881 | {
882 | Properties.SystemCallServiceSettings.Default.HostIdentifier = Path.GetRandomFileName();
883 | Properties.SystemCallServiceSettings.Default.Save();
884 | }
885 | hostname = Properties.SystemCallServiceSettings.Default.HostIdentifier;
886 | }
887 | else
888 | {
889 | hostname = Environment.MachineName;
890 | }
891 | return hostname;
892 | }
893 |
894 |
895 | ///
896 | /// Ges system information and save it in the database
897 | ///
898 | private void GetSystemInformation()
899 | {
900 | // Anonymize the hostname (if necessary) by generating random string instead and saving it in properties
901 | string hostname = GetHostname();
902 |
903 |
904 | // Creates object to hold system info and populates it
905 | _systemInfo = new SystemInformation
906 | {
907 | Cores = Environment.ProcessorCount,
908 | NtoskrnlVersion =
909 | FileVersionInfo.GetVersionInfo(
910 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), _ntKernelImageName))
911 | .ProductVersion,
912 | NtoskrnlMd5 = ComputeMd5(_ntKernelImageName),
913 | Hostname = hostname,
914 | ThreadSampling = 0,
915 | ProcessSampling = 0,
916 | HostSampling = 0,
917 | ThreadTrace = 0,
918 | ProcessTrace = 0,
919 | HostTrace = 0
920 | };
921 |
922 | if (Properties.SystemCallServiceSettings.Default.TracePerThread)
923 | {
924 | _systemInfo.ThreadTrace = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls;
925 | }
926 | if (Properties.SystemCallServiceSettings.Default.TracePerProcess)
927 | {
928 | _systemInfo.ProcessTrace = Properties.SystemCallServiceSettings.Default.MaxTraceSyscalls;
929 | }
930 | if (Properties.SystemCallServiceSettings.Default.TraceHostLevel)
931 | {
932 | _systemInfo.HostTrace = 1;
933 | }
934 |
935 | // Save logical processor count because we use it during tracing
936 | _logicalProcessorCount = _systemInfo.Cores;
937 |
938 | // Add to database
939 | _database.AddSystemInformation(_systemInfo);
940 | }
941 |
942 |
943 | ///
944 | /// Wrapper for regular starts.
945 | ///
946 | /// data from trace event
947 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
948 | private void ProcessStart(TraceEvent data)
949 | {
950 | ProcessStartHelper(data, false);
951 | }
952 |
953 | ///
954 | /// Wrapper for dc starts.
955 | ///
956 | /// data from trace event
957 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
958 | private void ProcessDcStart(TraceEvent data)
959 | {
960 | ProcessStartHelper(data, true);
961 | }
962 |
963 | ///
964 | /// Get the full path of anexecutable image.
965 | ///
966 | ///
967 | /// the path
968 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
969 | public static string GetFullPath(string fileName)
970 | {
971 | // Trim surrounding quotes
972 | string path = fileName.Trim('\"');
973 |
974 | // If it already exists, just return it.
975 | if (File.Exists(path))
976 | return Path.GetFullPath(path);
977 |
978 | // If there isn't a dot, try adding an extension
979 | if (!path.Contains('.'))
980 | {
981 | path = path + ".exe";
982 | if (File.Exists(path))
983 | return Path.GetFullPath(path);
984 | }
985 |
986 | // If there is a %, try expanding environment variables
987 | // If there isn't a dot, try adding an extension
988 | if (path.Contains('%'))
989 | {
990 | path = Environment.ExpandEnvironmentVariables(path);
991 | if (File.Exists(path))
992 | return Path.GetFullPath(path);
993 | }
994 |
995 | // This appears at the beginning of some strings
996 | if (path.Contains(@"\??\"))
997 | {
998 | path = path.Replace(@"\??\", "");
999 | if (File.Exists(path))
1000 | return Path.GetFullPath(path);
1001 | }
1002 |
1003 | // If there aren't any slashes, check the environment PATH
1004 | if (!path.Contains(@"\"))
1005 | {
1006 | var values = Environment.GetEnvironmentVariable("PATH");
1007 | if (values == null) return null;
1008 | foreach (var t in values.Split(';'))
1009 | {
1010 | var fullPath = Path.Combine(t, fileName);
1011 | if (File.Exists(fullPath))
1012 | return fullPath;
1013 | }
1014 | }
1015 |
1016 | return null;
1017 | }
1018 |
1019 |
1020 | ///
1021 | /// When a process starts, add the process and the information about the process to the active processes dict and create a dict of threads for the process
1022 | ///
1023 | /// The trace event data
1024 | /// True if a DC start
1025 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1026 | private void ProcessStartHelper(TraceEvent data, bool dcStart)
1027 | {
1028 | if (_profileCode)
1029 | {
1030 | _codeProfileCounters["ProcessStart"] += 1;
1031 | _codeProfileTimers["ProcessStart"].Start();
1032 | }
1033 |
1034 | ProcessTraceData procData = (ProcessTraceData) data;
1035 |
1036 | // We don't care about the system idle service. We know it is there and that it does nothing.
1037 | if (procData.ProcessID == IdlePid)
1038 | {
1039 | if (_profileCode)
1040 | {
1041 | _codeProfileTimers["ProcessStart"].Stop();
1042 | }
1043 | return;
1044 | }
1045 |
1046 | // Scrub command line -- take away the arguments
1047 | String commandLine;
1048 | String scrubbedCommandLine;
1049 | Match m = _pathRegex.Match(procData.CommandLine);
1050 | if (m.Success)
1051 | {
1052 | scrubbedCommandLine = m.Value;
1053 | }
1054 | else
1055 | {
1056 | scrubbedCommandLine = "";
1057 | }
1058 |
1059 | if (_scrubCommandLine)
1060 | {
1061 | commandLine = scrubbedCommandLine;
1062 | }
1063 | else
1064 | {
1065 | commandLine = procData.CommandLine;
1066 | }
1067 |
1068 | // checksum the image if possible. Checks existence first to avoid unnecessary error handling overhead.
1069 | string md5Sum = "";
1070 | if (!dcStart)
1071 | {
1072 | try
1073 | {
1074 | string actualPath = GetFullPath(scrubbedCommandLine);
1075 |
1076 | if (actualPath != null)
1077 | {
1078 | using (
1079 | FileStream fs = new FileStream(actualPath, FileMode.Open, FileAccess.Read,
1080 | FileShare.ReadWrite))
1081 | {
1082 | using (MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider())
1083 | {
1084 | byte[] hash = md5.ComputeHash(fs);
1085 | StringBuilder buf = new StringBuilder(2*hash.Length);
1086 | foreach (byte b in hash)
1087 | {
1088 | buf.AppendFormat("{0:X2}", b);
1089 | }
1090 | md5Sum = buf.ToString();
1091 | }
1092 | }
1093 | }
1094 | }
1095 | catch (Exception e)
1096 | {
1097 | _debugLog.WriteLine("ERROR on " + scrubbedCommandLine);
1098 | _debugLog.WriteLine(e);
1099 | }
1100 | }
1101 |
1102 | //Create the process info struct
1103 | ProcessInfo newProcess = new ProcessInfo
1104 | {
1105 | Name = data.ProcessName,
1106 | Pid = data.ProcessID,
1107 | ProcessKey = (long) procData.UniqueProcessKey,
1108 | CommandLine = commandLine,
1109 | ImageFileName = procData.ImageFileName,
1110 | KernelImageFileName = procData.KernelImageFileName,
1111 | ParentId = procData.ParentID,
1112 | Start = data.TimeStamp,
1113 | StartRelativeMSec = data.TimeStampRelativeMSec,
1114 | Guid = Guid.NewGuid().ToString("N"),
1115 | Counter = null,
1116 | Md5 = md5Sum
1117 | };
1118 |
1119 | // Write a debug message indicating that a new process started
1120 | if (_verbosity >= 3)
1121 | {
1122 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1123 | data.TimeStampRelativeMSec + " " + "Process Start:" + newProcess.Name +
1124 | " " + newProcess.CommandLine + " " + newProcess.Pid);
1125 | }
1126 |
1127 | // If we already Have the PID in the active process lists but it has been marked for deletion, lets try to force the deletion.
1128 | if (_activeProcesses.ContainsKey(data.ProcessID))
1129 | {
1130 | if (_verbosity >= 1)
1131 | {
1132 | _debugLog.WriteLine("WARNING: Process ID already exists. " + data.ProcessID);
1133 | _debugLog.WriteLine("Deletion flag: " + _activeProcesses[data.ProcessID].DeletionFlag);
1134 | }
1135 |
1136 | if (_activeProcesses[data.ProcessID].DeletionFlag > 0)
1137 | {
1138 | foreach (var thread in _activeThreadsByProcess[data.ProcessID])
1139 | {
1140 | thread.Value.DeletionFlag = data.TimeStampRelativeMSec - (_threadDeletionDelay*2);
1141 | }
1142 | _activeProcesses[data.ProcessID].DeletionFlag = data.TimeStampRelativeMSec -
1143 | (_processDeletionDelay*2);
1144 |
1145 | ThreadDeletionQueue(data);
1146 | ProcessDeletionQueue(data);
1147 |
1148 | if (_activeProcesses.ContainsKey(data.ProcessID))
1149 | {
1150 | _debugLog.WriteLine("Error: Process ID already exists. " + data.ProcessID);
1151 | _debugLog.WriteLine("Deletion flag: " + _activeProcesses[data.ProcessID].DeletionFlag);
1152 | throw new Exception("Duplicate process disaster despite our correction efforts");
1153 | }
1154 | }
1155 | }
1156 |
1157 | // Add Process to active process list
1158 | _activeProcesses[data.ProcessID] = newProcess;
1159 |
1160 | // Add Process to active threads list
1161 | _activeThreadsByProcess[data.ProcessID] = new ThreadDict();
1162 |
1163 | // Create a new tracker
1164 | newProcess.Counter =
1165 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newProcess.Guid), _debugLog);
1166 | if (!dcStart && (_tracePerProcess))
1167 | {
1168 | newProcess.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec);
1169 | }
1170 |
1171 | // Add to database
1172 | if (_profileCode)
1173 | {
1174 | _codeProfileCounters["CreateTable"] += 1;
1175 | _codeProfileTimers["CreateTable"].Start();
1176 | }
1177 |
1178 | _database.AddProcess(newProcess);
1179 |
1180 | if (_profileCode)
1181 | {
1182 | _codeProfileTimers["CreateTable"].Stop();
1183 | }
1184 | if (_profileCode)
1185 | {
1186 | _codeProfileTimers["ProcessStart"].Stop();
1187 | }
1188 | }
1189 |
1190 | ///
1191 | /// Handle process stop events
1192 | ///
1193 | /// Trace event data
1194 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1195 | private void ProcessStop(TraceEvent data)
1196 | {
1197 | if (_profileCode)
1198 | {
1199 | _codeProfileCounters["ProcessStop"] += 1;
1200 | _codeProfileTimers["ProcessStop"].Start();
1201 | }
1202 |
1203 | int pid = data.ProcessID;
1204 |
1205 | if (_verbosity >= 3)
1206 | {
1207 | _debugLog.WriteLine("Process Stop " + pid);
1208 | }
1209 |
1210 | // Ignore the idle PID because we never created an object for it
1211 | if (pid == IdlePid)
1212 | {
1213 | if (_profileCode)
1214 | {
1215 | _codeProfileTimers["ProcessStop"].Stop();
1216 | }
1217 | return;
1218 | }
1219 |
1220 | // We were receiving DCSTOP events with no corresponding starts
1221 | if (!_activeProcesses.ContainsKey(pid))
1222 | {
1223 | _debugLog.WriteLine("Process missing from dict");
1224 | if (_endService)
1225 | {
1226 | _debugLog.WriteLine("Probably a DCSTOP, ignoring");
1227 | return;
1228 | }
1229 | }
1230 |
1231 | //Get process info
1232 | ProcessInfo stoppingProcess = _activeProcesses[pid];
1233 |
1234 | if (_verbosity >= 3)
1235 | {
1236 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1237 | data.TimeStampRelativeMSec + " " + "Process Stop: " +
1238 | stoppingProcess.Name + " " + stoppingProcess.Pid);
1239 | }
1240 |
1241 | // Set the stop time
1242 | stoppingProcess.StopRelativeMSec = data.TimeStampRelativeMSec;
1243 |
1244 | // Update the process end time in the database
1245 | _database.UpdateProcessEnd(stoppingProcess.StopRelativeMSec, stoppingProcess.Guid);
1246 |
1247 | // Flag for deletion
1248 | stoppingProcess.DeletionFlag = data.TimeStampRelativeMSec;
1249 |
1250 | // Put it in the deletion queue
1251 | _processesToDelete.Add(stoppingProcess);
1252 |
1253 | if (_profileCode)
1254 | {
1255 | _codeProfileTimers["ProcessStop"].Stop();
1256 | }
1257 | }
1258 |
1259 |
1260 | ///
1261 | /// Wrapper for regular thread starts
1262 | ///
1263 | ///
1264 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1265 | private void ThreadStart(TraceEvent data)
1266 | {
1267 | ThreadStartHelper(data, false);
1268 | }
1269 |
1270 |
1271 | ///
1272 | /// Wrapper for dc thread starts
1273 | ///
1274 | ///
1275 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1276 | private void ThreadDcStart(TraceEvent data)
1277 | {
1278 | ThreadStartHelper(data, true);
1279 | }
1280 |
1281 |
1282 | ///
1283 | /// Process thread starts
1284 | ///
1285 | /// Trace event data
1286 | /// True if DC start
1287 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1288 | private void ThreadStartHelper(TraceEvent data, bool dcStart)
1289 | {
1290 | if (_profileCode)
1291 | {
1292 | _codeProfileCounters["ThreadStart"] += 1;
1293 | _codeProfileTimers["ThreadStart"].Start();
1294 | }
1295 |
1296 | ThreadTraceData threadData = (ThreadTraceData) data;
1297 | int tid = data.ThreadID;
1298 |
1299 | if (_verbosity >= 4)
1300 | {
1301 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1302 | data.TimeStampRelativeMSec + "Thread start " + tid +
1303 | " for pid " + data.ProcessID + " " + threadData.ProcessID);
1304 | }
1305 |
1306 | // system idle process has as many threads as there are cores, all with diplicate Tid and Pid 0. We ignore these.
1307 | if (tid == 0 && data.ProcessID == 0)
1308 | {
1309 | if (_profileCode)
1310 | {
1311 | _codeProfileTimers["ThreadStart"].Stop();
1312 | }
1313 | return;
1314 | }
1315 |
1316 | if (_unkownThreads.ContainsKey(tid))
1317 | {
1318 | // This means it is a TID that we saw in a context switch already. We need to update its info.
1319 | _unkownThreads[tid].Pid = data.ProcessID;
1320 | _unkownThreads[tid].ProcessGuid = _activeProcesses[data.ProcessID].Guid;
1321 | _unkownThreads[tid].PidStartRelativeMSec = _activeProcesses[data.ProcessID].StartRelativeMSec;
1322 |
1323 | // Put it in the correct process list
1324 | _activeThreadsByProcess[data.ProcessID][tid] = _unkownThreads[tid];
1325 |
1326 | // Count new thread.
1327 | _activeProcesses[data.ProcessID].TotalThreads += 1;
1328 |
1329 | // Remove from unknown list
1330 | _unkownThreads.Remove(tid);
1331 |
1332 | if (_verbosity >= 4)
1333 | {
1334 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1335 | data.TimeStampRelativeMSec + " " + "Updated PID in thread start" +
1336 | _activeProcesses[data.ProcessID].Name + ", " +
1337 | _activeThreadsByProcess[data.ProcessID][tid].Tid);
1338 | }
1339 |
1340 | // Make sure the processor is updated if this thread is currently executing:
1341 | for (int i = 0; i < _processorActiveProcesses.Count(); i++)
1342 | {
1343 | if (_processorActiveThreads[i] == tid && _processorActiveProcesses[i] == UnknownPid)
1344 | {
1345 | if (_verbosity >= 4)
1346 | {
1347 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) +
1348 | " " + data.TimeStampRelativeMSec + " Updated executing PID ");
1349 | }
1350 | _processorActiveProcesses[i] = data.ProcessID;
1351 | }
1352 | }
1353 |
1354 | if (_profileCode)
1355 | {
1356 | _codeProfileTimers["ThreadStart"].Stop();
1357 | }
1358 | return;
1359 | }
1360 | // Need to add duplicate TID mitigation code here!
1361 | if (_activeThreadsByProcess.ContainsKey(data.ProcessID) &&
1362 | _activeThreadsByProcess[data.ProcessID].ContainsKey(tid))
1363 | {
1364 | if (_verbosity >= 1)
1365 | {
1366 | _debugLog.WriteLine("WARNING: TID " + tid + " already exists for " + data.ProcessID);
1367 | _debugLog.WriteLine("Deleted: " +
1368 | _activeThreadsByProcess[data.ProcessID][tid].Deleted);
1369 | _debugLog.WriteLine("Deletion flag: " +
1370 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag);
1371 | }
1372 |
1373 | if (_activeThreadsByProcess[data.ProcessID][tid].DeletionFlag > 0)
1374 | {
1375 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag = data.TimeStampRelativeMSec -
1376 | (_threadDeletionDelay*2);
1377 |
1378 | ThreadDeletionQueue(data);
1379 |
1380 | if (_activeThreadsByProcess[data.ProcessID].ContainsKey(tid))
1381 | {
1382 | _debugLog.WriteLine("ERROR: TID " + tid + " already exists for " +
1383 | data.ProcessID);
1384 | _debugLog.WriteLine("Deleted: " +
1385 | _activeThreadsByProcess[data.ProcessID][tid].Deleted);
1386 | _debugLog.WriteLine("Deletion flag: " +
1387 | _activeThreadsByProcess[data.ProcessID][tid].DeletionFlag);
1388 | throw new Exception("Duplicate thread disaster despite our correction efforts");
1389 | }
1390 | }
1391 | }
1392 | //Create thread info object
1393 | ThreadInfo newThread = new ThreadInfo
1394 | {
1395 | Pid = data.ProcessID,
1396 | Tid = tid,
1397 | Start = data.TimeStamp,
1398 | StartRelativeMSec = data.TimeStampRelativeMSec,
1399 | PidStartRelativeMSec = _activeProcesses[data.ProcessID].StartRelativeMSec,
1400 | Guid = Guid.NewGuid().ToString("N"),
1401 | ProcessGuid = _activeProcesses[data.ProcessID].Guid
1402 | };
1403 |
1404 | // Only create database entries and counter objects if we are doing thread tracing.
1405 | if (_tracePerThread)
1406 | {
1407 | newThread.Counter =
1408 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newThread.Guid),
1409 | _debugLog);
1410 | if (!dcStart && _tracePerThread)
1411 | {
1412 | newThread.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec);
1413 | }
1414 |
1415 | _database.AddThread(newThread);
1416 | }
1417 |
1418 | // Count new thread.
1419 | _activeProcesses[data.ProcessID].TotalThreads += 1;
1420 | _activeThreadsByProcess[data.ProcessID][tid] = newThread;
1421 | if (_profileCode)
1422 | {
1423 | _codeProfileTimers["ThreadStart"].Stop();
1424 | }
1425 | }
1426 |
1427 | ///
1428 | /// Process thread stops
1429 | ///
1430 | /// Trace event data
1431 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1432 | private void ThreadStop(TraceEvent data)
1433 | {
1434 | if (_profileCode)
1435 | {
1436 | _codeProfileCounters["ThreadStop"] += 1;
1437 | _codeProfileTimers["ThreadStop"].Start();
1438 | }
1439 |
1440 | if (_verbosity >= 4)
1441 | {
1442 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1443 | data.TimeStampRelativeMSec + " " + "Thread Stop: " + data.ThreadID + " " +
1444 | data.ProcessID);
1445 | }
1446 |
1447 | // system idle process has as many threads as there are cores, all with duplicate Tid and Pid 0
1448 | if (data.ProcessID == 0 && data.ThreadID == 0)
1449 | {
1450 | if (_profileCode)
1451 | {
1452 | _codeProfileTimers["ThreadStop"].Stop();
1453 | }
1454 | return;
1455 | }
1456 |
1457 | // Update Stop times for thread
1458 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].StopRelativeMSec = data.TimeStampRelativeMSec;
1459 |
1460 | // Flag for deletion
1461 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].DeletionFlag = data.TimeStampRelativeMSec;
1462 |
1463 | // Only update database if we are doing thread analysis
1464 | if (_tracePerThread)
1465 | {
1466 | _database.UpdateThreadEnd(data.TimeStampRelativeMSec,
1467 | _activeThreadsByProcess[data.ProcessID][data.ThreadID].Guid);
1468 | }
1469 |
1470 | _threadsToDelete.Add(_activeThreadsByProcess[data.ProcessID][data.ThreadID]);
1471 | if (_profileCode)
1472 | {
1473 | _codeProfileTimers["ThreadStop"].Stop();
1474 | }
1475 | }
1476 |
1477 | ///
1478 | /// Processes context switches, which is a lot of work. A lot of
1479 | /// error checking here to be sure what we are tracking matches the
1480 | /// the information reported by ETW.
1481 | ///
1482 | /// Trace event data
1483 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1484 | private void ContextSwitch(TraceEvent data)
1485 | {
1486 | // Get the context switch data
1487 | CSwitchTraceData cSwitchData = (CSwitchTraceData) data;
1488 |
1489 | if (_profileCode)
1490 | {
1491 | _codeProfileCounters["ContextSwitch"] += 1;
1492 | _codeProfileTimers["ContextSwitch"].Start();
1493 | }
1494 |
1495 | // Debug logging
1496 | if (_verbosity >= 5)
1497 | {
1498 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1499 | data.TimeStampRelativeMSec + " Exchanged " + cSwitchData.OldThreadID +
1500 | " " + cSwitchData.OldProcessID + " for " + cSwitchData.NewThreadID + " " +
1501 | cSwitchData.NewProcessID + " ON CORE " + cSwitchData.ProcessorNumber);
1502 | }
1503 |
1504 |
1505 | // At the context switches we check to see whether we should do some writing and comitting.
1506 | if (_lastCommit < -99)
1507 | {
1508 | _lastCommit = data.TimeStampRelativeMSec;
1509 | }
1510 | if (_lastCommit + _commitInterval <= data.TimeStampRelativeMSec)
1511 | {
1512 | //Database commits
1513 | if (_profileCode)
1514 | {
1515 | _codeProfileCounters["Commit"] += 1;
1516 | _codeProfileTimers["Commit"].Start();
1517 | }
1518 | _database.Commit();
1519 | if (_profileCode)
1520 | {
1521 | _codeProfileTimers["Commit"].Stop();
1522 | }
1523 |
1524 | _lastCommit = data.TimeStampRelativeMSec;
1525 | }
1526 |
1527 |
1528 | // Update the last CSwitch time
1529 | _lastCSwitch[cSwitchData.ProcessorNumber] = data.TimeStampRelativeMSec;
1530 |
1531 | // Should we do a deletion check?
1532 | if (data.TimeStampRelativeMSec > _lastDeletionCheck + _minBackoff)
1533 | {
1534 | ThreadDeletionQueue(data);
1535 | ProcessDeletionQueue(data);
1536 | _lastDeletionCheck = data.TimeStampRelativeMSec;
1537 | }
1538 |
1539 | // First handle what is being switched out -- As long as it is not the default.
1540 | if (_processorActiveThreads[cSwitchData.ProcessorNumber] != DefaultProcessorValue)
1541 | {
1542 | // Verify that old thread IDs match
1543 | if (_processorActiveThreads[cSwitchData.ProcessorNumber] != cSwitchData.OldThreadID)
1544 | {
1545 | _debugLog.Write("CSWITCH error. Old thread mismatch. Switched out " + cSwitchData.OldThreadID +
1546 | " but should have been" + _processorActiveThreads[cSwitchData.ProcessorNumber]);
1547 | _debugLog.Flush();
1548 | throw new Exception("CSWITCH OldThread Mismatch");
1549 | }
1550 |
1551 | // For any old non-idle process, we need to update the old thread and process information.
1552 | if (cSwitchData.OldThreadID != IdlePid)
1553 | {
1554 | // Easy Case: We already know about old process and thread.
1555 | if (_activeThreadsByProcess.ContainsKey(cSwitchData.OldProcessID) &&
1556 | _activeThreadsByProcess[cSwitchData.OldProcessID].ContainsKey(cSwitchData.OldThreadID))
1557 | {
1558 | // Update thread activity
1559 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID].IsActive = false;
1560 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID].LastActive =
1561 | cSwitchData.TimeStampRelativeMSec;
1562 |
1563 | // Update process activity
1564 | _activeProcesses[cSwitchData.OldProcessID].ActiveThreads -= 1;
1565 | _activeProcesses[cSwitchData.OldProcessID].LastActive = cSwitchData.TimeStampRelativeMSec;
1566 | }
1567 |
1568 | // Harder case: We know about old thread, but not the process.
1569 | else if (_unkownThreads.ContainsKey(cSwitchData.OldThreadID))
1570 | {
1571 | _unkownThreads[cSwitchData.OldThreadID].IsActive = false;
1572 | _unkownThreads[cSwitchData.OldThreadID].LastActive = cSwitchData.TimeStampRelativeMSec;
1573 |
1574 | // Update the process information if the old PID exists now.
1575 | if (cSwitchData.OldProcessID > 0)
1576 | {
1577 | _unkownThreads[cSwitchData.OldThreadID].Pid = cSwitchData.OldProcessID;
1578 |
1579 | // Add thread to the process thread list
1580 | _activeThreadsByProcess[cSwitchData.OldProcessID][cSwitchData.OldThreadID] =
1581 | _unkownThreads[cSwitchData.OldThreadID];
1582 |
1583 | // Update GUID
1584 | _unkownThreads[cSwitchData.OldThreadID].ProcessGuid =
1585 | _activeProcesses[cSwitchData.OldProcessID].Guid;
1586 |
1587 | // New thread for this process
1588 | _activeProcesses[cSwitchData.OldProcessID].TotalThreads += 1;
1589 |
1590 | //Remove from UnkownThreads
1591 | _unkownThreads.Remove(cSwitchData.OldThreadID);
1592 |
1593 | // Log information
1594 | if (_verbosity >= 3)
1595 | {
1596 | _debugLog.WriteLine(
1597 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1598 | data.TimeStampRelativeMSec + "Updated PID to " +
1599 | cSwitchData.OldProcessID + " for switched out thread " +
1600 | cSwitchData.OldThreadID);
1601 | }
1602 |
1603 | // Update Active processors for this thread
1604 | for (int i = 0; i < _processorActiveProcesses.Count(); i++)
1605 | {
1606 | if (i != cSwitchData.ProcessorNumber &&
1607 | _processorActiveThreads[i] == cSwitchData.OldThreadID &&
1608 | _processorActiveProcesses[i] == UnknownPid)
1609 | {
1610 | if (_verbosity >= 3)
1611 | {
1612 | _debugLog.WriteLine(
1613 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1614 | data.TimeStampRelativeMSec + " Updated executing PID ");
1615 | }
1616 | _processorActiveProcesses[i] = cSwitchData.OldProcessID;
1617 | _activeProcesses[cSwitchData.OldProcessID].ActiveThreads += 1;
1618 | }
1619 | }
1620 | }
1621 | }
1622 |
1623 | // Otherwise, we are in an error condition.
1624 | else
1625 | {
1626 | _debugLog.Write("FATAL CSWITCH ERROR: Don't know anything about switched out thread.");
1627 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1628 | data.TimeStampRelativeMSec + " Exchanged " +
1629 | cSwitchData.OldThreadID + " " + cSwitchData.OldProcessID + " for " +
1630 | cSwitchData.NewThreadID + " " +
1631 | cSwitchData.NewProcessID + " ON CORE " +
1632 | cSwitchData.ProcessorNumber);
1633 | _debugLog.Flush();
1634 | throw new Exception("FATAL CSWITCH ERROR: Don't know anything about switched out thread.");
1635 | }
1636 | }
1637 | }
1638 |
1639 |
1640 | // Gratuitious logging for debugging purposes only.
1641 | //DebugLog.WriteLine("Processes:" + String.Join(",", ProcessorActiveProcesses));
1642 | //DebugLog.WriteLine("Threads:" + String.Join(",", ProcessorActiveThreads));
1643 | // If the new thread is the system IDLE process, we are fine. Just set it and continue
1644 | int newThreadId = cSwitchData.NewThreadID;
1645 | int newProcessId = cSwitchData.NewProcessID;
1646 |
1647 | // For Nonzero new processes, we have work to do.
1648 | if (cSwitchData.NewThreadID != IdlePid)
1649 | {
1650 | // If we know about both the thread and process already
1651 | if (_activeThreadsByProcess.ContainsKey(cSwitchData.NewProcessID) &&
1652 | _activeThreadsByProcess[cSwitchData.NewProcessID].ContainsKey(cSwitchData.NewThreadID))
1653 | {
1654 | // Update thread activity
1655 | _activeThreadsByProcess[cSwitchData.NewProcessID][cSwitchData.NewThreadID].IsActive = true;
1656 |
1657 | // Update process activity
1658 | _activeProcesses[cSwitchData.NewProcessID].ActiveThreads += 1;
1659 | }
1660 | // If we only know about the thread
1661 | else if (_unkownThreads.ContainsKey(cSwitchData.NewThreadID))
1662 | {
1663 | _unkownThreads[cSwitchData.NewThreadID].IsActive = true;
1664 | newProcessId = UnknownPid;
1665 | }
1666 |
1667 | // If we don't know about the thread yet and process is unknown, it is the weird case we see every now and then.
1668 | else if (cSwitchData.NewProcessID < 0)
1669 | {
1670 | if (_verbosity >= 4)
1671 | {
1672 | _debugLog.WriteLine("CSwitch: Created new TID in thread list (" + cSwitchData.NewThreadID + ")");
1673 | _debugLog.WriteLine("Threads Old: " + cSwitchData.OldThreadID + " New: " +
1674 | cSwitchData.NewThreadID);
1675 | _debugLog.WriteLine("Processes Old: " + cSwitchData.OldProcessID + " New: " +
1676 | cSwitchData.NewProcessID);
1677 | }
1678 |
1679 | //Create thread info object
1680 | ThreadInfo newThread = new ThreadInfo
1681 | {
1682 | Tid = cSwitchData.NewThreadID,
1683 | Pid = UnknownPid,
1684 | Start = data.TimeStamp,
1685 | StartRelativeMSec = data.TimeStampRelativeMSec,
1686 | Guid = Guid.NewGuid().ToString("N")
1687 | };
1688 |
1689 | // Create a new tracker
1690 | newThread.Counter =
1691 | new SystemCallTracer(Path.Combine(_tempPath, _dataDirectory, _dataSubFolder, newThread.Guid),
1692 | _debugLog);
1693 | if (_tracePerThread)
1694 | {
1695 | newThread.Counter.InitializeFullTrace(_maxTraceSyscalls, data.TimeStampRelativeMSec);
1696 | }
1697 |
1698 | _unkownThreads[cSwitchData.NewThreadID] = newThread;
1699 | newProcessId = UnknownPid;
1700 | }
1701 |
1702 | // Otherwise we are in an error condition
1703 | else
1704 | {
1705 | _debugLog.Write("FATAL CSWITCH ERROR: Don't know anything about switched in thread.");
1706 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1707 | data.TimeStampRelativeMSec + " Exchanged " + cSwitchData.OldThreadID +
1708 | " " + cSwitchData.OldProcessID + " for " + cSwitchData.NewThreadID +
1709 | " " + cSwitchData.NewProcessID + " ON CORE " +
1710 | cSwitchData.ProcessorNumber);
1711 | _debugLog.Flush();
1712 | throw new Exception("FATAL CSWITCH ERROR: Don't know anything about switched in thread.");
1713 | }
1714 | }
1715 |
1716 | // Update information about the threads and processes on the cores
1717 | _processorActiveProcesses[cSwitchData.ProcessorNumber] = newProcessId;
1718 | _processorActiveThreads[cSwitchData.ProcessorNumber] = newThreadId;
1719 |
1720 |
1721 | if (_profileCode)
1722 | {
1723 | _codeProfileTimers["ContextSwitch"].Stop();
1724 | }
1725 | }
1726 |
1727 |
1728 | ///
1729 | /// Processes the thread deletion queue
1730 | ///
1731 | /// Trace event data
1732 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1733 | private void ThreadDeletionQueue(TraceEvent data)
1734 | {
1735 | if (_profileCode)
1736 | {
1737 | _codeProfileCounters["ThreadDeletionQueue"] += 1;
1738 | _codeProfileTimers["ThreadDeletionQueue"].Start();
1739 | }
1740 |
1741 | // Return if there is nothing to do.
1742 | if (_threadsToDelete.Count != 0)
1743 | {
1744 | // Otherwise loop over all the threads to see which ones are ready to be deleted.
1745 | for (int i = _threadsToDelete.Count - 1; i >= 0; i--)
1746 | {
1747 | var thread = _threadsToDelete[i];
1748 |
1749 | if (thread.IsActive)
1750 | {
1751 | _threadDeletionDelay *= 1.1;
1752 | if (_verbosity >= 4)
1753 | {
1754 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) +
1755 | " " + data.TimeStampRelativeMSec +
1756 | " Thread delay updated because still active. " + thread.Tid);
1757 | }
1758 | }
1759 |
1760 | // If the deletion time has passed, see if it is ready
1761 | else if (data.TimeStampRelativeMSec > thread.DeletionFlag + _threadDeletionDelay)
1762 | {
1763 | // If there is no active process associated with this thread, good!
1764 | if (!_activeProcesses.ContainsKey(thread.Pid))
1765 | {
1766 | if (_verbosity >= 4)
1767 | {
1768 | _debugLog.WriteLine(
1769 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1770 | data.TimeStampRelativeMSec + " " +
1771 | "Deleted thread with no active process" + thread.Tid + "," +
1772 | thread.Pid);
1773 | }
1774 |
1775 | // Remove from the unknown threads
1776 | _unkownThreads.Remove(thread.Pid);
1777 |
1778 | // Dispose of the commands -- Do I need to write a dispose method for the Counter?
1779 | if (thread.Counter != null)
1780 | {
1781 | thread.Counter.Close();
1782 | }
1783 | thread.Deleted = true;
1784 |
1785 | // Remove thread from deletion list
1786 | _threadsToDelete.RemoveAt(i);
1787 | }
1788 |
1789 | // Else we just remove the old thread from its process
1790 | else
1791 | {
1792 | if (_verbosity >= 4)
1793 | {
1794 | _debugLog.WriteLine(
1795 | (_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) + " " +
1796 | data.TimeStampRelativeMSec + " " + "Thread deleted normally." +
1797 | thread.Tid + "," + thread.Pid);
1798 | }
1799 |
1800 | _activeThreadsByProcess[thread.Pid].Remove(thread.Tid);
1801 |
1802 | _activeProcesses[thread.Pid].TotalThreads -= 1;
1803 |
1804 | // Dispose of the commands
1805 | if (thread.Counter != null)
1806 | {
1807 | thread.Counter.Close();
1808 | }
1809 |
1810 | thread.Deleted = true;
1811 |
1812 | _threadsToDelete.RemoveAt(i);
1813 | }
1814 | }
1815 | }
1816 | }
1817 | if (_profileCode)
1818 | {
1819 | _codeProfileTimers["ThreadDeletionQueue"].Stop();
1820 | }
1821 | }
1822 |
1823 | ///
1824 | /// Process the process deletion queue
1825 | ///
1826 | /// Trace event data
1827 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1828 | private void ProcessDeletionQueue(TraceEvent data)
1829 | {
1830 | if (_processesToDelete.Count != 0)
1831 | {
1832 | for (int i = _processesToDelete.Count - 1; i >= 0; i--)
1833 | {
1834 | ProcessInfo process = _processesToDelete[i];
1835 |
1836 | // Process is still active
1837 | if (process.ActiveThreads > 0)
1838 | {
1839 | process.DeletionFlag = data.TimeStampRelativeMSec;
1840 | if (_verbosity >= 5)
1841 | {
1842 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) +
1843 | " " + data.TimeStampRelativeMSec + " " +
1844 | "process still active. Deletion delayed. " + process.Pid);
1845 | }
1846 | }
1847 |
1848 | // Process still has threads
1849 | else if (process.TotalThreads > 0)
1850 | {
1851 | }
1852 |
1853 | // Process is ready to be removed when it has no threads and delay is over
1854 | else if (data.TimeStampRelativeMSec > process.DeletionFlag + _processDeletionDelay)
1855 | {
1856 | if (_verbosity >= 3)
1857 | {
1858 | _debugLog.WriteLine((_timer.ElapsedMilliseconds - data.TimeStampRelativeMSec) +
1859 | " " + data.TimeStampRelativeMSec + " Removed old process " +
1860 | process.Pid);
1861 | }
1862 |
1863 | // Remove process
1864 | _activeProcesses.Remove(process.Pid);
1865 |
1866 | // remove thread list for process
1867 | _activeThreadsByProcess.Remove(process.Pid);
1868 |
1869 | // Dispose of the commands
1870 | if (process.Counter != null)
1871 | {
1872 | process.Counter.Close();
1873 | }
1874 |
1875 | process.Deleted = true;
1876 |
1877 | //Remove it from list
1878 | _processesToDelete.RemoveAt(i);
1879 | }
1880 | }
1881 | }
1882 | }
1883 |
1884 | ///
1885 | /// System call enter processing
1886 | ///
1887 | /// Trace event data
1888 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
1889 | private void SystemCallEnter(TraceEvent data)
1890 | {
1891 | if (_profileCode)
1892 | {
1893 | _codeProfileCounters["Syscall"] += 1;
1894 | _codeProfileTimers["Syscall"].Start();
1895 | }
1896 |
1897 | int index = -2;
1898 | SysCallEnterTraceData traceData = (SysCallEnterTraceData) data;
1899 |
1900 | if (traceData.SysCallAddress >= _ntLowestAddress && traceData.SysCallAddress <= _ntMaxAddress)
1901 | {
1902 | index = _ntMap[(traceData.SysCallAddress - _ntLowestAddress)];
1903 |
1904 | // This is here for now for debugging puposes as a sanity check that we are tracing whole kernel
1905 | if (index == -1)
1906 | {
1907 | _debugLog.WriteLine("UNKNOWN System Call Enter NT {0:X} on core {1} ", traceData.SysCallAddress,
1908 | traceData.ProcessorNumber);
1909 | }
1910 | }
1911 |
1912 | if (index >= 0)
1913 | {
1914 | // Do host-wide data collection
1915 | if (_traceHostLevel)
1916 | {
1917 | _systemWideCounter.Add((ushort) index, data.TimeStampRelativeMSec);
1918 | }
1919 |
1920 | // Do process level data collection
1921 | if (_tracePerProcess)
1922 | {
1923 | if (_activeProcesses.ContainsKey(_processorActiveProcesses[traceData.ProcessorNumber]))
1924 | {
1925 | ProcessInfo process = _activeProcesses[_processorActiveProcesses[traceData.ProcessorNumber]];
1926 | process.Counter.Add((ushort) index, data.TimeStampRelativeMSec);
1927 | }
1928 | }
1929 |
1930 |
1931 | // Do it per thread
1932 | // Do process level data collection
1933 | if (_tracePerThread)
1934 | {
1935 | ThreadInfo thread = null;
1936 |
1937 | if (_unkownThreads.ContainsKey(_processorActiveThreads[traceData.ProcessorNumber]))
1938 | {
1939 | thread = _unkownThreads[_processorActiveThreads[traceData.ProcessorNumber]];
1940 | }
1941 | else if (_activeThreadsByProcess.ContainsKey(_processorActiveProcesses[traceData.ProcessorNumber]) &&
1942 | _activeThreadsByProcess[_processorActiveProcesses[traceData.ProcessorNumber]].ContainsKey(
1943 | _processorActiveThreads[traceData.ProcessorNumber]))
1944 | {
1945 | thread =
1946 | _activeThreadsByProcess[_processorActiveProcesses[traceData.ProcessorNumber]][
1947 | _processorActiveThreads[traceData.ProcessorNumber]];
1948 | }
1949 |
1950 | if (thread != null)
1951 | {
1952 | thread.Counter.Add((ushort) index, data.TimeStampRelativeMSec);
1953 | }
1954 | }
1955 | }
1956 | if (_profileCode)
1957 | {
1958 | _codeProfileTimers["Syscall"].Stop();
1959 | }
1960 | }
1961 |
1962 | ///
1963 | /// Get the base addresses of the kernel
1964 | ///
1965 | /// true upon success
1966 | private bool GetBaseAddresses()
1967 | {
1968 | uint bytesNeeded;
1969 |
1970 | // See how big the buffer needs to be
1971 | var success = EnumDeviceDrivers(null, 0, out bytesNeeded);
1972 | _debugLog.WriteLine("EnumDeviceDrivers Finished");
1973 | _debugLog.Flush();
1974 |
1975 | // Check error conditions
1976 | if (!success)
1977 | {
1978 | return false;
1979 | }
1980 | if (bytesNeeded == 0)
1981 | {
1982 | return false;
1983 | }
1984 |
1985 | // Allocate the array; as each ID is a 4-byte int, it should be 1/4th the size of bytesNeeded
1986 | uint arraySizeBytes = bytesNeeded;
1987 | #if X86
1988 | uint ArraySize = BytesNeeded / 4;
1989 | UInt32[] Addresses = new UInt32[ArraySize];
1990 | #else
1991 | uint arraySize = bytesNeeded/8;
1992 | UInt64[] addresses = new UInt64[arraySize];
1993 | #endif
1994 |
1995 | // Now fill the array with device driver information
1996 | success = EnumDeviceDrivers(addresses, arraySizeBytes, out bytesNeeded);
1997 | _debugLog.WriteLine("Second EnumDeviceDrivers Finished");
1998 | _debugLog.Flush();
1999 | // Check error conditions
2000 | if (!success)
2001 | {
2002 | return false;
2003 | }
2004 |
2005 | // Iterate over all the device drivers until we find the kernel
2006 | // Assume the base name is no more than 1000 characters
2007 | StringBuilder driverName = new StringBuilder(1000);
2008 | for (int i = 0; i < arraySize; i++)
2009 | {
2010 | GetDeviceDriverBaseName(addresses[i], driverName, driverName.Capacity);
2011 |
2012 | String driverNameString = driverName.ToString();
2013 |
2014 | // Kernel has different names on different windows versions
2015 | String[] possibleNames = {"ntoskrnl.exe", "ntkrnlpa.exe", "ntkrnlmp.exe", "ntkrpamp.exe"};
2016 |
2017 | foreach (String name in possibleNames)
2018 | {
2019 | if (driverNameString == name)
2020 | {
2021 | _debugLog.WriteLine("Found " + name);
2022 | _debugLog.WriteLine(addresses[i]);
2023 | _debugLog.Flush();
2024 | _ntKernelAddress = addresses[i];
2025 | _ntKernelImageName = name;
2026 | break;
2027 | }
2028 | }
2029 | }
2030 | _debugLog.WriteLine("StringBuilder Finished");
2031 | _debugLog.Flush();
2032 | return (_ntKernelAddress > 0);
2033 | }
2034 |
2035 | ///
2036 | /// Starts data collection
2037 | ///
2038 | public void Start()
2039 | {
2040 | _endService = false;
2041 |
2042 | // Setup Profiling firsst
2043 | if (_profileCode)
2044 | {
2045 | foreach (string str in _codeProfileKeys)
2046 | {
2047 | _codeProfileTimers.Add(str, new Stopwatch());
2048 | _codeProfileCounters.Add(str, 0);
2049 | }
2050 | }
2051 |
2052 | // Reset Last SyscallEnter time and deletion check
2053 | _lastDeletionCheck = -110000;
2054 | _lastCommit = -1;
2055 |
2056 | // Create data directory (if it doesn't already exist).
2057 | Directory.CreateDirectory(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory));
2058 |
2059 | // Create a subdirectory to store the data
2060 | _dataSubFolder = DateTime.Now.ToString("yyyyMMdd_HHmmss");
2061 | Directory.CreateDirectory(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory,
2062 | _dataSubFolder));
2063 |
2064 | // Create the logfile
2065 | _debugLog =
2066 | new StreamWriter(Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory,
2067 | _dataSubFolder, Properties.SystemCallServiceSettings.Default.DebugLogFilename));
2068 |
2069 | // Dump some config information in the debug log
2070 | foreach (string prop in _properties)
2071 | {
2072 | _debugLog.WriteLine(prop + " " + Properties.SystemCallServiceSettings.Default[prop]);
2073 | }
2074 |
2075 | _debugLog.Flush();
2076 |
2077 | // Start the database interface
2078 | _database =
2079 | new DatabaseInterface(
2080 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, _dataSubFolder,
2081 | "database.sqlite"), _debugLog);
2082 |
2083 | _debugLog.WriteLine("Started Database Interface");
2084 | _debugLog.Flush();
2085 |
2086 | // Get base kernel addresses -- must be done first to get correct image name because of x86 implementation
2087 | if (!GetBaseAddresses())
2088 | {
2089 | _debugLog.WriteLine("Unable to fetch base addresses for the kernel. Unable to continue.");
2090 | _debugLog.Flush();
2091 | throw new Exception("Unable to fetch base addresses for the kernel. Unable to continue.");
2092 | }
2093 |
2094 | _debugLog.WriteLine("Done GetBaseAddresses");
2095 | _debugLog.Flush();
2096 |
2097 | // Get system information
2098 | GetSystemInformation();
2099 | _debugLog.WriteLine("Done adding SystemInformation");
2100 | _debugLog.Flush();
2101 |
2102 | // Load address mappings
2103 | _ntMap = LoadAddressMaps(_ntKernelImageName, _systemInfo.NtoskrnlVersion,
2104 | Properties.SystemCallServiceSettings.Default.NtSensorList, out _syscallNameList, out _ntLowestAddress,
2105 | out _ntMaxAddress, 0, _ntKernelAddress);
2106 | _debugLog.WriteLine("Done LoadAddressMaps");
2107 | _debugLog.Flush();
2108 |
2109 |
2110 | if (_ntMap == null)
2111 | {
2112 | // TODO: Exit cleanly? This was put here for the case when automatic downloading was enabled.
2113 | // We don't want to quit forever, but retry in whatever the specified interval is.
2114 | Thread.Sleep((int) Properties.SystemCallServiceSettings.Default.AutoResetMs);
2115 | return;
2116 | }
2117 |
2118 | _debugLog.WriteLine(_syscallNameList.Count() + " nt sensors active");
2119 | _debugLog.Flush();
2120 |
2121 | // Setup the data table creation and insertion queries and create one for the system-wide data
2122 | _systemWideCounter =
2123 | new SystemCallTracer(
2124 | Path.Combine(_tempPath, Properties.SystemCallServiceSettings.Default.DataDirectory, _dataSubFolder,
2125 | "host_data"), _debugLog);
2126 | if (Properties.SystemCallServiceSettings.Default.TraceHostLevel)
2127 | {
2128 | _systemWideCounter.InitializeFullTrace(-1, 0);
2129 | }
2130 |
2131 | // Start the timer
2132 | _resetTimer.Interval = Properties.SystemCallServiceSettings.Default.AutoResetMs;
2133 | _resetTimer.Start();
2134 |
2135 | // Clear all the data structures that are populated during a trace
2136 | _tableCreations.Clear();
2137 | _processesToDelete.Clear();
2138 | _threadsToDelete.Clear();
2139 | _activeThreadsByProcess.Clear();
2140 | _unkownThreads.Clear();
2141 | _activeProcesses.Clear();
2142 | _timer.Restart();
2143 |
2144 | // Setup Thread and Process tracking, initialize to default values
2145 | _processorActiveThreads = new int[_logicalProcessorCount];
2146 | _processorActiveProcesses = new int[_logicalProcessorCount];
2147 |
2148 | for (int i = 0; i < _logicalProcessorCount; i++)
2149 | {
2150 | _processorActiveThreads[i] = DefaultProcessorValue;
2151 | _processorActiveProcesses[i] = DefaultProcessorValue;
2152 | }
2153 |
2154 | // Create the last cswitch time vector
2155 | _lastCSwitch = new double[_logicalProcessorCount];
2156 | for (int i = 0; i < _lastCSwitch.Count(); i++)
2157 | {
2158 | // Start it at a very negative value since timestamps usually start out negative
2159 | _lastCSwitch[i] = -110000;
2160 | }
2161 |
2162 | // Kernel addresses
2163 | _debugLog.WriteLine("ntoskrnl.exe version: " +
2164 | FileVersionInfo.GetVersionInfo(
2165 | Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
2166 | _ntKernelImageName)).ProductVersion);
2167 | _debugLog.WriteLine("NT: {0:X}", _ntKernelAddress);
2168 | _debugLog.Flush();
2169 |
2170 | // The session name for the ETW trace has to be NT Kernel Logger for doing the kernel logging.
2171 | // Relevant links:
2172 | // http://stackoverflow.com/questions/16068051/consuming-an-etw-kernel-trace-using-c-sharp
2173 | // http://blogs.msdn.com/b/vancem/archive/2013/03/09/using-traceevent-to-mine-information-in-os-registered-etw-providers.aspx
2174 |
2175 | // Opens up a real time session for the trace events. Details about using statement http://msdn.microsoft.com/en-us/library/yh598w02.aspx
2176 | using (var eventTracingSession = new TraceEventSession(KernelTraceEventParser.KernelSessionName))
2177 | // the null second parameter means 'real time session'
2178 | {
2179 | // Save it as an instance variable
2180 | _eventTracingSession = eventTracingSession;
2181 |
2182 | // Select those providers that we want data from: PRocess, Thread, and Context switch.
2183 | eventTracingSession.EnableKernelProvider(KernelTraceEventParser.Keywords.ContextSwitch |
2184 | KernelTraceEventParser.Keywords.Process |
2185 | KernelTraceEventParser.Keywords.Thread |
2186 | KernelTraceEventParser.Keywords.SystemCall);
2187 | // Need to figure out whether DPC or anything else belongs here.
2188 |
2189 | // Setup the handlers
2190 | eventTracingSession.Source.Kernel.PerfInfoSysClEnter += SystemCallEnter;
2191 | eventTracingSession.Source.Kernel.ThreadCSwitch += ContextSwitch;
2192 |
2193 |
2194 | eventTracingSession.Source.Kernel.ThreadStart += ThreadStart;
2195 | eventTracingSession.Source.Kernel.ThreadDCStart += ThreadDcStart;
2196 | eventTracingSession.Source.Kernel.ThreadStop += ThreadStop;
2197 | eventTracingSession.Source.Kernel.ThreadDCStop += ThreadStop;
2198 |
2199 | eventTracingSession.Source.Kernel.ProcessStop += ProcessStop;
2200 | eventTracingSession.Source.Kernel.ProcessDCStop += ProcessStop;
2201 |
2202 |
2203 | eventTracingSession.Source.Kernel.ProcessStart += ProcessStart;
2204 | eventTracingSession.Source.Kernel.ProcessDCStart += ProcessDcStart;
2205 |
2206 | // Start the timer
2207 | _timer.Start();
2208 |
2209 | // Start Processing
2210 | try
2211 | {
2212 | eventTracingSession.Source.Process();
2213 | }
2214 | catch (Exception e)
2215 | {
2216 | _debugLog.WriteLine("FATAL ERROR: Exception in event processing.");
2217 | _debugLog.WriteLine(e.ToString());
2218 | _debugLog.WriteLine(e.StackTrace);
2219 | _eventLog.WriteEntry("Exception in event processing", EventLogEntryType.Error);
2220 | _eventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
2221 | }
2222 |
2223 | _debugLog.Flush();
2224 |
2225 | // If processing has stopped, commit!
2226 | _database.Commit();
2227 |
2228 | if (_profileCode)
2229 | {
2230 | foreach (string str in _codeProfileKeys)
2231 | {
2232 | _debugLog.WriteLine(str + " " + _codeProfileCounters[str] + " calls " +
2233 | _codeProfileTimers[str].ElapsedMilliseconds + " ms " +
2234 | _codeProfileTimers[str].ElapsedMilliseconds/
2235 | (float) _codeProfileCounters[str] + " ms per");
2236 | }
2237 | }
2238 | _eventLog.WriteEntry("Processing stopped", EventLogEntryType.Information);
2239 | _debugLog.WriteLine("Lost events: " + eventTracingSession.Source.EventsLost +
2240 | " Ideally, this number should be zero");
2241 | _debugLog.Flush();
2242 | }
2243 |
2244 |
2245 | //Cleanup all the old data lying around.
2246 | foreach (var process in _activeThreadsByProcess.Values)
2247 | {
2248 | foreach (var thread in process.Values)
2249 | {
2250 | if (thread.Counter != null)
2251 | {
2252 | thread.Counter.Close();
2253 | thread.Counter = null;
2254 | }
2255 | }
2256 | }
2257 |
2258 | foreach (var process in _unkownThreads.Values)
2259 | {
2260 | if (process.Counter != null)
2261 | {
2262 | process.Counter.Close();
2263 | process.Counter = null;
2264 | }
2265 | }
2266 |
2267 | foreach (var process in _processesToDelete)
2268 | {
2269 | if (process.Counter != null)
2270 | {
2271 | process.Counter.Close();
2272 | process.Counter = null;
2273 | }
2274 | }
2275 |
2276 | foreach (var process in _threadsToDelete)
2277 | {
2278 | if (process.Counter != null)
2279 | {
2280 | process.Counter.Close();
2281 | process.Counter = null;
2282 | }
2283 | }
2284 |
2285 | foreach (var process in _activeProcesses.Values)
2286 | {
2287 | if (process.Counter != null)
2288 | {
2289 | process.Counter.Close();
2290 | process.Counter = null;
2291 | }
2292 | }
2293 |
2294 | _database.Commit();
2295 | _database.CloseConnection();
2296 |
2297 | _debugLog.Flush();
2298 | _debugLog.Close();
2299 | _debugLog = null;
2300 |
2301 | _systemWideCounter.Close();
2302 |
2303 | SQLiteConnection.ClearAllPools();
2304 | GC.Collect();
2305 | GC.WaitForPendingFinalizers();
2306 | }
2307 |
2308 | ///
2309 | /// Stops the event tracing session
2310 | ///
2311 | /// Indicates service should be stopped.
2312 | public void Stop(bool stopService)
2313 | {
2314 | _endService = stopService;
2315 | _debugLog.WriteLine("SyscallCounter.Stop()");
2316 | _eventTracingSession.Stop();
2317 | }
2318 |
2319 | ///
2320 | /// Timer for resetting the service
2321 | ///
2322 | /// Timer source
2323 | /// Time arguments
2324 | private void ResetTimerEvent(object source, ElapsedEventArgs e)
2325 | {
2326 | _debugLog.WriteLine("SyscallCounter.ResetTimerEvent()");
2327 | Stop(false);
2328 | }
2329 | }
2330 | }
--------------------------------------------------------------------------------