[GnuTLS Library in a C# project] - c#

I am trying to import the GnuTLS library to my C# project and use its APIs. Unfortunately, I cannot find any way on how to do this with the C-based GnuTLS library.
Does anyone know a way on how to use the GnuTLS library in a C# project or even on how to use the Windows build of the GnuTLS library available on their website https://www.gnutls.org/download.html so that I can run it using a C compiler and use the P/Invoke in C# to access the necessary APIs.
(In C#, I tried to import the libraries as reference using MSVS2010 but it says that it is not a valid .NET assembly nor a COM component)
(Also tried the Windows build of this library using a simple C code that calls a function but fails on compilation due to an error "... undefined reference to ...". I put the header files in MinGW directory as well as the DLL and EXE files).

You can use gnutls via P\Invoke. So it's worked on unix platforms.
Example on linux:
namespace GnuTlsExample
{
internal static class NativeMethodsLinux {
internal enum GNUTLS_X509_FMT
{
GNUTLS_X509_FMT_DER = 0,
GNUTLS_X509_FMT_PEM = 1
}
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_crt_list_import(IntPtr certs, ref int cert_max, IntPtr data, GNUTLS_X509_FMT format, uint flags);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_privkey_init(ref IntPtr key);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_x509_privkey_import(IntPtr key, IntPtr data, GNUTLS_X509_FMT format);
[DllImport("libgnutls.so.30")]
internal static extern int gnutls_certificate_set_x509_key(IntPtr cred, IntPtr certs, int max, IntPtr key);
[StructLayout(LayoutKind.Sequential)]
internal class gnutls_datum_t
{
public IntPtr data = IntPtr.Zero;
public int size = 0;
}
}
class Program
{
static void Main(string[] args)
{
var buf = ByteArrayToGnuTlsDatum(File.ReadAllBytes(certificateFilePath));
var certs = Marshal.AllocHGlobal(IntPtr.Size);
var max = 6;
var tlsCtx = IntPtr.Zero;
var isServer = 0;
var key = IntPtr.Zero;
var bufKey = MarshalUtils.ByteArrayToGnuTlsDatum(File.ReadAllBytes(keyFilePath));
var res = NativeMethodsLinux.gnutls_x509_privkey_init(ref key);
res = NativeMethodsLinux.gnutls_x509_privkey_import(key, bufKey,
NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_PEM);
res = NativeMethodsLinux.gnutls_x509_crt_list_import(certs, ref max, buf,
NativeMethodsLinux.GNUTLS_X509_FMT.GNUTLS_X509_FMT_PEM, 0);
var cred = Marshal.AllocHGlobal(IntPtr.Size);
res = NativeMethodsLinux.gnutls_certificate_set_x509_key(cred, certs, max, key);
}
internal static IntPtr ByteArrayToGnuTlsDatum(byte[] bytes)
{
var berPtr = Marshal.AllocHGlobal(Marshal.SizeOf<NativeMethodsLinux.gnutls_datum_t>());
var valPtr = Marshal.AllocHGlobal(bytes.Length);
Marshal.Copy(bytes,0,valPtr,bytes.Length);
Marshal.StructureToPtr(new NativeMethodsLinux.gnutls_datum_t
{
data = valPtr,
size = bytes.Length
}, berPtr, true);
return berPtr;
}
}
}

Related

Calling a dll with a void* from C#

I've read most of the hints but I can't get it to work.
I have a native C dll with this prototype:
int utl_Conv_HexString(U8 u8_Mode, void* DataIn, void* DataOut, int *piInOutLen, int maxOutLen);
This dll converts several string formats in byte arrays:
The dll is used in a system with unmanaged code (written in C)
Now I would like to use this dll in a C# / WPF Enviroment.
I still use other dll's in C#, but all have prototypes with no void*.
Examples from C:
//ByteArr to Telegramm
u8_Dst[0] = 0xAA;
u8_Dst[1] = 0xBB;
u8_Dst[2] = 0xCC;
u32_InOutLen = 3;
s32_res = utl_Conv_HexString(UTL_CONV_BYTEARR_TO_TELEGRAM, u8_Dst, ac8_Src, &u32_InOutLen, sizeof(ac8_Src));
or
strcpy(ac8_Src, "0xAA,0xBB,0xCC");
memset(u8_Dst, 0, sizeof(u8_Dst));
s32_res = utl_Conv_HexString(UTL_CONV_TELEGRAM_TO_BYTEARR, ac8_Src, u8_Dst, &u32_InOutLen, sizeof(u8_Dst));
My problem is that I can not figure out how this could be used in C#
You should use it like:
public enum U8
{
UTL_CONV_BYTEARR_TO_TELEGRAM = 1, // TODO
UTL_CONV_TELEGRAM_TO_BYTEARR = 2,
}
(you will have to put here your constants...)
[DllImport("SomeDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int utl_Conv_HexString(U8 u8Mode, byte[] dataIn, byte[] dataOut, ref int piInOutLen, int maxOutLen);
(note that the CallingConvention could be StdCall... you'll have to check your code)
and then:
byte[] src = Encoding.UTF8.GetBytes("0xAA, 0xBB, 0xCC");
byte[] dest = new byte[64];
int lenSrc = src.Length;
int res = utl_Conv_HexString(U8.UTL_CONV_TELEGRAM_TO_BYTEARR, src, dest, ref lenSrc, dest.Length);
The void* is normally translated to a byte[].

my c++ and c# interop crashes in 64 bit, why? pointer size?

i got a native 32 bit dll (no source) which runs as a plugin in an application i use. I've done another native dll myself which will communicate with that plugin in order to create and update the plugin's controls.
From that dll i've exported the functions I need in order to control the plugin from my c# application (with p/invoke).
here's the code:
h file:
#pragma once
#include "include\SpoutControls.h"
extern "C" { __declspec(dllexport) void InitializeControls(char *sendername, int *numControls, char** names, int *types, float* floats, float* toggles, float* press, char** text); }
extern "C" { __declspec(dllexport) bool UpdateControls(const char** text, float *floats, float *toggles, float *press, int *numControls); }
extern "C" { __declspec(dllexport) void CloseControls(); }
//
extern "C" __declspec(dllexport) int ReleaseMemory(float *pArray)
{
delete[] pArray;
//delete[] Usize;
return 0;
};
the cpp:
#include "SpoutControls4vvvv.h"
//SpoutControls and the functions
//CreateControl, OpenControls, CheckControls, CloseControls
//are declared in SpoutControls.h, which comes with the 32 bit plugin dll
SpoutControls spoutcontrols;
void InitializeControls(char *sendername, int *numControls, char** names, int *types, float* floats, float* toggles, float* press, char** text) {
int Vcontrols = numControls[0];
int Tcontrols = numControls[1];
int Pcontrols = numControls[2];
int Scontrols = numControls[3];
int all = Vcontrols + Tcontrols + Pcontrols + Scontrols;
int v=0, t=0, p=0, s = 0;
for (int controlID = 0; controlID < all; controlID++) {
if (types[controlID] == 0) {
spoutcontrols.CreateControl(names[controlID], "float",0.0,1.0, floats[v]);
v++;
}
if (types[controlID] == 1) {
spoutcontrols.CreateControl(names[controlID], "bool", toggles[t]);
t++;
}
if (types[controlID] == 2) {
spoutcontrols.CreateControl(names[controlID], "event", press[p]);
p++;
}
if (types[controlID] == 3) {
spoutcontrols.CreateControl(names[controlID], "text", text[s]);
s++;
}
}
spoutcontrols.OpenControls(sendername);
}
bool UpdateControls(const char** text, float *floats, float *toggles, float *press, int *numControls) {
int Vcontrols = numControls[0];
int Tcontrols = numControls[1];
int Pcontrols = numControls[2];
int Scontrols = numControls[3];
int all = Vcontrols + Tcontrols + Pcontrols + Scontrols;
int v = 0, t = 0, p = 0, s = 0;
if (spoutcontrols.CheckControls(myControls)) {
for (int controlID = 0; controlID < all; controlID++) {
if (myControls[controlID].type == 10) {
floats[v] = myControls[controlID].value;
v++;
}
if (myControls[controlID].type == 0) {
toggles[t] = myControls[controlID].value;
t++;
}
if (myControls[controlID].type == 1) {
press[p] = myControls[controlID].value;
p++;
}
if (myControls[controlID].type == 100) {
text[s] = myControls[controlID].text.data();
s++;
}
}
return true;
}
return false;
}
void CloseControls() {
spoutcontrols.CloseControls();
}
and here's the c# code:
public unsafe class SystemSpoutSenderNode: IDisposable
{
[System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
private static extern void InitializeControls(IntPtr sendername, IntPtr numControls,String[] names, IntPtr types, IntPtr floats, IntPtr toggles, IntPtr press, String[] text);
[System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
private static extern int CloseControls();
[System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool UpdateControls([In, Out] String[] text, [In, Out] float[] floats, [In, Out] float[] toggles, [In, Out] float[] press, IntPtr numControls);
[System.Runtime.InteropServices.DllImport("SpoutControls4vvvv.dll")]
private static extern int ReleaseMemory(IntPtr ptr);
public void Evaluate(int SpreadMax)
{
//countControls determines number of controls per type (string,float,toggle,click)
int[] controls = countControls(FType);
//sumControls will just add up all elements in controls
int all = sumControls(controls);
//in my code these arrays will get filled with values, deleted here for readability
String[] names = new String[all];
int[] types = new int[all];
float[] floats = new float[controls[0]];
float[] toggles = new float[controls[1]];
float[] press = new float[controls[2]];
String[] text = new String[controls[3]];
//initialze return arrays
String[] Rtext = new String[controls[3]];
float[] Rfloats = new float[controls[0]];
float[] Rtoggles = new float[controls[1]];
float[] Rpress = new float[controls[2]];
//allocate pointers
IntPtr SndrNamePtr = NativeUtf8FromString(FSenderName);
IntPtr BinPtr = Marshal.AllocHGlobal(4*sizeof(int));
IntPtr TypePtr = Marshal.AllocHGlobal(all*sizeof(int));
IntPtr FloatPtr = Marshal.AllocHGlobal(controls[0]*sizeof(float));
IntPtr TogglePtr = Marshal.AllocHGlobal(controls[1]*sizeof(float));
IntPtr PressPtr = Marshal.AllocHGlobal(controls[2]*sizeof(float));
try
{
//copy control info + defaults to pointer
Marshal.Copy(controls, 0, BinPtr, 4);
Marshal.Copy(types, 0, TypePtr, all);
Marshal.Copy(floats, 0, FloatPtr, controls[0]);
Marshal.Copy(toggles, 0, TogglePtr, controls[1]);
Marshal.Copy(press, 0, PressPtr, controls[2]);
//initialize controls
if (FWrite) InitializeControls(SndrNamePtr,BinPtr,names,TypePtr,FloatPtr,TogglePtr,PressPtr,text);
//update controls
bool changed = UpdateControls(Rtext,Rfloats,Rtoggles,Rpress,BinPtr);
//FF, FT, FS and FP are the outputs in my c# host
if (changed){
for(int j=0; j<controls[0];j++){
FF[j]=Rfloats[j];
}
for(int j=0; j<controls[1];j++){
FT[j]=FloatToBool(Rtoggles[j]);
}
for(int j=0; j<controls[3];j++){
FS[j]=Rtext[j];
}
}
for(int j=0; j<controls[2];j++){
FP[j]=FloatToBool(Rpress[j]);
}
}
finally
{
Marshal.FreeHGlobal(SndrNamePtr);
Marshal.FreeHGlobal(BinPtr);
Marshal.FreeHGlobal(FloatPtr);
Marshal.FreeHGlobal(TogglePtr);
Marshal.FreeHGlobal(PressPtr);
}
}
}
}
public void Dispose()
{
CleanUp();
CloseControls();
}
}
NOTE: the c# code runs without precompiling in a frame-based, c# host environment for graphical programming (vvvv), therefore i've deleted host specific decalarations of inputs (FType,FSenderName) and outputs (FF,FS,FP,FT) to avoid confusion. These will be used to "connect" this code with other functionality. Evaluate will be called every frame by the host.
Now to the actual question(s):
it's working fine so far in 32 bit, but in 64 bit my c# host crashes without any message. after some reading i believe this is due to pointer sizes being different in 32/64bit systems, but i'm not exactly sure what to do/if this actually applies here. I would be very thankful if you could
explain me how (and why) to get this code to run in 64 bit
point out any other mistakes you might spot along the way- i'm completely new to c++ and still a beginner in c#, so i'm pretty confident there's a lot to improve here; especially: memory leaks and passing the values from c++ to c# and vice versa...uiuiui.
I've understood that I shouldn't cast a pointer to an int in 64 bit, so the last thing I've tried is to change from
int Vcontrols = numControls[0];
int Tcontrols = numControls[1];
int Pcontrols = numControls[2];
int Scontrols = numControls[3];
to
int Vcontrols = (INT_PTR)numControls[0];
int Tcontrols = (INT_PTR)numControls[1];
int Pcontrols = (INT_PTR)numControls[2];
int Scontrols = (INT_PTR)numControls[3];
but with no luck, therefore I'm posting my original problem, even if this is a correct improvement(?).
EDIT: thanks to #dkackman for pointing out one unclear point: my cpp code calls functions which come as source code (SpoutControls.h) with the native 32 bit dll. It's not the source for the 32 bit dll itself but declares the functions used to (as far as i can tell) access the same shared memory as the 32 bit dll.
I can also copy paste the code here if this might be the problem?
Also can be found here
thank you.
I am afraid you are out of luck. If your process is 64bit, you won't be able to load that 32bit dll, no matter how much you try.
Can I load a 32 bit DLL into a 64 bit process on Windows?
from https://msdn.microsoft.com/en-us/library/windows/desktop/aa384231(v=vs.85).aspx
On 64-bit Windows, a 64-bit process cannot load a 32-bit dynamic-link
library (DLL).
Without access to its source, your only option would be to convert your host to 32bit or otherwise figure out how to host the 32bit plugin in a 32bit process and use some sort of IPC to communicate with it from a 64bit host process.
So my guess is that this has nothing to do with your wrapper, array passing or interop code.

Using GhostScript 9.10 in Windows with Unicode characters in parameters

I want to use Ghostscript in a .NET / C# application to convert a .tiff file to PDF.
My problem: When the file path contains non-ansi characters (e.g. Umlaute), the function
gsapi_init_with_args
fails. (With GS 8.x, it works fine!).
I found information that the behaviour was changed in 9.x, and I also found a function called
gsapi_init_with_argsW
And this function should work with .NET without any problems (see http://permalink.gmane.org/gmane.comp.printing.ghostscript.cvs/31721)
So I use the following DLLImport:
[DllImport(#"gsdll32.dll")]
public static extern int gsapi_init_with_argsW( IntPtr instace, int argc, string[] argv);
but this still does not work, I get the error:
Error: /undefinedfilename
in (C:\\304NDERUNGEN\\TEST.PDF)
The name of the file schould be
C:\\ÄNDERUNGEN\\TEST.PDF
so the umlaut "Ä" is not recognized correctly.
I´ve search the web a lot but did not found a solution.
Any idea?
Thank you!
I suspect that you will need to use UTF-8 here. Make a call to gs_set_arg_encoding passing GS_ARG_ENCODING_UTF8.
Any strings that you pass to Ghostscript should be declared as IntPtr. To convert from a C# string to a null-terminated UTF-8 encoded string use this function provided by Hans Passant:
public static IntPtr NativeUtf8FromString(string managedString)
{
int len = Encoding.UTF8.GetByteCount(managedString);
byte[] buffer = new byte[len + 1]; // null-terminator allocated
Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0);
IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length);
return nativeUtf8;
}
Make sure that you remember to clean up with a call to Marshal.FreeHGlobal.
The overall code might look a little like this:
public class Ghostscript
{
public const int GS_ARG_ENCODING_LOCAL = 0;
public const int GS_ARG_ENCODING_UTF8 = 1;
[DllImport("gsdll32.dll")]
private static extern int gsapi_new_instance(out IntPtr inst, IntPtr handle);
[DllImport("gsdll32.dll")]
private static extern int gsapi_set_arg_encoding(IntPtr inst, int encoding);
[DllImport("gsdll32.dll")]
private static extern int gsapi_init_with_args(IntPtr inst, int argc, IntPtr[] argv);
[DllImport("gsdll32.dll")]
private static extern int gsapi_exit(IntPtr inst);
[DllImport("gsdll32.dll")]
private static extern void gsapi_delete_instance(IntPtr inst);
private static void checkReturnValue(int retval)
{
if (retval != 0)
throw ...; // implement error handling here
}
public static void run(string[] argv)
{
IntPtr inst;
checkReturnValue(gsapi_new_instance(out inst, IntPtr.Zero));
try
{
IntPtr[] utf8argv = new IntPtr[argv.length];
for (int i=0; i<utf8argv.Length; i++)
utf8argv[i] = NativeUtf8FromString(argv[i]);
try
{
checkReturnValue(gsapi_set_arg_encoding(inst, GS_ARG_ENCODING_UTF8));
checkReturnValue(gsapi_init_with_args(inst, utf8argv.Length, utf8argv));
checkReturnValue(gsapi_exit(inst));
finally
{
for (int i=0; i<utf8argv.Length; i++)
Marshal.FreeHGlobal(utf8argv[i]);
}
}
finally
{
gsapi_delete_instance(inst);
}
}
}

Embedded MySQL Server C# Wrapper?

I have been heavily contemplating adding the Embedded MYSQL Server Library into my application. My software is a layer between a Game Server and a Web Management Panel that provides extra functionality. Many of our customers have been requesting MySQL databases for their servers (since this is what their plugins are developed to use), and being able to run one within my software rather than manually set them up would be fantastic.
Is there a .NET wrapper for this library I am missing?
The software being ran by my application will need to be able to connect to it, but the software is obviously being ran locally. Will this work?
i'm not aware of any .NET wrapper for this library although i remember there was a talk about introducing support for this library in the .NET Connector from version 5. I can't find any information about that right now though.
There is some sample code out there on the web which you can extend your code upon. I quess the most complete would be http://forums.mysql.com/read.php?38,67281,67917 ->
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Configuration;
class EntryPoint
{
[DllImport("libmySQL.dll")]
static extern IntPtr mysql_init(IntPtr mysql);
[DllImport("libmySQL.dll")]
static extern IntPtr mysql_fetch_lengths(IntPtr result);
[DllImport("libmySQL.dll")]
static extern IntPtr mysql_store_result(IntPtr mysql);
[DllImport("libmySQL.dll")]
static extern IntPtr mysql_fetch_row(IntPtr result);
[DllImport("libmySQL.dll")]
static extern IntPtr mysql_real_connect(IntPtr mysql, string host, string user, string passwd, string db, uint port, string unix_socket, uint client_flag);
[DllImport("libmySQL.dll")]
static extern uint mysql_field_count(IntPtr mysql);
[DllImport("libmySQL.dll")]
static extern string mysql_error(IntPtr mysql);
[DllImport("libmySQL.dll")]
static extern int mysql_real_query(IntPtr mysql, string query, uint length);
static Array MarshalArray(Type structureType, IntPtr arrayPtr, int length)
{
if (structureType == null)
throw new ArgumentNullException("structureType");
if (!structureType.IsValueType)
throw new ArgumentException("Only struct types are supported.", "structureType");
if (length < 0)
throw new ArgumentOutOfRangeException("length", length, "length must be equal to or greater than zero.");
if (arrayPtr == IntPtr.Zero)
return null;
int size = System.Runtime.InteropServices.Marshal.SizeOf(structureType);
Array array = Array.CreateInstance(structureType, length);
for (int i = 0; i < length; i++)
{
IntPtr offset = new IntPtr((long)arrayPtr + (size * i));
object value = System.Runtime.InteropServices.Marshal.PtrToStructure(offset, structureType);
array.SetValue(value, i);
}
return array;
}
static void mysql_real_query(IntPtr mysql, string query)
{
int result = (query != null) ? mysql_real_query(mysql, query, (uint)query.Length) : mysql_real_query(mysql, null, 0);
if (result == 0)
return;
throw new ApplicationException(mysql_error(mysql));
}
static int Main(string[] args)
{
IntPtr ptr = mysql_init(IntPtr.Zero);
Debug.Assert(ptr != IntPtr.Zero);
IntPtr mysql = mysql_real_connect(ptr, ConfigurationSettings.AppSettings["server"], ConfigurationSettings.AppSettings["username"], ConfigurationSettings.AppSettings["password"], ConfigurationSettings.AppSettings["database"], 0, null, 0);
Debug.Assert(ptr != IntPtr.Zero, mysql_error(ptr));
string query = "SELECT * FROM proxy_servers";
Console.WriteLine("Executing query: {0}", query);
mysql_real_query(mysql, query);
IntPtr result = mysql_store_result(mysql);
Debug.Assert(result != IntPtr.Zero, mysql_error(mysql));
uint fieldCount = mysql_field_count(mysql);
Console.WriteLine("field count: {0}", fieldCount);
for (IntPtr ptrRow = mysql_fetch_row(result); ptrRow != IntPtr.Zero; ptrRow = mysql_fetch_row(result))
{
IntPtr[] mysqlRow = (IntPtr[])MarshalArray(typeof(IntPtr), ptrRow, (int)fieldCount);
IntPtr ptrLengths = mysql_fetch_lengths(result);
uint[] lengths = (uint[])MarshalArray(typeof(uint), ptrLengths, (int)fieldCount);
for (int i = 0; i < (int)fieldCount; i++)
{
string str = Marshal.PtrToStringAnsi(mysqlRow[i], (int)lengths[i]);
Console.Write("{0}, ", str);
}
Console.WriteLine();
}
return 0;
}
}

Enumerating Network Sessions

I wanted to pull data about the connected network users from the Computer Management -> Shared Folders -> Sessions tab into my c# application. Can anybody guide me on what namespaces have to be used along with some sample code to import username and ip address from Computer Management -> Shared Folders -> Sessions tab?
Regards
You want NetSessionEnum, which:
Provides information about sessions established on a server.
When passed a level of 502, it'll return an array of:
...the name of the computer; name of the user; open files, pipes, and devices on the computer; and the name of the transport the client is using.
Luckily for you, pinvoke.net has the necessary signatures and even some sample code. Here's a full featured sample:
public class Program {
public void Main(string[] args) {
IntPtr pSessionInfo;
IntPtr pResumeHandle = IntPtr.Zero;
UInt32 entriesRead, totalEntries;
var netStatus = NativeMethods.NetSessionEnum(
null, // local computer
null, // client name
null, // username
502, // include all info
out pSessionInfo, // pointer to SESSION_INFO_502[]
NativeMethods.MAX_PREFERRED_LENGTH,
out entriesRead,
out totalEntries,
ref pResumeHandle
);
try {
if (netStatus != NativeMethods.NET_API_STATUS.NERR_Success) {
throw new InvalidOperationException(netStatus.ToString());
}
Console.WriteLine("Read {0} of {1} entries", entriesRead, totalEntries);
for (int i = 0; i < entriesRead; i++) {
var pCurrentSessionInfo = new IntPtr(pSessionInfo.ToInt32() + (NativeMethods.SESSION_INFO_502.SIZE_OF * i));
var s = (NativeMethods.SESSION_INFO_502)Marshal.PtrToStructure(pCurrentSessionInfo, typeof(NativeMethods.SESSION_INFO_502));
Console.WriteLine(
"User: {0}, Computer: {1}, Type: {2}, # Open Files: {3}, Connected Time: {4}s, Idle Time: {5}s, Guest: {6}",
s.sesi502_username,
s.sesi502_cname,
s.sesi502_cltype_name,
s.sesi502_num_opens,
s.sesi502_time,
s.sesi502_idle_time,
s.sesi502_user_flags == NativeMethods.SESSION_INFO_502_USER_FLAGS.SESS_GUEST
);
}
} finally {
NativeMethods.NetApiBufferFree(pSessionInfo);
}
}
}
public sealed class NativeMethods {
[DllImport("netapi32.dll", SetLastError=true)]
public static extern NET_API_STATUS NetSessionEnum(
string serverName,
string uncClientName,
string userName,
UInt32 level,
out IntPtr bufPtr,
int prefMaxLen,
out UInt32 entriesRead,
out UInt32 totalEntries,
ref IntPtr resume_handle
);
[DllImport("netapi32.dll")]
public static extern uint NetApiBufferFree(IntPtr Buffer);
public const int MAX_PREFERRED_LENGTH = -1;
public enum NET_API_STATUS : uint {
NERR_Success = 0,
NERR_InvalidComputer = 2351,
NERR_NotPrimary = 2226,
NERR_SpeGroupOp = 2234,
NERR_LastAdmin = 2452,
NERR_BadPassword = 2203,
NERR_PasswordTooShort = 2245,
NERR_UserNotFound = 2221,
ERROR_ACCESS_DENIED = 5,
ERROR_NOT_ENOUGH_MEMORY = 8,
ERROR_INVALID_PARAMETER = 87,
ERROR_INVALID_NAME = 123,
ERROR_INVALID_LEVEL = 124,
ERROR_MORE_DATA = 234 ,
ERROR_SESSION_CREDENTIAL_CONFLICT = 1219
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct SESSION_INFO_502 {
public static readonly int SIZE_OF = Marshal.SizeOf(typeof(SESSION_INFO_502));
public string sesi502_cname;
public string sesi502_username;
public uint sesi502_num_opens;
public uint sesi502_time;
public uint sesi502_idle_time;
public SESSION_INFO_502_USER_FLAGS sesi502_user_flags;
public string sesi502_cltype_name;
public string sesi502_transport;
}
public enum SESSION_INFO_502_USER_FLAGS : uint {
SESS_GUEST = 1,
SESS_NOENCRYPTION = 2
}
}
You don't want to interact with Computer Management, you want to call the same functions it does and cut the middle man out of the loop.
For finding out about current network connection, you might be looking for WNetOpenEnum or NetConnectionEnum
I don't think there's a .NET function for this in the BCL, you'd have to use p/invoke or look for a third-party library (or my personal favorite, use C++/CLI to write a wrapper)

Categories