source: branches/client-2.0/src/ndpsmb.c@ 520

Last change on this file since 520 was 520, checked in by Silvan Scherrer, 15 years ago

Samba Client 2.0: another bunch of updates

  • Property svn:eol-style set to native
File size: 54.1 KB
Line 
1/*
2 Netdrive Samba client plugin
3 plugin API
4 Copyright (C) netlabs.org 2003-2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include <stdio.h>
22#include <stdlib.h>
23#include <stdarg.h>
24#include <string.h>
25#include <time.h>
26
27#define NDPL_LARGEFILES
28#define INCL_LONGLONG
29#include <ndextpl2.h>
30#include "smbwrp.h"
31#include "util.h"
32
33#if 0
34
35#ifndef DEBUG_PRINTF
36#define debug_printf( ...)
37#endif
38
39#define log debug_printf
40#endif
41
42#define debug_printf(...) debuglocal(9, __VA_ARGS__)
43
44// -------------------------------------------------------------
45
46/* time conversion functions: SMB protocol sends timestamps in GMT time,
47* os2 api uses localtime,
48* emx/klibc uses timezone and daylight saving to convert GMT timestamps,
49* so only the timezone must be counted in conversion.
50*/
51void fsphUnixTimeToDosDate( time_t time, FDATE* fdate, FTIME *ftime)
52{
53 struct tm* gmt = localtime( &time);
54#if 0 // as localtime() already does dst we don't need to add something
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#endif
61 fdate->day = gmt->tm_mday;
62 fdate->month = gmt->tm_mon+1;
63 fdate->year = gmt->tm_year + 1900 - 1980;
64 ftime->twosecs = gmt->tm_sec/2;
65 ftime->minutes = gmt->tm_min;
66 ftime->hours = gmt->tm_hour;
67 debug_printf("fsphUnixDateToDosDate\n");
68}
69
70void fsphDosDateToUnixTime( FDATE fdate, FTIME ftime, ULONG* time)
71{
72 struct tm gmtime = { 0 };
73
74 debug_printf( "fsphDosDateToUnixTime time %02d:%02d\n", ftime.hours, ftime.minutes);
75 gmtime.tm_mday = fdate.day;
76 gmtime.tm_mon = fdate.month-1;
77 gmtime.tm_year = fdate.year + 1980 - 1900;
78 gmtime.tm_sec = ftime.twosecs*2;
79 gmtime.tm_min = ftime.minutes;
80 gmtime.tm_hour = ftime.hours;
81 gmtime.tm_isdst = -1; // force libc to check dst saving
82
83 *time = mktime( &gmtime);
84 debug_printf( "fsphDosDateToUnixTime time1 %d %s", *time, ctime( (time_t*)time));
85#if 0 // as mktime() already does dst we don't need to add something
86 struct tm* gmt;
87 gmt = localtime( (time_t*) time);
88 if (gmt->tm_isdst>0) {
89 debug_printf( "fsphDosDateToUnixTime daylight saving in effect %d, timezone %d\n",gmt->tm_isdst, timezone);
90 *time += 3600;
91 }
92#endif
93 debug_printf( "fsphDosDateToUnixTime time2 %d %s", *time, ctime( (time_t*)time));
94}
95
96// -------------------------------------------------------------
97
98int StrLen(char * s)
99{
100 char * p;
101 if (!s)
102 {
103 return 0;
104 }
105 for (p = s; *p; p++);
106 return (p - s);
107}
108
109char * StrNCat(char *dst, const char *src, int count)
110{
111 int i;
112 if (!dst || !src || count <= 0)
113 {
114 return dst;
115 }
116 for (i = 0; dst[i]; i++);
117 for (;i < count && *src; i++, src++)
118 {
119 dst[i] = *src;
120 }
121 dst[i] = 0;
122 return dst;
123}
124
125char * StrNCpy(char *dst, const char *src, int count)
126{
127 if (!dst || !src || count <= 0)
128 {
129 return dst;
130 }
131 *dst = 0;
132 return StrNCat(dst, src, count);
133}
134
135char * StrCpy(char *dst, const char *src)
136{
137 char * p;
138 if (!dst || !src)
139 {
140 return dst;
141 }
142 p = dst;
143 while (*p++ = *src++);
144 return dst;
145}
146
147char * StrCat(char *dst, const char *src)
148{
149 int i;
150 if (!dst || !src)
151 {
152 return dst;
153 }
154 for (i = 0; dst[i]; i++);
155 for (; *src; i++, src++)
156 {
157 dst[i] = *src;
158 }
159 dst[i] = 0;
160 return dst;
161}
162
163void * MemCpy(void * dst, const void * src, int len)
164{
165 int i;
166 if (!src || !dst || len <= 0)
167 {
168 return dst;
169 }
170 for (i = 0; i < len; i++)
171 {
172 ((char *)dst)[i] = ((char *)src)[i];
173 }
174 return dst;
175}
176
177void *MemSet(void *dst, char c, int len)
178{
179 int i;
180 if (!dst || len <= 0)
181 {
182 return dst;
183 }
184 for (i = 0; i < len; i++)
185 {
186 ((char *)dst)[i] = c;
187 }
188 return dst;
189}
190
191// -------------------------------------------------------------
192
193/* uppercased type of resource */
194const char *NdpTypes[] =
195{
196 "SMBFS",
197 NULL
198}
199;
200
201/* Properties of supported resource types */
202
203/* Properties of resource */
204static const NDPROPERTYINFO smbProperties[] =
205{
206 {ND_PROP_STRING, 0, "WORKGROUP", ""},
207 {ND_PROP_STRING, 0, "SERVER", ""},
208 {ND_PROP_STRING, 0, "SHARE", ""},
209 {ND_PROP_STRING, 0, "USER", "guest"},
210 {ND_PROP_STRING, 0, "PASSWORD", ""},
211 {ND_PROP_STRING, 0, "SPASSWORD", ""},
212 {ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
213 {ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
214 {ND_PROP_ULONG, 0, "CTO", "10"},
215 {ND_PROP_ULONG, 0, "CLD", "32"},
216 {ND_PROP_ULONG, 0, "EASUPPORT", "1"},
217 {ND_PROP_STRING, 0, NULL, NULL}
218};
219
220
221/* Exported array of properties */
222const NDPROPERTYINFO *NdpPropertiesInfo[] =
223{
224 smbProperties
225};
226
227
228PLUGINHELPERTABLE2L *ph;
229static int ifL;
230
231int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
232{
233 int rc;
234 HPIPE pipe;
235 unsigned long action;
236 ph = pPHT;
237 ifL = 0;
238/*
239 if (ph->cb < sizeof (PLUGINHELPERTABLE2))
240 {
241 return ERROR_INVALID_FUNCTION;
242 }
243*/
244 if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
245 {
246 ifL = 1;
247 }
248 debuglocal(9,"Working with %s bit fileio NDFS\n", ifL ? "64" : "32");
249 return NO_ERROR;
250}
251
252
253int APIENTRY NdpPluginFree (void)
254{
255 return NO_ERROR;
256}
257
258
259void getfindinfo(Connection * pConn, FILEFINDBUF3 * stat, smbwrp_fileinfo * finfo)
260{
261 char * name = ph->fsphStrRChr(finfo->fname, '\\');
262 if (name)
263 {
264 name++;
265 }
266 else
267 {
268 name = finfo->fname;
269 }
270 if (!*name)
271 {
272 name = pConn->pRes->srv.share_name;
273 }
274 StrNCpy(stat->achName, name, CCHMAXPATHCOMP - 1);
275 stat->cbFile = finfo->size;
276 stat->cbFileAlloc = stat->cbFile;
277 stat->oNextEntryOffset = 0ul;
278 stat->cchName = StrLen(stat->achName);
279 stat->attrFile = (finfo->attr & 0x37);
280
281 fsphUnixTimeToDosDate(finfo->mtime, &stat->fdateLastWrite, &stat->ftimeLastWrite);
282 fsphUnixTimeToDosDate(finfo->ctime, &stat->fdateCreation, &stat->ftimeCreation);
283 fsphUnixTimeToDosDate(finfo->atime, &stat->fdateLastAccess, &stat->ftimeLastAccess);
284}
285
286int getfindinfoL(Connection * pConn, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
287{
288 FILESTATUS3L stat = {0};
289 char * name = ph->fsphStrRChr(finfo->fname, '\\');
290 if (name)
291 {
292 name++;
293 }
294 else
295 {
296 name = finfo->fname;
297 }
298 if (!*name)
299 {
300 name = pConn->pRes->srv.share_name;
301 }
302 if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
303 {
304 return 0;
305 }
306
307 stat.cbFile = finfo->size;
308 stat.cbFileAlloc = stat.cbFile;
309 stat.attrFile = (finfo->attr & 0x37);
310
311 fsphUnixTimeToDosDate(finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
312 fsphUnixTimeToDosDate(finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
313 fsphUnixTimeToDosDate(finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
314 debug_printf( "fname %s\n", finfo->fname);
315 debug_printf( "mtime %d %s", finfo->mtime, ctime( (time_t*)&finfo->mtime));
316 debug_printf( "ftimeLastAccess %02d:%02d:%02d\n", stat.ftimeLastWrite.hours, stat.ftimeLastWrite.minutes, stat.ftimeLastWrite.twosecs*2);
317
318 ph->fsphAddFile32L(plist, &stat, name, StrLen(name), finfo, sizeof(*finfo), 0);
319 return 1;
320}
321
322static unsigned char fromhex (char c)
323{
324 if ('0' <= c && c <= '9')
325 {
326 return c - '0';
327 }
328
329 if ('A' <= c && c <= 'F')
330 {
331 return c - 'A' + 0xA;
332 }
333
334 if ('a' <= c && c <= 'f')
335 {
336 return c - 'a' + 0xA;
337 }
338
339 return 0;
340}
341
342static char tohex (unsigned char b)
343{
344 b &= 0xF;
345
346 if (b <= 9)
347 {
348 return b + '0';
349 }
350
351 return 'A' + (b - 0xA);
352}
353
354static void decryptPassword (const char *pszCrypt, char *pszPlain)
355{
356 /* A simple "decryption", character from the hex value. */
357 const char *s = pszCrypt;
358 char *d = pszPlain;
359
360 while (*s)
361 {
362 *d++ = (char)((fromhex (*s++) << 4) + fromhex (*s++));
363 }
364
365 *d++ = 0;
366}
367
368static void encryptPassword (const char *pszPlain, char *pszCrypt)
369{
370 /* A simple "encryption" encode each character as hex value. */
371 const char *s = pszPlain;
372 char *d = pszCrypt;
373
374 while (*s)
375 {
376 *d++ = tohex ((*s) >> 4);
377 *d++ = tohex (*s);
378 s++;
379 }
380
381 *d++ = 0;
382}
383
384/* accept parameters in form
385 * [filename][;name=filename]
386 */
387int initResource (Resource *pRes, NDPROPERTYHANDLE properties)
388{
389 int rc = NO_ERROR;
390 unsigned long t;
391 const CHAR * q = NULL;
392 int defaultPassword = 1;
393
394 pRes->rootlevel = 0;
395 pRes->easupport = 1;
396#ifdef HAVE_KRB5_H
397 pRes->krb5support = 1;
398#else
399 pRes->krb5support = 0;
400#endif
401 pRes->pdc = NULL;
402
403 t = 0, q = NULL;
404 rc = ph->fsphQueryStringProperty (properties, "WORKGROUP", &q, &t);
405 if (!rc && t && *q)
406 {
407 StrNCpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
408 pRes->rootlevel = 1;
409 }
410
411 t = 0, q = NULL;
412 rc = ph->fsphQueryStringProperty (properties, "SERVER", &q, &t);
413 if (!rc && t && *q)
414 {
415 StrNCpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
416 pRes->rootlevel = 2;
417 }
418
419 t = 0, q = NULL;
420 rc = ph->fsphQueryStringProperty (properties, "SHARE", &q, &t);
421 if (!rc && t && *q)
422 {
423 StrNCpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
424 pRes->rootlevel = 3;
425 }
426
427 t = 0, q = NULL;
428 rc = ph->fsphQueryStringProperty (properties, "USER", &q, &t);
429 if (!rc && t && *q)
430 {
431 StrNCpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
432 }
433
434 t = 0, q = NULL;
435 rc = ph->fsphQueryStringProperty (properties, "PASSWORD", &q, &t);
436 if (!rc && t && *q)
437 {
438 StrNCpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
439 defaultPassword = 0;
440 }
441
442 t = 0, q = NULL;
443 rc = ph->fsphQueryStringProperty (properties, "SPASSWORD", &q, &t);
444 if ( rc == NO_ERROR
445 && *q != '\0'
446 && defaultPassword)
447 {
448 char p[1024];
449 p[0] = 0;
450
451 decryptPassword (q, p);
452
453 if (*p)
454 {
455 StrNCpy(pRes->srv.password, p, sizeof(pRes->srv.password) - 1);
456
457 /* clear the plain password */
458 ph->fsphSetProperty (properties, "PASSWORD", "");
459 }
460 }
461 else
462 {
463 char c[1024];
464 encryptPassword (pRes->srv.password, c);
465
466 ph->fsphSetProperty (properties, "SPASSWORD", c);
467
468 // clear the plain password
469 ph->fsphSetProperty (properties, "PASSWORD", "");
470 }
471
472 t = 0, q = NULL;
473 rc = ph->fsphQueryStringProperty (properties, "MASTER", &q, &t);
474 if (!rc && t && *q)
475 {
476 StrNCpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
477 }
478
479 t = 0, q = NULL;
480
481 t = 0;
482 rc = ph->fsphQueryUlongProperty (properties, "MASTERTYPE", &t);
483 if (!rc)
484 {
485 if (t > 1)
486 {
487 rc = ERROR_INVALID_PARAMETER;
488 }
489 else
490 {
491 pRes->srv.ifmastergroup = t;
492 }
493 }
494
495 t = 0;
496 rc = ph->fsphQueryUlongProperty (properties, "EASUPPORT", &t);
497 if (!rc)
498 {
499 if (t > 1)
500 {
501 rc = ERROR_INVALID_PARAMETER;
502 }
503 else
504 {
505 pRes->easupport = t;
506 }
507 }
508
509 t = 0;
510 rc = ph->fsphQueryUlongProperty (properties, "CTO", &t);
511 if (!rc)
512 {
513 if (t > 600)
514 {
515 rc = ERROR_INVALID_PARAMETER;
516 }
517 else
518 {
519 pRes->cachetimeout = t;
520 }
521 }
522
523 t = 0;
524 rc = ph->fsphQueryUlongProperty (properties, "CLD", &t);
525 if (!rc)
526 {
527 if (t > 96)
528 {
529 rc = ERROR_INVALID_PARAMETER;
530 }
531 else
532 {
533 pRes->cachedepth = t;
534 }
535 }
536
537 /*
538 * Create a directory cache with expiration time and cache listings
539 * the above values come from the gui. default: timeout 10; listings: 32
540 */
541 dircache_create(&pRes->pdc, pRes->cachetimeout, pRes->cachedepth);
542
543 return rc;
544}
545
546int iftestpath(char * path)
547{
548 char * p = path;
549 if (!path)
550 {
551 return 0;
552 }
553 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
554 {
555 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
556 {
557 return 1;
558 }
559 p++;
560 }
561 return 0;
562}
563
564int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
565{
566 int rootlevel;
567 int rc = NO_ERROR;
568 if (!pRes || !path || !result)
569 {
570 return ERROR_INVALID_PARAMETER;
571 }
572 // handle special case when someone wants to test support of LFN or smth similar
573 if (iftestpath(path))
574 {
575 StrCpy(result, "\\A.+,;=[].B");
576 return NO_ERROR;
577 }
578
579 rootlevel = pRes->rootlevel;
580 if (*path == '\\') path++;
581
582 if (rootlevel < 3)
583 {
584 char * p;
585 // flag: 1 parameters changed, reconnection required, 0 do nothing
586 int newlevel = 0;
587 // use a temporary resource to test disconnection/reconnection
588 Resource tmpRes;
589 // copy exising data
590 memcpy( &tmpRes, pRes, sizeof( tmpRes));
591 // pointer to new connection fields
592 smbwrp_server * tmp = &tmpRes.srv;
593 if (rootlevel == 0)
594 {
595 p = ph->fsphStrChr(path, '\\');
596 if (!p)
597 {
598 p = path + StrLen(path);
599 }
600 if (StrLen(tmp->workgroup) != p - path
601 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
602 {
603 StrNCpy(tmp->workgroup, path, p - path);
604 tmp->workgroup[p - path] = 0;
605 newlevel = 1;
606 }
607 path = *p == '\\' ? p + 1 : p;
608 rootlevel = 1;
609 }
610 if (rootlevel == 1) // root path starts from server name
611 {
612 p = ph->fsphStrChr(path, '\\');
613 if (!p)
614 {
615 p = path + StrLen(path);
616 }
617 if (StrLen(tmp->server_name) != p - path
618 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
619 {
620 StrNCpy(tmp->server_name, path, p - path);
621 tmp->server_name[p - path] = 0;
622 newlevel = 1;
623 }
624 path = *p == '\\' ? p + 1 : p;
625 rootlevel = 2;
626 }
627 if (rootlevel == 2) // root path starts from share name
628 {
629 p = ph->fsphStrChr(path, '\\');
630 if (!p)
631 {
632 p = path + StrLen(path);
633 }
634 if (StrLen(tmp->share_name) != (p - path)
635 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
636 {
637 StrNCpy(tmp->share_name, path, p - path);
638 tmp->share_name[p - path] = 0;
639 newlevel = 1;
640 }
641 path = *p == '\\' ? p + 1 : p;
642 }
643 if (newlevel)
644 {
645 // reconnect to server here, first test new connection
646 cli_state* tmp_cli = NULL;
647 rc = smbwrp_connect( &tmpRes, &tmp_cli);
648 if (!rc)
649 {
650 // new connection is ok, disconnect old one
651 cli_state* cli = pConn->cli;
652 smbwrp_disconnect( pRes, cli);
653 // save tmp data structure
654 memcpy( pRes, &tmpRes, sizeof( tmpRes));
655 // save new connection handle
656 pConn->cli = tmp_cli;
657 }
658 }
659 }
660
661 StrCpy(result, "\\");
662 StrNCat(result, path, CCHMAXPATH);
663
664 return rc;
665}
666
667
668// -------------------------------------------------------------
669
670/* check if the requested resource is available */
671static int checkMountResource( Resource* pRes)
672{
673 int rc;
674 unsigned long action;
675 cli_state* cli = NULL;
676 smbwrp_file file;
677
678 debug_printf("checkMountResource in tid#%d\n", _gettid());
679 rc = smbwrp_connect( pRes, &cli);
680/* changed to real error codes SCS
681 if (rc)
682 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_ACCESS_DENIED); */
683 switch (rc) {
684 case 0:
685 rc = NO_ERROR;
686 break;
687 case 1:
688 case 10:
689 case 11:
690 rc = ERROR_BAD_NET_NAME;
691 break;
692 case 2:
693 rc = ERROR_INIT_ROUTINE_FAILED;
694 break;
695 case 3:
696 rc = ERROR_BAD_NET_RESP;
697 break;
698 case 4:
699 rc = ERROR_NETWORK_BUSY;
700 break;
701 case 6:
702 rc = ERROR_NETWORK_ACCESS_DENIED;
703 break;
704 case 7:
705 rc = ERROR_BAD_NETPATH;
706 break;
707 default:
708 rc = ERROR_UNEXP_NET_ERR;
709 break;
710 } /* endswitch */
711
712 smbwrp_disconnect( pRes, cli);
713
714 return rc;
715}
716
717int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
718{
719 int rc = NO_ERROR;
720 unsigned long objany = OBJ_ANY;
721 Resource *pRes = NULL;
722
723 debuglocal(9,"NdpMountResource in\n");
724
725 // init code
726 smbwrp_init();
727
728 /* since samba plugin support only 1 type of resources we do not need */
729 /* to check what the found type really is */
730 pRes = malloc( sizeof(Resource));
731 if (pRes == NULL)
732 {
733 rc = ERROR_NOT_ENOUGH_MEMORY;
734 }
735 else
736 {
737 MemSet(pRes, 0, sizeof(Resource));
738 //pRes->objany = objany;
739 // parse init string
740 rc = initResource (pRes, properties);
741 // try to connect to resource (check type) only if thread!=1, so ndctl startup
742 // is not slowed down by network connections.
743 // ndctl does mounting on main thread (#1)
744 // nd/ndpm do not use main thread
745 if (!rc && _gettid()!=1)
746 rc = checkMountResource( pRes);
747 if (!rc)
748 {
749 // store resource data
750 *presource = (HRESOURCE)pRes;
751 }
752 else
753 {
754 free(pRes);
755 }
756 }
757 debuglocal(9,"NdpMountResource rc=%d\n", rc);
758 return rc;
759}
760
761// -------------------------------------------------------------
762
763int APIENTRY NdpFreeResource (HRESOURCE resource)
764{
765 Resource *pRes = (Resource *)resource;
766 dircache_delete(pRes->pdc);
767 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
768 free(pRes);
769 debuglocal(9,"NdpFreeResource %d\n", NO_ERROR);
770 return NO_ERROR;
771}
772
773// -------------------------------------------------------------
774
775int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
776{
777 Resource *pRes = (Resource *)resource;
778 Resource *pRes2 = (Resource *)resource2;
779 int rc = ND_RSRC_DIFFERENT;
780
781 debuglocal(9,"NdpRsrcCompare in\n");
782 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
783 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
784 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
785 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
786 {
787 // resources are equal
788 rc = ND_RSRC_EQUAL;
789 }
790
791 debuglocal(9,"NdpRsrcCompare %d\n", rc);
792
793 return rc;
794}
795
796int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
797{
798 // do nothing
799 debuglocal(9,"NdpRsrcUpdate %d\n", NO_ERROR);
800 return NO_ERROR;
801}
802
803int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
804{
805 Resource *pRes = (Resource *)resource;
806 int rc = NO_ERROR;
807 char s[4096];
808
809 debuglocal(9,"NdpRsrcQueryInfo in\n");
810
811 switch (pRes->rootlevel)
812 {
813 case 0:
814 {
815 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
816 } break;
817 case 1:
818 {
819 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
820 } break;
821 case 2:
822 {
823 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);
824 } break;
825 default:
826 {
827 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);
828 } break;
829 }
830 *poutlen = StrLen(s) + 1;
831 if (*poutlen > insize)
832 {
833 rc = ERROR_BUFFER_OVERFLOW;
834 }
835 else
836 {
837 MemCpy(pdata, s, *poutlen);
838 }
839
840 debuglocal(9,"NdpRsrcQueryInfo %d\n", rc);
841
842 return rc;
843}
844
845int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
846{
847 ULONG ulDummy = 0;
848 /* just return the resource info string */
849 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
850}
851
852int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
853{
854 Resource *pRes = (Resource *)resource;
855 int rc = NO_ERROR, rc1;
856 unsigned long action = 0;
857 smbwrp_file file;
858 cli_state* cli = NULL;
859 FSALLOCATE fsa;
860
861 debuglocal(9,"NdpRsrcQueryFSAllocate %08x\n", pfsa);
862
863 if (!pfsa)
864 {
865 return NO_ERROR;
866 }
867
868 debug_printf("checkMountResource in tid#%d\n", _gettid());
869 rc = smbwrp_connect( pRes, &cli);
870 if (rc)
871 {
872 debuglocal(9,"NdpCreateConnection failed rc=%d\n", rc);
873 pfsa->cSectorUnit = 1;
874 pfsa->cUnit = 123456;
875 pfsa->cUnitAvail = 123456;
876 pfsa->cbSector = 2048;
877 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_ACCESS_DENIED);
878 return rc;
879 }
880
881 rc = smbwrp_dskattr( cli, &fsa);
882 if (rc)
883 {
884 pfsa->cSectorUnit = 1;
885 pfsa->cUnit = 123456;
886 pfsa->cUnitAvail = 123456;
887 pfsa->cbSector = 2048;
888 //rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
889 }
890 else
891 {
892 pfsa->cSectorUnit = fsa.cSectorUnit;
893 pfsa->cUnit = fsa.cUnit;
894 pfsa->cUnitAvail = fsa.cUnitAvail;
895 pfsa->cbSector = fsa.cbSector;
896 }
897
898 smbwrp_disconnect( pRes, cli);
899
900 debuglocal(9,"NdpRsrcQueryFSAllocate %d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
901 return rc;
902}
903
904// -------------------------------------------------------------
905
906int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
907{
908 int rc = 0;
909 Resource * pRes = (Resource *)resource;
910 unsigned long action;
911 Connection *pConn = NULL;
912
913 debuglocal(9,"NdpCreateConnection in\n");
914
915 pConn = malloc( sizeof(Connection));
916 if (pConn == NULL)
917 {
918 rc = ERROR_NOT_ENOUGH_MEMORY;
919 }
920 if (rc)
921 {
922 debuglocal(9,"NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
923 return rc;
924 }
925 MemSet(pConn, 0, sizeof(Connection));
926 pConn->pRes = pRes;
927 pConn->file.fd = -1;
928
929 debuglocal(9,"NdpCreateConnection send CONNECT\n");
930 rc = smbwrp_connect( pRes, &pConn->cli);
931 if (rc)
932 {
933 free(pConn);
934 pConn = NULL;
935 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_INVALID_PARAMETER);
936 }
937
938 *pconn = (HCONNECTION)pConn;
939 debuglocal(9,"NdpCreateConnection [%p] %d\n", pConn, rc);
940 return rc;
941}
942
943// -------------------------------------------------------------
944
945int APIENTRY NdpFreeConnection (HCONNECTION conn)
946{
947 Connection *pConn = (Connection *)conn;
948 Resource *pRes = pConn->pRes;
949 int rc;
950
951 debuglocal(9,"NdpFreeConnection in [%p]\n", pConn);
952 if (pConn->file.fd >= 0)
953 {
954 rc = smbwrp_close( pConn->cli, &pConn->file);
955 pConn->file.fd = -1;
956 }
957
958 smbwrp_disconnect( pRes, pConn->cli);
959
960 free(pConn);
961 debuglocal(9,"NdpFreeConnection %d\n", NO_ERROR);
962 return NO_ERROR;
963}
964
965// -------------------------------------------------------------
966
967/*
968 * NdpQueryPathInfo is the most important function :) netdrive always calls
969 * the function before every operation to find out the path status: does it exist, is it a file, does a
970 * parent directory exist, etc.
971 * Plugin must return one of the following error codes:
972 * NO_ERROR - path exists and the path information have been successfully retrieved.
973 * ERROR_FILE_NOT_FOUND - all but the last component of the path exist and the
974 * path without the last component is a directory. dir1_ok\dir2_ok\does_not_exist.
975 * the wildcard can not exist, so the plugin returns FILE_NOT_FOUND, if the parent
976 * directory exist.
977 * ERROR_PATH_NOT_FOUND - any of not last path components does not exist, or all
978 * but the last component exist and is a file: \dir_ok\dir2_ok\file_ok\non_existing.
979 * ERROR_REM_NOT_LIST - resource is temporarily unavailable for some reasons.
980 * Any other error codes means an internal plugin error, not related to the status
981 * of the path queried.
982 */
983int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
984{
985 Connection *pConn = (Connection *)conn;
986 Resource *pRes = pConn->pRes;
987 smbwrp_fileinfo finfo;
988 int rc = 0;
989 unsigned long action;
990 char path[CCHMAXPATH+1] = {0};
991 int retry = 0;
992
993 debuglocal(9,"NdpQueryPathInfo in [%p] <%s>, retry = %d\n", pConn, szPath, retry);
994
995 // is wildcard is specified, we suppose parent dir exist, so exit immediately
996 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
997 {
998 return ERROR_FILE_NOT_FOUND;
999 }
1000
1001
1002 do {
1003 /* First check if there is information in the directory cache. */
1004 unsigned long ulAge = 0;
1005 if (dircache_find_path(pRes->pdc, szPath, &finfo, &ulAge))
1006 {
1007 if (ulAge <= 15) /* @todo configurable. */
1008 {
1009 rc = NO_ERROR;
1010 finfo.easize = -1;
1011 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1012 break;
1013 }
1014 }
1015
1016 rc = pathparser(pRes, pConn, szPath, path);
1017 debuglocal(9,"NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
1018 switch (rc)
1019 {
1020 case NO_ERROR :
1021 case ERROR_FILE_NOT_FOUND:
1022 case ERROR_PATH_NOT_FOUND:
1023 case ERROR_ACCESS_DENIED:
1024 case ERROR_INVALID_PARAMETER:
1025 {
1026 break;
1027 }
1028 default :
1029 {
1030 rc = ERROR_PATH_NOT_FOUND;
1031 }
1032 }
1033 if (rc)
1034 {
1035 break;
1036 }
1037 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1038 debuglocal(9,"NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
1039 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1040 if (rc)
1041 {
1042 // remote server not available for first time?
1043 if (rc == ERROR_REM_NOT_LIST && retry == 0)
1044 {
1045 // free current cli resources
1046 smbwrp_disconnect( pRes, pConn->cli);
1047 // reconnect
1048 smbwrp_connect( pRes, &pConn->cli);
1049 // try file list again
1050 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1051 debuglocal(9,"NdpQueryPathInfo remote connection lost, retry rc = %d\n", rc);
1052 }
1053 switch (rc)
1054 {
1055 case NO_ERROR :
1056 case ERROR_FILE_NOT_FOUND:
1057 case ERROR_PATH_NOT_FOUND:
1058 case ERROR_ACCESS_DENIED:
1059 case ERROR_INVALID_PARAMETER:
1060 case ERROR_REM_NOT_LIST:
1061 break;
1062 default :
1063 {
1064 rc = ERROR_PATH_NOT_FOUND;
1065 }
1066 }
1067 }
1068 else
1069 {
1070 finfo.easize = -1;
1071 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1072 }
1073 if (rc == ERROR_FILE_NOT_FOUND)
1074 {
1075 // now try the upper path
1076 char * p = ph->fsphStrChr(finfo.fname, '\\');
1077 if (p && p > finfo.fname)
1078 {
1079 *p = 0;
1080 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1081 if (rc)
1082 {
1083 debuglocal(9,"NdpQueryPathInfo upper path in <%s>, retry = %d\n", finfo.fname, retry);
1084 rc = rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER;
1085 }
1086 }
1087 }
1088 } while (0);
1089 debuglocal(9,"NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
1090
1091 return rc;
1092}
1093
1094// -------------------------------------------------------------
1095
1096int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1097{
1098 Connection *pConn = (Connection *)conn;
1099 Resource *pRes = pConn->pRes;
1100 int rc = NO_ERROR, count = 0;
1101 unsigned long action;
1102 char *mask = "*";
1103 char dir[CCHMAXPATH+1] = {0};
1104 char path[CCHMAXPATH+1] = {0};
1105 smbwrp_fileinfo * data;
1106 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1107 filelist_state state;
1108 char * p;
1109
1110 debug_printf("NdpFindStart in [%p]\n", pConn);
1111
1112 StrNCpy(dir, szPath, sizeof(dir) - 1);
1113 if (pel)
1114 {
1115 mask = pel->name;
1116 dir[StrLen(szPath) - pel->length] = 0;
1117 }
1118 action = StrLen(dir) - 1;
1119 if (dir[action] == '\\')
1120 {
1121 dir[action] = 0;
1122 }
1123 rc = pathparser(pRes, pConn, dir, path);
1124 if (rc)
1125 {
1126 return rc;
1127 }
1128 action = StrLen(path) - 1;
1129 if (path[action] != '\\')
1130 {
1131 StrNCat(path, "\\", sizeof(path) - 1);
1132 }
1133 StrCpy(dir, path);
1134 StrNCat(path, mask, sizeof(path) - 1);
1135
1136 // this structure will be used by libsmb callbacks, so we store here all we need
1137 // to fill netdrive structures
1138 state.pConn = pConn;
1139 state.plist = plist;
1140 state.ulAttribute = ulAttribute;
1141 strcpy( state.dir, dir);
1142 strcpy( state.dir_mask, mask);
1143 strcpy( state.mask, path);
1144 state.fullpath = szPath;
1145 /* This plugin always reads a complete directory listing and filters results
1146 * using actual mask (state.dir_mask) in getfindinfoL.
1147 * May be this was a workaround for some server bug.
1148 * If this will be changed, then directory listing cache must be changed too,
1149 * and must remember the mask, which was used to obtain a listing.
1150 * Now the directory cache saves complete directory listings and then uses them to find
1151 * information about single files.
1152 * However, with a directory cache, it is probably faster to get a full listing and
1153 * then use it to obtain info about separate files than to perform a network
1154 * list query operation using actual wild cards for each file. Some application,
1155 * for example OpenOffice, do this.
1156 */
1157 p = getlastslash(state.mask);
1158 if (p)
1159 {
1160 *(p + 1) = '*';
1161 *(p + 2) = 0;
1162 }
1163 else
1164 {
1165 strcpy(state.mask, "\\*");
1166 }
1167 debuglocal(9,"NdpFindStart: dir [%s], dir_mask [%s], mask [%s], szPath [%s]\n",
1168 state.dir, state.dir_mask, state.mask, state.fullpath);
1169 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1170 // we need to handle reconnection also here, because NdpQueryPathInfo
1171 // could be called with '*' and exit then immediately (without calling libsmb)
1172 if (rc == ERROR_REM_NOT_LIST)
1173 {
1174 // free current cli resources
1175 smbwrp_disconnect( pRes, pConn->cli);
1176 // reconnect
1177 smbwrp_connect( pRes, &pConn->cli);
1178 // try file list again next loop
1179 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1180 debuglocal(9,"NdpFindStart remote connection lost, retry rc = %d\n", rc);
1181 }
1182
1183 debuglocal(9,"NdpFindStart <%s> (%s) cnt %d %d\n", szPath, path, count, rc);
1184
1185 return rc;
1186}
1187
1188int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1189{
1190// debuglocal(9,"NdpDeletePathInfo %d\n", 0);
1191 return NO_ERROR;
1192}
1193
1194int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1195{
1196 debuglocal(9,"NdpRefresh <%s> %d\n", path, 0);
1197 return NO_ERROR;
1198}
1199
1200int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1201{
1202 // The plugin do not have to deallocate anything
1203 // because resource data did not contain any pointers
1204 // to plugins data.
1205 // Data stored by fsphSetResourceData will be
1206 // deallocated by NetDrive.
1207
1208 debuglocal(9,"NdpDicardresourceData %d\n", 0);
1209 return NO_ERROR;
1210}
1211
1212int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1213{
1214 Connection *pConn = (Connection *)conn;
1215 Resource *pRes = pConn->pRes;
1216 int rc = 0;
1217 unsigned long action;
1218 char path[CCHMAXPATH+1] = {0};
1219 smbwrp_fileinfo finfo;
1220
1221 debug_printf("NdpSetPathInfo in [%p]\n", pConn);
1222
1223 // delete the dir cache
1224 dircache_invalidate(szPathName, pRes->pdc, 1);
1225
1226 do {
1227 rc = pathparser(pRes, pConn, szPathName, path);
1228 if (rc)
1229 {
1230 break;
1231 }
1232
1233 MemSet(&finfo, 0, sizeof(finfo));
1234
1235 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1236 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
1237 finfo.attr = pfi->stat.attrFile & 0x37;
1238 rc = smbwrp_setattr(pConn->cli, &finfo);
1239 } while (0);
1240 debuglocal(9,"NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
1241
1242 return rc;
1243}
1244
1245int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1246{
1247 int rc = 0;
1248 FEA * pfea;
1249 FEA * pfeadest;
1250 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1251
1252 size = pFEASrc->cbList;
1253 pfea = pFEASrc->list;
1254 pfeadest = pFEAList->list;
1255 dsize = pFEAList->cbList;
1256//debuglocal(9,"buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1257 while (done < size)
1258 {
1259 char * name = (char *)(pfea + 1);
1260 int insert = 1;
1261 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1262 {
1263 GEA * pgea = pGEAList->list;
1264 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1265 insert = 0;
1266 while (done < size)
1267 {
1268//debuglocal(9,"comp <%s> <%s>\n", name, pgea->szName);
1269 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1270 {
1271 insert = 1;
1272 break;
1273 }
1274 done += pgea->cbName + 2;
1275 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1276 }
1277 }
1278 if (insert)
1279 {
1280 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1281 if (ddone <= dsize)
1282 {
1283 pfeadest->cbName = pfea->cbName;
1284 pfeadest->cbValue = pfea->cbValue;
1285 pfeadest->fEA = 0;
1286 StrCpy((char *)(pfeadest + 1), name);
1287 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1288 pfeadest = (FEA *)((char *)pFEAList + ddone);
1289 }
1290 }
1291 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1292//debuglocal(9,"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);
1293 pfea = (FEA *)((char *)pFEASrc + done);
1294 }
1295 pFEAList->cbList = ddone;
1296 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1297 {
1298 rc = ERROR_BUFFER_OVERFLOW;
1299 }
1300 debuglocal(9,"buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1301 return rc;
1302}
1303
1304int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1305{
1306 Connection *pConn = (Connection *)conn;
1307 Resource *pRes = pConn->pRes;
1308 int rc = 0;
1309 unsigned long action;
1310 char * path = NULL;
1311 FEALIST * pFEASrc;
1312 NDDATABUF fdata = {0};
1313 smbwrp_fileinfo *finfo;
1314 char pBuffer[64*1024];
1315
1316 if (!pfi || !pfi->pszName || !pFEAList)
1317 {
1318 return ERROR_EAS_NOT_SUPPORTED;
1319 }
1320 if (!pRes->easupport)
1321 {
1322 return ERROR_EAS_NOT_SUPPORTED;
1323 }
1324
1325 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1326 if (rc || !fdata.ulSize || !fdata.pData)
1327 {
1328 debuglocal(9,"NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1329 return ERROR_EAS_NOT_SUPPORTED;
1330 }
1331 finfo = (smbwrp_fileinfo *)fdata.pData;
1332 path = finfo->fname;
1333
1334 debuglocal(9,"NdpEAQuery in [%p] <%s> %08x %d\n", pConn, path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1335
1336 do {
1337 rc = smbwrp_listea( pConn->cli, path, pBuffer, sizeof( pBuffer));
1338 pFEASrc = (FEALIST*) pBuffer;
1339 if (rc)
1340 {
1341 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1342 switch (rc)
1343 {
1344 case ERROR_FILE_NOT_FOUND :
1345 case ERROR_PATH_NOT_FOUND :
1346 {
1347 pFEAList->cbList = sizeof(pFEAList->cbList);
1348 rc = NO_ERROR;
1349 } break;
1350 case ERROR_BUFFER_OVERFLOW :
1351 {
1352 pFEAList->cbList = pFEASrc->cbList;
1353 } break;
1354 default :
1355 {
1356 rc = ERROR_EAS_NOT_SUPPORTED;
1357 }
1358 }
1359 }
1360 else
1361 {
1362 rc = buildFEALIST((FEALIST *)pFEASrc, pGEAList, pFEAList);
1363 }
1364 } while (0);
1365 debuglocal(9,"NdpEAQuery <%s> %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList);
1366
1367 return rc;
1368}
1369
1370int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1371{
1372 Connection *pConn = (Connection *)conn;
1373 Resource *pRes = pConn->pRes;
1374 int rc = 0;
1375 char * path;
1376 unsigned long action;
1377 NDDATABUF fdata = {0};
1378 smbwrp_fileinfo *finfo;
1379
1380 debuglocal(9,"NdpEASet in [%p]\n", pConn);
1381
1382 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1383 {
1384 return ERROR_EAS_NOT_SUPPORTED;
1385 }
1386 if (!pRes->easupport)
1387 {
1388 return ERROR_EAS_NOT_SUPPORTED;
1389 }
1390
1391 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1392 if (rc || !fdata.ulSize || !fdata.pData)
1393 {
1394 debuglocal(9,"NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1395 return ERROR_EAS_NOT_SUPPORTED;
1396 }
1397 finfo = (smbwrp_fileinfo *)fdata.pData;
1398 path = finfo->fname;
1399
1400 do {
1401 // got FEA there
1402 FEA * pfea;
1403 unsigned long done = sizeof(long);
1404 pfea = pFEAList->list;
1405 while (done < pFEAList->cbList)
1406 {
1407 rc = smbwrp_setea(pConn->cli, path, (char*)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1408 if (rc)
1409 {
1410 break;
1411 }
1412 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1413 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1414 }
1415 } while (0);
1416 debuglocal(9,"NdpEASet %d\n", rc);
1417
1418 return rc;
1419}
1420
1421int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1422{
1423 Connection *pConn = (Connection *)conn;
1424 Resource *pRes = pConn->pRes;
1425 int rc = 0;
1426 unsigned long action;
1427 char * path = NULL;
1428 FEALIST * pfealist;
1429 NDDATABUF fdata = {0};
1430 smbwrp_fileinfo *finfo;
1431 char pBuffer[64*1024];
1432 int easize;
1433
1434 if (!pfi || !pulEASize)
1435 {
1436 return ERROR_EAS_NOT_SUPPORTED;
1437 }
1438 if (!pRes->easupport)
1439 {
1440 return ERROR_EAS_NOT_SUPPORTED;
1441 }
1442
1443 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1444 if (rc || !fdata.ulSize || !fdata.pData)
1445 {
1446 debuglocal(9,"NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1447 return ERROR_EAS_NOT_SUPPORTED;
1448 }
1449 finfo = (smbwrp_fileinfo *)fdata.pData;
1450 easize = finfo->easize;
1451 finfo->easize = -1;
1452 path = finfo->fname;
1453 if (easize >= 0)
1454 {
1455 *pulEASize = easize;
1456 debuglocal(9,"NdpEASize <%s> cached %d\n", path, easize);
1457 return NO_ERROR;
1458 }
1459
1460 debuglocal(9,"NdpEASize in [%p] <%s>\n", pConn, path);
1461
1462 do {
1463 rc = smbwrp_listea(pConn->cli, path, pBuffer, sizeof( pBuffer));
1464 pfealist = (FEALIST*)pBuffer;
1465 if (rc)
1466 {
1467 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1468 switch (rc)
1469 {
1470 case ERROR_FILE_NOT_FOUND :
1471 case ERROR_PATH_NOT_FOUND :
1472 {
1473 pfealist->cbList = sizeof(pfealist->cbList);
1474 } /* Fall through */
1475 case ERROR_BUFFER_OVERFLOW :
1476 {
1477 rc = NO_ERROR;
1478 } break;
1479 default :
1480 {
1481 rc = ERROR_EAS_NOT_SUPPORTED;
1482 }
1483 }
1484 }
1485 *pulEASize = pfealist->cbList;
1486 } while (0);
1487 debuglocal(9,"NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
1488
1489 return rc;
1490}
1491
1492int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1493{
1494 Connection *pConn = (Connection *)conn;
1495 Resource *pRes = pConn->pRes;
1496 int rc = 0;
1497 unsigned long action;
1498 char path[CCHMAXPATH+1] = {0};
1499
1500 debuglocal(9,"NdpSetCurrentDir in [%p]\n", pConn);
1501
1502 do {
1503 rc = pathparser(pRes, pConn, szPath, path);
1504 if (rc)
1505 {
1506 break;
1507 }
1508
1509 rc = smbwrp_chdir(&pRes->srv, pConn->cli, path);
1510 } while (0);
1511 debuglocal(9,"NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
1512
1513 return rc;
1514}
1515
1516int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1517{
1518 debuglocal(9,"NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1519 return ERROR_CANNOT_COPY;
1520}
1521
1522int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1523{
1524 debuglocal(9,"NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1525 return ERROR_CANNOT_COPY;
1526}
1527
1528int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1529{
1530 Connection *pConn = (Connection *)conn;
1531 Resource *pRes = pConn->pRes;
1532 int rc = 0;
1533 unsigned long action;
1534 char path[CCHMAXPATH+1] = {0};
1535
1536 debuglocal(9,"NdpForceDelete in [%p]\n", pConn);
1537
1538 dircache_invalidate(szFile, pRes->pdc, 1);
1539
1540 do {
1541 rc = pathparser(pRes, pConn, szFile, path);
1542 if (rc)
1543 {
1544 break;
1545 }
1546
1547 rc = smbwrp_unlink(pConn->cli, path);
1548 } while (0);
1549 debuglocal(9,"NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
1550
1551 return rc;
1552}
1553
1554int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1555{
1556 Connection *pConn = (Connection *)conn;
1557 Resource *pRes = pConn->pRes;
1558 int rc = 0;
1559 unsigned long action;
1560 char path[CCHMAXPATH+1] = {0};
1561
1562 debuglocal(9,"NdpCreateDir in [%p]\n", pConn);
1563
1564 dircache_invalidate(szDirName, pRes->pdc, 1);
1565
1566 do {
1567 rc = pathparser(pRes, pConn, szDirName, path);
1568 if (rc)
1569 {
1570 break;
1571 }
1572
1573 rc = smbwrp_mkdir(pConn->cli, path);
1574 } while (0);
1575 debuglocal(9,"NdpCreateDir <%s> (%s) %d\n", szDirName, path, rc);
1576
1577 return rc;
1578}
1579
1580int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1581{
1582 Connection *pConn = (Connection *)conn;
1583 Resource *pRes = pConn->pRes;
1584 int rc = 0;
1585 unsigned long action;
1586 char path[CCHMAXPATH+1] = {0};
1587
1588 debuglocal(9,"NdpDeleteDir in [%p]\n", pConn);
1589
1590 dircache_invalidate(szDir, pRes->pdc, 1);
1591
1592 do {
1593 rc = pathparser(pRes, pConn, szDir, path);
1594 if (rc)
1595 {
1596 break;
1597 }
1598
1599 rc = smbwrp_rmdir(pConn->cli, path);
1600 } while (0);
1601 debuglocal(9,"NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
1602
1603 return rc;
1604}
1605
1606int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1607{
1608 Connection *pConn = (Connection *)conn;
1609 Resource *pRes = pConn->pRes;
1610 int rc = 0;
1611 unsigned long action;
1612 char src[CCHMAXPATH+1] = {0};
1613 int l1, l2;
1614 char * p = szDst;
1615
1616 debuglocal(9,"NdpMove in [%p] from <%s> to <%s>\n", pConn, szSrc, szDst);
1617
1618 dircache_invalidate(szSrc, pRes->pdc, 1);
1619 dircache_invalidate(szDst, pRes->pdc, 1);
1620
1621 do
1622 {
1623 rc = pathparser(pRes, pConn, szSrc, src);
1624 if (rc)
1625 {
1626 break;
1627 }
1628 l1 = StrLen(szSrc);
1629 l2 = StrLen(src);
1630 if (l1 > l2)
1631 {
1632 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1633 {
1634 // the file moved accross different shares or servers or workgroups
1635 rc = ERROR_WRITE_PROTECT;
1636 break;
1637 }
1638 p = szDst + l1 - l2 + 1;
1639 }
1640 //pConn->mem[CCHMAXPATH + 1] = '\\';
1641 rc = smbwrp_rename(pConn->cli, src, p);
1642 } while (0);
1643 debuglocal(9,"NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
1644
1645 return rc;
1646}
1647
1648int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1649{
1650 debuglocal(9,"NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1651 return ERROR_WRITE_PROTECT;
1652}
1653
1654
1655int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1656{
1657 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1658}
1659
1660int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1661{
1662 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1663}
1664
1665int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1666{
1667 Resource *pRes = pConn->pRes;
1668 unsigned long action;
1669 int rc = 0;
1670 char path[CCHMAXPATH+1] = {0};
1671
1672 debuglocal(9,"smbopen in [%p] %d\n", pConn, pConn->file.fd);
1673
1674 if (flags & O_CREAT)
1675 {
1676 dircache_invalidate(szFileName, pRes->pdc, 1);
1677 }
1678 do {
1679 if (pConn->file.fd > 0)
1680 {
1681 rc = ERROR_TOO_MANY_OPEN_FILES;
1682 break;
1683 }
1684
1685 rc = pathparser(pRes, pConn, szFileName, path);
1686 if (rc)
1687 {
1688 break;
1689 }
1690
1691 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1692 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1693 flags |= O_BINARY;
1694 switch (ulOpenMode & 3)
1695 {
1696 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1697 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1698 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1699 default : flags |= O_RDWR;
1700 }
1701 pConn->file.openmode = flags;
1702 pConn->file.openattr = ulAttribute & 0x37;
1703 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1704 rc = smbwrp_open(pConn->cli, &pConn->file);
1705 } while (0);
1706 debuglocal(9,"smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
1707 if (!rc && pFEAList)
1708 {
1709 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1710 debuglocal(9,"smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1711 }
1712
1713 return rc;
1714}
1715
1716int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1717{
1718 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1719}
1720
1721int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1722{
1723 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1724}
1725
1726int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1727{
1728// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1729 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1730}
1731
1732int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1733{
1734 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1735}
1736
1737int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1738{
1739 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1740 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1741}
1742
1743int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1744{
1745 Connection *pConn = (Connection *)conn;
1746 Resource *pRes = pConn->pRes;
1747 int rc = 0;
1748 unsigned long action;
1749
1750 smbwrp_fileinfo finfo;
1751 char path[CCHMAXPATH+1] = {0};
1752
1753 debuglocal(9,"NdpSetFileAttribute in [%p]\n", pConn);
1754 do {
1755 rc = pathparser(pRes, pConn, szFileName, path);
1756 if (rc)
1757 {
1758 break;
1759 }
1760
1761 MemSet(&finfo, 0, sizeof(finfo));
1762 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1763 finfo.attr = usAttr & 0x37;
1764 rc = smbwrp_setattr(pConn->cli, &finfo);
1765 } while (0);
1766 debuglocal(9,"NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
1767
1768 return rc;
1769}
1770
1771int APIENTRY NdpFlush (HRESOURCE resource)
1772{
1773 debuglocal(9,"NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1774 return ERROR_NOT_SUPPORTED;
1775}
1776
1777// Called when a new thread will call the plugin. Allows to do per thread init, like disable signals.
1778#define ND_PL_INIT_THREAD 0xFFFF0000
1779
1780int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1781{
1782 if (function == ND_PL_INIT_THREAD)
1783 {
1784 smbwrp_initthread();
1785 debuglocal(9, "NdpIOCTL init thread\n");
1786 return NO_ERROR;
1787 }
1788
1789 debuglocal(9,"NdpIOCTL <%s> %d\n", path, function);
1790
1791 if (in && insize > 4096)
1792 {
1793 char out[4096];
1794 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1795 *poutlen = strlen(out);
1796 strcpy (in, out);
1797 return NO_ERROR;
1798 }
1799
1800 return ERROR_NOT_SUPPORTED;
1801}
1802
1803int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1804{
1805 Connection *pConn = (Connection *)conn;
1806 Resource *pRes = pConn->pRes;
1807 int rc = 0;
1808 unsigned long action;
1809 smbwrp_fileinfo finfo;
1810
1811 debug_printf("NdpFileQueryInfo in [%p]\n", pConn);
1812 do {
1813 if (pConn->file.fd < 0 || !*pConn->file.fname)
1814 {
1815 rc = ERROR_INVALID_HANDLE;
1816 break;
1817 }
1818 StrNCpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
1819 rc = smbwrp_fgetattr(pConn->cli, &pConn->file, &finfo);
1820 if (!rc)
1821 {
1822 finfo.easize = -1;
1823 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1824 }
1825 } while (0);
1826 debuglocal(9,"NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
1827
1828 return rc;
1829}
1830
1831int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1832{
1833 Connection *pConn = (Connection *)conn;
1834 Resource *pRes = pConn->pRes;
1835 int rc = 0;
1836 unsigned long action;
1837 char pBuffer[64*1024];
1838 FEALIST * pFEASrc;
1839
1840 if (!pFEAList)
1841 {
1842 return ERROR_EAS_NOT_SUPPORTED;
1843 }
1844 if (!pRes->easupport)
1845 {
1846 return ERROR_EAS_NOT_SUPPORTED;
1847 }
1848
1849 debuglocal(9,"NdpFileEAQuery in [%p] <%s>/%d pGEAList=%08x\n", pConn, pConn->file.fname, pConn->file.fd, pGEAList);
1850 do {
1851 if (pConn->file.fd < 0)
1852 {
1853 rc = ERROR_INVALID_HANDLE;
1854 break;
1855 }
1856 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof( pBuffer));
1857 pFEASrc = (FEALIST *) pBuffer;
1858 if (rc)
1859 {
1860 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1861 switch (rc)
1862 {
1863 case ERROR_FILE_NOT_FOUND :
1864 case ERROR_PATH_NOT_FOUND :
1865 {
1866 pFEAList->cbList = sizeof(pFEAList->cbList);
1867 rc = NO_ERROR;
1868 } break;
1869 case ERROR_BUFFER_OVERFLOW :
1870 {
1871 pFEAList->cbList = pFEASrc->cbList;
1872 } break;
1873 default :
1874 {
1875 rc = ERROR_EAS_NOT_SUPPORTED;
1876 }
1877 }
1878 }
1879 else
1880 {
1881 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1882 }
1883 } while (0);
1884 debuglocal(9,"NdpFileEAQuery out <%s>/%d pFEASrc->cbList=%d pFEAList->cbList=%d rc=%d\n", pConn->file.fname, pConn->file.fd, pFEASrc->cbList, pFEAList->cbList, rc);
1885
1886 return rc;
1887}
1888
1889int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1890{
1891 Connection *pConn = (Connection *)conn;
1892 Resource *pRes = pConn->pRes;
1893 int rc = 0;
1894 unsigned long action;
1895
1896 debuglocal(9,"NdpFileEASet in [%p]\n", pConn);
1897
1898 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1899 {
1900 return ERROR_EAS_NOT_SUPPORTED;
1901 }
1902 if (!pRes->easupport)
1903 {
1904 return ERROR_EAS_NOT_SUPPORTED;
1905 }
1906
1907 do {
1908 // got FEA there
1909 FEA * pfea;
1910 unsigned long done = sizeof(long);
1911 if (pConn->file.fd < 0)
1912 {
1913 rc = ERROR_INVALID_HANDLE;
1914 break;
1915 }
1916
1917 pfea = pFEAList->list;
1918 while (done < pFEAList->cbList)
1919 {
1920 rc = smbwrp_fsetea(pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1921 if (rc)
1922 {
1923 break;
1924 }
1925 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1926 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1927 }
1928
1929 } while (0);
1930 debuglocal(9,"NdpFileEASet %d\n", rc);
1931
1932 return rc;
1933}
1934
1935int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1936{
1937 Connection *pConn = (Connection *)conn;
1938 Resource *pRes = pConn->pRes;
1939 int rc = 0;
1940 unsigned long action;
1941 char path[CCHMAXPATH+1] = {0};
1942 FEALIST * pFEAList;
1943 char pBuffer[64*1024];
1944
1945 if (!pulEASize)
1946 {
1947 return ERROR_EAS_NOT_SUPPORTED;
1948 }
1949 if (!pRes->easupport)
1950 {
1951 return ERROR_EAS_NOT_SUPPORTED;
1952 }
1953
1954 debuglocal(9,"NdpFileEASize in [%p] <%s>/%d \n", pConn, pConn->file.fname, pConn->file.fd);
1955 do {
1956 if (pConn->file.fd < 0)
1957 {
1958 rc = ERROR_INVALID_HANDLE;
1959 break;
1960 }
1961 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof(pBuffer));
1962 pFEAList = (FEALIST*) pBuffer;
1963 if (rc)
1964 {
1965 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1966 switch (rc)
1967 {
1968 case ERROR_FILE_NOT_FOUND :
1969 case ERROR_PATH_NOT_FOUND :
1970 {
1971 pFEAList->cbList = sizeof(pFEAList->cbList);
1972 } /* Fall through */
1973 case ERROR_BUFFER_OVERFLOW :
1974 {
1975 rc = NO_ERROR;
1976 } break;
1977 default :
1978 {
1979 rc = ERROR_EAS_NOT_SUPPORTED;
1980 }
1981 }
1982 }
1983 *pulEASize = pFEAList->cbList;
1984 } while (0);
1985 debuglocal(9,"NdpFileEASize %d %d\n", *pulEASize, rc);
1986
1987 return rc;
1988}
1989
1990int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
1991{
1992 Connection *pConn = (Connection *)conn;
1993 Resource *pRes = pConn->pRes;
1994 int rc = 0;
1995 unsigned long action, attrFile;
1996
1997 debug_printf("NdpFileSetInfo in [%p]\n", pConn);
1998
1999 // delete the dir cache
2000 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
2001
2002 do {
2003 if (pConn->file.fd < 0 || !*pConn->file.fname)
2004 {
2005 rc = ERROR_INVALID_HANDLE;
2006 break;
2007 }
2008 attrFile = pfi->stat.attrFile;
2009 // deferred setinfo - on closing the file
2010 pConn->file.openattr = attrFile;
2011 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
2012 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
2013 } while (0);
2014 debuglocal(9,"NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
2015
2016 return NO_ERROR;
2017}
2018
2019int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2020{
2021 Connection *pConn = (Connection *)conn;
2022 Resource *pRes = pConn->pRes;
2023 int rc = 0;
2024 unsigned long action;
2025
2026 debuglocal(9,"NdpFileSetFilePtrL in [%p]\n", pConn);
2027
2028 do {
2029 if (pConn->file.fd < 0)
2030 {
2031 rc = ERROR_INVALID_HANDLE;
2032 break;
2033 }
2034
2035 rc = smbwrp_lseek(pConn->cli, &pConn->file, ulMethod, llOffset);
2036 if (!rc)
2037 *pllActual = pConn->file.offset;
2038
2039 } while (0);
2040 debuglocal(9,"NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
2041
2042 return rc;
2043}
2044
2045int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2046{
2047 LONGLONG llActual;
2048 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2049 *pulActual = llActual & 0xFFFFFFFF;
2050 debuglocal(9,"NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2051 return rc;
2052}
2053
2054int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2055{
2056 Connection *pConn = (Connection *)conn;
2057 Resource *pRes = pConn->pRes;
2058 int rc = 0;
2059 unsigned long action;
2060
2061 debuglocal(9,"NdpFileClose in [%p] %d <%s>\n", pConn, pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2062
2063 do {
2064 if (pConn->file.fd < 0)
2065 {
2066 rc = ERROR_INVALID_HANDLE;
2067 break;
2068 }
2069
2070 rc = smbwrp_close(pConn->cli, &pConn->file);
2071
2072 } while (0);
2073 debuglocal(9,"NdpFileClose %d %d\n", pConn->file.fd, rc);
2074
2075 pConn->file.fd = -1;
2076 return rc;
2077}
2078
2079int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2080{
2081 debuglocal(9,"NdpFileCommit %d\n", NO_ERROR);
2082 return NO_ERROR;
2083}
2084
2085
2086int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2087{
2088 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2089 debuglocal(9,"NdpFileNewSize %ld %d\n", ulLen, rc);
2090 return rc;
2091}
2092
2093int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2094{
2095 Connection *pConn = (Connection *)conn;
2096 Resource *pRes = pConn->pRes;
2097 int rc = 0;
2098 unsigned long action;
2099
2100 debuglocal(9,"NdpFileNewSizeL in [%p]\n", pConn);
2101
2102 do {
2103 if (pConn->file.fd < 0)
2104 {
2105 rc = ERROR_INVALID_HANDLE;
2106 break;
2107 }
2108
2109 rc = smbwrp_setfilesize(pConn->cli, &pConn->file, llLen);
2110
2111 } while (0);
2112 debuglocal(9,"NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
2113
2114 return rc;
2115}
2116
2117#define NDPSMB_READ_MAX_SIZE (65536 - 4096)
2118
2119int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2120{
2121 Connection *pConn = (Connection *)conn;
2122 Resource *pRes = pConn->pRes;
2123 int rc = 0;
2124 unsigned long done = 0;
2125 unsigned long onedone;
2126 unsigned long action;
2127 ULONG ulReadCompleted = 0;
2128
2129 debuglocal(9,"NdpFileRead in [%p]\n", pConn);
2130
2131 do {
2132 if (pConn->file.fd < 0)
2133 {
2134 rc = ERROR_INVALID_HANDLE;
2135 break;
2136 }
2137
2138 while (ulReadCompleted < ulRead)
2139 {
2140 ULONG ulActual;
2141 ULONG ulToRead = ulRead - ulReadCompleted;
2142 debuglocal(9,"NdpFileRead completed %d, to read %d\n", ulReadCompleted, ulToRead);
2143 if (ulToRead > NDPSMB_READ_MAX_SIZE)
2144 {
2145 ulToRead = NDPSMB_READ_MAX_SIZE;
2146 }
2147 rc = smbwrp_read(pConn->cli, &pConn->file, (char *)pBuffer + ulReadCompleted, ulToRead, &ulActual);
2148 if (ulActual == 0 || rc != NO_ERROR)
2149 {
2150 break;
2151 }
2152 ulReadCompleted += ulActual;
2153 }
2154
2155 //*pulActual = ulRead;
2156 //DosSleep(0);
2157
2158 } while (0);
2159
2160 if (ulReadCompleted > 0)
2161 {
2162 rc = NO_ERROR; /* Still were able to read some data. */
2163 }
2164
2165 if (rc == NO_ERROR)
2166 {
2167 *pulActual = ulReadCompleted;
2168 }
2169
2170 debuglocal(9,"NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
2171
2172 return rc;
2173}
2174
2175int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2176{
2177 Connection *pConn = (Connection *)conn;
2178 Resource *pRes = pConn->pRes;
2179 int rc = 0;
2180 unsigned long done = 0;
2181 unsigned long onedone;
2182 unsigned long action;
2183
2184 debuglocal(9,"NdpFileWrite in [%p]\n", pConn);
2185
2186 /* delete the dir cache
2187 this was moved from NdpFileClose() becasue if there are a lot files in the tree all are reread
2188 the problem when moved to here is, that last accessed time is not refreshed
2189 if this is needed, a new function needs to be done to update only one file in the cache */
2190 dircache_invalidate(pConn->file.fullname, pRes->pdc, 1);
2191
2192 do {
2193 if (pConn->file.fd < 0)
2194 {
2195 rc = ERROR_INVALID_HANDLE;
2196 break;
2197 }
2198 rc = smbwrp_write(pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
2199
2200 } while (0);
2201 debuglocal(9,"NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
2202
2203 return rc;
2204}
2205
Note: See TracBrowser for help on using the repository browser.