bbrowning-virtualbox 0.7.6.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. data/.gitignore +8 -0
  2. data/.yardopts +3 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +19 -0
  5. data/Rakefile +33 -0
  6. data/Readme.md +70 -0
  7. data/docs/GettingStarted.md +196 -0
  8. data/docs/WhatsNew.md +12 -0
  9. data/features/README.md +33 -0
  10. data/features/global.feature +19 -0
  11. data/features/global_extra_data.feature +27 -0
  12. data/features/step_definitions/abstract_model_steps.rb +39 -0
  13. data/features/step_definitions/extra_data_steps.rb +36 -0
  14. data/features/step_definitions/global_steps.rb +29 -0
  15. data/features/step_definitions/nat_engine_steps.rb +76 -0
  16. data/features/step_definitions/network_adapter_steps.rb +38 -0
  17. data/features/step_definitions/shared_folder_steps.rb +76 -0
  18. data/features/step_definitions/snapshot_steps.rb +74 -0
  19. data/features/step_definitions/storage_controller_steps.rb +16 -0
  20. data/features/step_definitions/virtualbox_steps.rb +17 -0
  21. data/features/step_definitions/vm_steps.rb +50 -0
  22. data/features/support/env.rb +61 -0
  23. data/features/support/helpers.rb +38 -0
  24. data/features/support/hooks.rb +30 -0
  25. data/features/support/ordered_hash.rb +49 -0
  26. data/features/support/vboxmanage.rb +191 -0
  27. data/features/version.feature +16 -0
  28. data/features/vm.feature +13 -0
  29. data/features/vm_bios.feature +29 -0
  30. data/features/vm_cpu.feature +29 -0
  31. data/features/vm_extra_data.feature +35 -0
  32. data/features/vm_hw_virt.feature +29 -0
  33. data/features/vm_nat_engine.feature +57 -0
  34. data/features/vm_network_adapters.feature +27 -0
  35. data/features/vm_shared_folders.feature +42 -0
  36. data/features/vm_snapshots.feature +29 -0
  37. data/features/vm_storage_controllers.feature +11 -0
  38. data/lib/virtualbox.rb +11 -0
  39. data/lib/virtualbox/abstract_model.rb +281 -0
  40. data/lib/virtualbox/abstract_model/attributable.rb +290 -0
  41. data/lib/virtualbox/abstract_model/dirty.rb +177 -0
  42. data/lib/virtualbox/abstract_model/interface_attributes.rb +98 -0
  43. data/lib/virtualbox/abstract_model/relatable.rb +332 -0
  44. data/lib/virtualbox/abstract_model/validatable.rb +167 -0
  45. data/lib/virtualbox/abstract_model/version_matcher.rb +35 -0
  46. data/lib/virtualbox/appliance.rb +62 -0
  47. data/lib/virtualbox/audio_adapter.rb +52 -0
  48. data/lib/virtualbox/bios.rb +50 -0
  49. data/lib/virtualbox/com.rb +23 -0
  50. data/lib/virtualbox/com/abstract_enum.rb +43 -0
  51. data/lib/virtualbox/com/abstract_implementer.rb +45 -0
  52. data/lib/virtualbox/com/abstract_interface.rb +167 -0
  53. data/lib/virtualbox/com/base_interface.rb +38 -0
  54. data/lib/virtualbox/com/ffi/interface.rb +150 -0
  55. data/lib/virtualbox/com/ffi/interfaces.rb +54 -0
  56. data/lib/virtualbox/com/ffi/util.rb +119 -0
  57. data/lib/virtualbox/com/ffi/vboxxpcomc.rb +31 -0
  58. data/lib/virtualbox/com/ffi_interface.rb +96 -0
  59. data/lib/virtualbox/com/implementer/base.rb +59 -0
  60. data/lib/virtualbox/com/implementer/ffi.rb +361 -0
  61. data/lib/virtualbox/com/implementer/mscom.rb +175 -0
  62. data/lib/virtualbox/com/implementer/nil.rb +10 -0
  63. data/lib/virtualbox/com/interface/3.1.x/access_mode.rb +11 -0
  64. data/lib/virtualbox/com/interface/3.1.x/appliance.rb +22 -0
  65. data/lib/virtualbox/com/interface/3.1.x/audio_adapter.rb +15 -0
  66. data/lib/virtualbox/com/interface/3.1.x/audio_controller_type.rb +11 -0
  67. data/lib/virtualbox/com/interface/3.1.x/audio_driver_type.rb +11 -0
  68. data/lib/virtualbox/com/interface/3.1.x/bios_boot_menu_mode.rb +11 -0
  69. data/lib/virtualbox/com/interface/3.1.x/bios_settings.rb +21 -0
  70. data/lib/virtualbox/com/interface/3.1.x/clipboard_mode.rb +11 -0
  71. data/lib/virtualbox/com/interface/3.1.x/console.rb +50 -0
  72. data/lib/virtualbox/com/interface/3.1.x/cpu_property_type.rb +11 -0
  73. data/lib/virtualbox/com/interface/3.1.x/device_type.rb +11 -0
  74. data/lib/virtualbox/com/interface/3.1.x/dhcp_server.rb +22 -0
  75. data/lib/virtualbox/com/interface/3.1.x/firmware_type.rb +11 -0
  76. data/lib/virtualbox/com/interface/3.1.x/guest_os_type.rb +23 -0
  77. data/lib/virtualbox/com/interface/3.1.x/host.rb +42 -0
  78. data/lib/virtualbox/com/interface/3.1.x/host_network_interface.rb +30 -0
  79. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_medium_type.rb +11 -0
  80. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_status.rb +11 -0
  81. data/lib/virtualbox/com/interface/3.1.x/host_network_interface_type.rb +11 -0
  82. data/lib/virtualbox/com/interface/3.1.x/host_usb_device.rb +13 -0
  83. data/lib/virtualbox/com/interface/3.1.x/host_usb_device_filter.rb +13 -0
  84. data/lib/virtualbox/com/interface/3.1.x/hw_virt_ex_property_type.rb +11 -0
  85. data/lib/virtualbox/com/interface/3.1.x/machine.rb +105 -0
  86. data/lib/virtualbox/com/interface/3.1.x/machine_state.rb +14 -0
  87. data/lib/virtualbox/com/interface/3.1.x/medium.rb +50 -0
  88. data/lib/virtualbox/com/interface/3.1.x/medium_attachment.rb +18 -0
  89. data/lib/virtualbox/com/interface/3.1.x/medium_format.rb +18 -0
  90. data/lib/virtualbox/com/interface/3.1.x/medium_state.rb +11 -0
  91. data/lib/virtualbox/com/interface/3.1.x/medium_type.rb +11 -0
  92. data/lib/virtualbox/com/interface/3.1.x/medium_variant.rb +11 -0
  93. data/lib/virtualbox/com/interface/3.1.x/network_adapter.rb +30 -0
  94. data/lib/virtualbox/com/interface/3.1.x/network_adapter_type.rb +11 -0
  95. data/lib/virtualbox/com/interface/3.1.x/network_attachment_type.rb +11 -0
  96. data/lib/virtualbox/com/interface/3.1.x/nsiexception.rb +23 -0
  97. data/lib/virtualbox/com/interface/3.1.x/nsisupports.rb +15 -0
  98. data/lib/virtualbox/com/interface/3.1.x/parallel_port.rb +17 -0
  99. data/lib/virtualbox/com/interface/3.1.x/port_mode.rb +11 -0
  100. data/lib/virtualbox/com/interface/3.1.x/progress.rb +63 -0
  101. data/lib/virtualbox/com/interface/3.1.x/serial_port.rb +19 -0
  102. data/lib/virtualbox/com/interface/3.1.x/session.rb +18 -0
  103. data/lib/virtualbox/com/interface/3.1.x/session_state.rb +11 -0
  104. data/lib/virtualbox/com/interface/3.1.x/session_type.rb +11 -0
  105. data/lib/virtualbox/com/interface/3.1.x/shared_folder.rb +17 -0
  106. data/lib/virtualbox/com/interface/3.1.x/snapshot.rb +20 -0
  107. data/lib/virtualbox/com/interface/3.1.x/storage_bus.rb +11 -0
  108. data/lib/virtualbox/com/interface/3.1.x/storage_controller.rb +23 -0
  109. data/lib/virtualbox/com/interface/3.1.x/storage_controller_type.rb +11 -0
  110. data/lib/virtualbox/com/interface/3.1.x/system_properties.rb +37 -0
  111. data/lib/virtualbox/com/interface/3.1.x/usb_controller.rb +20 -0
  112. data/lib/virtualbox/com/interface/3.1.x/usb_device.rb +24 -0
  113. data/lib/virtualbox/com/interface/3.1.x/usb_device_filter.rb +23 -0
  114. data/lib/virtualbox/com/interface/3.1.x/usb_device_filter_action.rb +11 -0
  115. data/lib/virtualbox/com/interface/3.1.x/usb_device_state.rb +11 -0
  116. data/lib/virtualbox/com/interface/3.1.x/virtual_box_error_info.rb +17 -0
  117. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description.rb +19 -0
  118. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description_type.rb +14 -0
  119. data/lib/virtualbox/com/interface/3.1.x/virtual_system_description_value_type.rb +11 -0
  120. data/lib/virtualbox/com/interface/3.1.x/virtualbox.rb +67 -0
  121. data/lib/virtualbox/com/interface/3.1.x/vrdp_auth_type.rb +11 -0
  122. data/lib/virtualbox/com/interface/3.1.x/vrdp_server.rb +19 -0
  123. data/lib/virtualbox/com/interface/3.2.x/access_mode.rb +11 -0
  124. data/lib/virtualbox/com/interface/3.2.x/appliance.rb +22 -0
  125. data/lib/virtualbox/com/interface/3.2.x/audio_adapter.rb +15 -0
  126. data/lib/virtualbox/com/interface/3.2.x/audio_controller_type.rb +11 -0
  127. data/lib/virtualbox/com/interface/3.2.x/audio_driver_type.rb +11 -0
  128. data/lib/virtualbox/com/interface/3.2.x/bios_boot_menu_mode.rb +11 -0
  129. data/lib/virtualbox/com/interface/3.2.x/bios_settings.rb +21 -0
  130. data/lib/virtualbox/com/interface/3.2.x/clipboard_mode.rb +11 -0
  131. data/lib/virtualbox/com/interface/3.2.x/console.rb +50 -0
  132. data/lib/virtualbox/com/interface/3.2.x/cpu_property_type.rb +11 -0
  133. data/lib/virtualbox/com/interface/3.2.x/device_type.rb +11 -0
  134. data/lib/virtualbox/com/interface/3.2.x/dhcp_server.rb +22 -0
  135. data/lib/virtualbox/com/interface/3.2.x/firmware_type.rb +11 -0
  136. data/lib/virtualbox/com/interface/3.2.x/guest.rb +13 -0
  137. data/lib/virtualbox/com/interface/3.2.x/guest_os_type.rb +33 -0
  138. data/lib/virtualbox/com/interface/3.2.x/host.rb +43 -0
  139. data/lib/virtualbox/com/interface/3.2.x/host_network_interface.rb +30 -0
  140. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_medium_type.rb +11 -0
  141. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_status.rb +11 -0
  142. data/lib/virtualbox/com/interface/3.2.x/host_network_interface_type.rb +11 -0
  143. data/lib/virtualbox/com/interface/3.2.x/host_usb_device.rb +13 -0
  144. data/lib/virtualbox/com/interface/3.2.x/host_usb_device_filter.rb +13 -0
  145. data/lib/virtualbox/com/interface/3.2.x/hw_virt_ex_property_type.rb +11 -0
  146. data/lib/virtualbox/com/interface/3.2.x/keyboard_hid_type.rb +11 -0
  147. data/lib/virtualbox/com/interface/3.2.x/machine.rb +118 -0
  148. data/lib/virtualbox/com/interface/3.2.x/machine_state.rb +14 -0
  149. data/lib/virtualbox/com/interface/3.2.x/medium.rb +51 -0
  150. data/lib/virtualbox/com/interface/3.2.x/medium_attachment.rb +18 -0
  151. data/lib/virtualbox/com/interface/3.2.x/medium_format.rb +18 -0
  152. data/lib/virtualbox/com/interface/3.2.x/medium_state.rb +11 -0
  153. data/lib/virtualbox/com/interface/3.2.x/medium_type.rb +11 -0
  154. data/lib/virtualbox/com/interface/3.2.x/medium_variant.rb +11 -0
  155. data/lib/virtualbox/com/interface/3.2.x/nat_alias_mode.rb +11 -0
  156. data/lib/virtualbox/com/interface/3.2.x/nat_engine.rb +27 -0
  157. data/lib/virtualbox/com/interface/3.2.x/nat_protocol.rb +11 -0
  158. data/lib/virtualbox/com/interface/3.2.x/network_adapter.rb +34 -0
  159. data/lib/virtualbox/com/interface/3.2.x/network_adapter_type.rb +11 -0
  160. data/lib/virtualbox/com/interface/3.2.x/network_attachment_type.rb +11 -0
  161. data/lib/virtualbox/com/interface/3.2.x/nsiexception.rb +23 -0
  162. data/lib/virtualbox/com/interface/3.2.x/nsisupports.rb +15 -0
  163. data/lib/virtualbox/com/interface/3.2.x/parallel_port.rb +17 -0
  164. data/lib/virtualbox/com/interface/3.2.x/pointing_hid_type.rb +11 -0
  165. data/lib/virtualbox/com/interface/3.2.x/port_mode.rb +11 -0
  166. data/lib/virtualbox/com/interface/3.2.x/progress.rb +63 -0
  167. data/lib/virtualbox/com/interface/3.2.x/serial_port.rb +19 -0
  168. data/lib/virtualbox/com/interface/3.2.x/session.rb +18 -0
  169. data/lib/virtualbox/com/interface/3.2.x/session_state.rb +11 -0
  170. data/lib/virtualbox/com/interface/3.2.x/session_type.rb +11 -0
  171. data/lib/virtualbox/com/interface/3.2.x/shared_folder.rb +17 -0
  172. data/lib/virtualbox/com/interface/3.2.x/snapshot.rb +20 -0
  173. data/lib/virtualbox/com/interface/3.2.x/storage_bus.rb +11 -0
  174. data/lib/virtualbox/com/interface/3.2.x/storage_controller.rb +24 -0
  175. data/lib/virtualbox/com/interface/3.2.x/storage_controller_type.rb +11 -0
  176. data/lib/virtualbox/com/interface/3.2.x/system_properties.rb +42 -0
  177. data/lib/virtualbox/com/interface/3.2.x/usb_controller.rb +21 -0
  178. data/lib/virtualbox/com/interface/3.2.x/usb_device.rb +24 -0
  179. data/lib/virtualbox/com/interface/3.2.x/usb_device_filter.rb +23 -0
  180. data/lib/virtualbox/com/interface/3.2.x/usb_device_filter_action.rb +11 -0
  181. data/lib/virtualbox/com/interface/3.2.x/usb_device_state.rb +11 -0
  182. data/lib/virtualbox/com/interface/3.2.x/virtual_box_error_info.rb +17 -0
  183. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description.rb +19 -0
  184. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description_type.rb +14 -0
  185. data/lib/virtualbox/com/interface/3.2.x/virtual_system_description_value_type.rb +11 -0
  186. data/lib/virtualbox/com/interface/3.2.x/virtualbox.rb +67 -0
  187. data/lib/virtualbox/com/interface/3.2.x/vrdp_auth_type.rb +11 -0
  188. data/lib/virtualbox/com/interface/3.2.x/vrdp_server.rb +21 -0
  189. data/lib/virtualbox/com/mscom_interface.rb +44 -0
  190. data/lib/virtualbox/com/nil_interface.rb +7 -0
  191. data/lib/virtualbox/com/util.rb +32 -0
  192. data/lib/virtualbox/cpu.rb +61 -0
  193. data/lib/virtualbox/dhcp_server.rb +89 -0
  194. data/lib/virtualbox/dvd.rb +27 -0
  195. data/lib/virtualbox/exceptions.rb +39 -0
  196. data/lib/virtualbox/ext/byte_normalizer.rb +17 -0
  197. data/lib/virtualbox/ext/glob_loader.rb +22 -0
  198. data/lib/virtualbox/ext/logger.rb +38 -0
  199. data/lib/virtualbox/ext/platform.rb +27 -0
  200. data/lib/virtualbox/ext/subclass_listing.rb +24 -0
  201. data/lib/virtualbox/extra_data.rb +127 -0
  202. data/lib/virtualbox/forwarded_port.rb +222 -0
  203. data/lib/virtualbox/global.rb +102 -0
  204. data/lib/virtualbox/guest_property.rb +116 -0
  205. data/lib/virtualbox/hard_drive.rb +246 -0
  206. data/lib/virtualbox/host.rb +71 -0
  207. data/lib/virtualbox/host_network_interface.rb +137 -0
  208. data/lib/virtualbox/hw_virtualization.rb +63 -0
  209. data/lib/virtualbox/lib.rb +84 -0
  210. data/lib/virtualbox/media.rb +20 -0
  211. data/lib/virtualbox/medium.rb +145 -0
  212. data/lib/virtualbox/medium_attachment.rb +61 -0
  213. data/lib/virtualbox/nat_engine.rb +71 -0
  214. data/lib/virtualbox/nat_forwarded_port.rb +171 -0
  215. data/lib/virtualbox/network_adapter.rb +166 -0
  216. data/lib/virtualbox/proxies/collection.rb +57 -0
  217. data/lib/virtualbox/shared_folder.rb +220 -0
  218. data/lib/virtualbox/snapshot.rb +185 -0
  219. data/lib/virtualbox/storage_controller.rb +160 -0
  220. data/lib/virtualbox/system_properties.rb +74 -0
  221. data/lib/virtualbox/usb_controller.rb +59 -0
  222. data/lib/virtualbox/usb_device_filter.rb +74 -0
  223. data/lib/virtualbox/version.rb +36 -0
  224. data/lib/virtualbox/virtual_system_description.rb +47 -0
  225. data/lib/virtualbox/vm.rb +684 -0
  226. data/lib/virtualbox/vrdp_server.rb +59 -0
  227. data/test/test_helper.rb +18 -0
  228. data/test/virtualbox/abstract_model/attributable_test.rb +269 -0
  229. data/test/virtualbox/abstract_model/dirty_test.rb +83 -0
  230. data/test/virtualbox/abstract_model/interface_attributes_test.rb +194 -0
  231. data/test/virtualbox/abstract_model/relatable_test.rb +348 -0
  232. data/test/virtualbox/abstract_model/validatable_test.rb +308 -0
  233. data/test/virtualbox/abstract_model/version_matcher_test.rb +41 -0
  234. data/test/virtualbox/abstract_model_test.rb +462 -0
  235. data/test/virtualbox/appliance_test.rb +159 -0
  236. data/test/virtualbox/audio_adapter_test.rb +83 -0
  237. data/test/virtualbox/bios_test.rb +83 -0
  238. data/test/virtualbox/com/abstract_enum_test.rb +49 -0
  239. data/test/virtualbox/com/abstract_implementer_test.rb +40 -0
  240. data/test/virtualbox/com/abstract_interface_test.rb +140 -0
  241. data/test/virtualbox/com/ffi/interface_test.rb +249 -0
  242. data/test/virtualbox/com/ffi/util_test.rb +108 -0
  243. data/test/virtualbox/com/ffi_interface_test.rb +42 -0
  244. data/test/virtualbox/com/implementer/base_test.rb +38 -0
  245. data/test/virtualbox/com/implementer/ffi_test.rb +527 -0
  246. data/test/virtualbox/com/implementer/mscom_test.rb +247 -0
  247. data/test/virtualbox/com/mscom_interface_test.rb +17 -0
  248. data/test/virtualbox/com/util_test.rb +17 -0
  249. data/test/virtualbox/cpu_test.rb +103 -0
  250. data/test/virtualbox/dhcp_server_test.rb +165 -0
  251. data/test/virtualbox/dvd_test.rb +28 -0
  252. data/test/virtualbox/ext/byte_normalizer_test.rb +34 -0
  253. data/test/virtualbox/ext/platform_test.rb +50 -0
  254. data/test/virtualbox/ext/subclass_listing_test.rb +25 -0
  255. data/test/virtualbox/extra_data_test.rb +155 -0
  256. data/test/virtualbox/forwarded_port_test.rb +286 -0
  257. data/test/virtualbox/global_test.rb +46 -0
  258. data/test/virtualbox/hard_drive_test.rb +141 -0
  259. data/test/virtualbox/host_network_interface_test.rb +254 -0
  260. data/test/virtualbox/host_test.rb +94 -0
  261. data/test/virtualbox/hw_virtualization_test.rb +103 -0
  262. data/test/virtualbox/lib_test.rb +93 -0
  263. data/test/virtualbox/medium_attachment_test.rb +147 -0
  264. data/test/virtualbox/medium_test.rb +192 -0
  265. data/test/virtualbox/nat_engine_test.rb +106 -0
  266. data/test/virtualbox/nat_forwarded_port_test.rb +222 -0
  267. data/test/virtualbox/network_adapter_test.rb +191 -0
  268. data/test/virtualbox/proxies/collection_test.rb +102 -0
  269. data/test/virtualbox/shared_folder_test.rb +219 -0
  270. data/test/virtualbox/snapshot_test.rb +231 -0
  271. data/test/virtualbox/storage_controller_test.rb +197 -0
  272. data/test/virtualbox/system_properties_test.rb +87 -0
  273. data/test/virtualbox/usb_controller_test.rb +112 -0
  274. data/test/virtualbox/usb_device_filter_test.rb +93 -0
  275. data/test/virtualbox/version_test.rb +59 -0
  276. data/test/virtualbox/virtual_system_description_test.rb +61 -0
  277. data/test/virtualbox/vm_test.rb +637 -0
  278. data/test/virtualbox/vrdp_server_test.rb +83 -0
  279. data/test/virtualbox_test.rb +11 -0
  280. data/virtualbox.gemspec +25 -0
  281. metadata +397 -0
