From d0cec33de5b261c7b269d29077f45ffef980266a Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sat, 23 Nov 2019 13:24:44 +0100 Subject: [PATCH] + fix: elevated relaunch after encoding change --- Versions/build.txt | 2 +- minipath/src/minipath.c | 7 +- res/Notepad3.exe.manifest.conf | 2 +- src/Dialogs.c | 13 +- src/Dialogs.h | 2 +- src/Helpers.c | 299 ++++++++++++++++++++++++++++++--- src/Helpers.h | 48 +++--- src/MuiLanguage.c | 6 +- src/Notepad3.c | 66 +++++--- src/TypeDefs.h | 5 +- src/VersionEx.h | 4 +- 11 files changed, 364 insertions(+), 90 deletions(-) diff --git a/Versions/build.txt b/Versions/build.txt index 47fe54a35..14057d17e 100644 --- a/Versions/build.txt +++ b/Versions/build.txt @@ -1 +1 @@ -2685 +2686 diff --git a/minipath/src/minipath.c b/minipath/src/minipath.c index 6552a9982..24c80da81 100644 --- a/minipath/src/minipath.c +++ b/minipath/src/minipath.c @@ -191,15 +191,16 @@ static HMODULE __fastcall _LoadLanguageResources(const WCHAR* localeName, LANGID StringCchCopyW(tchAvailLngs, 512, g_tchAvailableLanguages); WCHAR tchUserLangMultiStrg[512] = { L'\0' }; if (!_LngStrToMultiLngStr(tchAvailLngs, tchUserLangMultiStrg, 512)) { - GetLastErrorToMsgBox(L"_LngStrToMultiLngStr()", ERROR_MUI_INVALID_LOCALE_NAME); + GetLastErrorToMsgBox(L"Trying to load Language resource!", ERROR_MUI_INVALID_LOCALE_NAME); return NULL; } // set the appropriate fallback list DWORD langCount = 0; // using SetProcessPreferredUILanguages is recommended for new applications (esp. multi-threaded applications) - if (!SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, tchUserLangMultiStrg, &langCount) || (langCount == 0)) { - GetLastErrorToMsgBox(L"SetProcessPreferredUILanguages()", 0); + if (!SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, tchUserLangMultiStrg, &langCount) || (langCount == 0)) + { + GetLastErrorToMsgBox(L"Trying to set preferred Language!", ERROR_RESOURCE_LANG_NOT_FOUND); return NULL; } SetThreadUILanguage(langID); diff --git a/res/Notepad3.exe.manifest.conf b/res/Notepad3.exe.manifest.conf index a6349de34..a681a8bd9 100644 --- a/res/Notepad3.exe.manifest.conf +++ b/res/Notepad3.exe.manifest.conf @@ -3,7 +3,7 @@ Notepad3 BETA diff --git a/src/Dialogs.c b/src/Dialogs.c index beab2c6a9..c31940fcc 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -140,9 +140,9 @@ int MessageBoxLng(HWND hwnd, UINT uType, UINT uidMsg, ...) //============================================================================= // -// GetLastErrorToMsgBox() +// MsgBoxLastError() // -DWORD GetLastErrorToMsgBox(LPWSTR lpszFunction, DWORD dwErrID) +DWORD MsgBoxLastError(LPCWSTR lpszMessage, DWORD dwErrID) { // Retrieve the system error message for the last-error code if (!dwErrID) { @@ -162,12 +162,12 @@ DWORD GetLastErrorToMsgBox(LPWSTR lpszFunction, DWORD dwErrID) if (lpMsgBuf) { // Display the error message and exit the process - size_t const len = StringCchLenW((LPCWSTR)lpMsgBuf, 0) + StringCchLenW((LPCWSTR)lpszFunction, 0) + 80; + size_t const len = StringCchLenW((LPCWSTR)lpMsgBuf, 0) + StringCchLenW(lpszMessage, 0) + 80; LPWSTR lpDisplayBuf = (LPWSTR)AllocMem(len * sizeof(WCHAR), HEAP_ZERO_MEMORY); if (lpDisplayBuf) { StringCchPrintf(lpDisplayBuf, len, L"Error: '%s' failed with error id %d:\n%s.\n", - lpszFunction, dwErrID, (LPCWSTR)lpMsgBuf); + lpszMessage, dwErrID, (LPCWSTR)lpMsgBuf); // center message box to main HWND focus = GetFocus(); @@ -197,7 +197,6 @@ typedef struct _infbox { bool bDisableCheckBox; } INFOBOXLNG, *LPINFOBOXLNG; - static INT_PTR CALLBACK _InfoBoxLngDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) { switch (umsg) @@ -221,6 +220,9 @@ static INT_PTR CALLBACK _InfoBoxLngDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, case MB_ICONERROR: // = MB_ICONSTOP, MB_ICONHAND SendDlgItemMessage(hwnd, IDC_INFOBOXICON, STM_SETICON, (WPARAM)Globals.hIconMsgError, 0); break; + case MB_ICONSHIELD: + SendDlgItemMessage(hwnd, IDC_INFOBOXICON, STM_SETICON, (WPARAM)Globals.hIconMsgShield, 0); + break; case MB_USERICON: SendDlgItemMessage(hwnd, IDC_INFOBOXICON, STM_SETICON, (WPARAM)Globals.hIcon48, 0); break; @@ -293,6 +295,7 @@ static INT_PTR CALLBACK _InfoBoxLngDlgProc(HWND hwnd, UINT umsg, WPARAM wParam, // InfoBoxLng() // // + INT_PTR InfoBoxLng(UINT uType, LPCWSTR lpstrSetting, UINT uidMsg, ...) { int const iMode = StrIsEmpty(lpstrSetting) ? 0 : IniFileGetInt(Globals.IniFile, Constants.SectionSuppressedMessages, lpstrSetting, 0); diff --git a/src/Dialogs.h b/src/Dialogs.h index a4702c5cf..7493147dd 100644 --- a/src/Dialogs.h +++ b/src/Dialogs.h @@ -51,7 +51,7 @@ void DialogAdminExe(HWND hwnd,bool); int MessageBoxLng(HWND hwnd, UINT uType, UINT uIdMsg, ...); INT_PTR InfoBoxLng(UINT uType, LPCWSTR lpstrSetting, UINT uidMessage, ...); -DWORD GetLastErrorToMsgBox(LPWSTR lpszFunction, DWORD dwErrID); +DWORD MsgBoxLastError(LPCWSTR lpszMessage, DWORD dwErrID); bool SetWindowTitle(HWND hwnd, UINT uIDAppName, bool, UINT uIDUntitled, LPCWSTR lpszFile, int iFormat, bool, UINT uIDReadOnly, bool, LPCWSTR lpszExcerpt); void SetAdditionalTitleInfo(LPCWSTR lpszAddTitleInfo); diff --git a/src/Helpers.c b/src/Helpers.c index 717dec9d5..18b76834f 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -28,6 +28,7 @@ #include "Encoding.h" #include "MuiLanguage.h" #include "Notepad3.h" +#include "Dialogs.h" #include "Config/Config.h" #include "Scintilla.h" @@ -212,26 +213,26 @@ void GetWinVersionString(LPWSTR szVersionStr, size_t cchVersionStr) { StringCchCopy(szVersionStr, cchVersionStr, L"OS Version: Windows "); - if (IsWin10()) { + if (IsWin10OrHigher()) { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Server 2016 " : L"10 "); } - else if (IsWin81()) { + else if (IsWin81OrHigher()) { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Server 2012 R2 " : L"8.1"); } - else if (IsWin8()) { + else if (IsWin8OrHigher()) { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Server 2012 " : L"8"); } - else if (IsWin71()) { + else if (IsWin71OrHigher()) { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Server 2008 R2 " : L"7 (SP1)"); } - else if (IsWin7()) { + else if (IsWin7OrHigher()) { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Server 2008 " : L"7"); } else { StringCchCat(szVersionStr, cchVersionStr, IsWinServer() ? L"Unkown Server " : L"?"); } - if (IsWin10()) { + if (IsWin10OrHigher()) { WCHAR win10ver[80] = { L'\0' }; if (s_OSversion.dwOSVersionInfoSize == 0) { _GetTrueWindowsVersion(); } DWORD const build = s_OSversion.dwBuildNumber; @@ -267,6 +268,55 @@ bool SetClipboardTextW(HWND hwnd, LPCWSTR pszTextW, size_t cchTextW) } +//============================================================================= +// +// ConvertIconToBitmap() +// +HBITMAP ConvertIconToBitmap(const HICON hIcon, const int cx, const int cy) +{ + const HDC hScreenDC = GetDC(NULL); + const HBITMAP hbmpTmp = CreateCompatibleBitmap(hScreenDC, cx, cy); + const HDC hMemDC = CreateCompatibleDC(hScreenDC); + const HBITMAP hOldBmp = SelectObject(hMemDC, hbmpTmp); + DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL); + SelectObject(hMemDC, hOldBmp); + + const HBITMAP hDibBmp = (HBITMAP)CopyImage((HANDLE)hbmpTmp, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION); + + DeleteObject(hbmpTmp); + DeleteDC(hMemDC); + ReleaseDC(NULL, hScreenDC); + + return hDibBmp; +} + + +//============================================================================= +// +// SetUACIcon() +// +void SetUACIcon(const HMENU hMenu, const UINT nItem) +{ + static bool bInitialized = false; + if (bInitialized) { return; } + + //const int cx = GetSystemMetrics(SM_CYMENU) - 4; + //const int cy = cx; + int const cx = GetSystemMetrics(SM_CXSMICON); + int const cy = GetSystemMetrics(SM_CYSMICON); + + if (Globals.hIconMsgShieldSmall) + { + MENUITEMINFO mii = { 0 }; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_BITMAP; + mii.hbmpItem = ConvertIconToBitmap(Globals.hIconMsgShieldSmall, cx, cy); + SetMenuItemInfo(hMenu, nItem, FALSE, &mii); + } + bInitialized = true; +} + + //============================================================================= // // GetCurrentDPI() @@ -275,7 +325,7 @@ DPI_T GetCurrentDPI(HWND hwnd) { DPI_T curDPI = { 0, 0 }; - if (IsWin10()) { + if (IsWin10OrHigher()) { HMODULE const hModule = GetModuleHandle(L"user32.dll"); if (hModule) { FARPROC const pfnGetDpiForWindow = GetProcAddress(hModule, "GetDpiForWindow"); @@ -285,7 +335,7 @@ DPI_T GetCurrentDPI(HWND hwnd) { } } - if ((curDPI.x == 0) && IsWin81()) { + if ((curDPI.x == 0) && IsWin81OrHigher()) { HMODULE hShcore = LoadLibrary(L"shcore.dll"); if (hShcore) { FARPROC const pfnGetDpiForMonitor = GetProcAddress(hShcore, "GetDpiForMonitor"); @@ -420,36 +470,67 @@ HRESULT PrivateSetCurrentProcessExplicitAppUserModelID(PCWSTR AppID) //============================================================================= // -// IsElevated() +// IsProcessElevated() // -bool IsElevated() { +// PURPOSE: The function gets the elevation information of the current +// process. It dictates whether the process is elevated or not. Token +// elevation is only available on Windows Vista and newer operating +// systems, thus IsProcessElevated throws a C++ exception if it is called +// on systems prior to Windows Vista. It is not appropriate to use this +// function to determine whether a process is run as administartor. +// +// RETURN VALUE: Returns TRUE if the process is elevated. Returns FALSE if +// it is not. +// +// NOTE: TOKEN_INFORMATION_CLASS provides TokenElevationType to check the +// elevation type (TokenElevationTypeDefault / TokenElevationTypeLimited / +// TokenElevationTypeFull) of the process. It is different from +// TokenElevation in that, when UAC is turned off, elevation type always +// returns TokenElevationTypeDefault even though the process is elevated +// (Integrity Level == High). In other words, it is not safe to say if the +// process is elevated based on elevation type. Instead, we should use +// TokenElevation. +// +bool IsProcessElevated() { + + // When the process is run on operating systems prior to Windows + // Vista, GetTokenInformation returns FALSE with the + // ERROR_INVALID_PARAMETER error code because TokenElevation is + // not supported on those operating systems. + if (!IsVistaOrHigher()) { return false; } bool bIsElevated = false; HANDLE hToken = NULL; + Globals.dwLastError = ERROR_SUCCESS; - if (!IsVista()) - return false; - - if (OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken)) { - - TOKEN_ELEVATION te; + if (OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken)) + { + TOKEN_ELEVATION elevationToken; DWORD expectedRetVal = sizeof(TOKEN_ELEVATION); DWORD dwReturnLength = 0; - if (GetTokenInformation(hToken,TokenElevation,&te,expectedRetVal,&dwReturnLength)) { - if (dwReturnLength == expectedRetVal) - bIsElevated = (bool)te.TokenIsElevated; + if (GetTokenInformation(hToken,TokenElevation,&elevationToken,expectedRetVal,&dwReturnLength)) + { + if (dwReturnLength == expectedRetVal) { + bIsElevated = elevationToken.TokenIsElevated; + } } - if (hToken) + if (hToken) { CloseHandle(hToken); + hToken = NULL; + } + } + else { + Globals.dwLastError = GetLastError(); + //GetLastErrorToMessageBox(L"IsProcessElevated()", Globals.dwLastError); } return bIsElevated; } - +#if 0 //============================================================================= // -// IsUserAdmin() +// IsUserInAdminGroup() // // Routine Description: This routine returns true if the caller's // process is a member of the Administrators local group. Caller is NOT @@ -460,7 +541,8 @@ bool IsElevated() { // true - Caller has Administrators local group. // false - Caller does not have Administrators local group. -- // -bool IsUserAdmin() + +bool IsUserInAdminGroup() { PSID AdminGroup; SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; @@ -473,6 +555,175 @@ bool IsUserAdmin() } return(bIsAdmin); } +#endif + +//============================================================================= +// +// IsUserInAdminGroup() +// +// PURPOSE: The function checks whether the primary access token of the +// process belongs to user account that is a member of the local +// Administrators group, even if it currently is not elevated. +// +// RETURN VALUE: Returns TRUE if the primary access token of the process +// belongs to user account that is a member of the local Administrators +// group. Returns FALSE if the token does not. +// +// +// +bool IsUserInAdminGroup() +{ + BOOL fInAdminGroup = FALSE; + HANDLE hToken = NULL; + HANDLE hTokenToCheck = NULL; + + Globals.dwLastError = ERROR_SUCCESS; + const WCHAR* pLastErrMsg = L""; + + do { + // Open the primary access token of the process for query and duplicate. + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"OpenProcessToken()"; + break; + } + + DWORD cbSize = 0; + + // Determine token type: limited, elevated, or default. + TOKEN_ELEVATION_TYPE elevType; + if (!GetTokenInformation(hToken, TokenElevationType, &elevType, sizeof(elevType), &cbSize)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"GetTokenInformation()"; + break; + } + + // If limited, get the linked elevated token for further check. + if (TokenElevationTypeLimited == elevType) + { + if (!GetTokenInformation(hToken, TokenLinkedToken, &hTokenToCheck, sizeof(hTokenToCheck), &cbSize)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"GetTokenInformation()"; + break; + } + } + + // CheckTokenMembership requires an impersonation token. If we just got a + // linked token, it already is an impersonation token. If we did not get + // a linked token, duplicate the original into an impersonation token for + // CheckTokenMembership. + if (!hTokenToCheck) + { + if (!DuplicateToken(hToken, SecurityIdentification, &hTokenToCheck)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"DuplicateToken()"; + break; + } + } + + // Create the SID corresponding to the Administrators group. + BYTE adminSID[SECURITY_MAX_SID_SIZE]; + cbSize = sizeof(adminSID); + if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, &cbSize)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"CreateWellKnownSid()"; + break; + } + + // Check if the token to be checked contains admin SID. + // http://msdn.microsoft.com/en-us/library/aa379596(VS.85).aspx: + // To determine whether a SID is enabled in a token, that is, whether it + // has the SE_GROUP_ENABLED attribute, call CheckTokenMembership. + if (!CheckTokenMembership(hTokenToCheck, &adminSID, &fInAdminGroup)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"CheckTokenMembership()"; + break; + } + + } while (false); // Centralized cleanup for all allocated resources. + + if (hToken) + { + CloseHandle(hToken); + hToken = NULL; + } + if (hTokenToCheck) + { + CloseHandle(hTokenToCheck); + hTokenToCheck = NULL; + } + + if (Globals.dwLastError != ERROR_SUCCESS) { + MsgBoxLastError(pLastErrMsg, Globals.dwLastError); + } + + return fInAdminGroup; +} + + +//============================================================================= +// +// IsRunAsAdmin() +// +// PURPOSE: The function checks whether the current process is run as +// administrator. In other words, it dictates whether the primary access +// token of the process belongs to user account that is a member of the +// local Administrators group and it is elevated. +// +// RETURN VALUE: Returns TRUE if the primary access token of the process +// belongs to user account that is a member of the local Administrators +// group and it is elevated. Returns FALSE if the token does not. +// +bool IsRunAsAdmin() +{ + BOOL fIsRunAsAdmin = FALSE; + PSID pAdministratorsGroup = NULL; + + Globals.dwLastError = ERROR_SUCCESS; + const WCHAR* pLastErrMsg = L""; + + do { + // Allocate and initialize a SID of the administrators group. + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + if (!AllocateAndInitializeSid( + &NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdministratorsGroup)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"AllocateAndInitializeSid()"; + break; + } + + // Determine whether the SID of administrators group is enabled in + // the primary access token of the process. + if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) + { + Globals.dwLastError = GetLastError(); + pLastErrMsg = L"CheckTokenMembership()"; + break; + } + + } while (false); // Centralized cleanup for all allocated resources. + + // Centralized cleanup for all allocated resources. + if (pAdministratorsGroup) + { + FreeSid(pAdministratorsGroup); + pAdministratorsGroup = NULL; + } + + return (bool)fIsRunAsAdmin; +} @@ -484,7 +735,7 @@ bool IsUserAdmin() //{ // FARPROC pfnSetWindowTheme; // -// if (IsVista()) { +// if (IsVistaOrHigher()) { // if (hLocalModUxTheme) { // pfnSetWindowTheme = GetProcAddress(hLocalModUxTheme,"SetWindowTheme"); // diff --git a/src/Helpers.h b/src/Helpers.h index bd7dc8576..e6a60bb2b 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -175,28 +175,28 @@ inline COLORREF GetBackgroundColor(HWND hwnd) { return GetBkColor(GetDC(hwnd)); // ---------------------------------------------------------------------------- //#define Is2k() (g_uWinVer >= 0x0500) -#define IsXP() IsWindowsXPOrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP version. -#define IsXP1() IsWindowsXPSP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 1 (SP1)version. -#define IsXP2() IsWindowsXPSP2OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 2 (SP2)version. -#define IsXP3() IsWindowsXPSP3OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 3 (SP3)version. +#define IsXPOrHigher() IsWindowsXPOrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP version. +#define IsXP1OrHigher() IsWindowsXPSP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 1 (SP1)version. +#define IsXP2OrHigher() IsWindowsXPSP2OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 2 (SP2)version. +#define IsXP3OrHigher() IsWindowsXPSP3OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows XP with Service Pack 3 (SP3)version. -#define IsVista() IsWindowsVistaOrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista version. -#define IsVista1() IsWindowsVistaSP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista with Service Pack 1 (SP1)version. -#define IsVista2() IsWindowsVistaSP2OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista with Service Pack 2 (SP2)version. +#define IsVistaOrHigher() IsWindowsVistaOrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista version. +#define IsVista1OrHigher() IsWindowsVistaSP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista with Service Pack 1 (SP1)version. +#define IsVista2OrHigher() IsWindowsVistaSP2OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows Vista with Service Pack 2 (SP2)version. -#define IsWin7() IsWindows7OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 7 version. -#define IsWin71() IsWindows7SP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 7 with Service Pack 1 (SP1)version. -#define IsWin8() IsWindows8OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 8 version. -#define IsWin81() IsWindows8Point1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 8.1 version. - // For Windows 10,IsWindows8Point1OrGreater returns false unless the application contains a manifest that includes - // a compatibility section that contains the GUIDs that designate Windows 8.1 and/or Windows 10. +#define IsWin7OrHigher() IsWindows7OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 7 version. +#define IsWin71OrHigher() IsWindows7SP1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 7 with Service Pack 1 (SP1)version. +#define IsWin8OrHigher() IsWindows8OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 8 version. +#define IsWin81OrHigher() IsWindows8Point1OrGreater() // Indicates if the current OS version matches,or is greater than,the Windows 8.1 version. + // For Windows 10,IsWindows8Point1OrGreater returns false unless the application contains a manifest that includes + // a compatibility section that contains the GUIDs that designate Windows 8.1 and/or Windows 10. -#define IsWin10() IsWindows10OrGreater() // Indicates if the current OS version matches, or is greater than, the Windows 10 version. - // For Windows 10,IsWindows10OrGreater returns false unless the application contains a manifest that includes - // a compatibility section that contains the GUID that designates Windows 10. +#define IsWin10OrHigher() IsWindows10OrGreater() // Indicates if the current OS version matches, or is greater than, the Windows 10 version. + // For Windows 10,IsWindows10OrGreater returns false unless the application contains a manifest that includes + // a compatibility section that contains the GUID that designates Windows 10. -#define IsWinServer() IsWindowsServer() // Indicates if the current OS is a Windows Server release. - // Applications that need to distinguish between server and client versions of Windows should call this function. +#define IsWinServer() IsWindowsServer() // Indicates if the current OS is a Windows Server release. + // Applications that need to distinguish between server and client versions of Windows should call this function. void GetWinVersionString(LPWSTR szVersionStr, size_t cchVersionStr); @@ -209,6 +209,8 @@ void GetWinVersionString(LPWSTR szVersionStr, size_t cchVersionStr); // ---------------------------------------------------------------------------- bool SetClipboardTextW(HWND hwnd, LPCWSTR pszTextW, size_t cchTextW); +HBITMAP ConvertIconToBitmap(const HICON hIcon, const int cx, const int cy); +void SetUACIcon(const HMENU hMenu, const UINT nItem); // ---------------------------------------------------------------------------- @@ -253,8 +255,9 @@ inline float GetBaseFontSize(HWND hwnd) { return ((IsFullHD(hwnd, -1, -1) < 0) ? // ---------------------------------------------------------------------------- HRESULT PrivateSetCurrentProcessExplicitAppUserModelID(PCWSTR AppID); -bool IsElevated(); -bool IsUserAdmin(); +bool IsProcessElevated(); +bool IsUserInAdminGroup(); +bool IsRunAsAdmin(); //bool SetExplorerTheme(HWND); @@ -277,13 +280,14 @@ inline bool IsButtonUnchecked(HWND hwnd, int iButtonID) { return (IsDlgButtonChe #define EnableCmd(hmenu,id,b) EnableMenuItem((hmenu),(id),(b)?MF_BYCOMMAND|MF_ENABLED:MF_BYCOMMAND|MF_GRAYED) #define CheckCmd(hmenu,id,b) CheckMenuItem((hmenu),(id),(b)?MF_BYCOMMAND|MF_CHECKED:MF_BYCOMMAND|MF_UNCHECKED) -#define EnableTool(htbar,id,b) SendMessage(htbar,TB_ENABLEBUTTON,id, MAKELONG(((b) ? 1 : 0), 0)) -#define CheckTool(htbar,id,b) SendMessage(htbar,TB_CHECKBUTTON,id, MAKELONG((b),0)) +#define EnableTool(htbar,id,b) SendMessage((htbar),TB_ENABLEBUTTON,(id), MAKELONG(((b) ? 1 : 0), 0)) +#define CheckTool(htbar,id,b) SendMessage((htbar),TB_CHECKBUTTON,(id), MAKELONG((b),0)) #define EnableCmdPos(hmenu,pos,b) EnableMenuItem((hmenu),(pos),(b)?MF_BYPOSITION|MF_ENABLED:MF_BYPOSITION|MF_GRAYED) #define CheckCmdPos(hmenu,pos,b) CheckMenuItem((hmenu),(pos),(b)?MF_BYPOSITION|MF_CHECKED:MF_BYPOSITION|MF_UNCHECKED) + bool GetKnownFolderPath(REFKNOWNFOLDERID, LPWSTR lpOutPath, size_t cchCount); void PathRelativeToApp(LPWSTR lpszSrc,LPWSTR lpszDest,int cchDest,bool,bool,bool); void PathAbsoluteFromApp(LPWSTR lpszSrc,LPWSTR lpszDest,int cchDest,bool); diff --git a/src/MuiLanguage.c b/src/MuiLanguage.c index b41d7e639..f18912393 100644 --- a/src/MuiLanguage.c +++ b/src/MuiLanguage.c @@ -241,13 +241,13 @@ LANGID LoadLanguageResources() WCHAR tchUserLangMultiStrg[LARGE_BUFFER] = { L'\0' }; if (!_LngStrToMultiLngStr(tchAvailLngs, tchUserLangMultiStrg, COUNTOF(tchUserLangMultiStrg))) { - GetLastErrorToMsgBox(L"_LngStrToMultiLngStr()", ERROR_MUI_INVALID_LOCALE_NAME); + MsgBoxLastError(L"Trying to load Language resource!", ERROR_MUI_INVALID_LOCALE_NAME); } DWORD langCount = 0; // using SetProcessPreferredUILanguages is recommended for new applications (esp. multi-threaded applications) if (!SetThreadPreferredUILanguages(MUI_LANGUAGE_NAME, tchUserLangMultiStrg, &langCount) || (langCount == 0)) { - GetLastErrorToMsgBox(L"SetProcessPreferredUILanguages()", 0); + MsgBoxLastError(L"Trying to set preferred Language!", ERROR_RESOURCE_LANG_NOT_FOUND); } // obtains access to the proper resource container @@ -266,7 +266,7 @@ LANGID LoadLanguageResources() } if (!_hLangResourceContainer) { // fallback to ENGLISH_US - //GetLastErrorToMsgBox(L"LoadMUILibrary", 0); + //MsgBoxLastError(L"LoadMUILibrary", 0); Globals.bPrefLngNotAvail = (languageID != MUI_LanguageDLLs[0].LangId); languageID = MUI_LanguageDLLs[0].LangId; _hLangResourceContainer = Globals.hInstance; diff --git a/src/Notepad3.c b/src/Notepad3.c index 1b24a2723..b5754adc4 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -606,6 +606,9 @@ static void _SetSaveNeededFlag(const bool setSaveNeeded) PostWMCommand(Globals.hwndDlgFindReplace, IDC_DOC_MODIFIED); } } + else { + Encoding_HasChanged(Encoding_Current(CPI_GET)); + } } //============================================================================== @@ -625,10 +628,11 @@ static void _InitGlobals() Globals.pFileMRU = NULL; Globals.pMRUfind = NULL; Globals.pMRUreplace = NULL; - Globals.CallTipType = CT_NONE; Globals.uConsoleCodePage = 0; Globals.iAvailLngCount = 1; + Globals.iPrefLANGID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); Globals.iWrapCol = 0; + Globals.CallTipType = CT_NONE; Globals.flagPosParam = false; Globals.flagWindowPos = 0; @@ -660,7 +664,7 @@ static void _InitGlobals() Flags.RelativeFileMRU = DefaultFlags.RelativeFileMRU = true; Flags.PortableMyDocs = DefaultFlags.PortableMyDocs = Flags.RelativeFileMRU; Flags.NoFadeHidden = DefaultFlags.NoFadeHidden = false; - Flags.ToolbarLook = DefaultFlags.ToolbarLook = IsXP() ? 1 : 2; + Flags.ToolbarLook = DefaultFlags.ToolbarLook = IsXPOrHigher() ? 1 : 2; Flags.SimpleIndentGuides = DefaultFlags.SimpleIndentGuides = false; Flags.NoHTMLGuess =DefaultFlags.NoHTMLGuess = false; Flags.NoCGIGuess = DefaultFlags.NoCGIGuess = false; @@ -812,13 +816,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); // check if running at least on Windows 7 - if (!IsWin7()) { - GetLastErrorToMsgBox(L"WinMain", ERROR_OLD_WIN_VERSION); + if (!IsWin7OrHigher()) { + MsgBoxLastError(L"Application Initialization", ERROR_OLD_WIN_VERSION); return 1; // exit } // Check if running with elevated privileges - s_bIsElevated = IsUserAdmin() || IsElevated(); + s_bIsElevated = IsUserInAdminGroup() || IsProcessElevated() || IsRunAsAdmin(); // Default Encodings (may already be used for command line parsing) Encoding_InitDefaults(); @@ -905,12 +909,15 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, if (!Globals.hIconMsgQuest) { LoadIconWithScaleDown(NULL, IDI_QUESTION, cxl, cyl, &(Globals.hIconMsgQuest)); } + if (!Globals.hIconMsgShieldSmall) { + LoadIconWithScaleDown(NULL, IDI_SHIELD, cxs, cys, &(Globals.hIconMsgShieldSmall)); + } if (!Globals.hIconMsgShield) { LoadIconWithScaleDown(NULL, IDI_SHIELD, cxl, cyl, &(Globals.hIconMsgShield)); } - if (!Globals.hIconMsgWinLogo) { - LoadIconWithScaleDown(NULL, IDI_SHIELD, cxl, cyl, &(Globals.hIconMsgWinLogo)); - } + //if (!Globals.hIconMsgWinLogo) { + // LoadIconWithScaleDown(NULL, IDI_SHIELD, cxl, cyl, &(Globals.hIconMsgWinLogo)); + //} // Command Line Help Dialog if (s_flagDisplayHelp) { @@ -923,7 +930,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, Globals.hMainMenu = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_MAINMENU)); if (!Globals.hMainMenu) { - GetLastErrorToMsgBox(L"LoadMenu()", 0); + MsgBoxLastError(L"LoadMenu()", 0); _CleanUpResources(NULL, false); return 1; } @@ -1796,7 +1803,7 @@ static void _SetWrapVisualFlags(HWND hwndEditCtrl) // static void _InitializeSciEditCtrl(HWND hwndEditCtrl) { - if (IsVista()) { + if (IsVistaOrHigher()) { // Current platforms perform window buffering so it is almost always better for this option to be turned off. // There are some older platforms and unusual modes where buffering may still be useful - so keep it ON //~SciCall_SetBufferedDraw(true); // default is true @@ -2037,7 +2044,7 @@ LRESULT MsgCreate(HWND hwnd, WPARAM wParam,LPARAM lParam) SetWindowLongPtr(Globals.hwndEdit,GWL_EXSTYLE,GetWindowLongPtr(Globals.hwndEdit,GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE); SetWindowPos(Globals.hwndEdit,NULL,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED); - if (IsVista()) { + if (IsVistaOrHigher()) { s_cxEditFrame = 0; s_cyEditFrame = 0; } @@ -2381,10 +2388,10 @@ void CreateBars(HWND hwnd, HINSTANCE hInstance) if (Flags.ToolbarLook == 1) { fProcessed = BitmapAlphaBlend(hbmpCopy, GetSysColor(COLOR_3DFACE), 0x60); } - else if (Flags.ToolbarLook == 2 || (!IsXP() && Flags.ToolbarLook == 0)) { + else if (Flags.ToolbarLook == 2 || (!IsXPOrHigher() && Flags.ToolbarLook == 0)) { fProcessed = BitmapGrayScale(hbmpCopy); } - if (fProcessed && !IsXP()) { + if (fProcessed && !IsXPOrHigher()) { BitmapMergeAlpha(hbmpCopy, GetSysColor(COLOR_3DFACE)); } if (fProcessed) { @@ -2619,7 +2626,7 @@ LRESULT MsgThemeChanged(HWND hwnd, WPARAM wParam ,LPARAM lParam) SetWindowLongPtr(Globals.hwndEdit,GWL_EXSTYLE,GetWindowLongPtr(Globals.hwndEdit,GWL_EXSTYLE) & ~WS_EX_CLIENTEDGE); SetWindowPos(Globals.hwndEdit,NULL,0,0,0,0,SWP_NOZORDER|SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE); - if (IsVista()) { + if (IsVistaOrHigher()) { s_cxEditFrame = 0; s_cyEditFrame = 0; } @@ -3168,7 +3175,10 @@ LRESULT MsgInitMenu(HWND hwnd, WPARAM wParam, LPARAM lParam) EnableCmd(hmenu, CMD_RECODEGB18030, cf); EnableCmd(hmenu, IDM_FILE_LAUNCH, cf); - EnableCmd(hmenu,IDM_FILE_LAUNCH_ELEVATED, !s_bIsElevated); + SetUACIcon(hmenu, IDM_FILE_LAUNCH_ELEVATED); + CheckCmd(hmenu, IDM_FILE_LAUNCH_ELEVATED, s_bIsElevated); + EnableCmd(hmenu, IDM_FILE_LAUNCH_ELEVATED, !s_bIsElevated); + EnableCmd(hmenu,IDM_FILE_LAUNCH,cf); EnableCmd(hmenu,IDM_FILE_PROPERTIES,cf); EnableCmd(hmenu,IDM_FILE_CREATELINK,cf); @@ -3542,7 +3552,7 @@ static void _DynamicLanguageMenuCmd(int cmd) Globals.iPrefLANGID = LoadLanguageResources(); Globals.hMainMenu = LoadMenu(Globals.hLngResContainer, MAKEINTRESOURCE(IDR_MUI_MAINMENU)); if (!Globals.hMainMenu) { - GetLastErrorToMsgBox(L"LoadMenu()", 0); + MsgBoxLastError(L"LoadMenu()", 0); CloseApplication(); return; } @@ -3752,7 +3762,8 @@ LRESULT MsgCommand(HWND hwnd, UINT umsg, WPARAM wParam, LPARAM lParam) fioStatus.iEncoding = Encoding_Current(CPI_GET); fioStatus.iEOLMode = SciCall_GetEOLMode(); - if (DoElevatedRelaunch(&fioStatus, false)) { + if (DoElevatedRelaunch(&fioStatus, false)) + { CloseApplication(); } else { @@ -7787,7 +7798,7 @@ void ParseCommandLine() lp1 + CSTRLEN(RELAUNCH_ELEVATED_BUF_ARG), len - CSTRLEN(RELAUNCH_ELEVATED_BUF_ARG)); TrimSpcW(s_wchTmpFilePath); NormalizePathEx(s_wchTmpFilePath, COUNTOF(s_wchTmpFilePath), true, s_flagSearchPathIfRelative); - s_bIsElevated = s_IsThisAnElevatedRelaunch = true; + s_bIsElevated = s_IsThisAnElevatedRelaunch = IsProcessElevated(); } else { @@ -9564,7 +9575,7 @@ bool FileLoad(bool bDontSave, bool bNew, bool bReload, Style_SetDefaultLexer(Globals.hwndEdit); s_bFileReadOnly = false; - _SetSaveNeededFlag(false); + SciCall_SetSavePoint(); UpdateAllBars(false); @@ -9960,7 +9971,7 @@ bool DoElevatedRelaunch(EditFileIOStatus* pFioStatus, bool bAutoSaveOnRelaunch) if (RelaunchElevated(szArguments)) { // set no change and quit SciCall_SetSavePoint(); - _SetSaveNeededFlag(false); + //_SetSaveNeededFlag(false); } else { Globals.dwLastError = GetLastError(); @@ -10118,7 +10129,7 @@ bool FileSave(bool bSaveAlways, bool bAsk, bool bSaveAs, bool bSaveCopy, bool bP SHAddToRecentDocs(SHARD_PATHW, Globals.CurrentFile); } - _SetSaveNeededFlag(false); + SciCall_SetSavePoint(); // Install watching of the current file if (bSaveAs && Settings.ResetFileWatching) { @@ -10134,7 +10145,7 @@ bool FileSave(bool bSaveAlways, bool bAsk, bool bSaveAs, bool bSaveCopy, bool bP { if (!s_bIsElevated && (Globals.dwLastError == ERROR_ACCESS_DENIED)) { - INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONWARNING, NULL, IDS_MUI_ERR_ACCESSDENIED, PathFindFileName(Globals.CurrentFile)); + INT_PTR const answer = InfoBoxLng(MB_YESNO | MB_ICONSHIELD, NULL, IDS_MUI_ERR_ACCESSDENIED, PathFindFileName(Globals.CurrentFile)); if ((IDOK == answer) || (IDYES == answer)) { if (DoElevatedRelaunch(&fioStatus, true)) { @@ -10542,12 +10553,13 @@ bool RelaunchMultiInst() { // bool RelaunchElevated(LPWSTR lpNewCmdLnArgs) { - if (!IsVista() || - !s_flagDoRelaunchElevated || - s_bIsElevated || s_IsThisAnElevatedRelaunch || - s_flagDisplayHelp) + if (!IsVistaOrHigher() || + !s_flagDoRelaunchElevated || + s_bIsElevated || + s_IsThisAnElevatedRelaunch || + s_flagDisplayHelp) { - return false; + return false; } STARTUPINFO si; diff --git a/src/TypeDefs.h b/src/TypeDefs.h index 7a36fb0c8..032960903 100644 --- a/src/TypeDefs.h +++ b/src/TypeDefs.h @@ -155,6 +155,8 @@ typedef enum { #define STATUSBAR_SECTION_WIDTH_SPECS L"30 20 20 20 20 20 0 0 0 0 0 0 20 20 20" #define STAUSBAR_RIGHT_MARGIN 20 +#define MB_ICONSHIELD 0x000000B0L + // -------------------------------------------------------------------------- typedef enum { CT_NONE = 0, CT_ZOOM, CT_ZEROLEN_MATCH, CT_ENC_INFO, CT_DWELL } CALLTIPTYPE; @@ -305,7 +307,8 @@ typedef struct _globals_t HICON hIconMsgError; HICON hIconMsgQuest; HICON hIconMsgShield; - HICON hIconMsgWinLogo; + HICON hIconMsgShieldSmall; + //HICON hIconMsgWinLogo; HWND hwndDlgFindReplace; HWND hwndDlgCustomizeSchemes; int iDefaultCharSet; diff --git a/src/VersionEx.h b/src/VersionEx.h index 13aa563e4..02ac50012 100644 --- a/src/VersionEx.h +++ b/src/VersionEx.h @@ -8,8 +8,8 @@ #define SAPPNAME "Notepad3" #define VERSION_MAJOR 5 #define VERSION_MINOR 19 -#define VERSION_REV 1122 -#define VERSION_BUILD 2685 +#define VERSION_REV 1123 +#define VERSION_BUILD 2686 #define SCINTILLA_VER 421 #define ONIGURUMA_REGEX_VER 6.9.4 #define UCHARDET_VER 2018.09.27