X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bin%2Fwinvlc.c;h=90ed7ce4de1cbea559207622261811dcb451d16d;hb=69d7fdea2da6f773fd7993f78c2bea494eb2d819;hp=18c1b13b1234e3989db029fc72b63df17ed5ba22;hpb=2c364f7a23dcea11d5e1c6fcb39130e66a4579db;p=vlc diff --git a/bin/winvlc.c b/bin/winvlc.c index 18c1b13b12..90ed7ce4de 100644 --- a/bin/winvlc.c +++ b/bin/winvlc.c @@ -35,6 +35,32 @@ #include #include +#if !defined(UNDER_CE) +# ifndef _WIN32_IE +# define _WIN32_IE 0x501 +# endif +# include +# include +# include +# ifndef _WIN64 +static void check_crashdump(void); +LONG WINAPI vlc_exception_filter(struct _EXCEPTION_POINTERS *lpExceptionInfo); +# endif +#define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1 +#endif + +#ifndef UNDER_CE +static char *FromWide (const wchar_t *wide) +{ + size_t len; + len = WideCharToMultiByte (CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL); + + char *out = (char *)malloc (len); + if (out) + WideCharToMultiByte (CP_UTF8, 0, wide, -1, out, len, NULL, NULL); + return out; +} +#else static int parse_cmdline (char *line, char ***argvp) { char **argv = malloc (sizeof (char *)); @@ -60,20 +86,20 @@ static int parse_cmdline (char *line, char ***argvp) argv[argc++] = line; more: - while (*line && !strchr ("\t ", *line)) + while (*line && !strchr ("\t ", *line)) line++; - if (line > argv[argc - 1] && line[-1] == quote) - /* End of quoted parameter */ - line[-1] = 0; - else + if (line > argv[argc - 1] && line[-1] == quote) + /* End of quoted parameter */ + line[-1] = 0; + else if (*line && quote) - { - /* Space within a quote */ - line++; - goto more; - } - else + { + /* Space within a quote */ + line++; + goto more; + } + else /* End of unquoted parameter */ if (*line) *line++ = 0; @@ -82,55 +108,216 @@ static int parse_cmdline (char *line, char ***argvp) *argvp = argv; return argc; } - -#ifdef UNDER_CE -# define wWinMain WinMain #endif -/***************************************************************************** - * wWinMain: parse command line, start interface and spawn threads. - *****************************************************************************/ -int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPWSTR lpCmdLine, int nCmdShow ) +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, +#ifndef UNDER_CE + LPSTR lpCmdLine, +#else + LPWSTR lpCmdLine, +#endif + int nCmdShow ) { - char **argv, psz_cmdline[wcslen(lpCmdLine) * 4 + 1]; - int argc, ret; + int argc; +#ifndef UNDER_CE + HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); + wchar_t **wargv = CommandLineToArgvW (GetCommandLine (), &argc); + if (wargv == NULL) + return 1; + + char *argv[argc + 1]; + BOOL crash_handling = TRUE; + int j = 0; + + argv[j++] = FromWide( L"--no-ignore-config" ); + for (int i = 1; i < argc; i++) + { + if(!wcscmp(wargv[i], L"--no-crashdump")) + { + crash_handling = FALSE; + } + else + { + argv[j] = FromWide (wargv[i]); + j++; + } + } + + argc = j; + argv[argc] = NULL; + LocalFree (wargv); - (void)hInstance; (void)hPrevInstance; (void)nCmdShow; +# ifndef _WIN64 + if(crash_handling) + { + check_crashdump(); + SetUnhandledExceptionFilter(vlc_exception_filter); + } +# endif /* WIN64 */ + +#else + char **argv, psz_cmdline[wcslen(lpCmdLine) * 4]; WideCharToMultiByte( CP_UTF8, 0, lpCmdLine, -1, psz_cmdline, sizeof (psz_cmdline), NULL, NULL ); argc = parse_cmdline (psz_cmdline, &argv); - - libvlc_exception_t ex, dummy; - libvlc_exception_init (&ex); - libvlc_exception_init (&dummy); +#endif /* Initialize libvlc */ - libvlc_instance_t *vlc = libvlc_new (argc, (const char **)argv, &ex); + libvlc_instance_t *vlc; + vlc = libvlc_new (argc, (const char **)argv); if (vlc != NULL) { - libvlc_add_intf (vlc, NULL, &ex); - libvlc_playlist_play (vlc, -1, 0, NULL, &dummy); + libvlc_add_intf (vlc, "globalhotkeys,none"); + libvlc_add_intf (vlc, NULL); + libvlc_playlist_play (vlc, -1, 0, NULL); libvlc_wait (vlc); libvlc_release (vlc); } - free (argv); - ret = libvlc_exception_raised (&ex); - libvlc_exception_clear (&ex); - libvlc_exception_clear (&dummy); - return ret; + for (int i = 0; i < argc; i++) + free (argv[i]); + + (void)hInstance; (void)hPrevInstance; (void)lpCmdLine; (void)nCmdShow; + return 0; } -#ifndef IF_MINGW_SUPPORTED_UNICODE -int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPSTR args, int nCmdShow) +#if !defined( UNDER_CE ) && !defined( _WIN64 ) + +static void get_crashdump_path(wchar_t * wdir) { - /* This makes little sense, but at least it links properly */ - wchar_t lpCmdLine[(strlen (args) + 1) * 3]; - MultiByteToWideChar (CP_ACP, 0, args, -1, lpCmdLine, sizeof (lpCmdLine)); - return wWinMain (hInstance, hPrevInstance, lpCmdLine, nCmdShow); + if( S_OK != SHGetFolderPathW( NULL, + CSIDL_APPDATA | CSIDL_FLAG_CREATE, + NULL, SHGFP_TYPE_CURRENT, wdir ) ) + fprintf( stderr, "Can't open the vlc conf PATH\n" ); + + swprintf( wdir+wcslen( wdir ), L"%s", L"\\vlc\\crashdump" ); +} + +static void check_crashdump() +{ + wchar_t * wdir = (wchar_t *)malloc(sizeof(wchar_t)*MAX_PATH); + get_crashdump_path(wdir); + + FILE * fd = _wfopen ( wdir, L"r, ccs=UTF-8" ); + if( fd ) + { + fclose( fd ); + int answer = MessageBox( NULL, L"VLC media player just crashed." \ + " Do you want to send a bug report to the developers team?", + L"VLC crash reporting", MB_YESNO); + + if(answer == IDYES) + { + HINTERNET Hint = InternetOpen(L"VLC Crash Reporter", INTERNET_OPEN_TYPE_PRECONFIG, NULL,NULL,0); + if(Hint) + { + HINTERNET ftp = InternetConnect(Hint, L"crash.videolan.org", INTERNET_DEFAULT_FTP_PORT, + NULL, NULL, INTERNET_SERVICE_FTP, 0, 0); + if(ftp) + { + SYSTEMTIME now; + GetSystemTime(&now); + wchar_t remote_file[MAX_PATH]; + swprintf( remote_file, L"/crashs/%04d%02d%02d%02d%02d%02d",now.wYear, + now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond ); + + FtpPutFile( ftp, wdir, remote_file, FTP_TRANSFER_TYPE_BINARY, 0); + InternetCloseHandle(ftp); + } + else + fprintf(stderr,"Can't connect to FTP server%d\n",GetLastError()); + InternetCloseHandle(Hint); + } + } + + _wremove(wdir); + } + free((void *)wdir); +} + +/***************************************************************************** + * vlc_exception_filter: handles unhandled exceptions, like segfaults + *****************************************************************************/ +LONG WINAPI vlc_exception_filter(struct _EXCEPTION_POINTERS *lpExceptionInfo) +{ + if(IsDebuggerPresent()) + { + //If a debugger is present, pass the exception to the debugger with EXCEPTION_CONTINUE_SEARCH + return EXCEPTION_CONTINUE_SEARCH; + } + else + { + fprintf( stderr, "unhandled vlc exception\n" ); + + wchar_t * wdir = (wchar_t *)malloc(sizeof(wchar_t)*MAX_PATH); + get_crashdump_path(wdir); + FILE * fd = _wfopen ( wdir, L"w, ccs=UTF-8" ); + free((void *)wdir); + + if( !fd ) + { + fprintf( stderr, "\nerror while opening file" ); + exit( 1 ); + } + + OSVERSIONINFO osvi; + ZeroMemory( &osvi, sizeof(OSVERSIONINFO) ); + osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO ); + GetVersionEx( &osvi ); + + fwprintf( fd, L"[version]\nOS=%d.%d.%d.%d.%s\nVLC=" VERSION_MESSAGE, osvi.dwMajorVersion, + osvi.dwMinorVersion, + osvi.dwBuildNumber, + osvi.dwPlatformId, + osvi.szCSDVersion); + + const CONTEXT *const pContext = (const CONTEXT *)lpExceptionInfo->ContextRecord; + const EXCEPTION_RECORD *const pException = (const EXCEPTION_RECORD *)lpExceptionInfo->ExceptionRecord; + /*No nested exceptions for now*/ + fwprintf( fd, L"\n\n[exceptions]\n%08x at %08x",pException->ExceptionCode, + pException->ExceptionAddress ); + if( pException->NumberParameters > 0 ) + { + unsigned int i; + for( i = 0; i < pException->NumberParameters; i++ ) + fprintf( fd, " | %08x", pException->ExceptionInformation[i] ); + } + + fwprintf( fd, L"\n\n[context]\nEDI:%08x\nESI:%08x\n" \ + "EBX:%08x\nEDX:%08x\nECX:%08x\nEAX:%08x\n" \ + "EBP:%08x\nEIP:%08x\nESP:%08x\n", + pContext->Edi,pContext->Esi,pContext->Ebx, + pContext->Edx,pContext->Ecx,pContext->Eax, + pContext->Ebp,pContext->Eip,pContext->Esp ); + + fwprintf( fd, L"\n[stacktrace]\n#EIP|base|module\n" ); + + wchar_t module[ 256 ]; + MEMORY_BASIC_INFORMATION mbi ; + VirtualQuery( (DWORD *)pContext->Eip, &mbi, sizeof( mbi ) ) ; + HINSTANCE hInstance = mbi.AllocationBase; + GetModuleFileName( hInstance, module, 256 ) ; + fwprintf( fd, L"%08x|%s\n", pContext->Eip, module ); + + DWORD pEbp = pContext->Ebp; + DWORD caller = *((DWORD*)pEbp + 1); + + do + { + VirtualQuery( (DWORD *)caller, &mbi, sizeof( mbi ) ) ; + HINSTANCE hInstance = mbi.AllocationBase; + GetModuleFileName( hInstance, module, 256 ) ; + fwprintf( fd, L"%08x|%s\n", caller, module ); + pEbp = *(DWORD*)pEbp ; + caller = *((DWORD*)pEbp + 1) ; + /*The last EBP points to NULL!*/ + }while(caller); + + fclose( fd ); + fflush( stderr ); + exit( 1 ); + } } #endif