- Added the properties dialog
- Add an about dialog
- Split up the query code to make it more usable
- Call description from the registry
- Many other code mods
Modified: trunk/reactos/subsys/system/servman/En.rc
Added: trunk/reactos/subsys/system/servman/about.c
Added: trunk/reactos/subsys/system/servman/geterror.c
Added: trunk/reactos/subsys/system/servman/propsheet.c
Added: trunk/reactos/subsys/system/servman/query.c
Modified: trunk/reactos/subsys/system/servman/resource.h
Modified: trunk/reactos/subsys/system/servman/servman.c
Added: trunk/reactos/subsys/system/servman/servman.h
Modified: trunk/reactos/subsys/system/servman/servman.rc
Modified: trunk/reactos/subsys/system/servman/servman.xml

Modified: trunk/reactos/subsys/system/servman/En.rc
--- trunk/reactos/subsys/system/servman/En.rc	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/En.rc	2006-01-06 18:28:27 UTC (rev 20616)
@@ -27,6 +27,46 @@
   END
 END
 
+IDD_ABOUTBOX DIALOG DISCARDABLE  22,16,190,182
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About Service Manager"
+FONT 8, "Tahoma"
+BEGIN
+    CONTROL         "Service Manager v0.1\nCopyright (C) 2006\nby Ged Murphy (gedmurphy@gmail.com)",
+                    IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,48,7,130,26
+    DEFPUSHBUTTON   "Close",IDOK,140,162,44,15,WS_GROUP
+    ICON            IDI_SM_ICON,IDC_STATIC,12,7,30,20
+    EDITTEXT        IDC_LICENSE_EDIT,8,44,174,107,ES_MULTILINE |
+                    ES_READONLY | WS_VSCROLL
+END
+
+
+IDD_DLG_GENERAL DIALOGEX 6,6,253,225
+CAPTION "General"
+FONT 8,"MS Sans Serif",0,0
+STYLE 0x10CF0000
+BEGIN
+  CONTROL "Service name:",IDC_STATIC,"Static",0x50000000,4,11,53,11
+  CONTROL "Display name:",IDC_STATIC,"Static",0x50000000,4,29,53,11
+  CONTROL "Description",IDC_STATIC,"Static",0x50000000,4,51,53,11
+  CONTROL "",IDC_SERV_NAME,"Static",0x50000000,70,11,176,11
+  CONTROL "",IDC_DISP_NAME,"Static",0x50001000,70,29,176,12
+  CONTROL "",IDC_DESCRIPTION,"Static",0x50201000,70,46,176,22
+  CONTROL "Path to executable:",IDC_STATIC,"Static",0x50000000,6,73,82,9
+  CONTROL "",IDC_STATIC,"Static",0x50001000,6,86,238,12
+  CONTROL "Startup type:",IDC_STATIC,"Static",0x50000000,6,108,53,11
+  CONTROL "",IDC_START_TYPE,"ComboBox",0x50010003,70,107,176,11
+  CONTROL "Service status:",IDC_STATIC,"Static",0x50000000,4,138,53,11
+  CONTROL "",IDC_SERV_STATUS,"Static",0x50000000,70,138,176,11
+  CONTROL "Start",IDC_START,"Button",0x50010000,6,155,54,15
+  CONTROL "Stop",IDC_STOP,"Button",0x50010000,68,155,54,15
+  CONTROL "Pause",IDC_PAUSE,"Button",0x50010000,130,155,54,15
+  CONTROL "Resume",IDC_RESUME,"Button",0x50010000,192,155,54,15
+  CONTROL "You can specify the start parameters that apply when you start the service from here.",IDC_STATIC,"Static",0x50000000,6,177,240,15
+  CONTROL "Start parameters",IDC_STATIC,"Static",0x50000000,6,199,53,11
+  CONTROL "",IDC_START_PARAM,"Static",0x50001000,70,199,176,11
+END
+
 STRINGTABLE DISCARDABLE
 BEGIN
   IDS_FIRSTCOLUMN "Name"
@@ -48,6 +88,20 @@
 BEGIN
   IDS_SERVICES_NUM_SERVICES "Num Services: %d"
   IDB_START "res/start.bmp"
+  IDS_LICENSE "This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.\r\n\r\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.\r\n\r\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA."
+  /*"This program is free software; you can redistribute it "
+              "and/or modify it under the terms of the GNU Lesser General "
+              "Public License as published by the Free Software Foundation; "
+              "either version 2.1 of the License, or (at your option) any "
+              "later version.\r\n\r\nThis program is distributed in the hope "
+              "that it will be useful, but WITHOUT ANY WARRANTY; without even "
+              "the implied warranty of MERCHANTABILITY or FITNESS FOR A "
+              "PARTICULAR PURPOSE.  See the GNU General Public License for more "
+              "details.\r\n\r\nYou should have received a copy of the GNU "
+              "General Public License along with this program; if not, write "
+              "to the Free Software Foundation, Inc., 59 Temple Place - Suite "
+              "330, Boston, MA  02111-1307, USA." */
+  
 END
 
 STRINGTABLE DISCARDABLE

Added: trunk/reactos/subsys/system/servman/about.c
--- trunk/reactos/subsys/system/servman/about.c	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/about.c	2006-01-06 18:28:27 UTC (rev 20616)
@@ -0,0 +1,35 @@
+#include "servman.h"
+
+extern HINSTANCE hInstance;
+
+BOOL CALLBACK
+AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    HWND    hLicenseEditWnd;
+    TCHAR    strLicense[0x1000];
+
+    switch (message)
+    {
+    case WM_INITDIALOG:
+
+        hLicenseEditWnd = GetDlgItem(hDlg, IDC_LICENSE_EDIT);
+
+        LoadString(hInstance, IDS_LICENSE, strLicense, 0x1000);
+
+        SetWindowText(hLicenseEditWnd, strLicense);
+
+        return TRUE;
+
+    case WM_COMMAND:
+
+        if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
+        {
+            EndDialog(hDlg, LOWORD(wParam));
+            return TRUE;
+        }
+
+        break;
+    }
+
+    return 0;
+}

Added: trunk/reactos/subsys/system/servman/geterror.c
--- trunk/reactos/subsys/system/servman/geterror.c	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/geterror.c	2006-01-06 18:28:27 UTC (rev 20616)
@@ -0,0 +1,28 @@
+#include "servman.h"
+/* temp file for debugging */
+
+VOID GetError(VOID)
+{
+    LPVOID lpMsgBuf;
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL,
+                  GetLastError(),
+                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
+                  (LPTSTR) &lpMsgBuf,
+                   0,
+                   NULL );
+
+        MessageBox(NULL, lpMsgBuf, _T("Error!"), MB_OK | MB_ICONERROR);
+
+        LocalFree(lpMsgBuf);
+}
+
+
+VOID DisplayString(PTCHAR Msg)
+{
+    MessageBox(NULL, Msg, _T("Error!"), MB_OK | MB_ICONERROR);
+
+}

