• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

kkernel_win.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (C) 2004 Jarosław Staniek <staniek@kde.org>
00004    Copyright (C) 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de>
00005    Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
00006    Copyright (C) 2008-2009 Ralf Habacker <ralf.habacker@freenet.de>
00007 
00008    This library is free software; you can redistribute it and/or
00009    modify it under the terms of the GNU Library General Public
00010    License version 2 as published by the Free Software Foundation.
00011 
00012    This library 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 GNU
00015    Library General Public License for more details.
00016 
00017    You should have received a copy of the GNU Library General Public License
00018    along with this library; see the file COPYING.LIB.  If not, write to
00019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020    Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include "kkernel_win.h"
00024 
00025 #include <config.h>
00026 #include <QtCore/QBool>
00027 #include <QtCore/QTextCodec>
00028 
00029 #ifdef Q_OS_WIN
00030 
00031 #include "kglobal.h"
00032 #include <klocale.h>
00033 
00034 #include <QtCore/QDir>
00035 #include <QtCore/QString>
00036 #include <QtCore/QLibrary>
00037 
00038 #include <windows.h>
00039 #include <shellapi.h>
00040 #include <process.h>
00041 
00042 // console related includes
00043 #include <stdio.h>
00044 #include <fcntl.h>
00045 #include <io.h>
00046 #include <iostream>
00047 #include <fstream>
00048 #ifndef _USE_OLD_IOSTREAMS
00049 using namespace std;
00050 #endif
00051 
00052 #if defined(__MINGW32__)
00053 # define WIN32_CAST_CHAR (const WCHAR*)
00054 #else
00055 # define WIN32_CAST_CHAR (LPCWSTR)
00056 #endif
00057 
00058 #ifndef _WIN32_WCE
00059 static HINSTANCE kdecoreDllInstance = NULL;
00060 #else
00061 static HANDLE kdecoreDllInstance = NULL;
00062 #endif
00063 #ifdef KDELIBS_STATIC_LIBS
00064 static bool kde4prefixInitialized = false;
00065 #endif
00066 static wchar_t kde4prefixUtf16[MAX_PATH + 2] = L"";
00067 
00068 static QString *kde4Prefix = NULL;
00069 
00070 void initKde4prefixUtf16()
00071 {
00072     //the path is C:\some\path\kde4\bin\kdecore.dll
00073 #ifndef _WIN32_WCE
00074     GetModuleFileNameW(kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
00075 #else
00076     GetModuleFileNameW((HMODULE)kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
00077 #endif
00078     int bs1 = 0, bs2 = 0;
00079 
00080     //we convert \ to / and remove \bin\kdecore.dll from the string
00081     int pos;
00082     for (pos = 0; pos < MAX_PATH + 1 && kde4prefixUtf16[pos] != 0; ++pos) {
00083         if (kde4prefixUtf16[pos] == '\\') {
00084             bs1 = bs2;
00085             bs2 = pos;
00086             kde4prefixUtf16[pos] = '/';
00087         }
00088     }
00089     Q_ASSERT(bs1);
00090     Q_ASSERT(pos < MAX_PATH + 1);
00091     kde4prefixUtf16[bs1] = '/';
00092     kde4prefixUtf16[bs1+1] = 0;
00093 }
00094 
00095 // can't use QCoreApplication::applicationDirPath() because sometimes we
00096 // don't have an instantiated QCoreApplication
00097 QString getKde4Prefix()
00098 {
00099 #ifdef _WIN32_WCE
00100     if (kde4prefixInitialized)
00101         return QString::fromUtf16((ushort*) kde4prefixUtf16);
00102     
00103     QDir kde4prefixDir(QString::fromUtf16((ushort*) STATIC_INSTALL_PATH));
00104     if (kde4prefixDir.exists()){
00105         wcscpy(kde4prefixUtf16, STATIC_INSTALL_PATH);
00106         kde4prefixUtf16[wcslen(kde4prefixUtf16)] = 0;       
00107         kde4prefixInitialized = true;
00108         return QString::fromUtf16((ushort*) kde4prefixUtf16);
00109     } else {
00110         bool ok;
00111         QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
00112         if (!ok){
00113             return QString();
00114         } else {
00115             retval = QDir::fromNativeSeparators(retval);
00116             wcscpy(kde4prefixUtf16, retval.utf16());
00117             kde4prefixUtf16[wcslen(kde4prefixUtf16)] = 0;
00118             kde4prefixInitialized = true;
00119             return retval;
00120         }
00121     }
00122 #else
00123   // we can get called after DLL_PROCESS_DETACH!
00124   return kde4Prefix ? *kde4Prefix : QString::fromUtf16((ushort*) kde4prefixUtf16);
00125 #endif
00126 }
00127 
00128 #ifndef KDELIBS_STATIC_LIBS
00129 
00133 extern "C"
00134 #ifndef _WIN32_WCE
00135 BOOL WINAPI DllMain ( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
00136 #else
00137 BOOL WINAPI DllMain ( HANDLE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
00138 #endif
00139 {
00140     switch ( fdwReason ) {
00141     case DLL_PROCESS_ATTACH:
00142         kdecoreDllInstance = hinstDLL;
00143         initKde4prefixUtf16();
00144         kde4Prefix = new QString( QString::fromUtf16((ushort*) kde4prefixUtf16) );
00145         break;
00146     case DLL_PROCESS_DETACH:
00147         /* msdn:
00148            When handling DLL_PROCESS_DETACH, a DLL should free resources such
00149            as heap memory only if the DLL is being unloaded dynamically (the
00150            lpReserved parameter is NULL). If the process is terminating (the
00151            lpvReserved parameter is non-NULL), all threads in the process except
00152            the current thread either have exited already or have been explicitly
00153            terminated by a call to the ExitProcess function, which might leave
00154            some process resources such as heaps in an inconsistent state. In this
00155            case, it is not safe for the DLL to clean up the resources. Instead,
00156            the DLL should allow the operating system to reclaim the memory.
00157          */
00158         if( lpReserved == NULL )
00159             delete kde4Prefix;
00160         kde4Prefix = 0;
00161         break;
00162     default:
00163         break;
00164     }
00165     return true;
00166 }
00167 
00168 #endif
00169 
00180 QString getWin32RegistryValue ( HKEY key, const QString& subKey, const QString& item, bool *ok )
00181 {
00182 #define FAILURE \
00183  { if (ok) \
00184   *ok = false; \
00185  return QString(); }
00186 
00187     if ( subKey.isEmpty() )
00188         FAILURE;
00189     HKEY hKey;
00190     TCHAR *lszValue;
00191     DWORD dwType=REG_SZ;
00192     DWORD dwSize;
00193 
00194     if ( ERROR_SUCCESS!=RegOpenKeyExW ( key, WIN32_CAST_CHAR subKey.utf16(), 0, KEY_READ, &hKey ) )
00195         FAILURE;
00196 
00197     if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, NULL, NULL, &dwSize ) )
00198         FAILURE;
00199 
00200     lszValue = new TCHAR[dwSize];
00201 
00202     if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, &dwType, ( LPBYTE ) lszValue, &dwSize ) ) {
00203         delete [] lszValue;
00204         FAILURE;
00205     }
00206     RegCloseKey ( hKey );
00207 
00208     QString res = QString::fromUtf16 ( ( const ushort* ) lszValue );
00209     delete [] lszValue;
00210     
00211     if (ok)
00212         *ok = true;
00213     
00214     return res;
00215 }
00216 
00217 
00218 bool showWin32FilePropertyDialog ( const QString& fileName )
00219 {
00220     QString path_ = QDir::convertSeparators ( QFileInfo ( fileName ).absoluteFilePath() );
00221 
00222 #ifndef _WIN32_WCE
00223     SHELLEXECUTEINFOW execInfo;
00224 #else
00225     SHELLEXECUTEINFO execInfo;
00226 #endif
00227     memset ( &execInfo,0,sizeof ( execInfo ) );
00228     execInfo.cbSize = sizeof ( execInfo );
00229 #ifndef _WIN32_WCE
00230     execInfo.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
00231 #else
00232     execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
00233 #endif
00234     const QString verb ( QLatin1String ( "properties" ) );
00235     execInfo.lpVerb = WIN32_CAST_CHAR verb.utf16();
00236     execInfo.lpFile = WIN32_CAST_CHAR path_.utf16();
00237 #ifndef _WIN32_WCE
00238     return ShellExecuteExW ( &execInfo );
00239 #else
00240     return ShellExecuteEx ( &execInfo );
00241     //There is no native file property dialog in wince
00242    // return false;
00243 #endif
00244 }
00245 
00246 // note: QLocale().name().left(2).toLatin1() returns the same
00247 
00248 QByteArray getWin32LocaleName()
00249 {
00250     bool ok;
00251     QString localeNumber = getWin32RegistryValue ( HKEY_CURRENT_USER,
00252                            QLatin1String("Control Panel\\International"),
00253                            QLatin1String("Locale"), &ok );
00254     if ( !ok )
00255         return QByteArray();
00256     QString localeName = getWin32RegistryValue ( HKEY_LOCAL_MACHINE,
00257                          QLatin1String("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout\\DosKeybCodes"),
00258                          localeNumber, &ok );
00259     if ( !ok )
00260         return QByteArray();
00261     return localeName.toLatin1();
00262 }
00263 
00267 QString getWin32ShellFoldersPath ( const QString& folder )
00268 {
00269     return getWin32RegistryValue ( HKEY_CURRENT_USER,
00270                                    QLatin1String("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"),
00271                                    folder );
00272 }
00273 
00277 static void kMessageOutputDebugString(QtMsgType type, const char *msg)
00278 {
00279     int BUFSIZE=4096;
00280     char *buf = new char[BUFSIZE];
00281     switch (type) {
00282         case QtDebugMsg:
00283             strlcpy(buf,"Debug:",BUFSIZE);
00284             strlcat(buf,msg,BUFSIZE);
00285             break;
00286         case QtWarningMsg:
00287             strlcpy(buf,"Warning:",BUFSIZE);
00288             strlcat(buf,msg,BUFSIZE);
00289             break;
00290         case QtCriticalMsg:
00291             strlcpy(buf,"Critical:",BUFSIZE);
00292             strlcat(buf,msg,BUFSIZE);
00293             break;
00294         case QtFatalMsg:
00295             strlcpy(buf,"Fatal:",BUFSIZE);
00296             strlcat(buf,msg,BUFSIZE);
00297             //abort();
00298             break;
00299     }
00300     strlcat(buf,"\n",BUFSIZE);
00301     OutputDebugStringW( (WCHAR*)QString::fromAscii(buf).utf16());
00302     delete[] buf;
00303 }
00304 
00308 static void kMessageOutputFileIO(QtMsgType type, const char *msg)
00309 {
00310     switch (type) {
00311     case QtDebugMsg:
00312         fprintf(stderr, "Debug: %s\n", msg);
00313         break;
00314     case QtWarningMsg:
00315         fprintf(stderr, "Warning: %s\n", msg);
00316         break;
00317     case QtCriticalMsg:
00318         fprintf(stderr, "Critical: %s\n", msg);
00319         break;
00320     case QtFatalMsg:
00321         fprintf(stderr, "Fatal: %s\n", msg);
00322         //abort();
00323     }
00324 }
00325 
00330 typedef BOOL (WINAPI*attachConsolePtr)(DWORD dwProcessId);
00331 static attachConsolePtr attachConsole = 0;
00332 static bool attachConsoleResolved = false;
00333 static bool attachToConsole()
00334 {
00335     if(!attachConsoleResolved) {
00336       attachConsoleResolved = true;
00337       attachConsole = (attachConsolePtr)QLibrary::resolve(QLatin1String("kernel32"), "AttachConsole");
00338     }
00339     return attachConsole ? attachConsole(~0U) != 0 : false;
00340 }
00341 
00346 static void redirectToConsole()
00347 {
00348 //FIXME: for wince we cannot set stdio buffers
00349 #ifndef _WIN32_WCE
00350     int hCrt;
00351     FILE *hf;
00352     int i;
00353     
00354     hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_INPUT_HANDLE),_O_TEXT);
00355     if(hCrt != -1) {
00356         hf = _fdopen( hCrt, "r" );
00357         *stdin = *hf;
00358         i = setvbuf( stdin, NULL, _IONBF, 0 );
00359     }
00360 
00361     hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
00362     if(hCrt != -1) {
00363         hf = _fdopen( hCrt, "w" );
00364         *stdout = *hf;
00365         i = setvbuf( stdout, NULL, _IONBF, 0 );
00366     }
00367 
00368     hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE),_O_TEXT);
00369     if(hCrt != -1) {
00370         hf = _fdopen( hCrt, "w" );
00371         *stderr = *hf;
00372         i = setvbuf( stderr, NULL, _IONBF, 0 );
00373     }
00374     // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
00375     // point to console as well
00376     ios::sync_with_stdio();
00377 #endif
00378 }
00379 
00380 #include <streambuf>
00381 
00385 class debug_streambuf: public std::streambuf
00386 {
00387     public:
00388         debug_streambuf(const char *prefix)
00389         {
00390             strcpy(buf,prefix);
00391             index = rindex = strlen(buf);
00392         }
00393 
00394     protected:
00395         virtual int overflow(int c = EOF)
00396         {
00397             if (c != EOF)
00398             {
00399                 char cc = traits_type::to_char_type(c);
00400                 // @TODO: buffer size checking
00401                 buf[index++] = cc;
00402                 if (cc == '\n')
00403                 {
00404                     buf[index] = '\0';
00405                     OutputDebugStringW((WCHAR*)QString::fromAscii(buf).utf16());
00406                     index = rindex;
00407                 }
00408             }
00409             return traits_type::not_eof(c);
00410         }
00411     private:
00412         char buf[4096];
00413         int index, rindex;
00414 };
00415 
00420 static int subSystem()
00421 {
00422 #ifdef _WIN32_WCE
00423     // there is only one subsystem on Windows CE
00424     return IMAGE_SUBSYSTEM_WINDOWS_CE_GUI;
00425 #else
00426     static int subSystem = -1;
00427     if (subSystem > -1)
00428         return subSystem; 
00429 
00430     // get base address of memory mapped executable
00431     PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
00432     PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS) ((char *)dosHeader + dosHeader->e_lfanew);
00433     if (ntHeader->Signature != 0x00004550) 
00434     {
00435         subSystem = IMAGE_SUBSYSTEM_UNKNOWN;
00436         return subSystem;
00437     }
00438     subSystem = ntHeader->OptionalHeader.Subsystem;
00439     return subSystem;
00440 #endif
00441 }
00442     
00471 static class kMessageOutputInstaller {
00472     public:
00473         kMessageOutputInstaller() : stdoutBuffer("stdout:"), stderrBuffer("stderr:"), oldStdoutBuffer(0), oldStderrBuffer(0)
00474         {
00475             if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
00476                 if (attachToConsole()) {
00477                     // setup kde and qt level 
00478                     qInstallMsgHandler(kMessageOutputFileIO);
00479                     // redirect ios and file io to console
00480                     redirectToConsole();
00481                 }
00482                 else {
00483                     // setup kde and qt level 
00484                     qInstallMsgHandler(kMessageOutputDebugString);
00485                     // redirect ios to debug message port 
00486                     oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00487                     oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00488                 }
00489             }
00490             else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
00491                 // setup kde and qt level 
00492                 qInstallMsgHandler(kMessageOutputDebugString);
00493                 // try to get a console
00494                 if (attachToConsole()) {
00495                     redirectToConsole();
00496                 }
00497                 else {
00498                     // redirect ios to debug message port
00499                     oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00500                     oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00501                     // TODO: redirect FILE * level to console, no idea how to do yet
00502                 }
00503             } else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_CE_GUI) {
00504                 // do not try to get a console on WinCE systems
00505                 qInstallMsgHandler(kMessageOutputDebugString);
00506                 oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00507                 oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00508             }
00509             else
00510                 qWarning("unknown subsystem %d detected, could not setup qt message handler",subSystem());
00511         }
00512         ~kMessageOutputInstaller()
00513         {
00514             if (oldStdoutBuffer) 
00515                 std::cout.rdbuf(oldStdoutBuffer);
00516             if (oldStderrBuffer) 
00517                 std::cerr.rdbuf(oldStderrBuffer);
00518         }
00519     
00520     private:
00521         debug_streambuf stdoutBuffer;
00522         debug_streambuf stderrBuffer;
00523         std::streambuf* oldStdoutBuffer;
00524         std::streambuf* oldStderrBuffer;
00525 
00526 } kMessageOutputInstallerInstance;
00527 
00528 
00529 bool isExecutable(const QString &file)
00530 {
00531   return ( file.endsWith( QLatin1String( ".exe" ) ) ||
00532            file.endsWith( QLatin1String( ".com" ) ) ||
00533            file.endsWith( QLatin1String( ".bat" ) ) ||
00534            file.endsWith( QLatin1String( ".sln" ) ) ||
00535            file.endsWith( QLatin1String( ".lnk" ) ) );
00536 
00537 }
00538 
00539 #endif  // Q_OS_WIN

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal