forked from bsi-group/dumpntds
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
2,592 additions
and
255 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using System; | ||
using System.Text; | ||
|
||
namespace ditjson | ||
{ | ||
internal static class ByteHelper | ||
{ | ||
|
||
/// <summary> | ||
/// Return the string format of a byte array. | ||
/// </summary> | ||
/// <param name="data"> | ||
/// The data to format. | ||
/// </param> | ||
/// <returns> | ||
/// A string representation of the data. | ||
/// </returns> | ||
/// <exception cref="FormatException"> | ||
/// </exception> | ||
/// <exception cref="OverflowException"> | ||
/// </exception> | ||
internal static string FormatBytes(byte[] data) | ||
{ | ||
if (data == null) | ||
{ | ||
return string.Empty; | ||
} | ||
|
||
var sb = new StringBuilder(data.Length * 2); | ||
foreach (var b in data) | ||
{ | ||
sb.AppendFormat("{0:x2}", b); | ||
} | ||
|
||
return sb.ToString(); | ||
} | ||
|
||
internal static byte[] ConvertHexStringToBytes(string hexString) | ||
{ | ||
if (hexString.Length % 2 != 0) | ||
throw new ArgumentException("Invalid hex string length"); | ||
|
||
var bytes = new byte[hexString.Length / 2]; | ||
for (var i = 0; i < bytes.Length; i++) | ||
{ | ||
var byteValue = hexString.Substring(i * 2, 2); | ||
bytes[i] = Convert.ToByte(byteValue, 16); | ||
} | ||
return bytes; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text.Json; | ||
using Microsoft.Isam.Esent.Interop; | ||
|
||
namespace ditjson | ||
{ | ||
internal static class NtdsData | ||
{ | ||
private static readonly JsonSerializerOptions options = new() | ||
{ | ||
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, | ||
NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.Strict, | ||
WriteIndented = true, | ||
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping, | ||
}; | ||
|
||
internal static string TablesToJson(Session session, JET_DBID dbid, List<string> tables) | ||
{ | ||
var ntdsDictionary = new Dictionary<string, object>(); | ||
foreach (var table in tables) | ||
{ | ||
ntdsDictionary.Add(table, TableToList(session, dbid, table)); | ||
} | ||
|
||
string json; | ||
try | ||
{ | ||
json = JsonSerializer.Serialize(ntdsDictionary, options); | ||
Check warning on line 29 in source/ditjson/NtdsData.cs GitHub Actions / Release (linux)
Check warning on line 29 in source/ditjson/NtdsData.cs GitHub Actions / Release (macOS)
|
||
} | ||
catch (NotSupportedException ex) | ||
{ | ||
throw new NtdsException("Failed to serialize to JSON.", ex); | ||
} | ||
|
||
return json; | ||
} | ||
|
||
/// <summary> | ||
/// Export table as a <see cref="List{Dictionary{string, object}}" /> | ||
/// </summary> | ||
/// <param name="session"> | ||
/// ESENT Session | ||
/// </param> | ||
/// <param name="dbid"> | ||
/// Handle to the database | ||
/// </param> | ||
/// <returns> | ||
/// A <see cref="List{Dictionary{string, object}}" /> containing table data | ||
/// </returns> | ||
/// <exception cref="NtdsException"> | ||
/// </exception> | ||
/// <exception cref="FormatException"> | ||
/// </exception> | ||
/// <exception cref="OverflowException"> | ||
/// </exception> | ||
internal static List<IDictionary<string, object>> TableToList(Session session, JET_DBID dbid, string tableName) | ||
{ | ||
var linktableValues = new List<IDictionary<string, object>>(); | ||
var columns = new List<ColumnInfo>(Api.GetTableColumns(session, dbid, tableName)); | ||
|
||
using (var table = new Table(session, dbid, tableName, OpenTableGrbit.ReadOnly)) | ||
{ | ||
Api.JetSetTableSequential(session, table, SetTableSequentialGrbit.None); | ||
Api.MoveBeforeFirst(session, table); | ||
|
||
var columnids = Api.GetColumnDictionary(session, table); | ||
var formattedData = string.Empty; | ||
while (Api.TryMoveNext(session, table)) | ||
{ | ||
var obj = new Dictionary<string, object>(); | ||
foreach (var column in columns) | ||
{ | ||
var test = columnids[column.Name]; | ||
formattedData = NtdsDataTypes.GetFormattedValue(session, table, column); | ||
var cellValue = formattedData; | ||
|
||
// Ignore emptry or null values | ||
if (!string.IsNullOrEmpty(cellValue)) | ||
{ | ||
if (NtdsMetadata.AttributeMapping.TryGetValue(column.Name, out var mappedValue)) | ||
{ | ||
obj.Add(mappedValue, cellValue); | ||
} | ||
else | ||
{ | ||
obj.Add(column.Name, cellValue); | ||
} | ||
} | ||
} | ||
|
||
linktableValues.Add(obj); | ||
} | ||
|
||
Api.JetResetTableSequential(session, table, ResetTableSequentialGrbit.None); | ||
} | ||
|
||
return linktableValues; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Microsoft.Isam.Esent.Interop; | ||
using Microsoft.Isam.Esent.Interop.Vista; | ||
using Microsoft.Isam.Esent.Interop.Windows10; | ||
|
||
namespace ditjson | ||
{ | ||
internal static class NtdsDataTypes | ||
{ | ||
/// <summary> | ||
/// Extracts the column data as the correct data type and formats appropriately | ||
/// </summary> | ||
/// <param name="session"> | ||
/// </param> | ||
/// <param name="table"> | ||
/// </param> | ||
/// <param name="columnInfo"> | ||
/// </param> | ||
/// <returns> | ||
/// </returns> | ||
/// <exception cref="NtdsException"> | ||
/// </exception> | ||
/// <exception cref="FormatException"> | ||
/// </exception> | ||
/// <exception cref="OverflowException"> | ||
/// </exception> | ||
internal static string GetFormattedValue(Session session, | ||
JET_TABLEID table, | ||
ColumnInfo columnInfo) | ||
{ | ||
var temp = string.Empty; | ||
|
||
// Edge case: link_data_v2 column cannot be retreived properly None of the | ||
// Api.RetrieveColumnXXX commands can process this column. | ||
if (columnInfo.Name.Equals("link_data_v2")) | ||
{ | ||
return temp; | ||
} | ||
|
||
if(columnInfo.Name.Equals("ATTp131353")) | ||
{ | ||
// | ||
} | ||
|
||
if (columnInfo.Grbit.HasFlag(ColumndefGrbit.ColumnMultiValued)) | ||
{ | ||
temp = GetMultipleValues(session, table, columnInfo.Columnid, columnInfo.Coltyp); | ||
} | ||
else | ||
{ | ||
temp = GetSingleValue(session, table, columnInfo.Columnid, columnInfo.Coltyp); | ||
} | ||
|
||
return temp.Replace("\0", string.Empty); | ||
} | ||
|
||
private static string GetMultipleValues(Session session, JET_TABLEID table, JET_COLUMNID columnId, JET_coltyp columnType) | ||
{ | ||
var values = new List<string>(); | ||
|
||
var retrievecolumn = new JET_RETRIEVECOLUMN | ||
{ | ||
columnid = columnId, | ||
itagSequence = 0 | ||
}; | ||
Api.JetRetrieveColumns(session, table, [retrievecolumn], 1); | ||
var count = retrievecolumn.itagSequence; | ||
|
||
if (count != 0) | ||
{ | ||
// itag value starts at 1 | ||
for (var itag = 1; itag <= count; ++itag) | ||
{ | ||
var s = GetSingleValue(session, table, columnId, columnType); | ||
values.Add(s); | ||
} | ||
} | ||
return values.Count > 0 ? string.Join(",", values) : string.Empty; | ||
} | ||
|
||
private static string GetSingleValue(Session session, JET_TABLEID table, JET_COLUMNID columnId, JET_coltyp columnType) | ||
{ | ||
var temp = string.Empty; | ||
switch (columnType) | ||
{ | ||
case JET_coltyp.Bit: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsBoolean(session, table, columnId)); | ||
break; | ||
|
||
case VistaColtyp.LongLong: | ||
case Windows10Coltyp.UnsignedLongLong: | ||
case JET_coltyp.Currency: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsInt64(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.IEEEDouble: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsDouble(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.IEEESingle: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsFloat(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.Long: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsInt32(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.Text: | ||
case JET_coltyp.LongText: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsString(session, table, columnId, Encoding.Unicode, RetrieveColumnGrbit.None)); | ||
break; | ||
|
||
case JET_coltyp.Short: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsInt16(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.UnsignedByte: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsByte(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.DateTime: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsDateTime(session, table, columnId)); | ||
break; | ||
|
||
case VistaColtyp.UnsignedShort: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsUInt16(session, table, columnId)); | ||
break; | ||
|
||
case VistaColtyp.UnsignedLong: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsUInt32(session, table, columnId)); | ||
break; | ||
|
||
case VistaColtyp.GUID: | ||
temp = string.Format("{0}", Api.RetrieveColumnAsGuid(session, table, columnId)); | ||
break; | ||
|
||
case JET_coltyp.Nil: | ||
break; | ||
|
||
case JET_coltyp.Binary: | ||
case JET_coltyp.LongBinary: | ||
var columnBytes = Api.RetrieveColumn(session, table, columnId); | ||
if (columnBytes != null) | ||
{ | ||
temp = ByteHelper.FormatBytes(columnBytes); | ||
} | ||
break; | ||
|
||
default: | ||
throw new NtdsException($"Unhandled column type {columnType} for {columnId}"); | ||
} | ||
|
||
return temp; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.