2025-11-28 00:35:46 +09:00

255 lines
8.0 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#ifndef UNICODE
#define UNICODE
#endif
#include "WebServices.h"
#include "process.h"
#include "stdio.h"
#include "string.h"
#include "LayeredChannel.h"
HRESULT CALLBACK CustomCreateChannel(
_In_ WS_CHANNEL_TYPE channelType,
_In_reads_bytes_(channelParametersSize) const void* channelParameters,
_In_ ULONG channelParametersSize,
_Outptr_ void** channelInstance,
_In_opt_ WS_ERROR* error)
{
HRESULT hr;
CustomChannel* customChannel = NULL;
// Get the parameters passed via WS_CHANNEL_PROPERTY_CUSTOM_CHANNEL_PARAMETERS
if (channelParametersSize != sizeof(LayeredChannelParameters))
{
return E_INVALIDARG;
}
LayeredChannelParameters* layeredChannelParameters = (LayeredChannelParameters*)channelParameters;
// Allocate the custom channel instance
customChannel = (CustomChannel*)HeapAlloc(GetProcessHeap(), 0, sizeof(CustomChannel));
if (customChannel == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
// Create the underlying channel using the passed in parameters
hr = WsCreateChannel(
channelType,
layeredChannelParameters->channelBinding,
layeredChannelParameters->channelProperties,
layeredChannelParameters->channelPropertyCount,
layeredChannelParameters->securityDescription,
&customChannel->channel,
error);
if (FAILED(hr))
{
goto Exit;
}
// we need to keep track of whether timeouts were disabled to be able to serve
// the WsGetChannelProperty calls later on.
for (ULONG i = 0; i < layeredChannelParameters->channelPropertyCount; i ++)
{
if (WS_CHANNEL_PROPERTY_ENABLE_TIMEOUTS == layeredChannelParameters->channelProperties[i].id)
{
customChannel->disabledTimeouts = *(BOOL*)layeredChannelParameters->channelProperties[i].value;
break;
}
}
// Return the channel instance. The instance
// will be freed by the CustomFreeChannel function.
*channelInstance = customChannel;
customChannel = NULL;
hr = S_OK;
Exit:
if (customChannel != NULL)
{
HeapFree(GetProcessHeap(), 0, customChannel);
}
return hr;
}
void CALLBACK CustomFreeChannel(
_In_ void* channelInstance)
{
CustomChannel* customChannel = (CustomChannel*)channelInstance;
// Free the underlying channel
WsFreeChannel(customChannel->channel);
// Free the instance that was allocated by CustomCreateChannel
HeapFree(GetProcessHeap(), 0, channelInstance);
}
HRESULT CALLBACK CustomResetChannel(
_In_ void* channelInstance,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsResetChannel(customChannel->channel, error);
}
HRESULT CALLBACK CustomAbortChannel(
_In_ void* channelInstance,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsAbortChannel(customChannel->channel, error);
}
HRESULT CALLBACK CustomOpenChannel(
_In_ void* channelInstance,
_In_ const WS_ENDPOINT_ADDRESS* endpointAddress,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsOpenChannel(customChannel->channel, endpointAddress, asyncContext, error);
}
HRESULT CALLBACK CustomCloseChannel(
_In_ void* channelInstance,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsCloseChannel(customChannel->channel, asyncContext, error);
}
HRESULT CALLBACK CustomSetChannelProperty(
_In_ void* channelInstance,
_In_ WS_CHANNEL_PROPERTY_ID id,
_In_reads_bytes_(valueSize) const void* value,
_In_ ULONG valueSize,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsSetChannelProperty(customChannel->channel, id, value, valueSize, error);
}
HRESULT CALLBACK CustomGetChannelProperty(
_In_ void* channelInstance,
_In_ WS_CHANNEL_PROPERTY_ID id,
_Out_writes_bytes_(valueSize) void* value,
_In_ ULONG valueSize,
_In_opt_ WS_ERROR* error)
{
CustomChannel* customChannel = (CustomChannel*)channelInstance;
// Underlying channels do not support querying WS_CHANNEL_PROPERTY_ENABLE_TIMEOUTS.
// Custom channel keeps track of whether timeouts were disabled and returns here.
// Service Model queries this property to ensure the timeouts were disabled in the custom channel.
if (WS_CHANNEL_PROPERTY_ENABLE_TIMEOUTS == id)
{
if (sizeof(BOOL) != valueSize)
{
return E_INVALIDARG;
}
*(BOOL*)value = customChannel->disabledTimeouts;
return S_OK;
}
// Delegate the rest of the property queries to the underlying channel
return WsGetChannelProperty(customChannel->channel, id, value, valueSize, error);
}
HRESULT CALLBACK CustomReadMessageStart(
_In_ void* channelInstance,
_In_ WS_MESSAGE* message,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsReadMessageStart(customChannel->channel, message, asyncContext, error);
}
HRESULT CALLBACK CustomReadMessageEnd(
_In_ void* channelInstance,
_In_ WS_MESSAGE* message,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsReadMessageEnd(customChannel->channel, message, asyncContext, error);
}
HRESULT CALLBACK CustomWriteMessageStart(
_In_ void* channelInstance,
_In_ WS_MESSAGE* message,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsWriteMessageStart(customChannel->channel, message, asyncContext, error);
}
HRESULT CALLBACK CustomWriteMessageEnd(
_In_ void* channelInstance,
_In_ WS_MESSAGE* message,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsWriteMessageEnd(customChannel->channel, message, asyncContext, error);
}
HRESULT CALLBACK CustomAbandonMessage(
_In_ void* channelInstance,
_In_ WS_MESSAGE* message,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsAbandonMessage(customChannel->channel, message, error);
}
HRESULT CALLBACK CustomShutdownSessionChannel(
_In_ void* channelInstance,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
// Delegate to the underlying channel
CustomChannel* customChannel = (CustomChannel*)channelInstance;
return WsShutdownSessionChannel(customChannel->channel, asyncContext, error);
}
// Initialize the callbacks that will implement the custom channel
WS_CUSTOM_CHANNEL_CALLBACKS layeredChannelCallbacks =
{
&CustomCreateChannel,
&CustomFreeChannel,
&CustomResetChannel,
&CustomOpenChannel,
&CustomCloseChannel,
&CustomAbortChannel,
&CustomGetChannelProperty,
&CustomSetChannelProperty,
&CustomWriteMessageStart,
&CustomWriteMessageEnd,
&CustomReadMessageStart,
&CustomReadMessageEnd,
&CustomAbandonMessage,
&CustomShutdownSessionChannel,
};