Quantcast
Channel: SCN : All Content - PowerBuilder Developer Center
Viewing all 2935 articles
Browse latest View live

TimeZoneAdjustment

$
0
0

Hello there

 

To calculate the time-offset to the UTC-time I found an useful function SELECT CONNECTION_PROPERTY ('TimeZoneAdjustment')

described in attached file timezone.txt.

According to the documentation it will not work in UltraLite-databases. My db Sybase ASA with  SqlAnywhere 11.0 driver.

Guess it's classified as an UltraLite but not sure?

Anyway, this function works fine and returns the expected value both in a stand-alone- procedure-

call (invoked select connection....) and in an app. Nice, but it won't work in an Appeon-Deploy and Run. Returns null.

In Appeon Configuration-Settings my db is described as 'Sybase ASA ! Ultralite'.

Not sure if this is an Appeon- or Sybase-issue or both?

Since the db-driver is SqlAnywhere 11.0 the other option described in attached doc

datatype timestamp with timezone won't work either. Only with Sybase Adaptive Server 12.0.

 

Is there an other method, function to get the time-offset calculated in SqlAnywhere 11.0?

 

Best Regards

 

Outi Vihko


Anyone know how to use Exchange Web Service API in PB Classic 12.5

$
0
0

Trying to figure out how to use the api/dll's of the EWS.  I am new to web services in pb so I seem to be going nowhere fast.  If you have used it I would appreciate some guidance or better yet code/instruction on how to use/access it/setup.  I need to be able to get to exchange (in this case using an office365 test account) and read emails/calendar info etc..

 

Thanks for any help..

Dave V.

PowerBuilder Soap 12.5 Project

$
0
0

I’m using: Windows 7 PowerBuilder 12.5 Build 2511 Microsoft .NET Framework 4 Microsoft Windows SDK for Windows 7 (7.1) I am tasked with my first Web Services project.  Connecting to a Vendor via a WSDL file and then pulling down large packets of data and then eventually, sending data back to them. I started with PowerBuilder 12.5 Classic.  I could successfully build the Project and Proxy by: New, Project, Web Service Proxy Wizard, Use .Net Engine etc. The vendor provided WSDL file was read and the PB objects were created.  The vendor provided a WSDL file and two separate .XSD files, stating as long as all three are in the same directory, they should be read just fine… I then learned that PB 12.5 Classic does not support Mtom and ws-security that are required by my vendor. So I am now trying this in PB12.5 .Net. New, WCF Client Proxy, enter the project name, enter the same exact WSDL file name that I used in PB Classic, enter in the Namespace:, Proxy assembly name:, Proxy library: When I click Next, I get the following Errors: Error: Cannot import wsdl:portType Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporte... Error: Schema with target namespace "http://methods.webservices..." could not be found. I’ve tried many things to resolve this.  Why does this WSDL file and .xsd files seem to work ok with PB 12.5 Classic, SoapUI, and Visual Studio .Net but not PB12.5 .NET?  Anyone have any thoughts? I’m very frustrated. Thanks

PB slow down on windows 7 and above?

$
0
0

So i have a PB classic application that is on 12.5 running on windows 7.  What looks like is happening is we have seen a general across the board slow down in all processes vs when it was running on XP.

 

 

It looks like the application is doing a lot of I/O to a few different registry settings:

located in

HKCU\control panel\international\

 

I don't have any place in the code that is doing this. So i am guessing that PB is doing it?

 

It looks like for some reason the I/O is getting interrupted every few seconds in windows 7 vs what it was doing in XP we think that is creating a slow down.

 

Does anyone know why this registry setting is being read? Or how to stop it?

 

Maybe if anyone knows why windows 7 and windows XP run the same PB process with the same data at two different speeds?

To save a graphic file with the Clipboard

$
0
0

Hello guys.

 

I want to work with the Web Cam to capture and save the image show it, I used capCreateCaptureWindowA function to work with the Web Cam, only when I want to use WM_CAP_FILE_SET_CAPTURE_FILEA it's dosen't work, so, I used WM_CAP_EDIT_COPY to copy the image to the clipboard, but I don't know how to save the clipboard to bmp or gif File.

 

Any ideas?

 

 

Thanks!

MDIFrame\Sheet behavior question

$
0
0

I'm using PB 11.5 and I've modernized the classic PB menus to appear more web-like in our applications.  Instead of embedding the menu on the frame's menuname property. I have a user object on the Frame's workspace along with the MDIClient that calls each of the menu objects like popup menus.

 

We've had good response from this approach, however a user questioned the behavior of the sheets when clicking on the menuitems generated by the "mergeoption = windowmenu!" setting.  These are provided by PB via the Menu Merge Options ( SyBooks Online )

 

When the menu is set on the frame via menuname and the user clicks on one of these menuitems to enlarge a minimize sheet, the sheet returns to it's previous pre-minimzed state.

 

When a popup menu is used and the user clicks on one of these menuitems to enlarge a minimize sheet, the sheet remains in it's minimized state.

 

