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 #include "rapps.h" 9 10 #include "unattended.h" 11 12 #include "winmain.h" 13 14 #include <setupapi.h> 15 16 #include <conutils.h> 17 18 BOOL MatchCmdOption(LPWSTR argvOption, LPCWSTR szOptToMacth) 19 { 20 WCHAR FirstCharList[] = { L'-', L'/' }; 21 22 for (UINT i = 0; i < _countof(FirstCharList); i++) 23 { 24 if (argvOption[0] == FirstCharList[i]) 25 { 26 if (StrCmpIW(argvOption + 1, szOptToMacth) == 0) 27 { 28 return TRUE; 29 } 30 else 31 { 32 return FALSE; 33 } 34 } 35 } 36 return FALSE; 37 } 38 39 BOOL HandleInstallCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) 40 { 41 if (argcLeft == 0) 42 { 43 ConInitStdStreams(); // Initialize the Console Standard Streams 44 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PACKAGE_NAME, szCommand); 45 return FALSE; 46 } 47 FreeConsole(); 48 49 ATL::CSimpleArray<ATL::CStringW> PkgNameList; 50 51 for (int i = 0; i < argcLeft; i++) 52 { 53 PkgNameList.Add(argvLeft[i]); 54 } 55 56 CAvailableApps apps; 57 apps.UpdateAppsDB(); 58 apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL); 59 60 ATL::CSimpleArray<CAvailableApplicationInfo> arrAppInfo = apps.FindAppsByPkgNameList(PkgNameList); 61 if (arrAppInfo.GetSize() > 0) 62 { 63 DownloadListOfApplications(arrAppInfo, TRUE); 64 return TRUE; 65 } 66 else 67 { 68 return FALSE; 69 } 70 } 71 72 BOOL HandleSetupCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) 73 { 74 if (argcLeft != 1) 75 { 76 ConInitStdStreams(); // Initialize the Console Standard Streams 77 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_FILE_NAME, szCommand); 78 return FALSE; 79 } 80 FreeConsole(); 81 82 ATL::CSimpleArray<ATL::CStringW> PkgNameList; 83 HINF InfHandle = SetupOpenInfFileW(argvLeft[0], NULL, INF_STYLE_WIN4, NULL); 84 if (InfHandle == INVALID_HANDLE_VALUE) 85 { 86 return FALSE; 87 } 88 89 INFCONTEXT Context; 90 if (SetupFindFirstLineW(InfHandle, L"RAPPS", L"Install", &Context)) 91 { 92 WCHAR szPkgName[MAX_PATH]; 93 do 94 { 95 if (SetupGetStringFieldW(&Context, 1, szPkgName, _countof(szPkgName), NULL)) 96 { 97 PkgNameList.Add(szPkgName); 98 } 99 } while (SetupFindNextLine(&Context, &Context)); 100 } 101 SetupCloseInfFile(InfHandle); 102 103 CAvailableApps apps; 104 apps.UpdateAppsDB(); 105 apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL); 106 107 ATL::CSimpleArray<CAvailableApplicationInfo> arrAppInfo = apps.FindAppsByPkgNameList(PkgNameList); 108 if (arrAppInfo.GetSize() > 0) 109 { 110 DownloadListOfApplications(arrAppInfo, TRUE); 111 return TRUE; 112 } 113 else 114 { 115 return FALSE; 116 } 117 } 118 119 BOOL CALLBACK CmdFindAppEnum(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param) 120 { 121 LPCWSTR lpszSearch = (LPCWSTR)param; 122 if (!SearchPatternMatch(Info->m_szName.GetString(), lpszSearch) && 123 !SearchPatternMatch(Info->m_szDesc.GetString(), lpszSearch)) 124 { 125 return TRUE; 126 } 127 128 ConPrintf(StdOut, (LPWSTR)L"%s (%s)\n", (LPCWSTR)(Info->m_szName), (LPCWSTR)(Info->m_szPkgName)); 129 return TRUE; 130 } 131 132 BOOL HandleFindCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 133 { 134 if (argcLeft < 1) 135 { 136 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PARAMS, szCommand); 137 return FALSE; 138 } 139 140 CAvailableApps apps; 141 apps.UpdateAppsDB(); 142 143 for (int i = 0; i < argcLeft; i++) 144 { 145 ConResMsgPrintf(StdOut, NULL, IDS_CMD_FIND_RESULT_FOR, argvLeft[i]); 146 apps.Enum(ENUM_ALL_AVAILABLE, CmdFindAppEnum, argvLeft[i]); 147 ConPrintf(StdOut, (LPWSTR)L"\n"); 148 } 149 150 return TRUE; 151 } 152 153 BOOL HandleInfoCommand(LPWSTR szCommand, int argcLeft, LPWSTR *argvLeft) 154 { 155 if (argcLeft < 1) 156 { 157 ConResMsgPrintf(StdOut, NULL, IDS_CMD_NEED_PARAMS, szCommand); 158 return FALSE; 159 } 160 161 CAvailableApps apps; 162 apps.UpdateAppsDB(); 163 apps.Enum(ENUM_ALL_AVAILABLE, NULL, NULL); 164 165 for (int i = 0; i < argcLeft; i++) 166 { 167 CAvailableApplicationInfo *AppInfo = apps.FindAppByPkgName(argvLeft[i]); 168 if (!AppInfo) 169 { 170 ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_NOT_FOUND, argvLeft[i]); 171 } 172 else 173 { 174 ConResMsgPrintf(StdOut, NULL, IDS_CMD_PACKAGE_INFO, argvLeft[i]); 175 // TODO: code about extracting information from CAvailableApplicationInfo (in appview.cpp, class CAppRichEdit) 176 // is in a mess. It should be refactored, and should not placed in class CAppRichEdit. 177 // and the code here should reused that code after refactor. 178 179 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szName); 180 181 if (AppInfo->m_szVersion) 182 { 183 ConResPrintf(StdOut, IDS_AINFO_VERSION); 184 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szVersion); 185 } 186 187 if (AppInfo->m_szLicense) 188 { 189 ConResPrintf(StdOut, IDS_AINFO_LICENSE); 190 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szLicense); 191 } 192 193 if (AppInfo->m_szSize) 194 { 195 ConResPrintf(StdOut, IDS_AINFO_SIZE); 196 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szSize); 197 } 198 199 if (AppInfo->m_szUrlSite) 200 { 201 ConResPrintf(StdOut, IDS_AINFO_URLSITE); 202 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szUrlSite); 203 } 204 205 if (AppInfo->m_szDesc) 206 { 207 ConResPrintf(StdOut, IDS_AINFO_DESCRIPTION); 208 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szDesc); 209 } 210 211 if (AppInfo->m_szUrlDownload) 212 { 213 ConResPrintf(StdOut, IDS_AINFO_URLDOWNLOAD); 214 ConPuts(StdOut, (LPWSTR)(LPCWSTR)AppInfo->m_szUrlDownload); 215 } 216 217 ConPrintf(StdOut, (LPWSTR)L"\n"); 218 } 219 ConPrintf(StdOut, (LPWSTR)L"\n"); 220 } 221 return TRUE; 222 } 223 224 BOOL HandleHelpCommand(LPWSTR szCommand, int argcLeft, LPWSTR * argvLeft) 225 { 226 if (argcLeft != 0) 227 { 228 return FALSE; 229 } 230 231 ConPrintf(StdOut, (LPWSTR)L"\n"); 232 ConResPuts(StdOut, IDS_APPTITLE); 233 ConPrintf(StdOut, (LPWSTR)L"\n\n"); 234 235 ConResPuts(StdOut, IDS_CMD_USAGE); 236 ConPrintf(StdOut, (LPWSTR)L"%ls\n", UsageString); 237 return TRUE; 238 } 239 240 BOOL ParseCmdAndExecute(LPWSTR lpCmdLine, BOOL bIsFirstLaunch, int nCmdShow) 241 { 242 INT argc; 243 LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc); 244 245 if (!argv) 246 { 247 return FALSE; 248 } 249 250 if (argc == 1) // RAPPS is launched without options 251 { 252 // Close the console, and open MainWindow 253 FreeConsole(); 254 255 256 // Check for if rapps MainWindow is already launched in another process 257 HANDLE hMutex; 258 259 hMutex = CreateMutexW(NULL, FALSE, szWindowClass); 260 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS)) 261 { 262 /* If already started, it is found its window */ 263 HWND hWindow = FindWindowW(szWindowClass, NULL); 264 265 /* Activate window */ 266 ShowWindow(hWindow, SW_SHOWNORMAL); 267 SetForegroundWindow(hWindow); 268 return FALSE; 269 } 270 271 if (SettingsInfo.bUpdateAtStart || bIsFirstLaunch) 272 CAvailableApps::ForceUpdateAppsDB(); 273 274 MainWindowLoop(nCmdShow); 275 276 if (hMutex) 277 CloseHandle(hMutex); 278 279 return TRUE; 280 } 281 else if (MatchCmdOption(argv[1], CMD_KEY_INSTALL)) 282 { 283 return HandleInstallCommand(argv[1], argc - 2, argv + 2); 284 } 285 else if (MatchCmdOption(argv[1], CMD_KEY_SETUP)) 286 { 287 return HandleSetupCommand(argv[1], argc - 2, argv + 2); 288 } 289 290 291 ConInitStdStreams(); // Initialize the Console Standard Streams 292 293 if (MatchCmdOption(argv[1], CMD_KEY_FIND)) 294 { 295 return HandleFindCommand(argv[1], argc - 2, argv + 2); 296 } 297 else if (MatchCmdOption(argv[1], CMD_KEY_INFO)) 298 { 299 return HandleInfoCommand(argv[1], argc - 2, argv + 2); 300 } 301 else if (MatchCmdOption(argv[1], CMD_KEY_HELP)) 302 { 303 return HandleHelpCommand(argv[1], argc - 2, argv + 2); 304 } 305 else 306 { 307 // unrecognized/invalid options 308 ConResPuts(StdOut, IDS_CMD_INVALID_OPTION); 309 return FALSE; 310 } 311 } 312