2 Samba Unix/Linux SMB client library
4 More client RAP (SMB Remote Procedure Calls) functions
5 Copyright (C) 2001 Steve French (sfrench@us.ibm.com)
6 Copyright (C) 2001 Jim McDonough (jmcd@us.ibm.com)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /*****************************************************/
26 /* Additional RAP functionality */
28 /* RAP is the original SMB RPC, documented */
29 /* by Microsoft and X/Open in the 1990s and */
30 /* supported by most SMB/CIFS servers although */
31 /* it is unlikely that any one implementation */
32 /* supports all RAP command codes since some */
33 /* are quite obsolete and a few are specific */
34 /* to a particular network operating system */
36 /* Although it has largely been replaced */
37 /* for complex remote admistration and management */
38 /* (of servers) by the relatively newer */
39 /* DCE/RPC based remote API (which better handles */
40 /* large >64K data structures), there are many */
41 /* important administrative and resource location */
42 /* tasks and user tasks (e.g. password change) */
43 /* that are performed via RAP. */
45 /* Although a few of the RAP calls are implemented */
46 /* in the Samba client library already (clirap.c) */
47 /* the new ones are in clirap2.c for easy patching */
48 /* and integration and a corresponding header */
49 /* file, rap.h, has been created. */
51 /* This is based on data from the CIFS spec */
52 /* and the LAN Server and LAN Manager */
53 /* Programming Reference books and published */
54 /* RAP document and CIFS forum postings and */
55 /* lots of trial and error */
57 /* Function names changed from API_ (as they are */
58 /* in the CIFS specification) to RAP_ in order */
59 /* to avoid confusion with other API calls */
60 /* sent via DCE RPC */
62 /*****************************************************/
64 /*****************************************************/
66 /* cifsrap.c already includes support for: */
68 /* WshareEnum ( API number 0, level 1) */
69 /* NetServerEnum2 (API num 104, level 1) */
70 /* WWkstaUserLogon (132) */
71 /* SamOEMchgPasswordUser2_P (214) */
73 /* cifsprint.c already includes support for: */
75 /* WPrintJobEnum (API num 76, level 2) */
76 /* WPrintJobDel (API num 81) */
78 /*****************************************************/
87 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
88 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
89 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
90 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
91 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
92 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
93 #define GETRES(p) p ? SVAL(p,0) : -1
94 /* put string s at p with max len n and increment p past string */
95 #define PUTSTRING(p,s,n) do {\
96 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
97 p = skip_string(p,1);\
99 /* put string s and p, using fixed len l, and increment p by l */
100 #define PUTSTRINGF(p,s,l) do {\
101 push_ascii(p,s?s:"",l,STR_TERMINATE);\
104 /* put string pointer at p, supplying offset o from rdata r, store */
105 /* dword offset at p, increment p by 4 and o by length of s. This */
106 /* means on the first call, you must calc the offset yourself! */
107 #define PUTSTRINGP(p,s,r,o) do {\
109 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
112 } else PUTDWORD(p,0);\
114 /* get asciiz string s from p, increment p past string */
115 #define GETSTRING(p,s) do {\
116 pull_ascii_pstring(s,p);\
117 p = skip_string(p,1);\
119 /* get fixed length l string s from p, increment p by l */
120 #define GETSTRINGF(p,s,l) do {\
121 pull_ascii_pstring(s,p);\
124 /* get string s from offset (obtained at p) from rdata r - converter c */
125 #define GETSTRINGP(p,s,r,c) do {\
128 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
129 pull_ascii_pstring(s, off?(r+off-c):"");\
132 static char *make_header(char *param, uint16 apinum, char *reqfmt, char *datafmt)
134 PUTWORD(param,apinum);
136 PUTSTRING(param,reqfmt,0);
141 PUTSTRING(param,datafmt,0);
149 /****************************************************************************
150 call a NetGroupDelete - delete user group from remote server
151 ****************************************************************************/
152 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
157 int rdrcnt,rprcnt, res;
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 int rdrcnt,rprcnt,res;
209 char param[WORDSIZE /* api number */
210 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
211 +sizeof(RAP_GROUP_INFO_L1) /* return string */
212 +WORDSIZE /* info level */
213 +WORDSIZE]; /* reserved word */
217 /* offset into data of free format strings. Will be updated */
218 /* by PUTSTRINGP macro and end up with total data length. */
219 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
221 /* now send a SMBtrans command with api WGroupAdd */
223 p = make_header(param, RAP_WGroupAdd,
224 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
225 PUTWORD(p, 1); /* info level */
226 PUTWORD(p, 0); /* reserved word 0 */
229 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
230 PUTBYTE(p, 0); /* pad byte 0 */
231 PUTSTRINGP(p, grinfo->comment, data, soffset);
234 param, sizeof(param), 1024, /* Param, length, maxlen */
235 data, soffset, sizeof(data), /* data, length, maxlen */
236 &rparam, &rprcnt, /* return params, length */
237 &rdata, &rdrcnt)) /* return data, length */
239 res = GETRES(rparam);
243 } else if ((res == 5) || (res == 65)) {
244 DEBUG(1, ("Access Denied\n"));
246 else if (res == 2223) {
247 DEBUG (1, ("Group already exists\n"));
250 DEBUG(4,("NetGroupAdd res=%d\n", res));
254 DEBUG(4,("NetGroupAdd failed\n"));
263 /****************************************************************************
264 call a NetGroupEnum - try and list user groups on a different host
265 ****************************************************************************/
266 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
268 char param[WORDSIZE /* api number */
269 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
270 +sizeof(RAP_GROUP_INFO_L1) /* return string */
271 +WORDSIZE /* info level */
272 +WORDSIZE]; /* buffer size */
280 memset(param, '\0', sizeof(param));
281 p = make_header(param, RAP_WGroupEnum,
282 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
283 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
284 PUTWORD(p,0xFFE0); /* Return buffer size */
287 param, PTR_DIFF(p,param),8,
288 NULL, 0, 0xFFE0 /* data area size */,
291 res = GETRES(rparam);
292 cli->rap_error = res;
293 if(cli->rap_error == 234)
294 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
295 else if (cli->rap_error != 0) {
296 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
301 if (res == 0 || res == ERRmoredata) {
302 int i, converter, count;
304 p = rparam + WORDSIZE; /* skip result */
305 GETWORD(p, converter);
308 for (i=0,p=rdata;i<count;i++) {
310 char groupname[RAP_GROUPNAME_LEN];
312 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
314 GETSTRINGP(p, comment, rdata, converter);
316 fn(groupname, comment, cli);
319 DEBUG(4,("NetGroupEnum res=%d\n", res));
322 DEBUG(4,("NetGroupEnum no data returned\n"));
331 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
336 int rdrcnt,rprcnt,res;
337 char param[WORDSIZE /* api number */
338 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
339 +1 /* no ret string */
340 +RAP_GROUPNAME_LEN /* group name */
341 +RAP_USERNAME_LEN]; /* user to del */
343 /* now send a SMBtrans command with api GroupMemberAdd */
344 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
345 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
346 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
349 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
350 NULL, 0, 200, /* data, length, maxlen */
351 &rparam, &rprcnt, /* return params, length */
352 &rdata, &rdrcnt)) /* return data, length */
354 res = GETRES(rparam);
361 DEBUG(1, ("Access Denied\n"));
364 DEBUG(1, ("Not supported by server\n"));
367 DEBUG(1, ("Group does not exist\n"));
370 DEBUG(1, ("User does not exist\n"));
373 DEBUG(1, ("User is not in group\n"));
376 DEBUG(4,("NetGroupDelUser res=%d\n", res));
380 DEBUG(4,("NetGroupDelUser failed\n"));
389 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
394 int rdrcnt,rprcnt,res;
395 char param[WORDSIZE /* api number */
396 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
397 +1 /* no ret string */
398 +RAP_GROUPNAME_LEN /* group name */
399 +RAP_USERNAME_LEN]; /* user to add */
401 /* now send a SMBtrans command with api GroupMemberAdd */
402 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
403 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
404 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
407 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
408 NULL, 0, 200, /* data, length, maxlen */
409 &rparam, &rprcnt, /* return params, length */
410 &rdata, &rdrcnt)) /* return data, length */
412 res = GETRES(rparam);
419 DEBUG(1, ("Access Denied\n"));
422 DEBUG(1, ("Not supported by server\n"));
425 DEBUG(1, ("Group does not exist\n"));
428 DEBUG(1, ("User does not exist\n"));
431 DEBUG(4,("NetGroupAddUser res=%d\n", res));
435 DEBUG(4,("NetGroupAddUser failed\n"));
445 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
452 char param[WORDSIZE /* api number */
453 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
454 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
455 +RAP_GROUPNAME_LEN /* group name */
456 +WORDSIZE /* info level */
457 +WORDSIZE]; /* buffer size */
459 /* now send a SMBtrans command with api GroupGetUsers */
460 p = make_header(param, RAP_WGroupGetUsers,
461 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
462 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
463 PUTWORD(p,0); /* info level 0 */
464 PUTWORD(p,0xFFE0); /* return buffer size */
467 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
468 NULL, 0, CLI_BUFFER_SIZE,
471 res = GETRES(rparam);
472 cli->rap_error = res;
474 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
478 if (res == 0 || res == ERRmoredata) {
479 int i, converter, count;
481 p = rparam +WORDSIZE;
482 GETWORD(p, converter);
485 for (i=0,p=rdata; i<count; i++) {
486 GETSTRINGF(p, username, RAP_USERNAME_LEN);
490 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
493 DEBUG(4,("NetGroupGetUsers no data returned\n"));
500 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
507 char param[WORDSIZE /* api number */
508 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
509 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
510 +RAP_USERNAME_LEN /* user name */
511 +WORDSIZE /* info level */
512 +WORDSIZE]; /* buffer size */
514 /* now send a SMBtrans command with api GroupGetUsers */
515 p = make_header(param, RAP_WUserGetGroups,
516 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
517 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
518 PUTWORD(p,0); /* info level 0 */
519 PUTWORD(p,0xFFE0); /* return buffer size */
522 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
523 NULL, 0, CLI_BUFFER_SIZE,
526 res = GETRES(rparam);
527 cli->rap_error = res;
529 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
533 if (res == 0 || res == ERRmoredata) {
534 int i, converter, count;
536 p = rparam +WORDSIZE;
537 GETWORD(p, converter);
540 for (i=0,p=rdata; i<count; i++) {
541 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
542 fn(groupname, state);
545 DEBUG(4,("NetUserGetGroups res=%d\n", res));
548 DEBUG(4,("NetUserGetGroups no data returned\n"));
556 /****************************************************************************
557 call a NetUserDelete - delete user from remote server
558 ****************************************************************************/
559 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
564 int rdrcnt,rprcnt, res;
565 char param[WORDSIZE /* api number */
566 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
567 +1 /* no ret string */
568 +RAP_USERNAME_LEN /* user to del */
569 +WORDSIZE]; /* reserved word */
571 /* now send a SMBtrans command with api UserDel */
572 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
573 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
574 PUTWORD(p,0); /* reserved word MBZ on input */
577 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
578 NULL, 0, 200, /* data, length, maxlen */
579 &rparam, &rprcnt, /* return params, length */
580 &rdata, &rdrcnt)) /* return data, length */
582 res = GETRES(rparam);
587 else if ((res == 5) || (res == 65)) {
588 DEBUG(1, ("Access Denied\n"));
590 else if (res == 2221) {
591 DEBUG (1, ("User does not exist\n"));
594 DEBUG(4,("NetUserDelete res=%d\n", res));
598 DEBUG(4,("NetUserDelete failed\n"));
607 /****************************************************************************
608 call a NetUserAdd - add user to remote server
609 ****************************************************************************/
610 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
618 int rdrcnt,rprcnt,res;
619 char param[WORDSIZE /* api number */
620 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
621 +sizeof(RAP_USER_INFO_L1) /* data string */
622 +WORDSIZE /* info level */
623 +WORDSIZE /* buffer length */
624 +WORDSIZE]; /* reserved */
627 /* offset into data of free format strings. Will be updated */
628 /* by PUTSTRINGP macro and end up with total data length. */
629 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
630 + RAP_UPASSWD_LEN /* password */
631 + DWORDSIZE /* password age */
632 + WORDSIZE /* privilege */
633 + DWORDSIZE /* home dir ptr */
634 + DWORDSIZE /* comment ptr */
635 + WORDSIZE /* flags */
636 + DWORDSIZE; /* login script ptr*/
638 /* now send a SMBtrans command with api NetUserAdd */
639 p = make_header(param, RAP_WUserAdd2,
640 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
641 PUTWORD(p, 1); /* info level */
643 PUTWORD(p, 0); /* pwencrypt */
644 if(userinfo->passwrd)
645 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
647 PUTWORD(p, 0); /* password length */
650 memset(data, '\0', soffset);
652 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
653 PUTBYTE(p, 0); /* pad byte 0 */
654 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
655 PUTDWORD(p, 0); /* pw age - n.a. on user add */
656 PUTWORD(p, userinfo->priv);
657 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
658 PUTSTRINGP(p, userinfo->comment, data, soffset);
659 PUTWORD(p, userinfo->userflags);
660 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
663 param, sizeof(param), 1024, /* Param, length, maxlen */
664 data, soffset, sizeof(data), /* data, length, maxlen */
665 &rparam, &rprcnt, /* return params, length */
666 &rdata, &rdrcnt)) /* return data, length */
668 res = GETRES(rparam);
673 else if ((res == 5) || (res == 65)) {
674 DEBUG(1, ("Access Denied\n"));
676 else if (res == 2224) {
677 DEBUG (1, ("User already exists\n"));
680 DEBUG(4,("NetUserAdd res=%d\n", res));
684 DEBUG(4,("NetUserAdd failed\n"));
693 /****************************************************************************
694 call a NetUserEnum - try and list users on a different host
695 ****************************************************************************/
696 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
698 char param[WORDSIZE /* api number */
699 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
700 +sizeof(RAP_USER_INFO_L1) /* return string */
701 +WORDSIZE /* info level */
702 +WORDSIZE]; /* buffer size */
710 memset(param, '\0', sizeof(param));
711 p = make_header(param, RAP_WUserEnum,
712 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
713 PUTWORD(p,1); /* Info level 1 */
714 PUTWORD(p,0xFF00); /* Return buffer size */
716 /* BB Fix handling of large numbers of users to be returned */
718 param, PTR_DIFF(p,param),8,
719 NULL, 0, CLI_BUFFER_SIZE,
722 res = GETRES(rparam);
723 cli->rap_error = res;
724 if (cli->rap_error != 0) {
725 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
729 if (res == 0 || res == ERRmoredata) {
730 int i, converter, count;
731 char username[RAP_USERNAME_LEN];
732 char userpw[RAP_UPASSWD_LEN];
733 pstring comment, homedir, logonscript;
734 int pwage, priv, flags;
736 p = rparam + WORDSIZE; /* skip result */
737 GETWORD(p, converter);
740 for (i=0,p=rdata;i<count;i++) {
741 GETSTRINGF(p, username, RAP_USERNAME_LEN);
743 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
744 GETDWORD(p, pwage); /* password age */
745 GETWORD(p, priv); /* 0=guest, 1=user, 2=admin */
746 GETSTRINGP(p, homedir, rdata, converter);
747 GETSTRINGP(p, comment, rdata, converter);
749 GETSTRINGP(p, logonscript, rdata, converter);
751 fn(username, comment, homedir, logonscript, cli);
754 DEBUG(4,("NetUserEnum res=%d\n", res));
757 DEBUG(4,("NetUserEnum no data returned\n"));
766 /****************************************************************************
767 call a NetFileClose2 - close open file on another session to server
768 ****************************************************************************/
769 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
775 char param[WORDSIZE /* api number */
776 +sizeof(RAP_WFileClose2_REQ) /* req string */
777 +1 /* no ret string */
778 +DWORDSIZE]; /* file ID */
781 /* now send a SMBtrans command with api RNetShareEnum */
782 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
783 PUTDWORD(p, file_id);
786 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
787 NULL, 0, 200, /* data, length, maxlen */
788 &rparam, &rprcnt, /* return params, length */
789 &rdata, &rdrcnt)) /* return data, length */
791 res = GETRES(rparam);
795 } else if (res == 2314){
796 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
798 DEBUG(4,("NetFileClose2 res=%d\n", res));
802 DEBUG(4,("NetFileClose2 failed\n"));
811 /****************************************************************************
812 call a NetFileGetInfo - get information about server file opened from other
814 ****************************************************************************/
815 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
820 int rdrcnt,rprcnt, res;
821 char param[WORDSIZE /* api number */
822 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
823 +sizeof(RAP_FILE_INFO_L3) /* return string */
824 +DWORDSIZE /* file ID */
825 +WORDSIZE /* info level */
826 +WORDSIZE]; /* buffer size */
828 /* now send a SMBtrans command with api RNetShareEnum */
829 p = make_header(param, RAP_WFileGetInfo2,
830 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
831 PUTDWORD(p, file_id);
832 PUTWORD(p, 3); /* info level */
833 PUTWORD(p, 0x1000); /* buffer size */
835 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
836 NULL, 0, 0x1000, /* data, length, maxlen */
837 &rparam, &rprcnt, /* return params, length */
838 &rdata, &rdrcnt)) /* return data, length */
840 res = GETRES(rparam);
841 if (res == 0 || res == ERRmoredata) {
842 int converter,id, perms, locks;
843 pstring fpath, fuser;
845 p = rparam + WORDSIZE; /* skip result */
846 GETWORD(p, converter);
852 GETSTRINGP(p, fpath, rdata, converter);
853 GETSTRINGP(p, fuser, rdata, converter);
855 fn(fpath, fuser, perms, locks, id);
857 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
861 DEBUG(4,("NetFileGetInfo2 failed\n"));
870 /****************************************************************************
871 * Call a NetFileEnum2 - list open files on an SMB server
873 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
874 * server listing the files open via the network (and their
875 * corresponding open instance ids)
880 * cli - pointer to cli_state structure
881 * user - if present, return only files opened by this remote user
882 * base_path - if present, return only files opened below this
884 * fn - display function to invoke for each entry in the result
891 ****************************************************************************/
892 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
898 char param[WORDSIZE /* api number */
899 +sizeof(RAP_WFileEnum2_REQ) /* req string */
900 +sizeof(RAP_FILE_INFO_L3) /* return string */
901 +256 /* base path (opt) */
902 +RAP_USERNAME_LEN /* user name (opt) */
903 +WORDSIZE /* info level */
904 +WORDSIZE /* buffer size */
905 +DWORDSIZE /* resume key ? */
906 +DWORDSIZE]; /* resume key ? */
909 /* now send a SMBtrans command with api RNetShareEnum */
910 p = make_header(param, RAP_WFileEnum2,
911 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
913 PUTSTRING(p, base_path, 256);
914 PUTSTRING(p, user, RAP_USERNAME_LEN);
915 PUTWORD(p, 3); /* info level */
916 PUTWORD(p, 0xFF00); /* buffer size */
917 PUTDWORD(p, 0); /* zero out the resume key */
918 PUTDWORD(p, 0); /* or is this one the resume key? */
921 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
922 NULL, 0, 0xFF00, /* data, length, maxlen */
923 &rparam, &rprcnt, /* return params, length */
924 &rdata, &rdrcnt)) /* return data, length */
926 int res = GETRES(rparam);
928 if (res == 0 || res == ERRmoredata) {
931 p = rparam + WORDSIZE; /* skip result */
932 GETWORD(p, converter);
936 for (i=0; i<count; i++) {
937 int id, perms, locks;
938 pstring fpath, fuser;
943 GETSTRINGP(p, fpath, rdata, converter);
944 GETSTRINGP(p, fuser, rdata, converter);
946 fn(fpath, fuser, perms, locks, id);
947 } /* BB fix ERRmoredata case to send resume request */
949 DEBUG(4,("NetFileEnum2 res=%d\n", res));
952 DEBUG(4,("NetFileEnum2 failed\n"));
961 /****************************************************************************
962 call a NetShareAdd - share/export directory on remote server
963 ****************************************************************************/
964 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
969 int rdrcnt,rprcnt,res;
970 char param[WORDSIZE /* api number */
971 +sizeof(RAP_WShareAdd_REQ) /* req string */
972 +sizeof(RAP_SHARE_INFO_L2) /* return string */
973 +WORDSIZE /* info level */
974 +WORDSIZE]; /* reserved word */
976 /* offset to free format string section following fixed length data. */
977 /* will be updated by PUTSTRINGP macro and will end up with total len */
978 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
979 + WORDSIZE /* share type */
980 + DWORDSIZE /* comment pointer */
981 + WORDSIZE /* permissions */
982 + WORDSIZE /* max users */
983 + WORDSIZE /* active users */
984 + DWORDSIZE /* share path */
985 + RAP_SPASSWD_LEN + 1; /* share password + pad */
987 memset(param,'\0',sizeof(param));
988 /* now send a SMBtrans command with api RNetShareAdd */
989 p = make_header(param, RAP_WshareAdd,
990 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
991 PUTWORD(p, 2); /* info level */
992 PUTWORD(p, 0); /* reserved word 0 */
995 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
996 PUTBYTE(p, 0); /* pad byte 0 */
998 PUTWORD(p, sinfo->share_type);
999 PUTSTRINGP(p, sinfo->comment, data, soffset);
1000 PUTWORD(p, sinfo->perms);
1001 PUTWORD(p, sinfo->maximum_users);
1002 PUTWORD(p, sinfo->active_users);
1003 PUTSTRINGP(p, sinfo->path, data, soffset);
1004 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1005 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1008 param, sizeof(param), 1024, /* Param, length, maxlen */
1009 data, soffset, sizeof(data), /* data, length, maxlen */
1010 &rparam, &rprcnt, /* return params, length */
1011 &rdata, &rdrcnt)) /* return data, length */
1013 res = rparam? SVAL(rparam,0) : -1;
1019 DEBUG(4,("NetShareAdd res=%d\n", res));
1023 DEBUG(4,("NetShareAdd failed\n"));
1031 /****************************************************************************
1032 call a NetShareDelete - unshare exported directory on remote server
1033 ****************************************************************************/
1034 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1036 char *rparam = NULL;
1039 int rdrcnt,rprcnt, res;
1040 char param[WORDSIZE /* api number */
1041 +sizeof(RAP_WShareDel_REQ) /* req string */
1042 +1 /* no ret string */
1043 +RAP_SHARENAME_LEN /* share to del */
1044 +WORDSIZE]; /* reserved word */
1047 /* now send a SMBtrans command with api RNetShareDelete */
1048 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1049 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1050 PUTWORD(p,0); /* reserved word MBZ on input */
1053 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1054 NULL, 0, 200, /* data, length, maxlen */
1055 &rparam, &rprcnt, /* return params, length */
1056 &rdata, &rdrcnt)) /* return data, length */
1058 res = GETRES(rparam);
1064 DEBUG(4,("NetShareDelete res=%d\n", res));
1068 DEBUG(4,("NetShareDelete failed\n"));
1076 /*************************************************************************
1078 * Function Name: cli_get_pdc_name
1080 * PURPOSE: Remotes a NetServerEnum API call to the current server
1081 * requesting the name of a server matching the server
1082 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1084 * Dependencies: none
1087 * cli - pointer to cli_state structure
1088 * workgroup - pointer to string containing name of domain
1089 * pdc_name - pointer to string that will contain PDC name
1090 * on successful return
1096 ************************************************************************/
1097 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1099 char *rparam = NULL;
1103 char param[WORDSIZE /* api number */
1104 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1105 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1106 +WORDSIZE /* info level */
1107 +WORDSIZE /* buffer size */
1108 +DWORDSIZE /* server type */
1109 +RAP_MACHNAME_LEN]; /* workgroup */
1114 /* send a SMBtrans command with api NetServerEnum */
1115 p = make_header(param, RAP_NetServerEnum2,
1116 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1117 PUTWORD(p, 1); /* info level */
1118 PUTWORD(p, CLI_BUFFER_SIZE);
1119 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1120 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1123 param, PTR_DIFF(p,param), 8, /* params, length, max */
1124 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1125 &rparam, &rprcnt, /* return params, return size */
1126 &rdata, &rdrcnt /* return data, return size */
1128 cli->rap_error = GETRES(rparam);
1131 * We only really care to copy a name if the
1132 * API succeeded and we got back a name.
1134 if (cli->rap_error == 0) {
1135 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1140 GETSTRING(p, pdc_name);
1143 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1144 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1155 /*************************************************************************
1157 * Function Name: cli_get_server_domain
1159 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1160 * requesting wksta_info_10 level information to determine
1161 * the domain the server belongs to. On success, this
1162 * routine sets the server_domain field in the cli_state structure
1163 * to the server's domain name.
1165 * Dependencies: none
1168 * cli - pointer to cli_state structure
1174 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1176 ************************************************************************/
1177 BOOL cli_get_server_domain(struct cli_state *cli)
1179 char *rparam = NULL;
1183 char param[WORDSIZE /* api number */
1184 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1185 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1186 +WORDSIZE /* info level */
1187 +WORDSIZE]; /* buffer size */
1190 /* send a SMBtrans command with api NetWkstaGetInfo */
1191 p = make_header(param, RAP_WWkstaGetInfo,
1192 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1193 PUTWORD(p, 10); /* info level */
1194 PUTWORD(p, CLI_BUFFER_SIZE);
1196 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1197 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1198 &rparam, &rprcnt, /* return params, return size */
1199 &rdata, &rdrcnt)) { /* return data, return size */
1200 res = GETRES(rparam);
1206 p = rparam + WORDSIZE;
1207 GETWORD(p, converter);
1209 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1210 GETSTRINGP(p, cli->server_domain, rdata, converter);
1221 /*************************************************************************
1223 * Function Name: cli_get_server_type
1225 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1226 * requesting server_info_1 level information to retrieve
1229 * Dependencies: none
1232 * cli - pointer to cli_state structure
1233 * pstype - pointer to uint32 to contain returned server type
1239 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1241 ************************************************************************/
1242 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1244 char *rparam = NULL;
1248 char param[WORDSIZE /* api number */
1249 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1250 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1251 +WORDSIZE /* info level */
1252 +WORDSIZE]; /* buffer size */
1255 /* send a SMBtrans command with api NetServerGetInfo */
1256 p = make_header(param, RAP_WserverGetInfo,
1257 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1258 PUTWORD(p, 1); /* info level */
1259 PUTWORD(p, CLI_BUFFER_SIZE);
1262 param, PTR_DIFF(p,param), 8, /* params, length, max */
1263 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1264 &rparam, &rprcnt, /* return params, return size */
1265 &rdata, &rdrcnt /* return data, return size */
1268 res = GETRES(rparam);
1270 if (res == 0 || res == ERRmoredata) {
1272 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1279 return(res == 0 || res == ERRmoredata);
1283 /*************************************************************************
1285 * Function Name: cli_ns_check_server_type
1287 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1288 * requesting server_info_0 level information of machines
1289 * matching the given server type. If the returned server
1290 * list contains the machine name contained in cli->desthost
1291 * then we conclude the server type checks out. This routine
1292 * is useful to retrieve list of server's of a certain
1293 * type when all you have is a null session connection and
1294 * can't remote API calls such as NetWkstaGetInfo or
1297 * Dependencies: none
1300 * cli - pointer to cli_state structure
1301 * workgroup - pointer to string containing domain
1302 * stype - server type
1308 ************************************************************************/
1309 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1311 char *rparam = NULL;
1315 char param[WORDSIZE /* api number */
1316 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1317 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1318 +WORDSIZE /* info level */
1319 +WORDSIZE /* buffer size */
1320 +DWORDSIZE /* server type */
1321 +RAP_MACHNAME_LEN]; /* workgroup */
1322 BOOL found_server = False;
1325 /* send a SMBtrans command with api NetServerEnum */
1326 p = make_header(param, RAP_NetServerEnum2,
1327 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1328 PUTWORD(p, 0); /* info level 0 */
1329 PUTWORD(p, CLI_BUFFER_SIZE);
1331 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1334 param, PTR_DIFF(p,param), 8, /* params, length, max */
1335 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1336 &rparam, &rprcnt, /* return params, return size */
1337 &rdata, &rdrcnt /* return data, return size */
1340 res = GETRES(rparam);
1341 cli->rap_error = res;
1343 if (res == 0 || res == ERRmoredata) {
1344 int i, converter, count;
1346 p = rparam + WORDSIZE;
1347 GETWORD(p, converter);
1351 for (i = 0;i < count;i++, p += 16) {
1352 char ret_server[RAP_MACHNAME_LEN];
1354 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1355 if (strequal(ret_server, cli->desthost)) {
1356 found_server = True;
1362 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1363 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1370 return found_server;
1374 /****************************************************************************
1375 perform a NetWkstaUserLogoff
1376 ****************************************************************************/
1377 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1379 char *rparam = NULL;
1383 char param[WORDSIZE /* api number */
1384 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1385 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1386 +RAP_USERNAME_LEN+1 /* user name+pad */
1387 +RAP_MACHNAME_LEN /* wksta name */
1388 +WORDSIZE /* buffer size */
1389 +WORDSIZE]; /* buffer size? */
1392 memset(param, 0, sizeof(param));
1394 /* send a SMBtrans command with api NetWkstaUserLogoff */
1395 p = make_header(param, RAP_WWkstaUserLogoff,
1396 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1397 PUTDWORD(p, 0); /* Null pointer */
1398 PUTDWORD(p, 0); /* Null pointer */
1399 fstrcpy(upperbuf, user);
1401 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1402 p++; /* strange format, but ok */
1403 fstrcpy(upperbuf, workstation);
1405 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1406 PUTWORD(p, CLI_BUFFER_SIZE);
1407 PUTWORD(p, CLI_BUFFER_SIZE);
1410 param, PTR_DIFF(p,param),1024, /* param, length, max */
1411 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1412 &rparam, &rprcnt, /* return params, return size */
1413 &rdata, &rdrcnt /* return data, return size */
1415 cli->rap_error = GETRES(rparam);
1417 if (cli->rap_error != 0) {
1418 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1424 return (cli->rap_error == 0);
1427 int cli_NetPrintQEnum(struct cli_state *cli,
1428 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1429 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1431 char param[WORDSIZE /* api number */
1432 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1433 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1434 +WORDSIZE /* info level */
1435 +WORDSIZE /* buffer size */
1436 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1438 char *rparam = NULL;
1444 memset(param, '\0',sizeof(param));
1445 p = make_header(param, RAP_WPrintQEnum,
1446 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1447 PUTWORD(p,2); /* Info level 2 */
1448 PUTWORD(p,0xFFE0); /* Return buffer size */
1449 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1452 param, PTR_DIFF(p,param),1024,
1453 NULL, 0, CLI_BUFFER_SIZE,
1456 res = GETRES(rparam);
1457 cli->rap_error = res;
1459 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1464 if (res == 0 || res == ERRmoredata) {
1465 int i, converter, count;
1467 p = rparam + WORDSIZE;
1468 GETWORD(p, converter);
1472 for (i=0;i<count;i++) {
1473 pstring qname, sep_file, print_proc, dest, parms, comment;
1474 uint16 jobcount, priority, start_time, until_time, status;
1476 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1478 GETWORD(p, priority);
1479 GETWORD(p, start_time);
1480 GETWORD(p, until_time);
1481 GETSTRINGP(p, sep_file, rdata, converter);
1482 GETSTRINGP(p, print_proc, rdata, converter);
1483 GETSTRINGP(p, dest, rdata, converter);
1484 GETSTRINGP(p, parms, rdata, converter);
1485 GETSTRINGP(p, parms, comment, converter);
1487 GETWORD(p, jobcount);
1489 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1490 dest, parms, comment, status, jobcount);
1494 for (j=0;j<jobcount;j++) {
1495 uint16 jid, pos, fsstatus;
1496 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1497 uint submitted, jsize;
1500 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1502 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1503 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1504 GETSTRINGP(p, jparms, rdata, converter);
1506 GETWORD(p, fsstatus);
1507 GETSTRINGP(p, jstatus, rdata, converter);
1508 GETDWORD(p, submitted);
1510 GETSTRINGP(p, jcomment, rdata, converter);
1512 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1513 jstatus, submitted, jsize, jcomment);
1518 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1521 DEBUG(4,("NetPrintQEnum no data returned\n"));
1530 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1531 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1532 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1534 char param[WORDSIZE /* api number */
1535 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1536 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1537 +RAP_SHARENAME_LEN /* printer name */
1538 +WORDSIZE /* info level */
1539 +WORDSIZE /* buffer size */
1540 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1542 char *rparam = NULL;
1548 memset(param, '\0',sizeof(param));
1549 p = make_header(param, RAP_WPrintQGetInfo,
1550 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1551 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1552 PUTWORD(p, 2); /* Info level 2 */
1553 PUTWORD(p,0xFFE0); /* Return buffer size */
1554 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1557 param, PTR_DIFF(p,param),1024,
1558 NULL, 0, CLI_BUFFER_SIZE,
1561 res = GETRES(rparam);
1562 cli->rap_error = res;
1564 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1569 if (res == 0 || res == ERRmoredata) {
1570 int rsize, converter;
1571 pstring qname, sep_file, print_proc, dest, parms, comment;
1572 uint16 jobcount, priority, start_time, until_time, status;
1574 p = rparam + WORDSIZE;
1575 GETWORD(p, converter);
1579 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1581 GETWORD(p, priority);
1582 GETWORD(p, start_time);
1583 GETWORD(p, until_time);
1584 GETSTRINGP(p, sep_file, rdata, converter);
1585 GETSTRINGP(p, print_proc, rdata, converter);
1586 GETSTRINGP(p, dest, rdata, converter);
1587 GETSTRINGP(p, parms, rdata, converter);
1588 GETSTRINGP(p, comment, rdata, converter);
1590 GETWORD(p, jobcount);
1591 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1592 dest, parms, comment, status, jobcount);
1595 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1596 uint16 jid, pos, fsstatus;
1597 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1598 uint submitted, jsize;
1601 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1603 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1604 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1605 GETSTRINGP(p, jparms, rdata, converter);
1607 GETWORD(p, fsstatus);
1608 GETSTRINGP(p, jstatus, rdata, converter);
1609 GETDWORD(p, submitted);
1611 GETSTRINGP(p, jcomment, rdata, converter);
1613 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1614 jstatus, submitted, jsize, jcomment);
1618 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1621 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1630 /****************************************************************************
1631 call a NetServiceEnum - list running services on a different host
1632 ****************************************************************************/
1633 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1635 char param[WORDSIZE /* api number */
1636 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1637 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1638 +WORDSIZE /* info level */
1639 +WORDSIZE]; /* buffer size */
1641 char *rparam = NULL;
1647 memset(param, '\0', sizeof(param));
1648 p = make_header(param, RAP_WServiceEnum,
1649 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1650 PUTWORD(p,2); /* Info level 2 */
1651 PUTWORD(p,0xFFE0); /* Return buffer size */
1654 param, PTR_DIFF(p,param),8,
1655 NULL, 0, 0xFFE0 /* data area size */,
1658 res = GETRES(rparam);
1659 cli->rap_error = res;
1660 if(cli->rap_error == 234)
1661 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1662 else if (cli->rap_error != 0) {
1663 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1668 if (res == 0 || res == ERRmoredata) {
1669 int i, converter, count;
1671 p = rparam + WORDSIZE; /* skip result */
1672 GETWORD(p, converter);
1675 for (i=0,p=rdata;i<count;i++) {
1677 char servicename[RAP_SRVCNAME_LEN];
1679 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1680 p+=8; /* pass status words */
1681 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1683 fn(servicename, comment, cli); /* BB add status too */
1686 DEBUG(4,("NetServiceEnum res=%d\n", res));
1689 DEBUG(4,("NetServiceEnum no data returned\n"));
1699 /****************************************************************************
1700 call a NetSessionEnum - list workstations with sessions to an SMB server
1701 ****************************************************************************/
1702 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1704 char param[WORDSIZE /* api number */
1705 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1706 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1707 +WORDSIZE /* info level */
1708 +WORDSIZE]; /* buffer size */
1710 char *rparam = NULL;
1715 memset(param, '\0', sizeof(param));
1716 p = make_header(param, RAP_WsessionEnum,
1717 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1718 PUTWORD(p,2); /* Info level 2 */
1719 PUTWORD(p,0xFF); /* Return buffer size */
1722 param, PTR_DIFF(p,param),8,
1723 NULL, 0, CLI_BUFFER_SIZE,
1726 res = GETRES(rparam);
1727 cli->rap_error = res;
1729 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1734 if (res == 0 || res == ERRmoredata) {
1735 int i, converter, count;
1737 p = rparam + WORDSIZE;
1738 GETWORD(p, converter);
1741 for (i=0,p=rdata;i<count;i++) {
1742 pstring wsname, username, clitype_name;
1743 uint16 num_conns, num_opens, num_users;
1744 uint sess_time, idle_time, user_flags;
1746 GETSTRINGP(p, wsname, rdata, converter);
1747 GETSTRINGP(p, username, rdata, converter);
1748 GETWORD(p, num_conns);
1749 GETWORD(p, num_opens);
1750 GETWORD(p, num_users);
1751 GETDWORD(p, sess_time);
1752 GETDWORD(p, idle_time);
1753 GETDWORD(p, user_flags);
1754 GETSTRINGP(p, clitype_name, rdata, converter);
1756 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1757 idle_time, user_flags, clitype_name);
1761 DEBUG(4,("NetSessionEnum res=%d\n", res));
1764 DEBUG(4,("NetSesssionEnum no data returned\n"));
1773 /****************************************************************************
1774 Call a NetSessionGetInfo - get information about other session to an SMB server.
1775 ****************************************************************************/
1777 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1779 char param[WORDSIZE /* api number */
1780 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1781 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1782 +RAP_MACHNAME_LEN /* wksta name */
1783 +WORDSIZE /* info level */
1784 +WORDSIZE]; /* buffer size */
1786 char *rparam = NULL;
1792 memset(param, '\0', sizeof(param));
1793 p = make_header(param, RAP_WsessionGetInfo,
1794 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1795 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1796 PUTWORD(p,2); /* Info level 2 */
1797 PUTWORD(p,0xFF); /* Return buffer size */
1800 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1801 NULL, 0, CLI_BUFFER_SIZE,
1804 cli->rap_error = SVAL(rparam,0);
1805 if (cli->rap_error != 0) {
1806 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1811 res = GETRES(rparam);
1813 if (res == 0 || res == ERRmoredata) {
1814 int rsize, converter;
1815 pstring wsname, username, clitype_name;
1816 uint16 num_conns, num_opens, num_users;
1817 uint sess_time, idle_time, user_flags;
1819 p = rparam + WORDSIZE;
1820 GETWORD(p, converter);
1824 GETSTRINGP(p, wsname, rdata, converter);
1825 GETSTRINGP(p, username, rdata, converter);
1826 GETWORD(p, num_conns);
1827 GETWORD(p, num_opens);
1828 GETWORD(p, num_users);
1829 GETDWORD(p, sess_time);
1830 GETDWORD(p, idle_time);
1831 GETDWORD(p, user_flags);
1832 GETSTRINGP(p, clitype_name, rdata, converter);
1834 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1835 idle_time, user_flags, clitype_name);
1837 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
1840 DEBUG(4,("NetSessionGetInfo no data returned\n"));
1849 /****************************************************************************
1850 call a NetSessionDel - close a session to an SMB server
1851 ****************************************************************************/
1852 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
1854 char param[WORDSIZE /* api number */
1855 +sizeof(RAP_NetSessionDel_REQ) /* req string */
1856 +1 /* no return string */
1857 +RAP_MACHNAME_LEN /* workstation name */
1858 +WORDSIZE]; /* reserved (0) */
1860 char *rparam = NULL;
1865 memset(param, '\0', sizeof(param));
1866 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
1867 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1868 PUTWORD(p,0); /* reserved word of 0 */
1870 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1871 NULL, 0, 200, /* data, length, maxlen */
1872 &rparam, &rprcnt, /* return params, length */
1873 &rdata, &rdrcnt)) /* return data, length */
1875 res = GETRES(rparam);
1876 cli->rap_error = res;
1882 DEBUG(4,("NetFileClose2 res=%d\n", res));
1886 DEBUG(4,("NetFileClose2 failed\n"));
1896 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))
1898 char param[WORDSIZE /* api number */
1899 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
1900 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
1901 +RAP_MACHNAME_LEN /* wksta name */
1902 +WORDSIZE /* info level */
1903 +WORDSIZE]; /* buffer size */
1905 char *rparam = NULL;
1910 memset(param, '\0', sizeof(param));
1911 p = make_header(param, RAP_WconnectionEnum,
1912 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
1913 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
1914 PUTWORD(p,1); /* Info level 1 */
1915 PUTWORD(p,0xFFE0); /* Return buffer size */
1918 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1919 NULL, 0, CLI_BUFFER_SIZE,
1922 res = GETRES(rparam);
1923 cli->rap_error = res;
1925 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
1929 if (res == 0 || res == ERRmoredata) {
1930 int i, converter, count;
1932 p = rparam + WORDSIZE;
1933 GETWORD(p, converter);
1936 for (i=0,p=rdata;i<count;i++) {
1937 pstring netname, username;
1938 uint16 conn_id, conn_type, num_opens, num_users;
1942 GETWORD(p,conn_type);
1943 GETWORD(p,num_opens);
1944 GETWORD(p,num_users);
1945 GETDWORD(p,conn_time);
1946 GETSTRINGP(p, username, rdata, converter);
1947 GETSTRINGP(p, netname, rdata, converter);
1949 fn(conn_id, conn_type, num_opens, num_users, conn_time,
1954 DEBUG(4,("NetConnectionEnum res=%d\n", res));
1957 DEBUG(4,("NetConnectionEnum no data returned\n"));