2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Gerald (Jerry) Carter 2005,
5 * Copyright (C) Marcin Krzysztof Porwit 2005.
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 2 of the License, or
10 * (at your option) any later version.
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.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 /* TODO - Do the OpenService service name matching case-independently, or at least make it an option. */
28 #define DBGC_CLASS DBGC_RPC_SRV
30 #define SERVICEDB_VERSION_V1 1 /* Will there be more? */
31 #define INTERNAL_SERVICES_LIST "NETLOGON Spooler"
34 /* scripts will execute from the following libdir, if they are in the enable svcctl=<list of scripts> */
35 /* these should likely be symbolic links. Note that information about them will be extracted from the files themselves */
36 /* using the LSB standard keynames for various information */
38 #define SVCCTL_SCRIPT_DIR "/svcctl/"
41 * sertup the \PIPE\svcctl db API
44 #define SCVCTL_DATABASE_VERSION_V1 1
45 static TDB_CONTEXT *service_tdb; /* used for services tdb file */
47 /* there are two types of services -- internal, and external.
48 Internal services are "built-in" to samba -- there may be
49 functions that exist to provide the control and enumeration
50 functions. There certainly is information returned to be
51 displayed in the typical management console.
53 External services are those that can be specified in the smb.conf
54 file -- and they conform to the LSB specification as to having
55 particular keywords in the scripts. Note that these "scripts" are
56 located in the lib directory, and are likely links to LSB-compliant
57 init.d scripts, such as those that might come with Suse. Note
58 that the spec is located http://www.linuxbase.org/spec/ */
62 /* Expand this to include what can and can't be done
63 with a particular internal service. Expand as necessary
64 to add other infromation like what can be controlled,
67 typedef struct Internal_service_struct
69 const char *filename; /* internal name "index" */
70 const char *displayname;
71 const char *description;
72 const uint32 statustype;
75 } Internal_service_description;
78 static const Internal_service_description ISD[] = {
79 { "NETLOGON", "Net Logon", "Provides logon and authentication service to the network", 0x110, NULL, NULL},
80 { "Spooler", "Spooler", "Printing Services", 0x0020, NULL, NULL},
81 { NULL, NULL, NULL, 0, NULL, NULL}
85 /********************************************************************
87 (a) get and set security descriptors on services
88 (b) read and write QUERY_SERVICE_CONFIG structures (both kinds, country and western)
89 (c) create default secdesc objects for services and SCM
90 (d) check access control masks with se_access_check()
91 ********************************************************************/
94 /*********************************************************************
95 given a service nice name, find the underlying service name
96 *********************************************************************/
98 static BOOL convert_service_displayname(TDB_CONTEXT *stdb,pstring service_nicename, pstring servicename,int szsvcname)
103 if ((stdb == NULL) || (service_nicename==NULL) || (servicename == NULL))
106 pstr_sprintf(keystring,"SERVICE_NICENAME/%s", servicename);
108 DEBUG(5, ("convert_service_displayname: Looking for service name [%s], key [%s]\n",
109 service_nicename, keystring));
111 key_data = tdb_fetch_bystring(stdb,keystring);
113 if (key_data.dsize == 0) {
114 DEBUG(5, ("convert_service_displayname: [%s] Not found, tried key [%s]\n",service_nicename,keystring));
118 strncpy(servicename,key_data.dptr,szsvcname);
119 servicename[(key_data.dsize > szsvcname ? szsvcname : key_data.dsize)] = 0;
120 DEBUG(5, ("convert_service_displayname: Found service name [%s], name is [%s]\n",
121 service_nicename,servicename));
127 /*******************************************************************************
128 Get the INTERNAL services information for the given service name.
129 *******************************************************************************/
131 static BOOL get_internal_service_data(const Internal_service_description *isd, Service_info *si)
136 pstrcpy( si->servicename, isd->displayname);
137 pstrcpy( si->servicetype, "INTERNAL");
138 pstrcpy( si->filename, isd->filename);
139 pstrcpy( si->provides, isd->displayname);
140 pstrcpy( si->description, isd->description);
141 pstrcpy( si->shortdescription, isd->description);
148 /*******************************************************************************
149 Get the services information by reading and parsing the shell scripts. These
150 are symbolically linked into the SVCCTL_SCRIPT_DIR directory.
152 Get the names of the services/scripts to read from the smb.conf file.
153 *******************************************************************************/
155 static BOOL get_LSB_data(char *fname,Service_info *si )
159 const char *tokenptr;
162 int nlines, *numlines,i,in_section,in_description;
164 pstrcpy(si->servicename,"");
165 pstrcpy(si->servicetype,"EXTERNAL");
166 pstrcpy(si->filename,fname);
167 pstrcpy(si->provides,"");
168 pstrcpy(si->dependencies,"");
169 pstrcpy(si->shouldstart,"");
170 pstrcpy(si->shouldstop,"");
171 pstrcpy(si->requiredstart,"");
172 pstrcpy(si->requiredstop,"");
173 pstrcpy(si->description,"");
174 pstrcpy(si->shortdescription,"");
181 if( !fname || !*fname ) {
182 DEBUG(0, ("Must define an \"LSB-style init file\" to read.\n"));
185 pstrcpy(initdfile,dyn_LIBDIR);
186 pstrcat(initdfile,SVCCTL_SCRIPT_DIR);
187 pstrcat(initdfile,fname);
189 /* TODO - should check to see if the file that we're trying to open is
190 actually a script. If it's NOT, we should do something like warn,
191 and not continue to try to find info we're looking for */
193 DEBUG(10, ("Opening [%s]\n", initdfile));
195 fd = open(initdfile,O_RDONLY);
199 DEBUG(10, ("Couldn't open [%s]\n", initdfile));
203 qlines = fd_lines_load(fd, numlines);
204 DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
210 for(i = 0; i < *numlines; i++) {
212 DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
213 if (!in_section && (0==strwicmp("### BEGIN INIT INFO", qlines[i]))) {
214 /* we now can look for params */
215 DEBUGADD(10, ("Configuration information starts on line = [%d]\n", i));
218 } else if (in_section && (0==strwicmp("### END INIT INFO", qlines[i]))) {
219 DEBUGADD(10, ("Configuration information ends on line = [%d]\n", i));
220 DEBUGADD(10, ("Description is [%s]\n", si->description));
224 } else if (in_section) {
225 tokenptr = qlines[i];
226 if (in_description) {
227 DEBUGADD(10, ("Processing DESCRIPTION [%d]\n", *tokenptr));
228 if (tokenptr && (*tokenptr=='#') && (*(tokenptr+1)=='\t')) {
229 DEBUGADD(10, ("Adding to DESCRIPTION [%d]\n", *tokenptr));
230 pstrcat(si->description," ");
231 pstrcat(si->description,tokenptr+2);
235 DEBUGADD(10, ("Not a description!\n"));
237 if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
238 DEBUGADD(10, ("Invalid line [%d]\n", i));
239 break; /* bad line? */
241 if (0 != strncmp(mybuffer,"#",1)) {
242 DEBUGADD(10, ("Invalid line [%d], is %s\n", i,mybuffer));
245 if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
246 DEBUGADD(10, ("Invalid token on line [%d]\n", i));
247 break; /* bad line? */
249 DEBUGADD(10, ("Keyword is [%s]\n", mybuffer));
250 if (0==strwicmp(mybuffer,"Description:")) {
251 while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) {
254 pstrcpy(si->description,tokenptr);
255 DEBUGADD(10, ("FOUND DESCRIPTION! Data is [%s]\n", tokenptr));
258 while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) {
261 DEBUGADD(10, ("Data is [%s]\n", tokenptr));
264 /* save certain keywords, don't save others */
265 if (0==strwicmp(mybuffer, "Provides:")) {
266 pstrcpy(si->provides,tokenptr);
267 pstrcpy(si->servicename,tokenptr);
270 if (0==strwicmp(mybuffer, "Short-Description:")) {
271 pstrcpy(si->shortdescription,tokenptr);
274 if (0==strwicmp(mybuffer, "Required-start:")) {
275 pstrcpy(si->requiredstart,tokenptr);
276 pstrcpy(si->dependencies,tokenptr);
279 if (0==strwicmp(mybuffer, "Should-start:")) {
280 pstrcpy(si->shouldstart,tokenptr);
286 file_lines_free(qlines);
293 /********************************************************************
294 ********************************************************************/
296 static BOOL get_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si)
302 if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0))
305 /* TODO - error handling -- what if the service isn't in the DB? */
307 pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name);
308 key_data = tdb_fetch_bystring(stdb,keystring);
309 strncpy(si->servicetype,key_data.dptr,key_data.dsize);
310 si->servicetype[key_data.dsize] = 0;
312 /* crude check to see if the service exists... */
313 DEBUG(3,("Size of the TYPE field is %d\n",key_data.dsize));
314 if (key_data.dsize == 0)
317 pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name);
318 key_data = tdb_fetch_bystring(stdb,keystring);
319 strncpy(si->filename,key_data.dptr,key_data.dsize);
320 si->filename[key_data.dsize] = 0;
322 pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name);
323 key_data = tdb_fetch_bystring(stdb,keystring);
324 strncpy(si->provides,key_data.dptr,key_data.dsize);
325 si->provides[key_data.dsize] = 0;
326 strncpy(si->servicename,key_data.dptr,key_data.dsize);
327 si->servicename[key_data.dsize] = 0;
330 pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name);
331 key_data = tdb_fetch_bystring(stdb,keystring);
332 strncpy(si->dependencies,key_data.dptr,key_data.dsize);
333 si->dependencies[key_data.dsize] = 0;
335 pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name);
336 key_data = tdb_fetch_bystring(stdb,keystring);
337 strncpy(si->shouldstart,key_data.dptr,key_data.dsize);
338 si->shouldstart[key_data.dsize] = 0;
340 pstr_sprintf(keystring,"SERVICE/%s/SHOULD_STOP", service_name);
341 key_data = tdb_fetch_bystring(stdb,keystring);
342 strncpy(si->shouldstop,key_data.dptr,key_data.dsize);
343 si->shouldstop[key_data.dsize] = 0;
345 pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name);
346 key_data = tdb_fetch_bystring(stdb,keystring);
347 strncpy(si->requiredstart,key_data.dptr,key_data.dsize);
348 si->requiredstart[key_data.dsize] = 0;
350 pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name);
351 key_data = tdb_fetch_bystring(stdb,keystring);
352 strncpy(si->requiredstop,key_data.dptr,key_data.dsize);
353 si->requiredstop[key_data.dsize] = 0;
355 pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name);
356 key_data = tdb_fetch_bystring(stdb,keystring);
357 strncpy(si->description,key_data.dptr,key_data.dsize);
358 si->description[key_data.dsize] = 0;
360 pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name);
361 key_data = tdb_fetch_bystring(stdb,keystring);
362 strncpy(si->shortdescription,key_data.dptr,key_data.dsize);
363 si->shortdescription[key_data.dsize] = 0;
368 /*********************************************************************
369 *********************************************************************/
371 static BOOL store_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si)
375 /* Note -- when we write to the tdb, we "index" on the filename
376 field, not the nice name. when a service is "opened", it is
377 opened by the nice (SERVICENAME) name, not the file name.
378 So there needs to be a mapping from nice name back to the file name. */
380 if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0))
384 /* Store the nicename */
386 pstr_sprintf(keystring,"SERVICE_NICENAME/%s", si->servicename);
387 tdb_store_bystring(stdb,keystring,string_tdb_data(service_name),TDB_REPLACE);
389 pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name);
390 tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicetype),TDB_REPLACE);
392 pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name);
393 tdb_store_bystring(stdb,keystring,string_tdb_data(si->filename),TDB_REPLACE);
395 pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name);
396 tdb_store_bystring(stdb,keystring,string_tdb_data(si->provides),TDB_REPLACE);
398 pstr_sprintf(keystring,"SERVICE/%s/SERVICENAME", service_name);
399 tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicename),TDB_REPLACE);
401 pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name);
402 tdb_store_bystring(stdb,keystring,string_tdb_data(si->dependencies),TDB_REPLACE);
404 pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name);
405 tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstart),TDB_REPLACE);
407 pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTOP", service_name);
408 tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstop),TDB_REPLACE);
410 pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name);
411 tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstart),TDB_REPLACE);
413 pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name);
414 tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstop),TDB_REPLACE);
416 pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name);
417 tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE);
419 pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name);
420 tdb_lock_bystring(stdb, keystring, 0);
421 if (si->shortdescription && *si->shortdescription)
422 tdb_store_bystring(stdb,keystring,string_tdb_data(si->shortdescription),TDB_REPLACE);
424 tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE);
429 /********************************************************************
430 allocate an array of external services and return them. Null return
431 is okay, make sure &added is also zero!
432 ********************************************************************/
434 static int num_external_services(void)
438 pstring keystring, external_services_string;
443 DEBUG(8,("enum_external_services: service database is not open!!!\n"));
446 pstrcpy(keystring,"EXTERNAL_SERVICES");
447 tdb_lock_bystring(service_tdb, keystring, 0);
448 key_data = tdb_fetch_bystring(service_tdb, keystring);
450 if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
451 strncpy(external_services_string,key_data.dptr,key_data.dsize);
452 external_services_string[key_data.dsize] = 0;
453 DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize));
455 tdb_unlock_bystring(service_tdb, keystring);
457 svc_list = str_list_make(external_services_string,NULL);
459 num_services = str_list_count( (const char **)svc_list);
466 /********************************************************************
467 Gather information on the "external services". These are services
468 listed in the smb.conf file, and found to exist through checks in
469 this code. Note that added will be incremented on the basis of the
470 number of services added. svc_ptr should have enough memory allocated
471 to accommodate all of the services that exist.
473 Typically num_external_services is used to "size" the amount of
474 memory allocated, but does little/no work.
476 enum_external_services() actually examines each of the specified
477 external services, populates the memory structures, and returns.
479 ** note that 'added' may end up with less than the number of services
480 found in _num_external_services, such as the case when a service is
481 called out, but the actual service doesn't exist or the file can't be
482 read for the service information.
483 ********************************************************************/
485 static WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services,int *added)
487 /* *svc_ptr must have pre-allocated memory */
488 int num_services = 0;
490 ENUM_SERVICES_STATUS *services=NULL;
491 char **svc_list,**svcname;
492 pstring command, keystring, external_services_string;
498 *added = num_services;
501 DEBUG(8,("enum_external_services: service database is not open!!!\n"));
503 pstrcpy(keystring,"EXTERNAL_SERVICES");
504 tdb_lock_bystring(service_tdb, keystring, 0);
505 key_data = tdb_fetch_bystring(service_tdb, keystring);
506 if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
507 strncpy(external_services_string,key_data.dptr,key_data.dsize);
508 external_services_string[key_data.dsize] = 0;
509 DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize));
511 tdb_unlock_bystring(service_tdb, keystring);
513 svc_list = str_list_make(external_services_string,NULL);
515 num_services = str_list_count( (const char **)svc_list);
517 if (0 == num_services) {
518 DEBUG(8,("enum_external_services: there are no external services\n"));
519 *added = num_services;
522 DEBUG(8,("enum_external_services: there are [%d] external services\n",num_services));
523 si=TALLOC_ARRAY( tcx, Service_info, 1 );
525 DEBUG(8,("enum_external_services: Failed to alloc si\n"));
530 /* *svc_ptr has the pointer to the array if there is one already. NULL if not. */
531 if ((existing_services>0) && svc_ptr && *svc_ptr) { /* reallocate vs. allocate */
532 DEBUG(8,("enum_external_services: REALLOCing %x to %d services\n", *svc_ptr, existing_services+num_services));
534 services=TALLOC_REALLOC_ARRAY(tcx,*svc_ptr,ENUM_SERVICES_STATUS,existing_services+num_services);
535 DEBUG(8,("enum_external_services: REALLOCed to %x services\n", services));
537 if (!services) return WERR_NOMEM;
540 if ( !(services = TALLOC_ARRAY( tcx, ENUM_SERVICES_STATUS, num_services )) )
545 if (!svc_ptr || !(*svc_ptr))
548 if (existing_services > 0) {
549 i+=existing_services;
553 DEBUG(8,("enum_external_services: enumerating %d external services starting at index %d\n", num_services,existing_services));
556 DEBUG(10,("enum_external_services: Reading information on service %s, index %d\n",*svcname,i));
557 /* get_LSB_data(*svcname,si); */
558 if (!get_service_info(service_tdb,*svcname, si)) {
559 DEBUG(1,("enum_external_services: CAN'T FIND INFO FOR SERVICE %s in the services DB\n",*svcname));
562 if ((si->filename == NULL) || (*si->filename == 0)) {
563 init_unistr(&services[i].servicename, *svcname );
565 init_unistr( &services[i].servicename, si->filename );
566 /* init_unistr( &services[i].servicename, si->servicename ); */
569 if ((si->provides == NULL) || (*si->provides == 0)) {
570 init_unistr(&services[i].displayname, *svcname );
572 init_unistr( &services[i].displayname, si->provides );
575 /* TODO - we could keep the following info in the DB, too... */
577 DEBUG(8,("enum_external_services: Service name [%s] displayname [%s]\n",
578 si->filename, si->provides));
579 services[i].status.type = SVCCTL_WIN32_OWN_PROC;
580 services[i].status.win32_exit_code = 0x0;
581 services[i].status.service_exit_code = 0x0;
582 services[i].status.check_point = 0x0;
583 services[i].status.wait_hint = 0x0;
585 /* TODO - do callout here to get the status */
587 memset(command, 0, sizeof(command));
588 slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, *svcname, "status");
590 DEBUG(10, ("enum_external_services: status command is [%s]\n", command));
592 /* TODO - wrap in privilege check */
594 ret = smbrun(command, &fd);
595 DEBUGADD(10, ("returned [%d]\n", ret));
598 DEBUG(10, ("enum_external_services: Command returned [%d]\n", ret));
599 services[i].status.state = SVCCTL_STOPPED;
601 services[i].status.state = SVCCTL_RUNNING;
602 services[i].status.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP;
604 services[i].status.state = SVCCTL_STOPPED;
605 services[i].status.controls_accepted = 0;
611 DEBUG(10,("enum_external_services: Read services %d\n",num_services));
612 *added = num_services;
617 int num_internal_services(void)
621 pstring keystring, internal_services_string;
625 DEBUG(8,("enum_internal_services: service database is not open!!!\n"));
628 pstrcpy(keystring,"INTERNAL_SERVICES");
629 tdb_lock_bystring(service_tdb, keystring, 0);
630 key_data = tdb_fetch_bystring(service_tdb, keystring);
632 if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
633 strncpy(internal_services_string,key_data.dptr,key_data.dsize);
634 internal_services_string[key_data.dsize] = 0;
635 DEBUG(8,("enum_internal_services: services list is %s, size is %d\n",internal_services_string,key_data.dsize));
637 tdb_unlock_bystring(service_tdb, keystring);
639 svc_list = str_list_make(internal_services_string,NULL);
641 num_services = str_list_count( (const char **)svc_list);
646 /****************************************************************************
647 Create/Open the service control manager tdb. This code a clone of init_group_mapping.
648 ****************************************************************************/
650 BOOL init_svcctl_db(void)
652 const char *vstring = "INFO/version";
657 pstring external_service_list;
658 pstring internal_service_list;
660 const Internal_service_description *isd_ptr;
661 /* svc_list = str_list_make( "etc/init.d/skeleton etc/init.d/syslog", NULL ); */
662 svc_list=(char **)lp_enable_svcctl();
667 pstrcpy(external_service_list,"");
669 service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
671 DEBUG(0,("Failed to open service db\n"));
672 service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
673 if (!service_tdb) return False;
674 DEBUG(0,("Created new services db\n"));
677 if ((-1 == tdb_fetch_uint32(service_tdb, vstring,&vers_id)) || (vers_id != SERVICEDB_VERSION_V1)) {
678 /* wrong version of DB, or db was just created */
679 tdb_traverse(service_tdb, tdb_traverse_delete_fn, NULL);
680 tdb_store_uint32(service_tdb, vstring, SERVICEDB_VERSION_V1);
682 tdb_unlock_bystring(service_tdb, vstring);
684 DEBUG(0,("Initializing services db\n"));
688 /* Get the EXTERNAL services as mentioned by line in smb.conf */
691 DEBUG(10,("Reading information on service %s\n",*svcname));
692 if (get_LSB_data(*svcname,&si));{
693 /* write the information to the TDB */
694 store_service_info(service_tdb,*svcname,&si);
695 /* definitely not efficient to do it this way. */
696 pstrcat(external_service_list,"\"");
697 pstrcat(external_service_list,*svcname);
698 pstrcat(external_service_list,"\" ");
702 pstrcpy(keystring,"EXTERNAL_SERVICES");
703 tdb_lock_bystring(service_tdb, keystring, 0);
704 DEBUG(8,("Storing external service list [%s]\n",external_service_list));
705 tdb_store_bystring(service_tdb,keystring,string_tdb_data(external_service_list),TDB_REPLACE);
706 tdb_unlock_bystring(service_tdb,keystring);
708 /* Get the INTERNAL services */
710 pstrcpy(internal_service_list,"");
713 while (isd_ptr && (isd_ptr->filename)) {
714 DEBUG(10,("Reading information on service %s\n",isd_ptr->filename));
715 if (get_internal_service_data(isd_ptr,&si)){
716 /* write the information to the TDB */
717 store_service_info(service_tdb,(char *)isd_ptr->filename,&si);
718 /* definitely not efficient to do it this way. */
719 pstrcat(internal_service_list,"\"");
720 pstrcat(internal_service_list,isd_ptr->filename);
721 pstrcat(internal_service_list,"\" ");
726 pstrcpy(keystring,"INTERNAL_SERVICES");
727 tdb_lock_bystring(service_tdb, keystring, 0);
728 DEBUG(8,("Storing internal service list [%s]\n",internal_service_list));
729 tdb_store_bystring(service_tdb,keystring,string_tdb_data(internal_service_list),TDB_REPLACE);
730 tdb_unlock_bystring(service_tdb,keystring);
735 /********************************************************************
736 ********************************************************************/
738 static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token,
739 uint32 access_desired, uint32 *access_granted )
743 /* maybe add privilege checks in here later */
745 se_access_check( sec_desc, token, access_desired, access_granted, &result );
750 /********************************************************************
751 ********************************************************************/
753 static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
762 /* basic access for Everyone */
764 init_sec_access(&mask, SC_MANAGER_READ_ACCESS );
765 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
767 /* Full Access 'BUILTIN\Administrators' */
769 init_sec_access(&mask,SC_MANAGER_ALL_ACCESS );
770 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
773 /* create the security descriptor */
775 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
778 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
784 /********************************************************************
785 ********************************************************************/
787 static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
796 /* basic access for Everyone */
798 init_sec_access(&mask, SERVICE_READ_ACCESS );
799 init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
801 init_sec_access(&mask,SERVICE_EXECUTE_ACCESS );
802 init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
804 init_sec_access(&mask,SERVICE_ALL_ACCESS );
805 init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
806 init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
808 /* create the security descriptor */
810 if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
813 if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
819 /******************************************************************
820 free() function for REGISTRY_KEY
821 *****************************************************************/
823 static void free_service_handle_info(void *ptr)
825 SERVICE_INFO *info = (SERVICE_INFO*)ptr;
827 SAFE_FREE(info->name);
831 /******************************************************************
832 Find a registry key handle and return a SERVICE_INFO
833 *****************************************************************/
835 static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd)
837 SERVICE_INFO *service_info = NULL;
839 if( !find_policy_by_hnd( p, hnd, (void **)&service_info) ) {
840 DEBUG(2,("find_service_info_by_hnd: handle not found"));
847 /******************************************************************
848 *****************************************************************/
850 static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle,
851 const char *service, uint32 access_granted )
853 SERVICE_INFO *info = NULL;
855 if ( !(info = SMB_MALLOC_P( SERVICE_INFO )) )
858 ZERO_STRUCTP( info );
860 /* the Service Manager has a NULL name */
863 info->type = SVC_HANDLE_IS_SCM;
865 info->type = SVC_HANDLE_IS_SERVICE;
867 if ( !(info->name = SMB_STRDUP( service )) ) {
868 free_service_handle_info( info );
873 /* lookup the SERVICE_CONTROL_OPS */
875 for ( i=0; svcctl_ops[i].name; i++ ) {
881 info->access_granted = access_granted;
883 /* store the SERVICE_INFO and create an open handle */
885 if ( !create_policy_hnd( p, handle, free_service_handle_info, info ) ) {
886 free_service_handle_info( info );
887 return WERR_ACCESS_DENIED;
893 /********************************************************************
894 ********************************************************************/
896 WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u)
899 uint32 access_granted = 0;
902 /* perform access checks */
904 if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
907 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
908 if ( !NT_STATUS_IS_OK(status) )
909 return ntstatus_to_werror( status );
911 return create_open_service_handle( p, &r_u->handle, NULL, access_granted );
914 /********************************************************************
915 ********************************************************************/
917 WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u)
920 uint32 access_granted = 0;
923 SERVICE_INFO *scm_info;
925 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
927 DEBUG(5, ("_svcctl_open_service: Attempting to open Service [%s], \n", service));
930 /* based on my tests you can open a service if you have a valid scm handle */
932 if ( !(scm_info = find_service_info_by_hnd( p, &q_u->handle )) )
935 /* perform access checks */
937 if ( !(sec_desc = construct_service_sd( p->mem_ctx )) )
940 status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
941 if ( !NT_STATUS_IS_OK(status) )
942 return ntstatus_to_werror( status );
945 if ( ! get_service_info(service_tdb, service, info) ) {
946 return WERR_NO_SUCH_SERVICE;
949 return create_open_service_handle( p, &r_u->handle, service, access_granted );
952 /********************************************************************
953 ********************************************************************/
955 WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u)
957 return close_policy_hnd( p, &q_u->handle ) ? WERR_OK : WERR_BADFID;
960 /********************************************************************
961 ********************************************************************/
963 WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
967 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
969 /* can only use an SCM handle here */
971 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
974 rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
976 /* need a tdb lookup here or something */
978 fstrcpy( displayname, "FIX ME!" );
980 init_svcctl_r_get_display_name( r_u, displayname );
985 /********************************************************************
986 ********************************************************************/
988 WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u)
990 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
992 /* perform access checks */
994 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
997 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
998 return WERR_ACCESS_DENIED;
1000 r_u->svc_status.type = 0x0020;
1001 r_u->svc_status.state = 0x0004;
1002 r_u->svc_status.controls_accepted = 0x0005;
1008 /*********************************************************************
1009 TODO - for internal services, do similar to external services, except
1010 we have to call the right status routine...
1011 **********************************************************************/
1013 static WERROR enum_internal_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services, int *added)
1015 int num_services = 2;
1017 ENUM_SERVICES_STATUS *services=NULL;
1019 if (!svc_ptr || !(*svc_ptr))
1022 services = *svc_ptr;
1025 /* *svc_ptr has the pointer to the array if there is one already. NULL if not. */
1026 if ((existing_services>0) && svc_ptr && *svc_ptr) { /* reallocate vs. allocate */
1027 DEBUG(8,("enum_internal_services: REALLOCing %d services\n", num_services));
1028 services = TALLOC_REALLOC_ARRAY(tcx,*svc_ptr,ENUM_SERVICES_STATUS,existing_services+num_services);
1031 *svc_ptr = services;
1033 if ( !(services = TALLOC_ARRAY( tcx, ENUM_SERVICES_STATUS, num_services )) )
1038 if (existing_services > 0) {
1039 i += existing_services;
1041 DEBUG(8,("enum_internal_services: Creating %d services, starting index %d\n", num_services,existing_services));
1043 init_unistr( &services[i].servicename, "Spooler" );
1044 init_unistr( &services[i].displayname, "Print Spooler" );
1046 services[i].status.type = 0x110;
1047 services[i].status.controls_accepted = 0x0;
1048 services[i].status.win32_exit_code = 0x0;
1049 services[i].status.service_exit_code = 0x0;
1050 services[i].status.check_point = 0x0;
1051 services[i].status.wait_hint = 0x0;
1052 if ( !lp_disable_spoolss() )
1053 services[i].status.state = SVCCTL_RUNNING;
1055 services[i].status.state = SVCCTL_STOPPED;
1059 init_unistr( &services[i].servicename, "NETLOGON" );
1060 init_unistr( &services[i].displayname, "Net Logon" );
1062 services[i].status.type = 0x20;
1063 services[i].status.controls_accepted = 0x0;
1064 services[i].status.win32_exit_code = 0x0;
1065 services[i].status.service_exit_code = 0x0;
1066 services[i].status.check_point = 0x0;
1067 services[i].status.wait_hint = 0x0;
1068 if ( lp_servicenumber("NETLOGON") != -1 )
1069 services[i].status.state = SVCCTL_RUNNING;
1071 services[i].status.state = SVCCTL_STOPPED;
1073 *added = num_services;
1078 /********************************************************************
1079 ********************************************************************/
1081 WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
1083 ENUM_SERVICES_STATUS *services = NULL;
1084 uint32 num_int_services = 0;
1085 uint32 num_ext_services = 0;
1088 WERROR result = WERR_OK;
1089 WERROR ext_result = WERR_OK;
1090 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1092 /* perform access checks */
1094 if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
1097 if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) )
1098 return WERR_ACCESS_DENIED;
1100 /* num_services = str_list_count( lp_enable_svcctl() ); */
1102 /* here's where we'll read the db of external services */
1103 /* _svcctl_read_LSB_data(NULL,NULL); */
1104 /* init_svcctl_db(); */
1106 num_int_services = 0;
1108 num_int_services = num_internal_services();
1110 num_ext_services = num_external_services();
1112 if ( !(services = TALLOC_ARRAY(p->mem_ctx, ENUM_SERVICES_STATUS, num_int_services+num_ext_services )) )
1115 result = enum_internal_services(p->mem_ctx, &services, 0, &num_int_services);
1117 if (W_ERROR_IS_OK(result)) {
1118 DEBUG(8,("_svcctl_enum_services_status: Got %d internal services\n", num_int_services));
1121 ext_result=enum_external_services(p->mem_ctx, &services, num_int_services, &num_ext_services);
1123 if (W_ERROR_IS_OK(ext_result)) {
1124 DEBUG(8,("_svcctl_enum_services_status: Got %d external services\n", num_ext_services));
1127 DEBUG(8,("_svcctl_enum_services_status: total of %d services\n", num_int_services+num_ext_services));
1130 for (i=0;i<num_int_services+num_ext_services;i++) {
1131 buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
1135 buffer_size += buffer_size % 4;
1136 DEBUG(8,("_svcctl_enum_services_status: buffer size passed %d, we need %d\n",
1137 q_u->buffer_size, buffer_size));
1139 if (buffer_size > q_u->buffer_size ) {
1140 num_int_services = 0;
1141 num_ext_services = 0;
1142 result = WERR_MORE_DATA;
1145 rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);
1147 if ( W_ERROR_IS_OK(result) ) {
1148 for ( i=0; i<num_int_services+num_ext_services; i++ )
1149 svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
1152 r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
1153 r_u->returned = num_int_services+num_ext_services;
1155 if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
1163 /********************************************************************
1164 ********************************************************************/
1166 WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u)
1168 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1170 /* perform access checks */
1172 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1175 if ( !(info->access_granted & SC_RIGHT_SVC_START) )
1176 return WERR_ACCESS_DENIED;
1181 /********************************************************************
1182 ********************************************************************/
1184 WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u)
1186 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1188 /* perform access checks */
1189 /* we only support stop so don't get complicated */
1191 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1194 if ( q_u->control != SVCCTL_CONTROL_STOP )
1195 return WERR_ACCESS_DENIED;
1197 if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
1198 return WERR_ACCESS_DENIED;
1201 SERVICE_INFO *service_info;
1204 SERVICE_STATUS *service_status;
1207 /* need to find the service name by the handle that is open */
1208 handle = &(q_u->handle);
1210 service_info = find_service_info_by_hnd(p, handle);
1212 if (!service_info) {
1213 DEBUG(10, ("_svcctl_control_service : Can't find the service for the handle\n"));
1217 /* we return a SERVICE_STATUS structure if there's an error. */
1218 if ( !(service_status = TALLOC_ARRAY(p->mem_ctx, SERVICE_STATUS, 1 )) )
1221 DEBUG(10, ("_svcctl_control_service: Found service [%s], [%s]\n",
1222 service_info->servicename, service_info->filename));
1224 /* TODO - call the service config function here... */
1225 memset(command, 0, sizeof(command));
1226 if (q_u->control == SVCCTL_CONTROL_STOP) {
1227 slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR,
1228 service_info->filename, "stop");
1231 if (q_u->control == SVCCTL_CONTROL_PAUSE) {
1232 slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR,
1233 service_info->filename, "stop");
1236 if (q_u->control == SVCCTL_CONTROL_CONTINUE) {
1237 slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR,
1238 service_info->filename, "restart");
1241 DEBUG(10, ("_svcctl_control_service: status command is [%s]\n", command));
1243 /* TODO - wrap in privilege check */
1245 ret = smbrun(command, &fd);
1246 DEBUGADD(10, ("returned [%d]\n", ret));
1250 DEBUG(10, ("enum_external_services: Command returned [%d]\n", ret));
1252 /* SET all service_stats bits here...*/
1254 service_status->state = SVCCTL_RUNNING;
1255 service_status->controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP;
1257 service_status->state = SVCCTL_STOPPED;
1258 service_status->controls_accepted = 0;
1261 DEBUG(10, ("_svcctl_query_service_config: Should call the commFound service [%s], [%s]\n",service_info->servicename,service_info->filename));
1268 /********************************************************************
1269 ********************************************************************/
1271 WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u )
1273 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1275 /* perform access checks */
1277 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1280 if ( !(info->access_granted & SC_RIGHT_SVC_ENUMERATE_DEPENDENTS) )
1281 return WERR_ACCESS_DENIED;
1283 /* we have to set the outgoing buffer size to the same as the
1284 incoming buffer size (even in the case of failure */
1286 rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
1288 r_u->needed = q_u->buffer_size;
1290 /* no dependent services...basically a stub function */
1296 /********************************************************************
1297 ********************************************************************/
1299 WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u )
1301 SERVICE_STATUS_PROCESS ssp;
1303 SERVICE_INFO *service_info;
1305 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1307 /* perform access checks */
1309 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1312 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
1313 return WERR_ACCESS_DENIED;
1315 /* we have to set the outgoing buffer size to the same as the
1316 incoming buffer size (even in the case of failure */
1318 r_u->needed = q_u->buffer_size;
1320 /* need to find the service name by the handle that is open */
1321 handle = &(q_u->handle);
1324 /* get rid of the easy errors */
1326 if (q_u->info_level != SVC_STATUS_PROCESS_INFO) {
1327 DEBUG(10, ("_svcctl_query_service_status_ex : Invalid information level specified\n"));
1328 return WERR_UNKNOWN_LEVEL;
1331 service_info = find_service_info_by_hnd(p, handle);
1333 if (!service_info) {
1334 DEBUG(10, ("_svcctl_query_service_status_ex : Can't find the service for the handle\n"));
1338 if (r_u->needed < (sizeof(SERVICE_STATUS_PROCESS)+sizeof(uint32)+sizeof(uint32))) {
1339 DEBUG(10, ("_svcctl_query_service_status_ex : buffer size of [%d] is too small.\n",r_u->needed));
1340 return WERR_INSUFFICIENT_BUFFER;
1346 if (!strwicmp(service_info->servicetype,"EXTERNAL"))
1347 ssp.type = SVCCTL_WIN32_OWN_PROC;
1349 ssp.type = SVCCTL_WIN32_SHARED_PROC;
1352 /* Get the status of the service.. */
1354 memset(command, 0, sizeof(command));
1357 slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service_info->filename, "status");
1359 DEBUG(10, ("_svcctl_query_service_status_ex: status command is [%s]\n", command));
1361 /* TODO - wrap in privilege check */
1363 ret = smbrun(command, &fd);
1364 DEBUGADD(10, ("returned [%d]\n", ret));
1367 DEBUG(10, ("_svcctl_query_service_status_ex: Command returned [%d]\n", ret));
1369 /* SET all service_stats bits here... */
1371 ssp.state = SVCCTL_RUNNING;
1372 ssp.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP;
1374 ssp.state = SVCCTL_STOPPED;
1375 ssp.controls_accepted = 0;
1382 /********************************************************************
1383 ********************************************************************/
1385 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
1388 SERVICE_INFO *service_info;
1390 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1392 /* perform access checks */
1394 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1397 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
1398 return WERR_ACCESS_DENIED;
1400 /* we have to set the outgoing buffer size to the same as the
1401 incoming buffer size (even in the case of failure */
1403 r_u->needed = q_u->buffer_size;
1405 /* need to find the service name by the handle that is open */
1406 handle = &(q_u->handle);
1408 service_info = find_service_info_by_hnd(p, handle);
1411 if (q_u->buffer_size < sizeof(Service_info)) {
1412 /* have to report need more... */
1413 /* TODO worst case -- should actualy calc what we need here. */
1414 r_u->needed = sizeof(Service_info)+sizeof(pstring)*5;
1415 DEBUG(10, ("_svcctl_query_service_config: NOT ENOUGH BUFFER ALLOCATED FOR RETURN DATA -- provided %d wanted %d\n",
1416 q_u->buffer_size,r_u->needed));
1418 return WERR_INSUFFICIENT_BUFFER;
1421 if (!service_info) {
1422 DEBUG(10, ("_svcctl_query_service_config : Can't find the service for the handle\n"));
1427 if ( !(service_config = (SERVICE_CONFIG *)TALLOC_ZERO_P(p->mem_ctx, SERVICE_CONFIG)) )
1431 r_u->config.service_type = SVCCTL_WIN32_OWN_PROC;
1432 r_u->config.start_type = SVCCTL_DEMAND_START;
1433 r_u->config.error_control = SVCCTL_SVC_ERROR_IGNORE;
1434 r_u->config.tag_id = 0x00000000;
1436 /* Init the strings */
1438 r_u->config.executablepath = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1439 r_u->config.loadordergroup = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1440 r_u->config.dependencies = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1441 r_u->config.startname = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1442 r_u->config.displayname = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1445 pstrcpy(fullpathinfo,dyn_LIBDIR);
1446 pstrcat(fullpathinfo,SVCCTL_SCRIPT_DIR);
1447 pstrcat(fullpathinfo,service_info->filename);
1448 /* Get and calculate the size of the fields. Note that we're still building the fields in the "too-small buffer case"
1449 even though we throw it away. */
1451 DEBUG(10, ("_svcctl_query_service_config: fullpath info [%s]\n",fullpathinfo));
1452 init_unistr2(r_u->config.executablepath,fullpathinfo,UNI_STR_TERMINATE);
1453 init_unistr2(r_u->config.loadordergroup,"",UNI_STR_TERMINATE);
1454 init_unistr2(r_u->config.dependencies,service_info->dependencies,UNI_STR_TERMINATE);
1456 /* TODO - if someone really cares, perhaps "LocalSystem" should be changed to something else here... */
1458 init_unistr2(r_u->config.startname,"LocalSystem",UNI_STR_TERMINATE);
1459 init_unistr2(r_u->config.displayname,service_info->servicename,UNI_STR_TERMINATE);
1462 needed_size = 0x04 + sizeof(SERVICE_CONFIG)+ 2*(
1463 r_u->config.executablepath->uni_str_len +
1464 r_u->config.loadordergroup->uni_str_len +
1465 r_u->config.dependencies->uni_str_len +
1466 r_u->config.startname->uni_str_len +
1467 r_u->config.displayname->uni_str_len);
1469 DEBUG(10, ("_svcctl_query_service_config: ****** need to have a buffer of [%d], [%d] for struct \n",needed_size,
1470 sizeof(SERVICE_CONFIG)));
1471 DEBUG(10, ("\tsize of executable path : %d\n",r_u->config.executablepath->uni_str_len));
1472 DEBUG(10, ("\tsize of loadordergroup : %d\n", r_u->config.loadordergroup->uni_str_len));
1473 DEBUG(10, ("\tsize of dependencies : %d\n", r_u->config.dependencies->uni_str_len));
1474 DEBUG(10, ("\tsize of startname : %d\n", r_u->config.startname->uni_str_len));
1475 DEBUG(10, ("\tsize of displayname : %d\n", r_u->config.displayname->uni_str_len));
1477 if (q_u->buffer_size < needed_size) {
1478 /* have to report need more...*/
1479 r_u->needed = needed_size;
1480 DEBUG(10, ("_svcctl_query_service_config: ****** zeroing strings for return\n"));
1481 memset(&r_u->config,0,sizeof(SERVICE_CONFIG));
1482 DEBUG(10, ("_svcctl_query_service_config: Not enouh buffer provided for return -- provided %d wanted %d\n",
1483 q_u->buffer_size,needed_size));
1484 return WERR_INSUFFICIENT_BUFFER;
1490 /********************************************************************
1491 ********************************************************************/
1493 WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u )
1496 SERVICE_INFO *service_info;
1498 SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
1500 /* perform access checks */
1502 if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
1505 if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_CONFIG) )
1506 return WERR_ACCESS_DENIED;
1508 /* we have to set the outgoing buffer size to the same as the
1509 incoming buffer size (even in the case of failure */
1511 r_u->needed = q_u->buffer_size;
1512 r_u->description = NULL;
1513 r_u->returned = q_u->buffer_size;
1516 handle = &(q_u->handle);
1518 service_info = find_service_info_by_hnd(p, handle);
1520 if (!service_info) {
1521 DEBUG(10, ("_svcctl_query_service_config2 : Can't find the service for the handle\n"));
1526 TODO - perhaps move the RPC_DATA_BLOB into the R_QUERY_SERVICE_CONFIG structure, and to the processing in here, vs
1527 in the *r_query_config2 marshalling routine...
1530 level = q_u->info_level;
1533 if (SERVICE_CONFIG_DESCRIPTION == level) {
1534 if (service_info && service_info->shortdescription) {
1535 /* length of the string, plus the terminator... */
1536 string_buffer_size = strlen(service_info->shortdescription)+1;
1537 DEBUG(10, ("_svcctl_query_service_config: copying the description [%s] length [%d]\n",
1538 service_info->shortdescription,string_buffer_size));
1540 if (q_u->buffer_size >= ((string_buffer_size)*2+4)) {
1541 r_u->description = TALLOC_ZERO_P(p->mem_ctx, UNISTR2);
1542 if (!r_u->description) return WERR_NOMEM;
1543 init_unistr2(r_u->description,service_info->shortdescription,UNI_STR_TERMINATE);
1547 string_buffer_size = 0;
1549 DEBUG(10, ("_svcctl_query_service_config2: buffer needed is [%x], return buffer size is [%x]\n",
1550 string_buffer_size,q_u->buffer_size));
1551 if (((string_buffer_size)*2+4) > q_u->buffer_size) {
1552 r_u->needed = (string_buffer_size+1)*2+4;
1553 DEBUG(10, ("_svcctl_query_service_config2: INSUFFICIENT BUFFER\n"));
1554 return WERR_INSUFFICIENT_BUFFER;
1556 DEBUG(10, ("_svcctl_query_service_config2: returning ok, needed is [%x], buffer size is [%x]\n",
1557 r_u->needed,q_u->buffer_size));
1563 return WERR_ACCESS_DENIED;