Use talloc_strdup() instead of strdup().
[tprouty/samba.git] / source3 / libsmb / cli_samr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 2.2
4    RPC pipe client
5    Copyright (C) Tim Potter                        2000-2001,
6    Copyright (C) Andrew Tridgell              1992-1997,2000,
7    Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
8    Copyright (C) Paul Ashton                       1997,2000,
9    Copyright (C) Elrond                                 2000.
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 /* Opens a SMB connection to the SAMR pipe */
29
30 struct cli_state *cli_samr_initialise(struct cli_state *cli, char *system_name,
31                                       struct ntuser_creds *creds)
32 {
33         struct in_addr dest_ip;
34         struct nmb_name calling, called;
35         fstring dest_host;
36         extern pstring global_myname;
37         struct ntuser_creds anon;
38
39         /* Initialise cli_state information */
40
41         if (!cli_initialise(cli)) {
42                 return NULL;
43         }
44
45         if (!creds) {
46                 ZERO_STRUCT(anon);
47                 anon.pwd.null_pwd = 1;
48                 creds = &anon;
49         }
50
51         cli_init_creds(cli, creds);
52
53         /* Establish a SMB connection */
54
55         if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
56                 return NULL;
57         }
58
59         make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
60         make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
61
62         if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling, 
63                                       &called, "IPC$", "IPC", False, True)) {
64                 return NULL;
65         }
66
67         /* Open a NT session thingy */
68
69         if (!cli_nt_session_open(cli, PIPE_SAMR)) {
70                 cli_shutdown(cli);
71                 return NULL;
72         }
73
74         return cli;
75 }
76
77 /* Shut down a SMB connection to the SAMR pipe */
78
79 void cli_samr_shutdown(struct cli_state *cli)
80 {
81         if (cli->fd != -1) cli_ulogoff(cli);
82         cli_shutdown(cli);
83 }
84
85 /* Connect to SAMR database */
86
87 uint32 cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
88                         char *srv_name, uint32 access_mask, 
89                         POLICY_HND *connect_pol)
90 {
91         prs_struct qbuf, rbuf;
92         SAMR_Q_CONNECT q;
93         SAMR_R_CONNECT r;
94         uint32 result = NT_STATUS_UNSUCCESSFUL;
95
96         ZERO_STRUCT(q);
97         ZERO_STRUCT(r);
98
99         /* Initialise parse structures */
100
101         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
102         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
103
104         /* Marshall data and send request */
105
106         init_samr_q_connect(&q, srv_name, access_mask);
107
108         if (!samr_io_q_connect("", &q, &qbuf, 0) ||
109             !rpc_api_pipe_req(cli, SAMR_CONNECT, &qbuf, &rbuf)) {
110                 goto done;
111         }
112
113         /* Unmarshall response */
114
115         if (!samr_io_r_connect("", &r, &rbuf, 0)) {
116                 goto done;
117         }
118
119         /* Return output parameters */
120
121         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
122                 *connect_pol = r.connect_pol;
123         }
124
125  done:
126         prs_mem_free(&qbuf);
127         prs_mem_free(&rbuf);
128
129         return result;
130 }
131
132 /* Close SAMR handle */
133
134 uint32 cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
135                       POLICY_HND *connect_pol)
136 {
137         prs_struct qbuf, rbuf;
138         SAMR_Q_CLOSE_HND q;
139         SAMR_R_CLOSE_HND r;
140         uint32 result = NT_STATUS_UNSUCCESSFUL;
141
142         ZERO_STRUCT(q);
143         ZERO_STRUCT(r);
144
145         /* Initialise parse structures */
146
147         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
148         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
149
150         /* Marshall data and send request */
151
152         init_samr_q_close_hnd(&q, connect_pol);
153
154         if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
155             !rpc_api_pipe_req(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) {
156                 goto done;
157         }
158
159         /* Unmarshall response */
160
161         if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) {
162                 goto done;
163         }
164
165         /* Return output parameters */
166
167         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
168                 *connect_pol = r.pol;
169         }
170
171  done:
172         prs_mem_free(&qbuf);
173         prs_mem_free(&rbuf);
174
175         return result;
176 }
177
178 /* Open handle on a domain */
179
180 uint32 cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
181                             POLICY_HND *connect_pol, uint32 access_mask, 
182                             DOM_SID *domain_sid, POLICY_HND *domain_pol)
183 {
184         prs_struct qbuf, rbuf;
185         SAMR_Q_OPEN_DOMAIN q;
186         SAMR_R_OPEN_DOMAIN r;
187         uint32 result = NT_STATUS_UNSUCCESSFUL;
188
189         ZERO_STRUCT(q);
190         ZERO_STRUCT(r);
191
192         /* Initialise parse structures */
193
194         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
195         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
196
197         /* Marshall data and send request */
198
199         init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
200
201         if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
202             !rpc_api_pipe_req(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) {
203                 goto done;
204         }
205
206         /* Unmarshall response */
207
208         if (!samr_io_r_open_domain("", &r, &rbuf, 0)) {
209                 goto done;
210         }
211
212         /* Return output parameters */
213
214         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
215                 *domain_pol = r.domain_pol;
216         }
217
218  done:
219         prs_mem_free(&qbuf);
220         prs_mem_free(&rbuf);
221
222         return result;
223 }
224
225 /* Open handle on a user */
226
227 uint32 cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
228                           POLICY_HND *domain_pol, uint32 access_mask, 
229                           uint32 user_rid, POLICY_HND *user_pol)
230 {
231         prs_struct qbuf, rbuf;
232         SAMR_Q_OPEN_USER q;
233         SAMR_R_OPEN_USER r;
234         uint32 result = NT_STATUS_UNSUCCESSFUL;
235
236         ZERO_STRUCT(q);
237         ZERO_STRUCT(r);
238
239         /* Initialise parse structures */
240
241         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
242         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
243
244         /* Marshall data and send request */
245
246         init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
247
248         if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
249             !rpc_api_pipe_req(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) {
250                 goto done;
251         }
252
253         /* Unmarshall response */
254
255         if (!samr_io_r_open_user("", &r, &rbuf, 0)) {
256                 goto done;
257         }
258
259         /* Return output parameters */
260
261         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
262                 *user_pol = r.user_pol;
263         }
264
265  done:
266         prs_mem_free(&qbuf);
267         prs_mem_free(&rbuf);
268
269         return result;
270 }
271
272 /* Open handle on a group */
273
274 uint32 cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
275                            POLICY_HND *domain_pol, uint32 access_mask, 
276                            uint32 group_rid, POLICY_HND *group_pol)
277 {
278         prs_struct qbuf, rbuf;
279         SAMR_Q_OPEN_GROUP q;
280         SAMR_R_OPEN_GROUP r;
281         uint32 result =  NT_STATUS_UNSUCCESSFUL;
282
283         ZERO_STRUCT(q);
284         ZERO_STRUCT(r);
285
286         /* Initialise parse structures */
287
288         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
289         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
290
291         /* Marshall data and send request */
292
293         init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
294
295         if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
296             !rpc_api_pipe_req(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) {
297                 goto done;
298         }
299
300         /* Unmarshall response */
301
302         if (!samr_io_r_open_group("", &r, &rbuf, 0)) {
303                 goto done;
304         }
305
306         /* Return output parameters */
307
308         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
309                 *group_pol = r.pol;
310         }
311
312  done:
313         prs_mem_free(&qbuf);
314         prs_mem_free(&rbuf);
315
316         return result;
317 }
318
319 /* Query user info */
320
321 uint32 cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
322                                POLICY_HND *user_pol, uint16 switch_value, 
323                                SAM_USERINFO_CTR *ctr)
324 {
325         prs_struct qbuf, rbuf;
326         SAMR_Q_QUERY_USERINFO q;
327         SAMR_R_QUERY_USERINFO r;
328         uint32 result = NT_STATUS_UNSUCCESSFUL;
329
330         ZERO_STRUCT(q);
331         ZERO_STRUCT(r);
332
333         /* Initialise parse structures */
334
335         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
336         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
337
338         /* Marshall data and send request */
339
340         init_samr_q_query_userinfo(&q, user_pol, switch_value);
341
342         if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
343             !rpc_api_pipe_req(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) {
344                 goto done;
345         }
346
347         /* Unmarshall response */
348
349         r.ctr = ctr;
350
351         if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) {
352                 goto done;
353         }
354
355         /* Return output parameters */
356
357         result = r.status;
358
359  done:
360         prs_mem_free(&qbuf);
361         prs_mem_free(&rbuf);
362
363         return result;
364 }
365
366 /* Query group info */
367
368 uint32 cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
369                                 POLICY_HND *group_pol, uint32 info_level, 
370                                 GROUP_INFO_CTR *ctr)
371 {
372         prs_struct qbuf, rbuf;
373         SAMR_Q_QUERY_GROUPINFO q;
374         SAMR_R_QUERY_GROUPINFO r;
375         uint32 result = NT_STATUS_UNSUCCESSFUL;
376
377         ZERO_STRUCT(q);
378         ZERO_STRUCT(r);
379
380         /* Initialise parse structures */
381
382         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
383         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
384
385         /* Marshall data and send request */
386
387         init_samr_q_query_groupinfo(&q, group_pol, info_level);
388
389         if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
390             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) {
391                 goto done;
392         }
393
394         /* Unmarshall response */
395
396         r.ctr = ctr;
397
398         if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) {
399                 goto done;
400         }
401
402         /* Return output parameters */
403
404         result = r.status;
405
406  done:
407         prs_mem_free(&qbuf);
408         prs_mem_free(&rbuf);
409
410         return result;
411 }
412
413 /* Query user groups */
414
415 uint32 cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
416                                  POLICY_HND *user_pol, uint32 *num_groups, 
417                                  DOM_GID **gid)
418 {
419         prs_struct qbuf, rbuf;
420         SAMR_Q_QUERY_USERGROUPS q;
421         SAMR_R_QUERY_USERGROUPS r;
422         uint32 result = NT_STATUS_UNSUCCESSFUL;
423
424         ZERO_STRUCT(q);
425         ZERO_STRUCT(r);
426
427         /* Initialise parse structures */
428
429         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
430         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
431
432         /* Marshall data and send request */
433
434         init_samr_q_query_usergroups(&q, user_pol);
435
436         if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
437             !rpc_api_pipe_req(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) {
438                 goto done;
439         }
440
441         /* Unmarshall response */
442
443         if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) {
444                 goto done;
445         }
446
447         /* Return output parameters */
448
449         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
450                 *num_groups = r.num_entries;
451                 *gid = r.gid;
452         }
453
454  done:
455         prs_mem_free(&qbuf);
456         prs_mem_free(&rbuf);
457
458         return result;
459 }
460
461 /* Query user groups */
462
463 uint32 cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
464                                POLICY_HND *group_pol, uint32 *num_mem, 
465                                uint32 **rid, uint32 **attr)
466 {
467         prs_struct qbuf, rbuf;
468         SAMR_Q_QUERY_GROUPMEM q;
469         SAMR_R_QUERY_GROUPMEM r;
470         uint32 result = NT_STATUS_UNSUCCESSFUL;
471
472         ZERO_STRUCT(q);
473         ZERO_STRUCT(r);
474
475         /* Initialise parse structures */
476
477         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
478         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
479
480         /* Marshall data and send request */
481
482         init_samr_q_query_groupmem(&q, group_pol);
483
484         if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
485             !rpc_api_pipe_req(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) {
486                 goto done;
487         }
488
489         /* Unmarshall response */
490
491         if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) {
492                 goto done;
493         }
494
495         /* Return output parameters */
496
497         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
498                 *num_mem = r.num_entries;
499                 *rid = r.rid;
500                 *attr = r.attr;
501         }
502
503  done:
504         prs_mem_free(&qbuf);
505         prs_mem_free(&rbuf);
506
507         return result;
508 }
509
510 /* Enumerate domain groups */
511
512 uint32 cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
513                                 POLICY_HND *pol, uint32 *start_idx, 
514                                 uint32 size, struct acct_info **dom_groups,
515                                 uint32 *num_dom_groups)
516 {
517         prs_struct qbuf, rbuf;
518         SAMR_Q_ENUM_DOM_GROUPS q;
519         SAMR_R_ENUM_DOM_GROUPS r;
520         uint32 result = NT_STATUS_UNSUCCESSFUL, name_idx, i;
521
522         ZERO_STRUCT(q);
523         ZERO_STRUCT(r);
524
525         /* Initialise parse structures */
526
527         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
528         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
529
530         /* Marshall data and send request */
531
532         init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
533
534         if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
535             !rpc_api_pipe_req(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) {
536                 goto done;
537         }
538
539         /* Unmarshall response */
540
541         if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) {
542                 goto done;
543         }
544
545         /* Return output parameters */
546
547         result = r.status;
548
549         if (result != NT_STATUS_NOPROBLEMO &&
550             result != STATUS_MORE_ENTRIES) {
551                 goto done;
552         }
553
554         *num_dom_groups = r.num_entries2;
555
556         if (!((*dom_groups) = (struct acct_info *)
557               talloc(mem_ctx, sizeof(struct acct_info) * *num_dom_groups))) {
558                 result = NT_STATUS_UNSUCCESSFUL;
559                 goto done;
560         }
561
562         memset(*dom_groups, 0, sizeof(struct acct_info) * *num_dom_groups);
563
564         name_idx = 0;
565
566         for (i = 0; i < *num_dom_groups; i++) {
567
568                 (*dom_groups)[i].rid = r.sam[i].rid;
569
570                 if (r.sam[i].hdr_name.buffer) {
571                         unistr2_to_ascii((*dom_groups)[i].acct_name,
572                                          &r.uni_grp_name[name_idx],
573                                          sizeof(fstring) - 1);
574                         name_idx++;
575                 }
576
577                 *start_idx = r.next_idx;
578         }
579
580  done:
581         prs_mem_free(&qbuf);
582         prs_mem_free(&rbuf);
583
584         return result;
585 }
586
587 /* Query alias members */
588
589 uint32 cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
590                                POLICY_HND *alias_pol, uint32 *num_mem, 
591                                DOM_SID **sids)
592 {
593         prs_struct qbuf, rbuf;
594         SAMR_Q_QUERY_ALIASMEM q;
595         SAMR_R_QUERY_ALIASMEM r;
596         uint32 result = NT_STATUS_UNSUCCESSFUL, i;
597
598         ZERO_STRUCT(q);
599         ZERO_STRUCT(r);
600
601         /* Initialise parse structures */
602
603         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
604         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
605
606         /* Marshall data and send request */
607
608         init_samr_q_query_aliasmem(&q, alias_pol);
609
610         if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
611             !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
612                 goto done;
613         }
614
615         /* Unmarshall response */
616
617         if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
618                 goto done;
619         }
620
621         /* Return output parameters */
622
623         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
624                 goto done;
625         }
626
627         *num_mem = r.num_sids;
628
629         if (!(*sids = talloc(mem_ctx, sizeof(DOM_SID) * *num_mem))) {
630                 result = NT_STATUS_UNSUCCESSFUL;
631                 goto done;
632         }
633
634         for (i = 0; i < *num_mem; i++) {
635                 (*sids)[i] = r.sid[i].sid;
636         }
637
638  done:
639         prs_mem_free(&qbuf);
640         prs_mem_free(&rbuf);
641
642         return result;
643 }
644
645 /* Open handle on an alias */
646
647 uint32 cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
648                            POLICY_HND *domain_pol, uint32 access_mask, 
649                            uint32 alias_rid, POLICY_HND *alias_pol)
650 {
651         prs_struct qbuf, rbuf;
652         SAMR_Q_OPEN_ALIAS q;
653         SAMR_R_OPEN_ALIAS r;
654         uint32 result;
655
656         ZERO_STRUCT(q);
657         ZERO_STRUCT(r);
658
659         /* Initialise parse structures */
660
661         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
662         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
663
664         /* Marshall data and send request */
665
666         init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
667
668         if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
669             !rpc_api_pipe_req(cli, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
670                 result = NT_STATUS_UNSUCCESSFUL;
671                 goto done;
672         }
673
674         /* Unmarshall response */
675
676         if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
677                 result = NT_STATUS_UNSUCCESSFUL;
678                 goto done;
679         }
680
681         /* Return output parameters */
682
683         if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
684                 *alias_pol = r.pol;
685         }
686
687  done:
688         prs_mem_free(&qbuf);
689         prs_mem_free(&rbuf);
690
691         return result;
692 }
693
694 /* Query domain info */
695
696 uint32 cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
697                                POLICY_HND *domain_pol, uint16 switch_value,
698                                SAM_UNK_CTR *ctr)
699 {
700         prs_struct qbuf, rbuf;
701         SAMR_Q_QUERY_DOMAIN_INFO q;
702         SAMR_R_QUERY_DOMAIN_INFO r;
703         uint32 result = NT_STATUS_UNSUCCESSFUL;
704
705         ZERO_STRUCT(q);
706         ZERO_STRUCT(r);
707
708         /* Initialise parse structures */
709
710         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
711         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
712
713         /* Marshall data and send request */
714
715         init_samr_q_query_dom_info(&q, domain_pol, switch_value);
716
717         if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
718             !rpc_api_pipe_req(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
719                 goto done;
720         }
721
722         /* Unmarshall response */
723
724         r.ctr = ctr;
725
726         if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
727                 goto done;
728         }
729
730         /* Return output parameters */
731
732         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
733                 goto done;
734         }
735
736  done:
737         prs_mem_free(&qbuf);
738         prs_mem_free(&rbuf);
739
740         return result;
741 }
742
743 /* Query display info */
744
745 uint32 cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
746                                POLICY_HND *domain_pol, uint32 *start_idx,
747                                uint16 switch_value, uint32 *num_entries,
748                                uint32 max_entries, SAM_DISPINFO_CTR *ctr)
749 {
750         prs_struct qbuf, rbuf;
751         SAMR_Q_QUERY_DISPINFO q;
752         SAMR_R_QUERY_DISPINFO r;
753         uint32 result = NT_STATUS_UNSUCCESSFUL;
754
755         ZERO_STRUCT(q);
756         ZERO_STRUCT(r);
757
758         /* Initialise parse structures */
759
760         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
761         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
762
763         /* Marshall data and send request */
764
765         init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
766                                    *start_idx, max_entries);
767
768         if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
769             !rpc_api_pipe_req(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
770                 goto done;
771         }
772
773         /* Unmarshall response */
774
775         r.ctr = ctr;
776
777         if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
778                 goto done;
779         }
780
781         /* Return output parameters */
782
783         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
784                 goto done;
785         }
786
787         *num_entries = r.num_entries;
788         *start_idx += r.num_entries;  /* No next_idx in this structure! */
789
790  done:
791         prs_mem_free(&qbuf);
792         prs_mem_free(&rbuf);
793
794         return result;
795 }
796
797 /* Lookup rids */
798
799 uint32 cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
800                             POLICY_HND *domain_pol, uint32 flags,
801                             uint32 num_rids, uint32 *rids, 
802                             uint32 *num_names, char ***names,
803                             uint32 **name_types)
804 {
805         prs_struct qbuf, rbuf;
806         SAMR_Q_LOOKUP_RIDS q;
807         SAMR_R_LOOKUP_RIDS r;
808         uint32 result = NT_STATUS_UNSUCCESSFUL, i;
809
810         ZERO_STRUCT(q);
811         ZERO_STRUCT(r);
812
813         /* Initialise parse structures */
814
815         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
816         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
817
818         /* Marshall data and send request */
819
820         init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, flags,
821                                 num_rids, rids);
822
823         if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
824             !rpc_api_pipe_req(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
825                 goto done;
826         }
827
828         /* Unmarshall response */
829
830         if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
831                 goto done;
832         }
833
834         /* Return output parameters */
835
836         if ((result = r.status) != NT_STATUS_NOPROBLEMO) {
837                 goto done;
838         }
839
840         if (r.num_names1 == 0) {
841                 *num_names = 0;
842                 *names = NULL;
843                 goto done;
844         }
845
846         *num_names = r.num_names1;
847         *names = talloc(mem_ctx, sizeof(char *) * r.num_names1);
848         *name_types = talloc(mem_ctx, sizeof(uint32) * r.num_names1);
849
850         for (i = 0; i < r.num_names1; i++) {
851                 fstring tmp;
852
853                 unistr2_to_ascii(tmp, &r.uni_name[i], sizeof(tmp) - 1);
854                 (*names)[i] = talloc_strdup(mem_ctx, tmp);
855                 (*name_types)[i] = r.type[i];
856         }
857
858  done:
859         prs_mem_free(&qbuf);
860         prs_mem_free(&rbuf);
861
862         return result;
863 }