1 /****************************************************************************
3 * Nintendo Wii/GameCube SMB implementation
6 * Modified by Tantric to utilize NTLM authentication
7 * PathInfo added by rodries
8 * SMB devoptab by scip, rodries
10 * You will find WireShark (http://www.wireshark.org/)
11 * invaluable for debugging SAMBA implementations.
14 * Implementing CIFS - Christopher R Hertel
15 * http://www.ubiqx.org/cifs/SMB.html
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2.1 of the License, or (at your option) any later version.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 ****************************************************************************/
43 #include <processor.h>
44 #include <lwp_threads.h>
45 #include <lwp_objmgr.h>
46 #include <ogc/lwp_watchdog.h>
51 #define IOS_O_NONBLOCK 0x04
52 #define RECV_TIMEOUT 5000 // in ms
57 #define SMB_OFFSET_PROTO 0
58 #define SMB_OFFSET_CMD 4
59 #define SMB_OFFSET_NTSTATUS 5
60 #define SMB_OFFSET_ECLASS 5
61 #define SMB_OFFSET_ECODE 7
62 #define SMB_OFFSET_FLAGS 9
63 #define SMB_OFFSET_FLAGS2 10
64 #define SMB_OFFSET_EXTRA 12
65 #define SMB_OFFSET_TID 24
66 #define SMB_OFFSET_PID 26
67 #define SMB_OFFSET_UID 28
68 #define SMB_OFFSET_MID 30
69 #define SMB_HEADER_SIZE 32 /*** SMB Headers are always 32 bytes long ***/
74 #define NBT_SESSISON_MSG 0x00
76 #define SMB_NEG_PROTOCOL 0x72
77 #define SMB_SETUP_ANDX 0x73
78 #define SMB_TREEC_ANDX 0x75
81 #define NBT_KEEPALIVE_MSG 0x85
82 #define KEEPALIVE_SIZE 4
87 #define SMB_TRANS2 0x32
90 #define SMB_FIND_FIRST2 1
91 #define SMB_FIND_NEXT2 2
92 #define SMB_QUERY_FS_INFO 3
93 #define SMB_QUERY_PATH_INFO 5
94 #define SMB_SET_PATH_INFO 6
95 #define SMB_QUERY_FILE_INFO 7
96 #define SMB_SET_FILE_INFO 8
97 #define SMB_CREATE_DIR 13
98 #define SMB_FIND_CLOSE2 0x34
99 #define SMB_QUERY_FILE_ALL_INFO 0x107
104 #define SMB_OPEN_ANDX 0x2d
105 #define SMB_WRITE_ANDX 0x2f
106 #define SMB_READ_ANDX 0x2e
107 #define SMB_CLOSE 0x04
113 #define T2_WORD_CNT (SMB_HEADER_SIZE)
114 #define T2_PRM_CNT (T2_WORD_CNT+1)
115 #define T2_DATA_CNT (T2_PRM_CNT+2)
116 #define T2_MAXPRM_CNT (T2_DATA_CNT+2)
117 #define T2_MAXBUFFER (T2_MAXPRM_CNT+2)
118 #define T2_SETUP_CNT (T2_MAXBUFFER+2)
119 #define T2_SPRM_CNT (T2_SETUP_CNT+10)
120 #define T2_SPRM_OFS (T2_SPRM_CNT+2)
121 #define T2_SDATA_CNT (T2_SPRM_OFS+2)
122 #define T2_SDATA_OFS (T2_SDATA_CNT+2)
123 #define T2_SSETUP_CNT (T2_SDATA_OFS+2)
124 #define T2_SUB_CMD (T2_SSETUP_CNT+2)
125 #define T2_BYTE_CNT (T2_SUB_CMD+2)
128 #define SMB_PROTO 0x424d53ff
129 #define SMB_HANDLE_NULL 0xffffffff
130 #define SMB_MAX_BUFFERSIZE (62*1024) // cannot be larger than u16 (65536)
131 #define SMB_MAX_TRANSMIT_SIZE 7236
132 #define SMB_DEF_READOFFSET 59
134 #define SMB_CONNHANDLES_MAX 8
135 #define SMB_FILEHANDLES_MAX (32*SMB_CONNHANDLES_MAX)
137 #define SMB_OBJTYPE_HANDLE 7
138 #define SMB_CHECK_HANDLE(hndl) \
140 if(((hndl)==SMB_HANDLE_NULL) || (LWP_OBJTYPE(hndl)!=SMB_OBJTYPE_HANDLE)) \
154 typedef struct _nbtsmb
156 u8 msg
; /*** NBT Message ***/
157 u8 flags
; /*** Not much here really ***/
158 u16 length
; /*** Length, excluding NBT ***/
159 u8 smb
[SMB_MAX_TRANSMIT_SIZE
]; /*** Wii Actual is 7240 bytes ***/
163 * Session Information
165 typedef struct _smbsession
183 typedef struct _smbhandle
191 struct sockaddr_in server_addr
;
197 static u32 smb_dialectcnt
= 1;
198 static BOOL smb_inited
= FALSE
;
199 static lwp_objinfo smb_handle_objects
;
200 static lwp_queue smb_filehandle_queue
;
201 static struct _smbfile smb_filehandles
[SMB_FILEHANDLES_MAX
];
202 static const char *smb_dialects
[] = {"NT LM 0.12",NULL
};
204 extern void ntlm_smb_nt_encrypt(const char *passwd
, const u8
* challenge
, u8
* answer
);
207 * SMB Endian aware supporting functions
209 * SMB always uses Intel Little-Endian values, so htons etc are
210 * of little or no use :) ... Thanks M$
213 /*** get unsigned char ***/
214 static __inline__ u8
getUChar(u8
*buffer
,u32 offset
)
216 return (u8
)buffer
[offset
];
219 /*** set unsigned char ***/
220 static __inline__
void setUChar(u8
*buffer
,u32 offset
,u8 value
)
222 buffer
[offset
] = value
;
225 /*** get signed short ***/
226 static __inline__ s16
getShort(u8
*buffer
,u32 offset
)
228 return (s16
)((buffer
[offset
+1]<<8)|(buffer
[offset
]));
231 /*** get unsigned short ***/
232 static __inline__ u16
getUShort(u8
*buffer
,u32 offset
)
234 return (u16
)((buffer
[offset
+1]<<8)|(buffer
[offset
]));
237 /*** set unsigned short ***/
238 static __inline__
void setUShort(u8
*buffer
,u32 offset
,u16 value
)
240 buffer
[offset
] = (value
&0xff);
241 buffer
[offset
+1] = ((value
&0xff00)>>8);
244 /*** get unsigned int ***/
245 static __inline__ u32
getUInt(u8
*buffer
,u32 offset
)
247 return (u32
)((buffer
[offset
+3]<<24)|(buffer
[offset
+2]<<16)|(buffer
[offset
+1]<<8)|buffer
[offset
]);
250 /*** set unsigned int ***/
251 static __inline__
void setUInt(u8
*buffer
,u32 offset
,u32 value
)
253 buffer
[offset
] = (value
&0xff);
254 buffer
[offset
+1] = ((value
&0xff00)>>8);
255 buffer
[offset
+2] = ((value
&0xff0000)>>16);
256 buffer
[offset
+3] = ((value
&0xff000000)>>24);
259 /*** get unsigned long long ***/
260 static __inline__ u64
getULongLong(u8
*buffer
,u32 offset
)
262 return (u64
)(getUInt(buffer
, offset
) | (u64
)getUInt(buffer
, offset
+4) << 32);
265 static __inline__ SMBHANDLE
* __smb_handle_open(SMBCONN smbhndl
)
270 SMB_CHECK_HANDLE(smbhndl
);
272 _CPU_ISR_Disable(level
);
273 handle
= (SMBHANDLE
*)__lwp_objmgr_getnoprotection(&smb_handle_objects
,LWP_OBJMASKID(smbhndl
));
274 _CPU_ISR_Restore(level
);
279 static __inline__
void __smb_handle_free(SMBHANDLE
*handle
)
283 _CPU_ISR_Disable(level
);
284 __lwp_objmgr_close(&smb_handle_objects
,&handle
->object
);
285 __lwp_objmgr_free(&smb_handle_objects
,&handle
->object
);
286 _CPU_ISR_Restore(level
);
289 static void __smb_init()
292 __lwp_objmgr_initinfo(&smb_handle_objects
,SMB_CONNHANDLES_MAX
,sizeof(SMBHANDLE
));
293 __lwp_queue_initialize(&smb_filehandle_queue
,smb_filehandles
,SMB_FILEHANDLES_MAX
,sizeof(struct _smbfile
));
296 static SMBHANDLE
* __smb_allocate_handle()
301 _CPU_ISR_Disable(level
);
302 handle
= (SMBHANDLE
*)__lwp_objmgr_allocate(&smb_handle_objects
);
306 handle
->server_name
= NULL
;
307 handle
->share_name
= NULL
;
308 handle
->sck_server
= INVALID_SOCKET
;
309 handle
->conn_valid
= FALSE
;
310 __lwp_objmgr_open(&smb_handle_objects
,&handle
->object
);
312 _CPU_ISR_Restore(level
);
316 static void __smb_free_handle(SMBHANDLE
*handle
)
318 if(handle
->user
) free(handle
->user
);
319 if(handle
->pwd
) free(handle
->pwd
);
320 if(handle
->server_name
) free(handle
->server_name
);
321 if(handle
->share_name
) free(handle
->share_name
);
325 handle
->server_name
= NULL
;
326 handle
->share_name
= NULL
;
327 handle
->sck_server
= INVALID_SOCKET
;
329 __smb_handle_free(handle
);
332 static void MakeSMBHeader(u8 command
,u8 flags
,u16 flags2
,SMBHANDLE
*handle
)
334 u8
*ptr
= handle
->message
.smb
;
335 NBTSMB
*nbt
= &handle
->message
;
336 SMBSESSION
*sess
= &handle
->session
;
338 memset(nbt
,0,sizeof(NBTSMB
));
340 setUInt(ptr
,SMB_OFFSET_PROTO
,SMB_PROTO
);
341 setUChar(ptr
,SMB_OFFSET_CMD
,command
);
342 setUChar(ptr
,SMB_OFFSET_FLAGS
,flags
);
343 setUShort(ptr
,SMB_OFFSET_FLAGS2
,flags2
);
344 setUShort(ptr
,SMB_OFFSET_TID
,sess
->TID
);
345 setUShort(ptr
,SMB_OFFSET_PID
,sess
->PID
);
346 setUShort(ptr
,SMB_OFFSET_UID
,sess
->UID
);
347 setUShort(ptr
,SMB_OFFSET_MID
,sess
->MID
);
349 ptr
[SMB_HEADER_SIZE
] = 0;
355 static void MakeTRANS2Header(u8 subcommand
,SMBHANDLE
*handle
)
357 u8
*ptr
= handle
->message
.smb
;
358 SMBSESSION
*sess
= &handle
->session
;
360 setUChar(ptr
, T2_WORD_CNT
, 15);
361 setUShort(ptr
, T2_MAXPRM_CNT
, 10);
362 setUShort(ptr
, T2_MAXBUFFER
, sess
->MaxBuffer
);
363 setUChar(ptr
, T2_SSETUP_CNT
, 1);
364 setUShort(ptr
, T2_SUB_CMD
, subcommand
);
370 * blocking call with timeout
371 * will return when ALL data has been sent. Number of bytes sent is returned.
372 * OR timeout. Timeout will return -1
373 * OR network error. -ve value will be returned
375 static inline s32
smb_send(s32 s
,const void *data
,s32 size
)
380 t1
=ticks_to_millisecs(gettime());
383 ret
=net_send(s
,data
,len
,0);
386 t2
=ticks_to_millisecs(gettime());
387 if( (t2
- t1
) > RECV_TIMEOUT
)
389 return -1; /* timeout */
391 usleep(100); /* allow system to perform work. Stabilizes system */
396 return ret
; /* some error happened */
402 if(len
==0) return size
;
403 t1
=ticks_to_millisecs(gettime());
412 * blocking call with timeout
413 * will return when ANY data has been read from socket. Number of bytes read is returned.
414 * OR timeout. Timeout will return -1
415 * OR network error. -ve value will be returned
417 static s32
smb_recv(s32 s
,void *mem
,s32 len
)
422 t1
=ticks_to_millisecs(gettime());
425 ret
=net_recv(s
,mem
,len
,0);
426 if(ret
>=0) return ret
;
427 if(ret
!=-EAGAIN
) break;
428 t2
=ticks_to_millisecs(gettime());
429 if( (t2
- t1
) > RECV_TIMEOUT
)
434 usleep(100); /* allow system to perform work. Stabilizes system */
442 * Do very basic checking on the return SMB
443 * Read <readlen> bytes
444 * if <readlen>==0 then read a single SMB packet
445 * discard any NBT_KEEPALIVE_MSG packets along the way.
447 static s32
SMBCheck(u8 command
, s32 readlen
,SMBHANDLE
*handle
)
450 u8
*ptr
= handle
->message
.smb
;
451 NBTSMB
*nbt
= &handle
->message
;
453 u8 tempLength
= (readlen
==0);
455 /* if length is not specified,*/
458 /* read entire header if available. if not, just get whatever available.*/
459 readlen
= SMB_HEADER_SIZE
+4;
462 memset(nbt
,0,sizeof(NBTSMB
));
465 /*keep going till we get all the data we wanted*/
468 ret
=smb_recv(handle
->sck_server
, ptr2
+recvd
, readlen
-recvd
);
474 /* discard any and all keepalive packets */
475 while( (nbt
->msg
==NBT_KEEPALIVE_MSG
) && (recvd
>=KEEPALIVE_SIZE
) )
477 recvd
-=KEEPALIVE_SIZE
;
478 memmove(ptr2
, ptr2
+KEEPALIVE_SIZE
, recvd
);
480 /* obtain required length from NBT header if readlen==0*/
481 if(tempLength
&& recvd
>=KEEPALIVE_SIZE
)
483 /* get the length header */
484 if(nbt
->flags
!=0 || nbt
->length
>SMB_MAX_TRANSMIT_SIZE
)
486 /*length too big to be supported*/
487 return SMB_BAD_DATALEN
;
491 readlen
= nbt
->length
+KEEPALIVE_SIZE
;
497 /*** Do basic SMB Header checks ***/
498 ret
= getUInt(ptr
,SMB_OFFSET_PROTO
);
499 if(ret
!=SMB_PROTO
) return SMB_BAD_PROTOCOL
;
501 ret
= getUChar(ptr
, SMB_OFFSET_CMD
);
502 if(ret
!=command
) return SMB_BAD_COMMAND
;
504 ret
= getUInt(ptr
,SMB_OFFSET_NTSTATUS
);
505 if(ret
) return SMB_ERROR
;
513 * Setup the SMB session, including authentication with the
514 * magic 'NTLM Response'
516 static s32
SMB_SetupAndX(SMBHANDLE
*handle
)
521 u8
*ptr
= handle
->message
.smb
;
522 SMBSESSION
*sess
= &handle
->session
;
523 char pwd
[200], ntRespData
[24];
525 MakeSMBHeader(SMB_SETUP_ANDX
,0x08,0x01,handle
);
526 pos
= SMB_HEADER_SIZE
;
528 setUChar(ptr
,pos
,13);
529 pos
++; /*** Word Count ***/
530 setUChar(ptr
,pos
,0xff);
531 pos
++; /*** Next AndX ***/
532 pos
++; /*** Reserved ***/
533 pos
+= 2; /*** Next AndX Offset ***/
534 setUShort(ptr
,pos
,sess
->MaxBuffer
);
536 setUShort(ptr
,pos
,sess
->MaxMpx
);
538 setUShort(ptr
,pos
,sess
->MaxVCS
);
540 setUInt(ptr
,pos
,sess
->sKey
);
542 setUShort(ptr
,pos
,0); /*** Password length (case-insensitive) ***/
544 setUShort(ptr
,pos
,24); /*** Password length (case-sensitive) ***/
546 pos
+= 4; /*** Reserved ***/
547 pos
+= 4; /*** Capabilities ***/
549 pos
+= 2; /*** Byte count ***/
551 /*** The magic 'NTLM Response' ***/
552 strcpy(pwd
, handle
->pwd
);
553 ntlm_smb_nt_encrypt((const char *) pwd
, (const u8
*) sess
->challenge
, (u8
*) ntRespData
);
555 /*** Build information ***/
556 memcpy(&ptr
[pos
],ntRespData
,24);
560 strcpy(pwd
, handle
->user
);
561 for(i
=0;i
<strlen(pwd
);i
++) pwd
[i
] = toupper(pwd
[i
]);
562 memcpy(&ptr
[pos
],pwd
,strlen(pwd
));
563 pos
+= strlen(pwd
)+1;
565 /*** Primary Domain ***/
566 if(handle
->user
[0]=='\0') sess
->p_domain
[0] = '\0';
567 memcpy(&ptr
[pos
],sess
->p_domain
,strlen((const char*)sess
->p_domain
));
568 pos
+= strlen((const char*)sess
->p_domain
)+1;
571 strcpy(pwd
,"Unix (libOGC)");
572 memcpy(&ptr
[pos
],pwd
,strlen(pwd
));
573 pos
+= strlen(pwd
)+1;
575 /*** Native LAN Manager ***/
576 strcpy(pwd
,"Nintendo Wii");
577 memcpy(&ptr
[pos
],pwd
,strlen(pwd
));
578 pos
+= strlen (pwd
)+1;
580 /*** Update byte count ***/
581 setUShort(ptr
,bcpos
,((pos
-bcpos
)-2));
583 handle
->message
.msg
= NBT_SESSISON_MSG
;
584 handle
->message
.length
= htons (pos
);
587 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
588 if(ret
<=0) return SMB_ERROR
;
590 if((ret
=SMBCheck(SMB_SETUP_ANDX
,0,handle
))==SMB_SUCCESS
) {
591 /*** Collect UID ***/
592 sess
->UID
= getUShort(handle
->message
.smb
,SMB_OFFSET_UID
);
601 * Finally, net_connect to the remote share
603 static s32
SMB_TreeAndX(SMBHANDLE
*handle
)
607 u8
*ptr
= handle
->message
.smb
;
608 SMBSESSION
*sess
= &handle
->session
;
610 MakeSMBHeader(SMB_TREEC_ANDX
,0x08,0x01,handle
);
611 pos
= SMB_HEADER_SIZE
;
614 pos
++; /*** Word Count ***/
615 setUChar(ptr
,pos
,0xff);
616 pos
++; /*** Next AndX ***/
617 pos
++; /*** Reserved ***/
618 pos
+= 2; /*** Next AndX Offset ***/
619 pos
+= 2; /*** Flags ***/
620 setUShort(ptr
,pos
,1);
621 pos
+= 2; /*** Password Length ***/
624 pos
++; /*** NULL Password ***/
626 /*** Build server share path ***/
627 strcpy ((char*)path
, "\\\\");
628 strcat ((char*)path
, handle
->server_name
);
629 strcat ((char*)path
, "\\");
630 strcat ((char*)path
, handle
->share_name
);
631 for(ret
=0;ret
<strlen((const char*)path
);ret
++) path
[ret
] = toupper(path
[ret
]);
633 memcpy(&ptr
[pos
],path
,strlen((const char*)path
));
634 pos
+= strlen((const char*)path
)+1;
637 strcpy((char*)path
,"?????");
638 memcpy(&ptr
[pos
],path
,strlen((const char*)path
));
639 pos
+= strlen((const char*)path
)+1;
641 /*** Update byte count ***/
642 setUShort(ptr
,bcpos
,(pos
-bcpos
)-2);
644 handle
->message
.msg
= NBT_SESSISON_MSG
;
645 handle
->message
.length
= htons (pos
);
648 ret
= smb_send(handle
->sck_server
,(char *)&handle
->message
,pos
);
649 if(ret
<=0) return SMB_ERROR
;
651 if((ret
=SMBCheck(SMB_TREEC_ANDX
,0,handle
))==SMB_SUCCESS
) {
652 /*** Collect Tree ID ***/
653 sess
->TID
= getUShort(handle
->message
.smb
,SMB_OFFSET_TID
);
660 * SMB_NegotiateProtocol
662 * The only protocol we admit to is 'NT LM 0.12'
664 static s32
SMB_NegotiateProtocol(const char *dialects
[],int dialectc
,SMBHANDLE
*handle
)
674 if(!handle
|| !dialects
|| dialectc
<=0)
677 /*** Clear session variables ***/
678 sess
= &handle
->session
;
679 memset(sess
,0,sizeof(SMBSESSION
));
683 MakeSMBHeader(SMB_NEG_PROTOCOL
,0x08,0x01,handle
);
685 pos
= SMB_HEADER_SIZE
+3;
686 ptr
= handle
->message
.smb
;
687 for(i
=0,bcnt
=0;i
<dialectc
;i
++) {
688 len
= strlen(dialects
[i
])+1;
690 memcpy(&ptr
[pos
],dialects
[i
],len
);
694 /*** Update byte count ***/
695 setUShort(ptr
,(SMB_HEADER_SIZE
+1),bcnt
);
697 /*** Set NBT information ***/
698 handle
->message
.msg
= NBT_SESSISON_MSG
;
699 handle
->message
.length
= htons(pos
);
702 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
703 if(ret
<=0) return SMB_ERROR
;
705 /*** Check response ***/
706 if((ret
=SMBCheck(SMB_NEG_PROTOCOL
,0,handle
))==SMB_SUCCESS
) {
707 pos
= SMB_HEADER_SIZE
;
708 ptr
= handle
->message
.smb
;
710 /*** Collect information ***/
711 if(getUChar(ptr
,pos
)!=17) return SMB_PROTO_FAIL
; // UCHAR WordCount; Count of parameter words = 17
714 if(getUShort(ptr
,pos
)) return SMB_PROTO_FAIL
; // USHORT DialectIndex; Index of selected dialect - should always be 0 since we only supplied 1!
717 if(getUChar(ptr
,pos
)!=3) return SMB_NOT_USER
; //UCHAR SecurityMode; Security mode:
720 sess
->MaxMpx
= getUShort(ptr
, pos
); //USHORT MaxMpxCount; Max pending outstanding requests
723 sess
->MaxVCS
= getUShort(ptr
, pos
); //USHORT MaxNumberVcs; Max VCs between client and server
726 serverMaxBuffer
= getUInt(ptr
, pos
); //ULONG MaxBufferSize; Max transmit buffer size
727 if(serverMaxBuffer
>SMB_MAX_TRANSMIT_SIZE
)
728 sess
->MaxBuffer
= SMB_MAX_TRANSMIT_SIZE
;
730 sess
->MaxBuffer
= serverMaxBuffer
;
733 pos
+= 4; //ULONG MaxRawSize; Maximum raw buffer size
734 sess
->sKey
= getUInt(ptr
,pos
); pos
+= 4;
735 pos
+= 4; //ULONG Capabilities; Server capabilities
736 pos
+= 4; //ULONG SystemTimeLow; System (UTC) time of the server (low).
737 pos
+= 4; //ULONG SystemTimeHigh; System (UTC) time of the server (high).
738 sess
->timeOffset
= getShort(ptr
,pos
) * 600000000LL; pos
+= 2; //SHORT ServerTimeZone; Time zone of server (minutes from UTC)
739 if(getUChar(ptr
,pos
)!=8) return SMB_BAD_KEYLEN
; //UCHAR EncryptionKeyLength - 0 or 8
742 bytecount
= getUShort(ptr
,pos
);
744 /*** Copy challenge key ***/
746 memcpy(&sess
->challenge
,&ptr
[pos
],8);
748 /*** Primary domain ***/
751 while(ptr
[pos
+j
]!=0) {
752 sess
->p_domain
[i
] = ptr
[pos
+j
];
756 sess
->p_domain
[i
] = '\0';
764 static s32
do_netconnect(SMBHANDLE
*handle
)
772 /*** Create the global net_socket ***/
773 sock
= net_socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
);
774 if(sock
==INVALID_SOCKET
) return -1;
776 /*** Switch off Nagle, ON TCP_NODELAY ***/
778 ret
= net_setsockopt(sock
,IPPROTO_TCP
,TCP_NODELAY
,&nodelay
,sizeof(nodelay
));
780 //create non blocking socket
781 flags
= net_fcntl(sock
, F_GETFL
, 0);
782 flags
|= IOS_O_NONBLOCK
;
783 ret
=net_fcntl(sock
, F_SETFL
, flags
);
785 t1
=ticks_to_millisecs(gettime());
788 ret
= net_connect(sock
,(struct sockaddr
*)&handle
->server_addr
,sizeof(handle
->server_addr
));
789 t2
=ticks_to_millisecs(gettime());
791 if(t2
-t1
> 3000) break; // 3 secs to try to connect to handle->server_addr
800 handle
->sck_server
= sock
;
804 static s32
do_smbconnect(SMBHANDLE
*handle
)
808 ret
= SMB_NegotiateProtocol(smb_dialects
,smb_dialectcnt
,handle
);
809 if(ret
!=SMB_SUCCESS
) {
810 net_close(handle
->sck_server
);
814 ret
= SMB_SetupAndX(handle
);
815 if(ret
!=SMB_SUCCESS
) {
816 net_close(handle
->sck_server
);
820 ret
= SMB_TreeAndX(handle
);
821 if(ret
!=SMB_SUCCESS
) {
822 net_close(handle
->sck_server
);
826 handle
->conn_valid
= TRUE
;
830 /****************************************************************************
831 * Primary setup, logon and connection all in one :)
832 ****************************************************************************/
833 s32
SMB_Connect(SMBCONN
*smbhndl
, const char *user
, const char *password
, const char *share
, const char *server
)
840 if(!user
|| !password
|| !share
|| !server
||
841 strlen(user
) > 20 || strlen(password
) > 14 ||
842 strlen(share
) > 80 || strlen(server
) > 80)
844 return SMB_BAD_LOGINDATA
;
847 *smbhndl
= SMB_HANDLE_NULL
;
849 if(smb_inited
==FALSE
) {
851 _CPU_ISR_Disable(level
);
853 _CPU_ISR_Restore(level
);
856 handle
= __smb_allocate_handle();
857 if(!handle
) return SMB_ERROR
;
859 handle
->user
= strdup(user
);
860 handle
->pwd
= strdup(password
);
861 handle
->server_name
= strdup(server
);
862 handle
->share_name
= strdup(share
);
863 handle
->server_addr
.sin_family
= AF_INET
;
864 handle
->server_addr
.sin_port
= htons(445);
866 if(strlen(server
) < 16 && inet_aton(server
, &val
))
868 handle
->server_addr
.sin_addr
.s_addr
= val
.s_addr
;
870 else // might be a hostname
872 hp
= net_gethostbyname(server
);
873 if (!hp
|| !(hp
->h_addrtype
== PF_INET
))
874 ret
= SMB_BAD_LOGINDATA
;
876 memcpy((char *)&handle
->server_addr
.sin_addr
.s_addr
, hp
->h_addr_list
[0], hp
->h_length
);
881 ret
= do_netconnect(handle
);
882 if(ret
==0) ret
= do_smbconnect(handle
);
887 handle
->server_addr
.sin_port
= htons(139);
888 ret
= do_netconnect(handle
);
889 if(ret
==0) ret
= do_smbconnect(handle
);
894 __smb_free_handle(handle
);
899 *smbhndl
=(SMBCONN
)(LWP_OBJMASKTYPE(SMB_OBJTYPE_HANDLE
)|LWP_OBJMASKID(handle
->object
.id
));
904 /****************************************************************************
907 * Probably NEVER called on GameCube, but here for completeness
908 ****************************************************************************/
909 void SMB_Close(SMBCONN smbhndl
)
913 handle
= __smb_handle_open(smbhndl
);
916 if(handle
->sck_server
!=INVALID_SOCKET
) net_close(handle
->sck_server
);
917 __smb_free_handle(handle
);
920 s32
SMB_Reconnect(SMBCONN
*_smbhndl
, BOOL test_conn
)
922 s32 ret
= SMB_SUCCESS
;
923 SMBCONN smbhndl
= *_smbhndl
;
924 SMBHANDLE
*handle
= __smb_handle_open(smbhndl
);
926 return SMB_ERROR
; // we have no handle, so we can't reconnect
928 if(handle
->conn_valid
&& test_conn
)
931 if(SMB_PathInfo("\\", &dentry
, smbhndl
)==SMB_SUCCESS
) return SMB_SUCCESS
; // no need to reconnect
932 handle
->conn_valid
= FALSE
; // else connection is invalid
935 if(!handle
->conn_valid
)
937 // save connection details
938 const char * user
= strdup(handle
->user
);
939 const char * pwd
= strdup(handle
->pwd
);
940 const char * ip
= strdup(handle
->server_name
);
941 const char * share
= strdup(handle
->share_name
);
943 // shut down connection, and reopen
945 ret
= SMB_Connect(_smbhndl
, user
, pwd
, share
, ip
);
950 SMBFILE
SMB_OpenFile(const char *filename
, u16 access
, u16 creation
,SMBCONN smbhndl
)
955 struct _smbfile
*fid
= NULL
;
959 if(SMB_Reconnect(&smbhndl
,TRUE
)!=SMB_SUCCESS
) return NULL
;
961 handle
= __smb_handle_open(smbhndl
);
962 if(!handle
) return NULL
;
964 MakeSMBHeader(SMB_OPEN_ANDX
,0x08,0x01,handle
);
966 pos
= SMB_HEADER_SIZE
;
967 ptr
= handle
->message
.smb
;
968 setUChar(ptr
, pos
, 15);
969 pos
++; /*** Word Count ***/
970 setUChar(ptr
, pos
, 0xff);
971 pos
++; /*** Next AndX ***/
972 pos
+= 3; /*** Next AndX Offset ***/
974 pos
+= 2; /*** Flags ***/
975 setUShort(ptr
, pos
, access
);
976 pos
+= 2; /*** Access mode ***/
977 setUShort(ptr
, pos
, 0x6);
978 pos
+= 2; /*** Type of file ***/
979 pos
+= 2; /*** Attributes ***/
980 pos
+= 4; /*** File time - don't care - let server decide ***/
981 setUShort(ptr
, pos
, creation
);
982 pos
+= 2; /*** Creation flags ***/
983 pos
+= 4; /*** Allocation size ***/
984 pos
+= 8; /*** Reserved ***/
985 pos
+= 2; /*** Byte Count ***/
988 if (filename
[0] != '\\') {
989 strcpy(realfile
, "\\");
990 strcat(realfile
,filename
);
992 strcpy(realfile
,filename
);
994 memcpy(&ptr
[pos
],realfile
,strlen(realfile
));
995 pos
+= strlen(realfile
)+1;
997 setUShort(ptr
,(bpos
-2),(pos
-bpos
));
999 handle
->message
.msg
= NBT_SESSISON_MSG
;
1000 handle
->message
.length
= htons(pos
);
1003 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1004 if(ret
<0) goto failed
;
1006 if(SMBCheck(SMB_OPEN_ANDX
,0,handle
)==SMB_SUCCESS
) {
1007 /*** Check file handle ***/
1008 fid
= (struct _smbfile
*)__lwp_queue_get(&smb_filehandle_queue
);
1010 fid
->conn
= smbhndl
;
1011 fid
->sfid
= getUShort(handle
->message
.smb
,(SMB_HEADER_SIZE
+5));
1014 return (SMBFILE
)fid
;
1017 handle
->conn_valid
= FALSE
;
1024 void SMB_CloseFile(SMBFILE sfid
)
1029 struct _smbfile
*fid
= (struct _smbfile
*)sfid
;
1033 handle
= __smb_handle_open(fid
->conn
);
1036 MakeSMBHeader(SMB_CLOSE
,0x08,0x01,handle
);
1038 pos
= SMB_HEADER_SIZE
;
1039 ptr
= handle
->message
.smb
;
1040 setUChar(ptr
, pos
, 3);
1041 pos
++; /** Word Count **/
1042 setUShort(ptr
, pos
, fid
->sfid
);
1044 setUInt(ptr
, pos
, 0xffffffff);
1045 pos
+= 4; /*** Last Write ***/
1046 pos
+= 2; /*** Byte Count ***/
1048 handle
->message
.msg
= NBT_SESSISON_MSG
;
1049 handle
->message
.length
= htons(pos
);
1052 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1053 if(ret
<0) handle
->conn_valid
= FALSE
;
1054 else SMBCheck(SMB_CLOSE
,0,handle
);
1055 __lwp_queue_append(&smb_filehandle_queue
,&fid
->node
);
1061 s32
SMB_ReadFile(char *buffer
, int size
, int offset
, SMBFILE sfid
)
1067 struct _smbfile
*fid
= (struct _smbfile
*)sfid
;
1071 /*** Don't let the size exceed! ***/
1072 if(size
>SMB_MAX_BUFFERSIZE
) return 0;
1074 handle
= __smb_handle_open(fid
->conn
);
1075 if(!handle
) return 0;
1077 MakeSMBHeader(SMB_READ_ANDX
,0x08,0x01,handle
);
1079 pos
= SMB_HEADER_SIZE
;
1080 ptr
= handle
->message
.smb
;
1081 setUChar(ptr
, pos
, 10);
1082 pos
++; /*** Word count ***/
1083 setUChar(ptr
, pos
, 0xff);
1085 pos
+= 3; /*** Reserved, Next AndX Offset ***/
1086 setUShort(ptr
, pos
, fid
->sfid
);
1087 pos
+= 2; /*** FID ***/
1088 setUInt(ptr
, pos
, offset
);
1089 pos
+= 4; /*** Offset ***/
1091 setUShort(ptr
, pos
, size
& 0xffff);
1093 setUShort(ptr
, pos
, size
& 0xffff);
1095 setUInt(ptr
, pos
, 0);
1097 pos
+= 2; /*** Remaining ***/
1098 pos
+= 2; /*** Byte count ***/
1100 handle
->message
.msg
= NBT_SESSISON_MSG
;
1101 handle
->message
.length
= htons(pos
);
1104 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
, pos
);
1105 if(ret
<0) goto failed
;
1107 /*** SMBCheck should now only read up to the end of a standard header ***/
1108 if((ret
=SMBCheck(SMB_READ_ANDX
,(SMB_HEADER_SIZE
+27+4),handle
))==SMB_SUCCESS
) {
1109 ptr
= handle
->message
.smb
;
1110 /*** Retrieve data length for this packet ***/
1111 length
= getUShort(ptr
,(SMB_HEADER_SIZE
+11));
1112 /*** Retrieve offset to data ***/
1113 ofs
= getUShort(ptr
,(SMB_HEADER_SIZE
+13));
1115 /*** Default offset, with no padding is 59, so grab any outstanding padding ***/
1116 while(ofs
>SMB_DEF_READOFFSET
) {
1118 ret
= smb_recv(handle
->sck_server
,pad
,(ofs
-SMB_DEF_READOFFSET
));
1119 if(ret
<0) return ret
;
1123 /*** Finally, go grab the data ***/
1127 while ((ret
=smb_recv(handle
->sck_server
,&dest
[ofs
],length
-ofs
))!=0) {
1128 if(ret
<0) return ret
;
1131 if (ofs
>=length
) break;
1139 handle
->conn_valid
= FALSE
;
1146 s32
SMB_WriteFile(const char *buffer
, int size
, int offset
, SMBFILE sfid
)
1153 struct _smbfile
*fid
= (struct _smbfile
*)sfid
;
1157 handle
= __smb_handle_open(fid
->conn
);
1158 if(!handle
) return SMB_ERROR
;
1160 MakeSMBHeader(SMB_WRITE_ANDX
,0x08,0x01,handle
);
1162 pos
= SMB_HEADER_SIZE
;
1163 ptr
= handle
->message
.smb
;
1164 setUChar(ptr
, pos
, 12);
1165 pos
++; /*** Word Count ***/
1166 setUChar(ptr
, pos
, 0xff);
1167 pos
+= 2; /*** Next AndX ***/
1168 pos
+= 2; /*** Next AndX Offset ***/
1170 setUShort(ptr
, pos
, fid
->sfid
);
1172 setUInt(ptr
, pos
, offset
);
1174 pos
+= 4; /*** Reserved ***/
1175 pos
+= 2; /*** Write Mode ***/
1176 pos
+= 2; /*** Remaining ***/
1178 blocks64
= size
>> 16;
1180 setUShort(ptr
, pos
, blocks64
);
1181 pos
+= 2; /*** Length High ***/
1182 setUShort(ptr
, pos
, size
& 0xffff);
1183 pos
+= 2; /*** Length Low ***/
1184 setUShort(ptr
, pos
, 59);
1185 pos
+= 2; /*** Data Offset ***/
1186 setUShort(ptr
, pos
, size
& 0xffff);
1187 pos
+= 2; /*** Data Byte Count ***/
1189 handle
->message
.msg
= NBT_SESSISON_MSG
;
1190 handle
->message
.length
= htons(pos
+size
);
1194 if((copy_len
+pos
)>SMB_MAX_TRANSMIT_SIZE
) copy_len
= (SMB_MAX_TRANSMIT_SIZE
-pos
);
1196 memcpy(&ptr
[pos
],src
,copy_len
);
1203 /*** Send Header Information ***/
1204 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1205 if(ret
<0) goto failed
;
1208 /*** Send the data ***/
1209 ret
= smb_send(handle
->sck_server
,src
,size
);
1210 if(ret
<0) goto failed
;
1214 if(SMBCheck(SMB_WRITE_ANDX
,0,handle
)==SMB_SUCCESS
) {
1215 ptr
= handle
->message
.smb
;
1216 ret
= getUShort(ptr
,(SMB_HEADER_SIZE
+5));
1222 handle
->conn_valid
= FALSE
;
1229 s32
SMB_PathInfo(const char *filename
, SMBDIRENTRY
*sdir
, SMBCONN smbhndl
)
1238 handle
= __smb_handle_open(smbhndl
);
1239 if (!handle
) return SMB_ERROR
;
1241 MakeSMBHeader(SMB_TRANS2
, 0x08, 0x01, handle
);
1242 MakeTRANS2Header(SMB_QUERY_PATH_INFO
, handle
);
1244 bpos
= pos
= (T2_BYTE_CNT
+ 2);
1245 pos
+= 3; /*** Padding ***/
1246 ptr
= handle
->message
.smb
;
1247 setUShort(ptr
, pos
, SMB_QUERY_FILE_ALL_INFO
);
1250 setUInt(ptr
, pos
, 0);
1251 pos
+= 4; /*** reserved ***/
1253 if (filename
[0] != '\\') {
1254 strcpy(realfile
, "\\");
1255 strcat(realfile
, filename
);
1257 strcpy(realfile
, filename
);
1259 memcpy(&ptr
[pos
], realfile
, strlen(realfile
));
1260 pos
+= strlen(realfile
) + 1; /*** Include padding ***/
1262 /*** Update counts ***/
1263 setUShort(ptr
, T2_PRM_CNT
, (7 + strlen(realfile
)));
1264 setUShort(ptr
, T2_SPRM_CNT
, (7 + strlen(realfile
)));
1265 setUShort(ptr
, T2_SPRM_OFS
, 68);
1266 setUShort(ptr
, T2_SDATA_OFS
, (75 + strlen(realfile
)));
1267 setUShort(ptr
, T2_BYTE_CNT
, (pos
- bpos
));
1269 handle
->message
.msg
= NBT_SESSISON_MSG
;
1270 handle
->message
.length
= htons(pos
);
1273 ret
= smb_send(handle
->sck_server
, (char*) &handle
->message
, pos
);
1274 if(ret
<0) goto failed
;
1277 if (SMBCheck(SMB_TRANS2
, 0, handle
) == SMB_SUCCESS
) {
1279 ptr
= handle
->message
.smb
;
1280 /*** Get parameter offset ***/
1281 pos
= getUShort(ptr
, (SMB_HEADER_SIZE
+ 9));
1282 pos
+= 4; // padding
1283 sdir
->ctime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - creation time
1284 sdir
->atime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - access time
1285 sdir
->mtime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - write time
1286 pos
+= 8; // ULONGLONG - change time
1287 sdir
->attributes
= getUInt(ptr
,pos
); pos
+= 4; // ULONG - file attributes
1288 pos
+= 4; // padding
1289 pos
+= 8; // ULONGLONG - allocated file size
1290 sdir
->size
= getULongLong(ptr
, pos
); pos
+= 8; // ULONGLONG - file size
1291 pos
+= 4; // ULONG NumberOfLinks;
1292 pos
+= 2; // UCHAR DeletePending;
1293 pos
+= 2; // UCHAR Directory;
1294 pos
+= 2; // USHORT Pad2; // for alignment only
1295 pos
+= 4; // ULONG EaSize;
1296 pos
+= 4; // ULONG FileNameLength;
1298 strcpy(sdir
->name
,realfile
);
1305 handle
->conn_valid
= FALSE
;
1312 * Uses TRANS2 to support long filenames
1314 s32
SMB_FindFirst(const char *filename
, unsigned short flags
, SMBDIRENTRY
*sdir
, SMBCONN smbhndl
)
1323 if(SMB_Reconnect(&smbhndl
,TRUE
)!=SMB_SUCCESS
) return SMB_ERROR
;
1325 handle
= __smb_handle_open(smbhndl
);
1326 if(!handle
) return SMB_ERROR
;
1328 sess
= &handle
->session
;
1329 MakeSMBHeader(SMB_TRANS2
,0x08,0x01,handle
);
1330 MakeTRANS2Header(SMB_FIND_FIRST2
,handle
);
1332 bpos
= pos
= (T2_BYTE_CNT
+2);
1333 pos
+= 3; /*** Padding ***/
1334 ptr
= handle
->message
.smb
;
1335 setUShort(ptr
, pos
, flags
);
1336 pos
+= 2; /*** Flags ***/
1337 setUShort(ptr
, pos
, 1);
1338 pos
+= 2; /*** Count ***/
1339 setUShort(ptr
, pos
, 6);
1340 pos
+= 2; /*** Internal Flags ***/
1341 setUShort(ptr
, pos
, 260); // SMB_FIND_FILE_BOTH_DIRECTORY_INFO
1342 pos
+= 2; /*** Level of Interest ***/
1343 pos
+= 4; /*** Storage Type == 0 ***/
1344 memcpy(&ptr
[pos
], filename
, strlen(filename
));
1345 pos
+= strlen(filename
)+1; /*** Include padding ***/
1347 /*** Update counts ***/
1348 setUShort(ptr
, T2_PRM_CNT
, (13+strlen(filename
)));
1349 setUShort(ptr
, T2_SPRM_CNT
, (13+strlen(filename
)));
1350 setUShort(ptr
, T2_SPRM_OFS
, 68);
1351 setUShort(ptr
, T2_SDATA_OFS
,(81+strlen(filename
)));
1352 setUShort(ptr
, T2_BYTE_CNT
,(pos
-bpos
));
1354 handle
->message
.msg
= NBT_SESSISON_MSG
;
1355 handle
->message
.length
= htons(pos
);
1358 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1359 if(ret
<0) goto failed
;
1365 if(SMBCheck(SMB_TRANS2
,0,handle
)==SMB_SUCCESS
) {
1366 ptr
= handle
->message
.smb
;
1367 /*** Get parameter offset ***/
1368 pos
= getUShort(ptr
,(SMB_HEADER_SIZE
+9));
1369 sess
->sid
= getUShort(ptr
, pos
); pos
+= 2;
1370 sess
->count
= getUShort(ptr
, pos
); pos
+= 2;
1371 sess
->eos
= getUShort(ptr
, pos
); pos
+= 2;
1372 pos
+= 2; // USHORT EaErrorOffset;
1373 pos
+= 2; // USHORT LastNameOffset;
1374 pos
+= 2; // padding?
1378 pos
+= 4; // ULONG NextEntryOffset;
1379 pos
+= 4; // ULONG FileIndex;
1380 sdir
->ctime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - creation time
1381 sdir
->atime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - access time
1382 sdir
->mtime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - write time
1383 pos
+= 8; // ULONGLONG - change time low
1384 sdir
->size
= getULongLong(ptr
, pos
); pos
+= 8;
1386 sdir
->attributes
= getUInt(ptr
, pos
); pos
+= 4;
1388 strcpy(sdir
->name
, (const char*)&ptr
[pos
]);
1396 handle
->conn_valid
= FALSE
;
1403 s32
SMB_FindNext(SMBDIRENTRY
*sdir
,SMBCONN smbhndl
)
1412 if(SMB_Reconnect(&smbhndl
,TRUE
)!=SMB_SUCCESS
) return SMB_ERROR
;
1414 handle
= __smb_handle_open(smbhndl
);
1415 if(!handle
) return SMB_ERROR
;
1417 sess
= &handle
->session
;
1418 if(sess
->eos
|| sess
->sid
==0) return SMB_ERROR
;
1420 MakeSMBHeader(SMB_TRANS2
,0x08,0x01,handle
);
1421 MakeTRANS2Header(SMB_FIND_NEXT2
,handle
);
1423 bpos
= pos
= (T2_BYTE_CNT
+2);
1424 pos
+= 3; /*** Padding ***/
1425 ptr
= handle
->message
.smb
;
1426 setUShort(ptr
, pos
, sess
->sid
);
1427 pos
+= 2; /*** Search ID ***/
1428 setUShort(ptr
, pos
, 1);
1429 pos
+= 2; /*** Count ***/
1430 setUShort(ptr
, pos
, 260); // SMB_FIND_FILE_BOTH_DIRECTORY_INFO
1431 pos
+= 2; /*** Level of Interest ***/
1432 pos
+= 4; /*** Storage Type == 0 ***/
1433 setUShort(ptr
, pos
, 12);
1434 pos
+=2; /*** Search flags ***/
1437 /*** Update counts ***/
1438 setUShort(ptr
, T2_PRM_CNT
, 13);
1439 setUShort(ptr
, T2_SPRM_CNT
, 13);
1440 setUShort(ptr
, T2_SPRM_OFS
, 68);
1441 setUShort(ptr
, T2_SDATA_OFS
, 81);
1442 setUShort(ptr
, T2_BYTE_CNT
, (pos
-bpos
));
1444 handle
->message
.msg
= NBT_SESSISON_MSG
;
1445 handle
->message
.length
= htons(pos
);
1448 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1449 if(ret
<0) goto failed
;
1452 if (SMBCheck(SMB_TRANS2
,0,handle
)==SMB_SUCCESS
) {
1453 ptr
= handle
->message
.smb
;
1454 /*** Get parameter offset ***/
1455 pos
= getUShort(ptr
,(SMB_HEADER_SIZE
+9));
1456 sess
->count
= getUShort(ptr
, pos
); pos
+= 2;
1457 sess
->eos
= getUShort(ptr
, pos
); pos
+= 2;
1458 pos
+= 2; // USHORT EaErrorOffset;
1459 pos
+= 2; // USHORT LastNameOffset;
1463 pos
+= 4; // ULONG NextEntryOffset;
1464 pos
+= 4; // ULONG FileIndex;
1465 sdir
->ctime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - creation time
1466 sdir
->atime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - access time
1467 sdir
->mtime
= getULongLong(ptr
, pos
) - handle
->session
.timeOffset
; pos
+= 8; // ULONGLONG - write time
1468 pos
+= 8; // ULONGLONG - change time low
1469 sdir
->size
= getULongLong(ptr
, pos
); pos
+= 8;
1471 sdir
->attributes
= getUInt(ptr
, pos
); pos
+= 4;
1473 strcpy (sdir
->name
, (const char*)&ptr
[pos
]);
1481 handle
->conn_valid
= FALSE
;
1488 s32
SMB_FindClose(SMBCONN smbhndl
)
1496 if(SMB_Reconnect(&smbhndl
,TRUE
)!=SMB_SUCCESS
) return SMB_ERROR
;
1498 handle
= __smb_handle_open(smbhndl
);
1499 if(!handle
) return SMB_ERROR
;
1501 sess
= &handle
->session
;
1502 if(sess
->sid
==0) return SMB_ERROR
;
1504 MakeSMBHeader(SMB_FIND_CLOSE2
,0x08,0x01,handle
);
1506 pos
= SMB_HEADER_SIZE
;
1507 ptr
= handle
->message
.smb
;
1508 setUChar(ptr
, pos
, 1);
1509 pos
++; /*** Word Count ***/
1510 setUShort(ptr
, pos
, sess
->sid
);
1512 pos
+= 2; /*** Byte Count ***/
1514 handle
->message
.msg
= NBT_SESSISON_MSG
;
1515 handle
->message
.length
= htons(pos
);
1518 ret
= smb_send(handle
->sck_server
,(char*)&handle
->message
,pos
);
1519 if(ret
<0) goto failed
;
1521 ret
= SMBCheck(SMB_FIND_CLOSE2
,0,handle
);
1525 handle
->conn_valid
= FALSE
;