Added: trunk/reactos/subsys/system/servman/propsheet.c
--- trunk/reactos/subsys/system/servman/propsheet.c	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/propsheet.c	2006-01-06 18:28:27 UTC (rev 20616)
@@ -0,0 +1,90 @@
+#include "servman.h"
+
+extern HINSTANCE hInstance;
+
+
+/* Property page dialog callback */
+INT_PTR CALLBACK
+GeneralPageProc(HWND hwndDlg,
+                UINT uMsg,
+		        WPARAM wParam,
+		        LPARAM lParam)
+{
+
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+
+            break;
+
+        case WM_COMMAND:
+            switch(LOWORD(wParam))
+            {
+                case IDC_START:
+                    break;
+
+                case IDC_STOP:
+
+                    break;
+            }
+            break;
+
+        case WM_DESTROY:
+            break;
+
+        case WM_NOTIFY:
+            {
+                LPNMHDR lpnm = (LPNMHDR)lParam;
+
+                switch (lpnm->code)
+
+                default:
+                    break;
+            }
+            break;
+    }
+
+    return FALSE;
+}
+
+
+
+static VOID
+InitPropSheetPage(PROPSHEETPAGE *psp, WORD idDlg, DLGPROC DlgProc)
+{
+  ZeroMemory(psp, sizeof(PROPSHEETPAGE));
+  psp->dwSize = sizeof(PROPSHEETPAGE);
+  psp->dwFlags = PSP_DEFAULT;
+  psp->hInstance = hInstance;
+  psp->pszTemplate = MAKEINTRESOURCE(idDlg);
+  psp->pfnDlgProc = DlgProc;
+}
+
+
+LONG APIENTRY
+PropSheets(HWND hwnd)
+{
+  PROPSHEETHEADER psh;
+  PROPSHEETPAGE psp[1];
+  TCHAR Caption[256];
+
+  LoadString(hInstance, IDS_PROP_SHEET, Caption, sizeof(Caption) / sizeof(TCHAR));
+
+  ZeroMemory(&psh, sizeof(PROPSHEETHEADER));
+  psh.dwSize = sizeof(PROPSHEETHEADER);
+  psh.dwFlags =  PSH_PROPSHEETPAGE | PSH_PROPTITLE;
+  psh.hwndParent = NULL;
+  psh.hInstance = hInstance;
+  psh.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SM_ICON));
+  psh.pszCaption = Caption;
+  psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
+  psh.nStartPage = 0;
+  psh.ppsp = psp;
+
+  InitPropSheetPage(&psp[0], IDD_DLG_GENERAL, GeneralPageProc);
+  //logon
+  //recovery
+  //dependancies
+
+  return (LONG)(PropertySheet(&psh) != -1);
+}