In both cases if the windows are in any other state these menuitems work the same, the behavior only seems to differentiate when the sheets are minimized.

 

I've considered writing a workaround, however, each of the windows functions will not restore a sheet that is in a minimized state.  Closing and re-opening seems like the only possibility and we are not considering this option.

 

Questions:

1. Any known reason for this behavior?

2. Any other options to consider as workarounds?

 

Any input would be useful.

 

- Mike

Default value doesn't work in data window.

$
0
0

We recently added a new column to a long established table. It's a one character yes/no column. The DBA tells me that this is an attribute "Named default "Set_to_N" is bound to Telephone.Preferred_Num.  The problem is that when I add a new row in that datawindow in my application, I get a message "Required value missing for preferred_Num on row 3.  Please enter a value."   If I check the box and then uncheck it, I'm able to save the row.  So it seems like the "Set_to_N" is not taking effect.  Is there a default value property I can get at in the datawindow painter?  My current idea is that I have to do something in the catalog tables, but I can't figure out how to get to them.  It's been many years, over a decade, since I've done that.  Googling hasn't helped me.  I'm running 12.5.  How do I get to them?

 

Other info

When a new row is added in the datawindow I get no error, but neither is the row actually saved to the database.

I can add a new row to that table via a SQL statement without setting the value of the preferred_num column.  It is automatically set to 'N'.

 

TIA

LAS

Error "unable to initialize database metadata class" occurs on connecting to sybase db from powerbuilder 12.5 using jtds 1.3.1 jdbc driver

$
0
0

Error "unable to initialize database metadata class" occurs on connecting to sybase db from powerbuilder 12.5 using jtds 1.3.1 jdbc driver.

 

I have entered classpath for jtds 1.3.1 .jar(placed on same path as pbjdbc125.dll) in CLASSPATH in java tab in system option of PB and in environment variable of system.

 

Is there any setting i am missing?Please help.


Communication with a smart card from PowerBuilder

$
0
0

We're going to look at using the Smart Card SDK provided in more recent versions of Windows (XP and later).  Earlier versions of Windows had an ActiveX installed called CAPICOM which could be accessed from PowerBuilder through OLE Automation, but that control was removed as of Windows Vista because of security issues.

 

We're going to look at a number of operations:

 

 

Communicating with the card

 

The first step is establish a context for the API calls.  To do that, we need to declare the following local external function for SCardEstablishContext:

 

Function ulong SCardEstablishContext  ( &  Long dwScope, &  long pvReserved1, &  long pvReserved2, &  REF ulong phContext &  ) Library "winscard.dll"

And call it as follows:

 

ulong    rc
rc = scardestablishcontext( SCARD_SCOPE_USER, 0, 0, context )
IF rc = SCARD_S_SUCCESS THEN    Return SUCCESS
ELSE    Return FAILURE
END IF

Where the following are defined as constants.

 

CONSTANT LONG SCARD_S_SUCCESS            = 0
CONSTANT LONG SCARD_SCOPE_USER          = 0

Context (the last argument) should be defined as an instance variable because we will need to release it when we are done making API calls.  We will also be passing a reference to it in many of the API calls.

 

ulong        context

The second step is get a reference to the smart card reader(s) that the user's machine is equipped with.  We do that by declaring the following local external function for the SCardListReaders method in the SDK:

 

Function ulong SCardListReaders  ( &  ulong hContext, &  Long mszGroups, &  REF Blob mszReaders, &  REF Long pcchReaders &  ) Library "winscard.dll" Alias For "SCardListReadersW"

The API defines the second argument as a string.  However, we want to pass a null, and the way we do that with PowerBuilder is by declaring the argument as a long and then passing a zero.  That causes the method to return all readers, rather than just a subset.

 

Once we've declared that we can use the following PowerScript to get an array that contains the name of all smart card readers on the system.  The SDK returns the list as a null terminated array, so we parse the blob we get back and use the String function to pull the names out and put them in an array that PowerBuilder is more comfortable with.

 

ulong                    rc
long                    ll_bufflen = 32000
long                    ll_readerlen
string                    ls_reader = Space ( ll_bufflen )
blob                    buffer
buffer = Blob ( ls_reader )  // Preallocate space in the buffer or the call will fail
rc = SCardListReaders ( context, 0, buffer, ll_bufflen )
IF ll_bufflen > 0 THEN    // BlobMid is messed up.  Len reports Unicode chars, BlobMid acts like ANSI chars    // so we have to double the values we pass to it to get full Unicode characters    //Truncate the buffer to what was actually returned    buffer = BlobMid ( buffer, 1, ( ll_bufflen - 1 ) * 2 )    //Read off the first value (string stops at the null terminator)    ls_reader = String ( buffer )    //Add it to the array    readers[1] = ls_reader    //See if we have any data left    ll_readerlen = ( Len ( ls_reader ) * 2 ) + 3    buffer = BlobMid ( buffer, ll_readerlen )    ll_bufflen = Len ( buffer )    //Loop through for the remaining data    DO WHILE ll_bufflen > 0        ls_reader = String ( buffer )        readers[UpperBound(readers)+1] = ls_reader        ll_readerlen = ( Len ( ls_reader ) * 2 ) + 3        buffer = BlobMid ( buffer, ll_readerlen )        ll_bufflen = Len ( buffer )    LOOP
END IF

