source: branches/client-3.0/src/ndpsmb.c@ 1007

Last change on this file since 1007 was 1006, checked in by Paul Smedley, 9 years ago

Add support for enabling/disabling encryption - fixes #289

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