r14683: Get rid of hardcoded output file. With no arg, print to stdout,
[Samba.git] / source / libsmb / clirap2.c
bloba327bae31746ae17cdcb98734b5e57659dbd8f8f
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)
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.
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.
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.
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 /*****************************************************/
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 /*****************************************************/
79 #include "includes.h"
81 #define WORDSIZE 2
82 #define DWORDSIZE 4
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)
129 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
131 PUTWORD(param,apinum);
132 if (reqfmt)
133 PUTSTRING(param,reqfmt,0);
134 else
135 *param++ = (char) 0;
137 if (datafmt)
138 PUTSTRING(param,datafmt,0);
139 else
140 *param++ = (char) 0;
142 return param;
146 /****************************************************************************
147 call a NetGroupDelete - delete user group from remote server
148 ****************************************************************************/
149 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
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 */
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 */
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 */
173 res = GETRES(rparam);
175 if (res == 0) {
176 /* nothing to do */
178 else if ((res == 5) || (res == 65)) {
179 DEBUG(1, ("Access Denied\n"));
181 else if (res == 2220) {
182 DEBUG (1, ("Group does not exist\n"));
184 else {
185 DEBUG(4,("NetGroupDelete res=%d\n", res));
187 } else {
188 res = -1;
189 DEBUG(4,("NetGroupDelete failed\n"));
192 SAFE_FREE(rparam);
193 SAFE_FREE(rdata);
195 return res;
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 )
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 */
214 char data[1024];
216 /* offset into data of free format strings. Will be updated */
217 /* by PUTSTRINGP macro and end up with total data length. */
218 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
220 /* now send a SMBtrans command with api WGroupAdd */
222 p = make_header(param, RAP_WGroupAdd,
223 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
224 PUTWORD(p, 1); /* info level */
225 PUTWORD(p, 0); /* reserved word 0 */
227 p = data;
228 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
229 PUTBYTE(p, 0); /* pad byte 0 */
230 PUTSTRINGP(p, grinfo->comment, data, soffset);
232 if (cli_api(cli,
233 param, sizeof(param), 1024, /* Param, length, maxlen */
234 data, soffset, sizeof(data), /* data, length, maxlen */
235 &rparam, &rprcnt, /* return params, length */
236 &rdata, &rdrcnt)) /* return data, length */
238 res = GETRES(rparam);
240 if (res == 0) {
241 /* nothing to do */
242 } else if ((res == 5) || (res == 65)) {
243 DEBUG(1, ("Access Denied\n"));
245 else if (res == 2223) {
246 DEBUG (1, ("Group already exists\n"));
248 else {
249 DEBUG(4,("NetGroupAdd res=%d\n", res));
251 } else {
252 res = -1;
253 DEBUG(4,("NetGroupAdd failed\n"));
256 SAFE_FREE(rparam);
257 SAFE_FREE(rdata);
259 return res;
262 /****************************************************************************
263 call a NetGroupEnum - try and list user groups on a different host
264 ****************************************************************************/
265 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
267 char param[WORDSIZE /* api number */
268 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
269 +sizeof(RAP_GROUP_INFO_L1) /* return string */
270 +WORDSIZE /* info level */
271 +WORDSIZE]; /* buffer size */
272 char *p;
273 char *rparam = NULL;
274 char *rdata = NULL;
275 unsigned int rprcnt, rdrcnt;
276 int res = -1;
279 memset(param, '\0', sizeof(param));
280 p = make_header(param, RAP_WGroupEnum,
281 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
282 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
283 PUTWORD(p,0xFFE0); /* Return buffer size */
285 if (cli_api(cli,
286 param, PTR_DIFF(p,param),8,
287 NULL, 0, 0xFFE0 /* data area size */,
288 &rparam, &rprcnt,
289 &rdata, &rdrcnt)) {
290 res = GETRES(rparam);
291 cli->rap_error = res;
292 if(cli->rap_error == 234)
293 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
294 else if (cli->rap_error != 0) {
295 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
299 if (rdata) {
300 if (res == 0 || res == ERRmoredata) {
301 int i, converter, count;
303 p = rparam + WORDSIZE; /* skip result */
304 GETWORD(p, converter);
305 GETWORD(p, count);
307 for (i=0,p=rdata;i<count;i++) {
308 pstring comment;
309 char groupname[RAP_GROUPNAME_LEN];
311 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
312 p++; /* pad byte */
313 GETSTRINGP(p, comment, rdata, converter);
315 fn(groupname, comment, cli);
317 } else {
318 DEBUG(4,("NetGroupEnum res=%d\n", res));
320 } else {
321 DEBUG(4,("NetGroupEnum no data returned\n"));
324 SAFE_FREE(rparam);
325 SAFE_FREE(rdata);
327 return res;
330 int cli_RNetGroupEnum0(struct cli_state *cli,
331 void (*fn)(const char *, void *),
332 void *state)
334 char param[WORDSIZE /* api number */
335 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
336 +sizeof(RAP_GROUP_INFO_L0) /* return string */
337 +WORDSIZE /* info level */
338 +WORDSIZE]; /* buffer size */
339 char *p;
340 char *rparam = NULL;
341 char *rdata = NULL;
342 unsigned int rprcnt, rdrcnt;
343 int res = -1;
346 memset(param, '\0', sizeof(param));
347 p = make_header(param, RAP_WGroupEnum,
348 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
349 PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
350 is the resume count, at least
351 that's what smbd believes... */
352 PUTWORD(p,0xFFE0); /* Return buffer size */
354 if (cli_api(cli,
355 param, PTR_DIFF(p,param),8,
356 NULL, 0, 0xFFE0 /* data area size */,
357 &rparam, &rprcnt,
358 &rdata, &rdrcnt)) {
359 res = GETRES(rparam);
360 cli->rap_error = res;
361 if(cli->rap_error == 234)
362 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
363 else if (cli->rap_error != 0) {
364 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
368 if (rdata) {
369 if (res == 0 || res == ERRmoredata) {
370 int i, count;
372 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
373 GETWORD(p, count);
375 for (i=0,p=rdata;i<count;i++) {
376 char groupname[RAP_GROUPNAME_LEN];
377 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
378 fn(groupname, cli);
380 } else {
381 DEBUG(4,("NetGroupEnum res=%d\n", res));
383 } else {
384 DEBUG(4,("NetGroupEnum no data returned\n"));
387 SAFE_FREE(rparam);
388 SAFE_FREE(rdata);
390 return res;
393 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
395 char *rparam = NULL;
396 char *rdata = NULL;
397 char *p;
398 unsigned int rdrcnt,rprcnt;
399 int res;
400 char param[WORDSIZE /* api number */
401 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
402 +1 /* no ret string */
403 +RAP_GROUPNAME_LEN /* group name */
404 +RAP_USERNAME_LEN]; /* user to del */
406 /* now send a SMBtrans command with api GroupMemberAdd */
407 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
408 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
409 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
411 if (cli_api(cli,
412 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
413 NULL, 0, 200, /* data, length, maxlen */
414 &rparam, &rprcnt, /* return params, length */
415 &rdata, &rdrcnt)) /* return data, length */
417 res = GETRES(rparam);
419 switch(res) {
420 case 0:
421 break;
422 case 5:
423 case 65:
424 DEBUG(1, ("Access Denied\n"));
425 break;
426 case 50:
427 DEBUG(1, ("Not supported by server\n"));
428 break;
429 case 2220:
430 DEBUG(1, ("Group does not exist\n"));
431 break;
432 case 2221:
433 DEBUG(1, ("User does not exist\n"));
434 break;
435 case 2237:
436 DEBUG(1, ("User is not in group\n"));
437 break;
438 default:
439 DEBUG(4,("NetGroupDelUser res=%d\n", res));
441 } else {
442 res = -1;
443 DEBUG(4,("NetGroupDelUser failed\n"));
446 SAFE_FREE(rparam);
447 SAFE_FREE(rdata);
449 return res;
452 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
454 char *rparam = NULL;
455 char *rdata = NULL;
456 char *p;
457 unsigned int rdrcnt,rprcnt;
458 int res;
459 char param[WORDSIZE /* api number */
460 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
461 +1 /* no ret string */
462 +RAP_GROUPNAME_LEN /* group name */
463 +RAP_USERNAME_LEN]; /* user to add */
465 /* now send a SMBtrans command with api GroupMemberAdd */
466 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
467 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
468 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
470 if (cli_api(cli,
471 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
472 NULL, 0, 200, /* data, length, maxlen */
473 &rparam, &rprcnt, /* return params, length */
474 &rdata, &rdrcnt)) /* return data, length */
476 res = GETRES(rparam);
478 switch(res) {
479 case 0:
480 break;
481 case 5:
482 case 65:
483 DEBUG(1, ("Access Denied\n"));
484 break;
485 case 50:
486 DEBUG(1, ("Not supported by server\n"));
487 break;
488 case 2220:
489 DEBUG(1, ("Group does not exist\n"));
490 break;
491 case 2221:
492 DEBUG(1, ("User does not exist\n"));
493 break;
494 default:
495 DEBUG(4,("NetGroupAddUser res=%d\n", res));
497 } else {
498 res = -1;
499 DEBUG(4,("NetGroupAddUser failed\n"));
502 SAFE_FREE(rparam);
503 SAFE_FREE(rdata);
505 return res;
509 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
511 char *rparam = NULL;
512 char *rdata = NULL;
513 char *p;
514 unsigned int rdrcnt,rprcnt;
515 int res = -1;
516 char param[WORDSIZE /* api number */
517 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
518 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
519 +RAP_GROUPNAME_LEN /* group name */
520 +WORDSIZE /* info level */
521 +WORDSIZE]; /* buffer size */
523 /* now send a SMBtrans command with api GroupGetUsers */
524 p = make_header(param, RAP_WGroupGetUsers,
525 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
526 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
527 PUTWORD(p,0); /* info level 0 */
528 PUTWORD(p,0xFFE0); /* return buffer size */
530 if (cli_api(cli,
531 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
532 NULL, 0, CLI_BUFFER_SIZE,
533 &rparam, &rprcnt,
534 &rdata, &rdrcnt)) {
535 res = GETRES(rparam);
536 cli->rap_error = res;
537 if (res != 0) {
538 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
541 if (rdata) {
542 if (res == 0 || res == ERRmoredata) {
543 int i, count;
544 fstring username;
545 p = rparam + WORDSIZE + WORDSIZE;
546 GETWORD(p, count);
548 for (i=0,p=rdata; i<count; i++) {
549 GETSTRINGF(p, username, RAP_USERNAME_LEN);
550 fn(username, state);
552 } else {
553 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
555 } else {
556 DEBUG(4,("NetGroupGetUsers no data returned\n"));
558 SAFE_FREE(rdata);
559 SAFE_FREE(rparam);
560 return res;
563 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
565 char *rparam = NULL;
566 char *rdata = NULL;
567 char *p;
568 unsigned int rdrcnt,rprcnt;
569 int res = -1;
570 char param[WORDSIZE /* api number */
571 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
572 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
573 +RAP_USERNAME_LEN /* user name */
574 +WORDSIZE /* info level */
575 +WORDSIZE]; /* buffer size */
577 /* now send a SMBtrans command with api GroupGetUsers */
578 p = make_header(param, RAP_WUserGetGroups,
579 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
580 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
581 PUTWORD(p,0); /* info level 0 */
582 PUTWORD(p,0xFFE0); /* return buffer size */
584 if (cli_api(cli,
585 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
586 NULL, 0, CLI_BUFFER_SIZE,
587 &rparam, &rprcnt,
588 &rdata, &rdrcnt)) {
589 res = GETRES(rparam);
590 cli->rap_error = res;
591 if (res != 0) {
592 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
595 if (rdata) {
596 if (res == 0 || res == ERRmoredata) {
597 int i, count;
598 fstring groupname;
599 p = rparam + WORDSIZE + WORDSIZE;
600 GETWORD(p, count);
602 for (i=0,p=rdata; i<count; i++) {
603 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
604 fn(groupname, state);
606 } else {
607 DEBUG(4,("NetUserGetGroups res=%d\n", res));
609 } else {
610 DEBUG(4,("NetUserGetGroups no data returned\n"));
612 SAFE_FREE(rdata);
613 SAFE_FREE(rparam);
614 return res;
618 /****************************************************************************
619 call a NetUserDelete - delete user from remote server
620 ****************************************************************************/
621 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
623 char *rparam = NULL;
624 char *rdata = NULL;
625 char *p;
626 unsigned int rdrcnt,rprcnt;
627 int res;
628 char param[WORDSIZE /* api number */
629 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
630 +1 /* no ret string */
631 +RAP_USERNAME_LEN /* user to del */
632 +WORDSIZE]; /* reserved word */
634 /* now send a SMBtrans command with api UserDel */
635 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
636 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
637 PUTWORD(p,0); /* reserved word MBZ on input */
639 if (cli_api(cli,
640 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
641 NULL, 0, 200, /* data, length, maxlen */
642 &rparam, &rprcnt, /* return params, length */
643 &rdata, &rdrcnt)) /* return data, length */
645 res = GETRES(rparam);
647 if (res == 0) {
648 /* nothing to do */
650 else if ((res == 5) || (res == 65)) {
651 DEBUG(1, ("Access Denied\n"));
653 else if (res == 2221) {
654 DEBUG (1, ("User does not exist\n"));
656 else {
657 DEBUG(4,("NetUserDelete res=%d\n", res));
659 } else {
660 res = -1;
661 DEBUG(4,("NetUserDelete failed\n"));
664 SAFE_FREE(rparam);
665 SAFE_FREE(rdata);
667 return res;
670 /****************************************************************************
671 call a NetUserAdd - add user to remote server
672 ****************************************************************************/
673 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
678 char *rparam = NULL;
679 char *rdata = NULL;
680 char *p;
681 unsigned int rdrcnt,rprcnt;
682 int res;
683 char param[WORDSIZE /* api number */
684 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
685 +sizeof(RAP_USER_INFO_L1) /* data string */
686 +WORDSIZE /* info level */
687 +WORDSIZE /* buffer length */
688 +WORDSIZE]; /* reserved */
690 char data[1024];
691 /* offset into data of free format strings. Will be updated */
692 /* by PUTSTRINGP macro and end up with total data length. */
693 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
694 + RAP_UPASSWD_LEN /* password */
695 + DWORDSIZE /* password age */
696 + WORDSIZE /* privilege */
697 + DWORDSIZE /* home dir ptr */
698 + DWORDSIZE /* comment ptr */
699 + WORDSIZE /* flags */
700 + DWORDSIZE; /* login script ptr*/
702 /* now send a SMBtrans command with api NetUserAdd */
703 p = make_header(param, RAP_WUserAdd2,
704 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
705 PUTWORD(p, 1); /* info level */
707 PUTWORD(p, 0); /* pwencrypt */
708 if(userinfo->passwrd)
709 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
710 else
711 PUTWORD(p, 0); /* password length */
713 p = data;
714 memset(data, '\0', soffset);
716 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
717 PUTBYTE(p, 0); /* pad byte 0 */
718 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
719 PUTDWORD(p, 0); /* pw age - n.a. on user add */
720 PUTWORD(p, userinfo->priv);
721 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
722 PUTSTRINGP(p, userinfo->comment, data, soffset);
723 PUTWORD(p, userinfo->userflags);
724 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
726 if (cli_api(cli,
727 param, sizeof(param), 1024, /* Param, length, maxlen */
728 data, soffset, sizeof(data), /* data, length, maxlen */
729 &rparam, &rprcnt, /* return params, length */
730 &rdata, &rdrcnt)) /* return data, length */
732 res = GETRES(rparam);
734 if (res == 0) {
735 /* nothing to do */
737 else if ((res == 5) || (res == 65)) {
738 DEBUG(1, ("Access Denied\n"));
740 else if (res == 2224) {
741 DEBUG (1, ("User already exists\n"));
743 else {
744 DEBUG(4,("NetUserAdd res=%d\n", res));
746 } else {
747 res = -1;
748 DEBUG(4,("NetUserAdd failed\n"));
751 SAFE_FREE(rparam);
752 SAFE_FREE(rdata);
754 return res;
757 /****************************************************************************
758 call a NetUserEnum - try and list users on a different host
759 ****************************************************************************/
760 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
762 char param[WORDSIZE /* api number */
763 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
764 +sizeof(RAP_USER_INFO_L1) /* return string */
765 +WORDSIZE /* info level */
766 +WORDSIZE]; /* buffer size */
767 char *p;
768 char *rparam = NULL;
769 char *rdata = NULL;
770 unsigned int rprcnt, rdrcnt;
771 int res = -1;
774 memset(param, '\0', sizeof(param));
775 p = make_header(param, RAP_WUserEnum,
776 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
777 PUTWORD(p,1); /* Info level 1 */
778 PUTWORD(p,0xFF00); /* Return buffer size */
780 /* BB Fix handling of large numbers of users to be returned */
781 if (cli_api(cli,
782 param, PTR_DIFF(p,param),8,
783 NULL, 0, CLI_BUFFER_SIZE,
784 &rparam, &rprcnt,
785 &rdata, &rdrcnt)) {
786 res = GETRES(rparam);
787 cli->rap_error = res;
788 if (cli->rap_error != 0) {
789 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
792 if (rdata) {
793 if (res == 0 || res == ERRmoredata) {
794 int i, converter, count;
795 char username[RAP_USERNAME_LEN];
796 char userpw[RAP_UPASSWD_LEN];
797 pstring comment, homedir, logonscript;
799 p = rparam + WORDSIZE; /* skip result */
800 GETWORD(p, converter);
801 GETWORD(p, count);
803 for (i=0,p=rdata;i<count;i++) {
804 GETSTRINGF(p, username, RAP_USERNAME_LEN);
805 p++; /* pad byte */
806 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
807 p += DWORDSIZE; /* skip password age */
808 p += WORDSIZE; /* skip priv: 0=guest, 1=user, 2=admin */
809 GETSTRINGP(p, homedir, rdata, converter);
810 GETSTRINGP(p, comment, rdata, converter);
811 p += WORDSIZE; /* skip flags */
812 GETSTRINGP(p, logonscript, rdata, converter);
814 fn(username, comment, homedir, logonscript, cli);
816 } else {
817 DEBUG(4,("NetUserEnum res=%d\n", res));
819 } else {
820 DEBUG(4,("NetUserEnum no data returned\n"));
823 SAFE_FREE(rparam);
824 SAFE_FREE(rdata);
826 return res;
829 int cli_RNetUserEnum0(struct cli_state *cli,
830 void (*fn)(const char *, void *),
831 void *state)
833 char param[WORDSIZE /* api number */
834 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
835 +sizeof(RAP_USER_INFO_L0) /* return string */
836 +WORDSIZE /* info level */
837 +WORDSIZE]; /* buffer size */
838 char *p;
839 char *rparam = NULL;
840 char *rdata = NULL;
841 unsigned int rprcnt, rdrcnt;
842 int res = -1;
845 memset(param, '\0', sizeof(param));
846 p = make_header(param, RAP_WUserEnum,
847 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
848 PUTWORD(p,0); /* Info level 1 */
849 PUTWORD(p,0xFF00); /* Return buffer size */
851 /* BB Fix handling of large numbers of users to be returned */
852 if (cli_api(cli,
853 param, PTR_DIFF(p,param),8,
854 NULL, 0, CLI_BUFFER_SIZE,
855 &rparam, &rprcnt,
856 &rdata, &rdrcnt)) {
857 res = GETRES(rparam);
858 cli->rap_error = res;
859 if (cli->rap_error != 0) {
860 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
863 if (rdata) {
864 if (res == 0 || res == ERRmoredata) {
865 int i, count;
866 char username[RAP_USERNAME_LEN];
868 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
869 GETWORD(p, count);
871 for (i=0,p=rdata;i<count;i++) {
872 GETSTRINGF(p, username, RAP_USERNAME_LEN);
873 fn(username, cli);
875 } else {
876 DEBUG(4,("NetUserEnum res=%d\n", res));
878 } else {
879 DEBUG(4,("NetUserEnum no data returned\n"));
882 SAFE_FREE(rparam);
883 SAFE_FREE(rdata);
885 return res;
888 /****************************************************************************
889 call a NetFileClose2 - close open file on another session to server
890 ****************************************************************************/
891 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
893 char *rparam = NULL;
894 char *rdata = NULL;
895 char *p;
896 unsigned int rdrcnt,rprcnt;
897 char param[WORDSIZE /* api number */
898 +sizeof(RAP_WFileClose2_REQ) /* req string */
899 +1 /* no ret string */
900 +DWORDSIZE]; /* file ID */
901 int res = -1;
903 /* now send a SMBtrans command with api RNetShareEnum */
904 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
905 PUTDWORD(p, file_id);
907 if (cli_api(cli,
908 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
909 NULL, 0, 200, /* data, length, maxlen */
910 &rparam, &rprcnt, /* return params, length */
911 &rdata, &rdrcnt)) /* return data, length */
913 res = GETRES(rparam);
915 if (res == 0) {
916 /* nothing to do */
917 } else if (res == 2314){
918 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
919 } else {
920 DEBUG(4,("NetFileClose2 res=%d\n", res));
922 } else {
923 res = -1;
924 DEBUG(4,("NetFileClose2 failed\n"));
927 SAFE_FREE(rparam);
928 SAFE_FREE(rdata);
930 return res;
933 /****************************************************************************
934 call a NetFileGetInfo - get information about server file opened from other
935 workstation
936 ****************************************************************************/
937 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
939 char *rparam = NULL;
940 char *rdata = NULL;
941 char *p;
942 unsigned int rdrcnt,rprcnt;
943 int res;
944 char param[WORDSIZE /* api number */
945 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
946 +sizeof(RAP_FILE_INFO_L3) /* return string */
947 +DWORDSIZE /* file ID */
948 +WORDSIZE /* info level */
949 +WORDSIZE]; /* buffer size */
951 /* now send a SMBtrans command with api RNetShareEnum */
952 p = make_header(param, RAP_WFileGetInfo2,
953 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
954 PUTDWORD(p, file_id);
955 PUTWORD(p, 3); /* info level */
956 PUTWORD(p, 0x1000); /* buffer size */
957 if (cli_api(cli,
958 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
959 NULL, 0, 0x1000, /* data, length, maxlen */
960 &rparam, &rprcnt, /* return params, length */
961 &rdata, &rdrcnt)) /* return data, length */
963 res = GETRES(rparam);
964 if (res == 0 || res == ERRmoredata) {
965 int converter,id, perms, locks;
966 pstring fpath, fuser;
968 p = rparam + WORDSIZE; /* skip result */
969 GETWORD(p, converter);
971 p = rdata;
972 GETDWORD(p, id);
973 GETWORD(p, perms);
974 GETWORD(p, locks);
975 GETSTRINGP(p, fpath, rdata, converter);
976 GETSTRINGP(p, fuser, rdata, converter);
978 fn(fpath, fuser, perms, locks, id);
979 } else {
980 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
982 } else {
983 res = -1;
984 DEBUG(4,("NetFileGetInfo2 failed\n"));
987 SAFE_FREE(rparam);
988 SAFE_FREE(rdata);
990 return res;
993 /****************************************************************************
994 * Call a NetFileEnum2 - list open files on an SMB server
996 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
997 * server listing the files open via the network (and their
998 * corresponding open instance ids)
1000 * Dependencies: none
1002 * Parameters:
1003 * cli - pointer to cli_state structure
1004 * user - if present, return only files opened by this remote user
1005 * base_path - if present, return only files opened below this
1006 * base path
1007 * fn - display function to invoke for each entry in the result
1010 * Returns:
1011 * True - success
1012 * False - failure
1014 ****************************************************************************/
1015 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1017 char *rparam = NULL;
1018 char *rdata = NULL;
1019 char *p;
1020 unsigned int rdrcnt,rprcnt;
1021 char param[WORDSIZE /* api number */
1022 +sizeof(RAP_WFileEnum2_REQ) /* req string */
1023 +sizeof(RAP_FILE_INFO_L3) /* return string */
1024 +256 /* base path (opt) */
1025 +RAP_USERNAME_LEN /* user name (opt) */
1026 +WORDSIZE /* info level */
1027 +WORDSIZE /* buffer size */
1028 +DWORDSIZE /* resume key ? */
1029 +DWORDSIZE]; /* resume key ? */
1030 int count = -1;
1032 /* now send a SMBtrans command with api RNetShareEnum */
1033 p = make_header(param, RAP_WFileEnum2,
1034 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1036 PUTSTRING(p, base_path, 256);
1037 PUTSTRING(p, user, RAP_USERNAME_LEN);
1038 PUTWORD(p, 3); /* info level */
1039 PUTWORD(p, 0xFF00); /* buffer size */
1040 PUTDWORD(p, 0); /* zero out the resume key */
1041 PUTDWORD(p, 0); /* or is this one the resume key? */
1043 if (cli_api(cli,
1044 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1045 NULL, 0, 0xFF00, /* data, length, maxlen */
1046 &rparam, &rprcnt, /* return params, length */
1047 &rdata, &rdrcnt)) /* return data, length */
1049 int res = GETRES(rparam);
1051 if (res == 0 || res == ERRmoredata) {
1052 int converter, i;
1054 p = rparam + WORDSIZE; /* skip result */
1055 GETWORD(p, converter);
1056 GETWORD(p, count);
1058 p = rdata;
1059 for (i=0; i<count; i++) {
1060 int id, perms, locks;
1061 pstring fpath, fuser;
1063 GETDWORD(p, id);
1064 GETWORD(p, perms);
1065 GETWORD(p, locks);
1066 GETSTRINGP(p, fpath, rdata, converter);
1067 GETSTRINGP(p, fuser, rdata, converter);
1069 fn(fpath, fuser, perms, locks, id);
1070 } /* BB fix ERRmoredata case to send resume request */
1071 } else {
1072 DEBUG(4,("NetFileEnum2 res=%d\n", res));
1074 } else {
1075 DEBUG(4,("NetFileEnum2 failed\n"));
1078 SAFE_FREE(rparam);
1079 SAFE_FREE(rdata);
1081 return count;
1084 /****************************************************************************
1085 call a NetShareAdd - share/export directory on remote server
1086 ****************************************************************************/
1087 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1089 char *rparam = NULL;
1090 char *rdata = NULL;
1091 char *p;
1092 unsigned int rdrcnt,rprcnt;
1093 int res;
1094 char param[WORDSIZE /* api number */
1095 +sizeof(RAP_WShareAdd_REQ) /* req string */
1096 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1097 +WORDSIZE /* info level */
1098 +WORDSIZE]; /* reserved word */
1099 char data[1024];
1100 /* offset to free format string section following fixed length data. */
1101 /* will be updated by PUTSTRINGP macro and will end up with total len */
1102 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
1103 + WORDSIZE /* share type */
1104 + DWORDSIZE /* comment pointer */
1105 + WORDSIZE /* permissions */
1106 + WORDSIZE /* max users */
1107 + WORDSIZE /* active users */
1108 + DWORDSIZE /* share path */
1109 + RAP_SPASSWD_LEN + 1; /* share password + pad */
1111 memset(param,'\0',sizeof(param));
1112 /* now send a SMBtrans command with api RNetShareAdd */
1113 p = make_header(param, RAP_WshareAdd,
1114 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1115 PUTWORD(p, 2); /* info level */
1116 PUTWORD(p, 0); /* reserved word 0 */
1118 p = data;
1119 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1120 PUTBYTE(p, 0); /* pad byte 0 */
1122 PUTWORD(p, sinfo->share_type);
1123 PUTSTRINGP(p, sinfo->comment, data, soffset);
1124 PUTWORD(p, sinfo->perms);
1125 PUTWORD(p, sinfo->maximum_users);
1126 PUTWORD(p, sinfo->active_users);
1127 PUTSTRINGP(p, sinfo->path, data, soffset);
1128 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1129 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1131 if (cli_api(cli,
1132 param, sizeof(param), 1024, /* Param, length, maxlen */
1133 data, soffset, sizeof(data), /* data, length, maxlen */
1134 &rparam, &rprcnt, /* return params, length */
1135 &rdata, &rdrcnt)) /* return data, length */
1137 res = rparam? SVAL(rparam,0) : -1;
1139 if (res == 0) {
1140 /* nothing to do */
1142 else {
1143 DEBUG(4,("NetShareAdd res=%d\n", res));
1145 } else {
1146 res = -1;
1147 DEBUG(4,("NetShareAdd failed\n"));
1150 SAFE_FREE(rparam);
1151 SAFE_FREE(rdata);
1153 return res;
1155 /****************************************************************************
1156 call a NetShareDelete - unshare exported directory on remote server
1157 ****************************************************************************/
1158 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1160 char *rparam = NULL;
1161 char *rdata = NULL;
1162 char *p;
1163 unsigned int rdrcnt,rprcnt;
1164 int res;
1165 char param[WORDSIZE /* api number */
1166 +sizeof(RAP_WShareDel_REQ) /* req string */
1167 +1 /* no ret string */
1168 +RAP_SHARENAME_LEN /* share to del */
1169 +WORDSIZE]; /* reserved word */
1172 /* now send a SMBtrans command with api RNetShareDelete */
1173 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1174 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1175 PUTWORD(p,0); /* reserved word MBZ on input */
1177 if (cli_api(cli,
1178 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1179 NULL, 0, 200, /* data, length, maxlen */
1180 &rparam, &rprcnt, /* return params, length */
1181 &rdata, &rdrcnt)) /* return data, length */
1183 res = GETRES(rparam);
1185 if (res == 0) {
1186 /* nothing to do */
1188 else {
1189 DEBUG(4,("NetShareDelete res=%d\n", res));
1191 } else {
1192 res = -1;
1193 DEBUG(4,("NetShareDelete failed\n"));
1196 SAFE_FREE(rparam);
1197 SAFE_FREE(rdata);
1199 return res;
1201 /*************************************************************************
1203 * Function Name: cli_get_pdc_name
1205 * PURPOSE: Remotes a NetServerEnum API call to the current server
1206 * requesting the name of a server matching the server
1207 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1209 * Dependencies: none
1211 * Parameters:
1212 * cli - pointer to cli_state structure
1213 * workgroup - pointer to string containing name of domain
1214 * pdc_name - pointer to string that will contain PDC name
1215 * on successful return
1217 * Returns:
1218 * True - success
1219 * False - failure
1221 ************************************************************************/
1222 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1224 char *rparam = NULL;
1225 char *rdata = NULL;
1226 unsigned int rdrcnt,rprcnt;
1227 char *p;
1228 char param[WORDSIZE /* api number */
1229 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1230 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1231 +WORDSIZE /* info level */
1232 +WORDSIZE /* buffer size */
1233 +DWORDSIZE /* server type */
1234 +RAP_MACHNAME_LEN]; /* workgroup */
1235 int count = -1;
1237 *pdc_name = '\0';
1239 /* send a SMBtrans command with api NetServerEnum */
1240 p = make_header(param, RAP_NetServerEnum2,
1241 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1242 PUTWORD(p, 1); /* info level */
1243 PUTWORD(p, CLI_BUFFER_SIZE);
1244 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1245 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1247 if (cli_api(cli,
1248 param, PTR_DIFF(p,param), 8, /* params, length, max */
1249 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1250 &rparam, &rprcnt, /* return params, return size */
1251 &rdata, &rdrcnt /* return data, return size */
1252 )) {
1253 cli->rap_error = GETRES(rparam);
1256 * We only really care to copy a name if the
1257 * API succeeded and we got back a name.
1259 if (cli->rap_error == 0) {
1260 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1261 GETWORD(p, count);
1262 p = rdata;
1264 if (count > 0)
1265 GETSTRING(p, pdc_name);
1267 else {
1268 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1269 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1273 SAFE_FREE(rparam);
1274 SAFE_FREE(rdata);
1276 return(count > 0);
1280 /*************************************************************************
1282 * Function Name: cli_get_server_domain
1284 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1285 * requesting wksta_info_10 level information to determine
1286 * the domain the server belongs to. On success, this
1287 * routine sets the server_domain field in the cli_state structure
1288 * to the server's domain name.
1290 * Dependencies: none
1292 * Parameters:
1293 * cli - pointer to cli_state structure
1295 * Returns:
1296 * True - success
1297 * False - failure
1299 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1301 ************************************************************************/
1302 BOOL cli_get_server_domain(struct cli_state *cli)
1304 char *rparam = NULL;
1305 char *rdata = NULL;
1306 unsigned int rdrcnt,rprcnt;
1307 char *p;
1308 char param[WORDSIZE /* api number */
1309 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1310 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1311 +WORDSIZE /* info level */
1312 +WORDSIZE]; /* buffer size */
1313 int res = -1;
1315 /* send a SMBtrans command with api NetWkstaGetInfo */
1316 p = make_header(param, RAP_WWkstaGetInfo,
1317 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1318 PUTWORD(p, 10); /* info level */
1319 PUTWORD(p, CLI_BUFFER_SIZE);
1321 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1322 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1323 &rparam, &rprcnt, /* return params, return size */
1324 &rdata, &rdrcnt)) { /* return data, return size */
1325 res = GETRES(rparam);
1326 p = rdata;
1328 if (res == 0) {
1329 int converter;
1331 p = rparam + WORDSIZE;
1332 GETWORD(p, converter);
1334 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1335 GETSTRINGP(p, cli->server_domain, rdata, converter);
1339 SAFE_FREE(rparam);
1340 SAFE_FREE(rdata);
1342 return(res == 0);
1346 /*************************************************************************
1348 * Function Name: cli_get_server_type
1350 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1351 * requesting server_info_1 level information to retrieve
1352 * the server type.
1354 * Dependencies: none
1356 * Parameters:
1357 * cli - pointer to cli_state structure
1358 * pstype - pointer to uint32 to contain returned server type
1360 * Returns:
1361 * True - success
1362 * False - failure
1364 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1366 ************************************************************************/
1367 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1369 char *rparam = NULL;
1370 char *rdata = NULL;
1371 unsigned int rdrcnt,rprcnt;
1372 char *p;
1373 char param[WORDSIZE /* api number */
1374 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1375 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1376 +WORDSIZE /* info level */
1377 +WORDSIZE]; /* buffer size */
1378 int res = -1;
1380 /* send a SMBtrans command with api NetServerGetInfo */
1381 p = make_header(param, RAP_WserverGetInfo,
1382 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1383 PUTWORD(p, 1); /* info level */
1384 PUTWORD(p, CLI_BUFFER_SIZE);
1386 if (cli_api(cli,
1387 param, PTR_DIFF(p,param), 8, /* params, length, max */
1388 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1389 &rparam, &rprcnt, /* return params, return size */
1390 &rdata, &rdrcnt /* return data, return size */
1391 )) {
1393 res = GETRES(rparam);
1395 if (res == 0 || res == ERRmoredata) {
1396 p = rdata;
1397 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1401 SAFE_FREE(rparam);
1402 SAFE_FREE(rdata);
1404 return(res == 0 || res == ERRmoredata);
1408 /*************************************************************************
1410 * Function Name: cli_ns_check_server_type
1412 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1413 * requesting server_info_0 level information of machines
1414 * matching the given server type. If the returned server
1415 * list contains the machine name contained in cli->desthost
1416 * then we conclude the server type checks out. This routine
1417 * is useful to retrieve list of server's of a certain
1418 * type when all you have is a null session connection and
1419 * can't remote API calls such as NetWkstaGetInfo or
1420 * NetServerGetInfo.
1422 * Dependencies: none
1424 * Parameters:
1425 * cli - pointer to cli_state structure
1426 * workgroup - pointer to string containing domain
1427 * stype - server type
1429 * Returns:
1430 * True - success
1431 * False - failure
1433 ************************************************************************/
1434 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1436 char *rparam = NULL;
1437 char *rdata = NULL;
1438 unsigned int rdrcnt,rprcnt;
1439 char *p;
1440 char param[WORDSIZE /* api number */
1441 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1442 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1443 +WORDSIZE /* info level */
1444 +WORDSIZE /* buffer size */
1445 +DWORDSIZE /* server type */
1446 +RAP_MACHNAME_LEN]; /* workgroup */
1447 BOOL found_server = False;
1448 int res = -1;
1450 /* send a SMBtrans command with api NetServerEnum */
1451 p = make_header(param, RAP_NetServerEnum2,
1452 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1453 PUTWORD(p, 0); /* info level 0 */
1454 PUTWORD(p, CLI_BUFFER_SIZE);
1455 PUTDWORD(p, stype);
1456 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1458 if (cli_api(cli,
1459 param, PTR_DIFF(p,param), 8, /* params, length, max */
1460 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1461 &rparam, &rprcnt, /* return params, return size */
1462 &rdata, &rdrcnt /* return data, return size */
1463 )) {
1465 res = GETRES(rparam);
1466 cli->rap_error = res;
1468 if (res == 0 || res == ERRmoredata) {
1469 int i, count;
1471 p = rparam + WORDSIZE + WORDSIZE;
1472 GETWORD(p, count);
1474 p = rdata;
1475 for (i = 0;i < count;i++, p += 16) {
1476 char ret_server[RAP_MACHNAME_LEN];
1478 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1479 if (strequal(ret_server, cli->desthost)) {
1480 found_server = True;
1481 break;
1485 else {
1486 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1487 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1491 SAFE_FREE(rparam);
1492 SAFE_FREE(rdata);
1494 return found_server;
1498 /****************************************************************************
1499 perform a NetWkstaUserLogoff
1500 ****************************************************************************/
1501 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1503 char *rparam = NULL;
1504 char *rdata = NULL;
1505 char *p;
1506 unsigned int rdrcnt,rprcnt;
1507 char param[WORDSIZE /* api number */
1508 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1509 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1510 +RAP_USERNAME_LEN+1 /* user name+pad */
1511 +RAP_MACHNAME_LEN /* wksta name */
1512 +WORDSIZE /* buffer size */
1513 +WORDSIZE]; /* buffer size? */
1514 fstring upperbuf;
1516 memset(param, 0, sizeof(param));
1518 /* send a SMBtrans command with api NetWkstaUserLogoff */
1519 p = make_header(param, RAP_WWkstaUserLogoff,
1520 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1521 PUTDWORD(p, 0); /* Null pointer */
1522 PUTDWORD(p, 0); /* Null pointer */
1523 fstrcpy(upperbuf, user);
1524 strupper_m(upperbuf);
1525 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1526 p++; /* strange format, but ok */
1527 fstrcpy(upperbuf, workstation);
1528 strupper_m(upperbuf);
1529 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1530 PUTWORD(p, CLI_BUFFER_SIZE);
1531 PUTWORD(p, CLI_BUFFER_SIZE);
1533 if (cli_api(cli,
1534 param, PTR_DIFF(p,param),1024, /* param, length, max */
1535 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1536 &rparam, &rprcnt, /* return params, return size */
1537 &rdata, &rdrcnt /* return data, return size */
1538 )) {
1539 cli->rap_error = GETRES(rparam);
1541 if (cli->rap_error != 0) {
1542 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1546 SAFE_FREE(rparam);
1547 SAFE_FREE(rdata);
1548 return (cli->rap_error == 0);
1551 int cli_NetPrintQEnum(struct cli_state *cli,
1552 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1553 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1555 char param[WORDSIZE /* api number */
1556 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1557 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1558 +WORDSIZE /* info level */
1559 +WORDSIZE /* buffer size */
1560 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1561 char *p;
1562 char *rparam = NULL;
1563 char *rdata = NULL;
1564 unsigned int rprcnt, rdrcnt;
1565 int res = -1;
1568 memset(param, '\0',sizeof(param));
1569 p = make_header(param, RAP_WPrintQEnum,
1570 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1571 PUTWORD(p,2); /* Info level 2 */
1572 PUTWORD(p,0xFFE0); /* Return buffer size */
1573 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1575 if (cli_api(cli,
1576 param, PTR_DIFF(p,param),1024,
1577 NULL, 0, CLI_BUFFER_SIZE,
1578 &rparam, &rprcnt,
1579 &rdata, &rdrcnt)) {
1580 res = GETRES(rparam);
1581 cli->rap_error = res;
1582 if (res != 0) {
1583 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1587 if (rdata) {
1588 if (res == 0 || res == ERRmoredata) {
1589 int i, converter, count;
1591 p = rparam + WORDSIZE;
1592 GETWORD(p, converter);
1593 GETWORD(p, count);
1595 p = rdata;
1596 for (i=0;i<count;i++) {
1597 pstring qname, sep_file, print_proc, dest, parms, comment;
1598 uint16 jobcount, priority, start_time, until_time, status;
1600 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1601 p++; /* pad */
1602 GETWORD(p, priority);
1603 GETWORD(p, start_time);
1604 GETWORD(p, until_time);
1605 GETSTRINGP(p, sep_file, rdata, converter);
1606 GETSTRINGP(p, print_proc, rdata, converter);
1607 GETSTRINGP(p, dest, rdata, converter);
1608 GETSTRINGP(p, parms, rdata, converter);
1609 GETSTRINGP(p, parms, comment, converter);
1610 GETWORD(p, status);
1611 GETWORD(p, jobcount);
1613 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1614 dest, parms, comment, status, jobcount);
1616 if (jobcount) {
1617 int j;
1618 for (j=0;j<jobcount;j++) {
1619 uint16 jid, pos, fsstatus;
1620 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1621 unsigned int submitted, jsize;
1623 GETWORD(p, jid);
1624 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1625 p++; /* pad byte */
1626 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1627 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1628 GETSTRINGP(p, jparms, rdata, converter);
1629 GETWORD(p, pos);
1630 GETWORD(p, fsstatus);
1631 GETSTRINGP(p, jstatus, rdata, converter);
1632 GETDWORD(p, submitted);
1633 GETDWORD(p, jsize);
1634 GETSTRINGP(p, jcomment, rdata, converter);
1636 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1637 jstatus, submitted, jsize, jcomment);
1641 } else {
1642 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1644 } else {
1645 DEBUG(4,("NetPrintQEnum no data returned\n"));
1648 SAFE_FREE(rparam);
1649 SAFE_FREE(rdata);
1651 return res;
1654 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1655 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1656 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1658 char param[WORDSIZE /* api number */
1659 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1660 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1661 +RAP_SHARENAME_LEN /* printer name */
1662 +WORDSIZE /* info level */
1663 +WORDSIZE /* buffer size */
1664 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1665 char *p;
1666 char *rparam = NULL;
1667 char *rdata = NULL;
1668 unsigned int rprcnt, rdrcnt;
1669 int res = -1;
1672 memset(param, '\0',sizeof(param));
1673 p = make_header(param, RAP_WPrintQGetInfo,
1674 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1675 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1676 PUTWORD(p, 2); /* Info level 2 */
1677 PUTWORD(p,0xFFE0); /* Return buffer size */
1678 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1680 if (cli_api(cli,
1681 param, PTR_DIFF(p,param),1024,
1682 NULL, 0, CLI_BUFFER_SIZE,
1683 &rparam, &rprcnt,
1684 &rdata, &rdrcnt)) {
1685 res = GETRES(rparam);
1686 cli->rap_error = res;
1687 if (res != 0) {
1688 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1692 if (rdata) {
1693 if (res == 0 || res == ERRmoredata) {
1694 int rsize, converter;
1695 pstring qname, sep_file, print_proc, dest, parms, comment;
1696 uint16 jobcount, priority, start_time, until_time, status;
1698 p = rparam + WORDSIZE;
1699 GETWORD(p, converter);
1700 GETWORD(p, rsize);
1702 p = rdata;
1703 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1704 p++; /* pad */
1705 GETWORD(p, priority);
1706 GETWORD(p, start_time);
1707 GETWORD(p, until_time);
1708 GETSTRINGP(p, sep_file, rdata, converter);
1709 GETSTRINGP(p, print_proc, rdata, converter);
1710 GETSTRINGP(p, dest, rdata, converter);
1711 GETSTRINGP(p, parms, rdata, converter);
1712 GETSTRINGP(p, comment, rdata, converter);
1713 GETWORD(p, status);
1714 GETWORD(p, jobcount);
1715 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1716 dest, parms, comment, status, jobcount);
1717 if (jobcount) {
1718 int j;
1719 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1720 uint16 jid, pos, fsstatus;
1721 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1722 unsigned int submitted, jsize;
1724 GETWORD(p, jid);
1725 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1726 p++; /* pad byte */
1727 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1728 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1729 GETSTRINGP(p, jparms, rdata, converter);
1730 GETWORD(p, pos);
1731 GETWORD(p, fsstatus);
1732 GETSTRINGP(p, jstatus, rdata, converter);
1733 GETDWORD(p, submitted);
1734 GETDWORD(p, jsize);
1735 GETSTRINGP(p, jcomment, rdata, converter);
1737 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1738 jstatus, submitted, jsize, jcomment);
1741 } else {
1742 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1744 } else {
1745 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1748 SAFE_FREE(rparam);
1749 SAFE_FREE(rdata);
1751 return res;
1754 /****************************************************************************
1755 call a NetServiceEnum - list running services on a different host
1756 ****************************************************************************/
1757 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1759 char param[WORDSIZE /* api number */
1760 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1761 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1762 +WORDSIZE /* info level */
1763 +WORDSIZE]; /* buffer size */
1764 char *p;
1765 char *rparam = NULL;
1766 char *rdata = NULL;
1767 unsigned int rprcnt, rdrcnt;
1768 int res = -1;
1771 memset(param, '\0', sizeof(param));
1772 p = make_header(param, RAP_WServiceEnum,
1773 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1774 PUTWORD(p,2); /* Info level 2 */
1775 PUTWORD(p,0xFFE0); /* Return buffer size */
1777 if (cli_api(cli,
1778 param, PTR_DIFF(p,param),8,
1779 NULL, 0, 0xFFE0 /* data area size */,
1780 &rparam, &rprcnt,
1781 &rdata, &rdrcnt)) {
1782 res = GETRES(rparam);
1783 cli->rap_error = res;
1784 if(cli->rap_error == 234)
1785 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1786 else if (cli->rap_error != 0) {
1787 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1791 if (rdata) {
1792 if (res == 0 || res == ERRmoredata) {
1793 int i, count;
1795 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1796 GETWORD(p, count);
1798 for (i=0,p=rdata;i<count;i++) {
1799 pstring comment;
1800 char servicename[RAP_SRVCNAME_LEN];
1802 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1803 p+=8; /* pass status words */
1804 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1806 fn(servicename, comment, cli); /* BB add status too */
1808 } else {
1809 DEBUG(4,("NetServiceEnum res=%d\n", res));
1811 } else {
1812 DEBUG(4,("NetServiceEnum no data returned\n"));
1815 SAFE_FREE(rparam);
1816 SAFE_FREE(rdata);
1818 return res;
1822 /****************************************************************************
1823 call a NetSessionEnum - list workstations with sessions to an SMB server
1824 ****************************************************************************/
1825 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1827 char param[WORDSIZE /* api number */
1828 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1829 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1830 +WORDSIZE /* info level */
1831 +WORDSIZE]; /* buffer size */
1832 char *p;
1833 char *rparam = NULL;
1834 char *rdata = NULL;
1835 unsigned int rprcnt, rdrcnt;
1836 int res = -1;
1838 memset(param, '\0', sizeof(param));
1839 p = make_header(param, RAP_WsessionEnum,
1840 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1841 PUTWORD(p,2); /* Info level 2 */
1842 PUTWORD(p,0xFF); /* Return buffer size */
1844 if (cli_api(cli,
1845 param, PTR_DIFF(p,param),8,
1846 NULL, 0, CLI_BUFFER_SIZE,
1847 &rparam, &rprcnt,
1848 &rdata, &rdrcnt)) {
1849 res = GETRES(rparam);
1850 cli->rap_error = res;
1851 if (res != 0) {
1852 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1856 if (rdata) {
1857 if (res == 0 || res == ERRmoredata) {
1858 int i, converter, count;
1860 p = rparam + WORDSIZE;
1861 GETWORD(p, converter);
1862 GETWORD(p, count);
1864 for (i=0,p=rdata;i<count;i++) {
1865 pstring wsname, username, clitype_name;
1866 uint16 num_conns, num_opens, num_users;
1867 unsigned int sess_time, idle_time, user_flags;
1869 GETSTRINGP(p, wsname, rdata, converter);
1870 GETSTRINGP(p, username, rdata, converter);
1871 GETWORD(p, num_conns);
1872 GETWORD(p, num_opens);
1873 GETWORD(p, num_users);
1874 GETDWORD(p, sess_time);
1875 GETDWORD(p, idle_time);
1876 GETDWORD(p, user_flags);
1877 GETSTRINGP(p, clitype_name, rdata, converter);
1879 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1880 idle_time, user_flags, clitype_name);
1883 } else {
1884 DEBUG(4,("NetSessionEnum res=%d\n", res));
1886 } else {
1887 DEBUG(4,("NetSesssionEnum no data returned\n"));
1890 SAFE_FREE(rparam);
1891 SAFE_FREE(rdata);
1893 return res;
1896 /****************************************************************************
1897 Call a NetSessionGetInfo - get information about other session to an SMB server.
1898 ****************************************************************************/
1900 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1902 char param[WORDSIZE /* api number */
1903 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1904 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1905 +RAP_MACHNAME_LEN /* wksta name */
1906 +WORDSIZE /* info level */
1907 +WORDSIZE]; /* buffer size */
1908 char *p;
1909 char *rparam = NULL;
1910 char *rdata = NULL;
1911 unsigned int rprcnt, rdrcnt;
1912 int res = -1;
1915 memset(param, '\0', sizeof(param));
1916 p = make_header(param, RAP_WsessionGetInfo,
1917 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1918 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1919 PUTWORD(p,2); /* Info level 2 */
1920 PUTWORD(p,0xFF); /* Return buffer size */
1922 if (cli_api(cli,
1923 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1924 NULL, 0, CLI_BUFFER_SIZE,
1925 &rparam, &rprcnt,
1926 &rdata, &rdrcnt)) {
1927 cli->rap_error = SVAL(rparam,0);
1928 if (cli->rap_error != 0) {
1929 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1933 if (rdata) {
1934 res = GETRES(rparam);
1936 if (res == 0 || res == ERRmoredata) {
1937 int converter;
1938 pstring wsname, username, clitype_name;
1939 uint16 num_conns, num_opens, num_users;
1940 unsigned int sess_time, idle_time, user_flags;
1942 p = rparam + WORDSIZE;
1943 GETWORD(p, converter);
1944 p += WORDSIZE; /* skip rsize */
1946 p = rdata;
1947 GETSTRINGP(p, wsname, rdata, converter);
1948 GETSTRINGP(p, username, rdata, converter);
1949 GETWORD(p, num_conns);
1950 GETWORD(p, num_opens);
1951 GETWORD(p, num_users);
1952 GETDWORD(p, sess_time);
1953 GETDWORD(p, idle_time);
1954 GETDWORD(p, user_flags);
1955 GETSTRINGP(p, clitype_name, rdata, converter);
1957 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1958 idle_time, user_flags, clitype_name);
1959 } else {
1960 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1962 } else {
1963 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1966 SAFE_FREE(rparam);
1967 SAFE_FREE(rdata);
1969 return res;
1972 /****************************************************************************
1973 call a NetSessionDel - close a session to an SMB server
1974 ****************************************************************************/
1975 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1977 char param[WORDSIZE /* api number */
1978 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1979 +1 /* no return string */
1980 +RAP_MACHNAME_LEN /* workstation name */
1981 +WORDSIZE]; /* reserved (0) */
1982 char *p;
1983 char *rparam = NULL;
1984 char *rdata = NULL;
1985 unsigned int rprcnt, rdrcnt;
1986 int res;
1988 memset(param, '\0', sizeof(param));
1989 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1990 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1991 PUTWORD(p,0); /* reserved word of 0 */
1992 if (cli_api(cli,
1993 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1994 NULL, 0, 200, /* data, length, maxlen */
1995 &rparam, &rprcnt, /* return params, length */
1996 &rdata, &rdrcnt)) /* return data, length */
1998 res = GETRES(rparam);
1999 cli->rap_error = res;
2001 if (res == 0) {
2002 /* nothing to do */
2004 else {
2005 DEBUG(4,("NetFileClose2 res=%d\n", res));
2007 } else {
2008 res = -1;
2009 DEBUG(4,("NetFileClose2 failed\n"));
2012 SAFE_FREE(rparam);
2013 SAFE_FREE(rdata);
2015 return res;
2019 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))
2021 char param[WORDSIZE /* api number */
2022 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
2023 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
2024 +RAP_MACHNAME_LEN /* wksta name */
2025 +WORDSIZE /* info level */
2026 +WORDSIZE]; /* buffer size */
2027 char *p;
2028 char *rparam = NULL;
2029 char *rdata = NULL;
2030 unsigned int rprcnt, rdrcnt;
2031 int res = -1;
2033 memset(param, '\0', sizeof(param));
2034 p = make_header(param, RAP_WconnectionEnum,
2035 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2036 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2037 PUTWORD(p,1); /* Info level 1 */
2038 PUTWORD(p,0xFFE0); /* Return buffer size */
2040 if (cli_api(cli,
2041 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2042 NULL, 0, CLI_BUFFER_SIZE,
2043 &rparam, &rprcnt,
2044 &rdata, &rdrcnt)) {
2045 res = GETRES(rparam);
2046 cli->rap_error = res;
2047 if (res != 0) {
2048 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2051 if (rdata) {
2052 if (res == 0 || res == ERRmoredata) {
2053 int i, converter, count;
2055 p = rparam + WORDSIZE;
2056 GETWORD(p, converter);
2057 GETWORD(p, count);
2059 for (i=0,p=rdata;i<count;i++) {
2060 pstring netname, username;
2061 uint16 conn_id, conn_type, num_opens, num_users;
2062 unsigned int conn_time;
2064 GETWORD(p,conn_id);
2065 GETWORD(p,conn_type);
2066 GETWORD(p,num_opens);
2067 GETWORD(p,num_users);
2068 GETDWORD(p,conn_time);
2069 GETSTRINGP(p, username, rdata, converter);
2070 GETSTRINGP(p, netname, rdata, converter);
2072 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2073 username, netname);
2076 } else {
2077 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2079 } else {
2080 DEBUG(4,("NetConnectionEnum no data returned\n"));
2082 SAFE_FREE(rdata);
2083 SAFE_FREE(rparam);
2084 return res;