diff --git a/src/modules/system/nt.c b/src/modules/system/nt.c index 2fb8834329fd119c4764701cf8f343356967ca42..eed2cbc9edf14283d429eaba54db932e61bf4bdc 100644 --- a/src/modules/system/nt.c +++ b/src/modules/system/nt.c @@ -1,5 +1,5 @@ /* - * $Id: nt.c,v 1.17 2000/01/10 00:43:12 hubbe Exp $ + * $Id: nt.c,v 1.18 2000/06/29 00:13:01 hubbe Exp $ * * NT system calls for Pike * @@ -38,6 +38,61 @@ static void f_cp(INT32 args) push_int(ret); } +static void push_tchar(TCHAR *buf, DWORD len) +{ + push_string(make_shared_binary_pcharp( + MKPCHARP(buf,my_log2(sizeof(TCHAR))),len)); +} + +static void push_regvalue(DWORD type, char* buffer, DWORD len) +{ + switch(type) + { + case REG_RESOURCE_LIST: + case REG_NONE: + case REG_LINK: + case REG_BINARY: + push_string(make_shared_binary_string(buffer,len)); + break; + + case REG_SZ: + push_string(make_shared_binary_string(buffer,len-1)); + break; + + case REG_EXPAND_SZ: + type=ExpandEnvironmentStrings((LPCTSTR)buffer, + buffer+len, + sizeof(buffer)-len-1); + if(type>sizeof(buffer)-len-1 || !type) + error("RegGetValue: Failed to expand data.\n"); + push_string(make_shared_string(buffer+len)); + break; + + case REG_MULTI_SZ: + push_string(make_shared_binary_string(buffer,len-1)); + push_string(make_shared_binary_string("\000",1)); + f_divide(2); + break; + + case REG_DWORD_LITTLE_ENDIAN: + push_int(EXTRACT_UCHAR(buffer)+ + (EXTRACT_UCHAR(buffer+1)<<1)+ + (EXTRACT_UCHAR(buffer+2)<<2)+ + (EXTRACT_UCHAR(buffer+3)<<3)); + break; + + case REG_DWORD_BIG_ENDIAN: + push_int(EXTRACT_UCHAR(buffer+3)+ + (EXTRACT_UCHAR(buffer+2)<<1)+ + (EXTRACT_UCHAR(buffer+1)<<2)+ + (EXTRACT_UCHAR(buffer)<<3)); + break; + + default: + error("RegGetValue: cannot handle this data type.\n"); + } +} + void f_RegGetValue(INT32 args) { long ret; @@ -58,54 +113,106 @@ void f_RegGetValue(INT32 args) if(ret==ERROR_SUCCESS) { pop_n_elems(args); - switch(type) + push_regvalue(type, buffer, len); + }else{ + error("RegQueryValueEx failed with error %d\n",ret); + } +} + +static void do_regclosekey(HKEY key) +{ + RegCloseKey(key); +} + +void f_RegGetKeyNames(INT32 args) +{ + INT32 hkey; + char *key; + int i,ret; + HKEY new_key; + ONERROR tmp; + get_all_args("RegGetKeyNames",args,"%d%s",&hkey,&key); + ret=RegOpenKeyEx((HKEY)hkey, (LPCTSTR)key, 0, KEY_READ, &new_key); + if(ret != ERROR_SUCCESS) + error("RegOpenKeyEx failed with error %d\n",ret); + + SET_ONERROR(tmp, do_regclosekey, new_key); + + pop_n_elems(args); + + for(i=0;;i++) + { + TCHAR buf[1024]; + DWORD len=sizeof(buf)-1; + FILETIME tmp2; + THREADS_ALLOW(); + ret=RegEnumKeyEx(new_key, i, buf, &len, 0,0,0, &tmp2); + THREADS_DISALLOW(); + switch(ret) { - case REG_RESOURCE_LIST: - case REG_NONE: - case REG_LINK: - case REG_BINARY: - push_string(make_shared_binary_string(buffer,len)); + case ERROR_SUCCESS: + check_stack(1); + push_tchar(buf,len); + continue; + + case ERROR_NO_MORE_ITEMS: break; + + default: + error("RegEnumKeyEx failed with error %d\n",ret); + } + break; + } + CALL_AND_UNSET_ONERROR(tmp); + f_aggregate(i); +} - case REG_SZ: - push_string(make_shared_binary_string(buffer,len-1)); - break; +void f_RegGetValues(INT32 args) +{ + INT32 hkey; + char *key; + int i,ret; + HKEY new_key; + ONERROR tmp; - case REG_EXPAND_SZ: - type=ExpandEnvironmentStrings((LPCTSTR)buffer, - buffer+len, - sizeof(buffer)-len-1); - if(type>sizeof(buffer)-len-1 || !type) - error("RegGetValue: Failed to expand data.\n"); - push_string(make_shared_string(buffer+len)); - break; + get_all_args("RegGetValues",args,"%d%s",&hkey,&key); + ret=RegOpenKeyEx((HKEY)hkey, (LPCTSTR)key, 0, KEY_READ, &new_key); + if(ret != ERROR_SUCCESS) + error("RegOpenKeyEx failed with error %d\n",ret); - case REG_MULTI_SZ: - push_string(make_shared_binary_string(buffer,len-1)); - push_string(make_shared_binary_string("\000",1)); - f_divide(2); - break; + SET_ONERROR(tmp, do_regclosekey, new_key); + pop_n_elems(args); - case REG_DWORD_LITTLE_ENDIAN: - push_int(EXTRACT_UCHAR(buffer)+ - (EXTRACT_UCHAR(buffer+1)<<1)+ - (EXTRACT_UCHAR(buffer+2)<<2)+ - (EXTRACT_UCHAR(buffer+3)<<3)); - break; + for(i=0;;i++) + { + TCHAR buf[1024]; + char buffer[8192]; + DWORD len=sizeof(buf)-1; + DWORD buflen=sizeof(buffer)-1; + DWORD type; - case REG_DWORD_BIG_ENDIAN: - push_int(EXTRACT_UCHAR(buffer+3)+ - (EXTRACT_UCHAR(buffer+2)<<1)+ - (EXTRACT_UCHAR(buffer+1)<<2)+ - (EXTRACT_UCHAR(buffer)<<3)); + THREADS_ALLOW(); + ret=RegEnumValue(new_key, i, buf, &len, 0,&type, buffer, &buflen); + THREADS_DISALLOW(); + switch(ret) + { + case ERROR_SUCCESS: + check_stack(2); + push_tchar(buf,len); + push_regvalue(type,buffer,buflen); + continue; + + case ERROR_NO_MORE_ITEMS: break; - + default: - error("RegGetValue: cannot handle this data type.\n"); + RegCloseKey(new_key); + error("RegEnumKeyEx failed with error %d\n",ret); } - }else{ - error("RegQueryValueEx failed with error %d\n",ret); + break; } + CALL_AND_UNSET_ONERROR(tmp); + f_aggregate_mapping(i*2); } static struct program *token_program; @@ -2130,6 +2237,10 @@ void init_nt_system_calls(void) /* function(int,string,string:string|int|string*) */ ADD_EFUN("RegGetValue",f_RegGetValue,tFunc(tInt tStr tStr,tOr3(tStr,tInt,tArr(tStr))),OPT_EXTERNAL_DEPEND); + ADD_EFUN("RegGetValues",f_RegGetValues,tFunc(tInt tStr,tMap(tStr,tOr3(tStr,tInt,tArr(tStr)))),OPT_EXTERNAL_DEPEND); + + ADD_EFUN("RegGetKeyNames",f_RegGetKeyNames,tFunc(tInt tStr,tArr(tStr)),OPT_EXTERNAL_DEPEND); + /* LogonUser only exists on NT, link it dynamically */ if(advapilib=LoadLibrary("advapi32"))