Initial import
[samba] / source / 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 byte_len, char ***values )
132 {
133         char **sz;
134         int i;
135         int num_strings = 0;
136         fstring buffer;
137         uint16 *wp;
138         size_t multi_len = byte_len / 2;
139         
140         if ( !multi_string || !values )
141                 return 0;
142
143         *values = NULL;
144
145         /* just count the NULLs */
146         
147         for ( i=0; (i<multi_len-1) && !(multi_string[i]==0x0 && multi_string[i+1]==0x0); i++ ) {
148                 /* peek ahead */
149                 if ( multi_string[i+1] == 0x0 )
150                         num_strings++;
151         }
152
153         if ( num_strings == 0 )
154                 return 0;
155         
156         if ( !(sz = TALLOC_ARRAY( NULL, char*, num_strings+1 )) ) {
157                 DEBUG(0,("reg_convert_multi_sz: talloc() failed!\n"));
158                 return -1;
159         }
160
161         wp = multi_string;
162         
163         for ( i=0; i<num_strings; i++ ) {
164                 rpcstr_pull( buffer, wp, sizeof(buffer), -1, STR_TERMINATE );
165                 sz[i] = talloc_strdup( sz, buffer );
166                 
167                 /* skip to the next string NULL and then one more */
168                 while ( *wp )
169                         wp++;
170                 wp++;
171         }
172         
173         /* tag the array off with an empty string */
174         sz[i] = '\0';
175         
176         *values = sz;
177         
178         return num_strings;
179 }
180
181 /**********************************************************************
182  Returns number of bytes, not number of unicode characters
183 *********************************************************************/
184
185 size_t regval_build_multi_sz( char **values, uint16 **buffer )
186 {
187         int i;
188         size_t buf_size = 0;
189         uint16 *buf, *b;
190         UNISTR2 sz;
191
192         if ( !values || !buffer )
193                 return 0;
194         
195         /* go ahead and alloc some space */
196         
197         if ( !(buf = TALLOC_ARRAY( NULL, uint16, 2 )) ) {
198                 DEBUG(0,("regval_build_multi_sz: talloc() failed!\n"));
199                 return 0;
200         }
201         
202         for ( i=0; values[i]; i++ ) {
203                 ZERO_STRUCT( sz );
204                 /* DEBUG(0,("regval_build_multi_sz: building [%s]\n",values[i])); */
205                 init_unistr2( &sz, values[i], UNI_STR_TERMINATE );
206                 
207                 /* Alloc some more memory.  Always add one one to account for the 
208                    double NULL termination */
209                    
210                 b = TALLOC_REALLOC_ARRAY( NULL, buf, uint16, buf_size+sz.uni_str_len+1 );
211                 if ( !b ) {
212                         DEBUG(0,("regval_build_multi_sz: talloc() reallocation error!\n"));
213                         TALLOC_FREE( buffer );
214                         return 0;
215                 }
216                 buf = b;
217
218                 /* copy the unistring2 buffer and increment the size */ 
219                 /* dump_data(1,sz.buffer,sz.uni_str_len*2); */
220                 memcpy( buf+buf_size, sz.buffer, sz.uni_str_len*2 );
221                 buf_size += sz.uni_str_len;
222                 
223                 /* cleanup rather than leaving memory hanging around */
224                 TALLOC_FREE( sz.buffer );
225         }
226         
227         buf[buf_size++] = 0x0;
228
229         *buffer = buf;
230
231         /* return number of bytes */
232         return buf_size*2;
233 }
234
235