net-ssh 6.2.0.rc2 → 6.3.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.github/workflows/ci.yml +27 -10
  5. data/.rubocop.yml +11 -1
  6. data/.rubocop_todo.yml +374 -173
  7. data/.travis.yml +10 -11
  8. data/CHANGES.txt +6 -0
  9. data/Gemfile +2 -0
  10. data/Gemfile.noed25519 +2 -0
  11. data/README.md +2 -2
  12. data/Rakefile +1 -0
  13. data/lib/net/ssh.rb +1 -2
  14. data/lib/net/ssh/authentication/agent.rb +4 -2
  15. data/lib/net/ssh/authentication/certificate.rb +3 -1
  16. data/lib/net/ssh/authentication/constants.rb +0 -1
  17. data/lib/net/ssh/authentication/ed25519.rb +6 -2
  18. data/lib/net/ssh/authentication/ed25519_loader.rb +4 -7
  19. data/lib/net/ssh/authentication/key_manager.rb +28 -29
  20. data/lib/net/ssh/authentication/methods/abstract.rb +0 -1
  21. data/lib/net/ssh/authentication/methods/hostbased.rb +0 -2
  22. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  23. data/lib/net/ssh/authentication/methods/none.rb +5 -8
  24. data/lib/net/ssh/authentication/methods/password.rb +1 -2
  25. data/lib/net/ssh/authentication/methods/publickey.rb +0 -2
  26. data/lib/net/ssh/authentication/pageant.rb +89 -89
  27. data/lib/net/ssh/authentication/session.rb +14 -15
  28. data/lib/net/ssh/buffer.rb +10 -5
  29. data/lib/net/ssh/buffered_io.rb +18 -19
  30. data/lib/net/ssh/config.rb +29 -16
  31. data/lib/net/ssh/connection/channel.rb +71 -69
  32. data/lib/net/ssh/connection/constants.rb +0 -4
  33. data/lib/net/ssh/connection/event_loop.rb +22 -16
  34. data/lib/net/ssh/connection/keepalive.rb +12 -12
  35. data/lib/net/ssh/connection/session.rb +95 -94
  36. data/lib/net/ssh/connection/term.rb +56 -58
  37. data/lib/net/ssh/errors.rb +10 -10
  38. data/lib/net/ssh/key_factory.rb +0 -1
  39. data/lib/net/ssh/known_hosts.rb +79 -11
  40. data/lib/net/ssh/loggable.rb +8 -9
  41. data/lib/net/ssh/packet.rb +1 -1
  42. data/lib/net/ssh/prompt.rb +8 -10
  43. data/lib/net/ssh/proxy/command.rb +1 -1
  44. data/lib/net/ssh/proxy/errors.rb +2 -4
  45. data/lib/net/ssh/proxy/http.rb +17 -19
  46. data/lib/net/ssh/proxy/https.rb +6 -8
  47. data/lib/net/ssh/proxy/jump.rb +8 -10
  48. data/lib/net/ssh/proxy/socks4.rb +1 -3
  49. data/lib/net/ssh/proxy/socks5.rb +2 -4
  50. data/lib/net/ssh/service/forward.rb +3 -3
  51. data/lib/net/ssh/test.rb +1 -2
  52. data/lib/net/ssh/test/channel.rb +20 -22
  53. data/lib/net/ssh/test/extensions.rb +29 -29
  54. data/lib/net/ssh/test/kex.rb +6 -8
  55. data/lib/net/ssh/test/local_packet.rb +0 -2
  56. data/lib/net/ssh/test/packet.rb +2 -2
  57. data/lib/net/ssh/test/remote_packet.rb +5 -7
  58. data/lib/net/ssh/test/script.rb +21 -23
  59. data/lib/net/ssh/test/socket.rb +11 -14
  60. data/lib/net/ssh/transport/algorithms.rb +2 -1
  61. data/lib/net/ssh/transport/cipher_factory.rb +13 -13
  62. data/lib/net/ssh/transport/constants.rb +3 -3
  63. data/lib/net/ssh/transport/ctr.rb +4 -4
  64. data/lib/net/ssh/transport/hmac/abstract.rb +0 -1
  65. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  66. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  67. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  68. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  69. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  70. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  71. data/lib/net/ssh/transport/identity_cipher.rb +10 -12
  72. data/lib/net/ssh/transport/kex.rb +2 -0
  73. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +1 -0
  74. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +4 -4
  75. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  76. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +0 -1
  77. data/lib/net/ssh/transport/key_expander.rb +6 -7
  78. data/lib/net/ssh/transport/openssl.rb +6 -11
  79. data/lib/net/ssh/transport/packet_stream.rb +1 -2
  80. data/lib/net/ssh/transport/server_version.rb +17 -16
  81. data/lib/net/ssh/transport/session.rb +3 -1
  82. data/lib/net/ssh/transport/state.rb +42 -42
  83. data/lib/net/ssh/verifiers/accept_new.rb +0 -2
  84. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  85. data/lib/net/ssh/verifiers/always.rb +6 -4
  86. data/lib/net/ssh/verifiers/never.rb +0 -2
  87. data/lib/net/ssh/version.rb +2 -2
  88. data/net-ssh-public_cert.pem +8 -8
  89. data/net-ssh.gemspec +2 -2
  90. data/support/ssh_tunnel_bug.rb +3 -3
  91. metadata +14 -13
  92. metadata.gz.sig +0 -0