Added: trunk/reactos/subsys/system/servman/query.c
--- trunk/reactos/subsys/system/servman/query.c	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/query.c	2006-01-06 18:28:27 UTC (rev 20616)
@@ -0,0 +1,328 @@
+#include "servman.h"
+
+extern HINSTANCE hInstance;
+extern HWND hListView;
+extern HWND hStatus;
+
+/* Stores the service array */
+ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
+
+
+/* free service array */
+VOID FreeMemory(VOID)
+{
+    HeapFree(GetProcessHeap(), 0, pServiceStatus);
+}
+
+
+BOOL
+RefreshServiceList(VOID)
+{
+    LV_ITEM item;
+    TCHAR szNumServices[32];
+    TCHAR szStatus[128];
+    DWORD NumServices = 0;
+    DWORD Index;
+
+    NumServices = GetServiceList();
+
+    if (NumServices)
+    {
+        HICON hiconItem;     /* icon for list-view items */
+        HIMAGELIST hSmall;   /* image list for other views */
+        TCHAR buf[40];
+
+        /* Create the icon image lists */
+        hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
+            GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1);
+
+        /* Add an icon to each image list */
+        hiconItem = LoadImage(hInstance, MAKEINTRESOURCE(IDI_SM_ICON), IMAGE_ICON, 16, 16, 0);
+        ImageList_AddIcon(hSmall, hiconItem);
+
+        ListView_SetImageList(hListView, hSmall, LVSIL_SMALL);
+
+        /* set the number of services in the status bar */
+        LoadString(hInstance, IDS_SERVICES_NUM_SERVICES, szNumServices, 32);
+        _stprintf(buf, szNumServices, NumServices);
+        SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)buf);
+
+        for (Index = 0; Index < NumServices; Index++)
+        {
+            HKEY hKey = NULL;
+            TCHAR Description[5000];
+            DWORD Size = 5000;
+
+            /* set the display name */
+
+            ZeroMemory(&item, sizeof(LV_ITEM));
+            item.mask = LVIF_TEXT;
+            //item.iImage = 0;
+            item.pszText = pServiceStatus[Index].lpDisplayName;
+            item.iItem = ListView_GetItemCount(hListView);
+            item.lParam = 0;
+            item.iItem = ListView_InsertItem(hListView, &item);
+
+
+            /* set the description */
+
+            _stprintf(buf, _T("System\\CurrentControlSet\\Services\\%s"),
+                      pServiceStatus[Index].lpServiceName);
+
+            if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                             buf,
+                             0,
+                             KEY_READ,
+                             &hKey) != ERROR_SUCCESS)
+            {
+                GetError();
+                return FALSE;
+            }
+
+            RegQueryValueEx(hKey,
+                            _T("Description"),
+                            NULL,
+                            NULL,
+                            (LPBYTE)Description,
+                            &Size);
+
+            item.pszText = Description;
+            item.iSubItem = 1;
+            SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+
+
+            /* set the status */
+
+            if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
+            {
+                LoadString(hInstance, IDS_SERVICES_STATUS_RUNNING, szStatus, 128);
+                item.pszText = szStatus;
+                item.iSubItem = 2;
+                SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+            }
+            else
+            {
+                item.pszText = '\0';
+                item.iSubItem = 2;
+                SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+            }
+         }
+    }
+
+    return TRUE;
+}
+
+
+
+
+DWORD
+GetServiceList(VOID)
+{
+    SC_HANDLE ScHandle;
+
+    DWORD BytesNeeded = 0;
+    DWORD ResumeHandle = 0;
+    DWORD NumServices = 0;
+
+    ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
+    if (ScHandle != INVALID_HANDLE_VALUE)
+    {
+        if (EnumServicesStatusEx(ScHandle,
+                                 SC_ENUM_PROCESS_INFO,
+                                 SERVICE_WIN32,
+                                 SERVICE_STATE_ALL,
+                                 (LPBYTE)pServiceStatus,
+                                 0, &BytesNeeded,
+                                 &NumServices,
+                                 &ResumeHandle,
+                                 0) == 0)
+        {
+            /* Call function again if required size was returned */
+            if (GetLastError() == ERROR_MORE_DATA)
+            {
+                /* reserve memory for service info array */
+                pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
+                if (pServiceStatus == NULL)
+			        return FALSE;
+
+                /* fill array with service info */
+                if (EnumServicesStatusEx(ScHandle,
+                                         SC_ENUM_PROCESS_INFO,
+                                         SERVICE_WIN32,
+                                         SERVICE_STATE_ALL,
+                                         (LPBYTE)pServiceStatus,
+                                         BytesNeeded,
+                                         &BytesNeeded,
+                                         &NumServices,
+                                         &ResumeHandle,
+                                         0) == 0)
+                {
+                    HeapFree(GetProcessHeap(), 0, pServiceStatus);
+                    return FALSE;
+                }
+            }
+            else /* exit on failure */
+            {
+                return FALSE;
+            }
+        }
+    }
+
+    CloseServiceHandle(ScHandle);
+
+    return NumServices;
+}
+
+
+
+
+
+
+
+
+
+
+
+/*
+    //WORD wCodePage;
+    //WORD wLangID;
+    //SC_HANDLE hService;
+    //DWORD dwHandle, dwLen;
+    //UINT BufLen;
+    //TCHAR* lpData;
+    //TCHAR* lpBuffer;
+    //TCHAR szStrFileInfo[80];
+    //TCHAR FileName[MAX_PATH];
+    //LPVOID pvData;
+
+    //LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
+    //LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
+
+               BytesNeeded = 0;
+                hService = OpenService(ScHandle,
+                                       pServiceStatus[Index].lpServiceName,
+                                       SC_MANAGER_CONNECT);
+                if (hService != INVALID_HANDLE_VALUE)
+                {
+                    / * check if service is required by the system* /
+                    if (!QueryServiceConfig2(hService,
+                                             SERVICE_CONFIG_FAILURE_ACTIONS,
+                                             (LPBYTE)pServiceFailureActions,
+                                             0,
+                                             &BytesNeeded))
+                    {
+                        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+                        {
+                            pServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)
+                                HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
+                            if (pServiceFailureActions == NULL)
+			                    return FALSE;
+
+                            if (!QueryServiceConfig2(hService,
+                                                     SERVICE_CONFIG_FAILURE_ACTIONS,
+                                                     (LPBYTE)pServiceFailureActions,
+                                                     BytesNeeded,
+                                                     &BytesNeeded))
+                            {
+                                HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
+                                return FALSE;
+                            }
+                        }
+                        else / * exit on failure * /
+                        {
+                            return FALSE;
+                        }
+                    }
+                    if (pServiceFailureActions->cActions)
+                    {
+                        if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
+                        {
+                            LoadString(hInstance, IDS_SERVICES_YES, szStatus, 128);
+                            item.pszText = szStatus;
+                            item.iSubItem = 1;
+                            SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+                        }
+                    }
+
+					if (pServiceFailureActions != NULL)
+					{
+						HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
+						pServiceFailureActions = NULL;
+					}
+
+                    / * get vendor of service binary * /
+                    BytesNeeded = 0;
+                    if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded))
+                    {
+                        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+                        {
+                            pServiceConfig = (LPQUERY_SERVICE_CONFIG)
+                                HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
+                            if (pServiceConfig == NULL)
+			                    return FALSE;
+
+                            if (!QueryServiceConfig(hService,
+                                                    pServiceConfig,
+                                                    BytesNeeded,
+                                                    &BytesNeeded))
+                            {
+                                HeapFree(GetProcessHeap(), 0, pServiceConfig);
+                                return FALSE;
+                            }
+                        }
+                        else / * exit on failure * /
+                        {
+                            return FALSE;
+                        }
+                    }
+
+                    memset(&FileName, 0, MAX_PATH);
+                    if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
+                    {
+                        _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
+                            _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
+                    }
+                    else
+                    {
+                        _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
+                    }
+
+					HeapFree(GetProcessHeap(), 0, pServiceConfig);
+					pServiceConfig = NULL;
+
+					dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
+                    if (dwLen)
+                    {
+                        lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
+                        if (lpData == NULL)
+			                return FALSE;
+
+                        if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
+		                    HeapFree(GetProcessHeap(), 0, lpData);
+		                    return FALSE;
+	                    }
+
+                        if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
+                        {
+                            wCodePage = LOWORD(*(DWORD*) pvData);
+                            wLangID = HIWORD(*(DWORD*) pvData);
+                            wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
+                        }
+
+                        if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen)) {
+                            item.pszText = lpBuffer;
+                            item.iSubItem = 2;
+                            SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+                        }
+						HeapFree(GetProcessHeap(), 0, lpData);
+                    }
+                    else
+                    {
+                        LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
+                        item.pszText = szStatus;
+                        item.iSubItem = 2;
+                        SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
+                    }
+                    CloseServiceHandle(hService);
+                }
+*/

