Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Windows API declarations for C#
#1
Download

This is for C# programmers, not for QM. In QM can be used only in C# scripts.

Contains 48000 declarations of struct, enum, delegate, extern functions, interfaces, coclasses, Guid, const.

Converted commonly used Windows 10 SDK header files. The list is below.

Tools used to convert C to C#:
Quick Macros - scripting.
Clang - preprocessing.
Dumpbin from SDK - extracting dll names and GUID.
My C-to-C# converter project.

More declarations may be added in the future. Usually for me it is easy to do with these tools. Your suggestions are welcome.

Macro SDK headers
Code:
Copy      Help
//#define __cplusplus 201103L //clang defines this
#define _MSC_VER 1900 //VS2015
#define _MSC_FULL_VER 190023026
#define _MSC_EXTENSIONS 1

#define _UNICODE 1
#define UNICODE 1
#define _WCHAR_T_DEFINED 1
#define _MT 1
#define _DLL 1
#define _WIN32 1 //defined for 32 and 64

#ifdef USE64BIT
#define _WIN64 1
#define _M_AMD64 100
#define _M_X64 100
#else
#define _M_IX86 600
#endif
#define _INTEGRAL_MAX_BITS 64 //need if 32

#define WINVER 0x0A00 //Win10
#define _WIN32_WINNT 0x0A00
#define _WIN32_IE 0x0B00 //IE11

//add __int128 struct, because C# does not have a matching type
struct __int128 { float a, b, c, d; };
struct __int128d { float a, b, c, d; };
struct __int128i { float a, b, c, d; };

//prevent adding XML interfaces, but need some for parameters
#define __msxml_h__
#define __msxml2_h__
#define __msxml6_h__
typedef IntPtr IXMLElement;
typedef IntPtr IXMLDOMDocument;

//add some that are in headers that we remove
#define size_t LPARAM
#define intptr_t LPARAM
#define uintptr_t LPARAM
#define time_t LPARAM
typedef void* va_list;
typedef struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; } FILE;

#define WIN32_LEAN_AND_MEAN //don't include come rarely used headers in windows.h
#define USE_COM_CONTEXT_DEF //IContext etc

#include <windows.h>

#include <regstr.h> //registry strings
#include <ole2.h> //OLE. Includes objbase.h, oleauto.h, urlmon.h, ...
#include <commctrl.h> //common controls
#include <shlobj.h> //shell
#include <shellapi.h> //shell
#include <shlwapi.h> //misc string functions etc
#include <olectl.h> //some OLE API
#include <oleacc.h> //MSAA accessible objects
#include <UIAutomation.h> //UI Automation
#include <mmsystem.h> //multimedia etc
#include <tlhelp32.h> //process info etc
#include <psapi.h> //process info etc
#include <wtsapi32.h> //user sessions etc
#include <winperf.h> //something used with PDH
#include <pdh.h> //performance counters //TODO: test System.Diagnostics.PerformanceCounter
#include <uxtheme.h> //visual styles
#include <vsstyle.h> //visual styles
#include <dwmapi.h> //DWM
#include <htmlhelp.h> //HTML help
#include <winioctl.h> //file IO low-level
#include <aclapi.h> //security //TODO: test System.Security.AccessControl etc
#include <sddl.h> //security strings
#include <taskschd.h> //Task Scheduler
#include <ShellScalingAPI.h> //high DPI
#include <appmodel.h> //Windows Store apps
#include <winternl.h> //Windows semi-internal API, eg NtX, RtlX
#include <iepmapi.h> //IE protected mode
#include <userenv.h> //user profiles, CreateEnvironmentBlock
#include <netlistmgr.h> //network list
#include <winnetwk.h> //networking
#include <cderr.h> //commdlg errors
#include <commdlg.h> //common dialogs //TODO: test System.Windows.Forms.OpenFileDialog, .FontDialog etc.
#include <dde.h> //DDE
#include <ddeml.h> //DDE
#include <wininet.h> //internet. We can instead use System.Net.Http namespace and System.Net.FtpWebRequest classes, but maybe this still can be useful.
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <winsock2.h> //sockets (TCP etc) //TODO: test System.Net.Sockets
#include <nspapi.h> //MS extensions for sockets
#include <richedit.h> //rich edit control
#include <usp10.h> //text drawing low-level
#include <dbt.h> //const/struct for WM_DEVICECHANGE
#include <ktmw32.h> //file transaction
#define _MSI_NO_CRYPTO
#include <msi.h> //installer. MsiGetShortcutTarget, MsiGetComponentPath.
#include <commoncontrols.h> //IImageList
#include <powrprof.h> //power profiles, SetSuspendState
#include <lm.h> //LAN management, NetServerEnum
#include <Wlanapi.h> //WiFi
#include <adhoc.h> //WiFi
#include <mscoree.h> //unmanaged .NET API

