summaryrefslogtreecommitdiffstats
path: root/src/winmain/qtmain_winrt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/winmain/qtmain_winrt.cpp')
-rw-r--r--src/winmain/qtmain_winrt.cpp430
1 files changed, 0 insertions, 430 deletions
diff --git a/src/winmain/qtmain_winrt.cpp b/src/winmain/qtmain_winrt.cpp
deleted file mode 100644
index 1828c4ca16..0000000000
--- a/src/winmain/qtmain_winrt.cpp
+++ /dev/null
@@ -1,430 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Windows main function of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*
- This file contains the code in the qtmain library for WinRT.
- qtmain contains the WinRT startup code and is required for
- linking to the Qt DLL.
-
- When a Windows application starts, the WinMain function is
- invoked. This WinMain creates the WinRT application
- container, which in turn calls the application's main()
- entry point within the newly created GUI thread.
-*/
-
-extern "C" {
- int main(int, char **);
-}
-
-#include <qbytearray.h>
-#include <qstring.h>
-#include <qdir.h>
-#include <qstandardpaths.h>
-#include <qfunctions_winrt.h>
-#include <qcoreapplication.h>
-#include <qmutex.h>
-
-#include <wrl.h>
-#include <Windows.ApplicationModel.core.h>
-#include <windows.ui.xaml.h>
-#include <windows.ui.xaml.controls.h>
-
-using namespace ABI::Windows::ApplicationModel;
-using namespace ABI::Windows::ApplicationModel::Activation;
-using namespace ABI::Windows::ApplicationModel::Core;
-using namespace ABI::Windows::Foundation;
-using namespace ABI::Windows::UI;
-using namespace Microsoft::WRL;
-using namespace Microsoft::WRL::Wrappers;
-
-#define qHString(x) Wrappers::HString::MakeReference(x).Get()
-#define CoreApplicationClass RuntimeClass_Windows_ApplicationModel_Core_CoreApplication
-typedef ITypedEventHandler<CoreApplicationView *, Activation::IActivatedEventArgs *> ActivatedHandler;
-
-const quint32 resizeMessageType = QtInfoMsg + 1;
-
-const PCWSTR shmemName = L"qdebug-shmem";
-const PCWSTR eventName = L"qdebug-event";
-const PCWSTR ackEventName = L"qdebug-event-ack";
-
-static QtMessageHandler defaultMessageHandler;
-static void devMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message)
-{
- static HANDLE shmem = 0;
- static HANDLE event = 0;
- static HANDLE ackEvent = 0;
-
- static QMutex messageMutex;
- QMutexLocker locker(&messageMutex);
-
- static quint64 mappingSize = 4096;
- const quint32 copiedMessageLength = message.length() + 1;
- // Message format is message type + message. We need the message's length + 4 bytes for the type
- const quint64 copiedMessageSize = copiedMessageLength * sizeof(wchar_t) + sizeof(quint32);
- if (copiedMessageSize > mappingSize) {
- if (!shmem)
- shmem = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, mappingSize, shmemName);
- Q_ASSERT_X(shmem, Q_FUNC_INFO, "Could not create file mapping");
-
- quint32 *data = reinterpret_cast<quint32 *>(MapViewOfFileFromApp(shmem, FILE_MAP_WRITE, 0, mappingSize));
- Q_ASSERT_X(data, Q_FUNC_INFO, "Could not map size file");
-
- mappingSize = copiedMessageSize;
-
- memcpy(data, (void *)&resizeMessageType, sizeof(quint32));
- memcpy(data + 1, (void *)&mappingSize, sizeof(quint64));
- UnmapViewOfFile(data);
- SetEvent(event);
- WaitForSingleObjectEx(ackEvent, INFINITE, false);
- if (shmem) {
- if (!CloseHandle(shmem))
- Q_ASSERT_X(false, Q_FUNC_INFO, "Could not close shared file handle");
- shmem = 0;
- }
- }
-
- if (!shmem)
- shmem = CreateFileMappingFromApp(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, mappingSize, shmemName);
- if (!event)
- event = CreateEventEx(NULL, eventName, 0, EVENT_ALL_ACCESS);
- if (!ackEvent)
- ackEvent = CreateEventEx(NULL, ackEventName, 0, EVENT_ALL_ACCESS);
-
- Q_ASSERT_X(shmem, Q_FUNC_INFO, "Could not create file mapping");
- Q_ASSERT_X(event, Q_FUNC_INFO, "Could not create debug event");
-
- void *data = MapViewOfFileFromApp(shmem, FILE_MAP_WRITE, 0, mappingSize);
- Q_ASSERT_X(data, Q_FUNC_INFO, "Could not map file");
-
- memset(data, quint32(type), sizeof(quint32));
- memcpy_s(static_cast<quint32 *>(data) + 1, mappingSize - sizeof(quint32),
- message.data(), copiedMessageLength * sizeof(wchar_t));
- UnmapViewOfFile(data);
- SetEvent(event);
- WaitForSingleObjectEx(ackEvent, INFINITE, false);
- locker.unlock();
- defaultMessageHandler(type, context, message);
-}
-
-class QActivationEvent : public QEvent
-{
-public:
- explicit QActivationEvent(IInspectable *args)
- : QEvent(QEvent::WinEventAct)
- {
- setAccepted(false);
- args->AddRef();
- d = reinterpret_cast<QEventPrivate *>(args);
- }
-
- ~QActivationEvent() {
- IUnknown *args = reinterpret_cast<IUnknown *>(d);
- args->Release();
- d = nullptr;
- }
-};
-
-class AppContainer : public RuntimeClass<Xaml::IApplicationOverrides>
-{
-public:
- AppContainer()
- {
- ComPtr<Xaml::IApplicationFactory> applicationFactory;
- HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(),
- IID_PPV_ARGS(&applicationFactory));
- Q_ASSERT_SUCCEEDED(hr);
-
- hr = applicationFactory->CreateInstance(this, &base, &core);
- RETURN_VOID_IF_FAILED("Failed to create application container instance");
-
- pidFile = INVALID_HANDLE_VALUE;
- }
-
- ~AppContainer()
- {
- }
-
- int exec()
- {
- mainThread = CreateThread(NULL, 0, [](void *param) -> DWORD {
- AppContainer *app = reinterpret_cast<AppContainer *>(param);
- int argc = app->args.count() - 1;
- char **argv = app->args.data();
- const int res = main(argc, argv);
- if (app->pidFile != INVALID_HANDLE_VALUE) {
- const QByteArray resString = QByteArray::number(res);
- WriteFile(app->pidFile, reinterpret_cast<LPCVOID>(resString.constData()),
- resString.size(), NULL, NULL);
- FlushFileBuffers(app->pidFile);
- CloseHandle(app->pidFile);
- }
- app->core->Exit();
- return res;
- }, this, CREATE_SUSPENDED, nullptr);
- Q_ASSERT_X(mainThread, Q_FUNC_INFO, "Could not create Qt main thread");
-
- HRESULT hr;
- ComPtr<Xaml::IApplicationStatics> appStatics;
- hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Application).Get(),
- IID_PPV_ARGS(&appStatics));
- Q_ASSERT_SUCCEEDED(hr);
- hr = appStatics->Start(Callback<Xaml::IApplicationInitializationCallback>([](Xaml::IApplicationInitializationCallbackParams *) {
- return S_OK;
- }).Get());
- Q_ASSERT_SUCCEEDED(hr);
-
- WaitForSingleObjectEx(mainThread, INFINITE, FALSE);
- DWORD exitCode;
- GetExitCodeThread(mainThread, &exitCode);
- return exitCode;
- }
-
-private:
- HRESULT activatedLaunch(IInspectable *activateArgs) {
- // Check if an application instance is already running
- // This is mostly needed for Windows Phone and file pickers
- QAbstractEventDispatcher *dispatcher = QCoreApplication::eventDispatcher();
- if (dispatcher) {
- QCoreApplication::postEvent(dispatcher, new QActivationEvent(activateArgs));
- return S_OK;
- }
-
- QCoreApplication *app = QCoreApplication::instance();
-
- // Check whether the app already runs
- if (!app) {
- // I*EventArgs have no launch arguments, hence we
- // need to prepend the application binary manually
- wchar_t fn[513];
- DWORD res = GetModuleFileName(0, fn, 512);
-
- if (SUCCEEDED(res))
- args.prepend(QString::fromWCharArray(fn, res).toUtf8().data());
-
- ResumeThread(mainThread);
-
- // We give main() a max of 100ms to create an application object.
- // No eventhandling needs to happen at that point, all we want is
- // append our activation event
- int iterations = 0;
- while (true) {
- app = QCoreApplication::instance();
- if (app || iterations++ > 10)
- break;
- Sleep(10);
- }
- }
-
- if (app)
- QCoreApplication::postEvent(app, new QActivationEvent(activateArgs));
- return S_OK;
- }
-
- HRESULT __stdcall OnActivated(IActivatedEventArgs *args) override
- {
- return activatedLaunch(args);
- }
-
- HRESULT __stdcall OnLaunched(ILaunchActivatedEventArgs *launchArgs) override
- {
- ComPtr<IPrelaunchActivatedEventArgs> preArgs;
- HRESULT hr = launchArgs->QueryInterface(preArgs.GetAddressOf());
- if (SUCCEEDED(hr)) {
- boolean prelaunched;
- preArgs->get_PrelaunchActivated(&prelaunched);
- if (prelaunched)
- return S_OK;
- }
-
- commandLine = QString::fromWCharArray(GetCommandLine()).toUtf8();
-
- HString launchCommandLine;
- launchArgs->get_Arguments(launchCommandLine.GetAddressOf());
- if (launchCommandLine.IsValid()) {
- quint32 launchCommandLineLength;
- const wchar_t *launchCommandLineBuffer = launchCommandLine.GetRawBuffer(&launchCommandLineLength);
- if (!commandLine.isEmpty() && launchCommandLineLength)
- commandLine += ' ';
- if (launchCommandLineLength)
- commandLine += QString::fromWCharArray(launchCommandLineBuffer, launchCommandLineLength).toUtf8();
- }
- if (!commandLine.isEmpty())
- args.append(commandLine.data());
-
- bool quote = false;
- bool escape = false;
- for (int i = 0; i < commandLine.size(); ++i) {
- switch (commandLine.at(i)) {
- case '\\':
- escape = true;
- break;
- case '"':
- if (escape) {
- escape = false;
- break;
- }
- quote = !quote;
- commandLine[i] = '\0';
- break;
- case ' ':
- if (quote)
- break;
- commandLine[i] = '\0';
- if (!args.isEmpty() && args.last() && args.last()[0] != '\0')
- args.append(commandLine.data() + i + 1);
- // fall through
- default:
- if (!args.isEmpty() && args.last() && args.last()[0] == '\0')
- args.last() = commandLine.data() + i;
- escape = false; // only quotes are escaped
- break;
- }
- }
-
- if (args.count() >= 2 && args.at(1) && strncmp(args.at(1), "-ServerName:", 12) == 0)
- args.remove(1);
-
- bool develMode = false;
- bool debugWait = false;
- for (int i = args.count() - 1; i >= 0; --i) {
- if (!args.at(i))
- continue;
-
- const char *arg = args.at(i);
- if (strcmp(arg, "-qdevel") == 0) {
- develMode = true;
- args.remove(i);
- } else if (strcmp(arg, "-qdebug") == 0) {
- debugWait = true;
- args.remove(i);
- }
- }
- args.append(nullptr);
-
- if (develMode) {
- // Write a PID file to help runner
- const QString pidFileName = QDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation))
- .absoluteFilePath(QString::asprintf("%u.pid", uint(GetCurrentProcessId())));
- CREATEFILE2_EXTENDED_PARAMETERS params = {
- sizeof(CREATEFILE2_EXTENDED_PARAMETERS),
- FILE_ATTRIBUTE_NORMAL
- };
- pidFile = CreateFile2(reinterpret_cast<LPCWSTR>(pidFileName.utf16()),
- GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS, &params);
- // Install the develMode message handler
- defaultMessageHandler = qInstallMessageHandler(devMessageHandler);
- }
- // Wait for debugger before continuing
- if (debugWait) {
- while (!IsDebuggerPresent())
- WaitForSingleObjectEx(GetCurrentThread(), 1, true);
- }
-
- ResumeThread(mainThread);
- return S_OK;
- }
-
- HRESULT __stdcall OnFileActivated(IFileActivatedEventArgs *args) override
- {
- return activatedLaunch(args);
- }
-
- HRESULT __stdcall OnSearchActivated(ISearchActivatedEventArgs *args) override
- {
- Q_UNUSED(args);
- return S_OK;
- }
-
- HRESULT __stdcall OnShareTargetActivated(IShareTargetActivatedEventArgs *args) override
- {
- return activatedLaunch(args);
- }
-
- HRESULT __stdcall OnFileOpenPickerActivated(IFileOpenPickerActivatedEventArgs *args) override
- {
- Q_UNUSED(args);
- return S_OK;
- }
-
- HRESULT __stdcall OnFileSavePickerActivated(IFileSavePickerActivatedEventArgs *args) override
- {
- Q_UNUSED(args);
- return S_OK;
- }
-
- HRESULT __stdcall OnCachedFileUpdaterActivated(ICachedFileUpdaterActivatedEventArgs *args) override
- {
- Q_UNUSED(args);
- return S_OK;
- }
-
- HRESULT __stdcall OnWindowCreated(Xaml::IWindowCreatedEventArgs *args) override
- {
- Q_UNUSED(args);
- return S_OK;
- }
-
- ComPtr<Xaml::IApplicationOverrides> base;
- ComPtr<Xaml::IApplication> core;
- QByteArray commandLine;
- QVarLengthArray<char *> args;
- HANDLE mainThread{0};
- HANDLE pidFile;
-};
-
-// Main entry point for Appx containers
-int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
-{
- if (FAILED(RoInitialize(RO_INIT_MULTITHREADED)))
- return 1;
-
- ComPtr<AppContainer> app = Make<AppContainer>();
- return app->exec();
-}