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

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • kernel
kkernel_win.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3  Copyright (C) 2004 JarosÅ‚aw Staniek <staniek@kde.org>
4  Copyright (C) 2007 Christian Ehrlicher <ch.ehrlicher@gmx.de>
5  Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de>
6  Copyright (C) 2008-2009 Ralf Habacker <ralf.habacker@freenet.de>
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License version 2 as published by the Free Software Foundation.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "kkernel_win.h"
24 
25 #include <config.h>
26 #include <QtCore/QBool>
27 #include <QtCore/QTextCodec>
28 
29 #ifdef Q_OS_WIN
30 
31 #include "kglobal.h"
32 #include <klocale.h>
33 
34 #include <QtCore/QDir>
35 #include <QtCore/QString>
36 #include <QtCore/QLibrary>
37 
38 #include <windows.h>
39 #include <shellapi.h>
40 #include <process.h>
41 
42 // console related includes
43 #include <stdio.h>
44 #include <fcntl.h>
45 #include <io.h>
46 #include <iostream>
47 #include <fstream>
48 #ifndef _USE_OLD_IOSTREAMS
49 using namespace std;
50 #endif
51 
52 #if defined(__MINGW32__)
53 # define WIN32_CAST_CHAR (const WCHAR*)
54 #else
55 # define WIN32_CAST_CHAR (LPCWSTR)
56 #endif
57 
58 #ifndef _WIN32_WCE
59 static HINSTANCE kdecoreDllInstance = NULL;
60 #else
61 static HANDLE kdecoreDllInstance = NULL;
62 #endif
63 #ifdef KDELIBS_STATIC_LIBS
64 static bool kde4prefixInitialized = false;
65 #endif
66 static wchar_t kde4prefixUtf16[MAX_PATH + 2] = L"";
67 
68 static QString *kde4Prefix = NULL;
69 
70 void initKde4prefixUtf16()
71 {
72  //the path is C:\some\path\kde4\bin\kdecore.dll
73 #ifndef _WIN32_WCE
74  GetModuleFileNameW(kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
75 #else
76  GetModuleFileNameW((HMODULE)kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
77 #endif
78  int bs1 = 0, bs2 = 0;
79 
80  //we convert \ to / and remove \bin\kdecore.dll from the string
81  int pos;
82  for (pos = 0; pos < MAX_PATH + 1 && kde4prefixUtf16[pos] != 0; ++pos) {
83  if (kde4prefixUtf16[pos] == '\\') {
84  bs1 = bs2;
85  bs2 = pos;
86  kde4prefixUtf16[pos] = '/';
87  }
88  }
89  Q_ASSERT(bs1);
90  Q_ASSERT(pos < MAX_PATH + 1);
91  kde4prefixUtf16[bs1] = '/';
92  kde4prefixUtf16[bs1+1] = 0;
93 }
94 
95 // can't use QCoreApplication::applicationDirPath() because sometimes we
96 // don't have an instantiated QCoreApplication
97 QString getKde4Prefix()
98 {
99 #ifdef _WIN32_WCE
100  if (kde4prefixInitialized)
101  return QString::fromUtf16((ushort*) kde4prefixUtf16);
102 
103  QDir kde4prefixDir(QString::fromUtf16((ushort*) STATIC_INSTALL_PATH));
104  if (kde4prefixDir.exists()){
105  wcscpy(kde4prefixUtf16, STATIC_INSTALL_PATH);
106  kde4prefixUtf16[wcslen(kde4prefixUtf16)] = 0;
107  kde4prefixInitialized = true;
108  return QString::fromUtf16((ushort*) kde4prefixUtf16);
109  } else {
110  bool ok;
111  QString retval = getWin32RegistryValue(HKEY_LOCAL_MACHINE, "Software\\kde", "KDEDIRS", &ok);
112  if (!ok){
113  return QString();
114  } else {
115  retval = QDir::fromNativeSeparators(retval);
116  wcscpy(kde4prefixUtf16, retval.utf16());
117  kde4prefixUtf16[wcslen(kde4prefixUtf16)] = 0;
118  kde4prefixInitialized = true;
119  return retval;
120  }
121  }
122 #else
123  // we can get called after DLL_PROCESS_DETACH!
124  return kde4Prefix ? *kde4Prefix : QString::fromUtf16((ushort*) kde4prefixUtf16);
125 #endif
126 }
127 
128 #ifndef KDELIBS_STATIC_LIBS
129 
133 extern "C"
134 #ifndef _WIN32_WCE
135 BOOL WINAPI DllMain ( HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
136 #else
137 BOOL WINAPI DllMain ( HANDLE hinstDLL,DWORD fdwReason,LPVOID lpReserved)
138 #endif
139 {
140  switch ( fdwReason ) {
141  case DLL_PROCESS_ATTACH:
142  kdecoreDllInstance = hinstDLL;
143  initKde4prefixUtf16();
144  kde4Prefix = new QString( QString::fromUtf16((ushort*) kde4prefixUtf16) );
145  break;
146  case DLL_PROCESS_DETACH:
147  /* msdn:
148  When handling DLL_PROCESS_DETACH, a DLL should free resources such
149  as heap memory only if the DLL is being unloaded dynamically (the
150  lpReserved parameter is NULL). If the process is terminating (the
151  lpvReserved parameter is non-NULL), all threads in the process except
152  the current thread either have exited already or have been explicitly
153  terminated by a call to the ExitProcess function, which might leave
154  some process resources such as heaps in an inconsistent state. In this
155  case, it is not safe for the DLL to clean up the resources. Instead,
156  the DLL should allow the operating system to reclaim the memory.
157  */
158  if( lpReserved == NULL )
159  delete kde4Prefix;
160  kde4Prefix = 0;
161  break;
162  default:
163  break;
164  }
165  return true;
166 }
167 
168 #endif
169 
180 QString getWin32RegistryValue ( HKEY key, const QString& subKey, const QString& item, bool *ok )
181 {
182 #define FAILURE \
183  { if (ok) \
184  *ok = false; \
185  return QString(); }
186 
187  if ( subKey.isEmpty() )
188  FAILURE;
189  HKEY hKey;
190  TCHAR *lszValue;
191  DWORD dwType=REG_SZ;
192  DWORD dwSize;
193 
194  if ( ERROR_SUCCESS!=RegOpenKeyExW ( key, WIN32_CAST_CHAR subKey.utf16(), 0, KEY_READ, &hKey ) )
195  FAILURE;
196 
197  if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, NULL, NULL, &dwSize ) )
198  FAILURE;
199 
200  lszValue = new TCHAR[dwSize];
201 
202  if ( ERROR_SUCCESS!=RegQueryValueExW ( hKey, WIN32_CAST_CHAR item.utf16(), NULL, &dwType, ( LPBYTE ) lszValue, &dwSize ) ) {
203  delete [] lszValue;
204  FAILURE;
205  }
206  RegCloseKey ( hKey );
207 
208  QString res = QString::fromUtf16 ( ( const ushort* ) lszValue );
209  delete [] lszValue;
210 
211  if (ok)
212  *ok = true;
213 
214  return res;
215 }
216 
217 
218 bool showWin32FilePropertyDialog ( const QString& fileName )
219 {
220  QString path_ = QDir::convertSeparators ( QFileInfo ( fileName ).absoluteFilePath() );
221 
222 #ifndef _WIN32_WCE
223  SHELLEXECUTEINFOW execInfo;
224 #else
225  SHELLEXECUTEINFO execInfo;
226 #endif
227  memset ( &execInfo,0,sizeof ( execInfo ) );
228  execInfo.cbSize = sizeof ( execInfo );
229 #ifndef _WIN32_WCE
230  execInfo.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
231 #else
232  execInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI;
233 #endif
234  const QString verb ( QLatin1String ( "properties" ) );
235  execInfo.lpVerb = WIN32_CAST_CHAR verb.utf16();
236  execInfo.lpFile = WIN32_CAST_CHAR path_.utf16();
237 #ifndef _WIN32_WCE
238  return ShellExecuteExW ( &execInfo );
239 #else
240  return ShellExecuteEx ( &execInfo );
241  //There is no native file property dialog in wince
242  // return false;
243 #endif
244 }
245 
246 // note: QLocale().name().left(2).toLatin1() returns the same
247 
248 QByteArray getWin32LocaleName()
249 {
250  bool ok;
251  QString localeNumber = getWin32RegistryValue ( HKEY_CURRENT_USER,
252  QLatin1String("Control Panel\\International"),
253  QLatin1String("Locale"), &ok );
254  if ( !ok )
255  return QByteArray();
256  QString localeName = getWin32RegistryValue ( HKEY_LOCAL_MACHINE,
257  QLatin1String("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layout\\DosKeybCodes"),
258  localeNumber, &ok );
259  if ( !ok )
260  return QByteArray();
261  return localeName.toLatin1();
262 }
263 
267 QString getWin32ShellFoldersPath ( const QString& folder )
268 {
269  return getWin32RegistryValue ( HKEY_CURRENT_USER,
270  QLatin1String("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"),
271  folder );
272 }
273 
277 static void kMessageOutputDebugString(QtMsgType type, const char *msg)
278 {
279  int BUFSIZE=4096;
280  char *buf = new char[BUFSIZE];
281  switch (type) {
282  case QtDebugMsg:
283  strlcpy(buf,"Debug:",BUFSIZE);
284  strlcat(buf,msg,BUFSIZE);
285  break;
286  case QtWarningMsg:
287  strlcpy(buf,"Warning:",BUFSIZE);
288  strlcat(buf,msg,BUFSIZE);
289  break;
290  case QtCriticalMsg:
291  strlcpy(buf,"Critical:",BUFSIZE);
292  strlcat(buf,msg,BUFSIZE);
293  break;
294  case QtFatalMsg:
295  strlcpy(buf,"Fatal:",BUFSIZE);
296  strlcat(buf,msg,BUFSIZE);
297  //abort();
298  break;
299  }
300  strlcat(buf,"\n",BUFSIZE);
301  OutputDebugStringW( (WCHAR*)QString::fromLatin1(buf).utf16());
302  delete[] buf;
303 }
304 
308 static void kMessageOutputFileIO(QtMsgType type, const char *msg)
309 {
310  switch (type) {
311  case QtDebugMsg:
312  fprintf(stderr, "Debug: %s\n", msg);
313  break;
314  case QtWarningMsg:
315  fprintf(stderr, "Warning: %s\n", msg);
316  break;
317  case QtCriticalMsg:
318  fprintf(stderr, "Critical: %s\n", msg);
319  break;
320  case QtFatalMsg:
321  fprintf(stderr, "Fatal: %s\n", msg);
322  //abort();
323  }
324 }
325 
330 typedef BOOL (WINAPI*attachConsolePtr)(DWORD dwProcessId);
331 static attachConsolePtr attachConsole = 0;
332 static bool attachConsoleResolved = false;
333 static bool attachToConsole()
334 {
335  bool out = true;
336  if(!attachConsoleResolved) {
337  attachConsoleResolved = true;
338  attachConsole = (attachConsolePtr)QLibrary::resolve(QLatin1String("kernel32"), "AttachConsole");
339  }
340  out = attachConsole ? attachConsole(~0U) != 0 : false;
341  if(GetLastError() == ERROR_ACCESS_DENIED)
342  {
343  //we are already atatched to a console
344  out = true;
345  }
346  return out;
347 }
348 
353 static void redirectToConsole()
354 {
355 //FIXME: for wince we cannot set stdio buffers
356 #ifndef _WIN32_WCE
357  int hCrt;
358  FILE *hf;
359  int i;
360 
361  hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_INPUT_HANDLE),_O_TEXT);
362  if(hCrt != -1) {
363  hf = _fdopen( hCrt, "r" );
364  *stdin = *hf;
365  i = setvbuf( stdin, NULL, _IONBF, 0 );
366  }
367 
368  hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
369  if(hCrt != -1) {
370  hf = _fdopen( hCrt, "w" );
371  *stdout = *hf;
372  i = setvbuf( stdout, NULL, _IONBF, 0 );
373  }
374 
375  hCrt = _open_osfhandle((intptr_t) GetStdHandle(STD_ERROR_HANDLE),_O_TEXT);
376  if(hCrt != -1) {
377  hf = _fdopen( hCrt, "w" );
378  *stderr = *hf;
379  i = setvbuf( stderr, NULL, _IONBF, 0 );
380  }
381  // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
382  // point to console as well
383  ios::sync_with_stdio();
384 #endif
385 }
386 
387 #include <streambuf>
388 
392 class debug_streambuf: public std::streambuf
393 {
394  public:
395  debug_streambuf(const char *prefix)
396  {
397  strcpy(buf,prefix);
398  index = rindex = strlen(buf);
399  }
400 
401  protected:
402  virtual int overflow(int c = EOF)
403  {
404  if (c != EOF)
405  {
406  char cc = traits_type::to_char_type(c);
407  // @TODO: buffer size checking
408  buf[index++] = cc;
409  if (cc == '\n')
410  {
411  buf[index] = '\0';
412  OutputDebugStringW((WCHAR*)QString::fromLatin1(buf).utf16());
413  index = rindex;
414  }
415  }
416  return traits_type::not_eof(c);
417  }
418  private:
419  char buf[4096];
420  int index, rindex;
421 };
422 
427 static int subSystem()
428 {
429 #ifdef _WIN32_WCE
430  // there is only one subsystem on Windows CE
431  return IMAGE_SUBSYSTEM_WINDOWS_CE_GUI;
432 #else
433  static int subSystem = -1;
434  if (subSystem > -1)
435  return subSystem;
436 
437  // get base address of memory mapped executable
438  PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
439  PIMAGE_NT_HEADERS ntHeader = (PIMAGE_NT_HEADERS) ((char *)dosHeader + dosHeader->e_lfanew);
440  if (ntHeader->Signature != 0x00004550)
441  {
442  subSystem = IMAGE_SUBSYSTEM_UNKNOWN;
443  return subSystem;
444  }
445  subSystem = ntHeader->OptionalHeader.Subsystem;
446  return subSystem;
447 #endif
448 }
449 
478 static class kMessageOutputInstaller {
479  public:
480  kMessageOutputInstaller() : stdoutBuffer("stdout:"), stderrBuffer("stderr:"), oldStdoutBuffer(0), oldStderrBuffer(0)
481  {
482  if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_CUI) {
483  if (attachToConsole()) {
484  // setup kde and qt level
485  qInstallMsgHandler(kMessageOutputFileIO);
486  // redirect ios and file io to console
487  redirectToConsole();
488  }
489  else {
490  // setup kde and qt level
491  qInstallMsgHandler(kMessageOutputDebugString);
492  // redirect ios to debug message port
493  oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
494  oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
495  }
496  }
497  else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
498  // setup kde and qt level
499  qInstallMsgHandler(kMessageOutputDebugString);
500  // try to get a console
501  if (attachToConsole()) {
502  redirectToConsole();
503  }
504  else {
505  // redirect ios to debug message port
506  oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
507  oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
508  // TODO: redirect FILE * level to console, no idea how to do yet
509  }
510  } else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_CE_GUI) {
511  // do not try to get a console on WinCE systems
512  qInstallMsgHandler(kMessageOutputDebugString);
513  oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
514  oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
515  }
516  else
517  qWarning("unknown subsystem %d detected, could not setup qt message handler",subSystem());
518  }
519  ~kMessageOutputInstaller()
520  {
521  if (oldStdoutBuffer)
522  std::cout.rdbuf(oldStdoutBuffer);
523  if (oldStderrBuffer)
524  std::cerr.rdbuf(oldStderrBuffer);
525  }
526 
527  private:
528  debug_streambuf stdoutBuffer;
529  debug_streambuf stderrBuffer;
530  std::streambuf* oldStdoutBuffer;
531  std::streambuf* oldStderrBuffer;
532 
533 } kMessageOutputInstallerInstance;
534 
535 
536 bool isExecutable(const QString &file)
537 {
538  return ( file.endsWith( QLatin1String( ".exe" ) ) ||
539  file.endsWith( QLatin1String( ".com" ) ) ||
540  file.endsWith( QLatin1String( ".bat" ) ) ||
541  file.endsWith( QLatin1String( ".sln" ) ) ||
542  file.endsWith( QLatin1String( ".lnk" ) ) );
543 
544 }
545 
546 #endif // Q_OS_WIN
DllMain
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
The dll entry point - get the instance handle for GetModuleFleNameW Maybe also some special initializ...
Definition: kkernel_win.cpp:135
getKde4Prefix
QString getKde4Prefix()
Definition: kkernel_win.cpp:97
QDir::fromNativeSeparators
QString fromNativeSeparators(const QString &pathName)
initKde4prefixUtf16
void initKde4prefixUtf16()
Definition: kkernel_win.cpp:70
QByteArray
kde4Prefix
static QString * kde4Prefix
Definition: kkernel_win.cpp:68
QDir::convertSeparators
QString convertSeparators(const QString &pathName)
isExecutable
bool isExecutable(const QString &file)
Definition: kkernel_win.cpp:536
subSystem
static int subSystem()
retrieve type of win32 subsystem from the executable header
Definition: kkernel_win.cpp:427
klocale.h
kdecoreDllInstance
static HINSTANCE kdecoreDllInstance
Definition: kkernel_win.cpp:59
prefix
QString prefix()
Definition: kstandarddirs_win.cpp:28
redirectToConsole
static void redirectToConsole()
redirect stdout, stderr and cout, wcout, cin, wcin, wcerr, cerr, wclog and clog to console ...
Definition: kkernel_win.cpp:353
attachConsoleResolved
static bool attachConsoleResolved
Definition: kkernel_win.cpp:332
kglobal.h
QDir::exists
bool exists() const
QString::fromUtf16
QString fromUtf16(const ushort *unicode, int size)
QString::isEmpty
bool isEmpty() const
attachConsolePtr
BOOL(WINAPI * attachConsolePtr)(DWORD dwProcessId)
try to attach to the parents console
Definition: kkernel_win.cpp:330
kMessageOutputDebugString
static void kMessageOutputDebugString(QtMsgType type, const char *msg)
kde and qt debug message printer using windows debug message port
Definition: kkernel_win.cpp:277
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QString
getWin32ShellFoldersPath
QString getWin32ShellFoldersPath(const QString &folder)
Windows-specific functions needed in kdecore.
Definition: kkernel_win.cpp:267
kkernel_win.h
QFileInfo
FAILURE
#define FAILURE
WIN32_CAST_CHAR
#define WIN32_CAST_CHAR
Definition: kkernel_win.cpp:55
kMessageOutputInstallerInstance
static class kMessageOutputInstaller kMessageOutputInstallerInstance
QDir
BOOL
typedef BOOL(WINAPI *PtrTzSpecificLocalTimeToSystemTime)(LPTIME_ZONE_INFORMATION lpTimeZoneInformation
attachToConsole
static bool attachToConsole()
Definition: kkernel_win.cpp:333
getWin32LocaleName
QByteArray getWin32LocaleName()
Definition: kkernel_win.cpp:248
QString::toLatin1
QByteArray toLatin1() const
QString::utf16
const ushort * utf16() const
QLibrary::resolve
void * resolve(const char *symbol)
QLatin1String
kde4prefixUtf16
static wchar_t kde4prefixUtf16[MAX_PATH+2]
Definition: kkernel_win.cpp:66
kMessageOutputFileIO
static void kMessageOutputFileIO(QtMsgType type, const char *msg)
kde and qt debug message printer using FILE pointer based output
Definition: kkernel_win.cpp:308
QString::fromLatin1
QString fromLatin1(const char *str, int size)
showWin32FilePropertyDialog
bool showWin32FilePropertyDialog(const QString &fileName)
Shows native MS Windows file property dialog for a file fileName.
Definition: kkernel_win.cpp:218
attachConsole
static attachConsolePtr attachConsole
Definition: kkernel_win.cpp:331
getWin32RegistryValue
QString getWin32RegistryValue(HKEY key, const QString &subKey, const QString &item, bool *ok)
Definition: kkernel_win.cpp:180
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

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

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • 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

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal