Rust语言从入门到精通系列 - 零基础入门Win32 API开发(下)
Rust语言是一种快速、安全、并发的系统编程语言。它的设计目标是为了提供更好的内存安全和线程安全,同时保持高性能。而winapi模块则是Rust语言的一个重要组成部分,它提供了与Windows操作系统API的交互能力。本教程将介绍winapi模块的基础用法和进阶用法,以及最佳实践。
上一篇 Rust语言从入门到精通系列 - 零基础入门Win32 API开发(上)
介绍了Win32 API的一些基础用法,本篇主要介绍一些进阶用法。
进阶用法
使用Rust风格的COM组件
use std::ptr::null_mut;
use winapi::um::combaseapi::{CoInitializeEx, CoCreateInstance, CoUninitialize};
use winapi::um::objbase::COINIT_APARTMENTTHREADED;
use winapi::um::winuser::MessageBoxW;
use winapi::Interface;
#[com_interface("87654321-4321-4321-4321-434343434343")]
trait IMyInterface {
fn my_method(&self);
}
#[com_class("12345678-1234-1234-1234-123412341234", IMyInterface)]
struct MyClass;
impl IMyInterface for MyClass {
fn my_method(&self) {
MessageBoxW(
null_mut(),
"My method is called!".to_wide_null().as_ptr(),
"Success\0".to_wide_null().as_ptr(),
0,
);
}
}
fn main() {
unsafe {
CoInitializeEx(null_mut(), COINIT_APARTMENTTHREADED);
let mut p_my_interface: *mut IMyInterface = null_mut();
let hr = CoCreateInstance(
&MyClass::uuidof(),
null_mut(),
winapi::um::combaseapi::CLSCTX_INPROC_SERVER,
&IMyInterface::uuidof(),
&mut p_my_interface as *mut _ as *mut *mut _,
);
if hr == winapi::S_OK {
(*p_my_interface).my_method();
(*p_my_interface).release();
}
CoUninitialize();
}
}
打印屏幕截图
以下代码使用winapi模块的函数和结构体,实现在Windows操作系统下截取屏幕并打印。
use winapi::um::winuser::{GetDC, GetSystemMetrics, ReleaseDC, CreateCompatibleDC, CreateCompatibleBitmap, SelectObject, BitBlt, DeleteDC, DeleteObject, SM_CXSCREEN, SM_CYSCREEN, SRCCOPY};
use winapi::um::wingdi::{BITMAPINFO, BITMAPINFOHEADER, BI_RGB, RGBQUAD, GetDIBits, SetDIBitsToDevice};
use winapi::shared::windef::{HDC, HWND, HBITMAP, RECT};
use winapi::shared::minwindef::{DWORD, UINT};
use std::ptr::null_mut;
use std::mem::{size_of, zeroed};
fn main() {
let mut rect: RECT = unsafe { zeroed() };
unsafe {
let hwnd = GetDesktopWindow();
GetWindowRect(hwnd, &mut rect);
let hdc_screen = GetDC(null_mut());
let hdc = CreateCompatibleDC(hdc_screen);
let hbitmap = CreateCompatibleBitmap(hdc_screen, rect.right, rect.bottom);
let hbitmap_old = SelectObject(hdc, hbitmap as *mut _);
BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdc_screen, 0, 0, SRCCOPY);
SelectObject(hdc, hbitmap_old as *mut _);
DeleteDC(hdc);
ReleaseDC(null_mut(), hdc_screen);
let mut bmi: BITMAPINFO = zeroed();
bmi.bmiHeader.biSize = size_of::<BITMAPINFOHEADER>() as DWORD;
bmi.bmiHeader.biWidth = rect.right;
bmi.bmiHeader.biHeight = -rect.bottom;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
let mut bits = Vec::with_capacity(rect.right as usize * rect.bottom as usize);
GetDIBits(
hdc_screen,
hbitmap,
0,
rect.bottom as UINT,
bits.as_mut_ptr() as *mut _,
&mut bmi,
DIB_RGB_COLORS,
);
bits.set_len(rect.right as usize * rect.bottom as usize);
SetDIBitsToDevice(
hdc_screen,
0,
0,
rect.right,
rect.bottom,
0,
0,
0,
rect.bottom,
bits.as_ptr() as *mut _,
&bmi,
DIB_RGB_COLORS,
);
DeleteObject(hbitmap as *mut _);
}
}
上述代码使用了许多winapi模块中的函数和结构体,包括GetDC、GetSystemMetrics、ReleaseDC、CreateCompatibleDC、CreateCompatibleBitmap、SelectObject、BitBlt、DeleteDC、DeleteObject、BITMAPINFO、BITMAPINFOHEADER、BI_RGB、RGBQUAD、GetDIBits、SetDIBitsToDevice、GetDesktopWindow、GetWindowRect、SRCCOPY、DIB_RGB_COLORS等。
获取硬件信息
以下代码使用winapi模块的函数和结构体,实现在Windows操作系统下获取硬件信息。
use winapi::um::winbase::{GetSystemFirmwareTable, SYSTEM_FIRMWARE_TABLE_PROVIDER_ACPI, SYSTEM_FIRMWARE_TABLE_ACPI, SYSTEM_FIRMWARE_TABLE_ACTION_READ};
use winapi::um::winnt::{HANDLE, PVOID, ULONG};
use std::ptr::null_mut;
use std::mem::size_of;
fn main() {
let mut buffer_size: ULONG = 0;
let mut buffer: Vec<u8> = Vec::new();
unsafe {
GetSystemFirmwareTable(
SYSTEM_FIRMWARE_TABLE_PROVIDER_ACPI,
SYSTEM_FIRMWARE_TABLE_ACPI,
null_mut(),
0,
);
buffer_size = GetSystemFirmwareTable(
SYSTEM_FIRMWARE_TABLE_PROVIDER_ACPI,
SYSTEM_FIRMWARE_TABLE_ACPI,
null_mut(),
0,
);
buffer = Vec::with_capacity(buffer_size as usize);
GetSystemFirmwareTable(
SYSTEM_FIRMWARE_TABLE_PROVIDER_ACPI,
SYSTEM_FIRMWARE_TABLE_ACPI,
buffer.as_mut_ptr() as PVOID,
buffer_size,
);
buffer.set_len(buffer_size as usize);
println!("ACPI table size: {}", buffer_size);
}
}
上述代码使用了winapi模块中的函数和结构体,包括GetSystemFirmwareTable、SYSTEM_FIRMWARE_TABLE_PROVIDER_ACPI、SYSTEM_FIRMWARE_TABLE_ACPI、SYSTEM_FIRMWARE_TABLE_ACTION_READ、HANDLE、PVOID和ULONG等。
获取系统信息
以下代码使用winapi模块的函数和结构体,实现在Windows操作系统下获取系统信息。
use winapi::um::sysinfoapi::{GetSystemInfo, SYSTEM_INFO};
use std::mem::zeroed;
fn main() {
let mut system_info: SYSTEM_INFO = unsafe { zeroed() };
unsafe {
GetSystemInfo(&mut system_info);
println!("Number of processors: {}", system_info.dwNumberOfProcessors);
println!("Page size: {}", system_info.dwPageSize);
println!("Processor architecture: {}", system_info.wProcessorArchitecture);
}
}
上述代码使用了winapi模块中的函数和结构体,包括GetSystemInfo和SYSTEM_INFO等。
获取网络信息
以下代码使用winapi模块的函数和结构体,实现在Windows操作系统下获取网络信息。
use winapi::um::iphlpapi::{GetAdaptersInfo, PIP_ADAPTER_INFO};
use std::ptr::null_mut;
use std::mem::size_of;
fn main() {
let mut adapter_info: PIP_ADAPTER_INFO = null_mut();
let mut buffer_size: u32 = 0;
unsafe {
GetAdaptersInfo(null_mut(), &mut buffer_size);
adapter_info = std::mem::zeroed();
GetAdaptersInfo(adapter_info, &mut buffer_size);
println!("Adapter name: {:?}", std::ffi::CStr::from_ptr((*adapter_info).AdapterName.as_ptr() as *const i8));
}
}
上述代码使用了winapi模块中的函数和结构体,包括GetAdaptersInfo和PIP_ADAPTER_INFO等。
使用Windows API发送邮件
发送邮件是一种常见的网络操作,可以用于发送电子邮件、短信等。下面是一个使用winapi模块发送邮件的示例:
use winapi::um::mapi::{MAPISendMailW, MapiMessage, MapiFileDesc, MapiRecipDesc, MAPI_LOGON_UI, MAPI_DIALOG};
use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;
use std::ptr::null_mut;
use std::mem::MaybeUninit;
fn main() {
let mut msg: MapiMessage = MaybeUninit::uninit().assume_init();
msg.lpszSubject = OsStr::new("Test Email").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
msg.lpszNoteText = OsStr::new("This is a test email.").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
msg.nRecipCount = 1;
let mut recip: MapiRecipDesc = MaybeUninit::uninit().assume_init();
recip.ulRecipClass = 1;
recip.lpszName = OsStr::new("John Smith").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
recip.lpszAddress = OsStr::new("john.smith@example.com").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
msg.lpRecips = &mut recip as *mut MapiRecipDesc;
msg.nFileCount = 1;
let mut file: MapiFileDesc = MaybeUninit::uninit().assume_init();
file.nPosition = 0xFFFFFFFF;
file.lpszPathName = OsStr::new("test.txt").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
file.lpszFileName = OsStr::new("test.txt").encode_wide().chain(Some(0)).collect::<Vec<_>>().as_ptr();
msg.lpFiles = &mut file as *mut MapiFileDesc;
unsafe {
let result = MAPISendMailW(null_mut(), null_mut(), &mut msg as *mut MapiMessage, MAPI_LOGON_UI | MAPI_DIALOG, 0);
if result != 0 {
println!("Error: {}", result);
}
}
}
在这个示例中,我们使用了mapi模块中的MAPISendMailW函数发送邮件。该函数的参数包括邮件消息、登录标志和对话框标志等。我们创建了一个MapiMessage结构体msg,并设置了邮件主题、正文和收件人等信息。我们还创建了一个MapiRecipDesc结构体recip,并设置了收件人姓名和地址。最后,我们创建了一个MapiFileDesc结构体file,并设置了附件的路径和文件名。
接着,我们将msg.lpRecips和msg.lpFiles分别设置为&mut recip和&mut file,以便将收件人和附件信息添加到邮件消息中。最后,我们使用MAPISendMailW函数发送邮件,并使用println!函数打印出错误信息(如果有)。
转载自:https://juejin.cn/post/7225257817346359357