Move core Win32 files to their own directory
authorRémi Denis-Courmont <remi@remlab.net>
Wed, 13 Jan 2010 16:13:17 +0000 (18:13 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Wed, 13 Jan 2010 16:14:45 +0000 (18:14 +0200)
There is still too much stuff in misc/ ;-)

po/POTFILES.in
src/Makefile.am
src/config/dirs_win.c [deleted file]
src/misc/w32thread.c [deleted file]
src/misc/win32_specific.c [deleted file]
src/network/winsock.c [deleted file]
src/win32/dirs.c [new file with mode: 0644]
src/win32/specific.c [new file with mode: 0644]
src/win32/thread.c [new file with mode: 0644]
src/win32/winsock.c [new file with mode: 0644]

index a8b9fb2..03682b2 100644 (file)
@@ -79,7 +79,6 @@ src/config/cmdline.c
 src/config/configuration.h
 src/config/core.c
 src/config/dirs_macos.c
-src/config/dirs_win.c
 src/config/dirs_xdg.c
 src/config/file.c
 src/config/intf.c
@@ -163,7 +162,6 @@ src/misc/update.c
 src/misc/update.h
 src/misc/variables.c
 src/misc/variables.h
-src/misc/win32_specific.c
 src/misc/xml.c
 src/missing.c
 src/modules/cache.c
@@ -180,7 +178,6 @@ src/network/rootbind.c
 src/network/tcp.c
 src/network/tls.c
 src/network/udp.c
-src/network/winsock.c
 src/osd/osd.c
 src/osd/osd_text.c
 src/osd/osd_widgets.c
index c20f17a..7d6dee7 100644 (file)
@@ -279,10 +279,10 @@ SOURCES_libvlc_linux = \
        $(NULL)
 
 SOURCES_libvlc_win32 = \
-       config/dirs_win.c \
-       misc/w32thread.c \
-       misc/win32_specific.c \
-       network/winsock.c \
+       win32/dirs.c \
+       win32/specific.c \
+       win32/thread.c \
+       win32/winsock.c \
        $(NULL)
 
 SOURCES_libvlc_other = \
diff --git a/src/config/dirs_win.c b/src/config/dirs_win.c
deleted file mode 100644 (file)
index 71d176e..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*****************************************************************************
- * dirs.c: directories configuration
- *****************************************************************************
- * Copyright (C) 2001-2007 the VideoLAN team
- * Copyright © 2007-2008 Rémi Denis-Courmont
- *
- * Authors: Gildas Bazin <gbazin@videolan.org>
- *
- * 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
-
-#include <vlc_common.h>
-
-#ifndef _WIN32_IE
-# define _WIN32_IE 0x0501
-#endif
-#include <w32api.h>
-#ifndef UNDER_CE
-# include <direct.h>
-#endif
-#include <shlobj.h>
-
-#include "../libvlc.h"
-#include <vlc_charset.h>
-#include <vlc_configuration.h>
-
-#include <assert.h>
-#include <limits.h>
-
-const char *config_GetDataDirDefault( void )
-{
-    static char path[PATH_MAX] = "";
-#warning FIXME: thread-safety!
-
-    if( *path == '\0' )
-        strlcpy (path, psz_vlcpath, sizeof (path));
-    return path;
-}
-
-const char *config_GetConfDir (void)
-{
-    static char appdir[PATH_MAX] = "";
-    wchar_t wdir[MAX_PATH];
-
-#warning FIXME: thread-safety!
-    if (*appdir)
-        return appdir;
-
-#if defined (UNDER_CE)
-    /*There are some errors in cegcc headers*/
-#undef SHGetSpecialFolderPath
-    BOOL WINAPI SHGetSpecialFolderPath(HWND,LPWSTR,int,BOOL);
-    if( SHGetSpecialFolderPath( NULL, wdir, CSIDL_APPDATA, 1 ) )
-#else
-    /* Get the "Application Data" folder for all users */
-    if( S_OK == SHGetFolderPathW( NULL, CSIDL_COMMON_APPDATA
-              | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, wdir ) )
-#endif
-    {
-        WideCharToMultiByte (CP_UTF8, 0, wdir, -1,
-                             appdir, PATH_MAX, NULL, NULL);
-        return appdir;
-    }
-    return NULL;
-}
-
-static char *config_GetShellDir (int csidl)
-{
-    wchar_t wdir[MAX_PATH];
-
-#if defined (UNDER_CE)
-    /*There are some errors in cegcc headers*/
-#undef SHGetSpecialFolderPath
-    BOOL WINAPI SHGetSpecialFolderPath(HWND,LPWSTR,int,BOOL);
-    if (SHGetSpecialFolderPath (NULL, wdir, CSIDL_APPDATA, 1))
-#else
-    if (SHGetFolderPathW (NULL, csidl | CSIDL_FLAG_CREATE,
-                          NULL, SHGFP_TYPE_CURRENT, wdir ) == S_OK)
-#endif
-        return FromWide (wdir);
-    return NULL;
-}
-
-static char *config_GetAppDir (void)
-{
-    char *psz_dir;
-    char *psz_parent = config_GetShellDir (CSIDL_APPDATA);
-
-    if (psz_parent == NULL
-     ||  asprintf (&psz_dir, "%s\\vlc", psz_parent) == -1)
-        psz_dir = NULL;
-    free (psz_parent);
-    return psz_dir;
-}
-
-#warning FIXME Use known folders on Vista and above
-char *config_GetUserDir (vlc_userdir_t type)
-{
-    switch (type)
-    {
-        case VLC_HOME_DIR:
-            return config_GetShellDir (CSIDL_PERSONAL);
-        case VLC_CONFIG_DIR:
-        case VLC_DATA_DIR:
-        case VLC_CACHE_DIR:
-            return config_GetAppDir ();
-
-        case VLC_DESKTOP_DIR:
-        case VLC_DOWNLOAD_DIR:
-        case VLC_TEMPLATES_DIR:
-        case VLC_PUBLICSHARE_DIR:
-        case VLC_DOCUMENTS_DIR:
-            return config_GetUserDir(VLC_HOME_DIR);
-        case VLC_MUSIC_DIR:
-            return config_GetShellDir (CSIDL_MYMUSIC);
-        case VLC_PICTURES_DIR:
-            return config_GetShellDir (CSIDL_MYPICTURES);
-        case VLC_VIDEOS_DIR:
-            return config_GetShellDir (CSIDL_MYVIDEO);
-    }
-    assert (0);
-}
diff --git a/src/misc/w32thread.c b/src/misc/w32thread.c
deleted file mode 100644 (file)
index 234ef8b..0000000
+++ /dev/null
@@ -1,829 +0,0 @@
-/*****************************************************************************
- * w32thread.c : Win32 back-end for LibVLC
- *****************************************************************************
- * Copyright (C) 1999-2009 the VideoLAN team
- * $Id$
- *
- * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
- *          Samuel Hocevar <sam@zoy.org>
- *          Gildas Bazin <gbazin@netcourrier.com>
- *          Clément Sténac
- *          Rémi Denis-Courmont
- *          Pierre Ynard
- *
- * 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
-
-#include <vlc_common.h>
-
-#include "libvlc.h"
-#include <stdarg.h>
-#include <assert.h>
-#include <limits.h>
-#include <errno.h>
-#ifdef UNDER_CE
-# include <mmsystem.h>
-#endif
-
-static vlc_threadvar_t cancel_key;
-
-/**
- * Per-thread cancellation data
- */
-typedef struct vlc_cancel_t
-{
-    vlc_cleanup_t *cleaners;
-#ifdef UNDER_CE
-    HANDLE         cancel_event;
-#endif
-    bool           killable;
-    bool           killed;
-} vlc_cancel_t;
-
-#ifndef UNDER_CE
-# define VLC_CANCEL_INIT { NULL, true, false }
-#else
-# define VLC_CANCEL_INIT { NULL, NULL, true, false }
-#endif
-
-#ifdef UNDER_CE
-static void CALLBACK vlc_cancel_self (ULONG_PTR dummy);
-
-static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles,
-                                  DWORD delay)
-{
-    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
-    if (nfo == NULL)
-    {
-        /* Main thread - cannot be cancelled anyway */
-        return WaitForMultipleObjects (count, handles, FALSE, delay);
-    }
-    HANDLE new_handles[count + 1];
-    memcpy(new_handles, handles, count * sizeof(HANDLE));
-    new_handles[count] = nfo->cancel_event;
-    DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE,
-                                           delay);
-    if (result == WAIT_OBJECT_0 + count)
-    {
-        vlc_cancel_self (NULL);
-        return WAIT_IO_COMPLETION;
-    }
-    else
-    {
-        return result;
-    }
-}
-
-DWORD SleepEx (DWORD dwMilliseconds, BOOL bAlertable)
-{
-    if (bAlertable)
-    {
-        DWORD result = vlc_cancelable_wait (0, NULL, dwMilliseconds);
-        return (result == WAIT_TIMEOUT) ? 0 : WAIT_IO_COMPLETION;
-    }
-    else
-    {
-        Sleep(dwMilliseconds);
-        return 0;
-    }
-}
-
-DWORD WaitForSingleObjectEx (HANDLE hHandle, DWORD dwMilliseconds,
-                             BOOL bAlertable)
-{
-    if (bAlertable)
-    {
-        /* The MSDN documentation specifies different return codes,
-         * but in practice they are the same. We just check that it
-         * remains so. */
-#if WAIT_ABANDONED != WAIT_ABANDONED_0
-# error Windows headers changed, code needs to be rewritten!
-#endif
-        return vlc_cancelable_wait (1, &hHandle, dwMilliseconds);
-    }
-    else
-    {
-        return WaitForSingleObject (hHandle, dwMilliseconds);
-    }
-}
-
-DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles,
-                                BOOL bWaitAll, DWORD dwMilliseconds,
-                                BOOL bAlertable)
-{
-    if (bAlertable)
-    {
-        /* We do not support the bWaitAll case */
-        assert (! bWaitAll);
-        return vlc_cancelable_wait (nCount, lpHandles, dwMilliseconds);
-    }
-    else
-    {
-        return WaitForMultipleObjects (nCount, lpHandles, bWaitAll,
-                                       dwMilliseconds);
-    }
-}
-#endif
-
-vlc_mutex_t super_mutex;
-vlc_cond_t  super_variable;
-
-BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
-{
-    (void) hinstDll;
-    (void) lpvReserved;
-
-    switch (fdwReason)
-    {
-        case DLL_PROCESS_ATTACH:
-            vlc_mutex_init (&super_mutex);
-            vlc_cond_init (&super_variable);
-            vlc_threadvar_create (&cancel_key, free);
-            break;
-
-        case DLL_PROCESS_DETACH:
-            vlc_threadvar_delete( &cancel_key );
-            vlc_cond_destroy (&super_variable);
-            vlc_mutex_destroy (&super_mutex);
-            break;
-    }
-    return TRUE;
-}
-
-/*** Mutexes ***/
-void vlc_mutex_init( vlc_mutex_t *p_mutex )
-{
-    /* This creates a recursive mutex. This is OK as fast mutexes have
-     * no defined behavior in case of recursive locking. */
-    InitializeCriticalSection (&p_mutex->mutex);
-    p_mutex->dynamic = true;
-}
-
-void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
-{
-    InitializeCriticalSection( &p_mutex->mutex );
-    p_mutex->dynamic = true;
-}
-
-
-void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
-{
-    assert (p_mutex->dynamic);
-    DeleteCriticalSection (&p_mutex->mutex);
-}
-
-void vlc_mutex_lock (vlc_mutex_t *p_mutex)
-{
-    if (!p_mutex->dynamic)
-    {   /* static mutexes */
-        assert (p_mutex != &super_mutex); /* this one cannot be static */
-
-        vlc_mutex_lock (&super_mutex);
-        while (p_mutex->locked)
-        {
-            p_mutex->contention++;
-            vlc_cond_wait (&super_variable, &super_mutex);
-            p_mutex->contention--;
-        }
-        p_mutex->locked = true;
-        vlc_mutex_unlock (&super_mutex);
-        return;
-    }
-
-    EnterCriticalSection (&p_mutex->mutex);
-}
-
-int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
-{
-    if (!p_mutex->dynamic)
-    {   /* static mutexes */
-        int ret = EBUSY;
-
-        assert (p_mutex != &super_mutex); /* this one cannot be static */
-        vlc_mutex_lock (&super_mutex);
-        if (!p_mutex->locked)
-        {
-            p_mutex->locked = true;
-            ret = 0;
-        }
-        vlc_mutex_unlock (&super_mutex);
-        return ret;
-    }
-
-    return TryEnterCriticalSection (&p_mutex->mutex) ? 0 : EBUSY;
-}
-
-void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
-{
-    if (!p_mutex->dynamic)
-    {   /* static mutexes */
-        assert (p_mutex != &super_mutex); /* this one cannot be static */
-
-        vlc_mutex_lock (&super_mutex);
-        assert (p_mutex->locked);
-        p_mutex->locked = false;
-        if (p_mutex->contention)
-            vlc_cond_broadcast (&super_variable);
-        vlc_mutex_unlock (&super_mutex);
-        return;
-    }
-
-    LeaveCriticalSection (&p_mutex->mutex);
-}
-
-/*** Condition variables ***/
-void vlc_cond_init( vlc_cond_t *p_condvar )
-{
-    /* Create a manual-reset event (manual reset is needed for broadcast). */
-    *p_condvar = CreateEvent (NULL, TRUE, FALSE, NULL);
-    if (!*p_condvar)
-        abort();
-}
-
-void vlc_cond_destroy (vlc_cond_t *p_condvar)
-{
-    CloseHandle (*p_condvar);
-}
-
-void vlc_cond_signal (vlc_cond_t *p_condvar)
-{
-    /* NOTE: This will cause a broadcast, that is wrong.
-     * This will also wake up the next waiting thread if no threads are yet
-     * waiting, which is also wrong. However both of these issues are allowed
-     * by the provision for spurious wakeups. Better have too many wakeups
-     * than too few (= deadlocks). */
-    SetEvent (*p_condvar);
-}
-
-void vlc_cond_broadcast (vlc_cond_t *p_condvar)
-{
-    SetEvent (*p_condvar);
-}
-
-void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
-{
-    DWORD result;
-
-    assert (p_mutex->dynamic); /* TODO */
-    do
-    {
-        vlc_testcancel ();
-        LeaveCriticalSection (&p_mutex->mutex);
-        result = WaitForSingleObjectEx (*p_condvar, INFINITE, TRUE);
-        EnterCriticalSection (&p_mutex->mutex);
-    }
-    while (result == WAIT_IO_COMPLETION);
-
-    assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
-    assert (result != WAIT_FAILED);
-    ResetEvent (*p_condvar);
-}
-
-int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
-                        mtime_t deadline)
-{
-    DWORD result;
-
-    assert (p_mutex->dynamic); /* TODO */
-    do
-    {
-        vlc_testcancel ();
-
-        mtime_t total = (deadline - mdate ())/1000;
-        if( total < 0 )
-            total = 0;
-
-        DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
-        LeaveCriticalSection (&p_mutex->mutex);
-        result = WaitForSingleObjectEx (*p_condvar, delay, TRUE);
-        EnterCriticalSection (&p_mutex->mutex);
-    }
-    while (result == WAIT_IO_COMPLETION);
-
-    assert (result != WAIT_ABANDONED);
-    assert (result != WAIT_FAILED);
-    ResetEvent (*p_condvar);
-
-    return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
-}
-
-/*** Semaphore ***/
-void vlc_sem_init (vlc_sem_t *sem, unsigned value)
-{
-    *sem = CreateSemaphore (NULL, value, 0x7fffffff, NULL);
-    if (*sem == NULL)
-        abort ();
-}
-
-void vlc_sem_destroy (vlc_sem_t *sem)
-{
-    CloseHandle (*sem);
-}
-
-int vlc_sem_post (vlc_sem_t *sem)
-{
-    ReleaseSemaphore (*sem, 1, NULL);
-    return 0; /* FIXME */
-}
-
-void vlc_sem_wait (vlc_sem_t *sem)
-{
-    DWORD result;
-
-    do
-    {
-        vlc_testcancel ();
-        result = WaitForSingleObjectEx (*sem, INFINITE, TRUE);
-    }
-    while (result == WAIT_IO_COMPLETION);
-}
-
-/*** Read/write locks */
-/* SRW (Slim Read Write) locks are available in Vista+ only */
-void vlc_rwlock_init (vlc_rwlock_t *lock)
-{
-    vlc_mutex_init (&lock->mutex);
-    vlc_cond_init (&lock->read_wait);
-    vlc_cond_init (&lock->write_wait);
-    lock->readers = 0; /* active readers */
-    lock->writers = 0; /* waiting or active writers */
-    lock->writer = 0; /* ID of active writer */
-}
-
-/**
- * Destroys an initialized unused read/write lock.
- */
-void vlc_rwlock_destroy (vlc_rwlock_t *lock)
-{
-    vlc_cond_destroy (&lock->read_wait);
-    vlc_cond_destroy (&lock->write_wait);
-    vlc_mutex_destroy (&lock->mutex);
-}
-
-/**
- * Acquires a read/write lock for reading. Recursion is allowed.
- */
-void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    while (lock->writer != 0)
-        vlc_cond_wait (&lock->read_wait, &lock->mutex);
-    if (lock->readers == ULONG_MAX)
-        abort ();
-    lock->readers++;
-    vlc_mutex_unlock (&lock->mutex);
-}
-
-/**
- * Acquires a read/write lock for writing. Recursion is not allowed.
- */
-void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    if (lock->writers == ULONG_MAX)
-        abort ();
-    lock->writers++;
-    while ((lock->readers > 0) || (lock->writer != 0))
-        vlc_cond_wait (&lock->write_wait, &lock->mutex);
-    lock->writers--;
-    lock->writer = GetCurrentThreadId ();
-    vlc_mutex_unlock (&lock->mutex);
-}
-
-/**
- * Releases a read/write lock.
- */
-void vlc_rwlock_unlock (vlc_rwlock_t *lock)
-{
-    vlc_mutex_lock (&lock->mutex);
-    if (lock->readers > 0)
-        lock->readers--; /* Read unlock */
-    else
-        lock->writer = 0; /* Write unlock */
-
-    if (lock->writers > 0)
-    {
-        if (lock->readers == 0)
-            vlc_cond_signal (&lock->write_wait);
-    }
-    else
-        vlc_cond_broadcast (&lock->read_wait);
-    vlc_mutex_unlock (&lock->mutex);
-}
-
-/*** Thread-specific variables (TLS) ***/
-int vlc_threadvar_create (vlc_threadvar_t *p_tls, void (*destr) (void *))
-{
-#warning FIXME: use destr() callback and stop leaking!
-    VLC_UNUSED( destr );
-
-    *p_tls = TlsAlloc();
-    return (*p_tls == TLS_OUT_OF_INDEXES) ? EAGAIN : 0;
-}
-
-void vlc_threadvar_delete (vlc_threadvar_t *p_tls)
-{
-    TlsFree (*p_tls);
-}
-
-/**
- * Sets a thread-local variable.
- * @param key thread-local variable key (created with vlc_threadvar_create())
- * @param value new value for the variable for the calling thread
- * @return 0 on success, a system error code otherwise.
- */
-int vlc_threadvar_set (vlc_threadvar_t key, void *value)
-{
-    return TlsSetValue (key, value) ? ENOMEM : 0;
-}
-
-/**
- * Gets the value of a thread-local variable for the calling thread.
- * This function cannot fail.
- * @return the value associated with the given variable for the calling
- * or NULL if there is no value.
- */
-void *vlc_threadvar_get (vlc_threadvar_t key)
-{
-    return TlsGetValue (key);
-}
-
-
-/*** Threads ***/
-void vlc_threads_setup (libvlc_int_t *p_libvlc)
-{
-    (void) p_libvlc;
-}
-
-struct vlc_entry_data
-{
-    void * (*func) (void *);
-    void *  data;
-#ifdef UNDER_CE
-    HANDLE  cancel_event;
-#endif
-};
-
-static unsigned __stdcall vlc_entry (void *p)
-{
-    vlc_cancel_t cancel_data = VLC_CANCEL_INIT;
-    struct vlc_entry_data data;
-
-    memcpy (&data, p, sizeof (data));
-    free (p);
-
-#ifdef UNDER_CE
-    cancel_data.cancel_event = data.cancel_event;
-#endif
-
-    vlc_threadvar_set (cancel_key, &cancel_data);
-    data.func (data.data);
-    return 0;
-}
-
-int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
-               int priority)
-{
-    int err = ENOMEM;
-    HANDLE hThread;
-
-    struct vlc_entry_data *entry_data = malloc (sizeof (*entry_data));
-    if (entry_data == NULL)
-        return ENOMEM;
-    entry_data->func = entry;
-    entry_data->data = data;
-
-#ifndef UNDER_CE
-    /* When using the MSVCRT C library you have to use the _beginthreadex
-     * function instead of CreateThread, otherwise you'll end up with
-     * memory leaks and the signal functions not working (see Microsoft
-     * Knowledge Base, article 104641) */
-    hThread = (HANDLE)(uintptr_t)
-        _beginthreadex (NULL, 0, vlc_entry, entry_data, CREATE_SUSPENDED, NULL);
-    if (! hThread)
-    {
-        err = errno;
-        goto error;
-    }
-
-    /* Thread closes the handle when exiting, duplicate it here
-     * to be on the safe side when joining. */
-    if (!DuplicateHandle (GetCurrentProcess (), hThread,
-                          GetCurrentProcess (), p_handle, 0, FALSE,
-                          DUPLICATE_SAME_ACCESS))
-    {
-        CloseHandle (hThread);
-        goto error;
-    }
-
-#else
-    vlc_thread_t th = malloc (sizeof (*th));
-    if (th == NULL)
-        goto error;
-    th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL);
-    if (th->cancel_event == NULL)
-    {
-        free (th);
-        goto error;
-    }
-    entry_data->cancel_event = th->cancel_event;
-
-    /* Not sure if CREATE_SUSPENDED + ResumeThread() is any useful on WinCE.
-     * Thread handles act up, too. */
-    th->handle = CreateThread (NULL, 128*1024, vlc_entry, entry_data,
-                               CREATE_SUSPENDED, NULL);
-    if (th->handle == NULL)
-    {
-        CloseHandle (th->cancel_event);
-        free (th);
-        goto error;
-    }
-
-    *p_handle = th;
-    hThread = th->handle;
-
-#endif
-
-    ResumeThread (hThread);
-    if (priority)
-        SetThreadPriority (hThread, priority);
-
-    return 0;
-
-error:
-    free (entry_data);
-    return err;
-}
-
-void vlc_join (vlc_thread_t handle, void **result)
-{
-#ifdef UNDER_CE
-# define handle handle->handle
-#endif
-    do
-        vlc_testcancel ();
-    while (WaitForSingleObjectEx (handle, INFINITE, TRUE)
-                                                        == WAIT_IO_COMPLETION);
-
-    CloseHandle (handle);
-    assert (result == NULL); /* <- FIXME if ever needed */
-#ifdef UNDER_CE
-# undef handle
-    CloseHandle (handle->cancel_event);
-    free (handle);
-#endif
-}
-
-void vlc_detach (vlc_thread_t handle)
-{
-#ifndef UNDER_CE
-    CloseHandle (handle);
-#else
-    /* FIXME: handle->cancel_event leak */
-    CloseHandle (handle->handle);
-    free (handle);
-#endif
-}
-
-/*** Thread cancellation ***/
-
-/* APC procedure for thread cancellation */
-static void CALLBACK vlc_cancel_self (ULONG_PTR dummy)
-{
-    (void)dummy;
-    vlc_control_cancel (VLC_DO_CANCEL);
-}
-
-void vlc_cancel (vlc_thread_t thread_id)
-{
-#ifndef UNDER_CE
-    QueueUserAPC (vlc_cancel_self, thread_id, 0);
-#else
-    SetEvent (thread_id->cancel_event);
-#endif
-}
-
-int vlc_savecancel (void)
-{
-    int state;
-
-    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
-    if (nfo == NULL)
-        return false; /* Main thread - cannot be cancelled anyway */
-
-    state = nfo->killable;
-    nfo->killable = false;
-    return state;
-}
-
-void vlc_restorecancel (int state)
-{
-    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
-    assert (state == false || state == true);
-
-    if (nfo == NULL)
-        return; /* Main thread - cannot be cancelled anyway */
-
-    assert (!nfo->killable);
-    nfo->killable = state != 0;
-}
-
-void vlc_testcancel (void)
-{
-    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
-    if (nfo == NULL)
-        return; /* Main thread - cannot be cancelled anyway */
-
-    if (nfo->killable && nfo->killed)
-    {
-        for (vlc_cleanup_t *p = nfo->cleaners; p != NULL; p = p->next)
-             p->proc (p->data);
-#ifndef UNDER_CE
-        _endthread ();
-#else
-        ExitThread(0);
-#endif
-    }
-}
-
-void vlc_control_cancel (int cmd, ...)
-{
-    /* NOTE: This function only modifies thread-specific data, so there is no
-     * need to lock anything. */
-    va_list ap;
-
-    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
-    if (nfo == NULL)
-        return; /* Main thread - cannot be cancelled anyway */
-
-    va_start (ap, cmd);
-    switch (cmd)
-    {
-        case VLC_DO_CANCEL:
-            nfo->killed = true;
-            break;
-
-        case VLC_CLEANUP_PUSH:
-        {
-            /* cleaner is a pointer to the caller stack, no need to allocate
-             * and copy anything. As a nice side effect, this cannot fail. */
-            vlc_cleanup_t *cleaner = va_arg (ap, vlc_cleanup_t *);
-            cleaner->next = nfo->cleaners;
-            nfo->cleaners = cleaner;
-            break;
-        }
-
-        case VLC_CLEANUP_POP:
-        {
-            nfo->cleaners = nfo->cleaners->next;
-            break;
-        }
-    }
-    va_end (ap);
-}
-
-
-/*** Timers ***/
-struct vlc_timer
-{
-#ifndef UNDER_CE
-    HANDLE handle;
-#else
-    unsigned id;
-    unsigned interval;
-#endif
-    void (*func) (void *);
-    void *data;
-};
-
-#ifndef UNDER_CE
-static void CALLBACK vlc_timer_do (void *val, BOOLEAN timeout)
-{
-    struct vlc_timer *timer = val;
-
-    assert (timeout);
-    timer->func (timer->data);
-}
-#else
-static void CALLBACK vlc_timer_do (unsigned timer_id, unsigned msg,
-                                   DWORD_PTR user, DWORD_PTR unused1,
-                                   DWORD_PTR unused2)
-{
-    struct vlc_timer *timer = (struct vlc_timer *) user;
-    assert (timer_id == timer->id);
-    (void) msg;
-    (void) unused1;
-    (void) unused2;
-
-    timer->func (timer->data);
-
-    if (timer->interval)
-    {
-        mtime_t interval = timer->interval * 1000;
-        vlc_timer_schedule (timer, false, interval, interval);
-    }
-}
-#endif
-
-int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
-{
-    struct vlc_timer *timer = malloc (sizeof (*timer));
-
-    if (timer == NULL)
-        return ENOMEM;
-    timer->func = func;
-    timer->data = data;
-#ifndef UNDER_CE
-    timer->handle = INVALID_HANDLE_VALUE;
-#else
-    timer->id = 0;
-    timer->interval = 0;
-#endif
-    *id = timer;
-    return 0;
-}
-
-void vlc_timer_destroy (vlc_timer_t timer)
-{
-#ifndef UNDER_CE
-    if (timer->handle != INVALID_HANDLE_VALUE)
-        DeleteTimerQueueTimer (NULL, timer->handle, INVALID_HANDLE_VALUE);
-#else
-    if (timer->id)
-        timeKillEvent (timer->id);
-    /* FIXME: timers that have not yet completed will trigger use-after-free */
-#endif
-    free (timer);
-}
-
-void vlc_timer_schedule (vlc_timer_t timer, bool absolute,
-                         mtime_t value, mtime_t interval)
-{
-#ifndef UNDER_CE
-    if (timer->handle != INVALID_HANDLE_VALUE)
-    {
-        DeleteTimerQueueTimer (NULL, timer->handle, NULL);
-        timer->handle = INVALID_HANDLE_VALUE;
-    }
-#else
-    if (timer->id)
-    {
-        timeKillEvent (timer->id);
-        timer->id = 0;
-        timer->interval = 0;
-    }
-#endif
-    if (value == 0)
-        return; /* Disarm */
-
-    if (absolute)
-        value -= mdate ();
-    value = (value + 999) / 1000;
-    interval = (interval + 999) / 1000;
-
-#ifndef UNDER_CE
-    if (!CreateTimerQueueTimer (&timer->handle, NULL, vlc_timer_do, timer,
-                                value, interval, WT_EXECUTEDEFAULT))
-#else
-    TIMECAPS caps;
-    timeGetDevCaps (&caps, sizeof(caps));
-
-    unsigned delay = value;
-    delay = __MAX(delay, caps.wPeriodMin);
-    delay = __MIN(delay, caps.wPeriodMax);
-
-    unsigned event = TIME_ONESHOT;
-
-    if (interval == delay)
-        event = TIME_PERIODIC;
-    else if (interval)
-        timer->interval = interval;
-
-    timer->id = timeSetEvent (delay, delay / 20, vlc_timer_do, (DWORD) timer,
-                              event);
-    if (!timer->id)
-#endif
-        abort ();
-}
-
-unsigned vlc_timer_getoverrun (vlc_timer_t timer)
-{
-    (void)timer;
-    return 0;
-}
diff --git a/src/misc/win32_specific.c b/src/misc/win32_specific.c
deleted file mode 100644 (file)
index e341bae..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*****************************************************************************
- * win32_specific.c: Win32 specific features
- *****************************************************************************
- * Copyright (C) 2001-2004 the VideoLAN team
- * $Id$
- *
- * Authors: Samuel Hocevar <sam@zoy.org>
- *          Gildas Bazin <gbazin@videolan.org>
- *
- * 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
-
-#define UNICODE
-#include <vlc_common.h>
-#include "../libvlc.h"
-#include <vlc_playlist.h>
-#include <vlc_charset.h>
-
-#include "../extras/getopt.h"
-
-#if !defined( UNDER_CE )
-#   include <io.h>
-#   include <fcntl.h>
-#   include  <mmsystem.h>
-#endif
-
-#include <winsock.h>
-
-/*****************************************************************************
- * system_Init: initialize winsock and misc other things.
- *****************************************************************************/
-void system_Init( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
-{
-    VLC_UNUSED( p_this ); VLC_UNUSED( pi_argc ); VLC_UNUSED( ppsz_argv );
-    WSADATA Data;
-
-    /* Get our full path */
-    char psz_path[MAX_PATH];
-    char *psz_vlc;
-
-    wchar_t psz_wpath[MAX_PATH];
-    if( GetModuleFileName( NULL, psz_wpath, MAX_PATH ) )
-    {
-        WideCharToMultiByte( CP_UTF8, 0, psz_wpath, -1,
-                             psz_path, MAX_PATH, NULL, NULL );
-    }
-    else psz_path[0] = '\0';
-
-    if( (psz_vlc = strrchr( psz_path, '\\' )) ) *psz_vlc = '\0';
-
-#ifndef HAVE_RELEASE
-    {
-        /* remove trailing \.libs from executable dir path if seen,
-           we assume we are running vlc through libtool wrapper in build dir */
-        int offset  = strlen(psz_path)-sizeof("\\.libs")+1;
-        if( offset > 0 )
-        {
-            psz_vlc = psz_path+offset;
-            if( ! strcmp(psz_vlc, "\\.libs") ) *psz_vlc = '\0';
-        }
-    }
-#endif
-
-    psz_vlcpath = strdup( psz_path );
-
-    /* Set the default file-translation mode */
-#if !defined( UNDER_CE )
-    _fmode = _O_BINARY;
-    _setmode( _fileno( stdin ), _O_BINARY ); /* Needed for pipes */
-
-    timeBeginPeriod(5);
-#endif
-
-    /* Call mdate() once to make sure it is initialized properly */
-    mdate();
-
-    /* WinSock Library Init. */
-    if( !WSAStartup( MAKEWORD( 2, 2 ), &Data ) )
-    {
-        /* Aah, pretty useless check, we should always have Winsock 2.2
-         * since it appeared in Win98. */
-        if( LOBYTE( Data.wVersion ) != 2 || HIBYTE( Data.wVersion ) != 2 )
-            /* We could not find a suitable WinSock DLL. */
-            WSACleanup( );
-        else
-            /* Everything went ok. */
-            return;
-    }
-
-    /* Let's try with WinSock 1.1 */
-    if( !WSAStartup( MAKEWORD( 1, 1 ), &Data ) )
-    {
-        /* Confirm that the WinSock DLL supports 1.1.*/
-        if( LOBYTE( Data.wVersion ) != 1 || HIBYTE( Data.wVersion ) != 1 )
-            /* We could not find a suitable WinSock DLL. */
-            WSACleanup( );
-        else
-            /* Everything went ok. */
-            return;
-    }
-
-    fprintf( stderr, "error: can't initialize WinSocks\n" );
-}
-
-/*****************************************************************************
- * system_Configure: check for system specific configuration options.
- *****************************************************************************/
-static unsigned __stdcall IPCHelperThread( void * );
-LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
-static vlc_object_t *p_helper = NULL;
-static unsigned long hIPCHelper;
-static HANDLE hIPCHelperReady;
-
-typedef struct
-{
-  int argc;
-  int enqueue;
-  char data[];
-} vlc_ipc_data_t;
-
-void system_Configure( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
-{
-#if !defined( UNDER_CE )
-    /* Raise default priority of the current process */
-#ifndef ABOVE_NORMAL_PRIORITY_CLASS
-#   define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
-#endif
-    if( config_GetInt( p_this, "high-priority" ) )
-    {
-        if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
-             || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
-        {
-            msg_Dbg( p_this, "raised process priority" );
-        }
-        else
-        {
-            msg_Dbg( p_this, "could not raise process priority" );
-        }
-    }
-
-    if( config_GetInt( p_this, "one-instance" )
-        || ( config_GetInt( p_this, "one-instance-when-started-from-file" )
-             && config_GetInt( p_this, "started-from-file" ) ) )
-    {
-        HANDLE hmutex;
-
-        msg_Info( p_this, "one instance mode ENABLED");
-
-        /* Use a named mutex to check if another instance is already running */
-        if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc "VERSION ) ) )
-        {
-            /* Failed for some reason. Just ignore the option and go on as
-             * normal. */
-            msg_Err( p_this, "one instance mode DISABLED "
-                     "(mutex couldn't be created)" );
-            return;
-        }
-
-        if( GetLastError() != ERROR_ALREADY_EXISTS )
-        {
-            /* We are the 1st instance. */
-            static const char typename[] = "ipc helper";
-            p_helper =
-                vlc_custom_create( p_this, sizeof(vlc_object_t),
-                                   VLC_OBJECT_GENERIC, typename );
-
-            /* Run the helper thread */
-            hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
-            hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
-                                         0, NULL );
-            if( hIPCHelper )
-                WaitForSingleObject( hIPCHelperReady, INFINITE );
-            else
-            {
-                msg_Err( p_this, "one instance mode DISABLED "
-                         "(IPC helper thread couldn't be created)" );
-                vlc_object_release (p_helper);
-                p_helper = NULL;
-            }
-            vlc_object_attach (p_helper, p_this);
-            CloseHandle( hIPCHelperReady );
-
-            /* Initialization done.
-             * Release the mutex to unblock other instances */
-            ReleaseMutex( hmutex );
-        }
-        else
-        {
-            /* Another instance is running */
-
-            HWND ipcwindow;
-
-            /* Wait until the 1st instance is initialized */
-            WaitForSingleObject( hmutex, INFINITE );
-
-            /* Locate the window created by the IPC helper thread of the
-             * 1st instance */
-            if( !( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) )
-            {
-                msg_Err( p_this, "one instance mode DISABLED "
-                         "(couldn't find 1st instance of program)" );
-                ReleaseMutex( hmutex );
-                return;
-            }
-
-            /* We assume that the remaining parameters are filenames
-             * and their input options */
-            if( *pi_argc - 1 >= optind )
-            {
-                COPYDATASTRUCT wm_data;
-                int i_opt;
-                vlc_ipc_data_t *p_data;
-                size_t i_data = sizeof (*p_data);
-
-                for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
-                {
-                    i_data += sizeof (size_t);
-                    i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
-                }
-
-                p_data = malloc( i_data );
-                p_data->argc = *pi_argc - optind;
-                p_data->enqueue = config_GetInt( p_this, "playlist-enqueue" );
-                i_data = 0;
-                for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
-                {
-                    size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
-                    /* Windows will never switch to an architecture
-                     * with stronger alignment requirements, right. */
-                    *((size_t *)(p_data->data + i_data)) = i_len;
-                    i_data += sizeof (size_t);
-                    memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
-                    i_data += i_len;
-                }
-                i_data += sizeof (*p_data);
-
-                /* Send our playlist items to the 1st instance */
-                wm_data.dwData = 0;
-                wm_data.cbData = i_data;
-                wm_data.lpData = p_data;
-                SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
-            }
-
-            /* Initialization done.
-             * Release the mutex to unblock other instances */
-            ReleaseMutex( hmutex );
-
-            /* Bye bye */
-            system_End( p_this );
-            exit( 0 );
-        }
-    }
-
-#endif
-}
-
-static unsigned __stdcall IPCHelperThread( void *data )
-{
-    vlc_object_t *p_this = data;
-    HWND ipcwindow;
-    MSG message;
-
-    ipcwindow =
-        CreateWindow( L"STATIC",                     /* name of window class */
-                  L"VLC ipc "VERSION,               /* window title bar text */
-                  0,                                         /* window style */
-                  0,                                 /* default X coordinate */
-                  0,                                 /* default Y coordinate */
-                  0,                                         /* window width */
-                  0,                                        /* window height */
-                  NULL,                                  /* no parent window */
-                  NULL,                            /* no menu in this window */
-                  GetModuleHandle(NULL),  /* handle of this program instance */
-                  NULL );                               /* sent to WM_CREATE */
-
-    SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
-    SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
-
-    /* Signal the creation of the thread and events queue */
-    SetEvent( hIPCHelperReady );
-
-    while( GetMessage( &message, NULL, 0, 0 ) )
-    {
-        TranslateMessage( &message );
-        DispatchMessage( &message );
-    }
-    return 0;
-}
-
-LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
-                                LPARAM lParam )
-{
-    if( uMsg == WM_COPYDATA )
-    {
-        COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
-        vlc_object_t *p_this;
-        playlist_t *p_playlist;
-
-        p_this = (vlc_object_t *)
-            (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
-
-        if( !p_this ) return 0;
-
-        /* Add files to the playlist */
-        p_playlist = pl_Hold( p_this );
-        if( !p_playlist ) return 0;
-
-        if( pwm_data->lpData )
-        {
-            char **ppsz_argv;
-            vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
-            size_t i_data = 0;
-            int i_argc = p_data->argc, i_opt, i_options;
-
-            ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
-            for( i_opt = 0; i_opt < i_argc; i_opt++ )
-            {
-                ppsz_argv[i_opt] = p_data->data + i_data + sizeof(int);
-                i_data += sizeof(int) + *((int *)(p_data->data + i_data));
-            }
-
-            for( i_opt = 0; i_opt < i_argc; i_opt++ )
-            {
-                i_options = 0;
-
-                /* Count the input options */
-                while( i_opt + i_options + 1 < i_argc &&
-                       *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
-                {
-                    i_options++;
-                }
-                playlist_AddExt( p_playlist, ppsz_argv[i_opt],
-                  NULL, PLAYLIST_APPEND |
-                        ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
-                  PLAYLIST_END, -1,
-                  i_options,
-                  (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
-                  VLC_INPUT_OPTION_TRUSTED,
-                  true, pl_Unlocked );
-
-                i_opt += i_options;
-            }
-
-            free( ppsz_argv );
-        }
-
-        vlc_object_release( p_playlist );
-    }
-
-    return DefWindowProc( hwnd, uMsg, wParam, lParam );
-}
-
-/*****************************************************************************
- * system_End: terminate winsock.
- *****************************************************************************/
-void system_End( libvlc_int_t *p_this )
-{
-    HWND ipcwindow;
-    if( p_this )
-    {
-        free( psz_vlcpath );
-        psz_vlcpath = NULL;
-    }
-
-    if( ( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) != 0 )
-    {
-        SendMessage( ipcwindow, WM_QUIT, 0, 0 );
-    }
-
-    if (p_helper && p_helper->p_parent == VLC_OBJECT(p_this) )
-    {
-        /* FIXME: thread-safety... */
-        vlc_object_detach (p_helper);
-        vlc_object_release (p_helper);
-        p_helper = NULL;
-    }
-
-#if !defined( UNDER_CE )
-    timeEndPeriod(5);
-#endif
-
-    WSACleanup();
-}
diff --git a/src/network/winsock.c b/src/network/winsock.c
deleted file mode 100644 (file)
index 2584dff..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*****************************************************************************
- * winsock.c: POSIX replacements for Winsock
- *****************************************************************************
- * Copyright © 2006-2008 Rémi Denis-Courmont
- *
- * 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
-
-#include <vlc_common.h>
-#include <errno.h>
-#include <vlc_network.h>
-
-#ifndef WSA_QOS_EUNKNOWNPSOBJ
-# define WSA_QOS_EUNKNOWNPSOBJ 11024L
-#endif
-
-typedef struct
-{
-    int code;
-    const char *msg;
-} wsaerrmsg_t;
-
-static const wsaerrmsg_t wsaerrmsg[] =
-{
-    { WSA_INVALID_HANDLE, "Specified event object handle is invalid" },
-    { WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available" },
-    { WSA_INVALID_PARAMETER, "One or more parameters are invalid" },
-    { WSA_OPERATION_ABORTED, "Overlapped operation aborted" },
-    { WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state" },
-    { WSA_IO_PENDING, "Overlapped operations will complete later" },
-    { WSAEINTR, "Interrupted function call" },
-    { WSAEBADF, "File handle is not valid" },
-    { WSAEACCES, "Access denied" },
-    { WSAEFAULT, "Invalid memory address" },
-    { WSAEINVAL, "Invalid argument" },
-    { WSAEMFILE, "Too many open sockets" },
-    { WSAEWOULDBLOCK, "Resource temporarily unavailable" },
-    { WSAEINPROGRESS, "Operation now in progress" },
-    { WSAEALREADY, "Operation already in progress" },
-    { WSAENOTSOCK, "Non-socket handle specified" },
-    { WSAEDESTADDRREQ, "Missing destination address" },
-    { WSAEMSGSIZE, "Message too long" },
-    { WSAEPROTOTYPE, "Protocol wrong type for socket", },
-    { WSAENOPROTOOPT, "Option not supported by protocol" },
-    { WSAEPROTONOSUPPORT, "Protocol not supported" },
-    { WSAESOCKTNOSUPPORT, "Socket type not supported" },
-    { WSAEOPNOTSUPP, "Operation not supported" },
-    { WSAEPFNOSUPPORT, "Protocol family not supported" },
-    { WSAEAFNOSUPPORT, "Address family not supported by protocol family" },
-    { WSAEADDRINUSE, "Address already in use" },
-    { WSAEADDRNOTAVAIL, "Cannot assign requested address" },
-    { WSAENETDOWN, "Network is down" },
-    { WSAENETUNREACH, "Network unreachable" },
-    { WSAENETRESET, "Network dropped connection on reset" },
-    { WSAECONNABORTED, "Software caused connection abort" },
-    { WSAECONNRESET, "Connection reset by peer" },
-    { WSAENOBUFS, "No buffer space available (not enough memory)" },
-    { WSAEISCONN, "Socket is already connected" },
-    { WSAENOTCONN, "Socket is not connected" },
-    { WSAESHUTDOWN, "Cannot send after socket shutdown" },
-    { WSAETOOMANYREFS, "Too many references" },
-    { WSAETIMEDOUT, "Connection timed out" },
-    { WSAECONNREFUSED, "Connection refused by peer" },
-    { WSAELOOP, "Cannot translate name" },
-    { WSAENAMETOOLONG, "Name too long" },
-    { WSAEHOSTDOWN, "Remote host is down" },
-    { WSAEHOSTUNREACH, "No route to host (unreachable)" },
-    { WSAENOTEMPTY, "Directory not empty" },
-    { WSAEPROCLIM, "Too many processes" },
-    { WSAEUSERS, "User quota exceeded" },
-    { WSAEDQUOT, "Disk quota exceeded" },
-    { WSAESTALE, "Stale file handle reference" },
-    { WSAEREMOTE, "Item is remote", },
-    { WSASYSNOTREADY, "Network subsystem is unavailable (network stack not ready)" },
-    { WSAVERNOTSUPPORTED, "Winsock.dll version out of range (network stack version not supported" },
-    { WSANOTINITIALISED, "Network not initialized" },
-    { WSAEDISCON, "Graceful shutdown in progress" },
-    { WSAENOMORE, "No more results" },
-    { WSAECANCELLED, "Call has been cancelled" },
-    { WSAEINVALIDPROCTABLE, "Procedure call table is invalid" },
-    { WSAEINVALIDPROVIDER, "Service provider is invalid" },
-    { WSAEPROVIDERFAILEDINIT, "Service provider failed to initialize" },
-    { WSASYSCALLFAILURE, "System call failure" },
-    { WSASERVICE_NOT_FOUND, "Service not found" },
-    { WSATYPE_NOT_FOUND, "Class type not found" },
-    { WSA_E_NO_MORE, "No more results" },
-    { WSA_E_CANCELLED, "Call was cancelled" },
-    { WSAEREFUSED, "Database query was refused" },
-    { WSAHOST_NOT_FOUND, "Host not found" },
-    { WSATRY_AGAIN, "Nonauthoritative host not found (temporary hostname error)" },
-    { WSANO_RECOVERY, "Non-recoverable hostname error" },
-    { WSANO_DATA, "Valid name, no data record of requested type" },
-    { WSA_QOS_RECEIVERS, "QOS receivers" },
-    { WSA_QOS_SENDERS, "QOS senders" },
-    { WSA_QOS_NO_SENDERS, "No QOS senders" },
-    { WSA_QOS_NO_RECEIVERS, "QOS no receivers" },
-    { WSA_QOS_REQUEST_CONFIRMED, "QOS request confirmed" },
-    { WSA_QOS_ADMISSION_FAILURE, "QOS admission error" },
-    { WSA_QOS_POLICY_FAILURE, "QOS policy failure" },
-    { WSA_QOS_BAD_STYLE, "QOS bad style" },
-    { WSA_QOS_BAD_OBJECT, "QOS bad object" },
-    { WSA_QOS_TRAFFIC_CTRL_ERROR, "QOS traffic control error" },
-    { WSA_QOS_GENERIC_ERROR, "QOS generic error" },
-    { WSA_QOS_ESERVICETYPE, "QOS service type error" },
-    { WSA_QOS_EFLOWSPEC, "QOS flowspec error" },
-    { WSA_QOS_EPROVSPECBUF, "Invalid QOS provider buffer" },
-    { WSA_QOS_EFILTERSTYLE, "Invalid QOS filter style" },
-    { WSA_QOS_EFILTERTYPE, "Invalid QOS filter type" },
-    { WSA_QOS_EFILTERCOUNT, "Incorrect QOS filter count" },
-    { WSA_QOS_EOBJLENGTH, "Invalid QOS object length" },
-    { WSA_QOS_EFLOWCOUNT, "Incorrect QOS flow count" },
-    { WSA_QOS_EUNKNOWNPSOBJ, "Unrecognized QOS object" },
-    { WSA_QOS_EPOLICYOBJ, "Invalid QOS policy object" },
-    { WSA_QOS_EFLOWDESC, "Invalid QOS flow descriptor" },
-    { WSA_QOS_EPSFLOWSPEC, "Invalid QOS provider-specific flowspec" },
-    { WSA_QOS_EPSFILTERSPEC, "Invalid QOS provider-specific filterspec" },
-    { WSA_QOS_ESDMODEOBJ, "Invalid QOS shape discard mode object" },
-    { WSA_QOS_ESHAPERATEOBJ, "Invalid QOS shaping rate object" },
-    { WSA_QOS_RESERVED_PETYPE, "Reserved policy QOS element type" },
-    { 0, NULL }
-    /* Winsock2 error codes are missing, they "never" occur */
-};
-
-
-const char *net_strerror( int value )
-{
-    /* There doesn't seem to be any portable error message generation for
-     * Winsock errors. Some old versions had s_error, but it appears to be
-     * gone, and is not documented.
-     */
-    for( const wsaerrmsg_t *e = wsaerrmsg; e->msg != NULL; e++ )
-        if( e->code == value )
-            return e->msg;
-
-    /* Remember to update src/misc/messages.c if you change this one */
-    return "Unknown network stack error";
-}
-
-#if 0
-ssize_t vlc_sendmsg (int s, struct msghdr *hdr, int flags)
-{
-    /* WSASendMsg would be more straightforward, and would support ancilliary
-     * data, but it's not yet in mingw32. */
-    if ((hdr->msg_iovlen > 100) || (hdr->msg_controllen > 0))
-    {
-        errno = EINVAL;
-        return -1;
-    }
-
-    WSABUF buf[hdr->msg_iovlen];
-    for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
-        buf[i].buf = hdr->msg_iov[i].iov_base,
-        buf[i].len = hdr->msg_iov[i].iov_len;
-
-    DWORD sent;
-    if (WSASendTo (s, buf, sizeof (buf) / sizeof (buf[0]), &sent, flags,
-                   hdr->msg_name, hdr->msg_namelen, NULL, NULL) == 0)
-        return sent;
-    return -1;
-}
-
-ssize_t vlc_recvmsg (int s, struct msghdr *hdr, int flags)
-{
-    /* WSARecvMsg would be more straightforward, and would support ancilliary
-     * data, but it's not yet in mingw32. */
-    if (hdr->msg_iovlen > 100)
-    {
-        errno = EINVAL;
-        return -1;
-    }
-
-    WSABUF buf[hdr->msg_iovlen];
-    for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
-        buf[i].buf = hdr->msg_iov[i].iov_base,
-        buf[i].len = hdr->msg_iov[i].iov_len;
-
-    DWORD recvd, dwFlags = flags;
-    INT fromlen = hdr->msg_namelen;
-    hdr->msg_controllen = 0;
-    hdr->msg_flags = 0;
-
-    int ret = WSARecvFrom (s, buf, sizeof (buf) / sizeof (buf[0]), &recvd,
-                           &dwFlags, hdr->msg_name, &fromlen, NULL, NULL);
-    hdr->msg_namelen = fromlen;
-    hdr->msg_flags = dwFlags;
-    if (ret == 0)
-        return recvd;
-
-#ifdef MSG_TRUNC
-    if (WSAGetLastError() == WSAEMSGSIZE)
-    {
-        hdr->msg_flags |= MSG_TRUNC;
-        return recvd;
-    }
-#else
-# warning Out-of-date Winsock header files!
-#endif
-    return -1;
-}
-#endif
diff --git a/src/win32/dirs.c b/src/win32/dirs.c
new file mode 100644 (file)
index 0000000..71d176e
--- /dev/null
@@ -0,0 +1,138 @@
+/*****************************************************************************
+ * dirs.c: directories configuration
+ *****************************************************************************
+ * Copyright (C) 2001-2007 the VideoLAN team
+ * Copyright © 2007-2008 Rémi Denis-Courmont
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * 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
+
+#include <vlc_common.h>
+
+#ifndef _WIN32_IE
+# define _WIN32_IE 0x0501
+#endif
+#include <w32api.h>
+#ifndef UNDER_CE
+# include <direct.h>
+#endif
+#include <shlobj.h>
+
+#include "../libvlc.h"
+#include <vlc_charset.h>
+#include <vlc_configuration.h>
+
+#include <assert.h>
+#include <limits.h>
+
+const char *config_GetDataDirDefault( void )
+{
+    static char path[PATH_MAX] = "";
+#warning FIXME: thread-safety!
+
+    if( *path == '\0' )
+        strlcpy (path, psz_vlcpath, sizeof (path));
+    return path;
+}
+
+const char *config_GetConfDir (void)
+{
+    static char appdir[PATH_MAX] = "";
+    wchar_t wdir[MAX_PATH];
+
+#warning FIXME: thread-safety!
+    if (*appdir)
+        return appdir;
+
+#if defined (UNDER_CE)
+    /*There are some errors in cegcc headers*/
+#undef SHGetSpecialFolderPath
+    BOOL WINAPI SHGetSpecialFolderPath(HWND,LPWSTR,int,BOOL);
+    if( SHGetSpecialFolderPath( NULL, wdir, CSIDL_APPDATA, 1 ) )
+#else
+    /* Get the "Application Data" folder for all users */
+    if( S_OK == SHGetFolderPathW( NULL, CSIDL_COMMON_APPDATA
+              | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, wdir ) )
+#endif
+    {
+        WideCharToMultiByte (CP_UTF8, 0, wdir, -1,
+                             appdir, PATH_MAX, NULL, NULL);
+        return appdir;
+    }
+    return NULL;
+}
+
+static char *config_GetShellDir (int csidl)
+{
+    wchar_t wdir[MAX_PATH];
+
+#if defined (UNDER_CE)
+    /*There are some errors in cegcc headers*/
+#undef SHGetSpecialFolderPath
+    BOOL WINAPI SHGetSpecialFolderPath(HWND,LPWSTR,int,BOOL);
+    if (SHGetSpecialFolderPath (NULL, wdir, CSIDL_APPDATA, 1))
+#else
+    if (SHGetFolderPathW (NULL, csidl | CSIDL_FLAG_CREATE,
+                          NULL, SHGFP_TYPE_CURRENT, wdir ) == S_OK)
+#endif
+        return FromWide (wdir);
+    return NULL;
+}
+
+static char *config_GetAppDir (void)
+{
+    char *psz_dir;
+    char *psz_parent = config_GetShellDir (CSIDL_APPDATA);
+
+    if (psz_parent == NULL
+     ||  asprintf (&psz_dir, "%s\\vlc", psz_parent) == -1)
+        psz_dir = NULL;
+    free (psz_parent);
+    return psz_dir;
+}
+
+#warning FIXME Use known folders on Vista and above
+char *config_GetUserDir (vlc_userdir_t type)
+{
+    switch (type)
+    {
+        case VLC_HOME_DIR:
+            return config_GetShellDir (CSIDL_PERSONAL);
+        case VLC_CONFIG_DIR:
+        case VLC_DATA_DIR:
+        case VLC_CACHE_DIR:
+            return config_GetAppDir ();
+
+        case VLC_DESKTOP_DIR:
+        case VLC_DOWNLOAD_DIR:
+        case VLC_TEMPLATES_DIR:
+        case VLC_PUBLICSHARE_DIR:
+        case VLC_DOCUMENTS_DIR:
+            return config_GetUserDir(VLC_HOME_DIR);
+        case VLC_MUSIC_DIR:
+            return config_GetShellDir (CSIDL_MYMUSIC);
+        case VLC_PICTURES_DIR:
+            return config_GetShellDir (CSIDL_MYPICTURES);
+        case VLC_VIDEOS_DIR:
+            return config_GetShellDir (CSIDL_MYVIDEO);
+    }
+    assert (0);
+}
diff --git a/src/win32/specific.c b/src/win32/specific.c
new file mode 100644 (file)
index 0000000..ea8a504
--- /dev/null
@@ -0,0 +1,398 @@
+/*****************************************************************************
+ * specific.c: Win32 specific initilization
+ *****************************************************************************
+ * Copyright (C) 2001-2004 the VideoLAN team
+ *
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ *          Gildas Bazin <gbazin@videolan.org>
+ *
+ * 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
+
+#define UNICODE
+#include <vlc_common.h>
+#include "../libvlc.h"
+#include <vlc_playlist.h>
+#include <vlc_charset.h>
+
+#include "../extras/getopt.h"
+
+#if !defined( UNDER_CE )
+#   include <io.h>
+#   include <fcntl.h>
+#   include  <mmsystem.h>
+#endif
+
+#include <winsock.h>
+
+/*****************************************************************************
+ * system_Init: initialize winsock and misc other things.
+ *****************************************************************************/
+void system_Init( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
+{
+    VLC_UNUSED( p_this ); VLC_UNUSED( pi_argc ); VLC_UNUSED( ppsz_argv );
+    WSADATA Data;
+
+    /* Get our full path */
+    char psz_path[MAX_PATH];
+    char *psz_vlc;
+
+    wchar_t psz_wpath[MAX_PATH];
+    if( GetModuleFileName( NULL, psz_wpath, MAX_PATH ) )
+    {
+        WideCharToMultiByte( CP_UTF8, 0, psz_wpath, -1,
+                             psz_path, MAX_PATH, NULL, NULL );
+    }
+    else psz_path[0] = '\0';
+
+    if( (psz_vlc = strrchr( psz_path, '\\' )) ) *psz_vlc = '\0';
+
+#ifndef HAVE_RELEASE
+    {
+        /* remove trailing \.libs from executable dir path if seen,
+           we assume we are running vlc through libtool wrapper in build dir */
+        int offset  = strlen(psz_path)-sizeof("\\.libs")+1;
+        if( offset > 0 )
+        {
+            psz_vlc = psz_path+offset;
+            if( ! strcmp(psz_vlc, "\\.libs") ) *psz_vlc = '\0';
+        }
+    }
+#endif
+
+    psz_vlcpath = strdup( psz_path );
+
+    /* Set the default file-translation mode */
+#if !defined( UNDER_CE )
+    _fmode = _O_BINARY;
+    _setmode( _fileno( stdin ), _O_BINARY ); /* Needed for pipes */
+
+    timeBeginPeriod(5);
+#endif
+
+    /* Call mdate() once to make sure it is initialized properly */
+    mdate();
+
+    /* WinSock Library Init. */
+    if( !WSAStartup( MAKEWORD( 2, 2 ), &Data ) )
+    {
+        /* Aah, pretty useless check, we should always have Winsock 2.2
+         * since it appeared in Win98. */
+        if( LOBYTE( Data.wVersion ) != 2 || HIBYTE( Data.wVersion ) != 2 )
+            /* We could not find a suitable WinSock DLL. */
+            WSACleanup( );
+        else
+            /* Everything went ok. */
+            return;
+    }
+
+    /* Let's try with WinSock 1.1 */
+    if( !WSAStartup( MAKEWORD( 1, 1 ), &Data ) )
+    {
+        /* Confirm that the WinSock DLL supports 1.1.*/
+        if( LOBYTE( Data.wVersion ) != 1 || HIBYTE( Data.wVersion ) != 1 )
+            /* We could not find a suitable WinSock DLL. */
+            WSACleanup( );
+        else
+            /* Everything went ok. */
+            return;
+    }
+
+    fprintf( stderr, "error: can't initialize WinSocks\n" );
+}
+
+/*****************************************************************************
+ * system_Configure: check for system specific configuration options.
+ *****************************************************************************/
+static unsigned __stdcall IPCHelperThread( void * );
+LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
+static vlc_object_t *p_helper = NULL;
+static unsigned long hIPCHelper;
+static HANDLE hIPCHelperReady;
+
+typedef struct
+{
+  int argc;
+  int enqueue;
+  char data[];
+} vlc_ipc_data_t;
+
+void system_Configure( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
+{
+#if !defined( UNDER_CE )
+    /* Raise default priority of the current process */
+#ifndef ABOVE_NORMAL_PRIORITY_CLASS
+#   define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
+#endif
+    if( config_GetInt( p_this, "high-priority" ) )
+    {
+        if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
+             || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
+        {
+            msg_Dbg( p_this, "raised process priority" );
+        }
+        else
+        {
+            msg_Dbg( p_this, "could not raise process priority" );
+        }
+    }
+
+    if( config_GetInt( p_this, "one-instance" )
+        || ( config_GetInt( p_this, "one-instance-when-started-from-file" )
+             && config_GetInt( p_this, "started-from-file" ) ) )
+    {
+        HANDLE hmutex;
+
+        msg_Info( p_this, "one instance mode ENABLED");
+
+        /* Use a named mutex to check if another instance is already running */
+        if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc "VERSION ) ) )
+        {
+            /* Failed for some reason. Just ignore the option and go on as
+             * normal. */
+            msg_Err( p_this, "one instance mode DISABLED "
+                     "(mutex couldn't be created)" );
+            return;
+        }
+
+        if( GetLastError() != ERROR_ALREADY_EXISTS )
+        {
+            /* We are the 1st instance. */
+            static const char typename[] = "ipc helper";
+            p_helper =
+                vlc_custom_create( p_this, sizeof(vlc_object_t),
+                                   VLC_OBJECT_GENERIC, typename );
+
+            /* Run the helper thread */
+            hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
+            hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
+                                         0, NULL );
+            if( hIPCHelper )
+                WaitForSingleObject( hIPCHelperReady, INFINITE );
+            else
+            {
+                msg_Err( p_this, "one instance mode DISABLED "
+                         "(IPC helper thread couldn't be created)" );
+                vlc_object_release (p_helper);
+                p_helper = NULL;
+            }
+            vlc_object_attach (p_helper, p_this);
+            CloseHandle( hIPCHelperReady );
+
+            /* Initialization done.
+             * Release the mutex to unblock other instances */
+            ReleaseMutex( hmutex );
+        }
+        else
+        {
+            /* Another instance is running */
+
+            HWND ipcwindow;
+
+            /* Wait until the 1st instance is initialized */
+            WaitForSingleObject( hmutex, INFINITE );
+
+            /* Locate the window created by the IPC helper thread of the
+             * 1st instance */
+            if( !( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) )
+            {
+                msg_Err( p_this, "one instance mode DISABLED "
+                         "(couldn't find 1st instance of program)" );
+                ReleaseMutex( hmutex );
+                return;
+            }
+
+            /* We assume that the remaining parameters are filenames
+             * and their input options */
+            if( *pi_argc - 1 >= optind )
+            {
+                COPYDATASTRUCT wm_data;
+                int i_opt;
+                vlc_ipc_data_t *p_data;
+                size_t i_data = sizeof (*p_data);
+
+                for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
+                {
+                    i_data += sizeof (size_t);
+                    i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
+                }
+
+                p_data = malloc( i_data );
+                p_data->argc = *pi_argc - optind;
+                p_data->enqueue = config_GetInt( p_this, "playlist-enqueue" );
+                i_data = 0;
+                for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
+                {
+                    size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
+                    /* Windows will never switch to an architecture
+                     * with stronger alignment requirements, right. */
+                    *((size_t *)(p_data->data + i_data)) = i_len;
+                    i_data += sizeof (size_t);
+                    memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
+                    i_data += i_len;
+                }
+                i_data += sizeof (*p_data);
+
+                /* Send our playlist items to the 1st instance */
+                wm_data.dwData = 0;
+                wm_data.cbData = i_data;
+                wm_data.lpData = p_data;
+                SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
+            }
+
+            /* Initialization done.
+             * Release the mutex to unblock other instances */
+            ReleaseMutex( hmutex );
+
+            /* Bye bye */
+            system_End( p_this );
+            exit( 0 );
+        }
+    }
+
+#endif
+}
+
+static unsigned __stdcall IPCHelperThread( void *data )
+{
+    vlc_object_t *p_this = data;
+    HWND ipcwindow;
+    MSG message;
+
+    ipcwindow =
+        CreateWindow( L"STATIC",                     /* name of window class */
+                  L"VLC ipc "VERSION,               /* window title bar text */
+                  0,                                         /* window style */
+                  0,                                 /* default X coordinate */
+                  0,                                 /* default Y coordinate */
+                  0,                                         /* window width */
+                  0,                                        /* window height */
+                  NULL,                                  /* no parent window */
+                  NULL,                            /* no menu in this window */
+                  GetModuleHandle(NULL),  /* handle of this program instance */
+                  NULL );                               /* sent to WM_CREATE */
+
+    SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
+    SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
+
+    /* Signal the creation of the thread and events queue */
+    SetEvent( hIPCHelperReady );
+
+    while( GetMessage( &message, NULL, 0, 0 ) )
+    {
+        TranslateMessage( &message );
+        DispatchMessage( &message );
+    }
+    return 0;
+}
+
+LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
+                                LPARAM lParam )
+{
+    if( uMsg == WM_COPYDATA )
+    {
+        COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
+        vlc_object_t *p_this;
+        playlist_t *p_playlist;
+
+        p_this = (vlc_object_t *)
+            (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
+
+        if( !p_this ) return 0;
+
+        /* Add files to the playlist */
+        p_playlist = pl_Hold( p_this );
+        if( !p_playlist ) return 0;
+
+        if( pwm_data->lpData )
+        {
+            char **ppsz_argv;
+            vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
+            size_t i_data = 0;
+            int i_argc = p_data->argc, i_opt, i_options;
+
+            ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
+            for( i_opt = 0; i_opt < i_argc; i_opt++ )
+            {
+                ppsz_argv[i_opt] = p_data->data + i_data + sizeof(int);
+                i_data += sizeof(int) + *((int *)(p_data->data + i_data));
+            }
+
+            for( i_opt = 0; i_opt < i_argc; i_opt++ )
+            {
+                i_options = 0;
+
+                /* Count the input options */
+                while( i_opt + i_options + 1 < i_argc &&
+                       *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
+                {
+                    i_options++;
+                }
+                playlist_AddExt( p_playlist, ppsz_argv[i_opt],
+                  NULL, PLAYLIST_APPEND |
+                        ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
+                  PLAYLIST_END, -1,
+                  i_options,
+                  (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
+                  VLC_INPUT_OPTION_TRUSTED,
+                  true, pl_Unlocked );
+
+                i_opt += i_options;
+            }
+
+            free( ppsz_argv );
+        }
+
+        vlc_object_release( p_playlist );
+    }
+
+    return DefWindowProc( hwnd, uMsg, wParam, lParam );
+}
+
+/*****************************************************************************
+ * system_End: terminate winsock.
+ *****************************************************************************/
+void system_End( libvlc_int_t *p_this )
+{
+    HWND ipcwindow;
+    if( p_this )
+    {
+        free( psz_vlcpath );
+        psz_vlcpath = NULL;
+    }
+
+    if( ( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) != 0 )
+    {
+        SendMessage( ipcwindow, WM_QUIT, 0, 0 );
+    }
+
+    if (p_helper && p_helper->p_parent == VLC_OBJECT(p_this) )
+    {
+        /* FIXME: thread-safety... */
+        vlc_object_detach (p_helper);
+        vlc_object_release (p_helper);
+        p_helper = NULL;
+    }
+
+#if !defined( UNDER_CE )
+    timeEndPeriod(5);
+#endif
+
+    WSACleanup();
+}
diff --git a/src/win32/thread.c b/src/win32/thread.c
new file mode 100644 (file)
index 0000000..f231e49
--- /dev/null
@@ -0,0 +1,828 @@
+/*****************************************************************************
+ * thread.c : Win32 back-end for LibVLC
+ *****************************************************************************
+ * Copyright (C) 1999-2009 the VideoLAN team
+ *
+ * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
+ *          Samuel Hocevar <sam@zoy.org>
+ *          Gildas Bazin <gbazin@netcourrier.com>
+ *          Clément Sténac
+ *          Rémi Denis-Courmont
+ *          Pierre Ynard
+ *
+ * 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
+
+#include <vlc_common.h>
+
+#include "libvlc.h"
+#include <stdarg.h>
+#include <assert.h>
+#include <limits.h>
+#include <errno.h>
+#ifdef UNDER_CE
+# include <mmsystem.h>
+#endif
+
+static vlc_threadvar_t cancel_key;
+
+/**
+ * Per-thread cancellation data
+ */
+typedef struct vlc_cancel_t
+{
+    vlc_cleanup_t *cleaners;
+#ifdef UNDER_CE
+    HANDLE         cancel_event;
+#endif
+    bool           killable;
+    bool           killed;
+} vlc_cancel_t;
+
+#ifndef UNDER_CE
+# define VLC_CANCEL_INIT { NULL, true, false }
+#else
+# define VLC_CANCEL_INIT { NULL, NULL, true, false }
+#endif
+
+#ifdef UNDER_CE
+static void CALLBACK vlc_cancel_self (ULONG_PTR dummy);
+
+static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles,
+                                  DWORD delay)
+{
+    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
+    if (nfo == NULL)
+    {
+        /* Main thread - cannot be cancelled anyway */
+        return WaitForMultipleObjects (count, handles, FALSE, delay);
+    }
+    HANDLE new_handles[count + 1];
+    memcpy(new_handles, handles, count * sizeof(HANDLE));
+    new_handles[count] = nfo->cancel_event;
+    DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE,
+                                           delay);
+    if (result == WAIT_OBJECT_0 + count)
+    {
+        vlc_cancel_self (NULL);
+        return WAIT_IO_COMPLETION;
+    }
+    else
+    {
+        return result;
+    }
+}
+
+DWORD SleepEx (DWORD dwMilliseconds, BOOL bAlertable)
+{
+    if (bAlertable)
+    {
+        DWORD result = vlc_cancelable_wait (0, NULL, dwMilliseconds);
+        return (result == WAIT_TIMEOUT) ? 0 : WAIT_IO_COMPLETION;
+    }
+    else
+    {
+        Sleep(dwMilliseconds);
+        return 0;
+    }
+}
+
+DWORD WaitForSingleObjectEx (HANDLE hHandle, DWORD dwMilliseconds,
+                             BOOL bAlertable)
+{
+    if (bAlertable)
+    {
+        /* The MSDN documentation specifies different return codes,
+         * but in practice they are the same. We just check that it
+         * remains so. */
+#if WAIT_ABANDONED != WAIT_ABANDONED_0
+# error Windows headers changed, code needs to be rewritten!
+#endif
+        return vlc_cancelable_wait (1, &hHandle, dwMilliseconds);
+    }
+    else
+    {
+        return WaitForSingleObject (hHandle, dwMilliseconds);
+    }
+}
+
+DWORD WaitForMultipleObjectsEx (DWORD nCount, const HANDLE *lpHandles,
+                                BOOL bWaitAll, DWORD dwMilliseconds,
+                                BOOL bAlertable)
+{
+    if (bAlertable)
+    {
+        /* We do not support the bWaitAll case */
+        assert (! bWaitAll);
+        return vlc_cancelable_wait (nCount, lpHandles, dwMilliseconds);
+    }
+    else
+    {
+        return WaitForMultipleObjects (nCount, lpHandles, bWaitAll,
+                                       dwMilliseconds);
+    }
+}
+#endif
+
+vlc_mutex_t super_mutex;
+vlc_cond_t  super_variable;
+
+BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
+{
+    (void) hinstDll;
+    (void) lpvReserved;
+
+    switch (fdwReason)
+    {
+        case DLL_PROCESS_ATTACH:
+            vlc_mutex_init (&super_mutex);
+            vlc_cond_init (&super_variable);
+            vlc_threadvar_create (&cancel_key, free);
+            break;
+
+        case DLL_PROCESS_DETACH:
+            vlc_threadvar_delete( &cancel_key );
+            vlc_cond_destroy (&super_variable);
+            vlc_mutex_destroy (&super_mutex);
+            break;
+    }
+    return TRUE;
+}
+
+/*** Mutexes ***/
+void vlc_mutex_init( vlc_mutex_t *p_mutex )
+{
+    /* This creates a recursive mutex. This is OK as fast mutexes have
+     * no defined behavior in case of recursive locking. */
+    InitializeCriticalSection (&p_mutex->mutex);
+    p_mutex->dynamic = true;
+}
+
+void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
+{
+    InitializeCriticalSection( &p_mutex->mutex );
+    p_mutex->dynamic = true;
+}
+
+
+void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
+{
+    assert (p_mutex->dynamic);
+    DeleteCriticalSection (&p_mutex->mutex);
+}
+
+void vlc_mutex_lock (vlc_mutex_t *p_mutex)
+{
+    if (!p_mutex->dynamic)
+    {   /* static mutexes */
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+
+        vlc_mutex_lock (&super_mutex);
+        while (p_mutex->locked)
+        {
+            p_mutex->contention++;
+            vlc_cond_wait (&super_variable, &super_mutex);
+            p_mutex->contention--;
+        }
+        p_mutex->locked = true;
+        vlc_mutex_unlock (&super_mutex);
+        return;
+    }
+
+    EnterCriticalSection (&p_mutex->mutex);
+}
+
+int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
+{
+    if (!p_mutex->dynamic)
+    {   /* static mutexes */
+        int ret = EBUSY;
+
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+        vlc_mutex_lock (&super_mutex);
+        if (!p_mutex->locked)
+        {
+            p_mutex->locked = true;
+            ret = 0;
+        }
+        vlc_mutex_unlock (&super_mutex);
+        return ret;
+    }
+
+    return TryEnterCriticalSection (&p_mutex->mutex) ? 0 : EBUSY;
+}
+
+void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
+{
+    if (!p_mutex->dynamic)
+    {   /* static mutexes */
+        assert (p_mutex != &super_mutex); /* this one cannot be static */
+
+        vlc_mutex_lock (&super_mutex);
+        assert (p_mutex->locked);
+        p_mutex->locked = false;
+        if (p_mutex->contention)
+            vlc_cond_broadcast (&super_variable);
+        vlc_mutex_unlock (&super_mutex);
+        return;
+    }
+
+    LeaveCriticalSection (&p_mutex->mutex);
+}
+
+/*** Condition variables ***/
+void vlc_cond_init( vlc_cond_t *p_condvar )
+{
+    /* Create a manual-reset event (manual reset is needed for broadcast). */
+    *p_condvar = CreateEvent (NULL, TRUE, FALSE, NULL);
+    if (!*p_condvar)
+        abort();
+}
+
+void vlc_cond_destroy (vlc_cond_t *p_condvar)
+{
+    CloseHandle (*p_condvar);
+}
+
+void vlc_cond_signal (vlc_cond_t *p_condvar)
+{
+    /* NOTE: This will cause a broadcast, that is wrong.
+     * This will also wake up the next waiting thread if no threads are yet
+     * waiting, which is also wrong. However both of these issues are allowed
+     * by the provision for spurious wakeups. Better have too many wakeups
+     * than too few (= deadlocks). */
+    SetEvent (*p_condvar);
+}
+
+void vlc_cond_broadcast (vlc_cond_t *p_condvar)
+{
+    SetEvent (*p_condvar);
+}
+
+void vlc_cond_wait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex)
+{
+    DWORD result;
+
+    assert (p_mutex->dynamic); /* TODO */
+    do
+    {
+        vlc_testcancel ();
+        LeaveCriticalSection (&p_mutex->mutex);
+        result = WaitForSingleObjectEx (*p_condvar, INFINITE, TRUE);
+        EnterCriticalSection (&p_mutex->mutex);
+    }
+    while (result == WAIT_IO_COMPLETION);
+
+    assert (result != WAIT_ABANDONED); /* another thread failed to cleanup! */
+    assert (result != WAIT_FAILED);
+    ResetEvent (*p_condvar);
+}
+
+int vlc_cond_timedwait (vlc_cond_t *p_condvar, vlc_mutex_t *p_mutex,
+                        mtime_t deadline)
+{
+    DWORD result;
+
+    assert (p_mutex->dynamic); /* TODO */
+    do
+    {
+        vlc_testcancel ();
+
+        mtime_t total = (deadline - mdate ())/1000;
+        if( total < 0 )
+            total = 0;
+
+        DWORD delay = (total > 0x7fffffff) ? 0x7fffffff : total;
+        LeaveCriticalSection (&p_mutex->mutex);
+        result = WaitForSingleObjectEx (*p_condvar, delay, TRUE);
+        EnterCriticalSection (&p_mutex->mutex);
+    }
+    while (result == WAIT_IO_COMPLETION);
+
+    assert (result != WAIT_ABANDONED);
+    assert (result != WAIT_FAILED);
+    ResetEvent (*p_condvar);
+
+    return (result == WAIT_OBJECT_0) ? 0 : ETIMEDOUT;
+}
+
+/*** Semaphore ***/
+void vlc_sem_init (vlc_sem_t *sem, unsigned value)
+{
+    *sem = CreateSemaphore (NULL, value, 0x7fffffff, NULL);
+    if (*sem == NULL)
+        abort ();
+}
+
+void vlc_sem_destroy (vlc_sem_t *sem)
+{
+    CloseHandle (*sem);
+}
+
+int vlc_sem_post (vlc_sem_t *sem)
+{
+    ReleaseSemaphore (*sem, 1, NULL);
+    return 0; /* FIXME */
+}
+
+void vlc_sem_wait (vlc_sem_t *sem)
+{
+    DWORD result;
+
+    do
+    {
+        vlc_testcancel ();
+        result = WaitForSingleObjectEx (*sem, INFINITE, TRUE);
+    }
+    while (result == WAIT_IO_COMPLETION);
+}
+
+/*** Read/write locks */
+/* SRW (Slim Read Write) locks are available in Vista+ only */
+void vlc_rwlock_init (vlc_rwlock_t *lock)
+{
+    vlc_mutex_init (&lock->mutex);
+    vlc_cond_init (&lock->read_wait);
+    vlc_cond_init (&lock->write_wait);
+    lock->readers = 0; /* active readers */
+    lock->writers = 0; /* waiting or active writers */
+    lock->writer = 0; /* ID of active writer */
+}
+
+/**
+ * Destroys an initialized unused read/write lock.
+ */
+void vlc_rwlock_destroy (vlc_rwlock_t *lock)
+{
+    vlc_cond_destroy (&lock->read_wait);
+    vlc_cond_destroy (&lock->write_wait);
+    vlc_mutex_destroy (&lock->mutex);
+}
+
+/**
+ * Acquires a read/write lock for reading. Recursion is allowed.
+ */
+void vlc_rwlock_rdlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    while (lock->writer != 0)
+        vlc_cond_wait (&lock->read_wait, &lock->mutex);
+    if (lock->readers == ULONG_MAX)
+        abort ();
+    lock->readers++;
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+/**
+ * Acquires a read/write lock for writing. Recursion is not allowed.
+ */
+void vlc_rwlock_wrlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    if (lock->writers == ULONG_MAX)
+        abort ();
+    lock->writers++;
+    while ((lock->readers > 0) || (lock->writer != 0))
+        vlc_cond_wait (&lock->write_wait, &lock->mutex);
+    lock->writers--;
+    lock->writer = GetCurrentThreadId ();
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+/**
+ * Releases a read/write lock.
+ */
+void vlc_rwlock_unlock (vlc_rwlock_t *lock)
+{
+    vlc_mutex_lock (&lock->mutex);
+    if (lock->readers > 0)
+        lock->readers--; /* Read unlock */
+    else
+        lock->writer = 0; /* Write unlock */
+
+    if (lock->writers > 0)
+    {
+        if (lock->readers == 0)
+            vlc_cond_signal (&lock->write_wait);
+    }
+    else
+        vlc_cond_broadcast (&lock->read_wait);
+    vlc_mutex_unlock (&lock->mutex);
+}
+
+/*** Thread-specific variables (TLS) ***/
+int vlc_threadvar_create (vlc_threadvar_t *p_tls, void (*destr) (void *))
+{
+#warning FIXME: use destr() callback and stop leaking!
+    VLC_UNUSED( destr );
+
+    *p_tls = TlsAlloc();
+    return (*p_tls == TLS_OUT_OF_INDEXES) ? EAGAIN : 0;
+}
+
+void vlc_threadvar_delete (vlc_threadvar_t *p_tls)
+{
+    TlsFree (*p_tls);
+}
+
+/**
+ * Sets a thread-local variable.
+ * @param key thread-local variable key (created with vlc_threadvar_create())
+ * @param value new value for the variable for the calling thread
+ * @return 0 on success, a system error code otherwise.
+ */
+int vlc_threadvar_set (vlc_threadvar_t key, void *value)
+{
+    return TlsSetValue (key, value) ? ENOMEM : 0;
+}
+
+/**
+ * Gets the value of a thread-local variable for the calling thread.
+ * This function cannot fail.
+ * @return the value associated with the given variable for the calling
+ * or NULL if there is no value.
+ */
+void *vlc_threadvar_get (vlc_threadvar_t key)
+{
+    return TlsGetValue (key);
+}
+
+
+/*** Threads ***/
+void vlc_threads_setup (libvlc_int_t *p_libvlc)
+{
+    (void) p_libvlc;
+}
+
+struct vlc_entry_data
+{
+    void * (*func) (void *);
+    void *  data;
+#ifdef UNDER_CE
+    HANDLE  cancel_event;
+#endif
+};
+
+static unsigned __stdcall vlc_entry (void *p)
+{
+    vlc_cancel_t cancel_data = VLC_CANCEL_INIT;
+    struct vlc_entry_data data;
+
+    memcpy (&data, p, sizeof (data));
+    free (p);
+
+#ifdef UNDER_CE
+    cancel_data.cancel_event = data.cancel_event;
+#endif
+
+    vlc_threadvar_set (cancel_key, &cancel_data);
+    data.func (data.data);
+    return 0;
+}
+
+int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
+               int priority)
+{
+    int err = ENOMEM;
+    HANDLE hThread;
+
+    struct vlc_entry_data *entry_data = malloc (sizeof (*entry_data));
+    if (entry_data == NULL)
+        return ENOMEM;
+    entry_data->func = entry;
+    entry_data->data = data;
+
+#ifndef UNDER_CE
+    /* When using the MSVCRT C library you have to use the _beginthreadex
+     * function instead of CreateThread, otherwise you'll end up with
+     * memory leaks and the signal functions not working (see Microsoft
+     * Knowledge Base, article 104641) */
+    hThread = (HANDLE)(uintptr_t)
+        _beginthreadex (NULL, 0, vlc_entry, entry_data, CREATE_SUSPENDED, NULL);
+    if (! hThread)
+    {
+        err = errno;
+        goto error;
+    }
+
+    /* Thread closes the handle when exiting, duplicate it here
+     * to be on the safe side when joining. */
+    if (!DuplicateHandle (GetCurrentProcess (), hThread,
+                          GetCurrentProcess (), p_handle, 0, FALSE,
+                          DUPLICATE_SAME_ACCESS))
+    {
+        CloseHandle (hThread);
+        goto error;
+    }
+
+#else
+    vlc_thread_t th = malloc (sizeof (*th));
+    if (th == NULL)
+        goto error;
+    th->cancel_event = CreateEvent (NULL, FALSE, FALSE, NULL);
+    if (th->cancel_event == NULL)
+    {
+        free (th);
+        goto error;
+    }
+    entry_data->cancel_event = th->cancel_event;
+
+    /* Not sure if CREATE_SUSPENDED + ResumeThread() is any useful on WinCE.
+     * Thread handles act up, too. */
+    th->handle = CreateThread (NULL, 128*1024, vlc_entry, entry_data,
+                               CREATE_SUSPENDED, NULL);
+    if (th->handle == NULL)
+    {
+        CloseHandle (th->cancel_event);
+        free (th);
+        goto error;
+    }
+
+    *p_handle = th;
+    hThread = th->handle;
+
+#endif
+
+    ResumeThread (hThread);
+    if (priority)
+        SetThreadPriority (hThread, priority);
+
+    return 0;
+
+error:
+    free (entry_data);
+    return err;
+}
+
+void vlc_join (vlc_thread_t handle, void **result)
+{
+#ifdef UNDER_CE
+# define handle handle->handle
+#endif
+    do
+        vlc_testcancel ();
+    while (WaitForSingleObjectEx (handle, INFINITE, TRUE)
+                                                        == WAIT_IO_COMPLETION);
+
+    CloseHandle (handle);
+    assert (result == NULL); /* <- FIXME if ever needed */
+#ifdef UNDER_CE
+# undef handle
+    CloseHandle (handle->cancel_event);
+    free (handle);
+#endif
+}
+
+void vlc_detach (vlc_thread_t handle)
+{
+#ifndef UNDER_CE
+    CloseHandle (handle);
+#else
+    /* FIXME: handle->cancel_event leak */
+    CloseHandle (handle->handle);
+    free (handle);
+#endif
+}
+
+/*** Thread cancellation ***/
+
+/* APC procedure for thread cancellation */
+static void CALLBACK vlc_cancel_self (ULONG_PTR dummy)
+{
+    (void)dummy;
+    vlc_control_cancel (VLC_DO_CANCEL);
+}
+
+void vlc_cancel (vlc_thread_t thread_id)
+{
+#ifndef UNDER_CE
+    QueueUserAPC (vlc_cancel_self, thread_id, 0);
+#else
+    SetEvent (thread_id->cancel_event);
+#endif
+}
+
+int vlc_savecancel (void)
+{
+    int state;
+
+    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
+    if (nfo == NULL)
+        return false; /* Main thread - cannot be cancelled anyway */
+
+    state = nfo->killable;
+    nfo->killable = false;
+    return state;
+}
+
+void vlc_restorecancel (int state)
+{
+    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
+    assert (state == false || state == true);
+
+    if (nfo == NULL)
+        return; /* Main thread - cannot be cancelled anyway */
+
+    assert (!nfo->killable);
+    nfo->killable = state != 0;
+}
+
+void vlc_testcancel (void)
+{
+    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
+    if (nfo == NULL)
+        return; /* Main thread - cannot be cancelled anyway */
+
+    if (nfo->killable && nfo->killed)
+    {
+        for (vlc_cleanup_t *p = nfo->cleaners; p != NULL; p = p->next)
+             p->proc (p->data);
+#ifndef UNDER_CE
+        _endthread ();
+#else
+        ExitThread(0);
+#endif
+    }
+}
+
+void vlc_control_cancel (int cmd, ...)
+{
+    /* NOTE: This function only modifies thread-specific data, so there is no
+     * need to lock anything. */
+    va_list ap;
+
+    vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key);
+    if (nfo == NULL)
+        return; /* Main thread - cannot be cancelled anyway */
+
+    va_start (ap, cmd);
+    switch (cmd)
+    {
+        case VLC_DO_CANCEL:
+            nfo->killed = true;
+            break;
+
+        case VLC_CLEANUP_PUSH:
+        {
+            /* cleaner is a pointer to the caller stack, no need to allocate
+             * and copy anything. As a nice side effect, this cannot fail. */
+            vlc_cleanup_t *cleaner = va_arg (ap, vlc_cleanup_t *);
+            cleaner->next = nfo->cleaners;
+            nfo->cleaners = cleaner;
+            break;
+        }
+
+        case VLC_CLEANUP_POP:
+        {
+            nfo->cleaners = nfo->cleaners->next;
+            break;
+        }
+    }
+    va_end (ap);
+}
+
+
+/*** Timers ***/
+struct vlc_timer
+{
+#ifndef UNDER_CE
+    HANDLE handle;
+#else
+    unsigned id;
+    unsigned interval;
+#endif
+    void (*func) (void *);
+    void *data;
+};
+
+#ifndef UNDER_CE
+static void CALLBACK vlc_timer_do (void *val, BOOLEAN timeout)
+{
+    struct vlc_timer *timer = val;
+
+    assert (timeout);
+    timer->func (timer->data);
+}
+#else
+static void CALLBACK vlc_timer_do (unsigned timer_id, unsigned msg,
+                                   DWORD_PTR user, DWORD_PTR unused1,
+                                   DWORD_PTR unused2)
+{
+    struct vlc_timer *timer = (struct vlc_timer *) user;
+    assert (timer_id == timer->id);
+    (void) msg;
+    (void) unused1;
+    (void) unused2;
+
+    timer->func (timer->data);
+
+    if (timer->interval)
+    {
+        mtime_t interval = timer->interval * 1000;
+        vlc_timer_schedule (timer, false, interval, interval);
+    }
+}
+#endif
+
+int vlc_timer_create (vlc_timer_t *id, void (*func) (void *), void *data)
+{
+    struct vlc_timer *timer = malloc (sizeof (*timer));
+
+    if (timer == NULL)
+        return ENOMEM;
+    timer->func = func;
+    timer->data = data;
+#ifndef UNDER_CE
+    timer->handle = INVALID_HANDLE_VALUE;
+#else
+    timer->id = 0;
+    timer->interval = 0;
+#endif
+    *id = timer;
+    return 0;
+}
+
+void vlc_timer_destroy (vlc_timer_t timer)
+{
+#ifndef UNDER_CE
+    if (timer->handle != INVALID_HANDLE_VALUE)
+        DeleteTimerQueueTimer (NULL, timer->handle, INVALID_HANDLE_VALUE);
+#else
+    if (timer->id)
+        timeKillEvent (timer->id);
+    /* FIXME: timers that have not yet completed will trigger use-after-free */
+#endif
+    free (timer);
+}
+
+void vlc_timer_schedule (vlc_timer_t timer, bool absolute,
+                         mtime_t value, mtime_t interval)
+{
+#ifndef UNDER_CE
+    if (timer->handle != INVALID_HANDLE_VALUE)
+    {
+        DeleteTimerQueueTimer (NULL, timer->handle, NULL);
+        timer->handle = INVALID_HANDLE_VALUE;
+    }
+#else
+    if (timer->id)
+    {
+        timeKillEvent (timer->id);
+        timer->id = 0;
+        timer->interval = 0;
+    }
+#endif
+    if (value == 0)
+        return; /* Disarm */
+
+    if (absolute)
+        value -= mdate ();
+    value = (value + 999) / 1000;
+    interval = (interval + 999) / 1000;
+
+#ifndef UNDER_CE
+    if (!CreateTimerQueueTimer (&timer->handle, NULL, vlc_timer_do, timer,
+                                value, interval, WT_EXECUTEDEFAULT))
+#else
+    TIMECAPS caps;
+    timeGetDevCaps (&caps, sizeof(caps));
+
+    unsigned delay = value;
+    delay = __MAX(delay, caps.wPeriodMin);
+    delay = __MIN(delay, caps.wPeriodMax);
+
+    unsigned event = TIME_ONESHOT;
+
+    if (interval == delay)
+        event = TIME_PERIODIC;
+    else if (interval)
+        timer->interval = interval;
+
+    timer->id = timeSetEvent (delay, delay / 20, vlc_timer_do, (DWORD) timer,
+                              event);
+    if (!timer->id)
+#endif
+        abort ();
+}
+
+unsigned vlc_timer_getoverrun (vlc_timer_t timer)
+{
+    (void)timer;
+    return 0;
+}
diff --git a/src/win32/winsock.c b/src/win32/winsock.c
new file mode 100644 (file)
index 0000000..2584dff
--- /dev/null
@@ -0,0 +1,216 @@
+/*****************************************************************************
+ * winsock.c: POSIX replacements for Winsock
+ *****************************************************************************
+ * Copyright © 2006-2008 Rémi Denis-Courmont
+ *
+ * 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
+
+#include <vlc_common.h>
+#include <errno.h>
+#include <vlc_network.h>
+
+#ifndef WSA_QOS_EUNKNOWNPSOBJ
+# define WSA_QOS_EUNKNOWNPSOBJ 11024L
+#endif
+
+typedef struct
+{
+    int code;
+    const char *msg;
+} wsaerrmsg_t;
+
+static const wsaerrmsg_t wsaerrmsg[] =
+{
+    { WSA_INVALID_HANDLE, "Specified event object handle is invalid" },
+    { WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available" },
+    { WSA_INVALID_PARAMETER, "One or more parameters are invalid" },
+    { WSA_OPERATION_ABORTED, "Overlapped operation aborted" },
+    { WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state" },
+    { WSA_IO_PENDING, "Overlapped operations will complete later" },
+    { WSAEINTR, "Interrupted function call" },
+    { WSAEBADF, "File handle is not valid" },
+    { WSAEACCES, "Access denied" },
+    { WSAEFAULT, "Invalid memory address" },
+    { WSAEINVAL, "Invalid argument" },
+    { WSAEMFILE, "Too many open sockets" },
+    { WSAEWOULDBLOCK, "Resource temporarily unavailable" },
+    { WSAEINPROGRESS, "Operation now in progress" },
+    { WSAEALREADY, "Operation already in progress" },
+    { WSAENOTSOCK, "Non-socket handle specified" },
+    { WSAEDESTADDRREQ, "Missing destination address" },
+    { WSAEMSGSIZE, "Message too long" },
+    { WSAEPROTOTYPE, "Protocol wrong type for socket", },
+    { WSAENOPROTOOPT, "Option not supported by protocol" },
+    { WSAEPROTONOSUPPORT, "Protocol not supported" },
+    { WSAESOCKTNOSUPPORT, "Socket type not supported" },
+    { WSAEOPNOTSUPP, "Operation not supported" },
+    { WSAEPFNOSUPPORT, "Protocol family not supported" },
+    { WSAEAFNOSUPPORT, "Address family not supported by protocol family" },
+    { WSAEADDRINUSE, "Address already in use" },
+    { WSAEADDRNOTAVAIL, "Cannot assign requested address" },
+    { WSAENETDOWN, "Network is down" },
+    { WSAENETUNREACH, "Network unreachable" },
+    { WSAENETRESET, "Network dropped connection on reset" },
+    { WSAECONNABORTED, "Software caused connection abort" },
+    { WSAECONNRESET, "Connection reset by peer" },
+    { WSAENOBUFS, "No buffer space available (not enough memory)" },
+    { WSAEISCONN, "Socket is already connected" },
+    { WSAENOTCONN, "Socket is not connected" },
+    { WSAESHUTDOWN, "Cannot send after socket shutdown" },
+    { WSAETOOMANYREFS, "Too many references" },
+    { WSAETIMEDOUT, "Connection timed out" },
+    { WSAECONNREFUSED, "Connection refused by peer" },
+    { WSAELOOP, "Cannot translate name" },
+    { WSAENAMETOOLONG, "Name too long" },
+    { WSAEHOSTDOWN, "Remote host is down" },
+    { WSAEHOSTUNREACH, "No route to host (unreachable)" },
+    { WSAENOTEMPTY, "Directory not empty" },
+    { WSAEPROCLIM, "Too many processes" },
+    { WSAEUSERS, "User quota exceeded" },
+    { WSAEDQUOT, "Disk quota exceeded" },
+    { WSAESTALE, "Stale file handle reference" },
+    { WSAEREMOTE, "Item is remote", },
+    { WSASYSNOTREADY, "Network subsystem is unavailable (network stack not ready)" },
+    { WSAVERNOTSUPPORTED, "Winsock.dll version out of range (network stack version not supported" },
+    { WSANOTINITIALISED, "Network not initialized" },
+    { WSAEDISCON, "Graceful shutdown in progress" },
+    { WSAENOMORE, "No more results" },
+    { WSAECANCELLED, "Call has been cancelled" },
+    { WSAEINVALIDPROCTABLE, "Procedure call table is invalid" },
+    { WSAEINVALIDPROVIDER, "Service provider is invalid" },
+    { WSAEPROVIDERFAILEDINIT, "Service provider failed to initialize" },
+    { WSASYSCALLFAILURE, "System call failure" },
+    { WSASERVICE_NOT_FOUND, "Service not found" },
+    { WSATYPE_NOT_FOUND, "Class type not found" },
+    { WSA_E_NO_MORE, "No more results" },
+    { WSA_E_CANCELLED, "Call was cancelled" },
+    { WSAEREFUSED, "Database query was refused" },
+    { WSAHOST_NOT_FOUND, "Host not found" },
+    { WSATRY_AGAIN, "Nonauthoritative host not found (temporary hostname error)" },
+    { WSANO_RECOVERY, "Non-recoverable hostname error" },
+    { WSANO_DATA, "Valid name, no data record of requested type" },
+    { WSA_QOS_RECEIVERS, "QOS receivers" },
+    { WSA_QOS_SENDERS, "QOS senders" },
+    { WSA_QOS_NO_SENDERS, "No QOS senders" },
+    { WSA_QOS_NO_RECEIVERS, "QOS no receivers" },
+    { WSA_QOS_REQUEST_CONFIRMED, "QOS request confirmed" },
+    { WSA_QOS_ADMISSION_FAILURE, "QOS admission error" },
+    { WSA_QOS_POLICY_FAILURE, "QOS policy failure" },
+    { WSA_QOS_BAD_STYLE, "QOS bad style" },
+    { WSA_QOS_BAD_OBJECT, "QOS bad object" },
+    { WSA_QOS_TRAFFIC_CTRL_ERROR, "QOS traffic control error" },
+    { WSA_QOS_GENERIC_ERROR, "QOS generic error" },
+    { WSA_QOS_ESERVICETYPE, "QOS service type error" },
+    { WSA_QOS_EFLOWSPEC, "QOS flowspec error" },
+    { WSA_QOS_EPROVSPECBUF, "Invalid QOS provider buffer" },
+    { WSA_QOS_EFILTERSTYLE, "Invalid QOS filter style" },
+    { WSA_QOS_EFILTERTYPE, "Invalid QOS filter type" },
+    { WSA_QOS_EFILTERCOUNT, "Incorrect QOS filter count" },
+    { WSA_QOS_EOBJLENGTH, "Invalid QOS object length" },
+    { WSA_QOS_EFLOWCOUNT, "Incorrect QOS flow count" },
+    { WSA_QOS_EUNKNOWNPSOBJ, "Unrecognized QOS object" },
+    { WSA_QOS_EPOLICYOBJ, "Invalid QOS policy object" },
+    { WSA_QOS_EFLOWDESC, "Invalid QOS flow descriptor" },
+    { WSA_QOS_EPSFLOWSPEC, "Invalid QOS provider-specific flowspec" },
+    { WSA_QOS_EPSFILTERSPEC, "Invalid QOS provider-specific filterspec" },
+    { WSA_QOS_ESDMODEOBJ, "Invalid QOS shape discard mode object" },
+    { WSA_QOS_ESHAPERATEOBJ, "Invalid QOS shaping rate object" },
+    { WSA_QOS_RESERVED_PETYPE, "Reserved policy QOS element type" },
+    { 0, NULL }
+    /* Winsock2 error codes are missing, they "never" occur */
+};
+
+
+const char *net_strerror( int value )
+{
+    /* There doesn't seem to be any portable error message generation for
+     * Winsock errors. Some old versions had s_error, but it appears to be
+     * gone, and is not documented.
+     */
+    for( const wsaerrmsg_t *e = wsaerrmsg; e->msg != NULL; e++ )
+        if( e->code == value )
+            return e->msg;
+
+    /* Remember to update src/misc/messages.c if you change this one */
+    return "Unknown network stack error";
+}
+
+#if 0
+ssize_t vlc_sendmsg (int s, struct msghdr *hdr, int flags)
+{
+    /* WSASendMsg would be more straightforward, and would support ancilliary
+     * data, but it's not yet in mingw32. */
+    if ((hdr->msg_iovlen > 100) || (hdr->msg_controllen > 0))
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    WSABUF buf[hdr->msg_iovlen];
+    for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
+        buf[i].buf = hdr->msg_iov[i].iov_base,
+        buf[i].len = hdr->msg_iov[i].iov_len;
+
+    DWORD sent;
+    if (WSASendTo (s, buf, sizeof (buf) / sizeof (buf[0]), &sent, flags,
+                   hdr->msg_name, hdr->msg_namelen, NULL, NULL) == 0)
+        return sent;
+    return -1;
+}
+
+ssize_t vlc_recvmsg (int s, struct msghdr *hdr, int flags)
+{
+    /* WSARecvMsg would be more straightforward, and would support ancilliary
+     * data, but it's not yet in mingw32. */
+    if (hdr->msg_iovlen > 100)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    WSABUF buf[hdr->msg_iovlen];
+    for (size_t i = 0; i < sizeof (buf) / sizeof (buf[0]); i++)
+        buf[i].buf = hdr->msg_iov[i].iov_base,
+        buf[i].len = hdr->msg_iov[i].iov_len;
+
+    DWORD recvd, dwFlags = flags;
+    INT fromlen = hdr->msg_namelen;
+    hdr->msg_controllen = 0;
+    hdr->msg_flags = 0;
+
+    int ret = WSARecvFrom (s, buf, sizeof (buf) / sizeof (buf[0]), &recvd,
+                           &dwFlags, hdr->msg_name, &fromlen, NULL, NULL);
+    hdr->msg_namelen = fromlen;
+    hdr->msg_flags = dwFlags;
+    if (ret == 0)
+        return recvd;
+
+#ifdef MSG_TRUNC
+    if (WSAGetLastError() == WSAEMSGSIZE)
+    {
+        hdr->msg_flags |= MSG_TRUNC;
+        return recvd;
+    }
+#else
+# warning Out-of-date Winsock header files!
+#endif
+    return -1;
+}
+#endif