mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-08-17 17:05:50 +00:00
Add new platform thread callbacks for Windows RT usage to avoid banned APIs
This commit is contained in:
parent
91f0351671
commit
7fb3ef3f79
@ -4,6 +4,7 @@
|
|||||||
static int stage = STAGE_NONE;
|
static int stage = STAGE_NONE;
|
||||||
static CONNECTION_LISTENER_CALLBACKS listenerCallbacks;
|
static CONNECTION_LISTENER_CALLBACKS listenerCallbacks;
|
||||||
static CONNECTION_LISTENER_CALLBACKS originalCallbacks;
|
static CONNECTION_LISTENER_CALLBACKS originalCallbacks;
|
||||||
|
static PLATFORM_CALLBACKS platformCallbacks;
|
||||||
|
|
||||||
static int alreadyTerminated;
|
static int alreadyTerminated;
|
||||||
|
|
||||||
@ -134,12 +135,19 @@ void ClInternalDisplayTransientMessage(char* message)
|
|||||||
originalCallbacks.displayTransientMessage(message);
|
originalCallbacks.displayTransientMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LiCompleteThreadStart(void)
|
||||||
|
{
|
||||||
|
PltRunThreadProc();
|
||||||
|
}
|
||||||
|
|
||||||
/* Starts the connection to the streaming machine */
|
/* Starts the connection to the streaming machine */
|
||||||
int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
||||||
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags) {
|
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, PPLATFORM_CALLBACKS plCallbacks,
|
||||||
|
void* renderContext, int drFlags) {
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
memcpy(&originalCallbacks, clCallbacks, sizeof(originalCallbacks));
|
memcpy(&originalCallbacks, clCallbacks, sizeof(originalCallbacks));
|
||||||
|
memcpy(&platformCallbacks, plCallbacks, sizeof(platformCallbacks));
|
||||||
|
|
||||||
listenerCallbacks.stageStarting = ClInternalStageStarting;
|
listenerCallbacks.stageStarting = ClInternalStageStarting;
|
||||||
listenerCallbacks.stageComplete = ClInternalStageComplete;
|
listenerCallbacks.stageComplete = ClInternalStageComplete;
|
||||||
@ -153,13 +161,13 @@ int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONN
|
|||||||
|
|
||||||
Limelog("Initializing platform...");
|
Limelog("Initializing platform...");
|
||||||
listenerCallbacks.stageStarting(STAGE_PLATFORM_INIT);
|
listenerCallbacks.stageStarting(STAGE_PLATFORM_INIT);
|
||||||
err = initializePlatformSockets();
|
err = initializePlatformSockets(&platformCallbacks);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
Limelog("failed: %d\n", err);
|
Limelog("failed: %d\n", err);
|
||||||
listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
|
listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
err = initializePlatformThreads();
|
err = initializePlatformThreads(&platformCallbacks);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
Limelog("failed: %d\n", err);
|
Limelog("failed: %d\n", err);
|
||||||
listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
|
listenerCallbacks.stageFailed(STAGE_PLATFORM_INIT, err);
|
||||||
|
@ -90,11 +90,21 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS {
|
|||||||
ConnListenerDisplayTransientMessage displayTransientMessage;
|
ConnListenerDisplayTransientMessage displayTransientMessage;
|
||||||
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
|
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
|
||||||
|
|
||||||
|
typedef void(*PlatformThreadStart)(void);
|
||||||
|
|
||||||
|
typedef struct _PLATFORM_CALLBACKS {
|
||||||
|
PlatformThreadStart threadStart;
|
||||||
|
} PLATFORM_CALLBACKS, *PPLATFORM_CALLBACKS;
|
||||||
|
|
||||||
int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
int LiStartConnection(IP_ADDRESS host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
|
||||||
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags);
|
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, PPLATFORM_CALLBACKS plCallbacks,
|
||||||
|
void* renderContext, int drFlags);
|
||||||
void LiStopConnection(void);
|
void LiStopConnection(void);
|
||||||
const char* LiGetStageName(int stage);
|
const char* LiGetStageName(int stage);
|
||||||
|
|
||||||
|
/* Call in the context of a new thread */
|
||||||
|
void LiCompleteThreadStart(void);
|
||||||
|
|
||||||
int LiSendMouseMoveEvent(short deltaX, short deltaY);
|
int LiSendMouseMoveEvent(short deltaX, short deltaY);
|
||||||
|
|
||||||
#define BUTTON_ACTION_PRESS 0x07
|
#define BUTTON_ACTION_PRESS 0x07
|
||||||
|
@ -80,7 +80,7 @@ int enableNoDelay(SOCKET s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int initializePlatformSockets(void) {
|
int initializePlatformSockets(PPLATFORM_CALLBACKS plCallbacks) {
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
WSADATA data;
|
WSADATA data;
|
||||||
return WSAStartup(MAKEWORD(2, 0), &data);
|
return WSAStartup(MAKEWORD(2, 0), &data);
|
||||||
|
@ -33,5 +33,5 @@ typedef ssize_t SOCK_RET;
|
|||||||
SOCKET connectTcpSocket(IP_ADDRESS dstaddr, unsigned short port);
|
SOCKET connectTcpSocket(IP_ADDRESS dstaddr, unsigned short port);
|
||||||
SOCKET bindUdpSocket(void);
|
SOCKET bindUdpSocket(void);
|
||||||
int enableNoDelay(SOCKET s);
|
int enableNoDelay(SOCKET s);
|
||||||
int initializePlatformSockets(void);
|
int initializePlatformSockets(PPLATFORM_CALLBACKS plCallbacks);
|
||||||
void cleanupPlatformSockets(void);
|
void cleanupPlatformSockets(void);
|
@ -1,28 +1,15 @@
|
|||||||
#include "PlatformThreads.h"
|
#include "PlatformThreads.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
struct thread_context {
|
|
||||||
ThreadEntry entry;
|
|
||||||
void* context;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
|
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
|
||||||
WCHAR DbgBuf[512];
|
WCHAR DbgBuf[512];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
PLT_MUTEX thread_list_lock;
|
PLT_MUTEX thread_list_lock;
|
||||||
|
PLT_THREAD *pending_thread_head;
|
||||||
PLT_THREAD *thread_head;
|
PLT_THREAD *thread_head;
|
||||||
|
PPLATFORM_CALLBACKS platformCallbacks;
|
||||||
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
|
|
||||||
struct thread_context *ctx = (struct thread_context *)lpParameter;
|
|
||||||
|
|
||||||
ctx->entry(ctx->context);
|
|
||||||
|
|
||||||
free(ctx);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
void* ThreadProc(void* context) {
|
void* ThreadProc(void* context) {
|
||||||
struct thread_context *ctx = (struct thread_context *)context;
|
struct thread_context *ctx = (struct thread_context *)context;
|
||||||
@ -86,7 +73,8 @@ void PltUnlockMutex(PLT_MUTEX *mutex) {
|
|||||||
|
|
||||||
void PltJoinThread(PLT_THREAD *thread) {
|
void PltJoinThread(PLT_THREAD *thread) {
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
|
// Wait for the thread to leave our code
|
||||||
|
WaitForSingleObjectEx(thread->termCompleted, INFINITE, FALSE);
|
||||||
#else
|
#else
|
||||||
pthread_join(*thread, NULL);
|
pthread_join(*thread, NULL);
|
||||||
#endif
|
#endif
|
||||||
@ -123,8 +111,8 @@ void PltCloseThread(PLT_THREAD *thread) {
|
|||||||
|
|
||||||
PltUnlockMutex(&thread_list_lock);
|
PltUnlockMutex(&thread_list_lock);
|
||||||
|
|
||||||
CloseHandle(thread->termevent);
|
CloseHandle(thread->termRequested);
|
||||||
CloseHandle(thread->handle);
|
CloseHandle(thread->termCompleted);
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -142,12 +130,47 @@ int PltIsThreadInterrupted(PLT_THREAD *thread) {
|
|||||||
void PltInterruptThread(PLT_THREAD *thread) {
|
void PltInterruptThread(PLT_THREAD *thread) {
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
thread->cancelled = 1;
|
thread->cancelled = 1;
|
||||||
SetEvent(thread->termevent);
|
SetEvent(thread->termRequested);
|
||||||
#else
|
#else
|
||||||
pthread_cancel(*thread);
|
pthread_cancel(*thread);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PltRunThreadProc(void) {
|
||||||
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
|
PLT_THREAD *thread;
|
||||||
|
|
||||||
|
// Grab the first entry from the pending list and move it
|
||||||
|
// to the active list
|
||||||
|
PltLockMutex(&thread_list_lock);
|
||||||
|
thread = pending_thread_head;
|
||||||
|
|
||||||
|
// If there's no pending thread, something is seriously wrong
|
||||||
|
LC_ASSERT(thread != NULL);
|
||||||
|
|
||||||
|
pending_thread_head = pending_thread_head->next;
|
||||||
|
|
||||||
|
thread->next = thread_head;
|
||||||
|
thread_head = thread;
|
||||||
|
PltUnlockMutex(&thread_list_lock);
|
||||||
|
|
||||||
|
// Set up final thread state before running
|
||||||
|
thread->tid = GetCurrentThreadId();
|
||||||
|
|
||||||
|
// Now we're going to invoke the thread proc
|
||||||
|
thread->ctx->entry(thread->ctx->context);
|
||||||
|
free(thread->ctx);
|
||||||
|
|
||||||
|
// Signal the event to indicate the thread has "terminated"
|
||||||
|
SetEvent(thread->termCompleted);
|
||||||
|
|
||||||
|
// PltCloseThread() frees this state
|
||||||
|
#else
|
||||||
|
// This code shouldn't be called on *NIX
|
||||||
|
LC_ASSERT(0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
|
int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
|
||||||
struct thread_context *ctx;
|
struct thread_context *ctx;
|
||||||
int err;
|
int err;
|
||||||
@ -162,32 +185,32 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
|
|||||||
|
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
{
|
{
|
||||||
thread->termevent = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
|
thread->termRequested = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
|
||||||
if (thread->termevent == NULL) {
|
if (thread->termRequested == NULL) {
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread->termCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
|
||||||
|
if (thread->termCompleted == NULL) {
|
||||||
|
CloseHandle(thread->termRequested);
|
||||||
|
free(ctx);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
thread->cancelled = 0;
|
thread->cancelled = 0;
|
||||||
// TODO we aren't allowed to use CreateThread API in kernel32.dll
|
thread->ctx = ctx;
|
||||||
thread->handle = CreateThread(NULL, 0, ThreadProc, ctx, CREATE_SUSPENDED, &thread->tid);
|
|
||||||
if (thread->handle == NULL) {
|
|
||||||
CloseHandle(thread->termevent);
|
|
||||||
free(ctx);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Add this thread to the thread list
|
|
||||||
PltLockMutex(&thread_list_lock);
|
|
||||||
thread->next = thread_head;
|
|
||||||
thread_head = thread;
|
|
||||||
PltUnlockMutex(&thread_list_lock);
|
|
||||||
|
|
||||||
// Now the thread can run
|
// Queue on the pending threads list
|
||||||
// TODO can't use ResumeThread in kernel32.dll
|
PltLockMutex(&thread_list_lock);
|
||||||
ResumeThread(thread->handle);
|
thread->next = pending_thread_head;
|
||||||
|
pending_thread_head = thread;
|
||||||
|
PltUnlockMutex(&thread_list_lock);
|
||||||
|
|
||||||
err = 0;
|
// Make a callback to managed code to ask for a thread to grab this
|
||||||
}
|
platformCallbacks->threadStart();
|
||||||
|
|
||||||
|
err = 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@ -263,7 +286,7 @@ int PltWaitForEvent(PLT_EVENT *event) {
|
|||||||
LC_ASSERT(current_thread != NULL);
|
LC_ASSERT(current_thread != NULL);
|
||||||
|
|
||||||
objects[0] = *event;
|
objects[0] = *event;
|
||||||
objects[1] = current_thread->termevent;
|
objects[1] = current_thread->termRequested;
|
||||||
error = WaitForMultipleObjectsEx(2, objects, FALSE, INFINITE, FALSE);
|
error = WaitForMultipleObjectsEx(2, objects, FALSE, INFINITE, FALSE);
|
||||||
if (error == WAIT_OBJECT_0) {
|
if (error == WAIT_OBJECT_0) {
|
||||||
return PLT_WAIT_SUCCESS;
|
return PLT_WAIT_SUCCESS;
|
||||||
@ -285,8 +308,14 @@ int PltWaitForEvent(PLT_EVENT *event) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int initializePlatformThreads(void) {
|
int initializePlatformThreads(PPLATFORM_CALLBACKS plCallbacks) {
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
|
pending_thread_head = thread_head = NULL;
|
||||||
|
|
||||||
|
// This data is stored in static memory in Connection.c, so we don't
|
||||||
|
// bother making our own copy
|
||||||
|
platformCallbacks = plCallbacks;
|
||||||
|
|
||||||
return PltCreateMutex(&thread_list_lock);
|
return PltCreateMutex(&thread_list_lock);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Limelight.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
typedef void (*ThreadEntry)(void *context);
|
typedef void (*ThreadEntry)(void *context);
|
||||||
|
|
||||||
|
struct thread_context {
|
||||||
|
ThreadEntry entry;
|
||||||
|
void* context;
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
|
||||||
typedef struct _PLT_THREAD {
|
typedef struct _PLT_THREAD {
|
||||||
HANDLE handle;
|
|
||||||
int cancelled;
|
int cancelled;
|
||||||
DWORD tid;
|
DWORD tid;
|
||||||
HANDLE termevent;
|
HANDLE termRequested;
|
||||||
|
HANDLE termCompleted;
|
||||||
|
|
||||||
|
struct thread_context *ctx;
|
||||||
|
|
||||||
struct _PLT_THREAD *next;
|
struct _PLT_THREAD *next;
|
||||||
} PLT_THREAD;
|
} PLT_THREAD;
|
||||||
@ -27,28 +35,7 @@ typedef struct _PLT_EVENT {
|
|||||||
#error Unsupported platform
|
#error Unsupported platform
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LC_WINDOWS_PHONE
|
int initializePlatformThreads(PPLATFORM_CALLBACKS plCallbacks);
|
||||||
WINBASEAPI
|
|
||||||
_Ret_maybenull_
|
|
||||||
HANDLE
|
|
||||||
WINAPI
|
|
||||||
CreateThread(
|
|
||||||
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
|
||||||
_In_ SIZE_T dwStackSize,
|
|
||||||
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
|
|
||||||
_In_opt_ __drv_aliasesMem LPVOID lpParameter,
|
|
||||||
_In_ DWORD dwCreationFlags,
|
|
||||||
_Out_opt_ LPDWORD lpThreadId
|
|
||||||
);
|
|
||||||
|
|
||||||
DWORD
|
|
||||||
WINAPI
|
|
||||||
ResumeThread(
|
|
||||||
_In_ HANDLE hThread
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int initializePlatformThreads(void);
|
|
||||||
void cleanupPlatformThreads(void);
|
void cleanupPlatformThreads(void);
|
||||||
|
|
||||||
int PltCreateMutex(PLT_MUTEX *mutex);
|
int PltCreateMutex(PLT_MUTEX *mutex);
|
||||||
@ -68,6 +55,8 @@ void PltSetEvent(PLT_EVENT *event);
|
|||||||
void PltClearEvent(PLT_EVENT *event);
|
void PltClearEvent(PLT_EVENT *event);
|
||||||
int PltWaitForEvent(PLT_EVENT *event);
|
int PltWaitForEvent(PLT_EVENT *event);
|
||||||
|
|
||||||
|
void PltRunThreadProc(void);
|
||||||
|
|
||||||
#define PLT_WAIT_SUCCESS 0
|
#define PLT_WAIT_SUCCESS 0
|
||||||
#define PLT_WAIT_INTERRUPTED 1
|
#define PLT_WAIT_INTERRUPTED 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user