@@ -6,7 +6,6 @@ module Net
6
6
  module SSH
7
7
  module Authentication
8
8
  module Methods
9
-
10
9
  # Implements the "publickey" SSH authentication method.
11
10
  class Publickey < Abstract
12
11
  # Attempts to perform public-key authentication for the given
@@ -90,7 +89,6 @@ module Net
90
89
  end
91
90
  end
92
91
  end
93
-
94
92
  end
95
93
  end
96
94
  end
@@ -21,10 +21,9 @@ end
21
21
 
22
22
  require 'net/ssh/errors'
23
23
 
24
- module Net
25
- module SSH
24
+ module Net
25
+ module SSH
26
26
  module Authentication
27
-
28
27
  # This module encapsulates the implementation of a socket factory that
29
28
  # uses the PuTTY "pageant" utility to obtain information about SSH
30
29
  # identities.
@@ -33,28 +32,27 @@ module Net
33
32
  # by Guillaume Marçais (guillaume.marcais@free.fr). It is used and
34
33
  # relicensed by permission.
35
34
  module Pageant
36
-
37
35
  # From Putty pageant.c
38
36
  AGENT_MAX_MSGLEN = 8192
39
37
  AGENT_COPYDATA_ID = 0x804e50ba
40
-
38
+
41
39
  # The definition of the Windows methods and data structures used in
42
40
  # communicating with the pageant process.
43
41
  module Win # rubocop:disable Metrics/ModuleLength
44
42
  # Compatibility on initialization
45
43
  if RUBY_VERSION < "1.9"
46
44
  extend DL::Importable
47
-
45
+
48
46
  dlload 'user32.dll'
49
47
  dlload 'kernel32.dll'
50
48
  dlload 'advapi32.dll'
51
-
49
+
52
50
  SIZEOF_DWORD = DL.sizeof('L')
53
51
  elsif RUBY_VERSION < "2.1"
54
52
  extend DL::Importer
55
53
  dlload 'user32.dll','kernel32.dll', 'advapi32.dll'
56
54
  include DL::Win32Types
57
-
55
+
58
56
  SIZEOF_DWORD = DL::SIZEOF_LONG
59
57
  else
60
58
  extend Fiddle::Importer
@@ -62,7 +60,7 @@ module Net
62
60
  include Fiddle::Win32Types
63
61
  SIZEOF_DWORD = Fiddle::SIZEOF_LONG
64
62
  end
65
-
63
+
66
64
  if RUBY_ENGINE == "jruby"
67
65
  typealias("HANDLE", "void *") # From winnt.h
68
66
  typealias("PHANDLE", "void *") # From winnt.h
@@ -76,105 +74,105 @@ module Net
76
74
  typealias("LPARAM", "long *") # From windef.h
77
75
  typealias("PDWORD_PTR", "long *") # From basetsd.h
78
76
  typealias("USHORT", "unsigned short") # From windef.h
79
-
77
+
80
78
  # From winbase.h, winnt.h
