• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • 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 static HINSTANCE kdecoreDllInstance = NULL;
00059 static wchar_t kde4prefixUtf16[MAX_PATH + 2];
00060 static QString *kde4Prefix = NULL;
00061 
00062 void initKde4prefixUtf16()
00063 {
00064     //the path is C:\some\path\kde4\bin\kdecore.dll
00065     GetModuleFileNameW(kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
00066     int bs1 = 0, bs2 = 0;
00067 
00068     //we convert \ to / and remove \bin\kdecore.dll from the string
00069     int pos;
00070     for (pos = 0; pos < MAX_PATH + 1 && kde4prefixUtf16[pos] != 0; ++pos) {
00071         if (kde4prefixUtf16[pos] == '\\') {
00072             bs1 = bs2;
00073             bs2 = pos;
00074             kde4prefixUtf16[pos] = '/';
00075         }
00076     }
00077     Q_ASSERT(bs1);
00078     Q_ASSERT(pos < MAX_PATH + 1);
00079     kde4prefixUtf16[bs1] = '/';
00080     kde4prefixUtf16[bs1+1] = 0;
00081 }
00082 
00083 // can't use QCoreApplication::applicationDirPath() because sometimes we
00084 // don't have an instantiated QCoreApplication
00085 QString getKde4Prefix()
00086 {
00087   // we can get called after DLL_PROCESS_DETACH!
00088   return kde4Prefix ? *kde4Prefix : QString::fromUtf16((ushort*) kde4prefixUtf16);
00089 }
00090 
00095 extern "C"
00096 BOOL WINAPI DllMain ( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
00097 {
00098     switch ( fdwReason ) {
00099     case DLL_PROCESS_ATTACH:
00100         kdecoreDllInstance = hinstDLL;
00101         initKde4prefixUtf16();
00102         kde4Prefix = new QString( QString::fromUtf16((ushort*) kde4prefixUtf16) );
00103         break;
00104     case DLL_PROCESS_DETACH:
00105         /* msdn:
00106            When handling DLL_PROCESS_DETACH, a DLL should free resources such
00107            as heap memory only if the DLL is being unloaded dynamically (the
00108            lpReserved parameter is NULL). If the process is terminating (the
00109            lpvReserved parameter is non-NULL), all threads in the process except
00110            the current thread either have exited already or have been explicitly
00111            terminated by a call to the ExitProcess function, which might leave
00112            some process resources such as heaps in an inconsistent state. In this
00113            case, it is not safe for the DLL to clean up the resources. Instead,
00114            the DLL should allow the operating system to reclaim the memory.
00115          */
00116         if( lpReserved == NULL )
00117             delete kde4Prefix;
00118         kde4Prefix = 0;
00119         break;
00120     default:
00121         break;
00122     }
00123     return true;
00124 }
00125 
00136 QString getWin32RegistryValue ( HKEY key, const QString& subKey, const QString& item, bool *ok = 0 )
00137 {
00138 #define FAILURE \
00139  { if (ok) \
00140   *ok = false; \
00141  return QString(); }
00142 
00143     if ( subKey.isEmpty() )
00144         FAILURE;
00145     HKEY hKey;
00146     TCHAR *lszValue;
00147     DWORD dwType=REG_SZ;
00148     DWORD dwSize;
00149 
00150     if ( ERROR_SUCCESS!=RegOpenKeyExW ( key, WIN32_CAST_CHAR subKey.utf16(), 0, KEY_READ, &hKey ) )
00151         FAILURE;
00152 
00153     if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, NULL, NULL, &dwSize ) )
00154         FAILURE;
00155 
00156     lszValue = new TCHAR[dwSize];
00157 
00158     if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, &dwType, ( LPBYTE ) lszValue, &dwSize ) ) {
00159         delete [] lszValue;
00160         FAILURE;
00161     }
00162     RegCloseKey ( hKey );
00163 
00164     QString res = QString::fromUtf16 ( ( const ushort* ) lszValue );
00165     delete [] lszValue;
00166     return res;
00167 }
00168 
00169 
00170 bool showWin32FilePropertyDialog ( const QString& fileName )
00171 {
00172     QString path_ = QDir::convertSeparators ( QFileInfo ( fileName ).absoluteFilePath() );
00173 
00174     SHELLEXECUTEINFOW execInfo;
00175     memset ( &execInfo,0,sizeof ( execInfo ) );
00176     execInfo.cbSize = sizeof ( execInfo );
00177     execInfo.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
00178     const QString verb ( QLatin1String ( "properties" ) );
00179     execInfo.lpVerb = WIN32_CAST_CHAR verb.utf16();
00180     execInfo.lpFile = WIN32_CAST_CHAR path_.utf16();
00181     return ShellExecuteExW ( &execInfo );
00182 }
00183 
00184 // note: QLocale().name().left(2).toLatin1() returns the same
00185 
00186 QByteArray getWin32LocaleName()
00187 {
00188     bool ok;
00189     QString localeNumber = getWin32RegistryValue ( HKEY_CURRENT_USER,
00190                            QLatin1String("Control Panel\\International"),
00191                            "Locale", &ok );
00192     if ( !ok )
00193         return QByteArray();
00194     QString localeName = getWin32RegistryValue ( HKEY_LOCAL_MACHINE,
00195                          QLatin1String("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout\\DosKeybCodes"),
00196                          localeNumber, &ok );
00197     if ( !ok )
00198         return QByteArray();
00199     return localeName.toLatin1();
00200 }
00201 
00205 QString getWin32ShellFoldersPath ( const QString& folder )
00206 {
00207     return getWin32RegistryValue ( HKEY_CURRENT_USER,
00208                                    QLatin1String("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"),
00209                                    folder );
00210 }
00211 
00215 static void kMessageOutputDebugString(QtMsgType type, const char *msg)
00216 {
00217     int BUFSIZE=4096;
00218     char *buf = new char[BUFSIZE];
00219     switch (type) {
00220         case QtDebugMsg:
00221             strlcpy(buf,"Debug:",BUFSIZE);
00222             strlcat(buf,msg,BUFSIZE);
00223             break;
00224         case QtWarningMsg:
00225             strlcpy(buf,"Warning:",BUFSIZE);
00226             strlcat(buf,msg,BUFSIZE);
00227             break;
00228         case QtCriticalMsg:
00229             strlcpy(buf,"Critical:",BUFSIZE);
00230             strlcat(buf,msg,BUFSIZE);
00231             break;
00232         case QtFatalMsg:
00233             strlcpy(buf,"Fatal:",BUFSIZE);
00234             strlcat(buf,msg,BUFSIZE);
00235             //abort();
00236             break;
00237     }
00238     strlcat(buf,"\n",BUFSIZE);
00239     OutputDebugStringA(buf);
00240     delete[] buf;
00241 }
00242 
00246 static void kMessageOutputFileIO(QtMsgType type, const char *msg)
00247 {
00248     switch (type) {
00249     case QtDebugMsg:
00250         fprintf(stderr, "Debug: %s\n", msg);
00251         break;
00252     case QtWarningMsg:
00253         fprintf(stderr, "Warning: %s\n", msg);
00254         break;
00255     case QtCriticalMsg:
00256         fprintf(stderr, "Critical: %s\n", msg);
00257         break;
00258     case QtFatalMsg:
00259         fprintf(stderr, "Fatal: %s\n", msg);
00260         //abort();
00261     }
00262 }
00263 
00268 typedef BOOL (WINAPI*attachConsolePtr)(DWORD dwProcessId);
00269 static attachConsolePtr attachConsole = 0;
00270 static bool attachConsoleResolved = false;
00271 static bool attachToConsole()
00272 {
00273     if(!attachConsoleResolved) {
00274       attachConsoleResolved = true;
00275       attachConsole = (attachConsolePtr)QLibrary::resolve(QLatin1String("kernel32"), "AttachConsole");
00276     }
00277     return attachConsole ? attachConsole(~0U) != 0 : false;
00278 }
00279 
00284 static void redirectToConsole()
00285 {
00286     int hCrt;
00287     FILE *hf;
00288     int i;
00289     
00290     hCrt = _open_osfhandle((long) GetStdHandle(STD_INPUT_HANDLE),_O_TEXT);
00291     if(hCrt != -1) {
00292         hf = _fdopen( hCrt, "r" );
00293         *stdin = *hf;
00294         i = setvbuf( stdin, NULL, _IONBF, 0 );
00295     }
00296 
00297     hCrt = _open_osfhandle((long) GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
00298     if(hCrt != -1) {
00299         hf = _fdopen( hCrt, "w" );
00300         *stdout = *hf;
00301         i = setvbuf( stdout, NULL, _IONBF, 0 );
00302     }
00303 
00304     hCrt = _open_osfhandle((long) GetStdHandle(STD_ERROR_HANDLE),_O_TEXT);
00305     if(hCrt != -1) {
00306         hf = _fdopen( hCrt, "w" );
00307         *stderr = *hf;
00308         i = setvbuf( stderr, NULL, _IONBF, 0 );
00309     }
00310     // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
00311     // point to console as well
00312     ios::sync_with_stdio();
00313 }
00314 
00315 #include <streambuf>
00316 
00320 class debug_streambuf: public std::streambuf
00321 {
00322     public:
00323         debug_streambuf(char *prefix)
00324         {
00325             strcpy(buf,prefix);
00326             index = rindex = strlen(buf);
00327         }
00328 
00329     protected:
00330         virtual int overflow(int c = EOF)
00331         {
00332             if (c != EOF)
00333             {
00334                 char cc = traits_type::to_char_type(c);
00335                 // @TODO: buffer size checking
00336                 buf[index++] = cc;
00337                 if (cc == '\n')
00338                 {
00339                     buf[index] = '\0';
00340                     OutputDebugStringA((LPCSTR)buf);
00341                     index = rindex;
00342                 }
00343             }
00344             return traits_type::not_eof(c);
00345         }
00346     private:
00347         char buf[4096];
00348         int index, rindex;
00349 };
00350 
00355 static int subSystem()
00356 {
00357     static int subSystem = -1;
00358     if (subSystem > -1)
00359         return subSystem; 
00360 
00361     // get base address of memory mapped executable
00362     PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
00363     PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS) ((char *)dosHeader + dosHeader->e_lfanew);
00364     if (ntHeader->Signature != 0x00004550) 
00365     {
00366         subSystem = IMAGE_SUBSYSTEM_UNKNOWN;
00367         return subSystem;
00368     }
00369     subSystem = ntHeader->OptionalHeader.Subsystem;
00370     return subSystem;
00371 }
00372     
00399 static class kMessageOutputInstaller {
00400     public:
00401         kMessageOutputInstaller() : stdoutBuffer("stdout:"), stderrBuffer("stderr:"), oldStdoutBuffer(0), oldStderrBuffer(0)
00402         {
00403             if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
00404                 if (attachToConsole()) {
00405                     // setup kde and qt level 
00406                     qInstallMsgHandler(kMessageOutputFileIO);
00407                     // redirect ios and file io to console
00408                     redirectToConsole();
00409                 }
00410                 else {
00411                     // setup kde and qt level 
00412                     qInstallMsgHandler(kMessageOutputDebugString);
00413                     // redirect ios to debug message port 
00414                     oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00415                     oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00416                 }
00417             }
00418             else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
00419                 // setup kde and qt level 
00420                 qInstallMsgHandler(kMessageOutputDebugString);
00421                 // try to get a console
00422                 if (attachToConsole()) {
00423                     redirectToConsole();
00424                 }
00425                 else {
00426                     // redirect ios to debug message port
00427                     oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00428                     oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00429                     // TODO: redirect FILE * level to console, no idea how to do yet
00430                 }
00431             }
00432             else
00433                 qWarning("unknown subsystem %d detected, could not setup qt message handler",subSystem());
00434         }
00435         ~kMessageOutputInstaller()
00436         {
00437             if (oldStdoutBuffer) 
00438                 std::cout.rdbuf(oldStdoutBuffer);
00439             if (oldStderrBuffer) 
00440                 std::cerr.rdbuf(oldStderrBuffer);
00441         }
00442     
00443     private:
00444         debug_streambuf stdoutBuffer;
00445         debug_streambuf stderrBuffer;
00446         std::streambuf* oldStdoutBuffer;
00447         std::streambuf* oldStderrBuffer;
00448 
00449 } kMessageOutputInstallerInstance;
00450 
00451 
00452 bool isExecutable(const QString &file)
00453 {
00454   return ( file.endsWith( QLatin1String( ".exe" ) ) ||
00455            file.endsWith( QLatin1String( ".com" ) ) ||
00456            file.endsWith( QLatin1String( ".bat" ) ) ||
00457            file.endsWith( QLatin1String( ".sln" ) ) ||
00458            file.endsWith( QLatin1String( ".lnk" ) ) );
00459 
00460 }
00461 
00462 #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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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