//core audio API
#include <Audioclient.h>
#include <Audiopolicy.h>
#include <Mmdeviceapi.h>
#include <Devicetopology.h>
#include <Endpointvolume.h>

#if 0
//these are little tested and probably not useful
#include <iphlpapi.h> //IP helper, eg list network adapters. Use System.Net.NetworkInformation namespace.
#include <icmpapi.h> //ICMP, eg to implement a Ping(). Use System.Net.NetworkInformation namespace.
#include <GL/gl.h> //openGL
#include <GL/glu.h> //openGL util

//these are never tested but seem interesting
#include <RestartManager.h> //restart manager
#include <Pla.h> //performance logs and alerts
#include <Esent.h> //extensible storage engine
#include <Clfsw32.h> //common log file system. .NET has something similar in System.Diagnostics.
#include <Clfsmgmtw32.h> //common log file management. .NET has something similar in System.Diagnostics.
#include <WinEvt.h> //event log. .NET has something similar in System.Diagnostics.
#include <Winsxs.h> //several interfaces for side-by-side assembly management

//these probably should not be added
#include <shldisp.h> //shell IDispatch interfaces
#include <scrnsave.h> //screen saver
#include <dbghelp.h> //debug help library
#include <imagehlp.h> //many the same as dbghelp.h. Includes wintrust.h -> wincrypt.h which is not welcome.
#include <setupapi.h> //obsolete
#include <mapi.h> //only for MS Outlook. Can instead use Outlook COM.
#include <snmp.h> //can instead download a SNMP .NET library
#include Sspi.h //authentication. Includes Security.h. Use .NET classes.
//these would be included if no WIN32_LEAN_AND_MEAN
#include <winefs.h> //encrypted file system. .NET can encrypt/decrypt a file, but maybe this also can be useful.
#include <winspool.h> //printer API. Big. Use System.Drawing.Printing namespace. See also System.Printing namespace.
#include <wincrypt.h> //cryptography. Large. Use System.Security.Cryptography namespace.
#endif

How to use the downloaded file containing Windows API declarations:
Code:
Copy      Help
// Don't add this file to your project. Copy-paste only declarations that you need.
// Not all declarations can be compiled without editing.
//    For example, cannot declare some struct pointer (use IntPtr instead, or in struct replace non-blittable types with IntPtr etc), cannot use undefined struct pointer/ref/out (use IntPtr instead).
// Not all declarations are correct, usually because declarations in Windows SDK files from which they have been automatically converted lack some info.
//    For example, some function parameters that should be 'out' or '[Out]' or '[In]' or array now are just 'ref', because SDK declarations didn't have proper in/out annotations. Also for this reason some parameters that should be 'string' now are 'StringBuilder'.
//    You may want to create overloads where parameters can be of more than one type.
//    You may want to add 'SetLastError=true' to DllImport attribute parameters.
// Some declarations contain pointers and therefore can be used only in 'unsafe' context, in some cases with 'fixed'. Or you can replace pointers to IntPtr.
// These declarations are for Windows 10. Some Windows API are different or missing on other Windows versions.
// In some cases need to use different declarations in 32-bit and 64-bit process. This file contains everything that is not different, + 64-bit versions, + 32-bit versions with name suffix ""__32"".

