1 /* 2 * PROJECT: ReactOS Applications Manager 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Functions to parse command-line flags and process them 5 * COPYRIGHT: Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) 6 * Copyright 2020 He Yang (1160386205@qq.com) 7 */ 8 9 #include "gui.h" 10 #include "unattended.h" 11 #include <setupapi.h> 12 #include <conutils.h> 13 14 static BOOL 15 MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth) 16 { 17 WCHAR FirstCharList[] = {L'-', L'/'}; 18 19 for (UINT i = 0; i < _countof(FirstCharList); i++) 20 { 21 if (argvOption[0] == FirstCharList[i]) 22 { 23 return StrCmpIW(argvOption + 1, szOptToMacth) == 0; 24 } 25 } 26 return FALSE; 27 } 28 29 static void 30 InitRappsConsole() 31 { 32 // First, try to attach to our parent's console 33 if (!AttachConsole(ATTACH_PARENT_PROCESS)) 34 { 35 // Did we already have a console? 36 if (GetLastError() != ERROR_ACCESS_DENIED) 37 { 38 // No, try to open a new one 39 AllocConsole(); 40 } 41 } 42 ConInitStdStreams(); // Initialize the Console Standard Streams 43 } 44 45 static BOOL 46 HandleInstallCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 47 { 48 if (argcLeft < 1) 49 { 50 InitRappsConsole(); 51 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PACKAGE_NAME, szCommand); 52 return FALSE; 53 } 54 55 CAtlList<CAppInfo *> Applications; 56 for (int i = 0; i < argcLeft; i++) 57 { 58 LPCWSTR PackageName = argvLeft[i]; 59 CAppInfo *AppInfo = db->FindByPackageName(PackageName); 60 if (AppInfo) 61 { 62 Applications.AddTail(AppInfo); 63 } 64 } 65 66 return DownloadListOfApplications(Applications, TRUE); 67 } 68 69 static BOOL 70 HandleSetupCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 71 { 72 if (argcLeft != 1) 73 { 74 InitRappsConsole(); 75 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_FILE_NAME, szCommand); 76 return FALSE; 77 } 78 79 CAtlList<CAppInfo *> Applications; 80 HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL); 81 if (InfHandle == INVALID_HANDLE_VALUE) 82 { 83 return FALSE; 84 } 85 86 INFCONTEXT Context; 87 if (SetupFindFirstLineW(InfHandle, L"RAPPS", L"Install", &Context)) 88 { 89 WCHAR szPkgName[MAX_PATH]; 90 do 91 { 92 if (SetupGetStringFieldW(&Context, 1, szPkgName, _countof(szPkgName), NULL)) 93 { 94 CAppInfo *AppInfo = db->FindByPackageName(szPkgName); 95 if (AppInfo) 96 { 97 Applications.AddTail(AppInfo); 98 } 99 } 100 } while (SetupFindNextLine(&Context, &Context)); 101 } 102 SetupCloseInfFile(InfHandle); 103 104 return DownloadListOfApplications(Applications, TRUE); 105 } 106 107 static BOOL 108 HandleFindCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 109 { 110 if (argcLeft < 1) 111 { 112 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PARAMS, szCommand); 113 return FALSE; 114 } 115 116 CAtlList<CAppInfo *> List; 117 db->GetApps(List, ENUM_ALL_AVAILABLE); 118 119 for (int i = 0; i < argcLeft; i++) 120 { 121 LPCWSTR lpszSearch = argvLeft[i]; 122 ConResMsgPrintf(StdOut, NULL, IDS_CMD_FIND_RESULT_FOR, lpszSearch); 123 124 POSITION CurrentListPosition = List.GetHeadPosition(); 125 while (CurrentListPosition) 126 { 127 CAppInfo *Info = List.GetNext(CurrentListPosition); 128 129 if (SearchPatternMatch(Info->szDisplayName, lpszSearch) || SearchPatternMatch(Info->szComments, lpszSearch)) 130 { 131 ConPrintf(StdOut, L"%s (%s)\n", Info->szDisplayName.GetString(), Info->szIdentifier.GetString()); 132 } 133 } 134 135 ConPrintf(StdOut, L"\n"); 136 } 137 138 return TRUE; 139 } 140 141 static BOOL 142 HandleInfoCommand(CAppDB *db, LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 143 { 144 if (argcLeft < 1) 145 { 146 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PARAMS, szCommand); 147 return FALSE; 148 } 149 150 for (int i = 0; i < argcLeft; i++) 151 { 152 LPCWSTR PackageName = argvLeft[i]; 153 CAppInfo *AppInfo = db->FindByPackageName(PackageName); 154 if (!AppInfo) 155 { 156 ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_NOT_FOUND, PackageName); 157 } 158 else 159 { 160 ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_INFO, PackageName); 161 162 ConPuts(StdOut, AppInfo->szDisplayName); 163 164 if (!AppInfo->szDisplayVersion.IsEmpty()) 165 { 166 ConResPrintf(StdOut, IDS_AINFO_VERSION); 167 ConPuts(StdOut, AppInfo->szDisplayVersion); 168 } 169 170 CStringW License, Size, UrlSite, UrlDownload; 171 AppInfo->GetDisplayInfo(License, Size, UrlSite, UrlDownload); 172 173 if (!License.IsEmpty()) 174 { 175 ConResPrintf(StdOut, IDS_AINFO_LICENSE); 176 ConPuts(StdOut, License); 177 } 178 179 if (!Size.IsEmpty()) 180 { 181 ConResPrintf(StdOut, IDS_AINFO_SIZE); 182 ConPuts(StdOut, Size); 183 } 184 185 if (!UrlSite.IsEmpty()) 186 { 187 ConResPrintf(StdOut, IDS_AINFO_URLSITE); 188 ConPuts(StdOut, UrlSite); 189 } 190 191 if (AppInfo->szComments) 192 { 193 ConResPrintf(StdOut, IDS_AINFO_DESCRIPTION); 194 ConPuts(StdOut, AppInfo->szComments); 195 } 196 197 if (!UrlDownload.IsEmpty()) 198 { 199 ConResPrintf(StdOut, IDS_AINFO_URLDOWNLOAD); 200 ConPuts(StdOut, UrlDownload); 201 } 202 ConPuts(StdOut, L"\n"); 203 } 204 ConPuts(StdOut, L"\n"); 205 } 206 return TRUE; 207 } 208 209 static VOID 210 PrintHelpCommand() 211 { 212 ConPrintf(StdOut, L"\n"); 213 ConResPuts(StdOut, IDS_APPTITLE); 214 ConPrintf(StdOut, L"\n\n"); 215 216 ConResPuts(StdOut, IDS_CMD_USAGE); 217 ConPrintf(StdOut, L"%ls\n", UsageString); 218 } 219 220 BOOL 221 ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) 222 { 223 INT argc; 224 LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc); 225 if (!argv) 226 return FALSE; 227 228 CStringW Directory; 229 GetStorageDirectory(Directory); 230 CAppDB db(Directory); 231 232 BOOL bAppwizMode = (argc > 1 && MatchCmdOption(argv[1], CMD_KEY_APPWIZ)); 233 if (!bAppwizMode) 234 { 235 if (SettingsInfo.bUpdateAtStart || bIsFirstLaunch) 236 db.RemoveCached(); 237 238 db.UpdateAvailable(); 239 } 240 241 db.UpdateInstalled(); 242 243 if (argc == 1 || bAppwizMode) // RAPPS is launched without options or APPWIZ mode is requested 244 { 245 // Check whether the RAPPS MainWindow is already launched in another process 246 HANDLE hMutex; 247 248 hMutex = CreateMutexW(NULL, FALSE, szWindowClass); 249 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS)) 250 { 251 /* If already started, find its window */ 252 HWND hWindow = FindWindowW(szWindowClass, NULL); 253 254 /* Activate window */ 255 ShowWindow(hWindow, SW_SHOWNORMAL); 256 SetForegroundWindow(hWindow); 257 if (bAppwizMode) 258 PostMessage(hWindow, WM_COMMAND, ID_ACTIVATE_APPWIZ, 0); 259 return FALSE; 260 } 261 262 CMainWindow wnd(&db, bAppwizMode); 263 MainWindowLoop(&wnd, nCmdShow); 264 265 if (hMutex) 266 CloseHandle(hMutex); 267 268 return TRUE; 269 } 270 271 if (MatchCmdOption(argv[1], CMD_KEY_INSTALL)) 272 { 273 return HandleInstallCommand(&db, argv[1], argc - 2, argv + 2); 274 } 275 else if (MatchCmdOption(argv[1], CMD_KEY_SETUP)) 276 { 277 return HandleSetupCommand(&db, argv[1], argc - 2, argv + 2); 278 } 279 280 InitRappsConsole(); 281 282 if (MatchCmdOption(argv[1], CMD_KEY_FIND)) 283 { 284 return HandleFindCommand(&db, argv[1], argc - 2, argv + 2); 285 } 286 else if (MatchCmdOption(argv[1], CMD_KEY_INFO)) 287 { 288 return HandleInfoCommand(&db, argv[1], argc - 2, argv + 2); 289 } 290 else if (MatchCmdOption(argv[1], CMD_KEY_HELP) || MatchCmdOption(argv[1], CMD_KEY_HELP_ALT)) 291 { 292 PrintHelpCommand(); 293 return TRUE; 294 } 295 else 296 { 297 // unrecognized/invalid options 298 ConResPuts(StdOut, IDS_CMD_INVALID_OPTION); 299 PrintHelpCommand(); 300 return FALSE; 301 } 302 } 303