Kernel32.dll - DeviceIOControl returns false while trying to get String descriptor in Win 10 - kernel32

I am currently using the DeviceIOControl API from kernel32.dll to get the String Descriptors of the list of connected USB devices.
public static String GetStringDescriptor(IntPtr deviceHandle, Int32 ConnectionIndex, Byte DescriptorIndex, UInt16 LanguageID)
{
USB_DESCRIPTOR_REQUEST Buffer = new USB_DESCRIPTOR_REQUEST();
Buffer.ConnectionIndex = ConnectionIndex;
Buffer.SetupPacket.wValue = (UInt16)((USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex);
Buffer.SetupPacket.wIndex = LanguageID;
Buffer.SetupPacket.wLength = MAXIMUM_USB_STRING_LENGTH;
Int32 nBytesReturned;
Boolean Status = DeviceIoControl(deviceHandle,
IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
ref Buffer,
Marshal.SizeOf(Buffer),
ref Buffer,
Marshal.SizeOf(Buffer),
out nBytesReturned,
IntPtr.Zero);
if (Status)
return Buffer.Data.bString;
else
return null;
}
We use this function to get the descriptor details such as Language ID, Serial number, Manufacturer and Product String. Only while requesting the Serial Number, the Status returned is TRUE and we get the expected values. But the status returns false for Language id, manufacturer and Product string.
I checked the error status returned by the DeviceIoControl using:
int error = Marshal.GetLastWin32Error();
It returns 31 as the error code which means that the Device is not working properly/ the driver for the device is not properly installed.
I tried all the obvious solutions like reinstalling the driver for the device and restarting the PC etc., but none seems to work. I am sure there are no issues in the device or the code because it works flawlessly in windows 7 PCs. Also, since I am able to get the serial number, I think the device handle is also proper.
I am not able to proceed with any further debugging. Is there some update to the DeviceIoControl function in Windows 10? Or is the way to get the languageID, manufacturer and Product String changed in Windows 10?

Most probably the device you are trying to get string descriptors from is in low power state. Check its current power state first, and if it differs from "PowerDeviceD0" - string descriptors may not be obtained (depending on device, actually, and actual power state level D1, D2, D3). This could be the cause of error code 31 from DeviceIOControl().
Try to wake the device first or get some stored strings with SetupAPI.

Related

yubihsm2 signatures are invalid when signing ETH transactions

I am trying to figure out how to get this yubihsm2 to work with signing eth transactions. I have been using the python lib and so far i have had some basic setup. Below is an abbreviation of what i have
web3_endpoint = ''
web3 = Web3(HTTPProvider(web3_endpoint))
hsm = YubiHsm.connect("http://localhost:12345")
session = hsm.create_session_derived(1, "password")
key = session.get_object(1,OBJECT.ASYMMETRIC_KEY)
#key = AsymmetricKey.generate(session, 1, "EC Key", 1, CAPABILITY.SIGN_ECDSA, ALGORITHM.EC_K256)
pub_key = key.get_public_key()
#raw_pub = pub_key.public_bytes(
# encoding=serialization.Encoding.DER,
# format=serialization.PublicFormat.SubjectPublicKeyInfo
# )
raw_pub = pub_key.public_bytes(
encoding=serialization.Encoding.X962,
format=serialization.PublicFormat.UncompressedPoint
)
print ("Public key (Uncompressed):\n",binascii.b2a_hex(raw_pub))
unindexPub = raw_pub[1:]
public_key_hash = Web3.keccak(unindexPub)
address_bytes = public_key_hash[-20:]
address = address_bytes.hex()
print(address)
Now so far i can consistently get the same public key and it looks correct. I then get the same public key each time. When i say correct, the formatting looks correct and is the correct number of bytes.
1). should i be using the commented out public key formatting or the uncompressed X962 encoding that i have above.
From there, this is where things get a bit weird
transaction = {
'to': Web3.toChecksumAddress('0x785AB1daE1b0Ee3f2412aCF55e4153A9517b07e1'),
'gas': 21000,
'gasPrice': Web3.toWei(5, 'gwei'),
'value': 1,
'nonce': 1,
'chainId': 4,
}
serializable_transaction = serializable_unsigned_transaction_from_dict(transaction)
transaction_hash = serializable_transaction.hash()
print(transaction_hash.hex())
# sign the transaction hash and calculate v value
signature = key.sign_ecdsa(transaction_hash,hashes.SHA3_256())
r, s = ecdsa.util.sigdecode_der(signature, ecdsa.SECP256k1.generator.order())
print("r: "+str(r)+"\ns: "+str(s))
v = 28
# encode the transaction along with the full signature and send it
encoded_transaction = encode_transaction(serializable_transaction, vrs=(v, r, s))
web3.eth.sendRawTransaction(encoded_transaction)
I am settings v to 28.. i also test it with 27.. I could use the correct amount with the chainid.. but it's not necessary right from the perspective of trying to get a valid signature (recoverable to get the same public key each time). Sometimes i am getting the error "invalid sender" and other times i am getting the error "insufficient gas." If i take the signature output and use a javascript lib to try to find the public key, each time i am getting a different public key. But i keep consistently generating the same public key from the yubihsm2 in this python app.
I have also commented out in sign_ecdsa the hashing function as i am passing in the data already hashed (in order to use keccak256).
Is there something i am missing? Why are these transactions not signing correctly for eth?
i am getting some of those serialization helpers from enter link description here
helper serialization functions
Thanks

