first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[sfrench/samba-autobuild/.git] / source3 / rpc_server / srv_srvsvc.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
9  *  
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30 extern pstring global_myname;
31
32 /*******************************************************************
33  Fill in a share info level 1 structure.
34  ********************************************************************/
35
36 static void init_srv_share_info_1(SRV_SHARE_INFO_1 *sh1, int snum)
37 {
38         int len_net_name;
39         pstring net_name;
40         pstring remark;
41         uint32 type;
42
43         pstrcpy(net_name, lp_servicename(snum));
44         pstrcpy(remark, lp_comment(snum));
45         pstring_sub(remark,"%S",lp_servicename(snum));
46         len_net_name = strlen(net_name);
47
48         /* work out the share type */
49         type = STYPE_DISKTREE;
50                 
51         if (lp_print_ok(snum))
52                 type = STYPE_PRINTQ;
53         if (strequal("IPC$", net_name))
54                 type = STYPE_IPC;
55         if (net_name[len_net_name] == '$')
56                 type |= STYPE_HIDDEN;
57
58         init_srv_share_info1(&sh1->info_1, net_name, type, remark);
59         init_srv_share_info1_str(&sh1->info_1_str, net_name, remark);
60 }
61
62 /*******************************************************************
63  Fill in a share info level 2 structure.
64  ********************************************************************/
65
66 static void init_srv_share_info_2(SRV_SHARE_INFO_2 *sh2, int snum)
67 {
68         int len_net_name;
69         pstring net_name;
70         pstring remark;
71         pstring path;
72         pstring passwd;
73         uint32 type;
74
75         pstrcpy(net_name, lp_servicename(snum));
76         pstrcpy(remark, lp_comment(snum));
77         pstring_sub(remark,"%S",lp_servicename(snum));
78         pstrcpy(path, lp_pathname(snum));
79         pstrcpy(passwd, "");
80         len_net_name = strlen(net_name);
81
82         /* work out the share type */
83         type = STYPE_DISKTREE;
84                 
85         if (lp_print_ok(snum))
86                 type = STYPE_PRINTQ;
87         if (strequal("IPC$", net_name))
88                 type = STYPE_IPC;
89         if (net_name[len_net_name] == '$')
90                 type |= STYPE_HIDDEN;
91
92         init_srv_share_info2(&sh2->info_2, net_name, type, remark, 0, 0xffffffff, 1, path, passwd);
93         init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
94 }
95
96 /*******************************************************************
97  Fill in a share info structure.
98  ********************************************************************/
99
100 static BOOL init_srv_share_info_ctr(SRV_SHARE_INFO_CTR *ctr,
101                uint32 info_level, uint32 *resume_hnd, uint32 *total_entries)
102 {
103         int num_entries = 0;
104         int num_services = lp_numservices();
105         int snum;
106
107         DEBUG(5,("init_srv_share_info_ctr\n"));
108
109         ZERO_STRUCTPN(ctr);
110
111         ctr->info_level = ctr->switch_value = info_level;
112         *resume_hnd = 0;
113
114         /* Count the number of entries. */
115         for (snum = 0; snum < num_services; snum++) {
116                 if (lp_browseable(snum) && lp_snum_ok(snum))
117                         num_entries++;
118         }
119
120         *total_entries = num_entries;
121         ctr->num_entries2 = ctr->num_entries = num_entries;
122         ctr->ptr_share_info = ctr->ptr_entries = 1;
123
124         if (!num_entries)
125                 return True;
126
127         switch (info_level) {
128         case 1:
129         {
130                 SRV_SHARE_INFO_1 *info1;
131                 int i = 0;
132
133                 info1 = malloc(num_entries * sizeof(SRV_SHARE_INFO_1));
134
135                 for (snum = *resume_hnd; snum < num_services; snum++) {
136                         if (lp_browseable(snum) && lp_snum_ok(snum)) {
137                                 init_srv_share_info_1(&info1[i++], snum);
138                         }
139                 }
140
141                 ctr->share.info1 = info1;
142                 break;
143         }
144
145         case 2:
146         {
147                 SRV_SHARE_INFO_2 *info2;
148                 int i = 0;
149
150                 info2 = malloc(num_entries * sizeof(SRV_SHARE_INFO_2));
151
152                 for (snum = *resume_hnd; snum < num_services; snum++) {
153                         if (lp_browseable(snum) && lp_snum_ok(snum)) {
154                                 init_srv_share_info_2(&info2[i++], snum);
155                         }
156                 }
157
158                 ctr->share.info2 = info2;
159                 break;
160         }
161
162         default:
163                 DEBUG(5,("init_srv_share_info_ctr: unsupported switch value %d\n", info_level));
164                 return False;
165         }
166
167         return True;
168 }
169
170 /*******************************************************************
171  Inits a SRV_R_NET_SHARE_ENUM structure.
172 ********************************************************************/
173
174 static void init_srv_r_net_share_enum(SRV_R_NET_SHARE_ENUM *r_n,
175                                       uint32 info_level, uint32 resume_hnd)  
176 {
177         DEBUG(5,("init_srv_r_net_share_enum: %d\n", __LINE__));
178
179         if (init_srv_share_info_ctr(&r_n->ctr, info_level,
180                                     &resume_hnd, &r_n->total_entries)) {
181                 r_n->status = 0x0;
182         } else {
183                 r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
184         }
185
186         init_enum_hnd(&r_n->enum_hnd, resume_hnd);
187 }
188
189 /*******************************************************************
190  Net share enum.
191 ********************************************************************/
192
193 static BOOL srv_reply_net_share_enum(SRV_Q_NET_SHARE_ENUM *q_n,
194                                 prs_struct *rdata)
195 {
196         SRV_R_NET_SHARE_ENUM r_n;
197         BOOL ret;
198
199         DEBUG(5,("srv_net_share_enum: %d\n", __LINE__));
200
201         /* Create the list of shares for the response. */
202         init_srv_r_net_share_enum(&r_n,
203                                 q_n->ctr.info_level,
204                                 get_enum_hnd(&q_n->enum_hnd));
205
206         /* store the response in the SMB stream */
207         ret = srv_io_r_net_share_enum("", &r_n, rdata, 0);
208
209         /* Free the memory used by the response. */
210         free_srv_r_net_share_enum(&r_n);
211
212         DEBUG(5,("srv_net_share_enum: %d\n", __LINE__));
213
214         return ret;
215 }
216
217 /*******************************************************************
218  Inits a SRV_R_NET_SHARE_GET_INFO structure.
219 ********************************************************************/
220
221 static void init_srv_r_net_share_get_info(SRV_R_NET_SHARE_GET_INFO *r_n,
222                                   char *share_name, uint32 info_level)
223 {
224         uint32 status = 0x0;
225         int snum;
226
227         DEBUG(5,("init_srv_r_net_share_get_info: %d\n", __LINE__));
228
229         r_n->switch_value = info_level;
230
231         snum = find_service(share_name);
232
233         if (snum >= 0) {
234                 switch (info_level) {
235                 case 1:
236                         init_srv_share_info_1(&r_n->share.info1, snum);
237                         break;
238                 case 2:
239                         init_srv_share_info_2(&r_n->share.info2, snum);
240                         break;
241                 default:
242                         DEBUG(5,("init_srv_net_share_get_info: unsupported switch value %d\n", info_level));
243                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
244                         break;
245                 }
246         } else {
247                 status = 0xC0000000 | NT_STATUS_BAD_NETWORK_NAME;
248         }
249
250         r_n->ptr_share_ctr = (status == 0x0) ? 1 : 0;
251         r_n->status = status;
252 }
253
254 /*******************************************************************
255  Net share get info.
256 ********************************************************************/
257
258 static BOOL srv_reply_net_share_get_info(SRV_Q_NET_SHARE_GET_INFO *q_n,
259                                          prs_struct *rdata)
260 {
261         SRV_R_NET_SHARE_GET_INFO r_n;
262         char *share_name;
263         BOOL ret;
264
265         DEBUG(5,("srv_net_share_get_info: %d\n", __LINE__));
266
267         /* Create the list of shares for the response. */
268         share_name = dos_unistr2_to_str(&q_n->uni_share_name);
269         init_srv_r_net_share_get_info(&r_n, share_name, q_n->info_level);
270
271         /* store the response in the SMB stream */
272         ret = srv_io_r_net_share_get_info("", &r_n, rdata, 0);
273
274         /* Free the memory used by the response. */
275         free_srv_r_net_share_get_info(&r_n);
276
277         DEBUG(5,("srv_net_share_get_info: %d\n", __LINE__));
278
279         return ret;
280 }
281
282 /*******************************************************************
283  fill in a sess info level 1 structure.
284
285  this function breaks the rule that i'd like to be in place, namely
286  it doesn't receive its data as arguments: it has to call lp_xxxx()
287  functions itself.  yuck.
288
289  ********************************************************************/
290 static void init_srv_sess_0_info(SESS_INFO_0    *se0, SESS_INFO_0_STR *str0,
291                                 char *name)
292 {
293         init_srv_sess_info0    (se0 , name);
294         init_srv_sess_info0_str(str0, name);
295 }
296
297 /*******************************************************************
298  fill in a sess info level 0 structure.
299
300  this function breaks the rule that i'd like to be in place, namely
301  it doesn't receive its data as arguments: it has to call lp_xxxx()
302  functions itself.  yuck.
303
304  ********************************************************************/
305 static void init_srv_sess_info_0(SRV_SESS_INFO_0 *ss0, uint32 *snum, uint32 *stot)
306 {
307         uint32 num_entries = 0;
308         (*stot) = 1;
309
310         if (ss0 == NULL)
311         {
312                 (*snum) = 0;
313                 return;
314         }
315
316         DEBUG(5,("init_srv_sess_0_ss0\n"));
317
318         if (snum)
319         {
320                 for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++)
321                 {
322                         init_srv_sess_0_info(&(ss0->info_0    [num_entries]),
323                                                                  &(ss0->info_0_str[num_entries]), "MACHINE");
324
325                         /* move on to creating next session */
326                         /* move on to creating next sess */
327                         num_entries++;
328                 }
329
330                 ss0->num_entries_read  = num_entries;
331                 ss0->ptr_sess_info     = num_entries > 0 ? 1 : 0;
332                 ss0->num_entries_read2 = num_entries;
333                 
334                 if ((*snum) >= (*stot))
335                 {
336                         (*snum) = 0;
337                 }
338         }
339         else
340         {
341                 ss0->num_entries_read = 0;
342                 ss0->ptr_sess_info = 0;
343                 ss0->num_entries_read2 = 0;
344         }
345 }
346
347 /*******************************************************************
348  fill in a sess info level 1 structure.
349
350  this function breaks the rule that i'd like to be in place, namely
351  it doesn't receive its data as arguments: it has to call lp_xxxx()
352  functions itself.  yuck.
353
354  ********************************************************************/
355 static void init_srv_sess_1_info(SESS_INFO_1    *se1, SESS_INFO_1_STR *str1,
356                                 char *name, char *user,
357                                 uint32 num_opens,
358                                 uint32 open_time, uint32 idle_time,
359                                 uint32 usr_flgs)
360 {
361         init_srv_sess_info1    (se1 , name, user, num_opens, open_time, idle_time, usr_flgs);
362         init_srv_sess_info1_str(str1, name, user);
363 }
364
365 /*******************************************************************
366  fill in a sess info level 1 structure.
367
368  this function breaks the rule that i'd like to be in place, namely
369  it doesn't receive its data as arguments: it has to call lp_xxxx()
370  functions itself.  yuck.
371
372  ********************************************************************/
373 static void init_srv_sess_info_1(SRV_SESS_INFO_1 *ss1, uint32 *snum, uint32 *stot)
374 {
375         uint32 num_entries = 0;
376         (*stot) = 1;
377
378         if (ss1 == NULL)
379         {
380                 (*snum) = 0;
381                 return;
382         }
383
384         DEBUG(5,("init_srv_sess_1_ss1\n"));
385
386         if (snum)
387         {
388                 for (; (*snum) < (*stot) && num_entries < MAX_SESS_ENTRIES; (*snum)++)
389                 {
390                         init_srv_sess_1_info(&(ss1->info_1    [num_entries]),
391                                                                  &(ss1->info_1_str[num_entries]),
392                                              "MACHINE", "dummy_user", 1, 10, 5, 0);
393
394                         /* move on to creating next session */
395                         /* move on to creating next sess */
396                         num_entries++;
397                 }
398
399                 ss1->num_entries_read  = num_entries;
400                 ss1->ptr_sess_info     = num_entries > 0 ? 1 : 0;
401                 ss1->num_entries_read2 = num_entries;
402                 
403                 if ((*snum) >= (*stot))
404                 {
405                         (*snum) = 0;
406                 }
407         }
408         else
409         {
410                 ss1->num_entries_read = 0;
411                 ss1->ptr_sess_info = 0;
412                 ss1->num_entries_read2 = 0;
413                 
414                 (*stot) = 0;
415         }
416 }
417
418 /*******************************************************************
419  makes a SRV_R_NET_SESS_ENUM structure.
420 ********************************************************************/
421 static uint32 init_srv_sess_info_ctr(SRV_SESS_INFO_CTR *ctr,
422                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
423 {
424         uint32 status = 0x0;
425         DEBUG(5,("init_srv_sess_info_ctr: %d\n", __LINE__));
426
427         ctr->switch_value = switch_value;
428
429         switch (switch_value)
430         {
431                 case 0:
432                 {
433                         init_srv_sess_info_0(&(ctr->sess.info0), resume_hnd, total_entries);
434                         ctr->ptr_sess_ctr = 1;
435                         break;
436                 }
437                 case 1:
438                 {
439                         init_srv_sess_info_1(&(ctr->sess.info1), resume_hnd, total_entries);
440                         ctr->ptr_sess_ctr = 1;
441                         break;
442                 }
443                 default:
444                 {
445                         DEBUG(5,("init_srv_sess_info_ctr: unsupported switch value %d\n",
446                                   switch_value));
447                         (*resume_hnd) = 0;
448                         (*total_entries) = 0;
449                         ctr->ptr_sess_ctr = 0;
450                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
451                         break;
452                 }
453         }
454
455         return status;
456 }
457
458 /*******************************************************************
459  makes a SRV_R_NET_SESS_ENUM structure.
460 ********************************************************************/
461 static void init_srv_r_net_sess_enum(SRV_R_NET_SESS_ENUM *r_n,
462                                 uint32 resume_hnd, int sess_level, int switch_value)  
463 {
464         DEBUG(5,("init_srv_r_net_sess_enum: %d\n", __LINE__));
465
466         r_n->sess_level  = sess_level;
467         if (sess_level == -1)
468         {
469                 r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
470         }
471         else
472         {
473                 r_n->status = init_srv_sess_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
474         }
475         if (r_n->status != 0x0)
476         {
477                 resume_hnd = 0;
478         }
479         init_enum_hnd(&(r_n->enum_hnd), resume_hnd);
480 }
481
482 /*******************************************************************
483 net sess enum
484 ********************************************************************/
485 static void srv_reply_net_sess_enum(SRV_Q_NET_SESS_ENUM *q_n,
486                                 prs_struct *rdata)
487 {
488         SRV_R_NET_SESS_ENUM r_n;
489         SRV_SESS_INFO_CTR ctr;
490
491         r_n.ctr = &ctr;
492
493         DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__));
494
495         /* set up the */
496         init_srv_r_net_sess_enum(&r_n,
497                                 get_enum_hnd(&q_n->enum_hnd),
498                                 q_n->sess_level,
499                                 q_n->ctr->switch_value);
500
501         /* store the response in the SMB stream */
502         srv_io_r_net_sess_enum("", &r_n, rdata, 0);
503
504         DEBUG(5,("srv_net_sess_enum: %d\n", __LINE__));
505 }
506
507 /*******************************************************************
508  fill in a conn info level 0 structure.
509
510  this function breaks the rule that i'd like to be in place, namely
511  it doesn't receive its data as arguments: it has to call lp_xxxx()
512  functions itself.  yuck.
513
514  ********************************************************************/
515 static void init_srv_conn_info_0(SRV_CONN_INFO_0 *ss0, uint32 *snum, uint32 *stot)
516 {
517         uint32 num_entries = 0;
518         (*stot) = 1;
519
520         if (ss0 == NULL)
521         {
522                 (*snum) = 0;
523                 return;
524         }
525
526         DEBUG(5,("init_srv_conn_0_ss0\n"));
527
528         if (snum)
529         {
530                 for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++)
531                 {
532                         init_srv_conn_info0(&(ss0->info_0    [num_entries]), (*stot));
533
534                         /* move on to creating next connection */
535                         /* move on to creating next conn */
536                         num_entries++;
537                 }
538
539                 ss0->num_entries_read  = num_entries;
540                 ss0->ptr_conn_info     = num_entries > 0 ? 1 : 0;
541                 ss0->num_entries_read2 = num_entries;
542                 
543                 
544
545                 if ((*snum) >= (*stot))
546                 {
547                         (*snum) = 0;
548                 }
549         }
550         else
551         {
552                 ss0->num_entries_read = 0;
553                 ss0->ptr_conn_info = 0;
554                 ss0->num_entries_read2 = 0;
555
556                 (*stot) = 0;
557         }
558 }
559
560 /*******************************************************************
561  fill in a conn info level 1 structure.
562
563  this function breaks the rule that i'd like to be in place, namely
564  it doesn't receive its data as arguments: it has to call lp_xxxx()
565  functions itself.  yuck.
566
567  ********************************************************************/
568 static void init_srv_conn_1_info(CONN_INFO_1    *se1, CONN_INFO_1_STR *str1,
569                                 uint32 id, uint32 type,
570                                 uint32 num_opens, uint32 num_users, uint32 open_time,
571                                 char *usr_name, char *net_name)
572 {
573         init_srv_conn_info1    (se1 , id, type, num_opens, num_users, open_time, usr_name, net_name);
574         init_srv_conn_info1_str(str1, usr_name, net_name);
575 }
576
577 /*******************************************************************
578  fill in a conn info level 1 structure.
579
580  this function breaks the rule that i'd like to be in place, namely
581  it doesn't receive its data as arguments: it has to call lp_xxxx()
582  functions itself.  yuck.
583
584  ********************************************************************/
585 static void init_srv_conn_info_1(SRV_CONN_INFO_1 *ss1, uint32 *snum, uint32 *stot)
586 {
587         uint32 num_entries = 0;
588         (*stot) = 1;
589
590         if (ss1 == NULL)
591         {
592                 (*snum) = 0;
593                 return;
594         }
595
596         DEBUG(5,("init_srv_conn_1_ss1\n"));
597
598         if (snum)
599         {
600                 for (; (*snum) < (*stot) && num_entries < MAX_CONN_ENTRIES; (*snum)++)
601                 {
602                         init_srv_conn_1_info(&(ss1->info_1    [num_entries]),
603                                                                  &(ss1->info_1_str[num_entries]),
604                                              (*stot), 0x3, 1, 1, 3,"dummy_user", "IPC$");
605
606                         /* move on to creating next connection */
607                         /* move on to creating next conn */
608                         num_entries++;
609                 }
610
611                 ss1->num_entries_read  = num_entries;
612                 ss1->ptr_conn_info     = num_entries > 0 ? 1 : 0;
613                 ss1->num_entries_read2 = num_entries;
614                 
615
616                 if ((*snum) >= (*stot))
617                 {
618                         (*snum) = 0;
619                 }
620         }
621         else
622         {
623                 ss1->num_entries_read = 0;
624                 ss1->ptr_conn_info = 0;
625                 ss1->num_entries_read2 = 0;
626                 
627                 (*stot) = 0;
628         }
629 }
630
631 /*******************************************************************
632  makes a SRV_R_NET_CONN_ENUM structure.
633 ********************************************************************/
634 static uint32 init_srv_conn_info_ctr(SRV_CONN_INFO_CTR *ctr,
635                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)
636 {
637         uint32 status = 0x0;
638         DEBUG(5,("init_srv_conn_info_ctr: %d\n", __LINE__));
639
640         ctr->switch_value = switch_value;
641
642         switch (switch_value)
643         {
644                 case 0:
645                 {
646                         init_srv_conn_info_0(&(ctr->conn.info0), resume_hnd, total_entries);
647                         ctr->ptr_conn_ctr = 1;
648                         break;
649                 }
650                 case 1:
651                 {
652                         init_srv_conn_info_1(&(ctr->conn.info1), resume_hnd, total_entries);
653                         ctr->ptr_conn_ctr = 1;
654                         break;
655                 }
656                 default:
657                 {
658                         DEBUG(5,("init_srv_conn_info_ctr: unsupported switch value %d\n",
659                                   switch_value));
660                         (*resume_hnd = 0);
661                         (*total_entries) = 0;
662                         ctr->ptr_conn_ctr = 0;
663                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
664                         break;
665                 }
666         }
667
668         return status;
669 }
670
671 /*******************************************************************
672  makes a SRV_R_NET_CONN_ENUM structure.
673 ********************************************************************/
674 static void init_srv_r_net_conn_enum(SRV_R_NET_CONN_ENUM *r_n,
675                                 uint32 resume_hnd, int conn_level, int switch_value)  
676 {
677         DEBUG(5,("init_srv_r_net_conn_enum: %d\n", __LINE__));
678
679         r_n->conn_level  = conn_level;
680         if (conn_level == -1)
681         {
682                 r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
683         }
684         else
685         {
686                 r_n->status = init_srv_conn_info_ctr(r_n->ctr, switch_value, &resume_hnd, &r_n->total_entries);
687         }
688         if (r_n->status != 0x0)
689         {
690                 resume_hnd = 0;
691         }
692         init_enum_hnd(&(r_n->enum_hnd), resume_hnd);
693 }
694
695 /*******************************************************************
696 net conn enum
697 ********************************************************************/
698 static void srv_reply_net_conn_enum(SRV_Q_NET_CONN_ENUM *q_n,
699                                 prs_struct *rdata)
700 {
701         SRV_R_NET_CONN_ENUM r_n;
702         SRV_CONN_INFO_CTR ctr;
703
704         r_n.ctr = &ctr;
705
706         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
707
708         /* set up the */
709         init_srv_r_net_conn_enum(&r_n,
710                                 get_enum_hnd(&q_n->enum_hnd),
711                                 q_n->conn_level,
712                                 q_n->ctr->switch_value);
713
714         /* store the response in the SMB stream */
715         srv_io_r_net_conn_enum("", &r_n, rdata, 0);
716
717         DEBUG(5,("srv_net_conn_enum: %d\n", __LINE__));
718 }
719
720 /*******************************************************************
721  fill in a file info level 3 structure.
722  ********************************************************************/
723 static void init_srv_file_3_info(FILE_INFO_3     *fl3, FILE_INFO_3_STR *str3,
724                                 uint32 fnum, uint32 perms, uint32 num_locks,
725                                 char *path_name, char *user_name)
726 {
727         init_srv_file_info3    (fl3 , fnum, perms, num_locks, path_name, user_name);
728         init_srv_file_info3_str(str3, path_name, user_name);
729 }
730
731 /*******************************************************************
732  fill in a file info level 3 structure.
733
734  this function breaks the rule that i'd like to be in place, namely
735  it doesn't receive its data as arguments: it has to call lp_xxxx()
736  functions itself.  yuck.
737
738  ********************************************************************/
739 static void init_srv_file_info_3(SRV_FILE_INFO_3 *fl3, uint32 *fnum, uint32 *ftot)
740 {
741         uint32 num_entries = 0;
742         (*ftot) = 1;
743
744         if (fl3 == NULL)
745         {
746                 (*fnum) = 0;
747                 return;
748         }
749
750         DEBUG(5,("init_srv_file_3_fl3\n"));
751
752         for (; (*fnum) < (*ftot) && num_entries < MAX_FILE_ENTRIES; (*fnum)++)
753         {
754                 init_srv_file_3_info(&(fl3->info_3    [num_entries]),
755                                          &(fl3->info_3_str[num_entries]),
756                                      (*fnum), 0x35, 0, "\\PIPE\\samr", "dummy user");
757
758                 /* move on to creating next file */
759                 num_entries++;
760         }
761
762         fl3->num_entries_read  = num_entries;
763         fl3->ptr_file_info     = num_entries > 0 ? 1 : 0;
764         fl3->num_entries_read2 = num_entries;
765         
766         if ((*fnum) >= (*ftot))
767         {
768                 (*fnum) = 0;
769         }
770 }
771
772 /*******************************************************************
773  makes a SRV_R_NET_FILE_ENUM structure.
774 ********************************************************************/
775 static uint32 init_srv_file_info_ctr(SRV_FILE_INFO_CTR *ctr,
776                                 int switch_value, uint32 *resume_hnd, uint32 *total_entries)  
777 {
778         uint32 status = 0x0;
779         DEBUG(5,("init_srv_file_info_ctr: %d\n", __LINE__));
780
781         ctr->switch_value = switch_value;
782
783         switch (switch_value)
784         {
785                 case 3:
786                 {
787                         init_srv_file_info_3(&(ctr->file.info3), resume_hnd, total_entries);
788                         ctr->ptr_file_ctr = 1;
789                         break;
790                 }
791                 default:
792                 {
793                         DEBUG(5,("init_srv_file_info_ctr: unsupported switch value %d\n",
794                                   switch_value));
795                         (*resume_hnd = 0);
796                         (*total_entries) = 0;
797                         ctr->ptr_file_ctr = 0;
798                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
799                         break;
800                 }
801         }
802
803         return status;
804 }
805
806 /*******************************************************************
807  makes a SRV_R_NET_FILE_ENUM structure.
808 ********************************************************************/
809 static void init_srv_r_net_file_enum(SRV_R_NET_FILE_ENUM *r_n,
810                                 uint32 resume_hnd, int file_level, int switch_value)  
811 {
812         DEBUG(5,("init_srv_r_net_file_enum: %d\n", __LINE__));
813
814         r_n->file_level  = file_level;
815         if (file_level == 0)
816         {
817                 r_n->status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
818         }
819         else
820         {
821                 r_n->status = init_srv_file_info_ctr(r_n->ctr, switch_value, &resume_hnd, &(r_n->total_entries));
822         }
823         if (r_n->status != 0x0)
824         {
825                 resume_hnd = 0;
826         }
827         init_enum_hnd(&(r_n->enum_hnd), resume_hnd);
828 }
829
830 /*******************************************************************
831 net file enum
832 ********************************************************************/
833 static void srv_reply_net_file_enum(SRV_Q_NET_FILE_ENUM *q_n,
834                                 prs_struct *rdata)
835 {
836         SRV_R_NET_FILE_ENUM r_n;
837         SRV_FILE_INFO_CTR ctr;
838
839         r_n.ctr = &ctr;
840
841         DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
842
843         /* set up the */
844         init_srv_r_net_file_enum(&r_n,
845                                 get_enum_hnd(&q_n->enum_hnd),
846                                 q_n->file_level,
847                                 q_n->ctr->switch_value);
848
849         /* store the response in the SMB stream */
850         srv_io_r_net_file_enum("", &r_n, rdata, 0);
851
852         DEBUG(5,("srv_net_file_enum: %d\n", __LINE__));
853 }
854
855 /*******************************************************************
856 net server get info
857 ********************************************************************/
858
859 static void srv_reply_net_srv_get_info(SRV_Q_NET_SRV_GET_INFO *q_n,
860                                 prs_struct *rdata)
861 {
862         SRV_R_NET_SRV_GET_INFO r_n;
863         uint32 status = 0x0;
864         SRV_INFO_CTR ctr;
865
866
867         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
868
869         switch (q_n->switch_value)
870         {
871                 case 102:
872                 {
873                         init_srv_info_102(&ctr.srv.sv102,
874                                           500, global_myname, 
875                                           string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH),
876                                           lp_major_announce_version(), lp_minor_announce_version(),
877                                           lp_default_server_announce(),
878                                           0xffffffff, /* users */
879                                           0xf, /* disc */
880                                           0, /* hidden */
881                                           240, /* announce */
882                                           3000, /* announce delta */
883                                           100000, /* licenses */
884                                           "c:\\"); /* user path */
885                         break;
886                 }
887                 case 101:
888                 {
889                         init_srv_info_101(&ctr.srv.sv101,
890                                           500, global_myname,
891                                           lp_major_announce_version(), lp_minor_announce_version(),
892                                           lp_default_server_announce(),
893                                           string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
894                         break;
895                 }
896                 default:
897                 {
898                         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
899                         break;
900                 }
901         }
902
903         /* set up the net server get info structure */
904         init_srv_r_net_srv_get_info(&r_n, q_n->switch_value, &ctr, status);
905
906         /* store the response in the SMB stream */
907         srv_io_r_net_srv_get_info("", &r_n, rdata, 0);
908
909         DEBUG(5,("srv_net_srv_get_info: %d\n", __LINE__));
910 }
911
912 /*******************************************************************
913 ********************************************************************/
914 static BOOL api_srv_net_srv_get_info( uint16 vuid, prs_struct *data,
915                                     prs_struct *rdata )
916 {
917         SRV_Q_NET_SRV_GET_INFO q_n;
918
919         /* grab the net server get info */
920         srv_io_q_net_srv_get_info("", &q_n, data, 0);
921
922         /* construct reply.  always indicate success */
923         srv_reply_net_srv_get_info(&q_n, rdata);
924
925         return True;
926 }
927
928
929 /*******************************************************************
930 ********************************************************************/
931 static BOOL api_srv_net_file_enum( uint16 vuid, prs_struct *data,
932                                     prs_struct *rdata )
933 {
934         SRV_Q_NET_FILE_ENUM q_n;
935         SRV_FILE_INFO_CTR ctr;
936
937         q_n.ctr = &ctr;
938
939         /* grab the net file enum */
940         srv_io_q_net_file_enum("", &q_n, data, 0);
941
942         /* construct reply.  always indicate success */
943         srv_reply_net_file_enum(&q_n, rdata);
944
945         return True;
946 }
947
948
949 /*******************************************************************
950 ********************************************************************/
951 static BOOL api_srv_net_conn_enum( uint16 vuid, prs_struct *data,
952                                     prs_struct *rdata )
953 {
954         SRV_Q_NET_CONN_ENUM q_n;
955         SRV_CONN_INFO_CTR ctr;
956
957         q_n.ctr = &ctr;
958
959         /* grab the net server get enum */
960         srv_io_q_net_conn_enum("", &q_n, data, 0);
961
962         /* construct reply.  always indicate success */
963         srv_reply_net_conn_enum(&q_n, rdata);
964
965         return True;
966 }
967
968
969 /*******************************************************************
970 ********************************************************************/
971 static BOOL api_srv_net_sess_enum( uint16 vuid, prs_struct *data,
972                                     prs_struct *rdata )
973 {
974         SRV_Q_NET_SESS_ENUM q_n;
975         SRV_SESS_INFO_CTR ctr;
976
977         q_n.ctr = &ctr;
978
979         /* grab the net server get enum */
980         srv_io_q_net_sess_enum("", &q_n, data, 0);
981
982         /* construct reply.  always indicate success */
983         srv_reply_net_sess_enum(&q_n, rdata);
984
985         return True;
986 }
987
988
989 /*******************************************************************
990  RPC to enumerate shares.
991 ********************************************************************/
992
993 static BOOL api_srv_net_share_enum( uint16 vuid, prs_struct *data,
994                                     prs_struct *rdata )
995 {
996         SRV_Q_NET_SHARE_ENUM q_n;
997         BOOL ret;
998
999         /* Unmarshall the net server get enum. */
1000         if(!srv_io_q_net_share_enum("", &q_n, data, 0)) {
1001                 DEBUG(0,("api_srv_net_share_enum: Failed to unmarshall SRV_Q_NET_SHARE_ENUM.\n"));
1002                 return False;
1003         }
1004
1005         ret = srv_reply_net_share_enum(&q_n, rdata);
1006
1007         /* Free any data allocated in the unmarshalling. */
1008         free_srv_q_net_share_enum(&q_n);
1009
1010         return ret;
1011 }
1012
1013 /*******************************************************************
1014  RPC to return share information.
1015 ********************************************************************/
1016
1017 static BOOL api_srv_net_share_get_info( uint16 vuid, prs_struct *data,
1018                                         prs_struct *rdata )
1019 {
1020         SRV_Q_NET_SHARE_GET_INFO q_n;
1021         BOOL ret;
1022
1023         /* Unmarshall the net server get info. */
1024         if(!srv_io_q_net_share_get_info("", &q_n, data, 0)) {
1025                 DEBUG(0,("api_srv_net_share_get_info: Failed to unmarshall SRV_Q_NET_SHARE_GET_INFO.\n"));
1026                 return False;
1027         }
1028
1029         ret = srv_reply_net_share_get_info(&q_n, rdata);
1030
1031         /* Free any data allocated in the unmarshalling. */
1032         free_srv_q_net_share_get_info(&q_n);
1033
1034         return ret;
1035 }
1036
1037 /*******************************************************************
1038 time of day
1039 ********************************************************************/
1040 static BOOL srv_reply_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_n,
1041                                 prs_struct *rdata)
1042 {
1043         SRV_R_NET_REMOTE_TOD r_n;
1044         TIME_OF_DAY_INFO tod;
1045         struct tm *t;
1046         time_t unixdate = time(NULL);
1047
1048         r_n.tod = &tod;
1049         r_n.ptr_srv_tod = 0x1;
1050         r_n.status = 0x0;
1051
1052         DEBUG(5,("srv_reply_net_remote_tod: %d\n", __LINE__));
1053
1054         t = gmtime(&unixdate);
1055
1056         /* set up the */
1057         init_time_of_day_info(&tod,
1058                               unixdate,
1059                               0,
1060                               t->tm_hour,
1061                               t->tm_min,
1062                               t->tm_sec,
1063                               0,
1064                               TimeDiff(unixdate)/60,
1065                               10000,
1066                               t->tm_mday,
1067                               t->tm_mon + 1,
1068                               1900+t->tm_year,
1069                               t->tm_wday);
1070         
1071         /* store the response in the SMB stream */
1072         srv_io_r_net_remote_tod("", &r_n, rdata, 0);
1073         
1074         DEBUG(5,("srv_reply_net_remote_tod: %d\n", __LINE__));
1075
1076         return True;
1077 }
1078 /*******************************************************************
1079 ********************************************************************/
1080 static BOOL api_srv_net_remote_tod( uint16 vuid, prs_struct *data,
1081                                     prs_struct *rdata )
1082 {
1083         SRV_Q_NET_REMOTE_TOD q_n;
1084
1085         /* grab the net server get enum */
1086         srv_io_q_net_remote_tod("", &q_n, data, 0);
1087
1088         /* construct reply.  always indicate success */
1089         srv_reply_net_remote_tod(&q_n, rdata);
1090
1091         return True;
1092 }
1093
1094
1095 /*******************************************************************
1096 \PIPE\srvsvc commands
1097 ********************************************************************/
1098 struct api_struct api_srv_cmds[] =
1099 {
1100         { "SRV_NETCONNENUM"       , SRV_NETCONNENUM       , api_srv_net_conn_enum    },
1101         { "SRV_NETSESSENUM"       , SRV_NETSESSENUM       , api_srv_net_sess_enum    },
1102         { "SRV_NETSHAREENUM"      , SRV_NETSHAREENUM      , api_srv_net_share_enum   },
1103         { "SRV_NET_SHARE_GET_INFO", SRV_NET_SHARE_GET_INFO, api_srv_net_share_get_info },
1104         { "SRV_NETFILEENUM"       , SRV_NETFILEENUM       , api_srv_net_file_enum    },
1105         { "SRV_NET_SRV_GET_INFO"  , SRV_NET_SRV_GET_INFO  , api_srv_net_srv_get_info },
1106         { "SRV_NET_REMOTE_TOD"    , SRV_NET_REMOTE_TOD    , api_srv_net_remote_tod   },
1107         { NULL                    , 0                     , NULL                     }
1108 };
1109
1110 /*******************************************************************
1111 receives a srvsvc pipe and responds.
1112 ********************************************************************/
1113 BOOL api_srvsvc_rpc(pipes_struct *p, prs_struct *data)
1114 {
1115         return api_rpcTNP(p, "api_srvsvc_rpc", api_srv_cmds, data);
1116 }