VirtualBox

source: vbox/trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp@ 1713

Last change on this file since 1713 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.2 KB
Line 
1/** @file
2 *
3 * tstVBoxAPILinux - sample program to illustrate the VirtualBox
4 * XPCOM API for machine management on Linux.
5 * It only uses standard C/C++ and XPCOM semantics,
6 * no additional VBox classes/macros/helpers.
7 *
8 */
9
10/*
11 * Copyright (C) 2006 InnoTek Systemberatung GmbH
12 *
13 * This file is part of VirtualBox Open Source Edition (OSE), as
14 * available from http://www.virtualbox.org. This file is free software;
15 * you can redistribute it and/or modify it under the terms of the GNU
16 * General Public License as published by the Free Software Foundation,
17 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
18 * distribution. VirtualBox OSE is distributed in the hope that it will
19 * be useful, but WITHOUT ANY WARRANTY of any kind.
20 *
21 * If you received this file as part of a commercial VirtualBox
22 * distribution, then only the terms of your commercial VirtualBox
23 * license agreement apply instead of the previous paragraph.
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <iconv.h>
29#include <errno.h>
30
31
32/*
33 * Include the XPCOM headers
34 */
35#include <nsIServiceManager.h>
36#include <nsIComponentRegistrar.h>
37#include <nsXPCOMGlue.h>
38#include <nsMemory.h>
39#include <nsString.h>
40#include <nsIProgrammingLanguage.h>
41#include <ipcIService.h>
42#include <ipcCID.h>
43#include <ipcIDConnectService.h>
44#include <nsIEventQueueService.h>
45
46/*
47 * Some XPCOM declarations that haven't made it
48 * into the official headers yet
49 */
50#define IPC_DCONNECTSERVICE_CONTRACTID \
51 "@mozilla.org/ipc/dconnect-service;1"
52static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
53static nsIEventQueue* gEventQ = nsnull;
54
55
56/*
57 * VirtualBox XPCOM interface. This header is generated
58 * from IDL which in turn is generated from a custom XML format.
59 */
60#include "VirtualBox_XPCOM.h"
61
62/*
63 * Prototypes
64 */
65char *nsIDToString(nsID *guid);
66
67
68
69/**
70 * Display all registered VMs on the screen with some information about each
71 *
72 * @param virtualBox VirtualBox instance object.
73 */
74void listVMs(IVirtualBox *virtualBox)
75{
76 nsresult rc;
77
78 printf("----------------------------------------------------\n");
79 printf("VM List:\n\n");
80
81 /*
82 * Get the list of all registered VMs
83 */
84 IMachineCollection *collection = nsnull;
85 IMachineEnumerator *enumerator = nsnull;
86 rc = virtualBox->GetMachines(&collection);
87 if (NS_SUCCEEDED(rc))
88 rc = collection->Enumerate(&enumerator);
89 if (NS_SUCCEEDED(rc))
90 {
91 /*
92 * Iterate through the collection
93 */
94 PRBool hasMore = false;
95 while (enumerator->HasMore(&hasMore), hasMore)
96 {
97 IMachine *machine = nsnull;
98 rc = enumerator->GetNext(&machine);
99 if ((NS_SUCCEEDED(rc)) && machine)
100 {
101 nsXPIDLString machineName;
102 machine->GetName(getter_Copies(machineName));
103 char *machineNameAscii = ToNewCString(machineName);
104 printf("\tName: %s\n", machineNameAscii);
105 free(machineNameAscii);
106
107 nsID *iid = nsnull;
108 machine->GetId(&iid);
109 const char *uuidString = nsIDToString(iid);
110 printf("\tUUID: %s\n", uuidString);
111 free((void*)uuidString);
112 nsMemory::Free(iid);
113
114 nsXPIDLString configFile;
115 machine->GetSettingsFilePath(getter_Copies(configFile));
116 char *configFileAscii = ToNewCString(configFile);
117 printf("\tConfig file: %s\n", configFileAscii);
118 free(configFileAscii);
119
120 PRUint32 memorySize;
121 machine->GetMemorySize(&memorySize);
122 printf("\tMemory size: %uMB\n", memorySize);
123
124 IGuestOSType *osType = nsnull;
125 machine->GetOSType(&osType);
126 nsXPIDLString osName;
127 osType->GetDescription(getter_Copies(osName));
128 char *osNameAscii = ToNewCString(osName);
129 printf("\tGuest OS: %s\n\n", osNameAscii);
130 free(osNameAscii);
131 osType->Release();
132
133 machine->Release();
134 }
135 }
136 }
137 printf("----------------------------------------------------\n\n");
138 /* don't forget to release the objects... */
139 if (enumerator)
140 enumerator->Release();
141 if (collection)
142 collection->Release();
143}
144
145/**
146 * Create a sample VM
147 *
148 * @param virtualBox VirtualBox instance object.
149 */
150void createVM(IVirtualBox *virtualBox)
151{
152 nsresult rc;
153 /*
154 * First create a new VM. It will be unconfigured and not be saved
155 * in the configuration until we explicitely choose to do so.
156 */
157 IMachine *machine;
158 rc = virtualBox->CreateMachine(nsnull, NS_LITERAL_STRING("A brand new VM").get(), &machine);
159
160 /*
161 * Set some properties
162 */
163 /* alternative to illustrate the use of string classes */
164 char vmName[] = "A new name";
165 rc = machine->SetName(NS_ConvertUTF8toUTF16((char*)vmName).get());
166 rc = machine->SetMemorySize(128);
167
168 /*
169 * Now a more advanced property -- the guest OS type. This is
170 * an object by itself which has to be found first. Note that we
171 * use the ID of the guest OS type here which is an internal
172 * representation (you can find that by configuring the OS type of
173 * a machine in the GUI and then looking at the <Guest ostype=""/>
174 * setting in the XML file. It is also possible to get the OS type from
175 * its description (win2k would be "Windows 2000") by getting the
176 * guest OS type collection and enumerating it.
177 */
178 IGuestOSType *osType = nsnull;
179 char win2k[] = "win2k";
180 rc = virtualBox->FindGuestOSType(NS_ConvertUTF8toUTF16((char*)win2k).get(), &osType);
181 if (NS_FAILED(rc) || !osType)
182 {
183 printf("Error: could not find guest OS type! rc = 0x%x\n", rc);
184 }
185 else
186 {
187 machine->SetOSType(osType);
188 osType->Release();
189 }
190
191 /*
192 * Create a virtual harddisk
193 */
194 IHardDisk *hardDisk = 0;
195 IVirtualDiskImage *vdi = 0;
196 char vdiName[] = "TestHardDisk.vdi";
197 rc = virtualBox->CreateHardDisk(HardDiskStorageType::VirtualDiskImage,
198 &hardDisk);
199 if (NS_SUCCEEDED (rc))
200 {
201 rc = hardDisk->QueryInterface(NS_GET_IID(IVirtualDiskImage), (void **)&vdi);
202 if (NS_SUCCEEDED (rc))
203 rc = vdi->SetFilePath(NS_ConvertUTF8toUTF16((char*)vdiName).get());
204 }
205
206 if (NS_FAILED(rc) || !hardDisk || !vdi)
207 {
208 printf("Failed creating a hard disk object!\n");
209 }
210 else
211 {
212 /*
213 * We have only created an object so far. No on disk representation exists
214 * because none of its properties has been set so far. Let's continue creating
215 * a dynamically expanding image.
216 */
217 IProgress *progress;
218 rc = vdi->CreateDynamicImage(100, // size in megabytes
219 &progress); // optional progress object
220 if (NS_FAILED(rc) || !progress)
221 {
222 printf("Failed creating hard disk image!\n");
223 }
224 else
225 {
226 /*
227 * Creating the image is done in the background because it can take quite
228 * some time (at least fixed size images). We have to wait for its completion.
229 * Here we wait forever (timeout -1) which is potentially dangerous.
230 */
231 rc = progress->WaitForCompletion(-1);
232 nsresult resultCode;
233 progress->GetResultCode(&resultCode);
234 progress->Release();
235 if (NS_FAILED(rc) || (resultCode != 0))
236 {
237 printf("Error: could not create hard disk!\n");
238 }
239 else
240 {
241 /*
242 * Now we have to register the new hard disk with VirtualBox.
243 */
244 rc = virtualBox->RegisterHardDisk(hardDisk);
245 if (NS_FAILED(rc))
246 {
247 printf("Error: could not register hard disk!\n");
248 }
249 else
250 {
251 /*
252 * Now that it's registered, we can assign it to the VM. This is done
253 * by UUID, so query that one fist. The UUID has been assigned automatically
254 * when we've created the image.
255 */
256 nsID *vdiUUID = nsnull;
257 hardDisk->GetId(&vdiUUID);
258 rc = machine->AttachHardDisk(*vdiUUID,
259 DiskControllerType::IDE0Controller, // controler identifier
260 0); // device number on the controller
261 nsMemory::Free(vdiUUID);
262 if (NS_FAILED(rc))
263 {
264 printf("Error: could not attach hard disk!\n");
265 }
266 }
267 }
268 }
269 }
270 if (vdi)
271 vdi->Release();
272 if (hardDisk)
273 hardDisk->Release();
274
275 /*
276 * It's got a hard disk but that one is new and thus not bootable. Make it
277 * boot from an ISO file. This requires some processing. First the ISO file
278 * has to be registered and then mounted to the VM's DVD drive and selected
279 * as the boot device.
280 */
281 nsID uuid = {0};
282 IDVDImage *dvdImage = nsnull;
283 char isoFile[] = "/home/achimha/isoimages/winnt4ger.iso";
284
285 rc = virtualBox->OpenDVDImage(NS_ConvertUTF8toUTF16((char*)isoFile).get(),
286 uuid, /* NULL UUID, i.e. a new one will be created */
287 &dvdImage);
288 if (NS_FAILED(rc) || !dvdImage)
289 {
290 printf("Error: could not open CD image!\n");
291 }
292 else
293 {
294 /*
295 * Register it with VBox
296 */
297 rc = virtualBox->RegisterDVDImage(dvdImage);
298 if (NS_FAILED(rc) || !dvdImage)
299 {
300 printf("Error: could not register CD image!\n");
301 }
302 else
303 {
304 /*
305 * Now assign it to our VM
306 */
307 nsID *isoUUID = nsnull;
308 dvdImage->GetId(&isoUUID);
309 IDVDDrive *dvdDrive = nsnull;
310 machine->GetDVDDrive(&dvdDrive);
311 rc = dvdDrive->MountImage(*isoUUID);
312 nsMemory::Free(isoUUID);
313 if (NS_FAILED(rc))
314 {
315 printf("Error: could not mount ISO image!\n");
316 }
317 else
318 {
319 /*
320 * Last step: tell the VM to boot from the CD.
321 */
322 rc = machine->SetBootOrder (1, DeviceType::DVDDevice);
323 if (NS_FAILED(rc))
324 {
325 printf("Could not set boot device!\n");
326 }
327 }
328 dvdDrive->Release();
329 dvdImage->Release();
330 }
331 }
332
333 /*
334 * Register the VM. Note that this call also saves the VM config
335 * to disk. It is also possible to save the VM settings but not
336 * register the VM.
337 */
338 virtualBox->RegisterMachine(machine);
339
340 machine->Release();
341}
342
343// main
344///////////////////////////////////////////////////////////////////////////////
345
346int main(int argc, char *argv[])
347{
348 nsresult rc;
349
350 /*
351 * This is the standard XPCOM init processing.
352 * What we do is just follow the required steps to get an instance
353 * of our main interface, which is IVirtualBox
354 */
355 XPCOMGlueStartup(nsnull);
356 nsCOMPtr<nsIServiceManager> serviceManager;
357 rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull);
358 if (NS_FAILED(rc))
359 {
360 printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc);
361 return -1;
362 }
363
364 // register our component
365 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager);
366 if (!registrar)
367 {
368 printf("Error: could not query nsIComponentRegistrar interface!\n");
369 return -1;
370 }
371 registrar->AutoRegister(nsnull);
372
373 // Create the Event Queue for this thread
374 nsCOMPtr<nsIEventQueueService> eqs = do_GetService(kEventQueueServiceCID, &rc);
375 if (NS_FAILED( rc ))
376 {
377 printf("Error: could not get event queue service! rc=%08X\n", rc);
378 return -1;
379 }
380
381 rc = eqs->CreateThreadEventQueue();
382 if (NS_FAILED( rc ))
383 {
384 printf("Error: could not create thread event queue! rc=%08X\n", rc);
385 return -1;
386 }
387
388 rc = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
389 if (NS_FAILED( rc ))
390 {
391 printf("Error: could not get tread event queue! rc=%08X\n", rc);
392 return -1;
393 }
394
395 // get ipc service
396 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
397 if (NS_FAILED( rc ))
398 {
399 printf("Error: could not get ipc service! rc=%08X\n", rc);
400 return -1;
401 }
402
403 // get dconnect service
404 nsCOMPtr<ipcIDConnectService> dcon = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
405 if (NS_FAILED( rc ))
406 {
407 printf("Error: could not get dconnect service! rc=%08X\n", rc);
408 return -1;
409 }
410
411 PRUint32 serverID = 0;
412 rc = ipcServ->ResolveClientName("VirtualBoxServer", &serverID);
413 if (NS_FAILED( rc ))
414 {
415 printf("Error: could not get VirtualBox server ID! rc=%08X\n", rc);
416 return -1;
417 }
418
419 nsCOMPtr<nsIComponentManager> manager = do_QueryInterface(registrar);
420 if (!manager)
421 {
422 printf("Error: could not query nsIComponentManager interface!\n");
423 return -1;
424 }
425
426 /*
427 * Now XPCOM is ready and we can start to do real work.
428 * IVirtualBox is the root interface of VirtualBox and will be
429 * retrieved from the XPCOM component registrar. We use the
430 * XPCOM provided smart pointer nsCOMPtr for all objects because
431 * that's very convenient and removes the need deal with reference
432 * counting and freeing.
433 */
434 nsCOMPtr<IVirtualBox> virtualBox;
435 rc = dcon->CreateInstanceByContractID(serverID, NS_VIRTUALBOX_CONTRACTID,
436 NS_GET_IID(IVirtualBox),
437 getter_AddRefs(virtualBox));
438 if (NS_FAILED(rc))
439 {
440 printf("Error, could not instantiate VirtualBox object! rc=0x%x\n", rc);
441 return -1;
442 }
443 printf("VirtualBox object created\n");
444
445 ////////////////////////////////////////////////////////////////////////////////
446 ////////////////////////////////////////////////////////////////////////////////
447 ////////////////////////////////////////////////////////////////////////////////
448
449
450 listVMs(virtualBox);
451
452 createVM(virtualBox);
453
454
455 ////////////////////////////////////////////////////////////////////////////////
456 ////////////////////////////////////////////////////////////////////////////////
457 ////////////////////////////////////////////////////////////////////////////////
458
459 /* this is enough to free the IVirtualBox instance -- smart pointers rule! */
460 virtualBox = nsnull;
461
462 /*
463 * Process events that might have queued up in the XPCOM event
464 * queue. If we don't process them, the server might hang.
465 */
466 gEventQ->ProcessPendingEvents();
467
468 /*
469 * Perform the standard XPCOM shutdown procedure
470 */
471 NS_ShutdownXPCOM(nsnull);
472 XPCOMGlueShutdown();
473 printf("Done!\n");
474 return 0;
475}
476
477
478//////////////////////////////////////////////////////////////////////////////////////////////////////
479//// Helpers
480//////////////////////////////////////////////////////////////////////////////////////////////////////
481
482/**
483 * Helper function to convert an nsID into a human readable string
484 *
485 * @returns result string, allocated. Has to be freed using free()
486 * @param guid Pointer to nsID that will be converted.
487 */
488char *nsIDToString(nsID *guid)
489{
490 char *res = (char*)malloc(39);
491
492 if (res != NULL)
493 {
494 snprintf(res, 39, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
495 guid->m0, (PRUint32)guid->m1, (PRUint32)guid->m2,
496 (PRUint32)guid->m3[0], (PRUint32)guid->m3[1], (PRUint32)guid->m3[2],
497 (PRUint32)guid->m3[3], (PRUint32)guid->m3[4], (PRUint32)guid->m3[5],
498 (PRUint32)guid->m3[6], (PRUint32)guid->m3[7]);
499 }
500 return res;
501}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette