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

367 lines
9.1 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 "new"
static const WS_STRING encodedContentType = WS_STRING_VALUE(L"myContentType");
struct Encoder
{
BYTE* buffer;
ULONG bufferLength;
WCHAR contentType[256];
ULONG contentTypeLength;
WS_WRITE_CALLBACK writeCallback;
void* writeContext;
};
HRESULT CALLBACK CreateEncoder(
_In_ void* createContext,
_In_ WS_WRITE_CALLBACK writeCallback,
_In_ void* writeContext,
_Outptr_ void** encoderContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(createContext);
UNREFERENCED_PARAMETER(error);
Encoder* encoder = new(std::nothrow) Encoder;
if (encoder == NULL)
{
return E_OUTOFMEMORY;
}
encoder->bufferLength = 1024;
encoder->buffer = new(std::nothrow) BYTE[encoder->bufferLength];
if (encoder->buffer == NULL)
{
delete encoder;
return E_OUTOFMEMORY;
}
encoder->writeCallback = writeCallback;
encoder->writeContext = writeContext;
(*encoderContext) = encoder;
return S_OK;
}
HRESULT CALLBACK EncoderGetContentType(
_In_ void* encoderContext,
_In_ const WS_STRING* contentType,
_Out_ WS_STRING* newContentType,
_Out_ WS_STRING* contentEncoding,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(error);
Encoder* encoder = (Encoder*)encoderContext;
if (contentType->length > WsCountOf(encoder->contentType))
{
return E_FAIL;
}
::memcpy(encoder->contentType, contentType->chars, contentType->length * sizeof(WCHAR));
encoder->contentTypeLength = contentType->length;
(*newContentType) = encodedContentType;
contentEncoding->length = 0;
contentEncoding->chars = NULL;
return S_OK;
}
HRESULT CALLBACK EncoderStart(
_In_ void* encoderContext,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
Encoder* encoder = (Encoder*)encoderContext;
WS_BYTES bytes1 = { sizeof(encoder->contentTypeLength), (BYTE*)&encoder->contentTypeLength };
hr = encoder->writeCallback(encoder->writeContext, &bytes1, 1, NULL, error);
if (FAILED(hr))
{
return hr;
}
WS_BYTES bytes2 = { encoder->contentTypeLength * sizeof(WCHAR), (BYTE*)encoder->contentType };
hr = encoder->writeCallback(encoder->writeContext, &bytes2, 1, NULL, error);
if (FAILED(hr))
{
return hr;
}
return S_OK;
}
HRESULT EncoderEncode(
_In_ Encoder* encoder,
_In_reads_(bufferLength) const BYTE* buffer,
_In_ ULONG bufferLength,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
while (bufferLength > encoder->bufferLength)
{
memcpy(encoder->buffer, buffer, encoder->bufferLength);
for (ULONG i = 0; i < encoder->bufferLength; i++)
{
encoder->buffer[i]++;
}
WS_BYTES newBytes = { encoder->bufferLength, encoder->buffer };
hr = encoder->writeCallback(encoder->writeContext, &newBytes, 1, NULL, error);
if (FAILED(hr))
{
return hr;
}
buffer += encoder->bufferLength;
bufferLength -= encoder->bufferLength;
}
memcpy(encoder->buffer, buffer, bufferLength);
for (ULONG i = 0; i < bufferLength; i++)
{
encoder->buffer[i]++;
}
WS_BYTES newBytes = { bufferLength, encoder->buffer };
return encoder->writeCallback(encoder->writeContext, &newBytes, 1, NULL, error);
}
HRESULT CALLBACK EncoderEncode(
_In_ void* encoderContext,
_In_reads_(count) const WS_BYTES* buffers,
_In_ ULONG count,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
Encoder* encoder = (Encoder*)encoderContext;
for (ULONG i = 0; i < count; i++)
{
hr = EncoderEncode(encoder, buffers[i].bytes, buffers[i].length, NULL, error);
if (FAILED(hr))
{
return hr;
}
}
return S_OK;
}
HRESULT CALLBACK EncoderEnd(
_In_ void* encoderContext,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(encoderContext);
UNREFERENCED_PARAMETER(asyncContext);
UNREFERENCED_PARAMETER(error);
return S_OK;
}
void CALLBACK FreeEncoder(
_In_ void* encoderContext)
{
Encoder* encoder = (Encoder*)encoderContext;
delete encoder;
}
WS_CHANNEL_ENCODER channelEncoder =
{
NULL,
CreateEncoder,
EncoderGetContentType,
EncoderStart,
EncoderEncode,
EncoderEnd,
FreeEncoder
};
struct Decoder
{
WCHAR contentType[256];
ULONG contentTypeLength;
WS_READ_CALLBACK readCallback;
void* readContext;
};
HRESULT ReadBlock(
_In_ Decoder* decoder,
_Out_writes_bytes_to_(maxLength, *outLength) void* buffer,
_In_ ULONG maxLength,
_Out_opt_ ULONG* outLength,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
ULONG length = 0;
while (length < maxLength)
{
ULONG actualLength;
hr = decoder->readCallback(decoder->readContext, &((BYTE*)buffer)[length], maxLength - length, &actualLength, NULL, error);
if (FAILED(hr))
{
return hr;
}
if (actualLength == 0)
{
break;
}
length += actualLength;
}
if (outLength == NULL)
{
if (length != maxLength)
{
return E_FAIL;
}
}
else
{
(*outLength) = length;
}
return S_OK;
}
HRESULT CALLBACK CreateDecoder(
_In_ void* createContext,
_In_ WS_READ_CALLBACK readCallback,
_In_ void* readContext,
_Outptr_ void** decoderContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(createContext);
UNREFERENCED_PARAMETER(error);
Decoder* decoder = new(std::nothrow) Decoder;
if (decoder == NULL)
{
return E_OUTOFMEMORY;
}
decoder->readCallback = readCallback;
decoder->readContext = readContext;
(*decoderContext) = decoder;
return S_OK;
}
HRESULT CALLBACK DecoderGetContentType(
_In_ void* decoderContext,
_In_ const WS_STRING* contentType,
_In_opt_ const WS_STRING* contentEncoding,
_Out_ WS_STRING* newContentType,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(error);
Decoder* decoder = (Decoder*)decoderContext;
if (contentEncoding != NULL)
{
return E_FAIL;
}
if (contentType->length != encodedContentType.length)
{
return E_FAIL;
}
if (::memcmp(contentType->chars, encodedContentType.chars, encodedContentType.length * sizeof(WCHAR)) != 0)
{
return E_FAIL;
}
newContentType->chars = decoder->contentType;
newContentType->length = decoder->contentTypeLength;
return S_OK;
}
HRESULT CALLBACK DecoderStart(
_In_ void* decoderContext,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
Decoder* decoder = (Decoder*)decoderContext;
hr = ReadBlock(decoder, &decoder->contentTypeLength, sizeof(ULONG), NULL, NULL, error);
if (FAILED(hr))
{
return hr;
}
if (decoder->contentTypeLength > WsCountOf(decoder->contentType))
{
return E_FAIL;
}
hr = ReadBlock(decoder, &decoder->contentType, decoder->contentTypeLength * sizeof(WCHAR), NULL, NULL, error);
if (FAILED(hr))
{
return hr;
}
return S_OK;
}
HRESULT CALLBACK DecoderDecode(
_In_ void* decoderContext,
_Out_writes_bytes_to_(maxLength, *outLength) void* buffer,
_In_ ULONG maxLength,
_Out_ ULONG* outLength,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(asyncContext);
HRESULT hr;
Decoder* decoder = (Decoder*)decoderContext;
ULONG length;
hr = ReadBlock(decoder, buffer, maxLength, &length, NULL, error);
if (FAILED(hr))
{
return hr;
}
for (ULONG i = 0; i < length; i++)
{
((BYTE*)buffer)[i]--;
}
(*outLength) = length;
return hr;
}
HRESULT CALLBACK DecoderEnd(
_In_ void* decoderContext,
_In_opt_ const WS_ASYNC_CONTEXT* asyncContext,
_In_opt_ WS_ERROR* error)
{
UNREFERENCED_PARAMETER(decoderContext);
UNREFERENCED_PARAMETER(asyncContext);
UNREFERENCED_PARAMETER(error);
return S_OK;
}
void CALLBACK FreeDecoder(
_In_ void* decoderContext)
{
Decoder* decoder = (Decoder*)decoderContext;
delete decoder;
}
WS_CHANNEL_DECODER channelDecoder =
{
NULL,
CreateDecoder,
DecoderGetContentType,
DecoderStart,
DecoderDecode,
DecoderEnd,
FreeDecoder
};