81
79
  INVALID_HANDLE_VALUE = -1
82
80
  NULL = nil
83
81
  PAGE_READWRITE = 0x0004
84
82
  FILE_MAP_WRITE = 2
85
83
  WM_COPYDATA = 74
86
-
84
+
87
85
  SMTO_NORMAL = 0 # From winuser.h
88
-
86
+
89
87
  SUFFIX = if RUBY_ENGINE == "jruby"
90
88
  "A"
91
89
  else
92
90
  ""
93
91
  end
94
-
92
+
95
93
  # args: lpClassName, lpWindowName
96
94
  extern "HWND FindWindow#{SUFFIX}(LPCTSTR, LPCTSTR)"
97
-
95
+
98
96
  # args: none
99
97
  extern 'DWORD GetCurrentThreadId()'
100
-
98
+
101
99
  # args: hFile, (ignored), flProtect, dwMaximumSizeHigh,
102
100
  # dwMaximumSizeLow, lpName
103
101
  extern "HANDLE CreateFileMapping#{SUFFIX}(HANDLE, void *, DWORD, " +
104
102
  "DWORD, DWORD, LPCTSTR)"
105
-
103
+
106
104
  # args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
107
105
  # dwfileOffsetLow, dwNumberOfBytesToMap
108
106
  extern 'LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD)'
109
-
107
+
110
108
  # args: lpBaseAddress
111
109
  extern 'BOOL UnmapViewOfFile(LPCVOID)'
112
-
110
+
113
111
  # args: hObject
114
112
  extern 'BOOL CloseHandle(HANDLE)'
115
-
113
+
116
114
  # args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult
117
115
  extern "LRESULT SendMessageTimeout#{SUFFIX}(HWND, UINT, WPARAM, LPARAM, " +
118
116
  "UINT, UINT, PDWORD_PTR)"
119
-
117
+
120
118
  # args: none
121
119
  extern 'DWORD GetLastError()'
122
-
120
+
123
121
  # args: none
124
122
  extern 'HANDLE GetCurrentProcess()'
125
-
123
+
126
124
  # args: hProcessHandle, dwDesiredAccess, (out) phNewTokenHandle
127
125
  extern 'BOOL OpenProcessToken(HANDLE, DWORD, PHANDLE)'
128
-
126
+
129
127
  # args: hTokenHandle, uTokenInformationClass,
130
128
  # (out) lpTokenInformation, dwTokenInformationLength
131
129
  # (out) pdwInfoReturnLength
132
130
  extern 'BOOL GetTokenInformation(HANDLE, UINT, LPVOID, DWORD, ' +
133
131
  'PDWORD)'
134
-
132
+
135
133
  # args: (out) lpSecurityDescriptor, dwRevisionLevel
136
134
  extern 'BOOL InitializeSecurityDescriptor(LPVOID, DWORD)'
137
-
135
+
138
136
  # args: (out) lpSecurityDescriptor, lpOwnerSid, bOwnerDefaulted
139
137
  extern 'BOOL SetSecurityDescriptorOwner(LPVOID, LPVOID, BOOL)'
140
-
138
+
141
139
  # args: pSecurityDescriptor
142
140
  extern 'BOOL IsValidSecurityDescriptor(LPVOID)'
143
-
141
+
144
142
  # Constants needed for security attribute retrieval.
145
143
  # Specifies the access mask corresponding to the desired access
146
144
  # rights.
147
145
  TOKEN_QUERY = 0x8
148
-
146
+
149
147
  # The value of TOKEN_USER from the TOKEN_INFORMATION_CLASS enum.
150
148
  TOKEN_USER_INFORMATION_CLASS = 1
151
-
149
+
152
150
  # The initial revision level assigned to the security descriptor.
153
151
  REVISION = 1
154
-
152
+
155
153
  # Structs for security attribute functions.
156
154
  # Holds the retrieved user access token.
157
155
  TOKEN_USER = struct ['void * SID', 'DWORD ATTRIBUTES']
158
-
156
+
159
157
  # Contains the security descriptor, this gets passed to the
160
158
  # function that constructs the shared memory map.
161
159
  SECURITY_ATTRIBUTES = struct ['DWORD nLength',
162
160
  'LPVOID lpSecurityDescriptor',
163
161
  'BOOL bInheritHandle']
164
-
162
+
165
163
  # The security descriptor holds security information.
166
164
  SECURITY_DESCRIPTOR = struct ['UCHAR Revision', 'UCHAR Sbz1',
167
165
  'USHORT Control', 'LPVOID Owner',
168
166
  'LPVOID Group', 'LPVOID Sacl',
169
167
  'LPVOID Dacl']
170
-
168
+
171
169
  # The COPYDATASTRUCT is used to send WM_COPYDATA messages
172
170
  COPYDATASTRUCT = if RUBY_ENGINE == "jruby"
173
171
  struct ['ULONG_PTR dwData', 'DWORD cbData', 'LPVOID lpData']
174
172
  else
175
173
  struct ['uintptr_t dwData', 'DWORD cbData', 'LPVOID lpData']
176
174
  end
177
-
175
+
178
176
  # Compatibility for security attribute retrieval.
179
177
  if RUBY_VERSION < "1.9"
180
178
  # Alias functions to > 1.9 capitalization
@@ -196,15 +194,15 @@ module Net
196
194
  alias_method new_name, name
197
195
  module_function new_name
198
196
  end
199
-
197
+
200
198
  def self.malloc_ptr(size)
201
199
  return DL.malloc(size)
202
200
  end
203
-
201
+
204
202
  def self.get_ptr(data)
205
203
  return data.to_ptr
206
204
  end
207
-
205
+
208
206
  def self.set_ptr_data(ptr, data)
209
207
  ptr[0] = data
210
208
  end
@@ -220,15 +218,15 @@ module Net
220
218
  attach_function :malloc, [:size_t], :pointer
221
219
  attach_function :free, [:pointer], :void
222
220
  end
223
-
221
+
224
222
  def self.malloc_ptr(size)
225
223
  Fiddle::Pointer.new(LibC.malloc(size), size, LibC.method(:free))
226
224
  end
227
-
225
+
228
226
  def self.get_ptr(ptr)
229
227
  return data.address
230
228
  end
231
-
229
+
232
230
  def self.set_ptr_data(ptr, data)
233
231
  ptr.write_string_length(data, data.size)
234
232
  end
@@ -236,19 +234,19 @@ module Net
236
234
  def self.malloc_ptr(size)
237
235
  return DL::CPtr.malloc(size, DL::RUBY_FREE)
238
236
  end
239
-
237
+
240
238
  def self.get_ptr(data)
241
239
  return DL::CPtr.to_ptr data
242
240
  end
243
-
241
+
244
242
  def self.set_ptr_data(ptr, data)
245
243
  DL::CPtr.new(ptr)[0,data.size] = data
246
244
  end
247
245
  end
248
-
246
+
249
247
  def self.get_security_attributes_for_user
250
248
  user = get_current_user
251
-
249
+
252
250
  psd_information = malloc_ptr(Win::SECURITY_DESCRIPTOR.size)
