wineboot: Start items in StartUp folder on boot, includes security
measures. [fixed]
Misha Koshelev
mk144210 at bcm.tmc.edu
Sun Feb 11 21:46:11 CST 2007
http://bugs.winehq.org/show_bug.cgi?id=7384
Installer requires Startup item execution on boot. This patch is the one
with security measures, it includes the ShellExecute fix so now works
properly. Also, I added a registry key (HKEY_CURRENT_USER\Software\Wine
\StartupItems) that if set to "always" makes it like Windows, and always
runs startup items without ever asking the user.
Changelog:
* wineboot: Start items in StartUp folder on boot, includes security
measures.
-------------- next part --------------
From 7465a6f5e695a33670343cd959fca3fbf763899a Mon Sep 17 00:00:00 2001
From: Misha Koshelev <mk144210 at bcm.tmc.edu>
Date: Sun, 11 Feb 2007 21:41:51 -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 | 222 +++++++++++++++++++++++++++++++++++++++++
programs/wineboot/wineboot.h | 21 ++++
programs/wineboot/wineboot.rc | 26 +++++
5 files changed, 307 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..ba973cf 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,214 @@ 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. User input is solicited to prevent malware by
+ * default. The following registry keys are used:
+ *
+ * HKEY_CURRENT_USER\Software\Wine\StartupItems - if set to "always" always runs, otherwise asks user
+ * (determines run behavior for all items)
+ * HKEY_CURRENT_USER\Software\Wine\StartupItems\FullPathOfFile - set to always or never
+ * (determines run behavior for item)
+ * */
+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;
+ BOOL bAskUser = TRUE; /* Change this default value to change the default behavior */
+
+ WINE_TRACE("Processing items in the StartUp folder.\n");
+
+ /* Get the startup items registry key and record our default ask behavior */
+ RegOpenKeyExW( HKEY_CURRENT_USER, StartupItemsW, 0, KEY_ALL_ACCESS, &hKeyStartupItems );
+ bufLength = MAX_PATH;
+ res = RegQueryValueExW(hKeyStartupItems, NULL, NULL, NULL, (LPBYTE)wszBuffer, &bufLength);
+ if (res == ERROR_SUCCESS) {
+ if (!StrCmpW(wszBuffer, AlwaysW)) bAskUser = FALSE; /* Always run means never ask */
+ else if (!StrCmpW(wszBuffer, NeverW)) bAskUser = TRUE; /* Never ask means always run */
+ else
+ WINE_ERR("Startup Item Ask Behavior has undefined value %s.\n", wine_dbgstr_w(wszBuffer));
+ }
+
+ 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 {
+ /* Set the default value based on our ask behavior */
+ if (bAskUser)
+ iRet = IDNO;
+ else
+ iRet = IDYES;
+
+ /* If the current behavior is not to start, check the registry for the default behavior for
+ * this item. */
+ if (iRet == IDNO && 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 our behavior is still no, 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, SW_SHOWNORMAL)) <= 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 +948,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-patches
mailing list