summaryrefslogtreecommitdiffstats
path: root/win/upgrade_wizard
diff options
context:
space:
mode:
Diffstat (limited to 'win/upgrade_wizard')
-rw-r--r--win/upgrade_wizard/CMakeLists.txt47
-rw-r--r--win/upgrade_wizard/res/upgrade.icobin0 -> 99678 bytes
-rw-r--r--win/upgrade_wizard/res/upgrade.rc213
-rw-r--r--win/upgrade_wizard/resource.h27
-rw-r--r--win/upgrade_wizard/stdafx.h47
-rw-r--r--win/upgrade_wizard/targetver.h8
-rw-r--r--win/upgrade_wizard/upgrade.cpp57
-rw-r--r--win/upgrade_wizard/upgrade.h32
-rw-r--r--win/upgrade_wizard/upgrade.rc148
-rw-r--r--win/upgrade_wizard/upgradeDlg.cpp641
-rw-r--r--win/upgrade_wizard/upgradeDlg.h73
-rw-r--r--win/upgrade_wizard/upgrade_wizard.exe.manifest15
12 files changed, 1108 insertions, 0 deletions
diff --git a/win/upgrade_wizard/CMakeLists.txt b/win/upgrade_wizard/CMakeLists.txt
new file mode 100644
index 00000000..fd3560e1
--- /dev/null
+++ b/win/upgrade_wizard/CMakeLists.txt
@@ -0,0 +1,47 @@
+IF((NOT MSVC) OR CLANG_CL OR WITH_ASAN)
+ RETURN()
+ENDIF()
+
+# We need MFC
+# /permissive- flag does not play well with MFC, disable it.
+STRING(REPLACE "/permissive-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+REMOVE_DEFINITIONS(-DNOSERVICE) # fixes "already defined" warning in an AFX header
+
+FIND_PACKAGE(MFC)
+IF(NOT MFC_FOUND)
+ IF(BUILD_RELEASE)
+ MESSAGE(FATAL_ERROR
+ "Can't find MFC. It is necessary for producing official package"
+ )
+ ENDIF()
+ RETURN()
+ENDIF()
+
+IF(MSVC_CRT_TYPE MATCHES "/MD")
+ # FORCE static CRT and MFC for upgrade wizard,
+ # so we do not have to redistribute MFC.
+ FORCE_STATIC_CRT()
+ SET(UPGRADE_WIZARD_SOURCES ${CMAKE_SOURCE_DIR}/sql/winservice.c)
+ELSE()
+ SET(UPGRADE_WIZARD_LINK_LIBRARIES winservice)
+ENDIF()
+
+# MFC should be statically linked
+SET(CMAKE_MFC_FLAG 1)
+
+# Enable exception handling (avoids warnings)
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc -DNO_WARN_MBCS_MFC_DEPRECATION")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql)
+MYSQL_ADD_EXECUTABLE(mariadb-upgrade-wizard
+ upgrade.cpp upgradeDlg.cpp upgrade.rc ${UPGRADE_WIZARD_SOURCES}
+ COMPONENT Server)
+
+
+TARGET_LINK_LIBRARIES(mariadb-upgrade-wizard ${UPGRADE_WIZARD_LINK_LIBRARIES})
+# upgrade_wizard is Windows executable, set WIN32_EXECUTABLE so it does not
+# create a console.
+SET_TARGET_PROPERTIES(mariadb-upgrade-wizard PROPERTIES
+ WIN32_EXECUTABLE 1
+ LINK_FLAGS "/MANIFESTUAC:level='requireAdministrator'"
+)
diff --git a/win/upgrade_wizard/res/upgrade.ico b/win/upgrade_wizard/res/upgrade.ico
new file mode 100644
index 00000000..33a61783
--- /dev/null
+++ b/win/upgrade_wizard/res/upgrade.ico
Binary files differ
diff --git a/win/upgrade_wizard/res/upgrade.rc2 b/win/upgrade_wizard/res/upgrade.rc2
new file mode 100644
index 00000000..8a1da417
--- /dev/null
+++ b/win/upgrade_wizard/res/upgrade.rc2
@@ -0,0 +1,13 @@
+//
+// zzz.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+#error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/win/upgrade_wizard/resource.h b/win/upgrade_wizard/resource.h
new file mode 100644
index 00000000..4c05cea2
--- /dev/null
+++ b/win/upgrade_wizard/resource.h
@@ -0,0 +1,27 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by upgrade.rc
+//
+#define IDD_UPGRADE_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDC_LIST1 1000
+#define IDC_PROGRESS1 1004
+#define IDC_EDIT1 1005
+#define IDC_EDIT2 1006
+#define IDC_EDIT3 1007
+#define IDC_EDIT7 1011
+#define IDC_EDIT8 1012
+#define IDC_EDIT9 1013
+#define IDC_BUTTON1 1014
+#define IDC_BUTTON2 1015
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1016
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/win/upgrade_wizard/stdafx.h b/win/upgrade_wizard/stdafx.h
new file mode 100644
index 00000000..86e4fd82
--- /dev/null
+++ b/win/upgrade_wizard/stdafx.h
@@ -0,0 +1,47 @@
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
+#ifndef _SECURE_ATL
+#define _SECURE_ATL 1
+#endif
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include "targetver.h"
+struct IUnknown;
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+// turns off MFC's hiding of some common and often safely ignored warning messages
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+
+
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/win/upgrade_wizard/targetver.h b/win/upgrade_wizard/targetver.h
new file mode 100644
index 00000000..87c0086d
--- /dev/null
+++ b/win/upgrade_wizard/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/win/upgrade_wizard/upgrade.cpp b/win/upgrade_wizard/upgrade.cpp
new file mode 100644
index 00000000..ea2f894c
--- /dev/null
+++ b/win/upgrade_wizard/upgrade.cpp
@@ -0,0 +1,57 @@
+
+// upgrade.cpp : Defines the class behaviors for the application.
+//
+
+#include "stdafx.h"
+#include "upgrade.h"
+#include "upgradeDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CUpgradeApp
+
+BEGIN_MESSAGE_MAP(CUpgradeApp, CWinApp)
+ ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+
+// CUpgradeApp construction
+
+CUpgradeApp::CUpgradeApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+
+// The one and only CUpgradeApp object
+
+CUpgradeApp theApp;
+
+
+// CUpgradeApp initialization
+
+BOOL CUpgradeApp::InitInstance()
+{
+ // InitCommonControlsEx() is required on Windows XP if an application
+ // manifest specifies use of ComCtl32.dll version 6 or later to enable
+ // visual styles. Otherwise, any window creation will fail.
+ INITCOMMONCONTROLSEX InitCtrls;
+ InitCtrls.dwSize = sizeof(InitCtrls);
+ // Set this to include all the common control classes you want to use
+ // in your application.
+ InitCtrls.dwICC = ICC_WIN95_CLASSES;
+
+ InitCommonControlsEx(&InitCtrls);
+ CWinApp::InitInstance();
+ CUpgradeDlg dlg;
+ m_pMainWnd = &dlg;
+ dlg.DoModal();
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
+
diff --git a/win/upgrade_wizard/upgrade.h b/win/upgrade_wizard/upgrade.h
new file mode 100644
index 00000000..b5dd10e7
--- /dev/null
+++ b/win/upgrade_wizard/upgrade.h
@@ -0,0 +1,32 @@
+
+// zzz.h : main header file for the PROJECT_NAME application
+//
+
+#pragma once
+
+#ifndef __AFXWIN_H__
+ #error "include 'stdafx.h' before including this file for PCH"
+#endif
+
+#include "resource.h" // main symbols
+
+
+// CzzzApp:
+// See zzz.cpp for the implementation of this class
+//
+
+class CUpgradeApp : public CWinApp
+{
+public:
+ CUpgradeApp();
+
+// Overrides
+public:
+ virtual BOOL InitInstance();
+
+// Implementation
+
+ DECLARE_MESSAGE_MAP()
+};
+
+extern CUpgradeApp theApp; \ No newline at end of file
diff --git a/win/upgrade_wizard/upgrade.rc b/win/upgrade_wizard/upgrade.rc
new file mode 100644
index 00000000..dbba9f67
--- /dev/null
+++ b/win/upgrade_wizard/upgrade.rc
@@ -0,0 +1,148 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#ifndef APSTUDIO_INVOKED
+#include "targetver.h"
+#endif
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// German (Germany) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#ifndef APSTUDIO_INVOKED\r\n"
+ "#include ""targetver.h""\r\n"
+ "#endif\r\n"
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#include ""res\\upgrade.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON "res\\upgrade.ico"
+#endif // German (Germany) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (United States) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_UPGRADE_DIALOG DIALOGEX 0, 0, 320, 200
+STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "MariaDB Upgrade Wizard"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,113,169,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,191,169,50,14
+ LISTBOX IDC_LIST1,24,39,216,80,LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ EDITTEXT IDC_EDIT1,97,124,193,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_EDIT2,98,138,181,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ CONTROL "",IDC_PROGRESS1,"msctls_progress32",PBS_SMOOTH | WS_BORDER,26,153,243,14
+ EDITTEXT IDC_EDIT3,98,151,40,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_EDIT7,27,124,65,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_EDIT8,27,137,62,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ EDITTEXT IDC_EDIT9,27,151,62,14,ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER
+ PUSHBUTTON "Select all",IDC_BUTTON1,245,61,50,14
+ PUSHBUTTON "Clear all",IDC_BUTTON2,246,88,50,14
+ LTEXT "Select services you want to upgrade and click on the [Upgrade] button.\nMake sure to backup data directories prior to upgrade.",IDC_STATIC,25,14,215,26
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_UPGRADE_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 313
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 193
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (United States) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+LANGUAGE 9, 1
+#include "res\upgrade.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/win/upgrade_wizard/upgradeDlg.cpp b/win/upgrade_wizard/upgradeDlg.cpp
new file mode 100644
index 00000000..10a1787c
--- /dev/null
+++ b/win/upgrade_wizard/upgradeDlg.cpp
@@ -0,0 +1,641 @@
+
+// upgradeDlg.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "upgrade.h"
+#include "upgradeDlg.h"
+#include "windows.h"
+#include "winsvc.h"
+#include <msi.h>
+#pragma comment(lib, "msi")
+#pragma comment(lib, "version")
+#include <map>
+#include <string>
+#include <vector>
+
+#include <winservice.h>
+#include <locale.h>
+
+using namespace std;
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#define PRODUCT_NAME "MariaDB"
+
+// CUpgradeDlg dialog
+
+CUpgradeDlg::CUpgradeDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CUpgradeDlg::IDD, pParent)
+{
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CUpgradeDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ DDX_Control(pDX, IDC_LIST1, m_Services);
+ DDX_Control(pDX, IDC_PROGRESS1, m_Progress);
+ DDX_Control(pDX, IDOK, m_Ok);
+ DDX_Control(pDX, IDCANCEL, m_Cancel);
+ DDX_Control(pDX, IDC_EDIT1, m_IniFilePath);
+ DDX_Control(pDX, IDC_EDIT2, m_DataDir);
+ DDX_Control(pDX, IDC_EDIT3, m_Version);
+ DDX_Control(pDX, IDC_EDIT7, m_IniFileLabel);
+ DDX_Control(pDX, IDC_EDIT8, m_DataDirLabel);
+ DDX_Control(pDX, IDC_EDIT9, m_VersionLabel);
+ DDX_Control(pDX, IDC_BUTTON1, m_SelectAll);
+ DDX_Control(pDX, IDC_BUTTON2, m_ClearAll);
+}
+
+BEGIN_MESSAGE_MAP(CUpgradeDlg, CDialog)
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_LBN_SELCHANGE(IDC_LIST1, &CUpgradeDlg::OnLbnSelchangeList1)
+ ON_CONTROL(CLBN_CHKCHANGE, IDC_LIST1, OnChkChange)
+ ON_BN_CLICKED(IDOK, &CUpgradeDlg::OnBnClickedOk)
+ ON_BN_CLICKED(IDCANCEL, &CUpgradeDlg::OnBnClickedCancel)
+ ON_BN_CLICKED(IDC_BUTTON1,&CUpgradeDlg::OnBnSelectAll)
+ ON_BN_CLICKED(IDC_BUTTON2,&CUpgradeDlg::OnBnClearAll)
+END_MESSAGE_MAP()
+
+
+struct ServiceProperties
+{
+ string servicename;
+ string myini;
+ string datadir;
+ string version;
+};
+
+vector<ServiceProperties> services;
+
+/*
+ Get version from an executable.
+ Returned version is either major.minor.patch or
+ <unknown> , of executable does not have any version
+ info embedded (like MySQL 5.1 for example)
+*/
+void GetExeVersion(const string& filename, int *major, int *minor, int *patch)
+{
+ DWORD handle;
+ *major= *minor= *patch= 0;
+
+ DWORD size = GetFileVersionInfoSize(filename.c_str(), &handle);
+ BYTE* versionInfo = new BYTE[size];
+ if (!GetFileVersionInfo(filename.c_str(), handle, size, versionInfo))
+ {
+ delete[] versionInfo;
+ return;
+ }
+ // we have version information
+ UINT len = 0;
+ VS_FIXEDFILEINFO* vsfi = NULL;
+ VerQueryValue(versionInfo, "\\", (void**)&vsfi, &len);
+
+ *major= (int)HIWORD(vsfi->dwFileVersionMS);
+ *minor= (int)LOWORD(vsfi->dwFileVersionMS);
+ *patch= (int)HIWORD(vsfi->dwFileVersionLS);
+ delete[] versionInfo;
+}
+
+
+void GetMyVersion(int *major, int *minor, int *patch)
+{
+ char path[MAX_PATH];
+ *major= *minor= *patch =0;
+ if (GetModuleFileName(NULL, path, MAX_PATH))
+ {
+ GetExeVersion(path, major, minor, patch);
+ }
+}
+// CUpgradeDlg message handlers
+
+/* Handle selection changes in services list */
+void CUpgradeDlg::SelectService(int index)
+{
+ m_IniFilePath.SetWindowText(services[index].myini.c_str());
+ m_DataDir.SetWindowText(services[index].datadir.c_str());
+ m_Version.SetWindowText(services[index].version.c_str());
+}
+
+
+
+/*
+ Iterate over services, lookup for mysqld.exe ones.
+ Compare mysqld.exe version with current version, and display
+ service if corresponding mysqld.exe has lower version.
+
+ The version check is not strict, i.e we allow to "upgrade"
+ for the same major.minor combination. This can be useful for
+ "upgrading" from 32 to 64 bit, or for MySQL=>Maria conversion.
+*/
+void CUpgradeDlg::PopulateServicesList()
+{
+
+ SC_HANDLE scm = OpenSCManager(NULL, NULL,
+ SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_CONNECT);
+ if (scm == NULL)
+ {
+ ErrorExit("OpenSCManager failed");
+ }
+
+ static BYTE buf[2*64*1024];
+ static BYTE configBuffer[8*1024];
+
+ DWORD bufsize= sizeof(buf);
+ DWORD bufneed;
+ DWORD num_services;
+ BOOL ok= EnumServicesStatusExW(scm, SC_ENUM_PROCESS_INFO, SERVICE_WIN32,
+ SERVICE_STATE_ALL, buf, bufsize, &bufneed, &num_services, NULL, NULL);
+ if(!ok)
+ ErrorExit("EnumServicesStatusEx failed");
+
+
+ LPENUM_SERVICE_STATUS_PROCESSW info =
+ (LPENUM_SERVICE_STATUS_PROCESSW)buf;
+ int index=-1;
+ for (ULONG i=0; i < num_services; i++)
+ {
+ SC_HANDLE service= OpenServiceW(scm, info[i].lpServiceName,
+ SERVICE_QUERY_CONFIG);
+ if (!service)
+ continue;
+ QUERY_SERVICE_CONFIGW *config=
+ (QUERY_SERVICE_CONFIGW*)(void *)configBuffer;
+ DWORD needed;
+ BOOL ok= QueryServiceConfigW(service, config,sizeof(configBuffer), &needed);
+ CloseServiceHandle(service);
+ if (ok)
+ {
+ mysqld_service_properties service_props;
+
+ if (get_mysql_service_properties(config->lpBinaryPathName,
+ &service_props))
+ continue;
+
+ /* Check if service uses mysqld in installation directory */
+ if (_strnicmp(service_props.mysqld_exe, m_InstallDir.c_str(),
+ m_InstallDir.size()) == 0)
+ continue;
+
+ if(m_MajorVersion > service_props.version_major ||
+ (m_MajorVersion == service_props.version_major && m_MinorVersion >=
+ service_props.version_minor))
+ {
+ ServiceProperties props;
+ props.myini= service_props.inifile;
+ props.datadir= service_props.datadir;
+ char service_name_buf[1024];
+ WideCharToMultiByte(GetACP(), 0, info[i].lpServiceName, -1,
+ service_name_buf, sizeof(service_name_buf),
+ 0, 0);
+ props.servicename= service_name_buf;
+ if (service_props.version_major)
+ {
+ char ver[64];
+ sprintf(ver, "%d.%d.%d", service_props.version_major,
+ service_props.version_minor, service_props.version_patch);
+ props.version= ver;
+ }
+ else
+ props.version= "<unknown>";
+
+ index = m_Services.AddString(service_name_buf);
+ services.resize(index+1);
+ services[index] = props;
+ }
+ }
+ if (index != -1)
+ {
+ m_Services.SetCurSel(0);
+ SelectService(m_Services.GetCurSel());
+ }
+ }
+ if (services.size())
+ {
+ SelectService(0);
+ }
+ else
+ {
+ char message[128];
+ sprintf(message,
+ "There is no service that can be upgraded to " PRODUCT_NAME " %d.%d.%d",
+ m_MajorVersion, m_MinorVersion, m_PatchVersion);
+ MessageBox(message, PRODUCT_NAME " Upgrade Wizard", MB_ICONINFORMATION);
+ exit(0);
+ }
+ if(scm)
+ CloseServiceHandle(scm);
+}
+
+BOOL CUpgradeDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+ m_UpgradeRunning= FALSE;
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+ m_Ok.SetWindowText("Upgrade");
+ m_DataDirLabel.SetWindowText("Data directory:");
+ m_IniFileLabel.SetWindowText("Configuration file:");
+ m_VersionLabel.SetWindowText("Version:");
+
+ char myFilename[MAX_PATH];
+ GetModuleFileName(NULL, myFilename, MAX_PATH);
+ char *p= strrchr(myFilename,'\\');
+ if(p)
+ p[1]=0;
+ m_InstallDir= myFilename;
+
+ GetMyVersion(&m_MajorVersion, &m_MinorVersion, &m_PatchVersion);
+ char windowTitle[64];
+
+ sprintf(windowTitle, PRODUCT_NAME " %d.%d.%d Upgrade Wizard",
+ m_MajorVersion, m_MinorVersion, m_PatchVersion);
+ SetWindowText(windowTitle);
+
+ m_JobObject= CreateJobObject(NULL, NULL);
+
+ /*
+ Make all processes associated with the job terminate when the
+ last handle to the job is closed or job is teminated.
+ */
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
+ jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+ SetInformationJobObject(m_JobObject, JobObjectExtendedLimitInformation,
+ &jeli, sizeof(jeli));
+
+
+ m_Progress.ShowWindow(SW_HIDE);
+ m_Ok.EnableWindow(FALSE);
+ if (GetACP() == CP_UTF8)
+ {
+ /* Required for mbstowcs, used in some functions.*/
+ setlocale(LC_ALL, "en_US.UTF8");
+ }
+ PopulateServicesList();
+ return TRUE; // return TRUE unless you set the focus to a control
+}
+
+// If you add a minimize button to your dialog, you will need the code below
+// to draw the icon. For MFC applications using the document/view model,
+// this is automatically done for you by the framework.
+
+void CUpgradeDlg::OnPaint()
+{
+ if (IsIconic())
+ {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND,
+ reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else
+ {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this function to obtain the cursor to display while the user
+// drags the minimized window.
+HCURSOR CUpgradeDlg::OnQueryDragIcon()
+{
+ return static_cast<HCURSOR>(m_hIcon);
+}
+
+
+void CUpgradeDlg::OnLbnSelchangeList1()
+{
+ SelectService(m_Services.GetCurSel());
+}
+
+void CUpgradeDlg::OnChkChange()
+{
+ if(m_Services.GetCheck( m_Services.GetCurSel()))
+ {
+ GetDlgItem(IDOK)->EnableWindow();
+ }
+ else
+ {
+ for(int i=0; i< m_Services.GetCount(); i++)
+ {
+ if(m_Services.GetCheck(i))
+ return;
+ }
+ // all items unchecked, disable OK button
+ GetDlgItem(IDOK)->EnableWindow(FALSE);
+ }
+}
+
+
+
+void CUpgradeDlg::ErrorExit(LPCSTR str)
+{
+ MessageBox(str, "Fatal Error", MB_ICONERROR);
+ exit(1);
+}
+
+
+const int MAX_MESSAGES=512;
+
+/* Main thread of the child process */
+static HANDLE hChildThread;
+
+void CUpgradeDlg::UpgradeOneService(const string& servicename)
+{
+ static string allMessages[MAX_MESSAGES];
+ static char npname[MAX_PATH];
+ static char pipeReadBuf[1];
+ SECURITY_ATTRIBUTES saAttr;
+ STARTUPINFO si={0};
+ PROCESS_INFORMATION pi;
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ saAttr.lpSecurityDescriptor = NULL;
+
+ HANDLE hPipeRead, hPipeWrite;
+ if(!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 1))
+ ErrorExit("CreateNamedPipe failed");
+
+ /* Make sure read end of the pipe is not inherited */
+ if (!SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, 0) )
+ ErrorExit("Stdout SetHandleInformation");
+
+ string commandline("mysql_upgrade_service.exe --service=");
+ commandline += "\"";
+ commandline += servicename;
+ commandline += "\"";
+
+ si.cb = sizeof(si);
+ si.hStdInput= GetStdHandle(STD_INPUT_HANDLE);
+ si.hStdOutput= hPipeWrite;
+ si.hStdError= hPipeWrite;
+ si.wShowWindow= SW_HIDE;
+ si.dwFlags= STARTF_USESTDHANDLES |STARTF_USESHOWWINDOW;
+
+
+ /*
+ We will try to assign child process to a job, to be able to
+ terminate the process and all of its children. It might fail,
+ in case current process is already part of the job which does
+ not allows breakaways.
+ */
+ if (CreateProcess(NULL, (LPSTR)commandline.c_str(), NULL, NULL, TRUE,
+ CREATE_BREAKAWAY_FROM_JOB|CREATE_SUSPENDED, NULL, NULL, &si, &pi))
+ {
+ if(!AssignProcessToJobObject(m_JobObject, pi.hProcess))
+ {
+ char errmsg[128];
+ sprintf(errmsg, "AssignProcessToJobObject failed, error %d",
+ GetLastError());
+ ErrorExit(errmsg);
+ }
+ ResumeThread(pi.hThread);
+ }
+ else
+ {
+ /*
+ Creating a process with CREATE_BREAKAWAY_FROM_JOB failed, reset this flag
+ and retry.
+ */
+ if (!CreateProcess(NULL, (LPSTR)commandline.c_str(), NULL, NULL, TRUE,
+ 0, NULL, NULL, &si, &pi))
+ {
+ string errmsg("Create Process ");
+ errmsg+= commandline;
+ errmsg+= " failed";
+ ErrorExit(errmsg.c_str());
+ }
+ }
+
+ hChildThread = pi.hThread;
+ DWORD nbytes;
+ int lines=0;
+ CloseHandle(hPipeWrite);
+
+ string output_line;
+ while(ReadFile(hPipeRead, pipeReadBuf, 1, &nbytes, NULL))
+ {
+ if(pipeReadBuf[0] == '\n')
+ {
+ allMessages[lines%MAX_MESSAGES] = output_line;
+ m_DataDir.SetWindowText(allMessages[lines%MAX_MESSAGES].c_str());
+ lines++;
+
+ int curPhase, numPhases;
+
+ // Parse output line to update progress indicator
+ if (strncmp(output_line.c_str(),"Phase ",6) == 0 &&
+ sscanf(output_line.c_str() +6 ,"%d/%d",&curPhase,&numPhases) == 2
+ && numPhases > 0 )
+ {
+ int stepsTotal= m_ProgressTotal*numPhases;
+ int stepsCurrent= m_ProgressCurrent*numPhases+ curPhase;
+ int percentDone= stepsCurrent*100/stepsTotal;
+ m_Progress.SetPos(percentDone);
+ m_Progress.SetPos(stepsCurrent * 100 / stepsTotal);
+ }
+ output_line.clear();
+ }
+ else
+ {
+ if(pipeReadBuf[0] != '\r')
+ output_line.push_back(pipeReadBuf[0]);
+ }
+ }
+ CloseHandle(hPipeRead);
+
+ if(WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_OBJECT_0)
+ ErrorExit("WaitForSingleObject failed");
+ DWORD exitcode;
+ if (!GetExitCodeProcess(pi.hProcess, &exitcode))
+ ErrorExit("GetExitCodeProcess failed");
+
+ if (exitcode != 0)
+ {
+ string errmsg= "mysql_upgrade_service returned error for service ";
+ errmsg += servicename;
+ errmsg += ":\r\n";
+ errmsg+= output_line;
+ ErrorExit(errmsg.c_str());
+ }
+ CloseHandle(pi.hProcess);
+ hChildThread= 0;
+ CloseHandle(pi.hThread);
+}
+
+
+void CUpgradeDlg::UpgradeServices()
+{
+
+ /*
+ Disable some dialog items during upgrade (OK button,
+ services list)
+ */
+ m_Ok.EnableWindow(FALSE);
+ m_Services.EnableWindow(FALSE);
+ m_SelectAll.EnableWindow(FALSE);
+ m_ClearAll.EnableWindow(FALSE);
+
+ /*
+ Temporarily repurpose IniFileLabel/IniFilePath and
+ DatDirLabel/DataDir controls to show progress messages.
+ */
+ m_VersionLabel.ShowWindow(FALSE);
+ m_Version.ShowWindow(FALSE);
+ m_Progress.ShowWindow(TRUE);
+ m_IniFileLabel.SetWindowText("Converting service:");
+ m_IniFilePath.SetWindowText("");
+ m_DataDirLabel.SetWindowText("Progress message:");
+ m_DataDir.SetWindowText("");
+
+
+ m_ProgressTotal=0;
+ for(int i=0; i< m_Services.GetCount(); i++)
+ {
+ if(m_Services.GetCheck(i))
+ m_ProgressTotal++;
+ }
+ m_ProgressCurrent=0;
+ for(int i=0; i< m_Services.GetCount(); i++)
+ {
+ if(m_Services.GetCheck(i))
+ {
+ m_IniFilePath.SetWindowText(services[i].servicename.c_str());
+ m_Services.SelectString(0, services[i].servicename.c_str());
+ UpgradeOneService(services[i].servicename);
+ m_ProgressCurrent++;
+ }
+ }
+
+ MessageBox("Service(s) successfully upgraded", "Success",
+ MB_ICONINFORMATION);
+
+ /* Rebuild services list */
+ vector<ServiceProperties> new_instances;
+ for(int i=0; i< m_Services.GetCount(); i++)
+ {
+ if(!m_Services.GetCheck(i))
+ new_instances.push_back(services[i]);
+ }
+
+ services= new_instances;
+ m_Services.ResetContent();
+ for(size_t i=0; i< services.size();i++)
+ m_Services.AddString(services[i].servicename.c_str());
+ if(services.size())
+ {
+ m_Services.SelectString(0,services[0].servicename.c_str());
+ SelectService(0);
+ }
+ else
+ {
+ /* Nothing to do, there are no upgradable services */
+ exit(0);
+ }
+
+ /*
+ Restore controls that were temporarily repurposed for
+ progress info to their normal state
+ */
+ m_IniFileLabel.SetWindowText("Configuration file:");
+ m_DataDirLabel.SetWindowText("Data Directory:");
+ m_VersionLabel.ShowWindow(TRUE);
+ m_Version.ShowWindow(TRUE);
+ m_Progress.SetPos(0);
+ m_Progress.ShowWindow(FALSE);
+
+ /* Re-enable controls */
+ m_Ok.EnableWindow(TRUE);
+ m_Services.EnableWindow(TRUE);
+ m_SelectAll.EnableWindow(TRUE);
+ m_ClearAll.EnableWindow(TRUE);
+
+ m_UpgradeRunning= FALSE;
+}
+
+
+/* Thread procedure for upgrade services operation */
+static UINT UpgradeServicesThread(void *param)
+{
+ CUpgradeDlg *dlg= (CUpgradeDlg *)param;
+ dlg->UpgradeServices();
+ return 0;
+}
+
+
+/*
+ Do upgrade for all services currently selected
+ in the list. Since it is a potentially lengthy operation that
+ might block it has to be done in a background thread.
+*/
+void CUpgradeDlg::OnBnClickedOk()
+{
+ if(m_UpgradeRunning)
+ return;
+ m_UpgradeRunning= TRUE;
+ AfxBeginThread(UpgradeServicesThread, this);
+}
+
+
+/*
+ Cancel button clicked.
+ If upgrade is running, suspend mysql_upgrade_service,
+ and ask user whether he really wants to stop.Terminate
+ upgrade wizard and all subprocesses if users wants it.
+
+ If upgrade is not running, terminate the Wizard
+*/
+void CUpgradeDlg::OnBnClickedCancel()
+{
+ if(m_UpgradeRunning)
+ {
+ bool suspended = (SuspendThread(hChildThread) != (DWORD)-1);
+ int ret = MessageBox(
+ "Upgrade is in progress. Are you sure you want to terminate?",
+ 0, MB_YESNO|MB_DEFBUTTON2|MB_ICONQUESTION);
+ if(ret != IDYES)
+ {
+ if(suspended)
+ ResumeThread(hChildThread);
+ return;
+ }
+ }
+ TerminateJobObject(m_JobObject, 1);
+ exit(1);
+}
+
+/*
+ Select all services from the list
+*/
+void CUpgradeDlg::OnBnSelectAll()
+{
+ for(int i=0; i < m_Services.GetCount(); i++)
+ m_Services.SetCheck(i, 1);
+ m_Ok.EnableWindow(TRUE);
+}
+
+/*
+ Clear all services in the list
+*/
+void CUpgradeDlg::OnBnClearAll()
+{
+ for(int i=0; i < m_Services.GetCount(); i++)
+ m_Services.SetCheck(i, 0);
+ m_Ok.EnableWindow(FALSE);
+}
diff --git a/win/upgrade_wizard/upgradeDlg.h b/win/upgrade_wizard/upgradeDlg.h
new file mode 100644
index 00000000..636f9489
--- /dev/null
+++ b/win/upgrade_wizard/upgradeDlg.h
@@ -0,0 +1,73 @@
+
+// upgradeDlg.h : header file
+//
+
+#pragma once
+#include "afxcmn.h"
+#include "afxwin.h"
+#include <string>
+
+
+// CUpgradeDlg dialog
+class CUpgradeDlg : public CDialog
+{
+ // Construction
+public:
+ CUpgradeDlg(CWnd* pParent = NULL); // standard constructor
+
+ // Dialog Data
+ enum { IDD = IDD_UPGRADE_DIALOG };
+
+protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+
+ // job object for current process and children
+ HANDLE m_JobObject;
+
+ // Services are being upgraded
+ BOOL m_UpgradeRunning;
+
+ // ProgressBar related: number of services to upgrade
+ int m_ProgressTotal;
+
+ //ProgressBar related: current service being upgraded
+ int m_ProgressCurrent;
+
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ virtual BOOL OnInitDialog();
+ void PopulateServicesList();
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ DECLARE_MESSAGE_MAP()
+public:
+ void SelectService(int index);
+ void UpgradeServices();
+ void UpgradeOneService(const std::string& name);
+ void ErrorExit(const char *);
+ std::string m_InstallDir;
+ CCheckListBox m_Services;
+ CProgressCtrl m_Progress;
+ CButton m_Ok;
+ CButton m_Cancel;
+ CButton m_SelectAll;
+ CButton m_ClearAll;
+ int m_MajorVersion;
+ int m_MinorVersion;
+ int m_PatchVersion;
+
+ CEdit m_IniFilePath;
+ afx_msg void OnLbnSelchangeList1();
+ afx_msg void OnChkChange();
+ CEdit m_DataDir;
+ CEdit m_Version;
+ afx_msg void OnBnClickedOk();
+ afx_msg void OnBnClickedCancel();
+ afx_msg void OnBnSelectAll();
+ afx_msg void OnBnClearAll();
+ CEdit m_IniFileLabel;
+ CEdit m_DataDirLabel;
+ CEdit m_VersionLabel;
+};
diff --git a/win/upgrade_wizard/upgrade_wizard.exe.manifest b/win/upgrade_wizard/upgrade_wizard.exe.manifest
new file mode 100644
index 00000000..ca89deae
--- /dev/null
+++ b/win/upgrade_wizard/upgrade_wizard.exe.manifest
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+ <security>
+ <requestedPrivileges>
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel>
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
+ </dependentAssembly>
+ </dependency>
+</assembly> \ No newline at end of file