/*!
 * @file powershell_bindings.cpp
 * @brief Wrapper functions for bridging native meterp calls to powershell
 */
extern "C" {
#include "common.h"
#include "common_metapi.h"
#include "powershell_bindings.h"
}

Remote* gRemote = NULL;

VOID MeterpreterInvoke(unsigned int isLocal, unsigned char* input, unsigned int inputLength, unsigned char** output, unsigned int* outputLength)
{
	dprintf("[PSH BINDING] Input %p of %d bytes received", input, inputLength);

	Packet packet = { 0 };
	packet.header = *(PacketHeader*)input;
	packet.header.length = ntohl(packet.header.length);
	packet.payload = (PUCHAR)(input + sizeof(PacketHeader));
	packet.payloadLength = (ULONG)inputLength - sizeof(PacketHeader);
	packet.local = isLocal == 1;

	dprintf("[PSH BINDING] Packet header length:  %u", packet.header.length);
	dprintf("[PSH BINDING] Packet header type:    %u", packet.header.type);
	dprintf("[PSH BINDING] Packet payload length: %u", packet.payloadLength);
	dprintf("[PSH BINDING] Packet local flag:     %u", isLocal);
	dprintf("[PSH BINDING] Request ID:            %s", met_api->packet.get_tlv_value_string(&packet, TLV_TYPE_REQUEST_ID));
	dprintf("[PSH BINDING] Command ID:            %u", met_api->packet.get_tlv_value_uint(&packet, TLV_TYPE_COMMAND_ID));

	met_api->command.handle(gRemote, &packet);

	if (packet.partner != NULL)
	{
		dprintf("[PSH BINDING] Response packet generated");
		// This memory is deliberately left allocated, because the .NET side will clean it up
		*output = (unsigned char*)LocalAlloc(LPTR, packet.partner->payloadLength);
		*outputLength = packet.partner->payloadLength;
		memcpy(*output, packet.partner->payload, packet.partner->payloadLength);
		dprintf("[PSH BINDING] Partner packet copied");
		met_api->packet.destroy(packet.partner);
		dprintf("[PSH BINDING] Partner packet destroyed");
	}
	else
	{
		dprintf("[PSH BINDING] Response packet not generated");
		*output = NULL;
		*outputLength = 0;
	}
	dprintf("[PSH BINDING] MeterpreterInvoke done.");
}