Modified: trunk/reactos/subsys/system/servman/resource.h
--- trunk/reactos/subsys/system/servman/resource.h	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/resource.h	2006-01-06 18:28:27 UTC (rev 20616)
@@ -1,5 +1,10 @@
 #define IDC_STATIC -1
 
+/* about box info */
+#define IDD_ABOUTBOX        200
+#define IDC_LICENSE_EDIT    201
+#define IDS_LICENSE         202
+
 #define IDC_SERVLIST        1000
 #define IDC_TOOLBAR         1001
 #define IDC_STATUSBAR	    1002
@@ -42,3 +47,19 @@
 
 #define IDB_START 50
 #define IDI_SM_ICON 51
+
+
+
+
+#define IDS_PROP_SHEET 10000
+#define IDD_DLG_GENERAL 10001
+#define IDC_SERV_NAME 10041
+#define IDC_DISP_NAME 10051
+#define IDC_DESCRIPTION 10061
+#define IDC_START_TYPE 10101
+#define IDC_SERV_STATUS 10121
+#define IDC_START 10131
+#define IDC_STOP 10141
+#define IDC_PAUSE 10151
+#define IDC_RESUME 10161
+#define IDC_START_PARAM 10191

Modified: trunk/reactos/subsys/system/servman/servman.c
--- trunk/reactos/subsys/system/servman/servman.c	2006-01-06 17:46:36 UTC (rev 20615)
+++ trunk/reactos/subsys/system/servman/servman.c	2006-01-06 18:28:27 UTC (rev 20616)
@@ -1,270 +1,14 @@
-#include <windows.h>
-#include <stdio.h>
-#include <tchar.h>
-#include <commctrl.h>
-#include "resource.h"
+#include "servman.h"
 
