1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Service Control Services (SVCCTL) RPC interface definition. 28 * This interface provides remote access to list SMF services 29 * from a Windows client. 30 * 31 * SVCCTL access is restricted to administrators: members of the 32 * Domain Admins or Administrators groups. 33 */ 34 #include <stdio.h> 35 #include <strings.h> 36 37 #include <smbsrv/ntstatus.h> 38 #include <smbsrv/nmpipes.h> 39 #include <smbsrv/mlsvc_util.h> 40 41 #include "svcctl_scm.h" 42 43 #define SVCCTL_OPENSVC_OP_UNIMPLEMENTED(S) \ 44 ((S) & SERVICE_CHANGE_CONFIG) || \ 45 ((S) & SERVICE_PAUSE_CONTINUE) || \ 46 ((S) & SERVICE_START) || \ 47 ((S) & SERVICE_STOP) || \ 48 ((S) & SERVICE_ENUMERATE_DEPENDENTS) 49 50 static int svcctl_s_Close(void *, struct mlrpc_xaction *); 51 static int svcctl_s_OpenManager(void *, struct mlrpc_xaction *); 52 static int svcctl_s_OpenService(void *, struct mlrpc_xaction *); 53 static int svcctl_s_QueryServiceStatus(void *, struct mlrpc_xaction *); 54 static int svcctl_s_QueryServiceConfig(void *, struct mlrpc_xaction *); 55 static int svcctl_s_EnumServicesStatus(void *, struct mlrpc_xaction *); 56 static int svcctl_s_GetServiceDisplayNameW(void *, struct mlrpc_xaction *); 57 static int svcctl_s_GetServiceKeyNameW(void *, struct mlrpc_xaction *); 58 static int svcctl_s_QueryServiceConfig2W(void *, struct mlrpc_xaction *); 59 60 static mlrpc_stub_table_t svcctl_stub_table[] = { 61 { svcctl_s_Close, SVCCTL_OPNUM_Close }, 62 { svcctl_s_OpenManager, SVCCTL_OPNUM_OpenManager }, 63 { svcctl_s_OpenService, SVCCTL_OPNUM_OpenService }, 64 { svcctl_s_QueryServiceStatus, SVCCTL_OPNUM_QueryServiceStatus }, 65 { svcctl_s_QueryServiceConfig, SVCCTL_OPNUM_QueryServiceConfig }, 66 { svcctl_s_EnumServicesStatus, SVCCTL_OPNUM_EnumServicesStatus }, 67 { svcctl_s_GetServiceDisplayNameW, 68 SVCCTL_OPNUM_GetServiceDisplayNameW }, 69 { svcctl_s_GetServiceKeyNameW, SVCCTL_OPNUM_GetServiceKeyNameW }, 70 { svcctl_s_QueryServiceConfig2W, SVCCTL_OPNUM_QueryServiceConfig2W }, 71 {0} 72 }; 73 74 static mlrpc_service_t svcctl_service = { 75 "SVCCTL", /* name */ 76 "Service Control Services", /* desc */ 77 "\\svcctl", /* endpoint */ 78 PIPE_NTSVCS, /* sec_addr_port */ 79 "367abb81-9844-35f1-ad3298f038001003", 2, /* abstract */ 80 "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer */ 81 0, /* no bind_instance_size */ 82 0, /* no bind_req() */ 83 0, /* no unbind_and_close() */ 84 0, /* use generic_call_stub() */ 85 &TYPEINFO(svcctl_interface), /* interface ti */ 86 svcctl_stub_table /* stub_table */ 87 }; 88 89 /* 90 * svcctl_initialize 91 * 92 * This function registers the SVCCTL RPC interface with the RPC runtime 93 * library. It must be called in order to use either the client side 94 * or the server side functions. 95 */ 96 void 97 svcctl_initialize(void) 98 { 99 (void) mlrpc_register_service(&svcctl_service); 100 } 101 102 /* 103 * svcctl_hdlookup 104 * 105 * Handle lookup wrapper to validate the local service and/or manager context. 106 */ 107 static ndr_handle_t * 108 svcctl_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, svcctl_context_type_t type) 109 { 110 ndr_handle_t *hd; 111 svcctl_context_t *ctx; 112 113 if ((hd = ndr_hdlookup(mxa, id)) == NULL) 114 return (NULL); 115 116 if ((ctx = (svcctl_context_t *)hd->nh_data) == NULL) 117 return (NULL); 118 119 if ((ctx->c_type != type) || (ctx->c_ctx.uc_cp == NULL)) 120 return (NULL); 121 122 return (hd); 123 } 124 125 /* 126 * svcctl_hdfree 127 * 128 * Handle deallocation wrapper to free the local service and/or manager context. 129 */ 130 static void 131 svcctl_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id) 132 { 133 ndr_handle_t *hd; 134 svcctl_context_t *ctx; 135 svcctl_manager_context_t *mgr_ctx; 136 svcctl_service_context_t *svc_ctx; 137 138 if ((hd = ndr_hdlookup(mxa, id)) != NULL) { 139 ctx = (svcctl_context_t *)hd->nh_data; 140 141 switch (ctx->c_type) { 142 case SVCCTL_MANAGER_CONTEXT: 143 mgr_ctx = ctx->c_ctx.uc_mgr; 144 svcctl_scm_fini(mgr_ctx); 145 svcctl_scm_scf_handle_fini(mgr_ctx); 146 free(mgr_ctx); 147 break; 148 149 case SVCCTL_SERVICE_CONTEXT: 150 svc_ctx = ctx->c_ctx.uc_svc; 151 free(svc_ctx->sc_mgrid); 152 free(svc_ctx->sc_svcname); 153 free(svc_ctx); 154 break; 155 156 default: 157 break; 158 } 159 160 free(ctx); 161 ndr_hdfree(mxa, id); 162 } 163 } 164 165 /* 166 * svcctl_mgr_hdalloc 167 * 168 * Handle allocation wrapper to setup the local manager context. 169 */ 170 static ndr_hdid_t * 171 svcctl_mgr_hdalloc(ndr_xa_t *mxa) 172 { 173 svcctl_context_t *ctx; 174 svcctl_manager_context_t *mgr_ctx; 175 176 if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL) 177 return (NULL); 178 ctx->c_type = SVCCTL_MANAGER_CONTEXT; 179 180 if ((mgr_ctx = malloc(sizeof (svcctl_manager_context_t))) == NULL) { 181 free(ctx); 182 return (NULL); 183 } 184 bzero(mgr_ctx, sizeof (svcctl_manager_context_t)); 185 186 if (svcctl_scm_scf_handle_init(mgr_ctx) < 0) { 187 free(mgr_ctx); 188 free(ctx); 189 return (NULL); 190 } 191 192 if (svcctl_scm_init(mgr_ctx) < 0) { 193 svcctl_scm_scf_handle_fini(mgr_ctx); 194 free(mgr_ctx); 195 free(ctx); 196 return (NULL); 197 } 198 199 ctx->c_ctx.uc_mgr = mgr_ctx; 200 201 return (ndr_hdalloc(mxa, ctx)); 202 } 203 204 /* 205 * svcctl_get_mgr_ctx 206 * 207 * This function looks up a reference to local manager context. 208 */ 209 static svcctl_manager_context_t * 210 svcctl_get_mgr_ctx(ndr_xa_t *mxa, ndr_hdid_t *mgr_id) 211 { 212 ndr_handle_t *hd; 213 svcctl_manager_context_t *mgr_ctx; 214 215 hd = svcctl_hdlookup(mxa, mgr_id, SVCCTL_MANAGER_CONTEXT); 216 if (hd == NULL) 217 return (NULL); 218 219 mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr; 220 221 return (mgr_ctx); 222 } 223 224 /* 225 * svcctl_svc_hdalloc 226 * 227 * Handle allocation wrapper to setup the local service context. 228 */ 229 static ndr_hdid_t * 230 svcctl_svc_hdalloc(ndr_xa_t *mxa, ndr_hdid_t *mgr_id, char *svc_name) 231 { 232 svcctl_context_t *ctx; 233 svcctl_service_context_t *svc_ctx; 234 svcctl_manager_context_t *mgr_ctx; 235 int max_name_sz = 0; 236 char *svcname; 237 238 mgr_ctx = svcctl_get_mgr_ctx(mxa, mgr_id); 239 if (mgr_ctx == NULL) 240 return (NULL); 241 max_name_sz = mgr_ctx->mc_scf_max_fmri_len; 242 243 if ((ctx = malloc(sizeof (svcctl_context_t))) == NULL) { 244 svcctl_hdfree(mxa, mgr_id); 245 return (NULL); 246 } 247 ctx->c_type = SVCCTL_SERVICE_CONTEXT; 248 249 if ((svc_ctx = malloc(sizeof (svcctl_service_context_t))) == NULL) { 250 svcctl_hdfree(mxa, mgr_id); 251 free(ctx); 252 return (NULL); 253 } 254 bzero(svc_ctx, sizeof (svcctl_service_context_t)); 255 256 svc_ctx->sc_mgrid = malloc(sizeof (ndr_hdid_t)); 257 svcname = malloc(max_name_sz); 258 259 if ((svc_ctx->sc_mgrid == NULL) || (svcname == NULL)) { 260 free(svc_ctx->sc_mgrid); 261 free(svc_ctx); 262 svcctl_hdfree(mxa, mgr_id); 263 free(ctx); 264 return (NULL); 265 } 266 267 svc_ctx->sc_svcname = svcname; 268 269 bcopy(mgr_id, svc_ctx->sc_mgrid, sizeof (ndr_hdid_t)); 270 (void) strlcpy(svc_ctx->sc_svcname, svc_name, max_name_sz); 271 272 ctx->c_ctx.uc_svc = svc_ctx; 273 274 return (ndr_hdalloc(mxa, ctx)); 275 } 276 277 /* 278 * svcctl_s_Close 279 * 280 * This is a request to close the SVCCTL interface specified by the 281 * handle. Free the handle and zero out the result handle for the 282 * client. 283 * 284 * Returns: 285 * ERROR_SUCCESS 286 * ERROR_INVALID_HANDLE 287 */ 288 static int 289 svcctl_s_Close(void *arg, struct mlrpc_xaction *mxa) 290 { 291 struct svcctl_Close *param = arg; 292 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle; 293 294 svcctl_hdfree(mxa, id); 295 296 bzero(¶m->result_handle, sizeof (svcctl_handle_t)); 297 param->status = ERROR_SUCCESS; 298 return (MLRPC_DRC_OK); 299 } 300 301 /* 302 * svcctl_s_OpenManager 303 * 304 * Request to open the service control manager. 305 * The caller must have administrator rights in order to open this 306 * interface. We don't support write (SC_MANAGER_LOCK) access. 307 * 308 * Returns: 309 * ERROR_SUCCESS 310 * ERROR_ACCESS_DENIED 311 * 312 * On success, returns a handle for use with subsequent svcctl requests. 313 */ 314 static int 315 svcctl_s_OpenManager(void *arg, struct mlrpc_xaction *mxa) 316 { 317 struct svcctl_OpenManager *param = arg; 318 ndr_hdid_t *id = NULL; 319 int rc; 320 321 rc = ndr_is_admin(mxa); 322 323 if ((rc == 0) || (param->desired_access & SC_MANAGER_LOCK) != 0) { 324 bzero(¶m->handle, sizeof (svcctl_handle_t)); 325 param->status = ERROR_ACCESS_DENIED; 326 return (MLRPC_DRC_OK); 327 } 328 329 id = svcctl_mgr_hdalloc(mxa); 330 if (id) { 331 bcopy(id, ¶m->handle, sizeof (svcctl_handle_t)); 332 param->status = ERROR_SUCCESS; 333 } else { 334 bzero(¶m->handle, sizeof (svcctl_handle_t)); 335 param->status = ERROR_ACCESS_DENIED; 336 } 337 338 return (MLRPC_DRC_OK); 339 } 340 341 /* 342 * svcctl_s_OpenService 343 * 344 * Return a handle for use with subsequent svcctl requests. 345 * 346 * Returns: 347 * ERROR_SUCCESS 348 * ERROR_INVALID_HANDLE 349 * ERROR_SERVICE_DOES_NOT_EXIST 350 * ERROR_CALL_NOT_IMPLEMENTED 351 */ 352 static int 353 svcctl_s_OpenService(void *arg, struct mlrpc_xaction *mxa) 354 { 355 struct svcctl_OpenService *param = arg; 356 ndr_hdid_t *mgrid = (ndr_hdid_t *)¶m->manager_handle; 357 ndr_hdid_t *id = NULL; 358 ndr_handle_t *hd; 359 DWORD status; 360 svcctl_manager_context_t *mgr_ctx; 361 char *svc_name = (char *)param->service_name; 362 boolean_t unimplemented_operations = B_FALSE; 363 364 /* Allow service handle allocations for only status & config queries */ 365 unimplemented_operations = 366 SVCCTL_OPENSVC_OP_UNIMPLEMENTED(param->desired_access); 367 368 if (unimplemented_operations) { 369 bzero(¶m->service_handle, sizeof (svcctl_handle_t)); 370 param->status = ERROR_CALL_NOT_IMPLEMENTED; 371 return (MLRPC_DRC_OK); 372 } 373 374 hd = svcctl_hdlookup(mxa, mgrid, SVCCTL_MANAGER_CONTEXT); 375 if (hd == NULL) { 376 bzero(¶m->service_handle, sizeof (svcctl_handle_t)); 377 param->status = ERROR_INVALID_HANDLE; 378 return (MLRPC_DRC_OK); 379 } 380 381 mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr; 382 status = svcctl_scm_validate_service(mgr_ctx, svc_name); 383 if (status != ERROR_SUCCESS) { 384 bzero(¶m->service_handle, sizeof (svcctl_handle_t)); 385 param->status = status; 386 return (MLRPC_DRC_OK); 387 } 388 389 id = svcctl_svc_hdalloc(mxa, mgrid, svc_name); 390 if (id) { 391 bcopy(id, ¶m->service_handle, sizeof (svcctl_handle_t)); 392 param->status = ERROR_SUCCESS; 393 } else { 394 bzero(¶m->service_handle, sizeof (svcctl_handle_t)); 395 param->status = ERROR_ACCESS_DENIED; 396 } 397 398 return (MLRPC_DRC_OK); 399 } 400 401 /* 402 * svcctl_s_QueryServiceStatus 403 * 404 * Returns: 405 * ERROR_SUCCESS 406 * ERROR_INVALID_HANDLE 407 */ 408 static int 409 svcctl_s_QueryServiceStatus(void *arg, struct mlrpc_xaction *mxa) 410 { 411 struct svcctl_QueryServiceStatus *param = arg; 412 ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; 413 ndr_handle_t *hd; 414 svcctl_manager_context_t *mgr_ctx; 415 svcctl_service_context_t *svc_ctx; 416 svcctl_svc_node_t *svc; 417 418 hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT); 419 if (hd == NULL) { 420 bzero(param, sizeof (struct svcctl_QueryServiceStatus)); 421 param->status = ERROR_INVALID_HANDLE; 422 return (MLRPC_DRC_OK); 423 } 424 425 svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc; 426 mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid); 427 if (mgr_ctx == NULL) { 428 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 429 param->status = ERROR_INVALID_HANDLE; 430 return (MLRPC_DRC_OK); 431 } 432 433 svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname); 434 if (svc == NULL || svc->sn_state == NULL) { 435 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 436 param->status = ERROR_SERVICE_DOES_NOT_EXIST; 437 return (MLRPC_DRC_OK); 438 } 439 440 param->service_status.service_type = SERVICE_WIN32_SHARE_PROCESS; 441 param->service_status.cur_state = svcctl_scm_map_status(svc->sn_state); 442 param->service_status.ctrl_accepted = 0; 443 param->service_status.w32_exitcode = 0; 444 param->service_status.svc_specified_exitcode = 0; 445 param->service_status.check_point = 0; 446 param->service_status.wait_hint = 0; 447 448 param->status = ERROR_SUCCESS; 449 return (MLRPC_DRC_OK); 450 } 451 452 /* 453 * svcctl_s_EnumServicesStatus 454 * 455 * Enumerate the list of services we support. Currently, this list 456 * is built in a fixed-size 1024 byte buffer - be careful not to 457 * over-run the buffer. 458 * 459 * Returns: 460 * ERROR_SUCCESS 461 * ERROR_INVALID_HANDLE 462 * ERROR_NOT_ENOUGH_MEMORY 463 */ 464 static int 465 svcctl_s_EnumServicesStatus(void *arg, struct mlrpc_xaction *mxa) 466 { 467 struct svcctl_EnumServicesStatus *param = arg; 468 ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; 469 ndr_handle_t *hd; 470 int input_bufsize = 0; 471 svcctl_manager_context_t *mgr_ctx; 472 473 hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT); 474 if (hd == NULL) { 475 bzero(param, sizeof (struct svcctl_EnumServicesStatus)); 476 param->services = MLRPC_HEAP_STRSAVE(mxa, ""); 477 param->status = ERROR_INVALID_HANDLE; 478 return (MLRPC_DRC_OK); 479 } 480 481 mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr; 482 if (svcctl_scm_refresh(mgr_ctx) != 0) { 483 bzero(param, sizeof (struct svcctl_EnumServicesStatus)); 484 param->status = ERROR_INVALID_DATA; 485 return (MLRPC_DRC_OK); 486 } 487 488 input_bufsize = param->buf_size; 489 param->services = MLRPC_HEAP_MALLOC(mxa, input_bufsize); 490 if (param->services == NULL) { 491 bzero(param, sizeof (struct svcctl_EnumServicesStatus)); 492 param->status = ERROR_NOT_ENOUGH_MEMORY; 493 return (MLRPC_DRC_OK); 494 } 495 bzero(param->services, input_bufsize); 496 497 if (input_bufsize <= mgr_ctx->mc_bytes_needed) { 498 param->bytes_needed = mgr_ctx->mc_bytes_needed; 499 param->svc_num = 0; 500 param->resume_handle = 0; 501 param->status = ERROR_MORE_DATA; 502 return (MLRPC_DRC_OK); 503 } 504 505 svcctl_scm_enum_services(mgr_ctx, param->services); 506 507 param->buf_size = input_bufsize; 508 param->bytes_needed = 0; 509 param->svc_num = mgr_ctx->mc_scf_numsvcs; 510 param->resume_handle = 0; 511 param->status = ERROR_SUCCESS; 512 return (MLRPC_DRC_OK); 513 } 514 515 /* 516 * svcctl_s_QueryServiceConfig 517 * 518 * Returns: 519 * ERROR_SUCCESS 520 * ERROR_INVALID_HANDLE 521 */ 522 static int 523 svcctl_s_QueryServiceConfig(void *arg, struct mlrpc_xaction *mxa) 524 { 525 struct svcctl_QueryServiceConfig *param = arg; 526 ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; 527 ndr_handle_t *hd; 528 svcctl_manager_context_t *mgr_ctx; 529 svcctl_service_context_t *svc_ctx; 530 svcctl_svc_node_t *svc; 531 int bytes_needed = 0; 532 svc_config_t *cfg; 533 534 hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT); 535 if (hd == NULL) { 536 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 537 param->status = ERROR_INVALID_HANDLE; 538 return (MLRPC_DRC_OK); 539 } 540 541 svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc; 542 mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid); 543 if (mgr_ctx == NULL) { 544 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 545 param->status = ERROR_INVALID_HANDLE; 546 return (MLRPC_DRC_OK); 547 } 548 549 svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname); 550 if (svc == NULL || svc->sn_fmri == NULL) { 551 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 552 param->status = ERROR_SERVICE_DOES_NOT_EXIST; 553 return (MLRPC_DRC_OK); 554 } 555 556 cfg = ¶m->service_cfg; 557 cfg->service_type = SERVICE_WIN32_SHARE_PROCESS; 558 cfg->start_type = SERVICE_AUTO_START; 559 cfg->error_control = SERVICE_AUTO_START; 560 cfg->binary_pathname = MLRPC_HEAP_STRSAVE(mxa, ""); 561 cfg->loadorder_group = MLRPC_HEAP_STRSAVE(mxa, ""); 562 cfg->tag_id = 0; 563 cfg->dependencies = MLRPC_HEAP_STRSAVE(mxa, ""); 564 cfg->service_startname = MLRPC_HEAP_STRSAVE(mxa, ""); 565 cfg->display_name = MLRPC_HEAP_STRSAVE(mxa, svc->sn_fmri); 566 567 bytes_needed = sizeof (svc_config_t); 568 bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->binary_pathname); 569 bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->loadorder_group); 570 bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->dependencies); 571 bytes_needed += SVCCTL_WNSTRLEN((const char *)cfg->service_startname); 572 bytes_needed += SVCCTL_WNSTRLEN(svc->sn_fmri); 573 574 if (param->buf_size < bytes_needed) { 575 bzero(param, sizeof (struct svcctl_QueryServiceConfig)); 576 param->cfg_bytes = bytes_needed; 577 param->status = ERROR_MORE_DATA; 578 return (MLRPC_DRC_OK); 579 } 580 581 param->cfg_bytes = bytes_needed; 582 param->status = ERROR_SUCCESS; 583 return (MLRPC_DRC_OK); 584 } 585 586 /* 587 * svcctl_s_GetServiceDisplayNameW 588 * 589 * Returns: 590 * ERROR_SUCCESS 591 * ERROR_INVALID_HANDLE 592 * ERROR_SERVICE_DOES_NOT_EXIST 593 */ 594 static int 595 svcctl_s_GetServiceDisplayNameW(void *arg, struct mlrpc_xaction *mxa) 596 { 597 struct svcctl_GetServiceDisplayNameW *param = arg; 598 ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; 599 ndr_handle_t *hd; 600 svcctl_svc_node_t *svc; 601 svcctl_manager_context_t *mgr_ctx; 602 603 hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT); 604 if (hd == NULL) { 605 bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW)); 606 param->display_name = MLRPC_HEAP_STRSAVE(mxa, ""); 607 param->status = ERROR_INVALID_HANDLE; 608 return (MLRPC_DRC_OK); 609 } 610 611 mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr; 612 svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name); 613 if (svc == NULL || svc->sn_fmri == NULL) { 614 bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW)); 615 param->display_name = MLRPC_HEAP_STRSAVE(mxa, ""); 616 param->status = ERROR_SERVICE_DOES_NOT_EXIST; 617 return (MLRPC_DRC_OK); 618 } 619 620 param->display_name = MLRPC_HEAP_STRSAVE(mxa, svc->sn_fmri); 621 if (param->display_name == NULL) { 622 bzero(param, sizeof (struct svcctl_GetServiceDisplayNameW)); 623 param->display_name = MLRPC_HEAP_STRSAVE(mxa, ""); 624 param->status = ERROR_NOT_ENOUGH_MEMORY; 625 return (MLRPC_DRC_OK); 626 } 627 628 param->buf_size = strlen(svc->sn_fmri); 629 param->status = ERROR_SUCCESS; 630 return (MLRPC_DRC_OK); 631 } 632 633 /* 634 * svcctl_s_GetServiceKeyNameW 635 * 636 * Returns: 637 * ERROR_SUCCESS 638 * ERROR_INVALID_HANDLE 639 * ERROR_SERVICE_DOES_NOT_EXIST 640 */ 641 static int 642 svcctl_s_GetServiceKeyNameW(void *arg, struct mlrpc_xaction *mxa) 643 { 644 struct svcctl_GetServiceKeyNameW *param = arg; 645 ndr_hdid_t *id = (ndr_hdid_t *)¶m->manager_handle; 646 ndr_handle_t *hd; 647 svcctl_svc_node_t *svc; 648 svcctl_manager_context_t *mgr_ctx; 649 650 hd = svcctl_hdlookup(mxa, id, SVCCTL_MANAGER_CONTEXT); 651 if (hd == NULL) { 652 bzero(param, sizeof (struct svcctl_GetServiceKeyNameW)); 653 param->key_name = MLRPC_HEAP_STRSAVE(mxa, ""); 654 param->status = ERROR_INVALID_HANDLE; 655 return (MLRPC_DRC_OK); 656 } 657 658 mgr_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_mgr; 659 svc = svcctl_scm_find_service(mgr_ctx, (char *)param->service_name); 660 if (svc == NULL || svc->sn_name == NULL) { 661 bzero(param, sizeof (struct svcctl_GetServiceKeyNameW)); 662 param->key_name = MLRPC_HEAP_STRSAVE(mxa, ""); 663 param->status = ERROR_SERVICE_DOES_NOT_EXIST; 664 return (MLRPC_DRC_OK); 665 } 666 667 param->key_name = MLRPC_HEAP_STRSAVE(mxa, svc->sn_name); 668 if (param->key_name == NULL) { 669 bzero(param, sizeof (struct svcctl_GetServiceKeyNameW)); 670 param->key_name = MLRPC_HEAP_STRSAVE(mxa, ""); 671 param->status = ERROR_NOT_ENOUGH_MEMORY; 672 return (MLRPC_DRC_OK); 673 } 674 675 param->buf_size = strlen(svc->sn_name); 676 param->status = ERROR_SUCCESS; 677 return (MLRPC_DRC_OK); 678 } 679 680 /* 681 * svcctl_s_QueryServiceConfig2W 682 * 683 * Returns: 684 * ERROR_SUCCESS 685 * ERROR_INVALID_HANDLE 686 * ERROR_INVALID_LEVEL 687 * ERROR_NOT_ENOUGH_MEMORY 688 */ 689 static int 690 svcctl_s_QueryServiceConfig2W(void *arg, struct mlrpc_xaction *mxa) 691 { 692 struct svcctl_QueryServiceConfig2W *param = arg; 693 ndr_hdid_t *id = (ndr_hdid_t *)¶m->service_handle; 694 ndr_handle_t *hd; 695 svcctl_manager_context_t *mgr_ctx; 696 svcctl_service_context_t *svc_ctx; 697 svcctl_svc_node_t *svc; 698 svc_description_t *svc_desc; 699 svc_failure_actions_t *fac; 700 int offset, input_bufsize, bytes_needed = 0; 701 mts_wchar_t *wide_desc; 702 char *desc; 703 DWORD status; 704 705 hd = svcctl_hdlookup(mxa, id, SVCCTL_SERVICE_CONTEXT); 706 if (hd == NULL) { 707 bzero(param, sizeof (struct svcctl_QueryServiceConfig2W)); 708 param->buffer = MLRPC_HEAP_STRSAVE(mxa, ""); 709 param->status = ERROR_INVALID_HANDLE; 710 return (MLRPC_DRC_OK); 711 } 712 713 input_bufsize = param->buf_size; 714 param->buffer = MLRPC_HEAP_MALLOC(mxa, input_bufsize); 715 if (param->buffer == NULL) { 716 bzero(param, sizeof (struct svcctl_QueryServiceConfig2W)); 717 param->status = ERROR_NOT_ENOUGH_MEMORY; 718 return (MLRPC_DRC_OK); 719 } 720 bzero(param->buffer, input_bufsize); 721 722 status = ERROR_SUCCESS; 723 switch (param->info_level) { 724 case SERVICE_CONFIG_DESCRIPTION: 725 svc_ctx = ((svcctl_context_t *)hd->nh_data)->c_ctx.uc_svc; 726 mgr_ctx = svcctl_get_mgr_ctx(mxa, svc_ctx->sc_mgrid); 727 if (mgr_ctx == NULL) { 728 param->status = ERROR_INVALID_HANDLE; 729 break; 730 } 731 732 svc = svcctl_scm_find_service(mgr_ctx, svc_ctx->sc_svcname); 733 if (svc == NULL || svc->sn_desc == NULL) { 734 status = ERROR_SERVICE_DOES_NOT_EXIST; 735 break; 736 } 737 738 desc = svc->sn_desc; 739 bytes_needed = SVCCTL_WNSTRLEN(desc); 740 741 if (input_bufsize <= bytes_needed) { 742 param->bytes_needed = bytes_needed; 743 param->status = ERROR_MORE_DATA; 744 return (MLRPC_DRC_OK); 745 } 746 747 offset = sizeof (svc_description_t); 748 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 749 svc_desc = (svc_description_t *)param->buffer; 750 svc_desc->desc = offset; 751 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 752 wide_desc = (mts_wchar_t *)¶m->buffer[offset]; 753 (void) mts_mbstowcs(wide_desc, desc, (strlen(desc) + 1)); 754 offset = SVCCTL_WNSTRLEN(desc); 755 756 param->bytes_needed = offset; 757 break; 758 759 case SERVICE_CONFIG_FAILURE_ACTIONS: 760 /*LINTED E_BAD_PTR_CAST_ALIGN*/ 761 fac = (svc_failure_actions_t *)param->buffer; 762 bzero(fac, sizeof (svc_failure_actions_t)); 763 764 param->bytes_needed = input_bufsize; 765 break; 766 767 default: 768 status = ERROR_INVALID_LEVEL; 769 break; 770 } 771 772 if (status != ERROR_SUCCESS) { 773 bzero(param, sizeof (struct svcctl_QueryServiceConfig2W)); 774 param->buffer = MLRPC_HEAP_STRSAVE(mxa, ""); 775 param->status = status; 776 return (MLRPC_DRC_OK); 777 } 778 779 param->status = ERROR_SUCCESS; 780 return (MLRPC_DRC_OK); 781 } 782