winvlc.c 8.72 KB
Newer Older
1
/*****************************************************************************
2
 * winvlc.c: the Windows VLC media player
3
 *****************************************************************************
4
 * Copyright (C) 1998-2011 the VideoLAN team
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 *
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
 *          Samuel Hocevar <sam@zoy.org>
 *          Gildas Bazin <gbazin@videolan.org>
 *          Derk-Jan Hartman <hartman at videolan dot org>
 *          Lots of other people, see the libvlc AUTHORS file
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
31
#ifndef UNICODE
32
#define UNICODE
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
33 34
#endif

35 36
#include <vlc/vlc.h>
#include <windows.h>
37
#include <shellapi.h>
38

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
39 40 41 42 43 44 45
#ifndef _WIN32_IE
#  define  _WIN32_IE 0x501
#endif
#include <fcntl.h>
#include <io.h>
#include <shlobj.h>
#define HeapEnableTerminationOnCorruption (HEAP_INFORMATION_CLASS)1
46 47 48 49 50 51

#ifdef HAVE_BREAKPAD
void CheckCrashDump( const wchar_t* crashdump_path );
void* InstallCrashHandler( const wchar_t* crashdump_path );
void ReleaseCrashHandler( void* handler );
#endif
52

53
static char *FromWide (const wchar_t *wide)
54
{
55 56
    size_t len;
    len = WideCharToMultiByte (CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
57

58 59 60 61
    char *out = (char *)malloc (len);
    if (out)
        WideCharToMultiByte (CP_UTF8, 0, wide, -1, out, len, NULL, NULL);
    return out;
62 63
}

64 65 66 67 68 69 70
#if (_WIN32_WINNT < _WIN32_WINNT_WIN8)
static BOOL SetDefaultDllDirectories_(DWORD flags)
{
    HMODULE h = GetModuleHandle(TEXT("kernel32.dll"));
    if (h == NULL)
        return FALSE;

71
    BOOL (WINAPI * SetDefaultDllDirectoriesReal)(DWORD);
72 73 74 75 76 77 78 79 80

    SetDefaultDllDirectoriesReal = GetProcAddress(h,
                                                  "SetDefaultDllDirectories");
    if (SetDefaultDllDirectoriesReal == NULL)
        return FALSE;

    return SetDefaultDllDirectoriesReal(flags);
}
# define SetDefaultDllDirectories SetDefaultDllDirectories_
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

#endif

static void PrioritizeSystem32(void)
{
#ifndef HAVE_PROCESS_MITIGATION_IMAGE_LOAD_POLICY
    typedef struct _PROCESS_MITIGATION_IMAGE_LOAD_POLICY {
      union {
        DWORD  Flags;
        struct {
          DWORD NoRemoteImages  :1;
          DWORD NoLowMandatoryLabelImages  :1;
          DWORD PreferSystem32Images  :1;
          DWORD ReservedFlags  :29;
        };
      };
    } PROCESS_MITIGATION_IMAGE_LOAD_POLICY;
98
#endif
99 100 101 102 103 104 105 106 107 108 109 110 111 112
#if _WIN32_WINNT < _WIN32_WINNT_WIN8
    BOOL WINAPI (*SetProcessMitigationPolicy)(PROCESS_MITIGATION_POLICY, PVOID, SIZE_T);
    HINSTANCE h_Kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
    if ( !h_Kernel32 )
        return;
    SetProcessMitigationPolicy = (BOOL (WINAPI *)(PROCESS_MITIGATION_POLICY, PVOID, SIZE_T))
                                   GetProcAddress(h_Kernel32, "SetProcessMitigationPolicy");
    if (SetProcessMitigationPolicy == NULL)
        return;
#endif
    PROCESS_MITIGATION_IMAGE_LOAD_POLICY m = { .Flags = 0 };
    m.PreferSystem32Images = 1;
    SetProcessMitigationPolicy( 10 /* ProcessImageLoadPolicy */, &m, sizeof( m ) );
}
113

114 115 116 117 118 119 120
static void vlc_kill(void *data)
{
    HANDLE *semp = data;

    ReleaseSemaphore(*semp, 1, NULL);
}

121 122 123
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine,
                    int nCmdShow )
