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

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

Check for resource type at mount time, only for nd/ndpm, so ndpm can retry operation. ticket:58.

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