+
 const TCHAR ClassName[] = _T("ServiceManager");
 
 HINSTANCE hInstance;
+HWND hMainWnd;
 HWND hListView;
 HWND hStatus;
 
 
-void
-GetServices ( void )
-{
-    LV_ITEM item;
-    WORD wCodePage;
-    WORD wLangID;
-    SC_HANDLE ScHandle;
-    SC_HANDLE hService;
-    DWORD BytesNeeded = 0;
-    DWORD ResumeHandle = 0;
-    DWORD NumServices = 0;
-    DWORD dwHandle, dwLen;
-    size_t Index;
-    UINT BufLen;
-    TCHAR szStatus[128];
-    TCHAR* lpData;
-    TCHAR* lpBuffer;
-    TCHAR szStrFileInfo[80];
-    TCHAR FileName[MAX_PATH];
-    TCHAR szNumServices[32];
-    LPVOID pvData;
-
-    LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
-    LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
-    ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
-
-    ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
-    if (ScHandle != INVALID_HANDLE_VALUE)
-    {
-        if (EnumServicesStatusEx(ScHandle,
-                                 SC_ENUM_PROCESS_INFO,
-                                 SERVICE_WIN32,
-                                 SERVICE_STATE_ALL,
-                                 (LPBYTE)pServiceStatus,
-                                 0, &BytesNeeded,
-                                 &NumServices,
-                                 &ResumeHandle,
-                                 0) == 0)
-        {
-            /* Call function again if required size was returned */
-            if (GetLastError() == ERROR_MORE_DATA)
-            {
-                /* reserve memory for service info array */
-                pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
-                if (pServiceStatus == NULL)
-			        return;
-
-                /* fill array with service info */
-                if (EnumServicesStatusEx(ScHandle,
-                                         SC_ENUM_PROCESS_INFO,
-                                         SERVICE_WIN32,
-                                         SERVICE_STATE_ALL,
-                                         (LPBYTE)pServiceStatus,
-                                         BytesNeeded,
-                                         &BytesNeeded,
-                                         &NumServices,
-                                         &ResumeHandle,
-                                         0) == 0)
-                {
-                    HeapFree(GetProcessHeap(), 0, pServiceStatus);
-                    return;
-                }
-            }
-            else /* exit on failure */
-            {
-                return;
-            }
-        }
-
-        if (NumServices)
-        {
-            HICON hiconItem;     // icon for list-view items
-            HIMAGELIST hSmall;   // image list for other views
-            TCHAR buf[40];
-
-            /* Create the icon image lists */
-            hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
-                GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1);
-
-            /* Add an icon to each image list */
-            hiconItem = LoadImage(hInstance, MAKEINTRESOURCE(IDI_SM_ICON), IMAGE_ICON, 16, 16, 0);
-            ImageList_AddIcon(hSmall, hiconItem);
-
-            ListView_SetImageList(hListView, hSmall, LVSIL_SMALL);
-
-            /* set the number of services in the status bar */
-            LoadString(hInstance, IDS_SERVICES_NUM_SERVICES, szNumServices, 32);
-            _stprintf(buf, szNumServices, NumServices);
-            SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)buf);
-
-            for (Index = 0; Index < NumServices; Index++)
-            {
-                memset(&item, 0, sizeof(LV_ITEM));
-                item.mask = LVIF_TEXT;
-                //item.iImage = 0;
-                item.pszText = pServiceStatus[Index].lpDisplayName;
-                item.iItem = ListView_GetItemCount(hListView);
-                item.lParam = 0;
-                item.iItem = ListView_InsertItem(hListView, &item);
-
-                BytesNeeded = 0;
-                hService = OpenService(ScHandle,
-                                       pServiceStatus[Index].lpServiceName,
-                                       SC_MANAGER_CONNECT);
-                if (hService != INVALID_HANDLE_VALUE)
-                {
-                    /* check if service is required by the system*/
-                    if (!QueryServiceConfig2(hService,
-                                             SERVICE_CONFIG_FAILURE_ACTIONS,
-                                             (LPBYTE)pServiceFailureActions,
-                                             0,
-                                             &BytesNeeded))
-                    {
-                        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-                        {
-                            pServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)
-                                HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
-                            if (pServiceFailureActions == NULL)
-			                    return;
-
-                            if (!QueryServiceConfig2(hService,
-                                                     SERVICE_CONFIG_FAILURE_ACTIONS,
-                                                     (LPBYTE)pServiceFailureActions,
-                                                     BytesNeeded,
-                                                     &BytesNeeded))
-                            {
-                                HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
-                                return;
-                            }
-                        }
-                        else /* exit on failure */
-                        {
-                            return;
-                        }
-                    }
-                    if (pServiceFailureActions->cActions)
-                    {
-                        if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
-                        {
-                            LoadString(hInstance, IDS_SERVICES_YES, szStatus, 128);
-                            item.pszText = szStatus;
-                            item.iSubItem = 1;
-                            SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                        }
-                    }
-
-					if (pServiceFailureActions != NULL)
-					{
-						HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
-						pServiceFailureActions = NULL;
-					}
-
-                    /* get vendor of service binary */
-                    BytesNeeded = 0;
-                    if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded))
-                    {
-                        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
-                        {
-                            pServiceConfig = (LPQUERY_SERVICE_CONFIG)
-                                HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
-                            if (pServiceConfig == NULL)
-			                    return;
-
-                            if (!QueryServiceConfig(hService,
-                                                    pServiceConfig,
-                                                    BytesNeeded,
-                                                    &BytesNeeded))
-                            {
-                                HeapFree(GetProcessHeap(), 0, pServiceConfig);
-                                return;
-                            }
-                        }
-                        else /* exit on failure */
-                        {
-                            return;
-                        }
-                    }
-
-                    memset(&FileName, 0, MAX_PATH);
-                    if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
-                    {
-                        _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
-                            _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
-                    }
-                    else
-                    {
-                        _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
-                    }
-
-					HeapFree(GetProcessHeap(), 0, pServiceConfig);
-					pServiceConfig = NULL;
-
-					dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
-                    if (dwLen)
-                    {
-                        lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
-                        if (lpData == NULL)
-			                return;
-
-                        if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
-		                    HeapFree(GetProcessHeap(), 0, lpData);
-		                    return;
-	                    }
-
-                        if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
-                        {
-                            wCodePage = LOWORD(*(DWORD*) pvData);
-                            wLangID = HIWORD(*(DWORD*) pvData);
-                            wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
-                        }
-
-                        if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen)) {
-                            item.pszText = lpBuffer;
-                            item.iSubItem = 2;
-                            SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                        }
-						HeapFree(GetProcessHeap(), 0, lpData);
-                    }
-                    else
-                    {
-                        LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
-                        item.pszText = szStatus;
-                        item.iSubItem = 2;
-                        SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                    }
-                    CloseServiceHandle(hService);
-                }
-
-                if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
-                {
-                    LoadString(hInstance, IDS_SERVICES_STATUS_RUNNING, szStatus, 128);
-                    item.pszText = szStatus;
-                    item.iSubItem = 2;
-                    SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                }
-                else
-                {
-                    item.pszText = '\0';
-                    item.iSubItem = 2;
-                    SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
-                }
-
-            }
-        }
-
-        HeapFree(GetProcessHeap(), 0, pServiceStatus);
-        CloseServiceHandle(ScHandle);
-    }
-
-
-}
-
-
-
 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 	switch(msg)
