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 smb2.twrp.listdir_fix f886ca1c Lines: 229 443 51.7 %
Date: 2023-11-07 19:11:32 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      484455 : static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
      46             :                                                struct policy_handle *hnd,
      47             :                                                enum handle_types type)
      48             : {
      49      484455 :         struct registry_key *regkey = NULL;
      50           0 :         NTSTATUS status;
      51             : 
      52      484455 :         regkey = find_policy_by_hnd(p,
      53             :                                     hnd,
      54             :                                     type,
      55             :                                     struct registry_key,
      56           0 :                                     &status);
      57      484455 :         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      484409 :         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       86878 : 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       86878 :         struct dcesrv_call_state *dce_call = p->dce_call;
      81           0 :         struct auth_session_info *session_info =
      82       86878 :                 dcesrv_call_session_info(dce_call);
      83       86878 :         WERROR result = WERR_OK;
      84           0 :         struct registry_key *key;
      85             : 
      86       86878 :         if (parent == NULL) {
      87       44514 :                 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
      88       44514 :                                       session_info->security_token, &key);
      89             :         }
      90             :         else {
      91       42364 :                 result = reg_openkey(p->mem_ctx, parent, subkeyname,
      92             :                                      access_desired, &key);
      93             :         }
      94             : 
      95       86878 :         if ( !W_ERROR_IS_OK(result) ) {
      96        2038 :                 return result;
      97             :         }
      98             : 
      99       84840 :         if ( !create_policy_hnd( p, hnd, HTYPE_REGKEY, key ) ) {
     100           0 :                 return WERR_FILE_NOT_FOUND;
     101             :         }
     102             : 
     103       84840 :         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       90405 : static bool close_registry_key(struct pipes_struct *p,
     112             :                                struct policy_handle *hnd,
     113             :                                enum handle_types type)
     114             : {
     115       90405 :         struct registry_key *regkey = find_regkey_by_hnd(p, hnd, type);
     116             : 
     117       90405 :         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       90359 :         close_policy_hnd(p, hnd);
     124             : 
     125       90359 :         return True;
     126             : }
     127             : 
     128             : /********************************************************************
     129             :  _winreg_CloseKey
     130             :  ********************************************************************/
     131             : 
     132       90405 : 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       90405 :         ok = close_registry_key(p, r->in.handle, HTYPE_REGKEY);
     140       90405 :         if (!ok) {
     141          46 :                 return WERR_INVALID_HANDLE;
     142             :         }
     143             : 
     144       90359 :         ZERO_STRUCTP(r->out.handle);
     145             : 
     146       90359 :         return WERR_OK;
     147             : }
     148             : 
     149             : /*******************************************************************
     150             :  _winreg_OpenHKLM
     151             :  ********************************************************************/
     152             : 
     153       44493 : WERROR _winreg_OpenHKLM(struct pipes_struct *p,
     154             :                         struct winreg_OpenHKLM *r)
     155             : {
     156       44493 :         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       42364 : WERROR _winreg_OpenKey(struct pipes_struct *p,
     244             :                        struct winreg_OpenKey *r)
     245             : {
     246       42364 :         struct registry_key *parent = find_regkey_by_hnd(p,
     247             :                                                          r->in.parent_handle,
     248             :                                                          HTYPE_REGKEY);
     249             : 
     250       42364 :         if ( !parent )
     251           0 :                 return WERR_INVALID_HANDLE;
     252             : 
     253       42364 :         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       46484 : WERROR _winreg_QueryValue(struct pipes_struct *p,
     261             :                           struct winreg_QueryValue *r)
     262             : {
     263       46484 :         WERROR        status = WERR_FILE_NOT_FOUND;
     264       46484 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     265             :                                                          r->in.handle,
     266             :                                                          HTYPE_REGKEY);
     267           0 :         prs_struct    prs_hkpd;
     268             : 
     269       46484 :         uint8_t *outbuf = NULL;
     270       46484 :         uint32_t outbuf_size = 0;
     271             : 
     272       46484 :         bool free_buf = False;
     273       46484 :         bool free_prs = False;
     274             : 
     275       46484 :         if ( !regkey )
     276           0 :                 return WERR_INVALID_HANDLE;
     277             : 
     278       46484 :         if (r->in.value_name->name == NULL) {
     279         196 :                 return WERR_INVALID_PARAMETER;
     280             :         }
     281             : 
     282       46288 :         if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
     283         441 :                 return WERR_INVALID_PARAMETER;
     284             :         }
     285             : 
     286       45847 :         DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
     287       45847 :         DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
     288             : 
     289             :         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
     290       45847 :         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       45847 :                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
     335             :                                         &val);
     336       45847 :                 if (!W_ERROR_IS_OK(status)) {
     337             : 
     338        7712 :                         DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
     339             :                                 win_errstr(status)));
     340             : 
     341        7712 :                         if (r->out.data_size) {
     342        7712 :                                 *r->out.data_size = 0;
     343             :                         }
     344        7712 :                         if (r->out.data_length) {
     345        7712 :                                 *r->out.data_length = 0;
     346             :                         }
     347        7712 :                         return status;
     348             :                 }
     349             : 
     350       38135 :                 outbuf = val->data.data;
     351       38135 :                 outbuf_size = val->data.length;
     352       38135 :                 *r->out.type = val->type;
     353             :         }
     354             : 
     355       38135 :         status = WERR_FILE_NOT_FOUND;
     356             : 
     357       38135 :         if (*r->in.data_size < outbuf_size) {
     358       19056 :                 *r->out.data_size = outbuf_size;
     359       19056 :                 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
     360             :         } else {
     361       19079 :                 *r->out.data_length = outbuf_size;
     362       19079 :                 *r->out.data_size = outbuf_size;
     363       19079 :                 if (r->out.data) {
     364       19043 :                         memcpy(r->out.data, outbuf, outbuf_size);
     365             :                 }
     366       19079 :                 status = WERR_OK;
     367             :         }
     368             : 
     369       38135 :         if (free_prs) prs_mem_free(&prs_hkpd);
     370       38135 :         if (free_buf) SAFE_FREE(outbuf);
     371             : 
     372       38135 :         return status;
     373             : }
     374             : 
     375             : /*****************************************************************************
     376             :  _winreg_QueryInfoKey
     377             :  ****************************************************************************/
     378             : 
     379       20352 : WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
     380             :                             struct winreg_QueryInfoKey *r)
     381             : {
     382       20352 :         WERROR  status = WERR_OK;
     383       20352 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     384             :                                                          r->in.handle,
     385             :                                                          HTYPE_REGKEY);
     386             : 
     387       20352 :         if ( !regkey )
     388           0 :                 return WERR_INVALID_HANDLE;
     389             : 
     390       20352 :         r->out.classname->name = NULL;
     391             : 
     392       20352 :         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       20352 :         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       20352 :         *r->out.max_subkeylen *= 2;
     406             : 
     407       20352 :         *r->out.max_valnamelen += 1;
     408       20352 :         *r->out.max_valnamelen *= 2;
     409             : 
     410       20352 :         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       66253 : WERROR _winreg_EnumKey(struct pipes_struct *p,
     437             :                        struct winreg_EnumKey *r)
     438             : {
     439       66253 :         WERROR err = WERR_OK;
     440       66253 :         struct registry_key *key = find_regkey_by_hnd(p,
     441             :                                                       r->in.handle,
     442             :                                                       HTYPE_REGKEY);
     443           0 :         char *name;
     444             : 
     445       66253 :         if ( !key )
     446           0 :                 return WERR_INVALID_HANDLE;
     447             : 
     448       66253 :         if ( !r->in.name || !r->in.keyclass )
     449           0 :                 return WERR_INVALID_PARAMETER;
     450             : 
     451       66253 :         DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
     452             : 
     453       66253 :         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
     454             :                           r->out.last_changed_time);
     455       66253 :         if (!W_ERROR_IS_OK(err)) {
     456          80 :                 return err;
     457             :         }
     458       66173 :         r->out.name->name = name;
     459       66173 :         r->out.keyclass->name = "";
     460       66173 :         return WERR_OK;
     461             : }
     462             : 
     463             : /*****************************************************************************
     464             :  _winreg_EnumValue
     465             :  ****************************************************************************/
     466             : 
     467      191556 : WERROR _winreg_EnumValue(struct pipes_struct *p,
     468             :                          struct winreg_EnumValue *r)
     469             : {
     470      191556 :         WERROR err = WERR_OK;
     471      191556 :         struct registry_key *key = find_regkey_by_hnd(p,
     472             :                                                       r->in.handle,
     473             :                                                       HTYPE_REGKEY);
     474      191556 :         char *valname = NULL;
     475      191556 :         struct registry_value *val = NULL;
     476             : 
     477      191556 :         if ( !key )
     478           0 :                 return WERR_INVALID_HANDLE;
     479             : 
     480      191556 :         if ( !r->in.name )
     481           0 :                 return WERR_INVALID_PARAMETER;
     482             : 
     483      191556 :         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
     484             :                  key->key->name));
     485             : 
     486      191556 :         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
     487      191556 :         if (!W_ERROR_IS_OK(err)) {
     488         352 :                 return err;
     489             :         }
     490             : 
     491      191204 :         if (r->out.name != NULL) {
     492      191204 :                 r->out.name->name = valname;
     493             :         }
     494             : 
     495      191204 :         if (r->out.type != NULL) {
     496      191204 :                 *r->out.type = val->type;
     497             :         }
     498             : 
     499      191204 :         if (r->out.value != NULL) {
     500      191132 :                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
     501           0 :                         return WERR_INVALID_PARAMETER;
     502             :                 }
     503             : 
     504      191132 :                 if (val->data.length > *r->out.size) {
     505           0 :                         return WERR_MORE_DATA;
     506             :                 }
     507             : 
     508      191132 :                 memcpy( r->out.value, val->data.data, val->data.length );
     509             :         }
     510             : 
     511      191204 :         if (r->out.length != NULL) {
     512      191204 :                 *r->out.length = val->data.length;
     513             :         }
     514      191204 :         if (r->out.size != NULL) {
     515      191132 :                 *r->out.size = val->data.length;
     516             :         }
     517             : 
     518      191204 :         return WERR_OK;
     519             : }
     520             : 
     521             : /*******************************************************************
     522             :  _winreg_InitiateSystemShutdown
     523             :  ********************************************************************/
     524             : 
     525           0 : WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
     526             :                                       struct winreg_InitiateSystemShutdown *r)
     527             : {
     528           0 :         struct winreg_InitiateSystemShutdownEx s;
     529             : 
     530           0 :         s.in.hostname = r->in.hostname;
     531           0 :         s.in.message = r->in.message;
     532           0 :         s.in.timeout = r->in.timeout;
     533           0 :         s.in.force_apps = r->in.force_apps;
     534           0 :         s.in.do_reboot = r->in.do_reboot;
     535           0 :         s.in.reason = 0;
     536             : 
     537             :         /* thunk down to _winreg_InitiateSystemShutdownEx()
     538             :            (just returns a status) */
     539             : 
     540           0 :         return _winreg_InitiateSystemShutdownEx( p, &s );
     541             : }
     542             : 
     543             : /*******************************************************************
     544             :  _winreg_InitiateSystemShutdownEx
     545             :  ********************************************************************/
     546             : 
     547             : #define SHUTDOWN_R_STRING "-r"
     548             : #define SHUTDOWN_F_STRING "-f"
     549             : 
     550             : 
     551           0 : WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
     552             :                                         struct winreg_InitiateSystemShutdownEx *r)
     553             : {
     554           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     555           0 :         struct auth_session_info *session_info =
     556           0 :                 dcesrv_call_session_info(dce_call);
     557           0 :         const struct loadparm_substitution *lp_sub =
     558           0 :                 loadparm_s3_global_substitution();
     559           0 :         char *shutdown_script = NULL;
     560           0 :         char *chkmsg = NULL;
     561           0 :         fstring str_timeout;
     562           0 :         fstring str_reason;
     563           0 :         fstring do_reboot;
     564           0 :         fstring f;
     565           0 :         int ret = -1;
     566           0 :         bool can_shutdown = false;
     567             : 
     568           0 :         shutdown_script = lp_shutdown_script(p->mem_ctx, lp_sub);
     569           0 :         if (!shutdown_script) {
     570           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     571             :         }
     572           0 :         if (!*shutdown_script) {
     573           0 :                 return WERR_ACCESS_DENIED;
     574             :         }
     575             : 
     576             :         /* pull the message string and perform necessary sanity checks on it */
     577             : 
     578           0 :         if ( r->in.message && r->in.message->string ) {
     579           0 :                 chkmsg = talloc_alpha_strcpy(p->mem_ctx,
     580           0 :                                              r->in.message->string,
     581             :                                              NULL);
     582           0 :                 if (chkmsg == NULL) {
     583           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     584             :                 }
     585             :         }
     586             : 
     587           0 :         fstr_sprintf(str_timeout, "%d", r->in.timeout);
     588           0 :         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
     589           0 :         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
     590           0 :         fstr_sprintf(str_reason, "%d", r->in.reason );
     591             : 
     592           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     593             :                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
     594           0 :         if (!shutdown_script) {
     595           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     596             :         }
     597           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     598             :                                         shutdown_script, "%t", str_timeout);
     599           0 :         if (!shutdown_script) {
     600           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     601             :         }
     602           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     603             :                                                 shutdown_script, "%r", do_reboot);
     604           0 :         if (!shutdown_script) {
     605           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     606             :         }
     607           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     608             :                                                 shutdown_script, "%f", f);
     609           0 :         if (!shutdown_script) {
     610           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     611             :         }
     612           0 :         shutdown_script = talloc_all_string_sub(p->mem_ctx,
     613             :                                         shutdown_script, "%x", str_reason);
     614           0 :         if (!shutdown_script) {
     615           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     616             :         }
     617             : 
     618           0 :         can_shutdown = security_token_has_privilege(
     619           0 :                 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
     620             : 
     621             :         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
     622             :            Take the error return from the script and provide it as the Windows return code. */
     623             : 
     624             :         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
     625             : 
     626           0 :         if ( can_shutdown )
     627           0 :                 become_root();
     628             : 
     629           0 :         ret = smbrun(shutdown_script, NULL, NULL);
     630             : 
     631           0 :         if ( can_shutdown )
     632           0 :                 unbecome_root();
     633             : 
     634             :         /********** END SeRemoteShutdownPrivilege BLOCK **********/
     635             : 
     636           0 :         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
     637             :                 shutdown_script, ret));
     638             : 
     639           0 :         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
     640             : }
     641             : 
     642             : /*******************************************************************
     643             :  _winreg_AbortSystemShutdown
     644             :  ********************************************************************/
     645             : 
     646           0 : WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
     647             :                                    struct winreg_AbortSystemShutdown *r)
     648             : {
     649           0 :         struct dcesrv_call_state *dce_call = p->dce_call;
     650           0 :         struct auth_session_info *session_info =
     651           0 :                 dcesrv_call_session_info(dce_call);
     652           0 :         const char *abort_shutdown_script = NULL;
     653           0 :         const struct loadparm_substitution *lp_sub =
     654           0 :                 loadparm_s3_global_substitution();
     655           0 :         int ret = -1;
     656           0 :         bool can_shutdown = false;
     657             : 
     658           0 :         abort_shutdown_script = lp_abort_shutdown_script(talloc_tos(), lp_sub);
     659           0 :         if (!*abort_shutdown_script)
     660           0 :                 return WERR_ACCESS_DENIED;
     661             : 
     662           0 :         can_shutdown = security_token_has_privilege(
     663           0 :                 session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
     664             : 
     665             :         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
     666             : 
     667           0 :         if ( can_shutdown )
     668           0 :                 become_root();
     669             : 
     670           0 :         ret = smbrun(abort_shutdown_script, NULL, NULL);
     671             : 
     672           0 :         if ( can_shutdown )
     673           0 :                 unbecome_root();
     674             : 
     675             :         /********** END SeRemoteShutdownPrivilege BLOCK **********/
     676             : 
     677           0 :         DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
     678             :                 abort_shutdown_script, ret));
     679             : 
     680           0 :         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
     681             : }
     682             : 
     683             : /*******************************************************************
     684             :  _winreg_RestoreKey
     685             :  ********************************************************************/
     686             : 
     687           0 : WERROR _winreg_RestoreKey(struct pipes_struct *p,
     688             :                           struct winreg_RestoreKey *r)
     689             : {
     690           0 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     691             :                                                          r->in.handle,
     692             :                                                          HTYPE_REGKEY);
     693             : 
     694           0 :         if ( !regkey ) {
     695           0 :                 return WERR_INVALID_HANDLE;
     696             :         }
     697           0 :         return WERR_BAD_PATHNAME;
     698             : }
     699             : 
     700             : /*******************************************************************
     701             :  _winreg_SaveKey
     702             :  ********************************************************************/
     703             : 
     704           0 : WERROR _winreg_SaveKey(struct pipes_struct *p,
     705             :                        struct winreg_SaveKey *r)
     706             : {
     707           0 :         struct registry_key *regkey = find_regkey_by_hnd(p,
     708             :                                                          r->in.handle,
     709             :                                                          HTYPE_REGKEY);
     710             : 
     711           0 :         if ( !regkey ) {
     712           0 :                 return WERR_INVALID_HANDLE;
     713             :         }
     714           0 :         return WERR_BAD_PATHNAME;
     715             : }
     716             : 
     717             : /*******************************************************************
     718             :  _winreg_SaveKeyEx
     719             :  ********************************************************************/
     720             : 
     721           0 : WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
     722             :                          struct winreg_SaveKeyEx *r)
     723             : {
     724             :         /* fill in your code here if you think this call should
     725             :            do anything */
     726             : 
     727           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     728           0 :         return WERR_NOT_SUPPORTED;
     729             : }
     730             : 
     731             : /*******************************************************************
     732             :  _winreg_CreateKey
     733             :  ********************************************************************/
     734             : 
     735        6261 : WERROR _winreg_CreateKey(struct pipes_struct *p,
     736             :                          struct winreg_CreateKey *r)
     737             : {
     738        6261 :         struct registry_key *parent = find_regkey_by_hnd(p,
     739             :                                                          r->in.handle,
     740             :                                                          HTYPE_REGKEY);
     741        6261 :         struct registry_key *new_key = NULL;
     742        6261 :         WERROR result = WERR_OK;
     743             : 
     744        6261 :         if ( !parent )
     745           0 :                 return WERR_INVALID_HANDLE;
     746             : 
     747        6261 :         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
     748             :                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
     749             : 
     750        6261 :         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
     751             :                                &new_key, r->out.action_taken);
     752        6261 :         if (!W_ERROR_IS_OK(result)) {
     753           0 :                 return result;
     754             :         }
     755             : 
     756        6261 :         if (!create_policy_hnd(p, r->out.new_handle, HTYPE_REGKEY, new_key)) {
     757           0 :                 TALLOC_FREE(new_key);
     758           0 :                 return WERR_FILE_NOT_FOUND;
     759             :         }
     760             : 
     761        6261 :         return WERR_OK;
     762             : }
     763             : 
     764             : /*******************************************************************
     765             :  _winreg_SetValue
     766             :  ********************************************************************/
     767             : 
     768       16328 : WERROR _winreg_SetValue(struct pipes_struct *p,
     769             :                         struct winreg_SetValue *r)
     770             : {
     771       16328 :         struct registry_key *key = find_regkey_by_hnd(p,
     772             :                                                       r->in.handle,
     773             :                                                       HTYPE_REGKEY);
     774       16328 :         struct registry_value *val = NULL;
     775             : 
     776       16328 :         if ( !key )
     777           0 :                 return WERR_INVALID_HANDLE;
     778             : 
     779       16328 :         DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
     780             :                          key->key->name, r->in.name.name));
     781             : 
     782       16328 :         val = talloc_zero(p->mem_ctx, struct registry_value);
     783       16328 :         if (val == NULL) {
     784           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     785             :         }
     786             : 
     787       16328 :         val->type = r->in.type;
     788       16328 :         val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
     789             : 
     790       16328 :         return reg_setvalue(key, r->in.name.name, val);
     791             : }
     792             : 
     793             : /*******************************************************************
     794             :  _winreg_DeleteKey
     795             :  ********************************************************************/
     796             : 
     797        1186 : WERROR _winreg_DeleteKey(struct pipes_struct *p,
     798             :                          struct winreg_DeleteKey *r)
     799             : {
     800        1186 :         struct registry_key *parent = find_regkey_by_hnd(p,
     801             :                                                          r->in.handle,
     802             :                                                          HTYPE_REGKEY);
     803             : 
     804        1186 :         if ( !parent )
     805           0 :                 return WERR_INVALID_HANDLE;
     806             : 
     807        1186 :         return reg_deletekey(parent, r->in.key.name);
     808             : }
     809             : 
     810             : 
     811             : /*******************************************************************
     812             :  _winreg_DeleteValue
     813             :  ********************************************************************/
     814             : 
     815        3062 : WERROR _winreg_DeleteValue(struct pipes_struct *p,
     816             :                            struct winreg_DeleteValue *r)
     817             : {
     818        3062 :         struct registry_key *key = find_regkey_by_hnd(p,
     819             :                                                       r->in.handle,
     820             :                                                       HTYPE_REGKEY);
     821             : 
     822        3062 :         if ( !key )
     823           0 :                 return WERR_INVALID_HANDLE;
     824             : 
     825        3062 :         return reg_deletevalue(key, r->in.value.name);
     826             : }
     827             : 
     828             : /*******************************************************************
     829             :  _winreg_GetKeySecurity
     830             :  ********************************************************************/
     831             : 
     832           0 : WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
     833             :                               struct winreg_GetKeySecurity *r)
     834             : {
     835           0 :         struct registry_key *key = find_regkey_by_hnd(p,
     836             :                                                       r->in.handle,
     837             :                                                       HTYPE_REGKEY);
     838           0 :         WERROR err = WERR_OK;
     839           0 :         struct security_descriptor *secdesc = NULL;
     840           0 :         uint8_t *data = NULL;
     841           0 :         size_t len = 0;
     842             : 
     843           0 :         if ( !key )
     844           0 :                 return WERR_INVALID_HANDLE;
     845             : 
     846             :         /* access checks first */
     847             : 
     848           0 :         if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
     849           0 :                 return WERR_ACCESS_DENIED;
     850             : 
     851           0 :         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
     852           0 :         if (!W_ERROR_IS_OK(err)) {
     853           0 :                 return err;
     854             :         }
     855             : 
     856           0 :         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
     857             :                                                    &data, &len));
     858           0 :         if (!W_ERROR_IS_OK(err)) {
     859           0 :                 return err;
     860             :         }
     861             : 
     862           0 :         if (len > r->out.sd->size) {
     863           0 :                 r->out.sd->size = len;
     864           0 :                 return WERR_INSUFFICIENT_BUFFER;
     865             :         }
     866             : 
     867           0 :         r->out.sd->size = len;
     868           0 :         r->out.sd->len = len;
     869           0 :         r->out.sd->data = data;
     870             : 
     871           0 :         return WERR_OK;
     872             : }
     873             : 
     874             : /*******************************************************************
     875             :  _winreg_SetKeySecurity
     876             :  ********************************************************************/
     877             : 
     878           0 : WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
     879             :                               struct winreg_SetKeySecurity *r)
     880             : {
     881           0 :         struct registry_key *key = find_regkey_by_hnd(p,
     882             :                                                       r->in.handle,
     883             :                                                       HTYPE_REGKEY);
     884           0 :         struct security_descriptor *secdesc = NULL;
     885           0 :         WERROR err = WERR_OK;
     886             : 
     887           0 :         if ( !key )
     888           0 :                 return WERR_INVALID_HANDLE;
     889             : 
     890             :         /* access checks first */
     891             : 
     892           0 :         if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
     893           0 :                 return WERR_ACCESS_DENIED;
     894             : 
     895           0 :         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
     896           0 :                                                      r->in.sd->len, &secdesc));
     897           0 :         if (!W_ERROR_IS_OK(err)) {
     898           0 :                 return err;
     899             :         }
     900             : 
     901           0 :         return reg_setkeysecurity(key, secdesc);
     902             : }
     903             : 
     904             : /*******************************************************************
     905             :  _winreg_FlushKey
     906             :  ********************************************************************/
     907             : 
     908          56 : WERROR _winreg_FlushKey(struct pipes_struct *p,
     909             :                         struct winreg_FlushKey *r)
     910             : {
     911             :         /* I'm just replying OK because there's not a lot
     912             :            here I see to do i  --jerry */
     913             : 
     914          56 :         return WERR_OK;
     915             : }
     916             : 
     917             : /*******************************************************************
     918             :  _winreg_UnLoadKey
     919             :  ********************************************************************/
     920             : 
     921           0 : WERROR _winreg_UnLoadKey(struct pipes_struct *p,
     922             :                          struct winreg_UnLoadKey *r)
     923             : {
     924             :         /* fill in your code here if you think this call should
     925             :            do anything */
     926             : 
     927           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     928           0 :         return WERR_NOT_SUPPORTED;
     929             : }
     930             : 
     931             : /*******************************************************************
     932             :  _winreg_ReplaceKey
     933             :  ********************************************************************/
     934             : 
     935           0 : WERROR _winreg_ReplaceKey(struct pipes_struct *p,
     936             :                           struct winreg_ReplaceKey *r)
     937             : {
     938             :         /* fill in your code here if you think this call should
     939             :            do anything */
     940             : 
     941           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     942           0 :         return WERR_NOT_SUPPORTED;
     943             : }
     944             : 
     945             : /*******************************************************************
     946             :  _winreg_LoadKey
     947             :  ********************************************************************/
     948             : 
     949           0 : WERROR _winreg_LoadKey(struct pipes_struct *p,
     950             :                        struct winreg_LoadKey *r)
     951             : {
     952             :         /* fill in your code here if you think this call should
     953             :            do anything */
     954             : 
     955           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
     956           0 :         return WERR_NOT_SUPPORTED;
     957             : }
     958             : 
     959             : /*******************************************************************
     960             :  _winreg_NotifyChangeKeyValue
     961             :  ********************************************************************/
     962             : 
     963          28 : WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
     964             :                                     struct winreg_NotifyChangeKeyValue *r)
     965             : {
     966          28 :         return WERR_NOT_SUPPORTED;
     967             : }
     968             : 
     969             : /*******************************************************************
     970             :  _winreg_QueryMultipleValues
     971             :  ********************************************************************/
     972             : 
     973          88 : WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
     974             :                                    struct winreg_QueryMultipleValues *r)
     975             : {
     976           0 :         struct winreg_QueryMultipleValues2 r2;
     977          88 :         uint32_t needed = 0;
     978             : 
     979          88 :         r2.in.key_handle        = r->in.key_handle;
     980          88 :         r2.in.values_in         = r->in.values_in;
     981          88 :         r2.in.num_values        = r->in.num_values;
     982          88 :         r2.in.offered           = r->in.buffer_size;
     983          88 :         r2.in.buffer            = r->in.buffer;
     984          88 :         r2.out.values_out       = r->out.values_out;
     985          88 :         r2.out.needed           = &needed;
     986          88 :         r2.out.buffer           = r->out.buffer;
     987             : 
     988          88 :         return _winreg_QueryMultipleValues2(p, &r2);
     989             : }
     990             : 
     991             : /*******************************************************************
     992             :  ********************************************************************/
     993             : 
     994         200 : static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
     995             :                                        const char *valuename,
     996             :                                        uint32_t value_length,
     997             :                                        uint32_t offset,
     998             :                                        enum winreg_Type type,
     999             :                                        struct QueryMultipleValue *r)
    1000             : {
    1001         200 :         r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
    1002         200 :         if (r->ve_valuename == NULL) {
    1003           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1004             :         }
    1005             : 
    1006         200 :         r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
    1007         200 :         if (r->ve_valuename->name == NULL) {
    1008           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1009             :         }
    1010             : 
    1011         200 :         r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
    1012         200 :         r->ve_valuelen = value_length;
    1013         200 :         r->ve_valueptr = offset;
    1014         200 :         r->ve_type = type;
    1015             : 
    1016         200 :         return WERR_OK;
    1017             : }
    1018             : 
    1019             : /*******************************************************************
    1020             :  _winreg_QueryMultipleValues2
    1021             :  ********************************************************************/
    1022             : 
    1023         176 : WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
    1024             :                                     struct winreg_QueryMultipleValues2 *r)
    1025             : {
    1026         176 :         struct registry_key *regkey = find_regkey_by_hnd(p,
    1027             :                                                          r->in.key_handle,
    1028             :                                                          HTYPE_REGKEY);
    1029         176 :         struct registry_value *vals = NULL;
    1030         176 :         const char **names = NULL;
    1031         176 :         uint32_t offset = 0, num_vals = 0;
    1032         176 :         DATA_BLOB result = data_blob_null;
    1033         176 :         uint32_t i = 0;
    1034         176 :         WERROR err = WERR_OK;
    1035             : 
    1036         176 :         if (!regkey) {
    1037           0 :                 return WERR_INVALID_HANDLE;
    1038             :         }
    1039             : 
    1040         176 :         names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
    1041         176 :         if (names == NULL) {
    1042           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1043             :         }
    1044             : 
    1045         376 :         for (i=0; i < r->in.num_values; i++) {
    1046         200 :                 if (r->in.values_in[i].ve_valuename &&
    1047         200 :                     r->in.values_in[i].ve_valuename->name) {
    1048         384 :                         names[i] = talloc_strdup(names,
    1049         192 :                                 r->in.values_in[i].ve_valuename->name);
    1050         192 :                         if (names[i] == NULL) {
    1051           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    1052             :                         }
    1053             :                 }
    1054             :         }
    1055             : 
    1056         176 :         err = reg_querymultiplevalues(p->mem_ctx, regkey,
    1057             :                                       r->in.num_values, names,
    1058             :                                       &num_vals, &vals);
    1059         176 :         if (!W_ERROR_IS_OK(err)) {
    1060           0 :                 return err;
    1061             :         }
    1062             : 
    1063         176 :         result = data_blob_talloc(p->mem_ctx, NULL, 0);
    1064             : 
    1065         376 :         for (i=0; i < r->in.num_values; i++) {
    1066         200 :                 const char *valuename = NULL;
    1067             : 
    1068         200 :                 if (vals[i].data.length > 0) {
    1069         160 :                         if (!data_blob_append(p->mem_ctx, &result,
    1070         160 :                                               vals[i].data.data,
    1071         160 :                                               vals[i].data.length)) {
    1072           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    1073             :                         }
    1074             :                 }
    1075             : 
    1076         200 :                 if (r->in.values_in[i].ve_valuename &&
    1077         200 :                     r->in.values_in[i].ve_valuename->name) {
    1078         192 :                         valuename = r->in.values_in[i].ve_valuename->name;
    1079             :                 }
    1080             : 
    1081         200 :                 err = construct_multiple_entry(r->out.values_out,
    1082             :                                                valuename,
    1083         200 :                                                vals[i].data.length,
    1084             :                                                offset,
    1085         200 :                                                vals[i].type,
    1086         200 :                                                &r->out.values_out[i]);
    1087         200 :                 if (!W_ERROR_IS_OK(err)) {
    1088           0 :                         return err;
    1089             :                 }
    1090             : 
    1091         200 :                 offset += vals[i].data.length;
    1092             :         }
    1093             : 
    1094         176 :         *r->out.needed = result.length;
    1095             : 
    1096         176 :         if (r->in.num_values != num_vals) {
    1097          40 :                 return WERR_FILE_NOT_FOUND;
    1098             :         }
    1099             : 
    1100         136 :         if (*r->in.offered >= *r->out.needed) {
    1101         104 :                 if (r->out.buffer) {
    1102          32 :                         memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
    1103             :                 }
    1104         104 :                 return WERR_OK;
    1105             :         } else {
    1106          32 :                 return WERR_MORE_DATA;
    1107             :         }
    1108             : }
    1109             : 
    1110             : /*******************************************************************
    1111             :  _winreg_DeleteKeyEx
    1112             :  ********************************************************************/
    1113             : 
    1114           0 : WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
    1115             :                            struct winreg_DeleteKeyEx *r)
    1116             : {
    1117             :         /* fill in your code here if you think this call should
    1118             :            do anything */
    1119             : 
    1120           0 :         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
    1121           0 :         return WERR_NOT_SUPPORTED;
    1122             : }
    1123             : 
    1124             : /* include the generated boilerplate */
    1125             : #include "librpc/gen_ndr/ndr_winreg_scompat.c"

Generated by: LCOV version 1.14