ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

win32.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 // Disable symbol overrides so that we can use system headers.
00024 #define FORBIDDEN_SYMBOL_ALLOW_ALL
00025 
00026 #ifdef WIN32
00027 
00028 #define WIN32_LEAN_AND_MEAN
00029 #include <windows.h>
00030 #include <shellapi.h>
00031 #if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
00032 // required for SHGFP_TYPE_CURRENT in shlobj.h
00033 #define _WIN32_IE 0x500
00034 #endif
00035 #include <shlobj.h>
00036 
00037 #include "common/scummsys.h"
00038 #include "common/config-manager.h"
00039 #include "common/error.h"
00040 #include "common/textconsole.h"
00041 
00042 #include "backends/audiocd/win32/win32-audiocd.h"
00043 #include "backends/platform/sdl/win32/win32.h"
00044 #include "backends/platform/sdl/win32/win32-window.h"
00045 #include "backends/platform/sdl/win32/win32_wrapper.h"
00046 #include "backends/saves/windows/windows-saves.h"
00047 #include "backends/fs/windows/windows-fs-factory.h"
00048 #include "backends/taskbar/win32/win32-taskbar.h"
00049 #include "backends/updates/win32/win32-updates.h"
00050 #include "backends/dialogs/win32/win32-dialogs.h"
00051 
00052 #include "common/memstream.h"
00053 
00054 #define DEFAULT_CONFIG_FILE "residualvm.ini"
00055 
00056 void OSystem_Win32::init() {
00057     // Initialize File System Factory
00058     _fsFactory = new WindowsFilesystemFactory();
00059 
00060     // Create Win32 specific window
00061     _window = new SdlWindow_Win32();
00062 
00063 #if defined(USE_TASKBAR)
00064     // Initialize taskbar manager
00065     _taskbarManager = new Win32TaskbarManager((SdlWindow_Win32*)_window);
00066 #endif
00067 
00068 #if defined(USE_SYSDIALOGS)
00069     // Initialize dialog manager
00070     _dialogManager = new Win32DialogManager((SdlWindow_Win32*)_window);
00071 #endif
00072 
00073     // Invoke parent implementation of this method
00074     OSystem_SDL::init();
00075 }
00076 
00077 void OSystem_Win32::initBackend() {
00078     // Console window is enabled by default on Windows
00079     ConfMan.registerDefault("console", true);
00080 
00081     // Enable or disable the window console window
00082     if (ConfMan.getBool("console")) {
00083         if (AllocConsole()) {
00084             freopen("CONIN$","r",stdin);
00085             freopen("CONOUT$","w",stdout);
00086             freopen("CONOUT$","w",stderr);
00087         }
00088         SetConsoleTitle("ResidualVM Status Window");
00089     } else {
00090         FreeConsole();
00091     }
00092 
00093     // Create the savefile manager
00094     if (_savefileManager == 0)
00095         _savefileManager = new WindowsSaveFileManager();
00096 
00097 #if defined(USE_SPARKLE)
00098     // Initialize updates manager
00099     _updateManager = new Win32UpdateManager();
00100 #endif
00101 
00102     // Invoke parent implementation of this method
00103     OSystem_SDL::initBackend();
00104 }
00105 
00106 
00107 bool OSystem_Win32::hasFeature(Feature f) {
00108     if (f == kFeatureDisplayLogFile || f == kFeatureOpenUrl)
00109         return true;
00110 
00111 #ifdef USE_SYSDIALOGS
00112     if (f == kFeatureSystemBrowserDialog)
00113         return true;
00114 #endif
00115 
00116     return OSystem_SDL::hasFeature(f);
00117 }
00118 
00119 bool OSystem_Win32::displayLogFile() {
00120     if (_logFilePath.empty())
00121         return false;
00122 
00123     // Try opening the log file with the default text editor
00124     // log files should be registered as "txtfile" by default and thus open in the default text editor
00125     HINSTANCE shellExec = ShellExecute(NULL, NULL, _logFilePath.c_str(), NULL, NULL, SW_SHOWNORMAL);
00126     if ((intptr_t)shellExec > 32)
00127         return true;
00128 
00129     // ShellExecute with the default verb failed, try the "Open with..." dialog
00130     PROCESS_INFORMATION processInformation;
00131     STARTUPINFO startupInfo;
00132     memset(&processInformation, 0, sizeof(processInformation));
00133     memset(&startupInfo, 0, sizeof(startupInfo));
00134     startupInfo.cb = sizeof(startupInfo);
00135 
00136     char cmdLine[MAX_PATH * 2];  // CreateProcess may change the contents of cmdLine
00137     sprintf(cmdLine, "rundll32 shell32.dll,OpenAs_RunDLL %s", _logFilePath.c_str());
00138     BOOL result = CreateProcess(NULL,
00139                                 cmdLine,
00140                                 NULL,
00141                                 NULL,
00142                                 FALSE,
00143                                 NORMAL_PRIORITY_CLASS,
00144                                 NULL,
00145                                 NULL,
00146                                 &startupInfo,
00147                                 &processInformation);
00148     if (result)
00149         return true;
00150 
00151     return false;
00152 }
00153 
00154 bool OSystem_Win32::openUrl(const Common::String &url) {
00155     const uint64 result = (uint64)ShellExecute(0, 0, /*(wchar_t*)nativeFilePath.utf16()*/url.c_str(), 0, 0, SW_SHOWNORMAL);
00156     // ShellExecute returns a value greater than 32 if successful
00157     if (result <= 32) {
00158         warning("ShellExecute failed: error = %u", result);
00159         return false;
00160     }
00161     return true;
00162 }
00163 
00164 void OSystem_Win32::logMessage(LogMessageType::Type type, const char *message) {
00165     OSystem_SDL::logMessage(type, message);
00166 
00167 #if defined( USE_WINDBG )
00168     OutputDebugString(message);
00169 #endif
00170 }
00171 
00172 Common::String OSystem_Win32::getSystemLanguage() const {
00173 #if defined(USE_DETECTLANG) && defined(USE_TRANSLATION)
00174     // We can not use "setlocale" (at least not for MSVC builds), since it
00175     // will return locales like: "English_USA.1252", thus we need a special
00176     // way to determine the locale string for Win32.
00177     char langName[9];
00178     char ctryName[9];
00179 
00180     if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 &&
00181         GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) {
00182         Common::String localeName = langName;
00183         localeName += "_";
00184         localeName += ctryName;
00185 
00186         return localeName;
00187     }
00188 #endif // USE_DETECTLANG
00189     // Falback to SDL implementation
00190     return OSystem_SDL::getSystemLanguage();
00191 }
00192 
00193 Common::String OSystem_Win32::getScreenshotsPath() {
00194     Common::String screenshotsPath = ConfMan.get("screenshotpath");
00195     if (!screenshotsPath.empty()) {
00196         if (!screenshotsPath.hasSuffix("\\") && !screenshotsPath.hasSuffix("/"))
00197             screenshotsPath += "\\";
00198         return screenshotsPath;
00199     }
00200 
00201     // Use the My Pictures folder.
00202     char picturesPath[MAXPATHLEN];
00203 
00204     if (SHGetFolderPathFunc(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, picturesPath) != S_OK) {
00205         warning("Unable to access My Pictures directory");
00206         return Common::String();
00207     }
00208 
00209     screenshotsPath = Common::String(picturesPath) + "\\ResidualVM Screenshots\\";
00210 
00211     // If the directory already exists (as it should in most cases),
00212     // we don't want to fail, but we need to stop on other errors (such as ERROR_PATH_NOT_FOUND)
00213     if (!CreateDirectory(screenshotsPath.c_str(), NULL)) {
00214         if (GetLastError() != ERROR_ALREADY_EXISTS)
00215             error("Cannot create ResidualVM Screenshots folder");
00216     }
00217 
00218     return screenshotsPath;
00219 }
00220 
00221 Common::String OSystem_Win32::getDefaultConfigFileName() {
00222     char configFile[MAXPATHLEN];
00223 
00224     // Use the Application Data directory of the user profile.
00225     if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, configFile) == S_OK) {
00226         strcat(configFile, "\\ResidualVM");
00227         if (!CreateDirectory(configFile, NULL)) {
00228             if (GetLastError() != ERROR_ALREADY_EXISTS)
00229                 error("Cannot create ResidualVM application data folder");
00230         }
00231 
00232         strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
00233 
00234         FILE *tmp = NULL;
00235         if ((tmp = fopen(configFile, "r")) == NULL) {
00236             // Check windows directory
00237             char oldConfigFile[MAXPATHLEN];
00238             uint ret = GetWindowsDirectory(oldConfigFile, MAXPATHLEN);
00239             if (ret == 0 || ret > MAXPATHLEN)
00240                 error("Cannot retrieve the path of the Windows directory");
00241 
00242             strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE);
00243             if ((tmp = fopen(oldConfigFile, "r"))) {
00244                 strcpy(configFile, oldConfigFile);
00245 
00246                 fclose(tmp);
00247             }
00248         } else {
00249             fclose(tmp);
00250         }
00251     } else {
00252         warning("Unable to access application data directory");
00253         // Check windows directory
00254         uint ret = GetWindowsDirectory(configFile, MAXPATHLEN);
00255         if (ret == 0 || ret > MAXPATHLEN)
00256             error("Cannot retrieve the path of the Windows directory");
00257 
00258         strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
00259     }
00260 
00261     return configFile;
00262 }
00263 
00264 Common::WriteStream *OSystem_Win32::createLogFile() {
00265     // Start out by resetting _logFilePath, so that in case
00266     // of a failure, we know that no log file is open.
00267     _logFilePath.clear();
00268 
00269     char logFile[MAXPATHLEN];
00270 
00271     // Use the Application Data directory of the user profile.
00272     if (SHGetFolderPathFunc(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, logFile) == S_OK) {
00273         strcat(logFile, "\\ResidualVM");
00274         CreateDirectory(logFile, NULL);
00275         strcat(logFile, "\\Logs");
00276         CreateDirectory(logFile, NULL);
00277         strcat(logFile, "\\residualvm.log");
00278 
00279         Common::FSNode file(logFile);
00280         Common::WriteStream *stream = file.createWriteStream();
00281         if (stream)
00282             _logFilePath= logFile;
00283 
00284         return stream;
00285     } else {
00286         warning("Unable to access application data directory");
00287         return 0;
00288     }
00289 }
00290 
00291 namespace {
00292 
00293 class Win32ResourceArchive : public Common::Archive {
00294     friend BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam);
00295 public:
00296     Win32ResourceArchive();
00297 
00298     virtual bool hasFile(const Common::String &name) const;
00299     virtual int listMembers(Common::ArchiveMemberList &list) const;
00300     virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
00301     virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
00302 private:
00303     typedef Common::List<Common::String> FilenameList;
00304 
00305     FilenameList _files;
00306 };
00307 
00308 BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam) {
00309     if (IS_INTRESOURCE(lpszName))
00310         return TRUE;
00311 
00312     Win32ResourceArchive *arch = (Win32ResourceArchive *)lParam;
00313     arch->_files.push_back(lpszName);
00314     return TRUE;
00315 }
00316 
00317 Win32ResourceArchive::Win32ResourceArchive() {
00318     EnumResourceNames(NULL, MAKEINTRESOURCE(256), &EnumResNameProc, (LONG_PTR)this);
00319 }
00320 
00321 bool Win32ResourceArchive::hasFile(const Common::String &name) const {
00322     for (FilenameList::const_iterator i = _files.begin(); i != _files.end(); ++i) {
00323         if (i->equalsIgnoreCase(name))
00324             return true;
00325     }
00326 
00327     return false;
00328 }
00329 
00330 int Win32ResourceArchive::listMembers(Common::ArchiveMemberList &list) const {
00331     int count = 0;
00332 
00333     for (FilenameList::const_iterator i = _files.begin(); i != _files.end(); ++i, ++count)
00334         list.push_back(Common::ArchiveMemberPtr(new Common::GenericArchiveMember(*i, this)));
00335 
00336     return count;
00337 }
00338 
00339 const Common::ArchiveMemberPtr Win32ResourceArchive::getMember(const Common::String &name) const {
00340     return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
00341 }
00342 
00343 Common::SeekableReadStream *Win32ResourceArchive::createReadStreamForMember(const Common::String &name) const {
00344     HRSRC resource = FindResource(NULL, name.c_str(), MAKEINTRESOURCE(256));
00345 
00346     if (resource == NULL)
00347         return 0;
00348 
00349     HGLOBAL handle = LoadResource(NULL, resource);
00350 
00351     if (handle == NULL)
00352         return 0;
00353 
00354     const byte *data = (const byte *)LockResource(handle);
00355 
00356     if (data == NULL)
00357         return 0;
00358 
00359     uint32 size = SizeofResource(NULL, resource);
00360 
00361     if (size == 0)
00362         return 0;
00363 
00364     return new Common::MemoryReadStream(data, size);
00365 }
00366 
00367 } // End of anonymous namespace
00368 
00369 void OSystem_Win32::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
00370     s.add("Win32Res", new Win32ResourceArchive(), priority);
00371 
00372     OSystem_SDL::addSysArchivesToSearchSet(s, priority);
00373 }
00374 
00375 AudioCDManager *OSystem_Win32::createAudioCDManager() {
00376     return createWin32AudioCDManager();
00377 }
00378 
00379 #endif


Generated on Sat May 18 2019 05:01:30 for ResidualVM by doxygen 1.7.1
curved edge   curved edge