// drpfTest

// Sample code for calling the DinkeyRemote module

// The sample code contains 2 functions. The sample code is just a guide.  

// There are two methods to loading a DRPF file. These are shown in the first two functions:
// DoUpdateCode and DoUpdateCodewithMod

// DoUpdateCode: we load the DRPF file from disk and get a handle and use it "as is" using the API
//                  call LoadDRPFFromFile. You can make some limited changes to overwrite the default
//                  behaviour by using API flags.
                     
// DoUpdateCodewithMod: we load the DRPF file from disk and load into structures. We can then modify the
//                      DRPF settings by modifying this structure. This method uses the API calls
//                      ReadDRPFEx and LoadDRPF.              

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

#include "Visual Studio 5\DinkeyRemote\resource.h"
#include "drpf.h"

#ifdef _MSC_VER
  #pragma warning(disable:4996)							// to disable warnings about sprintf etc... means we can use the same source for all compilers
#endif


char g_szAppName[] = "drpfTest";

void DisplayLastMessage(void);							// gets & displays the message from the DinkeyRemote Module


// load a DRPF file from disk and generate an update code as specified by the DRPF file
int DoUpdateCode(char *szFileDRPF) {
	DRPF_HANDLE drpfHandle;
    UPDATE_CODE_OUTPUTS Outputs;
	int err_code;

	// load DRPF from File into memory
	drpfHandle = LoadDRPFFromFile(szFileDRPF, &err_code);
	if (drpfHandle == NULL) {
		DisplayLastMessage();
		return err_code;
	}

	// generate the update code as specified by the DRPF file
	err_code = GenerateUpdateCode(drpfHandle, 0, 0, NULL, NULL, &Outputs);

	// Unload DRPF from memory
	UnloadDRPF(&drpfHandle);

	// display message (error or success)
	DisplayLastMessage();
	return err_code;
}


// load a DRPF file from disk, modify it in memory and then generate the update code
int DoUpdateCodeWithMod(char *szFileDRPF) {
	DRPF_HANDLE drpfHandle;
	int dummy1, dummy2, err_code;
	REMOTEINFO RemoteInfo;
	LICENCEINFO LicenceInfo[MAX_LICENCES];
	ALGCHANGE AlgChanges[MAX_ALG_CHANGES];
	DATACHANGE DataChanges[MAX_DATA_CHANGES];
    UPDATE_CODE_OUTPUTS Outputs;

	// in this case we need to read the DRPF into our structures, so that the DRPF values can be modified
	err_code = ReadDRPFEx(szFileDRPF, &RemoteInfo, (LICENCEINFO *)&LicenceInfo, (ALGCHANGE *)&AlgChanges, (DATACHANGE *)&DataChanges, &dummy1, &dummy2);
	if (err_code != 0) {
		DisplayLastMessage();
		return err_code;
	}

	// patch new values in the RemoteInfo, LicenceInfo, AlgChanges, DataChanges structures
	LicenceInfo[0].FeaturesFlag = 1;                        // so that the features value below will be recognised
	LicenceInfo[0].Features = 12345;
	LicenceInfo[0].AddSetExecs = 1;                         // so the executions will be added to existing
	LicenceInfo[0].Execs = 100;

	// get DRPF handle
	drpfHandle = LoadDRPF(&RemoteInfo, LicenceInfo, AlgChanges, DataChanges, &err_code);
	if (drpfHandle == NULL) {
		DisplayLastMessage();
		return err_code;
	}

	// generate the update code as specified by the DRPF file
	err_code = GenerateUpdateCode(drpfHandle, 0, 0, NULL, NULL, &Outputs);

	// Unload DRPF from memory
	UnloadDRPF(&drpfHandle);

	// display message (error or success)
	DisplayLastMessage();
	return err_code;	
}


// routine for main dialog box
BOOL CALLBACK MainDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {            
	char szFileDRPF[256];

	switch (message)
		{
		case WM_INITDIALOG:
			break;
	
		case WM_COMMAND:
			GetDlgItemText(hwnd, IDC_DRPF_PATH, szFileDRPF, sizeof(szFileDRPF));
			
			// *** Generate Update Code button clicked ***
			if (LOWORD(wParam) == IDC_UPDATE_CODE && HIWORD(wParam) == BN_CLICKED) {	
				DoUpdateCode(szFileDRPF);		
			}			

			// *** Generate Update Code with Modification button clicked ***
			if (LOWORD(wParam) == IDC_UPDATE_CODE_MOD && HIWORD(wParam) == BN_CLICKED) {
				DoUpdateCodeWithMod(szFileDRPF);
			}
						
			break;
			
		case WM_CLOSE:
			EndDialog(hwnd, TRUE);
		    return TRUE;
		}

	return FALSE;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow ) {
	// display dialog allow user to enter code
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MainDlgProc);					// display main screen
   	return 0;
}


// gets & displays the message from the last API call to the DinkeyRemote Module
void DisplayLastMessage(void) {
	char *szMessage;
	int msg_len;

	GetLastMessage(NULL, 0, &msg_len);

	szMessage  = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, msg_len);

	if (szMessage != NULL) {
		GetLastMessage(szMessage, msg_len, NULL);
		MessageBox(NULL, szMessage, g_szAppName, MB_OK);
		HeapFree(GetProcessHeap(), 0, szMessage); 
	}
	return;
}
