20#include <winpr/cast.h>
22#include <freerdp/config.h>
24#include <freerdp/freerdp.h>
25#include <freerdp/channels/log.h>
26#include <freerdp/server/rdpecam.h>
28#define TAG CHANNELS_TAG("rdpecam.server")
32 CAMERA_DEVICE_INITIAL,
34} eCameraDeviceChannelState;
38 CameraDeviceServerContext context;
51 eCameraDeviceChannelState state;
56static UINT device_server_initialize(CameraDeviceServerContext* context, BOOL externalThread)
58 UINT error = CHANNEL_RC_OK;
59 device_server* device = (device_server*)context;
65 WLog_WARN(TAG,
"Application error: Camera channel already initialized, "
66 "calling in this state is not possible!");
67 return ERROR_INVALID_STATE;
70 device->externalThread = externalThread;
75static UINT device_server_open_channel(device_server* device)
77 CameraDeviceServerContext* context = &device->context;
78 DWORD Error = ERROR_SUCCESS;
80 DWORD BytesReturned = 0;
81 PULONG pSessionId = NULL;
87 if (WTSQuerySessionInformationA(device->context.vcm, WTS_CURRENT_SESSION, WTSSessionId,
88 (LPSTR*)&pSessionId, &BytesReturned) == FALSE)
90 WLog_ERR(TAG,
"WTSQuerySessionInformationA failed!");
91 return ERROR_INTERNAL_ERROR;
94 device->SessionId = (DWORD)*pSessionId;
95 WTSFreeMemory(pSessionId);
96 hEvent = WTSVirtualChannelManagerGetEventHandle(device->context.vcm);
98 if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED)
100 Error = GetLastError();
101 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", Error);
105 device->device_channel = WTSVirtualChannelOpenEx(device->SessionId, context->virtualChannelName,
106 WTS_CHANNEL_OPTION_DYNAMIC);
107 if (!device->device_channel)
109 Error = GetLastError();
110 WLog_ERR(TAG,
"WTSVirtualChannelOpenEx failed with error %" PRIu32
"!", Error);
114 channelId = WTSChannelGetIdByHandle(device->device_channel);
116 IFCALLRET(context->ChannelIdAssigned, status, context, channelId);
119 WLog_ERR(TAG,
"context->ChannelIdAssigned failed!");
120 return ERROR_INTERNAL_ERROR;
126static UINT device_server_handle_success_response(CameraDeviceServerContext* context,
131 UINT error = CHANNEL_RC_OK;
133 WINPR_ASSERT(context);
134 WINPR_ASSERT(header);
136 pdu.Header = *header;
138 IFCALLRET(context->SuccessResponse, error, context, &pdu);
140 WLog_ERR(TAG,
"context->SuccessResponse failed with error %" PRIu32
"", error);
145static UINT device_server_recv_error_response(CameraDeviceServerContext* context,
wStream* s,
149 UINT error = CHANNEL_RC_OK;
151 WINPR_ASSERT(context);
152 WINPR_ASSERT(header);
154 pdu.Header = *header;
156 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
157 return ERROR_NO_DATA;
159 Stream_Read_UINT32(s, pdu.ErrorCode);
161 IFCALLRET(context->ErrorResponse, error, context, &pdu);
163 WLog_ERR(TAG,
"context->ErrorResponse failed with error %" PRIu32
"", error);
168static UINT device_server_recv_stream_list_response(CameraDeviceServerContext* context,
wStream* s,
172 UINT error = CHANNEL_RC_OK;
174 WINPR_ASSERT(context);
175 WINPR_ASSERT(header);
177 pdu.Header = *header;
179 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
180 return ERROR_NO_DATA;
182 pdu.N_Descriptions = 255;
183 const size_t len = Stream_GetRemainingLength(s) / 5;
185 pdu.N_Descriptions = (BYTE)len;
187 for (BYTE i = 0; i < pdu.N_Descriptions; ++i)
191 Stream_Read_UINT16(s, StreamDescription->FrameSourceTypes);
192 Stream_Read_UINT8(s, StreamDescription->StreamCategory);
193 Stream_Read_UINT8(s, StreamDescription->Selected);
194 Stream_Read_UINT8(s, StreamDescription->CanBeShared);
197 IFCALLRET(context->StreamListResponse, error, context, &pdu);
199 WLog_ERR(TAG,
"context->StreamListResponse failed with error %" PRIu32
"", error);
204static UINT device_server_recv_media_type_list_response(CameraDeviceServerContext* context,
209 UINT error = CHANNEL_RC_OK;
211 WINPR_ASSERT(context);
212 WINPR_ASSERT(header);
214 pdu.Header = *header;
216 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
217 return ERROR_NO_DATA;
219 pdu.N_Descriptions = Stream_GetRemainingLength(s) / 26;
222 if (!pdu.MediaTypeDescriptions)
224 WLog_ERR(TAG,
"Failed to allocate %zu CAM_MEDIA_TYPE_DESCRIPTION structs",
226 return ERROR_NOT_ENOUGH_MEMORY;
229 for (
size_t i = 0; i < pdu.N_Descriptions; ++i)
233 Stream_Read_UINT8(s, MediaTypeDescriptions->Format);
234 Stream_Read_UINT32(s, MediaTypeDescriptions->Width);
235 Stream_Read_UINT32(s, MediaTypeDescriptions->Height);
236 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateNumerator);
237 Stream_Read_UINT32(s, MediaTypeDescriptions->FrameRateDenominator);
238 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioNumerator);
239 Stream_Read_UINT32(s, MediaTypeDescriptions->PixelAspectRatioDenominator);
240 Stream_Read_UINT8(s, MediaTypeDescriptions->Flags);
243 IFCALLRET(context->MediaTypeListResponse, error, context, &pdu);
245 WLog_ERR(TAG,
"context->MediaTypeListResponse failed with error %" PRIu32
"", error);
247 free(pdu.MediaTypeDescriptions);
252static UINT device_server_recv_current_media_type_response(CameraDeviceServerContext* context,
257 UINT error = CHANNEL_RC_OK;
259 WINPR_ASSERT(context);
260 WINPR_ASSERT(header);
262 pdu.Header = *header;
264 if (!Stream_CheckAndLogRequiredLength(TAG, s, 26))
265 return ERROR_NO_DATA;
267 Stream_Read_UINT8(s, pdu.MediaTypeDescription.Format);
268 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Width);
269 Stream_Read_UINT32(s, pdu.MediaTypeDescription.Height);
270 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateNumerator);
271 Stream_Read_UINT32(s, pdu.MediaTypeDescription.FrameRateDenominator);
272 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioNumerator);
273 Stream_Read_UINT32(s, pdu.MediaTypeDescription.PixelAspectRatioDenominator);
274 Stream_Read_UINT8(s, pdu.MediaTypeDescription.Flags);
276 IFCALLRET(context->CurrentMediaTypeResponse, error, context, &pdu);
278 WLog_ERR(TAG,
"context->CurrentMediaTypeResponse failed with error %" PRIu32
"", error);
283static UINT device_server_recv_sample_response(CameraDeviceServerContext* context,
wStream* s,
287 UINT error = CHANNEL_RC_OK;
289 WINPR_ASSERT(context);
290 WINPR_ASSERT(header);
292 pdu.Header = *header;
294 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
295 return ERROR_NO_DATA;
297 Stream_Read_UINT8(s, pdu.StreamIndex);
299 pdu.SampleSize = Stream_GetRemainingLength(s);
300 pdu.Sample = Stream_Pointer(s);
302 IFCALLRET(context->SampleResponse, error, context, &pdu);
304 WLog_ERR(TAG,
"context->SampleResponse failed with error %" PRIu32
"", error);
309static UINT device_server_recv_sample_error_response(CameraDeviceServerContext* context,
wStream* s,
313 UINT error = CHANNEL_RC_OK;
315 WINPR_ASSERT(context);
316 WINPR_ASSERT(header);
318 pdu.Header = *header;
320 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
321 return ERROR_NO_DATA;
323 Stream_Read_UINT8(s, pdu.StreamIndex);
324 Stream_Read_UINT32(s, pdu.ErrorCode);
326 IFCALLRET(context->SampleErrorResponse, error, context, &pdu);
328 WLog_ERR(TAG,
"context->SampleErrorResponse failed with error %" PRIu32
"", error);
333static UINT device_server_recv_property_list_response(CameraDeviceServerContext* context,
338 UINT error = CHANNEL_RC_OK;
340 WINPR_ASSERT(context);
341 WINPR_ASSERT(header);
343 pdu.Header = *header;
345 pdu.N_Properties = Stream_GetRemainingLength(s) / 19;
347 if (pdu.N_Properties > 0)
352 WLog_ERR(TAG,
"Failed to allocate %zu CAM_PROPERTY_DESCRIPTION structs",
354 return ERROR_NOT_ENOUGH_MEMORY;
357 for (
size_t i = 0; i < pdu.N_Properties; ++i)
359 Stream_Read_UINT8(s, pdu.Properties[i].PropertySet);
360 Stream_Read_UINT8(s, pdu.Properties[i].PropertyId);
361 Stream_Read_UINT8(s, pdu.Properties[i].Capabilities);
362 Stream_Read_INT32(s, pdu.Properties[i].MinValue);
363 Stream_Read_INT32(s, pdu.Properties[i].MaxValue);
364 Stream_Read_INT32(s, pdu.Properties[i].Step);
365 Stream_Read_INT32(s, pdu.Properties[i].DefaultValue);
369 IFCALLRET(context->PropertyListResponse, error, context, &pdu);
371 WLog_ERR(TAG,
"context->PropertyListResponse failed with error %" PRIu32
"", error);
373 free(pdu.Properties);
378static UINT device_server_recv_property_value_response(CameraDeviceServerContext* context,
383 UINT error = CHANNEL_RC_OK;
385 WINPR_ASSERT(context);
386 WINPR_ASSERT(header);
388 pdu.Header = *header;
390 if (!Stream_CheckAndLogRequiredLength(TAG, s, 5))
391 return ERROR_NO_DATA;
393 Stream_Read_UINT8(s, pdu.PropertyValue.Mode);
394 Stream_Read_INT32(s, pdu.PropertyValue.Value);
396 IFCALLRET(context->PropertyValueResponse, error, context, &pdu);
398 WLog_ERR(TAG,
"context->PropertyValueResponse failed with error %" PRIu32
"", error);
403static UINT device_process_message(device_server* device)
406 UINT error = ERROR_INTERNAL_ERROR;
407 ULONG BytesReturned = 0;
411 WINPR_ASSERT(device);
412 WINPR_ASSERT(device->device_channel);
417 Stream_SetPosition(s, 0);
418 rc = WTSVirtualChannelRead(device->device_channel, 0, NULL, 0, &BytesReturned);
422 if (BytesReturned < 1)
424 error = CHANNEL_RC_OK;
428 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
430 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
431 error = CHANNEL_RC_NO_MEMORY;
435 if (WTSVirtualChannelRead(device->device_channel, 0, Stream_BufferAs(s,
char),
436 (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
438 WLog_ERR(TAG,
"WTSVirtualChannelRead failed!");
442 Stream_SetLength(s, BytesReturned);
443 if (!Stream_CheckAndLogRequiredLength(TAG, s, CAM_HEADER_SIZE))
444 return ERROR_NO_DATA;
446 Stream_Read_UINT8(s, header.Version);
447 Stream_Read_UINT8(s, header.MessageId);
449 switch (header.MessageId)
451 case CAM_MSG_ID_SuccessResponse:
452 error = device_server_handle_success_response(&device->context, s, &header);
454 case CAM_MSG_ID_ErrorResponse:
455 error = device_server_recv_error_response(&device->context, s, &header);
457 case CAM_MSG_ID_StreamListResponse:
458 error = device_server_recv_stream_list_response(&device->context, s, &header);
460 case CAM_MSG_ID_MediaTypeListResponse:
461 error = device_server_recv_media_type_list_response(&device->context, s, &header);
463 case CAM_MSG_ID_CurrentMediaTypeResponse:
464 error = device_server_recv_current_media_type_response(&device->context, s, &header);
466 case CAM_MSG_ID_SampleResponse:
467 error = device_server_recv_sample_response(&device->context, s, &header);
469 case CAM_MSG_ID_SampleErrorResponse:
470 error = device_server_recv_sample_error_response(&device->context, s, &header);
472 case CAM_MSG_ID_PropertyListResponse:
473 error = device_server_recv_property_list_response(&device->context, s, &header);
475 case CAM_MSG_ID_PropertyValueResponse:
476 error = device_server_recv_property_value_response(&device->context, s, &header);
479 WLog_ERR(TAG,
"device_process_message: unknown or invalid MessageId %" PRIu8
"",
486 WLog_ERR(TAG,
"Response failed with error %" PRIu32
"!", error);
491static UINT device_server_context_poll_int(CameraDeviceServerContext* context)
493 device_server* device = (device_server*)context;
494 UINT error = ERROR_INTERNAL_ERROR;
496 WINPR_ASSERT(device);
498 switch (device->state)
500 case CAMERA_DEVICE_INITIAL:
501 error = device_server_open_channel(device);
503 WLog_ERR(TAG,
"device_server_open_channel failed with error %" PRIu32
"!", error);
505 device->state = CAMERA_DEVICE_OPENED;
507 case CAMERA_DEVICE_OPENED:
508 error = device_process_message(device);
517static HANDLE device_server_get_channel_handle(device_server* device)
520 DWORD BytesReturned = 0;
521 HANDLE ChannelEvent = NULL;
523 WINPR_ASSERT(device);
525 if (WTSVirtualChannelQuery(device->device_channel, WTSVirtualEventHandle, &buffer,
526 &BytesReturned) == TRUE)
528 if (BytesReturned ==
sizeof(HANDLE))
529 ChannelEvent = *(HANDLE*)buffer;
531 WTSFreeMemory(buffer);
537static DWORD WINAPI device_server_thread_func(LPVOID arg)
540 HANDLE events[2] = { 0 };
541 device_server* device = (device_server*)arg;
542 UINT error = CHANNEL_RC_OK;
545 WINPR_ASSERT(device);
548 events[nCount++] = device->stopEvent;
550 while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
552 switch (device->state)
554 case CAMERA_DEVICE_INITIAL:
555 error = device_server_context_poll_int(&device->context);
556 if (error == CHANNEL_RC_OK)
558 events[1] = device_server_get_channel_handle(device);
562 case CAMERA_DEVICE_OPENED:
563 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
568 case WAIT_OBJECT_0 + 1:
570 error = device_server_context_poll_int(&device->context);
575 error = ERROR_INTERNAL_ERROR;
584 (void)WTSVirtualChannelClose(device->device_channel);
585 device->device_channel = NULL;
587 if (error && device->context.rdpcontext)
588 setChannelError(device->context.rdpcontext, error,
589 "device_server_thread_func reported an error");
595static UINT device_server_open(CameraDeviceServerContext* context)
597 device_server* device = (device_server*)context;
599 WINPR_ASSERT(device);
601 if (!device->externalThread && (device->thread == NULL))
603 device->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
604 if (!device->stopEvent)
606 WLog_ERR(TAG,
"CreateEvent failed!");
607 return ERROR_INTERNAL_ERROR;
610 device->thread = CreateThread(NULL, 0, device_server_thread_func, device, 0, NULL);
613 WLog_ERR(TAG,
"CreateThread failed!");
614 (void)CloseHandle(device->stopEvent);
615 device->stopEvent = NULL;
616 return ERROR_INTERNAL_ERROR;
619 device->isOpened = TRUE;
621 return CHANNEL_RC_OK;
624static UINT device_server_close(CameraDeviceServerContext* context)
626 UINT error = CHANNEL_RC_OK;
627 device_server* device = (device_server*)context;
629 WINPR_ASSERT(device);
631 if (!device->externalThread && device->thread)
633 (void)SetEvent(device->stopEvent);
635 if (WaitForSingleObject(device->thread, INFINITE) == WAIT_FAILED)
637 error = GetLastError();
638 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", error);
642 (void)CloseHandle(device->thread);
643 (void)CloseHandle(device->stopEvent);
644 device->thread = NULL;
645 device->stopEvent = NULL;
647 if (device->externalThread)
649 if (device->state != CAMERA_DEVICE_INITIAL)
651 (void)WTSVirtualChannelClose(device->device_channel);
652 device->device_channel = NULL;
653 device->state = CAMERA_DEVICE_INITIAL;
656 device->isOpened = FALSE;
661static UINT device_server_context_poll(CameraDeviceServerContext* context)
663 device_server* device = (device_server*)context;
665 WINPR_ASSERT(device);
667 if (!device->externalThread)
668 return ERROR_INTERNAL_ERROR;
670 return device_server_context_poll_int(context);
673static BOOL device_server_context_handle(CameraDeviceServerContext* context, HANDLE* handle)
675 device_server* device = (device_server*)context;
677 WINPR_ASSERT(device);
678 WINPR_ASSERT(handle);
680 if (!device->externalThread)
682 if (device->state == CAMERA_DEVICE_INITIAL)
685 *handle = device_server_get_channel_handle(device);
690static wStream* device_server_packet_new(
size_t size, BYTE version, BYTE messageId)
695 s = Stream_New(NULL, size + CAM_HEADER_SIZE);
698 WLog_ERR(TAG,
"Stream_New failed!");
702 Stream_Write_UINT8(s, version);
703 Stream_Write_UINT8(s, messageId);
708static UINT device_server_packet_send(CameraDeviceServerContext* context,
wStream* s)
710 device_server* device = (device_server*)context;
711 UINT error = CHANNEL_RC_OK;
714 WINPR_ASSERT(context);
717 const size_t len = Stream_GetPosition(s);
718 WINPR_ASSERT(len <= UINT32_MAX);
719 if (!WTSVirtualChannelWrite(device->device_channel, Stream_BufferAs(s,
char), (UINT32)len,
722 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
723 error = ERROR_INTERNAL_ERROR;
727 if (written < Stream_GetPosition(s))
729 WLog_WARN(TAG,
"Unexpected bytes written: %" PRIu32
"/%" PRIuz
"", written,
730 Stream_GetPosition(s));
734 Stream_Free(s, TRUE);
738static UINT device_server_write_and_send_header(CameraDeviceServerContext* context, BYTE messageId)
742 WINPR_ASSERT(context);
744 s = device_server_packet_new(0, context->protocolVersion, messageId);
746 return ERROR_NOT_ENOUGH_MEMORY;
748 return device_server_packet_send(context, s);
751static UINT device_send_activate_device_request_pdu(
752 CameraDeviceServerContext* context,
755 WINPR_ASSERT(context);
757 return device_server_write_and_send_header(context, CAM_MSG_ID_ActivateDeviceRequest);
760static UINT device_send_deactivate_device_request_pdu(
761 CameraDeviceServerContext* context,
764 WINPR_ASSERT(context);
766 return device_server_write_and_send_header(context, CAM_MSG_ID_DeactivateDeviceRequest);
769static UINT device_send_stream_list_request_pdu(
770 CameraDeviceServerContext* context,
773 WINPR_ASSERT(context);
775 return device_server_write_and_send_header(context, CAM_MSG_ID_StreamListRequest);
779device_send_media_type_list_request_pdu(CameraDeviceServerContext* context,
784 WINPR_ASSERT(context);
785 WINPR_ASSERT(mediaTypeListRequest);
787 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_MediaTypeListRequest);
789 return ERROR_NOT_ENOUGH_MEMORY;
791 Stream_Write_UINT8(s, mediaTypeListRequest->StreamIndex);
793 return device_server_packet_send(context, s);
796static UINT device_send_current_media_type_request_pdu(
797 CameraDeviceServerContext* context,
802 WINPR_ASSERT(context);
803 WINPR_ASSERT(currentMediaTypeRequest);
805 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_CurrentMediaTypeRequest);
807 return ERROR_NOT_ENOUGH_MEMORY;
809 Stream_Write_UINT8(s, currentMediaTypeRequest->StreamIndex);
811 return device_server_packet_send(context, s);
815device_send_start_streams_request_pdu(CameraDeviceServerContext* context,
820 WINPR_ASSERT(context);
821 WINPR_ASSERT(startStreamsRequest);
823 s = device_server_packet_new(startStreamsRequest->N_Infos * 27ul, context->protocolVersion,
824 CAM_MSG_ID_StartStreamsRequest);
826 return ERROR_NOT_ENOUGH_MEMORY;
828 for (
size_t i = 0; i < startStreamsRequest->N_Infos; ++i)
833 Stream_Write_UINT8(s, info->StreamIndex);
835 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Format));
836 Stream_Write_UINT32(s, description->Width);
837 Stream_Write_UINT32(s, description->Height);
838 Stream_Write_UINT32(s, description->FrameRateNumerator);
839 Stream_Write_UINT32(s, description->FrameRateDenominator);
840 Stream_Write_UINT32(s, description->PixelAspectRatioNumerator);
841 Stream_Write_UINT32(s, description->PixelAspectRatioDenominator);
842 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, description->Flags));
845 return device_server_packet_send(context, s);
848static UINT device_send_stop_streams_request_pdu(
849 CameraDeviceServerContext* context,
852 WINPR_ASSERT(context);
854 return device_server_write_and_send_header(context, CAM_MSG_ID_StopStreamsRequest);
857static UINT device_send_sample_request_pdu(CameraDeviceServerContext* context,
862 WINPR_ASSERT(context);
863 WINPR_ASSERT(sampleRequest);
865 s = device_server_packet_new(1, context->protocolVersion, CAM_MSG_ID_SampleRequest);
867 return ERROR_NOT_ENOUGH_MEMORY;
869 Stream_Write_UINT8(s, sampleRequest->StreamIndex);
871 return device_server_packet_send(context, s);
874static UINT device_send_property_list_request_pdu(
875 CameraDeviceServerContext* context,
878 WINPR_ASSERT(context);
880 return device_server_write_and_send_header(context, CAM_MSG_ID_PropertyListRequest);
884device_send_property_value_request_pdu(CameraDeviceServerContext* context,
889 WINPR_ASSERT(context);
890 WINPR_ASSERT(propertyValueRequest);
892 s = device_server_packet_new(2, context->protocolVersion, CAM_MSG_ID_PropertyValueRequest);
894 return ERROR_NOT_ENOUGH_MEMORY;
896 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, propertyValueRequest->PropertySet));
897 Stream_Write_UINT8(s, propertyValueRequest->PropertyId);
899 return device_server_packet_send(context, s);
902static UINT device_send_set_property_value_request_pdu(
903 CameraDeviceServerContext* context,
908 WINPR_ASSERT(context);
909 WINPR_ASSERT(setPropertyValueRequest);
911 s = device_server_packet_new(2 + 5, context->protocolVersion,
912 CAM_MSG_ID_SetPropertyValueRequest);
914 return ERROR_NOT_ENOUGH_MEMORY;
916 Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertySet));
917 Stream_Write_UINT8(s, setPropertyValueRequest->PropertyId);
920 s, WINPR_ASSERTING_INT_CAST(uint8_t, setPropertyValueRequest->PropertyValue.Mode));
921 Stream_Write_INT32(s, setPropertyValueRequest->PropertyValue.Value);
923 return device_server_packet_send(context, s);
926CameraDeviceServerContext* camera_device_server_context_new(HANDLE vcm)
928 device_server* device = (device_server*)calloc(1,
sizeof(device_server));
933 device->context.vcm = vcm;
934 device->context.Initialize = device_server_initialize;
935 device->context.Open = device_server_open;
936 device->context.Close = device_server_close;
937 device->context.Poll = device_server_context_poll;
938 device->context.ChannelHandle = device_server_context_handle;
940 device->context.ActivateDeviceRequest = device_send_activate_device_request_pdu;
941 device->context.DeactivateDeviceRequest = device_send_deactivate_device_request_pdu;
943 device->context.StreamListRequest = device_send_stream_list_request_pdu;
944 device->context.MediaTypeListRequest = device_send_media_type_list_request_pdu;
945 device->context.CurrentMediaTypeRequest = device_send_current_media_type_request_pdu;
947 device->context.StartStreamsRequest = device_send_start_streams_request_pdu;
948 device->context.StopStreamsRequest = device_send_stop_streams_request_pdu;
949 device->context.SampleRequest = device_send_sample_request_pdu;
951 device->context.PropertyListRequest = device_send_property_list_request_pdu;
952 device->context.PropertyValueRequest = device_send_property_value_request_pdu;
953 device->context.SetPropertyValueRequest = device_send_set_property_value_request_pdu;
955 device->buffer = Stream_New(NULL, 4096);
959 return &device->context;
961 WINPR_PRAGMA_DIAG_PUSH
962 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
963 camera_device_server_context_free(&device->context);
964 WINPR_PRAGMA_DIAG_POP
968void camera_device_server_context_free(CameraDeviceServerContext* context)
970 device_server* device = (device_server*)context;
974 device_server_close(context);
975 Stream_Free(device->buffer, TRUE);
978 free(context->virtualChannelName);