Re: Saving configs (was: Nexus v2)
- Posted by euman at bellsouth.net Nov 01, 2002
- 419 views
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... -- 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.