Re: Saving configs (was: Nexus v2)

new topic     » goto parent     » topic index » view thread      » older message » newer message

Hey, mind my stepping in on the conversation?

The registry set/get is the same as far as I can tell by the MS-SDK
but Jonas is right about their being security features in 2k,NT,XP

Below I have some registry code that is untested on 2000 Pro, NT, XP
perhaps someone might be interested (maybe even you,  Don) if it
works well enough, that is.......

[Never submitted, Untested and "possibly buggy" code ahead, BEWARE]

<snip here>
-- Registry Code (Create/Delete Key only!) by Euman 2002
-- perhaps I'll actually write the rest of the wrappers someday.

with type_check
without warning

include machine.e
include dll.e
include msgbox.e

atom kernel32, advapi32
kernel32 = open_dll("kernel32.dll")
advapi32=open_dll("advapi32.dll")

constant
  xRegCreateKeyEx =
define_c_func(advapi32,"RegCreateKeyExA",{C_LONG,C_POINTER,C_LONG,C_POINTER,
C_LONG,C_LONG,C_POINTER,C_POINTER,C_POINTER},C_LONG)
  ,xRegSetValueEx =
define_c_func(advapi32,"RegSetValueExA",{C_LONG,C_POINTER,C_LONG,C_LONG,C_IN
T,C_LONG},C_INT)
  ,xRegQueryValueEx =
define_c_func(advapi32,"RegQueryValueExA",{C_LONG,C_POINTER,C_POINTER,C_POIN
TER,C_POINTER,C_POINTER},C_INT)
  ,xRegCloseKey = define_c_proc(advapi32,"RegCloseKey",{C_LONG})
  ,xRegDeleteKey =
define_c_func(advapi32,"RegDeleteKeyA",{C_LONG,C_POINTER},C_LONG)
  ,xRegDeleteValue =
define_c_func(advapi32,"RegDeleteValueA",{C_LONG,C_POINTER},C_LONG)
  ,xRegEnumKeyEx =
define_c_func(advapi32,"RegEnumKeyExA",{C_LONG,C_LONG,C_POINTER,C_POINTER,C_
LONG,C_POINTER,C_POINTER,C_POINTER},C_LONG)
  ,xRegEnumValueA =
define_c_func(advapi32,"RegEnumValueA",{C_LONG,C_LONG,C_POINTER,C_POINTER,C_
LONG,C_POINTER,C_POINTER,C_POINTER},C_LONG)
  ,xlstrlen = define_c_func(kernel32,"lstrlen",{C_POINTER},C_INT)

object junk

global function or_all(sequence s)
  -- or together all elements of a sequence
  atom result

  result = 0
  for i = 1 to length(s) do
    result = or_bits(result, s[i])
  end for
  return result
end function

procedure warning(sequence message)
  junk=message_box(message,"Error",MB_ICONERROR)
end procedure

constant
  ERROR_NONE = 0,
  ERROR_BADDB = 1,
  ERROR_BADKEY = 2,
  ERROR_CANTOPEN = 3,
  ERROR_CANTREAD = 4,
  ERROR_CANTWRITE = 5,
  ERROR_OUTOFMEMORY = 6,
  ERROR_ARENA_TRASHED = 7,
  ERROR_ACCESS_DENIED = 8,
  ERROR_INVALID_PARAMETERS = 87,
  ERROR_MORE_DATA = 234,
  ERROR_NO_MORE_ITEMS = 259

function reg_check(integer junk)
  if junk=ERROR_BADDB then warning("ERROR_BADDB") return 0
  elsif junk=ERROR_BADKEY then warning("ERROR_BADKEY") return 0
  elsif junk=ERROR_CANTOPEN then warning("ERROR_CANTOPEN") return 0
  elsif junk=ERROR_CANTREAD then warning("ERROR_CANTREAD") return 0
  elsif junk=ERROR_CANTWRITE then warning("ERROR_CANTWRITE") return 0
  elsif junk=ERROR_OUTOFMEMORY then warning("ERROR_OUTOFMEMORY") return 0
  elsif junk=ERROR_ARENA_TRASHED then warning("ERROR_ARENA_TRASHED") return
0
  elsif junk=ERROR_ACCESS_DENIED then warning("ERROR_ACCESS_DENIED") return
0
  elsif junk=ERROR_INVALID_PARAMETERS then
warning("ERROR_INVALID_PARAMETERS") return 0
  elsif junk=ERROR_MORE_DATA then warning("ERROR_MORE_DATA") return 0
  elsif junk=ERROR_NO_MORE_ITEMS then warning("ERROR_NO_MORE_ITEMS") return
0
  else
  return 1
  end if
end function

constant
  HKEY_CLASSES_ROOT = #80000000,
  HKEY_CURRENT_USER = #80000001,
  HKEY_LOCAL_MACHINE = #80000002,
  HKEY_USERS = #80000003,
  HKEY_CURRENT_CONFIG = #80000005,
  HKEY_DYN_DATA = #80000006

constant
  REG_CREATED_NEW_KEY = 1,
  REG_OPTION_NON_VOLATILE = 0,
  STANDARD_RIGHTS_ALL = #1F0000,
  STANDARD_RIGHTS_REQUIRED = #F0000,
  KEY_QUERY_VALUE = #1,
  KEY_SET_VALUE = #2,
  KEY_CREATE_SUB_KEY = #4,
  KEY_ENUMERATE_SUB_KEYS = #8,
  KEY_NOTIFY = #10,
  KEY_CREATE_LINK = #20,
  KEY_ALL_ACCESS = or_all({STANDARD_RIGHTS_REQUIRED, KEY_QUERY_VALUE,
  KEY_SET_VALUE,KEY_CREATE_SUB_KEY,KEY_ENUMERATE_SUB_KEYS,KEY_NOTIFY,
  KEY_CREATE_LINK})

constant
  REG_SZ = 1,
  REG_BINARY = 3,
  REG_DWORD = 4

function text_to_binary(sequence text)
    sequence binary
    binary = {}
    for i = 1 to length(text) do
        binary &= int_to_bits(text[i], 8)
    end for
    return binary
end function

function binary_to_text(sequence binary)
    sequence text
    text = {}
    for i = 1 to length(binary) by 8 do
        text &= bits_to_int(binary[i..i+7])
    end for
    return text
end function

object vNameptr, vDataptr, data_len

function Process_vName(object vName)
  if sequence(vName) then
    vNameptr = allocate_string(vName)
  else
    vNameptr = allocate(4)
    mem_set(vNameptr,0,4)
    poke4(vNameptr, vName)
  end if
  return vNameptr
end function

function Process_vData(object vData, integer rtype)
  if rtype = REG_SZ then
    vDataptr = allocate_string(vData)
  elsif rtype = REG_BINARY then
    vDataptr = allocate_string(binary_to_text(vData))
  else
    vDataptr = allocate(4)
    poke4(vDataptr, vData)
  end if
  return vDataptr
end function

