2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "CompileInfo.h"
10 #include "ServiceBroker.h"
11 #include "application/AppEnvironment.h"
12 #include "application/AppParamParser.h"
13 #include "application/AppParams.h"
14 #include "platform/Environment.h"
15 #include "platform/xbmc.h"
16 #include "threads/Thread.h"
17 #include "utils/CharsetConverter.h" // Required to initialize converters before usage
19 #include "platform/win32/CharsetConverter.h"
20 #include "platform/win32/threads/Win32Exception.h"
28 // Minidump creation function
29 LONG WINAPI
CreateMiniDump(EXCEPTION_POINTERS
* pEp
)
31 win32_exception::write_stacktrace(pEp
);
32 win32_exception::write_minidump(pEp
);
33 return pEp
->ExceptionRecord
->ExceptionCode
;
36 static bool isConsoleAttached
{false};
39 * \brief Basic error reporting before the log subsystem is initialized
41 * The message is formatted using printf and output to debugger and cmd.exe, as applicable.
43 * \param[in] format printf-style format string
44 * \param[in] ... optional parameters for the format string.
46 template<typename
... Args
>
47 static void LogError(const wchar_t* format
, Args
&&... args
)
49 const int count
= _snwprintf(nullptr, 0, format
, args
...);
50 // terminating null character not included in count
51 auto buf
= std::make_unique
<wchar_t[]>(count
+ 1);
52 swprintf(buf
.get(), format
, args
...);
54 OutputDebugString(buf
.get());
56 if (!isConsoleAttached
&& AttachConsole(ATTACH_PARENT_PROCESS
))
58 (void)freopen("CONOUT$", "w", stdout
);
60 isConsoleAttached
= true;
65 static std::shared_ptr
<CAppParams
> ParseCommandLine()
68 LPWSTR
* argvW
= CommandLineToArgvW(GetCommandLineW(), &argc
);
69 char** argv
= new char*[argc
];
71 for (int i
= 0; i
< argc
; ++i
)
73 int size
= WideCharToMultiByte(CP_UTF8
, 0, argvW
[i
], -1, nullptr, 0, nullptr, nullptr);
76 argv
[i
] = new char[size
];
77 WideCharToMultiByte(CP_UTF8
, 0, argvW
[i
], -1, argv
[i
], size
, nullptr, nullptr);
81 CAppParamParser appParamParser
;
82 appParamParser
.Parse(argv
, argc
);
84 for (int i
= 0; i
< argc
; ++i
)
88 return appParamParser
.GetAppParams();
91 //-----------------------------------------------------------------------------
93 // Desc: The application's entry point
94 //-----------------------------------------------------------------------------
95 _Use_decl_annotations_ INT WINAPI
WinMain(HINSTANCE
, HINSTANCE
, LPSTR
, INT
)
97 // parse command line parameters
98 const auto params
= ParseCommandLine();
100 // this fixes crash if OPENSSL_CONF is set to existed openssl.cfg
101 // need to set it as soon as possible
102 CEnvironment::unsetenv("OPENSSL_CONF");
104 // Initializes CreateMiniDump to handle exceptions.
106 if (strlen(CCompileInfo::GetSuffix()) > 0)
107 sprintf_s(ver
, "%d.%d-%s Git:%s", CCompileInfo::GetMajor(),
108 CCompileInfo::GetMinor(), CCompileInfo::GetSuffix(), CCompileInfo::GetSCMID());
110 sprintf_s(ver
, "%d.%d Git:%s", CCompileInfo::GetMajor(),
111 CCompileInfo::GetMinor(), CCompileInfo::GetSCMID());
113 if (win32_exception::ShouldHook())
115 win32_exception::set_version(std::string(ver
));
116 win32_exception::set_platformDirectories(params
->HasPlatformDirectories());
117 SetUnhandledExceptionFilter(CreateMiniDump
);
121 HRESULT hrCOM
{E_FAIL
};
122 int rcWinsock
{WSANOTINITIALISED
};
125 // check if Kodi is already running
126 using KODI::PLATFORM::WINDOWS::ToW
;
127 std::string appName
= CCompileInfo::GetAppName();
128 HANDLE appRunningMutex
= CreateMutex(nullptr, FALSE
, ToW(appName
+ " Media Center").c_str());
129 if (appRunningMutex
!= nullptr && GetLastError() == ERROR_ALREADY_EXISTS
)
131 auto appNameW
= ToW(appName
);
132 HWND hwnd
= FindWindow(appNameW
.c_str(), appNameW
.c_str());
135 // switch to the running instance
136 ShowWindow(hwnd
, SW_RESTORE
);
137 SetForegroundWindow(hwnd
);
144 if ((hrCOM
= CoInitializeEx(nullptr, COINIT_MULTITHREADED
)) != S_OK
)
146 LogError(L
"unable to initialize COM, error %ld\n", hrCOM
);
151 // Initialise Winsock
152 if ((rcWinsock
= WSAStartup(MAKEWORD(2, 2), &wd
)) != 0)
154 LogError(L
"unable to initialize Windows Sockets, error %i\n", rcWinsock
);
159 // use 1 ms timer precision - like SDL initialization used to do
163 // we don't want to see the "no disc in drive" windows message box
164 SetErrorMode(SEM_FAILCRITICALERRORS
| SEM_NOOPENFILEERRORBOX
);
167 CAppEnvironment::SetUp(params
);
169 // Create and run the app
170 status
= XBMC_Run(true);
172 CAppEnvironment::TearDown();
174 // clear previously set timer resolution
184 CloseHandle(appRunningMutex
);