Use rpccli_srvsvc_NetFileEnum in net and rpcclient.
[Samba/gebeck_regimport.git] / source3 / rpcclient / cmd_srvsvc.c
blob1062c95c72883ffaea6749414c85c3c4b8283e2d
1 /*
2 Unix SMB/CIFS implementation.
3 RPC pipe client
5 Copyright (C) Andrew Tridgell 1992-1999
6 Copyright (C) Luke Kenneth Casson Leighton 1996 - 1999
7 Copyright (C) Tim Potter 2000,2002
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "rpcclient.h"
26 /* Display server query info */
28 static char *get_server_type_str(uint32 type)
30 static fstring typestr;
31 int i;
33 if (type == SV_TYPE_ALL) {
34 fstrcpy(typestr, "All");
35 return typestr;
38 typestr[0] = 0;
40 for (i = 0; i < 32; i++) {
41 if (type & (1 << i)) {
42 switch (1 << i) {
43 case SV_TYPE_WORKSTATION:
44 fstrcat(typestr, "Wk ");
45 break;
46 case SV_TYPE_SERVER:
47 fstrcat(typestr, "Sv ");
48 break;
49 case SV_TYPE_SQLSERVER:
50 fstrcat(typestr, "Sql ");
51 break;
52 case SV_TYPE_DOMAIN_CTRL:
53 fstrcat(typestr, "PDC ");
54 break;
55 case SV_TYPE_DOMAIN_BAKCTRL:
56 fstrcat(typestr, "BDC ");
57 break;
58 case SV_TYPE_TIME_SOURCE:
59 fstrcat(typestr, "Tim ");
60 break;
61 case SV_TYPE_AFP:
62 fstrcat(typestr, "AFP ");
63 break;
64 case SV_TYPE_NOVELL:
65 fstrcat(typestr, "Nov ");
66 break;
67 case SV_TYPE_DOMAIN_MEMBER:
68 fstrcat(typestr, "Dom ");
69 break;
70 case SV_TYPE_PRINTQ_SERVER:
71 fstrcat(typestr, "PrQ ");
72 break;
73 case SV_TYPE_DIALIN_SERVER:
74 fstrcat(typestr, "Din ");
75 break;
76 case SV_TYPE_SERVER_UNIX:
77 fstrcat(typestr, "Unx ");
78 break;
79 case SV_TYPE_NT:
80 fstrcat(typestr, "NT ");
81 break;
82 case SV_TYPE_WFW:
83 fstrcat(typestr, "Wfw ");
84 break;
85 case SV_TYPE_SERVER_MFPN:
86 fstrcat(typestr, "Mfp ");
87 break;
88 case SV_TYPE_SERVER_NT:
89 fstrcat(typestr, "SNT ");
90 break;
91 case SV_TYPE_POTENTIAL_BROWSER:
92 fstrcat(typestr, "PtB ");
93 break;
94 case SV_TYPE_BACKUP_BROWSER:
95 fstrcat(typestr, "BMB ");
96 break;
97 case SV_TYPE_MASTER_BROWSER:
98 fstrcat(typestr, "LMB ");
99 break;
100 case SV_TYPE_DOMAIN_MASTER:
101 fstrcat(typestr, "DMB ");
102 break;
103 case SV_TYPE_SERVER_OSF:
104 fstrcat(typestr, "OSF ");
105 break;
106 case SV_TYPE_SERVER_VMS:
107 fstrcat(typestr, "VMS ");
108 break;
109 case SV_TYPE_WIN95_PLUS:
110 fstrcat(typestr, "W95 ");
111 break;
112 case SV_TYPE_ALTERNATE_XPORT:
113 fstrcat(typestr, "Xpt ");
114 break;
115 case SV_TYPE_LOCAL_LIST_ONLY:
116 fstrcat(typestr, "Dom ");
117 break;
118 case SV_TYPE_DOMAIN_ENUM:
119 fstrcat(typestr, "Loc ");
120 break;
125 i = strlen(typestr) - 1;
127 if (typestr[i] == ' ')
128 typestr[i] = 0;
130 return typestr;
133 static void display_server(const char *sname, uint32 type, const char *comment)
135 printf("\t%-15.15s%-20s %s\n", sname, get_server_type_str(type),
136 comment);
139 static void display_srv_info_101(struct srvsvc_NetSrvInfo101 *r)
141 display_server(r->server_name, r->server_type, r->comment);
143 printf("\tplatform_id :\t%d\n", r->platform_id);
144 printf("\tos version :\t%d.%d\n",
145 r->version_major, r->version_minor);
146 printf("\tserver type :\t0x%x\n", r->server_type);
149 static void display_srv_info_102(struct srvsvc_NetSrvInfo102 *r)
151 display_server(r->server_name, r->server_type, r->comment);
153 printf("\tplatform_id :\t%d\n", r->platform_id);
154 printf("\tos version :\t%d.%d\n",
155 r->version_major, r->version_minor);
156 printf("\tserver type :\t0x%x\n", r->server_type);
158 printf("\tusers :\t%x\n", r->users);
159 printf("\tdisc, hidden :\t%x, %x\n", r->disc, r->hidden);
160 printf("\tannounce, delta :\t%d, %d\n", r->announce,
161 r->anndelta);
162 printf("\tlicenses :\t%d\n", r->licenses);
163 printf("\tuser path :\t%s\n", r->userpath);
166 /* Server query info */
167 static WERROR cmd_srvsvc_srv_query_info(struct rpc_pipe_client *cli,
168 TALLOC_CTX *mem_ctx,
169 int argc, const char **argv)
171 uint32 info_level = 101;
172 union srvsvc_NetSrvInfo info;
173 WERROR result;
174 NTSTATUS status;
175 const char *server_name;
177 if (argc > 2) {
178 printf("Usage: %s [infolevel]\n", argv[0]);
179 return WERR_OK;
182 if (argc == 2)
183 info_level = atoi(argv[1]);
185 server_name = talloc_asprintf_strupper_m(mem_ctx, "\\\\%s",
186 cli->cli->desthost);
187 W_ERROR_HAVE_NO_MEMORY(server_name);
189 status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
190 server_name,
191 info_level,
192 &info,
193 &result);
194 if (!NT_STATUS_IS_OK(status)) {
195 return ntstatus_to_werror(status);
198 if (!W_ERROR_IS_OK(result)) {
199 goto done;
202 /* Display results */
204 switch (info_level) {
205 case 101:
206 display_srv_info_101(info.info101);
207 break;
208 case 102:
209 display_srv_info_102(info.info102);
210 break;
211 default:
212 printf("unsupported info level %d\n", info_level);
213 break;
216 done:
217 return result;
220 static void display_share_info_1(struct srvsvc_NetShareInfo1 *r)
222 printf("netname: %s\n", r->name);
223 printf("\tremark:\t%s\n", r->comment);
226 static void display_share_info_2(struct srvsvc_NetShareInfo2 *r)
228 printf("netname: %s\n", r->name);
229 printf("\tremark:\t%s\n", r->comment);
230 printf("\tpath:\t%s\n", r->path);
231 printf("\tpassword:\t%s\n", r->password);
234 static void display_share_info_502(struct srvsvc_NetShareInfo502 *r)
236 printf("netname: %s\n", r->name);
237 printf("\tremark:\t%s\n", r->comment);
238 printf("\tpath:\t%s\n", r->path);
239 printf("\tpassword:\t%s\n", r->password);
241 printf("\ttype:\t0x%x\n", r->type);
242 printf("\tperms:\t%d\n", r->permissions);
243 printf("\tmax_uses:\t%d\n", r->max_users);
244 printf("\tnum_uses:\t%d\n", r->current_users);
246 if (r->sd)
247 display_sec_desc(r->sd);
251 static WERROR cmd_srvsvc_net_share_enum_int(struct rpc_pipe_client *cli,
252 TALLOC_CTX *mem_ctx,
253 int argc, const char **argv,
254 uint32_t opcode)
256 uint32 info_level = 2;
257 struct srvsvc_NetShareInfoCtr info_ctr;
258 struct srvsvc_NetShareCtr0 ctr0;
259 struct srvsvc_NetShareCtr1 ctr1;
260 struct srvsvc_NetShareCtr2 ctr2;
261 struct srvsvc_NetShareCtr501 ctr501;
262 struct srvsvc_NetShareCtr502 ctr502;
263 struct srvsvc_NetShareCtr1004 ctr1004;
264 struct srvsvc_NetShareCtr1005 ctr1005;
265 struct srvsvc_NetShareCtr1006 ctr1006;
266 struct srvsvc_NetShareCtr1007 ctr1007;
267 struct srvsvc_NetShareCtr1501 ctr1501;
268 WERROR result;
269 NTSTATUS status;
270 uint32_t totalentries = 0;
271 uint32_t resume_handle = 0;
272 uint32 preferred_len = 0xffffffff, i;
274 if (argc > 3) {
275 printf("Usage: %s [infolevel] [resume_handle]\n", argv[0]);
276 return WERR_OK;
279 if (argc >= 2) {
280 info_level = atoi(argv[1]);
283 if (argc == 3) {
284 resume_handle = atoi(argv[2]);
287 ZERO_STRUCT(info_ctr);
289 info_ctr.level = info_level;
291 switch (info_level) {
292 case 0:
293 ZERO_STRUCT(ctr0);
294 info_ctr.ctr.ctr0 = &ctr0;
295 break;
296 case 1:
297 ZERO_STRUCT(ctr1);
298 info_ctr.ctr.ctr1 = &ctr1;
299 break;
300 case 2:
301 ZERO_STRUCT(ctr2);
302 info_ctr.ctr.ctr2 = &ctr2;
303 break;
304 case 501:
305 ZERO_STRUCT(ctr501);
306 info_ctr.ctr.ctr501 = &ctr501;
307 break;
308 case 502:
309 ZERO_STRUCT(ctr502);
310 info_ctr.ctr.ctr502 = &ctr502;
311 break;
312 case 1004:
313 ZERO_STRUCT(ctr1004);
314 info_ctr.ctr.ctr1004 = &ctr1004;
315 break;
316 case 1005:
317 ZERO_STRUCT(ctr1005);
318 info_ctr.ctr.ctr1005 = &ctr1005;
319 break;
320 case 1006:
321 ZERO_STRUCT(ctr1006);
322 info_ctr.ctr.ctr1006 = &ctr1006;
323 break;
324 case 1007:
325 ZERO_STRUCT(ctr1007);
326 info_ctr.ctr.ctr1007 = &ctr1007;
327 break;
328 case 1501:
329 ZERO_STRUCT(ctr1501);
330 info_ctr.ctr.ctr1501 = &ctr1501;
331 break;
334 switch (opcode) {
335 case NDR_SRVSVC_NETSHAREENUM:
336 status = rpccli_srvsvc_NetShareEnum(cli, mem_ctx,
337 cli->cli->desthost,
338 &info_ctr,
339 preferred_len,
340 &totalentries,
341 &resume_handle,
342 &result);
343 break;
344 case NDR_SRVSVC_NETSHAREENUMALL:
345 status = rpccli_srvsvc_NetShareEnumAll(cli, mem_ctx,
346 cli->cli->desthost,
347 &info_ctr,
348 preferred_len,
349 &totalentries,
350 &resume_handle,
351 &result);
352 break;
353 default:
354 return WERR_INVALID_PARAM;
357 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
358 goto done;
361 /* Display results */
363 switch (info_level) {
364 case 1:
365 for (i = 0; i < totalentries; i++)
366 display_share_info_1(&info_ctr.ctr.ctr1->array[i]);
367 break;
368 case 2:
369 for (i = 0; i < totalentries; i++)
370 display_share_info_2(&info_ctr.ctr.ctr2->array[i]);
371 break;
372 case 502:
373 for (i = 0; i < totalentries; i++)
374 display_share_info_502(&info_ctr.ctr.ctr502->array[i]);
375 break;
376 default:
377 printf("unsupported info level %d\n", info_level);
378 break;
381 done:
382 return result;
385 static WERROR cmd_srvsvc_net_share_enum(struct rpc_pipe_client *cli,
386 TALLOC_CTX *mem_ctx,
387 int argc, const char **argv)
389 return cmd_srvsvc_net_share_enum_int(cli, mem_ctx,
390 argc, argv,
391 NDR_SRVSVC_NETSHAREENUM);
394 static WERROR cmd_srvsvc_net_share_enum_all(struct rpc_pipe_client *cli,
395 TALLOC_CTX *mem_ctx,
396 int argc, const char **argv)
398 return cmd_srvsvc_net_share_enum_int(cli, mem_ctx,
399 argc, argv,
400 NDR_SRVSVC_NETSHAREENUMALL);
403 static WERROR cmd_srvsvc_net_share_get_info(struct rpc_pipe_client *cli,
404 TALLOC_CTX *mem_ctx,
405 int argc, const char **argv)
407 uint32 info_level = 502;
408 union srvsvc_NetShareInfo info;
409 WERROR result;
410 NTSTATUS status;
412 if (argc < 2 || argc > 3) {
413 printf("Usage: %s [sharename] [infolevel]\n", argv[0]);
414 return WERR_OK;
417 if (argc == 3)
418 info_level = atoi(argv[2]);
420 status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
421 cli->cli->desthost,
422 argv[1],
423 info_level,
424 &info,
425 &result);
427 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
428 goto done;
431 /* Display results */
433 switch (info_level) {
434 case 1:
435 display_share_info_1(info.info1);
436 break;
437 case 2:
438 display_share_info_2(info.info2);
439 break;
440 case 502:
441 display_share_info_502(info.info502);
442 break;
443 default:
444 printf("unsupported info level %d\n", info_level);
445 break;
448 done:
449 return result;
452 static WERROR cmd_srvsvc_net_share_set_info(struct rpc_pipe_client *cli,
453 TALLOC_CTX *mem_ctx,
454 int argc, const char **argv)
456 uint32 info_level = 502;
457 union srvsvc_NetShareInfo info_get;
458 WERROR result;
459 NTSTATUS status;
460 uint32_t parm_err = 0;
462 if (argc > 3) {
463 printf("Usage: %s [sharename] [comment]\n", argv[0]);
464 return WERR_OK;
467 /* retrieve share info */
468 status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
469 cli->cli->desthost,
470 argv[1],
471 info_level,
472 &info_get,
473 &result);
475 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
476 goto done;
479 info_get.info502->comment = argv[2];
481 /* set share info */
482 status = rpccli_srvsvc_NetShareSetInfo(cli, mem_ctx,
483 cli->cli->desthost,
484 argv[1],
485 info_level,
486 &info_get,
487 &parm_err,
488 &result);
490 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
491 goto done;
494 /* re-retrieve share info and display */
495 status = rpccli_srvsvc_NetShareGetInfo(cli, mem_ctx,
496 cli->cli->desthost,
497 argv[1],
498 info_level,
499 &info_get,
500 &result);
502 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
503 goto done;
506 display_share_info_502(info_get.info502);
508 done:
509 return result;
512 static WERROR cmd_srvsvc_net_remote_tod(struct rpc_pipe_client *cli,
513 TALLOC_CTX *mem_ctx,
514 int argc, const char **argv)
516 struct srvsvc_NetRemoteTODInfo *tod = NULL;
517 fstring srv_name_slash;
518 WERROR result;
519 NTSTATUS status;
521 if (argc > 1) {
522 printf("Usage: %s\n", argv[0]);
523 return WERR_OK;
526 fstr_sprintf(srv_name_slash, "\\\\%s", cli->cli->desthost);
527 status = rpccli_srvsvc_NetRemoteTOD(cli, mem_ctx,
528 srv_name_slash,
529 &tod,
530 &result);
531 if (!NT_STATUS_IS_OK(status)) {
532 result = ntstatus_to_werror(status);
533 goto done;
536 if (!W_ERROR_IS_OK(result))
537 goto done;
539 done:
540 return result;
543 static WERROR cmd_srvsvc_net_file_enum(struct rpc_pipe_client *cli,
544 TALLOC_CTX *mem_ctx,
545 int argc, const char **argv)
547 uint32 info_level = 3;
548 struct srvsvc_NetFileInfoCtr info_ctr;
549 struct srvsvc_NetFileCtr3 ctr3;
550 WERROR result;
551 NTSTATUS status;
552 uint32 preferred_len = 0xffff;
553 uint32_t total_entries = 0;
554 uint32_t resume_handle = 0;
556 if (argc > 2) {
557 printf("Usage: %s [infolevel]\n", argv[0]);
558 return WERR_OK;
561 if (argc == 2)
562 info_level = atoi(argv[1]);
564 ZERO_STRUCT(info_ctr);
565 ZERO_STRUCT(ctr3);
567 info_ctr.level = info_level;
568 info_ctr.ctr.ctr3 = &ctr3;
570 status = rpccli_srvsvc_NetFileEnum(cli, mem_ctx,
571 cli->cli->desthost,
572 NULL,
573 NULL,
574 &info_ctr,
575 preferred_len,
576 &total_entries,
577 &resume_handle,
578 &result);
580 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
581 goto done;
583 done:
584 return result;
587 static WERROR cmd_srvsvc_net_name_validate(struct rpc_pipe_client *cli,
588 TALLOC_CTX *mem_ctx,
589 int argc, const char **argv)
591 WERROR result;
592 NTSTATUS status;
593 uint32_t name_type = 9;
594 uint32_t flags = 0;
596 if (argc < 2 || argc > 3) {
597 printf("Usage: %s [sharename] [type]\n", argv[0]);
598 return WERR_OK;
601 if (argc == 3) {
602 name_type = atoi(argv[2]);
605 status = rpccli_srvsvc_NetNameValidate(cli, mem_ctx,
606 cli->cli->desthost,
607 argv[1],
608 name_type,
609 flags,
610 &result);
612 if (!W_ERROR_IS_OK(result))
613 goto done;
615 done:
616 return result;
619 static WERROR cmd_srvsvc_net_file_get_sec(struct rpc_pipe_client *cli,
620 TALLOC_CTX *mem_ctx,
621 int argc, const char **argv)
623 WERROR result;
624 NTSTATUS status;
625 struct sec_desc_buf *sd_buf = NULL;
627 if (argc < 2 || argc > 4) {
628 printf("Usage: %s [sharename] [file]\n", argv[0]);
629 return WERR_OK;
632 status = rpccli_srvsvc_NetGetFileSecurity(cli, mem_ctx,
633 cli->cli->desthost,
634 argv[1],
635 argv[2],
636 SECINFO_DACL,
637 &sd_buf,
638 &result);
640 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
641 goto done;
644 display_sec_desc(sd_buf->sd);
646 done:
647 return result;
650 static WERROR cmd_srvsvc_net_sess_del(struct rpc_pipe_client *cli,
651 TALLOC_CTX *mem_ctx,
652 int argc, const char **argv)
654 WERROR result;
655 NTSTATUS status;
657 if (argc < 2 || argc > 4) {
658 printf("Usage: %s [client] [user]\n", argv[0]);
659 return WERR_OK;
662 status = rpccli_srvsvc_NetSessDel(cli, mem_ctx,
663 cli->cli->desthost,
664 argv[1],
665 argv[2],
666 &result);
668 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
669 goto done;
672 done:
673 return result;
676 static WERROR cmd_srvsvc_net_sess_enum(struct rpc_pipe_client *cli,
677 TALLOC_CTX *mem_ctx,
678 int argc, const char **argv)
680 WERROR result;
681 NTSTATUS status;
682 struct srvsvc_NetSessInfoCtr info_ctr;
683 struct srvsvc_NetSessCtr0 ctr0;
684 struct srvsvc_NetSessCtr1 ctr1;
685 struct srvsvc_NetSessCtr2 ctr2;
686 struct srvsvc_NetSessCtr10 ctr10;
687 struct srvsvc_NetSessCtr502 ctr502;
688 uint32_t total_entries = 0;
689 uint32_t resume_handle = 0;
690 uint32_t level = 1;
691 const char *client = NULL;
692 const char *user = NULL;
694 if (argc > 5) {
695 printf("Usage: %s [client] [user]\n", argv[0]);
696 return WERR_OK;
699 if (argc >= 2) {
700 client = argv[1];
703 if (argc >= 3) {
704 user = argv[2];
707 if (argc >= 4) {
708 level = atoi(argv[3]);
711 ZERO_STRUCT(info_ctr);
713 info_ctr.level = level;
715 d_printf("trying level: %d\n", level);
717 switch (level) {
718 case 0:
719 ZERO_STRUCT(ctr0);
720 info_ctr.ctr.ctr0 = &ctr0;
721 break;
722 case 1:
723 ZERO_STRUCT(ctr1);
724 info_ctr.ctr.ctr1 = &ctr1;
725 break;
726 case 2:
727 ZERO_STRUCT(ctr2);
728 info_ctr.ctr.ctr2 = &ctr2;
729 break;
730 case 10:
731 ZERO_STRUCT(ctr10);
732 info_ctr.ctr.ctr10 = &ctr10;
733 break;
734 case 502:
735 ZERO_STRUCT(ctr502);
736 info_ctr.ctr.ctr502 = &ctr502;
737 break;
740 status = rpccli_srvsvc_NetSessEnum(cli, mem_ctx,
741 cli->cli->desthost,
742 client,
743 user,
744 &info_ctr,
745 0xffffffff,
746 &total_entries,
747 &resume_handle,
748 &result);
750 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
751 goto done;
754 done:
755 return result;
760 /* List of commands exported by this module */
762 struct cmd_set srvsvc_commands[] = {
764 { "SRVSVC" },
766 { "srvinfo", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, PI_SRVSVC, NULL, "Server query info", "" },
767 { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, PI_SRVSVC, NULL, "Enumerate shares", "" },
768 { "netshareenumall",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum_all, PI_SRVSVC, NULL, "Enumerate all shares", "" },
769 { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, PI_SRVSVC, NULL, "Get Share Info", "" },
770 { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, PI_SRVSVC, NULL, "Set Share Info", "" },
771 { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum, PI_SRVSVC, NULL, "Enumerate open files", "" },
772 { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, PI_SRVSVC, NULL, "Fetch remote time of day", "" },
773 { "netnamevalidate", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_name_validate, PI_SRVSVC, NULL, "Validate sharename", "" },
774 { "netfilegetsec", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_get_sec, PI_SRVSVC, NULL, "Get File security", "" },
775 { "netsessdel", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_sess_del, PI_SRVSVC, NULL, "Delete Session", "" },
776 { "netsessenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_sess_enum, PI_SRVSVC, NULL, "Enumerate Sessions", "" },
778 { NULL }