If there are no readers, there isn't much further to go.  If there is only one, then you can proceed immediately to check if there is a smart card in it.  If there is more than one reader, you may need to check them all to see which have cards in them, and if more than one do then prompt the user to select the card they want to work with.

 

There is a function in the SDK that can do some of this work for you (SCardUIDlgSelectCard).  It determines what cards are available and prompts the user to select the one they want to work with.  It does require working with an OPENCARDNAME_EX structure though, which is a bit tricky from PowerBuilder.  For a number of reasons, we found that method didn't serve our needs.  As a result, this sample does all of the work without using that method.

 

The third step is to attempt to open a connection to any card(s) in the card reader(s) we've found.  We do that by first declaring the following local external function for the SCardConnect method in the SDK.

 

Function ulong SCardConnect  ( &    Long hContext, &    String szReader, &    Long dwShareMode, &    Long dwPreferredProtocols, &    REF ulong phCard, &    REF ulong pdwActiveProtocol &    ) Library "winscard.dll" Alias For "SCardConnectW"

And then call it in PowerScript as follows:

 

ulong    rc
rc = SCardConnect ( context, &                             reader, &                             SCARD_SHARE_SHARED, &                             SCARD_PROTOCOL_Tx, &                             card, &                             protocol )

Where "reader" is the name of the smart card reader we obtained from the previous step.  The next two arguments are defined constants as follow (along with some other values you might use instead):

 

CONSTANT LONG SCARD_SHARE_EXCLUSIVE    = 1
CONSTANT LONG SCARD_SHARE_SHARED        = 2
CONSTANT LONG SCARD_SHARE_DIRECT        = 3
CONSTANT LONG SCARD_PROTOCOL_T0         = 1
CONSTANT LONG SCARD_PROTOCOL_T1         = 2
CONSTANT LONG SCARD_PROTOCOL_Tx         = 3

Once again, you'll want to save "card" and "protocol" off as instance variables, because you'll need to use them later.

 

protected ulong        card
protected ulong        protocol

The fourth step (assuming we found a card) is to get the card status to ensure that it's ready for us to communicate with it.  We do that using the SCardStatus API function:

 

Function ulong SCardStatus  ( &    ulong hCard, &    REF String szReaderName, &    REF Long pcchReaderLen, &    REF Long pdwState, &    REF Long pdwProtocol, &    REF byte pbAtr[], &    REF Long pcbAtrLen &    ) Library "winscard.dll" Alias For "SCardStatusW"

Which we then call via the following PowerScript:

 

integer    i
ulong    rc
long    pcchReaderLen = 32000
string    szReaderName = Space ( pcchReaderLen )
long    pdwState
long    pdwProtocol
byte     pbAtr[]
long    pcbAtrLen = 32
FOR i = 1 TO pcbAtrLen    pbAtr[i] = Byte ( Space(1) ) // Prepad the buffer
NEXT
rc = SCardStatus( card, &    szReaderName, &    pcchReaderLen, &    pdwState, &    pdwProtocol, &    pbAtr, &    pcbAtrLen )
IF rc = SCARD_S_SUCCESS THEN    CHOOSE CASE pdwState        CASE SCARD_UNKNOWN            status = 'Unknown'        CASE SCARD_ABSENT            status= 'Absent'        CASE SCARD_PRESENT            status= 'Present'        CASE SCARD_SWALLOWED            status= 'Swallowed'        CASE SCARD_POWERED            status= 'Powered'        CASE SCARD_NEGOTIABLE            status= 'Negotiable'        CASE SCARD_SPECIFIC            status= 'Specific'        CASE ELSE            status= 'Not Known'    END CHOOSE    atrbytes = pbAtr    atr = ""    FOR i = 1 TO pcbAtrLen        atr += of_bytetohex ( pbAtr[i] )    NEXT
END IF

Once again, you may want to save off the "status" and the "atr" (Answer to Reset) value.  For ease in using them from PowerBuilder, I've converted them to strings (the ATR being a hex encoded string).

 

The constants for the various possible state values are:

 

CONSTANT LONG SCARD_UNKNOWN               = 0
CONSTANT LONG SCARD_ABSENT                = 1
CONSTANT LONG SCARD_PRESENT               = 2
CONSTANT LONG SCARD_SWALLOWED             = 3
CONSTANT LONG SCARD_POWERED               = 4
CONSTANT LONG SCARD_NEGOTIABLE            = 5
CONSTANT LONG SCARD_SPECIFIC              = 6

And the of_bytetohex function was borrowed from PFC.

 

string    ls_hex=''
char    lch_hex[0 to 15] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', &                            'A', 'B', 'C', 'D', 'E', 'F'}
Do    ls_hex = lch_hex[mod (abyte, 16)] + ls_hex    abyte /= 16
Loop Until abyte = 0
IF Len ( ls_hex ) = 1 THEN    ls_hex = '0' + ls_hex
END IF
Return ls_hex

Now that we're connected to the card, the fifth step is to connect to the specific applet on the smart card we want to work with.  For this, you'll need to have information from the card manufacturer as to the applet IDs you need to communicate with and the specific APDU command syntax they require.  If you are working with US DoD Common Access Cards, a great deal of that information can be obtained from Common Access Card (CAC): Home, particularly Common Access Card (CAC) Security.  The "Test Materials" section contains links for instructions on obtaining test cards and the form to do so.  Also of particular interest on that page are DoD Implementation Guide for CAC Next Generation (NG) and Technical Bulletin: CAC Data Model Change in 144K Dual Interface

Cards

 

We'll need to declare the SCardTransmit API call to send commands to the applet:

 

Function ulong SCardTransmit( &      ulong hCard, &      Long pioSendPci, &     byte pbSendBuffer[], &      Long cbSendLength, &      Long pioRecvPci, &      REF byte pbRecvBuffer[], &      REF long pcbRecvLength &    ) Library "winscard.dll"

The API documentation indicates that the second argument is a SCARD_IO_REQUEST structure, but we're going to use a pointer to that structure that we obtain from the SDK.  The API documentation indicates that the fifth argument is a similar structure, but we're going to declare it as a long and pass 0 to indicate that we're passing null for that value.

 

We create a wrapper function because we're going to be sending a number of commands to the card.  The function takes a byte array as an argument and returns a string with status info.

 

integer    i
ulong        rc
byte        sendBuffer[]
long        pioSendPci
byte         pbRecvBuffer[]
long         pcbRecvLength
long        cbSendLength
byte        getdata[5]
string        respSW1
string        respSW2
cbSendLength = UpperBound ( apdu )
FOR i = 1 TO cbSendLength    sendBuffer[i] = of_hextobyte ( apdu[i] )
NEXT
pcbRecvLength = 2
FOR i = 1 TO pcbRecvLength    pbRecvBuffer[i] = 0 ;
NEXT
pioSendPci = of_getpci()
rc = SCardTransmit ( card, &      pioSendPci, &    sendBuffer, &      cbSendLength, &      0, &      pbRecvBuffer, &     pcbRecvLength )
IF rc <> scard_s_success THEN return ""
respSW1 = of_bytetohex ( pbRecvBuffer[1] )
respSW2 = of_bytetohex ( pbRecvBuffer[2] )
//This means there is more data to come
IF respSW1 = "61" THEN    getdata[1] = of_hextobyte ( "00" )    getdata[2] = of_hextobyte ( "C0" )    getdata[3] = of_hextobyte ( "00" )    getdata[4] = of_hextobyte ( "00" )    getdata[5] = pbRecvBuffer[2]    cbSendLength = 5    pcbRecvLength = pbRecvBuffer[2] + 2 // We need two extra bytes for the status bits    FOR i = 1 TO pcbRecvLength        pbRecvBuffer[i] = 0 ;    NEXT    rc = SCardTransmit ( card, &        pioSendPci, &        getdata, &        cbSendLength, &        0, &        pbRecvBuffer, &        pcbRecvLength )    IF rc <> SCARD_S_SUCCESS THEN Return ""    respSW1 = of_bytetohex ( pbRecvBuffer[pcbRecvLength - 1] )    respSW2 = of_bytetohex ( pbRecvBuffer[pcbRecvLength] )
END IF
Return respSW1 + respSW2

The script uses another method borrowed from PFC (of_hextobyte)  to convert a hex value to a byte:

 

char        lch_char[]
integer    li_byte
int li_dec[48 to 70], li_i, li_len
//Get the decimal code for hexadecimal value of '0' to 'F'
// Whose ASC Value are from 48 to 57 and 65 to 70
For li_i = 48 To 57    li_dec[li_i] = li_i - 48
Next
For li_i = 65 To 70    li_dec[li_i] = li_i - 55
Next
as_hex = upper(as_hex)
lch_char = as_hex
li_len = len (as_hex)
//Convert Hexadecimal data into decimal
For li_i = 1 to li_len    //Make sure only 0's through f's are present    Choose Case lch_char[li_i]        Case '0' to '9', 'A' to 'F'            li_byte = li_byte * 16 + li_dec[asc(lch_char[li_i])]        Case Else            Return li_byte    End Choose
Next
Return li_byte

The of_getpci method is the one that gets a pointer to a LPCSARD_IO_REQUEST structure from the winscard DLL:

 

ulong dllhandle
ulong pci
dllhandle = LoadLibrary ( "WinSCard.dll" )
pci = GetProcAddress ( dllhandle, "g_rgSCardT0Pci" )
FreeLibrary(dllhandle)
return pci

That method in turn relies on external function declarations for three Windows API functions:

 

Function ulong LoadLibrary ( &    string fileName&    ) Library "kernel32.dll" Alias For "LoadLibraryW"
SubRoutine FreeLibrary ( &    ulong dllhandle &    ) Library "kernel32.dll"
Function ulong GetProcAddress ( &    ulong dllhandle, &    string procName &    ) Library "kernel32.dll" Alias For "GetProcAddress;Ansi"

The return value from the SCardTransmit is "9000" if it works.  If the first two characters are "61", it means that the call returns more data than could be returned in the original request.  If that is the case, a second call is made to the function to retrieve the rest of the data.

 

Ok, now we're ready to select the applet.  This is the card specific process, so the following example will only work for US DoD CAC cards.  You will need to consult information from the manufacturer of the card for specific details on how to deal with it.

 

There are two versions of the US DoD CAC card, one in which you need to access an applet ID of 790101 (the first version).  If that fails, we attempt to connect to a container applet ID of 790100 and, if that works, an applet within it through it's object ID of 0101.

 

string    apdu[]
string    respSW
string    emptyarray[]
apdu[1] = "00"
apdu[2] = "A4" // Select
apdu[3] = "04" // By id
apdu[4] = "00" // first record
apdu[5] = "07" // Lenth of data
apdu[6] = "A0" // Applet ID to bit 11
apdu[7] = "00"
apdu[8] = "00"
apdu[9] = "00"
apdu[10] = "79"
apdu[11] = "01"
apdu[12] = "01"
respSW = of_sendapdu ( apdu )
// If we got OK, then it's an old card and we're already good
IF respSW =  SWRESPOK THEN  version = '1'
ELSE    //Otherwise, try using the new card method    //Select the master applet    apdu[12] = "00"    respSW = of_sendapdu ( apdu )    IF respSW <> SWRESPOK THEN        //We don't know what it is        Return FAILURE    END IF    //Reset the array    apdu = emptyarray    apdu[1] = "00" // CLA    apdu[2] = "A4" // INS - select object    apdu[3] = "02" // P1    apdu[4] = "00" // P2 -    apdu[5] = "02" // Lc - length of data    apdu[6] = "01" // file id    apdu[7] = "01"    respSW = of_sendapdu ( apdu )    IF respSW = SWRESPOK THEN        version = '2'    ELSE        //We couldn't select the applet        version = 'Unknown'        Return FAILURE    END IF
END IF
Return SUCCESS

Before we go into specific operations, let's see what we need to do to clean up after ourselves when we're done.  So, for our sixth step we need to disconnect from the card.  To do that, we declare a local external function for the SCardDisconnect method in the SDK:

 

Function ulong SCardDisconnect ( &    ulong hCard, &    long dwDisposition &    ) Library "winscard.dll"

And call it with the following PowerScript:

 

ulong    rc
rc = scarddisconnect( card, SCARD_LEAVE_CARD )
SetNull ( card )
IF rc = SCARD_S_SUCCESS THEN    Return SUCCESS
ELSE    Return FAILURE
END IF

Where SCARD_LEAVE_CARD (and other values you might need to use) are defined as:

 

CONSTANT LONG SCARD_LEAVE_CARD            = 0
CONSTANT LONG SCARD_RESET_CARD            = 1
CONSTANT LONG SCARD_UNPOWER_CARD      = 2

Finally, in our seventh step, we need to release the context that we established in the first step.  We need the SCardReleaseContext SDK method for that:

 

Function ulong SCardReleaseContext( &    ulong hContext &    ) Library "winscard.dll"

And then use the following PowerScript to call it:

 

ulong rc
rc = scardreleasecontext( context )
IF rc = SCARD_S_SUCCESS THEN    Return SUCCESS
ELSE    Return FAILURE
END IF

Validating the user's PIN

 

Now that we know how to connect to the card, we'll look at some specific operations that we might want to perform using it.  One is to have the user validate their PIN so we know that the user is actually the holder of the card.  To do that, we need to send a specific APDU command to the card while we're connected to it.  For US DoD CAC cards, the value is 00 20 00 followed by the length of the PIN buffer ( "08" ) and then the hex encoded PIN right padded to the length of the PIN buffer with FF values.

 

In the following sample, w_pin is a window that is presented to the user into which they enter their PIN.  The return code from the APDU call, if the PIN is invalid, indicates the number of additional attempts the user is allowed to make before the card is automatically locked and the user will need to go to a RAPIDS site to have the card unlocked.

 

