1 /*
2    Unix SMB/CIFS implementation.
3 
4    endpoint server for the winreg pipe
5 
6    Copyright (C) Jelmer Vernooij 2004
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "lib/registry/registry.h"
26 #include "librpc/gen_ndr/ndr_winreg.h"
27 #include "rpc_server/common/common.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 
30 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
31 
dcerpc_winreg_bind(struct dcesrv_call_state * dce_call,const struct dcesrv_interface * iface)32 static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface)
33 {
34 	struct registry_context *ctx;
35 	WERROR err;
36 
37 	err = reg_open_local(dce_call->context,
38 			     &ctx, dce_call->conn->auth_state.session_info, NULL);
39 
40 	dce_call->context->private = ctx;
41 
42 	return NT_STATUS_OK;
43 }
44 
45 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
46 
winreg_openhive(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,uint32_t hkey,struct policy_handle ** outh)47 static WERROR winreg_openhive (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, uint32_t hkey, struct policy_handle **outh)
48 {
49 	struct registry_context *ctx = dce_call->context->private;
50 	struct dcesrv_handle *h;
51 	WERROR error;
52 
53 	h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
54 
55 	error = reg_get_predefined_key(ctx, hkey, (struct registry_key **)&h->data);
56 	if (!W_ERROR_IS_OK(error)) {
57 		return error;
58 	}
59 
60 	*outh = &h->wire_handle;
61 
62 	return error;
63 }
64 
65 #define func_winreg_OpenHive(k,n) static WERROR winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
66 { \
67 	return winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
68 }
69 
func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)70 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
71 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
72 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
73 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
74 func_winreg_OpenHive(HKU,HKEY_USERS)
75 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
76 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
77 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
78 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
79 
80 /*
81   winreg_CloseKey
82 */
83 static WERROR winreg_CloseKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
84 			      struct winreg_CloseKey *r)
85 {
86 	struct dcesrv_handle *h;
87 
88 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
89 
90 	talloc_free(h);
91 
92 	ZERO_STRUCTP(r->out.handle);
93 
94 	return WERR_OK;
95 }
96 
97 
98 /*
99   winreg_CreateKey
100 */
winreg_CreateKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_CreateKey * r)101 static WERROR winreg_CreateKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
102 			       struct winreg_CreateKey *r)
103 {
104 	struct dcesrv_handle *h, *newh;
105 	WERROR error;
106 	struct security_descriptor sd;
107 
108 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
109 
110 	newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
111 
112 	/* the security descriptor is optional */
113 	if (r->in.secdesc != NULL) {
114 		DATA_BLOB sdblob;
115 		NTSTATUS status;
116 		sdblob.data = r->in.secdesc->sd.data;
117 		sdblob.length = r->in.secdesc->sd.len;
118 		if (sdblob.data == NULL) {
119 			return WERR_INVALID_PARAM;
120 		}
121 		status = ndr_pull_struct_blob_all(&sdblob, mem_ctx, &sd,
122 						  (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
123 		if (!NT_STATUS_IS_OK(status)) {
124 			return WERR_INVALID_PARAM;
125 		}
126 	}
127 
128 	error = reg_key_add_name(newh, (struct registry_key *)h->data, r->in.name.name,
129 				 r->in.access_mask,
130 				 r->in.secdesc?&sd:NULL,
131 				 (struct registry_key **)&newh->data);
132 	if (W_ERROR_IS_OK(error)) {
133 		r->out.new_handle = &newh->wire_handle;
134 	} else {
135 		talloc_free(newh);
136 	}
137 
138 	return error;
139 }
140 
141 
142 /*
143   winreg_DeleteKey
144 */
winreg_DeleteKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_DeleteKey * r)145 static WERROR winreg_DeleteKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
146 		       struct winreg_DeleteKey *r)
147 {
148 	struct dcesrv_handle *h;
149 
150 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
151 
152 	return reg_key_del((struct registry_key *)h->data, r->in.key.name);
153 }
154 
155 
156 /*
157   winreg_DeleteValue
158 */
winreg_DeleteValue(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_DeleteValue * r)159 static WERROR winreg_DeleteValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
160 		       struct winreg_DeleteValue *r)
161 {
162 	struct dcesrv_handle *h;
163 	struct registry_key *key;
164 
165 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
166 
167 	key = h->data;
168 
169 	return reg_del_value(key, r->in.value.name);
170 }
171 
172 
173 /*
174   winreg_EnumKey
175 */
winreg_EnumKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_EnumKey * r)176 static WERROR winreg_EnumKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
177 		       struct winreg_EnumKey *r)
178 {
179 	struct dcesrv_handle *h;
180 	struct registry_key *key;
181 
182 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
183 
184 	r->out.result = reg_key_get_subkey_by_index(mem_ctx, (struct registry_key *)h->data, r->in.enum_index, &key);
185 
186 	if (W_ERROR_IS_OK(r->out.result)) {
187 		if (2*strlen_m_term(key->name) > r->in.name->size) {
188 			return WERR_MORE_DATA;
189 		}
190 		r->out.name->length = 2*strlen_m_term(key->name);
191 		r->out.name->name = key->name;
192 		r->out.keyclass = talloc_zero(mem_ctx, struct winreg_StringBuf);
193 		if (r->in.last_changed_time) {
194 			r->out.last_changed_time = &key->last_mod;
195 		}
196 	}
197 
198 	return r->out.result;
199 }
200 
201 
202 /*
203   winreg_EnumValue
204 */
winreg_EnumValue(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_EnumValue * r)205 static WERROR winreg_EnumValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
206 			       struct winreg_EnumValue *r)
207 {
208 	struct dcesrv_handle *h;
209 	struct registry_key *key;
210 	struct registry_value *value;
211 	WERROR result;
212 
213 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
214 
215 	key = h->data;
216 
217 	result = reg_key_get_value_by_index(mem_ctx, key, r->in.enum_index, &value);
218 	if (!W_ERROR_IS_OK(result)) {
219 		return result;
220 	}
221 
222 	/* the client can optionally pass a NULL for type, meaning they don't
223 	   want that back */
224 	if (r->in.type != NULL) {
225 		r->out.type = talloc(mem_ctx, enum winreg_Type);
226 		*r->out.type = value->data_type;
227 	}
228 
229 	/* check the client has enough room for the value */
230 	if (r->in.value != NULL &&
231 	    r->in.size != NULL &&
232 	    value->data.length > *r->in.size) {
233 		return WERR_MORE_DATA;
234 	}
235 
236 	/* and enough room for the name */
237 	if (r->in.name->size < 2*strlen_m_term(value->name)) {
238 		return WERR_MORE_DATA;
239 	}
240 
241 	r->out.name->name = value->name;
242 	r->out.name->length = 2*strlen_m_term(value->name);
243 	r->out.name->size = 2*strlen_m_term(value->name);
244 
245 	if (r->in.value) {
246 		r->out.value = value->data.data;
247 	}
248 
249 	if (r->in.size) {
250 		r->out.size = talloc(mem_ctx, uint32_t);
251 		*r->out.size = value->data.length;
252 		r->out.length = r->out.size;
253 	}
254 
255 	return WERR_OK;
256 }
257 
258 
259 /*
260   winreg_FlushKey
261 */
winreg_FlushKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_FlushKey * r)262 static WERROR winreg_FlushKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
263 		       struct winreg_FlushKey *r)
264 {
265 	struct dcesrv_handle *h;
266 
267 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
268 
269 	return reg_key_flush(h->data);
270 }
271 
272 
273 /*
274   winreg_GetKeySecurity
275 */
winreg_GetKeySecurity(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_GetKeySecurity * r)276 static WERROR winreg_GetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
277 		       struct winreg_GetKeySecurity *r)
278 {
279 	struct dcesrv_handle *h;
280 
281 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
282 
283 	return WERR_NOT_SUPPORTED;
284 }
285 
286 
287 /*
288   winreg_LoadKey
289 */
winreg_LoadKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_LoadKey * r)290 static WERROR winreg_LoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
291 		       struct winreg_LoadKey *r)
292 {
293 	return WERR_NOT_SUPPORTED;
294 }
295 
296 
297 /*
298   winreg_NotifyChangeKeyValue
299 */
winreg_NotifyChangeKeyValue(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_NotifyChangeKeyValue * r)300 static WERROR winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
301 		       struct winreg_NotifyChangeKeyValue *r)
302 {
303 	return WERR_NOT_SUPPORTED;
304 }
305 
306 
307 /*
308   winreg_OpenKey
309 */
winreg_OpenKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_OpenKey * r)310 static WERROR winreg_OpenKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
311 		       struct winreg_OpenKey *r)
312 {
313 	struct dcesrv_handle *h, *newh;
314 	WERROR result;
315 
316 	DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
317 
318 	if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
319 		newh = talloc_reference(dce_call->context, h);
320 		result = WERR_OK;
321 	} else {
322 		newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
323 		result = reg_open_key(newh, (struct registry_key *)h->data,
324 				      r->in.keyname.name, (struct registry_key **)&newh->data);
325 	}
326 
327 	if (W_ERROR_IS_OK(result)) {
328 		r->out.handle = &newh->wire_handle;
329 	} else {
330 		talloc_free(newh);
331 	}
332 
333 	return result;
334 }
335 
336 
337 /*
338   winreg_QueryInfoKey
339 */
winreg_QueryInfoKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_QueryInfoKey * r)340 static WERROR winreg_QueryInfoKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
341 		       struct winreg_QueryInfoKey *r)
342 {
343 	struct dcesrv_handle *h;
344 	struct registry_key *k;
345 	WERROR ret;
346 
347 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
348 
349 	k = h->data;
350 
351 	ret = reg_key_num_subkeys(k, r->out.num_subkeys);
352 	if (!W_ERROR_IS_OK(ret)) {
353 		return ret;
354 	}
355 
356 	ret = reg_key_num_values(k, r->out.num_values);
357 	if (!W_ERROR_IS_OK(ret)) {
358 		return ret;
359 	}
360 
361 	ret = reg_key_subkeysizes(k, r->out.max_subkeysize, r->out.max_subkeylen);
362 	if (!W_ERROR_IS_OK(ret)) {
363 		return ret;
364 	}
365 
366 	ret = reg_key_valuesizes(k, r->out.max_valnamelen, r->out.max_valbufsize);
367 	if (!W_ERROR_IS_OK(ret)) {
368 		return ret;
369 	}
370 
371 	r->out.secdescsize = 0; /* FIXME */
372 	ZERO_STRUCT(r->out.last_changed_time); /* FIXME */
373 	if (!W_ERROR_IS_OK(ret)) {
374 		return ret;
375 	}
376 
377 
378 	return WERR_OK;
379 }
380 
381 
382 /*
383   winreg_QueryValue
384 */
winreg_QueryValue(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_QueryValue * r)385 static WERROR winreg_QueryValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
386 		       struct winreg_QueryValue *r)
387 {
388 	struct dcesrv_handle *h;
389 	struct registry_key *key;
390 	struct registry_value *val;
391 	WERROR result;
392 
393 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
394 
395 	key = h->data;
396 
397 	result = reg_key_get_value_by_name(mem_ctx, key, r->in.value_name.name, &val);
398 
399 	if (!W_ERROR_IS_OK(result)) {
400 		return result;
401 	}
402 
403 	/* Just asking for the size of the buffer */
404 	r->out.type = (enum winreg_Type *)&val->data_type;
405 	r->out.length = talloc(mem_ctx, uint32_t);
406 	if (!r->out.length) {
407 		return WERR_NOMEM;
408 	}
409 	*r->out.length = val->data.length;
410 	if (!r->in.data) {
411 		r->out.size = talloc(mem_ctx, uint32_t);
412 		*r->out.size = val->data.length;
413 	} else {
414 		r->out.size = r->in.size;
415 		r->out.data = val->data.data;
416 	}
417 
418 	return WERR_OK;
419 }
420 
421 
422 /*
423   winreg_ReplaceKey
424 */
winreg_ReplaceKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_ReplaceKey * r)425 static WERROR winreg_ReplaceKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
426 		       struct winreg_ReplaceKey *r)
427 {
428 	return WERR_NOT_SUPPORTED;
429 }
430 
431 
432 /*
433   winreg_RestoreKey
434 */
winreg_RestoreKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_RestoreKey * r)435 static WERROR winreg_RestoreKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
436 		       struct winreg_RestoreKey *r)
437 {
438 	return WERR_NOT_SUPPORTED;
439 }
440 
441 
442 /*
443   winreg_SaveKey
444 */
winreg_SaveKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_SaveKey * r)445 static WERROR winreg_SaveKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
446 		       struct winreg_SaveKey *r)
447 {
448 	return WERR_NOT_SUPPORTED;
449 }
450 
451 
452 /*
453   winreg_SetKeySecurity
454 */
winreg_SetKeySecurity(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_SetKeySecurity * r)455 static WERROR winreg_SetKeySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
456 		       struct winreg_SetKeySecurity *r)
457 {
458 	return WERR_NOT_SUPPORTED;
459 }
460 
461 
462 /*
463   winreg_SetValue
464 */
winreg_SetValue(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_SetValue * r)465 static WERROR winreg_SetValue(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
466 		       struct winreg_SetValue *r)
467 {
468 	struct dcesrv_handle *h;
469 	struct registry_key *key;
470 	WERROR result;
471 	DATA_BLOB data;
472 
473 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
474 
475 	key = h->data;
476 
477 	data.data = r->in.data;
478 	data.length = r->in.size;
479 	result = reg_val_set(key, r->in.name.name, r->in.type, data);
480 
481 	if (!W_ERROR_IS_OK(result)) {
482 		return result;
483 	}
484 
485 	return WERR_OK;
486 }
487 
488 
489 /*
490   winreg_UnLoadKey
491 */
winreg_UnLoadKey(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_UnLoadKey * r)492 static WERROR winreg_UnLoadKey(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
493 		       struct winreg_UnLoadKey *r)
494 {
495 	return WERR_NOT_SUPPORTED;
496 }
497 
498 
499 /*
500   winreg_InitiateSystemShutdown
501 */
winreg_InitiateSystemShutdown(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_InitiateSystemShutdown * r)502 static WERROR winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
503 		       struct winreg_InitiateSystemShutdown *r)
504 {
505 	return WERR_NOT_SUPPORTED;
506 }
507 
508 
509 /*
510   winreg_AbortSystemShutdown
511 */
winreg_AbortSystemShutdown(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_AbortSystemShutdown * r)512 static WERROR winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
513 		       struct winreg_AbortSystemShutdown *r)
514 {
515 	return WERR_NOT_SUPPORTED;
516 }
517 
518 
519 /*
520   winreg_GetVersion
521 */
winreg_GetVersion(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_GetVersion * r)522 static WERROR winreg_GetVersion(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
523 				struct winreg_GetVersion *r)
524 {
525 	struct dcesrv_handle *h;
526 
527 	DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
528 
529 	r->out.version = talloc(mem_ctx, uint32_t);
530 	W_ERROR_HAVE_NO_MEMORY(r->out.version);
531 
532 	*r->out.version = 5;
533 
534 	return WERR_OK;
535 }
536 
537 
538 /*
539   winreg_QueryMultipleValues
540 */
winreg_QueryMultipleValues(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_QueryMultipleValues * r)541 static WERROR winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
542 		       struct winreg_QueryMultipleValues *r)
543 {
544 	return WERR_NOT_SUPPORTED;
545 }
546 
547 
548 /*
549   winreg_InitiateSystemShutdownEx
550 */
winreg_InitiateSystemShutdownEx(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_InitiateSystemShutdownEx * r)551 static WERROR winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
552 		       struct winreg_InitiateSystemShutdownEx *r)
553 {
554 	return WERR_NOT_SUPPORTED;
555 }
556 
557 
558 /*
559   winreg_SaveKeyEx
560 */
winreg_SaveKeyEx(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_SaveKeyEx * r)561 static WERROR winreg_SaveKeyEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
562 		       struct winreg_SaveKeyEx *r)
563 {
564 	return WERR_NOT_SUPPORTED;
565 }
566 
567 
568 /*
569   winreg_QueryMultipleValues2
570 */
winreg_QueryMultipleValues2(struct dcesrv_call_state * dce_call,TALLOC_CTX * mem_ctx,struct winreg_QueryMultipleValues2 * r)571 static WERROR winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
572 		       struct winreg_QueryMultipleValues2 *r)
573 {
574 	return WERR_NOT_SUPPORTED;
575 }
576 
577 
578 /* include the generated boilerplate */
579 #include "librpc/gen_ndr/ndr_winreg_s.c"
580