diff --git a/base/applications/CMakeLists.txt b/base/applications/CMakeLists.txt index 74ddde5815c..082b2121b35 100644 --- a/base/applications/CMakeLists.txt +++ b/base/applications/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(network) add_subdirectory(notepad) add_subdirectory(osk) add_subdirectory(rapps) +add_subdirectory(rapps_com) add_subdirectory(regedit) add_subdirectory(regedt32) add_subdirectory(sc) diff --git a/base/applications/rapps/CMakeLists.txt b/base/applications/rapps/CMakeLists.txt index cb559b5509d..4da7397229f 100644 --- a/base/applications/rapps/CMakeLists.txt +++ b/base/applications/rapps/CMakeLists.txt @@ -41,7 +41,7 @@ add_definitions( file(GLOB_RECURSE rapps_rc_deps res/*.*) add_rc_deps(rapps.rc ${rapps_rc_deps}) add_executable(rapps ${SOURCE} rapps.rc) -set_module_type(rapps win32cui UNICODE) +set_module_type(rapps win32gui UNICODE) target_link_libraries(rapps conutils ${PSEH_LIB} uuid wine cpprt atl_classes) add_importlibs(rapps advapi32 comctl32 gdi32 wininet user32 shell32 shlwapi ole32 setupapi gdiplus msvcrt kernel32 ntdll) add_pch(rapps include/rapps.h SOURCE) diff --git a/base/applications/rapps/appview.cpp b/base/applications/rapps/appview.cpp index 0bdcc67cdbc..947df04d0bd 100644 --- a/base/applications/rapps/appview.cpp +++ b/base/applications/rapps/appview.cpp @@ -58,8 +58,14 @@ HIMAGELIST CMainToolbar::InitImageList() return hImageList; } -CMainToolbar::CMainToolbar() : m_iToolbarHeight(24) +CMainToolbar::CMainToolbar() + : m_iToolbarHeight(24) + , m_dButtonsWidthMax(0) { + memset(szInstallBtn, 0, sizeof(szInstallBtn)); + memset(szUninstallBtn, 0, sizeof(szUninstallBtn)); + memset(szModifyBtn, 0, sizeof(szModifyBtn)); + memset(szSelectAll, 0, sizeof(szSelectAll)); } VOID CMainToolbar::OnGetDispInfo(LPTOOLTIPTEXT lpttt) diff --git a/base/applications/rapps/available.cpp b/base/applications/rapps/available.cpp index 6de168024dd..fa266d7f5e1 100644 --- a/base/applications/rapps/available.cpp +++ b/base/applications/rapps/available.cpp @@ -7,15 +7,13 @@ * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) * Copyright 2020 He Yang (1160386205@qq.com) */ + #include "rapps.h" #include "available.h" #include "misc.h" #include "dialogs.h" -#include -#include -#include // CAvailableApplicationInfo CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam, AvailableStrings& AvlbStrings) diff --git a/base/applications/rapps/include/unattended.h b/base/applications/rapps/include/unattended.h index 301f54ab9e7..83aa2e06b9f 100644 --- a/base/applications/rapps/include/unattended.h +++ b/base/applications/rapps/include/unattended.h @@ -5,6 +5,8 @@ #define CMD_KEY_FIND L"FIND" #define CMD_KEY_INFO L"INFO" #define CMD_KEY_HELP L"?" +#define CMD_KEY_HELP_ALT L"HELP" + const WCHAR UsageString[] = L"RAPPS \ [/" CMD_KEY_HELP L"] \ diff --git a/base/applications/rapps/unattended.cpp b/base/applications/rapps/unattended.cpp index f1589a3b544..885c604fd5e 100644 --- a/base/applications/rapps/unattended.cpp +++ b/base/applications/rapps/unattended.cpp @@ -20,28 +20,36 @@ BOOL MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth) { if (argvOption[0] == FirstCharList[i]) { - if (StrCmpIW(argvOption + 1, szOptToMacth) == 0) - { - return TRUE; - } - else - { - return FALSE; - } + return StrCmpIW(argvOption + 1, szOptToMacth) == 0; } } return FALSE; } +void InitRappsConsole() +{ + // First, try to attach to our parent's console + if (!AttachConsole(ATTACH_PARENT_PROCESS)) + { + // Did we already have a console? + if (GetLastError() != ERROR_ACCESS_DENIED) + { + // No, try to open a new one + AllocConsole(); + } + } + ConInitStdStreams(); // Initialize the Console Standard Streams +} + + BOOL HandleInstallCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) { if (argcLeft == 0) { - ConInitStdStreams(); // Initialize the Console Standard Streams + InitRappsConsole(); ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PACKAGE_NAME, szCommand); return FALSE; } - FreeConsole(); ATL::CSimpleArray PkgNameList; @@ -70,11 +78,10 @@ BOOL HandleSetupCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) { if (argcLeft != 1) { - ConInitStdStreams(); // Initialize the Console Standard Streams + InitRappsConsole(); ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_FILE_NAME, szCommand); return FALSE; } - FreeConsole(); ATL::CSimpleArray PkgNameList; HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL); @@ -218,20 +225,14 @@ BOOL HandleInfoCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) return TRUE; } -BOOL HandleHelpCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) +VOID PrintHelpCommand() { - if (argcLeft != 0) - { - return FALSE; - } - ConPrintf(StdOut, L"\n"); ConResPuts(StdOut, IDS_APPTITLE); ConPrintf(StdOut, L"\n\n"); ConResPuts(StdOut, IDS_CMD_USAGE); ConPrintf(StdOut, L"%ls\n", UsageString); - return TRUE; } BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) @@ -246,10 +247,6 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) if (argc == 1) // RAPPS is launched without options { - // Close the console, and open MainWindow - FreeConsole(); - - // Check for if rapps MainWindow is already launched in another process HANDLE hMutex; @@ -275,7 +272,8 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) return TRUE; } - else if (MatchCmdOption(argv[1], CMD_KEY_INSTALL)) + + if (MatchCmdOption(argv[1], CMD_KEY_INSTALL)) { return HandleInstallCommand(argv[1], argc - 2, argv + 2); } @@ -283,9 +281,8 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) { return HandleSetupCommand(argv[1], argc - 2, argv + 2); } - - ConInitStdStreams(); // Initialize the Console Standard Streams + InitRappsConsole(); if (MatchCmdOption(argv[1], CMD_KEY_FIND)) { @@ -295,14 +292,16 @@ BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) { return HandleInfoCommand(argv[1], argc - 2, argv + 2); } - else if (MatchCmdOption(argv[1], CMD_KEY_HELP)) + else if (MatchCmdOption(argv[1], CMD_KEY_HELP) || MatchCmdOption(argv[1], CMD_KEY_HELP_ALT)) { - return HandleHelpCommand(argv[1], argc - 2, argv + 2); + PrintHelpCommand(); + return TRUE; } else { // unrecognized/invalid options ConResPuts(StdOut, IDS_CMD_INVALID_OPTION); + PrintHelpCommand(); return FALSE; } } diff --git a/base/applications/rapps/winmain.cpp b/base/applications/rapps/winmain.cpp index 9d36df598eb..c8604ca6c9e 100644 --- a/base/applications/rapps/winmain.cpp +++ b/base/applications/rapps/winmain.cpp @@ -7,15 +7,10 @@ * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) */ #include "rapps.h" - #include "unattended.h" - #include "winmain.h" - #include - #include - #include LPCWSTR szWindowClass = L"ROSAPPMGR"; @@ -63,11 +58,11 @@ VOID InitializeGDIPlus(BOOL bInitialize) } } -int wmain(int argc, wchar_t *argv[]) +INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nShowCmd) { BOOL bIsFirstLaunch; - InitializeAtlModule(GetModuleHandle(NULL), TRUE); + InitializeAtlModule(hInstance, TRUE); InitializeGDIPlus(TRUE); if (GetUserDefaultUILanguage() == MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT)) @@ -75,7 +70,7 @@ int wmain(int argc, wchar_t *argv[]) SetProcessDefaultLayout(LAYOUT_RTL); } - hInst = GetModuleHandle(NULL); + hInst = hInstance; bIsFirstLaunch = !LoadSettings(&SettingsInfo); if (bIsFirstLaunch) diff --git a/base/applications/rapps_com/CMakeLists.txt b/base/applications/rapps_com/CMakeLists.txt new file mode 100644 index 00000000000..4e2ff5599cd --- /dev/null +++ b/base/applications/rapps_com/CMakeLists.txt @@ -0,0 +1,7 @@ +project(rapps) + +add_executable(rapps.com main.c rapps.rc) +set_module_type(rapps.com win32cui UNICODE) +set_target_properties(rapps.com PROPERTIES SUFFIX "") +add_importlibs(rapps.com msvcrt kernel32 ntdll) +add_cd_file(TARGET rapps.com DESTINATION reactos/system32 FOR all) diff --git a/base/applications/rapps_com/main.c b/base/applications/rapps_com/main.c new file mode 100644 index 00000000000..fdb583f053d --- /dev/null +++ b/base/applications/rapps_com/main.c @@ -0,0 +1,73 @@ +/* + * PROJECT: ReactOS Applications Manager Command-Line Launcher (rapps.com) + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Allow explorer / cmd to wait for rapps.exe when passing commandline arguments + * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org) + */ + +#include +#include +#include + + +int run_rapps(LPWSTR cmdline) +{ + STARTUPINFOW si = { sizeof(si) }; + PROCESS_INFORMATION pi = { 0 }; + SetLastError(0); + if (!CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + fprintf(stderr, "Unable to create rapps.exe process...\n"); + return -1; + } + CloseHandle(pi.hThread); + WaitForSingleObject(pi.hProcess, INFINITE); + DWORD dwExit; + GetExitCodeProcess(pi.hProcess, &dwExit); + CloseHandle(pi.hProcess); + return dwExit; +} + +int wmain(int argc, wchar_t* argv[]) +{ + WCHAR RappsExe[MAX_PATH] = { 0 }; + + GetModuleFileNameW(NULL, RappsExe, ARRAYSIZE(RappsExe)); + size_t arglen = wcslen(RappsExe); + if (arglen > 4 && !wcsicmp(RappsExe + arglen - 4, L".com")) + { + wcscpy(RappsExe + arglen - 4, L".exe"); + } + else + { + fprintf(stderr, "Unable to build rapps.exe path...\n"); + return - 1; + } + + arglen += (1 + 2); // nullterminator + 2 quotes + + for (int n = 1; n < argc; ++n) + { + arglen += wcslen(argv[n]); + arglen += 3; // Surrounding quotes + space + } + + wchar_t* cmdline = LocalAlloc(LMEM_ZEROINIT, arglen * sizeof(WCHAR)); + if (cmdline) + { + wchar_t* ptr = cmdline; + size_t cchRemaining = arglen; + + StringCchPrintfExW(ptr, cchRemaining, &ptr, &cchRemaining, 0, L"\"%s\"", RappsExe); + + for (int n = 1; n < argc; ++n) + { + StringCchPrintfExW(ptr, cchRemaining, &ptr, &cchRemaining, 0, L" \"%s\"", argv[n]); + } + } + + int iRet = run_rapps(cmdline); + if (cmdline) + LocalFree(cmdline); + return iRet; +} diff --git a/base/applications/rapps_com/main.ico b/base/applications/rapps_com/main.ico new file mode 100644 index 00000000000..27f227da3b1 Binary files /dev/null and b/base/applications/rapps_com/main.ico differ diff --git a/base/applications/rapps_com/rapps.rc b/base/applications/rapps_com/rapps.rc new file mode 100644 index 00000000000..9282aae2b8c --- /dev/null +++ b/base/applications/rapps_com/rapps.rc @@ -0,0 +1,5 @@ +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Applications Manager console shim" +#define REACTOS_STR_INTERNAL_NAME "rapps" +#define REACTOS_STR_ORIGINAL_FILENAME "rapps.com" + +#include