Registry

There are P4GL functions for setting and getting registry information. I am not familiar with those P4GL functions so it may be silly to use Windows functions instead.

One thing the P4GL can not do is accessing (hexa)decimal data.
Before you try to access the registry directly you should try to find some specialized API call for the requested information type.

For example:

You can read a list of available printers from the registry, but you can also use the EnumPrinters API function for this task. It is generally speaking better to use the API function, because these are documented while the exact registry-locations are not. The EnumPrinters example is only one example. I don't know, but I guess there are documented functions for everything in the registry.
The point is, I think you should try to find an API function before you start digging in the registry directly. Unless of course you are writing and reading in your own key.


(hexa)decimal values in registry

Suppose there is a registry key

     HKEY_LOCAL_MACHINE\Software\Nerdware\Test

and suppose it contains a DWORD value, named "count".
This source example will read the value of "count", identifies the datatype, and increment the value of "count" by one.

{windows.i} /* March 28, 1998 or later */
 
DEFINE VARIABLE key-hdl        AS INTEGER NO-UNDO.
DEFINE VARIABLE lpBuffer       AS MEMPTR  NO-UNDO.
DEFINE VARIABLE lth            AS INTEGER NO-UNDO.
DEFINE VARIABLE reslt          AS INTEGER NO-UNDO.
DEFINE VARIABLE datatype       AS INTEGER NO-UNDO.             
DEFINE VARIABLE icount         AS INTEGER NO-UNDO.
 
 
RUN RegOpenKeyA IN hpApi ( {&HKEY_LOCAL_MACHINE},
                           "Software\Nerdware\Test",
                           OUTPUT key-hdl,
                           OUTPUT reslt).
 
IF reslt NE {&ERROR_SUCCESS} THEN DO:
   MESSAGE "key not found in registry" VIEW-AS ALERT-BOX.
   RETURN.
END.
 
/* read value of "count" into lpBuffer */
/* make buffer large, because we don't know 
   for sure if it is really a DWORD.
   The maximum size is supposed to be MAX_PATH + 1 */
 
ASSIGN lth                = {&MAX_PATH} + 1
       SET-SIZE(lpBuffer) = lth.
 
RUN RegQueryValueExA IN hpApi (key-hdl,
                               "count",
                               0, /* reserved, must be 0 */
                               OUTPUT datatype,
                               GET-POINTER-VALUE(lpBuffer),
                               INPUT-OUTPUT lth,
                               OUTPUT reslt).
 
IF reslt NE {&ERROR_SUCCESS} THEN
   MESSAGE "value not found in registry" VIEW-AS ALERT-BOX.
ELSE DO:
     CASE datatype :
        WHEN 1 THEN  MESSAGE "datatype=STRING" SKIP
                             "value="  GET-STRING(lpBuffer,1)
                             VIEW-AS ALERT-BOX.
        WHEN 4 THEN  MESSAGE "datatype=DWORD" SKIP
                             "value="  GET-LONG(lpBuffer,1)
                             VIEW-AS ALERT-BOX.
        OTHERWISE    MESSAGE "unexpected datatype:" SKIP
                             "datatype=" datatype   SKIP
                              VIEW-AS ALERT-BOX.
     END CASE.
 
 
     /* if it is a DWORD, then increment the value */
     IF datatype=4 THEN DO:
 
        icount = GET-LONG(lpBuffer,1). 
        SET-SIZE(lpBuffer)   = 4. /* =sizeof(DWORD) */
        PUT-LONG(lpBuffer,1) = icount + 1. 
 
        RUN RegSetValueExA IN hpApi (key-hdl,
                                     "count",
                                     INPUT 0, /* reserved, must be 0 */
                                     INPUT 4, /* = REG_DWORD */
                                     INPUT GET-POINTER-VALUE(lpBuffer),
                                     INPUT 4, /* = get-size(lpBuffer) */
                                     OUTPUT reslt).
        IF reslt NE {&ERROR_SUCCESS} THEN
           MESSAGE "can not write value in registry" VIEW-AS ALERT-BOX.
     END.
END.
 
SET-SIZE(lpBuffer)=0.
RUN RegCloseKey IN hpApi (key-hdl,OUTPUT reslt).

notes

function RegSetValueEx will create the value "count" if it did not exist yet. So even if RegQueryValue did not find the value, you can still set one. Of course you will have to change the logic of this source example to allow that.
There are more datatypes than just REG_SZ (=1) and REG_DWORD (=4). Check your API documentation for a complete list.


Enumerating registry values

This example enumerates all values in a given registry key.
In this case, it will return a list of all installed printers (with their names and ports), so it actually does the same as the EnumPrinters function.
As explained in the registry introduction you should prefer to use the EnumPrinters function instead of this RegEnumA stuff, because Microsoft may decide to store the printers info elsewhere in the future, while the EnumPrinters API will be maintained.

{windows.i}  /* March 28, 1998 or later */
 
DEFINE VARIABLE hKey        AS INTEGER NO-UNDO.
DEFINE VARIABLE hPrinterkey AS INTEGER NO-UNDO.
DEFINE VARIABLE subkey      AS CHARACTER    NO-UNDO.
DEFINE VARIABLE port        AS MEMPTR  NO-UNDO.
DEFINE VARIABLE lth         AS INTEGER NO-UNDO.
DEFINE VARIABLE reslt       AS INTEGER NO-UNDO.
DEFINE VARIABLE datatype    AS INTEGER NO-UNDO.
DEFINE VARIABLE ITEM        AS INTEGER NO-UNDO.
 
