diff --git a/src/NdisEtl2Pcap.sln b/src/NdisEtl2Pcap.sln
new file mode 100644
index 0000000..0042152
--- /dev/null
+++ b/src/NdisEtl2Pcap.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.28010.2019
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NdisEtl2Pcap", "NdisEtl2Pcap\NdisEtl2Pcap.csproj", "{E62E0034-A80B-4604-B803-F9DA3FCA7C73}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NdisEtl2PcapLib", "NdisEtl2PcapLib\NdisEtl2PcapLib.csproj", "{1861E72D-E4B7-43DF-BCC0-49E3FDD40DA2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E62E0034-A80B-4604-B803-F9DA3FCA7C73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E62E0034-A80B-4604-B803-F9DA3FCA7C73}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E62E0034-A80B-4604-B803-F9DA3FCA7C73}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E62E0034-A80B-4604-B803-F9DA3FCA7C73}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1861E72D-E4B7-43DF-BCC0-49E3FDD40DA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1861E72D-E4B7-43DF-BCC0-49E3FDD40DA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1861E72D-E4B7-43DF-BCC0-49E3FDD40DA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1861E72D-E4B7-43DF-BCC0-49E3FDD40DA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {07C12DCE-39C9-45B8-9165-EE2D8181E54D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/NdisEtl2Pcap/App.config b/src/NdisEtl2Pcap/App.config
new file mode 100644
index 0000000..787dcbe
--- /dev/null
+++ b/src/NdisEtl2Pcap/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/NdisEtl2Pcap/ExceptionTrapper.cs b/src/NdisEtl2Pcap/ExceptionTrapper.cs
new file mode 100644
index 0000000..f1fb80a
--- /dev/null
+++ b/src/NdisEtl2Pcap/ExceptionTrapper.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Text;
+
+namespace NdisEtl2Pcap
+{
+ internal static class ExceptionTrapper
+ {
+ public static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
+ {
+ var ex = (Exception)e.ExceptionObject;
+ var exceptionInfoText = BuildExceptionInformationText(ex);
+ Console.Error.WriteLine("**** EXCEPTION ****");
+ Console.Error.WriteLine(exceptionInfoText);
+ }
+
+ public static string BuildExceptionInformationText(Exception exception)
+ {
+ var builder = new StringBuilder();
+
+ var ex = exception;
+ while (true)
+ {
+ builder.AppendLine(string.Format("{0}: {1}", ex.GetType().FullName, ex.Message));
+
+ // Special handling for each exception type.
+ switch (ex)
+ {
+ case System.ComponentModel.Win32Exception win32Exception:
+ builder.AppendLine(string.Format("NativeErrorCode: {0}", win32Exception.NativeErrorCode));
+ builder.AppendLine(string.Format("ErrorCode: 0x{0:x8}", win32Exception.ErrorCode));
+ builder.AppendLine(string.Format("HResult: 0x{0:x8}", win32Exception.HResult));
+ break;
+ }
+
+ if (ex.Data.Count != 0)
+ {
+ builder.AppendLine("Data:");
+ foreach (string key in ex.Data.Keys)
+ {
+ builder.AppendLine(string.Format(" {0}: {1}", key, ex.Data[key]));
+ }
+ }
+
+ builder.AppendLine("Stack Trace:");
+ builder.AppendLine(ex.StackTrace);
+
+ if (ex.InnerException == null) break;
+
+ ex = ex.InnerException;
+ builder.AppendLine(@"--- Inner exception is below ---");
+ }
+
+ return builder.ToString();
+ }
+ }
+}
diff --git a/src/NdisEtl2Pcap/NdisEtl2Pcap.csproj b/src/NdisEtl2Pcap/NdisEtl2Pcap.csproj
new file mode 100644
index 0000000..fab8e9f
--- /dev/null
+++ b/src/NdisEtl2Pcap/NdisEtl2Pcap.csproj
@@ -0,0 +1,55 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E62E0034-A80B-4604-B803-F9DA3FCA7C73}
+ Exe
+ NdisEtl2Pcap
+ NdisEtl2Pcap
+ v4.7.1
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {1861e72d-e4b7-43df-bcc0-49e3fdd40da2}
+ NdisEtl2PcapLib
+
+
+
+
\ No newline at end of file
diff --git a/src/NdisEtl2Pcap/Program.cs b/src/NdisEtl2Pcap/Program.cs
new file mode 100644
index 0000000..3a47eaa
--- /dev/null
+++ b/src/NdisEtl2Pcap/Program.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Diagnostics;
+using System.Reflection;
+using NdisEtl2PcapLib;
+using NdisEtl2PcapLib.Pcap;
+
+namespace NdisEtl2Pcap
+{
+ internal class Program
+ {
+ private static ResultSummary ResultSummary { get; set; }
+
+ static void Main(string[] args)
+ {
+ AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionTrapper.UnhandledExceptionTrapper);
+
+ if (args.Length < 2)
+ {
+ PrintUsage();
+ return;
+ }
+ var etlFilePath = args[0];
+ var pcapFilePath = args[1];
+
+ ResultSummary = new ResultSummary();
+
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+
+ var packets = LoadNdisRecords(etlFilePath);
+ PcapFile.WritePcapFile(pcapFilePath, packets);
+
+ stopwatch.Stop();
+ ResultSummary.Elapsed = stopwatch.Elapsed;
+
+ PrintResultSummary();
+ }
+
+ private static void PrintUsage()
+ {
+ var exeName = Path.GetFileName(Assembly.GetEntryAssembly().Location);
+ Console.WriteLine("Usage: {0}