253
251
  raise_error_if_zero(
254
252
  Win.InitializeSecurityDescriptor(psd_information,
@@ -261,45 +259,46 @@ module Net
261
259
  raise_error_if_zero(
262
260
  Win.IsValidSecurityDescriptor(psd_information)
263
261
  )
264
-
262
+
265
263
  sa = Win::SECURITY_ATTRIBUTES.new(to_struct_ptr(malloc_ptr(Win::SECURITY_ATTRIBUTES.size)))
266
264
  sa.nLength = Win::SECURITY_ATTRIBUTES.size
267
265
  sa.lpSecurityDescriptor = psd_information.to_i
268
266
  sa.bInheritHandle = 1
269
-
267
+
270
268
  return sa
271
269
  end
272
-
270
+
273
271
  if RUBY_ENGINE == "jruby"
274
272
  def self.ptr_to_s(ptr, size)
275
273
  ret = ptr.to_s(size)
276
274
  ret << "\x00" while ret.size < size
277
275
  ret
278
276
  end
279
-
277
+
280
278
  def self.ptr_to_handle(phandle)
281
279
  phandle.ptr
282
280
  end
283
-
281
+
284
282
  def self.ptr_to_dword(ptr)
285
283
  first = ptr.ptr.to_i
286
284
  second = ptr_to_s(ptr,Win::SIZEOF_DWORD).unpack('L')[0]
287
285
  raise "Error" unless first == second
286
+
288
287
  first
289
288
  end
290
-
289
+
291
290
  def self.to_token_user(ptoken_information)
292
291
  TOKEN_USER.new(ptoken_information.to_ptr)
293
292
  end
294
-
293
+
295
294
  def self.to_struct_ptr(ptr)
296
295
  ptr.to_ptr
297
296
  end
298
-
297
+
299
298
  def self.get_sid(user)
300
299
  ptr_to_s(user.to_ptr.ptr,Win::SIZEOF_DWORD).unpack('L')[0]
301
300
  end
302
-
301
+
303
302
  def self.get_sid_ptr(user)
304
303
  user.to_ptr.ptr
305
304
  end
@@ -307,28 +306,28 @@ module Net
307
306
  def self.get_sid(user)
308
307
  user.SID
309
308
  end
310
-
309
+
311
310
  def self.ptr_to_handle(phandle)
312
311
  phandle.ptr.to_i
313
312
  end
314
-
313
+
315
314
  def self.to_struct_ptr(ptr)
316
315
  ptr
317
316
  end
318
-
317
+
319
318
  def self.ptr_to_dword(ptr)
320
319
  ptr.to_s(Win::SIZEOF_DWORD).unpack('L')[0]
321
320
  end
322
-
321
+
323
322
  def self.to_token_user(ptoken_information)
324
323
  TOKEN_USER.new(ptoken_information)
325
324
  end
326
-
325
+
327
326
  def self.get_sid_ptr(user)
328
327
  user.SID
329
328
  end
330
329
  end
331
-
330
+
332
331
  def self.get_current_user
333
332
  token_handle = open_process_token(Win.GetCurrentProcess,
334
333
  Win::TOKEN_QUERY)
@@ -336,10 +335,10 @@ module Net
336
335
  Win::TOKEN_USER_INFORMATION_CLASS)
337
336
  return token_user
338
337
  end
339
-
338
+
340
339
  def self.open_process_token(process_handle, desired_access)
341
340
  ptoken_handle = malloc_ptr(Win::SIZEOF_DWORD)
342
-
341
+
343
342
  raise_error_if_zero(
344
343
  Win.OpenProcessToken(process_handle, desired_access,
345
344
  ptoken_handle)
@@ -347,12 +346,12 @@ module Net
347
346
  token_handle = ptr_to_handle(ptoken_handle)
348
347
  return token_handle
349
348
  end
350
-
349
+
351
350
  def self.get_token_information(token_handle,
352
351
  token_information_class)
353
352
  # Hold the size of the information to be returned
354
353
  preturn_length = malloc_ptr(Win::SIZEOF_DWORD)
355
-
354
+
356
355
  # Going to throw an INSUFFICIENT_BUFFER_ERROR, but that is ok
357
356
  # here. This is retrieving the size of the information to be
358
357
  # returned.
@@ -360,7 +359,7 @@ module Net
360
359
  token_information_class,
361
360
  Win::NULL, 0, preturn_length)
362
361
  ptoken_information = malloc_ptr(ptr_to_dword(preturn_length))
363
-
362
+
364
363
  # This call is going to write the requested information to
365
364
  # the memory location referenced by token_information.
366
365
  raise_error_if_zero(
@@ -370,74 +369,76 @@ module Net
370
369
  ptoken_information.size,
371
370
  preturn_length)
372
371
  )
373
-
372
+
374
373
  return to_token_user(ptoken_information)
375
374
  end
376
-
375
+
377
376
  def self.raise_error_if_zero(result)
378
377
  if result == 0
379
378
  raise "Windows error: #{Win.GetLastError}"
380
379
  end
381
380
  end
382
-
381
+
383
382
  # Get a null-terminated string given a string.
384
383
  def self.get_cstr(str)
385
384
  return str + "\000"
386
385
  end
387
386
  end
388
-
387
+
389
388
  # This is the pseudo-socket implementation that mimics the interface of
390
389
  # a socket, translating each request into a Windows messaging call to
391
390
  # the pageant daemon. This allows pageant support to be implemented
392
391
  # simply by replacing the socket factory used by the Agent class.
393
392
  class Socket
394
393
  private_class_method :new
395
-
394
+
396
395
  # The factory method for creating a new Socket instance.
397
396
  def self.open
398
397
  new
399
398
  end
400
-
399
+
401
400
  # Create a new instance that communicates with the running pageant
402
401
  # instance. If no such instance is running, this will cause an error.
403
402
  def initialize
404
403
  @win = Win.FindWindow("Pageant", "Pageant")
405
-
404
+
406
405
  if @win.to_i == 0
407
406
  raise Net::SSH::Exception,
408
407
  "pageant process not running"
409
408
  end
410
-
409
+
411
410
  @input_buffer = Net::SSH::Buffer.new
412
411
  @output_buffer = Net::SSH::Buffer.new
413
412
  end
414
-
413
+
415
414
  # Forwards the data to #send_query, ignoring any arguments after
416
415
  # the first.
417
416
  def send(data, *args)
418
417
  @input_buffer.append(data)
419
-
418
+
420
419
  ret = data.length
421
-
420
+
422
421
  while true
423
422
  return ret if @input_buffer.length < 4
423
+
424
424
  msg_length = @input_buffer.read_long + 4
425
425
  @input_buffer.reset!
426
-
426
+
427
427
  return ret if @input_buffer.length < msg_length
428
+
428
429
  msg = @input_buffer.read!(msg_length)
429
430
  @output_buffer.append(send_query(msg))
430
431
  end
431
432
  end
432
-
433
+
433
434
  # Reads +n+ bytes from the cached result of the last query. If +n+
434
435
  # is +nil+, returns all remaining data from the last query.
435
436
  def read(n = nil)
436
437
  @output_buffer.read(n)
437
438
  end
438
-
439
+
439
440
  def close; end
440
-
441
+
441
442
  # Packages the given query string and sends it to the pageant
442
443
  # process via the Windows messaging subsystem. The result is
443
444
  # cached, to be returned piece-wise when #read is called.
@@ -446,29 +447,29 @@ module Net
446
447
  filemap = 0
447
448
  ptr = nil
448
449
  id = Win.malloc_ptr(Win::SIZEOF_DWORD)
449
-
450
+
450
451
  mapname = "PageantRequest%08x" % Win.GetCurrentThreadId()
451
452
  security_attributes = Win.get_ptr Win.get_security_attributes_for_user
452
-
453
+
453
454
  filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE,
454
455
  security_attributes,
455
456
  Win::PAGE_READWRITE, 0,
456
457
  AGENT_MAX_MSGLEN, mapname)
457
-
458
+
458
459
  if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE
459
460
  raise Net::SSH::Exception,
460
461
  "Creation of file mapping failed with error: #{Win.GetLastError}"
461
462
  end
462
-
463
+
463
464
  ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0,
464
465
  0)
465
-
466
+
466
467
  if ptr.nil? || ptr.null?
467
468
  raise Net::SSH::Exception, "Mapping of file failed"
468
469
  end
469
-
470
+
470
471
  Win.set_ptr_data(ptr, query)
471
-
472
+
472
473
  # using struct to achieve proper alignment and field size on 64-bit platform
473
474
  cds = Win::COPYDATASTRUCT.new(Win.malloc_ptr(Win::COPYDATASTRUCT.size))
474
475
  cds.dwData = AGENT_COPYDATA_ID
@@ -476,14 +477,14 @@ module Net
476
477
  cds.lpData = Win.get_cstr(mapname)
477
478
  succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL,
478
479
  cds.to_ptr, Win::SMTO_NORMAL, 5000, id)
479
-
480
+
480
481
  if succ > 0
481
482
  retlen = 4 + ptr.to_s(4).unpack("N")[0]
482
483
  res = ptr.to_s(retlen)
483
484
  else
484
485
  raise Net::SSH::Exception, "Message failed with error: #{Win.GetLastError}"
485
486
  end
486
-
487
+
487
488
  return res
488
489
  ensure
489
490
  Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null?
@@ -491,7 +492,6 @@ module Net
491
492
  end
492
493
  end
493
494
  end
494
-
495
495
  end
496
496
  end
497
497
  end