r7632: Cleanup "net share migrate"-code.
[vlendec/samba-autobuild/.git] / source3 / rpc_client / cli_srvsvc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    NT Domain Authentication SMB / MSRPC client
4    Copyright (C) Andrew Tridgell 1994-2000
5    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
6    Copyright (C) Tim Potter 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
8    
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 2 of the License, or
12    (at your option) any later version.
13    
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.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli, 
27                                    TALLOC_CTX *mem_ctx,
28                                    uint32 switch_value, SRV_INFO_CTR *ctr)
29 {
30         prs_struct qbuf, rbuf;
31         SRV_Q_NET_SRV_GET_INFO q;
32         SRV_R_NET_SRV_GET_INFO r;
33         WERROR result = W_ERROR(ERRgeneral);
34
35         ZERO_STRUCT(q);
36         ZERO_STRUCT(r);
37
38         /* Initialise parse structures */
39
40         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
41         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
42
43         /* Initialise input parameters */
44
45         init_srv_q_net_srv_get_info(&q, cli->srv_name_slash, switch_value);
46
47         /* Marshall data and send request */
48
49         if (!srv_io_q_net_srv_get_info("", &q, &qbuf, 0) ||
50             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SRV_GET_INFO, &qbuf, &rbuf))
51                 goto done;
52
53         /* Unmarshall response */
54
55         r.ctr = ctr;
56
57         if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0))
58                 goto done;
59
60         result = r.status;
61
62  done:
63         prs_mem_free(&qbuf);
64         prs_mem_free(&rbuf);
65
66         return result;
67 }
68
69 WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
70                                  uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
71                                  int preferred_len, ENUM_HND *hnd)
72 {
73         prs_struct qbuf, rbuf;
74         SRV_Q_NET_SHARE_ENUM q;
75         SRV_R_NET_SHARE_ENUM r;
76         WERROR result = W_ERROR(ERRgeneral);
77         int i;
78
79         ZERO_STRUCT(q);
80         ZERO_STRUCT(r);
81
82         /* Initialise parse structures */
83
84         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
85         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
86
87         /* Initialise input parameters */
88
89         init_srv_q_net_share_enum(
90                 &q, cli->srv_name_slash, info_level, preferred_len, hnd);
91
92         /* Marshall data and send request */
93
94         if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
95             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
96                 goto done;
97
98         /* Unmarshall response */
99
100         if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
101                 goto done;
102
103         result = r.status;
104
105         if (!W_ERROR_IS_OK(result))
106                 goto done;
107
108         /* Oh yuck yuck yuck - we have to copy all the info out of the
109            SRV_SHARE_INFO_CTR in the SRV_R_NET_SHARE_ENUM as when we do a
110            prs_mem_free() it will all be invalidated.  The various share
111            info structures suck badly too.  This really is gross. */
112
113         ZERO_STRUCTP(ctr);
114
115         if (!r.ctr.num_entries)
116                 goto done;
117
118         ctr->info_level = info_level;
119         ctr->num_entries = r.ctr.num_entries;
120
121         switch(info_level) {
122         case 1:
123                 ctr->share.info1 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_1, ctr->num_entries);
124                 
125                 memset(ctr->share.info1, 0, sizeof(SRV_SHARE_INFO_1));
126
127                 for (i = 0; i < ctr->num_entries; i++) {
128                         SRV_SHARE_INFO_1 *info1 = &ctr->share.info1[i];
129                         char *s;
130                         
131                         /* Copy pointer crap */
132
133                         memcpy(&info1->info_1, &r.ctr.share.info1[i].info_1, 
134                                sizeof(SH_INFO_1));
135
136                         /* Duplicate strings */
137
138                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname);
139                         if (s)
140                                 init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE);
141                 
142                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark);
143                         if (s)
144                                 init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE);
145
146                 }               
147
148                 break;
149         case 2:
150                 ctr->share.info2 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_2, ctr->num_entries);
151                 
152                 memset(ctr->share.info2, 0, sizeof(SRV_SHARE_INFO_2));
153
154                 for (i = 0; i < ctr->num_entries; i++) {
155                         SRV_SHARE_INFO_2 *info2 = &ctr->share.info2[i];
156                         char *s;
157                         
158                         /* Copy pointer crap */
159
160                         memcpy(&info2->info_2, &r.ctr.share.info2[i].info_2, 
161                                sizeof(SH_INFO_2));
162
163                         /* Duplicate strings */
164
165                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname);
166                         if (s)
167                                 init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE);
168
169                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark);
170                         if (s)
171                                 init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE);
172
173                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path);
174                         if (s)
175                                 init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE);
176
177                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd);
178                         if (s)
179                                 init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE);
180                 }
181                 break;
182         /* adding info-level 502 here */
183         case 502:
184                 ctr->share.info502 = TALLOC_ARRAY(mem_ctx, SRV_SHARE_INFO_502, ctr->num_entries);
185                 
186                 memset(ctr->share.info502, 0, sizeof(SRV_SHARE_INFO_502));
187
188                 for (i = 0; i < ctr->num_entries; i++) {
189                         SRV_SHARE_INFO_502 *info502 = &ctr->share.info502[i];
190                         char *s;
191                         
192                         /* Copy pointer crap */
193                         memcpy(&info502->info_502, &r.ctr.share.info502[i].info_502, 
194                                sizeof(SH_INFO_502));
195
196                         /* Duplicate strings */
197
198                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_netname);
199                         if (s)
200                                 init_unistr2(&info502->info_502_str.uni_netname, s, UNI_STR_TERMINATE);
201
202                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_remark);
203                         if (s)
204                                 init_unistr2(&info502->info_502_str.uni_remark, s, UNI_STR_TERMINATE);
205
206                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_path);
207                         if (s)
208                                 init_unistr2(&info502->info_502_str.uni_path, s, UNI_STR_TERMINATE);
209
210                         s = unistr2_tdup(mem_ctx, &r.ctr.share.info502[i].info_502_str.uni_passwd);
211                         if (s)
212                                 init_unistr2(&info502->info_502_str.uni_passwd, s, UNI_STR_TERMINATE);
213                 
214                         info502->info_502_str.sd = dup_sec_desc(mem_ctx, r.ctr.share.info502[i].info_502_str.sd);
215                 }
216                 break;
217         }
218  done:
219         prs_mem_free(&qbuf);
220         prs_mem_free(&rbuf);
221
222         return result;
223 }
224
225 WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli,
226                                      TALLOC_CTX *mem_ctx,
227                                      const char *sharename,
228                                      uint32 info_level,
229                                      SRV_SHARE_INFO *info)
230 {
231         prs_struct qbuf, rbuf;
232         SRV_Q_NET_SHARE_GET_INFO q;
233         SRV_R_NET_SHARE_GET_INFO r;
234         WERROR result = W_ERROR(ERRgeneral);
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         /* Initialise input parameters */
245
246         init_srv_q_net_share_get_info(&q, cli->srv_name_slash, sharename,
247                                       info_level);
248
249         /* Marshall data and send request */
250
251         if (!srv_io_q_net_share_get_info("", &q, &qbuf, 0) ||
252             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_GET_INFO, &qbuf, &rbuf))
253                 goto done;
254
255         /* Unmarshall response */
256
257         if (!srv_io_r_net_share_get_info("", &r, &rbuf, 0))
258                 goto done;
259
260         result = r.status;
261
262         if (!W_ERROR_IS_OK(result))
263                 goto done;
264
265         ZERO_STRUCTP(info);
266
267         info->switch_value = info_level;
268
269         switch(info_level) {
270         case 1:
271         {
272                 SRV_SHARE_INFO_1 *info1 = &info->share.info1;
273                 SH_INFO_1_STR *info1_str = &info1->info_1_str;
274                 
275                 char *s;
276
277                 info->share.info1 = r.info.share.info1;
278
279                 /* Duplicate strings */
280
281                 s = unistr2_tdup(mem_ctx, &info1_str->uni_netname);
282                 if (s)
283                         init_unistr2(&info1_str->uni_netname,
284                                      s, UNI_STR_TERMINATE);
285
286                 s = unistr2_tdup(mem_ctx, &info1_str->uni_remark);
287                 if (s)
288                         init_unistr2(&info1_str->uni_remark,
289                                      s, UNI_STR_TERMINATE);
290
291                 break;
292         }
293         case 2:
294         {
295                 SRV_SHARE_INFO_2 *info2 = &info->share.info2;
296                 SH_INFO_2_STR *info2_str = &info2->info_2_str;
297                 
298                 char *s;
299
300                 info->share.info2 = r.info.share.info2;
301
302                 /* Duplicate strings */
303
304                 s = unistr2_tdup(mem_ctx, &info2_str->uni_netname);
305                 if (s)
306                         init_unistr2(&info2_str->uni_netname,
307                                      s, UNI_STR_TERMINATE);
308
309                 s = unistr2_tdup(mem_ctx, &info2_str->uni_remark);
310                 if (s)
311                         init_unistr2(&info2_str->uni_remark,
312                                      s, UNI_STR_TERMINATE);
313
314                 s = unistr2_tdup(mem_ctx, &info2_str->uni_path);
315                 if (s)
316                         init_unistr2(&info2_str->uni_path,
317                                      s, UNI_STR_TERMINATE);
318
319                 s = unistr2_tdup(mem_ctx, &info2_str->uni_passwd);
320                 if (s)
321                         init_unistr2(&info2_str->uni_passwd,
322                                      s, UNI_STR_TERMINATE);
323
324
325                 break;
326         }
327         case 502:
328         {
329                 SRV_SHARE_INFO_502 *info502 = &info->share.info502;
330                 SH_INFO_502_STR *info502_str = &info502->info_502_str;
331                 
332                 char *s;
333
334                 info->share.info502 = r.info.share.info502;
335
336                 /* Duplicate strings */
337
338                 s = unistr2_tdup(mem_ctx, &info502_str->uni_netname);
339                 if (s)
340                         init_unistr2(&info502_str->uni_netname,
341                                      s, UNI_STR_TERMINATE);
342
343                 s = unistr2_tdup(mem_ctx, &info502_str->uni_remark);
344                 if (s)
345                         init_unistr2(&info502_str->uni_remark,
346                                      s, UNI_STR_TERMINATE);
347
348                 s = unistr2_tdup(mem_ctx, &info502_str->uni_path);
349                 if (s)
350                         init_unistr2(&info502_str->uni_path,
351                                      s, UNI_STR_TERMINATE);
352
353                 s = unistr2_tdup(mem_ctx, &info502_str->uni_passwd);
354                 if (s)
355                         init_unistr2(&info502_str->uni_passwd,
356                                      s, UNI_STR_TERMINATE);
357
358                 info502_str->sd = dup_sec_desc(mem_ctx, info502_str->sd);
359                 break;
360         }
361         default:
362                 DEBUG(0,("unimplemented info-level: %d\n", info_level));
363                 break;
364         }
365
366  done:
367         prs_mem_free(&qbuf);
368         prs_mem_free(&rbuf);
369
370         return result;
371 }
372
373 WERROR cli_srvsvc_net_share_set_info(struct cli_state *cli,
374                                      TALLOC_CTX *mem_ctx,
375                                      const char *sharename,
376                                      uint32 info_level,
377                                      SRV_SHARE_INFO *info)
378 {
379         prs_struct qbuf, rbuf;
380         SRV_Q_NET_SHARE_SET_INFO q;
381         SRV_R_NET_SHARE_SET_INFO r;
382         WERROR result = W_ERROR(ERRgeneral);
383
384         ZERO_STRUCT(q);
385         ZERO_STRUCT(r);
386
387         /* Initialise parse structures */
388
389         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
390         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
391
392         /* Initialise input parameters */
393
394         init_srv_q_net_share_set_info(&q, cli->srv_name_slash, sharename,
395                                       info_level, info);
396
397         /* Marshall data and send request */
398
399         if (!srv_io_q_net_share_set_info("", &q, &qbuf, 0) ||
400             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_SET_INFO, &qbuf, &rbuf))
401                 goto done;
402
403         /* Unmarshall response */
404
405         if (!srv_io_r_net_share_set_info("", &r, &rbuf, 0))
406                 goto done;
407
408         result = r.status;
409
410         if (!W_ERROR_IS_OK(result))
411                 goto done;
412
413  done:
414         prs_mem_free(&qbuf);
415         prs_mem_free(&rbuf);
416
417         return result;
418 }
419
420 WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx,
421                                 const char *sharename)
422 {
423         prs_struct qbuf, rbuf;
424         SRV_Q_NET_SHARE_DEL q;
425         SRV_R_NET_SHARE_DEL r;
426         WERROR result = W_ERROR(ERRgeneral);
427
428         ZERO_STRUCT(q);
429         ZERO_STRUCT(r);
430
431         /* Initialise parse structures */
432
433         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
434         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
435
436         /* Initialise input parameters */
437
438         init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename);
439
440         /* Marshall data and send request */
441
442         if (!srv_io_q_net_share_del("", &q, &qbuf, 0) ||
443             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_DEL, &qbuf, &rbuf))
444                 goto done;
445
446         /* Unmarshall response */
447
448         if (!srv_io_r_net_share_del("", &r, &rbuf, 0))
449                 goto done;
450
451         result = r.status;
452
453  done:
454         prs_mem_free(&qbuf);
455         prs_mem_free(&rbuf);
456
457         return result;
458 }
459
460 WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
461                                 const char *netname, uint32 type, 
462                                 const char *remark, uint32 perms, 
463                                 uint32 max_uses, uint32 num_uses, 
464                                 const char *path, const char *passwd,
465                                 int level, SEC_DESC *sd)
466 {
467         prs_struct qbuf, rbuf;
468         SRV_Q_NET_SHARE_ADD q;
469         SRV_R_NET_SHARE_ADD r;
470         WERROR result = W_ERROR(ERRgeneral);
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         init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
481                                  perms, max_uses, num_uses, path, passwd, 
482                                  level, sd);
483
484         /* Marshall data and send request */
485
486         if (!srv_io_q_net_share_add("", &q, &qbuf, 0) ||
487             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ADD, &qbuf, &rbuf))
488                 goto done;
489
490         /* Unmarshall response */
491
492         if (!srv_io_r_net_share_add("", &r, &rbuf, 0))
493                 goto done;
494
495         result = r.status;
496
497  done:
498         prs_mem_free(&qbuf);
499         prs_mem_free(&rbuf);
500
501         return result;  
502 }
503
504 WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx,
505                                  char *server, TIME_OF_DAY_INFO *tod)
506 {
507         prs_struct qbuf, rbuf;
508         SRV_Q_NET_REMOTE_TOD q;
509         SRV_R_NET_REMOTE_TOD r;
510         WERROR result = W_ERROR(ERRgeneral);
511
512         ZERO_STRUCT(q);
513         ZERO_STRUCT(r);
514
515         /* Initialise parse structures */
516
517         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
518         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
519
520         /* Initialise input parameters */
521
522         init_srv_q_net_remote_tod(&q, cli->srv_name_slash);
523
524         /* Marshall data and send request */
525
526         if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) ||
527             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_REMOTE_TOD, &qbuf, &rbuf))
528                 goto done;
529
530         /* Unmarshall response */
531
532         r.tod = tod;
533
534         if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0))
535                 goto done;
536
537         result = r.status;
538
539         if (!W_ERROR_IS_OK(result))
540                 goto done;
541
542  done:
543         prs_mem_free(&qbuf);
544         prs_mem_free(&rbuf);
545
546         return result;  
547 }
548
549 WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
550                                 uint32 file_level, const char *user_name,
551                                 SRV_FILE_INFO_CTR *ctr, int preferred_len,
552                                 ENUM_HND *hnd)
553 {
554         prs_struct qbuf, rbuf;
555         SRV_Q_NET_FILE_ENUM q;
556         SRV_R_NET_FILE_ENUM r;
557         WERROR result = W_ERROR(ERRgeneral);
558         int i;
559
560         ZERO_STRUCT(q);
561         ZERO_STRUCT(r);
562
563         /* Initialise parse structures */
564
565         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
566         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
567
568         /* Initialise input parameters */
569
570         init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name, 
571                                  file_level, ctr, preferred_len, hnd);
572
573         /* Marshall data and send request */
574
575         if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
576             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
577                 goto done;
578
579         /* Unmarshall response */
580
581         if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
582                 goto done;
583
584         result = r.status;
585
586         if (!W_ERROR_IS_OK(result))
587                 goto done;
588
589         /* copy the data over to the ctr */
590
591         ZERO_STRUCTP(ctr);
592
593         ctr->switch_value = file_level;
594
595         ctr->num_entries = ctr->num_entries2 = r.ctr.num_entries;
596         
597         switch(file_level) {
598         case 3:
599                 ctr->file.info3 = TALLOC_ARRAY(mem_ctx, SRV_FILE_INFO_3, ctr->num_entries);
600
601                 memset(ctr->file.info3, 0, 
602                        sizeof(SRV_FILE_INFO_3) * ctr->num_entries);
603
604                 for (i = 0; i < r.ctr.num_entries; i++) {
605                         SRV_FILE_INFO_3 *info3 = &ctr->file.info3[i];
606                         char *s;
607                         
608                         /* Copy pointer crap */
609
610                         memcpy(&info3->info_3, &r.ctr.file.info3[i].info_3, 
611                                sizeof(FILE_INFO_3));
612
613                         /* Duplicate strings */
614
615                         s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name);
616                         if (s)
617                                 init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE);
618                 
619                         s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name);
620                         if (s)
621                                 init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE);
622
623                 }               
624
625                 break;
626         }
627
628  done:
629         prs_mem_free(&qbuf);
630         prs_mem_free(&rbuf);
631
632         return result;
633 }
634
635 WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
636                                  uint32 file_id)
637 {
638         prs_struct qbuf, rbuf;
639         SRV_Q_NET_FILE_CLOSE q;
640         SRV_R_NET_FILE_CLOSE r;
641         WERROR result = W_ERROR(ERRgeneral);
642
643         ZERO_STRUCT(q);
644         ZERO_STRUCT(r);
645
646         /* Initialise parse structures */
647
648         prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
649         prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
650
651         /* Initialise input parameters */
652
653         init_srv_q_net_file_close(&q, cli->srv_name_slash, file_id);
654
655         /* Marshall data and send request */
656
657         if (!srv_io_q_net_file_close("", &q, &qbuf, 0) ||
658             !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_CLOSE, &qbuf, &rbuf))
659                 goto done;
660
661         /* Unmarshall response */
662
663         if (!srv_io_r_net_file_close("", &r, &rbuf, 0))
664                 goto done;
665
666         result = r.status;
667  done:
668         prs_mem_free(&qbuf);
669         prs_mem_free(&rbuf);
670         return result;
671 }