/* myTestDll.c */

/* Trivial functions to demonstrate calling from a Windows DLL. */

// Copyright 2025 David Ireland, DI Management Services Pty Limited
// <www.di-mgt.com.au> <www.cryptosys.net>.
// Use of this source code is governed by the Apache License 2.0
// available at https://opensource.org/license/apache-2-0

#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>

#include <string.h>
#include "myTestDll.h"

/** No input. Return the constant integer value 42 */
LONG __declspec(dllexport) __stdcall MyVoidFunc(void)
{
    return 42;
}

/* Return the integer input */
LONG __declspec(dllexport) __stdcall MyIntFunc(LONG n)
{
    return n;
}

/**
Output a copy of an input ANSI string.
@param szOutput Buffer to receive output
@param nOutChars The size of the output buffer in bytes (excluding the terminating null)
@param szInput The input ANSI string.
@param nOptions Flags. Default is zero (ignored here)
@return The number of bytes in or required for the output.
@remark Pass a NULL `szOutput` or zero `nOutChars` to find the required output length.
@remark Allocate a buffer of `n+1` bytes.
*/
LONG __declspec(dllexport) __stdcall MyStringFunc(LPSTR szOutput, DWORD nOutChars, LPCSTR szInput, DWORD nOptions)
{
    unsigned nchars = (unsigned)strlen(szInput);
    unsigned i;
    // User has just asked for output length
    if (!szOutput || nOutChars <= 0) {
        return nchars;
    }
    if (szOutput && nOutChars < nchars) {
        return -1;    // Error BUF too small
    }
    // Assumes output buffer has room for `nchars + 1` bytes.
    for (i = 0; i < nchars; i++) {
        szOutput[i] = szInput[i];
    }
    // Terminating null
    szOutput[nchars] = '\0';

    return (LONG)nchars;

}

/**
Output a copy of the input byte array.
@param lpOutput Buffer to receive output
@param nOutBytes The size of the output buffer in bytes
@param lpInput A byte array
@param nInbytes The size of the input byte array in bytes
@param nOptions Flags. Default is zero.
@return The number of bytes in or required for the output.
@remark Pass a NULL `lpInput` or zero `nOutBytes` to find the required output length.
*/
LONG __declspec(dllexport) __stdcall MyByteFunc(BYTE *lpOutput, DWORD nOutBytes, CONST BYTE *lpInput, DWORD nInBytes, DWORD nOptions)
{
    unsigned i;
    unsigned nbytes = nInBytes;

    // User has just asked for output length
    if (!lpOutput || nOutBytes <= 0) {
        return (LONG)nbytes;
    }
    if (lpOutput && nOutBytes < nbytes) {
        return -1;    // Error BUF too small
    }
    // Assumes output buffer has room for `nbytes` bytes.
    for (i = 0; i < nbytes; i++) {
        lpOutput[i] = lpInput[i];
    }

    return (LONG)nbytes;
}


LONG __declspec(dllexport) __stdcall MyUnicodeFunc(LPWSTR wsOutput, DWORD nOutChars, LPCWSTR wsInput, DWORD nOptions)
{
    // Get length of wide string in characters (1 char = 2 bytes)
    unsigned nwchars = (unsigned)wcslen(wsInput);
    unsigned i;
    // User has just asked for output length
    if (!wsOutput || nOutChars <= 0) {
        return nwchars;
    }
    if (wsOutput && nOutChars < nwchars) {
        return -1;    // Error BUF too small
    }
    // Assumes output buffer has room for `nwchars + 1` wchar_t.
    for (i = 0; i < nwchars; i++) {
        wsOutput[i] = wsInput[i];
    }
    // Terminating null
    wsOutput[nwchars] = '\0';

    return (LONG)nwchars;
}