RUN RegOpenKeyA IN hpApi( {&HKEY_LOCAL_MACHINE},
                          "System\CurrentControlSet\control\Print\Printers",
                          OUTPUT hKey,
                          OUTPUT reslt).
 
ASSIGN ITEM  = 0
       reslt = 0.
 
DO WHILE reslt NE {&ERROR_NO_MORE_ITEMS} :
 
   ASSIGN lth     = {&MAX_PATH} + 1
          subkey  = FILL("x", lth).
 
   RUN RegEnumKeyA IN hpApi (hKey, 
                             ITEM, 
                             OUTPUT subkey, 
                             INPUT LENGTH(subkey), 
                             OUTPUT reslt).
 
   IF reslt NE {&ERROR_NO_MORE_ITEMS} THEN DO:
 
      /* get the printer port (or description..) */
      RUN RegOpenKeyA IN hpApi ( hKey,
                                 subkey,
                                 OUTPUT hPrinterkey,
                                 OUTPUT reslt).
      lth  = {&MAX_PATH} + 1.
      SET-SIZE(port) = lth.
      RUN RegQueryValueExA IN hpApi (hPrinterkey,
                                     "port",
                                     0,  /* reserved, must be 0 */
                                     OUTPUT datatype,
                                     GET-POINTER-VALUE(port),
                                     INPUT-OUTPUT lth,
                                     OUTPUT reslt).
      RUN RegCloseKey IN hpApi (hPrinterkey,OUTPUT reslt).
 
      MESSAGE "printer name=" subkey SKIP 
              "port="         GET-STRING(port,1)
              VIEW-AS ALERT-BOX.
 
   END.
 
   ITEM = ITEM + 1.
END. /* do while not ERROR_NO_MORE_ITEMS */
 
SET-SIZE(port)=0.       
RUN RegCloseKey IN hpApi (hKey,OUTPUT reslt).

Notes

Obviously a (sub)key may contain values with different datatypes, like strings and numbers. You should test the 'datatype' parameter before you interpret a value. For an example of this, see RegQueryValueEx


RegCreateKeyEx

Function RegCreateKeyEx creates a registry key and opens it. If the key already exists, the function will just open it.

{windows.i}
 
&SCOPED-DEFINE KEY_ALL_ACCESS 983103
&SCOPED-DEFINE REG_OPTION_NON_VOLATILE 0
&SCOPED-DEFINE REG_OPTION_VOLATILE 1
&SCOPED-DEFINE REG_CREATED_NEW_KEY 1
&SCOPED-DEFINE REG_OPENED_EXISTING_KEY 2                                                 
 
PROCEDURE RegCreateKeyEx{&A} EXTERNAL {&ADVAPI} :
  DEFINE INPUT  PARAMETER hkey                 AS LONG.
  DEFINE INPUT  PARAMETER lpszSubKey           AS CHARACTER.
  DEFINE INPUT  PARAMETER dwReserved           AS LONG.
  DEFINE INPUT  PARAMETER plszClass            AS CHARACTER.
  DEFINE INPUT  PARAMETER dwOptions            AS LONG.
  DEFINE INPUT  PARAMETER samDesired           AS LONG.
  DEFINE INPUT  PARAMETER lpSecurityAttributes AS LONG.
  DEFINE OUTPUT PARAMETER phkResult            AS LONG.
  DEFINE OUTPUT PARAMETER lpdwDisposition      AS LONG.
  DEFINE RETURN PARAMETER lpResult             AS LONG.
END PROCEDURE.
 
 
/* example : */
 
DEFINE VARIABLE key-hdl    AS INTEGER NO-UNDO.
DEFINE VARIABLE dwDisposition     AS INTEGER NO-UNDO.  
DEFINE VARIABLE reslt      AS INTEGER NO-UNDO.
 
  RUN RegCreateKeyEx{&A} IN /* hpApi */ THIS-PROCEDURE 
    ( {&HKEY_CLASSES_ROOT},
    "SoftWare\MyCompany",
    0,
    '':U, 
    {&REG_OPTION_NON_VOLATILE},
    {&KEY_ALL_ACCESS}, 
    0,
    OUTPUT key-hdl,
    OUTPUT dwDisposition,
    OUTPUT reslt).
 
  IF reslt NE 0 THEN 
     MESSAGE "function RegCreateKeyEx failed" VIEW-AS ALERT-BOX.
  ELSE 
     CASE dwDisposition :
       WHEN {&REG_CREATED_NEW_KEY}     THEN MESSAGE "created new key" 
                                                    VIEW-AS ALERT-BOX.
       WHEN {&REG_OPENED_EXISTING_KEY} THEN MESSAGE "opened existing key"
                                                    VIEW-AS ALERT-BOX.
     END.   
 
 
  /* use the key */
  ....
 
  /* close it */
  RUN RegCloseKey IN hpApi (key-hdl, OUTPUT reslt).
 

notes

The example creates key "Software\MyCompany" or opens it if the key already exists.
Variable key-hdl returns a handle to the open key. This handle can be used in subsequent functions and must eventually be closed by function RegCloseKey.