Class: WIN32OLE_VARIANT

Inherits:
Object
  • Object
show all
Defined in:
lib/win32ole-pr.rb

Constant Summary collapse

Empty =
WIN32OLE_VARIANT.new(WIN32OLE::VARIANT::VT_EMPTY)
Null =
WIN32OLE_VARIANT.new(WIN32OLE::VARIANT::VT_NULL)
Nothing =
WIN32OLE_VARIANT.new(WIN32OLE::VARIANT::VT_DISPATCH)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(val = nil, vartype = nil) ⇒ WIN32OLE_VARIANT

Returns a new instance of WIN32OLE_VARIANT.



5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
# File 'lib/win32ole-pr.rb', line 5398

def initialize(val=nil, vartype=nil)
   WIN32OLE.ole_initialize    
   @var = 0.chr * 16
   @realvar = 0.chr * 16
   return self if val.nil?
   if !val.is_a?(WIN32OLE) && !val.is_a?(WIN32OLE_VARIANT) && !val.is_a?(Time)
      case val
      when Array,String,Fixnum,Bignum,TrueClass,FalseClass,NilClass
      else
         raise TypeError, "can not convert WIN32OLE_VARIANT from type #{val.class}"
      end
   end
   if vartype.nil?
      WIN32OLE.ole_val2variant(val,@var)
   else
      WIN32OLE_VARIANT.ole_val2olevariantdata(val,vartype)
   end
end

Class Method Details

.array(ary, vt) ⇒ Object



5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
# File 'lib/win32ole-pr.rb', line 5360

def self.array(ary,vt)
    obj = nil
   dim = 0
   i = 0

   WIN32OLE.ole_initialize()

   vt = (vt | VT_ARRAY)
   unless ary.is_a?(Array)
      raise TypeError, "1st parameter must be Array"
   end
   obj = WIN32OLE_VARIANT.new

   dim = ary.length

   psab = 0.chr * 8 * dim

   for i in 0 ... dim
      psab[i*8,4] = [ary[i]].pack('L')
      psab[i*8+4,4] = [0].pack('L')
   end

   psa = SafeArrayCreate((vt & VT_TYPEMASK), dim, psab)
   if psa == 0
      raise RuntimeError, "memory allocation error(SafeArrayCreate)"
   end

   @var[0,2] = [vt].pack('S')
   if (vt & VT_BYREF) != 0
      @realvar[0,2] = [vt & ~VT_BYREF].pack('S')
      @realvar[8,4] = [psa].pack('P')
      @var[8,4] = [@realvar.unpack('P')].pack('P')
   else
      @var[8,4] = [psa].pack('P')
   end
   obj
end

.ole_val2olevariantdata(val, vt) ⇒ Object



5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
# File 'lib/win32ole-pr.rb', line 5265

