谁会GOLANG和pascal这二种语言,我想把一个GO写的开源项目翻译成pascal
调用wintun.dll单元
unit WinTun;
{$mode ObjFPC}{$H+}
interface
uses
Classes, Windows, SysUtils, JwaWindows, Dialogs, WinUnit, Win32Proc;
const
//用于接收和发送数据包的内存区域大小
WINTUN_MIN_RING_CAPACITY = $20000; //128kiB
WINTUN_MAX_RING_CAPACITY = $4000000; //64MiB
//最大IP数据包大小常量。IP数据包是在网络中传输的数据单元,它包含了源IP地址、目标IP地址、协议类型、数据等信息
WINTUN_MAX_IP_PACKET_SIZE = $FFFF; //65535
type
WINTUN_ADAPTER_HANDLE = Pointer;
WINTUN_SESSION_HANDLE = Pointer;
WINTUN_LOGGER_LEVEL = (WINTUN_LOG_INFO, WINTUN_LOG_WARN, WINTUN_LOG_ERR);
WINTUN_CREATE_ADAPTER_FUNC = function(Name: LPCWSTR; TunnelType: LPCWSTR; RequestedGUID: PGUID): WINTUN_ADAPTER_HANDLE; stdcall;
WINTUN_OPEN_ADAPTER_FUNC = function(Name: LPCWSTR): WINTUN_ADAPTER_HANDLE; stdcall;
WINTUN_CLOSE_ADAPTER_PROC = procedure(Adapter: WINTUN_ADAPTER_HANDLE); stdcall;
WINTUN_DELETE_DRIVER_FUNC = function: BOOL; stdcall;
WINTUN_GET_ADAPTER_LUID_PROC = procedure(Adapter: WINTUN_ADAPTER_HANDLE; Luid: PNET_LUID_LH); stdcall;
//几乎所有的编程语言都需要在函数调用时使用括号,无论函数是否有参数(形参)。这是因为括号是函数调用的一部分,它们用于标识函数的名称和参数列表
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC = function(): DWORD; stdcall;
WINTUN_LOGGER_CALLBACK_PROC = procedure(Level: WINTUN_LOGGER_LEVEL; Timestamp: DWORD64; Message: pwidechar); stdcall;
WINTUN_SET_LOGGER_PROC = procedure(NewLogger: WINTUN_LOGGER_CALLBACK_PROC); stdcall;
WINTUN_START_SESSION_FUNC = function(Adapter: WINTUN_ADAPTER_HANDLE; Capacity: DWORD): WINTUN_SESSION_HANDLE; stdcall;
WINTUN_END_SESSION_PROC = procedure(Session: WINTUN_SESSION_HANDLE); stdcall;
WINTUN_GET_READ_WAIT_EVENT_FUNC = function(Session: WINTUN_SESSION_HANDLE): HANDLE; stdcall;
//删除PacketSize的var保留字,因为用@来指向这个形参,也算引用,与var功能差不多
WINTUN_RECEIVE_PACKET_FUNC = function(Session: WINTUN_SESSION_HANDLE; PacketSize: PDWORD): pbyte; stdcall;
WINTUN_RELEASE_RECEIVE_PACKET_PROC = procedure(Session: WINTUN_SESSION_HANDLE; Packet: pbyte); stdcall;
WINTUN_ALLOCATE_SEND_PACKET_FUNC = function(Session: WINTUN_SESSION_HANDLE; PacketSize: DWORD): pbyte; stdcall;
WINTUN_SEND_PACKET_PROC = procedure(Session: WINTUN_SESSION_HANDLE; Packet: pbyte); stdcall;
var
WintunCreateAdapter: WINTUN_CREATE_ADAPTER_FUNC;
WintunOpenAdapter: WINTUN_OPEN_ADAPTER_FUNC;
WintunCloseAdapter: WINTUN_CLOSE_ADAPTER_PROC;
WintunDeleteDriver: WINTUN_DELETE_DRIVER_FUNC;
WintunGetAdapterLUID: WINTUN_GET_ADAPTER_LUID_PROC;
WintunGetRunningDriverVersion: WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC;
WintunSetLogger: WINTUN_SET_LOGGER_PROC;
WintunStartSession: WINTUN_START_SESSION_FUNC;
WintunEndSession: WINTUN_END_SESSION_PROC;
WintunGetReadWaitEvent: WINTUN_GET_READ_WAIT_EVENT_FUNC;
WintunReceivePacket: WINTUN_RECEIVE_PACKET_FUNC;
WintunReleaseReceivePacket: WINTUN_RELEASE_RECEIVE_PACKET_PROC;
WintunAllocateSendPacket: WINTUN_ALLOCATE_SEND_PACKET_FUNC;
WintunSendPacket: WINTUN_SEND_PACKET_PROC;
implementation
const
WintunDll = 'wintun.dll';
var
WintunModule: HMODULE;
procedure LoadWintunLibrary;
var
ErrorCode: DWORD;
begin
//https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw
WintunModule := LoadLibraryExW(WintunDll, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
//https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes
if WintunModule = NULL then
begin
ShowMessage(SysErrorMessage(GetLastError));
Exit;
end;
//注意调用C++ dll方法名称,C++是大小写敏感的
Pointer(WintunCreateAdapter) := GetProcAddress(WintunModule, 'WintunCreateAdapter'); //创建适配器的函数
Pointer(WintunOpenAdapter) := GetProcAddress(WintunModule, 'WintunOpenAdapter'); //打开适配器的函数
Pointer(WintunCloseAdapter) := GetProcAddress(WintunModule, 'WintunCloseAdapter'); //关闭适配器的函数
Pointer(WintunDeleteDriver) := GetProcAddress(WintunModule, 'WintunDeleteDriver'); //删除驱动程序的函数
Pointer(WintunGetAdapterLUID) := GetProcAddress(WintunModule, 'WintunGetAdapterLUID'); //获取适配器LUID的函数
Pointer(WintunGetRunningDriverVersion) := GetProcAddress(WintunModule, 'WintunGetRunningDriverVersion'); //获取运行中驱动程序版本的函数
Pointer(WintunSetLogger) := GetProcAddress(WintunModule, 'WintunSetLogger'); //设置日志记录回调函数的函数
Pointer(WintunStartSession) := GetProcAddress(WintunModule, 'WintunStartSession'); //启动会话的函数,返回Wintun 会话句柄
Pointer(WintunEndSession) := GetProcAddress(WintunModule, 'WintunEndSession'); //结束会话的函数
Pointer(WintunGetReadWaitEvent) := GetProcAddress(WintunModule, 'WintunGetReadWaitEvent'); //获取wintun会话的读取等待事件的函数
Pointer(WintunReceivePacket) := GetProcAddress(WintunModule, 'WintunReceivePacket'); //接收数据包的函数
Pointer(WintunReleaseReceivePacket) := GetProcAddress(WintunModule, 'WintunReleaseReceivePacket'); //释放接收数据包的函数
Pointer(WintunAllocateSendPacket) := GetProcAddress(WintunModule, 'WintunAllocateSendPacket'); //分配发送数据包的函数
Pointer(WintunSendPacket) := GetProcAddress(WintunModule, 'WintunSendPacket'); //发送数据包的函数
ErrorCode := GetLastError;
if ErrorCode <> NO_ERROR then
//调用的这个方法https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-formatmessagew
ShowMessage(SysErrorMessage(ErrorCode));
end;
initialization
LoadWintunLibrary;
//finalization部分在程序退出时执行的,而不是手动调用的。
//因此,如果需要在程序运行过程中进行资源释放或其他清理操作,应该在适当的位置手动调用相应的代码
finalization
if not UnloadLibrary(WintunModule) then
ShowMessage(SysErrorMessage(GetLastError));
end.
调用windows API 单元
unit WinUnit;
{$mode ObjFPC}{$H+}
interface
uses
Classes, windows, SysUtils, Dialogs, JwaWindows;
type
SOCKADDR_INET = record
case integer of
0: (Ipv4: SOCKADDR_IN);
1: (Ipv6: SOCKADDR_IN6);
2: (si_family: word);
end;
PSOCKADDR_INET = ^SOCKADDR_INET;
//https://learn.microsoft.com/zh-cn/windows/win32/api/ifdef/ns-ifdef-net_luid_lh
NET_LUID_LH = record
case integer of
0: (Value: uint64);
1: (Info: record
Reserved: uint64;
NetLuidIndex: uint64;
IfType: word;
end);
end;
PNET_LUID_LH = ^NET_LUID_LH;
NL_PREFIX_ORIGIN = (
IpPrefixOriginOther = 0,
IpPrefixOriginManual,
IpPrefixOriginWellKnown,
IpPrefixOriginDhcp,
IpPrefixOriginRouterAdvertisement,
IpPrefixOriginUnchanged = 1 shl 4);
NL_SUFFIX_ORIGIN = (
IpSuffixOriginOther = 0,
IpSuffixOriginManual,
IpSuffixOriginWellKnown,
IpSuffixOriginDhcp,
IpSuffixOriginLinkLayerAddress,
IpSuffixOriginRandom,
IpSuffixOriginUnchanged = 1 shl 4);
//https://learn.microsoft.com/zh-cn/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row#members
MIB_UNICASTIPADDRESS_ROW = record
Address: SOCKADDR_INET;
InterfaceLuid: NET_LUID_LH;
InterfaceIndex: DWORD;
PrefixOrigin: NL_PREFIX_ORIGIN;
SuffixOrigin: NL_SUFFIX_ORIGIN;
ValidLifetime: ULONG;
PreferredLifetime: ULONG;
OnLinkPrefixLength: uint8; //子网掩网长度
SkipAsSource: boolean;
DadState: IP_DAD_STATE;
ScopeId: LARGE_INTEGER;
CreationTimeStamp: LARGE_INTEGER;
end;
PMIB_UNICASTIPADDRESS_ROW = ^MIB_UNICASTIPADDRESS_ROW;
var
//var修饰符表示参数是一个引用。对于指针类型的参数,使用var修饰符是不允许的,因为指针本身就是引用类型。
InitializeUnicastIpAddressEntry: procedure(PROW: PMIB_UNICASTIPADDRESS_ROW); stdcall;
CreateUnicastIpAddressEntry: function(const PROW: PMIB_UNICASTIPADDRESS_ROW): DWORD; stdcall;
SetUnicastIpAddressEntry: function(const PROW: PMIB_UNICASTIPADDRESS_ROW): DWORD;
//将 IPv6 地址转换为 Internet 标准格式的字符串
RtlIpv6AddressToStringW: function(const Addr: PIn6Addr; S: pwidechar): pwidechar; stdcall;
implementation
var
IPHLPAPIModule: HMODULE;
IPV6AddressTOSTRModule: HMODULE;
SetUnicastIpAddressEntryModule: HMODULE;
procedure LoadWinLibrary;
var
ErrorCode: DWORD;
begin
IPHLPAPIModule := LoadLibraryExW(iphlpapilib, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if IPHLPAPIModule = NULL then
begin
ShowMessage(SysErrorMessage(GetLastError));
Exit;
end;
IPV6AddressTOSTRModule := LoadLibraryExW(Ntdll, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if IPV6AddressTOSTRModule = NULL then
begin
ShowMessage(SysErrorMessage(GetLastError));
Exit;
end;
SetUnicastIpAddressEntryModule := LoadLibraryEx(iphlpapilib, 0, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
if SetUnicastIpAddressEntryModule = NULL then
begin
ShowMessage(SysErrorMessage(GetLastError));
Exit;
end;
Pointer(InitializeUnicastIpAddressEntry) := GetProcAddress(IPHLPAPIModule, 'InitializeUnicastIpAddressEntry'); //初始化PMIB_UNICASTIPADDRESS_ROW结构体
Pointer(CreateUnicastIpAddressEntry) := GetProcAddress(IPHLPAPIModule, 'CreateUnicastIpAddressEntry'); //此函数在本地设备上添加新的单播 IP 地址条目,如果函数成功,则返回值0
Pointer(RtlIpv6AddressToStringW) := GetProcAddress(IPV6AddressTOSTRModule, 'RtlIpv6AddressToStringW'); //以 Internet 标准格式将 IPv6 地址转换为字符串
Pointer(SetUnicastIpAddressEntry) := GetProcAddress(SetUnicastIpAddressEntryModule, 'SetUnicastIpAddressEntry'); //设置IP相关数据
ErrorCode := GetLastError;
if ErrorCode <> NO_ERROR then
//调用的这个方法https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-formatmessagew
ShowMessage(SysErrorMessage(ErrorCode));
end;
initialization
LoadWinLibrary;
finalization;
if not UnloadLibrary(IPHLPAPIModule) then
ShowMessage(SysErrorMessage(GetLastError));
if not UnloadLibrary(IPV6AddressTOSTRModule) then
ShowMessage(SysErrorMessage(GetLastError));
if not UnloadLibrary(SetUnicastIpAddressEntryModule) then
ShowMessage(SysErrorMessage(GetLastError));
end.
上面我自己写的PASCAL源码,有打算把 WireGuard 翻译成 pascal ,GO语言有点看不懂,如果有懂 GO 语言和 pascal 的可以交流一下!