~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/libsmb/clirap2.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Samba Unix/Linux SMB client library 
3
 
   More client RAP (SMB Remote Procedure Calls) functions
4
 
   Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
5
 
   Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
6
 
                    
7
 
   
8
 
   This program is free software; you can redistribute it and/or modify
9
 
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 2 of the License, or
11
 
   (at your option) any later version.
12
 
   
13
 
   This program is distributed in the hope that it will be useful,
14
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
   GNU General Public License for more details.
17
 
   
18
 
   You should have received a copy of the GNU General Public License
19
 
   along with this program; if not, write to the Free Software
20
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
*/
22
 
 
23
 
/*****************************************************/
24
 
/*                                                   */
25
 
/*   Additional RAP functionality                    */
26
 
/*                                                   */
27
 
/*   RAP is the original SMB RPC, documented         */
28
 
/*   by Microsoft and X/Open in the 1990s and        */
29
 
/*   supported by most SMB/CIFS servers although     */
30
 
/*   it is unlikely that any one implementation      */
31
 
/*   supports all RAP command codes since some       */
32
 
/*   are quite obsolete and a few are specific       */
33
 
/*   to a particular network operating system        */
34
 
/*                                                   */ 
35
 
/*   Although it has largely been replaced           */ 
36
 
/*   for complex remote admistration and management  */
37
 
/*   (of servers) by the relatively newer            */
38
 
/*   DCE/RPC based remote API (which better handles  */
39
 
/*   large >64K data structures), there are many     */
40
 
/*   important administrative and resource location  */
41
 
/*   tasks and user tasks (e.g. password change)     */
42
 
/*   that are performed via RAP.                     */
43
 
/*                                                   */
44
 
/*   Although a few of the RAP calls are implemented */
45
 
/*   in the Samba client library already (clirap.c)  */
46
 
/*   the new ones are in clirap2.c for easy patching */
47
 
/*   and integration and a corresponding header      */
48
 
/*   file, rap.h, has been created.                  */
49
 
/*                                                   */
50
 
/*   This is based on data from the CIFS spec        */
51
 
/*   and the LAN Server and LAN Manager              */
52
 
/*   Programming Reference books and published       */
53
 
/*   RAP document and CIFS forum postings and        */
54
 
/*   lots of trial and error                         */
55
 
/*                                                   */
56
 
/*   Function names changed from API_ (as they are   */
57
 
/*   in the CIFS specification) to RAP_ in order     */
58
 
/*   to avoid confusion with other API calls         */
59
 
/*   sent via DCE RPC                                */
60
 
/*                                                   */
61
 
/*****************************************************/
62
 
 
63
 
/*****************************************************/
64
 
/*                                                   */
65
 
/* cifsrap.c already includes support for:           */
66
 
/*                                                   */
67
 
/* WshareEnum ( API number 0, level 1)               */
68
 
/* NetServerEnum2 (API num 104, level 1)             */
69
 
/* WWkstaUserLogon (132)                             */
70
 
/* SamOEMchgPasswordUser2_P (214)                    */
71
 
/*                                                   */
72
 
/* cifsprint.c already includes support for:         */
73
 
/*                                                   */
74
 
/* WPrintJobEnum (API num 76, level 2)               */
75
 
/* WPrintJobDel  (API num 81)                        */
76
 
/*                                                   */
77
 
/*****************************************************/ 
78
 
 
79
 
#include "includes.h" 
80
 
 
81
 
#define WORDSIZE 2
82
 
#define DWORDSIZE 4
83
 
 
84
 
#define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
85
 
#define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
86
 
#define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
87
 
#define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
88
 
#define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
89
 
#define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
90
 
#define GETRES(p) p ? SVAL(p,0) : -1
91
 
/* put string s at p with max len n and increment p past string */
92
 
#define PUTSTRING(p,s,n) do {\
93
 
  push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
94
 
  p = skip_string(p,1);\
95
 
  } while(0)
96
 
/* put string s and p, using fixed len l, and increment p by l */
97
 
#define PUTSTRINGF(p,s,l) do {\
98
 
  push_ascii(p,s?s:"",l,STR_TERMINATE);\
99
 
  p += l;\
100
 
  } while (0)
101
 
/* put string pointer at p, supplying offset o from rdata r, store   */
102
 
/* dword offset at p, increment p by 4 and o by length of s.  This   */
103
 
/* means on the first call, you must calc the offset yourself!       */
104
 
#define PUTSTRINGP(p,s,r,o) do {\
105
 
  if (s) {\
106
 
    push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
107
 
    PUTDWORD(p,o);\
108
 
    o += strlen(s) + 1;\
109
 
  } else PUTDWORD(p,0);\
110
 
  }while(0);
111
 
/* get asciiz string s from p, increment p past string */
112
 
#define GETSTRING(p,s) do {\
113
 
  pull_ascii_pstring(s,p);\
114
 
  p = skip_string(p,1);\
115
 
  } while(0)
116
 
/* get fixed length l string s from p, increment p by l */
117
 
#define GETSTRINGF(p,s,l) do {\
118
 
  pull_ascii_pstring(s,p);\
119
 
  p += l;\
120
 
  } while(0)
121
 
/* get string s from offset (obtained at p) from rdata r - converter c */
122
 
#define GETSTRINGP(p,s,r,c) do {\
123
 
  uint32 off;\
124
 
  GETDWORD(p,off);\
125
 
  off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
126
 
  pull_ascii_pstring(s, off?(r+off-c):"");\
127
 
  } while(0)
128
 
 
129
 
static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
130
 
{
131
 
  PUTWORD(param,apinum);
132
 
  if (reqfmt) 
133
 
    PUTSTRING(param,reqfmt,0);
134
 
  else 
135
 
    *param++ = (char) 0;
136
 
 
137
 
  if (datafmt)
138
 
    PUTSTRING(param,datafmt,0);
139
 
  else
140
 
    *param++ = (char) 0;
141
 
 
142
 
  return param;
143
 
}
144
 
    
145
 
 
146
 
/****************************************************************************
147
 
 call a NetGroupDelete - delete user group from remote server
148
 
****************************************************************************/
149
 
int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
150
 
{
151
 
  char *rparam = NULL;
152
 
  char *rdata = NULL;
153
 
  char *p;
154
 
  unsigned int rdrcnt,rprcnt;
155
 
  int res;
156
 
  char param[WORDSIZE                    /* api number    */
157
 
            +sizeof(RAP_NetGroupDel_REQ) /* parm string   */
158
 
            +1                           /* no ret string */
159
 
            +RAP_GROUPNAME_LEN           /* group to del  */
160
 
            +WORDSIZE];                  /* reserved word */
161
 
 
162
 
  /* now send a SMBtrans command with api GroupDel */
163
 
  p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);  
164
 
  PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
165
 
  PUTWORD(p,0);  /* reserved word MBZ on input */
166
 
                 
167
 
  if (cli_api(cli, 
168
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
169
 
              NULL, 0, 200,       /* data, length, maxlen */
170
 
              &rparam, &rprcnt,   /* return params, length */
171
 
              &rdata, &rdrcnt))   /* return data, length */
172
 
    {
173
 
      res = GETRES(rparam);
174
 
                        
175
 
      if (res == 0) {
176
 
        /* nothing to do */             
177
 
      }
178
 
      else if ((res == 5) || (res == 65)) {
179
 
          DEBUG(1, ("Access Denied\n"));
180
 
      }
181
 
      else if (res == 2220) {
182
 
         DEBUG (1, ("Group does not exist\n"));
183
 
      }
184
 
      else {
185
 
        DEBUG(4,("NetGroupDelete res=%d\n", res));
186
 
      }      
187
 
    } else {
188
 
      res = -1;
189
 
      DEBUG(4,("NetGroupDelete failed\n"));
190
 
    }
191
 
  
192
 
  SAFE_FREE(rparam);
193
 
  SAFE_FREE(rdata);
194
 
  
195
 
  return res;
196
 
}
197
 
 
198
 
/****************************************************************************
199
 
 call a NetGroupAdd - add user group to remote server
200
 
****************************************************************************/
201
 
int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
202
 
{
203
 
  char *rparam = NULL;
204
 
  char *rdata = NULL;
205
 
  char *p;
206
 
  unsigned int rdrcnt,rprcnt;
207
 
  int res;
208
 
  char param[WORDSIZE                    /* api number    */
209
 
            +sizeof(RAP_NetGroupAdd_REQ) /* req string    */
210
 
            +sizeof(RAP_GROUP_INFO_L1)   /* return string */
211
 
            +WORDSIZE                    /* info level    */
212
 
            +WORDSIZE];                  /* reserved word */
213
 
 
214
 
  /* offset into data of free format strings.  Will be updated */
215
 
  /* by PUTSTRINGP macro and end up with total data length.    */
216
 
  int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE; 
217
 
  char *data;
218
 
  size_t data_size;
219
 
 
220
 
  /* Allocate data. */
221
 
  data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
222
 
 
223
 
  data = SMB_MALLOC_ARRAY(char, data_size);
224
 
  if (!data) {
225
 
    DEBUG (1, ("Malloc fail\n"));
226
 
    return -1;
227
 
  }
228
 
 
229
 
  /* now send a SMBtrans command with api WGroupAdd */
230
 
  
231
 
  p = make_header(param, RAP_WGroupAdd,
232
 
                  RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1); 
233
 
  PUTWORD(p, 1); /* info level */
234
 
  PUTWORD(p, 0); /* reserved word 0 */
235
 
  
236
 
  p = data;
237
 
  PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
238
 
  PUTBYTE(p, 0); /* pad byte 0 */
239
 
  PUTSTRINGP(p, grinfo->comment, data, soffset);
240
 
  
241
 
  if (cli_api(cli, 
242
 
              param, sizeof(param), 1024, /* Param, length, maxlen */
243
 
              data, soffset, sizeof(data), /* data, length, maxlen */
244
 
              &rparam, &rprcnt,   /* return params, length */
245
 
              &rdata, &rdrcnt))   /* return data, length */
246
 
    {
247
 
      res = GETRES(rparam);
248
 
      
249
 
      if (res == 0) {
250
 
        /* nothing to do */             
251
 
      } else if ((res == 5) || (res == 65)) {
252
 
        DEBUG(1, ("Access Denied\n"));
253
 
      }
254
 
      else if (res == 2223) {
255
 
        DEBUG (1, ("Group already exists\n"));
256
 
      }
257
 
      else {
258
 
        DEBUG(4,("NetGroupAdd res=%d\n", res));
259
 
      }
260
 
    } else {
261
 
      res = -1;
262
 
      DEBUG(4,("NetGroupAdd failed\n"));
263
 
    }
264
 
  
265
 
  SAFE_FREE(data);
266
 
  SAFE_FREE(rparam);
267
 
  SAFE_FREE(rdata);
268
 
 
269
 
  return res;
270
 
}
271
 
 
272
 
