/** * Start a VM. * * @param argv0 executable name * @param virtualBox ptr to IVirtualBox object * @param session ptr to ISession object * @param id identifies the machine to start */ static void startVM(const char *argv0, IVirtualBox *virtualBox, ISession *session, BSTR id) { HRESULT rc; IMachine *machine = NULL; IProgress *progress = NULL; BSTR env = NULL; BSTR sessionType; SAFEARRAY *groupsSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc(); rc = IVirtualBox_FindMachine(virtualBox, id, &machine); if (FAILED(rc) || !machine) { PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", rc); return; } rc = IMachine_get_Groups(machine, ComSafeArrayAsOutTypeParam(groupsSA, BSTR)); if (SUCCEEDED(rc)) { BSTR *groups = NULL; ULONG cbGroups = 0; ULONG i, cGroups; g_pVBoxFuncs->pfnSafeArrayCopyOutParamHelper((void **)&groups, &cbGroups, VT_BSTR, groupsSA); g_pVBoxFuncs->pfnSafeArrayDestroy(groupsSA); cGroups = cbGroups / sizeof(groups[0]); for (i = 0; i < cGroups; ++i) { /* Note that the use of %S might be tempting, but it is not * available on all platforms, and even where it is usable it * may depend on correct compiler options to make wchar_t a * 16 bit number. So better play safe and use UTF-8. */ char *group; g_pVBoxFuncs->pfnUtf16ToUtf8(groups[i], &group); printf("Groups[%d]: %s\n", i, group); g_pVBoxFuncs->pfnUtf8Free(group); } for (i = 0; i < cGroups; ++i) g_pVBoxFuncs->pfnComUnallocString(groups[i]); g_pVBoxFuncs->pfnArrayOutFree(groups); } g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType); rc = IMachine_LaunchVMProcess(machine, session, sessionType, env, &progress); g_pVBoxFuncs->pfnUtf16Free(sessionType); if (SUCCEEDED(rc)) { BOOL completed; LONG resultCode; printf("Waiting for the remote session to open...\n"); IProgress_WaitForCompletion(progress, -1); rc = IProgress_get_Completed(progress, &completed); if (FAILED(rc)) fprintf(stderr, "Error: GetCompleted status failed\n"); IProgress_get_ResultCode(progress, &resultCode); if (FAILED(resultCode)) { IVirtualBoxErrorInfo *errorInfo; BSTR textUtf16; char *text; IProgress_get_ErrorInfo(progress, &errorInfo); IVirtualBoxErrorInfo_get_Text(errorInfo, &textUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text); printf("Error: %s\n", text); g_pVBoxFuncs->pfnComUnallocString(textUtf16); g_pVBoxFuncs->pfnUtf8Free(text); IVirtualBoxErrorInfo_Release(errorInfo); } else { fprintf(stderr, "VM process has been successfully started\n"); /* Kick off the event listener demo part, which is quite separate. * Ignore it if you need a more basic sample. */ #ifdef USE_ACTIVE_EVENT_LISTENER registerActiveEventListener(virtualBox, session); #else registerPassiveEventListener(session); #endif } IProgress_Release(progress); } else PrintErrorInfo(argv0, "Error: LaunchVMProcess failed", rc); /* It's important to always release resources. */ IMachine_Release(machine); }
/** * List the registered VMs. * * @param argv0 executable name * @param virtualBox ptr to IVirtualBox object * @param session ptr to ISession object */ static void listVMs(const char *argv0, IVirtualBox *virtualBox, ISession *session) { HRESULT rc; SAFEARRAY *machinesSA = g_pVBoxFuncs->pfnSafeArrayOutParamAlloc(); IMachine **machines = NULL; ULONG machineCnt = 0; ULONG i; unsigned start_id; /* * Get the list of all registered VMs. */ rc = IVirtualBox_get_Machines(virtualBox, ComSafeArrayAsOutIfaceParam(machinesSA, IMachine *)); if (FAILED(rc)) { PrintErrorInfo(argv0, "could not get list of machines", rc); return; } /* * Extract interface pointers from machinesSA, and update the reference * counter of each object, as destroying machinesSA would call Release. */ g_pVBoxFuncs->pfnSafeArrayCopyOutIfaceParamHelper((IUnknown ***)&machines, &machineCnt, machinesSA); g_pVBoxFuncs->pfnSafeArrayDestroy(machinesSA); if (!machineCnt) { g_pVBoxFuncs->pfnArrayOutFree(machines); printf("\tNo VMs\n"); return; } printf("VM List:\n\n"); /* * Iterate through the collection. */ for (i = 0; i < machineCnt; ++i) { IMachine *machine = machines[i]; BOOL isAccessible = FALSE; printf("\tMachine #%u\n", (unsigned)i); if (!machine) { printf("\t(skipped, NULL)\n"); continue; } IMachine_get_Accessible(machine, &isAccessible); if (isAccessible) { BSTR machineNameUtf16; char *machineName; IMachine_get_Name(machine, &machineNameUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(machineNameUtf16,&machineName); g_pVBoxFuncs->pfnComUnallocString(machineNameUtf16); printf("\tName: %s\n", machineName); g_pVBoxFuncs->pfnUtf8Free(machineName); } else printf("\tName: <inaccessible>\n"); { BSTR uuidUtf16; char *uuidUtf8; IMachine_get_Id(machine, &uuidUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(uuidUtf16, &uuidUtf8); g_pVBoxFuncs->pfnComUnallocString(uuidUtf16); printf("\tUUID: %s\n", uuidUtf8); g_pVBoxFuncs->pfnUtf8Free(uuidUtf8); } if (isAccessible) { { BSTR configFileUtf16; char *configFileUtf8; IMachine_get_SettingsFilePath(machine, &configFileUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(configFileUtf16, &configFileUtf8); g_pVBoxFuncs->pfnComUnallocString(configFileUtf16); printf("\tConfig file: %s\n", configFileUtf8); g_pVBoxFuncs->pfnUtf8Free(configFileUtf8); } { ULONG memorySize; IMachine_get_MemorySize(machine, &memorySize); printf("\tMemory size: %uMB\n", memorySize); } { BSTR typeId; BSTR osNameUtf16; char *osName; IGuestOSType *osType = NULL; IMachine_get_OSTypeId(machine, &typeId); IVirtualBox_GetGuestOSType(virtualBox, typeId, &osType); g_pVBoxFuncs->pfnComUnallocString(typeId); IGuestOSType_get_Description(osType, &osNameUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(osNameUtf16,&osName); g_pVBoxFuncs->pfnComUnallocString(osNameUtf16); printf("\tGuest OS: %s\n\n", osName); g_pVBoxFuncs->pfnUtf8Free(osName); IGuestOSType_Release(osType); } } } /* * Let the user chose a machine to start. */ printf("Type Machine# to start (0 - %u) or 'quit' to do nothing: ", (unsigned)(machineCnt - 1)); fflush(stdout); if (scanf("%u", &start_id) == 1 && start_id < machineCnt) { IMachine *machine = machines[start_id]; if (machine) { BSTR uuidUtf16 = NULL; IMachine_get_Id(machine, &uuidUtf16); startVM(argv0, virtualBox, session, uuidUtf16); g_pVBoxFuncs->pfnComUnallocString(uuidUtf16); } } /* * Don't forget to release the objects in the array. */ for (i = 0; i < machineCnt; ++i) { IMachine *machine = machines[i]; if (machine) IMachine_Release(machine); } g_pVBoxFuncs->pfnArrayOutFree(machines); }
/** * Start a VM. * * @param argv0 executable name * @param virtualBox ptr to IVirtualBox object * @param session ptr to ISession object * @param id identifies the machine to start */ static void startVM(const char *argv0, IVirtualBox *virtualBox, ISession *session, BSTR id) { HRESULT rc; IMachine *machine = NULL; IProgress *progress = NULL; BSTR env = NULL; BSTR sessionType; rc = IVirtualBox_FindMachine(virtualBox, id, &machine); if (FAILED(rc) || !machine) { PrintErrorInfo(argv0, "Error: Couldn't get the Machine reference", rc); return; } g_pVBoxFuncs->pfnUtf8ToUtf16("gui", &sessionType); rc = IMachine_LaunchVMProcess(machine, session, sessionType, env, &progress); g_pVBoxFuncs->pfnUtf16Free(sessionType); if (SUCCEEDED(rc)) { BOOL completed; LONG resultCode; printf("Waiting for the remote session to open...\n"); IProgress_WaitForCompletion(progress, -1); rc = IProgress_get_Completed(progress, &completed); if (FAILED(rc)) fprintf(stderr, "Error: GetCompleted status failed\n"); IProgress_get_ResultCode(progress, &resultCode); if (FAILED(resultCode)) { IVirtualBoxErrorInfo *errorInfo; BSTR textUtf16; char *text; IProgress_get_ErrorInfo(progress, &errorInfo); IVirtualBoxErrorInfo_get_Text(errorInfo, &textUtf16); g_pVBoxFuncs->pfnUtf16ToUtf8(textUtf16, &text); printf("Error: %s\n", text); g_pVBoxFuncs->pfnComUnallocString(textUtf16); g_pVBoxFuncs->pfnUtf8Free(text); IVirtualBoxErrorInfo_Release(errorInfo); } else { fprintf(stderr, "VM process has been successfully started\n"); /* Kick off the event listener demo part, which is quite separate. * Ignore it if you need a more basic sample. */ #ifdef USE_ACTIVE_EVENT_LISTENER registerActiveEventListener(virtualBox, session, id); #else /* !USE_ACTIVE_EVENT_LISTENER */ registerPassiveEventListener(virtualBox, session, id); #endif /* !USE_ACTIVE_EVENT_LISTENER */ } IProgress_Release(progress); } else PrintErrorInfo(argv0, "Error: LaunchVMProcess failed", rc); /* It's important to always release resources. */ IMachine_Release(machine); }