VirtualBox

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

Last change on this file since 2981 was 2981, checked in by vboxsync, 18 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.3 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-2007 innotek 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 nsXPIDLString typeId;
125 machine->GetOSTypeId(getter_Copies(typeId));
126 IGuestOSType *osType = nsnull;
127 virtualBox->GetGuestOSType (typeId.get(), &osType);
128 nsXPIDLString osName;
129 osType->GetDescription(getter_Copies(osName));
130 char *osNameAscii = ToNewCString(osName);
131 printf("\tGuest OS: %s\n\n", osNameAscii);
132 free(osNameAscii);
133 osType->Release();
134
135 machine->Release();
136 }
137 }
138 }
139 printf("----------------------------------------------------\n\n");
140 /* don't forget to release the objects... */
141 if (enumerator)
142 enumerator->Release();
143 if (collection)
144 collection->Release();
145}
146
147/**
148 * Create a sample VM
149 *
150 * @param virtualBox VirtualBox instance object.
151 */
152void createVM(IVirtualBox *virtualBox)
153{
154 nsresult rc;
155 /*
156 * First create a new VM. It will be unconfigured and not be saved
157 * in the configuration until we explicitely choose to do so.
158 */
159 IMachine *machine;
160 rc = virtualBox->CreateMachine(nsnull, NS_LITERAL_STRING("A brand new VM").get(), &machine);
161
162 /*
163 * Set some properties
164 */
165 /* alternative to illustrate the use of string classes */
166 char vmName[] = "A new name";
167 rc = machine->SetName(NS_ConvertUTF8toUTF16((char*)vmName).get());
168 rc = machine->SetMemorySize(128);
169
170 /*
171 * Now a more advanced property -- the guest OS type. This is
172 * an object by itself which has to be found first. Note that we
173 * use the ID of the guest OS type here which is an internal
174 * representation (you can find that by configuring the OS type of
175 * a machine in the GUI and then looking at the <Guest ostype=""/>
176 * setting in the XML file. It is also possible to get the OS type from
177 * its description (win2k would be "Windows 2000") by getting the
178 * guest OS type collection and enumerating it.
179 */
180 IGuestOSType *osType = nsnull;
181 char win2k[] = "win2k";
182 rc = virtualBox->GetGuestOSType(NS_ConvertUTF8toUTF16((char*) win2k).get(), &osType);
183 if (NS_FAILED(rc) || !osType)
184 {
185 printf("Error: could not find guest OS type! rc = 0x%x\n", rc);
186 }
187 else
188 {
189 machine->SetOSTypeId (NS_ConvertUTF8toUTF16((char*) win2k).get());
190 osType->Release();
191 }
192
193 /*
194 * Create a virtual harddisk
195 */
196 IHardDisk *hardDisk = 0;
197 IVirtualDiskImage *vdi = 0;
198 char vdiName[] = "TestHardDisk.vdi";
199 rc = virtualBox->CreateHardDisk(HardDiskStorageType::VirtualDiskImage,
200 &hardDisk);
201 if (NS_SUCCEEDED (rc))
202 {
203 rc = hardDisk->QueryInterface(NS_GET_IID(IVirtualDiskImage), (void **)&vdi);
204 if (NS_SUCCEEDED (rc))
205 rc = vdi->SetFilePath(NS_ConvertUTF8toUTF16((char*)vdiName).get());
206 }
207
208 if (NS_FAILED(rc) || !hardDisk || !vdi)
209 {
210 printf("Failed creating a hard disk object!\n");
211 }
212 else
213 {
214 /*
215 * We have only created an object so far. No on disk representation exists
216 * because none of its properties has been set so far. Let's continue creating
217 * a dynamically expanding image.
218 */
219 IProgress *progress;
220 rc = vdi->CreateDynamicImage(100, // size in megabytes
221 &progress); // optional progress object
222 if (NS_FAILED(rc) || !progress)
223 {
224 printf("Failed creating hard disk image!\n");
225 }
226 else
227 {
228 /*
229 * Creating the image is done in the background because it can take quite
230 * some time (at least fixed size images). We have to wait for its completion.
231 * Here we wait forever (timeout -1) which is potentially dangerous.
232 */
233 rc = progress->WaitForCompletion(-1);
234 nsresult resultCode;
235 progress->GetResultCode(&resultCode);
236 progress->Release();
237 if (NS_FAILED(rc) || (resultCode != 0))
238 {
239 printf("Error: could not create hard disk!\n");
240 }
241 else
242 {
243 /*
244 * Now we have to register the new hard disk with VirtualBox.
245 */
246 rc = virtualBox->RegisterHardDisk(hardDisk);
247 if (NS_FAILED(rc))
248 {
249 printf("Error: could not register hard disk!\n");
250 }
251 else
252 {
253 /*
254 * Now that it's registered, we can assign it to the VM. This is done
255 * by UUID, so query that one fist. The UUID has been assigned automatically
256 * when we've created the image.
257 */
258 nsID *vdiUUID = nsnull;
259 hardDisk->GetId(&vdiUUID);
260 rc = machine->AttachHardDisk(*vdiUUID,
261 DiskControllerType::IDE0Controller, // controler identifier
262 0); // device number on the controller
263 nsMemory::Free(vdiUUID);
264 if (NS_FAILED(rc))
265 {
266 printf("Error: could not attach hard disk!\n");
267 }
268 }
269 }
270 }
271 }
272 if (vdi)
273 vdi->Release();
274 if (hardDisk)
275 hardDisk->Release();
276
277 /*
278 * It's got a hard disk but that one is new and thus not bootable. Make it
279 * boot from an ISO file. This requires some processing. First the ISO file
280 * has to be registered and then mounted to the VM's DVD drive and selected
281 * as the boot device.
282 */
283 nsID uuid = {0};
284 IDVDImage *dvdImage = nsnull;
285 char isoFile[] = "/home/achimha/isoimages/winnt4ger.iso";
286
287 rc = virtualBox->OpenDVDImage(NS_ConvertUTF8toUTF16((char*)isoFile).get(),
288 uuid, /* NULL UUID, i.e. a new one will be created */
289 &dvdImage);
290 if (NS_FAILED(rc) || !dvdImage)
291 {
292 printf("Error: could not open CD image!\n");
293 }
294 else
295 {
296 /*
297 * Register it with VBox
298 */
299 rc = virtualBox->RegisterDVDImage(dvdImage);
300 if (NS_FAILED(rc) || !dvdImage)
301 {
302 printf("Error: could not register CD image!\n");
303 }
304 else
305 {
306 /*
307 * Now assign it to our VM
308 */
309 nsID *isoUUID = nsnull;
310 dvdImage->GetId(&isoUUID);
311 IDVDDrive *dvdDrive = nsnull;
312 machine->GetDVDDrive(&dvdDrive);
313 rc = dvdDrive->MountImage(*isoUUID);
314 nsMemory::Free(isoUUID);
315 if (NS_FAILED(rc))
316 {
317 printf("Error: could not mount ISO image!\n");
318 }
319 else
320 {
321 /*
322 * Last step: tell the VM to boot from the CD.
323 */
324 rc = machine->SetBootOrder (1, DeviceType::DVDDevice);
325 if (NS_FAILED(rc))
326 {
327 printf("Could not set boot device!\n");
328 }
329 }
330 dvdDrive->Release();
331 dvdImage->Release();
332 }
333 }
334
335 /*
336 * Register the VM. Note that this call also saves the VM config
337 * to disk. It is also possible to save the VM settings but not
338 * register the VM.
339 */
340 virtualBox->RegisterMachine(machine);
341
342 machine->Release();
343}
344
345// main
346///////////////////////////////////////////////////////////////////////////////
347
348int main(int argc, char *argv[])
349{
350 nsresult rc;
351
352 /*
353 * This is the standard XPCOM init processing.
354 * What we do is just follow the required steps to get an instance
355 * of our main interface, which is IVirtualBox
356 */
357 XPCOMGlueStartup(nsnull);
358 nsCOMPtr<nsIServiceManager> serviceManager;
359 rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), nsnull, nsnull);
360 if (NS_FAILED(rc))
361 {
362 printf("Error: XPCOM could not be initialized! rc=0x%x\n", rc);
363 return -1;
364 }
365
366 // register our component
367 nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(serviceManager);
368 if (!registrar)
369 {
370 printf("Error: could not query nsIComponentRegistrar interface!\n");
371 return -1;
372 }
373 registrar->AutoRegister(nsnull);
374
375 // Create the Event Queue for this thread
376 nsCOMPtr<nsIEventQueueService> eqs = do_GetService(kEventQueueServiceCID, &rc);
377 if (NS_FAILED( rc ))
378 {
379 printf("Error: could not get event queue service! rc=%08X\n", rc);
380 return -1;
381 }
382
383 rc = eqs->CreateThreadEventQueue();
384 if (NS_FAILED( rc ))
385 {
386 printf("Error: could not create thread event queue! rc=%08X\n", rc);
387 return -1;
388 }
389
390 rc = eqs->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
391 if (NS_FAILED( rc ))
392 {
393 printf("Error: could not get tread event queue! rc=%08X\n", rc);
394 return -1;
395 }
396
397 // get ipc service
398 nsCOMPtr<ipcIService> ipcServ = do_GetService(IPC_SERVICE_CONTRACTID, &rc);
399 if (NS_FAILED( rc ))
400 {
401 printf("Error: could not get ipc service! rc=%08X\n", rc);
402 return -1;
403 }
404
405 // get dconnect service
406 nsCOMPtr<ipcIDConnectService> dcon = do_GetService(IPC_DCONNECTSERVICE_CONTRACTID, &rc);
407 if (NS_FAILED( rc ))
408 {
409 printf("Error: could not get dconnect service! rc=%08X\n", rc);
410 return -1;
411 }
412
413 PRUint32 serverID = 0;
414 rc = ipcServ->ResolveClientName("VirtualBoxServer", &serverID);
415 if (NS_FAILED( rc ))
416 {
417 printf("Error: could not get VirtualBox server ID! rc=%08X\n", rc);
418 return -1;
419 }
420
421 nsCOMPtr<nsIComponentManager> manager = do_QueryInterface(registrar);
422 if (!manager)
423 {
424 printf("Error: could not query nsIComponentManager interface!\n");
425 return -1;
426 }
427
428 /*
429 * Now XPCOM is ready and we can start to do real work.
430 * IVirtualBox is the root interface of VirtualBox and will be
431 * retrieved from the XPCOM component registrar. We use the
432 * XPCOM provided smart pointer nsCOMPtr for all objects because
433 * that's very convenient and removes the need deal with reference
434 * counting and freeing.
435 */
436 nsCOMPtr<IVirtualBox> virtualBox;
437 rc = dcon->CreateInstanceByContractID(serverID, NS_VIRTUALBOX_CONTRACTID,
438 NS_GET_IID(IVirtualBox),
439 getter_AddRefs(virtualBox));
440 if (NS_FAILED(rc))
441 {
442 printf("Error, could not instantiate VirtualBox object! rc=0x%x\n", rc);
443 return -1;
444 }
445 printf("VirtualBox object created\n");
446
447 ////////////////////////////////////////////////////////////////////////////////
448 ////////////////////////////////////////////////////////////////////////////////
449 ////////////////////////////////////////////////////////////////////////////////
450
451
452 listVMs(virtualBox);
453
454 createVM(virtualBox);
455
456
457 ////////////////////////////////////////////////////////////////////////////////
458 ////////////////////////////////////////////////////////////////////////////////
459 ////////////////////////////////////////////////////////////////////////////////
460
461 /* this is enough to free the IVirtualBox instance -- smart pointers rule! */
462 virtualBox = nsnull;
463
464 /*
465 * Process events that might have queued up in the XPCOM event
466 * queue. If we don't process them, the server might hang.
467 */
468 gEventQ->ProcessPendingEvents();
469
470 /*
471 * Perform the standard XPCOM shutdown procedure
472 */
473 NS_ShutdownXPCOM(nsnull);
474 XPCOMGlueShutdown();
475 printf("Done!\n");
476 return 0;
477}
478
479
480//////////////////////////////////////////////////////////////////////////////////////////////////////
481//// Helpers
482//////////////////////////////////////////////////////////////////////////////////////////////////////
483
484/**
485 * Helper function to convert an nsID into a human readable string
486 *
487 * @returns result string, allocated. Has to be freed using free()
488 * @param guid Pointer to nsID that will be converted.
489 */
490char *nsIDToString(nsID *guid)
491{
492 char *res = (char*)malloc(39);
493
494 if (res != NULL)
495 {
496 snprintf(res, 39, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
497 guid->m0, (PRUint32)guid->m1, (PRUint32)guid->m2,
498 (PRUint32)guid->m3[0], (PRUint32)guid->m3[1], (PRUint32)guid->m3[2],
499 (PRUint32)guid->m3[3], (PRUint32)guid->m3[4], (PRUint32)guid->m3[5],
500 (PRUint32)guid->m3[6], (PRUint32)guid->m3[7]);
501 }
502 return res;
503}
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