Jawin Instruction String Reference (in progress)

Important: Please note that the information in this document is from before the transition from com.develop.jawin to org.jawin in early 2003. Therefore this document may contain obsolete or incorrect information. Please also consult the instructions.h file.

Note: All instructions use little-endian byte ordering

List of instruction codes

codeuse
"A"[out] long* parameters
"G"passing in Unicode strings
"I"[in] long parameters
"k"skipping past input params that take 0 default in Win32 APIs
"L"skipping unused arguments, going back to pick up arg
"P"passing in structs, arrays
"r"arrays of complex types

I

copies four bytes from the input stream to the call stack

Use cases

  1. [in] long parameters

    //Sample C API
    __declspec (dllexport) bool WINAPI SendMeATen(long l) {
    return (l == 10);
    }

    //Implementing a Java stub for the C API
    static public void SendMeATen(int n) throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "SendMeATen");
    NakedByteStream nbs = new NakedByteStream();
    LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
    leos.writeInt(n);
    GenericStub.win32Invoke(fp.getPeer(),"I:T1:", 4, 4, nbs.getInternalBuffer(), null);
    }

    //Calling the Java stub
    InstructionTests.SendMeATen(10);

A

allocates a four-byte buffer and writes address onto call stack

Use cases

  1. [out] long* parameters

    //Sample C API
    __declspec (dllexport) void WINAPI FillInWithEleven(long* pl) {
    *pl = 11;
    }

    //Implementing a Java stub for the C API
    static public int FillInWithEleven() throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "FillInWithEleven");
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),"A::n4", 4, 0, null, null);
    return StructConverter.bytesIntoInt(result, 0);
    }

    //Calling the Java stub
    int eleven = InstructionTests.FillInWithEleven();
    TestAssert.isTrue(eleven == 11);

k

skips the next four bytes in the output stream

Use cases

  1. skipping past input params that take 0 default in Win32 APIs

    //Sample C API
    __declspec (dllexport) long WINAPI SkipDefaultedArg(long skip, long check) {
    return check;
    }

    //Implementing a Java stub for the C API
    static public int SkipDefaultedArg(int n) throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "SkipDefaultedArg");
    NakedByteStream nbs = new NakedByteStream();
    LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
    leos.writeInt(n);
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),"kI:I:", 8, 4, nbs.getInternalBuffer(), null);
    return StructConverter.bytesIntoInt(result, 0);
    }

    //Calling the Java stub
    int twelve = InstructionTests.SkipDefaultedArg(12);
    TestAssert.isTrue(twelve == 12);

G

converts a Java string on the input stream to a BSTR on the output stream

Use cases

  1. passing in Unicode strings

    //Sample C API
    __declspec (dllexport) long WINAPI GetStringLength(BSTR bs) {
    return wcslen(bs);
    }

    //Implementing a Java stub for the C API
    static public int GetStringLength(String s) throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "GetStringLength");
    NakedByteStream nbs = new NakedByteStream();
    LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
    leos.writeStringUnicode(s);
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),"G:I:", 4, leos.size(), nbs.getInternalBuffer(), null);
    return StructConverter.bytesIntoInt(result, 0);
    }

    //Calling the Java stub
    int five = InstructionTests.GetStringLength("hello");
    TestAssert.isTrue(five == 5);

P

creates a pointer to the current position in the input stream, write that pointer to the output stream, and then skips N octets on the input stream

Use cases

  1. passing in structs, arrays

    //Sample C API
    __declspec (dllexport) long WINAPI GetNthByte(byte* b, long n) {
    return (b[n]);
    }

    //Implementing a Java stub for the C API
    static public int GetNthByte(byte[] b, int n) throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "GetNthByte");
    NakedByteStream nbs = new NakedByteStream();
    LittleEndianOutputStream leos = new LittleEndianOutputStream(nbs);
    for (int loop=0; loop<b.length; loop++) {
    leos.writeByte(b[loop]);
    }
    leos.writeInt(n);
    String marshal = "P" + b.length + "I:I:";
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),marshal, 8, leos.size(), nbs.getInternalBuffer(), null);
    return StructConverter.bytesIntoInt(result, 0);
    }

    //Calling the Java stub
    byte[] bytes = {2,3,5,7,11};
    int three = InstructionTests.GetNthByte(bytes, 1);
    TestAssert.isTrue(three == 3);

L

skips N bytes in the input stream

Use cases

  1. skipping unused arguments, going back to pick up arg

    //Sample C API
    __declspec (dllexport) void WINAPI FillOneTwoThree(long* one, long* two, long* three) {
    *one = 1;
    *two = 2;
    *three = 3;
    }

    //Implementing a Java stub for the C API
    static public void FillOneTwoThree() throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "FillOneTwoThree");
    //extract second arg, then back up and extract first
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),"AAA::L4n4L-8n4", 12, 0, null, null);
    //verify extractions
    int two = StructConverter.bytesIntoInt(result, 0);
    int one = StructConverter.bytesIntoInt(result, 4);
    TestAssert.isTrue(two == 2);
    TestAssert.isTrue(one == 1);
    }

    //Calling the Java stub
    InstructionTests.FillOneTwoThree();

r

repeats next block N times

Use cases

  1. arrays of complex types

    //Sample C API
    __declspec (dllexport) void WINAPI OneFishTwoFish(VARIANT* fill) {
    fill[0].vt = VT_I4;
    fill[0].iVal = 1;
    fill[1].vt = VT_BSTR;
    fill[1].bstrVal = ::SysAllocString(L"fish");
    fill[2].vt = VT_I4;
    fill[2].iVal = 2;
    fill[3].vt = VT_BSTR;
    fill[3].bstrVal = ::SysAllocString(L"fish");
    }

    //Implementing a Java stub for the C API
    static public Object[] OneFishTwoFish() throws IOException, COMException {
    FuncPtr fp = new FuncPtr("bin\\CallCOMUnitTestD.DLL", "OneFishTwoFish");
    //extract second arg, then back up and extract first
    int size = Variant.SIZEOF * 4;
    String marshal = "M" + size + "::O|r4V!|";
    byte[] result = GenericStub.win32Invoke(fp.getPeer(),marshal, 4, 0, null, null);
    LittleEndianInputStream leis = new LittleEndianInputStream(new ByteArrayInputStream(result));
    Object[] ret = new Object[4];
    for (int n=0; n<4; n++) {
    ret[n] = Variant.marshalOut(leis);
    }
    return ret;
    }

    //Calling the Java stub
    Object[] oftf = InstructionTests.OneFishTwoFish();
    TestAssert.isTrue(new Integer(1).equals(oftf[0]));
    TestAssert.isTrue("fish".equals(oftf[1]));
    TestAssert.isTrue(new Integer(2).equals(oftf[2]));
    TestAssert.isTrue("fish".equals(oftf[3]));