2 * Copyright (C) 2002 Mike McCormack
4 * CIFS implementation for WINE
6 * This is a WINE's implementation of the Common Internet File System
8 * for specification see:
10 * http://www.codefx.com/CIFS_Explained.htm
11 * http://www.ubiqx.org/cifs/rfc-draft/rfc1002.html
12 * http://www.ubiqx.org/cifs/rfc-draft/draft-leach-cifs-v1-spec-02.html
13 * http://ubiqx.org/cifs/
14 * http://www.samba.org
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32 #include "wine/port.h"
41 #ifdef HAVE_SYS_ERRNO_H
42 #include <sys/errno.h>
44 #include <sys/types.h>
46 #ifdef HAVE_SYS_MMAN_H
54 #include <sys/socket.h>
55 #include <sys/types.h>
56 #ifdef HAVE_NETINET_IN_SYSTM_H
57 #include <netinet/in_systm.h>
59 #ifdef HAVE_NETINET_IN_H
60 #include <netinet/in.h>
62 #ifdef HAVE_NETINET_IP_H
63 #include <netinet/ip.h>
65 #ifdef HAVE_ARPA_INET_H
66 #include <arpa/inet.h>
77 #include "wine/server.h"
78 #include "wine/debug.h"
80 WINE_DEFAULT_DEBUG_CHANNEL(file
);
82 #define MAX_HOST_NAME 15
83 #define NB_TIMEOUT 10000
85 USHORT SMB_MultiplexId
= 0;
87 static int netbios_name(const char *p
, unsigned char *buffer
)
93 for(i
=0; i
<=MAX_HOST_NAME
; i
++)
98 ch
= *p
++&0xdf; /* add character from hostname */
100 ch
= ' '; /* add padding */
103 ch
= 0; /* add terminator */
104 buffer
[len
++] = ((ch
&0xf0) >> 4) + 'A';
105 buffer
[len
++] = (ch
&0x0f) + 'A';
107 buffer
[len
++] = 0; /* add second terminator */
111 static DWORD
NB_NameReq(LPCSTR host
, unsigned char *buffer
, int len
)
115 NBR_ADDWORD(&buffer
[i
],trn
); i
+=2;
116 NBR_ADDWORD(&buffer
[i
],0x0110); i
+=2;
117 NBR_ADDWORD(&buffer
[i
],0x0001); i
+=2;
118 NBR_ADDWORD(&buffer
[i
],0x0000); i
+=2;
119 NBR_ADDWORD(&buffer
[i
],0x0000); i
+=2;
120 NBR_ADDWORD(&buffer
[i
],0x0000); i
+=2;
122 i
+= netbios_name(host
,&buffer
[i
]);
124 NBR_ADDWORD(&buffer
[i
],0x0020); i
+=2;
125 NBR_ADDWORD(&buffer
[i
],0x0001); i
+=2;
127 ERR("packet is %d bytes in length\n",i
);
132 printf("%02x%c",buffer
[j
],(((j
+1)%16)&&((j
+1)!=j
))?' ':'\n');
138 /* unc = \\hostname\share\file... */
139 static BOOL
UNC_SplitName(LPSTR unc
, LPSTR
*hostname
, LPSTR
*share
, LPSTR
*file
)
145 p
= strchr(unc
,'\\');
148 p
= strchr(p
+1,'\\');
168 static BOOL
NB_Lookup(LPCSTR host
, struct sockaddr_in
*addr
)
172 struct sockaddr_in sin
;
173 unsigned char buffer
[256];
175 fd
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
179 r
= setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &on
, sizeof on
);
183 if(0==inet_aton("255.255.255.255", (struct in_addr
*)&sin
.sin_addr
.s_addr
))
185 FIXME("Error getting bcast address\n");
188 sin
.sin_family
= AF_INET
;
189 sin
.sin_port
= htons(137);
191 len
= NB_NameReq(host
,buffer
,sizeof buffer
);
195 r
= sendto(fd
, buffer
, len
, 0, &sin
, sizeof sin
);
198 FIXME("Error sending packet\n");
206 r
= poll(&fds
,1,NB_TIMEOUT
);
211 TRACE("Got response!\n");
215 #define NB_FIRST 0x40
219 #define NB_SESSION_MSG 0x00
220 #define NB_SESSION_REQ 0x81
222 /* RFC 1002, section 4.3.2 */
223 static BOOL
NB_SessionReq(int fd
, char *called
, char *calling
)
225 unsigned char buffer
[0x100];
229 ERR("called %s, calling %s\n",called
,calling
);
231 buffer
[0] = NB_SESSION_REQ
;
232 buffer
[1] = NB_FIRST
;
234 netbios_name(called
, &buffer
[NB_HDRSIZE
]);
236 netbios_name(calling
, &buffer
[NB_HDRSIZE
+len
]);
239 NBR_ADDWORD(&buffer
[2],len
);
241 /* for(i=0; i<(len+NB_HDRSIZE); i++)
242 DPRINTF("%02X%c",buffer[i],(((i+1)!=(len+4))&&((i+1)%16))?' ':'\n'); */
244 r
= write(fd
,buffer
,len
+4);
247 ERR("Write failed\n");
255 r
= poll(&fds
,1,NB_TIMEOUT
);
258 ERR("Poll failed\n");
262 r
= read(fd
, buffer
, NB_HDRSIZE
);
263 if((r
!=NB_HDRSIZE
) || (buffer
[0]!=0x82))
265 ERR("Received %d bytes\n",r
);
266 ERR("%02x %02x %02x %02x\n", buffer
[0],buffer
[1],buffer
[2],buffer
[3]);
273 static BOOL
NB_SendData(int fd
, unsigned char *data
, int size
)
275 unsigned char buffer
[NB_HDRSIZE
];
278 /* CHECK: is it always OK to do this in two writes? */
279 /* perhaps use scatter gather sendmsg instead? */
281 buffer
[0] = NB_SESSION_MSG
;
282 buffer
[1] = NB_FIRST
;
283 NBR_ADDWORD(&buffer
[2],size
);
285 r
= write(fd
, buffer
, NB_HDRSIZE
);
289 r
= write(fd
, data
, size
);
292 ERR("write failed\n");
299 static BOOL
NB_RecvData(int fd
, unsigned char *data
, int *outlen
)
302 unsigned char buffer
[NB_HDRSIZE
];
304 r
= read(fd
, buffer
, NB_HDRSIZE
);
305 if((r
!=NB_HDRSIZE
) || (buffer
[0]!=NB_SESSION_MSG
))
307 ERR("Received %d bytes\n",r
);
311 len
= NBR_GETWORD(&buffer
[2]);
312 r
= read(fd
, data
, len
);
315 ERR("Received %d bytes\n",r
);
323 static BOOL
NB_Transaction(int fd
, unsigned char *buffer
, int len
, int *outlen
)
328 DPRINTF("Sending request:\n");
330 DPRINTF("%02X%c",buffer
[i
],(((i
+1)!=len
)&&((i
+1)%16))?' ':'\n');
332 if(!NB_SendData(fd
,buffer
,len
))
339 r
= poll(&fds
,1,NB_TIMEOUT
);
342 ERR("Poll failed\n");
346 if(!NB_RecvData(fd
, buffer
, outlen
))
350 DPRINTF("Got response:\n");
352 DPRINTF("%02X%c",buffer
[i
],(((i
+1)!=len
)&&((i
+1)%16))?' ':'\n');
357 #define SMB_ADDHEADER(b,l) { b[(l)++]=0xff; b[(l)++]='S'; b[(l)++]='M'; b[(l)++]='B'; }
358 #define SMB_ADDERRINFO(b,l) { b[(l)++]=0; b[(l)++]=0; b[(l)++]=0; b[(l)++]=0; }
359 #define SMB_ADDPADSIG(b,l) { memset(&b[l],0,12); l+=12; }
361 #define SMB_ERRCLASS 5
362 #define SMB_ERRCODE 7
363 #define SMB_TREEID 24
364 #define SMB_PROCID 26
365 #define SMB_USERID 28
366 #define SMB_PLEXID 30
367 #define SMB_PCOUNT 32
368 #define SMB_HDRSIZE 33
370 static DWORD
SMB_GetError(unsigned char *buffer
)
372 if(buffer
[SMB_ERRCLASS
]==0)
373 return STATUS_SUCCESS
;
374 /* FIXME: return propper error codes */
375 return STATUS_INVALID_PARAMETER
;
378 static int SMB_Header(unsigned char *buffer
, unsigned char command
, USHORT tree_id
, USHORT user_id
)
384 SMB_ADDHEADER(buffer
,len
);
387 buffer
[len
++] = command
;
390 SMB_ADDERRINFO(buffer
,len
)
393 buffer
[len
++] = 0x00; /* flags */
394 SMB_ADDWORD(&buffer
[len
],1); len
+= 2; /* flags2 */
397 SMB_ADDPADSIG(buffer
,len
)
400 SMB_ADDWORD(&buffer
[len
],tree_id
); len
+= 2; /* treeid */
401 id
= GetCurrentThreadId();
402 SMB_ADDWORD(&buffer
[len
],id
); len
+= 2; /* process id */
403 SMB_ADDWORD(&buffer
[len
],user_id
); len
+= 2; /* user id */
404 SMB_ADDWORD(&buffer
[len
],SMB_MultiplexId
); len
+= 2; /* multiplex id */
410 static const char *SMB_ProtocolDialect
= "NT LM 0.12";
411 /* = "Windows for Workgroups 3.1a"; */
413 /* FIXME: support multiple SMB dialects */
414 static BOOL
SMB_NegotiateProtocol(int fd
, USHORT
*dialect
)
416 unsigned char buffer
[0x100];
421 memset(buffer
,0,sizeof buffer
);
423 len
= SMB_Header(buffer
, SMB_COM_NEGOTIATE
, 0, 0);
426 buffer
[len
++] = 0; /* no parameters */
429 buflen
= strlen(SMB_ProtocolDialect
)+2; /* include type and nul byte */
430 SMB_ADDWORD(&buffer
[len
],buflen
); len
+= 2;
433 strcpy(&buffer
[len
+1],SMB_ProtocolDialect
);
436 if(!NB_Transaction(fd
, buffer
, len
, &len
))
442 /* FIXME: check response */
443 if(SMB_GetError(buffer
))
445 ERR("returned error\n");
454 #define SMB_PARAM_COUNT(buffer) ((buffer)[SMB_PCOUNT])
455 #define SMB_PARAM(buffer,n) SMB_GETWORD(&(buffer)[SMB_HDRSIZE+2*(n)])
456 #define SMB_BUFFER_COUNT(buffer) SMB_GETWORD(buffer+SMB_HDRSIZE+2*SMB_PARAM_COUNT(buffer))
457 #define SMB_BUFFER(buffer,n) ((buffer)[SMB_HDRSIZE + 2*SMB_PARAM_COUNT(buffer) + 2 + (n) ])
459 static BOOL
SMB_SessionSetup(int fd
, USHORT
*userid
)
461 unsigned char buffer
[0x100];
465 memset(buffer
,0,sizeof buffer
);
467 len
= SMB_Header(buffer
, SMB_COM_SESSION_SETUP_ANDX
, 0, 0);
469 buffer
[len
++] = 0; /* no parameters? */
471 buffer
[len
++] = 0xff; /* AndXCommand: secondary request */
472 buffer
[len
++] = 0x00; /* AndXReserved */
473 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* AndXOffset */
474 SMB_ADDWORD(&buffer
[len
],0x400); len
+= 2; /* MaxBufferSize */
475 SMB_ADDWORD(&buffer
[len
],1); len
+= 2; /* MaxMpxCount */
476 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* VcNumber */
477 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* SessionKey */
478 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* SessionKey */
479 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* Password length */
480 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* Reserved */
481 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* Reserved */
483 /* FIXME: add name and password here */
484 buffer
[len
++] = 0; /* number of bytes in password */
486 if(!NB_Transaction(fd
, buffer
, len
, &len
))
489 if(SMB_GetError(buffer
))
492 pcount
= SMB_PARAM_COUNT(buffer
);
494 if( (SMB_HDRSIZE
+pcount
*2) > len
)
496 ERR("Bad parameter count %d\n",pcount
);
500 DPRINTF("SMB_COM_SESSION_SETUP response, %d args: ",pcount
);
501 for(i
=0; i
<pcount
; i
++)
502 DPRINTF("%04x ",SMB_PARAM(buffer
,i
));
505 bcount
= SMB_BUFFER_COUNT(buffer
);
506 if( (SMB_HDRSIZE
+pcount
*2+2+bcount
) > len
)
508 ERR("parameter count %x, buffer count %x, len %x\n",pcount
,bcount
,len
);
512 DPRINTF("response buffer %d bytes: ",bcount
);
513 for(i
=0; i
<bcount
; i
++)
515 unsigned char ch
= SMB_BUFFER(buffer
,i
);
516 DPRINTF("%c", isprint(ch
)?ch
:' ');
520 *userid
= SMB_GETWORD(&buffer
[SMB_USERID
]);
525 static BOOL
SMB_TreeConnect(int fd
, USHORT user_id
, LPCSTR share_name
, USHORT
*treeid
)
527 unsigned char buffer
[0x100];
530 ERR("%s\n",share_name
);
532 memset(buffer
,0,sizeof buffer
);
534 len
= SMB_Header(buffer
, SMB_COM_TREE_CONNECT
, 0, user_id
);
536 buffer
[len
++] = 4; /* parameters */
538 buffer
[len
++] = 0xff; /* AndXCommand: secondary request */
539 buffer
[len
++] = 0x00; /* AndXReserved */
540 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* AndXOffset */
541 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* Flags */
542 SMB_ADDWORD(&buffer
[len
],1); len
+= 2; /* Password length */
544 /* SMB command buffer */
545 SMB_ADDWORD(&buffer
[len
],3); len
+= 2; /* command buffer len */
546 buffer
[len
++] = 0; /* null terminated password */
548 slen
= strlen(share_name
);
549 if(slen
<(sizeof buffer
-len
))
550 strcpy(&buffer
[len
], share_name
);
555 /* name of the service */
558 if(!NB_Transaction(fd
, buffer
, len
, &len
))
561 if(SMB_GetError(buffer
))
564 *treeid
= SMB_GETWORD(&buffer
[SMB_TREEID
]);
566 ERR("OK, treeid = %04x\n", *treeid
);
571 static BOOL
SMB_NtCreateOpen(int fd
, USHORT tree_id
, USHORT user_id
, USHORT dialect
,
572 LPCSTR filename
, DWORD access
, DWORD sharing
,
573 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
574 DWORD attributes
, HANDLE
template, USHORT
*file_id
)
576 unsigned char buffer
[0x100];
579 ERR("%s\n",filename
);
581 memset(buffer
,0,sizeof buffer
);
583 len
= SMB_Header(buffer
, SMB_COM_NT_CREATE_ANDX
, tree_id
, user_id
);
586 buffer
[len
++] = 24; /* parameters */
588 buffer
[len
++] = 0xff; /* AndXCommand: secondary request */
589 buffer
[len
++] = 0x00; /* AndXReserved */
590 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* AndXOffset */
592 buffer
[len
++] = 0; /* reserved */
593 slen
= strlen(filename
);
594 SMB_ADDWORD(&buffer
[len
],slen
); len
+= 2; /* name length */
597 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* flags */
598 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* root directory fid */
600 SMB_ADDDWORD(&buffer
[len
],access
); len
+= 4; /* access */
601 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* allocation size */
603 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* root directory fid */
606 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* initial allocation */
607 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4;
610 SMB_ADDDWORD(&buffer
[len
],attributes
); len
+= 4; /* ExtFileAttributes*/
613 SMB_ADDDWORD(&buffer
[len
],sharing
); len
+= 4; /* ShareAccess */
616 ERR("creation = %08lx\n",creation
);
617 SMB_ADDDWORD(&buffer
[len
],creation
); len
+= 4; /* CreateDisposition */
620 SMB_ADDDWORD(&buffer
[len
],creation
); len
+= 4; /* CreateOptions */
623 SMB_ADDDWORD(&buffer
[len
],0); len
+= 4; /* Impersonation */
626 buffer
[len
++] = 0; /* security flags */
629 SMB_ADDWORD(&buffer
[len
],slen
); len
+= 2; /* size of buffer */
631 if(slen
<(sizeof buffer
-len
))
632 strcpy(&buffer
[len
], filename
);
637 /* name of the file */
640 if(!NB_Transaction(fd
, buffer
, len
, &len
))
643 if(SMB_GetError(buffer
))
649 /* *file_id = SMB_GETWORD(&buffer[xxx]); */
656 static USHORT
SMB_GetMode(DWORD access
, DWORD sharing
)
660 switch(access
&(GENERIC_READ
|GENERIC_WRITE
))
668 case (GENERIC_READ
|GENERIC_WRITE
):
669 mode
|= OF_READWRITE
;
673 switch(sharing
&(FILE_SHARE_READ
|FILE_SHARE_WRITE
))
675 case (FILE_SHARE_READ
|FILE_SHARE_WRITE
):
676 mode
|= OF_SHARE_DENY_NONE
;
678 case FILE_SHARE_READ
:
679 mode
|= OF_SHARE_DENY_WRITE
;
681 case FILE_SHARE_WRITE
:
682 mode
|= OF_SHARE_DENY_READ
;
685 mode
|= OF_SHARE_EXCLUSIVE
;
692 /* inverse of FILE_ConvertOFMode */
693 static BOOL
SMB_OpenAndX(int fd
, USHORT tree_id
, USHORT user_id
, USHORT dialect
,
694 LPCSTR filename
, DWORD access
, DWORD sharing
,
695 DWORD creation
, DWORD attributes
, USHORT
*file_id
)
697 unsigned char buffer
[0x100];
701 ERR("%s\n",filename
);
703 mode
= SMB_GetMode(access
,sharing
);
705 memset(buffer
,0,sizeof buffer
);
707 len
= SMB_Header(buffer
, SMB_COM_OPEN_ANDX
, tree_id
, user_id
);
710 buffer
[len
++] = 15; /* parameters */
711 buffer
[len
++] = 0xff; /* AndXCommand: secondary request */
712 buffer
[len
++] = 0x00; /* AndXReserved */
713 SMB_ADDWORD(buffer
+len
,0); len
+=2; /* AndXOffset */
714 SMB_ADDWORD(buffer
+len
,0); len
+=2; /* Flags */
715 SMB_ADDWORD(buffer
+len
,mode
); len
+=2; /* desired access */
716 SMB_ADDWORD(buffer
+len
,0); len
+=2; /* search attributes */
717 SMB_ADDWORD(buffer
+len
,0); len
+=2;
723 static BOOL
SMB_Open(int fd
, USHORT tree_id
, USHORT user_id
, USHORT dialect
,
724 LPCSTR filename
, DWORD access
, DWORD sharing
,
725 DWORD creation
, DWORD attributes
, USHORT
*file_id
)
727 unsigned char buffer
[0x100];
728 int len
= 0,slen
,pcount
,i
;
729 USHORT mode
= SMB_GetMode(access
,sharing
);
731 ERR("%s\n",filename
);
733 memset(buffer
,0,sizeof buffer
);
735 len
= SMB_Header(buffer
, SMB_COM_OPEN
, tree_id
, user_id
);
738 buffer
[len
++] = 2; /* parameters */
739 SMB_ADDWORD(buffer
+len
,mode
); len
+=2;
740 SMB_ADDWORD(buffer
+len
,0); len
+=2; /* search attributes */
742 slen
= strlen(filename
)+2; /* inc. nul and BufferFormat */
743 SMB_ADDWORD(buffer
+len
,slen
); len
+=2;
745 buffer
[len
] = 0x04; /* BufferFormat */
746 strcpy(&buffer
[len
+1],filename
);
749 if(!NB_Transaction(fd
, buffer
, len
, &len
))
752 if(SMB_GetError(buffer
))
755 pcount
= SMB_PARAM_COUNT(buffer
);
757 if( (SMB_HDRSIZE
+pcount
*2) > len
)
759 ERR("Bad parameter count %d\n",pcount
);
763 ERR("response, %d args: ",pcount
);
764 for(i
=0; i
<pcount
; i
++)
765 DPRINTF("%04x ",SMB_PARAM(buffer
,i
));
768 *file_id
= SMB_PARAM(buffer
,0);
770 ERR("file_id = %04x\n",*file_id
);
775 static BOOL
SMB_Read(int fd
, USHORT tree_id
, USHORT user_id
, USHORT dialect
, USHORT file_id
, DWORD offset
, LPVOID out
, USHORT count
, LPUSHORT read
)
777 unsigned char *buffer
;
778 int len
,buf_size
,n
,i
;
780 ERR("user %04x tree %04x file %04x count %04x offset %08lx\n",
781 user_id
, tree_id
, file_id
, count
, offset
);
783 buf_size
= count
+0x100;
784 buffer
= (unsigned char *) HeapAlloc(GetProcessHeap(),0,buf_size
);
786 memset(buffer
,0,buf_size
);
788 len
= SMB_Header(buffer
, SMB_COM_READ
, tree_id
, user_id
);
791 SMB_ADDWORD(&buffer
[len
],file_id
); len
+= 2;
792 SMB_ADDWORD(&buffer
[len
],count
); len
+= 2;
793 SMB_ADDDWORD(&buffer
[len
],offset
); len
+= 4;
794 SMB_ADDWORD(&buffer
[len
],0); len
+= 2; /* how many more bytes will be read */
798 if(!NB_Transaction(fd
, buffer
, len
, &len
))
800 HeapFree(GetProcessHeap(),0,buffer
);
804 if(SMB_GetError(buffer
))
806 HeapFree(GetProcessHeap(),0,buffer
);
810 n
= SMB_PARAM_COUNT(buffer
);
812 if( (SMB_HDRSIZE
+n
*2) > len
)
814 HeapFree(GetProcessHeap(),0,buffer
);
815 ERR("Bad parameter count %d\n",n
);
819 ERR("response, %d args: ",n
);
821 DPRINTF("%04x ",SMB_PARAM(buffer
,i
));
824 n
= SMB_PARAM(buffer
,5) - 3;
828 memcpy( out
, &SMB_BUFFER(buffer
,3), n
);
830 ERR("Read %d bytes\n",n
);
833 HeapFree(GetProcessHeap(),0,buffer
);
838 static int SMB_LoginAndConnect(LPCSTR host
, LPCSTR share
, USHORT
*tree_id
, USHORT
*user_id
, USHORT
*dialect
)
841 struct sockaddr_in sin
;
844 ERR("host %s share %s\n",host
,share
);
846 /* FIXME: use various lookup methods */
848 NB_Lookup(host
,&sin
);
851 if(0==inet_aton("127.0.0.1", (struct in_addr
*)&sin
.sin_addr
.s_addr
))
853 FIXME("Error getting localhost address\n");
854 SetLastError( ERROR_PATH_NOT_FOUND
);
855 return INVALID_HANDLE_VALUE
;
857 sin
.sin_family
= AF_INET
;
858 sin
.sin_port
= htons(139); /* netbios session */
861 fd
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
865 ERR("Connecting...\n");
866 r
= connect(fd
, &sin
, sizeof sin
);
870 if(!NB_SessionReq(fd
, "*SMBSERVER", "WINE"))
873 if(!SMB_NegotiateProtocol(fd
, dialect
))
876 if(!SMB_SessionSetup(fd
, user_id
))
879 name
= HeapAlloc(GetProcessHeap(),0,strlen(host
)+strlen(share
)+5);
882 sprintf(name
,"\\\\%s\\%s",host
,share
);
883 if(!SMB_TreeConnect(fd
,*user_id
,name
,tree_id
))
885 HeapFree(GetProcessHeap(),0,name
);
891 HeapFree(GetProcessHeap(),0,name
);
898 static HANDLE
SMB_RegisterFile( int fd
, USHORT tree_id
, USHORT user_id
, USHORT dialect
, USHORT file_id
)
903 wine_server_send_fd( fd
);
905 SERVER_START_REQ( create_smb
)
907 req
->tree_id
= tree_id
;
908 req
->user_id
= user_id
;
909 req
->file_id
= file_id
;
913 r
= wine_server_call_err( req
);
919 ERR("created wineserver smb object, handle = %04x\n",ret
);
921 SetLastError( ERROR_PATH_NOT_FOUND
);
926 HANDLE WINAPI
SMB_CreateFileA( LPCSTR uncname
, DWORD access
, DWORD sharing
,
927 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
928 DWORD attributes
, HANDLE
template )
931 USHORT tree_id
=0, user_id
=0, dialect
=0, file_id
=0;
932 LPSTR name
,host
,share
,file
;
935 name
= HeapAlloc(GetProcessHeap(),0,lstrlenA(uncname
));
939 lstrcpyA(name
,uncname
);
941 if( !UNC_SplitName(name
, &host
, &share
, &file
) )
943 HeapFree(GetProcessHeap(),0,name
);
947 ERR("server is %s, share is %s, file is %s\n", host
, share
, file
);
948 fd
= SMB_LoginAndConnect(host
, share
, &tree_id
, &user_id
, &dialect
);
951 HeapFree(GetProcessHeap(),0,name
);
956 if(!SMB_NtCreateOpen(fd
, tree_id
, user_id
, dialect
, file
,
957 access
, sharing
, sa
, creation
, attributes
, template, &file_id
))
960 HeapFree(GetProcessHeap(),0,name
);
961 ERR("CreateOpen failed\n");
965 if(!SMB_Open(fd
, tree_id
, user_id
, dialect
, file
,
966 access
, sharing
, creation
, attributes
, &file_id
))
969 HeapFree(GetProcessHeap(),0,name
);
970 ERR("CreateOpen failed\n");
974 HeapFree(GetProcessHeap(),0,name
);
976 handle
= SMB_RegisterFile(fd
, tree_id
, user_id
, dialect
, file_id
);
979 ERR("register failed\n");
986 static BOOL
SMB_GetSmbInfo(HANDLE hFile
, USHORT
*tree_id
, USHORT
*user_id
, USHORT
*dialect
, USHORT
*file_id
, LPDWORD offset
)
990 SERVER_START_REQ( get_smb_info
)
995 r
= wine_server_call_err( req
);
997 *tree_id
= reply
->tree_id
;
999 *user_id
= reply
->user_id
;
1001 *file_id
= reply
->file_id
;
1003 *dialect
= reply
->dialect
;
1005 *offset
= reply
->offset
;
1012 static BOOL
SMB_SetOffset(HANDLE hFile
, DWORD offset
)
1016 ERR("offset = %08lx\n",offset
);
1018 SERVER_START_REQ( get_smb_info
)
1020 req
->handle
= hFile
;
1021 req
->flags
= SMBINFO_SET_OFFSET
;
1022 req
->offset
= offset
;
1024 r
= wine_server_call_err( req
);
1026 *offset = reply->offset; */
1033 WINAPI BOOL
SMB_ReadFile(HANDLE hFile
, LPVOID buffer
, DWORD bytesToRead
, LPDWORD bytesRead
, LPOVERLAPPED lpOverlapped
)
1036 DWORD total
, count
, offset
;
1037 USHORT user_id
, tree_id
, dialect
, file_id
, read
;
1040 ERR("%04x %p %ld %p\n", hFile
, buffer
, bytesToRead
, bytesRead
);
1042 if(!SMB_GetSmbInfo(hFile
, &tree_id
, &user_id
, &dialect
, &file_id
, &offset
))
1045 fd
= FILE_GetUnixHandle(hFile
, GENERIC_READ
);
1052 count
= bytesToRead
- total
;
1058 r
= SMB_Read(fd
, tree_id
, user_id
, dialect
, file_id
, offset
, buffer
, count
, &read
);
1066 if(total
>=bytesToRead
)
1074 if(!SMB_SetOffset(hFile
, offset
))