Files
SDL/src/main/windows/SDL_sysmain_runapp.c
Ryan C. Gordon 7388054fa2 main: Restore public domain comment in Windows code.
This, strictly speaking, doesn't _need_ to be public domain any more, since
SDL3 no longer inserts this code into apps via a static SDL_main library; it's
just part of the normal zlib-licensed SDL library and called into through a
well-defined entry point at startup, now.

But removing a public domain notice isn't the done thing, so we'll leave it in.

(To a related point: even if others have rewritten good portions of this code,
they're doing it under the assumption that this specific file has a public
domain license.)
2025-11-23 13:41:08 -05:00

109 lines
4.2 KiB
C

/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"
#ifdef SDL_PLATFORM_WIN32
#include "../../core/windows/SDL_windows.h"
/* Win32-specific SDL_RunApp(), which does most of the SDL_main work,
based on SDL_windows_main.c, placed in the public domain by Sam Lantinga 4/13/98 */
#include <shellapi.h> // CommandLineToArgvW()
static int OutOfMemory(void)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL);
return -1;
}
static int ErrorProcessingCommandLine(void)
{
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments - aborting", NULL);
return -1;
}
int SDL_RunApp(int caller_argc, char *caller_argv[], SDL_main_func mainFunction, void * reserved)
{
int result;
(void)reserved;
// If the provided argv is valid, we pass it to the main function as-is, since it's probably what the user wants.
// Otherwise, we take a NULL argv as an instruction for SDL to parse the command line into an argv.
// On Windows, when SDL provides the main entry point, argv is always NULL.
if (caller_argv && caller_argc >= 0) {
result = mainFunction(caller_argc, caller_argv);
} else {
// We need to be careful about how we allocate/free memory here. We can't use SDL_alloc()/SDL_free()
// because the application might have used SDL_SetMemoryFunctions() to change the allocator.
LPWSTR *argvw = NULL;
char **argv = NULL;
const LPWSTR command_line = GetCommandLineW();
// Because of how the Windows command line is structured, we know for sure that the buffer size required to
// store all argument strings converted to UTF-8 (with null terminators) is guaranteed to be less than or equal
// to the size of the original command line string converted to UTF-8.
const int argdata_size = WideCharToMultiByte(CP_UTF8, 0, command_line, -1, NULL, 0, NULL, NULL); // Includes the null terminator
if (!argdata_size) {
result = ErrorProcessingCommandLine();
goto cleanup;
}
int argc;
argvw = CommandLineToArgvW(command_line, &argc);
if (!argvw || argc < 0) {
result = OutOfMemory();
goto cleanup;
}
// Allocate argv followed by the argument string buffer as one contiguous allocation.
argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv) + argdata_size);
if (!argv) {
result = OutOfMemory();
goto cleanup;
}
char *argdata = ((char *)argv) + (argc + 1) * sizeof(*argv);
int argdata_index = 0;
for (int i = 0; i < argc; ++i) {
const int bytes_written = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argdata + argdata_index, argdata_size - argdata_index, NULL, NULL);
if (!bytes_written) {
result = ErrorProcessingCommandLine();
goto cleanup;
}
argv[i] = argdata + argdata_index;
argdata_index += bytes_written;
}
argv[argc] = NULL;
result = mainFunction(argc, argv);
cleanup:
HeapFree(GetProcessHeap(), 0, argv);
LocalFree(argvw);
}
return result;
}
#endif // SDL_PLATFORM_WIN32