124
{
125
    int argc;
126

127 128 129 130 131 132 133
    /* VLC does not change the thread locale, so gettext/libintil will use the
     * user default locale as reference. */
    /* gettext versions 0.18-0.18.1 will use the Windows Vista locale name
     * if the GETTEXT_MUI environment variable is set. If not set or if running
     * on Windows 2000/XP/2003 an hard-coded language ID list is used. This
     * putenv() call may become redundant with later versions of gettext. */
    putenv("GETTEXT_MUI=1");
134 135
#ifdef TOP_BUILDDIR
    putenv("VLC_PLUGIN_PATH=Z:"TOP_BUILDDIR"/modules");
136
    putenv("VLC_DATA_PATH=Z:"TOP_SRCDIR"/share");
137 138
#endif

139 140 141 142 143 144
#ifndef NDEBUG
    /* Disable stderr buffering. Indeed, stderr can be buffered on Windows (if
     * connected to a pipe). */
    setvbuf (stderr, NULL, _IONBF, BUFSIZ);
#endif

145
    HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
146

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
147
    /* SetProcessDEPPolicy, SetDllDirectory, & Co. */
148 149
    HINSTANCE h_Kernel32 = GetModuleHandle(TEXT("kernel32.dll"));
    if (h_Kernel32 != NULL)
150
    {
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
151
        /* Enable DEP */
152
# define PROCESS_DEP_ENABLE 1
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
153
        BOOL (WINAPI * mySetProcessDEPPolicy)( DWORD dwFlags);
154
        mySetProcessDEPPolicy = (BOOL (WINAPI *)(DWORD))
155 156 157
                            GetProcAddress(h_Kernel32, "SetProcessDEPPolicy");
        if(mySetProcessDEPPolicy)
            mySetProcessDEPPolicy(PROCESS_DEP_ENABLE);
158

159 160
    }

161 162 163
    /* Do NOT load any library from cwd. */
    SetDllDirectory(TEXT(""));

Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
164 165 166 167
    /***
     * The LoadLibrary* calls from the modules and the 3rd party code
     * will search in SYSTEM32 only
     * */
168
    SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
169 170 171 172
    /***
     * Load DLLs from system32 before any other folder (when possible)
     */
    PrioritizeSystem32();
173

174
    /* Args */
175 176 177
    wchar_t **wargv = CommandLineToArgvW (GetCommandLine (), &argc);
    if (wargv == NULL)
        return 1;
178

179
    char *argv[argc + 3];
180 181
    BOOL crash_handling = TRUE;
    int j = 0;
182
    char *lang = NULL;
183

184
    argv[j++] = FromWide( L"--media-library" );
185 186
    argv[j++] = FromWide( L"--no-ignore-config" );
    for (int i = 1; i < argc; i++)
187 188 189 190
    {
        if(!wcscmp(wargv[i], L"--no-crashdump"))
        {
            crash_handling = FALSE;
Rafaël Carré's avatar
Rafaël Carré committed
191
            continue; /* don't give argument to libvlc */
192
        }
193 194 195 196 197 198
        if (!wcsncmp(wargv[i], L"--language", 10) )
        {
            if (i < argc - 1 && wcsncmp( wargv[i + 1], L"--", 2 ))
                lang = FromWide (wargv[++i]);
            continue;
        }
Rafaël Carré's avatar
Rafaël Carré committed
199 200

        argv[j++] = FromWide (wargv[i]);
201 202 203
    }

    argc = j;
204 205
    argv[argc] = NULL;
    LocalFree (wargv);
206

207
#ifdef HAVE_BREAKPAD
208
    void* eh = NULL;
209 210
    if(crash_handling)
    {
211 212 213 214
        static wchar_t path[MAX_PATH];
        if( S_OK != SHGetFolderPathW( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
                    NULL, SHGFP_TYPE_CURRENT, path ) )
            fprintf( stderr, "Can't open the vlc conf PATH\n" );
215
        _snwprintf( path+wcslen( path ), MAX_PATH,  L"%s", L"\\vlc\\crashdump" );
216 217
        CheckCrashDump( &path[0] );
        eh = InstallCrashHandler( &path[0] );
218
    }
219
#endif
220

221
    _setmode( _fileno( stdin ), _O_BINARY ); /* Needed for pipes */
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    /* */
    if (!lang)
    {
        HKEY h_key;
        if( RegOpenKeyEx( HKEY_CURRENT_USER, TEXT("Software\\VideoLAN\\VLC\\"), 0, KEY_READ, &h_key )
                == ERROR_SUCCESS )
        {
            TCHAR szData[256];
            DWORD len = 256;
            if( RegQueryValueEx( h_key, TEXT("Lang"), NULL, NULL, (LPBYTE) &szData, &len ) == ERROR_SUCCESS )
                lang = FromWide( szData );
        }
    }

    if (lang && strncmp( lang, "auto", 4 ) )
    {
239 240 241
        char tmp[11];
        snprintf(tmp, 11, "LANG=%s", lang);
        putenv(tmp);
242 243 244
    }
    free(lang);

245
    /* Initialize libvlc */
246
    libvlc_instance_t *vlc;
247
    vlc = libvlc_new (argc, (const char **)argv);
248 249
    if (vlc != NULL)
    {
250 251 252
        HANDLE sem = CreateSemaphore(NULL, 0, 1, NULL);

        libvlc_set_exit_handler(vlc, vlc_kill, &sem);
253 254
        libvlc_set_app_id (vlc, "org.VideoLAN.VLC", PACKAGE_VERSION,
                           PACKAGE_NAME);
255
        libvlc_set_user_agent (vlc, "VLC media player", "VLC/"PACKAGE_VERSION);
256
        libvlc_add_intf (vlc, "hotkeys,none");
257 258
        libvlc_add_intf (vlc, "globalhotkeys,none");
        libvlc_add_intf (vlc, NULL);
259
        libvlc_playlist_play (vlc);
260 261 262 263

        WaitForSingleObject(sem, INFINITE);
        CloseHandle(sem);

264 265
        libvlc_release (vlc);
    }
266 267 268 269 270 271
    else
        MessageBox (NULL, TEXT("VLC media player could not start.\n"
                    "Either the command line options were invalid or no plugins were found.\n"),
                    TEXT("VLC media player"),
                    MB_OK|MB_ICONERROR);

272

273 274 275
#ifdef HAVE_BREAKPAD
    ReleaseCrashHandler( eh );
#endif
276 277 278 279
    for (int i = 0; i < argc; i++)
        free (argv[i]);

    (void)hInstance; (void)hPrevInstance; (void)lpCmdLine; (void)nCmdShow;
280
    return 0;
281
}