%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file
Access Windows registry, use
wchar_t names.
CRT on Windows: Optional.
*/
#ifndef DK4CONF_H_INCLUDED
#include "dk4conf.h"
#endif
#ifndef DK4TYPES_H_INCLUDED
#include "dk4types.h"
#endif
#ifndef DK4ERROR_H_INCLUDED
#include "dk4error.h"
#endif
#ifndef DK4WREGK_H_INCLUDED
#include "dk4wregk.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Open a registry key.
@param pk Parent key identifier.
@param keyname Name of registry key to open.
@param wr Flag: Open for write access too.
@param erp Error report, may be NULL.
@return Pointer to key handle structure on success, NULL on error.
Error codes:
- DK4_E_NOT_SUPPORTED
if the function is run on a non-Windows system,
- DK4_E_INVALID_ARGUMENTS
if pk or keyname is invalid,
- DK4_E_NOT_FOUND
if opening or creating the registry key failed,
- DK4_E_MEMORY_ALLOCATION_FAILED
if memory allocation for the key handle structure failed.
*/
void *
dk4wreg_open_key_wc(int pk, const wchar_t *keyname, int wr, dk4_er_t *erp);
/** Set a string value.
@param kptr Key handle structure.
@param name Entry name.
@param val Entry value.
@param expand Flag: Use REG_EXPAND_SZ (1) or REG_SZ (0).
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_NOT_SUPPORTED
when called on non-Windows systems,
- DK4_E_INVALID_ARGUMENTS
if kptr or val is NULL,
- DK4_E_MATH_OVERFLOW
if the name is too long,
- DK4_E_SYSTEM
if RegSetValueExW() failed.
*/
int
dk4wreg_set_string_wc(
void *kptr, const wchar_t *name, const wchar_t *val, int expand, dk4_er_t *erp
);
/** Get string value.
@param kptr Key handle structure.
@param name Entry name.
@param bptr Buffer for result string.
@param sz Result buffer length, number of wchar_t.
@param expand Pointer to expand flag output variable.
This variable is set to 1 if the string found
is of type REG_EXPAND_SZ. The variable is left
unchanged for REG_SZ.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_NOT_SUPPORTED
when called on non-Windows systems,
- DK4_E_INVALID_ARGUMENTS
if kptr, name, or bptr is NULL or sz is 0,
- DK4_E_NOT_FOUND
if the entry is not found or has 0 length,
- DK4_E_SYNTAX
if the entry is not a string type.
*/
int
dk4wreg_get_string_wc(
void *kptr,
const wchar_t *name,
wchar_t *bptr,
size_t sz,
int *expand,
dk4_er_t *erp
);
/** Set DWORD registry entry.
@param kptr Key handle structure.
@param name Entry name.
@param val Value.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_NOT_SUPPORTED
when called on a non-Windows system,
- DK4_E_INVALID_ARGUMENTS
if kptr is NULL,
- DK4_E_SYSTEM
if RegSetValueExW() failed.
*/
int
dk4wreg_set_dword_wc(
void *kptr, const wchar_t *name, dk4_dword_t val, dk4_er_t *erp
);
/** Retrieve DWORD value from registry.
@param kptr Key handle structure.
@param name Entry name.
@param vptr Pointer to result variable.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
*/
int
dk4wreg_get_dword_wc(
void *kptr,
const wchar_t *name,
dk4_dword_t *vptr,
dk4_er_t *erp
);
/** Get string value.
@param kptr Key handle structure.
@param name Entry name.
@param dptr Buffer for result string.
@param dsz Result buffer length, number of wchar_t.
@param b1 First buffer, used for result from RegQueryValue().
Should have same size as dptr.
@param b1sz Size of b1, number of wchar_t.
@param b2 Second buffer, used for result from ExpandEnvironmentStrings.
Should be 2 characters larger than dptr.
@param b2sz Size of b2, number of wchar_t.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_NOT_SUPPORTED
when called on non-Windows systems,
- DK4_E_INVALID_ARGUMENTS
if kptr, name, or bptr is NULL or sz is 0,
- DK4_E_BUFFER_TOO_SMALL
if one of the buffers is too small,
- DK4_E_NOT_FOUND
if the entry is not found or has 0 length,
- DK4_E_SYNTAX
if the entry is not a string type.
*/
int
dk4wreg_get_expanded_string_wc(
void *kptr,
const wchar_t *name,
wchar_t *dptr,
size_t dsz,
wchar_t *b1,
size_t b1sz,
wchar_t *b2,
size_t b2sz,
dk4_er_t *erp
);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4conf.h"
#include "dk4wregt.h"
#include "dk4wregw.h"
#include "dk4strw.h"
#ifndef DK4MEM_H_INCLUDED
#include "dk4mem.h"
#endif
#include "dk4maasz.h"
#if DK4_ON_WINDOWS
#ifndef WINDOWS_H_INCLUDED
#include
#define WINDOWS_H_INCLUDED 1
#endif
#ifndef WINBASE_H_INCLUDED
#include
#define WINBASE_H_INCLUDED 1
#endif
#ifndef WINREG_H_INCLUDED
#include
#define WINREG_H_INCLUDED 1
#endif
#endif
$!trace-include
void *
dk4wreg_open_key_wc(int pk, const wchar_t *keyname, int wr, dk4_er_t *erp)
{
#if DK4_ON_WINDOWS
dk4_wreg_key_t *back = NULL;
HKEY park = HKEY_LOCAL_MACHINE;
LONG res;
DWORD disp;
if (NULL != keyname) {
switch (pk) {
case DK4_WREGKEY_HKLM:
case DK4_WREGKEY_HKCU:
case DK4_WREGKEY_HKCL:
case DK4_WREGKEY_KHUS:
case DK4_WREGKEY_HKCC: {
switch (pk) {
case DK4_WREGKEY_HKLM: {
park = HKEY_LOCAL_MACHINE;
} break;
case DK4_WREGKEY_HKCU: {
park = HKEY_CURRENT_USER;
} break;
case DK4_WREGKEY_HKCL: {
park = HKEY_CLASSES_ROOT;
} break;
case DK4_WREGKEY_KHUS: {
park = HKEY_USERS;
} break;
case DK4_WREGKEY_HKCC: {
park = HKEY_CURRENT_CONFIG;
} break;
}
back = dk4mem_new(dk4_wreg_key_t,1,erp);
if (NULL != back) {
res = RegCreateKeyExW(
park,
keyname,
(DWORD)0,
NULL,
REG_OPTION_NON_VOLATILE,
((0 != wr) ? (KEY_ALL_ACCESS) : (KEY_READ)),
NULL,
&(back->hk),
&disp
);
if (ERROR_SUCCESS != res) {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
dk4mem_free(back);
back = NULL;
}
}
} break;
default: {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return ((void *)back);
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return NULL;
#endif
}
int
dk4wreg_set_string_wc(
void *kptr, const wchar_t *name, const wchar_t *val, int expand, dk4_er_t *erp
)
{
#if DK4_ON_WINDOWS
dk4_er_t er;
dk4_wreg_key_t *hptr;
int back = 0;
size_t lgt;
DWORD dwt = REG_SZ;
DWORD dw0 = (DWORD)0UL;
DWORD sz;
LONG res;
if ((NULL != kptr) && (NULL != val)) {
if (0 != expand) { dwt = REG_EXPAND_SZ; }
dk4error_init(&er);
lgt = dk4ma_size_t_add( 1, dk4strw_len(val), &er );
lgt = dk4ma_size_t_mul( 2, lgt, &er );
if (DK4_E_NONE == er.ec) {
if ((dk4_um_t)0x7FFFFFFFUL >= (dk4_um_t)lgt) {
sz = (DWORD)lgt;
hptr = (dk4_wreg_key_t *)kptr;
res = RegSetValueExW(
hptr->hk,
name,
dw0,
dwt,
(const BYTE *)val,
sz
);
if (ERROR_SUCCESS == res) {
back = 1;
} else {
dk4error_set_ldetails(erp, DK4_E_SYSTEM, res);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#endif
}
int
dk4wreg_get_string_wc(
void *kptr,
const wchar_t *name,
wchar_t *bptr,
size_t sz,
int *expand,
dk4_er_t *erp
)
{
#if DK4_ON_WINDOWS
dk4_er_t er;
dk4_wreg_key_t *hptr;
int back = 0;
DWORD dwt = REG_SZ;
DWORD dws;
DWORD dwsbck;
LONG res;
size_t rsz;
if ((NULL != bptr) && (0 < sz)) {
*bptr = '\0';
}
if ((NULL != kptr) && (NULL != name) && (NULL != bptr) && (0 < sz)) {
dk4error_init(&er);
rsz = dk4ma_size_t_mul(sz, 2, &er);
if (DK4_E_NONE == er.ec) {
if ((dk4_um_t)0x7FFFFFFFUL >= (dk4_um_t)rsz) {
dws = (DWORD)rsz;
} else {
dws = (DWORD)0x7FFFFFFFUL;
}
dwsbck = dws;
hptr = (dk4_wreg_key_t *)kptr;
res = RegQueryValueExW(
hptr->hk,
name,
NULL,
&dwt,
(LPBYTE)bptr,
&dws
);
if (ERROR_SUCCESS == res) {
switch (dwt) {
case REG_SZ: case REG_EXPAND_SZ: {
if ((DWORD)1L < dws) {
dws = dws / 2;
if (dws < sz) { /* dws is positive */
bptr[dws] = L'\0';
} else {
bptr[sz-1] = L'\0';
}
back = 1;
if (REG_EXPAND_SZ == dwt) {
if (NULL != expand) {
*expand = 1;
}
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} break;
default: {
/* ERROR: Not a string */
dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#endif
}
int
dk4wreg_set_dword_wc(
void *kptr, const wchar_t *name, dk4_dword_t val, dk4_er_t *erp
)
{
#if DK4_ON_WINDOWS
dk4_wreg_key_t *hptr;
int back = 0;
DWORD dwt = REG_DWORD;
DWORD dws = sizeof(DWORD);
DWORD dw0 = (DWORD)0L;
LONG res;
if (NULL != kptr) {
hptr = (dk4_wreg_key_t *)kptr;
res = RegSetValueExW(
hptr->hk,
name,
dw0,
dwt,
(const BYTE *)(&val),
dws
);
if (ERROR_SUCCESS == res) {
back = 1;
} else {
dk4error_set_ldetails(erp, DK4_E_SYSTEM, res);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#endif
}
int
dk4wreg_get_dword_wc(
void *kptr,
const wchar_t *name,
dk4_dword_t *vptr,
dk4_er_t *erp
)
{
#if DK4_ON_WINDOWS
dk4_wreg_key_t *hptr;
int back = 0;
DWORD dwt = REG_DWORD;
DWORD dws = (DWORD)sizeof(DWORD);
LONG res;
if ((NULL != kptr) && (NULL != vptr)) {
hptr = (dk4_wreg_key_t *)kptr;
res = RegQueryValueExW(
hptr->hk,
name,
NULL,
&dwt,
(LPBYTE)vptr,
&dws
);
if (ERROR_SUCCESS == res) {
if (REG_DWORD == dwt) {
if ((DWORD)sizeof(DWORD) == dws) {
back = 1;
} else {
dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#endif
}
int
dk4wreg_get_expanded_string_wc(
void *kptr,
const wchar_t *name,
wchar_t *dptr,
size_t dsz,
wchar_t *b1,
size_t b1sz,
wchar_t *b2,
size_t b2sz,
dk4_er_t *erp
)
{
#if DK4_ON_WINDOWS
DWORD dws;
DWORD nc;
int expand = 0;
int back = 0;
if ((NULL != dptr) && (0 < dsz)) { *dptr = L'\0'; }
if ((NULL != kptr) && (NULL != name) && (NULL != dptr) && (0 < dsz)) {
if ((NULL != b1) && (NULL != b2) && (0 < b1sz) && (2 < b2sz)) {
back = dk4wreg_get_string_wc(kptr, name, b1, b1sz, &expand, erp);
if (0 != back) {
if (0 != expand) { $? ". expansion"
if ((dk4_um_t)0x7FFFFFFFUL >= (dk4_um_t)b2sz) {
dws = (DWORD)b2sz; $? ". original size"
} else {
dws = 0x7FFFFFFFUL; $? ". cut size"
}
dws = dws - 2;
nc = ExpandEnvironmentStringsW(b1, b2, dws);
if ((0 < nc) && (nc <= dws)) { $? ". size ok"
back = dk4strw_cpy_s(dptr, dsz, b2, erp);
$!trace-code if (0 != back) {
$? ". result \"%ls\"", dptr
$!trace-code }
} else { $? "! wrong size"
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
}
} else { $? ". no expansion"
back = dk4strw_cpy_s(dptr, dsz, b1, erp);
$!trace-code if (0 != back) {
$? ". result \"%ls\"", dptr
$!trace-code }
}
} else { $? "! dk4wreg_get_string_wc"
}
} else { $? "! arguments"
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
} else { $? "! arguments"
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
#else
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#endif
}