/*
* Copyright 2004 - 2008 Christian Sprajc. All rights reserved.
*
* This file is part of PowerFolder.
*
* PowerFolder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* PowerFolder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PowerFolder. If not, see <http://www.gnu.org/licenses/>.
*
* $Id$
*/
package de.dal33t.powerfolder.util.os.Win32;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.Map.Entry;
import java.util.logging.Logger;
import de.dal33t.powerfolder.Constants;
import de.dal33t.powerfolder.Controller;
import de.dal33t.powerfolder.util.StringUtils;
import de.dal33t.powerfolder.util.Translation;
import de.dal33t.powerfolder.util.logging.Loggable;
import de.dal33t.powerfolder.util.os.OSUtil;
/**
* Utilities for windows. http://vbnet.mvps.org/index.html?code/browse/csidl.htm
*
* @author <A HREF="mailto:bytekeeper@powerfolder.com">Dennis Waldherr</A>
* @version $Revision$
*/
public class WinUtils extends Loggable {
private static final Logger LOG = Logger
.getLogger(WinUtils.class.getName());
private static final String REGQUERY_UTIL = "reg query ";
private static final String REGSTR_TOKEN = "REG_SZ";
private static final String DESKTOP_FOLDER_CMD = REGQUERY_UTIL
+ "\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\Shell Folders\" /v DESKTOP";
/**
* The file system directory that contains the programs that appear in the
* Startup folder for all users. A typical path is C:\Documents and
* Settings\All Users\Start Menu\Programs\Startup. Valid only for Windows NT
* systems.
*/
public static final int CSIDL_COMMON_STARTUP = 0x0018;
/**
* The file system directory that corresponds to the user's Startup program
* group. The system starts these programs whenever any user logs onto
* Windows NT or starts Windows 95. A typical path is C:\Documents and
* Settings\\username\\Start Menu\\Programs\\Startup.
*/
public static final int CSIDL_STARTUP = 0x0007;
public static final int CSIDL_DESKTOP = 0x0000;
// Eigene Dokumente / My Documents
public static final int CSIDL_PERSONAL = 0x0005;
// Favoriten / Favorites
public static final int CSIDL_FAVORITES = 0x0006;
// Meine Musik / My Music
public static final int CSIDL_MYMUSIC = 0x000d;
// Meine Videos / My Videaos
public static final int CSIDL_MYVIDEO = 0x000e;
// Meine Bilder / My Pictures
public static final int CSIDL_MYPICTURES = 0x0027;
// e.g. C:\Windows
public static final int CSIDL_WINDOWS = 0x0024;
// Application Data of current user. Roaming and Local
public static final int CSIDL_APP_DATA = 0x001A;
public static final int CSIDL_LOCAL_APP_DATA = 0x001C;
// Application Data of ALL USERs.
public static final int CSIDL_COMMON_APP_DATA = 0x0023;
/*
* Other CSLIDs:
* http://vbnet.mvps.org/index.html?code/browse/csidlversions.htm
*/
private static WinUtils instance;
private static boolean error = false;
private WinUtils() {
}
/**
* @return true if this platform supports the winutils helpers.
*/
public static boolean isSupported() {
return getInstance() != null;
}
/**
* @return the instance or NULL if not supported on this platform.
*/
public static synchronized WinUtils getInstance() {
if (!OSUtil.isWindowsSystem()) {
return null;
}
if (instance == null && !error) {
if (OSUtil.loadLibrary(WinUtils.class, "desktoputils")) {
instance = new WinUtils();
instance.init();
} else {
error = true;
}
}
return instance;
}
/**
* Retrieve a path from Windows.
*
* @param id
* the path-id to retrieve
* @param defaultPath
* if true, returns the default path location instead of the
* current
* @return
*/
public native String getSystemFolderPath(int id, boolean defaultPath);
public native void createLink(ShellLink link, String lnkTarget)
throws IOException;
private native void init();
/**
* Create a 'PowerFolders' link in Links, pointing to the PowerFolder base
* dir.
*
* @param setup
* @param controller
* @throws IOException
*/
public void setPFLinks(boolean setup, Controller controller)
throws IOException
{
String userHome = System.getProperty("user.home");
File linksDir = new File(userHome, "Links");
if (!linksDir.exists()) {
logWarning("Could not locate the Links directory in " + userHome);
return;
}
File baseDir = controller.getFolderRepository().getFoldersBasedir();
File shortCut = new File(linksDir, baseDir.getName()
+ Constants.LINK_EXTENSION);
if (setup) {
ShellLink link = new ShellLink(null, baseDir.getName(),
baseDir.getAbsolutePath(), null);
createLink(link, shortCut.getAbsolutePath());
} else {
shortCut.delete();
}
}
public static void removePFLinks(String shortcutName) {
if (!OSUtil.isWindowsSystem()) {
return;
}
String userHome = System.getProperty("user.home");
File linksDir = new File(userHome, "Links");
if (!linksDir.exists()) {
return;
}
File shortCut = new File(linksDir, shortcutName
+ Constants.LINK_EXTENSION);
shortCut.delete();
}
public static boolean isPFLinks(String shortcutName) {
if (!OSUtil.isWindowsSystem()) {
return false;
}
String userHome = System.getProperty("user.home");
File linksDir = new File(userHome, "Links");
if (!linksDir.exists()) {
return false;
}
File shortCut = new File(linksDir, shortcutName
+ Constants.LINK_EXTENSION);
return shortCut.exists();
}
public void setPFStartup(boolean setup, Controller controller)
throws IOException
{
File pfile = new File(
new File(System.getProperty("java.class.path")).getParentFile(),
controller.getDistribution().getBinaryName() + ".exe");
if (!pfile.exists()) {
pfile = new File(controller.getDistribution().getBinaryName()
+ ".exe");
if (!pfile.exists()) {
throw new IOException("Couldn't find executable! "
+ "Note: Setting up a startup shortcut only works "
+ "when " + controller.getDistribution().getBinaryName()
+ " was started by " + pfile.getName());
}
return;
}
logFiner("Found " + pfile.getAbsolutePath());
String shortCutname = controller.getDistribution().getName()
+ Constants.LINK_EXTENSION;
File pflnk = new File(getSystemFolderPath(CSIDL_STARTUP, false),
shortCutname);
File pflnkAll = new File(getSystemFolderPath(CSIDL_COMMON_STARTUP,
false), shortCutname);
if (setup) {
ShellLink sl = new ShellLink("--minimized",
Translation.getTranslation("winutils.shortcut.description"),
pfile.getAbsolutePath(), pfile.getParent());
logInfo("Creating startup link: " + pflnk.getAbsolutePath());
createLink(sl, pflnk.getAbsolutePath());
} else {
logInfo("Deleting startup link.");
pflnk.delete();
pflnkAll.delete();
// PFC-2164: Fallback. Also delete binary name links
shortCutname = controller.getDistribution().getBinaryName()
+ Constants.LINK_EXTENSION;
pflnk = new File(getSystemFolderPath(CSIDL_STARTUP, false),
shortCutname);
pflnkAll = new File(
getSystemFolderPath(CSIDL_COMMON_STARTUP, false), shortCutname);
pflnk.delete();
pflnkAll.delete();
}
}
public boolean isPFStartup(Controller controller) {
String shortCutname = controller.getDistribution().getName()
+ Constants.LINK_EXTENSION;
File pflnk = new File(getSystemFolderPath(CSIDL_STARTUP, false),
shortCutname);
File pflnkAll = new File(getSystemFolderPath(CSIDL_COMMON_STARTUP,
false), shortCutname);
String shortCutname2 = controller.getDistribution().getBinaryName()
+ Constants.LINK_EXTENSION;
File pflnk2 = new File(getSystemFolderPath(CSIDL_STARTUP, false),
shortCutname2);
File pflnkAll2 = new File(getSystemFolderPath(CSIDL_COMMON_STARTUP,
false), shortCutname2);
return pflnk.exists() || pflnkAll.exists() || pflnk2.exists()
|| pflnkAll2.exists();
}
/**
* It returns the default location where the PowerFolder installer installs
* the program.
*
* @return the path on a Windows installation or null if unable to resolve.
*/
public static File getProgramInstallationPath() {
String programFiles = System.getenv("PROGRAMFILES");
if (StringUtils.isBlank(programFiles)) {
LOG.warning("Unable find installation path. Program files directory not found");
return null;
}
File f = new File(programFiles + "/PowerFolder.com/PowerFolder");
if (f.exists()) {
return f;
}
f = new File(programFiles + " (x86)/PowerFolder.com/PowerFolder");
if (f.exists()) {
return f;
}
// Try harder
try {
f = new File("").getCanonicalFile();
if (f.exists()) {
return f;
}
} catch (IOException e) {
}
LOG.warning("Unable find installation path. Program files directory not found");
return null;
}
/**
* @return the APPDATA directory for placing application data (Current
* user).
*/
public static String getAppDataCurrentUser() {
String appDataname = System.getenv("APPDATA");
if (StringUtils.isBlank(appDataname) && WinUtils.getInstance() != null)
{
appDataname = WinUtils.getInstance().getSystemFolderPath(
WinUtils.CSIDL_APP_DATA, false);
}
if (StringUtils.isBlank(appDataname) && OSUtil.isWindowsSystem()) {
LOG.severe("Unable to find APPDATA (current user) directory");
}
return appDataname;
}
/**
* @return the APPDATA directory for placing application data (All users).
*/
public static String getAppDataAllUsers() {
// "Normal" way. Get it from Windows DLLs directly
if (WinUtils.getInstance() != null) {
return WinUtils.getInstance().getSystemFolderPath(
WinUtils.CSIDL_COMMON_APP_DATA, false);
}
// Windows Vista and Windows 7
if (StringUtils.isNotBlank(System.getenv("ProgramData"))) {
// Source:
// http://en.wikipedia.org/wiki/Environment_variable#Default_Values_on_Microsoft_Windows
String appDataAllUsers = System.getenv("ProgramData");
File dir = new File(appDataAllUsers);
if (dir.exists()) {
LOG.warning("Retrieved APPDATA (all users) via ENV(ProgramData): "
+ appDataAllUsers);
return appDataAllUsers;
}
}
// Windows XP
if (StringUtils.isNotBlank(System.getenv("USERPROFILE"))
&& StringUtils.isNotBlank(System.getenv("APPDATA"))
&& StringUtils.isNotBlank(System.getenv("ALLUSERSPROFILE")))
{
// Source:
// http://stackoverflow.com/questions/2517940/windows-application-data-directory
/*
* Tested on WinXP 32 bit: APPDATA=C:\Dokumente und
* Einstellungen\Administrator\Anwendungsdaten
* USERPROFILE=C:\Dokumente und Einstellungen\Administrator
* ALLUSERSPROFILE=C:\Dokumente und Einstellungen\All Users
*/
String userProfile = System.getenv("USERPROFILE");
String appData = System.getenv("APPDATA");
String allUsersProfile = System.getenv("ALLUSERSPROFILE");
String temp = appData.replace(userProfile, "");
String appDataAllUsers = allUsersProfile + temp;
File dir = new File(appDataAllUsers);
if (dir.exists()) {
LOG.warning("Retrieved APPDATA (all users) via ENV(USERPROFILE/APPDATA/ALLUSERSPROFILE): "
+ appDataAllUsers);
return appDataAllUsers;
}
}
// Fail!
LOG.severe("Unable to find APPDATA (all users) directory");
LOG.warning("Dump of environment variables: ");
for (Entry<String, String> entry : System.getenv().entrySet()) {
LOG.warning(" " + entry.getKey() + "=" + entry.getValue());
}
return null;
}
private static final String TASKLIST = "tasklist";
private static final String KILL = "taskkill /IM ";
public static boolean isProcessRunging(String serviceName) throws Exception
{
Process p = Runtime.getRuntime().exec(TASKLIST);
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
if (line.contains(serviceName)) {
return true;
}
}
return false;
}
public static void killProcess(String serviceName) throws Exception {
Runtime.getRuntime().exec(KILL + serviceName);
}
/**
* @return
*/
private static String getCurrentUserDesktopPath() {
try {
Process process = Runtime.getRuntime().exec(DESKTOP_FOLDER_CMD);
StreamReader reader = new StreamReader(process.getInputStream());
reader.start();
process.waitFor();
reader.join();
String result = reader.getResult();
int p = result.indexOf(REGSTR_TOKEN);
if (p == -1)
return null;
return result.substring(p + REGSTR_TOKEN.length()).trim();
} catch (Exception e) {
return null;
}
}
private static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw;
StreamReader(InputStream is) {
this.is = is;
sw = new StringWriter();
}
public void run() {
try {
int c;
while ((c = is.read()) != -1)
sw.write(c);
} catch (IOException e) {
;
}
}
String getResult() {
return sw.toString();
}
}
}