不安全的 extern "system" fn service_main 如何传递变量

问题描述 投票:0回答:1

我尝试使用winapi编写一个Windows服务

如何使用main函数的“heventlog”传递给service_main

在其他语言中,我们可以使用全局变量。 Rust 中如何处理这种情况?

代码

use std::sync::{Arc, Mutex};
use windows::core::{w, PWSTR};
use windows::Win32::Foundation::HANDLE;
use windows::Win32::System::Services::{
    RegisterServiceCtrlHandlerW, SetServiceStatus, StartServiceCtrlDispatcherW,
    SERVICE_ACCEPT_STOP, SERVICE_CONTROL_STOP, SERVICE_RUNNING, SERVICE_START_PENDING,
    SERVICE_STATUS, SERVICE_STOPPED, SERVICE_TABLE_ENTRYW, SERVICE_WIN32_OWN_PROCESS,
};

unsafe extern "system" fn service_control_handler(dwcontrol: u32) {
    match dwcontrol {
        SERVICE_CONTROL_STOP => return,
        _ => {}
    }
}

unsafe extern "system" fn service_main(_dwnumservicesargs: u32, _lpserviceargvectors: *mut PWSTR) {
    // How to use heventlog

    let mut lpservicestatus = SERVICE_STATUS {
        dwServiceType: SERVICE_WIN32_OWN_PROCESS,
        dwCurrentState: SERVICE_START_PENDING,
        dwControlsAccepted: SERVICE_ACCEPT_STOP,
        dwWin32ExitCode: 0,
        dwServiceSpecificExitCode: 0,
        dwCheckPoint: 0,
        dwWaitHint: 0,
    };

    let lpservicename = w!("Demo Service");
    let hservicestatus =
        RegisterServiceCtrlHandlerW(lpservicename, Some(service_control_handler)).unwrap();

    lpservicestatus.dwCurrentState = SERVICE_RUNNING;
    SetServiceStatus(hservicestatus, &mut lpservicestatus).unwrap();
}

fn main() {
    use windows::Win32::System::EventLog::RegisterEventSourceW;
    let heventlog = unsafe { RegisterEventSourceW(None, w!("Demo Service")) }.unwrap();
    let heventlog: Arc<Mutex<HANDLE>> = Arc::new(Mutex::new(heventlog));
    // How heventlog is passed to service_main

    let mut lp_service_name = "Demo Service\0".encode_utf16().collect::<Vec<u16>>();
    let lp_service_name = PWSTR::from_raw(lp_service_name.as_mut_ptr());

    let lpservicestarttable = [
        SERVICE_TABLE_ENTRYW {
            lpServiceName: lp_service_name,
            lpServiceProc: Some(service_main),
        },
        SERVICE_TABLE_ENTRYW {
            lpServiceName: PWSTR::null(),
            lpServiceProc: None,
        },
    ]
    .as_ptr();

    unsafe { StartServiceCtrlDispatcherW(lpservicestarttable) }.unwrap();
}

service_main可以使用heventlog来记录日志

winapi rust
1个回答
0
投票

Rust 中也可以有全局变量:

use std::sync::OnceLock;

static H_EVENT_LOG: OnceLock<HANDLE> = OnceLock::new();

unsafe extern "system" fn service_main(_dwnumservicesargs: u32, _lpserviceargvectors: *mut PWSTR) {
    // use H_EVENT_LOG.get()
    // ...
}

fn main() {
    let heventlog = unsafe { RegisterEventSourceW(None, w!("Demo Service")) }.unwrap();
    H_EVENT_LOG.set(heventlog).unwrap();
    // ...
}
© www.soinside.com 2019 - 2024. All rights reserved.