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 3 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, see <http://www.gnu.org/licenses/>.
22 /*****************************************************/
24 /* Additional RAP functionality */
26 /* RAP is the original SMB RPC, documented */
27 /* by Microsoft and X/Open in the 1990s and */
28 /* supported by most SMB/CIFS servers although */
29 /* it is unlikely that any one implementation */
30 /* supports all RAP command codes since some */
31 /* are quite obsolete and a few are specific */
32 /* to a particular network operating system */
34 /* Although it has largely been replaced */
35 /* for complex remote admistration and management */
36 /* (of servers) by the relatively newer */
37 /* DCE/RPC based remote API (which better handles */
38 /* large >64K data structures), there are many */
39 /* important administrative and resource location */
40 /* tasks and user tasks (e.g. password change) */
41 /* that are performed via RAP. */
43 /* Although a few of the RAP calls are implemented */
44 /* in the Samba client library already (clirap.c) */
45 /* the new ones are in clirap2.c for easy patching */
46 /* and integration and a corresponding header */
47 /* file, rap.h, has been created. */
49 /* This is based on data from the CIFS spec */
50 /* and the LAN Server and LAN Manager */
51 /* Programming Reference books and published */
52 /* RAP document and CIFS forum postings and */
53 /* lots of trial and error */
55 /* Function names changed from API_ (as they are */
56 /* in the CIFS specification) to RAP_ in order */
57 /* to avoid confusion with other API calls */
58 /* sent via DCE RPC */
60 /*****************************************************/
62 /*****************************************************/
64 /* cifsrap.c already includes support for: */
66 /* WshareEnum ( API number 0, level 1) */
67 /* NetServerEnum2 (API num 104, level 1) */
68 /* WWkstaUserLogon (132) */
69 /* SamOEMchgPasswordUser2_P (214) */
71 /* cifsprint.c already includes support for: */
73 /* WPrintJobEnum (API num 76, level 2) */
74 /* WPrintJobDel (API num 81) */
76 /*****************************************************/
83 #define PUTBYTE(p,b) do {SCVAL(p,0,b); p++;} while(0)
84 #define GETBYTE(p,b) do {b = CVAL(p,0); p++;} while(0)
85 #define PUTWORD(p,w) do {SSVAL(p,0,w); p += WORDSIZE;} while(0)
86 #define GETWORD(p,w) do {w = SVAL(p,0); p += WORDSIZE;} while(0)
87 #define PUTDWORD(p,d) do {SIVAL(p,0,d); p += DWORDSIZE;} while(0)
88 #define GETDWORD(p,d) do {d = IVAL(p,0); p += DWORDSIZE;} while(0)
89 #define GETRES(p) p ? SVAL(p,0) : -1
90 /* put string s at p with max len n and increment p past string */
91 #define PUTSTRING(p,s,n) do {\
92 push_ascii(p,s?s:"",n?n:256,STR_TERMINATE);\
93 p = push_skip_string(p);\
95 /* put string s and p, using fixed len l, and increment p by l */
96 #define PUTSTRINGF(p,s,l) do {\
97 push_ascii(p,s?s:"",l,STR_TERMINATE);\
100 /* put string pointer at p, supplying offset o from rdata r, store */
101 /* dword offset at p, increment p by 4 and o by length of s. This */
102 /* means on the first call, you must calc the offset yourself! */
103 #define PUTSTRINGP(p,s,r,o) do {\
105 push_ascii(r+o,s,strlen(s)+1,STR_TERMINATE);\
108 } else PUTDWORD(p,0);\
110 /* get asciiz string s from p, increment p past string */
111 #define GETSTRING(p,s) do {\
112 pull_ascii_pstring(s,p);\
113 p = push_skip_string(p);\
115 /* get fixed length l string s from p, increment p by l */
116 #define GETSTRINGF(p,s,l) do {\
117 pull_ascii_pstring(s,p);\
120 /* get string s from offset (obtained at p) from rdata r - converter c */
121 #define GETSTRINGP(p,s,r,c) do {\
124 off &= 0x0000FFFF; /* mask the obsolete segment number from the offset */ \
125 pull_ascii_pstring(s, off?(r+off-c):"");\
128 static char *make_header(char *param, uint16 apinum, const char *reqfmt, const char *datafmt)
130 PUTWORD(param,apinum);
132 PUTSTRING(param,reqfmt,0);
137 PUTSTRING(param,datafmt,0);
145 /****************************************************************************
146 call a NetGroupDelete - delete user group from remote server
147 ****************************************************************************/
148 int cli_NetGroupDelete(struct cli_state *cli, const char *group_name )
153 unsigned int rdrcnt,rprcnt;
155 char param[WORDSIZE /* api number */
156 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
157 +1 /* no ret string */
158 +RAP_GROUPNAME_LEN /* group to del */
159 +WORDSIZE]; /* reserved word */
161 /* now send a SMBtrans command with api GroupDel */
162 p = make_header(param, RAP_WGroupDel, RAP_NetGroupDel_REQ, NULL);
163 PUTSTRING(p, group_name, RAP_GROUPNAME_LEN);
164 PUTWORD(p,0); /* reserved word MBZ on input */
167 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
168 NULL, 0, 200, /* data, length, maxlen */
169 &rparam, &rprcnt, /* return params, length */
170 &rdata, &rdrcnt)) /* return data, length */
172 res = GETRES(rparam);
177 else if ((res == 5) || (res == 65)) {
178 DEBUG(1, ("Access Denied\n"));
180 else if (res == 2220) {
181 DEBUG (1, ("Group does not exist\n"));
184 DEBUG(4,("NetGroupDelete res=%d\n", res));
188 DEBUG(4,("NetGroupDelete failed\n"));
197 /****************************************************************************
198 call a NetGroupAdd - add user group to remote server
199 ****************************************************************************/
200 int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo )
205 unsigned int rdrcnt,rprcnt;
207 char param[WORDSIZE /* api number */
208 +sizeof(RAP_NetGroupAdd_REQ) /* req string */
209 +sizeof(RAP_GROUP_INFO_L1) /* return string */
210 +WORDSIZE /* info level */
211 +WORDSIZE]; /* reserved word */
213 /* offset into data of free format strings. Will be updated */
214 /* by PUTSTRINGP macro and end up with total data length. */
215 int soffset = RAP_GROUPNAME_LEN + 1 + DWORDSIZE;
220 data_size = MAX(soffset + strlen(grinfo->comment) + 1, 1024);
222 data = SMB_MALLOC_ARRAY(char, data_size);
224 DEBUG (1, ("Malloc fail\n"));
228 /* now send a SMBtrans command with api WGroupAdd */
230 p = make_header(param, RAP_WGroupAdd,
231 RAP_NetGroupAdd_REQ, RAP_GROUP_INFO_L1);
232 PUTWORD(p, 1); /* info level */
233 PUTWORD(p, 0); /* reserved word 0 */
236 PUTSTRINGF(p, grinfo->group_name, RAP_GROUPNAME_LEN);
237 PUTBYTE(p, 0); /* pad byte 0 */
238 PUTSTRINGP(p, grinfo->comment, data, soffset);
241 param, sizeof(param), 1024, /* Param, length, maxlen */
242 data, soffset, sizeof(data), /* data, length, maxlen */
243 &rparam, &rprcnt, /* return params, length */
244 &rdata, &rdrcnt)) /* return data, length */
246 res = GETRES(rparam);
250 } else if ((res == 5) || (res == 65)) {
251 DEBUG(1, ("Access Denied\n"));
253 else if (res == 2223) {
254 DEBUG (1, ("Group already exists\n"));
257 DEBUG(4,("NetGroupAdd res=%d\n", res));
261 DEBUG(4,("NetGroupAdd failed\n"));
271 /****************************************************************************
272 call a NetGroupEnum - try and list user groups on a different host
273 ****************************************************************************/
274 int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
276 char param[WORDSIZE /* api number */
277 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
278 +sizeof(RAP_GROUP_INFO_L1) /* return string */
279 +WORDSIZE /* info level */
280 +WORDSIZE]; /* buffer size */
284 unsigned int rprcnt, rdrcnt;
288 memset(param, '\0', sizeof(param));
289 p = make_header(param, RAP_WGroupEnum,
290 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L1);
291 PUTWORD(p,1); /* Info level 1 */ /* add level 0 */
292 PUTWORD(p,0xFFE0); /* Return buffer size */
295 param, PTR_DIFF(p,param),8,
296 NULL, 0, 0xFFE0 /* data area size */,
299 res = GETRES(rparam);
300 cli->rap_error = res;
301 if(cli->rap_error == 234)
302 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
303 else if (cli->rap_error != 0) {
304 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
309 if (res == 0 || res == ERRmoredata) {
310 int i, converter, count;
312 p = rparam + WORDSIZE; /* skip result */
313 GETWORD(p, converter);
316 for (i=0,p=rdata;i<count;i++) {
318 char groupname[RAP_GROUPNAME_LEN];
320 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
322 GETSTRINGP(p, comment, rdata, converter);
324 fn(groupname, comment, cli);
327 DEBUG(4,("NetGroupEnum res=%d\n", res));
330 DEBUG(4,("NetGroupEnum no data returned\n"));
339 int cli_RNetGroupEnum0(struct cli_state *cli,
340 void (*fn)(const char *, void *),
343 char param[WORDSIZE /* api number */
344 +sizeof(RAP_NetGroupEnum_REQ) /* parm string */
345 +sizeof(RAP_GROUP_INFO_L0) /* return string */
346 +WORDSIZE /* info level */
347 +WORDSIZE]; /* buffer size */
351 unsigned int rprcnt, rdrcnt;
355 memset(param, '\0', sizeof(param));
356 p = make_header(param, RAP_WGroupEnum,
357 RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0);
358 PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this
359 is the resume count, at least
360 that's what smbd believes... */
361 PUTWORD(p,0xFFE0); /* Return buffer size */
364 param, PTR_DIFF(p,param),8,
365 NULL, 0, 0xFFE0 /* data area size */,
368 res = GETRES(rparam);
369 cli->rap_error = res;
370 if(cli->rap_error == 234)
371 DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n"));
372 else if (cli->rap_error != 0) {
373 DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error));
378 if (res == 0 || res == ERRmoredata) {
381 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
384 for (i=0,p=rdata;i<count;i++) {
385 char groupname[RAP_GROUPNAME_LEN];
386 GETSTRINGF(p, groupname, RAP_GROUPNAME_LEN);
390 DEBUG(4,("NetGroupEnum res=%d\n", res));
393 DEBUG(4,("NetGroupEnum no data returned\n"));
402 int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const char *user_name)
407 unsigned int rdrcnt,rprcnt;
409 char param[WORDSIZE /* api number */
410 +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */
411 +1 /* no ret string */
412 +RAP_GROUPNAME_LEN /* group name */
413 +RAP_USERNAME_LEN]; /* user to del */
415 /* now send a SMBtrans command with api GroupMemberAdd */
416 p = make_header(param, RAP_WGroupDelUser, RAP_NetGroupDelUser_REQ, NULL);
417 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
418 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
421 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
422 NULL, 0, 200, /* data, length, maxlen */
423 &rparam, &rprcnt, /* return params, length */
424 &rdata, &rdrcnt)) /* return data, length */
426 res = GETRES(rparam);
433 DEBUG(1, ("Access Denied\n"));
436 DEBUG(1, ("Not supported by server\n"));
439 DEBUG(1, ("Group does not exist\n"));
442 DEBUG(1, ("User does not exist\n"));
445 DEBUG(1, ("User is not in group\n"));
448 DEBUG(4,("NetGroupDelUser res=%d\n", res));
452 DEBUG(4,("NetGroupDelUser failed\n"));
461 int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const char *user_name)
466 unsigned int rdrcnt,rprcnt;
468 char param[WORDSIZE /* api number */
469 +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */
470 +1 /* no ret string */
471 +RAP_GROUPNAME_LEN /* group name */
472 +RAP_USERNAME_LEN]; /* user to add */
474 /* now send a SMBtrans command with api GroupMemberAdd */
475 p = make_header(param, RAP_WGroupAddUser, RAP_NetGroupAddUser_REQ, NULL);
476 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN);
477 PUTSTRING(p,user_name,RAP_USERNAME_LEN);
480 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
481 NULL, 0, 200, /* data, length, maxlen */
482 &rparam, &rprcnt, /* return params, length */
483 &rdata, &rdrcnt)) /* return data, length */
485 res = GETRES(rparam);
492 DEBUG(1, ("Access Denied\n"));
495 DEBUG(1, ("Not supported by server\n"));
498 DEBUG(1, ("Group does not exist\n"));
501 DEBUG(1, ("User does not exist\n"));
504 DEBUG(4,("NetGroupAddUser res=%d\n", res));
508 DEBUG(4,("NetGroupAddUser failed\n"));
518 int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (*fn)(const char *, void *), void *state )
523 unsigned int rdrcnt,rprcnt;
525 char param[WORDSIZE /* api number */
526 +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */
527 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
528 +RAP_GROUPNAME_LEN /* group name */
529 +WORDSIZE /* info level */
530 +WORDSIZE]; /* buffer size */
532 /* now send a SMBtrans command with api GroupGetUsers */
533 p = make_header(param, RAP_WGroupGetUsers,
534 RAP_NetGroupGetUsers_REQ, RAP_GROUP_USERS_INFO_0);
535 PUTSTRING(p,group_name,RAP_GROUPNAME_LEN-1);
536 PUTWORD(p,0); /* info level 0 */
537 PUTWORD(p,0xFFE0); /* return buffer size */
540 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
541 NULL, 0, CLI_BUFFER_SIZE,
544 res = GETRES(rparam);
545 cli->rap_error = res;
547 DEBUG(1,("NetGroupGetUsers gave error %d\n", res));
551 if (res == 0 || res == ERRmoredata) {
554 p = rparam + WORDSIZE + WORDSIZE;
557 for (i=0,p=rdata; i<count; i++) {
558 GETSTRINGF(p, username, RAP_USERNAME_LEN);
562 DEBUG(4,("NetGroupGetUsers res=%d\n", res));
565 DEBUG(4,("NetGroupGetUsers no data returned\n"));
572 int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*fn)(const char *, void *), void *state )
577 unsigned int rdrcnt,rprcnt;
579 char param[WORDSIZE /* api number */
580 +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */
581 +sizeof(RAP_GROUP_USERS_INFO_0) /* return string */
582 +RAP_USERNAME_LEN /* user name */
583 +WORDSIZE /* info level */
584 +WORDSIZE]; /* buffer size */
586 /* now send a SMBtrans command with api GroupGetUsers */
587 p = make_header(param, RAP_WUserGetGroups,
588 RAP_NetUserGetGroups_REQ, RAP_GROUP_USERS_INFO_0);
589 PUTSTRING(p,user_name,RAP_USERNAME_LEN-1);
590 PUTWORD(p,0); /* info level 0 */
591 PUTWORD(p,0xFFE0); /* return buffer size */
594 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
595 NULL, 0, CLI_BUFFER_SIZE,
598 res = GETRES(rparam);
599 cli->rap_error = res;
601 DEBUG(1,("NetUserGetGroups gave error %d\n", res));
605 if (res == 0 || res == ERRmoredata) {
608 p = rparam + WORDSIZE + WORDSIZE;
611 for (i=0,p=rdata; i<count; i++) {
612 GETSTRINGF(p, groupname, RAP_USERNAME_LEN);
613 fn(groupname, state);
616 DEBUG(4,("NetUserGetGroups res=%d\n", res));
619 DEBUG(4,("NetUserGetGroups no data returned\n"));
627 /****************************************************************************
628 call a NetUserDelete - delete user from remote server
629 ****************************************************************************/
630 int cli_NetUserDelete(struct cli_state *cli, const char * user_name )
635 unsigned int rdrcnt,rprcnt;
637 char param[WORDSIZE /* api number */
638 +sizeof(RAP_NetGroupDel_REQ) /* parm string */
639 +1 /* no ret string */
640 +RAP_USERNAME_LEN /* user to del */
641 +WORDSIZE]; /* reserved word */
643 /* now send a SMBtrans command with api UserDel */
644 p = make_header(param, RAP_WUserDel, RAP_NetGroupDel_REQ, NULL);
645 PUTSTRING(p, user_name, RAP_USERNAME_LEN);
646 PUTWORD(p,0); /* reserved word MBZ on input */
649 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
650 NULL, 0, 200, /* data, length, maxlen */
651 &rparam, &rprcnt, /* return params, length */
652 &rdata, &rdrcnt)) /* return data, length */
654 res = GETRES(rparam);
659 else if ((res == 5) || (res == 65)) {
660 DEBUG(1, ("Access Denied\n"));
662 else if (res == 2221) {
663 DEBUG (1, ("User does not exist\n"));
666 DEBUG(4,("NetUserDelete res=%d\n", res));
670 DEBUG(4,("NetUserDelete failed\n"));
679 /****************************************************************************
680 call a NetUserAdd - add user to remote server
681 ****************************************************************************/
682 int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo )
690 unsigned int rdrcnt,rprcnt;
692 char param[WORDSIZE /* api number */
693 +sizeof(RAP_NetUserAdd2_REQ) /* req string */
694 +sizeof(RAP_USER_INFO_L1) /* data string */
695 +WORDSIZE /* info level */
696 +WORDSIZE /* buffer length */
697 +WORDSIZE]; /* reserved */
700 /* offset into data of free format strings. Will be updated */
701 /* by PUTSTRINGP macro and end up with total data length. */
702 int soffset=RAP_USERNAME_LEN+1 /* user name + pad */
703 + RAP_UPASSWD_LEN /* password */
704 + DWORDSIZE /* password age */
705 + WORDSIZE /* privilege */
706 + DWORDSIZE /* home dir ptr */
707 + DWORDSIZE /* comment ptr */
708 + WORDSIZE /* flags */
709 + DWORDSIZE; /* login script ptr*/
711 /* now send a SMBtrans command with api NetUserAdd */
712 p = make_header(param, RAP_WUserAdd2,
713 RAP_NetUserAdd2_REQ, RAP_USER_INFO_L1);
714 PUTWORD(p, 1); /* info level */
716 PUTWORD(p, 0); /* pwencrypt */
717 if(userinfo->passwrd)
718 PUTWORD(p,MIN(strlen(userinfo->passwrd), RAP_UPASSWD_LEN));
720 PUTWORD(p, 0); /* password length */
723 memset(data, '\0', soffset);
725 PUTSTRINGF(p, userinfo->user_name, RAP_USERNAME_LEN);
726 PUTBYTE(p, 0); /* pad byte 0 */
727 PUTSTRINGF(p, userinfo->passwrd, RAP_UPASSWD_LEN);
728 PUTDWORD(p, 0); /* pw age - n.a. on user add */
729 PUTWORD(p, userinfo->priv);
730 PUTSTRINGP(p, userinfo->home_dir, data, soffset);
731 PUTSTRINGP(p, userinfo->comment, data, soffset);
732 PUTWORD(p, userinfo->userflags);
733 PUTSTRINGP(p, userinfo->logon_script, data, soffset);
736 param, sizeof(param), 1024, /* Param, length, maxlen */
737 data, soffset, sizeof(data), /* data, length, maxlen */
738 &rparam, &rprcnt, /* return params, length */
739 &rdata, &rdrcnt)) /* return data, length */
741 res = GETRES(rparam);
746 else if ((res == 5) || (res == 65)) {
747 DEBUG(1, ("Access Denied\n"));
749 else if (res == 2224) {
750 DEBUG (1, ("User already exists\n"));
753 DEBUG(4,("NetUserAdd res=%d\n", res));
757 DEBUG(4,("NetUserAdd failed\n"));
766 /****************************************************************************
767 call a NetUserEnum - try and list users on a different host
768 ****************************************************************************/
769 int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char *, const char *, const char *, void *), void *state)
771 char param[WORDSIZE /* api number */
772 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
773 +sizeof(RAP_USER_INFO_L1) /* return string */
774 +WORDSIZE /* info level */
775 +WORDSIZE]; /* buffer size */
779 unsigned int rprcnt, rdrcnt;
783 memset(param, '\0', sizeof(param));
784 p = make_header(param, RAP_WUserEnum,
785 RAP_NetUserEnum_REQ, RAP_USER_INFO_L1);
786 PUTWORD(p,1); /* Info level 1 */
787 PUTWORD(p,0xFF00); /* Return buffer size */
789 /* BB Fix handling of large numbers of users to be returned */
791 param, PTR_DIFF(p,param),8,
792 NULL, 0, CLI_BUFFER_SIZE,
795 res = GETRES(rparam);
796 cli->rap_error = res;
797 if (cli->rap_error != 0) {
798 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
802 if (res == 0 || res == ERRmoredata) {
803 int i, converter, count;
804 char username[RAP_USERNAME_LEN];
805 char userpw[RAP_UPASSWD_LEN];
806 pstring comment, homedir, logonscript;
808 p = rparam + WORDSIZE; /* skip result */
809 GETWORD(p, converter);
812 for (i=0,p=rdata;i<count;i++) {
813 GETSTRINGF(p, username, RAP_USERNAME_LEN);
815 GETSTRINGF(p, userpw, RAP_UPASSWD_LEN);
816 p += DWORDSIZE; /* skip password age */
817 p += WORDSIZE; /* skip priv: 0=guest, 1=user, 2=admin */
818 GETSTRINGP(p, homedir, rdata, converter);
819 GETSTRINGP(p, comment, rdata, converter);
820 p += WORDSIZE; /* skip flags */
821 GETSTRINGP(p, logonscript, rdata, converter);
823 fn(username, comment, homedir, logonscript, cli);
826 DEBUG(4,("NetUserEnum res=%d\n", res));
829 DEBUG(4,("NetUserEnum no data returned\n"));
838 int cli_RNetUserEnum0(struct cli_state *cli,
839 void (*fn)(const char *, void *),
842 char param[WORDSIZE /* api number */
843 +sizeof(RAP_NetUserEnum_REQ) /* parm string */
844 +sizeof(RAP_USER_INFO_L0) /* return string */
845 +WORDSIZE /* info level */
846 +WORDSIZE]; /* buffer size */
850 unsigned int rprcnt, rdrcnt;
854 memset(param, '\0', sizeof(param));
855 p = make_header(param, RAP_WUserEnum,
856 RAP_NetUserEnum_REQ, RAP_USER_INFO_L0);
857 PUTWORD(p,0); /* Info level 1 */
858 PUTWORD(p,0xFF00); /* Return buffer size */
860 /* BB Fix handling of large numbers of users to be returned */
862 param, PTR_DIFF(p,param),8,
863 NULL, 0, CLI_BUFFER_SIZE,
866 res = GETRES(rparam);
867 cli->rap_error = res;
868 if (cli->rap_error != 0) {
869 DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error));
873 if (res == 0 || res == ERRmoredata) {
875 char username[RAP_USERNAME_LEN];
877 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
880 for (i=0,p=rdata;i<count;i++) {
881 GETSTRINGF(p, username, RAP_USERNAME_LEN);
885 DEBUG(4,("NetUserEnum res=%d\n", res));
888 DEBUG(4,("NetUserEnum no data returned\n"));
897 /****************************************************************************
898 call a NetFileClose2 - close open file on another session to server
899 ****************************************************************************/
900 int cli_NetFileClose(struct cli_state *cli, uint32 file_id )
905 unsigned int rdrcnt,rprcnt;
906 char param[WORDSIZE /* api number */
907 +sizeof(RAP_WFileClose2_REQ) /* req string */
908 +1 /* no ret string */
909 +DWORDSIZE]; /* file ID */
912 /* now send a SMBtrans command with api RNetShareEnum */
913 p = make_header(param, RAP_WFileClose2, RAP_WFileClose2_REQ, NULL);
914 PUTDWORD(p, file_id);
917 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
918 NULL, 0, 200, /* data, length, maxlen */
919 &rparam, &rprcnt, /* return params, length */
920 &rdata, &rdrcnt)) /* return data, length */
922 res = GETRES(rparam);
926 } else if (res == 2314){
927 DEBUG(1, ("NetFileClose2 - attempt to close non-existant file open instance\n"));
929 DEBUG(4,("NetFileClose2 res=%d\n", res));
933 DEBUG(4,("NetFileClose2 failed\n"));
942 /****************************************************************************
943 call a NetFileGetInfo - get information about server file opened from other
945 ****************************************************************************/
946 int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const char *, const char *, uint16, uint16, uint32))
951 unsigned int rdrcnt,rprcnt;
953 char param[WORDSIZE /* api number */
954 +sizeof(RAP_WFileGetInfo2_REQ) /* req string */
955 +sizeof(RAP_FILE_INFO_L3) /* return string */
956 +DWORDSIZE /* file ID */
957 +WORDSIZE /* info level */
958 +WORDSIZE]; /* buffer size */
960 /* now send a SMBtrans command with api RNetShareEnum */
961 p = make_header(param, RAP_WFileGetInfo2,
962 RAP_WFileGetInfo2_REQ, RAP_FILE_INFO_L3);
963 PUTDWORD(p, file_id);
964 PUTWORD(p, 3); /* info level */
965 PUTWORD(p, 0x1000); /* buffer size */
967 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
968 NULL, 0, 0x1000, /* data, length, maxlen */
969 &rparam, &rprcnt, /* return params, length */
970 &rdata, &rdrcnt)) /* return data, length */
972 res = GETRES(rparam);
973 if (res == 0 || res == ERRmoredata) {
974 int converter,id, perms, locks;
975 pstring fpath, fuser;
977 p = rparam + WORDSIZE; /* skip result */
978 GETWORD(p, converter);
984 GETSTRINGP(p, fpath, rdata, converter);
985 GETSTRINGP(p, fuser, rdata, converter);
987 fn(fpath, fuser, perms, locks, id);
989 DEBUG(4,("NetFileGetInfo2 res=%d\n", res));
993 DEBUG(4,("NetFileGetInfo2 failed\n"));
1002 /****************************************************************************
1003 * Call a NetFileEnum2 - list open files on an SMB server
1005 * PURPOSE: Remotes a NetFileEnum API call to the current server or target
1006 * server listing the files open via the network (and their
1007 * corresponding open instance ids)
1009 * Dependencies: none
1012 * cli - pointer to cli_state structure
1013 * user - if present, return only files opened by this remote user
1014 * base_path - if present, return only files opened below this
1016 * fn - display function to invoke for each entry in the result
1023 ****************************************************************************/
1024 int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void (*fn)(const char *, const char *, uint16, uint16, uint32))
1026 char *rparam = NULL;
1029 unsigned int rdrcnt,rprcnt;
1030 char param[WORDSIZE /* api number */
1031 +sizeof(RAP_WFileEnum2_REQ) /* req string */
1032 +sizeof(RAP_FILE_INFO_L3) /* return string */
1033 +256 /* base path (opt) */
1034 +RAP_USERNAME_LEN /* user name (opt) */
1035 +WORDSIZE /* info level */
1036 +WORDSIZE /* buffer size */
1037 +DWORDSIZE /* resume key ? */
1038 +DWORDSIZE]; /* resume key ? */
1041 /* now send a SMBtrans command with api RNetShareEnum */
1042 p = make_header(param, RAP_WFileEnum2,
1043 RAP_WFileEnum2_REQ, RAP_FILE_INFO_L3);
1045 PUTSTRING(p, base_path, 256);
1046 PUTSTRING(p, user, RAP_USERNAME_LEN);
1047 PUTWORD(p, 3); /* info level */
1048 PUTWORD(p, 0xFF00); /* buffer size */
1049 PUTDWORD(p, 0); /* zero out the resume key */
1050 PUTDWORD(p, 0); /* or is this one the resume key? */
1053 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1054 NULL, 0, 0xFF00, /* data, length, maxlen */
1055 &rparam, &rprcnt, /* return params, length */
1056 &rdata, &rdrcnt)) /* return data, length */
1058 int res = GETRES(rparam);
1060 if (res == 0 || res == ERRmoredata) {
1063 p = rparam + WORDSIZE; /* skip result */
1064 GETWORD(p, converter);
1068 for (i=0; i<count; i++) {
1069 int id, perms, locks;
1070 pstring fpath, fuser;
1075 GETSTRINGP(p, fpath, rdata, converter);
1076 GETSTRINGP(p, fuser, rdata, converter);
1078 fn(fpath, fuser, perms, locks, id);
1079 } /* BB fix ERRmoredata case to send resume request */
1081 DEBUG(4,("NetFileEnum2 res=%d\n", res));
1084 DEBUG(4,("NetFileEnum2 failed\n"));
1093 /****************************************************************************
1094 call a NetShareAdd - share/export directory on remote server
1095 ****************************************************************************/
1096 int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo )
1098 char *rparam = NULL;
1101 unsigned int rdrcnt,rprcnt;
1103 char param[WORDSIZE /* api number */
1104 +sizeof(RAP_WShareAdd_REQ) /* req string */
1105 +sizeof(RAP_SHARE_INFO_L2) /* return string */
1106 +WORDSIZE /* info level */
1107 +WORDSIZE]; /* reserved word */
1109 /* offset to free format string section following fixed length data. */
1110 /* will be updated by PUTSTRINGP macro and will end up with total len */
1111 int soffset = RAP_SHARENAME_LEN + 1 /* share name + pad */
1112 + WORDSIZE /* share type */
1113 + DWORDSIZE /* comment pointer */
1114 + WORDSIZE /* permissions */
1115 + WORDSIZE /* max users */
1116 + WORDSIZE /* active users */
1117 + DWORDSIZE /* share path */
1118 + RAP_SPASSWD_LEN + 1; /* share password + pad */
1120 memset(param,'\0',sizeof(param));
1121 /* now send a SMBtrans command with api RNetShareAdd */
1122 p = make_header(param, RAP_WshareAdd,
1123 RAP_WShareAdd_REQ, RAP_SHARE_INFO_L2);
1124 PUTWORD(p, 2); /* info level */
1125 PUTWORD(p, 0); /* reserved word 0 */
1128 PUTSTRINGF(p, sinfo->share_name, RAP_SHARENAME_LEN);
1129 PUTBYTE(p, 0); /* pad byte 0 */
1131 PUTWORD(p, sinfo->share_type);
1132 PUTSTRINGP(p, sinfo->comment, data, soffset);
1133 PUTWORD(p, sinfo->perms);
1134 PUTWORD(p, sinfo->maximum_users);
1135 PUTWORD(p, sinfo->active_users);
1136 PUTSTRINGP(p, sinfo->path, data, soffset);
1137 PUTSTRINGF(p, sinfo->password, RAP_SPASSWD_LEN);
1138 SCVAL(p,-1,0x0A); /* required 0x0A at end of password */
1141 param, sizeof(param), 1024, /* Param, length, maxlen */
1142 data, soffset, sizeof(data), /* data, length, maxlen */
1143 &rparam, &rprcnt, /* return params, length */
1144 &rdata, &rdrcnt)) /* return data, length */
1146 res = rparam? SVAL(rparam,0) : -1;
1152 DEBUG(4,("NetShareAdd res=%d\n", res));
1156 DEBUG(4,("NetShareAdd failed\n"));
1164 /****************************************************************************
1165 call a NetShareDelete - unshare exported directory on remote server
1166 ****************************************************************************/
1167 int cli_NetShareDelete(struct cli_state *cli, const char * share_name )
1169 char *rparam = NULL;
1172 unsigned int rdrcnt,rprcnt;
1174 char param[WORDSIZE /* api number */
1175 +sizeof(RAP_WShareDel_REQ) /* req string */
1176 +1 /* no ret string */
1177 +RAP_SHARENAME_LEN /* share to del */
1178 +WORDSIZE]; /* reserved word */
1181 /* now send a SMBtrans command with api RNetShareDelete */
1182 p = make_header(param, RAP_WshareDel, RAP_WShareDel_REQ, NULL);
1183 PUTSTRING(p,share_name,RAP_SHARENAME_LEN);
1184 PUTWORD(p,0); /* reserved word MBZ on input */
1187 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
1188 NULL, 0, 200, /* data, length, maxlen */
1189 &rparam, &rprcnt, /* return params, length */
1190 &rdata, &rdrcnt)) /* return data, length */
1192 res = GETRES(rparam);
1198 DEBUG(4,("NetShareDelete res=%d\n", res));
1202 DEBUG(4,("NetShareDelete failed\n"));
1210 /*************************************************************************
1212 * Function Name: cli_get_pdc_name
1214 * PURPOSE: Remotes a NetServerEnum API call to the current server
1215 * requesting the name of a server matching the server
1216 * type of SV_TYPE_DOMAIN_CTRL (PDC).
1218 * Dependencies: none
1221 * cli - pointer to cli_state structure
1222 * workgroup - pointer to string containing name of domain
1223 * pdc_name - pointer to string that will contain PDC name
1224 * on successful return
1230 ************************************************************************/
1231 BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name)
1233 char *rparam = NULL;
1235 unsigned int rdrcnt,rprcnt;
1237 char param[WORDSIZE /* api number */
1238 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1239 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1240 +WORDSIZE /* info level */
1241 +WORDSIZE /* buffer size */
1242 +DWORDSIZE /* server type */
1243 +RAP_MACHNAME_LEN]; /* workgroup */
1248 /* send a SMBtrans command with api NetServerEnum */
1249 p = make_header(param, RAP_NetServerEnum2,
1250 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L1);
1251 PUTWORD(p, 1); /* info level */
1252 PUTWORD(p, CLI_BUFFER_SIZE);
1253 PUTDWORD(p, SV_TYPE_DOMAIN_CTRL);
1254 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1257 param, PTR_DIFF(p,param), 8, /* params, length, max */
1258 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1259 &rparam, &rprcnt, /* return params, return size */
1260 &rdata, &rdrcnt /* return data, return size */
1262 cli->rap_error = GETRES(rparam);
1265 * We only really care to copy a name if the
1266 * API succeeded and we got back a name.
1268 if (cli->rap_error == 0) {
1269 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1274 GETSTRING(p, pdc_name);
1277 DEBUG(4,("cli_get_pdc_name: machine %s failed the NetServerEnum call. "
1278 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1289 /*************************************************************************
1291 * Function Name: cli_get_server_domain
1293 * PURPOSE: Remotes a NetWkstaGetInfo API call to the current server
1294 * requesting wksta_info_10 level information to determine
1295 * the domain the server belongs to. On success, this
1296 * routine sets the server_domain field in the cli_state structure
1297 * to the server's domain name.
1299 * Dependencies: none
1302 * cli - pointer to cli_state structure
1308 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1310 ************************************************************************/
1311 BOOL cli_get_server_domain(struct cli_state *cli)
1313 char *rparam = NULL;
1315 unsigned int rdrcnt,rprcnt;
1317 char param[WORDSIZE /* api number */
1318 +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */
1319 +sizeof(RAP_WKSTA_INFO_L10) /* return string */
1320 +WORDSIZE /* info level */
1321 +WORDSIZE]; /* buffer size */
1324 /* send a SMBtrans command with api NetWkstaGetInfo */
1325 p = make_header(param, RAP_WWkstaGetInfo,
1326 RAP_WWkstaGetInfo_REQ, RAP_WKSTA_INFO_L10);
1327 PUTWORD(p, 10); /* info level */
1328 PUTWORD(p, CLI_BUFFER_SIZE);
1330 if (cli_api(cli, param, PTR_DIFF(p,param), 8, /* params, length, max */
1331 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1332 &rparam, &rprcnt, /* return params, return size */
1333 &rdata, &rdrcnt)) { /* return data, return size */
1334 res = GETRES(rparam);
1340 p = rparam + WORDSIZE;
1341 GETWORD(p, converter);
1343 p = rdata + DWORDSIZE + DWORDSIZE; /* skip computer & user names */
1344 GETSTRINGP(p, cli->server_domain, rdata, converter);
1355 /*************************************************************************
1357 * Function Name: cli_get_server_type
1359 * PURPOSE: Remotes a NetServerGetInfo API call to the current server
1360 * requesting server_info_1 level information to retrieve
1363 * Dependencies: none
1366 * cli - pointer to cli_state structure
1367 * pstype - pointer to uint32 to contain returned server type
1373 * Origins: samba 2.0.6 source/libsmb/clientgen.c cli_NetServerEnum()
1375 ************************************************************************/
1376 BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype)
1378 char *rparam = NULL;
1380 unsigned int rdrcnt,rprcnt;
1382 char param[WORDSIZE /* api number */
1383 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1384 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1385 +WORDSIZE /* info level */
1386 +WORDSIZE]; /* buffer size */
1389 /* send a SMBtrans command with api NetServerGetInfo */
1390 p = make_header(param, RAP_WserverGetInfo,
1391 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1392 PUTWORD(p, 1); /* info level */
1393 PUTWORD(p, CLI_BUFFER_SIZE);
1396 param, PTR_DIFF(p,param), 8, /* params, length, max */
1397 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1398 &rparam, &rprcnt, /* return params, return size */
1399 &rdata, &rdrcnt /* return data, return size */
1402 res = GETRES(rparam);
1404 if (res == 0 || res == ERRmoredata) {
1406 *pstype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
1413 return(res == 0 || res == ERRmoredata);
1416 BOOL cli_get_server_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
1419 char *rparam = NULL;
1421 unsigned int rdrcnt,rprcnt;
1423 char param[WORDSIZE /* api number */
1424 +sizeof(RAP_WserverGetInfo_REQ) /* req string */
1425 +sizeof(RAP_SERVER_INFO_L1) /* return string */
1426 +WORDSIZE /* info level */
1427 +WORDSIZE]; /* buffer size */
1431 /* send a SMBtrans command with api NetServerGetInfo */
1432 p = make_header(param, RAP_WserverGetInfo,
1433 RAP_WserverGetInfo_REQ, RAP_SERVER_INFO_L1);
1434 PUTWORD(p, 1); /* info level */
1435 PUTWORD(p, CLI_BUFFER_SIZE);
1438 param, PTR_DIFF(p,param), 8, /* params, length, max */
1439 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1440 &rparam, &rprcnt, /* return params, return size */
1441 &rdata, &rdrcnt /* return data, return size */
1446 if (GETRES(rparam) != 0) {
1451 DEBUG(10, ("invalid data count %d, expected >= 16\n", rdrcnt));
1455 if (pull_ascii(tmp, rdata, sizeof(tmp)-1, 16, STR_TERMINATE) == -1) {
1456 DEBUG(10, ("pull_ascii failed\n"));
1460 if (!(*servername = talloc_strdup(mem_ctx, tmp))) {
1461 DEBUG(1, ("talloc_strdup failed\n"));
1473 /*************************************************************************
1475 * Function Name: cli_ns_check_server_type
1477 * PURPOSE: Remotes a NetServerEnum2 API call to the current server
1478 * requesting server_info_0 level information of machines
1479 * matching the given server type. If the returned server
1480 * list contains the machine name contained in cli->desthost
1481 * then we conclude the server type checks out. This routine
1482 * is useful to retrieve list of server's of a certain
1483 * type when all you have is a null session connection and
1484 * can't remote API calls such as NetWkstaGetInfo or
1487 * Dependencies: none
1490 * cli - pointer to cli_state structure
1491 * workgroup - pointer to string containing domain
1492 * stype - server type
1498 ************************************************************************/
1499 BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 stype)
1501 char *rparam = NULL;
1503 unsigned int rdrcnt,rprcnt;
1505 char param[WORDSIZE /* api number */
1506 +sizeof(RAP_NetServerEnum2_REQ) /* req string */
1507 +sizeof(RAP_SERVER_INFO_L0) /* return string */
1508 +WORDSIZE /* info level */
1509 +WORDSIZE /* buffer size */
1510 +DWORDSIZE /* server type */
1511 +RAP_MACHNAME_LEN]; /* workgroup */
1512 BOOL found_server = False;
1515 /* send a SMBtrans command with api NetServerEnum */
1516 p = make_header(param, RAP_NetServerEnum2,
1517 RAP_NetServerEnum2_REQ, RAP_SERVER_INFO_L0);
1518 PUTWORD(p, 0); /* info level 0 */
1519 PUTWORD(p, CLI_BUFFER_SIZE);
1521 PUTSTRING(p, workgroup, RAP_MACHNAME_LEN);
1524 param, PTR_DIFF(p,param), 8, /* params, length, max */
1525 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1526 &rparam, &rprcnt, /* return params, return size */
1527 &rdata, &rdrcnt /* return data, return size */
1530 res = GETRES(rparam);
1531 cli->rap_error = res;
1533 if (res == 0 || res == ERRmoredata) {
1536 p = rparam + WORDSIZE + WORDSIZE;
1540 for (i = 0;i < count;i++, p += 16) {
1541 char ret_server[RAP_MACHNAME_LEN];
1543 GETSTRINGF(p, ret_server, RAP_MACHNAME_LEN);
1544 if (strequal(ret_server, cli->desthost)) {
1545 found_server = True;
1551 DEBUG(4,("cli_ns_check_server_type: machine %s failed the NetServerEnum call. "
1552 "Error was : %s.\n", cli->desthost, cli_errstr(cli) ));
1559 return found_server;
1563 /****************************************************************************
1564 perform a NetWkstaUserLogoff
1565 ****************************************************************************/
1566 BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation)
1568 char *rparam = NULL;
1571 unsigned int rdrcnt,rprcnt;
1572 char param[WORDSIZE /* api number */
1573 +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */
1574 +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */
1575 +RAP_USERNAME_LEN+1 /* user name+pad */
1576 +RAP_MACHNAME_LEN /* wksta name */
1577 +WORDSIZE /* buffer size */
1578 +WORDSIZE]; /* buffer size? */
1581 memset(param, 0, sizeof(param));
1583 /* send a SMBtrans command with api NetWkstaUserLogoff */
1584 p = make_header(param, RAP_WWkstaUserLogoff,
1585 RAP_NetWkstaUserLogoff_REQ, RAP_USER_LOGOFF_INFO_L1);
1586 PUTDWORD(p, 0); /* Null pointer */
1587 PUTDWORD(p, 0); /* Null pointer */
1588 fstrcpy(upperbuf, user);
1589 strupper_m(upperbuf);
1590 PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN);
1591 p++; /* strange format, but ok */
1592 fstrcpy(upperbuf, workstation);
1593 strupper_m(upperbuf);
1594 PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN);
1595 PUTWORD(p, CLI_BUFFER_SIZE);
1596 PUTWORD(p, CLI_BUFFER_SIZE);
1599 param, PTR_DIFF(p,param),1024, /* param, length, max */
1600 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
1601 &rparam, &rprcnt, /* return params, return size */
1602 &rdata, &rdrcnt /* return data, return size */
1604 cli->rap_error = GETRES(rparam);
1606 if (cli->rap_error != 0) {
1607 DEBUG(4,("NetwkstaUserLogoff gave error %d\n", cli->rap_error));
1613 return (cli->rap_error == 0);
1616 int cli_NetPrintQEnum(struct cli_state *cli,
1617 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1618 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1620 char param[WORDSIZE /* api number */
1621 +sizeof(RAP_NetPrintQEnum_REQ) /* req string */
1622 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1623 +WORDSIZE /* info level */
1624 +WORDSIZE /* buffer size */
1625 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1627 char *rparam = NULL;
1629 unsigned int rprcnt, rdrcnt;
1633 memset(param, '\0',sizeof(param));
1634 p = make_header(param, RAP_WPrintQEnum,
1635 RAP_NetPrintQEnum_REQ, RAP_PRINTQ_INFO_L2);
1636 PUTWORD(p,2); /* Info level 2 */
1637 PUTWORD(p,0xFFE0); /* Return buffer size */
1638 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1641 param, PTR_DIFF(p,param),1024,
1642 NULL, 0, CLI_BUFFER_SIZE,
1645 res = GETRES(rparam);
1646 cli->rap_error = res;
1648 DEBUG(1,("NetPrintQEnum gave error %d\n", res));
1653 if (res == 0 || res == ERRmoredata) {
1654 int i, converter, count;
1656 p = rparam + WORDSIZE;
1657 GETWORD(p, converter);
1661 for (i=0;i<count;i++) {
1662 pstring qname, sep_file, print_proc, dest, parms, comment;
1663 uint16 jobcount, priority, start_time, until_time, status;
1665 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1667 GETWORD(p, priority);
1668 GETWORD(p, start_time);
1669 GETWORD(p, until_time);
1670 GETSTRINGP(p, sep_file, rdata, converter);
1671 GETSTRINGP(p, print_proc, rdata, converter);
1672 GETSTRINGP(p, dest, rdata, converter);
1673 GETSTRINGP(p, parms, rdata, converter);
1674 GETSTRINGP(p, parms, comment, converter);
1676 GETWORD(p, jobcount);
1678 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1679 dest, parms, comment, status, jobcount);
1683 for (j=0;j<jobcount;j++) {
1684 uint16 jid, pos, fsstatus;
1685 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1686 unsigned int submitted, jsize;
1689 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1691 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1692 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1693 GETSTRINGP(p, jparms, rdata, converter);
1695 GETWORD(p, fsstatus);
1696 GETSTRINGP(p, jstatus, rdata, converter);
1697 GETDWORD(p, submitted);
1699 GETSTRINGP(p, jcomment, rdata, converter);
1701 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1702 jstatus, submitted, jsize, jcomment);
1707 DEBUG(4,("NetPrintQEnum res=%d\n", res));
1710 DEBUG(4,("NetPrintQEnum no data returned\n"));
1719 int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer,
1720 void (*qfn)(const char*,uint16,uint16,uint16,const char*,const char*,const char*,const char*,const char*,uint16,uint16),
1721 void (*jfn)(uint16,const char*,const char*,const char*,const char*,uint16,uint16,const char*,uint,uint,const char*))
1723 char param[WORDSIZE /* api number */
1724 +sizeof(RAP_NetPrintQGetInfo_REQ) /* req string */
1725 +sizeof(RAP_PRINTQ_INFO_L2) /* return string */
1726 +RAP_SHARENAME_LEN /* printer name */
1727 +WORDSIZE /* info level */
1728 +WORDSIZE /* buffer size */
1729 +sizeof(RAP_SMB_PRINT_JOB_L1)]; /* more ret data */
1731 char *rparam = NULL;
1733 unsigned int rprcnt, rdrcnt;
1737 memset(param, '\0',sizeof(param));
1738 p = make_header(param, RAP_WPrintQGetInfo,
1739 RAP_NetPrintQGetInfo_REQ, RAP_PRINTQ_INFO_L2);
1740 PUTSTRING(p, printer, RAP_SHARENAME_LEN-1);
1741 PUTWORD(p, 2); /* Info level 2 */
1742 PUTWORD(p,0xFFE0); /* Return buffer size */
1743 PUTSTRING(p, RAP_SMB_PRINT_JOB_L1, 0);
1746 param, PTR_DIFF(p,param),1024,
1747 NULL, 0, CLI_BUFFER_SIZE,
1750 res = GETRES(rparam);
1751 cli->rap_error = res;
1753 DEBUG(1,("NetPrintQGetInfo gave error %d\n", res));
1758 if (res == 0 || res == ERRmoredata) {
1759 int rsize, converter;
1760 pstring qname, sep_file, print_proc, dest, parms, comment;
1761 uint16 jobcount, priority, start_time, until_time, status;
1763 p = rparam + WORDSIZE;
1764 GETWORD(p, converter);
1768 GETSTRINGF(p, qname, RAP_SHARENAME_LEN);
1770 GETWORD(p, priority);
1771 GETWORD(p, start_time);
1772 GETWORD(p, until_time);
1773 GETSTRINGP(p, sep_file, rdata, converter);
1774 GETSTRINGP(p, print_proc, rdata, converter);
1775 GETSTRINGP(p, dest, rdata, converter);
1776 GETSTRINGP(p, parms, rdata, converter);
1777 GETSTRINGP(p, comment, rdata, converter);
1779 GETWORD(p, jobcount);
1780 qfn(qname, priority, start_time, until_time, sep_file, print_proc,
1781 dest, parms, comment, status, jobcount);
1784 for (j=0;(j<jobcount)&&(PTR_DIFF(p,rdata)< rsize);j++) {
1785 uint16 jid, pos, fsstatus;
1786 pstring ownername, notifyname, datatype, jparms, jstatus, jcomment;
1787 unsigned int submitted, jsize;
1790 GETSTRINGF(p, ownername, RAP_USERNAME_LEN);
1792 GETSTRINGF(p, notifyname, RAP_MACHNAME_LEN);
1793 GETSTRINGF(p, datatype, RAP_DATATYPE_LEN);
1794 GETSTRINGP(p, jparms, rdata, converter);
1796 GETWORD(p, fsstatus);
1797 GETSTRINGP(p, jstatus, rdata, converter);
1798 GETDWORD(p, submitted);
1800 GETSTRINGP(p, jcomment, rdata, converter);
1802 jfn(jid, ownername, notifyname, datatype, jparms, pos, fsstatus,
1803 jstatus, submitted, jsize, jcomment);
1807 DEBUG(4,("NetPrintQGetInfo res=%d\n", res));
1810 DEBUG(4,("NetPrintQGetInfo no data returned\n"));
1819 /****************************************************************************
1820 call a NetServiceEnum - list running services on a different host
1821 ****************************************************************************/
1822 int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const char *, void *), void *state)
1824 char param[WORDSIZE /* api number */
1825 +sizeof(RAP_NetServiceEnum_REQ) /* parm string */
1826 +sizeof(RAP_SERVICE_INFO_L2) /* return string */
1827 +WORDSIZE /* info level */
1828 +WORDSIZE]; /* buffer size */
1830 char *rparam = NULL;
1832 unsigned int rprcnt, rdrcnt;
1836 memset(param, '\0', sizeof(param));
1837 p = make_header(param, RAP_WServiceEnum,
1838 RAP_NetServiceEnum_REQ, RAP_SERVICE_INFO_L2);
1839 PUTWORD(p,2); /* Info level 2 */
1840 PUTWORD(p,0xFFE0); /* Return buffer size */
1843 param, PTR_DIFF(p,param),8,
1844 NULL, 0, 0xFFE0 /* data area size */,
1847 res = GETRES(rparam);
1848 cli->rap_error = res;
1849 if(cli->rap_error == 234)
1850 DEBUG(1,("Not all service names were returned (such as those longer than 15 characters)\n"));
1851 else if (cli->rap_error != 0) {
1852 DEBUG(1,("NetServiceEnum gave error %d\n", cli->rap_error));
1857 if (res == 0 || res == ERRmoredata) {
1860 p = rparam + WORDSIZE + WORDSIZE; /* skip result and converter */
1863 for (i=0,p=rdata;i<count;i++) {
1865 char servicename[RAP_SRVCNAME_LEN];
1867 GETSTRINGF(p, servicename, RAP_SRVCNAME_LEN);
1868 p+=8; /* pass status words */
1869 GETSTRINGF(p, comment, RAP_SRVCCMNT_LEN);
1871 fn(servicename, comment, cli); /* BB add status too */
1874 DEBUG(4,("NetServiceEnum res=%d\n", res));
1877 DEBUG(4,("NetServiceEnum no data returned\n"));
1887 /****************************************************************************
1888 call a NetSessionEnum - list workstations with sessions to an SMB server
1889 ****************************************************************************/
1890 int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, uint16, uint16, uint, uint, uint, char *))
1892 char param[WORDSIZE /* api number */
1893 +sizeof(RAP_NetSessionEnum_REQ) /* parm string */
1894 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1895 +WORDSIZE /* info level */
1896 +WORDSIZE]; /* buffer size */
1898 char *rparam = NULL;
1900 unsigned int rprcnt, rdrcnt;
1903 memset(param, '\0', sizeof(param));
1904 p = make_header(param, RAP_WsessionEnum,
1905 RAP_NetSessionEnum_REQ, RAP_SESSION_INFO_L2);
1906 PUTWORD(p,2); /* Info level 2 */
1907 PUTWORD(p,0xFF); /* Return buffer size */
1910 param, PTR_DIFF(p,param),8,
1911 NULL, 0, CLI_BUFFER_SIZE,
1914 res = GETRES(rparam);
1915 cli->rap_error = res;
1917 DEBUG(1,("NetSessionEnum gave error %d\n", res));
1922 if (res == 0 || res == ERRmoredata) {
1923 int i, converter, count;
1925 p = rparam + WORDSIZE;
1926 GETWORD(p, converter);
1929 for (i=0,p=rdata;i<count;i++) {
1930 pstring wsname, username, clitype_name;
1931 uint16 num_conns, num_opens, num_users;
1932 unsigned int sess_time, idle_time, user_flags;
1934 GETSTRINGP(p, wsname, rdata, converter);
1935 GETSTRINGP(p, username, rdata, converter);
1936 GETWORD(p, num_conns);
1937 GETWORD(p, num_opens);
1938 GETWORD(p, num_users);
1939 GETDWORD(p, sess_time);
1940 GETDWORD(p, idle_time);
1941 GETDWORD(p, user_flags);
1942 GETSTRINGP(p, clitype_name, rdata, converter);
1944 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
1945 idle_time, user_flags, clitype_name);
1949 DEBUG(4,("NetSessionEnum res=%d\n", res));
1952 DEBUG(4,("NetSesssionEnum no data returned\n"));
1961 /****************************************************************************
1962 Call a NetSessionGetInfo - get information about other session to an SMB server.
1963 ****************************************************************************/
1965 int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void (*fn)(const char *, const char *, uint16, uint16, uint16, uint, uint, uint, const char *))
1967 char param[WORDSIZE /* api number */
1968 +sizeof(RAP_NetSessionGetInfo_REQ) /* req string */
1969 +sizeof(RAP_SESSION_INFO_L2) /* return string */
1970 +RAP_MACHNAME_LEN /* wksta name */
1971 +WORDSIZE /* info level */
1972 +WORDSIZE]; /* buffer size */
1974 char *rparam = NULL;
1976 unsigned int rprcnt, rdrcnt;
1980 memset(param, '\0', sizeof(param));
1981 p = make_header(param, RAP_WsessionGetInfo,
1982 RAP_NetSessionGetInfo_REQ, RAP_SESSION_INFO_L2);
1983 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
1984 PUTWORD(p,2); /* Info level 2 */
1985 PUTWORD(p,0xFF); /* Return buffer size */
1988 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
1989 NULL, 0, CLI_BUFFER_SIZE,
1992 cli->rap_error = SVAL(rparam,0);
1993 if (cli->rap_error != 0) {
1994 DEBUG(1,("NetSessionGetInfo gave error %d\n", cli->rap_error));
1999 res = GETRES(rparam);
2001 if (res == 0 || res == ERRmoredata) {
2003 pstring wsname, username, clitype_name;
2004 uint16 num_conns, num_opens, num_users;
2005 unsigned int sess_time, idle_time, user_flags;
2007 p = rparam + WORDSIZE;
2008 GETWORD(p, converter);
2009 p += WORDSIZE; /* skip rsize */
2012 GETSTRINGP(p, wsname, rdata, converter);
2013 GETSTRINGP(p, username, rdata, converter);
2014 GETWORD(p, num_conns);
2015 GETWORD(p, num_opens);
2016 GETWORD(p, num_users);
2017 GETDWORD(p, sess_time);
2018 GETDWORD(p, idle_time);
2019 GETDWORD(p, user_flags);
2020 GETSTRINGP(p, clitype_name, rdata, converter);
2022 fn(wsname, username, num_conns, num_opens, num_users, sess_time,
2023 idle_time, user_flags, clitype_name);
2025 DEBUG(4,("NetSessionGetInfo res=%d\n", res));
2028 DEBUG(4,("NetSessionGetInfo no data returned\n"));
2037 /****************************************************************************
2038 call a NetSessionDel - close a session to an SMB server
2039 ****************************************************************************/
2040 int cli_NetSessionDel(struct cli_state *cli, const char *workstation)
2042 char param[WORDSIZE /* api number */
2043 +sizeof(RAP_NetSessionDel_REQ) /* req string */
2044 +1 /* no return string */
2045 +RAP_MACHNAME_LEN /* workstation name */
2046 +WORDSIZE]; /* reserved (0) */
2048 char *rparam = NULL;
2050 unsigned int rprcnt, rdrcnt;
2053 memset(param, '\0', sizeof(param));
2054 p = make_header(param, RAP_WsessionDel, RAP_NetSessionDel_REQ, NULL);
2055 PUTSTRING(p, workstation, RAP_MACHNAME_LEN-1);
2056 PUTWORD(p,0); /* reserved word of 0 */
2058 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
2059 NULL, 0, 200, /* data, length, maxlen */
2060 &rparam, &rprcnt, /* return params, length */
2061 &rdata, &rdrcnt)) /* return data, length */
2063 res = GETRES(rparam);
2064 cli->rap_error = res;
2070 DEBUG(4,("NetFileClose2 res=%d\n", res));
2074 DEBUG(4,("NetFileClose2 failed\n"));
2084 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))
2086 char param[WORDSIZE /* api number */
2087 +sizeof(RAP_NetConnectionEnum_REQ) /* req string */
2088 +sizeof(RAP_CONNECTION_INFO_L1) /* return string */
2089 +RAP_MACHNAME_LEN /* wksta name */
2090 +WORDSIZE /* info level */
2091 +WORDSIZE]; /* buffer size */
2093 char *rparam = NULL;
2095 unsigned int rprcnt, rdrcnt;
2098 memset(param, '\0', sizeof(param));
2099 p = make_header(param, RAP_WconnectionEnum,
2100 RAP_NetConnectionEnum_REQ, RAP_CONNECTION_INFO_L1);
2101 PUTSTRING(p, qualifier, RAP_MACHNAME_LEN-1);/* Workstation name */
2102 PUTWORD(p,1); /* Info level 1 */
2103 PUTWORD(p,0xFFE0); /* Return buffer size */
2106 param, PTR_DIFF(p,param),PTR_DIFF(p,param),
2107 NULL, 0, CLI_BUFFER_SIZE,
2110 res = GETRES(rparam);
2111 cli->rap_error = res;
2113 DEBUG(1,("NetConnectionEnum gave error %d\n", res));
2117 if (res == 0 || res == ERRmoredata) {
2118 int i, converter, count;
2120 p = rparam + WORDSIZE;
2121 GETWORD(p, converter);
2124 for (i=0,p=rdata;i<count;i++) {
2125 pstring netname, username;
2126 uint16 conn_id, conn_type, num_opens, num_users;
2127 unsigned int conn_time;
2130 GETWORD(p,conn_type);
2131 GETWORD(p,num_opens);
2132 GETWORD(p,num_users);
2133 GETDWORD(p,conn_time);
2134 GETSTRINGP(p, username, rdata, converter);
2135 GETSTRINGP(p, netname, rdata, converter);
2137 fn(conn_id, conn_type, num_opens, num_users, conn_time,
2142 DEBUG(4,("NetConnectionEnum res=%d\n", res));
2145 DEBUG(4,("NetConnectionEnum no data returned\n"));