00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
00065 GetModuleFileNameW(kdecoreDllInstance, kde4prefixUtf16, MAX_PATH + 1);
00066 int bs1 = 0, bs2 = 0;
00067
00068
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
00084
00085 QString getKde4Prefix()
00086 {
00087
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
00106
00107
00108
00109
00110
00111
00112
00113
00114
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
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
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
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
00311
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
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
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
00406 qInstallMsgHandler(kMessageOutputFileIO);
00407
00408 redirectToConsole();
00409 }
00410 else {
00411
00412 qInstallMsgHandler(kMessageOutputDebugString);
00413
00414 oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00415 oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00416 }
00417 }
00418 else if (subSystem() == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
00419
00420 qInstallMsgHandler(kMessageOutputDebugString);
00421
00422 if (attachToConsole()) {
00423 redirectToConsole();
00424 }
00425 else {
00426
00427 oldStdoutBuffer = std::cout.rdbuf(&stdoutBuffer);
00428 oldStderrBuffer = std::cerr.rdbuf(&stderrBuffer);
00429
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