mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
JetBrains products updater: invoke UAC elevation if needed (IDEA-52571)
This commit is contained in:
Binary file not shown.
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <windows.h>
|
||||
@@ -23,53 +23,168 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const wchar_t* INSTALL_PARAM = L"install";
|
||||
static const wchar_t* SKIP_ELEVATION_PARAM = L"--skip-uac-elevation--";
|
||||
|
||||
|
||||
bool isWritable(wchar_t* path)
|
||||
{
|
||||
wprintf(L"Trying to create temporary file in\"%s\"\n", path);
|
||||
wchar_t fileName[32768] = L"";
|
||||
wcscat_s(fileName, path);
|
||||
wcscat_s(fileName, L"\\.jetbrains-uac-check");
|
||||
HANDLE file = CreateFile(fileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
if (error == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
// looks like we need to request elevation
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// there's no need to request elevaion since patcher will most likely fail anyway
|
||||
wprintf(L"Unexpected error when creating temp file: %d\n", error);
|
||||
fflush(stdout);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(file);
|
||||
DeleteFile(fileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void appendArgument(wchar_t result[], wchar_t argument[])
|
||||
{
|
||||
bool needsQuoting = wcschr(argument, L' ') != NULL;
|
||||
if (needsQuoting)
|
||||
{
|
||||
wcscat_s(result, 32768, L"\"");
|
||||
}
|
||||
wcscat_s(result, 32768, argument);
|
||||
if (needsQuoting)
|
||||
{
|
||||
wcscat_s(result, 32768, L"\"");
|
||||
}
|
||||
wcscat_s(result, 32768, L" ");
|
||||
}
|
||||
|
||||
bool getElevationPath(int argc, _TCHAR* argv[], wchar_t result[])
|
||||
{
|
||||
int start = -1;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (wcscmp(argv[i], SKIP_ELEVATION_PARAM) == 0)
|
||||
{
|
||||
wprintf(L"Elevation suppressed\n");
|
||||
fflush(stdout);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wcscmp(argv[i], INSTALL_PARAM) == 0)
|
||||
{
|
||||
start = i;
|
||||
}
|
||||
else if (start >= 0)
|
||||
{
|
||||
if (i > start + 1)
|
||||
{
|
||||
wcscat_s(result, 32768, L" ");
|
||||
}
|
||||
wcscat_s(result, 32768, argv[i]);
|
||||
}
|
||||
}
|
||||
return start >= 0;
|
||||
}
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
STARTUPINFO startupInfo = {0};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInformation = {0};
|
||||
|
||||
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
wchar_t commandLine[32768] = L"";
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
wcscat_s(commandLine, L"\"");
|
||||
wcscat_s(commandLine, argv[i]);
|
||||
wcscat_s(commandLine, L"\" ");
|
||||
}
|
||||
|
||||
wprintf(L"Creating new process: %s\n", commandLine);
|
||||
fflush(stdout);
|
||||
|
||||
if (!CreateProcess(
|
||||
NULL, /*LPCTSTR lpApplicationName*/
|
||||
commandLine,/* LPTSTR lpCommandLine*/
|
||||
NULL, /*LPSECURITY_ATTRIBUTES lpProcessAttributes*/
|
||||
NULL, /*LPSECURITY_ATTRIBUTES lpThreadAttributes*/
|
||||
TRUE, /*BOOL bInheritHandles,*/
|
||||
0, /*DWORD dwCreationFlags*/
|
||||
NULL, /*LPVOID lpEnvironment*/
|
||||
NULL, /*LPCTSTR lpCurrentDirectory*/
|
||||
&startupInfo, /*LPSTARTUPINFO lpStartupInfo*/
|
||||
&processInformation /*LPPROCESS_INFORMATION lpProcessInformation*/))
|
||||
wchar_t elevationPath[32768] = L"";
|
||||
HANDLE processHandle = NULL;
|
||||
if (getElevationPath(argc, argv, elevationPath) && !isWritable(elevationPath))
|
||||
{
|
||||
wchar_t paramsLine[32768] = L"";
|
||||
wcscat_s(paramsLine, SKIP_ELEVATION_PARAM);
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
wcscat_s(paramsLine, L" ");
|
||||
appendArgument(paramsLine, argv[i]);
|
||||
}
|
||||
|
||||
wprintf(L"Creating elevated process: %s %s\n", argv[0], paramsLine);
|
||||
fflush(stdout);
|
||||
|
||||
SHELLEXECUTEINFO shExecInfo;
|
||||
shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
|
||||
shExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
shExecInfo.hwnd = NULL;
|
||||
shExecInfo.lpVerb = L"runas";
|
||||
shExecInfo.lpFile = argv[0];
|
||||
shExecInfo.lpParameters = paramsLine;
|
||||
shExecInfo.lpDirectory = NULL;
|
||||
shExecInfo.nShow = SW_HIDE;
|
||||
shExecInfo.hInstApp = NULL;
|
||||
|
||||
if (ShellExecuteEx(&shExecInfo) == FALSE)
|
||||
{
|
||||
wprintf(L"ShellExecuteEx() failed with error code %d\n", GetLastError());
|
||||
fflush(stdout);
|
||||
return -1;
|
||||
}
|
||||
processHandle = shExecInfo.hProcess;
|
||||
}
|
||||
else
|
||||
{
|
||||
STARTUPINFO startupInfo = {0};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInformation = {0};
|
||||
|
||||
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
wchar_t commandLine[32768] = L"";
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (wcscmp(argv[i], SKIP_ELEVATION_PARAM) != 0)
|
||||
{
|
||||
// add only original parameters
|
||||
appendArgument(commandLine, argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
wprintf(L"Creating new process: %s\n", commandLine);
|
||||
fflush(stdout);
|
||||
|
||||
if (!CreateProcess(
|
||||
NULL, /*LPCTSTR lpApplicationName*/
|
||||
commandLine,/* LPTSTR lpCommandLine*/
|
||||
NULL, /*LPSECURITY_ATTRIBUTES lpProcessAttributes*/
|
||||
NULL, /*LPSECURITY_ATTRIBUTES lpThreadAttributes*/
|
||||
TRUE, /*BOOL bInheritHandles,*/
|
||||
0, /*DWORD dwCreationFlags*/
|
||||
NULL, /*LPVOID lpEnvironment*/
|
||||
NULL, /*LPCTSTR lpCurrentDirectory*/
|
||||
&startupInfo, /*LPSTARTUPINFO lpStartupInfo*/
|
||||
&processInformation /*LPPROCESS_INFORMATION lpProcessInformation*/))
|
||||
{
|
||||
wprintf(L"Cannot create process: %d\n", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
processHandle = processInformation.hProcess;
|
||||
}
|
||||
|
||||
WaitForSingleObject(processInformation.hProcess, INFINITE);
|
||||
WaitForSingleObject(processHandle, INFINITE);
|
||||
|
||||
DWORD exitCode = 0;
|
||||
if (!GetExitCodeProcess(processInformation.hProcess, &exitCode))
|
||||
if (!GetExitCodeProcess(processHandle, &exitCode))
|
||||
{
|
||||
wprintf(L"Cannot retrieve process exit code: %d\n", GetLastError());
|
||||
exitCode = -1;
|
||||
}
|
||||
CloseHandle(processInformation.hProcess);
|
||||
CloseHandle(processHandle);
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
#include "windows.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
@@ -27,18 +27,18 @@ LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"#include ""windows.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
@@ -70,12 +70,12 @@ BEGIN
|
||||
BLOCK "041904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "JetBrains, Inc."
|
||||
VALUE "FileDescription", "IntelliJ IDEA Automatic Update"
|
||||
VALUE "FileDescription", "JetBrains Updater Launcher"
|
||||
VALUE "FileVersion", "1, 0, 0, 1"
|
||||
VALUE "InternalName", "fsnotifier"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2009 JetBrains, Inc."
|
||||
VALUE "InternalName", "vistalauncher"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2009-2011 JetBrains, Inc."
|
||||
VALUE "OriginalFilename", "vistalauncher.exe"
|
||||
VALUE "ProductName", "IntelliJ IDEA"
|
||||
VALUE "ProductName", "JetBrains Updater Launcher"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1"
|
||||
END
|
||||
END
|
||||
|
||||
Reference in New Issue
Block a user