wineboot: Start items in StartUp folder on boot, includes security measures. [with the patch]

Misha Koshelev mk144210 at bcm.tmc.edu
Sun Feb 11 17:58:47 CST 2007


I forgot to include the patch, so here it is.

Misha

---

Hi everybody,

Thanks for your suggestions. I just posted a new patch on wine-patches
where I tried to incorporate these and now it does the following (in
addition to my previous patch which just started items in the StartUp
folder):

- When wineboot finds a file that it wants to start in the StartUp
folder, it asks the user whether he wants to run the program. His
options are: Always, Yes, No (default), and Never.
- If he selects Yes the program is run, if he select No it is not.
- If he selects Always or Never, I create a registry key in:
HKEY_CURRENT_USER\Software\Wine\StartupItems with the full pathname
of the program and the value "always" or "never." When wineboot sees 
this program in the StartUp folder it checks this key, and if it is
set it performs the appropriate action.

What do you guys think? If you like the system, it would be pretty easy
to incorporate this into the run key running as well (which are
currently just run without any user confirmation)?

Thanks
Misha
-------------- next part --------------
From 47a35d8e5296a094b14b03d01ab001f90a60b50e Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Sun, 11 Feb 2007 15:19:46 -0600
Subject: wineboot: Start items in StartUp folder on boot, includes security measures.
---
 programs/wineboot/En.rc       |   36 +++++++
 programs/wineboot/Makefile.in |    5 +
 programs/wineboot/wineboot.c  |  201 +++++++++++++++++++++++++++++++++++++++++
 programs/wineboot/wineboot.h  |   21 ++++
 programs/wineboot/wineboot.rc |   26 +++++
 5 files changed, 286 insertions(+), 3 deletions(-)

