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) {
372 int i, converter, count;
374 p = rparam + WORDSIZE; /* skip result */
375 GETWORD(p, converter);
378 for (i=0,p=rdata;i<count;i++) {
379 char groupname[RAP_GROUPNAME_LEN];
380 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
384 DEBUG(4,("NetGroupEnum res=%d\n", res));
387 DEBUG(4,("NetGroupEnum no data returned\n"));
396 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
401 unsigned int rdrcnt,rprcnt;
403 char param[WORDSIZE /* api number */
404 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
405 +1 /* no ret string */
406 +RAP_GROUPNAME_LEN /* group name */
407 +RAP_USERNAME_LEN]; /* user to del */
409 /* now send a SMBtrans command with api GroupMemberAdd */
410 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
411 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
412 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
415 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
416 NULL, 0, 200, /* data, length, maxlen */
417 &rparam, &rprcnt, /* return params, length */
418 &rdata, &rdrcnt)) /* return data, length */
420 res = GETRES(rparam);
427 DEBUG(1, ("Access Denied\n"));
430 DEBUG(1, ("Not supported by server\n"));
433 DEBUG(1, ("Group does not exist\n"));
436 DEBUG(1, ("User does not exist\n"));
439 DEBUG(1, ("User is not in group\n"));
442 DEBUG(4,("NetGroupDelUser res=%d\n", res));
446 DEBUG(4,("NetGroupDelUser failed\n"));
455 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
460 unsigned int rdrcnt,rprcnt;
462 char param[WORDSIZE /* api number */
463 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
464 +1 /* no ret string */
465 +RAP_GROUPNAME_LEN /* group name */
466 +RAP_USERNAME_LEN]; /* user to add */
468 /* now send a SMBtrans command with api GroupMemberAdd */
469 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
470 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
471 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
474 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
475 NULL, 0, 200, /* data, length, maxlen */
476 &rparam, &rprcnt, /* return params, length */
477 &rdata, &rdrcnt)) /* return data, length */
479 res = GETRES(rparam);
486 DEBUG(1, ("Access Denied\n"));
489 DEBUG(1, ("Not supported by server\n"));
492 DEBUG(1, ("Group does not exist\n"));
495 DEBUG(1, ("User does not exist\n"));
498 DEBUG(4,("NetGroupAddUser res=%d\n", res));
502 DEBUG(4,("NetGroupAddUser failed\n"));
512 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
517 unsigned int rdrcnt,rprcnt;
519 char param[WORDSIZE /* api number */
520 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
521 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
522 +RAP_GROUPNAME_LEN /* group name */
523 +WORDSIZE /* info level */
524 +WORDSIZE]; /* buffer size */
526 /* now send a SMBtrans command with api GroupGetUsers */
527 p = make_header(param, RAP_WGroupGetUsers,
528 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
529 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
530 PUTWORD(p,0); /* info level 0 */
531 PUTWORD(p,0xFFE0); /* return buffer size */
534 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
535 NULL, 0, CLI_BUFFER_SIZE,
538 res = GETRES(rparam);
539 cli->rap_error = res;
541 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
545 if (res == 0 || res == ERRmoredata) {
546 int i, converter, count;
548 p = rparam +WORDSIZE;
549 GETWORD(p, converter);
552 for (i=0,p=rdata; i<count; i++) {
553 GETSTRINGF(p, username, RAP_USERNAME_LEN);
557 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
560 DEBUG(4,("NetGroupGetUsers no data returned\n"));
567 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
572 unsigned int rdrcnt,rprcnt;
574 char param[WORDSIZE /* api number */
575 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
576 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
577 +RAP_USERNAME_LEN /* user name */
578 +WORDSIZE /* info level */
579 +WORDSIZE]; /* buffer size */
581 /* now send a SMBtrans command with api GroupGetUsers */
582 p = make_header(param, RAP_WUserGetGroups,
583 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
584 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
585 PUTWORD(p,0); /* info level 0 */
586 PUTWORD(p,0xFFE0); /* return buffer size */
589 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
590 NULL, 0, CLI_BUFFER_SIZE,
593 res = GETRES(rparam);
594 cli->rap_error = res;
596 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
600 if (res == 0 || res == ERRmoredata) {
601 int i, converter, count;
603 p = rparam +WORDSIZE;
604 GETWORD(p, converter);
607 for (i=0,p=rdata; i<count; i++) {
608 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
609 fn(groupname, state);
612 DEBUG(4,("NetUserGetGroups res=%d\n", res));
615 DEBUG(4,("NetUserGetGroups no data returned\n"));
623 /****************************************************************************
624 call a NetUserDelete - delete user from remote server
625 ****************************************************************************/
626 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
631 unsigned int rdrcnt,rprcnt;
633 char param[WORDSIZE /* api number */
634 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
635 +1 /* no ret string */
636 +RAP_USERNAME_LEN /* user to del */
637 +WORDSIZE]; /* reserved word */
639 /* now send a SMBtrans command with api UserDel */
640 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
641 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
642 PUTWORD(p,0); /* reserved word MBZ on input */
645 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
646 NULL, 0, 200, /* data, length, maxlen */
647 &rparam, &rprcnt, /* return params, length */
648 &rdata, &rdrcnt)) /* return data, length */
650 res = GETRES(rparam);
655 else if ((res == 5) || (res == 65)) {
656 DEBUG(1, ("Access Denied\n"));
658 else if (res == 2221) {
659 DEBUG (1, ("User does not exist\n"));
662 DEBUG(4,("NetUserDelete res=%d\n", res));
666 DEBUG(4,("NetUserDelete failed\n"));
675 /****************************************************************************
676 call a NetUserAdd - add user to remote server
677 ****************************************************************************/
678 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
686 unsigned int rdrcnt,rprcnt;
688 char param[WORDSIZE /* api number */
689 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
690 +sizeof(RAP_USER_INFO_L1) /* data string */
691 +WORDSIZE /* info level */
692 +WORDSIZE /* buffer length */
693 +WORDSIZE]; /* reserved */
696 /* offset into data of free format strings. Will be updated */
697 /* by PUTSTRINGP macro and end up with total data length. */
698 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
699 + RAP_UPASSWD_LEN /* password */
700 + DWORDSIZE /* password age */
701 + WORDSIZE /* privilege */
702 + DWORDSIZE /* home dir ptr */
703 + DWORDSIZE /* comment ptr */
704 + WORDSIZE /* flags */
705 + DWORDSIZE; /* login script ptr*/
707 /* now send a SMBtrans command with api NetUserAdd */
708 p = make_header(param, RAP_WUserAdd2,
709 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
710 PUTWORD(p, 1); /* info level */
712 PUTWORD(p, 0); /* pwencrypt */
713 if(userinfo->passwrd)
714 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
716 PUTWORD(p, 0); /* password length */
719 memset(data, '\0', soffset);
721 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
722 PUTBYTE(p, 0); /* pad byte 0 */
723 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
724 PUTDWORD(p, 0); /* pw age - n.a. on user add */
725 PUTWORD(p, userinfo->priv);
726 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
727 PUTSTRINGP(p, userinfo->comment, data, soffset);
728 PUTWORD(p, userinfo->userflags);
729 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
732 param, sizeof(param), 1024, /* Param, length, maxlen */
733 data, soffset, sizeof(data), /* data, length, maxlen */
734 &rparam, &rprcnt, /* return params, length */
735 &rdata, &rdrcnt)) /* return data, length */
737 res = GETRES(rparam);
742 else if ((res == 5) || (res == 65)) {
743 DEBUG(1, ("Access Denied\n"));
745 else if (res == 2224) {
746 DEBUG (1, ("User already exists\n"));
749 DEBUG(4,("NetUserAdd res=%d\n", res));
753 DEBUG(4,("NetUserAdd failed\n"));
762 /****************************************************************************
763 call a NetUserEnum - try and list users on a different host
764 ****************************************************************************/
765 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
767 char param[WORDSIZE /* api number */
768 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
769 +sizeof(RAP_USER_INFO_L1) /* return string */
770 +WORDSIZE /* info level */
771 +WORDSIZE]; /* buffer size */
775 unsigned int rprcnt, rdrcnt;
779 memset(param, '\0', sizeof(param));
780 p = make_header(param, RAP_WUserEnum,
781 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
782 PUTWORD(p,1); /* Info level 1 */
783 PUTWORD(p,0xFF00); /* Return buffer size */
785 /* BB Fix handling of large numbers of users to be returned */
787 param, PTR_DIFF(p,param),8,
788 NULL, 0, CLI_BUFFER_SIZE,
791 res = GETRES(rparam);
792 cli->rap_error = res;
793 if (cli->rap_error != 0) {
794 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
798 if (res == 0 || res == ERRmoredata) {
799 int i, converter, count;
800 char username[RAP_USERNAME_LEN];
801 char userpw[RAP_UPASSWD_LEN];
802 pstring comment, homedir, logonscript;
803 int pwage, priv, flags;
805 p = rparam + WORDSIZE; /* skip result */
806 GETWORD(p, converter);
809 for (i=0,p=rdata;i<count;i++) {
810 GETSTRINGF(p, username, RAP_USERNAME_LEN);
812 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
813 GETDWORD(p, pwage); /* password age */
814 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */
815 GETSTRINGP(p, homedir, rdata, converter);
816 GETSTRINGP(p, comment, rdata, converter);
818 GETSTRINGP(p, logonscript, rdata, converter);
820 fn(username, comment, homedir, logonscript, cli);
823 DEBUG(4,("NetUserEnum res=%d\n", res));
826 DEBUG(4,("NetUserEnum no data returned\n"));
835 int cli_RNetUserEnum0(struct cli_state *cli,
836 void (*fn)(const char *, void *),
839 char param[WORDSIZE /* api number */
840 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
841 +sizeof(RAP_USER_INFO_L0) /* return string */
842 +WORDSIZE /* info level */
843 +WORDSIZE]; /* buffer size */
847 unsigned int rprcnt, rdrcnt;
851 memset(param, '\0', sizeof(param));
852 p = make_header(param, RAP_WUserEnum,
853 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
854 PUTWORD(p,0); /* Info level 1 */
855 PUTWORD(p,0xFF00); /* Return buffer size */
857 /* BB Fix handling of large numbers of users to be returned */
859 param, PTR_DIFF(p,param),8,
860 NULL, 0, CLI_BUFFER_SIZE,
863 res = GETRES(rparam);
864 cli->rap_error = res;
865 if (cli->rap_error != 0) {
866 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
870 if (res == 0 || res == ERRmoredata) {
871 int i, converter, count;
872 char username[RAP_USERNAME_LEN];
874 p = rparam + WORDSIZE; /* skip result */
875 GETWORD(p, converter);
878 for (i=0,p=rdata;i<count;i++) {
879 GETSTRINGF(p, username, RAP_USERNAME_LEN);
883 DEBUG(4,("NetUserEnum res=%d\n", res));
886 DEBUG(4,("NetUserEnum no data returned\n"));
895 /****************************************************************************
896 call a NetFileClose2 - close open file on another session to server
897 ****************************************************************************/
898 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
903 unsigned int rdrcnt,rprcnt;
904 char param[WORDSIZE /* api number */
905 +sizeof(RAP_WFileClose2_REQ) /* req string */
906 +1 /* no ret string */
907 +DWORDSIZE]; /* file ID */
910 /* now send a SMBtrans command with api RNetShareEnum */
911 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
912 PUTDWORD(p, file_id);
915 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
916 NULL, 0, 200, /* data, length, maxlen */
917 &rparam, &rprcnt, /* return params, length */
918 &rdata, &rdrcnt)) /* return data, length */
920 res = GETRES(rparam);
924 } else if (res == 2314){
925 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
927 DEBUG(4,("NetFileClose2 res=%d\n", res));
931 DEBUG(4,("NetFileClose2 failed\n"));
940 /****************************************************************************
941 call a NetFileGetInfo - get information about server file opened from other
943 ****************************************************************************/
944 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
949 unsigned int rdrcnt,rprcnt;
951 char param[WORDSIZE /* api number */
952 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
953 +sizeof(RAP_FILE_INFO_L3) /* return string */
954 +DWORDSIZE /* file ID */
955 +WORDSIZE /* info level */
956 +WORDSIZE]; /* buffer size */
958 /* now send a SMBtrans command with api RNetShareEnum */
959 p = make_header(param, RAP_WFileGetInfo2,
960 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
961 PUTDWORD(p, file_id);
962 PUTWORD(p, 3); /* info level */
963 PUTWORD(p, 0x1000); /* buffer size */
965 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
966 NULL, 0, 0x1000, /* data, length, maxlen */
967 &rparam, &rprcnt, /* return params, length */
968 &rdata, &rdrcnt)) /* return data, length */
970 res = GETRES(rparam);
971 if (res == 0 || res == ERRmoredata) {
972 int converter,id, perms, locks;
973 pstring fpath, fuser;
975 p = rparam + WORDSIZE; /* skip result */
976 GETWORD(p, converter);
982 GETSTRINGP(p, fpath, rdata, converter);
983 GETSTRINGP(p, fuser, rdata, converter);
985 fn(fpath, fuser, perms, locks, id);
987 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
991 DEBUG(4,("NetFileGetInfo2 failed\n"));
1000 /****************************************************************************
1001 * Call a NetFileEnum2 - list open files on an SMB server
1003 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
1004 * server listing the files open via the network (and their
1005 * corresponding open instance ids)
1007 * Dependencies: none
1010 * cli - pointer to cli_state structure
1011 * user - if present, return only files opened by this remote user
1012 * base_path - if present, return only files opened below this
1014 * fn - display function to invoke for each entry in the result
1021 ****************************************************************************/
1022 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1024 char *rparam = NULL;
1027 unsigned int rdrcnt,rprcnt;
1028 char param[WORDSIZE /* api number */
1029 +sizeof(RAP_WFileEnum2_REQ) /* req string */
1030 +sizeof(RAP_FILE_INFO_L3) /* return string */
1031 +256 /* base path (opt) */
1032 +RAP_USERNAME_LEN /* user name (opt) */
1033 +WORDSIZE /* info level */
1034 +WORDSIZE /* buffer size */
1035 +DWORDSIZE /* resume key ? */
1036 +DWORDSIZE]; /* resume key ? */
1039 /* now send a SMBtrans command with api RNetShareEnum */
1040 p = make_header(param, RAP_WFileEnum2,
1041 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1043 PUTSTRING(p, base_path, 256);
1044 PUTSTRING(p, user, RAP_USERNAME_LEN);
1045 PUTWORD(p, 3); /* info level */
1046 PUTWORD(p, 0xFF00); /* buffer size */
1047 PUTDWORD(p, 0); /* zero out the resume key */
1048 PUTDWORD(p, 0); /* or is this one the resume key? */
1051 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1052 NULL, 0, 0xFF00, /* data, length, maxlen */
1053 &rparam, &rprcnt, /* return params, length */
1054 &rdata, &rdrcnt)) /* return data, length */
1056 int res = GETRES(rparam);
1058 if (res == 0 || res == ERRmoredata) {
1061 p = rparam + WORDSIZE; /* skip result */
1062 GETWORD(p, converter);
1066 for (i=0; i<count; i++) {
1067 int id, perms, locks;
1068 pstring fpath, fuser;
1073 GETSTRINGP(p, fpath, rdata, converter);
1074 GETSTRINGP(p, fuser, rdata, converter);
1076 fn(fpath, fuser, perms, locks, id);
1077 } /* BB fix ERRmoredata case to send resume request */
1079 DEBUG(4,("NetFileEnum2 res=%d\n", res));
1082 DEBUG(4,("NetFileEnum2 failed\n"));
1091 /****************************************************************************
1092 call a NetShareAdd - share/export directory on remote server
1093 ****************************************************************************/
1094 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1096 char *rparam = NULL;
1099 unsigned int rdrcnt,rprcnt;
1101 char param[WORDSIZE /* api number */
1102 +sizeof(RAP_WShareAdd_REQ) /* req string */
1103 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1104 +WORDSIZE /* info level */
1105 +WORDSIZE]; /* reserved word */
1107 /* offset to free format string section following fixed length data. */
1108 /* will be updated by PUTSTRINGP macro and will end up with total len */
1109 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
1110 + WORDSIZE /* share type */
1111 + DWORDSIZE /* comment pointer */
1112 + WORDSIZE /* permissions */
1113 + WORDSIZE /* max users */
1114 + WORDSIZE /* active users */
1115 + DWORDSIZE /* share path */
1116 + RAP_SPASSWD_LEN + 1; /* share password + pad */
1118 memset(param,'\0',sizeof(param));
1119 /* now send a SMBtrans command with api RNetShareAdd */
1120 p = make_header(param, RAP_WshareAdd,
1121 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1122 PUTWORD(p, 2); /* info level */
1123 PUTWORD(p, 0); /* reserved word 0 */
1126 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1127 PUTBYTE(p, 0); /* pad byte 0 */
1129 PUTWORD(p, sinfo->share_type);
1130 PUTSTRINGP(p, sinfo->comment, data, soffset);
1131 PUTWORD(p, sinfo->perms);
1132 PUTWORD(p, sinfo->maximum_users);
1133 PUTWORD(p, sinfo->active_users);
1134 PUTSTRINGP(p, sinfo->path, data, soffset);
1135 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1136 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1139 param, sizeof(param), 1024, /* Param, length, maxlen */
1140 data, soffset, sizeof(data), /* data, length, maxlen */
1141 &rparam, &rprcnt, /* return params, length */
1142 &rdata, &rdrcnt)) /* return data, length */
1144 res = rparam? SVAL(rparam,0) : -1;
1150 DEBUG(4,("NetShareAdd res=%d\n", res));
1154 DEBUG(4,("NetShareAdd failed\n"));
1162 /****************************************************************************
1163 call a NetShareDelete - unshare exported directory on remote server
1164 ****************************************************************************/
1165 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1167 char *rparam = NULL;
1170 unsigned int rdrcnt,rprcnt;
1172 char param[WORDSIZE /* api number */
1173 +sizeof(RAP_WShareDel_REQ) /* req string */
1174 +1 /* no ret string */
1175 +RAP_SHARENAME_LEN /* share to del */
1176 +WORDSIZE]; /* reserved word */
1179 /* now send a SMBtrans command with api RNetShareDelete */
1180 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1181 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1182 PUTWORD(p,0); /* reserved word MBZ on input */
1185 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1186 NULL, 0, 200, /* data, length, maxlen */
1187 &rparam, &rprcnt, /* return params, length */
1188 &rdata, &rdrcnt)) /* return data, length */
1190 res = GETRES(rparam);
1196 DEBUG(4,("NetShareDelete res=%d\n", res));
1200 DEBUG(4,("NetShareDelete failed\n"));
1208 /*************************************************************************
1210 * Function Name: cli_get_pdc_name
1212 * PURPOSE: Remotes a NetServerEnum API call to the current server
1213 * requesting the name of a server matching the server
1214 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1216 * Dependencies: none
1219 * cli - pointer to cli_state structure
1220 * workgroup - pointer to string containing name of domain
1221 * pdc_name - pointer to string that will contain PDC name
1222 * on successful return
1228 ************************************************************************/
1229 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1231 char *rparam = NULL;
1233 unsigned int rdrcnt,rprcnt;
1235 char param[WORDSIZE /* api number */
1236 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1237 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1238 +WORDSIZE /* info level */
1239 +WORDSIZE /* buffer size */
1240 +DWORDSIZE /* server type */
1241 +RAP_MACHNAME_LEN]; /* workgroup */
1246 /* send a SMBtrans command with api NetServerEnum */
1247 p = make_header(param, RAP_NetServerEnum2,
1248 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1249 PUTWORD(p, 1); /* info level */
1250 PUTWORD(p, CLI_BUFFER_SIZE);
1251 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1252 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1255 param, PTR_DIFF(p,param), 8, /* params, length, max */
1256 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1257 &rparam, &rprcnt, /* return params, return size */
1258 &rdata, &rdrcnt /* return data, return size */
1260 cli->rap_error = GETRES(rparam);
1263 * We only really care to copy a name if the
1264 * API succeeded and we got back a name.
1266 if (cli->rap_error == 0) {
1267 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1272 GETSTRING(p, pdc_name);
1275 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1276 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1287 /*************************************************************************
1289 * Function Name: cli_get_server_domain
1291 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1292 * requesting wksta_info_10 level information to determine
1293 * the domain the server belongs to. On success, this
1294 * routine sets the server_domain field in the cli_state structure
1295 * to the server's domain name.
1297 * Dependencies: none
1300 * cli - pointer to cli_state structure
1306 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1308 ************************************************************************/
1309 BOOL cli_get_server_domain(struct cli_state *cli)
1311 char *rparam = NULL;
1313 unsigned int rdrcnt,rprcnt;
1315 char param[WORDSIZE /* api number */
1316 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1317 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1318 +WORDSIZE /* info level */
1319 +WORDSIZE]; /* buffer size */
1322 /* send a SMBtrans command with api NetWkstaGetInfo */
1323 p = make_header(param, RAP_WWkstaGetInfo,
1324 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1325 PUTWORD(p, 10); /* info level */
1326 PUTWORD(p, CLI_BUFFER_SIZE);
1328 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1329 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1330 &rparam, &rprcnt, /* return params, return size */
1331 &rdata, &rdrcnt)) { /* return data, return size */
1332 res = GETRES(rparam);
1338 p = rparam + WORDSIZE;
1339 GETWORD(p, converter);
1341 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1342 GETSTRINGP(p, cli->server_domain, rdata, converter);
1353 /*************************************************************************
1355 * Function Name: cli_get_server_type
1357 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1358 * requesting server_info_1 level information to retrieve
1361 * Dependencies: none
1364 * cli - pointer to cli_state structure
1365 * pstype - pointer to uint32 to contain returned server type
1371 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1373 ************************************************************************/
1374 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1376 char *rparam = NULL;
1378 unsigned int rdrcnt,rprcnt;
1380 char param[WORDSIZE /* api number */
1381 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1382 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1383 +WORDSIZE /* info level */
1384 +WORDSIZE]; /* buffer size */
1387 /* send a SMBtrans command with api NetServerGetInfo */
1388 p = make_header(param, RAP_WserverGetInfo,
1389 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1390 PUTWORD(p, 1); /* info level */
1391 PUTWORD(p, CLI_BUFFER_SIZE);
1394 param, PTR_DIFF(p,param), 8, /* params, length, max */
1395 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1396 &rparam, &rprcnt, /* return params, return size */
1397 &rdata, &rdrcnt /* return data, return size */
1400 res = GETRES(rparam);
1402 if (res == 0 || res == ERRmoredata) {
1404 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1411 return(res == 0 || res == ERRmoredata);
1415 /*************************************************************************
1417 * Function Name: cli_ns_check_server_type
1419 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1420 * requesting server_info_0 level information of machines
1421 * matching the given server type. If the returned server
1422 * list contains the machine name contained in cli->desthost
1423 * then we conclude the server type checks out. This routine
1424 * is useful to retrieve list of server's of a certain
1425 * type when all you have is a null session connection and
1426 * can't remote API calls such as NetWkstaGetInfo or
1429 * Dependencies: none
1432 * cli - pointer to cli_state structure
1433 * workgroup - pointer to string containing domain
1434 * stype - server type
1440 ************************************************************************/
1441 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1443 char *rparam = NULL;
1445 unsigned int rdrcnt,rprcnt;
1447 char param[WORDSIZE /* api number */
1448 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1449 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1450 +WORDSIZE /* info level */
1451 +WORDSIZE /* buffer size */
1452 +DWORDSIZE /* server type */
1453 +RAP_MACHNAME_LEN]; /* workgroup */
1454 BOOL found_server = False;
1457 /* send a SMBtrans command with api NetServerEnum */
1458 p = make_header(param, RAP_NetServerEnum2,
1459 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1460 PUTWORD(p, 0); /* info level 0 */
1461 PUTWORD(p, CLI_BUFFER_SIZE);
1463 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1466 param, PTR_DIFF(p,param), 8, /* params, length, max */
1467 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1468 &rparam, &rprcnt, /* return params, return size */
1469 &rdata, &rdrcnt /* return data, return size */
1472 res = GETRES(rparam);
1473 cli->rap_error = res;
1475 if (res == 0 || res == ERRmoredata) {
1476 int i, converter, count;
1478 p = rparam + WORDSIZE;
1479 GETWORD(p, converter);
1483 for (i = 0;i < count;i++, p += 16) {
1484 char ret_server[RAP_MACHNAME_LEN];
1486 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1487 if (strequal(ret_server, cli->desthost)) {
1488 found_server = True;
1494 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1495 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1502 return found_server;
1506 /****************************************************************************
1507 perform a NetWkstaUserLogoff
1508 ****************************************************************************/
1509 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1511 char *rparam = NULL;
1514 unsigned int rdrcnt,rprcnt;
1515 char param[WORDSIZE /* api number */
1516 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1517 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1518 +RAP_USERNAME_LEN+1 /* user name+pad */
1519 +RAP_MACHNAME_LEN /* wksta name */
1520 +WORDSIZE /* buffer size */
1521 +WORDSIZE]; /* buffer size? */
1524 memset(param, 0, sizeof(param));
1526 /* send a SMBtrans command with api NetWkstaUserLogoff */
1527 p = make_header(param, RAP_WWkstaUserLogoff,
1528 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1529 PUTDWORD(p, 0); /* Null pointer */
1530 PUTDWORD(p, 0); /* Null pointer */
1531 fstrcpy(upperbuf, user);
1532 strupper_m(upperbuf);
1533 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1534 p++; /* strange format, but ok */
1535 fstrcpy(upperbuf, workstation);
1536 strupper_m(upperbuf);
1537 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1538 PUTWORD(p, CLI_BUFFER_SIZE);
1539 PUTWORD(p, CLI_BUFFER_SIZE);
1542 param, PTR_DIFF(p,param),1024, /* param, length, max */
1543 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1544 &rparam, &rprcnt, /* return params, return size */
1545 &rdata, &rdrcnt /* return data, return size */
1547 cli->rap_error = GETRES(rparam);
1549 if (cli->rap_error != 0) {
1550 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1556 return (cli->rap_error == 0);
1559 int cli_NetPrintQEnum(struct cli_state *cli,
1560 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1561 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1563 char param[WORDSIZE /* api number */
1564 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1565 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1566 +WORDSIZE /* info level */
1567 +WORDSIZE /* buffer size */
1568 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1570 char *rparam = NULL;
1572 unsigned int rprcnt, rdrcnt;
1576 memset(param, '\0',sizeof(param));
1577 p = make_header(param, RAP_WPrintQEnum,
1578 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1579 PUTWORD(p,2); /* Info level 2 */
1580 PUTWORD(p,0xFFE0); /* Return buffer size */
1581 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1584 param, PTR_DIFF(p,param),1024,
1585 NULL, 0, CLI_BUFFER_SIZE,
1588 res = GETRES(rparam);
1589 cli->rap_error = res;
1591 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1596 if (res == 0 || res == ERRmoredata) {
1597 int i, converter, count;
1599 p = rparam + WORDSIZE;
1600 GETWORD(p, converter);
1604 for (i=0;i<count;i++) {
1605 pstring qname, sep_file, print_proc, dest, parms, comment;
1606 uint16 jobcount, priority, start_time, until_time, status;
1608 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1610 GETWORD(p, priority);
1611 GETWORD(p, start_time);
1612 GETWORD(p, until_time);
1613 GETSTRINGP(p, sep_file, rdata, converter);
1614 GETSTRINGP(p, print_proc, rdata, converter);
1615 GETSTRINGP(p, dest, rdata, converter);
1616 GETSTRINGP(p, parms, rdata, converter);
1617 GETSTRINGP(p, parms, comment, converter);
1619 GETWORD(p, jobcount);
1621 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1622 dest, parms, comment, status, jobcount);
1626 for (j=0;j<jobcount;j++) {
1627 uint16 jid, pos, fsstatus;
1628 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1629 unsigned int submitted, jsize;
1632 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1634 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1635 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1636 GETSTRINGP(p, jparms, rdata, converter);
1638 GETWORD(p, fsstatus);
1639 GETSTRINGP(p, jstatus, rdata, converter);
1640 GETDWORD(p, submitted);
1642 GETSTRINGP(p, jcomment, rdata, converter);
1644 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1645 jstatus, submitted, jsize, jcomment);
1650 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1653 DEBUG(4,("NetPrintQEnum no data returned\n"));
1662 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1663 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1664 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1666 char param[WORDSIZE /* api number */
1667 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1668 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1669 +RAP_SHARENAME_LEN /* printer name */
1670 +WORDSIZE /* info level */
1671 +WORDSIZE /* buffer size */
1672 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1674 char *rparam = NULL;
1676 unsigned int rprcnt, rdrcnt;
1680 memset(param, '\0',sizeof(param));
1681 p = make_header(param, RAP_WPrintQGetInfo,
1682 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1683 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1684 PUTWORD(p, 2); /* Info level 2 */
1685 PUTWORD(p,0xFFE0); /* Return buffer size */
1686 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1689 param, PTR_DIFF(p,param),1024,
1690 NULL, 0, CLI_BUFFER_SIZE,
1693 res = GETRES(rparam);
1694 cli->rap_error = res;
1696 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1701 if (res == 0 || res == ERRmoredata) {
1702 int rsize, converter;
1703 pstring qname, sep_file, print_proc, dest, parms, comment;
1704 uint16 jobcount, priority, start_time, until_time, status;
1706 p = rparam + WORDSIZE;
1707 GETWORD(p, converter);
1711 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1713 GETWORD(p, priority);
1714 GETWORD(p, start_time);
1715 GETWORD(p, until_time);
1716 GETSTRINGP(p, sep_file, rdata, converter);
1717 GETSTRINGP(p, print_proc, rdata, converter);
1718 GETSTRINGP(p, dest, rdata, converter);
1719 GETSTRINGP(p, parms, rdata, converter);
1720 GETSTRINGP(p, comment, rdata, converter);
1722 GETWORD(p, jobcount);
1723 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1724 dest, parms, comment, status, jobcount);
1727 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1728 uint16 jid, pos, fsstatus;
1729 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1730 unsigned int submitted, jsize;
1733 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1735 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1736 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1737 GETSTRINGP(p, jparms, rdata, converter);
1739 GETWORD(p, fsstatus);
1740 GETSTRINGP(p, jstatus, rdata, converter);
1741 GETDWORD(p, submitted);
1743 GETSTRINGP(p, jcomment, rdata, converter);
1745 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1746 jstatus, submitted, jsize, jcomment);
1750 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1753 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1762 /****************************************************************************
1763 call a NetServiceEnum - list running services on a different host
1764 ****************************************************************************/
1765 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1767 char param[WORDSIZE /* api number */
1768 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1769 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1770 +WORDSIZE /* info level */
1771 +WORDSIZE]; /* buffer size */
1773 char *rparam = NULL;
1775 unsigned int rprcnt, rdrcnt;
1779 memset(param, '\0', sizeof(param));
1780 p = make_header(param, RAP_WServiceEnum,
1781 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1782 PUTWORD(p,2); /* Info level 2 */
1783 PUTWORD(p,0xFFE0); /* Return buffer size */
1786 param, PTR_DIFF(p,param),8,
1787 NULL, 0, 0xFFE0 /* data area size */,
1790 res = GETRES(rparam);
1791 cli->rap_error = res;
1792 if(cli->rap_error == 234)
1793 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1794 else if (cli->rap_error != 0) {
1795 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1800 if (res == 0 || res == ERRmoredata) {
1801 int i, converter, count;
1803 p = rparam + WORDSIZE; /* skip result */
1804 GETWORD(p, converter);
1807 for (i=0,p=rdata;i<count;i++) {
1809 char servicename[RAP_SRVCNAME_LEN];
1811 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1812 p+=8; /* pass status words */
1813 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1815 fn(servicename, comment, cli); /* BB add status too */
1818 DEBUG(4,("NetServiceEnum res=%d\n", res));
1821 DEBUG(4,("NetServiceEnum no data returned\n"));
1831 /****************************************************************************
1832 call a NetSessionEnum - list workstations with sessions to an SMB server
1833 ****************************************************************************/
1834 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1836 char param[WORDSIZE /* api number */
1837 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1838 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1839 +WORDSIZE /* info level */
1840 +WORDSIZE]; /* buffer size */
1842 char *rparam = NULL;
1844 unsigned int rprcnt, rdrcnt;
1847 memset(param, '\0', sizeof(param));
1848 p = make_header(param, RAP_WsessionEnum,
1849 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1850 PUTWORD(p,2); /* Info level 2 */
1851 PUTWORD(p,0xFF); /* Return buffer size */
1854 param, PTR_DIFF(p,param),8,
1855 NULL, 0, CLI_BUFFER_SIZE,
1858 res = GETRES(rparam);
1859 cli->rap_error = res;
1861 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1866 if (res == 0 || res == ERRmoredata) {
1867 int i, converter, count;
1869 p = rparam + WORDSIZE;
1870 GETWORD(p, converter);
1873 for (i=0,p=rdata;i<count;i++) {
1874 pstring wsname, username, clitype_name;
1875 uint16 num_conns, num_opens, num_users;
1876 unsigned int sess_time, idle_time, user_flags;
1878 GETSTRINGP(p, wsname, rdata, converter);
1879 GETSTRINGP(p, username, rdata, converter);
1880 GETWORD(p, num_conns);
1881 GETWORD(p, num_opens);
1882 GETWORD(p, num_users);
1883 GETDWORD(p, sess_time);
1884 GETDWORD(p, idle_time);
1885 GETDWORD(p, user_flags);
1886 GETSTRINGP(p, clitype_name, rdata, converter);
1888 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1889 idle_time, user_flags, clitype_name);
1893 DEBUG(4,("NetSessionEnum res=%d\n", res));
1896 DEBUG(4,("NetSesssionEnum no data returned\n"));
1905 /****************************************************************************
1906 Call a NetSessionGetInfo - get information about other session to an SMB server.
1907 ****************************************************************************/
1909 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1911 char param[WORDSIZE /* api number */
1912 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1913 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1914 +RAP_MACHNAME_LEN /* wksta name */
1915 +WORDSIZE /* info level */
1916 +WORDSIZE]; /* buffer size */
1918 char *rparam = NULL;
1920 unsigned int rprcnt, rdrcnt;
1924 memset(param, '\0', sizeof(param));
1925 p = make_header(param, RAP_WsessionGetInfo,
1926 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1927 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1928 PUTWORD(p,2); /* Info level 2 */
1929 PUTWORD(p,0xFF); /* Return buffer size */
1932 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1933 NULL, 0, CLI_BUFFER_SIZE,
1936 cli->rap_error = SVAL(rparam,0);
1937 if (cli->rap_error != 0) {
1938 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1943 res = GETRES(rparam);
1945 if (res == 0 || res == ERRmoredata) {
1946 int rsize, converter;
1947 pstring wsname, username, clitype_name;
1948 uint16 num_conns, num_opens, num_users;
1949 unsigned int sess_time, idle_time, user_flags;
1951 p = rparam + WORDSIZE;
1952 GETWORD(p, converter);
1956 GETSTRINGP(p, wsname, rdata, converter);
1957 GETSTRINGP(p, username, rdata, converter);
1958 GETWORD(p, num_conns);
1959 GETWORD(p, num_opens);
1960 GETWORD(p, num_users);
1961 GETDWORD(p, sess_time);
1962 GETDWORD(p, idle_time);
1963 GETDWORD(p, user_flags);
1964 GETSTRINGP(p, clitype_name, rdata, converter);
1966 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1967 idle_time, user_flags, clitype_name);
1969 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1972 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1981 /****************************************************************************
1982 call a NetSessionDel - close a session to an SMB server
1983 ****************************************************************************/
1984 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1986 char param[WORDSIZE /* api number */
1987 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1988 +1 /* no return string */
1989 +RAP_MACHNAME_LEN /* workstation name */
1990 +WORDSIZE]; /* reserved (0) */
1992 char *rparam = NULL;
1994 unsigned int rprcnt, rdrcnt;
1997 memset(param, '\0', sizeof(param));
1998 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1999 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2000 PUTWORD(p,0); /* reserved word of 0 */
2002 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2003 NULL, 0, 200, /* data, length, maxlen */
2004 &rparam, &rprcnt, /* return params, length */
2005 &rdata, &rdrcnt)) /* return data, length */
2007 res = GETRES(rparam);
2008 cli->rap_error = res;
2014 DEBUG(4,("NetFileClose2 res=%d\n", res));
2018 DEBUG(4,("NetFileClose2 failed\n"));
2028 int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*fn)(uint16 conid, uint16 contype, uint16 numopens, uint16 numusers, uint32 contime, const char *username, const char *netname))
2030 char param[WORDSIZE /* api number */
2031 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
2032 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
2033 +RAP_MACHNAME_LEN /* wksta name */
2034 +WORDSIZE /* info level */
2035 +WORDSIZE]; /* buffer size */
2037 char *rparam = NULL;
2039 unsigned int rprcnt, rdrcnt;
2042 memset(param, '\0', sizeof(param));
2043 p = make_header(param, RAP_WconnectionEnum,
2044 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2045 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2046 PUTWORD(p,1); /* Info level 1 */
2047 PUTWORD(p,0xFFE0); /* Return buffer size */
2050 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2051 NULL, 0, CLI_BUFFER_SIZE,
2054 res = GETRES(rparam);
2055 cli->rap_error = res;
2057 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2061 if (res == 0 || res == ERRmoredata) {
2062 int i, converter, count;
2064 p = rparam + WORDSIZE;
2065 GETWORD(p, converter);
2068 for (i=0,p=rdata;i<count;i++) {
2069 pstring netname, username;
2070 uint16 conn_id, conn_type, num_opens, num_users;
2071 unsigned int conn_time;
2074 GETWORD(p,conn_type);
2075 GETWORD(p,num_opens);
2076 GETWORD(p,num_users);
2077 GETDWORD(p,conn_time);
2078 GETSTRINGP(p, username, rdata, converter);
2079 GETSTRINGP(p, netname, rdata, converter);
2081 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2086 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2089 DEBUG(4,("NetConnectionEnum no data returned\n"));