Handle self-destruct packages
[cygwin-setup.git] / desktop.cc
blob4b76568cd7e50c0839f9a4b3f3acbbcc22fef297
1 /*
2 * Copyright (c) 2000, 2001 Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* The purpose of this file is to manage all the desktop setup, such
17 as start menu, batch files, desktop icons, and shortcuts. Note
18 that unlike other do_* functions, this one is called directly from
19 install.cc */
21 #include "win32.h"
22 #include <shlobj.h>
23 #include "desktop.h"
24 #include "propsheet.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
30 #include "ini.h"
31 #include "resource.h"
32 #include "state.h"
33 #include "dialog.h"
34 #include "mount.h"
35 #include "mklink2.h"
36 #include "package_db.h"
37 #include "package_meta.h"
38 #include "filemanip.h"
39 #include "io_stream.h"
40 #include "getopt++/BoolOption.h"
41 #include "LogFile.h"
43 static BoolOption NoShortcutsOption (false, 'n', "no-shortcuts", IDS_HELPTEXT_NO_SHORTCUTS);
44 static BoolOption NoStartMenuOption (false, 'N', "no-startmenu", IDS_HELPTEXT_NO_STARTMENU);
45 static BoolOption NoDesktopOption (false, 'd', "no-desktop", IDS_HELPTEXT_NO_DESKTOP);
47 /* Lines starting with '@' are conditionals - include 'N' for NT,
48 '5' for Win95, '8' for Win98, '*' for all, like this:
49 echo foo
50 @N8
51 echo NT or 98
55 static std::string batname;
56 static ControlAdjuster::ControlInfo DesktopControlsInfo[] = {
57 {IDC_DESKTOP_SEPARATOR, CP_STRETCH, CP_BOTTOM},
58 {IDC_STATUS, CP_LEFT, CP_BOTTOM},
59 {IDC_STATUS_HEADER, CP_LEFT, CP_BOTTOM},
60 {0, CP_LEFT, CP_TOP}
63 DesktopSetupPage::DesktopSetupPage ()
65 sizeProcessor.AddControlInfo (DesktopControlsInfo);
68 static void
69 make_link (const std::string& linkpath,
70 const std::string& title,
71 const std::string& target,
72 const std::string& arg,
73 const std::string& icon)
75 std::string fname = linkpath + "/" + title + ".lnk";
77 if (_access (fname.c_str(), 0) == 0)
78 return; /* already exists */
80 LogBabblePrintf ("make_link %s, %s, %s\n",
81 fname.c_str(), title.c_str(), target.c_str());
83 io_stream::mkpath_p (PATH_TO_FILE, std::string ("file://") + fname, 0);
85 std::string exepath;
86 std::string argbuf;
88 exepath = target;
89 argbuf = arg;
91 LogBabblePrintf ("make_link_2 (%s, %s, %s, %s)",
92 exepath.c_str(), argbuf.c_str(),
93 icon.c_str(), fname.c_str());
94 make_link_2 (exepath.c_str(), argbuf.c_str(),
95 icon.c_str(), fname.c_str());
98 static const char *startmenudir()
100 if (!is_64bit && (WowNativeMachine() != IMAGE_FILE_MACHINE_I386))
101 return "/Cygwin (32-bit)";
102 else
103 return "/Cygwin";
106 static void
107 start_menu (const std::string& title, const std::string& target,
108 const std::string& arg, const std::string& iconpath)
110 /* Special folders always < MAX_PATH. */
111 char path[MAX_PATH];
112 LPITEMIDLIST id;
113 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
114 SHGetSpecialFolderLocation (NULL,
115 issystem ? CSIDL_COMMON_PROGRAMS :
116 CSIDL_PROGRAMS, &id);
117 SHGetPathFromIDList (id, path);
118 strncat (path, startmenudir(), MAX_PATH - strlen(path) - 1);
119 LogBabblePrintf ("Program directory for program link: %s", path);
120 make_link (path, title, target, arg, iconpath);
123 static void
124 desktop_icon (const std::string& title, const std::string& target,
125 const std::string& arg, const std::string& iconpath)
127 /* Special folders always < MAX_PATH. */
128 char path[MAX_PATH];
129 LPITEMIDLIST id;
130 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
131 SHGetSpecialFolderLocation (NULL,
132 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
133 CSIDL_DESKTOPDIRECTORY, &id);
134 SHGetPathFromIDList (id, path);
135 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
136 make_link (path, title, target, arg, iconpath);
139 static void
140 make_cygwin_bat ()
142 batname = backslash (cygpath ("/Cygwin.bat"));
143 FILE *bat;
145 size_t len = batname.size () + 7;
146 WCHAR wname[len];
147 mklongpath (wname, batname.c_str (), len);
149 /* if the batch file exists, don't overwrite it */
150 if (GetFileAttributesW (wname) != INVALID_FILE_ATTRIBUTES)
151 return;
153 bat = nt_wfopen (wname, "wt", 0755);
155 if (!bat)
156 return;
158 fprintf (bat, "@echo off\n\n");
160 fprintf (bat, "%.2s\n", get_root_dir ().c_str());
161 fprintf (bat, "chdir %s\n\n",
162 replace(backslash(get_root_dir() + "/bin"), "%", "%%").c_str());
164 fprintf (bat, "bash --login -i\n");
166 fclose (bat);
169 static void
170 save_icon (std::string &iconpath, const char *resource_name)
172 HRSRC rsrc = FindResource (NULL, resource_name, "FILE");
173 if (rsrc == NULL)
175 Log (LOG_PLAIN) << "FindResource failed" << GetLastError() << endLog;
176 return;
179 HGLOBAL res = LoadResource (NULL, rsrc);
180 char *data = (char *) LockResource (res);
181 int len = SizeofResource (NULL, rsrc);
183 FILE *f;
184 WIN32_FILE_ATTRIBUTE_DATA attr;
186 size_t ilen = iconpath.size () + 7;
187 WCHAR wname[ilen];
188 mklongpath (wname, iconpath.c_str (), ilen);
189 if (GetFileAttributesExW (wname, GetFileExInfoStandard, &attr)
190 && attr.dwFileAttributes != INVALID_FILE_ATTRIBUTES
191 && attr.nFileSizeLow > 7022) /* Size of old icon */
192 return;
194 f = nt_wfopen (wname, "wb", 0644);
195 if (f)
197 fwrite (data, 1, len, f);
198 fclose (f);
202 #define TARGET "/bin/mintty"
203 #define DEFAULTICON "/Cygwin.ico"
204 #define TERMINALICON "/Cygwin-Terminal.ico"
205 #define TERMINALTITLE (is_64bit ? "Cygwin64 Terminal" \
206 : "Cygwin Terminal")
208 static void
209 do_desktop_setup ()
211 std::string target = backslash (cygpath (TARGET));
212 std::string defaulticon = backslash (cygpath (DEFAULTICON));
213 std::string terminalicon = backslash (cygpath (TERMINALICON));
215 save_icon (defaulticon, "CYGWIN.ICON");
216 save_icon (terminalicon, "CYGWIN-TERMINAL.ICON");
218 make_cygwin_bat ();
220 if (root_menu)
221 start_menu (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
223 if (root_desktop)
224 desktop_icon (TERMINALTITLE, target, "-i " TERMINALICON " -", terminalicon);
227 static int da[] = { IDC_ROOT_DESKTOP, 0 };
228 static int ma[] = { IDC_ROOT_MENU, 0 };
230 static void
231 check_if_enable_next (HWND h)
233 EnableWindow (GetDlgItem (h, IDOK), 1);
236 static void
237 set_status (HWND h)
239 std::wstring fmt = LoadStringW(Logger ().getExitMsg ());
240 std::wstring buf = format(fmt, backslash (Logger ().getFileName (LOG_BABBLE)).c_str ());
241 eset (h, IDC_STATUS, buf);
244 static void
245 load_dialog (HWND h)
247 if (source == IDC_SOURCE_DOWNLOAD)
249 // Don't need the checkboxes
250 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), FALSE);
251 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), FALSE);
252 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_DOWNLOAD), SW_SHOW);
253 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_DOWNLOAD), SW_SHOW);
254 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_INSTALL), SW_HIDE);
255 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_INSTALL), SW_HIDE);
257 else
259 EnableWindow (GetDlgItem (h, IDC_ROOT_DESKTOP), TRUE);
260 EnableWindow (GetDlgItem (h, IDC_ROOT_MENU), TRUE);
261 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_DOWNLOAD), SW_HIDE);
262 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_DOWNLOAD), SW_HIDE);
263 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_INSTALL), SW_SHOW);
264 ShowWindow (GetDlgItem(h, IDC_DESKTOP_HEADER_TITLE_INSTALL), SW_SHOW);
265 rbset (h, da, root_desktop);
266 rbset (h, ma, root_menu);
268 check_if_enable_next (h);
269 set_status (h);
272 static int
273 check_desktop (const std::string title, const std::string target)
275 /* Special folders always < MAX_PATH. */
276 char path[MAX_PATH];
277 LPITEMIDLIST id;
278 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
279 SHGetSpecialFolderLocation (NULL,
280 issystem ? CSIDL_COMMON_DESKTOPDIRECTORY :
281 CSIDL_DESKTOPDIRECTORY, &id);
282 SHGetPathFromIDList (id, path);
283 LogBabblePrintf ("Desktop directory for desktop link: %s", path);
284 std::string fname = std::string(path) + "/" + title + ".lnk";
286 if (_access (fname.c_str(), 0) == 0)
287 return 0; /* already exists */
289 return IDC_ROOT_DESKTOP;
292 static int
293 check_startmenu (const std::string title, const std::string target)
295 /* Special folders always < MAX_PATH. */
296 char path[MAX_PATH];
297 LPITEMIDLIST id;
298 int issystem = (root_scope == IDC_ROOT_SYSTEM) ? 1 : 0;
299 SHGetSpecialFolderLocation (NULL,
300 issystem ? CSIDL_COMMON_PROGRAMS :
301 CSIDL_PROGRAMS, &id);
302 SHGetPathFromIDList (id, path);
303 LogBabblePrintf ("Program directory for program link: %s", path);
304 strcat (path, startmenudir());
305 std::string fname = std::string(path) + "/" + title + ".lnk";
307 if (_access (fname.c_str(), 0) == 0)
308 return 0; /* already exists */
310 return IDC_ROOT_MENU;
313 static void
314 save_dialog (HWND h)
316 root_desktop = rbget (h, da);
317 root_menu = rbget (h, ma);
320 static BOOL
321 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
323 switch (id)
326 case IDC_ROOT_DESKTOP:
327 case IDC_ROOT_MENU:
328 save_dialog (h);
329 check_if_enable_next (h);
330 break;
332 return 0;
335 bool
336 DesktopSetupPage::Create ()
338 return PropertyPage::Create (NULL, dialog_cmd, IDD_DESKTOP);
341 void
342 DesktopSetupPage::OnInit ()
344 SetDlgItemFont(IDC_STATUS_HEADER, "MS Shell Dlg", 8, FW_BOLD);
347 void
348 DesktopSetupPage::OnActivate ()
350 if (NoShortcutsOption || source == IDC_SOURCE_DOWNLOAD)
352 root_desktop = root_menu = 0;
354 else
356 std::string target = backslash (cygpath (TARGET));
358 if (NoStartMenuOption)
360 root_menu = 0;
362 else
364 root_menu = check_startmenu (TERMINALTITLE, target);
367 if (NoDesktopOption)
369 root_desktop = 0;
371 else
373 root_desktop = check_desktop (TERMINALTITLE, target);
377 load_dialog (GetHWND ());
380 long
381 DesktopSetupPage::OnBack ()
383 HWND h = GetHWND ();
384 save_dialog (h);
385 return IDD_CHOOSE;
388 bool
389 DesktopSetupPage::OnFinish ()
391 HWND h = GetHWND ();
392 save_dialog (h);
393 if (source != IDC_SOURCE_DOWNLOAD)
394 do_desktop_setup ();
396 return true;
399 long
400 DesktopSetupPage::OnUnattended ()
402 Window::PostMessageNow (WM_APP_UNATTENDED_FINISH);
403 // GetOwner ()->PressButton(PSBTN_FINISH);
404 return -1;
407 bool
408 DesktopSetupPage::OnMessageApp (UINT uMsg, WPARAM wParam, LPARAM lParam)
410 switch (uMsg)
412 case WM_APP_UNATTENDED_FINISH:
414 GetOwner ()->PressButton(PSBTN_FINISH);
415 break;
417 default:
419 // Not handled
420 return false;
424 return true;