@@ -0,0 +1,38 @@
1
+ require 'thread'
2
+
3
+ module VirtualBox
4
+ module COM
5
+ class BaseInterface
6
+ def initialize
7
+ @task_queue = Queue.new
8
+
9
+ @lib_thread = Thread.new(@task_queue) do |queue|
10
+ while true
11
+ task, result = queue.pop
12
+
13
+ # Run the task, set the return value, and run the waiter
14
+ # which will simply finish that thread
15
+ result << task.call
16
+ end
17
+ end
18
+ end
19
+
20
+ # This function takes a block and runs it on a thread which is
21
+ # guaranteed to be the same since the first time this is
22
+ # called. This is required by the MSCOM implementation and is a
23
+ # good idea in general so that multiple API calls aren't firing
24
+ # at once.
25
+ def on_lib_thread(&task)
26
+ # If we're already on the lib thread, then just run it!
27
+ return task.call if Thread.current == @lib_thread
28
+
29
+ # Add the task to the queue
30
+ result = Queue.new
31
+ @task_queue << [task, result]
32
+
33
+ # Pop the result off of the result queue
34
+ result.pop
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,150 @@
1
+ require 'ffi'
2
+
3
+ module VirtualBox
4
+ module COM
5
+ module FFI
6
+ extend ::FFI::Library
7
+
8
+ # FFI specific types
9
+ NSRESULT_TYPE = :uint
10
+
11
+ # Creates all the FFI classes for a given version.
12
+ def self.for_version(version, &block)
13
+ @__module = Module.new
14
+ ::VirtualBox::COM::Util.set_interface_version(version)
15
+ const_set(::VirtualBox::COM::Util.version_const, @__module)
16
+ instance_eval(&block)
17
+ @__module = Kernel
18
+ end
19
+
20
+ # Returns a Class which creates an FFI interface to the specified
21
+ # com interface and potentially a parent class as well.
22
+ def self.create_interface(interface, parent=nil)
23
+ klass = Class.new(Interface)
24
+ @__module.const_set(interface, klass)
25
+ klass.com_interface(interface, parent)
26
+ klass
27
+ end
28
+
29
+ # Represents a VirtualBox XPCOM C interface, which is a C struct
30
+ # which emulates an object (a struct with function pointers
31
+ # and getters/setters). This class does **a lot** of magic which pretty
32
+ # much represents everything wrong about ruby programmers, but keep
33
+ # in mind it is well tested and well commented, and the meta-programming
34
+ # was done out of a need to keep things DRY between Windows and Unix
35
+ # operating systems.
36
+ class Interface
37
+ extend ::FFI::Library
38
+
39
+ attr_reader :vtbl_parent
40
+ attr_reader :vtbl
41
+
42
+ class << self
43
+ # Sets up the args to the FFI::Struct `layout` method. This
44
+ # method defines all the callbacks necessary for working with
45
+ # FFI and also sets up any layout args to send in. The way the
46
+ # XPCOM C structs are setup, the properties are first, in
47
+ # `GetFoo` and `SetFoo` format. And the functions are next. They are
48
+ # put into the struct in the order defined in the {AbstractInterface}.
49
+ def com_interface(interface, parent=nil)
50
+ # Create the parent class and vtbl class
51
+ interface = ::VirtualBox::COM::Util.versioned_interface(interface)
52
+ define_vtbl_parent_for_interface(interface)
53
+ define_vtbl_for_interface(interface, parent)
54
+ end
55
+
56
+ # Creates the parent of the vtbl class associated with a given
57
+ # interface.
58
+ def define_vtbl_parent_for_interface(interface)
59
+ @vtbl_parent_klass = Class.new(::FFI::Struct)
60
+ @vtbl_parent_klass.layout(:vtbl, :pointer)
61
+
62
+ # Set the constant
63
+ const_set("VtblParent", @vtbl_parent_klass)
64
+ end
65
+
66
+ # Creates the vtbl class associated with a given interface.
67
+ def define_vtbl_for_interface(interface, parent=nil)
68
+ # Define the properties, then the functions, since thats the order
69
+ # the FFI structs are in
70
+ layout_args.clear
71
+ define_interface_parent(parent)
72
+ define_interface_properties(interface)
73
+ define_interface_functions(interface)
74
+
75
+ # Finally create the classes (the struct and the structs vtbl)
76
+ @vtbl_klass = Class.new(::FFI::Struct)
77
+
78
+ # Set the constant within this class
79
+ const_set("Vtbl", @vtbl_klass).layout(*layout_args.flatten)
80
+ end
81
+
82
+ # Defines the parent item of the layout. Since the VirtualBox XPCOM C
83
+ # library emulates an object-oriented environment using structs, the parent
84
+ # instance is pointed to by the first member of the struct. This method
85
+ # sets up that member.
86
+ #
87
+ # @param [Symbol] parent The name of the parent represented by a symbol
88
+ def define_interface_parent(parent)
89
+ return if parent.nil?
90
+
91
+ parent_klass = Object.module_eval("::VirtualBox::COM::FFI::#{::VirtualBox::COM::Util.version_const}::#{parent}::Vtbl")
92
+ layout_args << [:superklass, parent_klass]
93
+ end
94
+
95
+ # Defines all the properties on a com interface.
96
+ def define_interface_properties(interface)
97
+ interface.properties.each do |name, opts|
98
+ # Define the getter
99
+ define_interface_function("get_#{name}".to_sym, opts[:value_type])
100
+
101
+ # Define the setter unless the property is readonly
102
+ define_interface_function("set_#{name}".to_sym, nil, [opts[:value_type]]) unless opts[:opts] && opts[:opts][:readonly]
103
+ end
104
+ end
105
+
106
+ # Defines all the functions on a com interface.
107
+ def define_interface_functions(interface)
108
+ interface.functions.each do |name, opts|
109
+ # Define the function
110
+ define_interface_function(name, opts[:value_type], opts[:spec].dup)
111
+ end
112
+ end
113
+
114
+ # Defines a single function of a com interface
115
+ def define_interface_function(name, return_type, spec=[])
116
+ # Append the return type to the spec as an out parameter (this is how
117
+ # the C API handles it)
118
+ spec << [:out, return_type] unless return_type.nil?
119
+
120
+ # Define the "callback" type for the FFI module
121
+ callback(name, Util.spec_to_ffi(spec), NSRESULT_TYPE)
122
+
123
+ # Add to the layout args
124
+ layout_args << [name, name]
125
+ end
126
+
127
+ # Returns an array of the layout args to send to `layout` eventually.
128
+ #
129
+ # @return [Array]
130
+ def layout_args
131
+ @_layout_args ||= []
132
+ end
133
+ end
134
+
135
+ # Initializes the interface to the FFI struct with the given pointer. The
136
+ # pointer is used to initialize the VtblParent which is used to initialize
137
+ # the Vtbl itself.
138
+ def initialize(pointer)
139
+ initialize_vtbl(pointer)
140
+ end
141
+
142
+ def initialize_vtbl(pointer)
143
+ klass = self.class
144
+ @vtbl_parent = klass::VtblParent.new(pointer)
145
+ @vtbl = klass::Vtbl.new(vtbl_parent[:vtbl])
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,54 @@
1
+ module VirtualBox
2
+ module COM
3
+ module FFI
4
+ # Creates all the interfaces for the FFI implementation. Eventually this
5
+ # file should be conditionally loaded based on OS, so that Windows users
6
+ # don't have to wait for all this translation to occur.
7
+ def self.setup(version)
8
+ # TODO: This is so hacky and hard to maintain. Can we
9
+ # programatically get the modules in a namespace and
10
+ # instantiate them somehow?
11
+ for_version version do
12
+ create_interface(:NSISupports)
13
+ create_interface(:NSIException, :NSISupports)
14
+ create_interface(:Session, :NSISupports)
15
+ create_interface(:VirtualBox, :NSISupports)
16
+ create_interface(:Appliance, :NSISupports)
17
+ create_interface(:AudioAdapter, :NSISupports)
18
+ create_interface(:BIOSSettings, :NSISupports)
19
+ create_interface(:Console, :NSISupports)
20
+ create_interface(:DHCPServer, :NSISupports)
21
+ create_interface(:GuestOSType, :NSISupports)
22
+ create_interface(:Host, :NSISupports)
23
+ create_interface(:HostNetworkInterface, :NSISupports)
24
+ create_interface(:Machine, :NSISupports)
25
+ create_interface(:Medium, :NSISupports)
26
+ create_interface(:MediumAttachment, :NSISupports)
27
+ create_interface(:MediumFormat, :NSISupports)
28
+ create_interface(:NetworkAdapter, :NSISupports)
29
+ create_interface(:ParallelPort, :NSISupports)
30
+ create_interface(:Progress, :NSISupports)
31
+ create_interface(:SerialPort, :NSISupports)
32
+ create_interface(:SharedFolder, :NSISupports)
33
+ create_interface(:Snapshot, :NSISupports)
34
+ create_interface(:StorageController, :NSISupports)
35
+ create_interface(:SystemProperties, :NSISupports)
36
+ create_interface(:USBController, :NSISupports)
37
+ create_interface(:USBDevice, :NSISupports)
38
+ create_interface(:USBDeviceFilter, :NSISupports)
39
+ create_interface(:VirtualBoxErrorInfo, :NSIException)
40
+ create_interface(:VirtualSystemDescription, :NSISupports)
41
+ create_interface(:VRDPServer, :NSISupports)
42
+
43
+ create_interface(:HostUSBDevice, :USBDevice)
44
+ create_interface(:HostUSBDeviceFilter, :USBDeviceFilter)
45
+
46
+ # 3.2.x interfaces
47
+ if version == "3.2.x"
48
+ create_interface(:NATEngine, :NSISupports)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,119 @@
1
+ module VirtualBox
2
+ module COM
3
+ module FFI
4
+ # Class which contains many class-level utility methods to assist
5
+ # with the FFI interface. These functions range from converting a
6
+ # function spec to a FFI parameter list to dereferencing pointers.
7
+ class Util
8
+ class << self
9
+ # Finds and returns the `COM::Interface` class associated with the type.
10
+ # If the class does not exist, a `NameError` will be raised.
11
+ #
12
+ # @return [Class]
13
+ def interface_klass(type)
14
+ ::VirtualBox::COM::Util.versioned_interface(type)
15
+ end
16
+
17
+ # Finds the versioned interface for the FFI module.
18
+ #
19
+ # @return [Class]
20
+ def versioned_interface(interface)
21
+ ::VirtualBox::COM::FFI.const_get(::VirtualBox::COM::Util.version_const).const_get(interface)
22
+ end
23
+
24
+ # Converts a function spec from {AbstractInterface} to an FFI
25
+ # function spec. This handles custom types (unicode strings,
26
+ # arrays, and out-parameters) and will return a perfectly valid
27
+ # array ready to be passed into `callback`.
28
+ #
29
+ # @param [Array] spec The function spec
30
+ # @return [Array]
31
+ def spec_to_ffi(spec)
32
+ spec = spec.collect do |item|
33
+ if item.is_a?(Array) && item[0] == :out
34
+ if item[1].is_a?(Array)
35
+ # The out is an array of items, so we add in two pointers:
36
+ # one for size and one for the array
37
+ [:pointer, :pointer]
38
+ else
39
+ # A regular out parameter is just a single pointer
40
+ :pointer
41
+ end
42
+ elsif item.is_a?(Array) && item.length == 1
43
+ # The parameter is an array of somethings
44
+ [T_UINT32, :pointer]
45
+ elsif item == WSTRING
46
+ # Unicode strings are simply pointers
47
+ :pointer
48
+ elsif item.to_s[0,1] == item.to_s[0,1].upcase
49
+ begin
50
+ # Try to get the class from the interfaces
51
+ interface = interface_klass(item.to_sym)
52
+
53
+ if interface.superclass == COM::AbstractInterface
54
+ :pointer
55
+ elsif interface.superclass == COM::AbstractEnum
56
+ T_UINT32
57
+ end
58
+ rescue NameError
59
+ # Default to a pointer, since not all interfaces are implemented
60
+ :pointer
61
+ end
62
+ else
63
+ # Unknown items are simply passed as-is, hopefully FFI
64
+ # will catch any problems
65
+ item
66
+ end
67
+ end
68
+
69
+ # Prepend a :pointer to represent the `this` parameter required
70
+ # for the FFI parameter lists
71
+ spec.unshift(:pointer).flatten
72
+ end
73
+
74
+ # An "almost complete" camel-caser. Camel cases a string with a few
75
+ # exceptions. For example: `get_foo` becomes `GetFoo`, but `get_os_type`
76
+ # becomes `GetOSType` since `os` is a special case.
77
+ #
78
+ # @param [String] string The string to camel case
79
+ # @return [String]
80
+ def camelize(string)
81
+ special_cases = {
82
+ "os" => "OS",
83
+ "dhcp" => "DHCP",
84
+ "dvd" => "DVD",
85
+ "usb" => "USB",
86
+ "vram" => "VRAM",
87
+ "3d" => "3D",
88
+ "bios" => "BIOS",
89
+ "vrdp" => "VRDP",
90
+ "hw" => "HW",
91
+ "png" => "PNG",
92
+ "io" => "IO",
93
+ "apic" => "APIC",
94
+ "acpi" => "ACPI",
95
+ "pxe" => "PXE",
96
+ "nat" => "NAT",
97
+ "ide" => "IDE",
98
+ "vfs" => "VFS",
99
+ "ip" => "IP",
100
+ "vdi" => "VDI",
101
+ "cpu" => "CPU",
102
+ "ram" => "RAM",
103
+ "hdd" => "HDD",
104
+ "rtc" => "RTC",
105
+ "utc" => "UTC",
106
+ "io" => "IO"
107
+ }
108
+
109
+ parts = string.to_s.split(/_/).collect do |part|
110
+ special_cases[part] || part.capitalize
111
+ end
112
+
113
+ parts.join("")
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,31 @@
1
+ module VirtualBox
2
+ module COM
3
+ module FFI
4
+ # Callback types for VBOXXPCOMC
5
+ callback :pfnGetVersion, [], :uint
6
+ callback :pfnComInitialize, [:string, :pointer, :string, :pointer], :void
7
+ callback :pfnComUninitialize, [], :void
8
+ callback :pfnComUnallocMem, [:pointer], :void
9
+ callback :pfnUtf16Free, [:pointer], :void
10
+ callback :pfnUtf8Free, [:string], :void
11
+ callback :pfnUtf16ToUtf8, [:pointer, :pointer], :int
12
+ callback :pfnUtf8ToUtf16, [:string, :pointer], :int
13
+ callback :pfnGetEventQueue, [:pointer], :void
14
+
15
+ class VBOXXPCOMC < ::FFI::Struct
16
+ layout :cb, :uint,
17
+ :uVersion, :uint,
18
+ :pfnGetVersion, :pfnGetVersion,
19
+ :pfnComInitialize, :pfnComInitialize,
20
+ :pfnComUninitialize, :pfnComUninitialize,
21
+ :pfnComUnallocMem, :pfnComUnallocMem,
22
+ :pfnUtf16Free, :pfnUtf16Free,
23
+ :pfnUtf8Free, :pfnUtf8Free,
24
+ :pfnUtf16ToUtf8, :pfnUtf16ToUtf8,
25
+ :pfnUtf8ToUtf16, :pfnUtf8ToUtf16,
26
+ :pfnGetEventQueue, :pfnGetEventQueue,
27
+ :uEndVersion, :uint
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ module VirtualBox
2
+ module COM
3
+ class FFIInterface < BaseInterface
4
+ extend ::FFI::Library
5
+ include Logger
6
+
7
+ # Constant used to initialize the XPCOM C interface
8
+ XPCOMC_VERSION = 0x00020000
9
+
10
+ # VBOXXPCOMC struct. This typically won't be used.
11
+ attr_reader :xpcom
12
+
13
+ # The VirtualBox and Session interfaces, both of which are extremely
14
+ # important in interfacing with the VirtualBox API. Once these have been
15
+ # initialized, all other parts of the API can be accessed via these
16
+ # instances.
17
+ attr_reader :virtualbox
18
+ attr_reader :session
19
+
20
+ class << self
21
+ # Sets up the FFI interface and also initializes the interface,
22
+ # returning an instance of {FFIInterface}.
23
+ def create(lib_path=nil)
24
+ setup(lib_path)
25
+ new
26
+ end
27
+
28
+ # Sets up the FFI interface by specifying the FFI library path
29
+ # and attaching the initial function (which can't be done until
30
+ # the FFI library is specified).
31
+ #
32
+ # @param [String] lib_path
33
+ def setup(lib_path=nil)
34
+ # Setup the path to the C library
35
+ lib_path ||= "/Applications/VirtualBox.app/Contents/MacOS/VBoxXPCOMC.dylib"
36
+
37
+ # Attach to the interface
38
+ ffi_lib lib_path
39
+ attach_function :VBoxGetXPCOMCFunctions, [:uint], :pointer
40
+ end
41
+ end
42
+
43
+ def initialize
44
+ super
45
+ initialize_com
46
+ end
47
+
48
+ # Initializes the COM interface with XPCOM. This sets up the `virtualbox`,
49
+ # `session`, and `xpcom` attributes. This should only be called once.
50
+ def initialize_com
51
+ # Get the pointer to the XPCOMC struct which contains the functions
52
+ # to initialize
53
+ xpcom_pointer = self.class.VBoxGetXPCOMCFunctions(XPCOMC_VERSION)
54
+ @xpcom = FFI::VBOXXPCOMC.new(xpcom_pointer)
55
+
56
+ initialize_singletons
57
+ end
58
+
59
+ # Initializes the VirtualBox and Session interfaces. It goes through
60
+ # the various directories until it finds a working pair.
61
+ def initialize_singletons
62
+ interface_dir = File.expand_path(File.join(File.dirname(__FILE__), "interface"))
63
+ Dir[File.join(interface_dir, "*")].each do |f|
64
+ if File.directory?(f)
65
+ return if initialize_for_version(File.basename(f))
66
+ end
67
+ end
68
+ end
69
+
70
+ # Initializes the FFI interface for a specific version.
71
+ def initialize_for_version(version)
72
+ logger.debug("FFI init: Trying version #{version}")
73
+
74
+ # Setup the FFI classes
75
+ VirtualBox::COM::FFI.setup(version)
76
+ virtualbox_klass = COM::Util.versioned_interface(:VirtualBox)
77
+ session_klass = COM::Util.versioned_interface(:Session)
78
+
79
+ # Setup the OUT pointers
80
+ virtualbox_ptr = ::FFI::MemoryPointer.new(:pointer)
81
+ session_ptr = ::FFI::MemoryPointer.new(:pointer)
82
+
83
+ # Call the initialization functions
84
+ @xpcom[:pfnComInitialize].call(virtualbox_klass::IID_STR, virtualbox_ptr, session_klass::IID_STR, session_ptr)
85
+ @virtualbox = virtualbox_klass.new(Implementer::FFI, self, virtualbox_ptr.get_pointer(0))
86
+ @session = session_klass.new(Implementer::FFI, self, session_ptr.get_pointer(0))
87
+
88
+ logger.debug(" -- Valid version")
89
+ true
90
+ rescue Exception => e
91
+ logger.debug(" -- Invalid version")
92
+ false
93
+ end
94
+ end
95
+ end
96
+ end