alter external table TABLENAME refresh error

Error message - SQL execution internal error: Processing aborted due to error 300002:1263389222; incident 9679362.
Trying to refresh external table on S3. It has worked previously.
create or replace external table EXT_ANIXTER_WNT_PART(event_timestamp datetime as TO_TIMESTAMP(value:wirepas.wirepas.packetReceivedEvent.rxTimeMsEpoch::varchar),
source_endpoint int as (value:wirepas.wirepas.packetReceivedEvent.sourceEndpoint::int),
source_address int as (value:wirepas.wirepas.packetReceivedEvent.sourceAddress::int),
folder varchar as (split_part(metadata$filename,'/', 1)::varchar),
message_date date as to_date(split_part(metadata$filename,'/', 2) ||'/' || split_part(metadata$filename,'/', 3) ||'/' || split_part(metadata$filename,'/', 4), 'YYYY/MM/DD')
partition by (folder, message_date)
location = #LABS_DATA.SBAS.PROLOGIS2WPEWNT_EXTWIREPAS_COM
file_format = (type = JSON)
refresh_on_create = TRUE
auto_refresh = TRUE
Try increasing the warehouse size and see if that works. Maybe the current warehouse isnt enough to read all the files (it may be due to memory not enough on the current warehouse size) depending upon the number of files in the S3 bucket.

Azure eventhub sending several float array messages in python

I have three float arrays of data (A,B,C) that I want to send it to event hub.
The issue here is that the classes are nested and I can't figure out how to shape the data to be able to send successfully.
Here is the code that I am trying
logger = logging.getLogger("azure")
ADDRESS = ""
USER = ""
KEY = ""
try:
if not ADDRESS:
raise ValueError("No EventHubs URL supplied.")
# Create Event Hubs client
client = EventHubClient(ADDRESS, debug=False, username=USER, password=KEY)
sender = client.add_sender(partition="0")
client.run()
x_value = np.arange(100)
try:
start_time = time.time()
for i in range(100000):
A = np.asarray([1,2,3,4])
B = np.asarray([2,3,4,5])
C = np.asarray([3,4,5,6])
message = [A, B, C]
sender.send(EventData(body = message))
time.sleep(1)
except:
raise
finally:
end_time = time.time()
client.stop()
run_time = end_time - start_time
logger.info("Runtime: {} seconds".format(run_time))
except KeyboardInterrupt:
pass
In this way, I am seeing the error 'ValueBody' object has no attribute 'append'
I think by types, the class encodes the message differently.
Instead of sending a single message with a serial string, I want to send the message in a parallel way, and receive them something like this:
Receive one eventdata with the form of the list [A,B,C]
Receive three eventdata A, B, C separately, like calling three different objects basis.
For the second way, I am not sure if it would work since I am using only one partition and that may have the three eventdata A, B, C mixed when I receive them and I do not want that.
I have confirmed with ms support, the feedback is that: it only works for a list of string or bytes, but does not work for a list of int.
And also you should note that, even it sends a list of string, when receive the list, it will concatenate the all elements of the list to compose a single message. For example, if there is a list ["a","b","c","d"] for sending, when receive it, it will show this "abcd" as a whole string.
I have tested it by myself, the above information is correct.
So for your case, you should consider change the list to a string or json string. when receiving it, you can format the data to what you need.
Hope it helps.

Solidity and Web3 sha3() methods return something else

In my contract, I have a function that returns the sha3 hash of a certain set of values. While running some tests I found that the value returned from this function differs from the hash value generated by web3.utils.sha3() (with identical arguments).
Here is the code:
Solidity
function hashInfo() public onlyOwner view returns (bytes32) {
bytes32 hash = sha3(
'0x969A70A4fa9F69D2D655E4B743abb9cA297E5328',
'0x496AAFA2960f3Ff530716B5334c9aFf4612e3c27',
'jdiojd',
'oidjoidj',
'idjodj',
12345
)
return hash;
}
JS (web3)
async function testHash(instance){
const contractHash = await instance.methods.hashInfo().call({from: '0x969A70A4fa9F69D2D655E4B743abb9cA297E5328'});
const localHash = web3.utils.sha3(
'0x969A70A4fa9F69D2D655E4B743abb9cA297E5328',
'0x496AAFA2960f3Ff530716B5334c9aFf4612e3c27',
'jdiojd',
'oidjoidj',
'idjodj',
12345
)
console.log(contractHash);
console.log(localHash);
console.log('local == contract: ' + (contractHash == localHash));
}
The resulting console output is:
0xe65757c5a99964b72d217493c192c073b9a580ec4b477f40a6c1f4bc537be076
0x3c23cebfe35b4da6f6592d38876bdb93f548085baf9000d538a1beb31558fc6d
local == contract: false
Any ideas? Does this have something to do with passing multiple arguments to the functions? I have also tried to convert everything to a string and concatenate them into one single string, but also without success.
Thanks in advance!
UPDATE
I found out there also if a web3 method called web3.utils.soliditySha3(). This too did not work and gave the following result:
0xe65757c5a99964b72d217493c192c073b9a580ec4b477f40a6c1f4bc537be076
0x0cf65f7c81dab0a5d414539b0e2f3807526fd9c15e197eaa6c7706d27aa7a0f8
local == contract: false
I'm happy I came after your update as I was just gonna suggest solditySHA3. Now that you've got the right function your problem is most likely with Soldity packing it's parameters.
As you can see here, sha3 is an alias to keccak256 which tightly packs it's arguments. Following the link on that page takes you here which fully explains how it's handled. Basically just take the inputs to soliditySHA3 and pack the bits as if they were the sizes of the variables you used. So if you hashed two uint32s (32 bits each, 64 total) you need to take the 2 64 bit Javascript numbers and compress them into 1 Javascript number.
For cases where more than 64 bits are needed I believe you can pass sequential ints (sets of 64 bits) to soliditySHA3 or you could use a BigInt. Personally, I usually try to only hash 256 bit variables together to avoid having to manually pack my bits on the JS end, but we all know that space constraints are huge in Solidity. I hope I helped, and let me know if you have further questions.

Read GPS in to Access using VBA and compare

I've tried googling, but with limited luck - what I want to do is use VBA to read in coordinates from a serial GPS dongle (or bluetooth Android phone mimicking the former), log a "visit" record, and find the nearest matching record on a table of our clients. Has anyone seen an opensource script that will allow this?
Thanks in advance.
PG
For the serial port data acquisition see the Serial Port Communications page at my web site. Then you can write records to a table using a SQL Insert query or a DAO Recordset with an AddNew. However finding the nearest matching record will likely require using of geometry to figure out the reading through the table looking for the closest location I'd have to refresh my memory as to the exact equations required.
I'm also thinking that to speed up the search you might want to index the latitude and longitude and start your search at nearby lat/longs. That is limit the initial record set to plus/minus, for example, 0.1 of a lat/long which, just guessing would be about 10 kms square.
Here's a rough rundown of what you will need to do.
Lookup Longitude & Latitude For Your Clients' Addresses:
I posted a question a while back on SO asking how to get GPS Coordinates for an address. You can see that question here. There's actually two functions there for you, one to use Google Maps API and another that uses rpc.geocoder.us. Take your pick. Just be aware that each of them having limitations. Google has licensing restrictions as well as maximum queries per day. Geocoder.us has a limit of one query every 15 seconds and I don't remember what their maximum queries per day is, if they even have a limit.
Obviously, you will need to retrieve the Longitude and Latitude for your addresses beforehand, and store this information along with the address. You could possibly try to come up with a zip code for the area and lookup the addresses by that but it could be horribly inaccurate in sprawling urban areas, especially if you have a lot of customers concentrated in a single zip code. You'll need to take Tony's advice here and query your GPS coordinate data using a between statement to get addresses in the near vicinity.
Get GPS Data from the GPS Device
As Tony has already pointed out, you'll need to use something like an ActiveX control, DLL, or API call to perform serial communications with your GPS Device. I have used MS's communication ActiveX control in the past for getting GPS data and it did work satisfactory.
I don't know where my code is to retrieve the incoming data from the GPS device. It's not exactly trivial if you have never programmed serial communications before. You usually have an OnComm event that fires on incoming data. If I remember correctly you loop until an EOF (End of File) code or bit is found which indicates the end of a data stream. If you use MS's Communications Control you can see some sample code here: http://support.microsoft.com/kb/194922
I think I had to use 4800 in my settings instead of 9600 but your requirements may be different depending what type of device you are using.
Extract The Right Data From Your Incoming GPS Data
Step two is to extract the data you need from the incoming GPS Data. You may even find that you have to change it to match the GPS Data you have stored (see below).
In my sample NMEA sentences (above), the Longitude and Latitude are both in the following format:
ddmm.mmmm
For some programs or API's you may have to convert it into Degrees.Degrees, or to word it another way, dd.dddd. The formula to convert it is:
dd.dddd = ddd + mm.mmmm/60
So, for example, if we want to convert my sample data above to exact Longitude and Latitude in degrees, here's what it would look like:
3731.9404 ----> 37 + 31.9404/60 = 37.53234 degrees
10601.6986 ----> 106 + 1.6986/60 = 106.02831 degrees
Here are some functions I wrote back in 2007 to extract certain parts of the data from the NMEA sentence:
Public Function ExtractLatitude(strNMEAString As String, Optional strNMEAStringType As String = "GPRMC") As String
'This function extracts the latitude from an NMEA string and converts it to Decimal Degrees (as a string).
'To use this function you must specify what string type you are passing in, either GPRMC or GPGGA
Dim aryNMEAString() As String
aryNMEAString() = Split(strNMEAString, ",")
Dim dblMinutes As Single, dblLatitude As Single
Select Case strNMEAStringType
Case "GPRMC"
'Latitude is the Number 3 place in the array (4th place in the string)
If aryNMEAString(2) = "A" Then 'A represents a valid string
dblMinutes = (CDbl(Mid(aryNMEAString(3), 3, 7)) / 60)
dblLatitude = CDbl(Left(aryNMEAString(3), 2)) + dblMinutes
ExtractLatitude = CStr(dblLatitude)
End If
Case "GPGGA"
'Latitude is the Number 2 place in the array (3rd place in the string)
If CDbl(aryNMEAString(2)) <> 0 Then 'If string is invalid it will be 0
dblMinutes = (CDbl(Mid(aryNMEAString(2), 3, 7)) / 60)
dblLatitude = CDbl(Left(aryNMEAString(2), 2)) + dblMinutes
ExtractLatitude = CStr(dblLatitude)
End If
End Select
End Function
Public Function ExtractLongitude(strNMEAString As String, Optional strNMEAStringType As String = "GPRMC") As String
'This function extracts the longitude from an NMEA string and converts it to Decimal Degrees (as a string).
'To use this function you must specify what string type you are passing in, either GPRMC or GPGGA
Dim aryNMEAString() As String
aryNMEAString() = Split(strNMEAString, ",")
Dim dblMinutes As Single, dblLongitude As Single
Select Case strNMEAStringType
Case "GPRMC"
'Latitude is the Number 3 place in the array (4th place in the string)
If aryNMEAString(2) = "A" Then
dblMinutes = (CDbl(Mid(aryNMEAString(5), 4, 7)) / 60)
dblLongitude = CDbl(Left(aryNMEAString(5), 3)) + dblMinutes
ExtractLongitude = CStr(dblLongitude)
End If
Case "GPGGA"
'Latitude is the Number 2 place in the array (3rd place in the string)
If CDbl(aryNMEAString(4)) <> 0 Then
dblMinutes = (CDbl(Mid(aryNMEAString(4), 4, 7)) / 60)
dblLongitude = CDbl(Left(aryNMEAString(4), 3)) + dblMinutes
ExtractLongitude = CStr(dblLongitude)
End If
End Select
End Function
Public Function ExtractSpeed(strGPRMC As String) As Integer
'Expects a GPRMC NMEA Sentence
Dim aryGPRMC() As String, dblSpeed As Double
aryGPRMC() = Split(strGPRMC, ",")
If aryGPRMC(7) <> "" Then dblSpeed = CDbl(aryGPRMC(7))
'Convert knots to MPH
ExtractSpeed = CInt(dblSpeed * 1.15077945)
End Function
Public Function ExtractHeading(strGPRMC As String) As Double
'Expects a GPRMC NMEA Sentence
Dim aryGPRMC() As String
aryGPRMC() = Split(strGPRMC, ",")
If aryGPRMC(8) <> "" Then ExtractHeading = CDbl(aryGPRMC(8))
End Function
Public Function ExtractSatelliteCount(strGPGGA As String) As Integer
'Expects a GPGGA NMEA Sentence
Dim aryGPGGA() As String
aryGPGGA() = Split(strGPGGA, ",")
ExtractSatelliteCount = CInt(aryGPGGA(7))
End Function