#include <tchar.h>
#include <stdio.h>
#include <atlbase.h>
#include <windows.h>

#pragma warning (disable : 4192)

//
// Import TLB from DLL 
//
// Note: Make sure either you have the DLL in the current directory, or point 
//       it to the correct directory on you drive.
//
#import "capicom.dll"

//
// Use CAPICOM namespace.
//
using namespace CAPICOM;
using namespace std;

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  Module: main()

  Remark: Entry point of CAPICOM Store C++ sample.

-----------------------------------------------------------------------------*/

void Usage () {
	printf ("RHB64Encoder - base64 encode files\n");
	printf ("-----------------------------------\n");
	printf ("\n");
	printf ("RHBase64Encoder <input filename> <output filename>\n");
}

int __cdecl _tmain (int argc, _TCHAR  * argv[])
{
    HRESULT hr = S_OK;

    //
    // Initialize COM library.
    //
    CoInitialize(0);

	if (argc != 3) {
		Usage();
		exit (1);
	}
	
    try
    {
		int nFileLen;
		char *buf;
		FILE *fp;
		_bstr_t b;
		
		_wfopen_s (&fp, argv[1], L"rb");
		if (!fp) {
			printf ("Error opening input file\n");
			exit (2);
		}
		
		// Get file length
		fseek (fp, 0, SEEK_END);
		nFileLen = ftell(fp);
		fseek (fp, 0, SEEK_SET);
		
		// Allocate buffer
		buf = (char *) malloc (nFileLen + 1);
		if (!buf) {
			printf ("Error allocating memory\n");
			exit (3);
		}
		
		fread (buf, nFileLen, 1, fp);
		fclose (fp);
		
		// Convert to _bstr_t
		_bstr_t btFile;
		btFile.Assign (SysAllocStringByteLen(buf, nFileLen));
		
		// Base64 encode
        IUtilitiesPtr pIUtils(__uuidof(Utilities));
        b = pIUtils->Base64Encode (btFile);
        
        // Write output to file
        _wfopen_s (&fp, argv[2], L"w");
		if (!fp) {
			printf ("Error opening output file\n");
			exit (4);
		}

        fwprintf (fp, L"%s",(wchar_t *)b);
        fclose (fp);
    } catch (_com_error e) {
        hr = e.Error();
        ATLTRACE(_T("Error [%#x]: %s.\n"), hr, e.ErrorMessage());
    } catch (HRESULT hr) {
        ATLTRACE(_T("Error [%#x]: CAPICOM error.\n"), hr);
    } catch(...) {
        hr = CAPICOM_E_UNKNOWN;
        ATLTRACE(_T("Unknown error.\n"));
    }

    CoUninitialize();

    return (int) hr;
}