/****************************************************************************
273
 
call a NetGroupEnum - try and list user groups on a different host
274
 
****************************************************************************/
275
 
int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
276
 
{
277
 
  char param[WORDSIZE                     /* api number    */
278
 
            +sizeof(RAP_NetGroupEnum_REQ) /* parm string   */
279
 
            +sizeof(RAP_GROUP_INFO_L1)    /* return string */
280
 
            +WORDSIZE                     /* info level    */
281
 
            +WORDSIZE];                   /* buffer size   */
282
 
  char *p;
283
 
  char *rparam = NULL;
284
 
  char *rdata = NULL; 
285
 
  unsigned int rprcnt, rdrcnt;
286
 
  int res = -1;
287
 
  
288
 
  
289
 
  memset(param, '\0', sizeof(param));
290
 
  p = make_header(param, RAP_WGroupEnum,
291
 
                  RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
292
 
  PUTWORD(p,1); /* Info level 1 */  /* add level 0 */
293
 
  PUTWORD(p,0xFFE0); /* Return buffer size */
294
 
 
295
 
  if (cli_api(cli,
296
 
              param, PTR_DIFF(p,param),8,
297
 
              NULL, 0, 0xFFE0 /* data area size */,
298
 
              &rparam, &rprcnt,
299
 
              &rdata, &rdrcnt)) {
300
 
    res = GETRES(rparam);
301
 
    cli->rap_error = res;
302
 
    if(cli->rap_error == 234) 
303
 
        DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
304
 
    else if (cli->rap_error != 0) {
305
 
      DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
306
 
    }
307
 
  }
308
 
 
309
 
  if (rdata) {
310
 
    if (res == 0 || res == ERRmoredata) {
311
 
      int i, converter, count;
312
 
 
313
 
      p = rparam + WORDSIZE; /* skip result */
314
 
      GETWORD(p, converter);
315
 
      GETWORD(p, count);
316
 
 
317
 
      for (i=0,p=rdata;i<count;i++) {
318
 
            pstring comment;
319
 
            char groupname[RAP_GROUPNAME_LEN];
320
 
 
321
 
            GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
322
 
            p++; /* pad byte */
323
 
            GETSTRINGP(p, comment, rdata, converter);
324
 
 
325
 
            fn(groupname, comment, cli);
326
 
      } 
327
 
    } else {
328
 
      DEBUG(4,("NetGroupEnum res=%d\n", res));
329
 
    }
330
 
  } else {
331
 
    DEBUG(4,("NetGroupEnum no data returned\n"));
332
 
  }
333
 
    
334
 
  SAFE_FREE(rparam);
335
 
  SAFE_FREE(rdata);
336
 
 
337
 
  return res;
338
 
}
339
 
 
340
 
int cli_RNetGroupEnum0(struct cli_state *cli,
341
 
                       void (*fn)(const char *, void *),
342
 
                       void *state)
343
 
{
344
 
  char param[WORDSIZE                     /* api number    */
345
 
            +sizeof(RAP_NetGroupEnum_REQ) /* parm string   */
346
 
            +sizeof(RAP_GROUP_INFO_L0)    /* return string */
347
 
            +WORDSIZE                     /* info level    */
348
 
            +WORDSIZE];                   /* buffer size   */
349
 
  char *p;
350
 
  char *rparam = NULL;
351
 
  char *rdata = NULL; 
352
 
  unsigned int rprcnt, rdrcnt;
353
 
  int res = -1;
354
 
  
355
 
  
356
 
  memset(param, '\0', sizeof(param));
357
 
  p = make_header(param, RAP_WGroupEnum,
358
 
                  RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
359
 
  PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
360
 
                                      is the resume count, at least
361
 
                                      that's what smbd believes... */
362
 
  PUTWORD(p,0xFFE0); /* Return buffer size */
363
 
 
364
 
  if (cli_api(cli,
365
 
              param, PTR_DIFF(p,param),8,
366
 
              NULL, 0, 0xFFE0 /* data area size */,
367
 
              &rparam, &rprcnt,
368
 
              &rdata, &rdrcnt)) {
369
 
    res = GETRES(rparam);
370
 
    cli->rap_error = res;
371
 
    if(cli->rap_error == 234) 
372
 
        DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
373
 
    else if (cli->rap_error != 0) {
374
 
      DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
375
 
    }
376
 
  }
377
 
 
378
 
  if (rdata) {
379
 
    if (res == 0 || res == ERRmoredata) {
380
 
      int i, count;
381
 
 
382
 
      p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
383
 
      GETWORD(p, count);
384
 
 
385
 
      for (i=0,p=rdata;i<count;i++) {
386
 
            char groupname[RAP_GROUPNAME_LEN];
387
 
            GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
388
 
            fn(groupname, cli);
389
 
      } 
390
 
    } else {
391
 
      DEBUG(4,("NetGroupEnum res=%d\n", res));
392
 
    }
393
 
  } else {
394
 
    DEBUG(4,("NetGroupEnum no data returned\n"));
395
 
  }
396
 
    
397
 
  SAFE_FREE(rparam);
398
 
  SAFE_FREE(rdata);
399
 
 
400
 
  return res;
401
 
}
402
 
 
403
 
int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
404
 
{
405
 
  char *rparam = NULL;
406
 
  char *rdata = NULL;
407
 
  char *p;
408
 
  unsigned int rdrcnt,rprcnt;
409
 
  int res;
410
 
  char param[WORDSIZE                        /* api number    */
411
 
            +sizeof(RAP_NetGroupDelUser_REQ) /* parm string   */
412
 
            +1                               /* no ret string */
413
 
            +RAP_GROUPNAME_LEN               /* group name    */
414
 
            +RAP_USERNAME_LEN];              /* user to del   */
415
 
 
416
 
  /* now send a SMBtrans command with api GroupMemberAdd */
417
 
  p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
418
 
  PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
419
 
  PUTSTRING(p,user_name,RAP_USERNAME_LEN);
420
 
 
421
 
  if (cli_api(cli, 
422
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
423
 
              NULL, 0, 200,       /* data, length, maxlen */
424
 
              &rparam, &rprcnt,   /* return params, length */
425
 
              &rdata, &rdrcnt))   /* return data, length */
426
 
    {
427
 
      res = GETRES(rparam);
428
 
      
429
 
      switch(res) {
430
 
        case 0:
431
 
          break;
432
 
        case 5:
433
 
        case 65:
434
 
          DEBUG(1, ("Access Denied\n"));
435
 
          break;
436
 
        case 50:
437
 
          DEBUG(1, ("Not supported by server\n"));
438
 
          break;
439
 
        case 2220:
440
 
          DEBUG(1, ("Group does not exist\n"));
441
 
          break;
442
 
        case 2221:
443
 
          DEBUG(1, ("User does not exist\n"));
444
 
          break;
445
 
        case 2237:
446
 
          DEBUG(1, ("User is not in group\n"));
447
 
          break;
448
 
        default:
449
 
          DEBUG(4,("NetGroupDelUser res=%d\n", res));
450
 
      }
451
 
    } else {
452
 
      res = -1;
453
 
      DEBUG(4,("NetGroupDelUser failed\n"));
454
 
    }
455
 
  
456
 
  SAFE_FREE(rparam);
457
 
  SAFE_FREE(rdata);
458
 
        
459
 
  return res; 
460
 
}
461
 
 
462
 
int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
463
 
{
464
 
  char *rparam = NULL;
465
 
  char *rdata = NULL;
466
 
  char *p;
467
 
  unsigned int rdrcnt,rprcnt;
468
 
  int res;
469
 
  char param[WORDSIZE                        /* api number    */
470
 
            +sizeof(RAP_NetGroupAddUser_REQ) /* parm string   */
471
 
            +1                               /* no ret string */
472
 
            +RAP_GROUPNAME_LEN               /* group name    */
473
 
            +RAP_USERNAME_LEN];              /* user to add   */
474
 
 
475
 
  /* now send a SMBtrans command with api GroupMemberAdd */
476
 
  p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
477
 
  PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
478
 
  PUTSTRING(p,user_name,RAP_USERNAME_LEN);
479
 
 
480
 
  if (cli_api(cli, 
481
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
482
 
              NULL, 0, 200,       /* data, length, maxlen */
483
 
              &rparam, &rprcnt,   /* return params, length */
484
 
              &rdata, &rdrcnt))   /* return data, length */
485
 
    {
486
 
      res = GETRES(rparam);
487
 
      
488
 
      switch(res) {
489
 
        case 0:
490
 
          break;
491
 
        case 5:
492
 
        case 65:
493
 
          DEBUG(1, ("Access Denied\n"));
494
 
          break;
495
 
        case 50:
496
 
          DEBUG(1, ("Not supported by server\n"));
497
 
          break;
498
 
        case 2220:
499
 
          DEBUG(1, ("Group does not exist\n"));
500
 
          break;
501
 
        case 2221:
502
 
          DEBUG(1, ("User does not exist\n"));
503
 
          break;
504
 
        default:
505
 
          DEBUG(4,("NetGroupAddUser res=%d\n", res));
506
 
      }
507
 
    } else {
508
 
      res = -1;
509
 
      DEBUG(4,("NetGroupAddUser failed\n"));
510
 
    }
511
 
  
512
 
  SAFE_FREE(rparam);
513
 
  SAFE_FREE(rdata);
514
 
        
515
 
  return res;
516
 
}
517
 
 
518
 
 
519
 
int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
520
 
{
521
 
  char *rparam = NULL;
522
 
  char *rdata = NULL;
523
 
  char *p;
524
 
  unsigned int rdrcnt,rprcnt;
525
 
  int res = -1;
526
 
  char param[WORDSIZE                        /* api number    */
527
 
            +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string   */
528
 
            +sizeof(RAP_GROUP_USERS_INFO_0)  /* return string */
529
 
            +RAP_GROUPNAME_LEN               /* group name    */
530
 
            +WORDSIZE                        /* info level    */
531
 
            +WORDSIZE];                      /* buffer size   */
532
 
 
533
 
  /* now send a SMBtrans command with api GroupGetUsers */
534
 
  p = make_header(param, RAP_WGroupGetUsers,
535
 
                  RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
536
 
  PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
537
 
  PUTWORD(p,0); /* info level 0 */
538
 
  PUTWORD(p,0xFFE0); /* return buffer size */
539
 
 
540
 
  if (cli_api(cli,
541
 
              param, PTR_DIFF(p,param),PTR_DIFF(p,param),
542
 
              NULL, 0, CLI_BUFFER_SIZE,
543
 
              &rparam, &rprcnt,
544
 
              &rdata, &rdrcnt)) {
545
 
    res = GETRES(rparam);
546
 
    cli->rap_error = res;
547
 
    if (res != 0) {
548
 
      DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
549
 
    }
550
 
  }
551
 
  if (rdata) {
552
 
    if (res == 0 || res == ERRmoredata) {
553
 
      int i, count;
554
 
      fstring username;
555
 
      p = rparam + WORDSIZE + WORDSIZE;
556
 
      GETWORD(p, count);
557
 
 
558
 
      for (i=0,p=rdata; i<count; i++) {
559
 
        GETSTRINGF(p, username, RAP_USERNAME_LEN);
560
 
        fn(username, state);
561
 
      }
562
 
    } else {
563
 
      DEBUG(4,("NetGroupGetUsers res=%d\n", res));
564
 
    }
565
 
  } else {
566
 
    DEBUG(4,("NetGroupGetUsers no data returned\n"));
567
 
  }
568
 
  SAFE_FREE(rdata);
569
 
  SAFE_FREE(rparam);
570
 
  return res;
571
 
}
572
 
 
573
 
int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
574
 
{
575
 
  char *rparam = NULL;
576
 
  char *rdata = NULL;
577
 
  char *p;
578
 
  unsigned int rdrcnt,rprcnt;
579
 
  int res = -1;
580
 
  char param[WORDSIZE                        /* api number    */
581
 
            +sizeof(RAP_NetUserGetGroups_REQ)/* parm string   */
582
 
            +sizeof(RAP_GROUP_USERS_INFO_0)  /* return string */
583
 
            +RAP_USERNAME_LEN               /* user name    */
584
 
            +WORDSIZE                        /* info level    */
585
 
            +WORDSIZE];                      /* buffer size   */
586
 
 
587
 
  /* now send a SMBtrans command with api GroupGetUsers */
588
 
  p = make_header(param, RAP_WUserGetGroups,
589
 
                  RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
590
 
  PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
591
 
  PUTWORD(p,0); /* info level 0 */
592
 
  PUTWORD(p,0xFFE0); /* return buffer size */
593
 
 
594
 
  if (cli_api(cli,
595
 
              param, PTR_DIFF(p,param),PTR_DIFF(p,param),
596
 
              NULL, 0, CLI_BUFFER_SIZE,
597
 
              &rparam, &rprcnt,
598
 
              &rdata, &rdrcnt)) {
599
 
    res = GETRES(rparam);
600
 
    cli->rap_error = res;
601
 
    if (res != 0) {
602
 
      DEBUG(1,("NetUserGetGroups gave error %d\n", res));
603
 
    }
604
 
  }
605
 
  if (rdata) {
606
 
    if (res == 0 || res == ERRmoredata) {
607
 
      int i, count;
608
 
      fstring groupname;
609
 
      p = rparam + WORDSIZE + WORDSIZE;
610
 
      GETWORD(p, count);
611
 
 
612
 
      for (i=0,p=rdata; i<count; i++) {
613
 
        GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
614
 
            fn(groupname, state);
615
 
      }
616
 
    } else {
617
 
      DEBUG(4,("NetUserGetGroups res=%d\n", res));
618
 
    }
619
 
  } else {
620
 
    DEBUG(4,("NetUserGetGroups no data returned\n"));
621
 
  }
622
 
  SAFE_FREE(rdata);
623
 
  SAFE_FREE(rparam);
624
 
  return res;
625
 
}
626
 
 
627
 
 
628
 
/****************************************************************************
629
 
 call a NetUserDelete - delete user from remote server
630
 
****************************************************************************/
631
 
int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
632
 
{
633
 
  char *rparam = NULL;
634
 
  char *rdata = NULL;
635
 
  char *p;
636
 
  unsigned int rdrcnt,rprcnt;
637
 
  int res;
638
 
  char param[WORDSIZE                    /* api number    */
639
 
            +sizeof(RAP_NetGroupDel_REQ) /* parm string   */
640
 
            +1                           /* no ret string */
641
 
            +RAP_USERNAME_LEN            /* user to del   */
642
 
            +WORDSIZE];                  /* reserved word */
643
 
 
644
 
  /* now send a SMBtrans command with api UserDel */
645
 
  p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);  
646
 
  PUTSTRING(p, user_name, RAP_USERNAME_LEN);
647
 
  PUTWORD(p,0);  /* reserved word MBZ on input */
648
 
                 
649
 
  if (cli_api(cli, 
650
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
651
 
              NULL, 0, 200,       /* data, length, maxlen */
652
 
              &rparam, &rprcnt,   /* return params, length */
653
 
              &rdata, &rdrcnt))   /* return data, length */
654
 
    {
655
 
      res = GETRES(rparam);
656
 
      
657
 
      if (res == 0) {
658
 
        /* nothing to do */             
659
 
      }
660
 
      else if ((res == 5) || (res == 65)) {
661
 
         DEBUG(1, ("Access Denied\n"));
662
 
      }
663
 
      else if (res == 2221) {
664
 
         DEBUG (1, ("User does not exist\n"));
665
 
      }
666
 
      else {
667
 
          DEBUG(4,("NetUserDelete res=%d\n", res));
668
 
      }      
669
 
    } else {
670
 
      res = -1;
671
 
      DEBUG(4,("NetUserDelete failed\n"));
672
 
    }
673
 
  
674
 
  SAFE_FREE(rparam);
675
 
  SAFE_FREE(rdata);
676
 
        
677
 
  return res;
678
 
}
679
 
 
680
 
/****************************************************************************
681
 
 call a NetUserAdd - add user to remote server
682
 
****************************************************************************/
683
 
int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
684
 
{
685
 
   
686
 
 
687
 
 
688
 
  char *rparam = NULL;
689
 
  char *rdata = NULL;
690
 
  char *p;                                          
691
 
  unsigned int rdrcnt,rprcnt;
692
 
  int res;
693
 
  char param[WORDSIZE                    /* api number    */
694
 
            +sizeof(RAP_NetUserAdd2_REQ) /* req string    */
695
 
            +sizeof(RAP_USER_INFO_L1)    /* data string   */
696
 
            +WORDSIZE                    /* info level    */
697
 
            +WORDSIZE                    /* buffer length */
698
 
            +WORDSIZE];                  /* reserved      */
699
 
 
700
 
  char data[1024];
701
 
  /* offset into data of free format strings.  Will be updated */
702
 
  /* by PUTSTRINGP macro and end up with total data length.    */
703
 
  int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
704
 
    + RAP_UPASSWD_LEN            /* password        */
705
 
    + DWORDSIZE                  /* password age    */
706
 
    + WORDSIZE                   /* privilege       */
707
 
    + DWORDSIZE                  /* home dir ptr    */
708
 
    + DWORDSIZE                  /* comment ptr     */
709
 
    + WORDSIZE                   /* flags           */
710
 
    + DWORDSIZE;                 /* login script ptr*/
711
 
 
712
 
  /* now send a SMBtrans command with api NetUserAdd */
713
 
  p = make_header(param, RAP_WUserAdd2,
714
 
                  RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
715
 
  PUTWORD(p, 1); /* info level */
716
 
 
717
 
  PUTWORD(p, 0); /* pwencrypt */
718
 
  if(userinfo->passwrd)
719
 
    PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
720
 
  else
721
 
    PUTWORD(p, 0); /* password length */
722
 
 
723
 
  p = data;
724
 
  memset(data, '\0', soffset);
725
 
 
726
 
  PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
727
 
  PUTBYTE(p, 0); /* pad byte 0 */
728
 
  PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
729
 
  PUTDWORD(p, 0); /* pw age - n.a. on user add */
730
 
  PUTWORD(p, userinfo->priv);
731
 
  PUTSTRINGP(p, userinfo->home_dir, data, soffset);
732
 
  PUTSTRINGP(p, userinfo->comment, data, soffset);
733
 
  PUTWORD(p, userinfo->userflags);
734
 
  PUTSTRINGP(p, userinfo->logon_script, data, soffset);
735
 
 
736
 
  if (cli_api(cli, 
737
 
              param, sizeof(param), 1024, /* Param, length, maxlen */
738
 
              data, soffset, sizeof(data), /* data, length, maxlen */
739
 
              &rparam, &rprcnt,   /* return params, length */
740
 
              &rdata, &rdrcnt))   /* return data, length */
741
 
    {
742
 
      res = GETRES(rparam);
743
 
      
744
 
      if (res == 0) {
745
 
        /* nothing to do */             
746
 
      }       
747
 
      else if ((res == 5) || (res == 65)) {
748
 
        DEBUG(1, ("Access Denied\n"));
749
 
      }
750
 
      else if (res == 2224) {
751
 
        DEBUG (1, ("User already exists\n"));
752
 
      }
753
 
      else {
754
 
            DEBUG(4,("NetUserAdd res=%d\n", res));
755
 
      }
756
 
    } else {
757
 
      res = -1;
758
 
      DEBUG(4,("NetUserAdd failed\n"));
759
 
    }
760
 
  
761
 
  SAFE_FREE(rparam);
762
 
  SAFE_FREE(rdata);
763
 
 
764
 
  return res;
765
 
}
766
 
 
767
 
/****************************************************************************
768
 
call a NetUserEnum - try and list users on a different host
769
 
****************************************************************************/
770
 
int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
771
 
{
772
 
  char param[WORDSIZE                 /* api number    */
773
 
            +sizeof(RAP_NetUserEnum_REQ) /* parm string   */
774
 
            +sizeof(RAP_USER_INFO_L1)    /* return string */
775
 
            +WORDSIZE                 /* info level    */
776
 
            +WORDSIZE];               /* buffer size   */
777
 
  char *p;
778
 
  char *rparam = NULL;
779
 
  char *rdata = NULL; 
780
 
  unsigned int rprcnt, rdrcnt;
781
 
  int res = -1;
782
 
  
783
 
 
784
 
  memset(param, '\0', sizeof(param));
785
 
  p = make_header(param, RAP_WUserEnum,
786
 
                  RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
787
 
  PUTWORD(p,1); /* Info level 1 */
788
 
  PUTWORD(p,0xFF00); /* Return buffer size */
789
 
 
790
 
/* BB Fix handling of large numbers of users to be returned */
791
 
  if (cli_api(cli,
792
 
              param, PTR_DIFF(p,param),8,
793
 
              NULL, 0, CLI_BUFFER_SIZE,
794
 
              &rparam, &rprcnt,
795
 
              &rdata, &rdrcnt)) {
796
 
    res = GETRES(rparam);
797
 
    cli->rap_error = res;
798
 
    if (cli->rap_error != 0) {
799
 
      DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
800
 
    }
801
 
  }
802
 
  if (rdata) {
803
 
    if (res == 0 || res == ERRmoredata) {
804
 
      int i, converter, count;
805
 
      char username[RAP_USERNAME_LEN];
806
 
      char userpw[RAP_UPASSWD_LEN];
807
 
      pstring comment, homedir, logonscript;
808
 
 
809
 
      p = rparam + WORDSIZE; /* skip result */
810
 
      GETWORD(p, converter);
811
 
      GETWORD(p, count);
812
 
 
813
 
      for (i=0,p=rdata;i<count;i++) {
814
 
        GETSTRINGF(p, username, RAP_USERNAME_LEN);
815
 
        p++; /* pad byte */
816
 
        GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
817
 
        p += DWORDSIZE; /* skip password age */
818
 
        p += WORDSIZE;  /* skip priv: 0=guest, 1=user, 2=admin */
819
 
        GETSTRINGP(p, homedir, rdata, converter);
820
 
        GETSTRINGP(p, comment, rdata, converter);
821
 
        p += WORDSIZE;  /* skip flags */
822
 
        GETSTRINGP(p, logonscript, rdata, converter);
823
 
 
824
 
        fn(username, comment, homedir, logonscript, cli);
825
 
      }
826
 
    } else {
827
 
      DEBUG(4,("NetUserEnum res=%d\n", res));
828
 
    }
829
 
  } else {
830
 
    DEBUG(4,("NetUserEnum no data returned\n"));
831
 
  }
832
 
    
833
 
  SAFE_FREE(rparam);
834
 
  SAFE_FREE(rdata);
835
 
 
836
 
  return res;
837
 
}
838
 
 
839
 
int cli_RNetUserEnum0(struct cli_state *cli,
840
 
                      void (*fn)(const char *, void *),
841
 
                      void *state)
842
 
{
843
 
  char param[WORDSIZE                 /* api number    */
844
 
            +sizeof(RAP_NetUserEnum_REQ) /* parm string   */
845
 
            +sizeof(RAP_USER_INFO_L0)    /* return string */
846
 
            +WORDSIZE                 /* info level    */
847
 
            +WORDSIZE];               /* buffer size   */
848
 
  char *p;
849
 
  char *rparam = NULL;
850
 
  char *rdata = NULL; 
851
 
  unsigned int rprcnt, rdrcnt;
852
 
  int res = -1;
853
 
  
854
 
 
855
 
  memset(param, '\0', sizeof(param));
856
 
  p = make_header(param, RAP_WUserEnum,
857
 
                  RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
858
 
  PUTWORD(p,0); /* Info level 1 */
859
 
  PUTWORD(p,0xFF00); /* Return buffer size */
860
 
 
861
 
/* BB Fix handling of large numbers of users to be returned */
862
 
  if (cli_api(cli,
863
 
              param, PTR_DIFF(p,param),8,
864
 
              NULL, 0, CLI_BUFFER_SIZE,
865
 
              &rparam, &rprcnt,
866
 
              &rdata, &rdrcnt)) {
867
 
    res = GETRES(rparam);
868
 
    cli->rap_error = res;
869
 
    if (cli->rap_error != 0) {
870
 
      DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
871
 
    }
872
 
  }
873
 
  if (rdata) {
874
 
    if (res == 0 || res == ERRmoredata) {
875
 
      int i, count;
876
 
      char username[RAP_USERNAME_LEN];
877
 
 
878
 
      p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
879
 
      GETWORD(p, count);
880
 
 
881
 
      for (i=0,p=rdata;i<count;i++) {
882
 
        GETSTRINGF(p, username, RAP_USERNAME_LEN);
883
 
        fn(username, cli);
884
 
      }
885
 
    } else {
886
 
      DEBUG(4,("NetUserEnum res=%d\n", res));
887
 
    }
888
 
  } else {
889
 
    DEBUG(4,("NetUserEnum no data returned\n"));
890
 
  }
891
 
    
892
 
  SAFE_FREE(rparam);
893
 
  SAFE_FREE(rdata);
894
 
 
895
 
  return res;
896
 
}
897
 
 
898
 
/****************************************************************************
899
 
 call a NetFileClose2 - close open file on another session to server
900
 
****************************************************************************/
901
 
int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
902
 
{
903
 
  char *rparam = NULL;
904
 
  char *rdata = NULL;
905
 
  char *p;
906
 
  unsigned int rdrcnt,rprcnt;
907
 
  char param[WORDSIZE                    /* api number    */
908
 
            +sizeof(RAP_WFileClose2_REQ) /* req string    */
909
 
            +1                           /* no ret string */
910
 
            +DWORDSIZE];                 /* file ID          */
911
 
  int res = -1;
912
 
 
913
 
  /* now send a SMBtrans command with api RNetShareEnum */
914
 
  p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
915
 
  PUTDWORD(p, file_id);  
916
 
                 
917
 
  if (cli_api(cli, 
918
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
919
 
              NULL, 0, 200,       /* data, length, maxlen */
920
 
              &rparam, &rprcnt,   /* return params, length */
921
 
              &rdata, &rdrcnt))   /* return data, length */
922
 
    {
923
 
      res = GETRES(rparam);
924
 
      
925
 
      if (res == 0) {
926
 
        /* nothing to do */             
927
 
      } else if (res == 2314){
928
 
         DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
929
 
      } else {
930
 
        DEBUG(4,("NetFileClose2 res=%d\n", res));
931
 
      }      
932
 
    } else {
933
 
      res = -1;
934
 
      DEBUG(4,("NetFileClose2 failed\n"));
935
 
    }
936
 
  
937
 
  SAFE_FREE(rparam);
938
 
  SAFE_FREE(rdata);
939
 
  
940
 
  return res;
941
 
}
942
 
 
943
 
/****************************************************************************
944
 
call a NetFileGetInfo - get information about server file opened from other
945
 
     workstation
946
 
****************************************************************************/
947
 
int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
948
 
{
949
 
  char *rparam = NULL;
950
 
  char *rdata = NULL;
951
 
  char *p;
952
 
  unsigned int rdrcnt,rprcnt;
953
 
  int res;
954
 
  char param[WORDSIZE                      /* api number      */
955
 
            +sizeof(RAP_WFileGetInfo2_REQ) /* req string      */
956
 
            +sizeof(RAP_FILE_INFO_L3)      /* return string   */
957
 
            +DWORDSIZE                     /* file ID          */
958
 
            +WORDSIZE                      /* info level      */
959
 
            +WORDSIZE];                    /* buffer size     */
960
 
 
961
 
  /* now send a SMBtrans command with api RNetShareEnum */
962
 
  p = make_header(param, RAP_WFileGetInfo2,
963
 
                  RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3); 
964
 
  PUTDWORD(p, file_id);
965
 
  PUTWORD(p, 3);  /* info level */
966
 
  PUTWORD(p, 0x1000);   /* buffer size */ 
967
 
  if (cli_api(cli, 
968
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
969
 
              NULL, 0, 0x1000,  /* data, length, maxlen */
970
 
              &rparam, &rprcnt,               /* return params, length */
971
 
              &rdata, &rdrcnt))               /* return data, length */
972
 
    {
973
 
      res = GETRES(rparam);
974
 
      if (res == 0 || res == ERRmoredata) {
975
 
        int converter,id, perms, locks;
976
 
        pstring fpath, fuser;
977
 
          
978
 
        p = rparam + WORDSIZE; /* skip result */
979
 
        GETWORD(p, converter);
980
 
 
981
 
        p = rdata;
982
 
        GETDWORD(p, id);
983
 
        GETWORD(p, perms);
984
 
        GETWORD(p, locks);
985
 
        GETSTRINGP(p, fpath, rdata, converter);
986
 
        GETSTRINGP(p, fuser, rdata, converter);
987
 
        
988
 
        fn(fpath, fuser, perms, locks, id);
989
 
      } else {
990
 
        DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
991
 
      }      
992
 
    } else {
993
 
      res = -1;
994
 
      DEBUG(4,("NetFileGetInfo2 failed\n"));
995
 
    }
996
 
  
997
 
  SAFE_FREE(rparam);
998
 
  SAFE_FREE(rdata);
999
 
  
1000
 
  return res;
1001
 
}
1002
 
 
1003
 
/****************************************************************************
1004
 
* Call a NetFileEnum2 - list open files on an SMB server
1005
 
1006
 
* PURPOSE:  Remotes a NetFileEnum API call to the current server or target 
1007
 
*           server listing the files open via the network (and their
1008
 
*           corresponding open instance ids)
1009
 
*          
1010
 
* Dependencies: none
1011
 
*
1012
 
* Parameters: 
1013
 
*             cli    - pointer to cli_state structure
1014
 
*             user   - if present, return only files opened by this remote user
1015
 
*             base_path - if present, return only files opened below this 
1016
 
*                         base path
1017
 
*             fn     - display function to invoke for each entry in the result
1018
 
*                        
1019
 
*
1020
 
* Returns:
1021
 
*             True      - success
1022
 
*             False     - failure
1023
 
*
1024
 
****************************************************************************/
1025
 
int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1026
 
{
1027
 
  char *rparam = NULL;
1028
 
  char *rdata = NULL;
1029
 
  char *p;
1030
 
  unsigned int rdrcnt,rprcnt;
1031
 
  char param[WORDSIZE                   /* api number      */
1032
 
            +sizeof(RAP_WFileEnum2_REQ) /* req string      */
1033
 
            +sizeof(RAP_FILE_INFO_L3)   /* return string   */
1034
 
            +256                        /* base path (opt) */
1035
 
            +RAP_USERNAME_LEN           /* user name (opt) */
1036
 
            +WORDSIZE                   /* info level      */
1037
 
            +WORDSIZE                   /* buffer size     */
1038
 
            +DWORDSIZE                  /* resume key ?    */
1039
 
            +DWORDSIZE];                /* resume key ?    */
1040
 
  int count = -1;
1041
 
 
1042
 
  /* now send a SMBtrans command with api RNetShareEnum */
1043
 
  p = make_header(param, RAP_WFileEnum2,
1044
 
                  RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3); 
1045
 
 
1046
 
  PUTSTRING(p, base_path, 256);
1047
 
  PUTSTRING(p, user, RAP_USERNAME_LEN);
1048
 
  PUTWORD(p, 3); /* info level */
1049
 
  PUTWORD(p, 0xFF00);  /* buffer size */ 
1050
 
  PUTDWORD(p, 0);  /* zero out the resume key */
1051
 
  PUTDWORD(p, 0);  /* or is this one the resume key? */
1052
 
                 
1053
 
  if (cli_api(cli, 
1054
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1055
 
              NULL, 0, 0xFF00,  /* data, length, maxlen */
1056
 
              &rparam, &rprcnt,               /* return params, length */
1057
 
              &rdata, &rdrcnt))               /* return data, length */
1058
 
    {
1059
 
      int res = GETRES(rparam);
1060
 
      
1061
 
      if (res == 0 || res == ERRmoredata) {
1062
 
        int converter, i;
1063
 
 
1064
 
        p = rparam + WORDSIZE; /* skip result */
1065
 
        GETWORD(p, converter);
1066
 
        GETWORD(p, count);
1067
 
        
1068
 
        p = rdata;
1069
 
        for (i=0; i<count; i++) {
1070
 
          int id, perms, locks;
1071
 
          pstring fpath, fuser;
1072
 
          
1073
 
          GETDWORD(p, id);
1074
 
          GETWORD(p, perms);
1075
 
          GETWORD(p, locks);
1076
 
          GETSTRINGP(p, fpath, rdata, converter);
1077
 
          GETSTRINGP(p, fuser, rdata, converter);
1078
 
 
1079
 
          fn(fpath, fuser, perms, locks, id);
1080
 
        }  /* BB fix ERRmoredata case to send resume request */
1081
 
      } else {
1082
 
        DEBUG(4,("NetFileEnum2 res=%d\n", res));
1083
 
      }      
1084
 
    } else {
1085
 
      DEBUG(4,("NetFileEnum2 failed\n"));
1086
 
    }
1087
 
  
1088
 
  SAFE_FREE(rparam);
1089
 
  SAFE_FREE(rdata);
1090
 
  
1091
 
  return count;
1092
 
}
1093
 
 
1094
 
/****************************************************************************
1095
 
 call a NetShareAdd - share/export directory on remote server
1096
 
****************************************************************************/
1097
 
int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1098
 
{
1099
 
  char *rparam = NULL;
1100
 
  char *rdata = NULL;
1101
 
  char *p;
1102
 
  unsigned int rdrcnt,rprcnt;
1103
 
  int res;
1104
 
  char param[WORDSIZE                  /* api number    */
1105
 
            +sizeof(RAP_WShareAdd_REQ) /* req string    */
1106
 
            +sizeof(RAP_SHARE_INFO_L2) /* return string */
1107
 
            +WORDSIZE                  /* info level    */
1108
 
            +WORDSIZE];                /* reserved word */
1109
 
  char data[1024];
1110
 
  /* offset to free format string section following fixed length data.  */
1111
 
  /* will be updated by PUTSTRINGP macro and will end up with total len */
1112
 
  int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad   */
1113
 
    + WORDSIZE                        /* share type    */
1114
 
    + DWORDSIZE                       /* comment pointer */
1115
 
    + WORDSIZE                        /* permissions */
1116
 
    + WORDSIZE                        /* max users */
1117
 
    + WORDSIZE                        /* active users */
1118
 
    + DWORDSIZE                       /* share path */
1119
 
    + RAP_SPASSWD_LEN + 1;            /* share password + pad */
1120
 
 
1121
 
  memset(param,'\0',sizeof(param));
1122
 
  /* now send a SMBtrans command with api RNetShareAdd */
1123
 
  p = make_header(param, RAP_WshareAdd,
1124
 
                  RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2); 
1125
 
  PUTWORD(p, 2); /* info level */
1126
 
  PUTWORD(p, 0); /* reserved word 0 */
1127
 
 
1128
 
  p = data;
1129
 
  PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1130
 
  PUTBYTE(p, 0); /* pad byte 0 */
1131
 
 
1132
 
  PUTWORD(p, sinfo->share_type);
1133
 
  PUTSTRINGP(p, sinfo->comment, data, soffset);
1134
 
  PUTWORD(p, sinfo->perms);
1135
 
  PUTWORD(p, sinfo->maximum_users);
1136
 
  PUTWORD(p, sinfo->active_users);
1137
 
  PUTSTRINGP(p, sinfo->path, data, soffset);
1138
 
  PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1139
 
  SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1140
 
  
1141
 
  if (cli_api(cli, 
1142
 
              param, sizeof(param), 1024, /* Param, length, maxlen */
1143
 
              data, soffset, sizeof(data), /* data, length, maxlen */
1144
 
              &rparam, &rprcnt,   /* return params, length */
1145
 
              &rdata, &rdrcnt))   /* return data, length */
1146
 
    {
1147
 
      res = rparam? SVAL(rparam,0) : -1;
1148
 
                        
1149
 
      if (res == 0) {
1150
 
        /* nothing to do */             
1151
 
      }
1152
 
      else {
1153
 
        DEBUG(4,("NetShareAdd res=%d\n", res));
1154
 
      }      
1155
 
    } else {
1156
 
      res = -1;
1157
 
      DEBUG(4,("NetShareAdd failed\n"));
1158
 
    }
1159
 
  
1160
 
  SAFE_FREE(rparam);
1161
 
  SAFE_FREE(rdata);
1162
 
  
1163
 
  return res;
1164
 
}
1165
 
/****************************************************************************
1166
 
 call a NetShareDelete - unshare exported directory on remote server
1167
 
****************************************************************************/
1168
 
int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1169
 
{
1170
 
  char *rparam = NULL;
1171
 
  char *rdata = NULL;
1172
 
  char *p;
1173
 
  unsigned int rdrcnt,rprcnt;
1174
 
  int res;
1175
 
  char param[WORDSIZE                  /* api number    */
1176
 
            +sizeof(RAP_WShareDel_REQ) /* req string    */
1177
 
            +1                         /* no ret string */
1178
 
            +RAP_SHARENAME_LEN         /* share to del  */
1179
 
            +WORDSIZE];                /* reserved word */
1180
 
            
1181
 
 
1182
 
  /* now send a SMBtrans command with api RNetShareDelete */
1183
 
  p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1184
 
  PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1185
 
  PUTWORD(p,0);  /* reserved word MBZ on input */
1186
 
                 
1187
 
  if (cli_api(cli, 
1188
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1189
 
              NULL, 0, 200,       /* data, length, maxlen */
1190
 
              &rparam, &rprcnt,   /* return params, length */
1191
 
              &rdata, &rdrcnt))   /* return data, length */
1192
 
    {
1193
 
      res = GETRES(rparam);
1194
 
                        
1195
 
      if (res == 0) {
1196
 
        /* nothing to do */             
1197
 
      }
1198
 
      else {
1199
 
        DEBUG(4,("NetShareDelete res=%d\n", res));
1200
 
      }      
1201
 
    } else {
1202
 
      res = -1;
1203
 
      DEBUG(4,("NetShareDelete failed\n"));
1204
 
    }
1205
 
  
1206
 
  SAFE_FREE(rparam);
1207
 
  SAFE_FREE(rdata);
1208
 
        
1209
 
  return res;
1210
 
}
1211
 
/*************************************************************************
1212
 
*
1213
 
* Function Name:  cli_get_pdc_name
1214
 
*
1215
 
* PURPOSE:  Remotes a NetServerEnum API call to the current server
1216
 
*           requesting the name of a server matching the server
1217
 
*           type of SV_TYPE_DOMAIN_CTRL (PDC).
1218
 
*
1219
 
* Dependencies: none
1220
 
*
1221
 
* Parameters: 
1222
 
*             cli       - pointer to cli_state structure
1223
 
*             workgroup - pointer to string containing name of domain
1224
 
*             pdc_name  - pointer to string that will contain PDC name
1225
 
*                         on successful return
1226
 
*
1227
 
* Returns:
1228
 
*             True      - success
1229
 
*             False     - failure
1230
 
*
1231
 
************************************************************************/
1232
 
BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1233
 
{
1234
 
  char *rparam = NULL;
1235
 
  char *rdata = NULL;
1236
 
  unsigned int rdrcnt,rprcnt;
1237
 
  char *p;
1238
 
  char param[WORDSIZE                       /* api number    */
1239
 
            +sizeof(RAP_NetServerEnum2_REQ) /* req string    */
1240
 
            +sizeof(RAP_SERVER_INFO_L1)     /* return string */
1241
 
            +WORDSIZE                       /* info level    */
1242
 
            +WORDSIZE                       /* buffer size   */
1243
 
            +DWORDSIZE                      /* server type   */
1244
 
            +RAP_MACHNAME_LEN];             /* workgroup     */
1245
 
  int count = -1;
1246
 
  
1247
 
  *pdc_name = '\0';
1248
 
 
1249
 
  /* send a SMBtrans command with api NetServerEnum */
1250
 
  p = make_header(param, RAP_NetServerEnum2,
1251
 
                  RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1252
 
  PUTWORD(p, 1); /* info level */
1253
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1254
 
  PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1255
 
  PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1256
 
        
1257
 
  if (cli_api(cli, 
1258
 
              param, PTR_DIFF(p,param), 8,        /* params, length, max */
1259
 
              NULL, 0, CLI_BUFFER_SIZE,               /* data, length, max */
1260
 
              &rparam, &rprcnt,                   /* return params, return size */
1261
 
              &rdata, &rdrcnt                     /* return data, return size */
1262
 
              )) {
1263
 
    cli->rap_error = GETRES(rparam);
1264
 
                        
1265
 
        /*
1266
 
         * We only really care to copy a name if the
1267
 
         * API succeeded and we got back a name.
1268
 
         */
1269
 
    if (cli->rap_error == 0) {
1270
 
      p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1271
 
      GETWORD(p, count);
1272
 
      p = rdata;
1273
 
      
1274
 
      if (count > 0)
1275
 
        GETSTRING(p, pdc_name);
1276
 
    }
1277
 
    else {
1278
 
        DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1279
 
                 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1280
 
    }
1281
 
  }
1282
 
  
1283
 
  SAFE_FREE(rparam);
1284
 
  SAFE_FREE(rdata);
1285
 
  
1286
 
  return(count > 0);
1287
 
}
1288
 
 
1289
 
 
1290
 
/*************************************************************************
1291
 
*
1292
 
* Function Name:  cli_get_server_domain
1293
 
*
1294
 
* PURPOSE:  Remotes a NetWkstaGetInfo API call to the current server
1295
 
*           requesting wksta_info_10 level information to determine
1296
 
*           the domain the server belongs to. On success, this
1297
 
*           routine sets the server_domain field in the cli_state structure
1298
 
*           to the server's domain name.
1299
 
*
1300
 
* Dependencies: none
1301
 
*
1302
 
* Parameters: 
1303
 
*             cli       - pointer to cli_state structure
1304
 
*
1305
 
* Returns:
1306
 
*             True      - success
1307
 
*             False     - failure
1308
 
*
1309
 
* Origins:  samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1310
 
*
1311
 
************************************************************************/
1312
 
BOOL cli_get_server_domain(struct cli_state *cli)
1313
 
{
1314
 
  char *rparam = NULL;
1315
 
  char *rdata = NULL;
1316
 
  unsigned int rdrcnt,rprcnt;
1317
 
  char *p;
1318
 
  char param[WORDSIZE                      /* api number    */
1319
 
            +sizeof(RAP_WWkstaGetInfo_REQ) /* req string    */
1320
 
            +sizeof(RAP_WKSTA_INFO_L10)    /* return string */
1321
 
            +WORDSIZE                      /* info level    */
1322
 
            +WORDSIZE];                    /* buffer size   */
1323
 
  int res = -1;
1324
 
  
1325
 
  /* send a SMBtrans command with api NetWkstaGetInfo */
1326
 
  p = make_header(param, RAP_WWkstaGetInfo,
1327
 
                  RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1328
 
  PUTWORD(p, 10); /* info level */
1329
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1330
 
        
1331
 
  if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1332
 
              NULL, 0, CLI_BUFFER_SIZE,         /* data, length, max */
1333
 
              &rparam, &rprcnt,         /* return params, return size */
1334
 
              &rdata, &rdrcnt)) {       /* return data, return size */
1335
 
    res = GETRES(rparam);
1336
 
    p = rdata;          
1337
 
    
1338
 
    if (res == 0) {
1339
 
      int converter;
1340
 
 
1341
 
      p = rparam + WORDSIZE;
1342
 
      GETWORD(p, converter);
1343
 
      
1344
 
      p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1345
 
      GETSTRINGP(p, cli->server_domain, rdata, converter);
1346
 
    }
1347
 
  }
1348
 
  
1349
 
  SAFE_FREE(rparam);
1350
 
  SAFE_FREE(rdata);
1351
 
  
1352
 
  return(res == 0);
1353
 
}
1354
 
 
1355
 
 
1356
 
/*************************************************************************
1357
 
*
1358
 
* Function Name:  cli_get_server_type
1359
 
*
1360
 
* PURPOSE:  Remotes a NetServerGetInfo API call to the current server
1361
 
*           requesting server_info_1 level information to retrieve
1362
 
*           the server type.
1363
 
*
1364
 
* Dependencies: none
1365
 
*
1366
 
* Parameters: 
1367
 
*             cli       - pointer to cli_state structure
1368
 
*             pstype    - pointer to uint32 to contain returned server type
1369
 
*
1370
 
* Returns:
1371
 
*             True      - success
1372
 
*             False     - failure
1373
 
*
1374
 
* Origins:  samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1375
 
*
1376
 
************************************************************************/
1377
 
BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1378
 
{
1379
 
  char *rparam = NULL;
1380
 
  char *rdata = NULL;
1381
 
  unsigned int rdrcnt,rprcnt;
1382
 
  char *p;
1383
 
  char param[WORDSIZE                       /* api number    */
1384
 
            +sizeof(RAP_WserverGetInfo_REQ) /* req string    */
1385
 
            +sizeof(RAP_SERVER_INFO_L1)     /* return string */
1386
 
            +WORDSIZE                       /* info level    */
1387
 
            +WORDSIZE];                     /* buffer size   */
1388
 
  int res = -1;
1389
 
  
1390
 
  /* send a SMBtrans command with api NetServerGetInfo */
1391
 
  p = make_header(param, RAP_WserverGetInfo,
1392
 
                  RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1393
 
  PUTWORD(p, 1); /* info level */
1394
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1395
 
        
1396
 
  if (cli_api(cli, 
1397
 
              param, PTR_DIFF(p,param), 8, /* params, length, max */
1398
 
              NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1399
 
              &rparam, &rprcnt,         /* return params, return size */
1400
 
              &rdata, &rdrcnt           /* return data, return size */
1401
 
              )) {
1402
 
    
1403
 
    res = GETRES(rparam);
1404
 
    
1405
 
    if (res == 0 || res == ERRmoredata) {
1406
 
      p = rdata;                                        
1407
 
      *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1408
 
    }
1409
 
  }
1410
 
  
1411
 
  SAFE_FREE(rparam);
1412
 
  SAFE_FREE(rdata);
1413
 
  
1414
 
  return(res == 0 || res == ERRmoredata);
1415
 
}
1416
 
 
1417
 
 
1418
 
/*************************************************************************
1419
 
*
1420
 
* Function Name:  cli_ns_check_server_type
1421
 
*
1422
 
* PURPOSE:  Remotes a NetServerEnum2 API call to the current server
1423
 
*           requesting server_info_0 level information of machines
1424
 
*           matching the given server type. If the returned server
1425
 
*           list contains the machine name contained in cli->desthost
1426
 
*           then we conclude the server type checks out. This routine
1427
 
*           is useful to retrieve list of server's of a certain
1428
 
*           type when all you have is a null session connection and
1429
 
*           can't remote API calls such as NetWkstaGetInfo or 
1430
 
*           NetServerGetInfo.
1431
 
*
1432
 
* Dependencies: none
1433
 
*
1434
 
* Parameters: 
1435
 
*             cli       - pointer to cli_state structure
1436
 
*             workgroup - pointer to string containing domain
1437
 
*             stype     - server type
1438
 
*
1439
 
* Returns:
1440
 
*             True      - success
1441
 
*             False     - failure
1442
 
*
1443
 
************************************************************************/
1444
 
BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1445
 
{
1446
 
  char *rparam = NULL;
1447
 
  char *rdata = NULL;
1448
 
  unsigned int rdrcnt,rprcnt;
1449
 
  char *p;
1450
 
  char param[WORDSIZE                       /* api number    */
1451
 
            +sizeof(RAP_NetServerEnum2_REQ) /* req string    */
1452
 
            +sizeof(RAP_SERVER_INFO_L0)     /* return string */
1453
 
            +WORDSIZE                       /* info level    */
1454
 
            +WORDSIZE                       /* buffer size   */
1455
 
            +DWORDSIZE                      /* server type   */
1456
 
            +RAP_MACHNAME_LEN];             /* workgroup     */
1457
 
  BOOL found_server = False;
1458
 
  int res = -1;
1459
 
  
1460
 
  /* send a SMBtrans command with api NetServerEnum */
1461
 
  p = make_header(param, RAP_NetServerEnum2,
1462
 
                  RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1463
 
  PUTWORD(p, 0); /* info level 0 */
1464
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1465
 
  PUTDWORD(p, stype);
1466
 
  PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1467
 
        
1468
 
  if (cli_api(cli, 
1469
 
              param, PTR_DIFF(p,param), 8, /* params, length, max */
1470
 
              NULL, 0, CLI_BUFFER_SIZE,  /* data, length, max */
1471
 
              &rparam, &rprcnt,          /* return params, return size */
1472
 
              &rdata, &rdrcnt            /* return data, return size */
1473
 
              )) {
1474
 
        
1475
 
    res = GETRES(rparam);
1476
 
    cli->rap_error = res;
1477
 
 
1478
 
    if (res == 0 || res == ERRmoredata) {
1479
 
      int i, count;
1480
 
 
1481
 
      p = rparam + WORDSIZE + WORDSIZE;
1482
 
      GETWORD(p, count);
1483
 
 
1484
 
      p = rdata;
1485
 
      for (i = 0;i < count;i++, p += 16) {
1486
 
        char ret_server[RAP_MACHNAME_LEN];
1487
 
 
1488
 
        GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1489
 
        if (strequal(ret_server, cli->desthost)) {
1490
 
          found_server = True;
1491
 
          break;
1492
 
        }
1493
 
      }
1494
 
    }
1495
 
    else {
1496
 
      DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1497
 
               "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1498
 
    }
1499
 
  }
1500
 
  
1501
 
  SAFE_FREE(rparam);
1502
 
  SAFE_FREE(rdata);
1503
 
        
1504
 
  return found_server;
1505
 
 }
1506
 
 
1507
 
 
1508
 
/****************************************************************************
1509
 
 perform a NetWkstaUserLogoff
1510
 
****************************************************************************/
1511
 
BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1512
 
{
1513
 
  char *rparam = NULL;
1514
 
  char *rdata = NULL;
1515
 
  char *p;
1516
 
  unsigned int rdrcnt,rprcnt;
1517
 
  char param[WORDSIZE                           /* api number    */
1518
 
            +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string    */
1519
 
            +sizeof(RAP_USER_LOGOFF_INFO_L1)    /* return string */
1520
 
            +RAP_USERNAME_LEN+1                 /* user name+pad */
1521
 
            +RAP_MACHNAME_LEN                   /* wksta name    */
1522
 
            +WORDSIZE                           /* buffer size   */
1523
 
            +WORDSIZE];                         /* buffer size?  */
1524
 
  fstring upperbuf;
1525
 
  
1526
 
  memset(param, 0, sizeof(param));
1527
 
 
1528
 
  /* send a SMBtrans command with api NetWkstaUserLogoff */
1529
 
  p = make_header(param, RAP_WWkstaUserLogoff,
1530
 
                  RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1531
 
  PUTDWORD(p, 0); /* Null pointer */
1532
 
  PUTDWORD(p, 0); /* Null pointer */
1533
 
  fstrcpy(upperbuf, user);
1534
 
  strupper_m(upperbuf);
1535
 
  PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1536
 
  p++; /* strange format, but ok */
1537
 
  fstrcpy(upperbuf, workstation);
1538
 
  strupper_m(upperbuf);
1539
 
  PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1540
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1541
 
  PUTWORD(p, CLI_BUFFER_SIZE);
1542
 
  
1543
 
  if (cli_api(cli,
1544
 
              param, PTR_DIFF(p,param),1024,  /* param, length, max */
1545
 
              NULL, 0, CLI_BUFFER_SIZE,       /* data, length, max */
1546
 
              &rparam, &rprcnt,               /* return params, return size */
1547
 
              &rdata, &rdrcnt                 /* return data, return size */
1548
 
              )) {
1549
 
    cli->rap_error = GETRES(rparam);
1550
 
    
1551
 
    if (cli->rap_error != 0) {
1552
 
      DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1553
 
    }
1554
 
  }
1555
 
  
1556
 
  SAFE_FREE(rparam);
1557
 
  SAFE_FREE(rdata);
1558
 
  return (cli->rap_error == 0);
1559
 
}
1560
 
 
1561
 
int cli_NetPrintQEnum(struct cli_state *cli,
1562
 
                void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1563
 
                void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1564
 
{
1565
 
  char param[WORDSIZE                         /* api number    */
1566
 
            +sizeof(RAP_NetPrintQEnum_REQ)    /* req string    */
1567
 
            +sizeof(RAP_PRINTQ_INFO_L2)       /* return string */
1568
 
            +WORDSIZE                         /* info level    */
1569
 
            +WORDSIZE                         /* buffer size   */
1570
 
            +sizeof(RAP_SMB_PRINT_JOB_L1)];   /* more ret data */
1571
 
  char *p;
1572
 
  char *rparam = NULL;
1573
 
  char *rdata = NULL; 
1574
 
  unsigned int rprcnt, rdrcnt;
1575
 
  int res = -1;
1576
 
  
1577
 
 
1578
 
  memset(param, '\0',sizeof(param));
1579
 
  p = make_header(param, RAP_WPrintQEnum, 
1580
 
                  RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1581
 
  PUTWORD(p,2); /* Info level 2 */
1582
 
  PUTWORD(p,0xFFE0); /* Return buffer size */
1583
 
  PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1584
 
 
1585
 
  if (cli_api(cli,
1586
 
              param, PTR_DIFF(p,param),1024,
1587
 
              NULL, 0, CLI_BUFFER_SIZE,
1588
 
              &rparam, &rprcnt,
1589
 
              &rdata, &rdrcnt)) {
1590
 
    res = GETRES(rparam);
1591
 
    cli->rap_error = res;
1592
 
    if (res != 0) {
1593
 
      DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1594
 
    }
1595
 
  }
1596
 
 
1597
 
  if (rdata) {
1598
 
    if (res == 0 || res == ERRmoredata) {
1599
 
      int i, converter, count;
1600
 
 
1601
 
      p = rparam + WORDSIZE;
1602
 
      GETWORD(p, converter);
1603
 
      GETWORD(p, count);
1604
 
 
1605
 
      p = rdata;
1606
 
      for (i=0;i<count;i++) {
1607
 
        pstring qname, sep_file, print_proc, dest, parms, comment;
1608
 
        uint16 jobcount, priority, start_time, until_time, status;
1609
 
 
1610
 
        GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1611
 
        p++; /* pad */
1612
 
        GETWORD(p, priority);
1613
 
        GETWORD(p, start_time);
1614
 
        GETWORD(p, until_time);
1615
 
        GETSTRINGP(p, sep_file, rdata, converter);
1616
 
        GETSTRINGP(p, print_proc, rdata, converter);
1617
 
        GETSTRINGP(p, dest, rdata, converter);
1618
 
        GETSTRINGP(p, parms, rdata, converter);
1619
 
        GETSTRINGP(p, parms, comment, converter);
1620
 
        GETWORD(p, status);
1621
 
        GETWORD(p, jobcount);
1622
 
 
1623
 
        qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1624
 
            dest, parms, comment, status, jobcount);
1625
 
 
1626
 
        if (jobcount) {
1627
 
          int j;
1628
 
          for (j=0;j<jobcount;j++) {
1629
 
            uint16 jid, pos, fsstatus;
1630
 
            pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1631
 
            unsigned int submitted, jsize;
1632
 
            
1633
 
            GETWORD(p, jid);
1634
 
            GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1635
 
            p++; /* pad byte */
1636
 
            GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1637
 
            GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1638
 
            GETSTRINGP(p, jparms, rdata, converter);
1639
 
            GETWORD(p, pos);
1640
 
            GETWORD(p, fsstatus);
1641
 
            GETSTRINGP(p, jstatus, rdata, converter);
1642
 
            GETDWORD(p, submitted);
1643
 
            GETDWORD(p, jsize);
1644
 
            GETSTRINGP(p, jcomment, rdata, converter);
1645
 
          
1646
 
            jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1647
 
                jstatus, submitted, jsize, jcomment);
1648
 
          }
1649
 
        }
1650
 
      }
1651
 
    } else {
1652
 
      DEBUG(4,("NetPrintQEnum res=%d\n", res));
1653
 
    }
1654
 
  } else {
1655
 
    DEBUG(4,("NetPrintQEnum no data returned\n"));
1656
 
  }
1657
 
    
1658
 
  SAFE_FREE(rparam);
1659
 
  SAFE_FREE(rdata);
1660
 
 
1661
 
  return res;  
1662
 
}
1663
 
 
1664
 
int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1665
 
        void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1666
 
        void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1667
 
{
1668
 
  char param[WORDSIZE                         /* api number    */
1669
 
            +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string    */
1670
 
            +sizeof(RAP_PRINTQ_INFO_L2)       /* return string */ 
1671
 
            +RAP_SHARENAME_LEN                /* printer name  */
1672
 
            +WORDSIZE                         /* info level    */
1673
 
            +WORDSIZE                         /* buffer size   */
1674
 
            +sizeof(RAP_SMB_PRINT_JOB_L1)];   /* more ret data */
1675
 
  char *p;
1676
 
  char *rparam = NULL;
1677
 
  char *rdata = NULL; 
1678
 
  unsigned int rprcnt, rdrcnt;
1679
 
  int res = -1;
1680
 
  
1681
 
 
1682
 
  memset(param, '\0',sizeof(param));
1683
 
  p = make_header(param, RAP_WPrintQGetInfo,
1684
 
                  RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1685
 
  PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1686
 
  PUTWORD(p, 2);     /* Info level 2 */
1687
 
  PUTWORD(p,0xFFE0); /* Return buffer size */
1688
 
  PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1689
 
 
1690
 
  if (cli_api(cli,
1691
 
              param, PTR_DIFF(p,param),1024,
1692
 
              NULL, 0, CLI_BUFFER_SIZE,
1693
 
              &rparam, &rprcnt,
1694
 
              &rdata, &rdrcnt)) {
1695
 
    res = GETRES(rparam);
1696
 
    cli->rap_error = res;
1697
 
    if (res != 0) {
1698
 
      DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1699
 
    }
1700
 
  }
1701
 
 
1702
 
  if (rdata) {
1703
 
    if (res == 0 || res == ERRmoredata) {
1704
 
      int rsize, converter;
1705
 
      pstring qname, sep_file, print_proc, dest, parms, comment;
1706
 
      uint16 jobcount, priority, start_time, until_time, status;
1707
 
      
1708
 
      p = rparam + WORDSIZE;
1709
 
      GETWORD(p, converter);
1710
 
      GETWORD(p, rsize);
1711
 
 
1712
 
      p = rdata;
1713
 
      GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1714
 
      p++; /* pad */
1715
 
      GETWORD(p, priority);
1716
 
      GETWORD(p, start_time);
1717
 
      GETWORD(p, until_time);
1718
 
      GETSTRINGP(p, sep_file, rdata, converter);
1719
 
      GETSTRINGP(p, print_proc, rdata, converter);
1720
 
      GETSTRINGP(p, dest, rdata, converter);
1721
 
      GETSTRINGP(p, parms, rdata, converter);
1722
 
      GETSTRINGP(p, comment, rdata, converter);
1723
 
      GETWORD(p, status);
1724
 
      GETWORD(p, jobcount);
1725
 
      qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1726
 
          dest, parms, comment, status, jobcount);
1727
 
      if (jobcount) {
1728
 
        int j;
1729
 
        for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1730
 
          uint16 jid, pos, fsstatus;
1731
 
          pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1732
 
          unsigned int submitted, jsize;
1733
 
 
1734
 
          GETWORD(p, jid);
1735
 
          GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1736
 
          p++; /* pad byte */
1737
 
          GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1738
 
          GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1739
 
          GETSTRINGP(p, jparms, rdata, converter);
1740
 
          GETWORD(p, pos);
1741
 
          GETWORD(p, fsstatus);
1742
 
          GETSTRINGP(p, jstatus, rdata, converter);
1743
 
          GETDWORD(p, submitted);
1744
 
          GETDWORD(p, jsize);
1745
 
          GETSTRINGP(p, jcomment, rdata, converter);
1746
 
          
1747
 
          jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1748
 
              jstatus, submitted, jsize, jcomment);
1749
 
        }
1750
 
      }
1751
 
    } else {
1752
 
      DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1753
 
    }
1754
 
  } else {
1755
 
    DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1756
 
  }
1757
 
    
1758
 
  SAFE_FREE(rparam);
1759
 
  SAFE_FREE(rdata);
1760
 
 
1761
 
  return res;  
1762
 
}
1763
 
 
1764
 
/****************************************************************************
1765
 
call a NetServiceEnum - list running services on a different host
1766
 
****************************************************************************/
1767
 
int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1768
 
{
1769
 
  char param[WORDSIZE                     /* api number    */
1770
 
            +sizeof(RAP_NetServiceEnum_REQ) /* parm string   */
1771
 
            +sizeof(RAP_SERVICE_INFO_L2)    /* return string */
1772
 
            +WORDSIZE                     /* info level    */
1773
 
            +WORDSIZE];                   /* buffer size   */
1774
 
  char *p;
1775
 
  char *rparam = NULL;
1776
 
  char *rdata = NULL; 
1777
 
  unsigned int rprcnt, rdrcnt;
1778
 
  int res = -1;
1779
 
  
1780
 
  
1781
 
  memset(param, '\0', sizeof(param));
1782
 
  p = make_header(param, RAP_WServiceEnum,
1783
 
                  RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1784
 
  PUTWORD(p,2); /* Info level 2 */  
1785
 
  PUTWORD(p,0xFFE0); /* Return buffer size */
1786
 
 
1787
 
  if (cli_api(cli,
1788
 
              param, PTR_DIFF(p,param),8,
1789
 
              NULL, 0, 0xFFE0 /* data area size */,
1790
 
              &rparam, &rprcnt,
1791
 
              &rdata, &rdrcnt)) {
1792
 
    res = GETRES(rparam);
1793
 
    cli->rap_error = res;
1794
 
    if(cli->rap_error == 234) 
1795
 
        DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1796
 
    else if (cli->rap_error != 0) {
1797
 
      DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1798
 
    }
1799
 
  }
1800
 
 
1801
 
  if (rdata) {
1802
 
    if (res == 0 || res == ERRmoredata) {
1803
 
      int i, count;
1804
 
 
1805
 
      p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1806
 
      GETWORD(p, count);
1807
 
 
1808
 
      for (i=0,p=rdata;i<count;i++) {
1809
 
            pstring comment;
1810
 
            char servicename[RAP_SRVCNAME_LEN];
1811
 
 
1812
 
            GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1813
 
            p+=8; /* pass status words */
1814
 
            GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1815
 
 
1816
 
            fn(servicename, comment, cli);  /* BB add status too */
1817
 
      } 
1818
 
    } else {
1819
 
      DEBUG(4,("NetServiceEnum res=%d\n", res));
1820
 
    }
1821
 
  } else {
1822
 
    DEBUG(4,("NetServiceEnum no data returned\n"));
1823
 
  }
1824
 
    
1825
 
  SAFE_FREE(rparam);
1826
 
  SAFE_FREE(rdata);
1827
 
 
1828
 
  return res;
1829
 
}
1830
 
 
1831
 
 
1832
 
/****************************************************************************
1833
 
call a NetSessionEnum - list workstations with sessions to an SMB server
1834
 
****************************************************************************/
1835
 
int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1836
 
{
1837
 
  char param[WORDSIZE                       /* api number    */
1838
 
            +sizeof(RAP_NetSessionEnum_REQ) /* parm string   */
1839
 
            +sizeof(RAP_SESSION_INFO_L2)    /* return string */
1840
 
            +WORDSIZE                       /* info level    */
1841
 
            +WORDSIZE];                     /* buffer size   */
1842
 
  char *p;
1843
 
  char *rparam = NULL;
1844
 
  char *rdata = NULL; 
1845
 
  unsigned int rprcnt, rdrcnt;
1846
 
  int res = -1;
1847
 
  
1848
 
  memset(param, '\0', sizeof(param));
1849
 
  p = make_header(param, RAP_WsessionEnum, 
1850
 
                  RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1851
 
  PUTWORD(p,2);    /* Info level 2 */
1852
 
  PUTWORD(p,0xFF); /* Return buffer size */
1853
 
 
1854
 
  if (cli_api(cli,
1855
 
              param, PTR_DIFF(p,param),8,
1856
 
              NULL, 0, CLI_BUFFER_SIZE,
1857
 
              &rparam, &rprcnt,
1858
 
              &rdata, &rdrcnt)) {
1859
 
    res = GETRES(rparam);
1860
 
    cli->rap_error = res;
1861
 
    if (res != 0) {
1862
 
      DEBUG(1,("NetSessionEnum gave error %d\n", res));
1863
 
    }
1864
 
  }
1865
 
 
1866
 
  if (rdata) {
1867
 
    if (res == 0 || res == ERRmoredata) {
1868
 
      int i, converter, count;
1869
 
      
1870
 
      p = rparam + WORDSIZE;
1871
 
      GETWORD(p, converter);
1872
 
      GETWORD(p, count);
1873
 
 
1874
 
      for (i=0,p=rdata;i<count;i++) {
1875
 
        pstring wsname, username, clitype_name;
1876
 
        uint16  num_conns, num_opens, num_users;
1877
 
        unsigned int    sess_time, idle_time, user_flags;
1878
 
 
1879
 
        GETSTRINGP(p, wsname, rdata, converter);
1880
 
        GETSTRINGP(p, username, rdata, converter);
1881
 
        GETWORD(p, num_conns);
1882
 
        GETWORD(p, num_opens);
1883
 
        GETWORD(p, num_users);
1884
 
        GETDWORD(p, sess_time);
1885
 
        GETDWORD(p, idle_time);
1886
 
        GETDWORD(p, user_flags);
1887
 
        GETSTRINGP(p, clitype_name, rdata, converter);
1888
 
 
1889
 
        fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1890
 
           idle_time, user_flags, clitype_name);
1891
 
      }
1892
 
        
1893
 
    } else {
1894
 
      DEBUG(4,("NetSessionEnum res=%d\n", res));
1895
 
    }
1896
 
  } else {
1897
 
    DEBUG(4,("NetSesssionEnum no data returned\n"));
1898
 
  }
1899
 
    
1900
 
  SAFE_FREE(rparam);
1901
 
  SAFE_FREE(rdata);
1902
 
 
1903
 
  return res;
1904
 
}
1905
 
 
1906
 
/****************************************************************************
1907
 
 Call a NetSessionGetInfo - get information about other session to an SMB server.
1908
 
****************************************************************************/
1909
 
 
1910
 
int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1911
 
{
1912
 
  char param[WORDSIZE                          /* api number    */
1913
 
            +sizeof(RAP_NetSessionGetInfo_REQ) /* req string    */
1914
 
            +sizeof(RAP_SESSION_INFO_L2)       /* return string */ 
1915
 
            +RAP_MACHNAME_LEN                  /* wksta name    */
1916
 
            +WORDSIZE                          /* info level    */
1917
 
            +WORDSIZE];                        /* buffer size   */
1918
 
  char *p;
1919
 
  char *rparam = NULL;
1920
 
  char *rdata = NULL; 
1921
 
  unsigned int rprcnt, rdrcnt;
1922
 
  int res = -1;
1923
 
  
1924
 
 
1925
 
  memset(param, '\0', sizeof(param));
1926
 
  p = make_header(param, RAP_WsessionGetInfo, 
1927
 
                  RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1928
 
  PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1929
 
  PUTWORD(p,2); /* Info level 2 */
1930
 
  PUTWORD(p,0xFF); /* Return buffer size */
1931
 
 
1932
 
  if (cli_api(cli,
1933
 
              param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1934
 
              NULL, 0, CLI_BUFFER_SIZE,
1935
 
              &rparam, &rprcnt,
1936
 
              &rdata, &rdrcnt)) {
1937
 
    cli->rap_error = SVAL(rparam,0);
1938
 
    if (cli->rap_error != 0) {
1939
 
      DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1940
 
    }
1941
 
  }
1942
 
 
1943
 
  if (rdata) {
1944
 
    res = GETRES(rparam);
1945
 
    
1946
 
    if (res == 0 || res == ERRmoredata) {
1947
 
      int converter;
1948
 
      pstring wsname, username, clitype_name;
1949
 
      uint16  num_conns, num_opens, num_users;
1950
 
      unsigned int    sess_time, idle_time, user_flags;
1951
 
 
1952
 
      p = rparam + WORDSIZE;
1953
 
      GETWORD(p, converter);
1954
 
      p += WORDSIZE;            /* skip rsize */
1955
 
 
1956
 
      p = rdata;
1957
 
      GETSTRINGP(p, wsname, rdata, converter);
1958
 
      GETSTRINGP(p, username, rdata, converter);
1959
 
      GETWORD(p, num_conns);
1960
 
      GETWORD(p, num_opens);
1961
 
      GETWORD(p, num_users);
1962
 
      GETDWORD(p, sess_time);
1963
 
      GETDWORD(p, idle_time);
1964
 
      GETDWORD(p, user_flags);
1965
 
      GETSTRINGP(p, clitype_name, rdata, converter);
1966
 
      
1967
 
      fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1968
 
         idle_time, user_flags, clitype_name);
1969
 
    } else {
1970
 
      DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1971
 
    }
1972
 
  } else {
1973
 
    DEBUG(4,("NetSessionGetInfo no data returned\n"));
1974
 
  }
1975
 
    
1976
 
  SAFE_FREE(rparam);
1977
 
  SAFE_FREE(rdata);
1978
 
 
1979
 
  return res;  
1980
 
}
1981
 
 
1982
 
/****************************************************************************
1983
 
call a NetSessionDel - close a session to an SMB server
1984
 
****************************************************************************/
1985
 
int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1986
 
{
1987
 
  char param[WORDSIZE                      /* api number       */
1988
 
            +sizeof(RAP_NetSessionDel_REQ) /* req string       */
1989
 
            +1                             /* no return string */
1990
 
            +RAP_MACHNAME_LEN              /* workstation name */
1991
 
            +WORDSIZE];                    /* reserved (0)     */
1992
 
  char *p;
1993
 
  char *rparam = NULL;
1994
 
  char *rdata = NULL;
1995
 
  unsigned int rprcnt, rdrcnt;
1996
 
  int res;
1997
 
 
1998
 
  memset(param, '\0', sizeof(param));
1999
 
  p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
2000
 
  PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2001
 
  PUTWORD(p,0); /* reserved word of 0 */
2002
 
  if (cli_api(cli, 
2003
 
              param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2004
 
              NULL, 0, 200,       /* data, length, maxlen */
2005
 
              &rparam, &rprcnt,   /* return params, length */
2006
 
              &rdata, &rdrcnt))   /* return data, length */
2007
 
    {
2008
 
      res = GETRES(rparam);
2009
 
      cli->rap_error = res;
2010
 
      
2011
 
      if (res == 0) {
2012
 
        /* nothing to do */             
2013
 
      }
2014
 
      else {
2015
 
        DEBUG(4,("NetFileClose2 res=%d\n", res));
2016
 
      }      
2017
 
    } else {
2018
 
      res = -1;
2019
 
      DEBUG(4,("NetFileClose2 failed\n"));
2020
 
    }
2021
 
  
2022
 
  SAFE_FREE(rparam);
2023
 
  SAFE_FREE(rdata);
2024
 
 
2025
 
  return res;
2026
 
}
2027
 
  
2028
 
 
2029
 
int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*fn)(uint16 conid, uint16 contype, uint16 numopens, uint16 numusers, uint32 contime, const char *username, const char *netname))
2030
 
{
2031
 
  char param[WORDSIZE                          /* api number    */
2032
 
            +sizeof(RAP_NetConnectionEnum_REQ) /* req string    */
2033
 
            +sizeof(RAP_CONNECTION_INFO_L1)    /* return string */ 
2034
 
            +RAP_MACHNAME_LEN                  /* wksta name    */
2035
 
            +WORDSIZE                          /* info level    */
2036
 
            +WORDSIZE];                        /* buffer size   */
2037
 
  char *p;
2038
 
  char *rparam = NULL;
2039
 
  char *rdata = NULL; 
2040
 
  unsigned int rprcnt, rdrcnt;
2041
 
  int res = -1;
2042
 
 
2043
 
  memset(param, '\0', sizeof(param));
2044
 
  p = make_header(param, RAP_WconnectionEnum,
2045
 
                  RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2046
 
  PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2047
 
  PUTWORD(p,1);            /* Info level 1 */
2048
 
  PUTWORD(p,0xFFE0);       /* Return buffer size */
2049
 
 
2050
 
  if (cli_api(cli,
2051
 
              param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2052
 
              NULL, 0, CLI_BUFFER_SIZE,
2053
 
              &rparam, &rprcnt,
2054
 
              &rdata, &rdrcnt)) {
2055
 
    res = GETRES(rparam);
2056
 
    cli->rap_error = res;
2057
 
    if (res != 0) {
2058
 
      DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2059
 
    }
2060
 
  }
2061
 
  if (rdata) {
2062
 
    if (res == 0 || res == ERRmoredata) {
2063
 
      int i, converter, count;
2064
 
 
2065
 
      p = rparam + WORDSIZE;
2066
 
      GETWORD(p, converter);
2067
 
      GETWORD(p, count);
2068
 
 
2069
 
      for (i=0,p=rdata;i<count;i++) {
2070
 
        pstring netname, username;
2071
 
        uint16  conn_id, conn_type, num_opens, num_users;
2072
 
        unsigned int    conn_time;
2073
 
 
2074
 
        GETWORD(p,conn_id);
2075
 
        GETWORD(p,conn_type);
2076
 
        GETWORD(p,num_opens);
2077
 
        GETWORD(p,num_users);
2078
 
        GETDWORD(p,conn_time);
2079
 
        GETSTRINGP(p, username, rdata, converter);
2080
 
        GETSTRINGP(p, netname, rdata, converter);
2081
 
 
2082
 
        fn(conn_id, conn_type, num_opens, num_users, conn_time,
2083
 
           username, netname);
2084
 
      }
2085
 
        
2086
 
    } else {
2087
 
      DEBUG(4,("NetConnectionEnum res=%d\n", res));
2088
 
    }
2089
 
  } else {
2090
 
    DEBUG(4,("NetConnectionEnum no data returned\n"));
2091
 
  }
2092
 
  SAFE_FREE(rdata);
2093
 
  SAFE_FREE(rparam);
2094
 
  return res;
2095
 
}