@@ -285,7 +29,6 @@
             LVCOLUMN lvc = { 0 };
             //LVITEM   lv  = { 0 };
 
-            //GetClientRect(hwnd, &rc);
             hListView = CreateWindow(WC_LISTVIEW,
                                      NULL,
                                      WS_CHILD | WS_VISIBLE | LVS_REPORT | WS_BORDER | LVS_EDITLABELS,
@@ -309,13 +52,13 @@
             ListView_InsertColumn(hListView, 0, &lvc);
 
             lvc.iSubItem = 1;
-            lvc.cx       = 150;
+            lvc.cx       = 260;
             LoadString(hInstance, IDS_SECONDCOLUMN, szTemp, 256);
             lvc.pszText  = szTemp;
             ListView_InsertColumn(hListView, 1, &lvc);
 
             lvc.iSubItem = 2;
-            lvc.cx       = 80;
+            lvc.cx       = 75;
             LoadString(hInstance, IDS_THIRDCOLUMN, szTemp, 256);
             lvc.pszText  = szTemp;
             ListView_InsertColumn(hListView, 2, &lvc);
@@ -332,7 +75,7 @@
             lvc.pszText  = szTemp;
             ListView_InsertColumn(hListView, 4, &lvc);
 
-			// Create Toolbar
+			/* Create Toolbar */
 			hTool = CreateWindowEx(0,
                                    TOOLBARCLASSNAME,
                                    NULL,
@@ -396,12 +139,14 @@
                                      hInstance,
                                      NULL);
             if(hStatus == NULL)
-				MessageBox(hwnd, _T("Could not create status bar."), _T("Error"), MB_OK | MB_ICONERROR);
+				MessageBox(hwnd, _T("Could not create status bar."),
+                           _T("Error!"), MB_OK | MB_ICONERROR);
 
 			SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths);
 
 			/* populate the list view with all services */
