|
Passing byte arrays into C functions: msg#00012windows.devel.jawin
I give up - I must be stupid.. I have been trying to figure out how to run something as simple as GetComputerNameW in kernel32.dll.. and I keep getting horrible errors - Access violations, running out of memory, etc. I am going to explain my thinking step by step, you never know, it might help me figure out exactly what I'm doing wrong. Well, in the tradition of answering your own questions, this is exactly what happenned : after trying to get this right for the last many hours, and after getting a hole bunch of errors ranging from memory access violations (e.g. when I was passing the second param as a regular int (an I instruction) , and no as a pointer to an int (a P4 instruction)), running out of memory, "filename too long", I finally got it. Another error that I didn't figure out for the longest time was that I was creating a String with the length of 300, and then I wrote that string to the output stream (instead of writing an array of bytes with the length of 300, I was writing an unicode string with the length of 300 - which in bytes is probably 4 times longer) and then passing instructions that the byte array was 300 bytes long . I realize that I might be making an ass out of myself, but this could be helpful for some other newbie. Also, I might try to put together something like the mini-program below, and then provide them to the project as documentation. Ok, this is the description of the function: BOOL GetComputerName( LPTSTR lpBuffer, LPDWORD lpnSize ); Parameters lpBuffer [out] Pointer to a buffer that receives a null-terminated string containing the computer name or the cluster virtual server name. The buffer size should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters. lpnSize [in, out] On input, specifies the size of the buffer, in TCHARs. On output, the number of TCHARs copied to the destination buffer, not including the terminating null character. If the buffer is too small, the function fails and GetLastError returns ERROR_BUFFER_OVERFLOW. The lpnSize parameter specifies the size of the buffer required, not including the terminating null character. So, in order to get things right, this is what I do (in Jython again, but it should be easy to folow): from org.jawin import * from org.jawin.io import * from org.jawin.marshal import * from com.divintech.testing import * from java.io import * getCompName = FuncPtr("kernel32.dll","GetComputerNameW") nbs = NakedByteStream(); leos = LittleEndianOutputStream(nbs); # This creates a buffer, 300 bytes long writing 1 in each byte for i in range(300): leos.writeByte(1) #write out the length of the buffer leos.writeInt(300) # It doesn't seem like I can fit this method call into any of the "shortcut" invokes, so I go with the long one # this instruction doesn't work - I guess because the parameter of GetComputerName is an int pointer, and not an int # this part of the instructions, for me it means that I am passing a byte array with a length of 300 and a 4 byte out param - it would have been ok if the 2nd param of the function was taking an int, and not a # pointer to int # instructions = "P300A" #therefore, the correct instruction is, because the P4 basically says - take the address this, and put the address to the native method - essentially passing a pointer to the native method. instructions = "P300P4" # the return method is an int so then: instructions = instructions + ":I:" # at the end, we have 2 out parameter - the first is the buffer of length 300 and then an int of length 4 instructions = instructions + "n300n4" # then, the function call is # the first argument is the instruction string that I composed. # the second argument is the stack size - 304 - since we passed the whole buffer on the stack ??? - is this correct ? # the remaining arguments really don't need an explanation res = getCompName.invoke(instructions, 304, nbs, None, ReturnFlags.CHECK_FALSE) # now, construct the inputstream over the result leis = LittleEndianInputStream(ByteArrayInputStream(res)) # read the return value - at this point I'm not using it, it gets checked by the ReturnFlags param b1 = leis.readInt() # then, read the string , using the suggested length , which gives us the correct value ## Da-Da-a-a, this is the actual result, which is correct without any errors. leis.readUnicodeSz(300) # Finally , read in how many characters were put into the buffer r2 = leis.readInt() Regards, Alex Kotchnev Developer / Systems Analyst Diversified Information Technologies ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ CONFIDENTIALITY NOTICE: If you have received this e-mail in error, please immediately notify the sender by e-mail at the address shown. This e-mail transmission may contain confidential information. This information is intended only for the use of the individual(s) or entity to whom it is intended even if addressed incorrectly. Please delete it from your files if you are not the intended recipient. Thank you for your compliance. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Win32 functions, structs, constants stubs: 00012, Alex Kotchnev |
|---|---|
| Next by Date: | Re: Passing byte arrays into C functions: 00012, Roger I Martin PhD |
| Previous by Thread: | Win32 functions, structs, constants stubsi: 00012, Alex Kotchnev |
| Next by Thread: | Re: Passing byte arrays into C functions: 00012, Roger I Martin PhD |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |