r6334: revert 3.0.15pre1 changes. roll back to 3.0.14.
[Samba.git] / source / libsmb / clirap.c
blob8e6742d438077cb608c5740812211b2b0ed33711
1 /*
2 Unix SMB/CIFS implementation.
3 client RAP calls
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Gerald (Jerry) Carter 2004
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define NO_SYSLOG
24 #include "includes.h"
27 /****************************************************************************
28 Call a remote api on an arbitrary pipe. takes param, data and setup buffers.
29 ****************************************************************************/
30 BOOL cli_api_pipe(struct cli_state *cli, const char *pipe_name,
31 uint16 *setup, uint32 setup_count, uint32 max_setup_count,
32 char *params, uint32 param_count, uint32 max_param_count,
33 char *data, uint32 data_count, uint32 max_data_count,
34 char **rparam, uint32 *rparam_count,
35 char **rdata, uint32 *rdata_count)
37 cli_send_trans(cli, SMBtrans,
38 pipe_name,
39 0,0, /* fid, flags */
40 setup, setup_count, max_setup_count,
41 params, param_count, max_param_count,
42 data, data_count, max_data_count);
44 return (cli_receive_trans(cli, SMBtrans,
45 rparam, (unsigned int *)rparam_count,
46 rdata, (unsigned int *)rdata_count));
49 /****************************************************************************
50 call a remote api
51 ****************************************************************************/
52 BOOL cli_api(struct cli_state *cli,
53 char *param, int prcnt, int mprcnt,
54 char *data, int drcnt, int mdrcnt,
55 char **rparam, unsigned int *rprcnt,
56 char **rdata, unsigned int *rdrcnt)
58 cli_send_trans(cli,SMBtrans,
59 PIPE_LANMAN, /* Name */
60 0,0, /* fid, flags */
61 NULL,0,0, /* Setup, length, max */
62 param, prcnt, mprcnt, /* Params, length, max */
63 data, drcnt, mdrcnt /* Data, length, max */
66 return (cli_receive_trans(cli,SMBtrans,
67 rparam, rprcnt,
68 rdata, rdrcnt));
72 /****************************************************************************
73 perform a NetWkstaUserLogon
74 ****************************************************************************/
75 BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
77 char *rparam = NULL;
78 char *rdata = NULL;
79 char *p;
80 unsigned int rdrcnt,rprcnt;
81 pstring param;
83 memset(param, 0, sizeof(param));
85 /* send a SMBtrans command with api NetWkstaUserLogon */
86 p = param;
87 SSVAL(p,0,132); /* api number */
88 p += 2;
89 pstrcpy_base(p,"OOWb54WrLh",param);
90 p = skip_string(p,1);
91 pstrcpy_base(p,"WB21BWDWWDDDDDDDzzzD",param);
92 p = skip_string(p,1);
93 SSVAL(p,0,1);
94 p += 2;
95 pstrcpy_base(p,user,param);
96 strupper_m(p);
97 p += 21;
98 p++;
99 p += 15;
100 p++;
101 pstrcpy_base(p, workstation, param);
102 strupper_m(p);
103 p += 16;
104 SSVAL(p, 0, CLI_BUFFER_SIZE);
105 p += 2;
106 SSVAL(p, 0, CLI_BUFFER_SIZE);
107 p += 2;
109 if (cli_api(cli,
110 param, PTR_DIFF(p,param),1024, /* param, length, max */
111 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
112 &rparam, &rprcnt, /* return params, return size */
113 &rdata, &rdrcnt /* return data, return size */
114 )) {
115 cli->rap_error = rparam? SVAL(rparam,0) : -1;
116 p = rdata;
118 if (cli->rap_error == 0) {
119 DEBUG(4,("NetWkstaUserLogon success\n"));
120 cli->privileges = SVAL(p, 24);
121 /* The cli->eff_name field used to be set here
122 but it wasn't used anywhere else. */
123 } else {
124 DEBUG(1,("NetwkstaUserLogon gave error %d\n", cli->rap_error));
128 SAFE_FREE(rparam);
129 SAFE_FREE(rdata);
130 return (cli->rap_error == 0);
133 /****************************************************************************
134 call a NetShareEnum - try and browse available connections on a host
135 ****************************************************************************/
136 int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, const char *, void *), void *state)
138 char *rparam = NULL;
139 char *rdata = NULL;
140 char *p;
141 unsigned int rdrcnt,rprcnt;
142 pstring param;
143 int count = -1;
145 /* now send a SMBtrans command with api RNetShareEnum */
146 p = param;
147 SSVAL(p,0,0); /* api number */
148 p += 2;
149 pstrcpy_base(p,"WrLeh",param);
150 p = skip_string(p,1);
151 pstrcpy_base(p,"B13BWz",param);
152 p = skip_string(p,1);
153 SSVAL(p,0,1);
155 * Win2k needs a *smaller* buffer than 0xFFFF here -
156 * it returns "out of server memory" with 0xFFFF !!! JRA.
158 SSVAL(p,2,0xFFE0);
159 p += 4;
161 if (cli_api(cli,
162 param, PTR_DIFF(p,param), 1024, /* Param, length, maxlen */
163 NULL, 0, 0xFFE0, /* data, length, maxlen - Win2k needs a small buffer here too ! */
164 &rparam, &rprcnt, /* return params, length */
165 &rdata, &rdrcnt)) /* return data, length */
167 int res = rparam? SVAL(rparam,0) : -1;
169 if (res == 0 || res == ERRmoredata) {
170 int converter=SVAL(rparam,2);
171 int i;
173 count=SVAL(rparam,4);
174 p = rdata;
176 for (i=0;i<count;i++,p+=20) {
177 char *sname = p;
178 int type = SVAL(p,14);
179 int comment_offset = IVAL(p,16) & 0xFFFF;
180 const char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
181 pstring s1, s2;
183 pull_ascii_pstring(s1, sname);
184 pull_ascii_pstring(s2, cmnt);
186 fn(s1, type, s2, state);
188 } else {
189 DEBUG(4,("NetShareEnum res=%d\n", res));
191 } else {
192 DEBUG(4,("NetShareEnum failed\n"));
195 SAFE_FREE(rparam);
196 SAFE_FREE(rdata);
198 return count;
202 /****************************************************************************
203 call a NetServerEnum for the specified workgroup and servertype mask. This
204 function then calls the specified callback function for each name returned.
206 The callback function takes 4 arguments: the machine name, the server type,
207 the comment and a state pointer.
208 ****************************************************************************/
209 BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
210 void (*fn)(const char *, uint32, const char *, void *),
211 void *state)
213 char *rparam = NULL;
214 char *rdata = NULL;
215 unsigned int rdrcnt,rprcnt;
216 char *p;
217 pstring param;
218 int uLevel = 1;
219 int count = -1;
221 errno = 0; /* reset */
223 /* send a SMBtrans command with api NetServerEnum */
224 p = param;
225 SSVAL(p,0,0x68); /* api number */
226 p += 2;
227 pstrcpy_base(p,"WrLehDz", param);
228 p = skip_string(p,1);
230 pstrcpy_base(p,"B16BBDz", param);
232 p = skip_string(p,1);
233 SSVAL(p,0,uLevel);
234 SSVAL(p,2,CLI_BUFFER_SIZE);
235 p += 4;
236 SIVAL(p,0,stype);
237 p += 4;
239 p += push_ascii(p, workgroup, sizeof(pstring)-PTR_DIFF(p,param)-1, STR_TERMINATE|STR_UPPER);
241 if (cli_api(cli,
242 param, PTR_DIFF(p,param), 8, /* params, length, max */
243 NULL, 0, CLI_BUFFER_SIZE, /* data, length, max */
244 &rparam, &rprcnt, /* return params, return size */
245 &rdata, &rdrcnt /* return data, return size */
246 )) {
247 int res = rparam? SVAL(rparam,0) : -1;
249 if (res == 0 || res == ERRmoredata) {
250 int i;
251 int converter=SVAL(rparam,2);
253 count=SVAL(rparam,4);
254 p = rdata;
256 for (i = 0;i < count;i++, p += 26) {
257 char *sname = p;
258 int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
259 const char *cmnt = comment_offset?(rdata+comment_offset):"";
260 pstring s1, s2;
262 if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue;
264 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
266 pull_ascii_pstring(s1, sname);
267 pull_ascii_pstring(s2, cmnt);
268 fn(s1, stype, s2, state);
273 SAFE_FREE(rparam);
274 SAFE_FREE(rdata);
276 if (count < 0) {
277 errno = cli_errno(cli);
278 } else {
279 if (!count) {
280 /* this is a very special case, when the domain master for the
281 work group isn't part of the work group itself, there is something
282 wild going on */
283 errno = ENOENT;
287 return(count > 0);
292 /****************************************************************************
293 Send a SamOEMChangePassword command
294 ****************************************************************************/
295 BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char *new_password,
296 const char *old_password)
298 pstring param;
299 char data[532];
300 char *p = param;
301 unsigned char old_pw_hash[16];
302 unsigned char new_pw_hash[16];
303 unsigned int data_len;
304 unsigned int param_len = 0;
305 char *rparam = NULL;
306 char *rdata = NULL;
307 unsigned int rprcnt, rdrcnt;
309 if (strlen(user) >= sizeof(fstring)-1) {
310 DEBUG(0,("cli_oem_change_password: user name %s is too long.\n", user));
311 return False;
314 SSVAL(p,0,214); /* SamOEMChangePassword command. */
315 p += 2;
316 pstrcpy_base(p, "zsT", param);
317 p = skip_string(p,1);
318 pstrcpy_base(p, "B516B16", param);
319 p = skip_string(p,1);
320 pstrcpy_base(p,user, param);
321 p = skip_string(p,1);
322 SSVAL(p,0,532);
323 p += 2;
325 param_len = PTR_DIFF(p,param);
328 * Get the Lanman hash of the old password, we
329 * use this as the key to make_oem_passwd_hash().
331 E_deshash(old_password, old_pw_hash);
333 encode_pw_buffer(data, new_password, STR_ASCII);
335 #ifdef DEBUG_PASSWORD
336 DEBUG(100,("make_oem_passwd_hash\n"));
337 dump_data(100, data, 516);
338 #endif
339 SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, 516);
342 * Now place the old password hash in the data.
344 E_deshash(new_password, new_pw_hash);
346 E_old_pw_hash( new_pw_hash, old_pw_hash, (uchar *)&data[516]);
348 data_len = 532;
350 if (cli_send_trans(cli,SMBtrans,
351 PIPE_LANMAN, /* name */
352 0,0, /* fid, flags */
353 NULL,0,0, /* setup, length, max */
354 param,param_len,2, /* param, length, max */
355 data,data_len,0 /* data, length, max */
356 ) == False) {
357 DEBUG(0,("cli_oem_change_password: Failed to send password change for user %s\n",
358 user ));
359 return False;
362 if (!cli_receive_trans(cli,SMBtrans,
363 &rparam, &rprcnt,
364 &rdata, &rdrcnt)) {
365 DEBUG(0,("cli_oem_change_password: Failed to recieve reply to password change for user %s\n",
366 user ));
367 return False;
370 if (rparam)
371 cli->rap_error = SVAL(rparam,0);
373 SAFE_FREE(rparam);
374 SAFE_FREE(rdata);
376 return (cli->rap_error == 0);
380 /****************************************************************************
381 send a qpathinfo call
382 ****************************************************************************/
383 BOOL cli_qpathinfo(struct cli_state *cli, const char *fname,
384 time_t *c_time, time_t *a_time, time_t *m_time,
385 size_t *size, uint16 *mode)
387 unsigned int data_len = 0;
388 unsigned int param_len = 0;
389 unsigned int rparam_len, rdata_len;
390 uint16 setup = TRANSACT2_QPATHINFO;
391 pstring param;
392 char *rparam=NULL, *rdata=NULL;
393 int count=8;
394 BOOL ret;
395 time_t (*date_fn)(void *);
396 char *p;
398 p = param;
399 memset(p, 0, 6);
400 SSVAL(p, 0, SMB_INFO_STANDARD);
401 p += 6;
402 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
404 param_len = PTR_DIFF(p, param);
406 do {
407 ret = (cli_send_trans(cli, SMBtrans2,
408 NULL, /* Name */
409 -1, 0, /* fid, flags */
410 &setup, 1, 0, /* setup, length, max */
411 param, param_len, 10, /* param, length, max */
412 NULL, data_len, cli->max_xmit /* data, length, max */
413 ) &&
414 cli_receive_trans(cli, SMBtrans2,
415 &rparam, &rparam_len,
416 &rdata, &rdata_len));
417 if (!cli_is_dos_error(cli)) break;
418 if (!ret) {
419 /* we need to work around a Win95 bug - sometimes
420 it gives ERRSRV/ERRerror temprarily */
421 uint8 eclass;
422 uint32 ecode;
423 cli_dos_error(cli, &eclass, &ecode);
424 if (eclass != ERRSRV || ecode != ERRerror) break;
425 smb_msleep(100);
427 } while (count-- && ret==False);
429 if (!ret || !rdata || rdata_len < 22) {
430 return False;
433 if (cli->win95) {
434 date_fn = make_unix_date;
435 } else {
436 date_fn = make_unix_date2;
439 if (c_time) {
440 *c_time = date_fn(rdata+0);
442 if (a_time) {
443 *a_time = date_fn(rdata+4);
445 if (m_time) {
446 *m_time = date_fn(rdata+8);
448 if (size) {
449 *size = IVAL(rdata, 12);
451 if (mode) {
452 *mode = SVAL(rdata,l1_attrFile);
455 SAFE_FREE(rdata);
456 SAFE_FREE(rparam);
457 return True;
460 /****************************************************************************
461 send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
462 ****************************************************************************/
463 BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname,
464 time_t *c_time, time_t *a_time, time_t *m_time,
465 time_t *w_time, size_t *size, uint16 *mode,
466 SMB_INO_T *ino)
468 unsigned int data_len = 0;
469 unsigned int param_len = 0;
470 uint16 setup = TRANSACT2_QPATHINFO;
471 pstring param;
472 char *rparam=NULL, *rdata=NULL;
473 char *p;
475 p = param;
476 memset(p, 0, 6);
477 SSVAL(p, 0, SMB_QUERY_FILE_ALL_INFO);
478 p += 6;
479 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
481 param_len = PTR_DIFF(p, param);
483 if (!cli_send_trans(cli, SMBtrans2,
484 NULL, /* name */
485 -1, 0, /* fid, flags */
486 &setup, 1, 0, /* setup, length, max */
487 param, param_len, 10, /* param, length, max */
488 NULL, data_len, cli->max_xmit /* data, length, max */
489 )) {
490 return False;
493 if (!cli_receive_trans(cli, SMBtrans2,
494 &rparam, &param_len,
495 &rdata, &data_len)) {
496 return False;
499 if (!rdata || data_len < 22) {
500 return False;
503 if (c_time) {
504 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
506 if (a_time) {
507 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
509 if (m_time) {
510 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
512 if (w_time) {
513 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
515 if (mode) {
516 *mode = SVAL(rdata, 32);
518 if (size) {
519 *size = IVAL(rdata, 48);
521 if (ino) {
522 *ino = IVAL(rdata, 64);
525 SAFE_FREE(rdata);
526 SAFE_FREE(rparam);
527 return True;
531 /****************************************************************************
532 send a qfileinfo QUERY_FILE_NAME_INFO call
533 ****************************************************************************/
534 BOOL cli_qfilename(struct cli_state *cli, int fnum,
535 pstring name)
537 unsigned int data_len = 0;
538 unsigned int param_len = 0;
539 uint16 setup = TRANSACT2_QFILEINFO;
540 pstring param;
541 char *rparam=NULL, *rdata=NULL;
543 param_len = 4;
544 memset(param, 0, param_len);
545 SSVAL(param, 0, fnum);
546 SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO);
548 if (!cli_send_trans(cli, SMBtrans2,
549 NULL, /* name */
550 -1, 0, /* fid, flags */
551 &setup, 1, 0, /* setup, length, max */
552 param, param_len, 2, /* param, length, max */
553 NULL, data_len, cli->max_xmit /* data, length, max */
554 )) {
555 return False;
558 if (!cli_receive_trans(cli, SMBtrans2,
559 &rparam, &param_len,
560 &rdata, &data_len)) {
561 return False;
564 if (!rdata || data_len < 4) {
565 return False;
568 clistr_pull(cli, name, rdata+4, sizeof(pstring), IVAL(rdata, 0), STR_UNICODE);
570 return True;
574 /****************************************************************************
575 send a qfileinfo call
576 ****************************************************************************/
577 BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
578 uint16 *mode, size_t *size,
579 time_t *c_time, time_t *a_time, time_t *m_time,
580 time_t *w_time, SMB_INO_T *ino)
582 unsigned int data_len = 0;
583 unsigned int param_len = 0;
584 uint16 setup = TRANSACT2_QFILEINFO;
585 pstring param;
586 char *rparam=NULL, *rdata=NULL;
588 /* if its a win95 server then fail this - win95 totally screws it
589 up */
590 if (cli->win95) return False;
592 param_len = 4;
594 memset(param, 0, param_len);
595 SSVAL(param, 0, fnum);
596 SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO);
598 if (!cli_send_trans(cli, SMBtrans2,
599 NULL, /* name */
600 -1, 0, /* fid, flags */
601 &setup, 1, 0, /* setup, length, max */
602 param, param_len, 2, /* param, length, max */
603 NULL, data_len, cli->max_xmit /* data, length, max */
604 )) {
605 return False;
608 if (!cli_receive_trans(cli, SMBtrans2,
609 &rparam, &param_len,
610 &rdata, &data_len)) {
611 return False;
614 if (!rdata || data_len < 68) {
615 return False;
618 if (c_time) {
619 *c_time = interpret_long_date(rdata+0) - cli->serverzone;
621 if (a_time) {
622 *a_time = interpret_long_date(rdata+8) - cli->serverzone;
624 if (m_time) {
625 *m_time = interpret_long_date(rdata+16) - cli->serverzone;
627 if (w_time) {
628 *w_time = interpret_long_date(rdata+24) - cli->serverzone;
630 if (mode) {
631 *mode = SVAL(rdata, 32);
633 if (size) {
634 *size = IVAL(rdata, 48);
636 if (ino) {
637 *ino = IVAL(rdata, 64);
640 SAFE_FREE(rdata);
641 SAFE_FREE(rparam);
642 return True;
646 /****************************************************************************
647 send a qpathinfo BASIC_INFO call
648 ****************************************************************************/
649 BOOL cli_qpathinfo_basic( struct cli_state *cli, const char *name,
650 SMB_STRUCT_STAT *sbuf, uint32 *attributes )
652 unsigned int param_len = 0;
653 unsigned int data_len = 0;
654 uint16 setup = TRANSACT2_QPATHINFO;
655 char param[sizeof(pstring)+6];
656 char *rparam=NULL, *rdata=NULL;
657 char *p;
658 pstring path;
659 int len;
661 /* send full paths to dfs root shares */
663 if ( cli->dfsroot )
664 pstr_sprintf(path, "\\%s\\%s\\%s", cli->desthost, cli->share, name );
665 else
666 pstrcpy( path, name );
668 /* cleanup */
670 len = strlen( path );
671 if ( path[len] == '\\' )
672 path[len] = '\0';
674 p = param;
675 memset(p, 0, 6);
676 SSVAL(p, 0, SMB_QUERY_FILE_BASIC_INFO);
677 p += 6;
678 p += clistr_push(cli, p, path, sizeof(pstring)-6, STR_TERMINATE);
679 param_len = PTR_DIFF(p, param);
681 if (!cli_send_trans(cli, SMBtrans2,
682 NULL, /* name */
683 -1, 0, /* fid, flags */
684 &setup, 1, 0, /* setup, length, max */
685 param, param_len, 2, /* param, length, max */
686 NULL, 0, cli->max_xmit /* data, length, max */
687 )) {
688 return False;
691 if (!cli_receive_trans(cli, SMBtrans2,
692 &rparam, &param_len,
693 &rdata, &data_len)) {
694 return False;
697 if (data_len < 36) {
698 SAFE_FREE(rdata);
699 SAFE_FREE(rparam);
700 return False;
703 sbuf->st_atime = interpret_long_date( rdata+8 );
704 sbuf->st_mtime = interpret_long_date( rdata+16 );
705 sbuf->st_ctime = interpret_long_date( rdata+24 );
707 *attributes = IVAL( rdata, 32 );
709 SAFE_FREE(rparam);
710 SAFE_FREE(rdata);
712 return True;
715 /****************************************************************************
716 send a qfileinfo call
717 ****************************************************************************/
719 BOOL cli_qfileinfo_test(struct cli_state *cli, int fnum, int level, char **poutdata, uint32 *poutlen)
721 unsigned int data_len = 0;
722 unsigned int param_len = 0;
723 uint16 setup = TRANSACT2_QFILEINFO;
724 pstring param;
725 char *rparam=NULL, *rdata=NULL;
727 *poutdata = NULL;
728 *poutlen = 0;
730 /* if its a win95 server then fail this - win95 totally screws it
731 up */
732 if (cli->win95)
733 return False;
735 param_len = 4;
737 memset(param, 0, param_len);
738 SSVAL(param, 0, fnum);
739 SSVAL(param, 2, level);
741 if (!cli_send_trans(cli, SMBtrans2,
742 NULL, /* name */
743 -1, 0, /* fid, flags */
744 &setup, 1, 0, /* setup, length, max */
745 param, param_len, 2, /* param, length, max */
746 NULL, data_len, cli->max_xmit /* data, length, max */
747 )) {
748 return False;
751 if (!cli_receive_trans(cli, SMBtrans2,
752 &rparam, &param_len,
753 &rdata, &data_len)) {
754 return False;
757 *poutdata = memdup(rdata, data_len);
758 *poutlen = data_len;
760 SAFE_FREE(rdata);
761 SAFE_FREE(rparam);
762 return True;
767 /****************************************************************************
768 send a qpathinfo SMB_QUERY_FILE_ALT_NAME_INFO call
769 ****************************************************************************/
770 NTSTATUS cli_qpathinfo_alt_name(struct cli_state *cli, const char *fname, fstring alt_name)
772 unsigned int data_len = 0;
773 unsigned int param_len = 0;
774 uint16 setup = TRANSACT2_QPATHINFO;
775 pstring param;
776 char *rparam=NULL, *rdata=NULL;
777 int count=8;
778 char *p;
779 BOOL ret;
780 unsigned int len;
782 p = param;
783 memset(p, 0, 6);
784 SSVAL(p, 0, SMB_QUERY_FILE_ALT_NAME_INFO);
785 p += 6;
786 p += clistr_push(cli, p, fname, sizeof(pstring)-6, STR_TERMINATE);
788 param_len = PTR_DIFF(p, param);
790 do {
791 ret = (cli_send_trans(cli, SMBtrans2,
792 NULL, /* Name */
793 -1, 0, /* fid, flags */
794 &setup, 1, 0, /* setup, length, max */
795 param, param_len, 10, /* param, length, max */
796 NULL, data_len, cli->max_xmit /* data, length, max */
797 ) &&
798 cli_receive_trans(cli, SMBtrans2,
799 &rparam, &param_len,
800 &rdata, &data_len));
801 if (!ret && cli_is_dos_error(cli)) {
802 /* we need to work around a Win95 bug - sometimes
803 it gives ERRSRV/ERRerror temprarily */
804 uint8 eclass;
805 uint32 ecode;
806 cli_dos_error(cli, &eclass, &ecode);
807 if (eclass != ERRSRV || ecode != ERRerror) break;
808 smb_msleep(100);
810 } while (count-- && ret==False);
812 if (!ret || !rdata || data_len < 4) {
813 return NT_STATUS_UNSUCCESSFUL;
816 len = IVAL(rdata, 0);
818 if (len > data_len - 4) {
819 return NT_STATUS_INVALID_NETWORK_RESPONSE;
822 clistr_pull(cli, alt_name, rdata+4, sizeof(fstring), len, STR_UNICODE);
824 SAFE_FREE(rdata);
825 SAFE_FREE(rparam);
827 return NT_STATUS_OK;