-			GetServices();
+			if (! RefreshServiceList() )
+                GetError();
 		}
 		break;
 		case WM_SIZE:
@@ -410,11 +155,11 @@
 			RECT rcTool;
 			int iToolHeight;
 
-			HWND hStatus;
+			//HWND hStatus;
 			RECT rcStatus;
 			int iStatusHeight;
 
-			HWND hListView;
+			//HWND hListView;
 			int lvHeight;
 			RECT rcClient;
 
@@ -490,14 +235,14 @@
                 }
                 break;
 
-                // Process other notifications here.
-
                 default:
                 break;
             }
         break;
 
 		case WM_CLOSE:
+            /* free the service array */
+            FreeMemory();
 			DestroyWindow(hwnd);
 		break;
 		case WM_DESTROY:
@@ -529,13 +274,18 @@
                 break;
 
                 case ID_PROP:
+                    PropSheets(hwnd);
                 break;
 
                 case ID_VIEW_CUSTOMIZE:
                 break;
 
                 case ID_HELP_ABOUT:
-                break;
+                    DialogBox(GetModuleHandle(NULL),
+                              MAKEINTRESOURCE(IDD_ABOUTBOX),
+                              hwnd,
+                              AboutDialogProc);
+                 break;
 
                 case ID_EXPORT:
                 break;
@@ -554,7 +304,6 @@
 	LPSTR lpCmdLine, int nCmdShow)
 {
 	WNDCLASSEX wc;
-	HWND hwnd;
 	MSG Msg;
 	BOOL bRet;
 
@@ -568,7 +317,7 @@
 	wc.cbClsExtra	 = 0;
 	wc.cbWndExtra	 = 0;
 	wc.hInstance	 = hInstance;
-	wc.hIcon		 = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SM_ICON));
[truncated at 1000 lines; 91 more skipped]