win32.cpp

Go to the documentation of this file.
00001 /****************************************************************
00002  *  Vidalia is distributed under the following license:
00003  *
00004  *  Copyright (C) 2006,  Matt Edman, Justin Hipple
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00019  *  Boston, MA  02110-1301, USA.
00020  ****************************************************************/
00021 
00022 /** 
00023  * \file win32.cpp
00024  * \version $Id: win32.cpp 1870 2007-08-25 04:02:53Z edmanm $ 
00025  * \brief Win32-specific functions
00026  */
00027 
00028 #include "win32.h"
00029 #include <tlhelp32.h>
00030 #include <shlobj.h>
00031 #include <QDir>
00032 #include <QLibrary>
00033 #include <QtDebug>
00034 
00035 #if defined(UNICODE)
00036 /* Force the ascii verisons of these functions, so we can run on Win98. We
00037  * don't pass any Unicode strings to these functions anyway. */
00038 #undef PROCESSENTRY32
00039 #undef LPPROCESSENTRY32
00040 #undef Process32First
00041 #undef Process32Next
00042 #endif
00043 
00044 /* Load the tool help functions dynamically, since they don't exist on
00045  * Windows NT 4.0 */
00046 typedef HANDLE (WINAPI *CreateToolhelp32Snapshot_fn)(DWORD, DWORD);
00047 typedef BOOL (WINAPI *Process32First_fn)(HANDLE, LPPROCESSENTRY32);
00048 typedef BOOL (WINAPI *Process32Next_fn)(HANDLE, LPPROCESSENTRY32);
00049 
00050 
00051 /** Finds the location of the "special" Windows folder using the given CSIDL
00052  * value. If the folder cannot be found, the given default path is used. */
00053 QString
00054 win32_get_folder_location(int folder, QString defaultPath)
00055 {
00056   TCHAR path[MAX_PATH+1];
00057   LPITEMIDLIST idl;
00058   IMalloc *m;
00059   HRESULT result;
00060 
00061   /* Find the location of %PROGRAMFILES% */
00062   if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &idl))) {
00063     /* Get the path from the IDL */
00064     result = SHGetPathFromIDList(idl, path);
00065     SHGetMalloc(&m);
00066     if (m) {
00067       m->Release();
00068     }
00069     if (SUCCEEDED(result)) {
00070       QT_WA(return QString::fromUtf16((const ushort *)path);,
00071             return QString::fromLocal8Bit((char *)path);)
00072     }
00073   }
00074   return defaultPath;
00075 }
00076 
00077 /** Gets the location of the user's %PROGRAMFILES% folder. */
00078 QString
00079 win32_program_files_folder()
00080 {
00081   return win32_get_folder_location(
00082      CSIDL_PROGRAM_FILES, QDir::rootPath() + "\\Program Files");
00083 }
00084 
00085 /** Gets the location of the user's %APPDATA% folder. */
00086 QString
00087 win32_app_data_folder()
00088 {
00089   return win32_get_folder_location(
00090       CSIDL_APPDATA, QDir::homePath() + "\\Application Data");
00091 }
00092 
00093 /** Returns the value in keyName at keyLocation. 
00094  *  Returns an empty QString if the keyName doesn't exist */
00095 QString
00096 win32_registry_get_key_value(QString keyLocation, QString keyName)
00097 {
00098   HKEY key;
00099   char data[255] = {0};
00100   DWORD size = sizeof(data);
00101 
00102   /* Open the key for reading (opens new key if it doesn't exist) */
00103   if (RegOpenKeyExA(HKEY_CURRENT_USER,
00104                     qPrintable(keyLocation), 
00105                     0L, KEY_READ, &key) == ERROR_SUCCESS) {
00106     
00107     /* Key exists, so read the value into data */
00108     RegQueryValueExA(key, qPrintable(keyName), 
00109                     NULL, NULL, (LPBYTE)data, &size);
00110   }
00111 
00112   /* Close anything that was opened */
00113   RegCloseKey(key);
00114 
00115   return QString(data);
00116 }
00117 
00118 /** Creates and/or sets the key to the specified value */
00119 void
00120 win32_registry_set_key_value(QString keyLocation, QString keyName, QString keyValue)
00121 {
00122   HKEY key;
00123   
00124   /* Open the key for writing (opens new key if it doesn't exist */
00125   if (RegOpenKeyExA(HKEY_CURRENT_USER,
00126                    qPrintable(keyLocation),
00127                    0, KEY_WRITE, &key) != ERROR_SUCCESS) {
00128 
00129     /* Key didn't exist, so write the newly opened key */
00130     RegCreateKeyExA(HKEY_CURRENT_USER,
00131                    qPrintable(keyLocation),
00132                    0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
00133                    &key, NULL);
00134   }
00135 
00136   /* Save the value in the key */
00137   RegSetValueExA(key, qPrintable(keyName), 0, REG_SZ, 
00138                 (BYTE *)qPrintable(keyValue),
00139                 (DWORD)keyValue.length() + 1); // include null terminator
00140 
00141   /* Close the key */
00142   RegCloseKey(key);
00143 }
00144 
00145 /** Removes the key from the registry if it exists */
00146 void
00147 win32_registry_remove_key(QString keyLocation, QString keyName)
00148 {
00149   HKEY key;
00150   
00151   /* Open the key for writing (opens new key if it doesn't exist */
00152   if (RegOpenKeyExA(HKEY_CURRENT_USER,
00153                    qPrintable(keyLocation),
00154                    0, KEY_SET_VALUE, &key) == ERROR_SUCCESS) {
00155   
00156     /* Key exists so delete it */
00157     RegDeleteValueA(key, qPrintable(keyName));
00158   }
00159 
00160   /* Close anything that was opened */
00161   RegCloseKey(key);
00162 }
00163 
00164 /** Returns a list of all currently active processes, including their pid
00165  * and exe filename. */
00166 QHash<qint64, QString>
00167 win32_process_list()
00168 {
00169   QHash<qint64, QString> procList;
00170   CreateToolhelp32Snapshot_fn pCreateToolhelp32Snapshot;
00171   Process32First_fn pProcess32First;
00172   Process32Next_fn pProcess32Next;
00173   HANDLE hSnapshot;
00174   PROCESSENTRY32 proc;
00175   QString exeFile;
00176   qint64 pid;
00177 
00178   /* Load the tool help functions */
00179   pCreateToolhelp32Snapshot =
00180     (CreateToolhelp32Snapshot_fn)QLibrary::resolve("kernel32", "CreateToolhelp32Snapshot");
00181   pProcess32First = (Process32First_fn)QLibrary::resolve("kernel32", "Process32First");
00182   pProcess32Next = (Process32Next_fn)QLibrary::resolve("kernel32", "Process32Next");
00183  
00184   if (!pCreateToolhelp32Snapshot || !pProcess32First || !pProcess32Next) {
00185     qWarning("Unable to load tool help functions. Running process information "
00186              "will be unavailable.");
00187     return QHash<qint64, QString>();
00188   }
00189 
00190   /* Create a snapshot of all active processes */
00191   hSnapshot = pCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
00192   if (hSnapshot != INVALID_HANDLE_VALUE) {
00193     proc.dwSize = sizeof(PROCESSENTRY32);
00194     
00195     /* Iterate through all the processes in the snapshot */
00196     if (pProcess32First(hSnapshot, &proc)) {
00197       do {
00198         /* Extract the PID and exe filename from the process record */
00199         pid = (qint64)proc.th32ProcessID;
00200         exeFile = QString::fromAscii((const char *)proc.szExeFile);
00201         
00202         /* Add this process to our list */
00203         procList.insert(pid, exeFile);
00204       } while (pProcess32Next(hSnapshot, &proc));
00205     }
00206     CloseHandle(hSnapshot);
00207   }
00208   return procList;
00209 }
00210 

Generated on Wed Sep 5 15:49:28 2007 for Vidalia by  doxygen 1.5.3