# See the License for the specific language governing permissions and
# limitations under the License.
-set(DISK_SRCS
+set(MODULE_NAME "disk")
+set(MODULE_PREFIX "CHANNEL_DEVICE_DISK")
+
+set(${MODULE_PREFIX}_SRCS
disk_file.c
disk_file.h
disk_main.c)
include_directories(..)
-add_library(disk ${DISK_SRCS})
-set_target_properties(disk PROPERTIES PREFIX "")
+add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
if(WITH_MONOLITHIC_BUILD)
- target_link_libraries(disk freerdp)
+ set(${MODULE_PREFIX}_LIBS freerdp winpr)
else()
- target_link_libraries(disk freerdp-utils)
+ set(${MODULE_PREFIX}_LIBS freerdp-utils winpr-synch winpr-thread)
endif()
-install(TARGETS disk DESTINATION ${FREERDP_PLUGIN_PATH})
+target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
+install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_PLUGIN_PATH})
#include <freerdp/utils/stream.h>
#include <freerdp/utils/unicode.h>
#include <freerdp/utils/list.h>
-#include <freerdp/utils/thread.h>
#include <freerdp/utils/svc_plugin.h>
+#include <winpr/synch.h>
+#include <winpr/thread.h>
+
#include "rdpdr_constants.h"
#include "rdpdr_types.h"
#include "disk_file.h"
typedef struct _DISK_DEVICE DISK_DEVICE;
+
struct _DISK_DEVICE
{
DEVICE device;
char* path;
LIST* files;
+ HANDLE mutex;
+ HANDLE thread;
LIST* irp_list;
- freerdp_thread* thread;
+ HANDLE irpEvent;
+ HANDLE stopEvent;
DEVMAN* devman;
pcRegisterDevice UnregisterDevice;
};
-static uint32
-disk_map_posix_err(int fs_errno)
+static uint32 disk_map_posix_err(int fs_errno)
{
uint32 rc;
rc = STATUS_UNSUCCESSFUL;
break;
}
+
DEBUG_SVC("errno 0x%x mapped to 0x%x", fs_errno, rc);
+
return rc;
}
for (item = disk->files->head; item; item = item->next)
{
- file = (DISK_FILE*)item->data;
+ file = (DISK_FILE*) item->data;
+
if (file->id == id)
return file;
}
}
else
{
- buffer = (uint8*)xmalloc(Length);
+ buffer = (uint8*) xmalloc(Length);
if (!disk_file_read(file, buffer, &Length))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
}
stream_write_uint32(irp->output, Length);
+
if (Length > 0)
{
stream_check_size(irp->output, Length);
stream_write(irp->output, buffer, Length);
}
+
xfree(buffer);
irp->Complete(irp);
struct STATVFS svfst;
struct STAT st;
UNICONV* uniconv;
- char *volumeLabel = {"FREERDP"}; /* TODO:: Add sub routine to correctly pick up Volume Label name for each O/S supported*/
- char *diskType = {"FAT32"};
+ char* volumeLabel = {"FREERDP"}; /* TODO: Add sub routine to correctly pick up Volume Label name for each O/S supported */
+ char* diskType = {"FAT32"};
char* outStr;
size_t len;
while (1)
{
- if (freerdp_thread_is_stopped(disk->thread))
+ if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
break;
- freerdp_thread_lock(disk->thread);
- irp = (IRP*)list_dequeue(disk->irp_list);
- freerdp_thread_unlock(disk->thread);
+ WaitForSingleObject(disk->mutex, INFINITE);
+
+ irp = (IRP*) list_dequeue(disk->irp_list);
+
+ ReleaseMutex(disk->mutex);
if (irp == NULL)
break;
static void* disk_thread_func(void* arg)
{
- DISK_DEVICE* disk = (DISK_DEVICE*)arg;
+ DISK_DEVICE* disk = (DISK_DEVICE*) arg;
while (1)
{
- freerdp_thread_wait(disk->thread);
+ WaitForSingleObject(disk->irpEvent, INFINITE);
- if (freerdp_thread_is_stopped(disk->thread))
+ if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
break;
- freerdp_thread_reset(disk->thread);
+ ResetEvent(disk->irpEvent);
disk_process_irp_list(disk);
}
- freerdp_thread_quit(disk->thread);
-
return NULL;
}
static void disk_irp_request(DEVICE* device, IRP* irp)
{
- DISK_DEVICE* disk = (DISK_DEVICE*)device;
+ DISK_DEVICE* disk = (DISK_DEVICE*) device;
- freerdp_thread_lock(disk->thread);
+ WaitForSingleObject(disk->mutex, INFINITE);
list_enqueue(disk->irp_list, irp);
- freerdp_thread_unlock(disk->thread);
+ ReleaseMutex(disk->mutex);
- freerdp_thread_signal(disk->thread);
+ SetEvent(disk->irpEvent);
}
static void disk_free(DEVICE* device)
{
- DISK_DEVICE* disk = (DISK_DEVICE*)device;
IRP* irp;
DISK_FILE* file;
+ DISK_DEVICE* disk = (DISK_DEVICE*) device;
- freerdp_thread_stop(disk->thread);
- freerdp_thread_free(disk->thread);
+ SetEvent(disk->stopEvent);
+ CloseHandle(disk->thread);
+ CloseHandle(disk->irpEvent);
+ CloseHandle(disk->mutex);
- while ((irp = (IRP*)list_dequeue(disk->irp_list)) != NULL)
+ while ((irp = (IRP*) list_dequeue(disk->irp_list)) != NULL)
irp->Discard(irp);
+
list_free(disk->irp_list);
- while ((file = (DISK_FILE*)list_dequeue(disk->files)) != NULL)
+ while ((file = (DISK_FILE*) list_dequeue(disk->files)) != NULL)
disk_file_free(file);
+
list_free(disk->files);
xfree(disk);
}
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
- DISK_DEVICE* disk;
char* name;
char* path;
int i, len;
+ DISK_DEVICE* disk;
- name = (char*)pEntryPoints->plugin_data->data[1];
- path = (char*)pEntryPoints->plugin_data->data[2];
+ name = (char*) pEntryPoints->plugin_data->data[1];
+ path = (char*) pEntryPoints->plugin_data->data[2];
if (name[0] && path[0])
{
len = strlen(name);
disk->device.data = stream_new(len + 1);
+
for (i = 0; i <= len; i++)
stream_write_uint8(disk->device.data, name[i] < 0 ? '_' : name[i]);
disk->files = list_new();
disk->irp_list = list_new();
- disk->thread = freerdp_thread_new();
+ disk->mutex = CreateMutex(NULL, FALSE, NULL);
+ disk->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ disk->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ disk->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) disk_thread_func, disk, CREATE_SUSPENDED, NULL);
- pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)disk);
+ pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) disk);
- freerdp_thread_start(disk->thread, disk_thread_func, disk);
+ ResumeThread(disk->thread);
}
return 0;
static void rdpdr_process_receive(rdpSvcPlugin* plugin, STREAM* data_in)
{
- rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
uint16 component;
uint16 packetID;
uint32 deviceID;
uint32 status;
+ rdpdrPlugin* rdpdr = (rdpdrPlugin*) plugin;
stream_read_uint16(data_in, component);
stream_read_uint16(data_in, packetID);
#include "scard_main.h"
-static void
-scard_free(DEVICE* dev)
+static void scard_free(DEVICE* dev)
{
- SCARD_DEVICE* scard = (SCARD_DEVICE*)dev;
IRP* irp;
COMPLETIONIDINFO* CompletionIdInfo;
+ SCARD_DEVICE* scard = (SCARD_DEVICE*) dev;
freerdp_thread_stop(scard->thread);
freerdp_thread_free(scard->thread);
- while ((irp = (IRP*)list_dequeue(scard->irp_list)) != NULL)
+ while ((irp = (IRP*) list_dequeue(scard->irp_list)) != NULL)
irp->Discard(irp);
+
list_free(scard->irp_list);
/* Begin TS Client defect workaround. */
- while ((CompletionIdInfo = (COMPLETIONIDINFO*)list_dequeue(scard->CompletionIds)) != NULL)
+
+ while ((CompletionIdInfo = (COMPLETIONIDINFO*) list_dequeue(scard->CompletionIds)) != NULL)
xfree(CompletionIdInfo);
+
list_free(scard->CompletionIds);
+
/* End TS Client defect workaround. */
xfree(dev);
return;
}
-
-static void
-scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
+static void scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
{
switch (irp->MajorFunction)
{
}
}
-
-static void
-scard_process_irp_list(SCARD_DEVICE* scard)
+static void scard_process_irp_list(SCARD_DEVICE* scard)
{
- IRP *irp;
+ IRP* irp;
while (!freerdp_thread_is_stopped(scard->thread))
{
freerdp_thread_lock(scard->thread);
- irp = (IRP *) list_dequeue(scard->irp_list);
+ irp = (IRP*) list_dequeue(scard->irp_list);
freerdp_thread_unlock(scard->thread);
if (irp == NULL)
}
}
-
-struct scard_irp_thread_args {
+struct scard_irp_thread_args
+{
SCARD_DEVICE* scard;
IRP* irp;
freerdp_thread* thread;
};
-
-static void
-scard_process_irp_thread_func(struct scard_irp_thread_args* args)
+static void scard_process_irp_thread_func(struct scard_irp_thread_args* args)
{
scard_process_irp(args->scard, args->irp);
xfree(args);
}
-
-static void *
-scard_thread_func(void* arg)
+static void* scard_thread_func(void* arg)
{
SCARD_DEVICE* scard = (SCARD_DEVICE*) arg;
return NULL;
}
-
/* Begin TS Client defect workaround. */
-static COMPLETIONIDINFO*
-scard_mark_duplicate_id(SCARD_DEVICE* scard, uint32 CompletionId)
+static COMPLETIONIDINFO* scard_mark_duplicate_id(SCARD_DEVICE* scard, uint32 CompletionId)
{
-/*
- * Search from the beginning of the LIST for one outstanding "CompletionID"
- * that matches the one passed in. If there is one, mark it as a duplicate
- * if it is not already marked.
- */
+ /*
+ * Search from the beginning of the LIST for one outstanding "CompletionID"
+ * that matches the one passed in. If there is one, mark it as a duplicate
+ * if it is not already marked.
+ */
LIST_ITEM* item;
COMPLETIONIDINFO* CompletionIdInfo;
return CompletionIdInfo;
}
}
+
return NULL; /* Either no items in the list or no match. */
}
-static boolean
-scard_check_for_duplicate_id(SCARD_DEVICE* scard, uint32 CompletionId)
+static boolean scard_check_for_duplicate_id(SCARD_DEVICE* scard, uint32 CompletionId)
{
-/*
- * Search from the end of the LIST for one outstanding "CompletionID"
- * that matches the one passed in. Remove it from the list and free the
- * memory associated with it. Return whether or not it was marked
- * as a duplicate.
- */
+ /*
+ * Search from the end of the LIST for one outstanding "CompletionID"
+ * that matches the one passed in. Remove it from the list and free the
+ * memory associated with it. Return whether or not it was marked
+ * as a duplicate.
+ */
LIST_ITEM* item;
COMPLETIONIDINFO* CompletionIdInfo;
boolean duplicate;
return duplicate;
}
}
+
/* This function should only be called when there is
* at least one outstanding CompletionID item in the list.
*/
DEBUG_WARN("Error!!! No CompletionIDs (or no matching IDs) in the list!");
+
return false;
}
-static void
-scard_irp_complete(IRP* irp)
+static void scard_irp_complete(IRP* irp)
{
-/* This function is (mostly) a copy of the statically-declared "irp_complete()"
- * function except that this function adds extra operations for the
- * smart card's handling of duplicate "CompletionID"s. This function needs
- * to be in this file so that "scard_irp_request()" can reference it.
- */
+ /* This function is (mostly) a copy of the statically-declared "irp_complete()"
+ * function except that this function adds extra operations for the
+ * smart card's handling of duplicate "CompletionID"s. This function needs
+ * to be in this file so that "scard_irp_request()" can reference it.
+ */
int pos;
boolean duplicate;
SCARD_DEVICE* scard = (SCARD_DEVICE*)irp->device;
}
/* End TS Client defect workaround. */
-
-static void
-scard_irp_request(DEVICE* device, IRP* irp)
+static void scard_irp_request(DEVICE* device, IRP* irp)
{
COMPLETIONIDINFO* CompletionIdInfo;
-
- SCARD_DEVICE* scard = (SCARD_DEVICE*)device;
+ SCARD_DEVICE* scard = (SCARD_DEVICE*) device;
/* Begin TS Client defect workaround. */
CompletionIdInfo= xnew(COMPLETIONIDINFO);
rdpSvcPlugin * plugin;
WaitForSingleObject(g_mutex, INFINITE);
+
for (list = g_svc_plugin_list; list; list = list->next)
{
plugin = list->plugin;
+
if (plugin->priv->open_handle == open_handle)
{
ReleaseMutex(g_mutex);
}
}
ReleaseMutex(g_mutex);
+
return NULL;
}
DEBUG_SVC("openHandle %d event %d dataLength %d totalLength %d dataFlags %d",
openHandle, event, dataLength, totalLength, dataFlags);
- plugin = (rdpSvcPlugin*)svc_plugin_find_by_open_handle(openHandle);
+ plugin = (rdpSvcPlugin*) svc_plugin_find_by_open_handle(openHandle);
+
if (plugin == NULL)
{
printf("svc_plugin_open_event: error no match\n");
return;
}
+
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
svc_plugin_process_received(plugin, pData, dataLength, totalLength, dataFlags);
break;
+
case CHANNEL_EVENT_WRITE_COMPLETE:
- stream_free((STREAM*)pData);
+ stream_free((STREAM*) pData);
break;
+
case CHANNEL_EVENT_USER:
- svc_plugin_process_event(plugin, (RDP_EVENT*)pData);
+ svc_plugin_process_event(plugin, (RDP_EVENT*) pData);
break;
}
}
DEBUG_SVC("event %d", event);
- plugin = (rdpSvcPlugin*)svc_plugin_find_by_init_handle(pInitHandle);
- if (plugin == NULL)
+ plugin = (rdpSvcPlugin*) svc_plugin_find_by_init_handle(pInitHandle);
+
+ if (!plugin)
{
printf("svc_plugin_init_event: error no match\n");
return;
}
+
switch (event)
{
case CHANNEL_EVENT_CONNECTED:
svc_plugin_process_connected(plugin, pData, dataLength);
break;
+
case CHANNEL_EVENT_DISCONNECTED:
break;
+
case CHANNEL_EVENT_TERMINATED:
svc_plugin_process_terminated(plugin);
break;
error = plugin->channel_entry_points.pVirtualChannelWrite(plugin->priv->open_handle,
stream_get_data(data_out), stream_get_length(data_out), data_out);
+
if (error != CHANNEL_RC_OK)
{
stream_free(data_out);
WINPR_API BOOL SetEvent(HANDLE hEvent);
WINPR_API BOOL ResetEvent(HANDLE hEvent);
+#ifdef UNICODE
+#define CreateEvent CreateEventW
+#define CreateEventEx CreateEventExW
+#define OpenEvent OpenEventW
+#else
+#define CreateEvent CreateEventA
+#define CreateEventEx CreateEventExA
+#define OpenEvent OpenEventA
+#endif
+
/* One-Time Initialization */
typedef union _RTL_RUN_ONCE
/* Thread */
-WINPR_API HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);
+#define CREATE_SUSPENDED 0x00000004
+#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
WINPR_API HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
+WINPR_API HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
+
WINPR_API VOID ExitThread(DWORD dwExitCode);
WINPR_API HANDLE GetCurrentThread(VOID);
#ifndef _WIN32
+#include <pthread.h>
+
+pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
typedef struct _HANDLE_TABLE_ENTRY
{
ULONG Type;
{
size_t size;
- HandleTable.Count = 0;
- HandleTable.MaxCount = 64;
+ pthread_mutex_lock(&mutex);
- size = sizeof(HANDLE_TABLE_ENTRY) * HandleTable.MaxCount;
+ if (HandleTable.MaxCount < 1)
+ {
+ HandleTable.Count = 0;
+ HandleTable.MaxCount = 64;
+
+ size = sizeof(HANDLE_TABLE_ENTRY) * HandleTable.MaxCount;
+
+ HandleTable.Entries = (PHANDLE_TABLE_ENTRY) malloc(size);
+ ZeroMemory(HandleTable.Entries, size);
+ }
- HandleTable.Entries = (PHANDLE_TABLE_ENTRY) malloc(size);
- ZeroMemory(HandleTable.Entries, size);
+ pthread_mutex_unlock(&mutex);
}
void winpr_HandleTable_Grow()
{
size_t size;
+
+ pthread_mutex_lock(&mutex);
+
HandleTable.MaxCount *= 2;
size = sizeof(HANDLE_TABLE_ENTRY) * HandleTable.MaxCount;
HandleTable.Entries = (PHANDLE_TABLE_ENTRY) realloc(HandleTable.Entries, size);
ZeroMemory((void*) &HandleTable.Entries[HandleTable.MaxCount / 2], size / 2);
+
+ pthread_mutex_unlock(&mutex);
}
void winpr_HandleTable_Free()
{
+ pthread_mutex_lock(&mutex);
+
HandleTable.Count = 0;
HandleTable.MaxCount = 0;
free(HandleTable.Entries);
HandleTable.Entries = NULL;
+
+ pthread_mutex_unlock(&mutex);
}
HANDLE winpr_Handle_Insert(ULONG Type, PVOID Object)
HandleTable_GetInstance();
+ pthread_mutex_lock(&mutex);
+
for (index = 0; index < (int) HandleTable.MaxCount; index++)
{
if (HandleTable.Entries[index].Object == NULL)
HandleTable.Entries[index].Type = Type;
HandleTable.Entries[index].Object = Object;
+ pthread_mutex_unlock(&mutex);
+
return Object;
}
}
+ pthread_mutex_unlock(&mutex);
+
/* no available entry was found, the table needs to be grown */
winpr_HandleTable_Grow();
HandleTable_GetInstance();
+ pthread_mutex_lock(&mutex);
+
for (index = 0; index < (int) HandleTable.MaxCount; index++)
{
if (HandleTable.Entries[index].Object == handle)
HandleTable.Entries[index].Object = NULL;
HandleTable.Count--;
+ pthread_mutex_unlock(&mutex);
+
return TRUE;
}
}
+ pthread_mutex_unlock(&mutex);
+
return FALSE;
}
HandleTable_GetInstance();
+ pthread_mutex_lock(&mutex);
+
for (index = 0; index < (int) HandleTable.MaxCount; index++)
{
if (HandleTable.Entries[index].Object == handle)
+ {
+ pthread_mutex_unlock(&mutex);
return HandleTable.Entries[index].Type;
+ }
}
+ pthread_mutex_unlock(&mutex);
+
return HANDLE_TYPE_NONE;
}
HandleTable_GetInstance();
+ pthread_mutex_lock(&mutex);
+
for (index = 0; index < (int) HandleTable.MaxCount; index++)
{
if (HandleTable.Entries[index].Object == handle)
{
*pType = HandleTable.Entries[index].Type;
*pObject = HandleTable.Entries[index].Object;
+
+ pthread_mutex_unlock(&mutex);
+
return TRUE;
}
}
+ pthread_mutex_unlock(&mutex);
+
return FALSE;
}
event = (WINPR_EVENT*) malloc(sizeof(WINPR_EVENT));
- if (!event)
+ if (event)
{
event->bManualReset = bManualReset;
if (pipe(event->pipe_fd) < 0)
{
+ printf("CreateEventW: failed to create event\n");
return NULL;
}
FD_SET(event->pipe_fd[0], &rfds);
ZeroMemory(&timeout, sizeof(timeout));
- if (dwMilliseconds != INFINITE)
+ if ((dwMilliseconds != INFINITE) && (dwMilliseconds != 0))
{
timeout.tv_usec = dwMilliseconds * 1000;
}
#ifndef _WIN32
+#include <winpr/crt.h>
+
#include <pthread.h>
/**
typedef void *(*pthread_start_routine)(void*);
-HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
- LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId)
+struct winpr_thread
{
- return NULL;
+ BOOL started;
+ pthread_t thread;
+ SIZE_T dwStackSize;
+ LPVOID lpParameter;
+ pthread_mutex_t mutex;
+ LPTHREAD_START_ROUTINE lpStartAddress;
+ LPSECURITY_ATTRIBUTES lpThreadAttributes;
+};
+typedef struct winpr_thread WINPR_THREAD;
+
+void winpr_StartThread(WINPR_THREAD* thread)
+{
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (thread->dwStackSize > 0)
+ pthread_attr_setstacksize(&attr, (size_t) thread->dwStackSize);
+
+ thread->started = TRUE;
+ pthread_create(&thread->thread, &attr, (pthread_start_routine) thread->lpStartAddress, thread->lpParameter);
+
+ pthread_attr_destroy(&attr);
}
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
HANDLE handle;
- pthread_t thread;
- pthread_attr_t attr;
+ WINPR_THREAD* thread;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ thread = (WINPR_THREAD*) malloc(sizeof(WINPR_THREAD));
+ ZeroMemory(thread, sizeof(WINPR_THREAD));
- if (dwStackSize > 0)
- pthread_attr_setstacksize(&attr, (size_t) dwStackSize);
+ thread->started = FALSE;
+ thread->dwStackSize = dwStackSize;
+ thread->lpParameter = lpParameter;
+ thread->lpStartAddress = lpStartAddress;
+ thread->lpThreadAttributes = lpThreadAttributes;
- pthread_create(&thread, &attr, (pthread_start_routine) lpStartAddress, lpParameter);
+ pthread_mutex_init(&thread->mutex, 0);
handle = winpr_Handle_Insert(HANDLE_TYPE_THREAD, (void*) thread);
- pthread_attr_destroy(&attr);
+ if (!(dwCreationFlags & CREATE_SUSPENDED))
+ winpr_StartThread(thread);
return handle;
}
-VOID ExitThread(DWORD dwExitCode)
+HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
{
+ return NULL;
+}
+VOID ExitThread(DWORD dwExitCode)
+{
+ pthread_exit((void*) dwExitCode);
}
HANDLE GetCurrentThread(VOID)
DWORD ResumeThread(HANDLE hThread)
{
+ ULONG Type;
+ PVOID Object;
+ WINPR_THREAD* thread;
+
+ if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
+ return 0;
+
+ thread = (WINPR_THREAD*) Object;
+
+ pthread_mutex_lock(&thread->mutex);
+
+ if (!thread->started)
+ winpr_StartThread(thread);
+
+ pthread_mutex_unlock(&thread->mutex);
+
return 0;
}
BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode)
{
+ ULONG Type;
+ PVOID Object;
+ WINPR_THREAD* thread;
+
+ if (!winpr_Handle_GetInfo(hThread, &Type, &Object))
+ return 0;
+
+ thread = (WINPR_THREAD*) Object;
+
+ pthread_mutex_lock(&thread->mutex);
+
+ pthread_cancel(thread->thread);
+
+ pthread_mutex_unlock(&thread->mutex);
+
return TRUE;
}