wpa_gui-qt4: Added wpasvc start/stop functionality for Windows
authorJouni Malinen <j@w1.fi>
Sun, 21 Dec 2008 12:28:45 +0000 (14:28 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 21 Dec 2008 12:28:45 +0000 (14:28 +0200)
wpa_gui will now ask user whether the wpasvc service should be started
if it is not running. In addition, File menu has items for starting and
stopping the service.

wpa_supplicant/wpa_gui-qt4/wpagui.cpp
wpa_supplicant/wpa_gui-qt4/wpagui.h

index e6bdf52..20bb353 100644 (file)
 #include <unistd.h>
 #endif
 
+#ifdef CONFIG_NATIVE_WINDOWS
+#include <windows.h>
+#endif /* CONFIG_NATIVE_WINDOWS */
+
 #include <cstdio>
 #include <QMessageBox>
 #include <QCloseEvent>
@@ -42,6 +46,23 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
 {
        setupUi(this);
 
+#ifdef CONFIG_NATIVE_WINDOWS
+       fileStopServiceAction = new QAction(this);
+       fileStopServiceAction->setObjectName("Stop Service");
+       fileStopServiceAction->setIconText("Stop Service");
+       fileMenu->insertAction(actionWPS, fileStopServiceAction);
+
+       fileStartServiceAction = new QAction(this);
+       fileStartServiceAction->setObjectName("Start Service");
+       fileStartServiceAction->setIconText("Start Service");
+       fileMenu->insertAction(fileStopServiceAction, fileStartServiceAction);
+
+       connect(fileStartServiceAction, SIGNAL(triggered()), this,
+               SLOT(startService()));
+       connect(fileStopServiceAction, SIGNAL(triggered()), this,
+               SLOT(stopService()));
+#endif /* CONFIG_NATIVE_WINDOWS */
+
        (void) statusBar();
 
        connect(fileEventHistoryAction, SIGNAL(triggered()), this,
@@ -269,8 +290,22 @@ int WpaGui::openCtrlConnection(const char *ifname)
 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
        }
 
-       if (ctrl_iface == NULL)
+       if (ctrl_iface == NULL) {
+#ifdef CONFIG_NATIVE_WINDOWS
+               static bool first = true;
+               if (first && !serviceRunning()) {
+                       first = false;
+                       if (QMessageBox::warning(
+                                   this, qAppName(),
+                                   "wpa_supplicant service is not running.\n"
+                                   "Do you want to start it?",
+                                   QMessageBox::Yes | QMessageBox::No) ==
+                           QMessageBox::Yes)
+                               startService();
+               }
+#endif /* CONFIG_NATIVE_WINDOWS */
                return -1;
+       }
 
 #ifdef CONFIG_CTRL_IFACE_UNIX
        flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2;
@@ -1456,3 +1491,132 @@ void WpaGui::stopWpsRun(bool success)
        wpsApPinEdit->setEnabled(false);
        wpsApPinButton->setEnabled(false);
 }
+
+
+#ifdef CONFIG_NATIVE_WINDOWS
+
+#ifndef WPASVC_NAME
+#define WPASVC_NAME TEXT("wpasvc")
+#endif
+
+class ErrorMsg : public QMessageBox {
+public:
+       ErrorMsg(QWidget *parent, DWORD last_err = GetLastError());
+       void showMsg(QString msg);
+private:
+       DWORD err;
+};
+
+ErrorMsg::ErrorMsg(QWidget *parent, DWORD last_err) :
+       QMessageBox(parent), err(last_err)
+{
+       setWindowTitle("wpa_gui error");
+       setIcon(QMessageBox::Warning);
+}
+
+void ErrorMsg::showMsg(QString msg)
+{
+       LPTSTR buf;
+
+       setText(msg);
+       if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                         FORMAT_MESSAGE_FROM_SYSTEM,
+                         NULL, err, 0, (LPTSTR) (void *) &buf,
+                         0, NULL) > 0) {
+               QString msg = QString::fromWCharArray(buf);
+               setInformativeText(QString("[%1] %2").arg(err).arg(msg));
+               LocalFree(buf);
+       } else {
+               setInformativeText(QString("[%1]").arg(err));
+       }
+
+       exec();
+}
+
+
+void WpaGui::startService()
+{
+       SC_HANDLE svc, scm;
+
+       scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+       if (!scm) {
+               ErrorMsg(this).showMsg("OpenSCManager failed");
+               return;
+       }
+
+       svc = OpenService(scm, WPASVC_NAME, SERVICE_START);
+       if (!svc) {
+               ErrorMsg(this).showMsg("OpenService failed");
+               CloseServiceHandle(scm);
+               return;
+       }
+
+       if (!StartService(svc, 0, NULL)) {
+               ErrorMsg(this).showMsg("Failed to start wpa_supplicant "
+                                      "service");
+       }
+
+       CloseServiceHandle(svc);
+       CloseServiceHandle(scm);
+}
+
+
+void WpaGui::stopService()
+{
+       SC_HANDLE svc, scm;
+       SERVICE_STATUS status;
+
+       scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+       if (!scm) {
+               ErrorMsg(this).showMsg("OpenSCManager failed");
+               return;
+       }
+
+       svc = OpenService(scm, WPASVC_NAME, SERVICE_STOP);
+       if (!svc) {
+               ErrorMsg(this).showMsg("OpenService failed");
+               CloseServiceHandle(scm);
+               return;
+       }
+
+       if (!ControlService(svc, SERVICE_CONTROL_STOP, &status)) {
+               ErrorMsg(this).showMsg("Failed to stop wpa_supplicant "
+                                      "service");
+       }
+
+       CloseServiceHandle(svc);
+       CloseServiceHandle(scm);
+}
+
+
+bool WpaGui::serviceRunning()
+{
+       SC_HANDLE svc, scm;
+       SERVICE_STATUS status;
+       bool running = false;
+
+       scm = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+       if (!scm) {
+               printf("OpenSCManager failed: %d\n", (int) GetLastError());
+               return false;
+       }
+
+       svc = OpenService(scm, WPASVC_NAME, SERVICE_QUERY_STATUS);
+       if (!svc) {
+               printf("OpenService failed: %d\n\n", (int) GetLastError());
+               CloseServiceHandle(scm);
+               return false;
+       }
+
+       if (QueryServiceStatus(svc, &status)) {
+               if (status.dwCurrentState != SERVICE_STOPPED)
+                       running = true;
+       }
+
+       CloseServiceHandle(svc);
+       CloseServiceHandle(scm);
+
+       return running;
+}
+
+#endif /* CONFIG_NATIVE_WINDOWS */
index 5aa7a9a..e433832 100644 (file)
@@ -78,6 +78,10 @@ public slots:
        virtual void wpsGeneratePin();
        virtual void wpsApPinChanged(const QString &text);
        virtual void wpsApPin();
+#ifdef CONFIG_NATIVE_WINDOWS
+       virtual void startService();
+       virtual void stopService();
+#endif /* CONFIG_NATIVE_WINDOWS */
 
 protected slots:
        virtual void languageChange();
@@ -118,6 +122,13 @@ private:
        QString bssFromScan;
 
        void stopWpsRun(bool success);
+
+#ifdef CONFIG_NATIVE_WINDOWS
+       QAction *fileStartServiceAction;
+       QAction *fileStopServiceAction;
+
+       bool serviceRunning();
+#endif /* CONFIG_NATIVE_WINDOWS */
 };
 
 #endif /* WPAGUI_H */