source: branches/samba-3.0/source/ndpsmb/ndpsmb.c@ 129

Last change on this file since 129 was 127, checked in by Yuri Dario, 17 years ago

Allow different return codes between ioctl and plugin. See ticket:47.

  • Property svn:eol-style set to native
File size: 67.1 KB
Line 
1#define NDPL_LARGEFILES
2#define INCL_LONGLONG
3#include <ndextpl2.h>
4#include <smbwrp.h>
5#include <smbcd.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <stdarg.h>
9#include <time.h>
10
11
12#define NULL ((void *)0)
13
14#ifndef DEBUG_PRINTF
15#define debug_printf( ...)
16#endif
17
18void log(const char *fmt, ...)
19{
20 char *ndpsmb_debug = getenv("NDPSMB_DEBUG");
21
22 if (ndpsmb_debug != NULL)
23 {
24 FILE * logfile = NULL;
25 va_list args;
26 time_t t = time(NULL);
27 char timebuf[80] = {0};
28 strftime(timebuf,sizeof(timebuf)-1,"%Y/%m/%d %H:%M:%S", localtime(&t));
29 logfile = fopen("smblog","a");
30 if (logfile == NULL)
31 {
32 DosBeep(400,400);
33 }
34 else
35 {
36 fprintf(logfile, "%s: (%02d) ", timebuf, _gettid());
37 va_start(args, fmt);
38 vfprintf(logfile, fmt, args);
39 va_end(args);
40 fclose(logfile);
41 }
42 }
43}
44
45// -------------------------------------------------------------
46
47/* time conversion functions: SMB protocol sends timestamps in GMT time,
48* os2 api uses localtime,
49* emx/klibc uses timezone and daylight saving to convert GMT timestamps,
50* so only the timezone must be counted in conversion.
51*/
52void fsphUnixTimeToDosDate( time_t time, FDATE* fdate, FTIME *ftime)
53{
54 struct tm* gmt = localtime( &time);
55 if (gmt->tm_isdst>0) {
56 debug_printf( "daylight saving in effect %d, timezone %d\n",gmt->tm_isdst, timezone);
57 time -= 3600;
58 gmt = localtime( &time);
59 }
60 fdate->day = gmt->tm_mday;
61 fdate->month = gmt->tm_mon+1;
62 fdate->year = gmt->tm_year + 1900 - 1980;
63 ftime->twosecs = gmt->tm_sec/2;
64 ftime->minutes = gmt->tm_min;
65 ftime->hours = gmt->tm_hour;
66}
67
68void fsphDosDateToUnixTime( FDATE fdate, FTIME ftime, unsigned long* time)
69{
70 struct tm gmtime = { 0 };
71 struct tm* gmt;
72
73 debug_printf( "fsphDosDateToUnixTime time %02d:%02d\n", ftime.hours, ftime.minutes);
74 gmtime.tm_mday = fdate.day;
75 gmtime.tm_mon = fdate.month-1;
76 gmtime.tm_year = fdate.year + 1980 - 1900;
77 gmtime.tm_sec = ftime.twosecs*2;
78 gmtime.tm_min = ftime.minutes;
79 gmtime.tm_hour = ftime.hours;
80 gmtime.tm_isdst = -1; // force libc to check dst saving
81
82 *time = mktime( &gmtime);
83 debug_printf( "fsphDosDateToUnixTime time1 %d %s", *time, ctime( time));
84 gmt = localtime( (time_t*) time);
85 if (gmt->tm_isdst>0) {
86 debug_printf( "fsphDosDateToUnixTime daylight saving in effect %d, timezone %d\n",gmt->tm_isdst, timezone);
87 *time += 3600;
88 }
89 debug_printf( "fsphDosDateToUnixTime time2 %d %s", *time, ctime( time));
90}
91
92// -------------------------------------------------------------
93
94int StrLen(char * s)
95{
96 char * p;
97 if (!s)
98 {
99 return 0;
100 }
101 for (p = s; *p; p++);
102 return (p - s);
103}
104
105char * StrNCat(char *dst, const char *src, int count)
106{
107 int i;
108 if (!dst || !src || count <= 0)
109 {
110 return dst;
111 }
112 for (i = 0; dst[i]; i++);
113 for (;i < count && *src; i++, src++)
114 {
115 dst[i] = *src;
116 }
117 dst[i] = 0;
118 return dst;
119}
120
121char * StrNCpy(char *dst, const char *src, int count)
122{
123 if (!dst || !src || count <= 0)
124 {
125 return dst;
126 }
127 *dst = 0;
128 return StrNCat(dst, src, count);
129}
130
131char * StrCpy(char *dst, const char *src)
132{
133 char * p;
134 if (!dst || !src)
135 {
136 return dst;
137 }
138 p = dst;
139 while (*p++ = *src++);
140 return dst;
141}
142
143char * StrCat(char *dst, const char *src)
144{
145 int i;
146 if (!dst || !src)
147 {
148 return dst;
149 }
150 for (i = 0; dst[i]; i++);
151 for (; *src; i++, src++)
152 {
153 dst[i] = *src;
154 }
155 dst[i] = 0;
156 return dst;
157}
158
159void * MemCpy(void * dst, const void * src, int len)
160{
161 int i;
162 if (!src || !dst || len <= 0)
163 {
164 return dst;
165 }
166 for (i = 0; i < len; i++)
167 {
168 ((char *)dst)[i] = ((char *)src)[i];
169 }
170 return dst;
171}
172
173void *MemSet(void *dst, char c, int len)
174{
175 int i;
176 if (!dst || len <= 0)
177 {
178 return dst;
179 }
180 for (i = 0; i < len; i++)
181 {
182 ((char *)dst)[i] = c;
183 }
184 return dst;
185}
186
187/* uppercased type of resource */
188const char *NdpTypes[] =
189{
190 "SMBFS",
191 NULL
192}
193;
194
195/* Properties of supported resource types */
196
197/* Properties of resource */
198static const NDPROPERTYINFO smbProperties[] =
199{
200 {ND_PROP_STRING, 0, "WORKGROUP", ""},
201 {ND_PROP_STRING, 0, "SERVER", ""},
202 {ND_PROP_STRING, 0, "SHARE", ""},
203 {ND_PROP_STRING, 0, "USER", "guest"},
204 {ND_PROP_STRING, 0, "PASSWORD", ""},
205 {ND_PROP_STRING, 0, "SPASSWORD", ""},
206 {ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
207 { ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
208 { ND_PROP_ULONG, 0, "MEMLEN", "2"},
209 {ND_PROP_STRING, 0, "LOGFILE", ""},
210 { ND_PROP_ULONG, 0, "LOGLEVEL", "0"},
211 { ND_PROP_ULONG, 0, "EASUPPORT", "1"},
212 {ND_PROP_STRING, 0, NULL, NULL}
213};
214
215
216/* Exported array of properties */
217const NDPROPERTYINFO *NdpPropertiesInfo[] =
218{
219 smbProperties
220};
221
222
223static PLUGINHELPERTABLE2L *ph;
224static int ifL;
225
226int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
227{
228 int rc;
229 HPIPE pipe;
230 unsigned long action;
231 ph = pPHT;
232 ifL = 0;
233/*
234 if (ph->cb < sizeof (PLUGINHELPERTABLE2))
235 {
236 return ERROR_INVALID_FUNCTION;
237 }
238*/
239 if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
240 {
241 ifL = 1;
242 }
243 log("Working with %s bit fileio NDFS\n", ifL ? "64" : "32");
244 return NO_ERROR;
245}
246
247
248int APIENTRY NdpPluginFree (void)
249{
250 return NO_ERROR;
251}
252
253typedef struct _Resource
254{
255 /* NetDrive information */
256 NDPROPERTYHANDLE properties; /* access handle for the properties */
257 int rootlevel;
258 unsigned long memlen;
259 unsigned long objany;
260 smbwrp_server srv;
261 char logfile[CCHMAXPATH + 1];
262 char loglevel;
263 int easupport;
264} Resource;
265
266typedef struct _Connection
267{
268 Resource *pRes;
269 HPIPE pipe;
270 char * mem;
271 int clientpid;
272 int rc;
273 smbwrp_server srv;
274 smbwrp_file file;
275} Connection;
276
277int openpipe(Resource * pRes, HPIPE * ppipe)
278{
279 HPIPE pipe = 0;
280 unsigned long rc = 0, action;
281
282 if (!pRes)
283 {
284 return ERROR_INVALID_PARAMETER;
285 }
286
287 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
288 log("DosOpen1 rc %d\n", rc);
289 if (rc)
290 {
291 unsigned long sid = 0, pid = 0;
292 STARTDATA sd;
293 char params[CCHMAXPATH * 2] = {0};
294
295 MemSet(&sd, 0, sizeof(sd));
296 sd.Length = sizeof(sd);
297 sd.Related = SSF_RELATED_INDEPENDENT;
298 sd.FgBg = SSF_FGBG_BACK;
299 sd.PgmName = EXECNAME;
300 if (pRes->loglevel)
301 {
302 char level[2];
303 level[0] = pRes->loglevel + '0';
304 level[1] = 0;
305 StrNCat(params, " -d ", sizeof(params) - 1);
306 StrNCat(params, level, sizeof(params) - 1);
307 }
308 if (*pRes->logfile)
309 {
310 StrNCat(params, " -l ", sizeof(params) - 1);
311 StrNCat(params, pRes->logfile, sizeof(params) - 1);
312 }
313 log("params <%s>\n", params);
314 sd.PgmInputs = *params ? params : NULL;
315 sd.SessionType = SSF_TYPE_WINDOWABLEVIO;
316 rc = DosStartSession(&sd, &sid, &pid);
317 log("smbcd startsession pid %d sid %d rc %d\n", pid, sid, rc);
318 if (rc == ERROR_SMG_INVALID_CALL)
319 {
320 // ndfs started ndctl detached, so we have to use dosexecpgm
321 char failed[CCHMAXPATH + 1] = {0};
322 RESULTCODES res = {0};
323 char * p = params;
324 StrCpy(p, EXECNAME);
325 p += StrLen(p) + 1;
326 if (*pRes->logfile)
327 {
328 StrCpy(p, "-l ");
329 StrNCat(p, pRes->logfile, sizeof(params) - (p - (char *)params));
330 p += StrLen(p) + 1;
331 if (pRes->loglevel)
332 {
333 char level[2];
334 level[0] = pRes->loglevel + '0';
335 level[1] = 0;
336 StrCpy(p, "-d ");
337 StrNCat(p, level, sizeof(params) - (p - (char *)params));
338 p += StrLen(p) + 1;
339 }
340 }
341 else
342 {
343 StrCpy(p, "-q");
344 p += StrLen(p) + 1;
345 }
346 *p = 0;
347 rc = DosExecPgm(failed, sizeof(failed), EXEC_BACKGROUND, params, NULL, &res, EXECNAME);
348 log("smbcd DosExecPgm codeTerminate %d codeResult %d rc %d\n", res.codeTerminate, res.codeResult, rc);
349 }
350 if (!rc)
351 {
352 DosSleep(500);
353 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
354 log("DosOpen2 rc %d\n", rc);
355 }
356 }
357 if (!rc)
358 {
359 if (ppipe)
360 {
361 *ppipe = pipe;
362 }
363 else
364 {
365 DosClose(pipe);
366 }
367 }
368 return rc;
369}
370
371
372void getfindinfo(Connection * pConn, FILEFINDBUF3 * stat, smbwrp_fileinfo * finfo)
373{
374 char * name = ph->fsphStrRChr(finfo->fname, '\\');
375 if (name)
376 {
377 name++;
378 }
379 else
380 {
381 name = finfo->fname;
382 }
383 if (!*name)
384 {
385 name = pConn->srv.share_name;
386 }
387 StrNCpy(stat->achName, name, CCHMAXPATHCOMP - 1);
388 stat->cbFile = finfo->size;
389 stat->cbFileAlloc = stat->cbFile;
390 stat->oNextEntryOffset = 0ul;
391 stat->cchName = StrLen(stat->achName);
392 stat->attrFile = (finfo->attr & 0x37);
393
394 fsphUnixTimeToDosDate(finfo->mtime, &stat->fdateLastWrite, &stat->ftimeLastWrite);
395 fsphUnixTimeToDosDate(finfo->ctime, &stat->fdateCreation, &stat->ftimeCreation);
396 fsphUnixTimeToDosDate(finfo->atime, &stat->fdateLastAccess, &stat->ftimeLastAccess);
397}
398
399int getfindinfoL(Connection * pConn, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
400{
401 FILESTATUS3L stat = {0};
402 char * name = ph->fsphStrRChr(finfo->fname, '\\');
403 if (name)
404 {
405 name++;
406 }
407 else
408 {
409 name = finfo->fname;
410 }
411 if (!*name)
412 {
413 name = pConn->srv.share_name;
414 }
415 if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
416 {
417 return 0;
418 }
419
420 stat.cbFile = finfo->size;
421 stat.cbFileAlloc = stat.cbFile;
422 stat.attrFile = (finfo->attr & 0x37);
423
424 fsphUnixTimeToDosDate(finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
425 fsphUnixTimeToDosDate(finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
426 fsphUnixTimeToDosDate(finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
427 debug_printf( "fname %s\n", finfo->fname);
428 debug_printf( "mtime %d %s", finfo->mtime, ctime( &finfo->mtime));
429 debug_printf( "ftimeLastAccess %02d:%02d:%02d\n", stat.ftimeLastWrite.hours, stat.ftimeLastWrite.minutes, stat.ftimeLastWrite.twosecs*2);
430
431 ph->fsphAddFile32L(plist, &stat, name, StrLen(name), finfo, sizeof(*finfo), 0);
432 return 1;
433}
434
435static unsigned char fromhex (char c)
436{
437 if ('0' <= c && c <= '9')
438 {
439 return c - '0';
440 }
441
442 if ('A' <= c && c <= 'F')
443 {
444 return c - 'A' + 0xA;
445 }
446
447 if ('a' <= c && c <= 'f')
448 {
449 return c - 'a' + 0xA;
450 }
451
452 return 0;
453}
454
455static char tohex (unsigned char b)
456{
457 b &= 0xF;
458
459 if (b <= 9)
460 {
461 return b + '0';
462 }
463
464 return 'A' + (b - 0xA);
465}
466
467static void decryptPassword (const char *pszCrypt, char *pszPlain)
468{
469 /* A simple "decryption", character from the hex value. */
470 const char *s = pszCrypt;
471 char *d = pszPlain;
472
473 while (*s)
474 {
475 *d++ = (char)((fromhex (*s++) << 4) + fromhex (*s++));
476 }
477
478 *d++ = 0;
479}
480
481static void encryptPassword (const char *pszPlain, char *pszCrypt)
482{
483 /* A simple "encryption" encode each character as hex value. */
484 const char *s = pszPlain;
485 char *d = pszCrypt;
486
487 while (*s)
488 {
489 *d++ = tohex ((*s) >> 4);
490 *d++ = tohex (*s);
491 s++;
492 }
493
494 *d++ = 0;
495}
496
497/* accept parameters in form
498 * [filename][;name=filename]
499 */
500int initResource (Resource *pRes)
501{
502 int rc = NO_ERROR;
503 unsigned long t;
504 const unsigned char * q = NULL;
505 HPIPE pipe;
506 int defaultPassword = 1;
507
508 pRes->memlen = 1 << 18;
509 pRes->rootlevel = 0;
510 *pRes->logfile = 0;
511 pRes->loglevel = 0;
512 pRes->easupport = 1;
513
514 t = 0, q = NULL;
515 rc = ph->fsphQueryStringProperty (pRes->properties, "WORKGROUP", &q, &t);
516 if (!rc && t && *q)
517 {
518 StrNCpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
519 pRes->rootlevel = 1;
520 }
521
522 t = 0, q = NULL;
523 rc = ph->fsphQueryStringProperty (pRes->properties, "SERVER", &q, &t);
524 if (!rc && t && *q)
525 {
526 StrNCpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
527 pRes->rootlevel = 2;
528 }
529
530 t = 0, q = NULL;
531 rc = ph->fsphQueryStringProperty (pRes->properties, "SHARE", &q, &t);
532 if (!rc && t && *q)
533 {
534 StrNCpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
535 pRes->rootlevel = 3;
536 }
537
538 t = 0, q = NULL;
539 rc = ph->fsphQueryStringProperty (pRes->properties, "USER", &q, &t);
540 if (!rc && t && *q)
541 {
542 StrNCpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
543 }
544
545 t = 0, q = NULL;
546 rc = ph->fsphQueryStringProperty (pRes->properties, "PASSWORD", &q, &t);
547 if (!rc && t && *q)
548 {
549 StrNCpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
550 defaultPassword = 0;
551 }
552
553 t = 0, q = NULL;
554 rc = ph->fsphQueryStringProperty (pRes->properties, "SPASSWORD", &q, &t);
555 if ( rc == NO_ERROR
556 && *q != '\0'
557 && defaultPassword)
558 {
559 char p[1024];
560 p[0] = 0;
561
562 decryptPassword (q, p);
563
564 if (*p)
565 {
566 StrNCpy(pRes->srv.password, p, sizeof(pRes->srv.password) - 1);
567
568 /* clear the plain password */
569 ph->fsphSetProperty (pRes->properties, "PASSWORD", "");
570 }
571 }
572 else
573 {
574 char c[1024];
575 encryptPassword (pRes->srv.password, c);
576
577 ph->fsphSetProperty (pRes->properties, "SPASSWORD", c);
578
579 // clear the plain password
580 ph->fsphSetProperty (pRes->properties, "PASSWORD", "");
581 }
582
583 t = 0, q = NULL;
584 rc = ph->fsphQueryStringProperty (pRes->properties, "MASTER", &q, &t);
585 if (!rc && t && *q)
586 {
587 StrNCpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
588 }
589
590 t = 0, q = NULL;
591 rc = ph->fsphQueryStringProperty (pRes->properties, "LOGFILE", &q, &t);
592 if (!rc && t && *q)
593 {
594 StrNCpy(pRes->logfile, q, sizeof(pRes->logfile) - 1);
595 }
596
597 t = 0;
598 rc = ph->fsphQueryUlongProperty (pRes->properties, "LOGLEVEL", &t);
599 if (!rc)
600 {
601 if (t > 9)
602 {
603 t = 9;
604 rc = ERROR_INVALID_PARAMETER;
605 }
606 pRes->loglevel = t;
607 }
608
609 t = 0;
610 rc = ph->fsphQueryUlongProperty (pRes->properties, "MASTERTYPE", &t);
611 if (!rc)
612 {
613 if (t > 1)
614 {
615 rc = ERROR_INVALID_PARAMETER;
616 }
617 else
618 {
619 pRes->srv.ifmastergroup = t;
620 }
621 }
622
623 t = 0;
624 rc = ph->fsphQueryUlongProperty (pRes->properties, "EASUPPORT", &t);
625 if (!rc)
626 {
627 if (t > 1)
628 {
629 rc = ERROR_INVALID_PARAMETER;
630 }
631 else
632 {
633 pRes->easupport = t;
634 }
635 }
636
637 t = 0;
638 rc = ph->fsphQueryUlongProperty (pRes->properties, "MEMLEN", &t);
639 if (!rc)
640 {
641 if (t <= (pRes->easupport ? 1 : 0) || t > 10)
642 {
643 rc = ERROR_INVALID_PARAMETER;
644 }
645 else
646 {
647 pRes->memlen = t * 65536;
648 }
649 }
650
651 return rc;
652}
653
654int checkconnection(Connection * pConn)
655{
656 int rc = NO_ERROR;
657 unsigned long action;
658 smb_request req = {0};
659 smb_response resp = {0};
660 char* mem;
661
662 if (!pConn)
663 {
664 return ERROR_INVALID_PARAMETER;
665 }
666 log("checkconnection pconnrc %d pipe %d\n", pConn->rc, pConn->pipe);
667 // YD this code need probably to be removed (reworked), since DosQueryNPHState,
668 // DosQueryNPipeInfo, DosPeekNPipe, DosResetBuffer, are all returning
669 // NO_ERROR even if the other pipe end is closed (smbcd crash).
670 //
671 // YD TODO probably checkconnection() call can be removed since we
672 // detect broken pipes inside _DosTransactNPipe
673 if (!pConn->rc)
674 {
675 unsigned long state = 0;
676 rc = DosQueryNPHState(pConn->pipe, &state);
677 log("DosQueryNPHstate(pConn->pipe) = %d (%08x)\n", pConn->rc, pConn->pipe, rc, state);
678 if (!rc)
679 {
680 return pConn->rc;
681 }
682 }
683 // there were error on pipe, reopen it and restore connection
684 if (pConn->pipe)
685 {
686 DosClose(pConn->pipe);
687 pConn->pipe = 0;
688 }
689 rc = openpipe(pConn->pRes, &pConn->pipe);
690 if (rc)
691 {
692 log("checkconnection openpipe %d\n", rc);
693 pConn->pipe = 0;
694 DosSleep(1000);
695 return ERROR_PIPE_NOT_CONNECTED;
696 }
697
698 // if we are reconnecting pipe because of a broken pipe, we
699 // need to save shared memory content to allow operation retry
700 mem = malloc( pConn->pRes->memlen);
701 if (mem)
702 memcpy( mem, pConn->mem, pConn->pRes->memlen);
703
704 // reinit connection
705 do {
706 req.request = SMBREQ_INIT;
707 req.param = (char *)0xFFFFFFFF;
708 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
709 if (pConn->rc || action < sizeof(resp) || resp.rc)
710 {
711 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
712 break;
713 }
714 pConn->clientpid = resp.value & 0xFFFF;
715 // client daemon pid changed
716 pConn->rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
717 if (pConn->rc)
718 {
719 rc = pConn->rc;
720 break;
721 }
722 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
723
724 req.request = SMBREQ_CONNECT;
725 req.param = pConn->mem;
726 req.paramlen = sizeof(pConn->srv);
727 req.length = req.paramlen;
728
729 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
730 if (pConn->rc || action < sizeof(resp) || resp.rc)
731 {
732 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
733 break;
734 }
735 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
736
737 rc = NO_ERROR;
738 } while (0);
739
740 // if we are reconnecting pipe because of a broken pipe, we
741 // need to restore shared memory content to allow operation retry
742 if (mem) {
743 memcpy( pConn->mem, mem, pConn->pRes->memlen);
744 free( mem);
745 }
746
747 if (pConn->rc && pConn->pipe)
748 {
749 DosClose(pConn->pipe);
750 pConn->pipe = 0;
751 }
752 return rc;
753}
754
755/*
756 * YD Since DosQueryNPHState,
757 * DosQueryNPipeInfo, DosPeekNPipe, DosResetBuffer, are all returning
758 * NO_ERROR even if the other pipe end is closed (smbcd crash),
759 * we can detect broken pipes only when writing/reading from the pipe.
760*/
761ULONG APIENTRY _DosTransactNPipe(Connection *pConn, PVOID pOutbuf, ULONG ulOutbufLength,
762 PVOID pInbuf, ULONG ulInbufLength, PULONG pulBytesRead)
763{
764 APIRET rc;
765
766 // try first
767 rc = DosTransactNPipe(pConn->pipe, pOutbuf, ulOutbufLength, pInbuf, ulInbufLength, pulBytesRead);
768 if (rc != ERROR_BROKEN_PIPE)
769 return rc;
770 // client daemon closed, force open connection again
771 pConn->rc = rc;
772 checkconnection( pConn);
773 // issue command again
774 rc = DosTransactNPipe(pConn->pipe, pOutbuf, ulOutbufLength, pInbuf, ulInbufLength, pulBytesRead);
775 return rc;
776}
777
778int iftestpath(char * path)
779{
780 char * p = path;
781 if (!path)
782 {
783 return 0;
784 }
785 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
786 {
787 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
788 {
789 return 1;
790 }
791 p++;
792 }
793 return 0;
794}
795
796int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
797{
798 int rootlevel;
799 int rc = NO_ERROR;
800 if (!pRes || !path || !result)
801 {
802 return ERROR_INVALID_PARAMETER;
803 }
804 // handle special case when someone wants to test support of LFN or smth similar
805 if (iftestpath(path))
806 {
807 StrCpy(result, "\\A.+,;=[].B");
808 return NO_ERROR;
809 }
810 rootlevel = pRes->rootlevel;
811 if (*path == '\\') path++;
812 if (rootlevel < 3)
813 {
814 char * p;
815 int newlevel = 0;
816 smbwrp_server * tmp = (smbwrp_server *)pConn->mem;
817 MemCpy(tmp, &pConn->srv, sizeof(pConn->srv));
818 if (rootlevel == 0)
819 {
820 p = ph->fsphStrChr(path, '\\');
821 if (!p)
822 {
823 p = path + StrLen(path);
824 }
825 if (StrLen(tmp->workgroup) != p - path
826 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
827 {
828 StrNCpy(tmp->workgroup, path, p - path);
829 tmp->workgroup[p - path] = 0;
830 newlevel = 1;
831 }
832 path = *p == '\\' ? p + 1 : p;
833 rootlevel = 1;
834 }
835 if (rootlevel == 1) // root path starts from server name
836 {
837 p = ph->fsphStrChr(path, '\\');
838 if (!p)
839 {
840 p = path + StrLen(path);
841 }
842 if (StrLen(tmp->server_name) != p - path
843 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
844 {
845 StrNCpy(tmp->server_name, path, p - path);
846 tmp->server_name[p - path] = 0;
847 newlevel = 1;
848 }
849 path = *p == '\\' ? p + 1 : p;
850 rootlevel = 2;
851 }
852 if (rootlevel == 2) // root path starts from share name
853 {
854 p = ph->fsphStrChr(path, '\\');
855 if (!p)
856 {
857 p = path + StrLen(path);
858 }
859 if (StrLen(tmp->share_name) != (p - path)
860 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
861 {
862 StrNCpy(tmp->share_name, path, p - path);
863 tmp->share_name[p - path] = 0;
864 newlevel = 1;
865 }
866 path = *p == '\\' ? p + 1 : p;
867 }
868 if (newlevel)
869 {
870 // reconnect to server here
871 unsigned long action;
872 smb_request req = {0};
873 smb_response resp = {0};
874
875 req.request = SMBREQ_DISCONNECT;
876 req.param = pConn->mem;
877 req.length = 0;
878 req.paramlen = 0;
879
880 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
881
882 req.request = SMBREQ_CONNECT;
883 req.param = pConn->mem;
884 req.length = pRes->memlen;
885 req.paramlen = sizeof(pConn->srv);
886
887 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
888 if (rc || action < sizeof(resp) || resp.rc)
889 {
890 APIRET rc2;
891 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
892 MemCpy(tmp, &pRes->srv, sizeof(pRes->srv));
893 rc2 = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
894 // TODO: what to do if the reconnect will fail ?
895 }
896 else
897 {
898 MemCpy(&pConn->srv, tmp, sizeof(pConn->srv));
899 }
900 }
901 }
902 StrCpy(result, "\\");
903 StrNCat(result, path, CCHMAXPATH);
904 return rc;
905}
906
907int APIENTRY NdpFreeResource (HRESOURCE resource)
908{
909 Resource *pRes = (Resource *)resource;
910 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
911 DosFreeMem(pRes);
912 log("NdpFreeResource %d\n", NO_ERROR);
913 return NO_ERROR;
914}
915
916
917int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
918{
919 int rc = NO_ERROR;
920 unsigned long objany = OBJ_ANY;
921 Resource *pRes = NULL;
922 /* since we support only 1 type of resources we do not need */
923 /* to check what the found type really is */
924 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE | objany);
925 if (rc == ERROR_INVALID_PARAMETER)
926 {
927 objany = 0;
928 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE);
929 }
930 if (!rc && pRes == NULL)
931 {
932 rc = ERROR_NOT_ENOUGH_MEMORY;
933 }
934 if (!rc)
935 {
936 MemSet(pRes, 0, sizeof(Resource));
937 pRes->properties = properties;
938 pRes->objany = objany;
939 rc = initResource (pRes);
940 if (rc == NO_ERROR)
941 {
942 *presource = (HRESOURCE)pRes;
943 }
944 else
945 {
946 NdpFreeResource((HRESOURCE)pRes);
947 }
948 }
949 log("NdpMountResource %d\n", rc);
950 return rc;
951}
952
953int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
954{
955 int rc;
956 Resource * pRes = (Resource *)resource;
957 unsigned long action;
958 smb_request req = {0};
959 smb_response resp = {0};
960 Connection *pConn = NULL;
961
962 log("NdpCreateConnection in\n");
963
964 rc = DosAllocMem((void **)&pConn, sizeof(Connection), PAG_COMMIT | PAG_READ | PAG_WRITE | pRes->objany);
965 if (!rc && pConn == NULL)
966 {
967 rc = ERROR_NOT_ENOUGH_MEMORY;
968 }
969 if (rc)
970 {
971 log("NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
972 return rc;
973 }
974 MemSet(pConn, 0, sizeof(Connection));
975 pConn->pRes = pRes;
976 pConn->file.fd = -1;
977
978 do {
979 log("NdpCreateConnection open pipe\n");
980 rc = openpipe(pRes, &pConn->pipe);
981 if (rc)
982 {
983 pConn->pipe = 0;
984 break;
985 }
986
987 log("NdpCreateConnection send INIT\n");
988 req.request = SMBREQ_INIT;
989 req.param = (char *)0xFFFFFFFF;
990 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
991 if (rc || action < sizeof(resp) || resp.rc)
992 {
993 return rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
994 }
995 pConn->clientpid = resp.value & 0xFFFF;
996
997 rc = DosAllocSharedMem((PPVOID)&pConn->mem, NULL, pRes->memlen, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | pRes->objany);
998 if (rc)
999 {
1000 break;
1001 }
1002 rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
1003 if (rc)
1004 {
1005 break;
1006 }
1007
1008 log("NdpCreateConnection send CONNECT\n");
1009 MemCpy(pConn->mem, &pRes->srv, sizeof(pRes->srv));
1010 req.request = SMBREQ_CONNECT;
1011 req.param = pConn->mem;
1012 req.paramlen = sizeof(pConn->srv);
1013 req.length = req.paramlen;
1014
1015 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1016 if (rc || action < sizeof(resp) || resp.rc)
1017 {
1018 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1019 }
1020 else
1021 {
1022 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
1023 }
1024 } while (0);
1025 if (rc)
1026 {
1027 if (pConn->mem)
1028 {
1029 DosFreeMem(pConn->mem);
1030 }
1031 if (pConn->pipe)
1032 {
1033 DosClose(pConn->pipe);
1034 }
1035 MemSet(pConn, 0, sizeof(*pConn));
1036 DosFreeMem(pConn);
1037 pConn = NULL;
1038 }
1039
1040 *pconn = (HCONNECTION)pConn;
1041 log("NdpCreateConnection %d %d\n", rc, resp.rc);
1042 return rc;
1043}
1044
1045
1046int APIENTRY NdpFreeConnection (HCONNECTION conn)
1047{
1048 Connection *pConn = (Connection *)conn;
1049 Resource *pRes = pConn->pRes;
1050
1051 log("NdpFreeConnection in\n");
1052 if (pConn->mem)
1053 {
1054 smb_request req = {0};
1055 smb_response resp = {0};
1056 unsigned long action;
1057 if (pConn->file.fd >= 0)
1058 {
1059 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
1060 req.request = SMBREQ_CLOSE;
1061 req.param = pConn->mem;
1062 req.length = sizeof(pConn->file);
1063 req.paramlen = sizeof(pConn->file);
1064
1065 _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1066 pConn->file.fd = -1;
1067 }
1068
1069 req.request = SMBREQ_DISCONNECT;
1070 req.param = pConn->mem;
1071 req.length = 0;
1072 req.paramlen = 0;
1073
1074 _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1075
1076 DosFreeMem(pConn->mem);
1077 DosClose(pConn->pipe);
1078 MemSet(pConn, 0, sizeof(*pConn));
1079 }
1080
1081 DosFreeMem(pConn);
1082 log("NdpFreeConnection %d\n", NO_ERROR);
1083 return NO_ERROR;
1084}
1085
1086int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
1087{
1088 Resource *pRes = (Resource *)resource;
1089 Resource *pRes2 = (Resource *)resource2;
1090 int rc = ND_RSRC_DIFFERENT;
1091
1092 log("NdpRsrcCompare in\n");
1093
1094 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
1095 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
1096 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
1097 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
1098 {
1099 // resources are equal
1100 rc = ND_RSRC_EQUAL;
1101 }
1102
1103 log("NdpRsrcCompare %d\n", rc);
1104
1105 return rc;
1106}
1107
1108int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
1109{
1110 // do nothing
1111 log("NdpRsrcUpdate %d\n", NO_ERROR);
1112 return NO_ERROR;
1113}
1114
1115int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
1116{
1117 Resource *pRes = (Resource *)resource;
1118 int rc = NO_ERROR;
1119 char s[4096];
1120
1121 log("NdpRsrcQueryInfo in\n");
1122
1123 switch (pRes->rootlevel)
1124 {
1125 case 0:
1126 {
1127 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
1128 } break;
1129 case 1:
1130 {
1131 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
1132 } break;
1133 case 2:
1134 {
1135 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.username);
1136 } break;
1137 default:
1138 {
1139 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\%s%s%s\\%s@%s", ifL ? "64" : "32", *pRes->srv.workgroup ? pRes->srv.workgroup : "", *pRes->srv.workgroup ? ":" : "", pRes->srv.server_name, pRes->srv.share_name, pRes->srv.username);
1140 } break;
1141 }
1142 *poutlen = StrLen(s) + 1;
1143 if (*poutlen > insize)
1144 {
1145 rc = ERROR_BUFFER_OVERFLOW;
1146 }
1147 else
1148 {
1149 MemCpy(pdata, s, *poutlen);
1150 }
1151
1152 log("NdpRsrcQueryInfo %d\n", rc);
1153
1154 return rc;
1155}
1156
1157int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
1158{
1159 ULONG ulDummy = 0;
1160 /* just return the resource info string */
1161 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
1162}
1163
1164int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
1165{
1166 int rc = NO_ERROR, rc1;
1167
1168 Connection *pConn = 0;
1169 smb_request req = {0};
1170 smb_response resp = {0};
1171 unsigned long action = 0;
1172
1173 log("NdpRsrcQueryFSAllocate %08x\n", pfsa);
1174
1175 if (!pfsa)
1176 {
1177 return NO_ERROR;
1178 }
1179
1180
1181 rc = NdpCreateConnection (resource, (HCONNECTION *)&pConn);
1182 if (rc)
1183 {
1184 log("NdpCreateConnection failed rc=%d\n", rc);
1185 pfsa->cSectorUnit = 1;
1186 pfsa->cUnit = 123456;
1187 pfsa->cUnitAvail = 123456;
1188 pfsa->cbSector = 2048;
1189 return rc;
1190 }
1191
1192 MemSet(pConn->mem, 0, sizeof(FSALLOCATE));
1193 req.request = SMBREQ_DSKATTR;
1194 req.param = pConn->mem;
1195 req.paramlen = sizeof(FSALLOCATE);
1196 req.length = req.paramlen;
1197
1198 rc = DosTransactNPipe( pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1199 if (rc || action < sizeof(resp) || resp.rc)
1200 {
1201 pfsa->cSectorUnit = 1;
1202 pfsa->cUnit = 123456;
1203 pfsa->cUnitAvail = 123456;
1204 pfsa->cbSector = 2048;
1205 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1206 }
1207 else
1208 {
1209 FSALLOCATE * fsa = (FSALLOCATE *)pConn->mem;
1210 pfsa->cSectorUnit = fsa->cSectorUnit;
1211 pfsa->cUnit = fsa->cUnit;
1212 pfsa->cUnitAvail = fsa->cUnitAvail;
1213 pfsa->cbSector = fsa->cbSector;
1214 }
1215
1216 rc1 = NdpFreeConnection((HCONNECTION)pConn);
1217
1218 log("NdpRsrcQueryFSAllocate %d/%d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, resp.rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
1219 return rc;
1220}
1221
1222int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1223{
1224 Connection *pConn = (Connection *)conn;
1225 Resource *pRes = pConn->pRes;
1226 int rc = NO_ERROR, count = 0;
1227 unsigned long action;
1228 smb_request req = {0};
1229 smb_response resp = {0};
1230 char *mask = "*";
1231 char dir[CCHMAXPATH+1] = {0};
1232 char path[CCHMAXPATH+1] = {0};
1233 char fullname[CCHMAXPATH+1] = {0};
1234 smbwrp_fileinfo * data;
1235 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1236
1237 debug_printf("NdpFindStart in\n");
1238 do
1239 {
1240 rc = checkconnection(pConn);
1241 if (rc)
1242 {
1243 break;
1244 }
1245
1246 StrNCpy(dir, szPath, sizeof(dir) - 1);
1247 if (pel)
1248 {
1249 mask = pel->name;
1250 dir[StrLen(szPath) - pel->length] = 0;
1251 }
1252 action = StrLen(dir) - 1;
1253 if (dir[action] == '\\')
1254 {
1255 dir[action] = 0;
1256 }
1257 rc = pathparser(pRes, pConn, dir, path);
1258 if (rc)
1259 {
1260 break;
1261 }
1262 action = StrLen(path) - 1;
1263 if (path[action] != '\\')
1264 {
1265 StrNCat(path, "\\", sizeof(path) - 1);
1266 }
1267 StrCpy(dir, path);
1268 StrNCat(path, mask, sizeof(path) - 1);
1269
1270 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
1271 StrCpy(pConn->mem + sizeof(pConn->srv), path);
1272 req.request = SMBREQ_FILELIST;
1273 req.param = pConn->mem;
1274 req.paramlen = sizeof(pConn->srv) + CCHMAXPATH + 1;
1275 req.length = pRes->memlen;
1276 data = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->srv) + CCHMAXPATH + 1);
1277
1278 do {
1279 int i;
1280 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1281 if (pConn->rc || action < sizeof(resp)
1282 || (resp.rc && resp.rc != ERROR_MORE_DATA))
1283 {
1284 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1285 break;
1286 }
1287log("NdpFindStart %d %d %d\n", pConn->rc, resp.rc, resp.length / sizeof(smbwrp_fileinfo));
1288 if (ifL)
1289 {
1290 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1291 {
1292 smbwrp_fileinfo * finfo = data + i;
1293log("NdpFindStart found <%s> %d\n", finfo->fname, finfo->easize);
1294 StrCpy(fullname, dir);
1295 StrCat(fullname, finfo->fname);
1296 StrCpy(finfo->fname, fullname);
1297 count += getfindinfoL(pConn, plist, finfo, ulAttribute, mask);
1298 }
1299 }
1300 else
1301 {
1302 FILEFINDBUF3 buf = {0};
1303 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1304 {
1305 smbwrp_fileinfo * finfo = data + i;
1306 getfindinfo(pConn, &buf, finfo);
1307
1308 if (ph->fsphAttrMatch(ulAttribute, buf.attrFile)
1309 && ph->fsphWildMatch(mask, buf.achName, ND_IGNORE_CASE))
1310 {
1311 StrCpy(fullname, dir);
1312 StrCat(fullname, finfo->fname);
1313 StrCpy(finfo->fname, fullname);
1314 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1315 count++;
1316 }
1317 }
1318 }
1319 } while (resp.rc == ERROR_MORE_DATA);
1320 } while (0);
1321
1322 log("NdpFindStart <%s> (%s) cnt %d %d %d\n", szPath, path, count, rc, pConn->rc);
1323 return rc;
1324}
1325
1326int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
1327{
1328 Connection *pConn = (Connection *)conn;
1329 Resource *pRes = pConn->pRes;
1330 int rc = 0;
1331 unsigned long action;
1332 smb_request req = {0};
1333 smb_response resp = {0};
1334 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1335 char path[CCHMAXPATH+1] = {0};
1336 int retry = 0;
1337
1338 do
1339 {
1340 debug_printf("NdpQueryInfo in <%s>, retry = %d\n", szPath, retry);
1341
1342 do {
1343
1344 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
1345 {
1346 rc = ERROR_FILE_NOT_FOUND;
1347 break;
1348 }
1349
1350 rc = checkconnection(pConn);
1351 if (rc)
1352 {
1353 break;
1354 }
1355
1356 rc = pathparser(pRes, pConn, szPath, path);
1357 switch (rc)
1358 {
1359 case NO_ERROR :
1360 case ERROR_FILE_NOT_FOUND:
1361 case ERROR_PATH_NOT_FOUND:
1362 case ERROR_ACCESS_DENIED:
1363 case ERROR_INVALID_PARAMETER:
1364 {
1365 break;
1366 }
1367 default :
1368 {
1369 rc = ERROR_PATH_NOT_FOUND;
1370 }
1371 }
1372 if (rc)
1373 {
1374 break;
1375 }
1376 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1377 req.request = SMBREQ_GETINFO;
1378 req.param = pConn->mem;
1379 req.paramlen = sizeof(*finfo);
1380 req.length = req.paramlen;
1381 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1382 if (pConn->rc || action < sizeof(resp) || resp.rc)
1383 {
1384 switch (resp.rc)
1385 {
1386 case NO_ERROR :
1387 case ERROR_FILE_NOT_FOUND:
1388 case ERROR_PATH_NOT_FOUND:
1389 case ERROR_ACCESS_DENIED:
1390 case ERROR_INVALID_PARAMETER:
1391 break;
1392 default :
1393 {
1394 resp.rc = ERROR_PATH_NOT_FOUND;
1395 }
1396 }
1397 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1398 }
1399 else
1400 {
1401 finfo->easize = -1;
1402 if (ifL)
1403 {
1404 getfindinfoL(pConn, plist, finfo, 0, NULL);
1405 }
1406 else
1407 {
1408 int trc;
1409 FILEFINDBUF3 buf = {0};
1410 getfindinfo(pConn, &buf, finfo);
1411 trc = ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1412 log("NdpQueryInfo got info <%s> attr %08x size %d namelen %d date %lu %lu. Plist 0x%08x rc = %d\n", buf.achName, buf.attrFile, buf.cbFile, buf.cchName, buf.fdateLastWrite, buf.ftimeLastWrite, plist, trc);
1413 }
1414 }
1415 if (rc == ERROR_FILE_NOT_FOUND)
1416 {
1417 // now try the upper path
1418 char * p = ph->fsphStrChr(finfo->fname, '\\');
1419 if (p && p > finfo->fname)
1420 {
1421 *p = 0;
1422 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1423 if (pConn->rc || action < sizeof(resp) || resp.rc)
1424 {
1425 rc = pConn->rc ? pConn->rc : (resp.rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER);
1426 }
1427 }
1428 }
1429 } while (0);
1430 log("NdpQueryInfo <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1431 retry = rc && !retry;
1432 } while (retry);
1433
1434 return rc;
1435}
1436
1437int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1438{
1439// log("NdpDeletePathInfo %d\n", 0);
1440 return NO_ERROR;
1441}
1442
1443int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1444{
1445 log("NdpRefresh <%s> %d\n", path, 0);
1446 return NO_ERROR;
1447}
1448
1449int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1450{
1451 // The plugin do not have to deallocate anything
1452 // because resource data did not contain any pointers
1453 // to plugins data.
1454 // Data stored by fsphSetResourceData will be
1455 // deallocated by NetDrive.
1456
1457 log("NdpDicardresourceData %d\n", 0);
1458 return NO_ERROR;
1459}
1460
1461int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1462{
1463 Connection *pConn = (Connection *)conn;
1464 Resource *pRes = pConn->pRes;
1465 int rc = 0;
1466 unsigned long action;
1467 smb_request req = {0};
1468 smb_response resp = {0};
1469 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1470 char path[CCHMAXPATH+1] = {0};
1471
1472 debug_printf("NdpSetPathInfo in\n");
1473 do {
1474 rc = checkconnection(pConn);
1475 if (rc)
1476 {
1477 break;
1478 }
1479
1480 rc = pathparser(pRes, pConn, szPathName, path);
1481 if (rc)
1482 {
1483 break;
1484 }
1485
1486 MemSet(finfo, 0, sizeof(*finfo));
1487
1488 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1489 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo->mtime));
1490 if (ifL)
1491 {
1492 finfo->attr = pfi->stat.attrFile & 0x37;
1493 }
1494 else
1495 {
1496 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
1497 finfo->attr = stat->attrFile & 0x37;
1498 }
1499 req.request = SMBREQ_SETINFO;
1500 req.param = pConn->mem;
1501 req.paramlen = sizeof(*finfo);
1502 req.length = req.paramlen;
1503 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1504 if (pConn->rc || action < sizeof(resp) || resp.rc)
1505 {
1506 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1507 }
1508 } while (0);
1509 log("NdpSetPathInfo <%s> (%s) %d %d\n", szPathName, path, rc, pConn->rc);
1510 return rc;
1511}
1512
1513int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1514{
1515 int rc = 0;
1516 FEA * pfea;
1517 FEA * pfeadest;
1518 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1519
1520 size = pFEASrc->cbList;
1521 pfea = pFEASrc->list;
1522 pfeadest = pFEAList->list;
1523 dsize = pFEAList->cbList;
1524//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1525 while (done < size)
1526 {
1527 char * name = (char *)(pfea + 1);
1528 int insert = 1;
1529 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1530 {
1531 GEA * pgea = pGEAList->list;
1532 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1533 insert = 0;
1534 while (done < size)
1535 {
1536//log("comp <%s> <%s>\n", name, pgea->szName);
1537 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1538 {
1539 insert = 1;
1540 break;
1541 }
1542 done += pgea->cbName + 2;
1543 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1544 }
1545 }
1546 if (insert)
1547 {
1548 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1549 if (ddone <= dsize)
1550 {
1551 pfeadest->cbName = pfea->cbName;
1552 pfeadest->cbValue = pfea->cbValue;
1553 pfeadest->fEA = 0;
1554 StrCpy((char *)(pfeadest + 1), name);
1555 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1556 pfeadest = (FEA *)((char *)pFEAList + ddone);
1557 }
1558 }
1559 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1560//log("buuildfea <%s> insert=%d pfea->cbName=%d pfea->cbValue=%d srcdone=%d destdone=%d pfeadest=%08x pfea=%08x\n", name, insert, pfea->cbName, pfea->cbValue, done, ddone, pfeadest, pfea);
1561 pfea = (FEA *)((char *)pFEASrc + done);
1562 }
1563 pFEAList->cbList = ddone;
1564 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1565 {
1566 rc = ERROR_BUFFER_OVERFLOW;
1567 }
1568 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1569 return rc;
1570}
1571
1572int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1573{
1574 Connection *pConn = (Connection *)conn;
1575 Resource *pRes = pConn->pRes;
1576 int rc = 0;
1577 unsigned long action;
1578 smb_request req = {0};
1579 smb_response resp = {0};
1580 char * path = NULL;
1581 FEALIST * pFEASrc;
1582 NDDATABUF fdata = {0};
1583 smbwrp_fileinfo *finfo;
1584
1585 if (!pfi || !pfi->pszName || !pFEAList)
1586 {
1587 return ERROR_EAS_NOT_SUPPORTED;
1588 }
1589 if (!pRes->easupport)
1590 {
1591 return ERROR_EAS_NOT_SUPPORTED;
1592 }
1593
1594 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1595 if (rc || !fdata.ulSize || !fdata.pData)
1596 {
1597 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1598 return ERROR_EAS_NOT_SUPPORTED;
1599 }
1600 finfo = (smbwrp_fileinfo *)fdata.pData;
1601 path = finfo->fname;
1602
1603 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1604 do {
1605 rc = checkconnection(pConn);
1606 if (rc)
1607 {
1608 break;
1609 }
1610
1611 StrNCpy(pConn->mem, path, CCHMAXPATH);
1612 req.request = SMBREQ_LISTEA;
1613 req.param = pConn->mem;
1614 req.paramlen = CCHMAXPATH + 1;
1615 req.length = pRes->memlen - req.paramlen;
1616 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
1617 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1618 if (pConn->rc || action < sizeof(resp) || resp.rc)
1619 {
1620 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1621 switch (rc)
1622 {
1623 case ERROR_FILE_NOT_FOUND :
1624 case ERROR_PATH_NOT_FOUND :
1625 {
1626 pFEAList->cbList = sizeof(pFEAList->cbList);
1627 rc = NO_ERROR;
1628 } break;
1629 case ERROR_BUFFER_OVERFLOW :
1630 {
1631 pFEAList->cbList = pFEASrc->cbList;
1632 } break;
1633 default :
1634 {
1635 rc = ERROR_EAS_NOT_SUPPORTED;
1636 }
1637 }
1638 }
1639 else
1640 {
1641 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1642 }
1643 } while (0);
1644 log("NdpEAQuery <%s> %d %d %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList, pConn->rc, resp.rc);
1645 return rc;
1646}
1647
1648int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1649{
1650 Connection *pConn = (Connection *)conn;
1651 Resource *pRes = pConn->pRes;
1652 int rc = 0;
1653 smb_request req = {0};
1654 smb_response resp = {0};
1655 char * path;
1656 unsigned long action;
1657 NDDATABUF fdata = {0};
1658 smbwrp_fileinfo *finfo;
1659
1660 log("NdpEASet in\n");
1661
1662 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1663 {
1664 return ERROR_EAS_NOT_SUPPORTED;
1665 }
1666 if (!pRes->easupport)
1667 {
1668 return ERROR_EAS_NOT_SUPPORTED;
1669 }
1670
1671 if (pFEAList->cbList > pRes->memlen)
1672 {
1673 return ERROR_NOT_ENOUGH_MEMORY;
1674 }
1675
1676 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1677 if (rc || !fdata.ulSize || !fdata.pData)
1678 {
1679 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1680 return ERROR_EAS_NOT_SUPPORTED;
1681 }
1682 finfo = (smbwrp_fileinfo *)fdata.pData;
1683 path = finfo->fname;
1684
1685 do {
1686 rc = checkconnection(pConn);
1687 if (rc)
1688 {
1689 break;
1690 }
1691
1692 StrNCpy(pConn->mem, path, CCHMAXPATH);
1693 MemCpy(pConn->mem + CCHMAXPATH + 1, pFEAList, pFEAList->cbList);
1694 req.request = SMBREQ_SETEA;
1695 req.param = pConn->mem;
1696 req.paramlen = pFEAList->cbList + CCHMAXPATH + 1;
1697 req.length = req.paramlen;
1698 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1699 if (pConn->rc || action < sizeof(resp) || resp.rc)
1700 {
1701 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1702 }
1703 } while (0);
1704 log("NdpEASet %d\n", rc);
1705 return rc;
1706}
1707
1708int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1709{
1710 Connection *pConn = (Connection *)conn;
1711 Resource *pRes = pConn->pRes;
1712 int rc = 0;
1713 unsigned long action;
1714 smb_request req = {0};
1715 smb_response resp = {0};
1716 char * path = NULL;
1717 FEALIST * pfealist;
1718 NDDATABUF fdata = {0};
1719 smbwrp_fileinfo *finfo;
1720 int easize;
1721
1722 if (!pfi || !pulEASize)
1723 {
1724 return ERROR_EAS_NOT_SUPPORTED;
1725 }
1726 if (!pRes->easupport)
1727 {
1728 return ERROR_EAS_NOT_SUPPORTED;
1729 }
1730
1731 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1732 if (rc || !fdata.ulSize || !fdata.pData)
1733 {
1734 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1735 return ERROR_EAS_NOT_SUPPORTED;
1736 }
1737 finfo = (smbwrp_fileinfo *)fdata.pData;
1738 easize = finfo->easize;
1739 finfo->easize = -1;
1740 path = finfo->fname;
1741 if (easize >= 0)
1742 {
1743 *pulEASize = easize;
1744 log("NdpEASize <%s> cached %d\n", path, easize);
1745 return NO_ERROR;
1746 }
1747
1748 log("NdpEASize in <%s> \n", path);
1749 do {
1750 rc = checkconnection(pConn);
1751 if (rc)
1752 {
1753 break;
1754 }
1755
1756 StrNCpy(pConn->mem, path, CCHMAXPATH);
1757 req.request = SMBREQ_LISTEA;
1758 req.param = pConn->mem;
1759 req.paramlen = CCHMAXPATH + 1;
1760 req.length = pRes->memlen - req.paramlen;
1761 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
1762 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1763 if (pConn->rc || action < sizeof(resp) || resp.rc)
1764 {
1765 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1766 switch (rc)
1767 {
1768 case ERROR_FILE_NOT_FOUND :
1769 case ERROR_PATH_NOT_FOUND :
1770 {
1771 pfealist->cbList = sizeof(pfealist->cbList);
1772 } /* Fall through */
1773 case ERROR_BUFFER_OVERFLOW :
1774 {
1775 rc = NO_ERROR;
1776 } break;
1777 default :
1778 {
1779 rc = ERROR_EAS_NOT_SUPPORTED;
1780 }
1781 }
1782 }
1783 *pulEASize = pfealist->cbList;
1784 } while (0);
1785 log("NdpEASize <%s> %d %d %d %d\n", pfi->pszName, *pulEASize, rc, pConn->rc, resp.rc);
1786 return rc;
1787}
1788
1789int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1790{
1791 Connection *pConn = (Connection *)conn;
1792 Resource *pRes = pConn->pRes;
1793 smb_request req = {0};
1794 smb_response resp = {0};
1795 int rc = 0;
1796 unsigned long action;
1797 char path[CCHMAXPATH+1] = {0};
1798
1799 log("NdpSetCurrentDir in\n");
1800 do {
1801 rc = checkconnection(pConn);
1802 if (rc)
1803 {
1804 break;
1805 }
1806
1807 rc = pathparser(pRes, pConn, szPath, path);
1808 if (rc)
1809 {
1810 break;
1811 }
1812
1813 StrNCpy(pConn->mem, path, CCHMAXPATH);
1814 req.request = SMBREQ_CHDIR;
1815 req.param = pConn->mem;
1816 req.paramlen = CCHMAXPATH + 1;
1817 req.length = req.paramlen;
1818 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1819 if (pConn->rc || action < sizeof(resp) || resp.rc)
1820 {
1821 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1822 }
1823 } while (0);
1824 log("NdpSetCurrentDir <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1825 return rc;
1826}
1827
1828int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1829{
1830 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1831 return ERROR_CANNOT_COPY;
1832}
1833
1834int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1835{
1836 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1837 return ERROR_CANNOT_COPY;
1838}
1839
1840int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1841{
1842 Connection *pConn = (Connection *)conn;
1843 Resource *pRes = pConn->pRes;
1844 smb_request req = {0};
1845 smb_response resp = {0};
1846 int rc = 0;
1847 unsigned long action;
1848 char path[CCHMAXPATH+1] = {0};
1849
1850 log("NdpForceDelete in\n");
1851 do {
1852 rc = checkconnection(pConn);
1853 if (rc)
1854 {
1855 break;
1856 }
1857
1858 rc = pathparser(pRes, pConn, szFile, path);
1859 if (rc)
1860 {
1861 break;
1862 }
1863
1864 StrNCpy(pConn->mem, path, CCHMAXPATH);
1865 req.request = SMBREQ_UNLINK;
1866 req.param = pConn->mem;
1867 req.paramlen = CCHMAXPATH + 1;
1868 req.length = req.paramlen;
1869 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1870 if (pConn->rc || action < sizeof(resp) || resp.rc)
1871 {
1872 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1873 }
1874 } while (0);
1875 log("NdpForceDelete <%s> (%s) %d %d\n", szFile, path, rc, pConn->rc);
1876 return rc;
1877}
1878
1879int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1880{
1881 Connection *pConn = (Connection *)conn;
1882 Resource *pRes = pConn->pRes;
1883 smb_request req = {0};
1884 smb_response resp = {0};
1885 int rc = 0;
1886 unsigned long action;
1887 char path[CCHMAXPATH+1] = {0};
1888
1889 log("NdpCreateDir in\n");
1890 do {
1891 rc = checkconnection(pConn);
1892 if (rc)
1893 {
1894 break;
1895 }
1896
1897 rc = pathparser(pRes, pConn, szDirName, path);
1898 if (rc)
1899 {
1900 break;
1901 }
1902
1903 StrNCpy(pConn->mem, path, CCHMAXPATH);
1904 req.request = SMBREQ_MKDIR;
1905 req.param = pConn->mem;
1906 req.paramlen = CCHMAXPATH + 1;
1907 req.length = req.paramlen;
1908 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1909 if (pConn->rc || action < sizeof(resp) || resp.rc)
1910 {
1911 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1912 }
1913 } while (0);
1914 log("NdpCreateDir <%s> (%s) %d %d\n", szDirName, path, rc, pConn->rc);
1915 return rc;
1916}
1917
1918int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1919{
1920 Connection *pConn = (Connection *)conn;
1921 Resource *pRes = pConn->pRes;
1922 smb_request req = {0};
1923 smb_response resp = {0};
1924 int rc = 0;
1925 unsigned long action;
1926 char path[CCHMAXPATH+1] = {0};
1927
1928 log("NdpDeleteDir in\n");
1929 do {
1930 rc = checkconnection(pConn);
1931 if (rc)
1932 {
1933 break;
1934 }
1935
1936 rc = pathparser(pRes, pConn, szDir, path);
1937 if (rc)
1938 {
1939 break;
1940 }
1941
1942 StrNCpy(pConn->mem, path, CCHMAXPATH);
1943 req.request = SMBREQ_RMDIR;
1944 req.param = pConn->mem;
1945 req.paramlen = CCHMAXPATH + 1;
1946 req.length = req.paramlen;
1947 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1948 if (pConn->rc || action < sizeof(resp) || resp.rc)
1949 {
1950 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1951 }
1952 } while (0);
1953 log("NdpDeleteDir <%s> (%s) %d %d\n", szDir, path, rc, pConn->rc);
1954 return rc;
1955}
1956
1957int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1958{
1959 Connection *pConn = (Connection *)conn;
1960 Resource *pRes = pConn->pRes;
1961 smb_request req = {0};
1962 smb_response resp = {0};
1963 int rc = 0;
1964 unsigned long action;
1965 char src[CCHMAXPATH+1] = {0};
1966 int l1, l2;
1967 char * p = szDst;
1968
1969 log("NdpMove in\n");
1970 do
1971 {
1972 rc = checkconnection(pConn);
1973 if (rc)
1974 {
1975 break;
1976 }
1977
1978 rc = pathparser(pRes, pConn, szSrc, src);
1979 if (rc)
1980 {
1981 break;
1982 }
1983 l1 = StrLen(szSrc);
1984 l2 = StrLen(src);
1985 if (l1 > l2)
1986 {
1987 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1988 {
1989 // the file moved accross different shares or servers or workgroups
1990 rc = ERROR_WRITE_PROTECT;
1991 break;
1992 }
1993 p = szDst + l1 - l2 + 1;
1994 }
1995 StrNCpy(pConn->mem, src, CCHMAXPATH);
1996 pConn->mem[CCHMAXPATH + 1] = '\\';
1997 StrNCpy(pConn->mem + CCHMAXPATH + 2, p, CCHMAXPATH - 1);
1998 req.request = SMBREQ_RENAME;
1999 req.param = pConn->mem;
2000 req.paramlen = 2 * (CCHMAXPATH + 1);
2001 req.length = req.paramlen;
2002 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2003 if (pConn->rc || action < sizeof(resp) || resp.rc)
2004 {
2005 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2006 }
2007 } while (0);
2008 log("NdpMove <%s> -> <%s> (%s) %d %d\n", szSrc, szDst, src, rc, pConn->rc);
2009
2010 return rc;
2011}
2012
2013int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
2014{
2015 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
2016 return ERROR_WRITE_PROTECT;
2017}
2018
2019
2020int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
2021{
2022 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
2023}
2024
2025int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
2026{
2027 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
2028}
2029
2030int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2031{
2032 Resource *pRes = pConn->pRes;
2033 smb_request req = {0};
2034 smb_response resp = {0};
2035 unsigned long action;
2036 int rc = 0;
2037 char path[CCHMAXPATH+1] = {0};
2038
2039 log("smbopen in %d\n", pConn->file.fd);
2040 do {
2041 if (pConn->file.fd > 0)
2042 {
2043 rc = ERROR_TOO_MANY_OPEN_FILES;
2044 break;
2045 }
2046
2047 rc = checkconnection(pConn);
2048 if (rc)
2049 {
2050 break;
2051 }
2052
2053 rc = pathparser(pRes, pConn, szFileName, path);
2054 if (rc)
2055 {
2056 break;
2057 }
2058
2059 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
2060 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
2061 flags |= O_BINARY;
2062 switch (ulOpenMode & 3)
2063 {
2064 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
2065 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
2066 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
2067 default : flags |= O_RDWR;
2068 }
2069 pConn->file.openmode = flags;
2070 pConn->file.openattr = ulAttribute & 0x37;
2071 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
2072 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2073 req.request = SMBREQ_OPEN;
2074 req.param = pConn->mem;
2075 req.paramlen = sizeof(pConn->file);
2076 req.length = req.paramlen;
2077 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2078 if (pConn->rc || action < sizeof(resp) || resp.rc)
2079 {
2080 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2081 }
2082 else
2083 {
2084 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2085 }
2086 } while (0);
2087 log("smbopen <%s> (%s) %08x %08x %08x %d %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->rc, pConn->file.fd);
2088 if (!rc && pFEAList)
2089 {
2090 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
2091 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
2092 }
2093
2094 return rc;
2095}
2096
2097int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2098{
2099 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
2100}
2101
2102int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2103{
2104 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
2105}
2106
2107int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2108{
2109// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
2110 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
2111}
2112
2113int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2114{
2115 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
2116}
2117
2118int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
2119{
2120 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
2121 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
2122}
2123
2124int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
2125{
2126 Connection *pConn = (Connection *)conn;
2127 Resource *pRes = pConn->pRes;
2128 int rc = 0;
2129 unsigned long action;
2130 smb_request req = {0};
2131 smb_response resp = {0};
2132 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2133 char path[CCHMAXPATH+1] = {0};
2134
2135 log("NdpSetFileAttribute in\n");
2136 do {
2137 rc = checkconnection(pConn);
2138 if (rc)
2139 {
2140 break;
2141 }
2142
2143 rc = pathparser(pRes, pConn, szFileName, path);
2144 if (rc)
2145 {
2146 break;
2147 }
2148
2149 MemSet(finfo, 0, sizeof(*finfo));
2150
2151 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
2152 finfo->attr = usAttr & 0x37;
2153 req.request = SMBREQ_SETINFO;
2154 req.param = pConn->mem;
2155 req.paramlen = sizeof(*finfo);
2156 req.length = req.paramlen;
2157 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2158 if (pConn->rc || action < sizeof(resp) || resp.rc)
2159 {
2160 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2161 }
2162 } while (0);
2163 log("NdpSetFileAttribute <%s> (%s) %04x %d %d\n", szFileName, path, usAttr, rc, pConn->rc);
2164 return rc;
2165}
2166
2167int APIENTRY NdpFlush (HRESOURCE resource)
2168{
2169 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
2170 return ERROR_NOT_SUPPORTED;
2171}
2172
2173int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
2174{
2175 log("NdpIOCTL <%s> %d\n", path, function);
2176
2177 if (in && insize > 4096)
2178 {
2179 char out[4096];
2180 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
2181 *poutlen = strlen(out);
2182 strcpy (in, out);
2183 return NO_ERROR;
2184 }
2185
2186 return ERROR_NOT_SUPPORTED;
2187}
2188
2189int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
2190{
2191 Connection *pConn = (Connection *)conn;
2192 Resource *pRes = pConn->pRes;
2193 int rc = 0;
2194 unsigned long action;
2195 smb_request req = {0};
2196 smb_response resp = {0};
2197 FILEFINDBUF3 buf;
2198 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->file));
2199
2200 debug_printf("NdpFileQueryInfo in\n");
2201 do {
2202 if (pConn->file.fd < 0 || !*pConn->file.fname)
2203 {
2204 rc = ERROR_INVALID_HANDLE;
2205 break;
2206 }
2207 if (pConn->rc)
2208 {
2209 rc = ERROR_PIPE_NOT_CONNECTED;
2210 break;
2211 }
2212
2213 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2214 StrNCpy(finfo->fname, pConn->file.fname, sizeof(finfo->fname) - 1);
2215 req.request = SMBREQ_FGETINFO;
2216 req.param = pConn->mem;
2217 req.paramlen = sizeof(pConn->file);
2218 req.length = req.paramlen + sizeof(*finfo);
2219 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2220 if (pConn->rc || action < sizeof(resp) || resp.rc)
2221 {
2222 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2223 }
2224 else
2225 {
2226 finfo->easize = -1;
2227 if (ifL)
2228 {
2229 getfindinfoL(pConn, plist, finfo, 0, NULL);
2230 }
2231 else
2232 {
2233 getfindinfo(pConn, &buf, finfo);
2234 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
2235 }
2236 }
2237 } while (0);
2238 log("NdpFileQueryInfo <%s> %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc, pConn->rc);
2239
2240 return rc;
2241}
2242
2243int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
2244{
2245 Connection *pConn = (Connection *)conn;
2246 Resource *pRes = pConn->pRes;
2247 int rc = 0;
2248 unsigned long action;
2249 smb_request req = {0};
2250 smb_response resp = {0};
2251 FEALIST * pFEASrc;
2252
2253 if (!pFEAList)
2254 {
2255 return ERROR_EAS_NOT_SUPPORTED;
2256 }
2257 if (!pRes->easupport)
2258 {
2259 return ERROR_EAS_NOT_SUPPORTED;
2260 }
2261
2262 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
2263 do {
2264 if (pConn->file.fd < 0)
2265 {
2266 rc = ERROR_INVALID_HANDLE;
2267 break;
2268 }
2269 if (pConn->rc)
2270 {
2271 rc = ERROR_PIPE_NOT_CONNECTED;
2272 break;
2273 }
2274
2275 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2276 req.request = SMBREQ_FLISTEA;
2277 req.param = pConn->mem;
2278 req.paramlen = sizeof(pConn->file);
2279 req.length = pRes->memlen - req.paramlen;
2280 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
2281 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2282 if (pConn->rc || action < sizeof(resp) || resp.rc)
2283 {
2284 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2285 switch (rc)
2286 {
2287 case ERROR_FILE_NOT_FOUND :
2288 case ERROR_PATH_NOT_FOUND :
2289 {
2290 pFEAList->cbList = sizeof(pFEAList->cbList);
2291 rc = NO_ERROR;
2292 } break;
2293 case ERROR_BUFFER_OVERFLOW :
2294 {
2295 pFEAList->cbList = pFEASrc->cbList;
2296 } break;
2297 default :
2298 {
2299 rc = ERROR_EAS_NOT_SUPPORTED;
2300 }
2301 }
2302 }
2303 else
2304 {
2305 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
2306 }
2307 } while (0);
2308 log("NdpFileEAQuery out <%s>/%d pFEASrc->cbList=%d pFEAList->cbList=%d rc=%d %d %d\n", pConn->file.fname, pConn->file.fd, pFEASrc->cbList, pFEAList->cbList, rc, pConn->rc, resp.rc);
2309 return rc;
2310}
2311
2312int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
2313{
2314 Connection *pConn = (Connection *)conn;
2315 Resource *pRes = pConn->pRes;
2316 int rc = 0;
2317 smb_request req = {0};
2318 smb_response resp = {0};
2319 unsigned long action;
2320
2321 log("NdpFileEASet in\n");
2322
2323 if (!pFEAList || pFEAList->cbList <= sizeof(long))
2324 {
2325 return ERROR_EAS_NOT_SUPPORTED;
2326 }
2327 if (!pRes->easupport)
2328 {
2329 return ERROR_EAS_NOT_SUPPORTED;
2330 }
2331 if (pFEAList->cbList > pRes->memlen)
2332 {
2333 return ERROR_NOT_ENOUGH_MEMORY;
2334 }
2335
2336 do {
2337 if (pConn->file.fd < 0)
2338 {
2339 rc = ERROR_INVALID_HANDLE;
2340 break;
2341 }
2342 if (pConn->rc)
2343 {
2344 rc = ERROR_PIPE_NOT_CONNECTED;
2345 break;
2346 }
2347
2348 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2349 MemCpy(pConn->mem + sizeof(pConn->file), pFEAList, pFEAList->cbList);
2350 req.request = SMBREQ_FSETEA;
2351 req.param = pConn->mem;
2352 req.paramlen = pFEAList->cbList + sizeof(pConn->file);
2353 req.length = req.paramlen;
2354
2355 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2356 if (pConn->rc || action < sizeof(resp) || resp.rc)
2357 {
2358 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2359 }
2360 } while (0);
2361 log("NdpFileEASet %d\n", rc);
2362 return rc;
2363}
2364
2365int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
2366{
2367 Connection *pConn = (Connection *)conn;
2368 Resource *pRes = pConn->pRes;
2369 int rc = 0;
2370 unsigned long action;
2371 smb_request req = {0};
2372 smb_response resp = {0};
2373 char path[CCHMAXPATH+1] = {0};
2374 FEALIST * pfealist;
2375
2376 if (!pulEASize)
2377 {
2378 return ERROR_EAS_NOT_SUPPORTED;
2379 }
2380 if (!pRes->easupport)
2381 {
2382 return ERROR_EAS_NOT_SUPPORTED;
2383 }
2384
2385 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
2386 do {
2387 if (pConn->file.fd < 0)
2388 {
2389 rc = ERROR_INVALID_HANDLE;
2390 break;
2391 }
2392 if (pConn->rc)
2393 {
2394 rc = ERROR_PIPE_NOT_CONNECTED;
2395 break;
2396 }
2397
2398 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2399 req.request = SMBREQ_FLISTEA;
2400 req.param = pConn->mem;
2401 req.paramlen = sizeof(pConn->file);
2402 req.length = pRes->memlen - req.paramlen;
2403 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
2404 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2405 if (pConn->rc || action < sizeof(resp) || resp.rc)
2406 {
2407 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2408 switch (rc)
2409 {
2410 case ERROR_FILE_NOT_FOUND :
2411 case ERROR_PATH_NOT_FOUND :
2412 {
2413 pfealist->cbList = sizeof(pfealist->cbList);
2414 } /* Fall through */
2415 case ERROR_BUFFER_OVERFLOW :
2416 {
2417 rc = NO_ERROR;
2418 } break;
2419 default :
2420 {
2421 rc = ERROR_EAS_NOT_SUPPORTED;
2422 }
2423 }
2424 }
2425 *pulEASize = pfealist->cbList;
2426 } while (0);
2427 log("NdpFileEASize %d %d %d %d\n", *pulEASize, rc, pConn->rc, resp.rc);
2428 return rc;
2429}
2430
2431int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2432{
2433 Connection *pConn = (Connection *)conn;
2434 Resource *pRes = pConn->pRes;
2435 int rc = 0;
2436 unsigned long action, attrFile;
2437 smb_request req = {0};
2438 smb_response resp = {0};
2439 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2440
2441 debug_printf("NdpFileSetInfo in\n");
2442 do {
2443 if (pConn->file.fd < 0 || !*pConn->file.fname)
2444 {
2445 rc = ERROR_INVALID_HANDLE;
2446 break;
2447 }
2448 if (pConn->rc)
2449 {
2450 rc = ERROR_PIPE_NOT_CONNECTED;
2451 break;
2452 }
2453 if (ifL)
2454 {
2455 attrFile = pfi->stat.attrFile;
2456 }
2457 else
2458 {
2459 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
2460 attrFile = stat->attrFile;
2461 }
2462 // deferred setinfo - on closing the file
2463 pConn->file.openattr = attrFile;
2464 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
2465 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
2466 } while (0);
2467 log("NdpFileSetInfo <%s> %08x %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc, pConn->rc);
2468 return NO_ERROR;
2469}
2470
2471int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2472{
2473 Connection *pConn = (Connection *)conn;
2474 Resource *pRes = pConn->pRes;
2475 int rc = 0;
2476 unsigned long action;
2477 smb_request req = {0};
2478 smb_response resp = {0};
2479
2480 log("NdpFileSetFilePtrl in\n");
2481 do {
2482 if (pConn->file.fd < 0)
2483 {
2484 rc = ERROR_INVALID_HANDLE;
2485 break;
2486 }
2487 if (pConn->rc)
2488 {
2489 rc = ERROR_PIPE_NOT_CONNECTED;
2490 break;
2491 }
2492
2493 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2494 *(unsigned long *)(pConn->mem + sizeof(pConn->file)) = ulMethod;
2495 *(long long *)(pConn->mem + sizeof(pConn->file) + sizeof(long)) = llOffset;
2496 req.request = SMBREQ_LSEEK;
2497 req.param = pConn->mem;
2498 req.paramlen = sizeof(pConn->file) + sizeof(long) + sizeof(long long);
2499 req.length = req.paramlen;
2500 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2501 if (pConn->rc || action < sizeof(resp) || resp.rc)
2502 {
2503 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2504 }
2505 else
2506 {
2507 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2508 *pllActual = pConn->file.offset;
2509 }
2510 } while (0);
2511 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc, pConn->rc);
2512
2513 return rc;
2514}
2515
2516int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2517{
2518 LONGLONG llActual;
2519 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2520 *pulActual = llActual & 0xFFFFFFFF;
2521 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2522 return rc;
2523}
2524
2525int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2526{
2527 Connection *pConn = (Connection *)conn;
2528 Resource *pRes = pConn->pRes;
2529 int rc = 0;
2530 unsigned long action;
2531 smb_request req = {0};
2532 smb_response resp = {0};
2533
2534 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2535
2536 do {
2537 if (pConn->file.fd < 0)
2538 {
2539 rc = ERROR_INVALID_HANDLE;
2540 break;
2541 }
2542 if (pConn->rc)
2543 {
2544 rc = ERROR_PIPE_NOT_CONNECTED;
2545 break;
2546 }
2547
2548 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2549 req.request = SMBREQ_CLOSE;
2550 req.param = pConn->mem;
2551 req.length = pRes->memlen;
2552 req.paramlen = sizeof(pConn->file);
2553 req.length = req.paramlen;
2554 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2555 if (pConn->rc || action < sizeof(resp) || resp.rc)
2556 {
2557 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2558 }
2559 else
2560 {
2561 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2562 }
2563 } while (0);
2564 log("NdpFileClose %d %d %d\n", pConn->file.fd, rc, pConn->rc);
2565 pConn->file.fd = -1;
2566 return rc;
2567}
2568
2569int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2570{
2571 log("NdpFileCommit %d\n", NO_ERROR);
2572 return NO_ERROR;
2573}
2574
2575
2576int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2577{
2578 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2579 log("NdpFileNewSize %ld %d\n", ulLen, rc);
2580 return rc;
2581}
2582
2583int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2584{
2585 Connection *pConn = (Connection *)conn;
2586 Resource *pRes = pConn->pRes;
2587 int rc = 0;
2588 unsigned long action;
2589 smb_request req = {0};
2590 smb_response resp = {0};
2591
2592 log("NdpFileNewSizeL in\n");
2593 do {
2594 if (pConn->file.fd < 0)
2595 {
2596 rc = ERROR_INVALID_HANDLE;
2597 break;
2598 }
2599 if (pConn->rc)
2600 {
2601 rc = ERROR_PIPE_NOT_CONNECTED;
2602 break;
2603 }
2604
2605 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2606 *(long long *)(pConn->mem + sizeof(pConn->file)) = llLen;
2607
2608 req.request = SMBREQ_NEWSIZE;
2609 req.param = pConn->mem;
2610 req.paramlen = sizeof(pConn->file) + sizeof(long long);
2611 req.length = req.paramlen;
2612
2613 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2614 if (pConn->rc || action < sizeof(resp) || resp.rc)
2615 {
2616 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2617 }
2618 else
2619 {
2620 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2621 }
2622 } while (0);
2623 log("NdpFileNewSizeL <%s> %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc, pConn->rc);
2624 return rc;
2625}
2626
2627int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2628{
2629 Connection *pConn = (Connection *)conn;
2630 Resource *pRes = pConn->pRes;
2631 int rc = 0;
2632 unsigned long done = 0;
2633 unsigned long onedone;
2634 unsigned long action;
2635 smb_request req = {0};
2636 smb_response resp = {0};
2637
2638 log("NdpFileRead in\n");
2639// log("NdpFileRead <%s> %lu\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead);
2640
2641 do {
2642 if (pConn->file.fd < 0)
2643 {
2644 rc = ERROR_INVALID_HANDLE;
2645 break;
2646 }
2647 if (pConn->rc)
2648 {
2649 rc = ERROR_PIPE_NOT_CONNECTED;
2650 break;
2651 }
2652
2653 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2654 req.request = SMBREQ_READ;
2655 req.param = pConn->mem;
2656 req.paramlen = sizeof(pConn->file);
2657
2658 while (done < ulRead)
2659 {
2660 req.length = req.paramlen + (pRes->memlen - req.paramlen < (ulRead - done) ? pRes->memlen - req.paramlen : (ulRead - done));
2661
2662 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2663 if (pConn->rc || action < sizeof(resp) || resp.rc)
2664 {
2665 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2666 break;
2667 }
2668 if (resp.value == 0)
2669 {
2670 break;
2671 }
2672 onedone = resp.value > req.length ? req.length : resp.value;
2673 MemCpy((char *)pBuffer + done, pConn->mem + sizeof(pConn->file), onedone);
2674 done += onedone;
2675 }
2676 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2677 *pulActual = done;
2678 } while (0);
2679 log("NdpFileRead <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc, pConn->rc);
2680
2681 return rc;
2682}
2683
2684int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2685{
2686 Connection *pConn = (Connection *)conn;
2687 Resource *pRes = pConn->pRes;
2688 int rc = 0;
2689 unsigned long done = 0;
2690 unsigned long onedone;
2691 unsigned long action;
2692 smb_request req = {0};
2693 smb_response resp = {0};
2694
2695 log("NdpFileWrite in\n");
2696 do {
2697 if (pConn->file.fd < 0)
2698 {
2699 rc = ERROR_INVALID_HANDLE;
2700 break;
2701 }
2702 if (pConn->rc)
2703 {
2704 rc = ERROR_PIPE_NOT_CONNECTED;
2705 break;
2706 }
2707
2708 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2709 req.request = SMBREQ_WRITE;
2710 req.param = pConn->mem;
2711 req.paramlen = sizeof(pConn->file);
2712
2713 while (done < ulWrite)
2714 {
2715 req.length = pRes->memlen - req.paramlen < (ulWrite - done) ? pRes->memlen - req.paramlen : (ulWrite - done);
2716 MemCpy(pConn->mem + sizeof(pConn->file), (char *)pBuffer + done, req.length);
2717 req.length += req.paramlen;
2718
2719 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2720 if (pConn->rc || action < sizeof(resp) || resp.rc)
2721 {
2722 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2723 break;
2724 }
2725 done += resp.value & 0xFFFFFFFF;
2726 if (resp.value < req.length)
2727 {
2728 break;
2729 }
2730 }
2731 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2732 *pulActual = done;
2733 } while (0);
2734 log("NdpFileWrite <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc, pConn->rc);
2735
2736 return rc;
2737}
Note: See TracBrowser for help on using the repository browser.