int        i
int        chances
int        pinlen
string apdu[]
string    ls_pin
string    respSW
Open ( w_pin )
ls_pin = message.StringParm
// User hit cancel
IF ls_pin = "" THEN Return NO_ACTION
pinlen = Len ( ls_pin )
apdu[1] = "00" // CLA
apdu[2] = "20"  // Verify PIN
apdu[3] = "00" // Not used
apdu[4] = "00" // Not used
apdu[5] = "08" // Indicate length of data, fixed at 8
// Add the PIN to the APDU
FOR i = 1 TO pinlen    apdu[5 + i] = of_bytetohex ( Asc ( Mid ( ls_pin, i, 1 ) ) )
NEXT
// Pad out the rest of the APDU with 0xFF
FOR i = pinlen + 6 TO 13    apdu[i] = "FF"
NEXT
respSW = of_sendapdu ( apdu )
CHOOSE CASE respSW    CASE SWRESPOK        // PIN Verified        Return SUCCESS    CASE PINLOCKED        Return PIN_LOCKED    CASE CACLOCKED        Return CAC_LOCKED    CASE INVALIDDATA        Return INVALID_DATA    CASE PINUNDEFINED        Return PIN_UNDEFINED    CASE ELSE        IF Left ( respSW, 2 ) = PININVALID THEN            chances = Integer ( Right ( respSW, 1 ) )            Return -chances        End If
END CHOOSE

The possible status codes returned from the APDU call are defined as:

 

CONSTANT STRING PININVALID         = "63"
CONSTANT STRING PINLOCKED        = "63C0"
CONSTANT STRING CACLOCKED       = "6983"
CONSTANT STRING INVALIDDATA      = "6984"
CONSTANT STRING PINUNDEFINED   = "6A88"

Reading the certificate Subject Name

 

The other thing we may want to do, once we've verified that the user knows the CAC PIN, is determine who the CAC card says the user is.  To do that, we're going to read the certificate off the card and then determine what the CN value of the Subject Name is. The US DoD stores the user's name and EDI/PI number in the CN value in the following format:  CN=LastName.FirstName.MiddleName.EDI/PI

 

The first step to access the certificate is to establish a cryptography context using the Windows API CryptAcquireContext method:

 

Function ulong CryptAcquireContext ( &    REF ulong hProv, &    ulong pszContainer, &    string pProviderName, &    long dwProvType, &    long dwFlags &    ) Library "advapi32.dll" Alias For "CryptAcquireContextW"

And call it using this PowerScript:

 

ulong    rc
rc = CryptAcquireContext ( &    prov, &    0, &    providername, &    PROV_RSA_FULL, &    0 )

"prov" is a pointer to the cryptography context that is passed by reference returned to us as a result of the call, defined as:

 

ulong        prov

We declared pszContainer as a ulong rather than a string (as in the SDK) because we're passing 0 indicating a null value.  "providername" is also passed by reference as is defined as follows.  However, we don't use the value.

 

string        providername

And PROV_RSA_FULL is defined as:

 

CONSTANT LONG PROV_RSA_FULL                = 1

The second step, once we have the context, we need to call CryptGetUserKey in the Windows API to get a handle to the certificate:

 

Protected Function ulong CryptGetUserKey ( &    ulong hProv, &    long dwKeySpec, &      REF ulong phUserKey &    ) Library "advapi32.dll"

And call it as follows:

 

ulong        rc
rc = CryptGetUserKey ( &  prov, &  AT_KEYEXCHANGE, &  userkey )

Where AT_KEYEXCHANGE is defined as:

 

LONG AT_KEYEXCHANGE   = 1

And "userkey" is passed by referenced and returned to us by the method, defined as:

 

ulong        userkey

The third step is to call CryptGetKeyParam in the Windows API, declared as follows, to get the actual certificate:

 

Function ulong CryptGetKeyParam ( &    ulong hKey, &    long dwParam, &    REF byte pbData[], &    REF long pdwDataLen, &    long dwFlags &    ) Library "advapi32.dll"

And call it as follows:

 

integer    i
ulong        rc
long        certlen
byte        temp[]
//Call it with 0 first to get the size
certlen = 0
rc =  CryptGetKeyParam ( &        userkey, &        KP_CERTIFICATE, &        temp, &        certlen, &        0 )
//Now setup the buffer and call again for that size
FOR i = 1 TO certlen    temp[i] = 0
NEXT
rc =  CryptGetKeyParam ( &        userkey, &        KP_CERTIFICATE, &        temp, &        certlen, &        0 )
certbytes = temp

Where KP_CERTIFICATE is defined as:

 

CONSTANT LONG KP_CERTIFICATE                    = 26

As indicated in the code comments, we call the function once with certlen set to 0 and the function returns the size of the certificate to use.  We then call it a second time with a byte buffer populated to that size to get the certificate data.

 

The fourth step once we have the certificate data is to convert it to a certificate.  To do that, we first have to establish a certificate context using CertCreateCertificateContext in the Windows API:

 

Protected Function ulong CertCreateCertificateContext ( &    long dwCertEncodingType, &    byte pbCertEncoded[], &    long cbCertEncoded &    ) Library "crypt32.dll"

And call it as follows:

 

long    certlen
long    encoding = X509_ASN_ENCODING + PKCS_7_ASN_ENCODING
certlen = UpperBound ( certbytes )
certContextPointer = CertCreateCertificateContext ( &    encoding, &    certbytes, &    certlen )

Where X509_ASN_ENCODING and PKCS_7_ASN_ENCODING are defined as:

 

CONSTANT LONG PKCS_7_ASN_ENCODING       = 65536 // 0x00010000
CONSTANT LONG X509_ASN_ENCODING            = 1

And certContextPointer is defined as:

 

ulong    certcontextpointer

The fifth step is to get the Subject Name off the certificate using the CertGetNameString method in the Windows API:

 

Function ulong CertGetNameString ( &    ulong pCertContext, &    long dwType, &    long dwFlags, &    long pvTypePara, &    REF string pszNameString, &    REF long cchNameString &    ) Library "crypt32.dll" Alias For "CertGetNameStringW"

And call it as follows:

 

ulong        rc
long        subjectlen
string        ls_subject
subjectlen = 256
ls_subject = Space ( subjectlen )
rc = CertGetNameString ( &    certContextPointer, &    CERT_NAME_SIMPLE_DISPLAY_TYPE, &    0, &    0, &    ls_subject, &    subjectlen )

Where CERT_NAME_SIMPLE_DISPLAY_TYPE is defined as:

 

CONSTANT LONG CERT_NAME_SIMPLE_DISPLAY_TYPE = 4

Now that we have the subject name, we need to release the certificate context.  We do that with the CertFreeCertificateContext Windows API function.

 

Function ulong CertFreeCertificateContext (&    ulong pCertContext &    ) Library "crypt32.dll"

Which we call as follows:

 

ulong    rc
rc = CertFreeCertificateContext ( certcontextpointer )

After which we need to release the cryptography context as well using the CryptReleaseContext Windows API function:

 

Function ulong CryptReleaseContext ( &    ulong hProv, &    long dwFlags &    ) Library "advapi32.dll"

And call as follows:

 

ulong rc
rc = CryptReleaseContext ( &    prov, &    0 )

Reading other Certificate Data

 

Once we have a pointer to a CERT_CONTEXT structure, one member of which is a CERT_INFO structure, we can actually access the certificate.


[To be finished tater]



What's up with PBWidth/PBHeight vs Width/Height attributes in PB .net 12.5.2?

$
0
0

I've verified that the .height/.width attributes in PB Classic 12.5.2 are mapped to PB .net 12.5.2 .PBHeight//PBWidth attributes. In PB .net 12.5.2 it appears there is also width/height attributes, but these appear to have values appx 20% of the respective PBWidth/PBHeight attributes.

 

At any rate I have an application that does a lot of dynamic resizing/moving of objects based on the "width" of various objects. To carry over the object positioning/sizing from PB Classic to PB .net, I need to replace coded references to the .width/.height attributes with PB .net friendly references to .PBWidth/.PBHeight. However I'm getting compiler errors when I do this, strangely enough these seem to be case sensitive, for instance a reference to .PBHeight attribute gives an error 'Cannot find the element "PBHeight"', whereas a reference to .pbheight yields the error 'Incompatible property pbheight for type XXXXXXXXXX'. I'm also getting 'Undefined variable: pbheight' when referencing the pbheight attribute of a window or user object. These errors all apply to pbwidth also.

 

I imagine I'm just missing something simple at this point, but it's been a ride just getting here, hoping that someone here has seen this issue, and can share a solution.

 

Thanks in advance,

 

Todd Oesterreich

Global external functions using power builder 12.5.2

$
0
0

Hi,

I am brand new at this. We have migrated an application from power builder 6.5 to power builder 12.5.2

 

Everything went well until the point where we encountered a global external function reference issue

 

This function is referenced through a DLL file, has the way the referencing of external functions changed?

 

this is the current definition of the function:

 

Public  FUNCTION Integer LABELS ( ref string userid, ref string pswd, ref string prefix, ref string pkgno, ref string jd) LIBRARY  "C:\pathtofile\labels2.dll" ALIAS FOR "LABELS;ansi"

 

However when the code gets to calling this particular function, it says it cannot find the reference.

 

What can be the cause of this? Is the global definition not correct?

 

I would appreciate any help you guys can provide. we have been on this for over a week!

 

-Luis

Appeon Text Alignment

$
0
0

need help,

 

text alignment only works for : left, center and right

justify alignment resulting the same as left alignment

have done trying to change it at runtime, still now working

 

just a simple feature that made a happy client wont smile

did anyone ever check on it?

 

- PB12

- Appeon 6.5.1 for Windows

 

is it appeon bugs?

 

thanks&regards

any help are very appreciated

menu

$
0
0

Hello all ,

 

Does anyone have an interesting idea of main menu ( not the PB menu object ) , something based on a datawindow .

( my menu must go under filter of the current user running the application , so all the parameters are saved in the database , therefore a datawindow menu is perfect for the job )

 

Thanks

 

<Moshe

Sizing problem with visual user object.

$
0
0

I have a user object which appears on several windows.  Sometimes directly on the window and sometimes on a tab control (also a user object).  It looks fine in all the windows but one.  There the bottom is cut off.  But the bottom is not cut off when I open the window in the database painter.  One of my pictures shows the object at runtime in two different windows (not an EXE, just in the development environment).  It shows how the bottom is cut off in one.  The other picture shows the offending window in the window painter.  All of the pieces live in the same PBL.  I've optimized it and regenerated it.  I've moved the edges around in the offending window and re-genned.  Any ideas about what else I can do?

 

TIA

LAS

PB 12.5.2 Publishing Issues

$
0
0

Hi, working with 12.5.2, doing a simple publish to http://localhost/<appname>, and worked fine the first few times.  However, now suddenly, I'm getting the error:

pbiu complete with exitcode=1.  Log results follow:

      Cannot copy related files to lcal publish folder.

 

So I check out the log file, and it shows the following:

 

Intelligent Updater Trace output file: C:\Dev\PB 12.5.net\CCC4\ccc.out\bin\debug\pbiupub.log

---------------------------------

Exception Time: 2014-02-18 23:29:51.5547570

Process ID: 5180

AppDomain: pbiu.exe Domain ID: 1

Managed Thread ID: 1

Current Thread State: Running

Method: Void WinIOError(Int32, System.String)

Exception Type: System.IO.FileNotFoundException

Exception Message: Could not find file 'C:\Dev\PB 12.5.net\CCC4\ccc.out\bin\debug\reachframework.dll'.

Exception Source: mscorlib

Exception StackTrace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

   at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite)

   at System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite)

   at PBIntelligentUpdater.FileOrganization.CopyRelatedFiles()

   at PBIntelligentUpdater.FileOrganization.PrepareLocalFiles()

Exception Call Stack:    at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)

   at System.Environment.get_StackTrace()

   at PBIntelligentUpdater.PublishLogger.logException(Exception ex, Boolean logCallStack)

   at PBIntelligentUpdater.PublishLogger.LogException(Exception e)

   at PBIntelligentUpdater.FileOrganization.PrepareLocalFiles()

   at PBIntelligentUpdater.PublishEngine.doPublish(PublishProperty myProperty)

   at PBIntelligentUpdater.PublishEngine.doPublish(String strXmlFileName)

   at PBIntelligentUpdater.Program.Main(String[] args)

---------------------------------

 

This is the 2nd time I've run into this problem with this project.  At one point, I could not get past this, even though this file exists, and is part of the .net framework.  And everything has worked fine, and published fine until this point.  I haven't added anything new, simple modification of code.  We're talking about a simple two window app. nothing sophisticated whatsoever.  And this error is very annoying as I have googled my fingers off, and can't seem to find anything about this, other than a ton of sites offering to have you download "their" fixed version of this file.

 

And the thing is, this reference is not marked for Copy Local, nor was it before, nor does it need to be since it's part of the framework, which I find extremely frustrating as it's never required it before, and even if I mark it for copy local, it doesn't copy it, and I can't figure out why it's suddenly requiring this file to be in the debug directory, and can't seem to find it.  I'm at the end of my rope on this one.  Thanks in advance!

 

System: Windows 7 64 bit

PB: 12.5.2 5602

 

--Brian


How to use Team foundation Server for Powerbuilder version control

$
0
0

As the title says, I would like to use Microsoft Team foundation Server for Version control.  Does anyone know if this is possible.  Even when I have attached to our Team Foundation Server (TFS), I do not see it listed in the version control choices under properties for the workspace.  Does anyone know if it is possible and how to get started with TFS.

 

Thanks,

 

Melvyn Polatchek

checkout vs GLV

$
0
0

Who came up with the idea of putting the check out menu option directly below the get latest version option?

 

Would it have killed you to add a warning that you are about to checkout everything?

OLE Resuorce release

$
0
0

Hello, all

I have the following problem when attempting to change files, which were accessed by OLE objects.

For example, I sent a file as attachement. THe sending program is an OLE object.

 

Even after I did DisconnectObject() and GarbageCollect() in the PB code, I still cannot delete the sent file, only if close the program, the block is released.

Does anyone know how to actually release all resources from memory taken by an OLE object?

 

Thank you

Arcady

SAP Price List

$
0
0

Hello,

 

We have been told that PowerBuilder is now on the SAP price list. Can someone please tell me how to find it in the SAP store? I need some pricing information.

 

Also can someone please refer me to the published definitive SAP statement on its commitment to PowerBuilder. I can't seem to find it. I don't mean what was said at conferences/meetings or on bits of slideware, I mean the real thing.

 

I so want to believe that PowerBuilder has a future but down here in this pathetic banana republic in the south west corner of the Pacific, it's not looking real good.

 

TIA, Paul

powerbuilder 12.1 and pgp

$
0
0

I need to be able to sign a file using pgp within my powerbuilder application

I'm using pb 12.1 classic

Is there an easy way to do this?

I thought about installing gpg4win, and use the command line options

but, that's a little cumbersome

is there an easier way?   I'm seeing some references to the window crypto library

or, the powerbuilder crypto.   Will it do pgp?  or, openpgp

 

below is my command line option

gpg.exe --armor --batch --yes --passphrase-file " + p_file + " --output " + s_path + '.asc ' + '--local-user ' + key_user + ' --sign ' + s_path

Viewing all 2935 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>