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