Creating a shared folder programaticly with ABE - c#

I am creating a Shared folder on a remote computer/server and have this working but am unable to find if it is possible to change the share settings. I would like to be able to turn off Allow caching of share and turn on Access-based Enumeration but am unable to find anything on this on here and through searching google. Does anybody know if this is possible with C#?
The code i am using to create the share is:
public static void CreateRemoteShare(string servername, string FolderPath, string ShareName, string Description)
{
try
{
string scope = string.Format("\\\\{0}\\root\\cimv2", servername);
ManagementScope ms = new ManagementScope(scope);
ManagementClass managementClass = new ManagementClass("Win32_Share");
managementClass.Scope = ms;
ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
ManagementBaseObject outParams;
inParams["Description"] = Description;
inParams["Name"] = ShareName;
inParams["Path"] = FolderPath;
inParams["Type"] = 0x0;
NTAccount everyoneAccount = new NTAccount(null, "EVERYONE");
SecurityIdentifier sid = (SecurityIdentifier)everyoneAccount.Translate(typeof(SecurityIdentifier));
byte[] sidArray = new byte[sid.BinaryLength];
sid.GetBinaryForm(sidArray, 0);
ManagementObject everyone = new ManagementClass("Win32_Trustee");
everyone["Domain"] = null;
everyone["Name"] = "EVERYONE";
everyone["SID"] = sidArray;
ManagementObject dacl = new ManagementClass("Win32_Ace");
dacl["AccessMask"] = 2032127;
dacl["AceFlags"] = 3;
dacl["AceType"] = 0;
dacl["Trustee"] = everyone;
ManagementObject securityDescriptor = new ManagementClass("Win32_SecurityDescriptor");
securityDescriptor["ControlFlags"] = 4; //SE_DACL_PRESENT
securityDescriptor["DACL"] = new object[] { dacl };
inParams["Access"] = securityDescriptor;
outParams = managementClass.InvokeMethod("Create", inParams, null);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
If anybody knows of any way to do this i would be eternaly greatfull.

After looking in to this a bit more i found a site that contained a way to do it in PowerShell and from the site i added this to my C# code. The site is: ABE Powershell
The resulting code extracted is as follows:
public enum Share_Type : uint
{
STYPE_DISKTREE = 0x00000000, // Disk Drive
STYPE_PRINTQ = 0x00000001, // Print Queue
STYPE_DEVICE = 0x00000002, // Communications Device
STYPE_IPC = 0x00000003, // InterProcess Communications
STYPE_SPECIAL = 0x80000000, // Special share types (C$, ADMIN$, IPC$, etc)
STYPE_TEMPORARY = 0x40000000 // Temporary share
}
public enum Share_ReturnValue : int
{
NERR_Success = 0,
ERROR_ACCESS_DENIED = 5,
ERROR_NOT_ENOUGH_MEMORY = 8,
ERROR_INVALID_PARAMETER = 87,
ERROR_INVALID_LEVEL = 124, // unimplemented level for info
ERROR_MORE_DATA = 234,
NERR_BufTooSmall = 2123, // The API return buffer is too small.
NERR_NetNameNotFound = 2310 // This shared resource does not exist.
}
[System.Flags]
public enum Shi1005_flags
{
SHI1005_FLAGS_DFS = 0x0001, // Part of a DFS tree (Cannot be set)
SHI1005_FLAGS_DFS_ROOT = 0x0002, // Root of a DFS tree (Cannot be set)
SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS = 0x0100, // Disallow Exclusive file open
SHI1005_FLAGS_FORCE_SHARED_DELETE = 0x0200, // Open files can be force deleted
SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING = 0x0400, // Clients can cache the namespace
SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM = 0x0800, // Only directories for which a user has FILE_LIST_DIRECTORY will be listed
SHI1005_FLAGS_FORCE_LEVELII_OPLOCK = 0x1000, // Prevents exclusive caching
SHI1005_FLAGS_ENABLE_HASH = 0x2000, // Used for server side support for peer caching
SHI1005_FLAGS_ENABLE_CA = 0X4000 // Used for Clustered shares
}
public static class NetApi32
{
// ********** Structures **********
// SHARE_INFO_502
[StructLayout(LayoutKind.Sequential)]
public struct SHARE_INFO_502
{
[MarshalAs(UnmanagedType.LPWStr)]
public string shi502_netname;
public uint shi502_type;
[MarshalAs(UnmanagedType.LPWStr)]
public string shi502_remark;
public Int32 shi502_permissions;
public Int32 shi502_max_uses;
public Int32 shi502_current_uses;
[MarshalAs(UnmanagedType.LPWStr)]
public string shi502_path;
public IntPtr shi502_passwd;
public Int32 shi502_reserved;
public IntPtr shi502_security_descriptor;
}
// SHARE_INFO_1005
[StructLayout(LayoutKind.Sequential)]
public struct SHARE_INFO_1005
{
public Int32 Shi1005_flags;
}
private class unmanaged
{
//NetShareGetInfo
[DllImport("Netapi32.dll", SetLastError = true)]
internal static extern int NetShareGetInfo(
[MarshalAs(UnmanagedType.LPWStr)] string serverName,
[MarshalAs(UnmanagedType.LPWStr)] string netName,
Int32 level,
ref IntPtr bufPtr
);
[DllImport("Netapi32.dll", SetLastError = true)]
public extern static Int32 NetShareSetInfo(
[MarshalAs(UnmanagedType.LPWStr)] string servername,
[MarshalAs(UnmanagedType.LPWStr)] string netname, Int32 level, IntPtr bufptr, out Int32 parm_err);
}
// ***** Functions *****
public static SHARE_INFO_502 NetShareGetInfo_502(string ServerName, string ShareName)
{
Int32 level = 502;
IntPtr lShareInfo = IntPtr.Zero;
SHARE_INFO_502 shi502_Info = new SHARE_INFO_502();
Int32 result = unmanaged.NetShareGetInfo(ServerName, ShareName, level, ref lShareInfo);
if ((Share_ReturnValue)result == Share_ReturnValue.NERR_Success)
{
shi502_Info = (SHARE_INFO_502)Marshal.PtrToStructure(lShareInfo, typeof(SHARE_INFO_502));
}
else
{
throw new Exception("Unable to get 502 structure. Function returned: " + (Share_ReturnValue)result);
}
return shi502_Info;
}
public static SHARE_INFO_1005 NetShareGetInfo_1005(string ServerName, string ShareName)
{
Int32 level = 1005;
IntPtr lShareInfo = IntPtr.Zero;
SHARE_INFO_1005 shi1005_Info = new SHARE_INFO_1005();
Int32 result = unmanaged.NetShareGetInfo(ServerName, ShareName, level, ref lShareInfo);
if ((Share_ReturnValue)result == Share_ReturnValue.NERR_Success)
{
shi1005_Info = (SHARE_INFO_1005)Marshal.PtrToStructure(lShareInfo, typeof(SHARE_INFO_1005));
}
else
{
throw new Exception("Unable to get 1005 structure. Function returned: " + (Share_ReturnValue)result);
}
return shi1005_Info;
}
public static int NetShareSetInfo_1005(string ServerName, string ShareName, SHARE_INFO_1005 shi1005_Info) // Int32 Shi1005_flags
{
Int32 level = 1005;
Int32 err;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(shi1005_Info));
Marshal.StructureToPtr(shi1005_Info, ptr, false);
var result = unmanaged.NetShareSetInfo(ServerName, ShareName, level, ptr, out err);
return result;
}
}
static void Main(string[] args)
{
abeTest();
}
public static void abeTest()
{
NetApi32.SHARE_INFO_1005 test = new NetApi32.SHARE_INFO_1005();
test.Shi1005_flags = 2048;
NetApi32.NetShareSetInfo_1005("FileStore2", "TestShare2$", test);
}
By combining both this and the above code you are able to create a share and set the access based enumeration.

Related

Extracting Windows File Properties (Custom Properties) C#

In Word/Excel you have to possibility to add Custom properties. (See Image)
Custom Properties.
As you guys can see there is the field: "Properties:", you can add any information you want there.
When you save the file and you go to the file location in the folder, you can right click -> Properties and you have all the tabs: General/Security/Details/Previous Versions. with the feature you add the tab Custom.
Now I want to get this information through coding: Custom Properties information. and extract it later to notepad.
So far i used the Shell32 but then I only get the information that is in the Details tab. I did some research and saw some possibilities with DSOfile.dll. But I want to know if there is a possibility to do this without installing other DLL?
This is my code so far with the Shell32.
static void Main(string[] args)
{
//using (StreamWriter writer = new StreamWriter(#"filepathhere"))
//{
//Console.SetOut(writer);
ReadProperties();
//}
}
static void ReadProperties()
{
List<string> arrHeaders = new List<string>();
Shell shell = new Shell();
Folder objFolder = shell.NameSpace(#"filepathhere");
FolderItem objFolderItem = objFolder.ParseName("filehere.doc");
for (int i = 0; i < short.MaxValue; i++)
{
string header = objFolder.GetDetailsOf(objFolder, i);
if (String.IsNullOrEmpty(header))
break;
arrHeaders.Add(header);
}
for ( int i = 0; i < arrHeaders.Count; i++)
{
Console.WriteLine("{0}\t{1}: {2}", i, arrHeaders[i], objFolder.GetDetailsOf(objFolderItem, i));
}
Console.ReadKey();
}
Thanks in advance!
Desu
Historically these properties were defined by the technology called "Structured Storage". The first Structured Storage implementation is the ancient (but still very alive) Compound File Format
After that, Microsoft added Structured Storage capabilities directly into NTFS. This allows you to define properties like author or title on any files (even .txt) files. Although the Explorer UI does not let you do this anymore for some reason, I think it still works programmatically.
And then, with Vista, Microsoft rebooted all that and introduced a superset of all this: the Windows Property System.
Unfortunately, there is no .NET API in the framework for all this. But Microsoft created an open source .NET library called the Windows API CodePack. So, the easiest way for you to extract properties is to add a reference to the WindowsAPICodePack Core NugetPackage and you can use it like this:
static void Main(string[] args)
{
foreach (var prop in new ShellPropertyCollection(#"mypath\myfile"))
{
Console.WriteLine(prop.CanonicalName + "=" + prop.ValueAsObject);
}
}
If you don't want to add extra DLLs, then you can extract the ShellPropertyCollection code from the WindowsAPICodePack source (Windows API Code Pack: Where is it?). It's quite a work but doable.
Another solution in your case, is to use the old Structure Storage native API. I've provided a sample that does this. Here is how you can use it:
static void Main(string[] args)
{
foreach (var prop in new StructuredStorage(#"mypath\myfile").Properties)
{
Console.WriteLine(prop.Name + "=" + prop.Value);
}
}
public sealed class StructuredStorage
{
public static readonly Guid SummaryInformationFormatId = new Guid("{F29F85E0-4FF9-1068-AB91-08002B27B3D9}");
public static readonly Guid DocSummaryInformationFormatId = new Guid("{D5CDD502-2E9C-101B-9397-08002B2CF9AE}");
public static readonly Guid UserDefinedPropertiesId = new Guid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
private List<StructuredProperty> _properties = new List<StructuredProperty>();
public StructuredStorage(string filePath)
{
if (filePath == null)
throw new ArgumentNullException("filePath");
FilePath = filePath;
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);
if (hr != 0)
throw new Win32Exception(hr);
try
{
LoadPropertySet(propertySetStorage, SummaryInformationFormatId);
LoadPropertySet(propertySetStorage, DocSummaryInformationFormatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}
// for some reason we can't read this one on the same COM ref?
LoadProperties(UserDefinedPropertiesId);
}
public string FilePath { get; private set; }
public IReadOnlyList<StructuredProperty> Properties
{
get
{
return _properties;
}
}
private void LoadPropertySet(IPropertySetStorage propertySetStorage, Guid fmtid)
{
IPropertyStorage propertyStorage;
int hr = propertySetStorage.Open(fmtid, STGM.STGM_READ | STGM.STGM_SHARE_EXCLUSIVE, out propertyStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_ACCESSDENIED)
return;
if (hr != 0)
throw new Win32Exception(hr);
IEnumSTATPROPSTG es;
propertyStorage.Enum(out es);
if (es == null)
return;
try
{
var stg = new STATPROPSTG();
int fetched;
do
{
hr = es.Next(1, ref stg, out fetched);
if (hr != 0 && hr != 1)
throw new Win32Exception(hr);
if (fetched == 1)
{
string name = GetPropertyName(fmtid, propertyStorage, stg);
var propsec = new PROPSPEC[1];
propsec[0] = new PROPSPEC();
propsec[0].ulKind = stg.lpwstrName != null ? PRSPEC.PRSPEC_LPWSTR : PRSPEC.PRSPEC_PROPID;
IntPtr lpwstr = IntPtr.Zero;
if (stg.lpwstrName != null)
{
lpwstr = Marshal.StringToCoTaskMemUni(stg.lpwstrName);
propsec[0].union.lpwstr = lpwstr;
}
else
{
propsec[0].union.propid = stg.propid;
}
var vars = new PROPVARIANT[1];
vars[0] = new PROPVARIANT();
try
{
hr = propertyStorage.ReadMultiple(1, propsec, vars);
if (hr != 0)
throw new Win32Exception(hr);
}
finally
{
if (lpwstr != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(lpwstr);
}
}
object value;
try
{
switch (vars[0].vt)
{
case VARTYPE.VT_BOOL:
value = vars[0].union.boolVal != 0 ? true : false;
break;
case VARTYPE.VT_BSTR:
value = Marshal.PtrToStringUni(vars[0].union.bstrVal);
break;
case VARTYPE.VT_CY:
value = decimal.FromOACurrency(vars[0].union.cyVal);
break;
case VARTYPE.VT_DATE:
value = DateTime.FromOADate(vars[0].union.date);
break;
case VARTYPE.VT_DECIMAL:
IntPtr dec = IntPtr.Zero;
Marshal.StructureToPtr(vars[0], dec, false);
value = Marshal.PtrToStructure(dec, typeof(decimal));
break;
case VARTYPE.VT_DISPATCH:
value = Marshal.GetObjectForIUnknown(vars[0].union.pdispVal);
break;
case VARTYPE.VT_ERROR:
case VARTYPE.VT_HRESULT:
value = vars[0].union.scode;
break;
case VARTYPE.VT_FILETIME:
value = DateTime.FromFileTime(vars[0].union.filetime);
break;
case VARTYPE.VT_I1:
value = vars[0].union.cVal;
break;
case VARTYPE.VT_I2:
value = vars[0].union.iVal;
break;
case VARTYPE.VT_I4:
value = vars[0].union.lVal;
break;
case VARTYPE.VT_I8:
value = vars[0].union.hVal;
break;
case VARTYPE.VT_INT:
value = vars[0].union.intVal;
break;
case VARTYPE.VT_LPSTR:
value = Marshal.PtrToStringAnsi(vars[0].union.pszVal);
break;
case VARTYPE.VT_LPWSTR:
value = Marshal.PtrToStringUni(vars[0].union.pwszVal);
break;
case VARTYPE.VT_R4:
value = vars[0].union.fltVal;
break;
case VARTYPE.VT_R8:
value = vars[0].union.dblVal;
break;
case VARTYPE.VT_UI1:
value = vars[0].union.bVal;
break;
case VARTYPE.VT_UI2:
value = vars[0].union.uiVal;
break;
case VARTYPE.VT_UI4:
value = vars[0].union.ulVal;
break;
case VARTYPE.VT_UI8:
value = vars[0].union.uhVal;
break;
case VARTYPE.VT_UINT:
value = vars[0].union.uintVal;
break;
case VARTYPE.VT_UNKNOWN:
value = Marshal.GetObjectForIUnknown(vars[0].union.punkVal);
break;
default:
value = null;
break;
}
}
finally
{
PropVariantClear(ref vars[0]);
}
var property = new StructuredProperty(fmtid, name, stg.propid);
property.Value = value;
_properties.Add(property);
}
}
while (fetched == 1);
}
finally
{
Marshal.ReleaseComObject(es);
}
}
private static string GetPropertyName(Guid fmtid, IPropertyStorage propertyStorage, STATPROPSTG stg)
{
if (!string.IsNullOrEmpty(stg.lpwstrName))
return stg.lpwstrName;
var propids = new int[1];
propids[0] = stg.propid;
var names = new string[1];
names[0] = null;
int hr = propertyStorage.ReadPropertyNames(1, propids, names);
if (hr == 0)
return names[0];
return null;
}
public void LoadProperties(Guid formatId)
{
IPropertySetStorage propertySetStorage;
int hr = StgOpenStorageEx(FilePath, STGM.STGM_READ | STGM.STGM_SHARE_DENY_NONE | STGM.STGM_DIRECT_SWMR, STGFMT.STGFMT_ANY, 0, IntPtr.Zero, IntPtr.Zero, typeof(IPropertySetStorage).GUID, out propertySetStorage);
if (hr == STG_E_FILENOTFOUND || hr == STG_E_PATHNOTFOUND)
throw new FileNotFoundException(null, FilePath);
if (hr != 0)
throw new Win32Exception(hr);
try
{
LoadPropertySet(propertySetStorage, formatId);
}
finally
{
Marshal.ReleaseComObject(propertySetStorage);
}
}
private const int STG_E_FILENOTFOUND = unchecked((int)0x80030002);
private const int STG_E_PATHNOTFOUND = unchecked((int)0x80030003);
private const int STG_E_ACCESSDENIED = unchecked((int)0x80030005);
private enum PRSPEC
{
PRSPEC_LPWSTR = 0,
PRSPEC_PROPID = 1
}
private enum STGFMT
{
STGFMT_ANY = 4,
}
[Flags]
private enum STGM
{
STGM_READ = 0x00000000,
STGM_READWRITE = 0x00000002,
STGM_SHARE_DENY_NONE = 0x00000040,
STGM_SHARE_DENY_WRITE = 0x00000020,
STGM_SHARE_EXCLUSIVE = 0x00000010,
STGM_DIRECT_SWMR = 0x00400000
}
// we only define what we handle
private enum VARTYPE : short
{
VT_I2 = 2,
VT_I4 = 3,
VT_R4 = 4,
VT_R8 = 5,
VT_CY = 6,
VT_DATE = 7,
VT_BSTR = 8,
VT_DISPATCH = 9,
VT_ERROR = 10,
VT_BOOL = 11,
VT_UNKNOWN = 13,
VT_DECIMAL = 14,
VT_I1 = 16,
VT_UI1 = 17,
VT_UI2 = 18,
VT_UI4 = 19,
VT_I8 = 20,
VT_UI8 = 21,
VT_INT = 22,
VT_UINT = 23,
VT_HRESULT = 25,
VT_LPSTR = 30,
VT_LPWSTR = 31,
VT_FILETIME = 64,
}
[StructLayout(LayoutKind.Explicit)]
private struct PROPVARIANTunion
{
[FieldOffset(0)]
public sbyte cVal;
[FieldOffset(0)]
public byte bVal;
[FieldOffset(0)]
public short iVal;
[FieldOffset(0)]
public ushort uiVal;
[FieldOffset(0)]
public int lVal;
[FieldOffset(0)]
public uint ulVal;
[FieldOffset(0)]
public int intVal;
[FieldOffset(0)]
public uint uintVal;
[FieldOffset(0)]
public long hVal;
[FieldOffset(0)]
public ulong uhVal;
[FieldOffset(0)]
public float fltVal;
[FieldOffset(0)]
public double dblVal;
[FieldOffset(0)]
public short boolVal;
[FieldOffset(0)]
public int scode;
[FieldOffset(0)]
public long cyVal;
[FieldOffset(0)]
public double date;
[FieldOffset(0)]
public long filetime;
[FieldOffset(0)]
public IntPtr bstrVal;
[FieldOffset(0)]
public IntPtr pszVal;
[FieldOffset(0)]
public IntPtr pwszVal;
[FieldOffset(0)]
public IntPtr punkVal;
[FieldOffset(0)]
public IntPtr pdispVal;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROPSPEC
{
public PRSPEC ulKind;
public PROPSPECunion union;
}
[StructLayout(LayoutKind.Explicit)]
private struct PROPSPECunion
{
[FieldOffset(0)]
public int propid;
[FieldOffset(0)]
public IntPtr lpwstr;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROPVARIANT
{
public VARTYPE vt;
public ushort wReserved1;
public ushort wReserved2;
public ushort wReserved3;
public PROPVARIANTunion union;
}
[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSTG
{
[MarshalAs(UnmanagedType.LPWStr)]
public string lpwstrName;
public int propid;
public VARTYPE vt;
}
[StructLayout(LayoutKind.Sequential)]
private struct STATPROPSETSTG
{
public Guid fmtid;
public Guid clsid;
public uint grfFlags;
public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
public System.Runtime.InteropServices.ComTypes.FILETIME atime;
public uint dwOSVersion;
}
[DllImport("ole32.dll")]
private static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string pwcsName, STGM grfMode, STGFMT stgfmt, int grfAttrs, IntPtr pStgOptions, IntPtr reserved2, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IPropertySetStorage ppObjectOpen);
[DllImport("ole32.dll")]
private static extern int PropVariantClear(ref PROPVARIANT pvar);
[Guid("0000013B-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSETSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSETSTG rgelt, out int pceltFetched);
// rest ommited
}
[Guid("00000139-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IEnumSTATPROPSTG
{
[PreserveSig]
int Next(int celt, ref STATPROPSTG rgelt, out int pceltFetched);
// rest ommited
}
[Guid("00000138-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertyStorage
{
[PreserveSig]
int ReadMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar);
[PreserveSig]
int WriteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPVARIANT[] rgpropvar, uint propidNameFirst);
[PreserveSig]
int DeleteMultiple(uint cpspec, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] PROPSPEC[] rgpspec);
[PreserveSig]
int ReadPropertyNames(uint cpropid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] int[] rgpropid, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0)] string[] rglpwstrName);
[PreserveSig]
int NotDeclared1();
[PreserveSig]
int NotDeclared2();
[PreserveSig]
int Commit(uint grfCommitFlags);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSTG ppenum);
// rest ommited
}
[Guid("0000013A-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IPropertySetStorage
{
[PreserveSig]
int Create([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, [MarshalAs(UnmanagedType.LPStruct)] Guid pclsid, uint grfFlags, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int Open([MarshalAs(UnmanagedType.LPStruct)] Guid rfmtid, STGM grfMode, out IPropertyStorage ppprstg);
[PreserveSig]
int NotDeclared3();
[PreserveSig]
int Enum(out IEnumSTATPROPSETSTG ppenum);
}
}
public sealed class StructuredProperty
{
public StructuredProperty(Guid formatId, string name, int id)
{
FormatId = formatId;
Name = name;
Id = id;
}
public Guid FormatId { get; private set; }
public string Name { get; private set; }
public int Id { get; private set; }
public object Value { get; set; }
public override string ToString()
{
return Name;
}
}
You can try NPOI engine to extract properties from different Office files (doc, xls, xlsx, docx, etc). This component doesn't have any third party dependencies and you don't need Office to use it.
However, this library is a bit tricky because you need to use different types of property extractors for different type of files. Good code sample can be found in official Git Hub repository TestHPSFPropertiesExtractor.
NuGet package can be found here.
There's a set of NuGet packages called NetOffice that you can use. There are packages for each of the Office applications, plus a few core assemblies. Get NetOffice.Word and NetOffice.Excel and install them in your solution. There's a little documentation at the Codeplex site, but I had to browse the source to really understand what was going on. Here's a sample program:
using NetOffice.OfficeApi;
using System;
namespace Office_Doc_Reader
{
class Program
{
static void Main(string[] args)
{
using (var wordApp = new NetOffice.WordApi.Application())
using (var excelApp = new NetOffice.ExcelApi.Application())
{
var doc = wordApp.Documents.Open("C:\\Users\\John\\Desktop\\test.docx");
var xls = excelApp.Workbooks.Open("C:\\Users\\John\\Desktop\\test.xlsx");
var customProperties = (DocumentProperties)doc.CustomDocumentProperties;
foreach (var property in customProperties)
{
Console.WriteLine(String.Format("Name: {0}, Value: {1}, Type: {2}", property.Name, property.Value, property.Type));
}
customProperties = (DocumentProperties)xls.CustomDocumentProperties;
foreach (var property in customProperties)
{
Console.WriteLine(String.Format("Name: {0}, Value: {1}, Type: {2}", property.Name, property.Value, property.Type));
}
}
Console.ReadKey();
}
}
}
That shows the following results:
Name: Custom prop 1, Value: Text Value, Type: msoPropertyTypeString
Name: Custom prop 2, Value: 2/21/2016 12:00:00 AM, Type: msoPropertyTypeDate
Name: Custom prop 3, Value: 42, Type: msoPropertyTypeNumber
Name: Custom prop 4, Value: True, Type: msoPropertyTypeBoolean
Name: Foo, Value: abc, Type: msoPropertyTypeString
Name: Bar, Value: 1/1/1970 12:00:00 AM, Type: msoPropertyTypeDate
Name: Baz, Value: 3.14159, Type: msoPropertyTypeFloat
Name: Qux, Value: False, Type: msoPropertyTypeBoolean
For a Word and Excel file with these properties:
I've not worked with these much at all, so I won't be able to go much deeper than this. Hope it helps.
You may use OpenXml SDK from Microsoft. I believe it is able to get any info from word/excel files.
Have a look at this https://msdn.microsoft.com/en-us/library/office/hh674468.aspx also this https://msdn.microsoft.com/en-us/library/office/bb448854.aspx
or
http://openxmldeveloper.org/
There could be a more generic approach.
If your source is a ...x file, the document can be extracted via XML queries.
If you unzip the file (eg.g with 7-Zip) you will find a file called custom.xml in the subfolder docProps.
The properties can easily be found within the XML file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="SAPDOKNR">
<vt:lpwstr>10002210058</vt:lpwstr>
</property>
...

How to store a password to authenticate to mySQL [duplicate]

In a WPF application, I would like to provide the typical "Remember Me" option to remember credentials and use them automatically next time the application is launched.
Using a one-way hash is clearly not an option, and while I can store credentials in isolated storage or in the registry, there is one issue to deal with when encrypting the credentials.
If I use a symmetric key encryption algorithm, I will need to store the key somewhere. And if the key is, for example, hardcoded in memory, then I imagine it would be easy to disassemble the .NET assemblies and find it.
What is the best way to encrypt credentials in .NET and keep them secure, keeping the encryption key completely out of reach?
Here's a summary of my blog post: How to store a password on Windows?
You can use the Data Protection API and its .NET implementation (ProtectedData) to encrypt the password. Here's an example:
public static string Protect(string str)
{
byte[] entropy = Encoding.ASCII.GetBytes(Assembly.GetExecutingAssembly().FullName);
byte[] data = Encoding.ASCII.GetBytes(str);
string protectedData = Convert.ToBase64String(ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser));
return protectedData;
}
public static string Unprotect(string str)
{
byte[] protectedData = Convert.FromBase64String(str);
byte[] entropy = Encoding.ASCII.GetBytes(Assembly.GetExecutingAssembly().FullName);
string data = Encoding.ASCII.GetString(ProtectedData.Unprotect(protectedData, entropy, DataProtectionScope.CurrentUser));
return data;
}
Or you can use the Windows Credential Manager (This is the way I prefer because it allows users to backup/restore/edit their credentials even if your application has no such functionality). I've created a NuGet package Meziantou.Framework.Win32.CredentialManager. How to use it:
CredentialManager.WriteCredential("ApplicationName", "username", "Pa$$w0rd", CredentialPersistence.Session);
var cred = CredentialManager.ReadCredential("ApplicationName");
Assert.AreEqual("username", cred.UserName);
Assert.AreEqual("Pa$$w0rd", cred.Password);
CredentialManager.DeleteCredential("ApplicationName");
Original answer with the native API wrapper (A more recent version of this is available on GitHub):
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
using System.Text;
using System.ComponentModel;
public static class CredentialManager
{
public static Credential ReadCredential(string applicationName)
{
IntPtr nCredPtr;
bool read = CredRead(applicationName, CredentialType.Generic, 0, out nCredPtr);
if (read)
{
using (CriticalCredentialHandle critCred = new CriticalCredentialHandle(nCredPtr))
{
CREDENTIAL cred = critCred.GetCredential();
return ReadCredential(cred);
}
}
return null;
}
private static Credential ReadCredential(CREDENTIAL credential)
{
string applicationName = Marshal.PtrToStringUni(credential.TargetName);
string userName = Marshal.PtrToStringUni(credential.UserName);
string secret = null;
if (credential.CredentialBlob != IntPtr.Zero)
{
secret = Marshal.PtrToStringUni(credential.CredentialBlob, (int)credential.CredentialBlobSize / 2);
}
return new Credential(credential.Type, applicationName, userName, secret);
}
public static int WriteCredential(string applicationName, string userName, string secret)
{
byte[] byteArray = Encoding.Unicode.GetBytes(secret);
if (byteArray.Length > 512)
throw new ArgumentOutOfRangeException("secret", "The secret message has exceeded 512 bytes.");
CREDENTIAL credential = new CREDENTIAL();
credential.AttributeCount = 0;
credential.Attributes = IntPtr.Zero;
credential.Comment = IntPtr.Zero;
credential.TargetAlias = IntPtr.Zero;
credential.Type = CredentialType.Generic;
credential.Persist = (UInt32)CredentialPersistence.Session;
credential.CredentialBlobSize = (UInt32)Encoding.Unicode.GetBytes(secret).Length;
credential.TargetName = Marshal.StringToCoTaskMemUni(applicationName);
credential.CredentialBlob = Marshal.StringToCoTaskMemUni(secret);
credential.UserName = Marshal.StringToCoTaskMemUni(userName ?? Environment.UserName);
bool written = CredWrite(ref credential, 0);
int lastError = Marshal.GetLastWin32Error();
Marshal.FreeCoTaskMem(credential.TargetName);
Marshal.FreeCoTaskMem(credential.CredentialBlob);
Marshal.FreeCoTaskMem(credential.UserName);
if (written)
return 0;
throw new Exception(string.Format("CredWrite failed with the error code {0}.", lastError));
}
public static IReadOnlyList<Credential> EnumerateCrendentials()
{
List<Credential> result = new List<Credential>();
int count;
IntPtr pCredentials;
bool ret = CredEnumerate(null, 0, out count, out pCredentials);
if (ret)
{
for (int n = 0; n < count; n++)
{
IntPtr credential = Marshal.ReadIntPtr(pCredentials, n * Marshal.SizeOf(typeof(IntPtr)));
result.Add(ReadCredential((CREDENTIAL)Marshal.PtrToStructure(credential, typeof(CREDENTIAL))));
}
}
else
{
int lastError = Marshal.GetLastWin32Error();
throw new Win32Exception(lastError);
}
return result;
}
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CredRead(string target, CredentialType type, int reservedFlag, out IntPtr credentialPtr);
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool CredWrite([In] ref CREDENTIAL userCredential, [In] UInt32 flags);
[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr pCredentials);
[DllImport("Advapi32.dll", EntryPoint = "CredFree", SetLastError = true)]
static extern bool CredFree([In] IntPtr cred);
private enum CredentialPersistence : uint
{
Session = 1,
LocalMachine,
Enterprise
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct CREDENTIAL
{
public UInt32 Flags;
public CredentialType Type;
public IntPtr TargetName;
public IntPtr Comment;
public System.Runtime.InteropServices.ComTypes.FILETIME LastWritten;
public UInt32 CredentialBlobSize;
public IntPtr CredentialBlob;
public UInt32 Persist;
public UInt32 AttributeCount;
public IntPtr Attributes;
public IntPtr TargetAlias;
public IntPtr UserName;
}
sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid
{
public CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
public CREDENTIAL GetCredential()
{
if (!IsInvalid)
{
CREDENTIAL credential = (CREDENTIAL)Marshal.PtrToStructure(handle, typeof(CREDENTIAL));
return credential;
}
throw new InvalidOperationException("Invalid CriticalHandle!");
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
CredFree(handle);
SetHandleAsInvalid();
return true;
}
return false;
}
}
}
public enum CredentialType
{
Generic = 1,
DomainPassword,
DomainCertificate,
DomainVisiblePassword,
GenericCertificate,
DomainExtended,
Maximum,
MaximumEx = Maximum + 1000,
}
public class Credential
{
private readonly string _applicationName;
private readonly string _userName;
private readonly string _password;
private readonly CredentialType _credentialType;
public CredentialType CredentialType
{
get { return _credentialType; }
}
public string ApplicationName
{
get { return _applicationName; }
}
public string UserName
{
get { return _userName; }
}
public string Password
{
get { return _password; }
}
public Credential(CredentialType credentialType, string applicationName, string userName, string password)
{
_applicationName = applicationName;
_userName = userName;
_password = password;
_credentialType = credentialType;
}
public override string ToString()
{
return string.Format("CredentialType: {0}, ApplicationName: {1}, UserName: {2}, Password: {3}", CredentialType, ApplicationName, UserName, Password);
}
}
Usage:
WriteCredential("ApplicationName", "Meziantou", "Passw0rd");
Console.WriteLine(ReadCredential("Demo"));

How to Programmatically Set GPO to Not Configured or Disabled

I'm looking for a programmatic solution that has the same effect as setting the "Configure Windows NTP Client" state in GPOE Administrative Templates > System > Windows Time Service > Time Providers > Configure Windows NTP Client to Not Configured or Disabled, but I'll take any help I can get at this point.
Is there a registry key I can modify using the .NET Registry class or a property I can modify using the RSoP WMI classes? I've been looking in both places for days, but haven't found anything that will effectively disable the GPO or have the same effect as disabling or setting it to Not Configured in the GUI.
Firstly you have to find the registry value to edit. They are all listed in the XLS document downloadable at http://www.microsoft.com/en-us/download/details.aspx?id=25250. This document does not indicate the type of the value (REGSZ, DWORD, etc), so you have to set the setting by using the editor and then look the type of the value with regedit.
Now you have the registry key, the value name and its type, let's add some C# and use the COM interface IGroupPolicyObject
[ComImport, Guid("EA502722-A23D-11d1-A7D3-0000F87571E3")]
internal class GPClass
{
}
[ComImport, Guid("EA502723-A23D-11d1-A7D3-0000F87571E3"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IGroupPolicyObject
{
uint New([MarshalAs(UnmanagedType.LPWStr)] string domainName, [MarshalAs(UnmanagedType.LPWStr)] string displayName, uint flags);
uint OpenDSGPO([MarshalAs(UnmanagedType.LPWStr)] string path, uint flags);
uint OpenLocalMachineGPO(uint flags);
uint OpenRemoteMachineGPO([MarshalAs(UnmanagedType.LPWStr)] string computerName, uint flags);
uint Save([MarshalAs(UnmanagedType.Bool)] bool machine, [MarshalAs(UnmanagedType.Bool)] bool add, [MarshalAs(UnmanagedType.LPStruct)] Guid extension, [MarshalAs(UnmanagedType.LPStruct)] Guid app);
uint Delete();
uint GetName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint GetDisplayName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint SetDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name);
uint GetPath([MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetDSPath(uint section, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetFileSysPath(uint section, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder path, int maxPath);
uint GetRegistryKey(uint section, out IntPtr key);
uint GetOptions(out uint options);
uint SetOptions(uint options, uint mask);
uint GetType(out IntPtr gpoType);
uint GetMachineName([MarshalAs(UnmanagedType.LPWStr)] StringBuilder name, int maxLength);
uint GetPropertySheetPages(out IntPtr pages);
}
public enum GroupPolicySection
{
Root = 0,
User = 1,
Machine = 2,
}
public abstract class GroupPolicyObject
{
protected const int MaxLength = 1024;
/// <summary>
/// The snap-in that processes .pol files
/// </summary>
private static readonly Guid RegistryExtension = new Guid(0x35378EAC, 0x683F, 0x11D2, 0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2);
/// <summary>
/// This application
/// </summary>
private static readonly Guid LocalGuid = new Guid(GetAssemblyAttribute<GuidAttribute>(Assembly.GetExecutingAssembly()).Value);
protected IGroupPolicyObject Instance = null;
static T GetAssemblyAttribute<T>(ICustomAttributeProvider assembly) where T : Attribute
{
object[] attributes = assembly.GetCustomAttributes(typeof(T), true);
if (attributes.Length == 0)
return null;
return (T)attributes[0];
}
internal GroupPolicyObject()
{
Instance = GetInstance();
}
public void Save()
{
var result = Instance.Save(true, true, RegistryExtension, LocalGuid);
if (result != 0)
{
throw new Exception("Error saving machine settings");
}
result = Instance.Save(false, true, RegistryExtension, LocalGuid);
if (result != 0)
{
throw new Exception("Error saving user settings");
}
}
public void Delete()
{
var result = Instance.Delete();
if (result != 0)
{
throw new Exception("Error deleting the GPO");
}
Instance = null;
}
public RegistryKey GetRootRegistryKey(GroupPolicySection section)
{
IntPtr key;
var result = Instance.GetRegistryKey((uint)section, out key);
if (result != 0)
{
throw new Exception(string.Format("Unable to get section '{0}'", Enum.GetName(typeof(GroupPolicySection), section)));
}
var handle = new SafeRegistryHandle(key, true);
return RegistryKey.FromHandle(handle, RegistryView.Default);
}
public abstract string GetPathTo(GroupPolicySection section);
protected static IGroupPolicyObject GetInstance()
{
var concrete = new GPClass();
return (IGroupPolicyObject)concrete;
}
}
public class GroupPolicyObjectSettings
{
public readonly bool LoadRegistryInformation;
public readonly bool Readonly;
public GroupPolicyObjectSettings(bool loadRegistryInfo = true, bool readOnly = false)
{
LoadRegistryInformation = loadRegistryInfo;
Readonly = readOnly;
}
private const uint RegistryFlag = 0x00000001;
private const uint ReadonlyFlag = 0x00000002;
internal uint Flag
{
get
{
uint flag = 0x00000000;
if (LoadRegistryInformation)
{
flag |= RegistryFlag;
}
if (Readonly)
{
flag |= ReadonlyFlag;
}
return flag;
}
}
}
public class ComputerGroupPolicyObject : GroupPolicyObject
{
public readonly bool IsLocal;
public ComputerGroupPolicyObject(GroupPolicyObjectSettings options = null)
{
options = options ?? new GroupPolicyObjectSettings();
var result = Instance.OpenLocalMachineGPO(options.Flag);
if (result != 0)
{
throw new Exception("Unable to open local machine GPO");
}
IsLocal = true;
}
public ComputerGroupPolicyObject(string computerName, GroupPolicyObjectSettings options = null)
{
options = options ?? new GroupPolicyObjectSettings();
var result = Instance.OpenRemoteMachineGPO(computerName, options.Flag);
if (result != 0)
{
throw new Exception(string.Format("Unable to open GPO on remote machine '{0}'", computerName));
}
IsLocal = false;
}
public static void SetPolicySetting(string registryInformation, string settingValue, RegistryValueKind registryValueKind)
{
string valueName;
GroupPolicySection section;
string key = Key(registryInformation, out valueName, out section);
// Thread must be STA
Exception exception = null;
var t = new Thread(() =>
{
try
{
var gpo = new ComputerGroupPolicyObject();
using (RegistryKey rootRegistryKey = gpo.GetRootRegistryKey(section))
{
// Data can't be null so we can use this value to indicate key must be delete
if (settingValue == null)
{
using (RegistryKey subKey = rootRegistryKey.OpenSubKey(key, true))
{
if (subKey != null)
{
subKey.DeleteValue(valueName);
}
}
}
else
{
using (RegistryKey subKey = rootRegistryKey.CreateSubKey(key))
{
subKey.SetValue(valueName, settingValue, registryValueKind);
}
}
}
gpo.Save();
}
catch (Exception ex)
{
exception = ex;
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
if (exception != null)
throw exception;
}
public static object GetPolicySetting(string registryInformation)
{
string valueName;
GroupPolicySection section;
string key = Key(registryInformation, out valueName, out section);
// Thread must be STA
object result = null;
var t = new Thread(() =>
{
var gpo = new ComputerGroupPolicyObject();
using (RegistryKey rootRegistryKey = gpo.GetRootRegistryKey(section))
{
// Data can't be null so we can use this value to indicate key must be delete
using (RegistryKey subKey = rootRegistryKey.OpenSubKey(key, true))
{
if (subKey == null)
{
result = null;
}
else
{
result = subKey.GetValue(valueName);
}
}
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
return result;
}
private static string Key(string registryInformation, out string value, out GroupPolicySection section)
{
// Parse parameter of format HKCU\Software\Policies\Microsoft\Windows\Personalization!NoChangingSoundScheme
string[] split = registryInformation.Split('!');
string key = split[0];
string hive = key.Substring(0, key.IndexOf('\\'));
key = key.Substring(key.IndexOf('\\') + 1);
value = split[1];
if (hive.Equals(#"HKLM", StringComparison.OrdinalIgnoreCase)
|| hive.Equals(#"HKEY_LOCAL_MACHINE", StringComparison.OrdinalIgnoreCase))
{
section = GroupPolicySection.Machine;
}
else
{
section = GroupPolicySection.User;
}
return key;
}
/// <summary>
/// Retrieves the file system path to the root of the specified GPO section.
/// The path is in UNC format.
/// </summary>
public override string GetPathTo(GroupPolicySection section)
{
var sb = new StringBuilder(MaxLength);
var result = Instance.GetFileSysPath((uint)section, sb, MaxLength);
if (result != 0)
{
throw new Exception(string.Format("Unable to retrieve path to section '{0}'", Enum.GetName(typeof(GroupPolicySection), section)));
}
return sb.ToString();
}
}
And how to use it:
static void Main(string[] args)
{
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", "0", RegistryValueKind.DWord);
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", "1", RegistryValueKind.DWord);
ComputerGroupPolicyObject.SetPolicySetting(#"HKLM\Software\Policies\Microsoft\Windows\HomeGroup!DisableHomeGroup", null, RegistryValueKind.Unknown);
}
Code inspired from https://bitbucket.org/MartinEden/local-policy

EnumDisplayDevices not returning anything

I am having an issue working with EnumDisplayDevices in C#. I used the code posted here and it worked seamlessly. However recently I switched to coding the application on my desktop computer. The code no longer works, not giving me anything.
If it helps, my monitor is an LG W2753VC running on an AMD Radeon HD 5770.
Here is my current code:
var device = new DISPLAY_DEVICE();
device.cb = Marshal.SizeOf(device);
try {
for (uint id = 0; EnumDisplayDevices(null, id, ref device, 0); id++) {
device.cb = Marshal.SizeOf(device);
EnumDisplayDevices(device.DeviceName, 0, ref device, 0);
device.cb = Marshal.SizeOf(device);
Console.WriteLine("id={0}, name={1}, devicestring={2}", id, device.DeviceName, device.DeviceString);
if (device.DeviceName == null || device.DeviceName == "") continue;
}
} catch (Exception ex) { }
What I'm getting on my laptop:
id=0, name=\\.\DISPLAY1\Monitor0, devicestring=Generic PnP Monitor
(That should be "Mobile PC Display", but it's not the problem here)
What I'm getting on my desktop:
id=0, name=, devicestring=
id=1, name=, devicestring=
Am I doing this wrong, and if not, is there any other way to get all connected displays? I have already tried the WMI and registry approach.
Hard to tell without you posting all your p/invoke code. Here's code that works on my workstation:
public class EnumDisplayDevicesTest
{
[DllImport("user32.dll")]
static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x10,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}
public void Display()
{
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
try
{
for (uint id = 0; EnumDisplayDevices(null, id, ref d, 0); id++)
{
if (d.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop))
{
Console.WriteLine(
String.Format("{0}, {1}, {2}, {3}, {4}, {5}",
id,
d.DeviceName,
d.DeviceString,
d.StateFlags,
d.DeviceID,
d.DeviceKey
)
);
d.cb = Marshal.SizeOf(d);
EnumDisplayDevices(d.DeviceName, 0, ref d, 0);
Console.WriteLine(
String.Format("{0}, {1}",
d.DeviceName,
d.DeviceString
)
);
}
d.cb = Marshal.SizeOf(d);
}
}
catch (Exception ex)
{
Console.WriteLine(String.Format("{0}", ex.ToString()));
}
}
}
The above code works as the OP desires on my machines, not sure why it won't work on his laptop.
An alternative method to getting the info is listed below, taken from here:
foreach (var display in DisplayDetails.GetMonitorDetails())
{
Console.WriteLine(display.Model);
}
public class DisplayDetails
{
public string PnPID { get; set; }
public string SerialNumber { get; set; }
public string Model { get; set; }
public string MonitorID { get; set; }
/// <summary>
/// The Constructor to create a new instances of the DisplayDetails class...
/// </summary>
public DisplayDetails(string sPnPID, string sSerialNumber, string sModel, string sMonitorID)
{
PnPID = sPnPID;
SerialNumber = sSerialNumber;
Model = sModel;
MonitorID = sMonitorID;
}
/// <summary>
/// This Function returns all Monitor Details
/// </summary>
/// <returns></returns>
static public IEnumerable<DisplayDetails> GetMonitorDetails()
{
//Open the Display Reg-Key
RegistryKey Display = Registry.LocalMachine;
Boolean bFailed = false;
try
{
Display = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Enum\DISPLAY");
}
catch
{
bFailed = true;
}
if (!bFailed & (Display != null))
{
//Get all MonitorIDss
foreach (string sMonitorID in Display.GetSubKeyNames())
{
RegistryKey MonitorID = Display.OpenSubKey(sMonitorID);
if (MonitorID != null)
{
//Get all Plug&Play ID's
foreach (string sPNPID in MonitorID.GetSubKeyNames())
{
RegistryKey PnPID = MonitorID.OpenSubKey(sPNPID);
if (PnPID != null)
{
string[] sSubkeys = PnPID.GetSubKeyNames();
//Check if Monitor is active
if (sSubkeys.Contains("Control"))
{
if (sSubkeys.Contains("Device Parameters"))
{
RegistryKey DevParam = PnPID.OpenSubKey("Device Parameters");
string sSerial = "";
string sModel = "";
//Define Search Keys
string sSerFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xff });
string sModFind = new string(new char[] { (char)00, (char)00, (char)00, (char)0xfc });
//Get the EDID code
byte[] bObj = DevParam.GetValue("EDID", null) as byte[];
if (bObj != null)
{
//Get the 4 Vesa descriptor blocks
string[] sDescriptor = new string[4];
sDescriptor[0] = Encoding.Default.GetString(bObj, 0x36, 18);
sDescriptor[1] = Encoding.Default.GetString(bObj, 0x48, 18);
sDescriptor[2] = Encoding.Default.GetString(bObj, 0x5A, 18);
sDescriptor[3] = Encoding.Default.GetString(bObj, 0x6C, 18);
//Search the Keys
foreach (string sDesc in sDescriptor)
{
if (sDesc.Contains(sSerFind))
{
sSerial = sDesc.Substring(4).Replace("\0", "").Trim();
}
if (sDesc.Contains(sModFind))
{
sModel = sDesc.Substring(4).Replace("\0", "").Trim();
}
}
}
if (!string.IsNullOrEmpty(sPNPID + sSerFind + sModel + sMonitorID))
{
yield return new DisplayDetails(sPNPID, sSerial, sModel, sMonitorID);
}
}
}
}
}
}
}
}
}
}
I had exactly this behavior when device.cb wasn't equal to one of 840 or 224 (sizeof DISPLAY_DEVICEW and DISPLAY_DEVICEA respectively). In my case I just mistakenly wrote device.cb = sizeof(device.cb);
Check value of Marshal.SizeOf(device) on both your computers.
I had the exact same problem and I found out that I was using the following to import EnumDisplayDevices:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
Rather than
[DllImport("user32.dll")]
The code example from GalacticJello is working for me. I forced the build of the assemblies for x86.
In other cases maybe try:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DISPLAY_DEVICE`
but this is not working for x86!

"A specified logon session does not exist. It may already have been terminated." when trying to copy a file using WindowsIdentity.Impersonate

I am trying to copy a file from sharepoint to a unc path. I am using the following code:
var id = new WindowsIdentity("administrator#mysite.com");
var p = new WindowsPrincipal(id);
var wic = id.Impersonate();
File.Move(oldName, newName);
wic.Undo();
oldname is C:\test.txt
newName is \\server\folder\test.txt
I am getting the error
A specified logon session does not exist. It may already have been terminated.
How do I go about removing this error OR copy a file from A to B(UNC path) using sharepoint.
The following class will allow you to access SMB shares via a user-name and password. I use it all the time when copying files to network shares in both windows-to-windows and windows-to-unix environments. The benefit here is that you do not need to be authenticate as the user. In essence, you can use credentials that are local only to the target machine.
class WNetConnection : IDisposable
{
public readonly string RemoteShare;
public WNetConnection( string remoteHost, string remoteUser, string remotePassword )
{
Uri loc;
if( !Uri.TryCreate( remoteHost, UriKind.Absolute, out loc ) || loc.IsUnc == false )
throw new ApplicationException( "Not a valid UNC path: " + remoteHost );
string auth = loc.Host;
string[] segments = loc.Segments;
// expected format is '\\machine\share'
this.RemoteShare = String.Format( #"\\{0}\{1}", auth, segments[1].Trim( '\\', '/' ) );
this.Connect( remoteUser, remotePassword );
}
~WNetConnection()
{
Disconnect();
}
public void Dispose()
{
Disconnect();
GC.SuppressFinalize( this );
}
#region Win32 API...
[StructLayout( LayoutKind.Sequential )]
internal struct NETRESOURCE
{
public int dwScope;
public int dwType;
public int dwDisplayType;
public int dwUsage;
[MarshalAs( UnmanagedType.LPWStr )]
public string lpLocalName;
[MarshalAs( UnmanagedType.LPWStr )]
public string lpRemoteName;
[MarshalAs( UnmanagedType.LPWStr )]
public string lpComment;
[MarshalAs( UnmanagedType.LPWStr )]
public string lpProvider;
}
[DllImport( "mpr.dll", EntryPoint = "WNetAddConnection2W", CharSet = System.Runtime.InteropServices.CharSet.Unicode )]
private static extern int WNetAddConnection2( ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, Int32 dwFlags );
[DllImport( "mpr.dll", EntryPoint = "WNetCancelConnectionW", CharSet = System.Runtime.InteropServices.CharSet.Unicode )]
private static extern int WNetCancelConnection( string lpRemoteName, bool bForce );
private const int RESOURCETYPE_ANY = 0x00000000;
private const int RESOURCETYPE_DISK = 0x00000001;
private const int CONNECT_INTERACTIVE = 0x00000008;
private const int CONNECT_PROMPT = 0x00000010;
private const int NO_ERROR = 0;
void Connect( string remoteUser, string remotePassword )
{
NETRESOURCE ConnInf = new NETRESOURCE();
ConnInf.dwScope = 0;
ConnInf.dwType = RESOURCETYPE_DISK;
ConnInf.dwDisplayType = 0;
ConnInf.dwUsage = 0;
ConnInf.lpRemoteName = this.RemoteShare;
ConnInf.lpLocalName = null;
ConnInf.lpComment = null;
ConnInf.lpProvider = null;
// user must be qualified 'authority\user'
if( remoteUser.IndexOf( '\\' ) < 0 )
remoteUser = String.Format( #"{0}\{1}", new Uri(RemoteShare).Host, remoteUser );
int dwResult = WNetAddConnection2( ref ConnInf, remotePassword, remoteUser, 0 );
if( NO_ERROR != dwResult )
throw new Win32Exception( dwResult );
}
void Disconnect()
{
int dwResult = WNetCancelConnection( this.RemoteShare, true );
if( NO_ERROR != dwResult )
throw new Win32Exception( dwResult );
}
#endregion
}
You are not actually getting a logon token to impersonate. You need to call the LogonUser API to get a valid logon token, which you can use to impersonate that user.
See this blog entry for example code in c# on impersonating a windows user. You can also see this KB article that also contains c# code (and a duplicatetoken call for issues with .net 1.0)

Categories