Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / modules / iopcore / cdvdman / smb.c
blob5578615fd348e852a4d33b4929253555e58b0a20
1 /*
2 Copyright 2009, jimmikaelkael
3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
5 */
7 #include <stdio.h>
8 #include <sysclib.h>
9 #include <ps2ip.h>
10 #include <thbase.h>
11 #include <intrman.h>
12 #include <sifman.h>
14 #include "smsutils.h"
15 #include "smb.h"
17 #ifdef VMC_DRIVER
18 #include <thsemap.h>
20 static int io_sema = -1;
22 #define WAITIOSEMA(x) WaitSema(x)
23 #define SIGNALIOSEMA(x) SignalSema(x)
24 #define SMBWRITE 1
25 #else
26 #define WAITIOSEMA(x)
27 #define SIGNALIOSEMA(x)
28 #define SMBWRITE 0
29 #endif
31 #define DMA_ADDR 0x000cff00
32 #define UNCACHEDSEG(vaddr) (0x20000000 | vaddr)
34 // !!! ps2ip exports functions pointers !!!
35 extern int (*plwip_close)(int s); // #6
36 extern int (*plwip_connect)(int s, struct sockaddr *name, socklen_t namelen); // #7
37 extern int (*plwip_recvfrom)(int s, void *header, int hlen, void *payload, int plen, unsigned int flags, struct sockaddr *from, socklen_t *fromlen); // #10
38 extern int (*plwip_send)(int s, void *dataptr, int size, unsigned int flags); // #11
39 extern int (*plwip_socket)(int domain, int type, int protocol); // #13
40 extern u32 (*pinet_addr)(const char *cp); // #24
42 extern int *p_part_start;
44 #define SMB_MAGIC 0x424d53ff
46 struct SMBHeader_t { //size = 36
47 u32 sessionHeader;
48 u32 Magic;
49 u8 Cmd;
50 short Eclass;
51 short Ecode;
52 u8 Flags;
53 u16 Flags2;
54 u8 Extra[12];
55 u16 TID;
56 u16 PID;
57 u16 UID;
58 u16 MID;
59 } __attribute__((packed));
61 struct NegociateProtocolRequest_t {
62 struct SMBHeader_t smbH; // 0
63 u8 smbWordcount; // 36
64 u16 ByteCount; // 37
65 u8 DialectFormat; // 39
66 char DialectName[0]; // 40
67 } __attribute__((packed));
69 struct NegociateProtocolResponse_t {
70 struct SMBHeader_t smbH; // 0
71 u8 smbWordcount; // 36
72 u16 DialectIndex; // 37
73 u8 SecurityMode; // 39
74 u16 MaxMpxCount; // 40
75 u16 MaxVC; // 42
76 u32 MaxBufferSize; // 44
77 u32 MaxRawBuffer; // 48
78 u32 SessionKey; // 52
79 u32 Capabilities; // 56
80 s64 SystemTime; // 60
81 u16 ServerTimeZone; // 68
82 u8 KeyLength; // 70
83 u16 ByteCount; // 71
84 u8 ByteField[0]; // 73
85 } __attribute__((packed));
87 struct SessionSetupAndXRequest_t {
88 struct SMBHeader_t smbH; // 0
89 u8 smbWordcount; // 36
90 u8 smbAndxCmd; // 37
91 u8 smbAndxReserved; // 38
92 u16 smbAndxOffset; // 39
93 u16 MaxBufferSize; // 41
94 u16 MaxMpxCount; // 43
95 u16 VCNumber; // 45
96 u32 SessionKey; // 47
97 u16 AnsiPasswordLength; // 51
98 u16 UnicodePasswordLength; // 53
99 u32 reserved; // 55
100 u32 Capabilities; // 59
101 u16 ByteCount; // 63
102 u8 ByteField[0]; // 65
103 } __attribute__((packed));
105 struct SessionSetupAndXResponse_t {
106 struct SMBHeader_t smbH; // 0
107 u8 smbWordcount; // 36
108 u8 smbAndxCmd; // 37
109 u8 smbAndxReserved; // 38
110 u16 smbAndxOffset; // 39
111 u16 Action; // 41
112 u16 ByteCount; // 43
113 u8 ByteField[0]; // 45
114 } __attribute__((packed));
116 struct TreeConnectAndXRequest_t {
117 struct SMBHeader_t smbH; // 0
118 u8 smbWordcount; // 36
119 u8 smbAndxCmd; // 37
120 u8 smbAndxReserved; // 38
121 u16 smbAndxOffset; // 39
122 u16 Flags; // 41
123 u16 PasswordLength; // 43
124 u16 ByteCount; // 45
125 u8 ByteField[0]; // 47
126 } __attribute__((packed));
128 struct TreeConnectAndXResponse_t {
129 struct SMBHeader_t smbH; // 0
130 u8 smbWordcount; // 36
131 u8 smbAndxCmd; // 37
132 u8 smbAndxReserved; // 38
133 u16 smbAndxOffset; // 39
134 u16 OptionalSupport; // 41
135 u16 ByteCount; // 43
136 } __attribute__((packed));
138 struct OpenAndXRequest_t {
139 struct SMBHeader_t smbH; // 0
140 u8 smbWordcount; // 36
141 u8 smbAndxCmd; // 37
142 u8 smbAndxReserved; // 38
143 u16 smbAndxOffset; // 39
144 u16 Flags; // 41
145 u16 AccessMask; // 43
146 u16 SearchAttributes; // 45
147 u16 FileAttributes; // 47
148 u8 CreationTime[4]; // 49
149 u16 CreateOptions; // 53
150 u32 AllocationSize; // 55
151 u32 reserved[2]; // 59
152 u16 ByteCount; // 67
153 u8 ByteField[0]; // 69
154 } __attribute__((packed));
156 struct OpenAndXResponse_t {
157 struct SMBHeader_t smbH; // 0
158 u8 smbWordcount; // 36
159 u8 smbAndxCmd; // 37
160 u8 smbAndxReserved; // 38
161 u16 smbAndxOffset; // 39
162 u16 FID; // 41
163 u16 FileAttributes; // 43
164 u8 LastWriteTime[4]; // 45
165 u32 FileSize; // 49
166 u16 GrantedAccess; // 53
167 u16 FileType; // 55
168 u16 IPCState; // 57
169 u16 Action; // 59
170 u32 ServerFID; // 61
171 u16 reserved; // 65
172 u16 ByteCount; // 67
173 } __attribute__((packed));
175 struct ReadAndXRequest_t { // size = 63
176 struct SMBHeader_t smbH; // 0
177 u8 smbWordcount; // 36
178 u8 smbAndxCmd; // 37
179 u8 smbAndxReserved; // 38
180 u16 smbAndxOffset; // 39
181 u16 FID; // 41
182 u32 OffsetLow; // 43
183 u16 MaxCountLow; // 47
184 u16 MinCount; // 49
185 u32 MaxCountHigh; // 51
186 u16 Remaining; // 55
187 u32 OffsetHigh; // 57
188 u16 ByteCount; // 61
189 } __attribute__((packed));
191 struct ReadAndXResponse_t {
192 struct SMBHeader_t smbH; // 0
193 u8 smbWordcount; // 36
194 u8 smbAndxCmd; // 37
195 u8 smbAndxReserved; // 38
196 u16 smbAndxOffset; // 39
197 u16 Remaining; // 41
198 u16 DataCompactionMode; // 43
199 u16 reserved; // 45
200 u16 DataLengthLow; // 47
201 u16 DataOffset; // 49
202 u32 DataLengthHigh; // 51
203 u8 reserved2[6]; // 55
204 u16 ByteCount; // 61
205 } __attribute__((packed));
207 struct WriteAndXRequest_t { // size = 63
208 struct SMBHeader_t smbH; // 0
209 u8 smbWordcount; // 36
210 u8 smbAndxCmd; // 37
211 u8 smbAndxReserved; // 38
212 u16 smbAndxOffset; // 39
213 u16 FID; // 41
214 u32 OffsetLow; // 43
215 u32 Reserved; // 47
216 u16 WriteMode; // 51
217 u16 Remaining; // 53
218 u16 DataLengthHigh; // 55
219 u16 DataLengthLow; // 57
220 u16 DataOffset; // 59
221 u32 OffsetHigh; // 61
222 u16 ByteCount; // 65
223 } __attribute__((packed));
225 typedef struct {
226 u32 MaxBufferSize;
227 u32 MaxMpxCount;
228 u32 SessionKey;
229 u32 StringsCF;
230 u8 PrimaryDomainServerName[32];
231 u8 EncryptionKey[8];
232 int SecurityMode; // 0 = share level, 1 = user level
233 int PasswordType; // 0 = PlainText passwords, 1 = use challenge/response
234 char Username[36];
235 u8 Password[48]; // either PlainText, either hashed
236 int PasswordLen;
237 int HashedFlag;
238 void *IOPaddr;
239 } server_specs_t;
241 static server_specs_t server_specs __attribute__((aligned(64))); // this must still on this alignment, as it's used for DMA
243 #define SERVER_SHARE_SECURITY_LEVEL 0
244 #define SERVER_USER_SECURITY_LEVEL 1
245 #define SERVER_USE_PLAINTEXT_PASSWORD 0
246 #define SERVER_USE_ENCRYPTED_PASSWORD 1
247 #define LM_AUTH 0
248 #define NTLM_AUTH 1
250 struct ReadAndXRequest_t smb_Read_Request = {
251 { 0,
252 SMB_MAGIC,
253 SMB_COM_READ_ANDX,
254 0, 0, 0, 0, "\0", 0, 0, 0, 0
256 12,
257 SMB_COM_NONE,
258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
261 #ifdef VMC_DRIVER
262 struct WriteAndXRequest_t smb_Write_Request = {
263 { 0,
264 SMB_MAGIC,
265 SMB_COM_WRITE_ANDX,
266 0, 0, 0, 0, "\0", 0, 0, 0, 0
268 12,
269 SMB_COM_NONE,
270 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
272 #endif
274 static u16 UID, TID;
275 static int main_socket;
277 static u8 SMB_buf[1024] __attribute__((aligned(64)));
279 extern unsigned int ReadPos;
281 //-------------------------------------------------------------------------
282 int rawTCP_SetSessionHeader(u32 size) // Write Session Service header: careful it's raw TCP transport here and not NBT transport
284 // maximum for raw TCP transport (24 bits) !!!
285 SMB_buf[0] = 0;
286 SMB_buf[1] = (size >> 16) & 0xff;
287 SMB_buf[2] = (size >> 8) & 0xff;
288 SMB_buf[3] = size;
290 return (int)size;
293 //-------------------------------------------------------------------------
294 int rawTCP_GetSessionHeader(void) // Read Session Service header: careful it's raw TCP transport here and not NBT transport
296 register u32 size;
298 // maximum for raw TCP transport (24 bits) !!!
299 size = SMB_buf[3];
300 size |= SMB_buf[2] << 8;
301 size |= SMB_buf[1] << 16;
303 return (int)size;
306 //-------------------------------------------------------------------------
307 int OpenTCPSession(struct in_addr dst_IP, u16 dst_port)
309 register int sock, ret;
310 struct sockaddr_in sock_addr;
312 // Creating socket
313 sock = plwip_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
314 if (sock < 0)
315 return -2;
317 mips_memset(&sock_addr, 0, sizeof(sock_addr));
318 sock_addr.sin_addr = dst_IP;
319 sock_addr.sin_family = AF_INET;
320 sock_addr.sin_port = htons(dst_port);
322 while (1) {
323 ret = plwip_connect(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr));
324 if (ret >= 0)
325 break;
326 DelayThread(500);
329 return sock;
332 //-------------------------------------------------------------------------
333 int GetSMBServerReply(void)
335 register int rcv_size, totalpkt_size, pkt_size;
337 rcv_size = plwip_send(main_socket, SMB_buf, rawTCP_GetSessionHeader() + 4, 0);
338 if (rcv_size <= 0)
339 return -1;
341 receive:
342 rcv_size = plwip_recvfrom(main_socket, NULL, 0, SMB_buf, sizeof(SMB_buf), 0, NULL, NULL);
343 if (rcv_size <= 0)
344 return -2;
346 if (SMB_buf[0] != 0) // dropping NBSS Session Keep alive
347 goto receive;
349 // Handle fragmented packets
350 totalpkt_size = rawTCP_GetSessionHeader() + 4;
352 while (rcv_size < totalpkt_size) {
353 pkt_size = plwip_recvfrom(main_socket, NULL, 0, &SMB_buf[rcv_size], sizeof(SMB_buf) - rcv_size, 0, NULL, NULL);
354 if (pkt_size <= 0)
355 return -2;
356 rcv_size += pkt_size;
359 return rcv_size;
362 //-------------------------------------------------------------------------
363 int smb_NegociateProtocol(char *SMBServerIP, int SMBServerPort, char *Username, char *Password)
365 char *dialect = "NT LM 0.12";
366 struct NegociateProtocolRequest_t *NPR = (struct NegociateProtocolRequest_t *)SMB_buf;
367 register int length;
368 struct in_addr dst_addr;
369 #ifdef VMC_DRIVER
370 iop_sema_t smp;
372 smp.initial = 1;
373 smp.max = 1;
374 smp.option = 0;
375 smp.attr = 1;
376 io_sema = CreateSema(&smp);
377 #endif
378 dst_addr.s_addr = pinet_addr(SMBServerIP);
380 // Opening TCP session
381 main_socket = OpenTCPSession(dst_addr, SMBServerPort);
383 negociate_retry:
385 mips_memset(SMB_buf, 0, sizeof(SMB_buf));
387 NPR->smbH.Magic = SMB_MAGIC;
388 NPR->smbH.Cmd = SMB_COM_NEGOCIATE;
389 NPR->smbH.Flags = SMB_FLAGS_CASELESS_PATHNAMES;
390 NPR->smbH.Flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
391 length = strlen(dialect);
392 NPR->ByteCount = length+2;
393 NPR->DialectFormat = 0x02;
394 strcpy(NPR->DialectName, dialect);
396 rawTCP_SetSessionHeader(37+length);
397 GetSMBServerReply();
399 struct NegociateProtocolResponse_t *NPRsp = (struct NegociateProtocolResponse_t *)SMB_buf;
401 // check sanity of SMB header
402 if (NPRsp->smbH.Magic != SMB_MAGIC)
403 goto negociate_retry;
405 // check there's no error
406 if (NPRsp->smbH.Eclass != STATUS_SUCCESS)
407 goto negociate_retry;
409 if (NPRsp->smbWordcount != 17)
410 goto negociate_retry;
412 if (NPRsp->Capabilities & SERVER_CAP_UNICODE)
413 server_specs.StringsCF = 2;
414 else
415 server_specs.StringsCF = 1;
417 if (NPRsp->SecurityMode & NEGOCIATE_SECURITY_USER_LEVEL)
418 server_specs.SecurityMode = SERVER_USER_SECURITY_LEVEL;
419 else
420 server_specs.SecurityMode = SERVER_SHARE_SECURITY_LEVEL;
422 if (NPRsp->SecurityMode & NEGOCIATE_SECURITY_CHALLENGE_RESPONSE)
423 server_specs.PasswordType = SERVER_USE_ENCRYPTED_PASSWORD;
424 else
425 server_specs.PasswordType = SERVER_USE_PLAINTEXT_PASSWORD;
427 // copy to global struct to keep needed information for further communication
428 server_specs.MaxBufferSize = NPRsp->MaxBufferSize;
429 server_specs.MaxMpxCount = NPRsp->MaxMpxCount;
430 server_specs.SessionKey = NPRsp->SessionKey;
431 mips_memcpy(&server_specs.EncryptionKey[0], &NPRsp->ByteField[0], NPRsp->KeyLength);
432 mips_memcpy(&server_specs.PrimaryDomainServerName[0], &NPRsp->ByteField[NPRsp->KeyLength], 32);
433 mips_memcpy(&server_specs.Username[0], Username, 16);
434 mips_memcpy(&server_specs.Password[0], Password, 16);
435 server_specs.IOPaddr = (void *)&server_specs;
436 server_specs.HashedFlag = (server_specs.PasswordType == SERVER_USE_ENCRYPTED_PASSWORD) ? 0 : -1;
438 // doing DMA to EE with server_specs
439 SifDmaTransfer_t dmat[2];
440 int oldstate, id;
441 int flag = 1;
443 dmat[0].dest = (void *)UNCACHEDSEG((DMA_ADDR + 0x40));
444 dmat[0].size = sizeof(server_specs_t);
445 dmat[0].src = (void *)&server_specs;
446 dmat[0].attr = dmat[1].attr = SIF_DMA_INT_O;
447 dmat[1].dest = (void *)UNCACHEDSEG(DMA_ADDR);
448 dmat[1].size = 4;
449 dmat[1].src = (void *)&flag;
451 id = 0;
452 while (!id) {
453 CpuSuspendIntr(&oldstate);
454 id = sceSifSetDma(&dmat[0], 2);
455 CpuResumeIntr(oldstate);
457 while (sceSifDmaStat(id) >= 0);
459 // wait smbauth code on EE hashed the password
460 while (!(server_specs.HashedFlag == 1))
461 DelayThread(2000);
463 return 1;
466 //-------------------------------------------------------------------------
467 int smb_SessionSetupAndX(void)
469 struct SessionSetupAndXRequest_t *SSR = (struct SessionSetupAndXRequest_t *)SMB_buf;
470 register int i, offset, CF;
471 int AuthType = NTLM_AUTH;
472 int password_len = 0;
474 lbl_session_setup:
475 mips_memset(SMB_buf, 0, sizeof(SMB_buf));
477 CF = server_specs.StringsCF;
479 SSR->smbH.Magic = SMB_MAGIC;
480 SSR->smbH.Cmd = SMB_COM_SESSION_SETUP_ANDX;
481 SSR->smbH.Flags = SMB_FLAGS_CASELESS_PATHNAMES;
482 SSR->smbH.Flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_32BIT_STATUS;
483 if (CF == 2)
484 SSR->smbH.Flags2 |= SMB_FLAGS2_UNICODE_STRING;
485 SSR->smbWordcount = 13;
486 SSR->smbAndxCmd = SMB_COM_NONE; // no ANDX command
487 SSR->MaxBufferSize = server_specs.MaxBufferSize > 65535 ? 65535 : (u16)server_specs.MaxBufferSize;
488 SSR->MaxMpxCount = server_specs.MaxMpxCount >= 2 ? 2 : (u16)server_specs.MaxMpxCount;
489 SSR->VCNumber = 1;
490 SSR->SessionKey = server_specs.SessionKey;
491 SSR->Capabilities = CLIENT_CAP_LARGE_READX | CLIENT_CAP_UNICODE | CLIENT_CAP_LARGE_FILES | CLIENT_CAP_STATUS32;
493 // Fill ByteField
494 offset = 0;
496 if (server_specs.SecurityMode == SERVER_USER_SECURITY_LEVEL) {
497 password_len = server_specs.PasswordLen;
498 // Copy the password accordingly to auth type
499 mips_memcpy(&SSR->ByteField[offset], &server_specs.Password[(AuthType << 4) + (AuthType << 3)], password_len);
500 // fill SSR->AnsiPasswordLength or SSR->UnicodePasswordLength accordingly to auth type
501 if (AuthType == LM_AUTH)
502 SSR->AnsiPasswordLength = password_len;
503 else
504 SSR->UnicodePasswordLength = password_len;
505 offset += password_len;
508 if ((CF == 2) && (!(password_len & 1)))
509 offset += 1; // pad needed only for unicode as aligment fix if password length is even
511 for (i = 0; i < strlen(server_specs.Username); i++) {
512 SSR->ByteField[offset] = server_specs.Username[i]; // add User name
513 offset += CF;
515 offset += CF; // null terminator
517 for (i = 0; server_specs.PrimaryDomainServerName[i] != 0; i+=CF) {
518 SSR->ByteField[offset] = server_specs.PrimaryDomainServerName[i]; // PrimaryDomain, acquired from Negociate Protocol Response Datas
519 offset += CF;
521 offset += CF; // null terminator
523 for (i = 0; i < (CF << 1); i++)
524 SSR->ByteField[offset++] = 0; // NativeOS, NativeLanMan
526 SSR->ByteCount = offset;
528 rawTCP_SetSessionHeader(61+offset);
529 GetSMBServerReply();
531 struct SessionSetupAndXResponse_t *SSRsp = (struct SessionSetupAndXResponse_t *)SMB_buf;
533 // check sanity of SMB header
534 if (SSRsp->smbH.Magic != SMB_MAGIC)
535 return -1;
537 // check there's no auth failure
538 if ((server_specs.SecurityMode == SERVER_USER_SECURITY_LEVEL)
539 && ((SSRsp->smbH.Eclass | (SSRsp->smbH.Ecode << 16)) == STATUS_LOGON_FAILURE)
540 && (AuthType == NTLM_AUTH)) {
541 AuthType = LM_AUTH;
542 goto lbl_session_setup;
545 // check there's no error (NT STATUS error type!)
546 if ((SSRsp->smbH.Eclass | SSRsp->smbH.Ecode) != STATUS_SUCCESS)
547 return -1000;
549 // keep UID
550 UID = SSRsp->smbH.UID;
552 return 1;
555 //-------------------------------------------------------------------------
556 int smb_TreeConnectAndX(char *ShareName)
558 struct TreeConnectAndXRequest_t *TCR = (struct TreeConnectAndXRequest_t *)SMB_buf;
559 register int i, offset, CF;
560 int AuthType = NTLM_AUTH;
561 int password_len = 0;
563 mips_memset(SMB_buf, 0, sizeof(SMB_buf));
565 CF = server_specs.StringsCF;
567 TCR->smbH.Magic = SMB_MAGIC;
568 TCR->smbH.Cmd = SMB_COM_TREE_CONNECT_ANDX;
569 TCR->smbH.Flags = SMB_FLAGS_CASELESS_PATHNAMES;
570 TCR->smbH.Flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES | SMB_FLAGS2_32BIT_STATUS;
571 if (CF == 2)
572 TCR->smbH.Flags2 |= SMB_FLAGS2_UNICODE_STRING;
573 TCR->smbH.UID = UID;
574 TCR->smbWordcount = 4;
575 TCR->smbAndxCmd = SMB_COM_NONE; // no ANDX command
577 // Fill ByteField
578 offset = 0;
580 password_len = 1;
581 if (server_specs.SecurityMode == SERVER_SHARE_SECURITY_LEVEL) {
582 password_len = server_specs.PasswordLen;
583 // Copy the password accordingly to auth type
584 mips_memcpy(&TCR->ByteField[offset], &server_specs.Password[(AuthType << 4) + (AuthType << 3)], password_len);
586 TCR->PasswordLength = password_len;
587 offset += password_len;
589 if ((CF == 2) && (!(password_len & 1)))
590 offset += 1; // pad needed only for unicode as aligment fix is password len is even
592 for (i = 0; i < strlen(ShareName); i++) {
593 TCR->ByteField[offset] = ShareName[i]; // add Share name
594 offset += CF;
596 offset += CF; // null terminator
598 mips_memcpy(&TCR->ByteField[offset], "?????\0", 6); // Service, any type of device
599 offset += 6;
601 TCR->ByteCount = offset;
603 rawTCP_SetSessionHeader(43+offset);
604 GetSMBServerReply();
606 struct TreeConnectAndXResponse_t *TCRsp = (struct TreeConnectAndXResponse_t *)SMB_buf;
608 // check sanity of SMB header
609 if (TCRsp->smbH.Magic != SMB_MAGIC)
610 return -1;
612 // check there's no error (NT STATUS error type!)
613 if ((TCRsp->smbH.Eclass | TCRsp->smbH.Ecode) != STATUS_SUCCESS)
614 return -1000;
616 // keep TID
617 TID = TCRsp->smbH.TID;
619 return 1;
622 //-------------------------------------------------------------------------
623 int smb_OpenAndX(char *filename, u16 *FID, int Write)
625 struct OpenAndXRequest_t *OR = (struct OpenAndXRequest_t *)SMB_buf;
626 register int i, offset, CF;
628 WAITIOSEMA(io_sema);
630 mips_memset(SMB_buf, 0, sizeof(SMB_buf));
632 CF = server_specs.StringsCF;
634 OR->smbH.Magic = SMB_MAGIC;
635 OR->smbH.Cmd = SMB_COM_OPEN_ANDX;
636 OR->smbH.Flags = SMB_FLAGS_CANONICAL_PATHNAMES; //| SMB_FLAGS_CASELESS_PATHNAMES;
637 OR->smbH.Flags2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
638 if (CF == 2)
639 OR->smbH.Flags2 |= SMB_FLAGS2_UNICODE_STRING;
640 OR->smbH.UID = UID;
641 OR->smbH.TID = TID;
642 OR->smbWordcount = 15;
643 OR->smbAndxCmd = SMB_COM_NONE; // no ANDX command
644 OR->AccessMask = (Write && (SMBWRITE)) ? 2 : 0;
645 OR->FileAttributes = (Write && (SMBWRITE)) ? EXT_ATTR_NORMAL : EXT_ATTR_READONLY;
646 OR->CreateOptions = 1;
648 offset = 0;
649 if (CF == 2)
650 offset++; // pad needed only for unicode as aligment fix
652 for (i = 0; i < strlen(filename); i++) {
653 OR->ByteField[offset] = filename[i]; // add filename
654 offset += CF;
656 offset += CF;
658 OR->ByteCount = offset;
660 rawTCP_SetSessionHeader(66+offset);
661 GetSMBServerReply();
663 struct OpenAndXResponse_t *ORsp = (struct OpenAndXResponse_t *)SMB_buf;
665 // check sanity of SMB header
666 if (ORsp->smbH.Magic != SMB_MAGIC)
667 return -1;
669 // check there's no error
670 if (ORsp->smbH.Eclass != STATUS_SUCCESS)
671 return -1000;
673 *FID = ORsp->FID;
675 // Prepare header of Read/Write Request by advance
676 smb_Read_Request.smbH.UID = UID;
677 smb_Read_Request.smbH.TID = TID;
679 #ifdef VMC_DRIVER
680 smb_Write_Request.smbH.UID = UID;
681 smb_Write_Request.smbH.TID = TID;
682 #endif
684 SIGNALIOSEMA(io_sema);
686 return 1;
689 //-------------------------------------------------------------------------
690 int smb_ReadFile(u16 FID, u32 offsetlow, u32 offsethigh, void *readbuf, u16 nbytes)
692 register int rcv_size, pkt_size, expected_size;
694 struct ReadAndXRequest_t *RR = (struct ReadAndXRequest_t *)SMB_buf;
696 WAITIOSEMA(io_sema);
698 mips_memcpy(RR, &smb_Read_Request.smbH.sessionHeader, sizeof(struct ReadAndXRequest_t));
700 RR->smbH.sessionHeader = 0x3b000000;
701 RR->smbH.Flags = 0;
702 RR->FID = FID;
703 RR->OffsetLow = offsetlow;
704 RR->OffsetHigh = offsethigh;
705 RR->MaxCountLow = nbytes;
706 RR->MinCount = 0;
707 RR->ByteCount = 0;
709 plwip_send(main_socket, SMB_buf, 63, 0);
710 receive:
711 rcv_size = plwip_recvfrom(main_socket, SMB_buf, 49, readbuf, nbytes, 0, NULL, NULL);
712 expected_size = rawTCP_GetSessionHeader() + 4;
714 if (SMB_buf[0] != 0) // dropping NBSS Session Keep alive
715 goto receive;
717 // Handle fragmented packets
718 while (rcv_size < expected_size) {
719 pkt_size = plwip_recvfrom(main_socket, NULL, 0, &((u8 *)readbuf)[rcv_size - SMB_buf[49] - 4], expected_size - rcv_size, 0, NULL, NULL); // - rcv_size
720 rcv_size += pkt_size;
723 SIGNALIOSEMA(io_sema);
725 return 1;
728 #ifdef VMC_DRIVER
729 //-------------------------------------------------------------------------
730 int smb_WriteFile(u16 FID, u32 offsetlow, u32 offsethigh, void *writebuf, u16 nbytes)
732 struct WriteAndXRequest_t *WR = (struct WriteAndXRequest_t *)SMB_buf;
734 WAITIOSEMA(io_sema);
736 mips_memcpy(WR, &smb_Write_Request.smbH.sessionHeader, sizeof(struct WriteAndXRequest_t));
738 WR->smbH.Flags = 0;
739 WR->FID = FID;
740 WR->WriteMode = 0x1;
741 WR->OffsetLow = offsetlow;
742 WR->OffsetHigh = offsethigh;
743 WR->Remaining = nbytes;
744 WR->DataLengthLow = nbytes;
745 WR->DataOffset = 0x3b;
746 WR->ByteCount = nbytes;
748 mips_memcpy((void *)(&SMB_buf[4 + WR->DataOffset]), writebuf, nbytes);
750 rawTCP_SetSessionHeader(59+nbytes);
751 GetSMBServerReply();
753 SIGNALIOSEMA(io_sema);
755 return 1;
757 #endif
759 //-------------------------------------------------------------------------
760 int smb_ReadCD(unsigned int lsn, unsigned int nsectors, void *buf, int part_num)
762 register u32 sectors, offset, nbytes;
763 u8 *p = (u8 *)buf;
765 offset = lsn;
767 while (nsectors > 0) {
768 sectors = nsectors;
769 if (sectors > MAX_SMB_SECTORS)
770 sectors = MAX_SMB_SECTORS;
772 nbytes = sectors << 11;
774 smb_ReadFile((u16)p_part_start[part_num], offset << 11, offset >> 21, p, nbytes);
776 p += nbytes;
777 offset += sectors;
778 nsectors -= sectors;
779 ReadPos += sectors;
782 return 1;
785 //-------------------------------------------------------------------------
786 int smb_Disconnect(void)
788 plwip_close(main_socket);
790 return 1;