static NTSTATUS rpc_service_list_internal(struct net_context *c, const DOM_SID *domain_sid, const char *domain_name, struct cli_state *cli, struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, int argc, const char **argv ) { struct policy_handle hSCM; struct ENUM_SERVICE_STATUSW *services = NULL; WERROR result = WERR_GENERAL_FAILURE; NTSTATUS status; int i; uint8_t *buffer = NULL; uint32_t buf_size = 0; uint32_t bytes_needed = 0; uint32_t num_services = 0; uint32_t resume_handle = 0; if (argc != 0 ) { d_printf(_("Usage: net rpc service list\n")); return NT_STATUS_OK; } status = rpccli_svcctl_OpenSCManagerW(pipe_hnd, mem_ctx, pipe_hnd->srv_name_slash, NULL, SC_RIGHT_MGR_ENUMERATE_SERVICE, &hSCM, &result); if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) { d_fprintf(stderr, _("Failed to open Service Control Manager. [%s]\n"), win_errstr(result)); return werror_to_ntstatus(result); } do { status = rpccli_svcctl_EnumServicesStatusW(pipe_hnd, mem_ctx, &hSCM, SERVICE_TYPE_WIN32, SERVICE_STATE_ALL, buffer, buf_size, &bytes_needed, &num_services, &resume_handle, &result); if (NT_STATUS_IS_ERR(status)) { d_fprintf(stderr, _("Failed to enumerate services. [%s]\n"), win_errstr(result)); break; } if (W_ERROR_EQUAL(result, WERR_MORE_DATA) && bytes_needed > 0) { buffer = talloc_array(mem_ctx, uint8_t, bytes_needed); buf_size = bytes_needed; continue; } if ( num_services == 0 ) { d_printf(_("No services returned\n")); break; } { enum ndr_err_code ndr_err; DATA_BLOB blob; struct ndr_pull *ndr; blob.length = buf_size; blob.data = talloc_steal(mem_ctx, buffer); services = talloc_array(mem_ctx, struct ENUM_SERVICE_STATUSW, num_services); if (!services) { status = NT_STATUS_NO_MEMORY; break; } ndr = ndr_pull_init_blob(&blob, mem_ctx, NULL); if (ndr == NULL) { status = NT_STATUS_NO_MEMORY; break; } ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array( ndr, num_services, services); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); break; } for ( i=0; i<num_services; i++ ) { d_printf("%-20s \"%s\"\n", services[i].service_name, services[i].display_name); } } } while (W_ERROR_EQUAL(result, WERR_MORE_DATA)); rpccli_svcctl_CloseServiceHandle(pipe_hnd, mem_ctx, &hSCM, NULL); return status; }
static bool test_EnumServicesStatus(struct torture_context *tctx, struct dcerpc_pipe *p) { struct svcctl_EnumServicesStatusW r; struct policy_handle h; int i; NTSTATUS status; uint32_t resume_handle = 0; struct ENUM_SERVICE_STATUSW *service = NULL; uint32_t needed = 0; uint32_t services_returned = 0; if (!test_OpenSCManager(p, tctx, &h)) return false; r.in.handle = &h; r.in.type = SERVICE_TYPE_WIN32; r.in.state = SERVICE_STATE_ALL; r.in.offered = 0; r.in.resume_handle = &resume_handle; r.out.service = NULL; r.out.resume_handle = &resume_handle; r.out.services_returned = &services_returned; r.out.needed = &needed; status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!"); if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) { r.in.offered = needed; r.out.service = talloc_array(tctx, uint8_t, needed); status = dcerpc_svcctl_EnumServicesStatusW(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "EnumServicesStatus failed!"); torture_assert_werr_ok(tctx, r.out.result, "EnumServicesStatus failed"); } if (services_returned > 0) { enum ndr_err_code ndr_err; DATA_BLOB blob; struct ndr_pull *ndr; blob.length = r.in.offered; blob.data = talloc_steal(tctx, r.out.service); ndr = ndr_pull_init_blob(&blob, tctx, lp_iconv_convenience(tctx->lp_ctx)); service = talloc_array(tctx, struct ENUM_SERVICE_STATUSW, services_returned); if (!service) { return false; } ndr_err = ndr_pull_ENUM_SERVICE_STATUSW_array( ndr, services_returned, service); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; } } for(i = 0; i < services_returned; i++) { torture_assert(tctx, service[i].service_name, "Service without name returned!"); printf("%-20s \"%s\", Type: %d, State: %d\n", service[i].service_name, service[i].display_name, service[i].status.type, service[i].status.state); } if (!test_CloseServiceHandle(p, tctx, &h)) return false; return true; }