Also known as P/invoke, pinvoke, platform invoke signatures, call unmanaged dll exported methods, Win32 API, COM interop.
#2
Could you give some simple examples how to use this Windows API in C#?
#3
Code:
Copy      Help
#region copy-paste-from-Api.cs

using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

using Wnd = System.IntPtr; //HWND (window handle)
using LPARAM = System.IntPtr; //LPARAM, WPARAM, LRESULT, X_PTR, SIZE_T, ... (non-pointer types that have different size in 64-bit and 32-bit process)

//add this to projects that will use these API
[module: DefaultCharSet(CharSet.Unicode)]

static unsafe class API
{
    //simplest Windows API function declaration  example
    [DllImport("user32.dll", EntryPoint = "FindWindowW")]
    public static extern Wnd FindWindow(string lpClassName, string lpWindowName);

    //example of a function that gets text using a caller-allocated buffer
    [DllImport("user32.dll")]
    public static extern int InternalGetWindowText(Wnd hWnd, [Out] StringBuilder pString, int cchMaxCount);

    //example of a function that uses a callback function (delegate)
    [DllImport("user32.dll")]
    public static extern bool EnumChildWindows(Wnd hWndParent, WNDENUMPROC lpEnumFunc, LPARAM lParam);

    //example delegate type declaration
    public delegate bool WNDENUMPROC(Wnd param1, LPARAM param2);

    //this is probably the most popular Windows API function, but .NET does not have a wrapper function or class that works with any window
    [DllImport("user32.dll", EntryPoint = "SendMessageW")]
    public static extern LPARAM SendMessage(Wnd hWnd, uint Msg, LPARAM wParam, LPARAM lParam);

    //overload example: lParam is string
    [DllImport("user32.dll", EntryPoint = "SendMessageW")]
    public static extern LPARAM SendMessage(Wnd hWnd, uint Msg, LPARAM wParam, string lParam);

    //constant example
    public const uint WM_SETTEXT = 0xC;

    //struct example
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        //of course here we can add member functions
        public override string ToString()
        {
            return string.Format("L={0} T={1} R={2} B={3}  W={4} H={5}", left, top, right, bottom, right-left, bottom-top);
        }
    }

    //and a function that uses the struct
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(Wnd hWnd, out RECT lpRect);

}

#endregion

#region my-console-program

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        //find Notepad window
        Wnd hwnd = API.FindWindow("Notepad", null);
        Console.WriteLine(hwnd);

        //get window name
        var sb = new StringBuilder(1000);
        API.InternalGetWindowText(hwnd, sb, sb.Capacity);
        var s = sb.ToString();
        Console.WriteLine(s);

        //find first child window
        Wnd hctrl = default(Wnd);
        API.EnumChildWindows(hwnd, (h, p) => { hctrl = h; return false; }, default(LPARAM) );

        //set child window text
        API.SendMessage(hctrl, API.WM_SETTEXT, default(LPARAM), "Notepad window name is " + s);

        //get window rectangle
        API.RECT r;
        API.GetWindowRect(hwnd, out r);
        Console.WriteLine(r);
        
        //don't close console immediately
        Console.ReadKey();
    }
}

#endregion

Normally you'll use this in C# projects. To allow 'unsafe' keyword, in project Properties Build tab check 'Allow unsafe code'. Or remove the 'unsafe' keyword.

