Add window to view parsed security descriptor
This commit is contained in:
parent
34fe2749a6
commit
d8008ba896
|
@ -208,6 +208,9 @@
|
|||
<Compile Include="TabPages\RpcServerList.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\SecurityDescriptorView.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Windows\Services.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
@ -248,6 +251,9 @@
|
|||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Windows\SecurityDescriptorView.resx">
|
||||
<DependentUpon>SecurityDescriptorView.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Windows\Services.resx">
|
||||
<DependentUpon>Services.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -20,6 +20,8 @@ using System.Security.AccessControl;
|
|||
using Newtonsoft.Json.Linq;
|
||||
using RpcInvestigator.Util;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.Text;
|
||||
using RpcInvestigator.Windows;
|
||||
|
||||
namespace RpcInvestigator
|
||||
{
|
||||
|
@ -68,14 +70,7 @@ namespace RpcInvestigator
|
|||
{
|
||||
if (col.Name == "SecurityDescriptor")
|
||||
{
|
||||
col.AspectToStringConverter = delegate (object Item)
|
||||
{
|
||||
if (Item == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
return SddlParser.Parse(Item.ToString());
|
||||
};
|
||||
col.IsVisible = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -204,6 +199,7 @@ namespace RpcInvestigator
|
|||
{
|
||||
TabPages.ContextMenu.BuildRightClickMenu(Args, new List<ToolStripMenuItem>{
|
||||
new ToolStripMenuItem("Open in Library", null, ContextMenuOpenAlpcServerInLibrary),
|
||||
new ToolStripMenuItem("View Security Descriptor", null, ContextMenuViewSecurityDescriptor),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -235,5 +231,27 @@ namespace RpcInvestigator
|
|||
};
|
||||
_ = await m_TabManager.LoadRpcLibraryServersTab(filter);
|
||||
}
|
||||
|
||||
private
|
||||
void
|
||||
ContextMenuViewSecurityDescriptor(
|
||||
object Sender,
|
||||
EventArgs Args
|
||||
)
|
||||
{
|
||||
object tag = ((ToolStripMenuItem)Sender).Tag;
|
||||
if (tag == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var args = (CellRightClickEventArgs)tag;
|
||||
var model = args.Model as RpcAlpcServer;
|
||||
var sd = model.SecurityDescriptor;
|
||||
|
||||
var sdView = new SecurityDescriptorView();
|
||||
|
||||
SddlParser.BuildSdView(sdView, sd.ToString());
|
||||
sdView.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ using AceType = NtApiDotNet.AceType;
|
|||
using AceFlags = NtApiDotNet.AceFlags;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using RpcInvestigator.Windows;
|
||||
using System.Windows.Forms;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace RpcInvestigator.Util
|
||||
{
|
||||
|
@ -26,7 +29,7 @@ namespace RpcInvestigator.Util
|
|||
{
|
||||
try
|
||||
{
|
||||
return SidValue.Translate(typeof(NTAccount)).Value;
|
||||
return SidValue.ToString() + " (" + SidValue.Translate(typeof(NTAccount)).Value + ")";
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -34,6 +37,54 @@ namespace RpcInvestigator.Util
|
|||
}
|
||||
}
|
||||
|
||||
private static Ace GetAce(GenericAce ace)
|
||||
{
|
||||
var aceData = new byte[ace.BinaryLength];
|
||||
IntPtr acePointer = Marshal.AllocHGlobal(ace.BinaryLength);
|
||||
IntPtr currentPointer = acePointer;
|
||||
try
|
||||
{
|
||||
ace.GetBinaryForm(aceData, 0);
|
||||
Marshal.Copy(aceData, 0, currentPointer, ace.BinaryLength);
|
||||
var header = (ACE_HEADER)Marshal.PtrToStructure(
|
||||
currentPointer, typeof(ACE_HEADER));
|
||||
//
|
||||
// What follows the header depends on the ACE type, but the
|
||||
// access mask, which is the last part we need, is always
|
||||
// directly after the header.
|
||||
//
|
||||
currentPointer = IntPtr.Add(
|
||||
currentPointer, Marshal.SizeOf(typeof(ACE_HEADER)));
|
||||
var accessMask = Marshal.ReadInt32(currentPointer);
|
||||
currentPointer = IntPtr.Add(currentPointer, 4);
|
||||
var type = (AceType)header.AceType;
|
||||
if (IsObjectAceType(type))
|
||||
{
|
||||
//
|
||||
// Skip 32 bytes (object type and inherited object type)
|
||||
//
|
||||
currentPointer = IntPtr.Add(currentPointer, 32);
|
||||
}
|
||||
|
||||
var sid = new Sid(currentPointer);
|
||||
return new Ace((AceType)header.AceType,
|
||||
(AceFlags)header.AceFlags,
|
||||
accessMask,
|
||||
sid);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace(TraceLoggerType.SddlParser,
|
||||
TraceEventType.Error,
|
||||
"Exception parsing SDDL string: " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(acePointer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string AclToString(RawAcl Acl)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
@ -44,55 +95,44 @@ namespace RpcInvestigator.Util
|
|||
}
|
||||
foreach (var ace in Acl)
|
||||
{
|
||||
var aceData = new byte[ace.BinaryLength];
|
||||
IntPtr acePointer = Marshal.AllocHGlobal(ace.BinaryLength);
|
||||
IntPtr currentPointer = acePointer;
|
||||
try
|
||||
var ntAce = GetAce(ace);
|
||||
if (ntAce != null)
|
||||
{
|
||||
ace.GetBinaryForm(aceData, 0);
|
||||
Marshal.Copy(aceData, 0, currentPointer, ace.BinaryLength);
|
||||
var header = (ACE_HEADER)Marshal.PtrToStructure(
|
||||
currentPointer, typeof(ACE_HEADER));
|
||||
//
|
||||
// What follows the header depends on the ACE type, but the
|
||||
// access mask, which is the last part we need, is always
|
||||
// directly after the header.
|
||||
//
|
||||
currentPointer = IntPtr.Add(
|
||||
currentPointer, Marshal.SizeOf(typeof(ACE_HEADER)));
|
||||
var accessMask = Marshal.ReadInt32(currentPointer);
|
||||
currentPointer = IntPtr.Add(currentPointer, 4);
|
||||
var type = (AceType)header.AceType;
|
||||
if (IsObjectAceType(type))
|
||||
if (ntAce.Type != AceType.Allowed)
|
||||
{
|
||||
//
|
||||
// Skip 32 bytes (object type and inherited object type)
|
||||
//
|
||||
currentPointer = IntPtr.Add(currentPointer, 32);
|
||||
result.Append("Type: " + ntAce.Type.ToString() + ", ");
|
||||
}
|
||||
|
||||
var sid = new Sid(currentPointer);
|
||||
var ntAce = new Ace((AceType)header.AceType,
|
||||
(AceFlags)header.AceFlags,
|
||||
accessMask,
|
||||
sid);
|
||||
result.Append(ntAce.ToString() + ", ");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Trace(TraceLoggerType.SddlParser,
|
||||
TraceEventType.Error,
|
||||
"Exception parsing SDDL string: " + ex.Message);
|
||||
break;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(acePointer);
|
||||
result.Append("Sid: " + ntAce.Sid.ToString() +
|
||||
" (" + ntAce.Sid.Name + ")" +
|
||||
", Mask: " + String.Format("0x{0:X}", ntAce.Mask));
|
||||
result.AppendLine();
|
||||
}
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
private static void AddAclDataToSdView(
|
||||
SecurityDescriptorView SdView,
|
||||
RawAcl Acl
|
||||
)
|
||||
{
|
||||
if (Acl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
foreach (var ace in Acl)
|
||||
{
|
||||
var ntAce = GetAce(ace);
|
||||
if (ntAce != null)
|
||||
{
|
||||
SdView.AddRow(ntAce.Sid.ToString() + " (" + ntAce.Sid.Name + ")",
|
||||
String.Format("0x{0:X}", ntAce.Mask),
|
||||
ntAce.Type.ToString(),
|
||||
ntAce.Flags.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string Parse(string SddlString)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
@ -110,6 +150,7 @@ namespace RpcInvestigator.Util
|
|||
result.AppendLine("Owner: " + SidToString(descriptor.Owner));
|
||||
result.AppendLine("Group: " + SidToString(descriptor.Group));
|
||||
result.Append("Discretionary ACL: ");
|
||||
result.AppendLine();
|
||||
result.Append(AclToString(descriptor.DiscretionaryAcl));
|
||||
result.AppendLine();
|
||||
result.Append("System ACL: ");
|
||||
|
@ -117,6 +158,27 @@ namespace RpcInvestigator.Util
|
|||
result.AppendLine();
|
||||
return result.ToString();
|
||||
}
|
||||
|
||||
public static void BuildSdView(
|
||||
SecurityDescriptorView SdView,
|
||||
string SddlString
|
||||
)
|
||||
{
|
||||
RawSecurityDescriptor descriptor;
|
||||
try
|
||||
{
|
||||
descriptor = new RawSecurityDescriptor(SddlString);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Unable to create RawSecurityDescriptor from " +
|
||||
"the provided SDDL string '" + SddlString + "': " + ex.Message);
|
||||
}
|
||||
|
||||
SdView.AddOwner(SidToString(descriptor.Owner));
|
||||
SdView.AddGroup(SidToString(descriptor.Group));
|
||||
AddAclDataToSdView(SdView, descriptor.DiscretionaryAcl);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace RpcInvestigator.Windows
|
||||
{
|
||||
public partial class SecurityDescriptorView : Form
|
||||
{
|
||||
private DataGridView dataGridView1;
|
||||
private RichTextBox richTextBox1;
|
||||
private DataGridViewTextBoxColumn Sid;
|
||||
private DataGridViewTextBoxColumn Mask;
|
||||
private DataGridViewTextBoxColumn Type;
|
||||
private DataGridViewTextBoxColumn Flags;
|
||||
private CheckedListBox checkedListBox1;
|
||||
private Button button1;
|
||||
|
||||
public SecurityDescriptorView(
|
||||
|
||||
)
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void AddRow(
|
||||
string Sid,
|
||||
string Mask,
|
||||
string Type,
|
||||
string Flags
|
||||
)
|
||||
{
|
||||
this.dataGridView1.Rows.Add(Sid, Mask, Type, Flags);
|
||||
}
|
||||
|
||||
public void AddOwner(
|
||||
string Owner
|
||||
)
|
||||
{
|
||||
this.richTextBox1.Text += "Owner: " + Owner + "\n";
|
||||
}
|
||||
public void AddGroup(
|
||||
string Group
|
||||
)
|
||||
{
|
||||
this.richTextBox1.Text += "Group: " + Group + "\n";
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.dataGridView1 = new System.Windows.Forms.DataGridView();
|
||||
this.Sid = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Mask = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Type = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.Flags = new System.Windows.Forms.DataGridViewTextBoxColumn();
|
||||
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
|
||||
this.checkedListBox1 = new System.Windows.Forms.CheckedListBox();
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.button1.Location = new System.Drawing.Point(543, 262);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(71, 26);
|
||||
this.button1.TabIndex = 0;
|
||||
this.button1.Text = "OK";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// dataGridView1
|
||||
//
|
||||
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
|
||||
this.Sid,
|
||||
this.Mask,
|
||||
this.Type,
|
||||
this.Flags});
|
||||
this.dataGridView1.Location = new System.Drawing.Point(12, 12);
|
||||
this.dataGridView1.Name = "dataGridView1";
|
||||
this.dataGridView1.RowHeadersWidth = 102;
|
||||
this.dataGridView1.Size = new System.Drawing.Size(602, 140);
|
||||
this.dataGridView1.TabIndex = 1;
|
||||
this.dataGridView1.CellClick += DataGridView1_CellClick;
|
||||
this.dataGridView1.CellEnter += DataGridView1_CellClick;
|
||||
//
|
||||
// Sid
|
||||
//
|
||||
this.Sid.HeaderText = "Sid";
|
||||
this.Sid.MinimumWidth = 12;
|
||||
this.Sid.Name = "Sid";
|
||||
this.Sid.ReadOnly = true;
|
||||
this.Sid.Width = 250;
|
||||
//
|
||||
// Mask
|
||||
//
|
||||
this.Mask.HeaderText = "Mask";
|
||||
this.Mask.MinimumWidth = 12;
|
||||
this.Mask.Name = "Mask";
|
||||
this.Mask.ReadOnly = true;
|
||||
this.Mask.Width = 50;
|
||||
//
|
||||
// Type
|
||||
//
|
||||
this.Type.HeaderText = "Type";
|
||||
this.Type.MinimumWidth = 12;
|
||||
this.Type.Name = "Type";
|
||||
this.Type.ReadOnly = true;
|
||||
this.Type.Width = 70;
|
||||
//
|
||||
// Flags
|
||||
//
|
||||
this.Flags.HeaderText = "Flags";
|
||||
this.Flags.MinimumWidth = 12;
|
||||
this.Flags.Name = "Flags";
|
||||
this.Flags.ReadOnly = true;
|
||||
this.Flags.Width = 50;
|
||||
//
|
||||
// richTextBox1
|
||||
//
|
||||
this.richTextBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.richTextBox1.Location = new System.Drawing.Point(12, 158);
|
||||
this.richTextBox1.Name = "richTextBox1";
|
||||
this.richTextBox1.ReadOnly = true;
|
||||
this.richTextBox1.Size = new System.Drawing.Size(304, 100);
|
||||
this.richTextBox1.TabIndex = 2;
|
||||
this.richTextBox1.Text = "";
|
||||
//
|
||||
// checkedListBox1
|
||||
//
|
||||
this.checkedListBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.checkedListBox1.FormattingEnabled = true;
|
||||
this.checkedListBox1.Items.AddRange(new object[] {
|
||||
"Connect",
|
||||
"Delete",
|
||||
"Read Control",
|
||||
"Write DAC",
|
||||
"Write Owner",
|
||||
"Synchronize"});
|
||||
this.checkedListBox1.Location = new System.Drawing.Point(322, 158);
|
||||
this.checkedListBox1.Name = "checkedListBox1";
|
||||
this.checkedListBox1.SelectionMode = System.Windows.Forms.SelectionMode.None;
|
||||
this.checkedListBox1.Size = new System.Drawing.Size(292, 100);
|
||||
this.checkedListBox1.TabIndex = 3;
|
||||
//
|
||||
// SecurityDescriptorView
|
||||
//
|
||||
this.ClientSize = new System.Drawing.Size(626, 300);
|
||||
this.Controls.Add(this.checkedListBox1);
|
||||
this.Controls.Add(this.richTextBox1);
|
||||
this.Controls.Add(this.dataGridView1);
|
||||
this.Controls.Add(this.button1);
|
||||
this.Name = "SecurityDescriptorView";
|
||||
this.Text = "Security Descriptor";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.SecurityDescriptorView_FormClosing);
|
||||
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
private void DataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void SecurityDescriptorView_FormClosing(object sender, EventArgs e)
|
||||
{
|
||||
//Close();
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private void DataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
|
||||
{
|
||||
foreach (int i in this.checkedListBox1.CheckedIndices)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(i, CheckState.Unchecked);
|
||||
}
|
||||
int rowIndex = e.RowIndex;
|
||||
DataGridViewRow row = dataGridView1.Rows[rowIndex];
|
||||
foreach (DataGridViewCell cell in row.Cells)
|
||||
{
|
||||
if (cell.OwningColumn.Name == "Mask")
|
||||
{
|
||||
if (cell.Value == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
var mask = Convert.ToInt32(cell.Value.ToString(), 16);
|
||||
if ((mask & 1) == 1)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(0, CheckState.Checked);
|
||||
}
|
||||
if ((mask & 0x10000) == 0x10000)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(1, CheckState.Checked);
|
||||
}
|
||||
if ((mask & 0x20000) == 0x20000)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(2, CheckState.Checked);
|
||||
}
|
||||
if ((mask & 0x40000) == 0x40000)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(3, CheckState.Checked);
|
||||
}
|
||||
if ((mask & 0x80000) == 0x80000)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(4, CheckState.Checked);
|
||||
}
|
||||
if ((mask & 0x100000) == 0x100000)
|
||||
{
|
||||
this.checkedListBox1.SetItemCheckState(1, CheckState.Checked);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="Sid.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="Mask.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="Type.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
<metadata name="Flags.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<value>True</value>
|
||||
</metadata>
|
||||
</root>
|
Loading…
Reference in New Issue