def self.ole_val2olevariantdata(val,vt)
   hr = S_OK

   if (vt & ~VT_BYREF) ==  (VT_ARRAY | VT_UI1) && val.class == String
      len = val.length
      psa = SafeArrayCreateVector(VT_UI1, 0, len)
      if psa == 0
         raise RuntimeError, "fail to SafeArrayCreateVector"
      end
      pdest = 0.chr * 4
      hr = SafeArrayAccessData(psa, pdest)
      if hr == S_OK
         memcpy(pdest.unpack('L').first, val, len)
         SafeArrayUnaccessData(psa)
         @realvar[0,2] = [(vt & ~VT_BYREF)].pack('S')
         p = @realvar[8,4].unpack('L').first
         if p != 0
            SafeArrayDestroy(p)
         end
         @realvar[8,4] = [psa].pack('L')
         if (vt & VT_BYREF) != 0
            @var[0,2] = [vt].pack('S')
            @var[8,4] = [[@realvar].pack('P')].pack('L')
          else 
            hr = VariantCopy(@var, @realvar)
         end
      else 
         if psa != 0
            SafeArrayDestroy(psa)
         end
      end
    elsif (vt & VT_ARRAY) != 0
      if val.nil?
         @var[0,2] = [vt].pack('S')
         if (vt & VT_BYREF) != 0
            @var[8,4] = [[@realvar].pack('P')].pack('L')
         end
      else 
         hr = ole_val_ary2variant_ary(val, @realvar, (vt & ~VT_BYREF))
         if hr == S_OK
            if (vt & VT_BYREF) != 0
               @var[0,2] = [vt].pack('S')
               @var[8,4] = [[@realvar].pack('P')].pack('L')
            else 
               hr = VariantCopy(@var,@realvar)
            end 
         end         
      end
    elsif  (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8 
      ole_val2variant_ex(val, @realvar, (vt & ~VT_BYREF))
      ole_val2variant_ex(val, @var, (vt & ~VT_BYREF))
      @var[0,2] = [vt].pack('S')
      if (vt & VT_BYREF) != 0
         ole_set_byref(@realvar, @var, vt)
      end
    else 
      if val.nil?
         @var[0,2] = [vt].pack('S')
         if (vt == (VT_BYREF | VT_VARIANT)) 
            ole_set_byref(@realvar, @var, vt)
         else 
            @realvar[0,2] = [vt & ~VT_BYREF].pack('S')
            if (vt & VT_BYREF) != 0
               ole_set_byref(@realvar, @var, vt)
            end
         end
      else 
         ole_val2variant_ex(val, @realvar, (vt & ~VT_BYREF))
         if (vt == (VT_BYREF | VT_VARIANT)) 
            ole_set_byref(@realvar, @var, vt)
         elsif (vt & VT_BYREF) != 0
            if  (vt & ~VT_BYREF) != @realvar[0,2].unpack('S').first 
               hr = VariantChangeTypeEx(@realvar, @realvar, 
                     WIN32OLE.locale, 0, (vt & ~VT_BYREF))
            end
            if hr == S_OK
               ole_set_byref(@realvar, @var, vt)
            end
         else 
            if vt == @realvar[0,2].unpack('S').first 
               hr = VariantCopy(@var, @realvar)
            else 
               hr = VariantChangeTypeEx(@var, @realvar, 
                     WIN32OLE.locale, 0, vt)
            end
         end   
      end   
   end   
   
   if hr != S_OK
      raise WIN32OLERuntimeError, "failed to change type"
   end

end

Instance Method Details

#[](*args) ⇒ Object



5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
# File 'lib/win32ole-pr.rb', line 5490

def [](*args)
   val = nil
   if (@var[0,2].unpack('S').first & VT_ARRAY) != 0
      raise WIN32OLERuntimeError, "`[]' is not available for this variant type object"
   end
   psa = get_locked_safe_array()
   return val if psa==0
   
   pid = ary2safe_array_index(args, psa)
   variant = 0.chr*16
   VariantInit(variant)
   variant[0,2] = [(@var[0,2].unpack('S').first & ~VT_ARRAY) | VT_BYREF].pack('S')
   hr = SafeArrayPtrOfIndex(psa, pid, variant[8,4])
   if hr != S_OK
      raise WIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"
   end
   val = WIN32OLE.ole_variant2val(variant)

   unlock_safe_array(psa)
   val      
end

#[]=(*args) ⇒ Object



5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
# File 'lib/win32ole-pr.rb', line 5512

def []=(*args)
   if (@var[0,2].unpack('S').first & VT_ARRAY) != 0
      raise WIN32OLERuntimeError, "`[]' is not available for this variant type object"
   end
   psa = get_locked_safe_array()
   if psa == 0
      raise RuntimeError, "failed to get SafeArray pointer"
   end
   pid = ary2safe_array_index(args[0..-2], psa)
   var = 0.chr * 16
   VariantInit(var)
   vt = @var[0,2].unpack('S').first & ~VT_ARRAY
   p = val2variant_ptr(args[-1], var, vt)
   if (var[0,2].unpack('S').first == VT_DISPATCH || var[0,2].unpack('S').first == VT_UNKNOWN) && var[8,4].unpack('L').first == 0
      raise WIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface"
   end
   hr = SafeArrayPutElement(psa, pid, p)
   if hr != S_OK
      raise WIN32OLERuntimeError, "failed to SafeArrayPutElement"
   end

   unlock_safe_array(psa)
   args[1]
end

#ary2safe_array_index(ary, psa) ⇒ Object



5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
# File 'lib/win32ole-pr.rb', line 5471

def ary2safe_array_index(ary,psa)
   dim = SafeArrayGetDim(psa)
   if dim != ary.length
      raise ArgError, "unmatch number of indices"        
   end
   pid = 0.chr * 4 * dim
   for i in 0 ... dim
      pid[i*4,4] = [ary[i]].pack('L')
   end
   pid
end

#get_locked_safe_arrayObject



5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
# File 'lib/win32ole-pr.rb', line 5452

def get_locked_safe_array
   if (@var[0,2].unpack('S').first & VT_ARRAY) != 0
      raise TypeError, "variant type is not VT_ARRAY."
   end
   if (@var[0,2].unpack('S').first & VT_BYREF) != 0
      ref = 0.chr * 16
      memcpy(ref,@var[8,4].unpack('L').first,16)
      pas = ref[8,4].unpack('L').first
   else
      psa = @var[8,4].unpack('L').first
   end
   return psa if psa == 0
   hr = SafeArrayLock(psa)
   if hr != S_OK
      raise eRuntimeError, "failed to SafeArrayLock"
   end
   psa
end

#unlock_safe_array(psa) ⇒ Object



5483
5484
5485
5486
5487
5488
# File 'lib/win32ole-pr.rb', line 5483

def unlock_safe_array(psa)
   hr = SafeArrayUnlock(psa)
   if hr != S_OK
      raise RuntimeError, "failed to SafeArrayUnlock"
   end
end

#valueObject



5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
# File 'lib/win32ole-pr.rb', line 5417

def value
   val = WIN32OLE.ole_variant2val(@var)
   vt = @var[0,2].unpack('S').first

   if (vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)
      if (vt & VT_BYREF) != 0
         memcpy(ref,@var[8,4].unpack('L').first,16)            
         psa = ref[8,4].unpack('L').first
      else 
         psa = @var[8,4].unpack('L').first
      end
      if psa == 0
         return val
      end
      dim = SafeArrayGetDim(psa)
      if dim == 1
         val = val.pack('C*')
      end
   end
   val
end

#value=(val) ⇒ Object



5439
5440
5441
5442
5443
5444
5445
5446
# File 'lib/win32ole-pr.rb', line 5439

def value=(val)
   vt = @var[0,2].unpack('S').first
   if (vt & VT_ARRAY) != 0 && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || val.class != String)
      raise WIN32OLERuntimeError, "`value=' is not available for this variant type object"
   end
   WIN32OLE_VARIANT.ole_val2olevariantdata(val, vt)
   nil
end

#vartypeObject



5448
5449
5450
# File 'lib/win32ole-pr.rb', line 5448

def vartype
   @var.unpack('S').first
end