mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
shadow: improve DXGI 1.2 error checking
This commit is contained in:
parent
eae6efd23f
commit
c45ddc783e
@ -55,6 +55,7 @@ typedef int (*pfnShadowSubsystemStop)(rdpShadowSubsystem* subsystem);
|
||||
typedef void (*pfnShadowSubsystemFree)(rdpShadowSubsystem* subsystem);
|
||||
|
||||
typedef int (*pfnShadowSurfaceCopy)(rdpShadowSubsystem* subsystem);
|
||||
typedef int (*pfnShadowSurfaceUpdate)(rdpShadowSubsystem* subsystem, REGION16* region);
|
||||
|
||||
typedef int (*pfnShadowSynchronizeEvent)(rdpShadowSubsystem* subsystem, UINT32 flags);
|
||||
typedef int (*pfnShadowKeyboardEvent)(rdpShadowSubsystem* subsystem, UINT16 flags, UINT16 code);
|
||||
@ -72,8 +73,11 @@ struct rdp_shadow_client
|
||||
BOOL mayView;
|
||||
BOOL mayInteract;
|
||||
HANDLE StopEvent;
|
||||
CRITICAL_SECTION lock;
|
||||
REGION16 invalidRegion;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* lobby;
|
||||
rdpShadowEncoder* encoder;
|
||||
|
||||
HANDLE vcm;
|
||||
EncomspServerContext* encomsp;
|
||||
@ -85,15 +89,18 @@ struct rdp_shadow_server
|
||||
void* ext;
|
||||
HANDLE thread;
|
||||
HANDLE StopEvent;
|
||||
wArrayList* clients;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowEncoder* encoder;
|
||||
rdpShadowSubsystem* subsystem;
|
||||
|
||||
DWORD port;
|
||||
BOOL mayView;
|
||||
BOOL mayInteract;
|
||||
char* ConfigPath;
|
||||
char* CertificateFile;
|
||||
char* PrivateKeyFile;
|
||||
CRITICAL_SECTION lock;
|
||||
freerdp_listener* listener;
|
||||
pfnShadowCreateSubsystem CreateSubsystem;
|
||||
};
|
||||
@ -103,6 +110,7 @@ struct rdp_shadow_server
|
||||
int monitorCount; \
|
||||
MONITOR_DEF monitors[16]; \
|
||||
MONITOR_DEF virtualScreen; \
|
||||
REGION16 invalidRegion; \
|
||||
\
|
||||
pfnShadowSubsystemInit Init; \
|
||||
pfnShadowSubsystemUninit Uninit; \
|
||||
@ -111,6 +119,7 @@ struct rdp_shadow_server
|
||||
pfnShadowSubsystemFree Free; \
|
||||
\
|
||||
pfnShadowSurfaceCopy SurfaceCopy; \
|
||||
pfnShadowSurfaceUpdate SurfaceUpdate; \
|
||||
\
|
||||
pfnShadowSynchronizeEvent SynchronizeEvent; \
|
||||
pfnShadowKeyboardEvent KeyboardEvent; \
|
||||
|
@ -136,6 +136,87 @@ DEFINE_GUID(IID_IDXGIFactory2, 0x50c83a1c, 0xe072, 0x4c48, 0x87, 0xb0, 0x36, 0x3
|
||||
DEFINE_GUID(IID_IDXGIAdapter2, 0x0AA1AE0A, 0xFA0E, 0x4B84, 0x86, 0x44, 0xE0, 0x5F, 0xF8, 0xE5, 0xAC, 0xB5);
|
||||
DEFINE_GUID(IID_IDXGIOutput1, 0x00cddea8, 0x939b, 0x4b83, 0xa3, 0x40, 0xa6, 0x85, 0x22, 0x66, 0x66, 0xcc);
|
||||
|
||||
const char* GetDxgiErrorString(HRESULT hr)
|
||||
{
|
||||
switch (hr)
|
||||
{
|
||||
case DXGI_STATUS_OCCLUDED:
|
||||
return "DXGI_STATUS_OCCLUDED";
|
||||
case DXGI_STATUS_CLIPPED:
|
||||
return "DXGI_STATUS_CLIPPED";
|
||||
case DXGI_STATUS_NO_REDIRECTION:
|
||||
return "DXGI_STATUS_NO_REDIRECTION";
|
||||
case DXGI_STATUS_NO_DESKTOP_ACCESS:
|
||||
return "DXGI_STATUS_NO_DESKTOP_ACCESS";
|
||||
case DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE:
|
||||
return "DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE";
|
||||
case DXGI_STATUS_MODE_CHANGED:
|
||||
return "DXGI_STATUS_MODE_CHANGED";
|
||||
case DXGI_STATUS_MODE_CHANGE_IN_PROGRESS:
|
||||
return "DXGI_STATUS_MODE_CHANGE_IN_PROGRESS";
|
||||
case DXGI_ERROR_INVALID_CALL:
|
||||
return "DXGI_ERROR_INVALID_CALL";
|
||||
case DXGI_ERROR_NOT_FOUND:
|
||||
return "DXGI_ERROR_NOT_FOUND";
|
||||
case DXGI_ERROR_MORE_DATA:
|
||||
return "DXGI_ERROR_MORE_DATA";
|
||||
case DXGI_ERROR_UNSUPPORTED:
|
||||
return "DXGI_ERROR_UNSUPPORTED";
|
||||
case DXGI_ERROR_DEVICE_REMOVED:
|
||||
return "DXGI_ERROR_DEVICE_REMOVED";
|
||||
case DXGI_ERROR_DEVICE_HUNG:
|
||||
return "DXGI_ERROR_DEVICE_HUNG";
|
||||
case DXGI_ERROR_DEVICE_RESET:
|
||||
return "DXGI_ERROR_DEVICE_RESET";
|
||||
case DXGI_ERROR_WAS_STILL_DRAWING:
|
||||
return "DXGI_ERROR_WAS_STILL_DRAWING";
|
||||
case DXGI_ERROR_FRAME_STATISTICS_DISJOINT:
|
||||
return "DXGI_ERROR_FRAME_STATISTICS_DISJOINT";
|
||||
case DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE:
|
||||
return "DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE";
|
||||
case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
|
||||
return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";
|
||||
case DXGI_ERROR_NONEXCLUSIVE:
|
||||
return "DXGI_ERROR_NONEXCLUSIVE";
|
||||
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
|
||||
return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE";
|
||||
case DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED:
|
||||
return "DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED";
|
||||
case DXGI_ERROR_REMOTE_OUTOFMEMORY:
|
||||
return "DXGI_ERROR_REMOTE_OUTOFMEMORY";
|
||||
case DXGI_ERROR_ACCESS_LOST:
|
||||
return "DXGI_ERROR_ACCESS_LOST";
|
||||
case DXGI_ERROR_WAIT_TIMEOUT:
|
||||
return "DXGI_ERROR_WAIT_TIMEOUT";
|
||||
case DXGI_ERROR_SESSION_DISCONNECTED:
|
||||
return "DXGI_ERROR_SESSION_DISCONNECTED";
|
||||
case DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE:
|
||||
return "DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE";
|
||||
case DXGI_ERROR_CANNOT_PROTECT_CONTENT:
|
||||
return "DXGI_ERROR_CANNOT_PROTECT_CONTENT";
|
||||
case DXGI_ERROR_ACCESS_DENIED:
|
||||
return "DXGI_ERROR_ACCESS_DENIED";
|
||||
case DXGI_ERROR_NAME_ALREADY_EXISTS:
|
||||
return "DXGI_ERROR_NAME_ALREADY_EXISTS";
|
||||
case DXGI_ERROR_SDK_COMPONENT_MISSING:
|
||||
return "DXGI_ERROR_SDK_COMPONENT_MISSING";
|
||||
case DXGI_STATUS_UNOCCLUDED:
|
||||
return "DXGI_STATUS_UNOCCLUDED";
|
||||
case DXGI_STATUS_DDA_WAS_STILL_DRAWING:
|
||||
return "DXGI_STATUS_DDA_WAS_STILL_DRAWING";
|
||||
case DXGI_ERROR_MODE_CHANGE_IN_PROGRESS:
|
||||
return "DXGI_ERROR_MODE_CHANGE_IN_PROGRESS";
|
||||
case DXGI_DDI_ERR_WASSTILLDRAWING:
|
||||
return "DXGI_DDI_ERR_WASSTILLDRAWING";
|
||||
case DXGI_DDI_ERR_UNSUPPORTED:
|
||||
return "DXGI_DDI_ERR_UNSUPPORTED";
|
||||
case DXGI_DDI_ERR_NONEXCLUSIVE:
|
||||
return "DXGI_DDI_ERR_NONEXCLUSIVE";
|
||||
}
|
||||
|
||||
return "DXGI_ERROR_UNKNOWN";
|
||||
}
|
||||
|
||||
static void win_shadow_d3d11_module_init()
|
||||
{
|
||||
if (d3d11_module)
|
||||
@ -155,39 +236,55 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
|
||||
UINT dTop, i = 0;
|
||||
IDXGIOutput* pOutput;
|
||||
DXGI_OUTPUT_DESC outputDesc;
|
||||
DXGI_OUTPUT_DESC* pOutputDesc;
|
||||
D3D11_TEXTURE2D_DESC textureDesc;
|
||||
IDXGIDevice* DxgiDevice = NULL;
|
||||
IDXGIAdapter* DxgiAdapter = NULL;
|
||||
IDXGIOutput* DxgiOutput = NULL;
|
||||
IDXGIOutput1* DxgiOutput1 = NULL;
|
||||
IDXGIDevice* dxgiDevice = NULL;
|
||||
IDXGIAdapter* dxgiAdapter = NULL;
|
||||
IDXGIOutput* dxgiOutput = NULL;
|
||||
IDXGIOutput1* dxgiOutput1 = NULL;
|
||||
|
||||
hr = subsystem->dxgiDevice->lpVtbl->QueryInterface(subsystem->dxgiDevice,
|
||||
&IID_IDXGIDevice, (void**) &DxgiDevice);
|
||||
&IID_IDXGIDevice, (void**) &dxgiDevice);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "ID3D11Device::QueryInterface(IDXGIDevice) failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = DxgiDevice->lpVtbl->GetParent(DxgiDevice, &IID_IDXGIAdapter, (void**) &DxgiAdapter);
|
||||
hr = dxgiDevice->lpVtbl->GetParent(dxgiDevice, &IID_IDXGIAdapter, (void**) &dxgiAdapter);
|
||||
|
||||
DxgiDevice->lpVtbl->Release(DxgiDevice);
|
||||
DxgiDevice = NULL;
|
||||
if (dxgiDevice)
|
||||
{
|
||||
dxgiDevice->lpVtbl->Release(dxgiDevice);
|
||||
dxgiDevice = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIDevice::GetParent(IDXGIAdapter) failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pOutput = NULL;
|
||||
ZeroMemory(&outputDesc, sizeof(outputDesc));
|
||||
|
||||
while (DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND)
|
||||
while (dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
DXGI_OUTPUT_DESC* pDesc = &outputDesc;
|
||||
pOutputDesc = &outputDesc;
|
||||
|
||||
hr = pOutput->lpVtbl->GetDesc(pOutput, pDesc);
|
||||
hr = pOutput->lpVtbl->GetDesc(pOutput, pOutputDesc);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutput::GetDesc failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pDesc->AttachedToDesktop)
|
||||
if (pOutputDesc->AttachedToDesktop)
|
||||
dTop = i;
|
||||
|
||||
pOutput->lpVtbl->Release(pOutput);
|
||||
@ -196,30 +293,51 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
|
||||
|
||||
dTop = 0; /* screen id */
|
||||
|
||||
hr = DxgiAdapter->lpVtbl->EnumOutputs(DxgiAdapter, dTop, &DxgiOutput);
|
||||
hr = dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, dTop, &dxgiOutput);
|
||||
|
||||
DxgiAdapter->lpVtbl->Release(DxgiAdapter);
|
||||
DxgiAdapter = NULL;
|
||||
if (dxgiAdapter)
|
||||
{
|
||||
dxgiAdapter->lpVtbl->Release(dxgiAdapter);
|
||||
dxgiAdapter = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIAdapter::EnumOutputs failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = DxgiOutput->lpVtbl->QueryInterface(DxgiOutput, &IID_IDXGIOutput1, (void**) &DxgiOutput1);
|
||||
hr = dxgiOutput->lpVtbl->QueryInterface(dxgiOutput, &IID_IDXGIOutput1, (void**) &dxgiOutput1);
|
||||
|
||||
DxgiOutput->lpVtbl->Release(DxgiOutput);
|
||||
DxgiOutput = NULL;
|
||||
if (dxgiOutput)
|
||||
{
|
||||
dxgiOutput->lpVtbl->Release(dxgiOutput);
|
||||
dxgiOutput = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutput::QueryInterface(IDXGIOutput1) failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = DxgiOutput1->lpVtbl->DuplicateOutput(DxgiOutput1, (IUnknown*) subsystem->dxgiDevice,
|
||||
hr = dxgiOutput1->lpVtbl->DuplicateOutput(dxgiOutput1, (IUnknown*) subsystem->dxgiDevice,
|
||||
&(subsystem->dxgiOutputDuplication));
|
||||
|
||||
DxgiOutput1->lpVtbl->Release(DxgiOutput1);
|
||||
DxgiOutput1 = NULL;
|
||||
if (dxgiOutput1)
|
||||
{
|
||||
dxgiOutput1->lpVtbl->Release(dxgiOutput1);
|
||||
dxgiOutput1 = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutput1::DuplicateOutput failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
textureDesc.Width = subsystem->width;
|
||||
textureDesc.Height = subsystem->height;
|
||||
@ -237,7 +355,11 @@ int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
|
||||
&textureDesc, NULL, &(subsystem->dxgiStage));
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "ID3D11Device::CreateTexture2D failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -268,7 +390,10 @@ int win_shadow_dxgi_init(winShadowSubsystem* subsystem)
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "D3D11CreateDevice failure: 0x%04X\n", hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
win_shadow_dxgi_init_duplication(subsystem);
|
||||
|
||||
@ -317,6 +442,9 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
|
||||
D3D11_BOX Box;
|
||||
DXGI_MAPPED_RECT mappedRect;
|
||||
|
||||
if ((width * height) < 1)
|
||||
return 1;
|
||||
|
||||
Box.top = x;
|
||||
Box.left = y;
|
||||
Box.right = x + width;
|
||||
@ -331,12 +459,22 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
|
||||
&IID_IDXGISurface, (void**) &(subsystem->dxgiSurface));
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "ID3D11Texture2D::QueryInterface(IDXGISurface) failure: %s 0x%04X\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = subsystem->dxgiSurface->lpVtbl->Map(subsystem->dxgiSurface, &mappedRect, DXGI_MAP_READ);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGISurface::Map failure: %s 0x%04X\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
subsystem->dxgiSurfaceMapped = TRUE;
|
||||
|
||||
*ppDstData = mappedRect.pBits;
|
||||
*pnDstStep = mappedRect.Pitch;
|
||||
@ -346,22 +484,26 @@ int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem,
|
||||
|
||||
int win_shadow_dxgi_release_frame_data(winShadowSubsystem* subsystem)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (subsystem->dxgiSurface)
|
||||
{
|
||||
subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface);
|
||||
if (subsystem->dxgiSurfaceMapped)
|
||||
{
|
||||
subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface);
|
||||
subsystem->dxgiSurfaceMapped = FALSE;
|
||||
}
|
||||
|
||||
subsystem->dxgiSurface->lpVtbl->Release(subsystem->dxgiSurface);
|
||||
subsystem->dxgiSurface = NULL;
|
||||
}
|
||||
|
||||
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
|
||||
if (subsystem->dxgiFrameAcquired)
|
||||
{
|
||||
subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
|
||||
subsystem->dxgiFrameAcquired = FALSE;
|
||||
}
|
||||
|
||||
subsystem->pendingFrames = 0;
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -373,7 +515,7 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
|
||||
UINT DataBufferSize = 0;
|
||||
BYTE* DataBuffer = NULL;
|
||||
|
||||
if (subsystem->pendingFrames > 0)
|
||||
if (subsystem->dxgiFrameAcquired)
|
||||
{
|
||||
win_shadow_dxgi_release_frame_data(subsystem);
|
||||
}
|
||||
@ -387,11 +529,20 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
|
||||
hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(subsystem->dxgiOutputDuplication,
|
||||
0, &(subsystem->dxgiFrameInfo), &(subsystem->dxgiResource));
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
subsystem->dxgiFrameAcquired = TRUE;
|
||||
subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames;
|
||||
}
|
||||
|
||||
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
|
||||
return 0;
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutputDuplication::AcquireNextFrame failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
|
||||
if (hr == DXGI_ERROR_ACCESS_LOST)
|
||||
{
|
||||
if (subsystem->dxgiDesktopImage)
|
||||
@ -413,34 +564,24 @@ int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
hr = subsystem->dxgiResource->lpVtbl->QueryInterface(subsystem->dxgiResource,
|
||||
&IID_ID3D11Texture2D, (void**) &(subsystem->dxgiDesktopImage));
|
||||
|
||||
subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource);
|
||||
subsystem->dxgiResource = NULL;
|
||||
if (subsystem->dxgiResource)
|
||||
{
|
||||
subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource);
|
||||
subsystem->dxgiResource = NULL;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames;
|
||||
|
||||
if (subsystem->pendingFrames == 0)
|
||||
{
|
||||
hr = subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(subsystem->dxgiOutputDuplication);
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
fprintf(stderr, "IDXGIResource::QueryInterface(ID3D11Texture2D) failure: %s (0x%04X)\n",
|
||||
GetDxgiErrorString(hr), hr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -456,21 +597,13 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
UINT numMoveRects;
|
||||
UINT numDirtyRects;
|
||||
UINT UsedBufferSize;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowScreen* screen;
|
||||
RECTANGLE_16 invalidRect;
|
||||
UINT MetadataBufferSize;
|
||||
UINT MoveRectsBufferSize;
|
||||
UINT DirtyRectsBufferSize;
|
||||
UINT PointerShapeBufferSize;
|
||||
RECT* pDirtyRectsBuffer;
|
||||
void* pPointerShapeBuffer;
|
||||
DXGI_OUTDUPL_MOVE_RECT* pMoveRect;
|
||||
DXGI_OUTDUPL_MOVE_RECT* pMoveRectBuffer;
|
||||
DXGI_OUTDUPL_POINTER_SHAPE_INFO PointerShapeInfo;
|
||||
|
||||
server = subsystem->server;
|
||||
screen = server->screen;
|
||||
|
||||
if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0)
|
||||
return 0;
|
||||
@ -501,7 +634,11 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
MoveRectsBufferSize, pMoveRectBuffer, &MoveRectsBufferSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutputDuplication::GetFrameMoveRects failure: %s (0x%04X) Size: %d Total %d Used: %d\n",
|
||||
GetDxgiErrorString(hr), hr, MoveRectsBufferSize, MetadataBufferSize, UsedBufferSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* GetFrameDirtyRects */
|
||||
|
||||
@ -514,22 +651,11 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
DirtyRectsBufferSize, pDirtyRectsBuffer, &DirtyRectsBufferSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
fprintf(stderr, "IDXGIOutputDuplication::GetFrameDirtyRects failure: %s (0x%04X) Size: %d Total %d Used: %d\n",
|
||||
GetDxgiErrorString(hr), hr, DirtyRectsBufferSize, MetadataBufferSize, UsedBufferSize);
|
||||
return -1;
|
||||
|
||||
/* GetFramePointerShape */
|
||||
|
||||
UsedBufferSize += MoveRectsBufferSize;
|
||||
|
||||
PointerShapeBufferSize = MetadataBufferSize - UsedBufferSize;
|
||||
pPointerShapeBuffer = (void*) &(subsystem->MetadataBuffer[UsedBufferSize]);
|
||||
|
||||
hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFramePointerShape(subsystem->dxgiOutputDuplication,
|
||||
PointerShapeBufferSize, pPointerShapeBuffer, &PointerShapeBufferSize, &PointerShapeInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
EnterCriticalSection(&(screen->lock));
|
||||
}
|
||||
|
||||
numMoveRects = MoveRectsBufferSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
|
||||
|
||||
@ -544,7 +670,7 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
invalidRect.right = (UINT16) pDstRect->right;
|
||||
invalidRect.bottom = (UINT16) pDstRect->bottom;
|
||||
|
||||
region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
numDirtyRects = DirtyRectsBufferSize / sizeof(RECT);
|
||||
@ -558,11 +684,9 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
invalidRect.right = (UINT16) pDirtyRect->right;
|
||||
invalidRect.bottom = (UINT16) pDirtyRect->bottom;
|
||||
|
||||
region16_union_rect(&(screen->invalidRegion), &(screen->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(screen->lock));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -747,7 +871,6 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
int status;
|
||||
int nDstStep = 0;
|
||||
BYTE* pDstData = NULL;
|
||||
rdpShadowScreen* screen;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
@ -755,7 +878,6 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
|
||||
server = subsystem->server;
|
||||
surface = server->surface;
|
||||
screen = server->screen;
|
||||
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
@ -763,7 +885,8 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(screen->invalidRegion), &surfaceRect);
|
||||
region16_copy(&(surface->invalidRegion), &(subsystem->invalidRegion));
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(surface->invalidRegion)))
|
||||
return 1;
|
||||
@ -775,7 +898,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
width = extents->right - extents->left;
|
||||
height = extents->bottom - extents->top;
|
||||
|
||||
printf("x: %d y: %d width: %d height: %d right: %d bottom: %d\n",
|
||||
printf("SurfaceCopy x: %d y: %d width: %d height: %d right: %d bottom: %d\n",
|
||||
x, y, width, height, x + width, y + height);
|
||||
|
||||
status = win_shadow_dxgi_fetch_frame_data(subsystem, &pDstData, &nDstStep, x, y, width, height);
|
||||
@ -783,10 +906,14 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
EnterCriticalSection(&(surface->lock));
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32,
|
||||
surface->scanline, x - surface->x, y - surface->y, width, height,
|
||||
pDstData, PIXEL_FORMAT_XRGB32, nDstStep, x, y);
|
||||
|
||||
LeaveCriticalSection(&(surface->lock));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -832,14 +959,16 @@ void* win_shadow_subsystem_thread(winShadowSubsystem* subsystem)
|
||||
#ifdef WITH_DXGI_1_2
|
||||
int dxgi_status;
|
||||
|
||||
//win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
|
||||
|
||||
dxgi_status = win_shadow_dxgi_get_next_frame(subsystem);
|
||||
dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
|
||||
win_shadow_surface_copy(subsystem);
|
||||
|
||||
if (subsystem->pendingFrames > 0)
|
||||
{
|
||||
dxgi_status = win_shadow_dxgi_get_invalid_region(subsystem);
|
||||
if (subsystem->SurfaceUpdate)
|
||||
subsystem->SurfaceUpdate((rdpShadowSubsystem*) subsystem, &(subsystem->invalidRegion));
|
||||
|
||||
win_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
|
||||
}
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
#endif
|
||||
|
||||
dwInterval = 1000 / fps;
|
||||
@ -941,6 +1070,8 @@ void win_shadow_subsystem_free(winShadowSubsystem* subsystem)
|
||||
|
||||
win_shadow_subsystem_uninit(subsystem);
|
||||
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
|
||||
free(subsystem);
|
||||
}
|
||||
|
||||
@ -955,6 +1086,8 @@ winShadowSubsystem* win_shadow_subsystem_new(rdpShadowServer* server)
|
||||
|
||||
subsystem->server = server;
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
subsystem->Init = (pfnShadowSubsystemInit) win_shadow_subsystem_init;
|
||||
subsystem->Uninit = (pfnShadowSubsystemInit) win_shadow_subsystem_uninit;
|
||||
subsystem->Start = (pfnShadowSubsystemStart) win_shadow_subsystem_start;
|
||||
|
@ -56,6 +56,8 @@ struct win_shadow_subsystem
|
||||
UINT pendingFrames;
|
||||
BYTE* MetadataBuffer;
|
||||
UINT MetadataBufferSize;
|
||||
BOOL dxgiSurfaceMapped;
|
||||
BOOL dxgiFrameAcquired;
|
||||
ID3D11Device* dxgiDevice;
|
||||
IDXGISurface* dxgiSurface;
|
||||
ID3D11Texture2D* dxgiStage;
|
||||
|
@ -27,69 +27,8 @@
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <winpr/tools/makecert.h>
|
||||
|
||||
#include "shadow.h"
|
||||
|
||||
static const char* makecert_argv[6] =
|
||||
{
|
||||
"makecert",
|
||||
"-rdp",
|
||||
"-live",
|
||||
"-silent",
|
||||
"-y", "5"
|
||||
};
|
||||
|
||||
static int makecert_argc = (sizeof(makecert_argv) / sizeof(char*));
|
||||
|
||||
int shadow_generate_certificate(rdpShadowClient* client)
|
||||
{
|
||||
char* filepath;
|
||||
rdpContext* context;
|
||||
rdpSettings* settings;
|
||||
MAKECERT_CONTEXT* makecert;
|
||||
rdpShadowServer* server = client->server;
|
||||
|
||||
context = (rdpContext*) client;
|
||||
settings = context->settings;
|
||||
|
||||
if (!PathFileExistsA(server->ConfigPath))
|
||||
CreateDirectoryA(server->ConfigPath, 0);
|
||||
|
||||
filepath = GetCombinedPath(server->ConfigPath, "shadow");
|
||||
|
||||
if (!filepath)
|
||||
return -1;
|
||||
|
||||
if (!PathFileExistsA(filepath))
|
||||
CreateDirectoryA(filepath, 0);
|
||||
|
||||
settings->CertificateFile = GetCombinedPath(filepath, "shadow.crt");
|
||||
settings->PrivateKeyFile = GetCombinedPath(filepath, "shadow.key");
|
||||
|
||||
if ((!PathFileExistsA(settings->CertificateFile)) ||
|
||||
(!PathFileExistsA(settings->PrivateKeyFile)))
|
||||
{
|
||||
makecert = makecert_context_new();
|
||||
|
||||
makecert_context_process(makecert, makecert_argc, (char**) makecert_argv);
|
||||
|
||||
makecert_context_set_output_file_name(makecert, "shadow");
|
||||
|
||||
if (!PathFileExistsA(settings->CertificateFile))
|
||||
makecert_context_output_certificate_file(makecert, filepath);
|
||||
|
||||
if (!PathFileExistsA(settings->PrivateKeyFile))
|
||||
makecert_context_output_private_key_file(makecert, filepath);
|
||||
|
||||
makecert_context_free(makecert);
|
||||
}
|
||||
|
||||
free(filepath);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
||||
{
|
||||
rdpSettings* settings;
|
||||
@ -110,19 +49,36 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
|
||||
settings->TlsSecurity = TRUE;
|
||||
settings->NlaSecurity = FALSE;
|
||||
|
||||
shadow_generate_certificate(client);
|
||||
settings->CertificateFile = _strdup(server->CertificateFile);
|
||||
settings->PrivateKeyFile = _strdup(server->PrivateKeyFile);
|
||||
|
||||
client->inLobby = TRUE;
|
||||
client->mayView = server->mayView;
|
||||
client->mayInteract = server->mayInteract;
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&(client->lock), 4000);
|
||||
|
||||
region16_init(&(client->invalidRegion));
|
||||
|
||||
client->vcm = WTSOpenServerA((LPSTR) peer->context);
|
||||
|
||||
client->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
client->encoder = shadow_encoder_new(server);
|
||||
|
||||
ArrayList_Add(server->clients, (void*) client);
|
||||
}
|
||||
|
||||
void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
|
||||
{
|
||||
rdpShadowServer* server = client->server;
|
||||
|
||||
ArrayList_Remove(server->clients, (void*) client);
|
||||
|
||||
DeleteCriticalSection(&(client->lock));
|
||||
|
||||
region16_uninit(&(client->invalidRegion));
|
||||
|
||||
WTSCloseServer((HANDLE) client->vcm);
|
||||
|
||||
CloseHandle(client->StopEvent);
|
||||
@ -132,6 +88,12 @@ void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client)
|
||||
shadow_surface_free(client->lobby);
|
||||
client->lobby = NULL;
|
||||
}
|
||||
|
||||
if (client->encoder)
|
||||
{
|
||||
shadow_encoder_free(client->encoder);
|
||||
client->encoder = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shadow_client_capabilities(freerdp_peer* peer)
|
||||
@ -189,7 +151,7 @@ BOOL shadow_client_activate(freerdp_peer* peer)
|
||||
client->activated = TRUE;
|
||||
client->inLobby = client->mayView ? FALSE : TRUE;
|
||||
|
||||
shadow_encoder_reset(client->server->encoder);
|
||||
shadow_encoder_reset(client->encoder);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -199,7 +161,7 @@ void shadow_client_surface_frame_acknowledge(rdpShadowClient* client, UINT32 fra
|
||||
SURFACE_FRAME* frame;
|
||||
wListDictionary* frameList;
|
||||
|
||||
frameList = client->server->encoder->frameList;
|
||||
frameList = client->encoder->frameList;
|
||||
frame = (SURFACE_FRAME*) ListDictionary_GetItemValue(frameList, (void*) (size_t) frameId);
|
||||
|
||||
if (frame)
|
||||
@ -248,7 +210,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
settings = context->settings;
|
||||
|
||||
server = client->server;
|
||||
encoder = server->encoder;
|
||||
encoder = client->encoder;
|
||||
|
||||
pSrcData = surface->data;
|
||||
nSrcStep = surface->scanline;
|
||||
@ -336,8 +298,6 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
|
||||
free(messages);
|
||||
}
|
||||
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
|
||||
if (encoder->frameAck)
|
||||
{
|
||||
shadow_client_send_surface_frame_marker(client, SURFACECMD_FRAMEACTION_END, frameId);
|
||||
@ -372,7 +332,7 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
|
||||
settings = context->settings;
|
||||
|
||||
server = client->server;
|
||||
encoder = server->encoder;
|
||||
encoder = client->encoder;
|
||||
|
||||
pSrcData = surface->data;
|
||||
nSrcStep = surface->scanline;
|
||||
@ -562,27 +522,39 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
||||
rdpShadowServer* server;
|
||||
rdpShadowSurface* surface;
|
||||
rdpShadowEncoder* encoder;
|
||||
REGION16 invalidRegion;
|
||||
RECTANGLE_16 surfaceRect;
|
||||
const RECTANGLE_16* extents;
|
||||
|
||||
context = (rdpContext*) client;
|
||||
settings = context->settings;
|
||||
server = client->server;
|
||||
encoder = server->encoder;
|
||||
encoder = client->encoder;
|
||||
|
||||
surface = client->inLobby ? client->lobby : server->surface;
|
||||
|
||||
EnterCriticalSection(&(client->lock));
|
||||
|
||||
region16_init(&invalidRegion);
|
||||
region16_copy(&invalidRegion, &(client->invalidRegion));
|
||||
region16_clear(&(client->invalidRegion));
|
||||
|
||||
LeaveCriticalSection(&(client->lock));
|
||||
|
||||
surfaceRect.left = surface->x;
|
||||
surfaceRect.top = surface->y;
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
region16_intersect_rect(&invalidRegion, &invalidRegion, &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(surface->invalidRegion)))
|
||||
if (region16_is_empty(&invalidRegion))
|
||||
{
|
||||
region16_uninit(&invalidRegion);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
extents = region16_extents(&invalidRegion);
|
||||
|
||||
nXSrc = extents->left - surface->x;
|
||||
nYSrc = extents->top - surface->y;
|
||||
@ -608,9 +580,31 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
|
||||
status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
|
||||
}
|
||||
|
||||
region16_uninit(&invalidRegion);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
|
||||
{
|
||||
int index;
|
||||
int numRects = 0;
|
||||
const RECTANGLE_16* rects;
|
||||
|
||||
EnterCriticalSection(&(client->lock));
|
||||
|
||||
rects = region16_rects(region, &numRects);
|
||||
|
||||
for (index = 0; index < numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(client->invalidRegion), &(client->invalidRegion), &rects[index]);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&(client->lock));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* shadow_client_thread(rdpShadowClient* client)
|
||||
{
|
||||
int fps;
|
||||
@ -633,7 +627,7 @@ void* shadow_client_thread(rdpShadowClient* client)
|
||||
|
||||
server = client->server;
|
||||
screen = server->screen;
|
||||
encoder = server->encoder;
|
||||
encoder = client->encoder;
|
||||
subsystem = server->subsystem;
|
||||
|
||||
peer = ((rdpContext*) client)->peer;
|
||||
|
@ -25,6 +25,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region);
|
||||
void shadow_client_accepted(freerdp_listener* instance, freerdp_peer* client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -83,7 +83,7 @@ static int encomsp_change_participant_control_level(EncomspServerContext* contex
|
||||
|
||||
if (inLobby != client->inLobby)
|
||||
{
|
||||
shadow_encoder_reset(client->server->encoder);
|
||||
shadow_encoder_reset(client->encoder);
|
||||
client->inLobby = inLobby;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include <winpr/tools/makecert.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/select.h>
|
||||
#include <sys/signal.h>
|
||||
@ -226,6 +228,32 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
|
||||
return status;
|
||||
}
|
||||
|
||||
int shadow_server_surface_update(rdpShadowSubsystem* subsystem, REGION16* region)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
wArrayList* clients;
|
||||
rdpShadowServer* server;
|
||||
rdpShadowClient* client;
|
||||
|
||||
server = subsystem->server;
|
||||
clients = server->clients;
|
||||
|
||||
ArrayList_Lock(clients);
|
||||
|
||||
count = ArrayList_Count(clients);
|
||||
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
client = ArrayList_GetItem(clients, index);
|
||||
shadow_client_surface_update(client, region);
|
||||
}
|
||||
|
||||
ArrayList_Unlock(clients);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* shadow_server_thread(rdpShadowServer* server)
|
||||
{
|
||||
DWORD status;
|
||||
@ -317,6 +345,59 @@ int shadow_server_stop(rdpShadowServer* server)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int shadow_server_init_certificate(rdpShadowServer* server)
|
||||
{
|
||||
char* filepath;
|
||||
MAKECERT_CONTEXT* makecert;
|
||||
|
||||
const char* makecert_argv[6] =
|
||||
{
|
||||
"makecert",
|
||||
"-rdp",
|
||||
"-live",
|
||||
"-silent",
|
||||
"-y", "5"
|
||||
};
|
||||
|
||||
int makecert_argc = (sizeof(makecert_argv) / sizeof(char*));
|
||||
|
||||
if (!PathFileExistsA(server->ConfigPath))
|
||||
CreateDirectoryA(server->ConfigPath, 0);
|
||||
|
||||
filepath = GetCombinedPath(server->ConfigPath, "shadow");
|
||||
|
||||
if (!filepath)
|
||||
return -1;
|
||||
|
||||
if (!PathFileExistsA(filepath))
|
||||
CreateDirectoryA(filepath, 0);
|
||||
|
||||
server->CertificateFile = GetCombinedPath(filepath, "shadow.crt");
|
||||
server->PrivateKeyFile = GetCombinedPath(filepath, "shadow.key");
|
||||
|
||||
if ((!PathFileExistsA(server->CertificateFile)) ||
|
||||
(!PathFileExistsA(server->PrivateKeyFile)))
|
||||
{
|
||||
makecert = makecert_context_new();
|
||||
|
||||
makecert_context_process(makecert, makecert_argc, (char**) makecert_argv);
|
||||
|
||||
makecert_context_set_output_file_name(makecert, "shadow");
|
||||
|
||||
if (!PathFileExistsA(server->CertificateFile))
|
||||
makecert_context_output_certificate_file(makecert, filepath);
|
||||
|
||||
if (!PathFileExistsA(server->PrivateKeyFile))
|
||||
makecert_context_output_private_key_file(makecert, filepath);
|
||||
|
||||
makecert_context_free(makecert);
|
||||
}
|
||||
|
||||
free(filepath);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_server_init(rdpShadowServer* server)
|
||||
{
|
||||
int status;
|
||||
@ -325,6 +406,11 @@ int shadow_server_init(rdpShadowServer* server)
|
||||
|
||||
server->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
status = shadow_server_init_certificate(server);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
server->listener = freerdp_listener_new();
|
||||
|
||||
if (!server->listener)
|
||||
@ -351,6 +437,8 @@ int shadow_server_init(rdpShadowServer* server)
|
||||
if (!server->subsystem)
|
||||
return -1;
|
||||
|
||||
server->subsystem->SurfaceUpdate = shadow_server_surface_update;
|
||||
|
||||
if (server->subsystem->Init)
|
||||
{
|
||||
status = server->subsystem->Init(server->subsystem);
|
||||
@ -364,11 +452,6 @@ int shadow_server_init(rdpShadowServer* server)
|
||||
if (!server->screen)
|
||||
return -1;
|
||||
|
||||
server->encoder = shadow_encoder_new(server);
|
||||
|
||||
if (!server->encoder)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -382,18 +465,24 @@ int shadow_server_uninit(rdpShadowServer* server)
|
||||
server->listener = NULL;
|
||||
}
|
||||
|
||||
if (server->encoder)
|
||||
{
|
||||
shadow_encoder_free(server->encoder);
|
||||
server->encoder = NULL;
|
||||
}
|
||||
|
||||
if (server->subsystem)
|
||||
{
|
||||
server->subsystem->Free(server->subsystem);
|
||||
server->subsystem = NULL;
|
||||
}
|
||||
|
||||
if (server->CertificateFile)
|
||||
{
|
||||
free(server->CertificateFile);
|
||||
server->CertificateFile = NULL;
|
||||
}
|
||||
|
||||
if (server->PrivateKeyFile)
|
||||
{
|
||||
free(server->PrivateKeyFile);
|
||||
server->PrivateKeyFile = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -417,6 +506,10 @@ rdpShadowServer* shadow_server_new()
|
||||
if (!server->ConfigPath)
|
||||
server->ConfigPath = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, "freerdp");
|
||||
|
||||
InitializeCriticalSectionAndSpinCount(&(server->lock), 4000);
|
||||
|
||||
server->clients = ArrayList_New(TRUE);
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
@ -425,6 +518,14 @@ void shadow_server_free(rdpShadowServer* server)
|
||||
if (!server)
|
||||
return;
|
||||
|
||||
DeleteCriticalSection(&(server->lock));
|
||||
|
||||
if (server->clients)
|
||||
{
|
||||
ArrayList_Free(server->clients);
|
||||
server->clients = NULL;
|
||||
}
|
||||
|
||||
shadow_server_uninit(server);
|
||||
|
||||
free(server);
|
||||
|
Loading…
Reference in New Issue
Block a user