mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
243 lines
8.0 KiB
C
243 lines
8.0 KiB
C
//-----------------------------------------------------------------------------
|
|
// Win32GUI.c
|
|
// Main routine for frozen programs written for the Win32 GUI subsystem.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include <Python.h>
|
|
#include <windows.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FatalError()
|
|
// Handle a fatal error.
|
|
//-----------------------------------------------------------------------------
|
|
static int FatalError(
|
|
char *a_Message) // message to display
|
|
{
|
|
MessageBox(NULL, a_Message, "cx_Freeze Fatal Error", MB_ICONERROR);
|
|
Py_Finalize();
|
|
return -1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// StringifyObject()
|
|
// Stringify a Python object.
|
|
//-----------------------------------------------------------------------------
|
|
static char *StringifyObject(
|
|
PyObject *object, // object to stringify
|
|
PyObject **stringRep) // string representation
|
|
{
|
|
if (object) {
|
|
*stringRep = PyObject_Str(object);
|
|
if (*stringRep)
|
|
return PyString_AS_STRING(*stringRep);
|
|
return "Unable to stringify";
|
|
}
|
|
|
|
// object is NULL
|
|
*stringRep = NULL;
|
|
return "None";
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FatalPythonErrorNoTraceback()
|
|
// Handle a fatal Python error without traceback.
|
|
//-----------------------------------------------------------------------------
|
|
static int FatalPythonErrorNoTraceback(
|
|
PyObject *origType, // exception type
|
|
PyObject *origValue, // exception value
|
|
char *message) // message to display
|
|
{
|
|
PyObject *typeStrRep, *valueStrRep, *origTypeStrRep, *origValueStrRep;
|
|
char *totalMessage, *typeStr, *valueStr, *origTypeStr, *origValueStr;
|
|
PyObject *type, *value, *traceback;
|
|
int totalMessageLength;
|
|
char *messageFormat;
|
|
|
|
// fetch error and string representations of the error
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
origTypeStr = StringifyObject(origType, &origTypeStrRep);
|
|
origValueStr = StringifyObject(origValue, &origValueStrRep);
|
|
typeStr = StringifyObject(type, &typeStrRep);
|
|
valueStr = StringifyObject(value, &valueStrRep);
|
|
|
|
// fill out the message to be displayed
|
|
messageFormat = "Type: %s\nValue: %s\nOther Type: %s\nOtherValue: %s\n%s";
|
|
totalMessageLength = strlen(origTypeStr) + strlen(origValueStr) +
|
|
strlen(typeStr) + strlen(valueStr) + strlen(message) +
|
|
strlen(messageFormat) + 1;
|
|
totalMessage = malloc(totalMessageLength);
|
|
if (!totalMessage)
|
|
return FatalError("Out of memory!");
|
|
sprintf(totalMessage, messageFormat, typeStr, valueStr, origTypeStr,
|
|
origValueStr, message);
|
|
|
|
// display the message
|
|
MessageBox(NULL, totalMessage,
|
|
"cx_Freeze: Python error in main script (traceback unavailable)",
|
|
MB_ICONERROR);
|
|
free(totalMessage);
|
|
return -1;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ArgumentValue()
|
|
// Return a suitable argument value by replacing NULL with Py_None.
|
|
//-----------------------------------------------------------------------------
|
|
static PyObject *ArgumentValue(
|
|
PyObject *object) // argument to massage
|
|
{
|
|
if (object) {
|
|
Py_INCREF(object);
|
|
return object;
|
|
}
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// HandleSystemExitException()
|
|
// Handles a system exit exception differently. If an integer value is passed
|
|
// through then that becomes the exit value; otherwise the string value of the
|
|
// value passed through is displayed in a message box.
|
|
//-----------------------------------------------------------------------------
|
|
static void HandleSystemExitException()
|
|
{
|
|
PyObject *type, *value, *traceback, *valueStr;
|
|
int exitCode = 0;
|
|
char *message;
|
|
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
if (PyInstance_Check(value)) {
|
|
PyObject *code = PyObject_GetAttrString(value, "code");
|
|
if (code) {
|
|
Py_DECREF(value);
|
|
value = code;
|
|
if (value == Py_None)
|
|
Py_Exit(0);
|
|
}
|
|
}
|
|
if (PyInt_Check(value))
|
|
exitCode = PyInt_AsLong(value);
|
|
else {
|
|
message = StringifyObject(value, &valueStr);
|
|
MessageBox(NULL, message, "cx_Freeze: Application Terminated",
|
|
MB_ICONERROR);
|
|
Py_XDECREF(valueStr);
|
|
exitCode = 1;
|
|
}
|
|
Py_Exit(exitCode);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// FatalScriptError()
|
|
// Handle a fatal Python error with traceback.
|
|
//-----------------------------------------------------------------------------
|
|
static int FatalScriptError()
|
|
{
|
|
PyObject *type, *value, *traceback, *argsTuple, *module, *method, *result;
|
|
int tracebackLength, i;
|
|
char *tracebackStr;
|
|
|
|
// if a system exception, handle it specially
|
|
if (PyErr_ExceptionMatches(PyExc_SystemExit))
|
|
HandleSystemExitException();
|
|
|
|
// get the exception details
|
|
PyErr_Fetch(&type, &value, &traceback);
|
|
|
|
// import the traceback module
|
|
module = PyImport_ImportModule("traceback");
|
|
if (!module)
|
|
return FatalPythonErrorNoTraceback(type, value,
|
|
"Cannot import traceback module.");
|
|
|
|
// get the format_exception method
|
|
method = PyObject_GetAttrString(module, "format_exception");
|
|
Py_DECREF(module);
|
|
if (!method)
|
|
return FatalPythonErrorNoTraceback(type, value,
|
|
"Cannot get format_exception method.");
|
|
|
|
// create a tuple for the arguments
|
|
argsTuple = PyTuple_New(3);
|
|
if (!argsTuple) {
|
|
Py_DECREF(method);
|
|
return FatalPythonErrorNoTraceback(type, value,
|
|
"Cannot create arguments tuple for traceback.");
|
|
}
|
|
PyTuple_SET_ITEM(argsTuple, 0, ArgumentValue(type));
|
|
PyTuple_SET_ITEM(argsTuple, 1, ArgumentValue(value));
|
|
PyTuple_SET_ITEM(argsTuple, 2, ArgumentValue(traceback));
|
|
|
|
// call the format_exception method
|
|
result = PyObject_CallObject(method, argsTuple);
|
|
Py_DECREF(method);
|
|
Py_DECREF(argsTuple);
|
|
if (!result)
|
|
return FatalPythonErrorNoTraceback(type, value,
|
|
"Failed calling format_exception method.");
|
|
|
|
// determine length of string representation of formatted traceback
|
|
tracebackLength = 1;
|
|
for (i = 0; i < PyList_GET_SIZE(result); i++)
|
|
tracebackLength += PyString_GET_SIZE(PyList_GET_ITEM(result, i));
|
|
|
|
// create a string representation of the formatted traceback
|
|
tracebackStr = malloc(tracebackLength);
|
|
if (!tracebackStr) {
|
|
Py_DECREF(result);
|
|
return FatalError("Out of memory!");
|
|
}
|
|
tracebackStr[0] = '\0';
|
|
for (i = 0; i < PyList_GET_SIZE(result); i++)
|
|
strcat(tracebackStr, PyString_AS_STRING(PyList_GET_ITEM(result, i)));
|
|
Py_DECREF(result);
|
|
|
|
// bring up the error
|
|
MessageBox(NULL, tracebackStr, "cx_Freeze: Python error in main script",
|
|
MB_ICONERROR);
|
|
Py_Finalize();
|
|
return 1;
|
|
}
|
|
|
|
|
|
#include "Common.c"
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// WinMain()
|
|
// Main routine for the executable in Windows.
|
|
//-----------------------------------------------------------------------------
|
|
int WINAPI WinMain(
|
|
HINSTANCE instance, // handle to application
|
|
HINSTANCE prevInstance, // previous handle to application
|
|
LPSTR commandLine, // command line
|
|
int showFlag) // show flag
|
|
{
|
|
const char *fileName;
|
|
|
|
// initialize Python
|
|
Py_NoSiteFlag = 1;
|
|
Py_FrozenFlag = 1;
|
|
Py_IgnoreEnvironmentFlag = 1;
|
|
Py_SetPythonHome("");
|
|
Py_SetProgramName(__argv[0]);
|
|
fileName = Py_GetProgramFullPath();
|
|
Py_Initialize();
|
|
PySys_SetArgv(__argc, __argv);
|
|
|
|
// do the work
|
|
if (ExecuteScript(fileName) < 0)
|
|
return 1;
|
|
|
|
// terminate Python
|
|
Py_Finalize();
|
|
return 0;
|
|
}
|
|
|