LCOV - code coverage report
Current view: top level - source3/rpc_server/winreg - srv_winreg_nt.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 231 444 52.0 %
Date: 2024-04-21 15:09:00 Functions: 23 40 57.5 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  RPC Pipe client / server routines
       4             :  *
       5             :  *  Copyright (C) Gerald Carter                 2002-2006.
       6             :  *
       7             :  *  This program is free software; you can redistribute it and/or modify
       8             :  *  it under the terms of the GNU General Public License as published by
       9             :  *  the Free Software Foundation; either version 3 of the License, or
      10             :  *  (at your option) any later version.
      11             :  *
      12             :  *  This program is distributed in the hope that it will be useful,
      13             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  *  GNU General Public License for more details.
      16             :  *
      17             :  *  You should have received a copy of the GNU General Public License
      18             :  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : /* Implementation of registry functions. */
      22             : 
      23             : #include "includes.h"
      24             : #include "ntdomain.h"
      25             : #include "librpc/rpc/dcesrv_core.h"
      26             : #include "librpc/gen_ndr/ndr_winreg.h"
      27             : #include "librpc/gen_ndr/ndr_winreg_scompat.h"
      28             : #include "registry.h"
      29             : #include "registry/reg_api.h"
      30             : #include "registry/reg_perfcount.h"
      31             : #include "rpc_misc.h"
      32             : #include "auth.h"
      33             : #include "lib/privileges.h"
      34             : #include "libcli/security/secdesc.h"
      35             : 
      36             : #undef DBGC_CLASS
      37             : #define DBGC_CLASS DBGC_RPC_SRV
      38             : 
      39             : enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
      40             : 
      41             : /******************************************************************
      42             :  Find a registry key handle and return a struct registry_key *
      43             :  *****************************************************************/
      44             : 
      45      485458 : static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
      46             :                                                struct policy_handle *hnd,
      47             :                                                enum handle_types type)
      48             : {
      49      485458 :         struct registry_key *regkey = NULL;
      50           0 :         NTSTATUS status;
      51             : 
      52      485458 :         regkey = find_policy_by_hnd(p,
      53             :                                     hnd,
      54             :                                     type,
      55             :                                     struct registry_key,
      56           0 :                                     &status);
      57      485458 :         if (!NT_STATUS_IS_OK(status)) {
      58          46 :                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: %s\n",
      59             :                          nt_errstr(status)));
      60          46 :                 return NULL;
      61             :         }
      62             : 
      63      485412 :         return regkey;
      64             : }
      65             : 
      66             : /*******************************************************************
      67             :  Function for open a new registry handle and creating a handle
      68             :  Note that P should be valid & hnd should already have space
      69             : 
      70             :  When we open a key, we store the full path to the key as
      71             :  HK[LM|U]\<key>\<key>\...
      72             :  *******************************************************************/
      73             : 
      74       86934 : static WERROR open_registry_key(struct pipes_struct *p,
      75             :                                 struct policy_handle *hnd,
      76             :                                 struct registry_key *parent,
      77             :                                 const char *subkeyname,
      78             :                                 uint32_t access_desired)
      79             : {
      80       86934 :         struct dcesrv_call_state *dce_call = p->dce_call;
      81           0 :         struct auth_session_info *session_info =
      82       86934 :                 dcesrv_call_session_info(dce_call);
      83       86934 :         WERROR result = WERR_OK;
      84           0 :         struct registry_key *key;
      85             : 
      86       86934 :         if (parent == NULL) {
      87       44538 :                 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
      88       44538 :                                       session_info->security_token, &key);
      89             :         }
      90             :         else {
      91       42396 :                 result = reg_openkey(p->mem_ctx, parent, subkeyname,
      92             :                                      access_desired, &key);
      93             :         }
      94             : 
      95       86934 :         if ( !W_ERROR_IS_OK(result) ) {
      96        2038 :                 return result;
      97             :         }
      98             : 
      99       84896 :         if ( !create_policy_hnd( p, hnd, HTYPE_REGKEY, key ) ) {
     100           0 :                 return WERR_FILE_NOT_FOUND;
     101             :         }
     102             : 
     103       84896 :         return WERR_OK;
     104             : }
     105             : 
     106             : /*******************************************************************
     107             :  Function for open a new registry handle and creating a handle
     108             :  Note that P should be valid & hnd should already have space
     109             :  *******************************************************************/
     110             : 
     111       90497 : static bool close_registry_key(struct pipes_struct *p,
     112             :                                struct policy_handle *hnd,
     113             :                                enum handle_types type)
     114             : {
     115       90497 :         struct registry_key *regkey = find_regkey_by_hnd(p, hnd, type);
     116             : 
     117       90497 :         if ( !regkey ) {
     118          46 :                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
     119             :                          OUR_HANDLE(hnd)));
     120          46 :                 return False;
     121             :         }
     122             : 
     123       90451 :         close_policy_hnd(p, hnd);
     124             : 
     125       90451 :         return True;
     126             : }
     127             : 
     128             : /********************************************************************
     129             :  _winreg_CloseKey
     130             :  ********************************************************************/
     131             : 
     132       90497 : WERROR _winreg_CloseKey(struct pipes_struct *p,
     133             :                         struct winreg_CloseKey *r)
     134             : {
     135           0 :         bool ok;
     136             : 
     137             :         /* close the policy handle */
     138             : 
     139       90497 :         ok = close_registry_key(p, r->in.handle, HTYPE_REGKEY);
     140       90497 :         if (!ok) {
     141          46 :                 return WERR_INVALID_HANDLE;
     142             :         }
     143             : 
     144       90451 :         ZERO_STRUCTP(r->out.handle);
     145             : 
     146       90451 :         return WERR_OK;
     147             : }
     148             : 
     149             : /*******************************************************************
     150             :  _winreg_OpenHKLM
     151             :  ********************************************************************/
     152             : 
     153       44517 : WERROR _winreg_OpenHKLM(struct pipes_struct *p,
     154             :                         struct winreg_OpenHKLM *r)
     155             : {
     156       44517 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
     157             : }
     158             : 
     159             : /*******************************************************************
     160             :  _winreg_OpenHKPD
     161             :  ********************************************************************/
     162             : 
     163           0 : WERROR _winreg_OpenHKPD(struct pipes_struct *p,
     164             :                         struct winreg_OpenHKPD *r)
     165             : {
     166           0 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
     167             : }
     168             : 
     169             : /*******************************************************************
     170             :  _winreg_OpenHKPT
     171             :  ********************************************************************/
     172             : 
     173           0 : WERROR _winreg_OpenHKPT(struct pipes_struct *p,
     174             :                         struct winreg_OpenHKPT *r)
     175             : {
     176           0 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
     177             : }
     178             : 
     179             : /*******************************************************************
     180             :  _winreg_OpenHKCR
     181             :  ********************************************************************/
     182             : 
     183           7 : WERROR _winreg_OpenHKCR(struct pipes_struct *p,
     184             :                         struct winreg_OpenHKCR *r)
     185             : {
     186           7 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
     187             : }
     188             : 
     189             : /*******************************************************************
     190             :  _winreg_OpenHKU
     191             :  ********************************************************************/
     192             : 
     193           7 : WERROR _winreg_OpenHKU(struct pipes_struct *p,
     194             :                        struct winreg_OpenHKU *r)
     195             : {
     196           7 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
     197             : }
     198             : 
     199             : /*******************************************************************
     200             :  _winreg_OpenHKCU
     201             :  ********************************************************************/
     202             : 
     203           7 : WERROR _winreg_OpenHKCU(struct pipes_struct *p,
     204             :                         struct winreg_OpenHKCU *r)
     205             : {
     206           7 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
     207             : }
     208             : 
     209             : /*******************************************************************
     210             :  _winreg_OpenHKCC
     211             :  ********************************************************************/
     212             : 
     213           0 : WERROR _winreg_OpenHKCC(struct pipes_struct *p,
     214             :                         struct winreg_OpenHKCC *r)
     215             : {
     216           0 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
     217             : }
     218             : 
     219             : /*******************************************************************
     220             :  _winreg_OpenHKDD
     221             :  ********************************************************************/
     222             : 
     223           0 : WERROR _winreg_OpenHKDD(struct pipes_struct *p,
     224             :                         struct winreg_OpenHKDD *r)
     225             : {
     226           0 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
     227             : }
     228             : 
     229             : /*******************************************************************
     230             :  _winreg_OpenHKPN
     231             :  ********************************************************************/
     232             : 
     233           0 : WERROR _winreg_OpenHKPN(struct pipes_struct *p,
     234             :                         struct winreg_OpenHKPN *r)
     235             : {
     236           0 :         return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
     237             : }
     238             : 
     239             : /*******************************************************************
     240             :  _winreg_OpenKey
     241             :  ********************************************************************/
     242             : 
     243       42396 : WERROR _winreg_OpenKey(struct pipes_struct *p,
     244             :                        struct winreg_OpenKey *r)
     245             : {
     246       42396 :         struct registry_key *parent = find_regkey_by_hnd(p,
     247             :                                                          r->in.parent_handle,
     248             :                                                          HTYPE_REGKEY);
     249             : 
     250       42396 :         if ( !parent )
     251           0 :                 return WERR_INVALID_HANDLE;
     252             : 
     253       42396 :         return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
     254             : }
     255             : 
     256             : /*******************************************************************
     257             :  _winreg_QueryValue
     258             :  ********************************************************************/
     259             : 
     260       46514 : WERROR _winreg_QueryValue(struct pipes_struct *p,
     261             :                           struct winreg_QueryValue *r)
     262             : {
     263       46514 :         WERROR        status = WERR_FILE_NOT_FOUND;
     264       46514 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     265             :                                                          r->in.handle,
     266             :                                                          HTYPE_REGKEY);
     267           0 :         prs_struct    prs_hkpd;
     268             : 
     269       46514 :         uint8_t *outbuf = NULL;
     270       46514 :         uint32_t outbuf_size = 0;
     271             : 
     272       46514 :         bool free_buf = False;
     273       46514 :         bool free_prs = False;
     274             : 
     275       46514 :         if ( !regkey )
     276           0 :                 return WERR_INVALID_HANDLE;
     277             : 
     278       46514 :         if (r->in.value_name->name == NULL) {
     279         196 :                 return WERR_INVALID_PARAMETER;
     280             :         }
     281             : 
     282       46318 :         if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
     283         441 :                 return WERR_INVALID_PARAMETER;
     284             :         }
     285             : 
     286       45877 :         DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
     287       45877 :         DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
     288             : 
     289             :         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
     290       45877 :         if(regkey->key->type == REG_KEY_HKPD)
     291             :         {
     292           0 :                 if (strequal(r->in.value_name->name, "Global")) {
     293           0 :                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
     294           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     295           0 :                         status = reg_perfcount_get_hkpd(
     296           0 :                                 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
     297           0 :                         outbuf = (uint8_t *)prs_hkpd.data_p;
     298           0 :                         free_prs = True;
     299             :                 }
     300           0 :                 else if (strequal(r->in.value_name->name, "Counter 009")) {
     301           0 :                         outbuf_size = reg_perfcount_get_counter_names(
     302             :                                 reg_perfcount_get_base_index(),
     303             :                                 (char **)(void *)&outbuf);
     304           0 :                         free_buf = True;
     305             :                 }
     306           0 :                 else if (strequal(r->in.value_name->name, "Explain 009")) {
     307           0 :                         outbuf_size = reg_perfcount_get_counter_help(
     308             :                                 reg_perfcount_get_base_index(),
     309             :                                 (char **)(void *)&outbuf);
     310           0 :                         free_buf = True;
     311             :                 }
     312           0 :                 else if (isdigit(r->in.value_name->name[0])) {
     313             :                         /* we probably have a request for a specific object
     314             :                          * here */
     315           0 :                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
     316           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     317           0 :                         status = reg_perfcount_get_hkpd(
     318           0 :                                 &prs_hkpd, *r->in.data_size, &outbuf_size,
     319           0 :                                 r->in.value_name->name);
     320           0 :                         outbuf = (uint8_t *)prs_hkpd.data_p;
     321           0 :                         free_prs = True;
     322             :                 }
     323             :                 else {
     324           0 :                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
     325             :                                  r->in.value_name->name));
     326           0 :                         return WERR_FILE_NOT_FOUND;
     327             :                 }
     328             : 
     329           0 :                 *r->out.type = REG_BINARY;
     330             :         }
     331             :         else {
     332           0 :                 struct registry_value *val;
     333             : 
     334       45877 :                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
     335             :                                         &val);
     336       45877 :                 if (!W_ERROR_IS_OK(status)) {
     337             : 
     338        7722 :                         DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
     339             :                                 win_errstr(status)));
     340             : 
     341        7722 :                         if (r->out.data_size) {
     342        7722 :                                 *r->out.data_size = 0;
     343             :                         }
     344        7722 :                         if (r->out.data_length) {
     345        7722 :                                 *r->out.data_length = 0;
     346             :                         }
     347        7722 :                         return status;
     348             :                 }
     349             : 
     350       38155 :                 outbuf = val->data.data;
     351       38155 :                 outbuf_size = val->data.length;
     352       38155 :                 *r->out.type = val->type;
     353             :         }
     354             : 
     355       38155 :         status = WERR_FILE_NOT_FOUND;
     356             : 
     357       38155 :         if (*r->in.data_size < outbuf_size) {
     358       19066 :                 *r->out.data_size = outbuf_size;
     359       19066 :                 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
     360             :         } else {
     361       19089 :                 *r->out.data_length = outbuf_size;
     362       19089 :                 *r->out.data_size = outbuf_size;
     363       19089 :                 if (r->out.data) {
     364       19053 :                         memcpy(r->out.data, outbuf, outbuf_size);
     365             :                 }
     366       19089 :                 status = WERR_OK;
     367             :         }
     368             : 
     369       38155 :         if (free_prs) prs_mem_free(&prs_hkpd);
     370       38155 :         if (free_buf) SAFE_FREE(outbuf);
     371             : 
     372       38155 :         return status;
     373             : }
     374             : 
     375             : /*****************************************************************************
     376             :  _winreg_QueryInfoKey
     377             :  ****************************************************************************/
     378             : 
     379       20374 : WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
     380             :                             struct winreg_QueryInfoKey *r)
     381             : {
     382       20374 :         WERROR  status = WERR_OK;
     383       20374 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     384             :                                                          r->in.handle,
     385             :                                                          HTYPE_REGKEY);
     386             : 
     387       20374 :         if ( !regkey )
     388           0 :                 return WERR_INVALID_HANDLE;
     389             : 
     390       20374 :         r->out.classname->name = NULL;
     391             : 
     392       20374 :         status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
     393             :                                   r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
     394             :                                   r->out.max_valbufsize, r->out.secdescsize,
     395             :                                   r->out.last_changed_time);
     396       20374 :         if (!W_ERROR_IS_OK(status)) {
     397           0 :                 return status;
     398             :         }
     399             : 
     400             :         /*
     401             :          * These calculations account for the registry buffers being
     402             :          * UTF-16. They are inexact at best, but so far they worked.
     403             :          */
     404             : 
     405       20374 :         *r->out.max_subkeylen *= 2;
     406             : 
     407       20374 :         *r->out.max_valnamelen += 1;
     408       20374 :         *r->out.max_valnamelen *= 2;
     409             : 
     410       20374 :         return WERR_OK;
     411             : }
     412             : 
     413             : 
     414             : /*****************************************************************************
     415             :  _winreg_GetVersion
     416             :  ****************************************************************************/
     417             : 
     418          28 : WERROR _winreg_GetVersion(struct pipes_struct *p,
     419             :                           struct winreg_GetVersion *r)
     420             : {
     421          28 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     422             :                                                          r->in.handle,
     423             :                                                          HTYPE_REGKEY);
     424             : 
     425          28 :         if ( !regkey )
     426           0 :                 return WERR_INVALID_HANDLE;
     427             : 
     428          28 :         return reg_getversion(r->out.version);
     429             : }
     430             : 
     431             : 
     432             : /*****************************************************************************
     433             :  _winreg_EnumKey
     434             :  ****************************************************************************/
     435             : 
     436       66293 : WERROR _winreg_EnumKey(struct pipes_struct *p,
     437             :                        struct winreg_EnumKey *r)
     438             : {
     439       66293 :         WERROR err = WERR_OK;
     440       66293 :         struct registry_key *key = find_regkey_by_hnd(p,
     441             :                                                       r->in.handle,
     442             :                                                       HTYPE_REGKEY);
     443           0 :         char *name;
     444             : 
     445       66293 :         if ( !key )
     446           0 :                 return WERR_INVALID_HANDLE;
     447             : 
     448       66293 :         if ( !r->in.name || !r->in.keyclass )
     449           0 :                 return WERR_INVALID_PARAMETER;
     450             : 
     451       66293 :         DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
     452             : 
     453       66293 :         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
     454             :                           r->out.last_changed_time);
     455       66293 :         if (!W_ERROR_IS_OK(err)) {
     456          80 :                 return err;
     457             :         }
     458       66213 :         r->out.name->name = name;
     459       66213 :         r->out.keyclass->name = "";
     460       66213 :         return WERR_OK;
     461             : }
     462             : 
     463             : /*****************************************************************************
     464             :  _winreg_EnumValue
     465             :  ****************************************************************************/
     466             : 
     467      191827 : WERROR _winreg_EnumValue(struct pipes_struct *p,
     468             :                          struct winreg_EnumValue *r)
     469             : {
     470      191827 :         WERROR err = WERR_OK;
     471      191827 :         struct registry_key *key = find_regkey_by_hnd(p,
     472             :                                                       r->in.handle,
     473             :                                                       HTYPE_REGKEY);
     474      191827 :         char *valname = NULL;
     475      191827 :         struct registry_value *val = NULL;
     476             : 
     477      191827 :         if ( !key )
     478           0 :                 return WERR_INVALID_HANDLE;
     479             : 
     480      191827 :         if ( !r->in.name )
     481           0 :                 return WERR_INVALID_PARAMETER;
     482             : 
     483      191827 :         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
     484             :                  key->key->name));
     485             : 
     486      191827 :         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
     487      191827 :         if (!W_ERROR_IS_OK(err)) {
     488         401 :                 return err;
     489             :         }
     490             : 
     491      191426 :         if (r->out.name != NULL) {
     492      191426 :                 r->out.name->name = valname;
     493             :         }
     494             : 
     495      191426 :         if (r->out.type != NULL) {
     496      191426 :                 *r->out.type = val->type;
     497             :         }
     498             : 
     499      191426 :         if (r->out.value != NULL) {
     500      191354 :                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
     501           0 :                         return WERR_INVALID_PARAMETER;
     502             :                 }
     503             : 
     504      191354 :                 if (val->data.length > *r->out.size) {
     505          98 :                         *r->out.size = val->data.length;
     506          98 :                         return WERR_MORE_DATA;
     507             :                 }
     508             : 
     509      191256 :                 memcpy( r->out.value, val->data.data, val->data.length );
     510             :         }
     511             : 
     512      191328 :         if (r->out.length != NULL) {
     513      191328 :                 *r->out.length = val->data.length;
     514             :         }
     515      191328 :         if (r->out.size != NULL) {
     516      191256 :                 *r->out.size = val->data.length;
     517             :         }
     518             : 
     519      191328 :         return WERR_OK;
     520             : }
     521             : 
     522             : /*******************************************************************
     523             :  _winreg_InitiateSystemShutdown
     524             :  ********************************************************************/
     525             : 
     526           0 : WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
     527             :                                       struct winreg_InitiateSystemShutdown *r)
     528             : {
     529           0 :         struct winreg_InitiateSystemShutdownEx s;
     530             : 
     531           0 :         s.in.hostname = r->in.hostname;
     532           0 :         s.in.message = r->in.message;
     533           0 :         s.in.timeout = r->in.timeout;
     534           0 :         s.in.force_apps = r->in.force_apps;
     535           0 :         s.in.do_reboot = r->in.do_reboot;
     536           0 :         s.in.reason = 0;
     537             : 
     538             :         /* thunk down to _winreg_InitiateSystemShutdownEx()
     539             :            (just returns a status) */
     540             : 
     541           0 :         return _winreg_InitiateSystemShutdownEx( p, &s );
     542             : }
     543             : 
     544             : /*******************************************************************
     545             :  _winreg_InitiateSystemShutdownEx
     546             :  ********************************************************************/
     547             : 
     548             : #define SHUTDOWN_R_STRING "-r"
     549             : #define SHUTDOWN_F_STRING "-f"
     550             : 
     551             : 
     552           0 : WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
     553             :                                         struct winreg_InitiateSystemShutdownEx *r)
     554             : {
     555           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     556           0 :         struct auth_session_info *session_info =
     557           0 :                 dcesrv_call_session_info(dce_call);
     558           0 :         const struct loadparm_substitution *lp_sub =
     559           0 :                 loadparm_s3_global_substitution();
     560           0 :         char *shutdown_script = NULL;
     561           0 :         char *chkmsg = NULL;
     562           0 :         fstring str_timeout;
     563           0 :         fstring str_reason;
     564           0 :         fstring do_reboot;
     565           0 :         fstring f;
     566           0 :         int ret = -1;
     567           0 :         bool can_shutdown = false;
     568             : 
     569           0 :         shutdown_script = lp_shutdown_script(p->mem_ctx, lp_sub);
     570           0 :         if (!shutdown_script) {
     571           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     572             :         }
     573           0 :         if (!*shutdown_script) {
     574           0 :                 return WERR_ACCESS_DENIED;
     575             :         }
     576             : 
     577             :         /* pull the message string and perform necessary sanity checks on it */
     578             : 
     579           0 :         if ( r->in.message && r->in.message->string ) {
     580           0 :                 chkmsg = talloc_alpha_strcpy(p->mem_ctx,
     581           0 :                                              r->in.message->string,
     582             :                                              NULL);
     583           0 :                 if (chkmsg == NULL) {
     584           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     585             :                 }
     586             :         }
     587             : 
     588           0 :         fstr_sprintf(str_timeout, "%d", r->in.timeout);
     589           0 :         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
     590           0 :         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
     591           0 :         fstr_sprintf(str_reason, "%d", r->in.reason );
     592             : 
     593           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     594             :                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
     595           0 :         if (!shutdown_script) {
     596           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     597             :         }
     598           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     599             :                                         shutdown_script, "%t", str_timeout);
     600           0 :         if (!shutdown_script) {
     601           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     602             :         }
     603           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     604             :                                                 shutdown_script, "%r", do_reboot);
     605           0 :         if (!shutdown_script) {
     606           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     607             :         }
     608           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     609             :                                                 shutdown_script, "%f", f);
     610           0 :         if (!shutdown_script) {
     611           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     612             :         }
     613           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     614             :                                         shutdown_script, "%x", str_reason);
     615           0 :         if (!shutdown_script) {
     616           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     617             :         }
     618             : 
     619           0 :         can_shutdown = security_token_has_privilege(
     620           0 :                 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
     621             : 
     622             :         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
     623             :            Take the error return from the script and provide it as the Windows return code. */
     624             : 
     625             :         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
     626             : 
     627           0 :         if ( can_shutdown )
     628           0 :                 become_root();
     629             : 
     630           0 :         ret = smbrun(shutdown_script, NULL, NULL);
     631             : 
     632           0 :         if ( can_shutdown )
     633           0 :                 unbecome_root();
     634             : 
     635             :         /********** END SeRemoteShutdownPrivilege BLOCK **********/
     636             : 
     637           0 :         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
     638             :                 shutdown_script, ret));
     639             : 
     640           0 :         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
     641             : }
     642             : 
     643             : /*******************************************************************
     644             :  _winreg_AbortSystemShutdown
     645             :  ********************************************************************/
     646             : 
     647           0 : WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
     648             :                                    struct winreg_AbortSystemShutdown *r)
     649             : {
     650           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     651           0 :         struct auth_session_info *session_info =
     652           0 :                 dcesrv_call_session_info(dce_call);
     653           0 :         const char *abort_shutdown_script = NULL;
     654           0 :         const struct loadparm_substitution *lp_sub =
     655           0 :                 loadparm_s3_global_substitution();
     656           0 :         int ret = -1;
     657           0 :         bool can_shutdown = false;
     658             : 
     659           0 :         abort_shutdown_script = lp_abort_shutdown_script(talloc_tos(), lp_sub);
     660           0 :         if (!*abort_shutdown_script)
     661           0 :                 return WERR_ACCESS_DENIED;
     662             : 
     663           0 :         can_shutdown = security_token_has_privilege(
     664           0 :                 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
     665             : 
     666             :         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
     667             : 
     668           0 :         if ( can_shutdown )
     669           0 :                 become_root();
     670             : 
     671           0 :         ret = smbrun(abort_shutdown_script, NULL, NULL);
     672             : 
     673           0 :         if ( can_shutdown )
     674           0 :                 unbecome_root();
     675             : 
     676             :         /********** END SeRemoteShutdownPrivilege BLOCK **********/
     677             : 
     678           0 :         DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
     679             :                 abort_shutdown_script, ret));
     680             : 
     681           0 :         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
     682             : }
     683             : 
     684             : /*******************************************************************
     685             :  _winreg_RestoreKey
     686             :  ********************************************************************/
     687             : 
     688           0 : WERROR _winreg_RestoreKey(struct pipes_struct *p,
     689             :                           struct winreg_RestoreKey *r)
     690             : {
     691           0 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     692             :                                                          r->in.handle,
     693             :                                                          HTYPE_REGKEY);
     694             : 
     695           0 :         if ( !regkey ) {
     696           0 :                 return WERR_INVALID_HANDLE;
     697             :         }
     698           0 :         return WERR_BAD_PATHNAME;
     699             : }
     700             : 
     701             : /*******************************************************************
     702             :  _winreg_SaveKey
     703             :  ********************************************************************/
     704             : 
     705           0 : WERROR _winreg_SaveKey(struct pipes_struct *p,
     706             :                        struct winreg_SaveKey *r)
     707             : {
     708           0 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     709             :                                                          r->in.handle,
     710             :                                                          HTYPE_REGKEY);
     711             : 
     712           0 :         if ( !regkey ) {
     713           0 :                 return WERR_INVALID_HANDLE;
     714             :         }
     715           0 :         return WERR_BAD_PATHNAME;
     716             : }
     717             : 
     718             : /*******************************************************************
     719             :  _winreg_SaveKeyEx
     720             :  ********************************************************************/
     721             : 
     722           0 : WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
     723             :                          struct winreg_SaveKeyEx *r)
     724             : {
     725             :         /* fill in your code here if you think this call should
     726             :            do anything */
     727             : 
     728           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     729           0 :         return WERR_NOT_SUPPORTED;
     730             : }
     731             : 
     732             : /*******************************************************************
     733             :  _winreg_CreateKey
     734             :  ********************************************************************/
     735             : 
     736        6325 : WERROR _winreg_CreateKey(struct pipes_struct *p,
     737             :                          struct winreg_CreateKey *r)
     738             : {
     739        6325 :         struct registry_key *parent = find_regkey_by_hnd(p,
     740             :                                                          r->in.handle,
     741             :                                                          HTYPE_REGKEY);
     742        6325 :         struct registry_key *new_key = NULL;
     743        6325 :         WERROR result = WERR_OK;
     744             : 
     745        6325 :         if ( !parent )
     746           0 :                 return WERR_INVALID_HANDLE;
     747             : 
     748        6325 :         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
     749             :                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
     750             : 
     751        6325 :         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
     752             :                                &new_key, r->out.action_taken);
     753        6325 :         if (!W_ERROR_IS_OK(result)) {
     754           0 :                 return result;
     755             :         }
     756             : 
     757        6325 :         if (!create_policy_hnd(p, r->out.new_handle, HTYPE_REGKEY, new_key)) {
     758           0 :                 TALLOC_FREE(new_key);
     759           0 :                 return WERR_FILE_NOT_FOUND;
     760             :         }
     761             : 
     762        6325 :         return WERR_OK;
     763             : }
     764             : 
     765             : /*******************************************************************
     766             :  _winreg_SetValue
     767             :  ********************************************************************/
     768             : 
     769       16674 : WERROR _winreg_SetValue(struct pipes_struct *p,
     770             :                         struct winreg_SetValue *r)
     771             : {
     772       16674 :         struct registry_key *key = find_regkey_by_hnd(p,
     773             :                                                       r->in.handle,
     774             :                                                       HTYPE_REGKEY);
     775       16674 :         struct registry_value *val = NULL;
     776             : 
     777       16674 :         if ( !key )
     778           0 :                 return WERR_INVALID_HANDLE;
     779             : 
     780       16674 :         DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
     781             :                          key->key->name, r->in.name.name));
     782             : 
     783       16674 :         val = talloc_zero(p->mem_ctx, struct registry_value);
     784       16674 :         if (val == NULL) {
     785           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     786             :         }
     787             : 
     788       16674 :         val->type = r->in.type;
     789       16674 :         val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
     790             : 
     791       16674 :         return reg_setvalue(key, r->in.name.name, val);
     792             : }
     793             : 
     794             : /*******************************************************************
     795             :  _winreg_DeleteKey
     796             :  ********************************************************************/
     797             : 
     798        1194 : WERROR _winreg_DeleteKey(struct pipes_struct *p,
     799             :                          struct winreg_DeleteKey *r)
     800             : {
     801        1194 :         struct registry_key *parent = find_regkey_by_hnd(p,
     802             :                                                          r->in.handle,
     803             :                                                          HTYPE_REGKEY);
     804             : 
     805        1194 :         if ( !parent )
     806           0 :                 return WERR_INVALID_HANDLE;
     807             : 
     808        1194 :         return reg_deletekey(parent, r->in.key.name);
     809             : }
     810             : 
     811             : 
     812             : /*******************************************************************
     813             :  _winreg_DeleteValue
     814             :  ********************************************************************/
     815             : 
     816        3160 : WERROR _winreg_DeleteValue(struct pipes_struct *p,
     817             :                            struct winreg_DeleteValue *r)
     818             : {
     819        3160 :         struct registry_key *key = find_regkey_by_hnd(p,
     820             :                                                       r->in.handle,
     821             :                                                       HTYPE_REGKEY);
     822             : 
     823        3160 :         if ( !key )
     824           0 :                 return WERR_INVALID_HANDLE;
     825             : 
     826        3160 :         return reg_deletevalue(key, r->in.value.name);
     827             : }
     828             : 
     829             : /*******************************************************************
     830             :  _winreg_GetKeySecurity
     831             :  ********************************************************************/
     832             : 
     833           0 : WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
     834             :                               struct winreg_GetKeySecurity *r)
     835             : {
     836           0 :         struct registry_key *key = find_regkey_by_hnd(p,
     837             :                                                       r->in.handle,
     838             :                                                       HTYPE_REGKEY);
     839           0 :         WERROR err = WERR_OK;
     840           0 :         struct security_descriptor *secdesc = NULL;
     841           0 :         uint8_t *data = NULL;
     842           0 :         size_t len = 0;
     843             : 
     844           0 :         if ( !key )
     845           0 :                 return WERR_INVALID_HANDLE;
     846             : 
     847             :         /* access checks first */
     848             : 
     849           0 :         if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
     850           0 :                 return WERR_ACCESS_DENIED;
     851             : 
     852           0 :         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
     853           0 :         if (!W_ERROR_IS_OK(err)) {
     854           0 :                 return err;
     855             :         }
     856             : 
     857           0 :         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
     858             :                                                    &data, &len));
     859           0 :         if (!W_ERROR_IS_OK(err)) {
     860           0 :                 return err;
     861             :         }
     862             : 
     863           0 :         if (len > r->out.sd->size) {
     864           0 :                 r->out.sd->size = len;
     865           0 :                 return WERR_INSUFFICIENT_BUFFER;
     866             :         }
     867             : 
     868           0 :         r->out.sd->size = len;
     869           0 :         r->out.sd->len = len;
     870           0 :         r->out.sd->data = data;
     871             : 
     872           0 :         return WERR_OK;
     873             : }
     874             : 
     875             : /*******************************************************************
     876             :  _winreg_SetKeySecurity
     877             :  ********************************************************************/
     878             : 
     879           0 : WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
     880             :                               struct winreg_SetKeySecurity *r)
     881             : {
     882           0 :         struct registry_key *key = find_regkey_by_hnd(p,
     883             :                                                       r->in.handle,
     884             :                                                       HTYPE_REGKEY);
     885           0 :         struct security_descriptor *secdesc = NULL;
     886           0 :         WERROR err = WERR_OK;
     887             : 
     888           0 :         if ( !key )
     889           0 :                 return WERR_INVALID_HANDLE;
     890             : 
     891             :         /* access checks first */
     892             : 
     893           0 :         if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
     894           0 :                 return WERR_ACCESS_DENIED;
     895             : 
     896           0 :         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
     897           0 :                                                      r->in.sd->len, &secdesc));
     898           0 :         if (!W_ERROR_IS_OK(err)) {
     899           0 :                 return err;
     900             :         }
     901             : 
     902           0 :         return reg_setkeysecurity(key, secdesc);
     903             : }
     904             : 
     905             : /*******************************************************************
     906             :  _winreg_FlushKey
     907             :  ********************************************************************/
     908             : 
     909          56 : WERROR _winreg_FlushKey(struct pipes_struct *p,
     910             :                         struct winreg_FlushKey *r)
     911             : {
     912             :         /* I'm just replying OK because there's not a lot
     913             :            here I see to do i  --jerry */
     914             : 
     915          56 :         return WERR_OK;
     916             : }
     917             : 
     918             : /*******************************************************************
     919             :  _winreg_UnLoadKey
     920             :  ********************************************************************/
     921             : 
     922           0 : WERROR _winreg_UnLoadKey(struct pipes_struct *p,
     923             :                          struct winreg_UnLoadKey *r)
     924             : {
     925             :         /* fill in your code here if you think this call should
     926             :            do anything */
     927             : 
     928           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     929           0 :         return WERR_NOT_SUPPORTED;
     930             : }
     931             : 
     932             : /*******************************************************************
     933             :  _winreg_ReplaceKey
     934             :  ********************************************************************/
     935             : 
     936           0 : WERROR _winreg_ReplaceKey(struct pipes_struct *p,
     937             :                           struct winreg_ReplaceKey *r)
     938             : {
     939             :         /* fill in your code here if you think this call should
     940             :            do anything */
     941             : 
     942           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     943           0 :         return WERR_NOT_SUPPORTED;
     944             : }
     945             : 
     946             : /*******************************************************************
     947             :  _winreg_LoadKey
     948             :  ********************************************************************/
     949             : 
     950           0 : WERROR _winreg_LoadKey(struct pipes_struct *p,
     951             :                        struct winreg_LoadKey *r)
     952             : {
     953             :         /* fill in your code here if you think this call should
     954             :            do anything */
     955             : 
     956           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     957           0 :         return WERR_NOT_SUPPORTED;
     958             : }
     959             : 
     960             : /*******************************************************************
     961             :  _winreg_NotifyChangeKeyValue
     962             :  ********************************************************************/
     963             : 
     964          28 : WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
     965             :                                     struct winreg_NotifyChangeKeyValue *r)
     966             : {
     967          28 :         return WERR_NOT_SUPPORTED;
     968             : }
     969             : 
     970             : /*******************************************************************
     971             :  _winreg_QueryMultipleValues
     972             :  ********************************************************************/
     973             : 
     974          88 : WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
     975             :                                    struct winreg_QueryMultipleValues *r)
     976             : {
     977           0 :         struct winreg_QueryMultipleValues2 r2;
     978          88 :         uint32_t needed = 0;
     979             : 
     980          88 :         r2.in.key_handle        = r->in.key_handle;
     981          88 :         r2.in.values_in         = r->in.values_in;
     982          88 :         r2.in.num_values        = r->in.num_values;
     983          88 :         r2.in.offered           = r->in.buffer_size;
     984          88 :         r2.in.buffer            = r->in.buffer;
     985          88 :         r2.out.values_out       = r->out.values_out;
     986          88 :         r2.out.needed           = &needed;
     987          88 :         r2.out.buffer           = r->out.buffer;
     988             : 
     989          88 :         return _winreg_QueryMultipleValues2(p, &r2);
     990             : }
     991             : 
     992             : /*******************************************************************
     993             :  ********************************************************************/
     994             : 
     995         200 : static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
     996             :                                        const char *valuename,
     997             :                                        uint32_t value_length,
     998             :                                        uint32_t offset,
     999             :                                        enum winreg_Type type,
    1000             :                                        struct QueryMultipleValue *r)
    1001             : {
    1002         200 :         r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
    1003         200 :         if (r->ve_valuename == NULL) {
    1004           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1005             :         }
    1006             : 
    1007         200 :         r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
    1008         200 :         if (r->ve_valuename->name == NULL) {
    1009           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1010             :         }
    1011             : 
    1012         200 :         r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
    1013         200 :         r->ve_valuelen = value_length;
    1014         200 :         r->ve_valueptr = offset;
    1015         200 :         r->ve_type = type;
    1016             : 
    1017         200 :         return WERR_OK;
    1018             : }
    1019             : 
    1020             : /*******************************************************************
    1021             :  _winreg_QueryMultipleValues2
    1022             :  ********************************************************************/
    1023             : 
    1024         176 : WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
    1025             :                                     struct winreg_QueryMultipleValues2 *r)
    1026             : {
    1027         176 :         struct registry_key *regkey = find_regkey_by_hnd(p,
    1028             :                                                          r->in.key_handle,
    1029             :                                                          HTYPE_REGKEY);
    1030         176 :         struct registry_value *vals = NULL;
    1031         176 :         const char **names = NULL;
    1032         176 :         uint32_t offset = 0, num_vals = 0;
    1033         176 :         DATA_BLOB result = data_blob_null;
    1034         176 :         uint32_t i = 0;
    1035         176 :         WERROR err = WERR_OK;
    1036             : 
    1037         176 :         if (!regkey) {
    1038           0 :                 return WERR_INVALID_HANDLE;
    1039             :         }
    1040             : 
    1041         176 :         names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
    1042         176 :         if (names == NULL) {
    1043           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1044             :         }
    1045             : 
    1046         376 :         for (i=0; i < r->in.num_values; i++) {
    1047         200 :                 if (r->in.values_in[i].ve_valuename &&
    1048         200 :                     r->in.values_in[i].ve_valuename->name) {
    1049         384 :                         names[i] = talloc_strdup(names,
    1050         192 :                                 r->in.values_in[i].ve_valuename->name);
    1051         192 :                         if (names[i] == NULL) {
    1052           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    1053             :                         }
    1054             :                 }
    1055             :         }
    1056             : 
    1057         176 :         err = reg_querymultiplevalues(p->mem_ctx, regkey,
    1058             :                                       r->in.num_values, names,
    1059             :                                       &num_vals, &vals);
    1060         176 :         if (!W_ERROR_IS_OK(err)) {
    1061           0 :                 return err;
    1062             :         }
    1063             : 
    1064         176 :         result = data_blob_talloc(p->mem_ctx, NULL, 0);
    1065             : 
    1066         376 :         for (i=0; i < r->in.num_values; i++) {
    1067         200 :                 const char *valuename = NULL;
    1068             : 
    1069         200 :                 if (vals[i].data.length > 0) {
    1070         160 :                         if (!data_blob_append(p->mem_ctx, &result,
    1071         160 :                                               vals[i].data.data,
    1072         160 :                                               vals[i].data.length)) {
    1073           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    1074             :                         }
    1075             :                 }
    1076             : 
    1077         200 :                 if (r->in.values_in[i].ve_valuename &&
    1078         200 :                     r->in.values_in[i].ve_valuename->name) {
    1079         192 :                         valuename = r->in.values_in[i].ve_valuename->name;
    1080             :                 }
    1081             : 
    1082         200 :                 err = construct_multiple_entry(r->out.values_out,
    1083             :                                                valuename,
    1084         200 :                                                vals[i].data.length,
    1085             :                                                offset,
    1086         200 :                                                vals[i].type,
    1087         200 :                                                &r->out.values_out[i]);
    1088         200 :                 if (!W_ERROR_IS_OK(err)) {
    1089           0 :                         return err;
    1090             :                 }
    1091             : 
    1092         200 :                 offset += vals[i].data.length;
    1093             :         }
    1094             : 
    1095         176 :         *r->out.needed = result.length;
    1096             : 
    1097         176 :         if (r->in.num_values != num_vals) {
    1098          40 :                 return WERR_FILE_NOT_FOUND;
    1099             :         }
    1100             : 
    1101         136 :         if (*r->in.offered >= *r->out.needed) {
    1102         104 :                 if (r->out.buffer) {
    1103          32 :                         memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
    1104             :                 }
    1105         104 :                 return WERR_OK;
    1106             :         } else {
    1107          32 :                 return WERR_MORE_DATA;
    1108             :         }
    1109             : }
    1110             : 
    1111             : /*******************************************************************
    1112             :  _winreg_DeleteKeyEx
    1113             :  ********************************************************************/
    1114             : 
    1115           0 : WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
    1116             :                            struct winreg_DeleteKeyEx *r)
    1117             : {
    1118             :         /* fill in your code here if you think this call should
    1119             :            do anything */
    1120             : 
    1121           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
    1122           0 :         return WERR_NOT_SUPPORTED;
    1123             : }
    1124             : 
    1125             : /* include the generated boilerplate */
    1126             : #include "librpc/gen_ndr/ndr_winreg_scompat.c"

Generated by: LCOV version 1.14