static BOOL serial_check_fds(SERIAL_DEVICE* serial) { if (list_size(serial->pending_irps) == 0) return 1; serial_set_fds(serial); DEBUG_SVC("waiting %lu %lu", serial->tv.tv_sec, serial->tv.tv_usec); switch (select(serial->nfds + 1, &serial->read_fds, &serial->write_fds, NULL, &serial->tv)) { case -1: DEBUG_SVC("select has returned -1 with error: %s", strerror(errno)); return 0; case 0: if (serial->select_timeout) { __serial_check_fds(serial); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_NONE, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_READ, STATUS_TIMEOUT); serial_abort_single_io(serial, serial->timeout_id, SERIAL_ABORT_IO_WRITE, STATUS_TIMEOUT); } DEBUG_SVC("select has timed out"); return 0; default: break; } __serial_check_fds(serial); return 1; }
static void* svc_plugin_thread_func(void* arg) { rdpSvcPlugin* plugin = (rdpSvcPlugin*)arg; DEBUG_SVC("in"); IFCALL(plugin->connect_callback, plugin); while (1) { if (plugin->interval_ms > 0) freerdp_thread_wait_timeout(plugin->priv->thread, plugin->interval_ms); else freerdp_thread_wait(plugin->priv->thread); if (freerdp_thread_is_stopped(plugin->priv->thread)) break; freerdp_thread_reset(plugin->priv->thread); svc_plugin_process_data_in(plugin); if (plugin->interval_ms > 0) IFCALL(plugin->interval_callback, plugin); } freerdp_thread_quit(plugin->priv->thread); DEBUG_SVC("out"); return 0; }
static void __serial_check_fds(SERIAL_DEVICE* serial) { IRP* irp; IRP* prev; SERIAL_TTY* tty; uint32 result = 0; memset(&serial->tv, 0, sizeof(struct timeval)); tty = serial->tty; /* scan every pending */ irp = list_peek(serial->pending_irps); while (irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_READ: if (FD_ISSET(tty->fd, &serial->read_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_read(serial, irp); } break; case IRP_MJ_WRITE: if (FD_ISSET(tty->fd, &serial->write_fds)) { irp->IoStatus = STATUS_SUCCESS; serial_process_irp_write(serial, irp); } break; case IRP_MJ_DEVICE_CONTROL: if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; stream_write_uint32(irp->output, result); irp->Complete(irp); } break; default: DEBUG_SVC("no request found"); break; } prev = irp; irp = (IRP*)list_next(serial->pending_irps, irp); if (prev->IoStatus == STATUS_SUCCESS) { list_remove(serial->pending_irps, prev); wait_obj_set(serial->in_event); } } }
static void serial_abort_single_io(SERIAL_DEVICE* serial, UINT32 file_id, UINT32 abort_io, UINT32 io_status) { UINT32 major; IRP* irp = NULL; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; if(!tty) { DEBUG_WARN("tty = %p", tty); return; } switch (abort_io) { case SERIAL_ABORT_IO_NONE: major = 0; break; case SERIAL_ABORT_IO_READ: major = IRP_MJ_READ; break; case SERIAL_ABORT_IO_WRITE: major = IRP_MJ_WRITE; break; default: DEBUG_SVC("unexpected abort_io code %d", abort_io); return; } irp = (IRP*) list_peek(serial->pending_irps); while (irp) { if (irp->FileId != file_id || irp->MajorFunction != major) { irp = (IRP*) list_next(serial->pending_irps, irp); continue; } /* Process a SINGLE FileId and MajorFunction */ list_remove(serial->pending_irps, irp); irp->IoStatus = io_status; Stream_Write_UINT32(irp->output, 0); irp->Complete(irp); break; } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); }
static void parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp) { if (close(parallel->file) < 0) DEBUG_SVC("failed to close %s(%d)", parallel->path, parallel->id); else DEBUG_SVC("%s(%d) closed", parallel->path, parallel->id); stream_write_zero(irp->output, 5); /* Padding(5) */ irp->Complete(irp); }
static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else { buffer = (BYTE*) malloc(Length); if (!serial_tty_read(tty, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); } } Stream_Write_UINT32(irp->output, Length); if (Length > 0) { Stream_EnsureRemainingCapacity(irp->output, Length); Stream_Write(irp->output, buffer, Length); } free(buffer); irp->Complete(irp); }
static void serial_handle_async_irp(SERIAL_DEVICE* serial, IRP* irp) { UINT32 timeout = 0; UINT32 itv_timeout = 0; SERIAL_TTY* tty; tty = serial->tty; if(!tty) { DEBUG_WARN("tty = %p", tty); return; } switch (irp->MajorFunction) { case IRP_MJ_WRITE: DEBUG_SVC("handling IRP_MJ_WRITE"); break; case IRP_MJ_READ: DEBUG_SVC("handling IRP_MJ_READ"); serial_get_timeouts(serial, irp, &timeout, &itv_timeout); /* Check if io request timeout is smaller than current (but not 0). */ if (timeout && ((serial->select_timeout == 0) || (timeout < serial->select_timeout))) { serial->select_timeout = timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } if (itv_timeout && ((serial->select_timeout == 0) || (itv_timeout < serial->select_timeout))) { serial->select_timeout = itv_timeout; serial->tv.tv_sec = serial->select_timeout / 1000; serial->tv.tv_usec = (serial->select_timeout % 1000) * 1000; serial->timeout_id = tty->id; } DEBUG_SVC("select_timeout %u, tv_sec %lu tv_usec %lu, timeout_id %u", serial->select_timeout, serial->tv.tv_sec, serial->tv.tv_usec, serial->timeout_id); break; default: DEBUG_SVC("no need to handle %d", irp->MajorFunction); return; } irp->IoStatus = STATUS_PENDING; list_enqueue(serial->pending_irps, irp); }
static void serial_process_irp_read(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; uint32 Length; uint64 Offset; uint8* buffer = NULL; stream_read_uint32(irp->input, Length); stream_read_uint64(irp->input, Offset); DEBUG_SVC("length %u offset %llu", Length, Offset); tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("tty not valid."); } else { buffer = (uint8*)xmalloc(Length); if (!serial_tty_read(tty, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; xfree(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", serial->path, tty->id); } else { DEBUG_SVC("read %llu-%llu from %d", Offset, Offset + Length, tty->id); } } 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); }
static UINT32 drive_map_posix_err(int fs_errno) { UINT32 rc; /* try to return NTSTATUS version of error code */ switch (fs_errno) { case EPERM: case EACCES: rc = STATUS_ACCESS_DENIED; break; case ENOENT: rc = STATUS_NO_SUCH_FILE; break; case EBUSY: rc = STATUS_DEVICE_BUSY; break; case EEXIST: rc = STATUS_OBJECT_NAME_COLLISION; break; case EISDIR: rc = STATUS_FILE_IS_A_DIRECTORY; break; default: rc = STATUS_UNSUCCESSFUL; break; } DEBUG_SVC("errno 0x%x mapped to 0x%x", fs_errno, rc); return rc; }
static void drive_process_irp_set_information(DRIVE_DEVICE* disk, IRP* irp) { DRIVE_FILE* file; UINT32 FsInformationClass; UINT32 Length; stream_read_UINT32(irp->input, FsInformationClass); stream_read_UINT32(irp->input, Length); stream_seek(irp->input, 24); /* Padding */ file = drive_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input)) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("FsInformationClass %d on %s(%d) failed.", FsInformationClass, file->fullpath, file->id); } else { DEBUG_SVC("FsInformationClass %d on %s(%d) ok.", FsInformationClass, file->fullpath, file->id); } stream_write_UINT32(irp->output, Length); irp->Complete(irp); }
static void serial_set_fds(SERIAL_DEVICE* serial) { fd_set* fds; IRP* irp; SERIAL_TTY* tty; DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); tty = serial->tty; irp = (IRP*)list_peek(serial->pending_irps); while (irp) { fds = NULL; switch (irp->MajorFunction) { case IRP_MJ_WRITE: fds = &serial->write_fds; break; case IRP_MJ_READ: fds = &serial->read_fds; break; } if (fds && (tty->fd >= 0)) { FD_SET(tty->fd, fds); serial->nfds = MAX(serial->nfds, tty->fd); } irp = (IRP*)list_next(serial->pending_irps, irp); } }
static void svc_plugin_init_event(void* pInitHandle, UINT32 event, void* pData, UINT32 dataLength) { rdpSvcPlugin* plugin; DEBUG_SVC("event %d", event); plugin = (rdpSvcPlugin*) svc_plugin_find_by_init_handle(pInitHandle); if (!plugin) { fprintf(stderr, "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; } }
static void svc_plugin_open_event(UINT32 openHandle, UINT32 event, void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpSvcPlugin* plugin; 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); if (!plugin) { fprintf(stderr, "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((wStream*) pData); break; case CHANNEL_EVENT_USER: svc_plugin_process_event(plugin, (wMessage*) pData); break; } }
static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) { UINT32 Length; UINT64 Offset; rdpPrintJob* printjob = NULL; stream_read_UINT32(irp->input, Length); stream_read_UINT64(irp->input, Offset); stream_seek(irp->input, 20); /* Padding */ if (printer_dev->printer != NULL) printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (printjob == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("printjob id %d not found.", irp->FileId); } else { printjob->Write(printjob, stream_get_tail(irp->input), Length); DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length); } stream_write_UINT32(irp->output, Length); stream_write_BYTE(irp->output, 0); /* Padding */ irp->Complete(irp); }
static VOID VCAPITYPE svc_plugin_open_event(DWORD openHandle, UINT event, LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) { rdpSvcPlugin* plugin; DEBUG_SVC("openHandle %d event %d dataLength %d totalLength %d dataFlags %d", openHandle, event, dataLength, totalLength, dataFlags); plugin = (rdpSvcPlugin*) svc_plugin_get_open_handle_data(openHandle); if (!plugin) { fprintf(stderr, "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((wStream*) pData, TRUE); break; case CHANNEL_EVENT_USER: svc_plugin_process_event(plugin, (wMessage*) pData); break; } }
static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) { DEBUG_SVC("server closes."); if (rdpsnd->device) IFCALL(rdpsnd->device->Close, rdpsnd->device); rdpsnd->is_open = false; }
static void serial_free(DEVICE* device) { SERIAL_DEVICE* serial = (SERIAL_DEVICE*) device; DEBUG_SVC("freeing device"); /* Stop thread */ SetEvent(serial->stopEvent); if(serial->mthread) { TerminateThread(serial->mthread, 0); WaitForSingleObject(serial->mthread, INFINITE); CloseHandle(serial->mthread); } WaitForSingleObject(serial->thread, INFINITE); serial_tty_free(serial->tty); /* Clean up resources */ Stream_Free(serial->device.data, TRUE); Queue_Free(serial->queue); list_free(serial->pending_irps); CloseHandle(serial->stopEvent); CloseHandle(serial->newEvent); CloseHandle(serial->thread); free(serial); }
static void serial_process_irp_close(SERIAL_DEVICE* serial, IRP* irp) { SERIAL_TTY* tty; tty = serial->tty; if (tty == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; DEBUG_WARN("tty not valid."); } else { DEBUG_SVC("%s(%d) closed.", serial->path, tty->id); TerminateThread(serial->mthread, 0); WaitForSingleObject(serial->mthread, INFINITE); CloseHandle(serial->mthread); serial->mthread = NULL; serial_tty_free(tty); serial->tty = NULL; } Stream_Zero(irp->output, 5); /* Padding(5) */ irp->Complete(irp); }
static VOID VCAPITYPE svc_plugin_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength) { rdpSvcPlugin* plugin; DEBUG_SVC("event %d", event); plugin = (rdpSvcPlugin*) svc_plugin_get_init_handle_data(pInitHandle); if (!plugin) { fprintf(stderr, "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; } }
static void rdpsnd_process_message_wave_info(rdpsndPlugin* rdpsnd, STREAM* data_in, uint16 BodySize) { uint16 wFormatNo; stream_read_uint16(data_in, rdpsnd->wTimeStamp); stream_read_uint16(data_in, wFormatNo); stream_read_uint8(data_in, rdpsnd->cBlockNo); stream_seek(data_in, 3); /* bPad */ stream_read(data_in, rdpsnd->waveData, 4); rdpsnd->waveDataSize = BodySize - 8; rdpsnd->wave_timestamp = get_mstime(); rdpsnd->expectingWave = true; DEBUG_SVC("waveDataSize %d wFormatNo %d", rdpsnd->waveDataSize, wFormatNo); rdpsnd->close_timestamp = 0; if (!rdpsnd->is_open) { rdpsnd->current_format = wFormatNo; rdpsnd->is_open = true; if (rdpsnd->device) IFCALL(rdpsnd->device->Open, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], rdpsnd->latency); } else if (wFormatNo != rdpsnd->current_format) { rdpsnd->current_format = wFormatNo; if (rdpsnd->device) IFCALL(rdpsnd->device->SetFormat, rdpsnd->device, &rdpsnd->supported_formats[wFormatNo], rdpsnd->latency); } }
static void parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) { DEBUG_SVC("MajorFunction %u", irp->MajorFunction); switch (irp->MajorFunction) { case IRP_MJ_CREATE: parallel_process_irp_create(parallel, irp); break; case IRP_MJ_CLOSE: parallel_process_irp_close(parallel, irp); break; case IRP_MJ_READ: parallel_process_irp_read(parallel, irp); break; case IRP_MJ_WRITE: parallel_process_irp_write(parallel, irp); break; case IRP_MJ_DEVICE_CONTROL: parallel_process_irp_device_control(parallel, irp); break; default: DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction); irp->IoStatus = STATUS_NOT_SUPPORTED; irp->Complete(irp); break; } }
static void devman_register_device(DEVMAN* devman, DEVICE* device) { device->id = devman->id_sequence++; list_add(devman->devices, device); DEBUG_SVC("device %d.%s registered", device->id, device->name); }
static void cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, STREAM* data_in) { uint16 cCapabilitiesSets; stream_read_uint16(data_in, cCapabilitiesSets); DEBUG_SVC("cCapabilitiesSets %d", cCapabilitiesSets); }
static void svc_plugin_open_event(uint32 openHandle, uint32 event, void* pData, uint32 dataLength, uint32 totalLength, uint32 dataFlags) { rdpSvcPlugin* plugin; 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); 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); break; case CHANNEL_EVENT_USER: svc_plugin_process_event(plugin, (RDP_EVENT*)pData); break; } }
static void rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, STREAM* data_in) { stream_read_UINT16(data_in, rdpdr->versionMajor); stream_read_UINT16(data_in, rdpdr->versionMinor); stream_read_UINT32(data_in, rdpdr->clientID); DEBUG_SVC("version %d.%d clientID %d", rdpdr->versionMajor, rdpdr->versionMinor, rdpdr->clientID); }
static void irp_free(IRP* irp) { DEBUG_SVC("DeviceId %d FileId %d CompletionId %d", irp->device->id, irp->FileId, irp->CompletionId); stream_free(irp->input); stream_free(irp->output); xfree(irp); }
static void rdpsnd_process_message_close(rdpsndPlugin* rdpsnd) { DEBUG_SVC("server closes."); if (rdpsnd->device) IFCALL(rdpsnd->device->Start, rdpsnd->device); rdpsnd->close_timestamp = get_mstime() + 2000; rdpsnd->plugin.interval_ms = 10; }
static void rdpsnd_process_message_setvolume(rdpsndPlugin* rdpsnd, STREAM* data_in) { uint32 dwVolume; stream_read_uint32(data_in, dwVolume); DEBUG_SVC("dwVolume 0x%X", dwVolume); if (rdpsnd->device) IFCALL(rdpsnd->device->SetVolume, rdpsnd->device, dwVolume); }
static void serial_check_for_events(SERIAL_DEVICE* serial) { IRP* irp = NULL; IRP* prev; UINT32 result = 0; SERIAL_TTY* tty; tty = serial->tty; if(!tty) { DEBUG_WARN("tty = %p", tty); return; } DEBUG_SVC("[in] pending size %d", list_size(serial->pending_irps)); irp = (IRP*) list_peek(serial->pending_irps); while (irp) { prev = NULL; if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL) { if (serial_tty_get_event(tty, &result)) { DEBUG_SVC("got event result %u", result); irp->IoStatus = STATUS_SUCCESS; Stream_Write_UINT32(irp->output, result); irp->Complete(irp); prev = irp; irp = (IRP*) list_next(serial->pending_irps, irp); list_remove(serial->pending_irps, prev); } } if (!prev) irp = (IRP*) list_next(serial->pending_irps, irp); } DEBUG_SVC("[out] pending size %d", list_size(serial->pending_irps)); }
static void drive_process_irp_read(DRIVE_DEVICE* disk, IRP* irp) { DRIVE_FILE* file; UINT32 Length; UINT64 Offset; BYTE* buffer = NULL; stream_read_UINT32(irp->input, Length); stream_read_UINT64(irp->input, Offset); file = drive_get_file_by_id(disk, irp->FileId); if (file == NULL) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("FileId %d not valid.", irp->FileId); } else if (!drive_file_seek(file, Offset)) { irp->IoStatus = STATUS_UNSUCCESSFUL; Length = 0; DEBUG_WARN("seek %s(%d) failed.", file->fullpath, file->id); } else { buffer = (BYTE*) malloc(Length); if (!drive_file_read(file, buffer, &Length)) { irp->IoStatus = STATUS_UNSUCCESSFUL; free(buffer); buffer = NULL; Length = 0; DEBUG_WARN("read %s(%d) failed.", file->fullpath, file->id); } else { DEBUG_SVC("read %llu-%llu from %s(%d).", Offset, Offset + Length, file->fullpath, file->id); } } stream_write_UINT32(irp->output, Length); if (Length > 0) { stream_check_size(irp->output, (int) Length); stream_write(irp->output, buffer, Length); } free(buffer); irp->Complete(irp); }