r11073: safety checks on pointers to prevent crashing when converting REG_MULTI_SZ
[kai/samba.git] / source3 / registry / reg_util.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Virtual Windows Registry Layer (utility functions)
4  *  Copyright (C) Gerald Carter                     2002-2005
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *  
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *  
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 /* Implementation of registry frontend view functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /***********************************************************************
29  Utility function for splitting the base path of a registry path off
30  by setting base and new_path to the apprapriate offsets withing the
31  path.
32  
33  WARNING!!  Does modify the original string!
34  ***********************************************************************/
35
36 BOOL reg_split_path( char *path, char **base, char **new_path )
37 {
38         char *p;
39         
40         *new_path = *base = NULL;
41         
42         if ( !path)
43                 return False;
44         
45         *base = path;
46         
47         p = strchr( path, '\\' );
48         
49         if ( p ) {
50                 *p = '\0';
51                 *new_path = p+1;
52         }
53         
54         return True;
55 }
56
57
58 /***********************************************************************
59  Utility function for splitting the base path of a registry path off
60  by setting base and new_path to the appropriate offsets withing the
61  path.
62  
63  WARNING!!  Does modify the original string!
64  ***********************************************************************/
65
66 BOOL reg_split_key( char *path, char **base, char **key )
67 {
68         char *p;
69         
70         *key = *base = NULL;
71         
72         if ( !path)
73                 return False;
74         
75         *base = path;
76         
77         p = strrchr( path, '\\' );
78         
79         if ( p ) {
80                 *p = '\0';
81                 *key = p+1;
82         }
83         
84         return True;
85 }
86
87
88 /**********************************************************************
89  The full path to the registry key is used as database after the 
90  \'s are converted to /'s.  Key string is also normalized to UPPER
91  case. 
92 **********************************************************************/
93
94 void normalize_reg_path( pstring keyname )
95 {
96         pstring_sub( keyname, "\\", "/" );
97         strupper_m( keyname  );
98 }
99
100 /**********************************************************************
101  move to next non-delimter character
102 *********************************************************************/
103
104 char* reg_remaining_path( const char *key )
105 {
106         static pstring new_path;
107         char *p;
108         
109         if ( !key || !*key )
110                 return NULL;
111
112         pstrcpy( new_path, key );
113         /* normalize_reg_path( new_path ); */
114         
115         if ( !(p = strchr( new_path, '\\' )) ) 
116         {
117                 if ( !(p = strchr( new_path, '/' )) )
118                         p = new_path;
119                 else 
120                         p++;
121         }
122         else
123                 p++;
124                 
125         return p;
126 }
127
128 /**********************************************************************
129 *********************************************************************/
130
131 int regval_convert_multi_sz( uint16 *multi_string, size_t multi_len, char ***values )
132 {
133         char **sz;
134         int i;
135         int num_strings = 0;
136         fstring buffer;
137         uint16 *wp;
138         
139         *values = NULL;
140
141         if ( !multi_string || !*values )
142                 return 0;
143
144         /* just count the NULLs */
145         
146         for ( i=0; (i<multi_len-1) && !(multi_string[i]==0x0 && multi_string[i+1]==0x0); i++ ) {
147                 if ( multi_string[i] == 0x0 )
148                         num_strings++;
149         }
150         
151         if ( num_strings == 0 )
152                 return 0;
153         
154         if ( !(sz = TALLOC_ARRAY( NULL, char*, num_strings+1 )) ) {
155                 DEBUG(0,("reg_convert_multi_sz: talloc() failed!\n"));
156                 return -1;
157         }
158
159         wp = multi_string;
160         
161         for ( i=0; i<num_strings; i++ ) {
162                 rpcstr_pull( buffer, wp, sizeof(buffer), -1, STR_TERMINATE );
163                 sz[i] = talloc_strdup( sz, buffer );
164                 
165                 /* skip to the next string NULL and then one more */
166                 while ( *wp )
167                         wp++;
168                 wp++;
169         }
170         
171         /* tag the array off with an empty string */
172         sz[i] = '\0';
173         
174         *values = sz;
175         
176         return num_strings;
177 }
178
179 /**********************************************************************
180  Returns number of bytes, not number of unicode characters
181 *********************************************************************/
182
183 size_t regval_build_multi_sz( char **values, uint16 **buffer )
184 {
185         int i;
186         size_t buf_size = 0;
187         uint16 *buf, *b;
188         UNISTR2 sz;
189
190         if ( !values || !*buffer )
191                 return 0;
192         
193         /* go ahead and alloc some space */
194         
195         if ( !(buf = TALLOC_ARRAY( NULL, uint16, 2 )) ) {
196                 DEBUG(0,("regval_build_multi_sz: talloc() failed!\n"));
197                 return 0;
198         }
199         
200         for ( i=0; values[i]; i++ ) {
201                 ZERO_STRUCT( sz );
202                 
203                 init_unistr2( &sz, values[i], UNI_STR_TERMINATE );
204                 
205                 /* Alloc some more memory.  Always add one one to account for the 
206                    double NULL termination */
207                    
208                 b = TALLOC_REALLOC_ARRAY( NULL, buf, uint16, buf_size+sz.uni_str_len+1 );
209                 if ( !b ) {
210                         DEBUG(0,("regval_build_multi_sz: talloc() reallocation error!\n"));
211                         TALLOC_FREE( buffer );
212                         return 0;
213                 }
214                 buf = b;
215
216                 /* copy the unistring2 buffer and increment the size */ 
217                 
218                 memcpy( buf+buf_size, sz.buffer, sz.uni_str_len );
219                 buf_size += sz.uni_str_len;
220                 
221                 /* cleanup rather than leaving memory hanging around */
222                 TALLOC_FREE( sz.buffer );
223         }
224         
225         buf[buf_size++] = 0x0;
226
227         *buffer = buf;
228
229         /* return number of bytes */
230         return buf_size*2;
231 }
232
233
234
235
236
237