Страницы

Поиск по вопросам

Показаны сообщения с ярлыком pinvoke. Показать все сообщения
Показаны сообщения с ярлыком pinvoke. Показать все сообщения

суббота, 7 марта 2020 г.

Как проверить разрядность системы?

#c_sharp #pinvoke


Имея данный алгоритм, почему-то большую часть показывает x32. У меня стоит x64



private static bool Is64Bit()
{
    return IntPtr.Size == 8;
}

public static string CheckOS()
{
    if (Is64Bit())
        return "x64";
    else
        return "x32";
}

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process([In] IntPtr hProcess, out bool lpSystemInfo);




Как нормально проверить на всех осях разрядность?
    


Ответы

Ответ 1



Начиная с 4 версии фреймворка существует простой способ проверить разрядность ОС, используя статический класс Environment и его свойство Is64BitOperatingSystem: using System; static string GetOSBit() { if (Environment.Is64BitOperatingSystem) return "x64"; else return "x32"; } Console.WriteLine(GetOSBit());

Ответ 2



Решил проблему так: internal class OSCheckBit { private static bool Is32BitProcessOn64BitProcessor() { IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate(); if (fnDelegate == null) return false; bool isWow64; bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64); if (retVal == false) return false; return isWow64; } private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate() { IntPtr handle = LoadLibrary("kernel32"); if (handle != IntPtr.Zero) { IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process"); if (fnPtr != IntPtr.Zero) return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate)); } return null; } public enum SoftwareArchitecture { Unknown = 0, x32 = 1, x64 = 2 } static public SoftwareArchitecture OSBits { get { SoftwareArchitecture osbits = SoftwareArchitecture.Unknown; switch (IntPtr.Size * 8) { case 64: osbits = SoftwareArchitecture.x64; break; case 32: if (Is32BitProcessOn64BitProcessor()) osbits = SoftwareArchitecture.x64; else osbits = SoftwareArchitecture.x32; break; default: osbits = SoftwareArchitecture.Unknown; break; } return osbits; } } [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr LoadLibrary(string libraryName); [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName); private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process); Вызов: Console.WriteLine($"Версия Вашей ОС: {OSCheckBit.OSBits}");

среда, 26 февраля 2020 г.

Вызов неуправляемого кода из управляемого

#pinvoke #c_sharp


Есть необходимость вызвать функцию WinAPI из кода на C#. Какие средства языка позволяют
это сделать?    


Ответы

Ответ 1



Есть разные подходы. Практические рекомендации по взаимодействию управляемого и машинного кода. Например, если использовать P/Invoke из C#, то это выглядит так: using System; using System.Runtime.InteropServices; namespace Sample { class Program { static void Main(string[] args) { MessageBox(IntPtr.Zero, "Hello, World!", "", 0); } [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int MessageBox(IntPtr hWnd, String message, String caption, int options); } }

пятница, 24 января 2020 г.

Передача делегата в неуправляемый код как указатель на функцию

#c_sharp #pinvoke #interop


Имеется неуправляемый метод, который принимает указатель на функцию callback.

Определенный прототип выглядит так:

typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)
                          (SDL_Window *win, const SDL_Point *area, void *data);


Думаю определение делегата должно быть соответственно таким:

delegate HitTestResult HitTestDelegate(IntPtr windowPtr,
                                       IntPtr pointAreaPtr, IntPtr userData);


Но тут теперь возникает вопрос, нужно ли данный делегат помечать как указатель на
неуправляемую функцию, т.е. ставить ему атрибут

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate HitTestResult HitTestDelegate(IntPtr windowPtr,
                                       IntPtr pointAreaPtr, IntPtr userData);


Т.к. стоит SDLCALL определнный как __cdecl.
    


Ответы

Ответ 1



Этот атрибут нужен не столько для указания того факта, что делегат нужно маршаллировать как указатель на функцию, сколько для указания соглашения о вызове. Соглашение вызова по умолчанию - stdcall, поэтому, если используется другое соглашение, естественно нужно это указать.

Ответ 2



Вот так? [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void MyFunctionDelegate(IntPtr frame); [DllImport("my.dll")] public extern static int MySetDataHandlerFunc( [MarshalAs(UnmanagedType.FunctionPtr)]MyFunctionDelegate functionCallback); https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getdelegateforfunctionpointer?view=netframework-4.7.2 https://stackoverflow.com/questions/1969049/c-sharp-p-invoke-marshalling-structures-containing-function-pointers http://www.xinterop.com/index.php/2013/04/13/introduction-to-c-pinvoke-interop-sdk/

вторник, 31 декабря 2019 г.

Как передать в C# массив строк из неуправляемой библиотеки?

#c #pinvoke #c_sharp


Привет!
Функция на C в DLL (которую я не могу менять), возвращает массив строк. Число элементов
массива заранее неизвестно и может быть от 0 до 255.
#define MAX_ARRAY_SIZE 255

//
// Возвращает длину массива (количество строк)
//
LONG GetStringArray(char **Array);

Реально ли вообще передать такие данные через P/Invoke? Если да, то как подступиться
к задаче?    


Ответы

Ответ 1



Самый удобный способ это по совету wow использовать Managed C++ и написать обертку оттуда. Можно и сделать чуть более криво примерно так(я добавил ссылку на входной массив, чтобы не использовать внешнюю функцию инициализации, которая необходима при вашем описании GetStringArray ) как: С++ extern "C" __declspec(dllexport) LONG StringFunc(char** &data); LONG StringFunc(char** & data) { LONG count = 2; data = new char*[count]; data[0] = new char[10]; data[1] = new char[10]; strcpy(data[0], "str1"); strcpy(data[1], "bla bla1"); return count; } С#: [DllImport(@"..\..\..\..\debug\NativeDll.dll")] public static extern LONG StringFunc(ref IntPtr data); public static String[] CallNative() { IntPtr ptr_start = IntPtr.Zero; LONG count = StringFunc(ref ptr_start); //массив указателей на строки IntPtr []ptr_strings = new IntPtr[count]; //копируем указатели на строки Marshal.Copy(ptr_start, ptr_strings, 0, count); String[] strings = new string[count]; for (int i=0;i< count; i++) { strings[i] = Marshal.PtrToStringAnsi(ptr_strings[i]); } return strings; } static void Main(string[] args) { String[] strings = CallNative(); Array.ForEach(strings, s => Console.WriteLine(s)); }

Ответ 2



Посмотрите PInvoke Interop Assistant. Это набор инструментов по работе с pinvoke. Если окажется, что массив никак не протащить через pinvoke, можно написать библиотеку-обертку, которая будет преобразовывать неудобный формат в удобный. Например, можно в обертке принимать массив строк, а выдавать строки по отдельности.

вторник, 24 декабря 2019 г.

Узнать, использует ли процесс технологию ASLR на C#

#c_sharp #pinvoke


В общем, был написан сей опус, что внизу. Гуглю уже пятый день, ничего толкового
не смог сделать. Код должен работать, но скорее всего я не правильно определил функции
и переменные, от чего на каждом процессе выдается False.

Вот код:

class Program{
    const int PROCESS_QUERY_INFORMATION = 0x0400;
    const int PROCESS_WM_READ = 0x0010;

    public enum PROCESS_MITIGATION_POLICY
    {
        ProcessDEPPolicy = 0,
        ProcessASLRPolicy = 1,
        ProcessDynamicCodePolicy = 2,
        ProcessStrictHandleCheckPolicy = 3,
        ProcessSystemCallDisablePolicy = 4,
        ProcessMitigationOptionsMask = 5,
        ProcessExtensionPointDisablePolicy = 6,
        ProcessControlFlowGuardPolicy = 7,
        ProcessSignaturePolicy = 8,
        ProcessFontDisablePolicy = 9,
        ProcessImageLoadPolicy = 10,
        MaxProcessMitigationPolicy = 11
    }
    [StructLayout(LayoutKind.Explicit)]
    public struct union
    {
        [FieldOffset(0)]
        uint EnableBottomUpRandomization;
        [FieldOffset(0)]
        uint EnableForceRelocateImages;
        [FieldOffset(0)]
        uint EnableHighEntropy;
        [FieldOffset(0)]
        uint DisallowStrippedImages;
        [FieldOffset(0)]
        uint ReservedFlags;
    }

    public struct PROCESS_MITIGATION_ASLR_POLICY
    {
        uint Flags;
        union other;
    }

    [DllImport("kernel32.dll")]
    public static extern IntPtr OpenProcess(
        int dwDesiredAccess,
        bool bInheritHandle,
        int dwProcessId);

    [DllImport("kernel32.dll")]
    static extern bool GetProcessMitigationPolicy(
        IntPtr hProcess,
        PROCESS_MITIGATION_POLICY mitigationPolicy,
        ref PROCESS_MITIGATION_ASLR_POLICY lpBuffer,
        int dwLength);

    static void Main()
    {
        string ID_str = Console.ReadLine();
        int ID = int.Parse(ID_str);
        Process proc = Process.GetProcessById(ID);

        IntPtr hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false,
proc.Id);
        PROCESS_MITIGATION_ASLR_POLICY PMAP = new PROCESS_MITIGATION_ASLR_POLICY();

        bool result = GetProcessMitigationPolicy(hProc, PROCESS_MITIGATION_POLICY.ProcessASLRPolicy,
ref PMAP, Marshal.SizeOf(PMAP));
        Console.WriteLine(result);
        Console.ReadKey();
    }
}


pinvoke.net не шарит эти функции, так что я вообще в тупике.
    


Ответы

Ответ 1



В оригинале PROCESS_MITIGATION_ASLR_POLICY содержит битовую структуру, которые C# не поддерживает. Поэтому определение нужно немного переделать (проверьте, Marshal.SizeOf должен возвращать 4): struct PROCESS_MITIGATION_ASLR_POLICY { uint Flags; bool EnableBottomUpRandomization { get { return (Flags & 1) > 0; } } bool EnableForceRelocateImages { get { return (Flags & 2) > 0; } } bool EnableHighEntropy { get { return (Flags & 4) > 0; } } bool DisallowStrippedImages { get { return (Flags & 8) > 0; } } }

среда, 22 мая 2019 г.

Как проверить разрядность системы?

Имея данный алгоритм, почему-то большую часть показывает x32. У меня стоит x64

private static bool Is64Bit() { return IntPtr.Size == 8; }
public static string CheckOS() { if (Is64Bit()) return "x64"; else return "x32"; }
[DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool IsWow64Process([In] IntPtr hProcess, out bool lpSystemInfo);

Как нормально проверить на всех осях разрядность?


Ответ

Решил проблему так:
internal class OSCheckBit { private static bool Is32BitProcessOn64BitProcessor() { IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate(); if (fnDelegate == null) return false; bool isWow64; bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64); if (retVal == false) return false; return isWow64; } private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate() { IntPtr handle = LoadLibrary("kernel32"); if (handle != IntPtr.Zero) { IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process"); if (fnPtr != IntPtr.Zero) return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate)); } return null; } public enum SoftwareArchitecture { Unknown = 0, x32 = 1, x64 = 2 } static public SoftwareArchitecture OSBits { get { SoftwareArchitecture osbits = SoftwareArchitecture.Unknown;
switch (IntPtr.Size * 8) { case 64: osbits = SoftwareArchitecture.x64; break; case 32: if (Is32BitProcessOn64BitProcessor()) osbits = SoftwareArchitecture.x64; else osbits = SoftwareArchitecture.x32; break; default: osbits = SoftwareArchitecture.Unknown; break; }
return osbits; } } [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr LoadLibrary(string libraryName); [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)] public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName); private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process);
Вызов: Console.WriteLine($"Версия Вашей ОС: {OSCheckBit.OSBits}");

среда, 15 мая 2019 г.

Вызов неуправляемого кода из управляемого

Есть необходимость вызвать функцию WinAPI из кода на C#. Какие средства языка позволяют это сделать?


Ответ

Есть разные подходы. Практические рекомендации по взаимодействию управляемого и машинного кода Например, если использовать P/Invoke из C#, то это выглядит так: using System; using System.Runtime.InteropServices;
namespace Sample { class Program { static void Main(string[] args) { MessageBox(IntPtr.Zero, "Hello, World!", "", 0); }
[DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int MessageBox(IntPtr hWnd, String message, String caption, int options); } }

четверг, 20 декабря 2018 г.

Как передать в C# массив строк из неуправляемой библиотеки?

Привет! Функция на C в DLL (которую я не могу менять), возвращает массив строк. Число элементов массива заранее неизвестно и может быть от 0 до 255. #define MAX_ARRAY_SIZE 255
// // Возвращает длину массива (количество строк) // LONG GetStringArray(char **Array); Реально ли вообще передать такие данные через P/Invoke? Если да, то как подступиться к задаче?


Ответ

Самый удобный способ это по совету wow использовать Managed C++ и написать обертку оттуда. Можно и сделать чуть более криво примерно так(я добавил ссылку на входной массив, чтобы не использовать внешнюю функцию инициализации, которая необходима при вашем описании GetStringArray ) как: С++ extern "C" __declspec(dllexport) LONG StringFunc(char** &data);
LONG StringFunc(char** & data) { LONG count = 2; data = new char*[count]; data[0] = new char[10]; data[1] = new char[10]; strcpy(data[0], "str1"); strcpy(data[1], "bla bla1"); return count;
} С#: [DllImport(@"..\..\..\..\debug\NativeDll.dll")]
public static extern LONG StringFunc(ref IntPtr data);
public static String[] CallNative() { IntPtr ptr_start = IntPtr.Zero; LONG count = StringFunc(ref ptr_start);
//массив указателей на строки IntPtr []ptr_strings = new IntPtr[count]; //копируем указатели на строки Marshal.Copy(ptr_start, ptr_strings, 0, count); String[] strings = new string[count];
for (int i=0;i< count; i++) { strings[i] = Marshal.PtrToStringAnsi(ptr_strings[i]); }
return strings; }
static void Main(string[] args) { String[] strings = CallNative(); Array.ForEach(strings, s => Console.WriteLine(s)); }

вторник, 27 ноября 2018 г.

Узнать, использует ли процесс технологию ASLR на C#

В общем, был написан сей опус, что внизу. Гуглю уже пятый день, ничего толкового не смог сделать. Код должен работать, но скорее всего я не правильно определил функции и переменные, от чего на каждом процессе выдается False.
Вот код:
class Program{ const int PROCESS_QUERY_INFORMATION = 0x0400; const int PROCESS_WM_READ = 0x0010;
public enum PROCESS_MITIGATION_POLICY { ProcessDEPPolicy = 0, ProcessASLRPolicy = 1, ProcessDynamicCodePolicy = 2, ProcessStrictHandleCheckPolicy = 3, ProcessSystemCallDisablePolicy = 4, ProcessMitigationOptionsMask = 5, ProcessExtensionPointDisablePolicy = 6, ProcessControlFlowGuardPolicy = 7, ProcessSignaturePolicy = 8, ProcessFontDisablePolicy = 9, ProcessImageLoadPolicy = 10, MaxProcessMitigationPolicy = 11 } [StructLayout(LayoutKind.Explicit)] public struct union { [FieldOffset(0)] uint EnableBottomUpRandomization; [FieldOffset(0)] uint EnableForceRelocateImages; [FieldOffset(0)] uint EnableHighEntropy; [FieldOffset(0)] uint DisallowStrippedImages; [FieldOffset(0)] uint ReservedFlags; }
public struct PROCESS_MITIGATION_ASLR_POLICY { uint Flags; union other; }
[DllImport("kernel32.dll")] public static extern IntPtr OpenProcess( int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")] static extern bool GetProcessMitigationPolicy( IntPtr hProcess, PROCESS_MITIGATION_POLICY mitigationPolicy, ref PROCESS_MITIGATION_ASLR_POLICY lpBuffer, int dwLength);
static void Main() { string ID_str = Console.ReadLine(); int ID = int.Parse(ID_str); Process proc = Process.GetProcessById(ID);
IntPtr hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, proc.Id); PROCESS_MITIGATION_ASLR_POLICY PMAP = new PROCESS_MITIGATION_ASLR_POLICY();
bool result = GetProcessMitigationPolicy(hProc, PROCESS_MITIGATION_POLICY.ProcessASLRPolicy, ref PMAP, Marshal.SizeOf(PMAP)); Console.WriteLine(result); Console.ReadKey(); } }
pinvoke.net не шарит эти функции, так что я вообще в тупике.


Ответ

В оригинале PROCESS_MITIGATION_ASLR_POLICY содержит битовую структуру, которые C# не поддерживает. Поэтому определение нужно немного переделать (проверьте, Marshal.SizeOf должен возвращать 4):
struct PROCESS_MITIGATION_ASLR_POLICY { uint Flags;
bool EnableBottomUpRandomization { get { return (Flags & 1) > 0; } }
bool EnableForceRelocateImages { get { return (Flags & 2) > 0; } }
bool EnableHighEntropy { get { return (Flags & 4) > 0; } }
bool DisallowStrippedImages { get { return (Flags & 8) > 0; } } }