category-group: os
layer: 0
header file(s): z_func.h
libraries: libz00.lib

description.
This area consists of a few functions that relate to getting information from the host computer that the program runs on, such as:

z_rawenv() - get the value of an environment variable;

z_start(), z_finish() - functions for program initialization and cleanup;

z_hostname() - gets the name of the current computer;

z_pid() - gets the ID number of the current process;

and a group of functions for manipulating data in the "registry" - a concept specific to the Microsoft's operating systems. The registry functions here, as of this writing, work only on Microsoft's host environments (NT, XP, Vista, version 7, etc). The registry functions can best be summed up as a compromise. Since the registry resembles so much a logical file system (aka hierarchical database), we opted for employing file system terminology: instead of "keys", our registry operations refer to "directories" (and not 'folders'). One goal reducing the volume of words (eg recycling words when appropriate) is to simplify the interfaces. A good example is the ubiquitious size() member function. Forward-slashes separate the directories (Microsoft: hives, or keys), although Microsoft's API functions require back-slashes. We strive for a standard terminology based on the over-all purpose and functionality, even when the domain is specific to Microsoft. Hence we settle on a blend of our ways in that territory. Also, since a registry is [so far] basically available only on Microsoft OS platforms, these functions simply return an error condition (usually a -1) on other platforms. Another option is to avoid the registry entirely, but since this is such an important part of software development on Microsoft OS's, we do provide operations to manipulate the registry. No doubt, whatever approach taken is arguable.

All strings used for registry paths use forward slashes and can employ the following [standard] abbreviations:
HKEY_CLASSES_ROOT: HKCR
HKEY_CURRENT_USER: HKCU
HKEY_LOCAL_MACHINE: HKLM
HKEY_USERS: HKU

Here is an example of getting a registry value:

#include "z_string.h"
#include "z_func.h"

void main() { int ie1, ie2; size_t nb, n = 8000; char buf[8000]; string_o path, item; path = "HKLM/SOFTWARE/Adobe/Acrobat Reader/10.0/Installer"; item = "Path"; ie1 = z_registry_getvalue (path.data(), item.data(), buf, &n, &ie2); }

There are some general behaviours that should be known about in using these registry functions. All data going in or coming out of registry entries are via (char *) character buffers. Binary data can safely be moved about this way, as internally z_bcopy() is used for copying data into and out of registry variables.

z_registry_type() can be used to ascertain the general registry variable's type, but the enumerations provided - zt_RegistryEntry, in z_func.h - are not as detailed as the types available from Micrsoft. To compensate, additional detail information is available via the trailing integer-type output parameter to this function - which doubles to serve as an error indicator flag also. Thus, if the actual type is, for example, REG_QWORD_LITTLE_ENDIAN, z_registry_type() would return the enum z_Registry_LongInt, and set the 3rd [output] parameter to 6, which means the long int is little-endian. More information is available in the function's reference entry in this section.

[C] functions (aka subroutines):

z_rawenv()
SIGNATURE: z_rawenv (const char *varname, char *buf, size_t n, int *pi = NULL)
SYNOPSIS:
gets the value for a specified environment variable and copies it into output variable 'buf'. The [maximum] size of 'buf' must be specified, in input parameter 'n'.
There is an easier-to-use version of this function in layer 2, z_env_to_str() (also aliased as z_env()).
HEADER FILE: z_func.h
PARAMETERS
  • varname: character buffer string containing the variable name
  • buf: destination character buffer to recieve the value of the variable
  • n: the maximum length of the buffer
  • pi: [output] error indicator flag variable. possible values:
    0: all ok; environment variable found & retrieved
    zErr_NotFound: environment variable not found
    zErr_Param_NullPointer: bad input (0-length, or null pointer provided)
    zErr_Result_TooBig: value of the result [output] variable exceeds the specified buffer size
DESCRIPTION:
This function provides a simple mapping-wrapper for the getenv() system call. Its older name was 'z_env()'. The name was changed October 23, 2012, to indicate that it is a "raw" version of "z_env()", which is found in layer 2. The latter version uses Z Directory string objects (string_o) instead of raw character buffers, obviating the need for managing buffer sizes. z_env() is the recommended version for this functionality.
RETURNS:
0: successful fetch
1: no such variable found in the environment
-1: error occured (see value of "pi")
 

ms_com_init()
SIGNATURE: int ms_com_init ()
SYNOPSIS:
this is a wrapper around the Microsoft system call CoInitialize(). It is strictly for Microsoft operating system platforms and is not meant to be called directly by the application.
RETURNS:
0: success
-1: error occured; system call failure
 

ms_com_end()
SIGNATURE: int ms_com_end ()
SYNOPSIS:
this is a Z Directory internal function that is not to be called by the application. It is a simple wrapper around the Microsoft system call CoUninitialize().
RETURNS: 0 [always]
 

ms_wsa_init()
SIGNATURE: int ms_wsa_init (int *pi = NULL)
SYNOPSIS:
this is a Z Directory internal function that is not meant to be called by the application directly. It is a wrapper around the Microsoft system call WSAStartup().
DESCRIPTION: this function is required to initialize the Microsoft winsock system.
RETURNS: 0 [always]
 

ms_wsa_end()
SIGNATURE: int ms_wsa_end (int *pi = NULL)
SYNOPSIS: this is simply and purely a wrapper around the Microsoft system call function WSACleanup().
RETURNS:
0: success [always happens in a Microsoft OS environment].
-1: error, function not called from within Microsoft
 

z_start()
SIGNATURE: int z_start (VOID)
SYNOPSIS:
performs any and all initialization required by the Z Directory (including COM, and WinSock on Microsoft platforms). Performs initialization of exemplars (eg calls z_start_exemplars()).
HEADER FILE: z_func.h
RETURNS:
0: success
-1: error occured; system failure or possibly memory exhaustion
 

z_finish()
SIGNATURE: int z_finish (VOID)
SYNOPSIS: performs any and all post-run cleanup required for the Z Directory and the OS
HEADER FILE: z_func.h
RETURNS: 0
 

z_hostname()
SIGNATURE: int z_hostname (char *str, size_t max_n)
SYNOPSIS:
gets the name of the current host computer. Caution: this routine will fail if z_start() has not been called earlier.
HEADER FILE: z_types.h
PARAMETERS

  • str - target buffer for host name
  • max_n - mex length of "str"
RETURNS:
0: success
-1: error occured; system failure
 

z_pid()
SIGNATURE: count_t pid (VOID)
SYNOPSIS: returns the process ID number for the current, main running process.
HEADER FILE: z_func.h
DESCRIPTION: this routine serves as a "1 size fits all" wrapper around the "getpid()" series of functions.
RETURNS: 0
 

z_registry_entry_exists()
SIGNATURE: boolean z_registry_entry_exists (const char *path, const char *item, int *pi = NULL)
SYNOPSIS: tells if a regular registry variable-entry exists or not
HEADER FILE: z_func.h
DESCRIPTION: specify the 'path' to the registry variable in input parameter 'path'. specify the name of the variable in 'item'.
RETURNS:
TRUE: item found
FALSE: item not found, or error occured
 

z_registry_getvalue()
SIGNATURE: int z_registry_getvalue (const char *path, const char *item, char *buff, size_t *nb, int *pi = NULL)
SYNOPSIS:
gets the value from the registry of an item ("item") in the hive/key/directory specified by "path". The path must be valid and the entry must exist. If the entry is of binary type data, "item" will be loaded with binary (possibly non-readable) bytes of data. If the entry is an integer type, the value will be formatted to string form.
HEADER FILE: z_func.h
PARAMETERS

  • path: a character string representing the directory (Microsoft terminology: the "key") to be accessed. This string must use forward-slashes to separated registry directories. Shorthand abbreviations may be used to access the major top-level directory-groups (ie, HKLM, HKU, etc)
  • item: the name of the registry element ("Key"). This entry will have a type - String, Binary, DWORD, Multi-String, or "Expandable String Value". The default type is "String".
  • buff: the character array buffer that is to recieve the current contents of the item, if found, as a character array.
  • nb: the buffer size. This MUST BE INITIALIZED to the size of the buffer that is to recieve the contents of the registry item. After this function call, it will be set to the number of bytes written
  • pi: error indicator output variable. values:
    0: all ok; retrieved
    1: this operation not supported
    2: invalid path (no main top-level group)
    3: buffer is too short for stuff following group name
    4: error in calling RegOpenKeyEx() system call
    5: error in calling RegQueryValueEx() system call
    6: buffer overflow - output is truncated
    7: buffer overflow - output exceeds 8K
    8: data type not supported (eg, "REG_MULTI_SZ")
    9: strange out of bounds index value (this should never happen)
EXAMPLE:

/* this code snippet returns the BIOS version info, in "buf" */
char buf[4096];
int ie, ie2;
size_t buflen = 4096;
string_o s1 ("HKLM/HARDWARE/DESCRIPTION/System");
ie = z_registry_getvalue (s1.data(), "SystemBiosVersion", buf, &buflen, &ie2);
if (ie) { /* error processing */ }

RETURNS:
0: item's value retrieved
-1: error occurred (see output variable pie for more info)
TRAITS:
the 1st and 2nd parameters can be combined (indeed, this was the case in earlier versions). The "item" and "directory" have been separated for a consistent interface.
 

