smbRpc 0.0.3

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 (79) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +11 -0
  3. data/examples/enumLsa.rb +44 -0
  4. data/examples/enumSmbPipe.rb +16 -0
  5. data/lib/smbRpc.rb +33 -0
  6. data/lib/smbRpc/epmapper.rb +13 -0
  7. data/lib/smbRpc/epmapper/constants.rb +28 -0
  8. data/lib/smbRpc/epmapper/epmLookup.rb +98 -0
  9. data/lib/smbRpc/lsarpc.rb +22 -0
  10. data/lib/smbRpc/lsarpc/close.rb +48 -0
  11. data/lib/smbRpc/lsarpc/constants.rb +54 -0
  12. data/lib/smbRpc/lsarpc/enumerateAccounts.rb +55 -0
  13. data/lib/smbRpc/lsarpc/enumeratePrivilegesAccount.rb +49 -0
  14. data/lib/smbRpc/lsarpc/lookupNames.rb +74 -0
  15. data/lib/smbRpc/lsarpc/lookupPrivilegeName.rb +37 -0
  16. data/lib/smbRpc/lsarpc/lookupSids.rb +96 -0
  17. data/lib/smbRpc/lsarpc/openAccount.rb +49 -0
  18. data/lib/smbRpc/lsarpc/openPolicy.rb +52 -0
  19. data/lib/smbRpc/lsarpc/queryInformationPolicy.rb +92 -0
  20. data/lib/smbRpc/lsarpc/querySecurityObject.rb +75 -0
  21. data/lib/smbRpc/rpc.rb +5 -0
  22. data/lib/smbRpc/rpc/connection.rb +34 -0
  23. data/lib/smbRpc/rpc/constants.rb +64 -0
  24. data/lib/smbRpc/rpc/endpoints.rb +38 -0
  25. data/lib/smbRpc/rpc/ndrep.rb +24 -0
  26. data/lib/smbRpc/rpc/pdu.rb +40 -0
  27. data/lib/smbRpc/samr.rb +40 -0
  28. data/lib/smbRpc/samr/addMemberToAlias.rb +43 -0
  29. data/lib/smbRpc/samr/addMemberToGroup.rb +36 -0
  30. data/lib/smbRpc/samr/changePasswordUser.rb +64 -0
  31. data/lib/smbRpc/samr/closeHandle.rb +50 -0
  32. data/lib/smbRpc/samr/connect.rb +46 -0
  33. data/lib/smbRpc/samr/constants.rb +114 -0
  34. data/lib/smbRpc/samr/createAliasInDomain.rb +45 -0
  35. data/lib/smbRpc/samr/createGroupInDomain.rb +46 -0
  36. data/lib/smbRpc/samr/createUserInDomain.rb +48 -0
  37. data/lib/smbRpc/samr/deleteAlias.rb +35 -0
  38. data/lib/smbRpc/samr/deleteGroup.rb +35 -0
  39. data/lib/smbRpc/samr/deleteUser.rb +35 -0
  40. data/lib/smbRpc/samr/enumerateAliasesInDomain.rb +61 -0
  41. data/lib/smbRpc/samr/enumerateDomainsInSamServer.rb +52 -0
  42. data/lib/smbRpc/samr/enumerateGroupsInDomain.rb +60 -0
  43. data/lib/smbRpc/samr/enumerateUsersInDomain.rb +67 -0
  44. data/lib/smbRpc/samr/getMembersInAlias.rb +41 -0
  45. data/lib/smbRpc/samr/getMembersInGroup.rb +45 -0
  46. data/lib/smbRpc/samr/lookupDomainInSamServer.rb +41 -0
  47. data/lib/smbRpc/samr/lookupIdsInDomain.rb +52 -0
  48. data/lib/smbRpc/samr/lookupNamesInDomain.rb +55 -0
  49. data/lib/smbRpc/samr/openAlias.rb +39 -0
  50. data/lib/smbRpc/samr/openDomain.rb +48 -0
  51. data/lib/smbRpc/samr/openGroup.rb +39 -0
  52. data/lib/smbRpc/samr/openUser.rb +39 -0
  53. data/lib/smbRpc/samr/queryInformationUser.rb +182 -0
  54. data/lib/smbRpc/samr/removeMemberFromAlias.rb +43 -0
  55. data/lib/smbRpc/samr/removeMemberFromGroup.rb +34 -0
  56. data/lib/smbRpc/samr/setInformationUser.rb +53 -0
  57. data/lib/smbRpc/srvsvc.rb +12 -0
  58. data/lib/smbRpc/srvsvc/netShareEnum.rb +104 -0
  59. data/lib/smbRpc/srvsvc/serverGetInfo.rb +57 -0
  60. data/lib/smbRpc/svcctl.rb +20 -0
  61. data/lib/smbRpc/svcctl/closeService.rb +48 -0
  62. data/lib/smbRpc/svcctl/constants.rb +88 -0
  63. data/lib/smbRpc/svcctl/controlService.rb +48 -0
  64. data/lib/smbRpc/svcctl/createService.rb +68 -0
  65. data/lib/smbRpc/svcctl/deleteService.rb +31 -0
  66. data/lib/smbRpc/svcctl/enumServicesStatus.rb +96 -0
  67. data/lib/smbRpc/svcctl/openScm.rb +37 -0
  68. data/lib/smbRpc/svcctl/openService.rb +36 -0
  69. data/lib/smbRpc/svcctl/queryServiceConfig.rb +67 -0
  70. data/lib/smbRpc/svcctl/startService.rb +35 -0
  71. data/lib/smbRpc/updateRuby_smb.rb +3 -0
  72. data/lib/smbRpc/updateRuby_smb/client.rb +29 -0
  73. data/lib/smbRpc/updateRuby_smb/dcerpc.rb +30 -0
  74. data/lib/smbRpc/updateRuby_smb/ioctl_request.rb +53 -0
  75. data/lib/smbRpc/updateString.rb +3 -0
  76. data/lib/smbRpc/updateString/raise_not_error_success.rb +11 -0
  77. data/lib/smbRpc/updateString/to_des_ecb_lm.rb +34 -0
  78. data/smbRpc.gemspec +16 -0
  79. metadata +148 -0
