Accessing DLL

Posted by bart.syryn on 04-Dec-2014 01:51

Hi, In our application we have a program that reads info on identity-cards. For years we created a handle like : CREATE "EIDLIBCTRL.EIDlib" chctrlframe NO-ERROR. At that point we could access the dll (like an ocx). The government released new software and the above isn't possible anymore. There's a new DLL and we can't access it like we use to access an OCX or DLL. I think it's possible in OE AppBuilder OE11.3, but I really don't know where to start. Can someone point me into the right direction or where can I find docs that can get me started. They give some examples in C, C# and Java. An example in C# is : using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using Net.Sf.Pkcs11; using Net.Sf.Pkcs11.Objects; using Net.Sf.Pkcs11.Wrapper; using System.Security.Cryptography.X509Certificates; namespace EidSamples { class ReadData { private Module m = null; private String mFileName; /// /// Default constructor. Will instantiate the beidpkcs11.dll pkcs11 module /// public ReadData() { mFileName = "beidpkcs11.dll"; } public ReadData(String moduleFileName) { mFileName = moduleFileName; }

Posted by bart.syryn on 05-Dec-2014 01:34

Hi,

Thanks for the link.  Seems like I need to do a lot of reading. But it's a good to time to start with it.

I hope it isn't to complicated ....

All Replies

Posted by Frank Meulblok on 04-Dec-2014 06:23

Given that they're now providing C# examples, looks like the new .dll is now a .NET assembly.

You'll want to add this to your assemblies.xml (if you're still using old AppBuilder, using the proasmref command-line tool).

From there on you should be able to use it via normal class-referencing syntax.

Posted by bart.syryn on 04-Dec-2014 06:31

Thanks for the answer.

I'm still using the old AppBuilder (11.3). They give examples in C, C# and java. The one I posted was indeed C#.

I have no knowledge on how to use .Net assembly in OpenEdge. You mention I need to add it to the assemblies.xml. Is that only in development or also in deployment ?

And the next question is, where can I found documentation on how to use class-referencing syntax in OpenEdge ?

Posted by olivier.dunemann on 04-Dec-2014 07:01

The assemblies.xml is required at both sides (development & deployment).

>>where can I found documentation on how to use class-referencing syntax in OpenEdge ?

You can start with the OpenEdge Product Documentation, section "OpenEdge GUI for .Net"

Posted by bart.syryn on 05-Dec-2014 01:34

Hi,

Thanks for the link.  Seems like I need to do a lot of reading. But it's a good to time to start with it.

I hope it isn't to complicated ....

Posted by Marian Edu on 05-Dec-2014 12:33

don't remember the exact details but think we got better results using the interop wrapper (http://www.pkcs11interop.net) instead of the one from sf.net (http://sf.net/p/pkcs11net/)...

using Progress.Lang.*.
using Net.Pkcs11Interop.Common.*.
using Net.Pkcs11Interop.HighLevelAPI.*.
using System.BitConverter.
using System.Collections.IEnumerator.
using System.Collections.ArrayList.

routine-level on error undo, throw.

class com.xpower.beid.ReadDataInterop:
    define private variable moduleFile      as character    no-undo.
    define private variable pkcsModule      as Pkcs11       no-undo.
   
    constructor public ReadDataInterop (  ):
        this-object('beidpkcs11.dll':u).
    end constructor.
   
    constructor public ReadDataInterop ( moduleFile as character ):
        this-object:moduleFile = moduleFile.
    end constructor.
   
    destructor public ReadDataInterop ( ):
        if valid-object(pkcsModule) then
            pkcsModule:Dispose() no-error.
       
        delete object pkcsModule no-error.
    end destructor.
   
    method public character GetSurname():
        return GetData('surname':u).
    end method.
   
    method public character GetFirstName():
        return GetData('firstnames':u).
    end method.
   
    method public character GetNameInitials():
        return GetData('first_letter_of_third_given_name':u).
    end method.
   
    method public character GetNationality():
        return GetData('nationality':u).
    end method.
   
    method public character GetCardNumber():
        return GetData('card_number':u, true).
    end method.

    method public character GetChipNumber():
        return GetData('chip_number':u).
    end method.
   
    method public character GetSerialNumber():
        return GetData('carddata_serialnumber':u).
    end method.
   
    method public character GetNationalNumber():
        return GetData('national_number':u).
    end method.
   
    method public character GetDocumentType():
        return GetData('document_type':u).
    end method.
   
    method public character GetAddressStreet():
        return GetData('address_street_and_number':u).
    end method.
   
    method public character GetAddressZip():
        return GetData('address_zip':u).
    end method.
   
    method public character GetAddressMunicipality():
        return GetData('address_municipality':u).
    end method.
   
    method public character GetPhoto():
        return GetData('photo_hash':u).
    end method.
   
    method public character GetDateOfBirth():
        return GetData('date_of_birth':u).
    end method.
   
    method public character GetPlaceOfBirth():
        return GetData('location_of_birth':u).
    end method.
   
    method public character GetValidityDateStart():
        return GetData('validity_begin_date':u).
    end method.
   
    method public character GetValidityDateEnd():
        return GetData('validity_end_date':u).
    end method.
   
    method public character GetGender():
        return GetData('gender':u).
    end method.
   
    method public character GetData(labelName as character):
        return GetData(labelName, false).
    end method.
   
    method public character GetData(labelName as character, displayBytes as logical):
        define variable retValue            as character            no-undo.
        define variable numItem             as integer              no-undo.
        define variable pkcsSession         as Session              no-undo.
        define variable classAttribute      as ObjectAttribute      no-undo.
        define variable labelAttribute      as ObjectAttribute      no-undo.
        define variable readAttribute       as ObjectAttribute      no-undo.
        define variable pkcsObject          as ObjectHandle         no-undo.
       
        define variable colEnum             as IEnumerator          no-undo.
        define variable attrEnum            as IEnumerator          no-undo.
        define variable slotList            as 'System.Collections.Generic.List<Slot>'              no-undo.
        define variable attrArray           as 'System.Collections.Generic.List<ObjectAttribute>'   no-undo.
        define variable foundObjects        as 'System.Collections.Generic.List<ObjectHandle>'      no-undo.
        define variable objAttr             as 'System.Collections.Generic.List<CKA>'               no-undo.
       
        if not valid-object(pkcsModule) then
            pkcsModule = new Pkcs11(moduleFile, true).
           
        /* Get the first slot (cardreader) with a token */
        slotList = pkcsModule:GetSlotList(true).
       
        if slotlist:Count > 0 then do:
            colEnum = slotList:GetEnumerator().
            if colEnum:MoveNext() then
                pkcsSession = cast(colEnum:Current, 'Slot'):OpenSession(true).

            delete object colEnum.
            /* Search for objects
               First, define a search template */

            /* 'The label attribute of the objects should equal ...' */
            classAttribute = new ObjectAttribute(CKA:CKA_CLASS, CKO:CKO_DATA).
            labelAttribute = new ObjectAttribute(CKA:CKA_LABEL, labelName).

            attrArray = new 'System.Collections.Generic.List<ObjectAttribute>' (2).
            attrArray:Add(classAttribute).
            attrArray:Add(labelAttribute).
           
            pkcsSession:FindObjectsInit(attrArray).
           
            delete object classAttribute.
            delete object labelAttribute.
            delete object attrArray.
               
            foundObjects = pkcsSession:FindObjects(1).
           
            message 'found objects' skip foundObjects:Count view-as alert-box.
           
            colEnum = foundObjects:GetEnumerator().
            objAttr = new 'System.Collections.Generic.List<CKA>' (2).
            objAttr:Add(CKA:CKA_LABEL).
            objAttr:Add(CKA:CKA_VALUE).
           
            do while colEnum:MoveNext():
                pkcsObject = cast(colEnum:current, 'ObjectHandle':u).
               
                if not valid-object(pkcsObject) or pkcsObject:ObjectId eq 0 then do:
                    message 'invalid object' view-as alert-box.
                    next.
                end.
               
                message 'object' skip pkcsObject:ToString() view-as alert-box.
                
                attrArray = pkcsSession:GetAttributeValue(pkcsObject, objAttr).   
               
                message 'attributes list' skip attrArray:count view-as alert-box.
               
                if attrArray:count > 0 then do:
                    attrEnum = attrArray:GetEnumerator().
                   
                    do while attrEnum:MoveNext():
                        readAttribute = cast(attrEnum:Current, 'ObjectAttribute').
                       
                        message 'attribute' skip readAttribute:GetValueAsString() view-as alert-box.
                    end.        
                   
                    delete object attrEnum no-error.
                   
                    return readAttribute:GetValueAsString().
                end.
               
                delete object pkcsObject no-error.
                delete object attrArray  no-error.
            end.
           
            delete object colEnum.
            delete object objAttr.
            delete object foundObjects.
           
            pkcsSession:FindObjectsFinal().
        end.
       
        undo, throw new AppError('Can not read card slot', -1).
       
        finally:
            if valid-object (pkcsSession) then do:
                if valid-object(pkcsObject) then
                    pkcsSession:DestroyObject(pkcsObject) no-error.
                   
                pkcsSession:CloseSession() no-error.
            end.

            if valid-object (pkcsModule) then
                pkcsModule:Dispose() no-error.
               
            delete object pkcsObject no-error.
            delete object pkcsSession   no-error.
            delete object pkcsModule    no-error.
            delete object attrArray     no-error.
            delete object attrEnum no-error.
            delete object colEnum       no-error.
            delete object objAttr       no-error.
            delete object foundObjects  no-error.
        end.   
    end method.
   
end class.


Posted by bart.syryn on 05-Dec-2014 13:19

Hi,

Marian, thanks a lot ! Seems exactly what I'm looking for !!!

Do I need to add something to the assemblies.xml ? Because when I just copy your code in the procedure editor (Old Appbuilder) I get syntax error 15214 on :

define variable slotList            as 'System.Collections.Generic.List<Slot>'              no-undo.

       define variable attrArray           as 'System.Collections.Generic.List<ObjectAttribute>'   no-undo.

       define variable foundObjects        as 'System.Collections.Generic.List<ObjectHandle>'      no-undo.

       define variable objAttr             as 'System.Collections.Generic.List<CKA>'               no-undo.

I'm completely new on using .NET,and started reading the documents as suggested. But it's seems that I have to do a lot of reading ...

How can I call this class from an ABL Window or procedure ?

King regards

Bart Syryn

Posted by Marian Edu on 05-Dec-2014 14:53

Bart,

you need to get the interop assembly from www.pkcs11interop.net, add pkcs11interop.dll in your assemblies.xml and then the er ror will hopefully go away.

The module file (beidpkcs11.dll) i think you can get it from here unless you already have that... eid.belgium.be/.../de_eid-middleware_installeren

To call the class something like this should do it...

define variable pkcsRead    as com.xpower.beid.ReadDataInterop     no-undo.

pkcsRead = new com.xpower.beid.ReadDataInterop().

message pkcsRead:GetSurname() view-as alert-box.

catch e as Progress.Lang.Error :

message e:getmessage(1) view-as alert-box.

end catch.

finally:

   delete object pkcsRead no-error.

end finally.

Posted by bart.syryn on 06-Dec-2014 02:50

Hi Marian,

Thanks for the quick response !!!

I'm new in the use of .net in OE, it's hard ...

I've searched the website www.pkcs11interop.net for the last hour and I didn't find any download for the pkcs11interop.dll

I've googled the .dll and also no results .... Do you have a link to the file itself ?

I still get errors ofcourse because I'm missing the dll (error 5638 on define private variable pkcsModule      as Pkcs11       no-undo.)

Any help or hints ? Thanks !

Posted by Marian Edu on 06-Dec-2014 05:50

Bart,

you can download source code from sf.net and compile but guess this is not that straight forward so go for the binaries:

- get NuGet command line from here: http://nuget.org/nuget.exe

- install Pkcs11interop 'package' using: nuget.exe install Pkcs11Interop

- get the dll from Pkcs11Interop folder created by install above, go for .net 4.0 or 2.0 depending on your OE version (try 4.0 first and see if it works)

Mind you that code is just something quickly and blindly crafted but not tested... so it's more to get you started.  

Posted by bart.syryn on 06-Dec-2014 08:13

Hi Marian,

Thanks !

Now I was able to download it and got the .dll.  I've added it to the assemblies.xml file in my procedure editor but I still get the error 5638 (unknown class) on define private variable pkcsModule      as Pkcs11       no-undo.  The assemblies.xml file is in my working directory.

I think it's better to read more documentation from the Progress Site to understand what the cause is of the error.

Kind regards

Bart Syryn

Posted by bart.syryn on 09-Dec-2014 05:13

Hi Marian,

I'm sorry, but I have another question. I finaly got your example working, main reason was that I'm not familier with using gui .net.

I can read out the data, but I also need the picture on the EID. In a CSharp example I see that they use GetFile('PHOTO_FILE'). So I assume that it's a memptr with the photo in it. So I added GetFile like the CSharp example, but the only thing that is returned are ????. Probably I do something wrong with GetValueAs???? like it's described in Pkcs11Interop.xml, but I don't know what to use, and I also don't know what type of variable I need to use in the class.

Do you have any experience on reading the picture ?

kind regards

Bart Syryn

Posted by Marian Edu on 09-Dec-2014 07:22

Bart,

glad you did get it to work... most probably something can be done for the picture, time is scarce now but if that turn out in consulting/billable something could be arranged :)

Regards,

Marian

Posted by bart.syryn on 09-Dec-2014 07:34

Marian,

Thanks for answering.  I agree with your proposal. Maybe it's better to contact me directly. If it's alright with you, I can add you in linkedIn and then you've got my emailadres to contact me directly.

Kind regards

Bart Syryn

This thread is closed