procedure CreateRegKey(atom hkey, sequence key, sequence Data)
-- This routine will create your Name, Value pair regardless if
-- the key/subkey exist. This will be usefull for many projects.
  atom keyptr, nullptr, hRegKey, result
  integer regtype
  object vName, vData, binary
  sequence sdata

    keyptr = allocate_string(key)
    nullptr = allocate_string("")
    hRegKey = allocate(4)
    result = allocate(4)

    if c_func(xRegCreateKeyEx,{hkey, keyptr, 0, nullptr, 0, KEY_ALL_ACCESS,
0, hRegKey, result}) = 0 then
      if peek4u(result) =  REG_CREATED_NEW_KEY then
        for i = 1 to length(Data) do
          sdata = Data[i]
          vNameptr = Process_vName(sdata[1])
          regtype  = sdata[2]
          vDataptr = Process_vData(sdata[3], regtype)
          data_len = c_func(xlstrlen,{vDataptr}) + 1
          junk = c_func(xRegSetValueEx,{peek4u(hRegKey), vNameptr, 0,
regtype, vDataptr, data_len})
          free(vNameptr)
          free(vDataptr)
        end for
     else -- Key exist, now check for Name, Value pair.
        for i = 1 to length(Data) do
          sdata = Data[i]
          vNameptr = Process_vName(sdata[1])
          regtype  = allocate(4)
          vDataptr = Process_vData(sdata[3], sdata[2])
          data_len = allocate(4)
          poke4(data_len, c_func(xlstrlen,{vDataptr}) + 1)
          junk = c_func(xRegQueryValueEx,{peek4u(hRegKey), vNameptr, 0,
regtype, vDataptr, data_len})
          if junk = 2 then -- Name, Value pair doesnt exist, create them.
            regtype  = sdata[2]
            data_len = c_func(xlstrlen,{vDataptr}) + 1
            junk = c_func(xRegSetValueEx,{peek4u(hRegKey), vNameptr, 0,
regtype, vDataptr, data_len})
          else
            free(regtype)
            free(data_len)
          end if
            free(vNameptr)
            free(vDataptr)
        end for
      end if
    c_proc(xRegCloseKey,{peek4u(hRegKey)})
    end if
end procedure

function DeleteRegKey(atom hkey, sequence subkey)
  atom keyptr
    keyptr = allocate_string(subkey)
    junk = c_func(xRegDeleteKey,{hkey,keyptr})
    free(keyptr)
    return reg_check(junk)
end function

-- A Couple of examples commented out, be extra carefull de/uncommenting...
blink
-- Run the demo uncommenting 1) first then comment out 1) and run with 2)

-- 1) Create and write
                                              -- sequence of Name, Type,
Value
--CreateRegKey(HKEY_CURRENT_USER, "Environment",
--                                              {{"EUDIR", REG_SZ,
"Euphoria"},
--                                               {"PATH", REG_SZ,
"Euphoria\\BIN"},
--                                               {"112", REG_BINARY,
text_to_binary("Euman")}
--                                              })

-- 2) Delete what we just wrote

--junk = DeleteRegKey(HKEY_CURRENT_USER, "Environment")

<de/unsnip here>

The Euman


----- Original Message -----
From: "Don Phillips" <EuNexus at yahoo.com>

> > Personally, I don't like saving preferences in the Registry, and I
> > always feel threatened by programs that do.  For one, it makes the
> > program harder to uninstall.  For another, there's always the danger of
> > trashing your OS if the PC dies in the middle of a registry write.
> > While the danger is small, it does exist.  A separate config file stored
> > in the same directory as the executable removes these two constraints.
> > My preference is an INI file.  It makes it easier for the user to make
> > config changes outside the program if necessary.  It also makes it
> > easier to change configurations for different users.  The format is
> > extensible for newer versions of your program, and it is readily
> > understood by most advanced users and developers.  There is also an INI
> > library already in the archives, although I haven't used it myself (I
> > have my own routine that I adapt to each program).  Lastly, an INI file
> > is much more portable than registry keys are, including across different
> > versions of Windows.
> >
> > Just my ½ cent (inflation, ya know...),
> > Mike Sabal
>
> Mike:
> I am in the same boat as you mike.  I personally think that the registry
> is over used and often times abused.  However, in this case I thought it
> was the right thing to do.  As many may or may not know, the Toolbar
> control has built in functions to save/ restore its position on
> application close/ open respectively.  This was the first thing I added
> to Nexus via direct API calls.  It turns out the built in functions
> write to the registry under a key given by the program.  I figured that
> as long as I was already using a key in the registry for the Toolbar
> (does not give a choice), I might as well place my other settings there
> as well.
>
> Jonas:
> Ahh, 2k Pro.  My dev machine at home is a 98 box.  I have a 2k box at
> work and during my down time I will see what I can do.  I am sure there
> is a flag or setting I am not using.  Have to take another peek at my
> API references.  Good call Jonas.

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu