%% options copyright owner = Dirk Krause copyright year = 2013-2014 license = bsd %% header #include #if DK3_ON_WINDOWS && ((2 == DK3_CHAR_SIZE) || (1 == DK3_CHAR_SIZE)) #ifdef __cplusplus extern "C" { #endif /** Open registry key for access as specified. @param b Base key. @param n Key name. @param p Required access permissions. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_open_perms( HKEY b, dkChar const *n, REGSAM p, HKEY *r, dk3_app_t *app ); /** Open registry key for read-only access. @param b Base key. @param n Key name. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_open_read(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app); /** Open registry key for modification. @param b Base key. @param n Key name. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_open_modify(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app); /** Open registry key for access as specified, create if necessary. @param b Base key. @param n Key name. @param p Permissions for access. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_create_perms( HKEY b,dkChar const *n,REGSAM p,HKEY *r,dk3_app_t *app ); /** Open registry key for read-only access, create if necessary. @param b Base key. @param n Key name. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_create_read(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app); /** Open registry key for modification, create if necessary. @param b Base key. @param n Key name. @param r Pointer to result variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_create_modify(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app); /** Close registry key. @param k Key to close. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_close(HKEY k, dkChar const *n, dk3_app_t *app); /** Remove registry key including all contents. @param b Base key. @param n Key name. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_key_delete(HKEY b, dkChar const *n, dk3_app_t *app); /** Set REG_EXPAND_SZ entry. @param k Registry key. @param n Entry name. @param v Value. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_set_sz(HKEY k, dkChar const *n, dkChar const *v, dk3_app_t *app); /** Set REG_EXPAND_SZ entry. @param k Registry key. @param n Entry name. @param v Value. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_set_expand_sz(HKEY k, dkChar const *n, dkChar const *v, dk3_app_t *app); /** Set DWORD entry. @param k Registry key. @param n Entry name. @param v Value to set. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_set_dword(HKEY k, dkChar const *n, DWORD v, dk3_app_t *app); /** Get string entry (REG_EXPAND_SZ or REG_SZ). @param k Registry key. @param n Entry name. @param b Pointer to result buffer. @param s Result buffer size (number of dkChar). @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_get_sz(HKEY k, dkChar const *n, dkChar *b, size_t s, dk3_app_t *app); /** Get string entry (REG_EXPAND_SZ or REG_SZ), save type. @param k Registry key. @param n Entry name. @param b Pointer to result buffer. @param s Result buffer size (number of dkChar). @param e Pointer to type variable. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_get_expand_sz( HKEY k, dkChar const *n, dkChar *b, size_t s, DWORD *e, dk3_app_t *app ); /** Get string entry, expand if necessary. @param k Registry key. @param n Entry name. @param dp Destination buffer. @param ds Destination buffer size (number of dkChar). @param tp Temporary buffer for unexpanded string. @param ts Size of temporary buffer (number of dkChar). @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_get_expanded_sz( HKEY k, dkChar const * n, dkChar *dp, size_t ds, dkChar *tp, size_t ts, dk3_app_t *app ); /** Get DWORD registry entry. @param k Registry key. @param n Entry name. @param b Pointer to result buffer. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_get_dword(HKEY k, dkChar const *n, DWORD *b, dk3_app_t *app); /** Delete registry entry. @param k Registry key. @param n Entry name. @param app Application structure for diagnostics, may be NULL. @return 1 on success, 0 on error. */ int dk3wreg_entry_delete(HKEY k, dkChar const *n, dk3_app_t *app); #ifdef __cplusplus } #endif #else #endif %% module #include "dk3all.h" #include "dk3wreg.h" #if DK3_ON_WINDOWS && ((2 == DK3_CHAR_SIZE) || (1 == DK3_CHAR_SIZE)) static dkChar const * const dk3wreg_default_texts[] = { $!string-table file=dk3wreg.str,macro=dkT # # 0 # dk3wreg.str # # 1 # Failed to open registry key! # # 2, 3 # Failed to open registry key:\n" "! # # 4, 5, 6 # Failed to open or create registry key! Failed to open or create registry key:\n" "! # # 7, 8, 9 # Failed to close registry key! Failed to close registry key:\n" "! # # 10, 11, 12 # Failed to write registry entry! Failed to write registry entry:\n" "! # # 13, 14, 15 # Failed to retrieve registry entry! Failed to retrieve registry entry:\n" "! # # 16, 17, 18 # Registry entry is not a string! Registry entry is not a string:\n" "! # # 19, 20, 21 # Registry entry is not a DWORD! Registry entry is not a DWORD:\n" "! # # 22, 23, 24 # Registry entry is an incomplete DWORD! Registry entry is an incomplete DWORD:\n" "! # # 25, 26, 27 # Failed to delete registry key tree! Failed to delete registry key tree:\n" "! # # 28, 29, 30 # Failed to delete registry entry! Failed to delete registry entry:\n" "! # # 31 # String to long for result buffer! # # 32 # Environment variable expansion failed! # # 33 # Can not delete registry keys when compiled for legacy versions! $!end }; static void dk3wreg_report_error( dk3_app_t *app, dkChar const *n, size_t m1, size_t m2, size_t o ) { dkChar const * const *lmsg; /* Localized messages. */ $? "+ dk3wreg_report_error" if(app) { lmsg = dk3app_messages( app, dk3wreg_default_texts[0], (dkChar const **)dk3wreg_default_texts ); if(lmsg) { if(n) { dk3app_log_3(app, DK3_LL_ERROR, lmsg, m1, m2, n); } else { dk3app_log_1(app, DK3_LL_ERROR, lmsg, o); } } } $? "- dk3wreg_report_error" } int dk3wreg_key_open_perms( HKEY b, dkChar const *n, REGSAM p, HKEY *r, dk3_app_t *app ) { int back = 0; long res; $? "+ dk3wreg_key_open_perms \"%s\"", TR_STR(n) if((n) && (r)) { #if 2 == DK3_CHAR_SIZE res = RegOpenKeyExW( b, /* Base key. */ n, /* Subkey name. */ (DWORD)0UL, /* Reserviced. */ p, /* Required access. */ r /* Result pointer. */ ); #else res = RegOpenKeyExA( b, /* Base key. */ n, /* Subkey name. */ (DWORD)0UL, /* Reserviced. */ p, /* Required access. */ r /* Result pointer. */ ); #endif if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to open key! */ dk3wreg_report_error(app, n, 2, 3, 1); } } $? "- dk3wreg_key_open_perms %d", back return back; } int dk3wreg_key_open_read(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app) { int back = 0; $? "+ dk3wreg_key_open_read \"%s\"", TR_STR(n) back = dk3wreg_key_open_perms(b, n, KEY_QUERY_VALUE, r, app); $? "- dk3wreg_key_open_read %d", back return back; } int dk3wreg_key_open_modify(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app) { int back = 0; $? "+ dk3wreg_key_open_modify \"%s\"", TR_STR(n) back = dk3wreg_key_open_perms(b, n, KEY_ALL_ACCESS, r, app); $? "- dk3wreg_key_open_modify %d", back return back; } int dk3wreg_key_create_perms(HKEY b,dkChar const *n,REGSAM p,HKEY *r,dk3_app_t *app) { int back = 0; long res; DWORD disp = (DWORD)0UL; $? "+ dk3wreg_key_create_perms \"%s\"", TR_STR(n) if((n) && (r)) { #if 2 == DK3_CHAR_SIZE res = RegCreateKeyExW( b, /* Base key. */ n, /* Key name. */ (DWORD)0UL, /* Reserved. */ NULL, /* Key class. */ REG_OPTION_NON_VOLATILE, /* Options. */ p, /* SAM desired. */ NULL, /* Security descriptor. */ r, /* Result pointer. */ &disp /* Disposition. */ ); #else res = RegCreateKeyExA( b, /* Base key. */ n, /* Key name. */ (DWORD)0UL, /* Reserved. */ NULL, /* Key class. */ REG_OPTION_NON_VOLATILE, /* Options. */ p, /* SAM desired. */ NULL, /* Security descriptor. */ r, /* Result pointer. */ &disp /* Disposition. */ ); #endif if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to open/create registry key! */ dk3wreg_report_error(app, n, 5, 6, 4); } } $? "- dk3wreg_key_create_perms %d", back return back; } int dk3wreg_key_create_read(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app) { int back = 0; $? "+ dk3wreg_key_create_read \"%s\"", TR_STR(n) back = dk3wreg_key_create_perms(b, n, KEY_QUERY_VALUE, r, app); $? "- dk3wreg_key_create_read %d", back return back; } int dk3wreg_key_create_modify(HKEY b, dkChar const *n, HKEY *r, dk3_app_t *app) { int back = 0; $? "+ dk3wreg_key_create_modify \"%s\"", TR_STR(n) back = dk3wreg_key_create_perms(b, n, KEY_ALL_ACCESS, r, app); $? "- dk3wreg_key_create_modify %d", back return back; } int dk3wreg_key_close(HKEY k, dkChar const *n, dk3_app_t *app) { int back = 0; long res; $? "+ dk3wreg_key_close" res = RegCloseKey(k); if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to close registry key!. */ dk3wreg_report_error(app, n, 8, 9, 7); } $? "- dk3wreg_key_close %d", back return back; } int dk3wreg_key_delete(HKEY b, dkChar const *n, dk3_app_t *app) { int back = 0; #if _MSC_VER >= 1700 long res; $? "+ dk3wreg_key_delete \"%s\"", TR_STR(n) if(n) { #if 2 == DK3_CHAR_SIZE res = RegDeleteTreeW(b, n); #else res = RegDeleteTreeA(b, n); #endif if(ERROR_SUCCESS == res) { back = 1; } else { dk3wreg_report_error(app, n, 26, 27, 25); } } $? "- dk3wreg_key_delete %d", back #else dk3wreg_report_error(app, n, 26, 27, 25); dk3wreg_report_error(app, NULL, 0, 0, 33); #endif return back; } int dk3wreg_set_sz(HKEY k, dkChar const *n, dkChar const *v, dk3_app_t *app) { int back = 0; DWORD dwt = REG_SZ; DWORD dw0 = (DWORD)0UL; DWORD sz; long res; $? "+ dk3wreg_set_sz \"%s\"=\"%s\"", TR_STR(n), TR_STR(v) if(v) { sz = (DWORD)(1 + dk3str_len(v)); sz *= DK3_CHAR_SIZE; #if 2 == DK3_CHAR_SIZE res = RegSetValueExW( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)v, /* Data. */ sz /* Number of bytes. */ ); #else res = RegSetValueExA( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)v, /* Data. */ sz /* Number of bytes. */ ); #endif if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to save registry entry. */ dk3wreg_report_error(app, n, 11, 12, 10); } } $? "- dk3wreg_set_sz %d", back return back; } int dk3wreg_set_expand_sz(HKEY k, dkChar const *n, dkChar const *v, dk3_app_t *app) { int back = 0; DWORD dwt = REG_EXPAND_SZ; DWORD dw0 = (DWORD)0UL; DWORD sz; long res; $? "+ dk3wreg_set_expand_sz \"%s\"=\"%s\"", TR_STR(n), TR_STR(v) if(v) { sz = (DWORD)(1 + dk3str_len(v)); sz *= DK3_CHAR_SIZE; #if 2 == DK3_CHAR_SIZE res = RegSetValueExW( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)v, /* Data. */ sz /* Number of bytes. */ ); #else res = RegSetValueExA( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)v, /* Data. */ sz /* Number of bytes. */ ); #endif if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to save registry entry. */ dk3wreg_report_error(app, n, 11, 12, 10); } } $? "- dk3wreg_set_expand_sz %d", back return back; } int dk3wreg_set_dword(HKEY k, dkChar const *n, DWORD v, dk3_app_t *app) { int back = 0; DWORD dwt = REG_DWORD; DWORD dw0 = (DWORD)0UL; DWORD sz; long res; $? "+ dk3wreg_set_dword \"%s\" %lx", TR_STR(n), (unsigned long)v if((n) && (v)) { sz = (DWORD)sizeof(DWORD); #if 2 == DK3_CHAR_SIZE res = RegSetValueExW( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)(&v), /* Data. */ sz /* Number of bytes. */ ); #else res = RegSetValueExA( k, /* Key. */ n, /* Entry name. */ dw0, /* Reserved. */ dwt, /* Type. */ (const BYTE *)(&v), /* Data. */ sz /* Number of bytes. */ ); #endif if(ERROR_SUCCESS == res) { back = 1; } else { /* ERROR: Failed to save registry entry. */ dk3wreg_report_error(app, n, 11, 12, 10); } } $? "- dk3wreg_set_dword %d", back return back; } int dk3wreg_get_expand_sz( HKEY k, dkChar const *n, dkChar *b, size_t s, DWORD *e, dk3_app_t *app ) { int back = 0; DWORD dwt = REG_SZ; DWORD dws; long res; $? "+ dk3wreg_get_expand_sz \"%s\"", TR_STR(n) if((b) && (s)) { dws = (DWORD)(s * DK3_CHAR_SIZE); #if 2 == DK3_CHAR_SIZE res = RegQueryValueExW( k, /* Key. */ n, /* Entry name. */ NULL, /* Reserved. */ &dwt, /* Type. */ (BYTE *)b, /* Result buffer. */ &dws /* Size (number of bytes). */ ); #else res = RegQueryValueExA( k, /* Key. */ n, /* Entry name. */ NULL, /* Reserved. */ &dwt, /* Type. */ (BYTE *)b, /* Result buffer. */ &dws /* Size (number of bytes). */ ); #endif if(ERROR_SUCCESS == res) { switch(dwt) { case REG_SZ: case REG_EXPAND_SZ: { if(e) { *e = dwt; } back = 1; if(0UL < dws) { #if 1 < DK3_CHAR_SIZE dws = dws / DK3_CHAR_SIZE; #endif if(0UL < dws) { if(dws < (DWORD)s) { b[dws] = dkT('\0'); } else { b[s - 1] = dkT('\0'); } } else { *b = dkT('\0'); } } else { *b = dkT('\0'); } } break; default: { *b = dkT('\0'); /* ERROR: Not a string value! */ dk3wreg_report_error(app, n, 17, 18, 16); } break; } } else { *b = dkT('\0'); /* ERROR: Failed to retrieve value! */ dk3wreg_report_error(app, n, 14, 15, 13); } } $!trace-code if(back) { $? ". text = \"%s\"", b $!trace-code } $? "- dk3wreg_get_expand_sz %d", back return back; } int dk3wreg_get_sz(HKEY k, dkChar const *n, dkChar *b, size_t s, dk3_app_t *app) { int back = 0; $? "+ dk3wreg_get_sz \"%s\"", TR_STR(n) back = dk3wreg_get_expand_sz(k, n, b, s, NULL, app); $? "- dk3wreg_get_sz %d", back return back; } int dk3wreg_get_expanded_sz( HKEY k, dkChar const * n, dkChar *dp, size_t ds, dkChar *tp, size_t ts, dk3_app_t *app ) { DWORD fe; /* Flag: Expand. */ DWORD res; /* Result from expand function. */ int back = 0; $? "+ dk3wreg_get_expanded_sz \"%s\"", TR_STR(n) if((n) && (dp) && (ds) && (tp) && (ts)) { dp[0] = dkT('\0'); fe = REG_SZ; if(dk3wreg_get_expand_sz(k, n, tp, ts, &fe, app)) { if(REG_EXPAND_SZ == fe) { res = ExpandEnvironmentStrings(tp, dp, (DWORD)ds); if(0 < res) { if((size_t)res < ds) { back = 1; } else { /* ERROR: String too long for final buffer! */ dk3wreg_report_error(app, NULL, 0, 0, 31); } } else { /* ERROR: Expansion failed! */ dk3wreg_report_error(app, NULL, 0, 0, 32); } } else { if(dk3str_len(tp) < ds) { dk3str_cpy(dp, tp); back = 1; } else { /* ERROR: String too long for final buffer! */ dk3wreg_report_error(app, NULL, 0, 0, 31); } } } } $!trace-code if(back) { $? ". text = \"%s\"", dp $!trace-code } $? "- dk3wreg_get_expanded_sz %d", back return back; } int dk3wreg_get_dword(HKEY k, dkChar const *n, DWORD *b, dk3_app_t *app) { int back = 0; DWORD dwt = REG_DWORD; DWORD dws; DWORD dwres; long res; $? "+ dk3wreg_get_dword \"%s\"", TR_STR(n) if((n) && (b)) { dws = (DWORD)sizeof(DWORD); dwres = (DWORD)0UL; #if 2 == DK3_CHAR_SIZE res = RegQueryValueExW( k, n, NULL, &dwt, (BYTE *)(&dwres), &dws ); #else res = RegQueryValueExA( k, n, NULL, &dwt, (BYTE *)(&dwres), &dws ); #endif if(ERROR_SUCCESS == res) { switch(dwt) { case REG_DWORD: { if((DWORD)sizeof(DWORD) == dws) { *b = dwres; back = 1; } else { /* ERROR: Incomplete value! */ dk3wreg_report_error(app, n, 23, 24, 22); } } break; default: { /* ERROR: Not a DWORD entry! */ dk3wreg_report_error(app, n, 20, 21, 19); } break; } } else { /* ERROR: Failed to retrieve value! */ dk3wreg_report_error(app, n, 14, 15, 13); } } $? "- dk3wreg_get_dword %d %lx", back, (unsigned long)dwres return back; } int dk3wreg_entry_delete(HKEY k, dkChar const *n, dk3_app_t *app) { int back = 0; long res; $? "+ dk3wreg_entry_delete \"%s\"", TR_STR(n) if(n) { #if 2 == DK3_CHAR_SIZE res = RegDeleteValueW(k, n); #else res = RegDeleteValueA(k, n); #endif if(ERROR_SUCCESS == res) { back = 1; } else { dk3wreg_report_error(app, n, 29, 30, 28); } } $? "- dk3wreg_entry_delete %d", back return back; } #else #endif