Absent Member.
Absent Member.
2667 views

Retrieving a Windows user name in VisCobol

Jump to solution

[Migrated content. Thread originally posted on 21 May 2012]

In NET EXPRESS code we have code that reads as:

SET MPR-POINTER TO ENTRY "MPR.DLL".

IF MPR-POINTER = NULLS
MOVE "** UNKNOWN **" TO WS-OPERATOR.


(where MPR-POINTER defined as 01 PROCEDURE-POINTER)

This works and when run ALWAYS returns a value into MPR-POINTER.

In VisCOBOL code reads as:

SET MPR-POINTER TO ENTRY "MPR.DLL".

IF MPR-POINTER = NULLS
MOVE "** UNKNOWN **" TO WS-OPERATOR.


(where MPR-POINTER defined as 01 PROCEDURE-POINTER)

This DOES NOT work and the value returned to MPR-POINTER = NULL.

As mpr.dll is in C:\Windows\System32 directory and is correctly pathed in the Viscobol setup (as seen by typing PATH in the VisCOBOL command Prompt Dos BOX) then why does this code fail to work in VisCOBOL??


0 Likes
1 Solution

Accepted Solutions
Micro Focus Expert
Micro Focus Expert
If you set an procedure-pointer to "mpr", the runtime will not only search and load the DLL called "mpr.dll" but it will also find the exported symbol "mpr". In the native runtime if this symbol is not present it will return oridinal #0 but the managed runtime we choose not return ordinal #0 because you can do nothing with it.

The code you are using assumes this but the work around is simple, compare the procedure-pointer against the API you require eg:

My original code snippet was:

           set BadPtr to entry "mybadptr"
           set MprPtr to entry "mpr"
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if

and the portable version being:

           set BadPtr to entry "mybadptr"
           set MprPtr to entry "mpr"
           set MprPtr to entry WNetGetUser
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if


Then compiled as:

D:\DemoAndTests\nx51tests\win32\getnuser>cobol GETNUSER.CBL ilgen constant(intcode(1)) iltarget"x86" noilnative;
Micro Focus COBOL
Version 2.X.XXXX Copyright (C) Micro Focus 1984-2012. All rights reserved.
* Checking complete with no errors

Y:\DemoAndTests\nx51tests\win32\getnuser>getnuser
NetWork UserName : spg


The source code for getnuser.cbl is:
      $set ans85 mf defaultbyte"00" case
      *
      * To compile for intcode change the below to intcode
      * constant to 1 eg:
      $set constant intcode(0)
      *
      * To compile/link for .EXE use:
      *  cbllink getnuser.cbl mpr.lib
      *
      * mpr.lib can be found in the Microsoft SDK eg: mstools\lib\mpr.lib
      *

      *  $set constant intcode(0)


       identification division.
       program-id. getnuser.
       special-names.
           call-convention 74 is WINAPI.

       data division.
       working-storage section.
       copy "miniwin.cpy".
       copy "wintypes.cpy".
       copy "winnetwk.cpy".
       copy "error.cpy".
       copy "winerror.cpy".

       78 BufferSizeConst   value 1024.
       01 UserName          pic x(BufferSizeConst).
       01 BufferLength      DWORD.
       01 NetRetCode        DWORD.

       01 MprPtr            procedure-pointer.
       01 BadPtr            procedure-pointer.

       01 LastErrorCode     DWORD.

       linkage section.
       procedure division.

      $if intcode = 1
           call "cob32api"
           set BadPtr to entry "mybadptr"

           set MprPtr to entry "mpr"
           set MprPtr to entry WNetGetUser
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if

      *
      * You need to call GetLastError at least once when
      * using .INT/.GNT code otherwise the RTS will return
      * 127 (ERROR_PROC_NOT_FOUND)
      *
           call WINAPI GetLastError returning NetRetCode
      $end

      *
      * Get the WNetGetUser
      *
           move BufferSizeConst to BufferLength

      *
      * Parameters
      *
      * lpName,             pointer to local name to get user name for
      *                   (NULL equals current user)
      * UserName,         pointer to buffer for user name
      * BufferLength      pointer to buffer size variable
      *

           call WINAPI WNetGetUser using
                by reference omitted
                by reference UserName,
                by reference BufferLength
                returning NetRetCode
           end-call

      *
      * Do some simple error checking
      *
           if NetRetCode not equal NO-ERROR

               call WINAPI GetLastError
                   returning LastErrorCode
               end-call

               evaluate LastErrorCode
                    when ERROR-NOT-CONNECTED
                         display "Machine not connected"
                    when ERROR-MORE-DATA
                         display "The buffer is too small"
                         display "Should be ... " BufferLength
                    when ERROR-NO-NETWORK
                         display "No network is present"
                    when ERROR-EXTENDED-ERROR
                         display "See WNetGetLastError for more info"
                    when ERROR-NO-NET-OR-BAD-PATH
                         display "No network or bad path"
               end-evaluate

               display "WNetGetUser failed (" NetRetCode ")"
               stop run
           end-if

           display "NetWork UserName : " UserName(1:BufferLength)

View solution in original post

0 Likes
5 Replies
Absent Member.
Absent Member.
I actually now get the same when calling out to "KERNEL32.DLL" also...MPR-POINTER returns NULL.

Have added both kernell32.dll & mpr.dll to the 'References' block in the solution...no joy.

Have added Microfocus.COBOL.Runtime to the 'References' block in the solution...still no joy!!!

Grrrr!!
0 Likes
Micro Focus Expert
Micro Focus Expert
If you set an procedure-pointer to "mpr", the runtime will not only search and load the DLL called "mpr.dll" but it will also find the exported symbol "mpr". In the native runtime if this symbol is not present it will return oridinal #0 but the managed runtime we choose not return ordinal #0 because you can do nothing with it.

The code you are using assumes this but the work around is simple, compare the procedure-pointer against the API you require eg:

My original code snippet was:

           set BadPtr to entry "mybadptr"
           set MprPtr to entry "mpr"
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if

and the portable version being:

           set BadPtr to entry "mybadptr"
           set MprPtr to entry "mpr"
           set MprPtr to entry WNetGetUser
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if


Then compiled as:

D:\DemoAndTests\nx51tests\win32\getnuser>cobol GETNUSER.CBL ilgen constant(intcode(1)) iltarget"x86" noilnative;
Micro Focus COBOL
Version 2.X.XXXX Copyright (C) Micro Focus 1984-2012. All rights reserved.
* Checking complete with no errors

Y:\DemoAndTests\nx51tests\win32\getnuser>getnuser
NetWork UserName : spg


The source code for getnuser.cbl is:
      $set ans85 mf defaultbyte"00" case
      *
      * To compile for intcode change the below to intcode
      * constant to 1 eg:
      $set constant intcode(0)
      *
      * To compile/link for .EXE use:
      *  cbllink getnuser.cbl mpr.lib
      *
      * mpr.lib can be found in the Microsoft SDK eg: mstools\lib\mpr.lib
      *

      *  $set constant intcode(0)


       identification division.
       program-id. getnuser.
       special-names.
           call-convention 74 is WINAPI.

       data division.
       working-storage section.
       copy "miniwin.cpy".
       copy "wintypes.cpy".
       copy "winnetwk.cpy".
       copy "error.cpy".
       copy "winerror.cpy".

       78 BufferSizeConst   value 1024.
       01 UserName          pic x(BufferSizeConst).
       01 BufferLength      DWORD.
       01 NetRetCode        DWORD.

       01 MprPtr            procedure-pointer.
       01 BadPtr            procedure-pointer.

       01 LastErrorCode     DWORD.

       linkage section.
       procedure division.

      $if intcode = 1
           call "cob32api"
           set BadPtr to entry "mybadptr"

           set MprPtr to entry "mpr"
           set MprPtr to entry WNetGetUser
           if BadPtr equals MprPtr
                display "Unable to load MPR.DLL"
                stop run
           end-if

      *
      * You need to call GetLastError at least once when
      * using .INT/.GNT code otherwise the RTS will return
      * 127 (ERROR_PROC_NOT_FOUND)
      *
           call WINAPI GetLastError returning NetRetCode
      $end

      *
      * Get the WNetGetUser
      *
           move BufferSizeConst to BufferLength

      *
      * Parameters
      *
      * lpName,             pointer to local name to get user name for
      *                   (NULL equals current user)
      * UserName,         pointer to buffer for user name
      * BufferLength      pointer to buffer size variable
      *

           call WINAPI WNetGetUser using
                by reference omitted
                by reference UserName,
                by reference BufferLength
                returning NetRetCode
           end-call

      *
      * Do some simple error checking
      *
           if NetRetCode not equal NO-ERROR

               call WINAPI GetLastError
                   returning LastErrorCode
               end-call

               evaluate LastErrorCode
                    when ERROR-NOT-CONNECTED
                         display "Machine not connected"
                    when ERROR-MORE-DATA
                         display "The buffer is too small"
                         display "Should be ... " BufferLength
                    when ERROR-NO-NETWORK
                         display "No network is present"
                    when ERROR-EXTENDED-ERROR
                         display "See WNetGetLastError for more info"
                    when ERROR-NO-NET-OR-BAD-PATH
                         display "No network or bad path"
               end-evaluate

               display "WNetGetUser failed (" NetRetCode ")"
               stop run
           end-if

           display "NetWork UserName : " UserName(1:BufferLength)

View solution in original post

0 Likes
Absent Member.
Absent Member.
Thanks for your input.

Can you tell me why the code I put up works in Net Express but NOT in Visual COBOL?

Thanks.
0 Likes
Micro Focus Expert
Micro Focus Expert
Sure, we used to have support for "simulating" ordinal #0 support but we found it was not a very reliable solution as it interfered with other functionality.
0 Likes
Absent Member.
Absent Member.
Thanks for the help.

Can I just point out as well to VisCOBOL users that I've had to include both the MPR.DLL & KERNEL32.DLL from the C:\Windows\Systems32 directory as REFERENCES within the VisCOBOL solution in order to access them via the method stated earlier in this thread.

Failure to do this results in the program NOT working!
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.