From 478d30189f5875c631b6f50b953992c3ad3c7a85 Mon Sep 17 00:00:00 2001
From: Federico Terzi <federico-terzi@users.noreply.github.com>
Date: Mon, 16 Sep 2019 10:56:14 +0200
Subject: [PATCH] Implement start subcommand on Windows. Fix #34

---
 Cargo.toml                     |  1 -
 native/libwinbridge/bridge.cpp | 30 +++++++++++++++++++++++++++++-
 native/libwinbridge/bridge.h   |  4 ++++
 src/bridge/windows.rs          |  1 +
 src/main.rs                    |  7 ++++++-
 5 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 5558ee8..991b459 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,7 +29,6 @@ lazy_static = "1.4.0"
 [target.'cfg(unix)'.dependencies]
 libc = "0.2.62"
 
-
 [dev-dependencies]
 tempfile = "3.1.0"
 
diff --git a/native/libwinbridge/bridge.cpp b/native/libwinbridge/bridge.cpp
index 0c2058c..c3af3f2 100644
--- a/native/libwinbridge/bridge.cpp
+++ b/native/libwinbridge/bridge.cpp
@@ -27,7 +27,7 @@
 
 #define UNICODE
 
-#include <Windows.h>
+#include <windows.h>
 #include <strsafe.h>
 #include <shellapi.h>
 
@@ -530,4 +530,32 @@ int32_t show_context_menu(MenuItem * items, int32_t count) {
     }
 
     return -1;
+}
+
+int32_t start_daemon_process() {
+    wchar_t cmd[MAX_PATH];
+    swprintf(cmd, MAX_PATH, L"espanso.exe daemon");
+
+    STARTUPINFO si = { sizeof(si) };
+    PROCESS_INFORMATION pi;
+
+    // Documentation: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
+    BOOL res = CreateProcess(
+            L"./espanso.exe",
+            cmd,
+            NULL,
+            NULL,
+            FALSE,
+            DETACHED_PROCESS,
+            NULL,
+            NULL,
+            &si,
+            &pi
+    );
+
+    if (!res) {
+        return -1;
+    }
+
+    return 1;
 }
\ No newline at end of file
diff --git a/native/libwinbridge/bridge.h b/native/libwinbridge/bridge.h
index ecedd47..f6e02b7 100644
--- a/native/libwinbridge/bridge.h
+++ b/native/libwinbridge/bridge.h
@@ -23,6 +23,10 @@
 #include <stdio.h>
 #include <stdint.h>
 
+// SYSTEM
+
+extern "C" int32_t start_daemon_process();
+
 extern void * manager_instance;
 
 /*
diff --git a/src/bridge/windows.rs b/src/bridge/windows.rs
index f556d7e..72c9627 100644
--- a/src/bridge/windows.rs
+++ b/src/bridge/windows.rs
@@ -29,6 +29,7 @@ pub struct WindowsMenuItem {
 #[allow(improper_ctypes)]
 #[link(name="winbridge", kind="static")]
 extern {
+    pub fn start_daemon_process() -> i32;
     pub fn initialize(s: *const c_void, ico_path: *const u16, bmp_path: *const u16) -> i32;
 
     // SYSTEM
diff --git a/src/main.rs b/src/main.rs
index 2da67c2..6d7f4a5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -294,7 +294,12 @@ fn start_main(config_set: ConfigSet) {
 
 #[cfg(target_os = "windows")]
 fn detach_daemon() {
-    // TODO
+    unsafe {
+        let res = bridge::windows::start_daemon_process();
+        if res < 0 {
+            println!("Error starting daemon process");
+        }
+    }
 }
 
 #[cfg(not(target_os = "windows"))]