Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(FACT-1418) Replaces COM moniker call for Nano Server support #1327

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion lib/facter/util/wmi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ module Facter::Util::WMI
class << self
def connect(uri = wmi_resource_uri)
require 'win32ole'
WIN32OLE.connect(uri)
#WIN32OLE.connect(uri)
swbem = WIN32OLE.new("WbemScripting.SWbemLocator")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the code that I'm currently using in the (working) Nano tests.
WIN32OLE.ole_initialize() is not called here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd - there are no other places that Ruby directly calls CoInitialize / CoInitializeEx / OleInitialize / OleInitializeEx that I see. So how is Ruby able to init COM then?

I wrote a trivial script in Ruby demonstrating that you are correct - this basic approach works:

require 'win32ole'
swbem = WIN32OLE.new('WbemScripting.SWbemLocator')
server = swbem.ConnectServer('.', 'root\\cimv2')

results = server.ExecQuery('SELECT manufacturer, model FROM Win32_ComputerSystem')
for result in results
  puts result.manufacturer
  puts result.model
end

Output:

[10.0.16.145]: PS C:\puppet> ruby --version
ruby 2.1.8p440 (2015-12-16 revision 53160) [x64-mingw32]

[10.0.16.145]: PS C:\puppet> ruby .\wmi-com-basic.rb
Microsoft Corporation
Virtual Machine

Copy link

@Iristyle Iristyle May 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my testing, I'm not seeing a failure to call OleInitialize from Ruby:

require 'ffi'

module COM
  extend FFI::Library

  ffi_convention :stdcall

  S_OK = 0
  S_FALSE = 1

  def SUCCEEDED(hr) hr >= 0 end
  def FAILED(hr) hr < 0 end

  module_function :SUCCEEDED, :FAILED

  def raise_if_hresult_failed(name, *args)
    failed = FAILED(result = send(name, *args)) and raise "#{name} failed (hresult #{format('%#08x', result)})."

    result
  ensure
    yield failed if block_given?
  end

  module_function :raise_if_hresult_failed

  ffi_lib :ole32
  attach_function :OleInitialize, [:pointer], :int32
  attach_function :OleUninitialize, [], :void

  def InitializeOle
    raise_if_hresult_failed(:OleInitialize, FFI::Pointer::NULL)

    puts 'Successfully called OleInitialize'


    at_exit { OleUninitialize() }
  end

  module_function :InitializeOle
end

COM.InitializeOle

Results

[10.0.16.145]: PS C:\puppet> bundle exec ruby .\ole-init-test.rb
Successfully called OleInitialize

Copy link
Author

@alexpilotti alexpilotti May 9, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is indeed interesting. Looks like OleInitialize calls CoInitializeEx with COINIT_MULTITHREADED (against what the documentation states), so it can be safely ignored. I'll ask the Nano team.

require 'ffi'

module Functions
    extend FFI::Library        
    ffi_convention :stdcall

    ffi_lib :ole32
    attach_function :OleInitialize, [:pointer], :int32
    attach_function :CoInitialize, [:pointer], :int32
    attach_function :CoInitializeEx, [:pointer, :int32], :int32    
end  

puts Functions.OleInitialize(FFI::Pointer::NULL)
puts Functions.CoInitialize(FFI::Pointer::NULL)
# COINIT_APARTMENTTHREADED
puts Functions.CoInitializeEx(FFI::Pointer::NULL, 2)
# COINIT_MULTITHREADED
puts Functions.CoInitializeEx(FFI::Pointer::NULL, 0)

Output on Nano TP5:

0
-2147467263
-2147467263
1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed https://tickets.puppetlabs.com/browse/FACT-1418 to cover this as we'll have to think a little about breaking API implications.

# TODO: parse wmi_resource_uri to extract host and namespace
swbem.ConnectServer(".", "root\\cimv2")
end

def wmi_resource_uri( host = '.' )
Expand Down