2007-06-14 15:29:35 +04:00
/*
* Unix SMB / CIFS implementation .
* Registry helper routines
* Copyright ( C ) Volker Lendecke 2006
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
2007-07-09 23:25:36 +04:00
* Software Foundation ; either version 3 of the License , or ( at your option )
2007-06-14 15:29:35 +04:00
* any later version .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
* more details .
*
* You should have received a copy of the GNU General Public License along with
2007-07-10 09:23:25 +04:00
* this program ; if not , see < http : //www.gnu.org/licenses/>.
2007-06-14 15:29:35 +04:00
*/
# include "includes.h"
WERROR registry_pull_value ( TALLOC_CTX * mem_ctx ,
struct registry_value * * pvalue ,
enum winreg_Type type , uint8 * data ,
uint32 size , uint32 length )
{
struct registry_value * value ;
WERROR err ;
if ( ! ( value = TALLOC_ZERO_P ( mem_ctx , struct registry_value ) ) ) {
return WERR_NOMEM ;
}
value - > type = type ;
switch ( type ) {
case REG_DWORD :
if ( ( size ! = 4 ) | | ( length ! = 4 ) ) {
err = WERR_INVALID_PARAM ;
goto error ;
}
value - > v . dword = IVAL ( data , 0 ) ;
break ;
case REG_SZ :
case REG_EXPAND_SZ :
{
/*
* Make sure we get a NULL terminated string for
* convert_string_talloc ( ) .
*/
smb_ucs2_t * tmp ;
2007-07-01 03:52:23 +04:00
if ( length = = 1 ) {
/* win2k regedit gives us a string of 1 byte when
* creating a new value of type REG_SZ . this workaround
* replaces the input by using the same string as
* winxp delivers . */
length = 2 ;
if ( ! ( tmp = SMB_MALLOC_ARRAY ( smb_ucs2_t , 2 ) ) ) {
err = WERR_NOMEM ;
goto error ;
}
2007-08-22 01:55:51 +04:00
tmp [ 0 ] = 0 ;
2007-07-01 03:52:23 +04:00
tmp [ 1 ] = 0 ;
2007-08-22 01:57:58 +04:00
DEBUG ( 10 , ( " got REG_SZ value of length 1 - workaround "
" activated. \n " ) ) ;
2007-07-01 03:52:23 +04:00
}
else if ( ( length % 2 ) ! = 0 ) {
2007-06-14 15:29:35 +04:00
err = WERR_INVALID_PARAM ;
goto error ;
}
2007-07-01 03:52:23 +04:00
else {
2007-07-01 04:09:20 +04:00
uint32 num_ucs2 = length / 2 ;
2007-07-01 03:52:23 +04:00
if ( ! ( tmp = SMB_MALLOC_ARRAY ( smb_ucs2_t , num_ucs2 + 1 ) ) ) {
err = WERR_NOMEM ;
goto error ;
}
2007-06-14 15:29:35 +04:00
2007-07-01 03:52:23 +04:00
memcpy ( ( void * ) tmp , ( const void * ) data , length ) ;
tmp [ num_ucs2 ] = 0 ;
2007-06-14 15:29:35 +04:00
}
2007-07-03 00:51:09 +04:00
if ( length + 2 < length ) {
/* Integer wrap. */
2007-07-09 11:55:09 +04:00
SAFE_FREE ( tmp ) ;
2007-07-03 00:51:09 +04:00
err = WERR_INVALID_PARAM ;
goto error ;
}
2007-06-14 15:29:35 +04:00
value - > v . sz . len = convert_string_talloc (
value , CH_UTF16LE , CH_UNIX , tmp , length + 2 ,
& value - > v . sz . str , False ) ;
SAFE_FREE ( tmp ) ;
if ( value - > v . sz . len = = ( size_t ) - 1 ) {
err = WERR_INVALID_PARAM ;
goto error ;
}
break ;
}
case REG_MULTI_SZ :
err = reg_pull_multi_sz ( value , ( void * ) data , length ,
& value - > v . multi_sz . num_strings ,
& value - > v . multi_sz . strings ) ;
if ( ! ( W_ERROR_IS_OK ( err ) ) ) {
goto error ;
}
break ;
case REG_BINARY :
2007-07-24 13:42:15 +04:00
value - > v . binary = data_blob_talloc ( mem_ctx , data , length ) ;
2007-06-14 15:29:35 +04:00
break ;
default :
err = WERR_INVALID_PARAM ;
goto error ;
}
* pvalue = value ;
return WERR_OK ;
error :
TALLOC_FREE ( value ) ;
return err ;
}
WERROR registry_push_value ( TALLOC_CTX * mem_ctx ,
const struct registry_value * value ,
DATA_BLOB * presult )
{
switch ( value - > type ) {
case REG_DWORD : {
char buf [ 4 ] ;
SIVAL ( buf , 0 , value - > v . dword ) ;
* presult = data_blob_talloc ( mem_ctx , ( void * ) buf , 4 ) ;
if ( presult - > data = = NULL ) {
return WERR_NOMEM ;
}
break ;
}
case REG_SZ :
case REG_EXPAND_SZ : {
presult - > length = convert_string_talloc (
mem_ctx , CH_UNIX , CH_UTF16LE , value - > v . sz . str ,
MIN ( value - > v . sz . len , strlen ( value - > v . sz . str ) + 1 ) ,
( void * ) & ( presult - > data ) , False ) ;
if ( presult - > length = = ( size_t ) - 1 ) {
return WERR_NOMEM ;
}
break ;
}
2007-07-24 13:42:15 +04:00
case REG_BINARY :
* presult = data_blob_talloc ( mem_ctx ,
value - > v . binary . data ,
value - > v . binary . length ) ;
break ;
2007-06-14 15:29:35 +04:00
default :
return WERR_INVALID_PARAM ;
}
return WERR_OK ;
}