z_registry_setvalue()
SIGNATURE: int z_registry_setvalue (const char *path, const char *item, const char *value, size_t *nb, int *pi)
SYNOPSIS:
sets an existing item (specified by input parameter #2, "item") to the value given by 'value'. The item must exist; else, nothing is done and an error condition is returned.
PARAMETERS

  • path: a character string representing the directory (Microsoft: "key") to be accessed. This string must use forward-slashes to separated registry directories. Shorthand abbreviations may be used to access the major top-level directory-groups (see example):
    HKEY_CLASSES_ROOT: 'HKCR'
    HKEY_CURRENT_USER: 'HKCU'
    HKEY_LOCAL_MACHINE: 'HKLM'
    HKEY_USERS: 'HKU'
  • item: a character string representing the name of the item in the registry directory to set.
  • value: a null-terminated character string containing the value to set 'item' to.
  • nb: input and output variable. for specifying how many bytes to write to. if the item is of type z_Registry_String, the number of characters to write should be specified in it. if the value is 0, or the pointer is NULL, z_strlen() will be applied to the buffer to get its size.
  • pi: error indicator output variable. values:
    0: all ok; retrieved
    zErr_Param_NullPointer: {z_Registry_Binary case} parameter 'nb' is null;
    zErr_TypeNotHandled: registry type not currently handled
    zErr_UnknownProto: unknown registry type encountered
    zErr_Syscall_Failure: system call failed: RegSetValueEx()
    [the following errors from to z_registry_type(), called internally]
    zErr_NotSupported: the operation is not supported on the current platform
    7: "int" type is big-endian (notification only)
    8: the item is of another [rare] type (eg, REG_LINK) (this is informational, a notification only)
    zErr_UnknownProto: unknown data type encountered
    [errors emanating from z_registry_opendir()]
    zErr_AccessDenied: can't access the registry
    zErr_Path_NotFound: RegOpenKeyEx() failed (bum path)
    zErr_Param_BadFormat: RegOpenKeyEx() failed (?!)
    zErr_Syscall_Failure: RegOpenKeyEx() failed; reason unknown
    [errors passed thru via check_registry_group_prefix()]
    zErr_NoMatch: invalid path (no main top-level group [like "HKLM")
    zErr_Param_TooSmall: the buffer is too short for the group name/abbrev
    zErr_StrangeImpossible: strange out-of-bounds index value encountered (this should never happen)
DESCRIPTION:
Given a registry path (in 'path'), where there is the entry 'item'. this subroutine sets its value to 'new_value'. The entry must exist, or else this routine does nothing and returns an error. This subroutine gets type information for the entry from the registry, and automatically converts the data to the appropriate type. in the case of binary data, the number of bytes must be provided via the input variable (parameter 4 in the function's argument list). In all other types of data, this parameter is ignored. the resultant number of bytes is returned in this variable.
RETURNS:
0: item successfully set-changed
-1: error occurred (see output variable pie for more info)
 

z_registry_create_entry()
SIGNATURE: int z_registry_create_entry (const char *my_path, const char *item, const char *my_value, zt_RegistryEntry my_type = z_Registry_String, size_t nb = 0, int *pie = NULL)
SYNOPSIS:
creates a new item in the registry directory given by "path". "path" must exist; "item" must not exist. The [initial] value of "item" will be set to "my_value", and its type will be set to that of "my_type". If "my_type" is z_Registry_Binary, the next parameter, "nb", must be set to a non-zero value - the number of bytes in "my_value" to write.
 

z_registry_remove_entry()
SIGNATURE: int z_registry_remove_entry (const char *path, const char *item, int *pie = NULL)
PARAMETERS

  • path: a character string representing the directory
  • item: a character string representing the name of the item in the registry directory to delete.
 

z_registrydir_exists()
SIGNATURE: boolean z_registrydir_exists (const char *path, int *pie = NULL)
SYNOPSIS: tells if directory ("key") exists in the registry.
PARAMETERS

  • path: a character string representing the directory to be examined. The sub-directory itself should be the leaf-node part of the path, at the end.
  • RETURNS:
    TRUE: directory exists
    FALSE: no such directory, or error
     

    z_registry_create_dir()
    SIGNATURE: int z_registry_create_dir (const char *my_path, const char *my_name, int *pexi = NULL)
    PARAMETERS

  • path: a character string representing the parent directory where the new sub-directory is to go. It must be a valid, existing path.
  •  

    z_registry_remove_dir()
    SIGNATURE: int z_registry_remove_dir (const char *path, boolean kill = TRUE, int * = NULL)
    SYNOPSIS: deletes an existing directory ("key") in the Registry. Currently, the directory cannot have any sub-directories.
    PARAMETERS

    • path: a character string representing the full directory path, including the new sub-directory is found. It must be a valid, existing path. The sub-directory itself should be the leaf-node part of the path, at the end.
    • kill: a TRUE / FALSE flag. If FALSE, and "subdir" contains any sub-directories itself, then this operation will fail and an error condition is returned. Note that THIS PARAMETER IS CURRENTLY NOT IMPLEMENTED.
    TRAITS: the directory will not be deleted, even if "kill" is set to TRUE (bug).
     

    bugs.
    Currently REG_MULTI_SZ (z_Registry_MultiLine) is not supported in the registry functions. Neither is big- or little-endian support. Thus, REG_DWORD_LITTLE_ENDIAN, REG_DWORD_BIG_ENDIAN, and REG_QWORD_LITTLE_ENDIAN all map onto types int or long int.

    history.

    Thu 04/13/1995: pid functionality created
    ??? 06/15/1995: z_pid() AS/400: the "va-arg stack error method"
    ??? 06/20/1995: z_pid() implemented politically correct on as/400
    ??? 07/31/2001: microsoft COM initialization code created
    Thu 02/10/2011: moved Exemplar management alongside z_init()
    Sun 08/28/2011: most registry functions (not "setvalue()") banged out