diff --git a/programs/wineboot/En.rc b/programs/wineboot/En.rc
new file mode 100644
index 0000000..286b03c
--- /dev/null
+++ b/programs/wineboot/En.rc
@@ -0,0 +1,36 @@
+/*
+ * Wine Boot
+ * English Language Support
+ *
+ * Copyright (c) 2007 Misha Koshelev.
+ *
+ * This library 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.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
+
+Run_Confirmation_Dialog DIALOG 100, 200, 300, 70
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "Simulating Windows Boot"
+FONT 8, "MS Shell Dlg"
+{
+ LTEXT "The following program would like to be run:", -1, 20, 10, 260, 12
+ LTEXT "Program name here", ID_PROGRAM, 20, 22, 260, 12
+ LTEXT "Would you like to run the program?", -1, 20, 34, 260, 12
+ PUSHBUTTON "Always", ID_ALWAYS, 40, 50, 50, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Yes", IDYES, 100, 50, 50, 14, WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "No", IDNO, 160, 50, 50, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Never", ID_NEVER, 220, 50, 50, 14, WS_GROUP | WS_TABSTOP
+}
diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in
index 08c27a5..7437cab 100644
--- a/programs/wineboot/Makefile.in
+++ b/programs/wineboot/Makefile.in
@@ -4,12 +4,15 @@ SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = wineboot.exe
 APPMODE   = -mconsole
-IMPORTS   = version user32 advapi32 kernel32
+IMPORTS   = version user32 advapi32 kernel32 shell32 shlwapi
+EXTRALIBS = -luuid
 
 C_SRCS = \
 	shutdown.c \
 	wineboot.c
 
+RC_SRCS = wineboot.rc
+
 @MAKE_PROG_RULES@
 
 @DEPENDENCIES@  # everything below this line is overwritten by make depend
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 1434003..d4095aa 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -37,7 +37,7 @@
  * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce (all, synch)
  * - HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run (all, asynch)
  * - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run (all, asynch)
- * - Startup folders (all, ?asynch?, no imp)
+ * - Startup folders (all, ?asynch?)
  * - HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce (all, asynch)
  *   
  * Somewhere in there is processing the RunOnceEx entries (also no imp)
@@ -63,6 +63,14 @@ #endif
 #include <windows.h>
 #include <wine/debug.h>
 
+#define COBJMACROS
+#include <shlobj.h>
+#include <shobjidl.h>
+#include <shlwapi.h>
+#include <shellapi.h>
+
+#include "wineboot.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(wineboot);
 
 #define MAX_LINE_LENGTH (2*MAX_PATH+2)
@@ -616,6 +624,193 @@ static int ProcessWindowsFileProtection(
     return 1;
 }
 
+/* A dialog box handler for the run confirmation dialog box. */
+static INT_PTR rcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    HWND hWndDesktop;
+    RECT rcDesktop, rc;
+    LPCWSTR wProgram;
+
+    switch(uMsg)
+    {
+	case WM_INITDIALOG:
+              /* Center the dialog box */
+	      hWndDesktop = GetDesktopWindow();
+	      GetWindowRect(hWndDesktop, &rcDesktop);
+	      GetWindowRect(hWnd, &rc);
+	      SetWindowPos(hWnd, HWND_TOP, (rcDesktop.right/2)-((rc.right-rc.left)/2), 
+                                           (rcDesktop.bottom/2)-((rc.bottom-rc.top)/2), 
+			   0, 0, SWP_NOSIZE);
+
+	      /* Set the program name. */
+	      wProgram = (LPCWSTR)lParam;
+	      SetDlgItemTextW(hWnd, ID_PROGRAM, wProgram);
+	      return TRUE; 
+
+	case WM_COMMAND:
+	      if (wParam == ID_ALWAYS || wParam == IDYES || wParam == IDNO || wParam == ID_NEVER)
+	         EndDialog(hWnd, wParam);
+	      return TRUE;
+  
+	default:
+	      return FALSE; /* since I don't process this particular message */
+    }
+}
+
+/* Process items in the StartUp group of the user's Programs under the Start Menu. Some installers put
+ * shell links here to restart themselves after boot. */
+static BOOL ProcessStartupItems()
+{
+    static const WCHAR AlwaysW[] = { 'a','l','w','a','y','s',0 };
+    static const WCHAR NeverW[] = { 'n','e','v','e','r',0 }; 
+    static const WCHAR StartupItemsW[] = { 'S','o','f','t','w','a','r','e','\\',
+				     'W','i','n','e','\\',
+				     'S','t','a','r','t','u','p','I','t','e','m','s',0 };
+
+    BOOL ret = FALSE;
+    HRESULT hr;
+    int iRet;
+    IMalloc *ppM = NULL;
+    IShellFolder *psfDesktop = NULL, *psfStartup = NULL;
+    LPITEMIDLIST pidlStartup = NULL, pidlItem;
+    ULONG NumPIDLs;
+    IEnumIDList *iEnumList = NULL;
+    STRRET strret;
+    WCHAR wszCommand[MAX_PATH], wszBuffer[MAX_PATH];
+    HINSTANCE hInst = GetModuleHandle(NULL);  
+    DWORD res, bufLength;
+    HKEY hKeyStartupItems = NULL;
+
+    WINE_TRACE("Processing items in the StartUp folder.\n");
+
+    RegOpenKeyExW( HKEY_CURRENT_USER, StartupItemsW, 0, KEY_ALL_ACCESS, &hKeyStartupItems );
+
+    hr = SHGetMalloc(&ppM);
+    if (FAILED(hr)) 
+    {
+	WINE_ERR("Couldn't get IMalloc object.\n");
+	goto done;
+    }
+
+    hr = SHGetDesktopFolder(&psfDesktop);
+    if (FAILED(hr))
+    {
+	WINE_ERR("Couldn't get desktop folder.\n");
+	goto done;
+    }
+
+    hr = SHGetSpecialFolderLocation(NULL, CSIDL_STARTUP, &pidlStartup);
+    if (FAILED(hr))
+    {
+	WINE_TRACE("Couldn't get StartUp folder location.\n");
+	goto done;
+    }
+  
+    hr = IShellFolder_BindToObject(psfDesktop, pidlStartup, NULL, &IID_IShellFolder, (LPVOID*)&psfStartup);
+    if (FAILED(hr))
+    {
+	WINE_TRACE("Couldn't bind IShellFolder to StartUp folder.\n");
+	goto done;
+    }
+
+    hr = IShellFolder_EnumObjects(psfStartup, NULL, SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &iEnumList);
+    if (FAILED(hr))
+    {
+	WINE_TRACE("Unable to enumerate StartUp objects.\n");
+	goto done;
+    }
+
+    while (IEnumIDList_Next(iEnumList, 1, &pidlItem, &NumPIDLs) == S_OK && 
+	   (NumPIDLs) == 1) 
+    {
+	hr = IShellFolder_GetDisplayNameOf(psfStartup, pidlItem, SHGDN_FORPARSING, &strret);
+	if (FAILED(hr)) 
+	    WINE_TRACE("Unable to get display name of enumeration item.\n");
+	else 
+	{
+	    hr = StrRetToBufW(&strret, pidlItem, wszCommand, MAX_PATH);
+	    if (FAILED(hr))
+		WINE_TRACE("Unable to parse display name.\n");
+	    else {
+		/* Our default behavior is not to run */
+		iRet = IDNO;
+  
+		/* Check the registry to see if a default behavior was previously selected for this item */
+		if (hKeyStartupItems) {
+		    bufLength = MAX_PATH;
+		    res = RegQueryValueExW(hKeyStartupItems, wszCommand, NULL, NULL, (LPBYTE)wszBuffer, &bufLength);
+		    if (res == ERROR_SUCCESS) {
+			/* Two possibilities here, always or never */
+			if (!StrCmpW(wszBuffer, AlwaysW)) iRet = ID_ALWAYS;
+			else if (!StrCmpW(wszBuffer, NeverW)) iRet = ID_NEVER;
+			else 
+			    WINE_ERR("StartupItem %s has undefined registry action %s.\n", wine_dbgstr_w(wszCommand), wine_dbgstr_w(wszBuffer));
+		    }
+		}
+
+		/* If did not find a key (our behavior is still not to run), ask the user */
+		if (iRet == IDNO)
+		    iRet = DialogBoxParam(hInst, "Run_Confirmation_Dialog", NULL, (DLGPROC)rcd_Setup, (LPARAM)wszCommand);
+
+		/* Now do what we determined either from the registry or from the user */
+	        switch (iRet) {
+		    case ID_ALWAYS:
+		      /* Set the appropriate registry key */
+		      if (!hKeyStartupItems &&
+			  (res = RegCreateKeyExW(HKEY_CURRENT_USER, StartupItemsW, 0, NULL, 
+						 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
+						 &hKeyStartupItems, NULL)) != ERROR_SUCCESS) 
+			  WINE_ERR("Error %d creating registry key %s.\n", res, wine_dbgstr_w(StartupItemsW));
+		      else if ((res = RegSetValueExW(hKeyStartupItems, wszCommand, 0, REG_SZ, 
+						     (LPBYTE) AlwaysW, 
+						     (lstrlenW(AlwaysW)+1)*sizeof(WCHAR))) != ERROR_SUCCESS)
+			  WINE_ERR("Error %d setting registry key %s value to %s.\n", res,
+				   wine_dbgstr_w(wszCommand), wine_dbgstr_w(AlwaysW));
+			 
+		      /* Go from always to running the command, no break needed here. */
+
+		    case IDYES:
+		      if ((iRet = (int)ShellExecuteW(NULL, NULL, wszCommand, NULL, NULL, 0)) <= 32)
+			WINE_ERR("Error %d executing command %s.\n", iRet, wine_dbgstr_w(wszCommand));
+		      break;
+
+		    case IDNO: /* don't run, but leave file intact. */
+		      break;
+
+		    case ID_NEVER: /* don't run, set registry key. */
+		      if (!hKeyStartupItems &&
+			  (res = RegCreateKeyExW(HKEY_CURRENT_USER, StartupItemsW, 0, NULL, 
+						 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, 
+						 &hKeyStartupItems, NULL)) != ERROR_SUCCESS) 
+			  WINE_ERR("Error %d creating registry key %s.\n", res, wine_dbgstr_w(StartupItemsW));
+		      else if ((res = RegSetValueExW(hKeyStartupItems, wszCommand, 0, REG_SZ, 
+						    (LPBYTE) NeverW, 
+						    (lstrlenW(NeverW)+1)*sizeof(WCHAR))) != ERROR_SUCCESS)
+			  WINE_ERR("Error %d setting registry key %s value to %s.\n", res,
+				   wine_dbgstr_w(wszCommand), wine_dbgstr_w(NeverW));
+		      break;
+
+		    default: /* Unknown return value */
+		      WINE_ERR("DialogBoxParam returned an unknown value %d.\n", iRet);
+		}
+	    }
+	}
+
+	IMalloc_Free(ppM, pidlItem);
+    }
+
+    /* Return success */
+    ret = TRUE;
+  
+done:
+    if (iEnumList) IEnumIDList_Release(iEnumList);
+    if (psfStartup) IShellFolder_Release(psfStartup);
+    if (pidlStartup) IMalloc_Free(ppM, pidlStartup); 
+    if (hKeyStartupItems) RegCloseKey(hKeyStartupItems);
+
+    return ret;
+}
+
 static void usage(void)
 {
     WINE_MESSAGE( "Usage: wineboot [options]\n" );
@@ -732,7 +927,9 @@ int main( int argc, char *argv[] )
                 FALSE, FALSE )) &&
         (!ops.postlogin || !ops.startup ||
          ProcessRunKeys( HKEY_CURRENT_USER, runkeys_names[RUNKEY_RUN],
-                FALSE, FALSE ));
+                FALSE, FALSE )) &&
+	(!ops.postlogin || !ops.startup ||
+	 ProcessStartupItems( ));
 
     WINE_TRACE("Operation done\n");
 
diff --git a/programs/wineboot/wineboot.h b/programs/wineboot/wineboot.h
new file mode 100644
index 0000000..5c838b4
--- /dev/null
+++ b/programs/wineboot/wineboot.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Misha Koshelev.
+ *
+ * This library 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.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define ID_PROGRAM           997
+#define ID_ALWAYS            998
+#define ID_NEVER             999
diff --git a/programs/wineboot/wineboot.rc b/programs/wineboot/wineboot.rc
new file mode 100644
index 0000000..0abd583
--- /dev/null
+++ b/programs/wineboot/wineboot.rc
@@ -0,0 +1,26 @@
+/*
+ * WINEBOOT.RC
+ *
+ * Copyright (c) 2007 Misha Koshelev.
+ *
+ * This library 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.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <windows.h>
+#include "wineboot.h"
+
+#include "En.rc"
+
+LANGUAGE LANG_NEUTRAL,SUBLANG_NEUTRAL
-- 
1.4.1



More information about the wine-devel mailing list