@@ -0,0 +1,31 @@
1
+ module SmbRpc
2
+ class Svcctl < Rpc
3
+
4
+ class DeleteServiceReq < BinData::Record
5
+ endian :little
6
+ request :request
7
+ string :serviceHandle, :length => 20
8
+
9
+ def initialize_instance
10
+ super
11
+ serviceHandle.value = get_parameter(:handle)
12
+ request.pduHead.frag_length = self.num_bytes
13
+ request.opnum.value = 2 #RDeleteService
14
+ end
15
+ end
16
+
17
+ class DeleteServiceRes < BinData::Record
18
+ endian :little
19
+ request :response
20
+ uint32 :windowsError
21
+ end
22
+
23
+ def deleteService()
24
+ deleteServiceReq = DeleteServiceReq.new(handle:@serviceHandle)
25
+ deleteServiceRes = @file.ioctl_send_recv(deleteServiceReq).buffer
26
+ deleteServiceRes.raise_not_error_success("deleteService")
27
+ return 0
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,96 @@
1
+ module SmbRpc
2
+ class Svcctl < Rpc
3
+ class EnumServicesStatusReq < BinData::Record
4
+ default_parameter :bytesNeeded => 0
5
+ endian :little
6
+ request :request
7
+ string :scHandle, :length => 20
8
+ uint32 :serviceType
9
+ uint32 :serviceState
10
+ uint32 :bufSize
11
+ uint32 :ref_id_resume, :value => 1
12
+ uint32 :resume_handle
13
+
14
+ def initialize_instance
15
+ super
16
+ scHandle.value = get_parameter(:handle)
17
+ bufSize.value = get_parameter(:bytesNeeded)
18
+ serviceType.value = get_parameter(:type)
19
+ serviceState.value = get_parameter(:state)
20
+ request.pduHead.frag_length = self.num_bytes
21
+ request.opnum.value = 14 #REnumServicesStatusW
22
+ end
23
+ end
24
+
25
+ class Service_status < BinData::Record
26
+ endian :little
27
+ uint32 :ref_id_serviceName
28
+ uint32 :ref_id_displayName
29
+ uint32 :serviceType #SERVICE_STATUS nested struct begin
30
+ uint32 :currentState #different from SmbRpc::Svcctl::SERVICE_STATE
31
+ uint32 :controlsAccepted
32
+ uint32 :win32ExitCode
33
+ uint32 :serviceSpecificExitCode
34
+ uint32 :checkPoint
35
+ uint32 :waitHint #SERVICE_STATUS nested struct ends
36
+ string :serviceName
37
+ string :displayName
38
+ end
39
+
40
+ class Enum_service_statusw < BinData::Record
41
+ array :service_status_array, :type => :service_status, :initial_length => :servicesReturned
42
+ end
43
+
44
+ class EnumServicesStatusRes < BinData::Record
45
+ endian :little
46
+ request :response
47
+ uint32 :buffLen
48
+ string :buffer, :onlyif => lambda{ buffLen > 0 }, :read_length => :buffLen
49
+ uint32 :bytesNeeded
50
+ uint32 :servicesReturned
51
+ uint32 :ref_id_resumeIndex
52
+ uint32 :resumeIndex
53
+ uint32 :windowsError
54
+
55
+ def getService
56
+ enum_service_statusw = Enum_service_statusw.new(:servicesReturned => self.servicesReturned)
57
+ enum_service_statusw.read(self.buffer)
58
+ num = self.servicesReturned * 36
59
+ serviceStr = self.buffer[num..-1 ].scan(/\w.+?\x00\x00\x00/)
60
+ len = enum_service_statusw.service_status_array.length - 1 #get service array index
61
+ len.downto(0).each do |idx| #lopp backward b/c MS thaough it was cool to add a buffer in the middle of struct :(
62
+ enum_service_statusw.service_status_array[idx].displayName = serviceStr.pop.unpack("v*").pack("C*").chop
63
+ enum_service_statusw.service_status_array[idx].serviceName = serviceStr.pop.unpack("v*").pack("C*").chop
64
+ end
65
+ return enum_service_statusw.service_status_array
66
+ end
67
+ end
68
+
69
+ #[MS-SCMR] SC_MANAGER_ENUMERATE_SERVICE access right MUST have been granted to the caller when the RPC context handle
70
+ #to the service record was created
71
+ def enumServicesStatus(type:SVCCTL_SERVICE_TYPE["ALL"], state:SVCCTL_SERVICE_STATE["SERVICE_STATE_ALL"])
72
+ services = []
73
+ response = ""
74
+ idx = 0
75
+ loop do
76
+ enumServicesStatusReq = EnumServicesStatusReq.new(handle:@scHandle, bytesNeeded:512, type:type, state:state)
77
+ enumServicesStatusReq.resume_handle = idx
78
+ enumServicesStatusRes = @file.ioctl_send_recv(enumServicesStatusReq).buffer
79
+ response = enumServicesStatusRes
80
+ enumServicesStatusRes = EnumServicesStatusRes.read(enumServicesStatusRes)
81
+ idx = enumServicesStatusRes.resumeIndex
82
+ enumServicesStatusRes.getService.each do |i|
83
+ services << { serviceType:i.serviceType, currentState:i.currentState,
84
+ controlsAccepted:i.controlsAccepted, win32ExitCode:i.win32ExitCode,
85
+ serviceSpecificExitCode:i.serviceSpecificExitCode, checkPoint:i.checkPoint,
86
+ waitHint:i.waitHint, serviceName:i.serviceName, displayName:i.displayName
87
+ }
88
+ end
89
+ break if enumServicesStatusRes.windowsError == 0 || enumServicesStatusRes.windowsError != 234
90
+ end
91
+ response.raise_not_error_success("enumServicesStatus")
92
+ return services
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,37 @@
1
+ module SmbRpc
2
+ class Svcctl < Rpc
3
+
4
+ class OpenScmReq < BinData::Record
5
+ endian :little
6
+ request :request
7
+ uint32 :ref_id_machine_name, :value => 1
8
+ conformantandVaryingStrings :machine_name
9
+ uint32 :databaseName
10
+ uint32 :desiredAccess
11
+
12
+ def initialize_instance
13
+ super
14
+ machine_name.str = "\\\\#{get_parameter(:serverName)}\x00".bytes.pack("v*")
15
+ desiredAccess.value = get_parameter(:accessMask)
16
+ request.pduHead.frag_length = self.num_bytes
17
+ request.opnum.value = 15 #ROpenSCManagerW
18
+ end
19
+ end
20
+
21
+ class OpenScmRes < BinData::Record
22
+ endian :little
23
+ response :response
24
+ string :scHandle, :length => 20
25
+ uint32 :windowsError
26
+ end
27
+
28
+ def openScm(scAccessMask:)
29
+ openScmReq = OpenScmReq.new(serverName:@ip, accessMask:scAccessMask)
30
+ openScmRes = @file.ioctl_send_recv(openScmReq).buffer
31
+ openScmRes.raise_not_error_success("openScm")
32
+ openScmRes = OpenScmRes.read(openScmRes)
33
+ @scHandle = openScmRes.scHandle
34
+ return self
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ module SmbRpc
2
+ class Svcctl < Rpc
3
+ class OpenServiceReq < BinData::Record
4
+ endian :little
5
+ request :request
6
+ string :scHandle, :length => 20
7
+ conformantandVaryingStrings :serviceName
8
+ uint32 :desiredAccess
9
+
10
+ def initialize_instance
11
+ super
12
+ scHandle.value = get_parameter(:handle)
13
+ serviceName.str = "#{get_parameter(:svcName)}\x00".bytes.pack("v*")
14
+ desiredAccess.value = get_parameter(:access)
15
+ request.pduHead.frag_length = self.num_bytes
16
+ request.opnum.value = 16 #ROpenServiceW
17
+ end
18
+ end
19
+
20
+ class OpenServiceRes < BinData::Record
21
+ endian :little
22
+ request :request
23
+ string :serviceHandle, :length => 20
24
+ uint32 :windowsError
25
+ end
26
+
27
+ def openService(serviceName:, serviceAccessMask:)
28
+ openServiceReq = OpenServiceReq.new(svcName:serviceName, handle:@scHandle, access:serviceAccessMask)
29
+ openServiceRes = @file.ioctl_send_recv(openServiceReq).buffer
30
+ openServiceRes.raise_not_error_success("openService")
31
+ openServiceRes = OpenServiceRes.read(openServiceRes)
32
+ @serviceHandle = openServiceRes.serviceHandle
33
+ return self
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+
2
+ module SmbRpc
3
+ class Svcctl < Rpc
4
+
5
+ class QueryServiceConfigReq < BinData::Record
6
+ mandatory_parameter :handle
7
+ endian :little
8
+ request :request
9
+ string :serviceHandle, :length => 20
10
+ uint32 :bufSize
11
+
12
+ def initialize_instance
13
+ super
14
+ serviceHandle.value = get_parameter(:handle)
15
+ bufSize.value = get_parameter(:bytesNeeded)
16
+ request.pduHead.frag_length = self.num_bytes
17
+ request.opnum.value = 17 #RQueryServiceConfigW
18
+ end
19
+ end
20
+
21
+ class Query_service_configw < BinData::Record
22
+ endian :little
23
+ uint32 :serviceType
24
+ uint32 :startType
25
+ uint32 :errorControl
26
+ uint32 :ref_id_binaryPathName
27
+ uint32 :ref_id_loadOrderGroup
28
+ uint32 :tagId
29
+ uint32 :ref_id_dependencies
30
+ uint32 :ref_id_serviceStartName
31
+ uint32 :ref_id_displayName
32
+ conformantandVaryingStrings :binaryPathName
33
+ conformantandVaryingStrings :loadOrderGroup
34
+ conformantandVaryingStrings :dependencies
35
+ conformantandVaryingStrings :serviceStartName
36
+ conformantandVaryingStrings :displayName
37
+ end
38
+
39
+ class QueryServiceConfigRes < BinData::Record
40
+ endian :little
41
+ request :response
42
+ query_service_configw :serviceConfig
43
+ uint32 :bytesNeeded #bytes needed to return all data if function fail
44
+ uint32 :windowsError
45
+ end
46
+
47
+ def queryServiceConfig()
48
+ queryServiceConfigReq = QueryServiceConfigReq.new(handle:@serviceHandle, bytesNeeded:512)
49
+ queryServiceConfigRes = @file.ioctl_send_recv(queryServiceConfigReq).buffer
50
+ queryServiceConfigRes.raise_not_error_success("queryServiceConfig")
51
+ queryServiceConfigRes = QueryServiceConfigRes.read(queryServiceConfigRes)
52
+ config = queryServiceConfigRes.serviceConfig
53
+ return {
54
+ serviceType:config.serviceType,
55
+ startType:config.startType,
56
+ errorControl:config.errorControl,
57
+ tagId:config.tagId,
58
+ binaryPathName:config.binaryPathName.str.unpack("v*").pack("C*").chop,
59
+ loadOrderGroup:config.loadOrderGroup.str.unpack("v*").pack("C*").chop,
60
+ dependencies:config.dependencies.str.unpack("v*").pack("C*").chop,
61
+ serviceStartName:config.serviceStartName.str.unpack("v*").pack("C*").chop,
62
+ displayName:config.displayName.str.unpack("v*").pack("C*").chop
63
+ }
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ module SmbRpc
2
+ class Svcctl < Rpc
3
+
4
+ class StartServiceReq < BinData::Record
5
+ mandatory_parameter :handle
6
+ endian :little
7
+ request :request
8
+ string :serviceHandle, :length => 20
9
+ uint32 :argc
10
+ uint32 :argv
11
+
12
+ def initialize_instance
13
+ super
14
+ serviceHandle.value = get_parameter(:handle)
15
+ request.pduHead.frag_length = self.num_bytes
16
+ request.opnum.value = 19 #RStartServiceW
17
+ end
18
+ end
19
+
20
+ class StartServiceRes < BinData::Record
21
+ endian :little
22
+ request :response
23
+ uint32 :windowsError
24
+ end
25
+
26
+ def startService()
27
+ startServiceReq = StartServiceReq.new(handle:@serviceHandle)
28
+ startServiceRes = @file.ioctl_send_recv(startServiceReq).buffer
29
+ startServiceRes.raise_not_error_success("startService")
30
+ return 0
31
+ end
32
+
33
+ end
34
+ end
35
+
@@ -0,0 +1,3 @@
1
+ require"smbRpc/updateRuby_smb/client"
2
+ require"smbRpc/updateRuby_smb/ioctl_request"
3
+ require"smbRpc/updateRuby_smb/dcerpc"
@@ -0,0 +1,29 @@
1
+ module RubySMB
2
+ class Client
3
+
4
+ def send_recv(packet)
5
+ case packet.packet_smb_version
6
+ when 'SMB1'
7
+ packet.smb_header.uid = user_id if user_id
8
+ packet = smb1_sign(packet)
9
+ when 'SMB2'
10
+ packet = increment_smb_message_id(packet)
11
+ packet.smb2_header.session_id = session_id
12
+ unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest)
13
+ packet = smb2_sign(packet)
14
+ end
15
+ else
16
+ packet = packet
17
+ end
18
+ dispatcher.send_packet(packet)
19
+ raw_response = dispatcher.recv_packet
20
+
21
+ #fix ioctl_send_recv() raise error when receive STATUS_PENDING
22
+ #force repeat read request if server sends NtStatus STATUS_PENDING
23
+ raw_response = dispatcher.recv_packet if raw_response[8,4].unpack("V")[0] == WindowsError::NTStatus::STATUS_PENDING.value
24
+
25
+ self.sequence_counter += 1 if signing_required && !session_key.empty?
26
+ raw_response
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Dcerpc
4
+
5
+ def ioctl_send_recv(action, options={})
6
+ #update ioctl_send_recv to use the new RubySMB::SMB2::Packet::IoctlRequest2 structure and avoid `ioctl_send_recv': STATUS_BUFFER_OVERFLOW
7
+ request = set_header_fields(RubySMB::SMB2::Packet::IoctlRequest2.new(options))
8
+ request.ctl_code = 0x0011C017
9
+ request.flags.is_fsctl = 0x00000001
10
+ request.buffer = action.to_binary_s
11
+ ioctl_raw_response = @tree.client.send_recv(request)
12
+ ioctl_response = RubySMB::SMB2::Packet::IoctlResponse.read(ioctl_raw_response)
13
+ unless ioctl_response.valid?
14
+ raise RubySMB::Error::InvalidPacket.new(
15
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
16
+ expected_cmd: RubySMB::SMB2::Packet::IoctlRequest::COMMAND,
17
+ received_proto: ioctl_response.smb2_header.protocol,
18
+ received_cmd: ioctl_response.smb2_header.command
19
+ )
20
+ end
21
+ unless ioctl_response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
22
+ raise RubySMB::Error::UnexpectedStatusCode, ioctl_response.status_code.name
23
+ end
24
+ ioctl_response
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,53 @@
1
+ module RubySMB
2
+ module SMB2
3
+ module Packet
4
+ # An SMB2 Ioctl Request Packet as defined in
5
+ # [2.2.31 SMB2 IOCTL Request](https://msdn.microsoft.com/en-us/library/cc246545.aspx)
6
+ class IoctlRequest2 < RubySMB::GenericPacket
7
+ #copy IoctlRequest to IoctlRequest2 to change max_output_response initial_value
8
+ COMMAND = RubySMB::SMB2::Commands::IOCTL
9
+
10
+ endian :little
11
+
12
+ smb2_header :smb2_header
13
+ uint16 :structure_size, label: 'Structure Size', initial_value: 57
14
+ uint16 :reserved1, label: 'Reserved Space'
15
+ uint32 :ctl_code, label: 'Control Code'
16
+ smb2_fileid :file_id, label: 'File Id'
17
+ uint32 :input_offset, label: 'Input Offset', initial_value: -> { calc_input_offset }
18
+ uint32 :input_count, label: 'Input Count', initial_value: -> { buffer.do_num_bytes }
19
+ uint32 :max_input_response, label: 'Max Input Response'
20
+ uint32 :output_offset, label: 'Output Offset', initial_value: -> { input_offset + output_count }
21
+ uint32 :output_count, label: 'Output Count'
22
+ #change initial_value from 2014 to 0x2000 to avoid /lib/ruby_smb/smb2/dcerpc.rb:67:in `ioctl_send_recv': STATUS_BUFFER_OVERFLOW
23
+ uint32 :max_output_response, label: 'Max Output response', initial_value: 0x2000
24
+
25
+ struct :flags do
26
+ bit7 :reserved1, label: 'Reserved Space'
27
+ bit1 :is_fsctl, label: 'FSCTL not IOCTL'
28
+
29
+ bit8 :reserved2, label: 'Reserved Space'
30
+ bit8 :reserved3, label: 'Reserved Space'
31
+ bit8 :reserved4, label: 'Reserved Space'
32
+ end
33
+
34
+ uint32 :reserved2, label: 'Reserved Space'
35
+ string :buffer, label: 'Input Buffer', read_length: -> { input_count + output_count }
36
+
37
+ # Calculates the value for the input_offset field.
38
+ # If the input buffer is empty then this should be set to 0,
39
+ # otherwise it should return the absolute offset of the input buffer.
40
+ #
41
+ # @return [Integer] the value to store in #input_offset
42
+ def calc_input_offset
43
+ if input_count.zero?
44
+ 0
45
+ else
46
+ buffer.abs_offset
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ require"smbRpc/updateString/raise_not_error_success"
2
+ require"smbRpc/updateString/to_des_ecb_lm"
3
+
@@ -0,0 +1,11 @@
1
+ class String
2
+
3
+ def raise_not_error_success(funcName)
4
+ winError = self[-4,4].unpack("V")[0]
5
+ error = WindowsError::Win32.find_by_retval(winError)[0]
6
+ error = WindowsError::NTStatus.find_by_retval(winError)[0] if error.nil?
7
+ raise "%s Fail, WinError: %s 0x%08x"%[funcName, "UNKNOWN ERROR CODE", winError ] if error.nil?
8
+ error.value == 0? error.value : (raise "%s Fail, WinError: %s %s"%[funcName, error.name, error.description])
9
+ end
10
+
11
+ end