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 /*****************************************************/
25 /* Additional RAP functionality */
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 */
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. */
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. */
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 */
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 */
61 /*****************************************************/
63 /*****************************************************/
65 /* cifsrap.c already includes support for: */
67 /* WshareEnum ( API number 0, level 1) */
68 /* NetServerEnum2 (API num 104, level 1) */
69 /* WWkstaUserLogon (132) */
70 /* SamOEMchgPasswordUser2_P (214) */
72 /* cifsprint.c already includes support for: */
74 /* WPrintJobEnum (API num 76, level 2) */
75 /* WPrintJobDel (API num 81) */
77 /*****************************************************/
86 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
87 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
88 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
89 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
90 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
91 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
92 #define GETRES(p) p ? SVAL(p,0) : -1
93 /* put string s at p with max len n and increment p past string */
94 #define PUTSTRING(p,s,n) do {\
95 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
96 p = skip_string(p,1);\
98 /* put string s and p, using fixed len l, and increment p by l */
99 #define PUTSTRINGF(p,s,l) do {\
100 push_ascii(p,s?s:"",l,STR_TERMINATE);\
103 /* put string pointer at p, supplying offset o from rdata r, store */
104 /* dword offset at p, increment p by 4 and o by length of s. This */
105 /* means on the first call, you must calc the offset yourself! */
106 #define PUTSTRINGP(p,s,r,o) do {\
108 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
111 } else PUTDWORD(p,0);\
113 /* get asciiz string s from p, increment p past string */
114 #define GETSTRING(p,s) do {\
115 pull_ascii_pstring(s,p);\
116 p = skip_string(p,1);\
118 /* get fixed length l string s from p, increment p by l */
119 #define GETSTRINGF(p,s,l) do {\
120 pull_ascii_pstring(s,p);\
123 /* get string s from offset (obtained at p) from rdata r - converter c */
124 #define GETSTRINGP(p,s,r,c) do {\
127 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
128 pull_ascii_pstring(s, off?(r+off-c):"");\
131 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
133 PUTWORD(param,apinum);
135 PUTSTRING(param,reqfmt,0);
140 PUTSTRING(param,datafmt,0);
148 /****************************************************************************
149 call a NetGroupDelete - delete user group from remote server
150 ****************************************************************************/
151 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
156 unsigned int rdrcnt,rprcnt;
158 char param[WORDSIZE /* api number */
159 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
160 +1 /* no ret string */
161 +RAP_GROUPNAME_LEN /* group to del */
162 +WORDSIZE]; /* reserved word */
164 /* now send a SMBtrans command with api GroupDel */
165 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
166 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
167 PUTWORD(p,0); /* reserved word MBZ on input */
170 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
171 NULL, 0, 200, /* data, length, maxlen */
172 &rparam, &rprcnt, /* return params, length */
173 &rdata, &rdrcnt)) /* return data, length */
175 res = GETRES(rparam);
180 else if ((res == 5) || (res == 65)) {
181 DEBUG(1, ("Access Denied\n"));
183 else if (res == 2220) {
184 DEBUG (1, ("Group does not exist\n"));
187 DEBUG(4,("NetGroupDelete res=%d\n", res));
191 DEBUG(4,("NetGroupDelete failed\n"));
200 /****************************************************************************
201 call a NetGroupAdd - add user group to remote server
202 ****************************************************************************/
203 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
208 unsigned int rdrcnt,rprcnt;
210 char param[WORDSIZE /* api number */
211 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
212 +sizeof(RAP_GROUP_INFO_L1) /* return string */
213 +WORDSIZE /* info level */
214 +WORDSIZE]; /* reserved word */
218 /* offset into data of free format strings. Will be updated */
219 /* by PUTSTRINGP macro and end up with total data length. */
220 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
222 /* now send a SMBtrans command with api WGroupAdd */
224 p = make_header(param, RAP_WGroupAdd,
225 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
226 PUTWORD(p, 1); /* info level */
227 PUTWORD(p, 0); /* reserved word 0 */
230 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
231 PUTBYTE(p, 0); /* pad byte 0 */
232 PUTSTRINGP(p, grinfo->comment, data, soffset);
235 param, sizeof(param), 1024, /* Param, length, maxlen */
236 data, soffset, sizeof(data), /* data, length, maxlen */
237 &rparam, &rprcnt, /* return params, length */
238 &rdata, &rdrcnt)) /* return data, length */
240 res = GETRES(rparam);
244 } else if ((res == 5) || (res == 65)) {
245 DEBUG(1, ("Access Denied\n"));
247 else if (res == 2223) {
248 DEBUG (1, ("Group already exists\n"));
251 DEBUG(4,("NetGroupAdd res=%d\n", res));
255 DEBUG(4,("NetGroupAdd failed\n"));
264 /****************************************************************************
265 call a NetGroupEnum - try and list user groups on a different host
266 ****************************************************************************/
267 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
269 char param[WORDSIZE /* api number */
270 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
271 +sizeof(RAP_GROUP_INFO_L1) /* return string */
272 +WORDSIZE /* info level */
273 +WORDSIZE]; /* buffer size */
277 unsigned int rprcnt, rdrcnt;
281 memset(param, '\0', sizeof(param));
282 p = make_header(param, RAP_WGroupEnum,
283 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
284 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
285 PUTWORD(p,0xFFE0); /* Return buffer size */
288 param, PTR_DIFF(p,param),8,
289 NULL, 0, 0xFFE0 /* data area size */,
292 res = GETRES(rparam);
293 cli->rap_error = res;
294 if(cli->rap_error == 234)
295 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
296 else if (cli->rap_error != 0) {
297 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
302 if (res == 0 || res == ERRmoredata) {
303 int i, converter, count;
305 p = rparam + WORDSIZE; /* skip result */
306 GETWORD(p, converter);
309 for (i=0,p=rdata;i<count;i++) {
311 char groupname[RAP_GROUPNAME_LEN];
313 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
315 GETSTRINGP(p, comment, rdata, converter);
317 fn(groupname, comment, cli);
320 DEBUG(4,("NetGroupEnum res=%d\n", res));
323 DEBUG(4,("NetGroupEnum no data returned\n"));
332 int cli_RNetGroupEnum0(struct cli_state *cli,
333 void (*fn)(const char *, void *),
336 char param[WORDSIZE /* api number */
337 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
338 +sizeof(RAP_GROUP_INFO_L0) /* return string */
339 +WORDSIZE /* info level */
340 +WORDSIZE]; /* buffer size */
344 unsigned int rprcnt, rdrcnt;
348 memset(param, '\0', sizeof(param));
349 p = make_header(param, RAP_WGroupEnum,
350 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
351 PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
352 is the resume count, at least
353 that's what smbd believes... */
354 PUTWORD(p,0xFFE0); /* Return buffer size */
357 param, PTR_DIFF(p,param),8,
358 NULL, 0, 0xFFE0 /* data area size */,
361 res = GETRES(rparam);
362 cli->rap_error = res;
363 if(cli->rap_error == 234)
364 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
365 else if (cli->rap_error != 0) {
366 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
371 if (res == 0 || res == ERRmoredata) {
374 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
377 for (i=0,p=rdata;i<count;i++) {
378 char groupname[RAP_GROUPNAME_LEN];
379 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
383 DEBUG(4,("NetGroupEnum res=%d\n", res));
386 DEBUG(4,("NetGroupEnum no data returned\n"));
395 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
400 unsigned int rdrcnt,rprcnt;
402 char param[WORDSIZE /* api number */
403 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
404 +1 /* no ret string */
405 +RAP_GROUPNAME_LEN /* group name */
406 +RAP_USERNAME_LEN]; /* user to del */
408 /* now send a SMBtrans command with api GroupMemberAdd */
409 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
410 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
411 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
414 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
415 NULL, 0, 200, /* data, length, maxlen */
416 &rparam, &rprcnt, /* return params, length */
417 &rdata, &rdrcnt)) /* return data, length */
419 res = GETRES(rparam);
426 DEBUG(1, ("Access Denied\n"));
429 DEBUG(1, ("Not supported by server\n"));
432 DEBUG(1, ("Group does not exist\n"));
435 DEBUG(1, ("User does not exist\n"));
438 DEBUG(1, ("User is not in group\n"));
441 DEBUG(4,("NetGroupDelUser res=%d\n", res));
445 DEBUG(4,("NetGroupDelUser failed\n"));
454 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
459 unsigned int rdrcnt,rprcnt;
461 char param[WORDSIZE /* api number */
462 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
463 +1 /* no ret string */
464 +RAP_GROUPNAME_LEN /* group name */
465 +RAP_USERNAME_LEN]; /* user to add */
467 /* now send a SMBtrans command with api GroupMemberAdd */
468 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
469 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
470 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
473 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
474 NULL, 0, 200, /* data, length, maxlen */
475 &rparam, &rprcnt, /* return params, length */
476 &rdata, &rdrcnt)) /* return data, length */
478 res = GETRES(rparam);
485 DEBUG(1, ("Access Denied\n"));
488 DEBUG(1, ("Not supported by server\n"));
491 DEBUG(1, ("Group does not exist\n"));
494 DEBUG(1, ("User does not exist\n"));
497 DEBUG(4,("NetGroupAddUser res=%d\n", res));
501 DEBUG(4,("NetGroupAddUser failed\n"));
511 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
516 unsigned int rdrcnt,rprcnt;
518 char param[WORDSIZE /* api number */
519 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
520 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
521 +RAP_GROUPNAME_LEN /* group name */
522 +WORDSIZE /* info level */
523 +WORDSIZE]; /* buffer size */
525 /* now send a SMBtrans command with api GroupGetUsers */
526 p = make_header(param, RAP_WGroupGetUsers,
527 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
528 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
529 PUTWORD(p,0); /* info level 0 */
530 PUTWORD(p,0xFFE0); /* return buffer size */
533 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
534 NULL, 0, CLI_BUFFER_SIZE,
537 res = GETRES(rparam);
538 cli->rap_error = res;
540 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
544 if (res == 0 || res == ERRmoredata) {
547 p = rparam + WORDSIZE + WORDSIZE;
550 for (i=0,p=rdata; i<count; i++) {
551 GETSTRINGF(p, username, RAP_USERNAME_LEN);
555 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
558 DEBUG(4,("NetGroupGetUsers no data returned\n"));
565 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
570 unsigned int rdrcnt,rprcnt;
572 char param[WORDSIZE /* api number */
573 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
574 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
575 +RAP_USERNAME_LEN /* user name */
576 +WORDSIZE /* info level */
577 +WORDSIZE]; /* buffer size */
579 /* now send a SMBtrans command with api GroupGetUsers */
580 p = make_header(param, RAP_WUserGetGroups,
581 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
582 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
583 PUTWORD(p,0); /* info level 0 */
584 PUTWORD(p,0xFFE0); /* return buffer size */
587 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
588 NULL, 0, CLI_BUFFER_SIZE,
591 res = GETRES(rparam);
592 cli->rap_error = res;
594 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
598 if (res == 0 || res == ERRmoredata) {
601 p = rparam + WORDSIZE + WORDSIZE;
604 for (i=0,p=rdata; i<count; i++) {
605 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
606 fn(groupname, state);
609 DEBUG(4,("NetUserGetGroups res=%d\n", res));
612 DEBUG(4,("NetUserGetGroups no data returned\n"));
620 /****************************************************************************
621 call a NetUserDelete - delete user from remote server
622 ****************************************************************************/
623 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
628 unsigned int rdrcnt,rprcnt;
630 char param[WORDSIZE /* api number */
631 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
632 +1 /* no ret string */
633 +RAP_USERNAME_LEN /* user to del */
634 +WORDSIZE]; /* reserved word */
636 /* now send a SMBtrans command with api UserDel */
637 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
638 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
639 PUTWORD(p,0); /* reserved word MBZ on input */
642 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
643 NULL, 0, 200, /* data, length, maxlen */
644 &rparam, &rprcnt, /* return params, length */
645 &rdata, &rdrcnt)) /* return data, length */
647 res = GETRES(rparam);
652 else if ((res == 5) || (res == 65)) {
653 DEBUG(1, ("Access Denied\n"));
655 else if (res == 2221) {
656 DEBUG (1, ("User does not exist\n"));
659 DEBUG(4,("NetUserDelete res=%d\n", res));
663 DEBUG(4,("NetUserDelete failed\n"));
672 /****************************************************************************
673 call a NetUserAdd - add user to remote server
674 ****************************************************************************/
675 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
683 unsigned int rdrcnt,rprcnt;
685 char param[WORDSIZE /* api number */
686 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
687 +sizeof(RAP_USER_INFO_L1) /* data string */
688 +WORDSIZE /* info level */
689 +WORDSIZE /* buffer length */
690 +WORDSIZE]; /* reserved */
693 /* offset into data of free format strings. Will be updated */
694 /* by PUTSTRINGP macro and end up with total data length. */
695 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
696 + RAP_UPASSWD_LEN /* password */
697 + DWORDSIZE /* password age */
698 + WORDSIZE /* privilege */
699 + DWORDSIZE /* home dir ptr */
700 + DWORDSIZE /* comment ptr */
701 + WORDSIZE /* flags */
702 + DWORDSIZE; /* login script ptr*/
704 /* now send a SMBtrans command with api NetUserAdd */
705 p = make_header(param, RAP_WUserAdd2,
706 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
707 PUTWORD(p, 1); /* info level */
709 PUTWORD(p, 0); /* pwencrypt */
710 if(userinfo->passwrd)
711 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
713 PUTWORD(p, 0); /* password length */
716 memset(data, '\0', soffset);
718 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
719 PUTBYTE(p, 0); /* pad byte 0 */
720 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
721 PUTDWORD(p, 0); /* pw age - n.a. on user add */
722 PUTWORD(p, userinfo->priv);
723 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
724 PUTSTRINGP(p, userinfo->comment, data, soffset);
725 PUTWORD(p, userinfo->userflags);
726 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
729 param, sizeof(param), 1024, /* Param, length, maxlen */
730 data, soffset, sizeof(data), /* data, length, maxlen */
731 &rparam, &rprcnt, /* return params, length */
732 &rdata, &rdrcnt)) /* return data, length */
734 res = GETRES(rparam);
739 else if ((res == 5) || (res == 65)) {
740 DEBUG(1, ("Access Denied\n"));
742 else if (res == 2224) {
743 DEBUG (1, ("User already exists\n"));
746 DEBUG(4,("NetUserAdd res=%d\n", res));
750 DEBUG(4,("NetUserAdd failed\n"));
759 /****************************************************************************
760 call a NetUserEnum - try and list users on a different host
761 ****************************************************************************/
762 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
764 char param[WORDSIZE /* api number */
765 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
766 +sizeof(RAP_USER_INFO_L1) /* return string */
767 +WORDSIZE /* info level */
768 +WORDSIZE]; /* buffer size */
772 unsigned int rprcnt, rdrcnt;
776 memset(param, '\0', sizeof(param));
777 p = make_header(param, RAP_WUserEnum,
778 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
779 PUTWORD(p,1); /* Info level 1 */
780 PUTWORD(p,0xFF00); /* Return buffer size */
782 /* BB Fix handling of large numbers of users to be returned */
784 param, PTR_DIFF(p,param),8,
785 NULL, 0, CLI_BUFFER_SIZE,
788 res = GETRES(rparam);
789 cli->rap_error = res;
790 if (cli->rap_error != 0) {
791 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
795 if (res == 0 || res == ERRmoredata) {
796 int i, converter, count;
797 char username[RAP_USERNAME_LEN];
798 char userpw[RAP_UPASSWD_LEN];
799 pstring comment, homedir, logonscript;
801 p = rparam + WORDSIZE; /* skip result */
802 GETWORD(p, converter);
805 for (i=0,p=rdata;i<count;i++) {
806 GETSTRINGF(p, username, RAP_USERNAME_LEN);
808 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
809 p += DWORDSIZE; /* skip password age */
810 p += WORDSIZE; /* skip priv: 0=guest, 1=user, 2=admin */
811 GETSTRINGP(p, homedir, rdata, converter);
812 GETSTRINGP(p, comment, rdata, converter);
813 p += WORDSIZE; /* skip flags */
814 GETSTRINGP(p, logonscript, rdata, converter);
816 fn(username, comment, homedir, logonscript, cli);
819 DEBUG(4,("NetUserEnum res=%d\n", res));
822 DEBUG(4,("NetUserEnum no data returned\n"));
831 int cli_RNetUserEnum0(struct cli_state *cli,
832 void (*fn)(const char *, void *),
835 char param[WORDSIZE /* api number */
836 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
837 +sizeof(RAP_USER_INFO_L0) /* return string */
838 +WORDSIZE /* info level */
839 +WORDSIZE]; /* buffer size */
843 unsigned int rprcnt, rdrcnt;
847 memset(param, '\0', sizeof(param));
848 p = make_header(param, RAP_WUserEnum,
849 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
850 PUTWORD(p,0); /* Info level 1 */
851 PUTWORD(p,0xFF00); /* Return buffer size */
853 /* BB Fix handling of large numbers of users to be returned */
855 param, PTR_DIFF(p,param),8,
856 NULL, 0, CLI_BUFFER_SIZE,
859 res = GETRES(rparam);
860 cli->rap_error = res;
861 if (cli->rap_error != 0) {
862 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
866 if (res == 0 || res == ERRmoredata) {
868 char username[RAP_USERNAME_LEN];
870 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
873 for (i=0,p=rdata;i<count;i++) {
874 GETSTRINGF(p, username, RAP_USERNAME_LEN);
878 DEBUG(4,("NetUserEnum res=%d\n", res));
881 DEBUG(4,("NetUserEnum no data returned\n"));
890 /****************************************************************************
891 call a NetFileClose2 - close open file on another session to server
892 ****************************************************************************/
893 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
898 unsigned int rdrcnt,rprcnt;
899 char param[WORDSIZE /* api number */
900 +sizeof(RAP_WFileClose2_REQ) /* req string */
901 +1 /* no ret string */
902 +DWORDSIZE]; /* file ID */
905 /* now send a SMBtrans command with api RNetShareEnum */
906 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
907 PUTDWORD(p, file_id);
910 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
911 NULL, 0, 200, /* data, length, maxlen */
912 &rparam, &rprcnt, /* return params, length */
913 &rdata, &rdrcnt)) /* return data, length */
915 res = GETRES(rparam);
919 } else if (res == 2314){
920 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
922 DEBUG(4,("NetFileClose2 res=%d\n", res));
926 DEBUG(4,("NetFileClose2 failed\n"));
935 /****************************************************************************
936 call a NetFileGetInfo - get information about server file opened from other
938 ****************************************************************************/
939 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
944 unsigned int rdrcnt,rprcnt;
946 char param[WORDSIZE /* api number */
947 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
948 +sizeof(RAP_FILE_INFO_L3) /* return string */
949 +DWORDSIZE /* file ID */
950 +WORDSIZE /* info level */
951 +WORDSIZE]; /* buffer size */
953 /* now send a SMBtrans command with api RNetShareEnum */
954 p = make_header(param, RAP_WFileGetInfo2,
955 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
956 PUTDWORD(p, file_id);
957 PUTWORD(p, 3); /* info level */
958 PUTWORD(p, 0x1000); /* buffer size */
960 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
961 NULL, 0, 0x1000, /* data, length, maxlen */
962 &rparam, &rprcnt, /* return params, length */
963 &rdata, &rdrcnt)) /* return data, length */
965 res = GETRES(rparam);
966 if (res == 0 || res == ERRmoredata) {
967 int converter,id, perms, locks;
968 pstring fpath, fuser;
970 p = rparam + WORDSIZE; /* skip result */
971 GETWORD(p, converter);
977 GETSTRINGP(p, fpath, rdata, converter);
978 GETSTRINGP(p, fuser, rdata, converter);
980 fn(fpath, fuser, perms, locks, id);
982 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
986 DEBUG(4,("NetFileGetInfo2 failed\n"));
995 /****************************************************************************
996 * Call a NetFileEnum2 - list open files on an SMB server
998 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
999 * server listing the files open via the network (and their
1000 * corresponding open instance ids)
1002 * Dependencies: none
1005 * cli - pointer to cli_state structure
1006 * user - if present, return only files opened by this remote user
1007 * base_path - if present, return only files opened below this
1009 * fn - display function to invoke for each entry in the result
1016 ****************************************************************************/
1017 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1019 char *rparam = NULL;
1022 unsigned int rdrcnt,rprcnt;
1023 char param[WORDSIZE /* api number */
1024 +sizeof(RAP_WFileEnum2_REQ) /* req string */
1025 +sizeof(RAP_FILE_INFO_L3) /* return string */
1026 +256 /* base path (opt) */
1027 +RAP_USERNAME_LEN /* user name (opt) */
1028 +WORDSIZE /* info level */
1029 +WORDSIZE /* buffer size */
1030 +DWORDSIZE /* resume key ? */
1031 +DWORDSIZE]; /* resume key ? */
1034 /* now send a SMBtrans command with api RNetShareEnum */
1035 p = make_header(param, RAP_WFileEnum2,
1036 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1038 PUTSTRING(p, base_path, 256);
1039 PUTSTRING(p, user, RAP_USERNAME_LEN);
1040 PUTWORD(p, 3); /* info level */
1041 PUTWORD(p, 0xFF00); /* buffer size */
1042 PUTDWORD(p, 0); /* zero out the resume key */
1043 PUTDWORD(p, 0); /* or is this one the resume key? */
1046 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1047 NULL, 0, 0xFF00, /* data, length, maxlen */
1048 &rparam, &rprcnt, /* return params, length */
1049 &rdata, &rdrcnt)) /* return data, length */
1051 int res = GETRES(rparam);
1053 if (res == 0 || res == ERRmoredata) {
1056 p = rparam + WORDSIZE; /* skip result */
1057 GETWORD(p, converter);
1061 for (i=0; i<count; i++) {
1062 int id, perms, locks;
1063 pstring fpath, fuser;
1068 GETSTRINGP(p, fpath, rdata, converter);
1069 GETSTRINGP(p, fuser, rdata, converter);
1071 fn(fpath, fuser, perms, locks, id);
1072 } /* BB fix ERRmoredata case to send resume request */
1074 DEBUG(4,("NetFileEnum2 res=%d\n", res));
1077 DEBUG(4,("NetFileEnum2 failed\n"));
1086 /****************************************************************************
1087 call a NetShareAdd - share/export directory on remote server
1088 ****************************************************************************/
1089 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1091 char *rparam = NULL;
1094 unsigned int rdrcnt,rprcnt;
1096 char param[WORDSIZE /* api number */
1097 +sizeof(RAP_WShareAdd_REQ) /* req string */
1098 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1099 +WORDSIZE /* info level */
1100 +WORDSIZE]; /* reserved word */
1102 /* offset to free format string section following fixed length data. */
1103 /* will be updated by PUTSTRINGP macro and will end up with total len */
1104 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
1105 + WORDSIZE /* share type */
1106 + DWORDSIZE /* comment pointer */
1107 + WORDSIZE /* permissions */
1108 + WORDSIZE /* max users */
1109 + WORDSIZE /* active users */
1110 + DWORDSIZE /* share path */
1111 + RAP_SPASSWD_LEN + 1; /* share password + pad */
1113 memset(param,'\0',sizeof(param));
1114 /* now send a SMBtrans command with api RNetShareAdd */
1115 p = make_header(param, RAP_WshareAdd,
1116 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1117 PUTWORD(p, 2); /* info level */
1118 PUTWORD(p, 0); /* reserved word 0 */
1121 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1122 PUTBYTE(p, 0); /* pad byte 0 */
1124 PUTWORD(p, sinfo->share_type);
1125 PUTSTRINGP(p, sinfo->comment, data, soffset);
1126 PUTWORD(p, sinfo->perms);
1127 PUTWORD(p, sinfo->maximum_users);
1128 PUTWORD(p, sinfo->active_users);
1129 PUTSTRINGP(p, sinfo->path, data, soffset);
1130 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1131 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1134 param, sizeof(param), 1024, /* Param, length, maxlen */
1135 data, soffset, sizeof(data), /* data, length, maxlen */
1136 &rparam, &rprcnt, /* return params, length */
1137 &rdata, &rdrcnt)) /* return data, length */
1139 res = rparam? SVAL(rparam,0) : -1;
1145 DEBUG(4,("NetShareAdd res=%d\n", res));
1149 DEBUG(4,("NetShareAdd failed\n"));
1157 /****************************************************************************
1158 call a NetShareDelete - unshare exported directory on remote server
1159 ****************************************************************************/
1160 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1162 char *rparam = NULL;
1165 unsigned int rdrcnt,rprcnt;
1167 char param[WORDSIZE /* api number */
1168 +sizeof(RAP_WShareDel_REQ) /* req string */
1169 +1 /* no ret string */
1170 +RAP_SHARENAME_LEN /* share to del */
1171 +WORDSIZE]; /* reserved word */
1174 /* now send a SMBtrans command with api RNetShareDelete */
1175 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1176 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1177 PUTWORD(p,0); /* reserved word MBZ on input */
1180 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1181 NULL, 0, 200, /* data, length, maxlen */
1182 &rparam, &rprcnt, /* return params, length */
1183 &rdata, &rdrcnt)) /* return data, length */
1185 res = GETRES(rparam);
1191 DEBUG(4,("NetShareDelete res=%d\n", res));
1195 DEBUG(4,("NetShareDelete failed\n"));
1203 /*************************************************************************
1205 * Function Name: cli_get_pdc_name
1207 * PURPOSE: Remotes a NetServerEnum API call to the current server
1208 * requesting the name of a server matching the server
1209 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1211 * Dependencies: none
1214 * cli - pointer to cli_state structure
1215 * workgroup - pointer to string containing name of domain
1216 * pdc_name - pointer to string that will contain PDC name
1217 * on successful return
1223 ************************************************************************/
1224 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1226 char *rparam = NULL;
1228 unsigned int rdrcnt,rprcnt;
1230 char param[WORDSIZE /* api number */
1231 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1232 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1233 +WORDSIZE /* info level */
1234 +WORDSIZE /* buffer size */
1235 +DWORDSIZE /* server type */
1236 +RAP_MACHNAME_LEN]; /* workgroup */
1241 /* send a SMBtrans command with api NetServerEnum */
1242 p = make_header(param, RAP_NetServerEnum2,
1243 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1244 PUTWORD(p, 1); /* info level */
1245 PUTWORD(p, CLI_BUFFER_SIZE);
1246 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1247 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1250 param, PTR_DIFF(p,param), 8, /* params, length, max */
1251 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1252 &rparam, &rprcnt, /* return params, return size */
1253 &rdata, &rdrcnt /* return data, return size */
1255 cli->rap_error = GETRES(rparam);
1258 * We only really care to copy a name if the
1259 * API succeeded and we got back a name.
1261 if (cli->rap_error == 0) {
1262 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1267 GETSTRING(p, pdc_name);
1270 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1271 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1282 /*************************************************************************
1284 * Function Name: cli_get_server_domain
1286 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1287 * requesting wksta_info_10 level information to determine
1288 * the domain the server belongs to. On success, this
1289 * routine sets the server_domain field in the cli_state structure
1290 * to the server's domain name.
1292 * Dependencies: none
1295 * cli - pointer to cli_state structure
1301 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1303 ************************************************************************/
1304 BOOL cli_get_server_domain(struct cli_state *cli)
1306 char *rparam = NULL;
1308 unsigned int rdrcnt,rprcnt;
1310 char param[WORDSIZE /* api number */
1311 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1312 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1313 +WORDSIZE /* info level */
1314 +WORDSIZE]; /* buffer size */
1317 /* send a SMBtrans command with api NetWkstaGetInfo */
1318 p = make_header(param, RAP_WWkstaGetInfo,
1319 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1320 PUTWORD(p, 10); /* info level */
1321 PUTWORD(p, CLI_BUFFER_SIZE);
1323 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1324 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1325 &rparam, &rprcnt, /* return params, return size */
1326 &rdata, &rdrcnt)) { /* return data, return size */
1327 res = GETRES(rparam);
1333 p = rparam + WORDSIZE;
1334 GETWORD(p, converter);
1336 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1337 GETSTRINGP(p, cli->server_domain, rdata, converter);
1348 /*************************************************************************
1350 * Function Name: cli_get_server_type
1352 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1353 * requesting server_info_1 level information to retrieve
1356 * Dependencies: none
1359 * cli - pointer to cli_state structure
1360 * pstype - pointer to uint32 to contain returned server type
1366 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1368 ************************************************************************/
1369 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1371 char *rparam = NULL;
1373 unsigned int rdrcnt,rprcnt;
1375 char param[WORDSIZE /* api number */
1376 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1377 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1378 +WORDSIZE /* info level */
1379 +WORDSIZE]; /* buffer size */
1382 /* send a SMBtrans command with api NetServerGetInfo */
1383 p = make_header(param, RAP_WserverGetInfo,
1384 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1385 PUTWORD(p, 1); /* info level */
1386 PUTWORD(p, CLI_BUFFER_SIZE);
1389 param, PTR_DIFF(p,param), 8, /* params, length, max */
1390 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1391 &rparam, &rprcnt, /* return params, return size */
1392 &rdata, &rdrcnt /* return data, return size */
1395 res = GETRES(rparam);
1397 if (res == 0 || res == ERRmoredata) {
1399 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1406 return(res == 0 || res == ERRmoredata);
1410 /*************************************************************************
1412 * Function Name: cli_ns_check_server_type
1414 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1415 * requesting server_info_0 level information of machines
1416 * matching the given server type. If the returned server
1417 * list contains the machine name contained in cli->desthost
1418 * then we conclude the server type checks out. This routine
1419 * is useful to retrieve list of server's of a certain
1420 * type when all you have is a null session connection and
1421 * can't remote API calls such as NetWkstaGetInfo or
1424 * Dependencies: none
1427 * cli - pointer to cli_state structure
1428 * workgroup - pointer to string containing domain
1429 * stype - server type
1435 ************************************************************************/
1436 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1438 char *rparam = NULL;
1440 unsigned int rdrcnt,rprcnt;
1442 char param[WORDSIZE /* api number */
1443 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1444 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1445 +WORDSIZE /* info level */
1446 +WORDSIZE /* buffer size */
1447 +DWORDSIZE /* server type */
1448 +RAP_MACHNAME_LEN]; /* workgroup */
1449 BOOL found_server = False;
1452 /* send a SMBtrans command with api NetServerEnum */
1453 p = make_header(param, RAP_NetServerEnum2,
1454 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1455 PUTWORD(p, 0); /* info level 0 */
1456 PUTWORD(p, CLI_BUFFER_SIZE);
1458 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1461 param, PTR_DIFF(p,param), 8, /* params, length, max */
1462 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1463 &rparam, &rprcnt, /* return params, return size */
1464 &rdata, &rdrcnt /* return data, return size */
1467 res = GETRES(rparam);
1468 cli->rap_error = res;
1470 if (res == 0 || res == ERRmoredata) {
1473 p = rparam + WORDSIZE + WORDSIZE;
1477 for (i = 0;i < count;i++, p += 16) {
1478 char ret_server[RAP_MACHNAME_LEN];
1480 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1481 if (strequal(ret_server, cli->desthost)) {
1482 found_server = True;
1488 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1489 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1496 return found_server;
1500 /****************************************************************************
1501 perform a NetWkstaUserLogoff
1502 ****************************************************************************/
1503 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1505 char *rparam = NULL;
1508 unsigned int rdrcnt,rprcnt;
1509 char param[WORDSIZE /* api number */
1510 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1511 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1512 +RAP_USERNAME_LEN+1 /* user name+pad */
1513 +RAP_MACHNAME_LEN /* wksta name */
1514 +WORDSIZE /* buffer size */
1515 +WORDSIZE]; /* buffer size? */
1518 memset(param, 0, sizeof(param));
1520 /* send a SMBtrans command with api NetWkstaUserLogoff */
1521 p = make_header(param, RAP_WWkstaUserLogoff,
1522 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1523 PUTDWORD(p, 0); /* Null pointer */
1524 PUTDWORD(p, 0); /* Null pointer */
1525 fstrcpy(upperbuf, user);
1526 strupper_m(upperbuf);
1527 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1528 p++; /* strange format, but ok */
1529 fstrcpy(upperbuf, workstation);
1530 strupper_m(upperbuf);
1531 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1532 PUTWORD(p, CLI_BUFFER_SIZE);
1533 PUTWORD(p, CLI_BUFFER_SIZE);
1536 param, PTR_DIFF(p,param),1024, /* param, length, max */
1537 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1538 &rparam, &rprcnt, /* return params, return size */
1539 &rdata, &rdrcnt /* return data, return size */
1541 cli->rap_error = GETRES(rparam);
1543 if (cli->rap_error != 0) {
1544 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1550 return (cli->rap_error == 0);
1553 int cli_NetPrintQEnum(struct cli_state *cli,
1554 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1555 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1557 char param[WORDSIZE /* api number */
1558 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1559 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1560 +WORDSIZE /* info level */
1561 +WORDSIZE /* buffer size */
1562 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1564 char *rparam = NULL;
1566 unsigned int rprcnt, rdrcnt;
1570 memset(param, '\0',sizeof(param));
1571 p = make_header(param, RAP_WPrintQEnum,
1572 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1573 PUTWORD(p,2); /* Info level 2 */
1574 PUTWORD(p,0xFFE0); /* Return buffer size */
1575 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1578 param, PTR_DIFF(p,param),1024,
1579 NULL, 0, CLI_BUFFER_SIZE,
1582 res = GETRES(rparam);
1583 cli->rap_error = res;
1585 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1590 if (res == 0 || res == ERRmoredata) {
1591 int i, converter, count;
1593 p = rparam + WORDSIZE;
1594 GETWORD(p, converter);
1598 for (i=0;i<count;i++) {
1599 pstring qname, sep_file, print_proc, dest, parms, comment;
1600 uint16 jobcount, priority, start_time, until_time, status;
1602 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1604 GETWORD(p, priority);
1605 GETWORD(p, start_time);
1606 GETWORD(p, until_time);
1607 GETSTRINGP(p, sep_file, rdata, converter);
1608 GETSTRINGP(p, print_proc, rdata, converter);
1609 GETSTRINGP(p, dest, rdata, converter);
1610 GETSTRINGP(p, parms, rdata, converter);
1611 GETSTRINGP(p, parms, comment, converter);
1613 GETWORD(p, jobcount);
1615 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1616 dest, parms, comment, status, jobcount);
1620 for (j=0;j<jobcount;j++) {
1621 uint16 jid, pos, fsstatus;
1622 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1623 unsigned int submitted, jsize;
1626 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1628 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1629 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1630 GETSTRINGP(p, jparms, rdata, converter);
1632 GETWORD(p, fsstatus);
1633 GETSTRINGP(p, jstatus, rdata, converter);
1634 GETDWORD(p, submitted);
1636 GETSTRINGP(p, jcomment, rdata, converter);
1638 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1639 jstatus, submitted, jsize, jcomment);
1644 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1647 DEBUG(4,("NetPrintQEnum no data returned\n"));
1656 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1657 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1658 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1660 char param[WORDSIZE /* api number */
1661 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1662 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1663 +RAP_SHARENAME_LEN /* printer name */
1664 +WORDSIZE /* info level */
1665 +WORDSIZE /* buffer size */
1666 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1668 char *rparam = NULL;
1670 unsigned int rprcnt, rdrcnt;
1674 memset(param, '\0',sizeof(param));
1675 p = make_header(param, RAP_WPrintQGetInfo,
1676 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1677 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1678 PUTWORD(p, 2); /* Info level 2 */
1679 PUTWORD(p,0xFFE0); /* Return buffer size */
1680 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1683 param, PTR_DIFF(p,param),1024,
1684 NULL, 0, CLI_BUFFER_SIZE,
1687 res = GETRES(rparam);
1688 cli->rap_error = res;
1690 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1695 if (res == 0 || res == ERRmoredata) {
1696 int rsize, converter;
1697 pstring qname, sep_file, print_proc, dest, parms, comment;
1698 uint16 jobcount, priority, start_time, until_time, status;
1700 p = rparam + WORDSIZE;
1701 GETWORD(p, converter);
1705 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1707 GETWORD(p, priority);
1708 GETWORD(p, start_time);
1709 GETWORD(p, until_time);
1710 GETSTRINGP(p, sep_file, rdata, converter);
1711 GETSTRINGP(p, print_proc, rdata, converter);
1712 GETSTRINGP(p, dest, rdata, converter);
1713 GETSTRINGP(p, parms, rdata, converter);
1714 GETSTRINGP(p, comment, rdata, converter);
1716 GETWORD(p, jobcount);
1717 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1718 dest, parms, comment, status, jobcount);
1721 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1722 uint16 jid, pos, fsstatus;
1723 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1724 unsigned int submitted, jsize;
1727 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1729 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1730 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1731 GETSTRINGP(p, jparms, rdata, converter);
1733 GETWORD(p, fsstatus);
1734 GETSTRINGP(p, jstatus, rdata, converter);
1735 GETDWORD(p, submitted);
1737 GETSTRINGP(p, jcomment, rdata, converter);
1739 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1740 jstatus, submitted, jsize, jcomment);
1744 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1747 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1756 /****************************************************************************
1757 call a NetServiceEnum - list running services on a different host
1758 ****************************************************************************/
1759 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1761 char param[WORDSIZE /* api number */
1762 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1763 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1764 +WORDSIZE /* info level */
1765 +WORDSIZE]; /* buffer size */
1767 char *rparam = NULL;
1769 unsigned int rprcnt, rdrcnt;
1773 memset(param, '\0', sizeof(param));
1774 p = make_header(param, RAP_WServiceEnum,
1775 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1776 PUTWORD(p,2); /* Info level 2 */
1777 PUTWORD(p,0xFFE0); /* Return buffer size */
1780 param, PTR_DIFF(p,param),8,
1781 NULL, 0, 0xFFE0 /* data area size */,
1784 res = GETRES(rparam);
1785 cli->rap_error = res;
1786 if(cli->rap_error == 234)
1787 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1788 else if (cli->rap_error != 0) {
1789 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1794 if (res == 0 || res == ERRmoredata) {
1797 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1800 for (i=0,p=rdata;i<count;i++) {
1802 char servicename[RAP_SRVCNAME_LEN];
1804 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1805 p+=8; /* pass status words */
1806 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1808 fn(servicename, comment, cli); /* BB add status too */
1811 DEBUG(4,("NetServiceEnum res=%d\n", res));
1814 DEBUG(4,("NetServiceEnum no data returned\n"));
1824 /****************************************************************************
1825 call a NetSessionEnum - list workstations with sessions to an SMB server
1826 ****************************************************************************/
1827 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1829 char param[WORDSIZE /* api number */
1830 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1831 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1832 +WORDSIZE /* info level */
1833 +WORDSIZE]; /* buffer size */
1835 char *rparam = NULL;
1837 unsigned int rprcnt, rdrcnt;
1840 memset(param, '\0', sizeof(param));
1841 p = make_header(param, RAP_WsessionEnum,
1842 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1843 PUTWORD(p,2); /* Info level 2 */
1844 PUTWORD(p,0xFF); /* Return buffer size */
1847 param, PTR_DIFF(p,param),8,
1848 NULL, 0, CLI_BUFFER_SIZE,
1851 res = GETRES(rparam);
1852 cli->rap_error = res;
1854 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1859 if (res == 0 || res == ERRmoredata) {
1860 int i, converter, count;
1862 p = rparam + WORDSIZE;
1863 GETWORD(p, converter);
1866 for (i=0,p=rdata;i<count;i++) {
1867 pstring wsname, username, clitype_name;
1868 uint16 num_conns, num_opens, num_users;
1869 unsigned int sess_time, idle_time, user_flags;
1871 GETSTRINGP(p, wsname, rdata, converter);
1872 GETSTRINGP(p, username, rdata, converter);
1873 GETWORD(p, num_conns);
1874 GETWORD(p, num_opens);
1875 GETWORD(p, num_users);
1876 GETDWORD(p, sess_time);
1877 GETDWORD(p, idle_time);
1878 GETDWORD(p, user_flags);
1879 GETSTRINGP(p, clitype_name, rdata, converter);
1881 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1882 idle_time, user_flags, clitype_name);
1886 DEBUG(4,("NetSessionEnum res=%d\n", res));
1889 DEBUG(4,("NetSesssionEnum no data returned\n"));
1898 /****************************************************************************
1899 Call a NetSessionGetInfo - get information about other session to an SMB server.
1900 ****************************************************************************/
1902 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1904 char param[WORDSIZE /* api number */
1905 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1906 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1907 +RAP_MACHNAME_LEN /* wksta name */
1908 +WORDSIZE /* info level */
1909 +WORDSIZE]; /* buffer size */
1911 char *rparam = NULL;
1913 unsigned int rprcnt, rdrcnt;
1917 memset(param, '\0', sizeof(param));
1918 p = make_header(param, RAP_WsessionGetInfo,
1919 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1920 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1921 PUTWORD(p,2); /* Info level 2 */
1922 PUTWORD(p,0xFF); /* Return buffer size */
1925 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1926 NULL, 0, CLI_BUFFER_SIZE,
1929 cli->rap_error = SVAL(rparam,0);
1930 if (cli->rap_error != 0) {
1931 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1936 res = GETRES(rparam);
1938 if (res == 0 || res == ERRmoredata) {
1940 pstring wsname, username, clitype_name;
1941 uint16 num_conns, num_opens, num_users;
1942 unsigned int sess_time, idle_time, user_flags;
1944 p = rparam + WORDSIZE;
1945 GETWORD(p, converter);
1946 p += WORDSIZE; /* skip rsize */
1949 GETSTRINGP(p, wsname, rdata, converter);
1950 GETSTRINGP(p, username, rdata, converter);
1951 GETWORD(p, num_conns);
1952 GETWORD(p, num_opens);
1953 GETWORD(p, num_users);
1954 GETDWORD(p, sess_time);
1955 GETDWORD(p, idle_time);
1956 GETDWORD(p, user_flags);
1957 GETSTRINGP(p, clitype_name, rdata, converter);
1959 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1960 idle_time, user_flags, clitype_name);
1962 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1965 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1974 /****************************************************************************
1975 call a NetSessionDel - close a session to an SMB server
1976 ****************************************************************************/
1977 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1979 char param[WORDSIZE /* api number */
1980 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1981 +1 /* no return string */
1982 +RAP_MACHNAME_LEN /* workstation name */
1983 +WORDSIZE]; /* reserved (0) */
1985 char *rparam = NULL;
1987 unsigned int rprcnt, rdrcnt;
1990 memset(param, '\0', sizeof(param));
1991 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1992 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1993 PUTWORD(p,0); /* reserved word of 0 */
1995 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1996 NULL, 0, 200, /* data, length, maxlen */
1997 &rparam, &rprcnt, /* return params, length */
1998 &rdata, &rdrcnt)) /* return data, length */
2000 res = GETRES(rparam);
2001 cli->rap_error = res;
2007 DEBUG(4,("NetFileClose2 res=%d\n", res));
2011 DEBUG(4,("NetFileClose2 failed\n"));
2021 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))
2023 char param[WORDSIZE /* api number */
2024 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
2025 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
2026 +RAP_MACHNAME_LEN /* wksta name */
2027 +WORDSIZE /* info level */
2028 +WORDSIZE]; /* buffer size */
2030 char *rparam = NULL;
2032 unsigned int rprcnt, rdrcnt;
2035 memset(param, '\0', sizeof(param));
2036 p = make_header(param, RAP_WconnectionEnum,
2037 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2038 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2039 PUTWORD(p,1); /* Info level 1 */
2040 PUTWORD(p,0xFFE0); /* Return buffer size */
2043 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2044 NULL, 0, CLI_BUFFER_SIZE,
2047 res = GETRES(rparam);
2048 cli->rap_error = res;
2050 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2054 if (res == 0 || res == ERRmoredata) {
2055 int i, converter, count;
2057 p = rparam + WORDSIZE;
2058 GETWORD(p, converter);
2061 for (i=0,p=rdata;i<count;i++) {
2062 pstring netname, username;
2063 uint16 conn_id, conn_type, num_opens, num_users;
2064 unsigned int conn_time;
2067 GETWORD(p,conn_type);
2068 GETWORD(p,num_opens);
2069 GETWORD(p,num_users);
2070 GETDWORD(p,conn_time);
2071 GETSTRINGP(p, username, rdata, converter);
2072 GETSTRINGP(p, netname, rdata, converter);
2074 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2079 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2082 DEBUG(4,("NetConnectionEnum no data returned\n"));