1 /*
2  *
3  * PROJECT:                 Add or Remove Programs (Console Version)
4  * FILE:                    rosapps/applications/cmdutils/appwiz/appwiz.c
5  * PURPOSE:                 ReactOS Software Control Panel
6  * PROGRAMMERS:             Dmitry Chapyshev (dmitry@reactos.org)
7  * UPDATE HISTORY:
8  *    07-28-2008  Created
9  */
10 
11 #define SHOW_ALL 1
12 #define APP_ONLY 2
13 #define UPD_ONLY 3
14 
15 #include <windows.h>
16 #include <stdio.h>
17 #include <conio.h>
18 #include <tchar.h>
19 
20 
21 void PrintHelp()
22 {
23 	printf(_T("Add or Remove Programs\n\
24 APPWIZ [/? /l] [/all /app /upd]\n\
25   /?\t Help\n\
26   /l\t Show list\n\
27   /all\t Show programs and updates\n\
28   /app\t Show programs only\n\
29   /upd\t Show updates only\n"));
30     _getch();
31 }
32 
33 
34 void RunGUIAppWiz()
35 {
36     SHELLEXECUTEINFO shInputDll;
37 
38     memset(&shInputDll, 0x0, sizeof(SHELLEXECUTEINFO));
39     shInputDll.cbSize = sizeof(shInputDll);
40     shInputDll.hwnd = NULL;
41     shInputDll.lpVerb = _T("open");
42     shInputDll.lpFile = _T("RunDll32.exe");
43     shInputDll.lpParameters = _T("shell32.dll,Control_RunDLL appwiz.cpl");
44 
45     if (ShellExecuteEx(&shInputDll) == 0)
46     {
47         MessageBox(NULL, _T("Can not start appwiz.cpl"), NULL, MB_OK | MB_ICONERROR);
48     }
49 }
50 
51 void CallUninstall(LPTSTR szUninstallString)
52 {
53     STARTUPINFO si;
54     PROCESS_INFORMATION pi;
55     DWORD dwRet;
56     MSG msg;
57 
58     ZeroMemory(&si, sizeof(si));
59     si.cb = sizeof(si);
60     si.wShowWindow = SW_SHOW;
61 
62     if (CreateProcess(NULL, szUninstallString, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
63     {
64         CloseHandle(pi.hThread);
65 
66         for (;;)
67         {
68             dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS);
69             if (dwRet == WAIT_OBJECT_0 + 1)
70             {
71                  while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
72                  {
73                      TranslateMessage(&msg);
74                      DispatchMessage(&msg);
75                  }
76             }
77             else if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED)
78                 break;
79         }
80         CloseHandle(pi.hProcess);
81     }
82 }
83 
84 
85 /*
86     dwMode:
87         SHOW_ALL - Applications & Updates
88         APP_ONLY - Applications only
89         UPD_ONLY - Updates only
90 */
91 int ShowAppList(DWORD dwMode, INT iItem)
92 {
93     HKEY hKey, hSubKey;
94     DWORD dwSize, dwType, dwValue;
95     TCHAR szName[MAX_PATH];
96     TCHAR szParentKeyName[MAX_PATH];
97     TCHAR szDisplayName[MAX_PATH];
98     TCHAR szOutBuf[MAX_PATH];
99     FILETIME FileTime;
100     BOOL bIsUpdate = FALSE;
101     BOOL bIsSystemComponent = FALSE;
102     INT iIndex = 0, iColor = 0, iCount = 1;
103     HANDLE hOutput;
104 
105     if (RegOpenKey(HKEY_LOCAL_MACHINE,
106                    _T("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"),
107                    &hKey) != ERROR_SUCCESS)
108     {
109         printf(_T("ERROR: Can not open Uninstall key. Press any key for continue...\n"));
110         _getch();
111         return 0;
112     }
113 
114     hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
115     SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
116 
117     dwSize = MAX_PATH;
118     while (RegEnumKeyEx(hKey, iIndex, szName, &dwSize, NULL, NULL, NULL, &FileTime) == ERROR_SUCCESS)
119     {
120         if (RegOpenKey(hKey, szName, &hSubKey) == ERROR_SUCCESS)
121         {
122             dwType = REG_DWORD;
123             dwSize = sizeof(DWORD);
124 
125             if (RegQueryValueEx(hSubKey, _T("SystemComponent"),
126                                 NULL, &dwType,
127                                 (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS)
128             {
129                 bIsSystemComponent = (dwValue == 0x1);
130             }
131             else
132             {
133                 bIsSystemComponent = FALSE;
134             }
135 
136             dwType = REG_SZ;
137             dwSize = MAX_PATH;
138 
139             bIsUpdate = (RegQueryValueEx(hSubKey, _T("ParentKeyName"),
140                                          NULL, &dwType,
141                                          (LPBYTE) szParentKeyName,
142                                          &dwSize) == ERROR_SUCCESS);
143             dwSize = MAX_PATH;
144             if (RegQueryValueEx(hSubKey, _T("DisplayName"),
145                                 NULL, &dwType,
146                                 (LPBYTE) szDisplayName,
147                                 &dwSize) == ERROR_SUCCESS)
148             {
149                 if (!bIsSystemComponent)
150                 {
151                     if ((dwMode == SHOW_ALL) || ((dwMode == APP_ONLY) && (!bIsUpdate)) || ((dwMode == UPD_ONLY) && (bIsUpdate)))
152                     {
153                         if (iItem == -1)
154                         {
155                             wsprintf(szOutBuf, _T(" %d \t %s\n"), iCount, szDisplayName);
156                             CharToOem(szOutBuf, szOutBuf);
157                             printf("%s", szOutBuf);
158                         }
159                         else
160                         {
161                             dwType = REG_SZ;
162                             dwSize = MAX_PATH;
163 
164                             if ((RegQueryValueEx(hSubKey, _T("UninstallString"), NULL, &dwType,
165                                                 (LPBYTE) szOutBuf, &dwSize) == ERROR_SUCCESS) && (iItem == iCount))
166                             {
167                                 CallUninstall(szOutBuf);
168                             }
169                         }
170                         iCount++;
171                         iColor++;
172                     }
173                 }
174             }
175         }
176 
177         if (iColor <= 5)
178         {
179             SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
180         }
181         else
182         {
183             SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY | FOREGROUND_RED);
184             if (iColor >= 10) iColor = 0;
185         }
186 
187         dwSize = MAX_PATH;
188         iIndex++;
189     }
190 
191     RegCloseKey(hSubKey);
192     RegCloseKey(hKey);
193 
194     SetConsoleTextAttribute(hOutput, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
195     printf("\n\nPlease enter application/update number and press ENTER for uninstall\nor press any key for Exit...\n");
196 
197     return 1;
198 }
199 
200 
201 int _tmain(int argc, _TCHAR* argv[])
202 {
203     INT iNumber;
204     TCHAR Char[4 + 1];
205 
206     SetConsoleTitle(_T("Application Wizard"));
207 
208     if (argc < 2)
209     {
210         RunGUIAppWiz();
211         return 0;
212     }
213 
214 	if (_tcsncmp(argv[1], _T("/?"), 2) == 0)
215 	{
216 		PrintHelp();
217 		return 0;
218 	}
219 
220     if (_tcsncmp(argv[1], _T("/l"), 2) == 0)
221     {
222         if (argc < 3) goto ShowAll;
223         if (_tcsncmp(argv[2], _T("/all"), 4) == 0)
224         {
225 ShowAll:
226             if (ShowAppList(SHOW_ALL, -1) == 0) return 0;
227             scanf(_T("%s"), Char);
228 
229             iNumber = atoi(Char);
230 
231             if (iNumber == 0) return 0;
232             ShowAppList(SHOW_ALL, iNumber);
233         }
234         else if (_tcsncmp(argv[2], _T("/app"), 4) == 0)
235         {
236             if (ShowAppList(APP_ONLY, -1) == 0) return 0;
237 
238             scanf(_T("%s"), Char);
239 
240             iNumber = atoi(Char);
241 
242             if (iNumber == 0) return 0;
243             ShowAppList(APP_ONLY, iNumber);
244         }
245         else if (_tcsncmp(argv[2], _T("/upd"), 4) == 0)
246         {
247             if (ShowAppList(UPD_ONLY, -1) == 0) return 0;
248 
249             scanf(_T("%s"), Char);
250 
251             iNumber = atoi(Char);
252 
253             if (iNumber == 0) return 0;
254             ShowAppList(UPD_ONLY, iNumber);
255         }
256 
257         return 0;
258     }
259 
260 	return 0;
261 }
262