Check correctness of my code, please
Posted: 27. Jul 2013, 14:04
I want to write DLL for taking screenshots of virtualized Windows. Host OS is Windows too. By the way, is it possible to replace TakeScreenShotToArray by TakeScreenShot for performance? However, performance is not a necessity. The beauty of the code also was not very attractive. The main requirement is hassle-free. Please look for errors very carefully. This code is assigned the top responsibility.
Code: Select all
#include <wtypes.h>
#include "VirtualBox.h"
#include "VBApi.h"
// GLOBAL VARIABLES
IVirtualBoxClient *CLIENT = NULL;
IDisplay *DISPLAY = NULL;
SAFEARRAY *BUFFER = NULL;
int PREVIOUS_INDEX = 0;
// Find running virtual machine. It's name coded by index.
// Returns pointer to display interface, NULL if something goes wrong.
IDisplay* findVM (int index) {
HRESULT rc;
if (!CLIENT) {
rc = CoCreateInstance(CLSID_VirtualBoxClient, NULL, CLSCTX_INPROC_SERVER,IID_IVirtualBoxClient, (void**)&CLIENT);
if FAILED(rc) return NULL;
}
IVirtualBox* box;
rc = CLIENT->get_VirtualBox(&box);
if FAILED(rc) return NULL;
ISession* session;
rc = CLIENT->get_Session(&session);
if FAILED(rc) return NULL;
IMachine *machine = NULL;
BSTR name;
// The code breaks all the ideological doctrine of programming, but it dosn't matter.
// If you have a idea, please implement it without explanations, because I'm ignoramus in C++ (the DLL will be used from the exotic scripting language).
switch (index) {
case 1: name = SysAllocString(L"Win2000"); break;
case 2: name = SysAllocString(L"WinXP"); break;
case 3: name = SysAllocString(L"WinVista"); break;
case 4: name = SysAllocString(L"Win7"); break;
default: return NULL;
}
rc = box->FindMachine(name, &machine);
SysFreeString(name);
if FAILED(rc) return NULL;
MachineState state = MachineState_Null;
rc = machine->get_State(&state);
if (FAILED(rc) || (state != MachineState_Running)) return NULL;
rc = machine->LockMachine(session, LockType_Shared);
if FAILED(rc) return NULL;
IConsole* console;
rc = session->get_Console(&console);
if FAILED(rc) return NULL;
IDisplay *display;
rc = console->get_Display(&display);
if FAILED(rc) return NULL;
rc = session->UnlockMachine();
if FAILED(rc) return NULL;
return display;
}
// Returns a pointer to the screenshot.
SAFEARRAY* __stdcall takeScreen(int index) {
if (index <= 0) return NULL;
if (index != PREVIOUS_INDEX) {
DISPLAY = findVM(index);
PREVIOUS_INDEX = 0; // if findVM fails, then it to be repeated at the next call of takeScreen.
if (!DISPLAY) return NULL;
PREVIOUS_INDEX = index;
}
if (BUFFER) {
SafeArrayDestroy(BUFFER);
BUFFER = NULL;
}
HRESULT rc = DISPLAY->TakeScreenShotToArray(0, 1024, 768, &BUFFER);
if FAILED(rc) return NULL;
return BUFFER;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,LPVOID lpvReserved) {
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
CoInitialize(NULL);
break;
case DLL_PROCESS_DETACH:
if (CLIENT) {
CLIENT->Release();
CLIENT = NULL;
}
if (BUFFER) {
SafeArrayDestroy(BUFFER);
BUFFER = NULL;
}
}
return TRUE;
}