source: branches/client-1.5/src/ndpsmb.c@ 180

Last change on this file since 180 was 180, checked in by Yuri Dario, 16 years ago

Enable reconnection on level change, fixes ticket:66.

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