If want to run this as a QM C# script, remove the 'unsafe' keyword or use code 'CsScript x.SetOptions("compilerOptions=/unsafe"); x.Exec("")'. Also remove 'Console.ReadKey();'.
#4
Thanks a lot for a thorough explanation.
I could compile and run it both as C# project and QM script.
Without your clarification and sample I have no clue how to get started on using this API stuff.
It really convenient to use C++ API in C# now.
#5
Function SDK_find_declaration
Trigger Cd     Help - how to add the trigger to the macro
Code:
Copy      Help
;Finds a Windows API declaration in Api.cs.
;How to use:
;;;In your C# editor type a Windows API name, move the mouse over it and run this macro.
;;;Or move the mouse over a Windows API name anywhere, for example in API documentation.
;;;To run this macro you can use a hotkey trigger; default is Ctrl+D.
;;;The macro shows a dialog with the API name, its C# declaration (empty if not found) and several options.
;;;In the dialog review the declaration, maybe change options, and click OK.
;;;If you start this macro while it is already running, it replaces text in the dialog.
;;;Also you can edit text in the dialog Name field to search for a new name.
;How it works:
;;;Double-clicks to select word from mouse, and gets the word through the clipboard.
;;;Finds the declaration in Api.cs file and shows it in dialog together with options.
;;;Api.cs file full path must be specified in the dialog.
;;;The macro can copy the declaration to the clipboard or/and run a macro that for example can insert the declaration in a C# file. Example - function SDK_insert_declaration.


spe 20
int w=win(mouse)
if w!=_hwndqm or !WinTest(child(mouse) "Toolbar*") ;;prevent double clicking the Run button
,if(w!=win) act w; key LR ;;prevent VS selecting whole line when there is selected text
,dou
,str name.getsel
,name.trim

if getopt(nthreads)>1
,w=win("Windows API for C#" "#32770")
,if w
,,name.setwintext(id(4 w))
,,act w
,,ret

str dd=
;BEGIN DIALOG
;0 "" 0x90C80AC8 0x0 0 0 552 166 "Windows API for C#"
;3 Static 0x54000000 0x0 8 8 28 12 "Name"
;4 Edit 0x54030080 0x200 40 8 152 12 "Nam" "Windows API name (a function, struct, enum, delegate, const, interface, COM class, Guid).[]In your C# editor type the name, move the mouse over it and run this macro."
;6 Edit 0x54231044 0x200 8 24 536 72 "Decl"
;10 Static 0x54000000 0x0 16 116 38 13 "File Api.cs"
;11 Edit 0x54030080 0x200 56 116 208 13 "Api"
;7 Button 0x54012003 0x0 288 116 76 13 "Copy to clipboard"
;14 Button 0x54012003 0x0 376 116 54 13 "Run macro"
;15 Edit 0x54030080 0x200 432 116 104 13 "Mac" "Should begin with:[]function str'name str'decl"
;1 Button 0x54030001 0x4 8 144 48 14 "OK"
;2 Button 0x54030000 0x4 60 144 48 14 "Cancel"
;5 Button 0x54020007 0x0 8 100 536 37 "Options"
;END DIALOG
;DIALOG EDITOR: "" 0x2040308 "*" "" "" ""

str controls = "4 6 11 7 14 15"
str e4Nam e6Dec e11Api c7Cop c14Run e15Mac
e4Nam=name
rget e11Api "Api.cs" "\CsharpWinAPI" 0 "$my qm$\Api.cs"
rget c7Cop "bClipboard" "\CsharpWinAPI" 0 "1"
rget c14Run "bMacro" "\CsharpWinAPI"
rget e15Mac "sMacro" "\CsharpWinAPI"

if(!ShowDialog(dd &sub.DlgProc &controls)) ret

rset e11Api "Api.cs" "\CsharpWinAPI"
rset c7Cop "bClipboard" "\CsharpWinAPI"
rset c14Run "bMacro" "\CsharpWinAPI"
rset e15Mac "sMacro" "\CsharpWinAPI"

if(!e6Dec.len) ret

if c7Cop=1
,e6Dec.setclip

if c14Run=1 and e15Mac.len
,mac e15Mac "" e4Nam e6Dec

err+ mes _error.description "" "x"


#sub DlgProc
function# hDlg message wParam lParam

sel message
,case WM_INITDIALOG
,sub.Find hDlg
,
,case WM_DESTROY
,case WM_COMMAND goto messages2
ret
;messages2
sel wParam
,case IDOK
,
,case EN_CHANGE<<16|4
,sub.Find hDlg
,
,case EN_CHANGE<<16|11
,_s.getwintext(lParam)
,if(FileExists(_s)) sub.Find hDlg
ret 1


#sub Find
function hDlg

str apiFile.getwintext(id(11 hDlg))
str name.getwintext(id(4 hDlg))

if(!apiFile.len) mes "Api.cs file not specified."; ret
if(!FileExists(apiFile)) mes "Api.cs file not found."; ret

type __CSHARPWINAPICACHE IStringMap'm str'path DateTime'time long'size
__CSHARPWINAPICACHE+ __g_csWinApiCache

DateTime t; long z
FileGetAttributes apiFile z t
if apiFile!=__g_csWinApiCache.path or t!=__g_csWinApiCache.time or z!=__g_csWinApiCache.size
,sub.ApiFileToStringMap __g_csWinApiCache.m apiFile
,if(__g_csWinApiCache.m.Count=0) mes "Found 0 declarations in Api.cs file."; ret
,__g_csWinApiCache.path=apiFile; __g_csWinApiCache.time=t; __g_csWinApiCache.size=z
,;out "loaded"

if(empty(name)) ret
str decl
__g_csWinApiCache.m.Get2(name decl)
str decl32
if(__g_csWinApiCache.m.Get2(F"{name}__32" decl32)) decl+"[][]"; decl+decl32
if(decl.len) decl+"[]"
decl.setwintext(id(6 hDlg))

err+ mes _error.description "" "x"


#sub ApiFileToStringMap
function IStringMap&m $apiFile

m._create; m.Flags=2

str s.getfile(apiFile)

ARRAY(str) a

str rxType="(?ms)^(?:\[[^\r\n]+\r\n)*public (?:struct|enum|interface|class) (\w+)[^\r\n\{]+\{(?:\}$|.+?^\})"
str rxFunc="(?m)^(?:\[[^\r\n]+\r\n)*public (?:static extern|delegate) \w+\** (\w+)\(.+;$"
str rxGuid="(?m)^public static Guid (\w+) =.+;$"
str rxConst="(?m)^public (?:const|readonly) \w+ (\w+) =.+;$"

if(!findrx(s rxType 0 4 a)) end "failed" 1
sub.AddToMap a m
if(!findrx(s rxFunc 0 4 a)) end "failed" 1
sub.AddToMap a m
if(!findrx(s rxGuid 0 4 a)) end "failed" 1
sub.AddToMap a m
if(!findrx(s rxConst 0 4 a)) end "failed" 1
sub.AddToMap a m


#sub AddToMap
function ARRAY(str)&a IStringMap'm

int i
for i 0 a.len
,m.Add(a[1 i] a[0 i])

Function SDK_insert_declaration
Code:
Copy      Help
;\
function str'name str'decl

;Inserts decl in file csFile, before line //insert new declaration here
;You can specify this function name in dialog "Windows API for C#" (function SDK_fine_declaration shows it) field "Run macro".
;If the file is open in Visual Studio, it nicely updates editor text, even with Undo, if the file is saved. Tested with Visual Studio 2015.

str csFile="Q:\Test\Test.cs" ;;change this


;out name
;out decl

str s.getfile(csFile)
int i=findrx(s "[][ \t]*//insert new declaration here")
if(i<0) end "the file must have line ''//insert new declaration here''"
decl-"[]"
decl.replacerx("(?m)^" "[9]") ;;tab-indent
s.insert(decl i)
s.setfile(csFile 0 -1 0x100)


Forum Jump:


Users browsing this thread: 1 Guest(s)