registry.c revision fc9b2e8809c305f340d86a789566f8abb1ca8a19
/*
* Functions to handle interacting with the Win32 registry
*/
/*
* Apache registry key structure
*
* Apache's registry information is stored in the HKEY_LOCAL_MACHINE
* key, under
*
* HKLM\SOFTWARE\Apache Group\Apache\version
*
* These keys are defined in this file. The definition of the "version" part
* will need updating each time Apache moves from beta to non-beta or from a
* release to a development or beta version.
*/
/* To allow for multiple services, store the configuration file's full path
* under each service entry:
*
* HKLM\System\CurrentControlSet\Services\[service name]\Parameters\ConfPath
*
* The default configuration path (for console apache) is still stored:
*
* HKLM\Software\[Vendor]\[Software]\[Version]\ServerRoot
*/
#include <windows.h>
#include <stdio.h>
#include "httpd.h"
#include "http_log.h"
/* Define where the Apache values are stored in the registry. In general
* VERSION will be the same across all beta releases for a particular
* major release, but will change when the final release is made.
*/
#define VENDOR "Apache Group"
#define SOFTWARE "Apache"
#define VERSION "1.3.9"
#define SERVICEKEYPRE "System\\CurrentControlSet\\Services\\"
#define SERVICEKEYPOST "\\Parameters"
/*
* The Windows API registry key functions don't set the last error
* value (the windows equivalent of errno). So we need to set it
* with SetLastError() before calling the aplog_error() function.
* Because this is common, let's have a macro.
*/
SetLastError(rv); \
} while (0);
/*
* Get the data for registry key value. This is a generic function that
* can either get a value into a caller-supplied buffer, or it can
* allocate space for the value from the pass in pool. It will normally
* be used by other functions within this file to get specific key values
* (e.g. registry_get_server_root()). This function returns a number of
* different error statuses, allowing the caller to differentiate
* between a key or value not existing and other kinds of errors. Depending
* on the type of data being obtained the caller can then either ignore
* the key-not-existing error, or treat it as a real error.
*
* If ppValue is NULL, allocate space for the value and return it in
* *pValue. The return value is the number of bytes in the value.
* The first argument is the ap_context_t to use to allocate space for the value.
*
* If pValue is not NULL, assume it is a buffer of nSizeValue bytes,
* and write the value into the buffer. The return value is the number
* of bytes in the value (so if the return value is greater than
* the supplied nSizeValue, the caller knows that *pValue is truncated).
* The ap_context_t argument is ignored.
*
* The return value is the number of bytes in the successfully retreived
* key if everything worked, or:
*
* -1 the key does not exists
* -2 if out of memory during the function
* -3 if the buffer specified by *pValue/nSizeValue was not large enough
* for the value.
* -4 if an error occurred
*
* If the return value is negative a message will be logged to the error
* log (aplog_error) function. If the return value is -2, -3 or -4 the message
* will be logged at priority "error", while if the return value is -1 the
* message will be logged at priority "warning".
*/
static int ap_registry_get_key_int(ap_context_t *p, char *key, char *name, char *pBuffer, int nSizeBuffer, char **ppValue)
{
long rv;
char *pValue;
int nSize;
int retval;
key,
0,
&hKey);
if (rv == ERROR_FILE_NOT_FOUND) {
"Registry does not contain key %s",key);
return -1;
}
if (rv != ERROR_SUCCESS) {
return -4;
}
/* Find the size required for the data by passing NULL as the buffer
* pointer. On return nSize will contain the size required for the
* buffer if the return value is ERROR_SUCCESS.
*/
name, /* key name */
NULL, /* reserved */
NULL, /* type */
NULL, /* for value */
&nSize); /* for size of "value" */
if (rv != ERROR_SUCCESS) {
return -1;
}
if (!pValue) {
/* Eek, out of memory, probably not worth trying to carry on,
* but let's give it a go
*/
"Error getting registry key: out of memory");
return -2;
}
}
else {
/* Get the value into the existing buffer of length nSizeBuffer */
nSize = nSizeBuffer;
}
name, /* key name */
NULL, /* reserved */
NULL, /* type */
pValue, /* for value */
&nSize); /* for size of "value" */
retval = 0; /* Return value */
if (rv == ERROR_FILE_NOT_FOUND) {
retval = -1;
}
else if (rv == ERROR_MORE_DATA) {
/* This should only happen if we got passed a pre-existing buffer
* (pBuffer, nSizeBuffer). But I suppose it could also happen if we
* allocate a buffer if another process changed the length of the
* value since we found out its length above. Umm.
*/
"Error getting registry value %s: buffer not big enough", key);
retval = -3;
}
else if (rv != ERROR_SUCCESS) {
retval = -4;
}
if (rv != ERROR_SUCCESS) {
if (retval == 0) {
/* Keep error status from RegQueryValueEx, if any */
retval = -4;
}
}
}
/*
* Get the server root from the registry into 'dir' which is
* size bytes long. Returns 0 if the server root was found
* or if the serverroot key does not exist (in which case
* dir will contain an empty string), or -1 if there was
* an error getting the key.
*/
{
int rv;
if (rv < 0) {
dir[0] = '\0';
}
}
char *ap_get_service_key(char *service_name)
{
return(key);
}
{
int rv;
if (rv < 0) {
dir[0] = '\0';
}
}
/**********************************************************************
* The rest of this file deals with storing keys or values in the registry
*/
{
int i;
if(!key)
return(NULL);
for(i = 0; i <= index; i++)
{
key++;
if (!key)
return(NULL);
}
if(!key)
*key = '\0';
*key = '\\';
return(skey);
}
/*
* ap_registry_create_apache_key() creates the Apache registry key
* (HLKM\SOFTWARE\Apache Group\Apache\version, as defined at the start
* of this file), if it does not already exist. It will be called by
* ap_registry_store_key_int() if it cannot open this key. This
* function is intended to be called by ap_registry_store_key_int() if
* the Apache key does not exist when it comes to store a data item.
*
* Returns 0 on success or -1 on error. If -1 is returned, the error will
* already have been logged.
*/
static int ap_registry_create_key(char *longkey)
{
int index;
int retval;
int rv;
char *key;
index = 0;
retval = 0;
/* Walk the tree, creating at each stage if necessary */
int result;
key, /* subkey */
0, /* reserved */
NULL, /* class */
NULL,
&hKeyNext,
&result);
if (rv != ERROR_SUCCESS) {
retval = -4;
}
/* Close the old key */
if (rv != ERROR_SUCCESS) {
if (retval == 0) {
/* Keep error status from RegCreateKeyEx, if any */
retval = -4;
}
}
if (retval) {
break;
}
index++;
}
if (!key) {
/* Close the final key we opened, if we walked the entire
* tree
*/
if (rv != ERROR_SUCCESS) {
if (retval == 0) {
/* Keep error status from RegCreateKeyEx, if any */
retval = -4;
}
}
}
else
return retval;
}
/*
* ap_registry_store_key_int() stores a value name and value under the
* Apache registry key. If the Apache key does not exist it is created
* first. This function is intended to be called from a wrapper function
* in this file to set particular data values, such as
* ap_registry_set_server_root() below.
*
* Returns 0 if the value name and data was stored successfully, or
* returns -1 if the Apache key does not exist (since we try to create
* this key, this should never happen), or -4 if any other error occurred
* (these values are consistent with ap_registry_get_key_int()).
* If the return value is negative then the error will already have been
* logged via aplog_error().
*/
static int ap_registry_store_key_int(char *key, char *name, DWORD type, void *value, int value_size)
{
long rv;
int retval;
key,
0,
&hKey);
if (rv == ERROR_FILE_NOT_FOUND) {
/* Key could not be opened -- try to create it
*/
if (ap_registry_create_key(key) < 0) {
/* Creation failed (error already reported) */
return -4;
}
/* Now it has been created we should be able to open it
*/
key,
0,
&hKey);
if (rv == ERROR_FILE_NOT_FOUND) {
"Registry does not contain key %s after creation",key);
return -1;
}
}
if (rv != ERROR_SUCCESS) {
return -4;
}
/* Now set the value and data */
name, /* value key name */
0, /* reserved */
type, /* type */
value, /* value data */
retval = 0; /* Return value */
if (rv != ERROR_SUCCESS) {
retval = -4;
}
else {
}
/* Make sure we close the key even if there was an error storing
* the data
*/
if (rv != ERROR_SUCCESS) {
if (retval == 0) {
/* Keep error status from RegQueryValueEx, if any */
retval = -4;
}
}
return retval;
}
/*
* Sets the service confpath value within the registry. Returns 0 on success
* or -1 on error. If -1 is return the error will already have been
* logged via aplog_error().
*/
{
int rv;
return rv < 0 ? -1: 0;
}
/*
* Sets the serverroot value within the registry. Returns 0 on success
* or -1 on error. If -1 is return the error will already have been
* logged via aplog_error().
*/
int ap_registry_set_server_root(char *dir)
{
int rv;
return rv < 0 ? -1 : 0;
}