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

Last change on this file since 179 was 179, checked in by Herwig Bauernfeind, 16 years ago

Fix for Ticket #47

  • Property svn:eol-style set to native
File size: 50.6 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#if 0 // FIXME
601 if (rootlevel < 3)
602 {
603 char * p;
604 int newlevel = 0;
605 smbwrp_server * tmp = (smbwrp_server *)pConn->mem;
606 MemCpy(tmp, &pConn->srv, sizeof(pConn->srv));
607 if (rootlevel == 0)
608 {
609 p = ph->fsphStrChr(path, '\\');
610 if (!p)
611 {
612 p = path + StrLen(path);
613 }
614 if (StrLen(tmp->workgroup) != p - path
615 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
616 {
617 StrNCpy(tmp->workgroup, path, p - path);
618 tmp->workgroup[p - path] = 0;
619 newlevel = 1;
620 }
621 path = *p == '\\' ? p + 1 : p;
622 rootlevel = 1;
623 }
624 if (rootlevel == 1) // root path starts from server name
625 {
626 p = ph->fsphStrChr(path, '\\');
627 if (!p)
628 {
629 p = path + StrLen(path);
630 }
631 if (StrLen(tmp->server_name) != p - path
632 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
633 {
634 StrNCpy(tmp->server_name, path, p - path);
635 tmp->server_name[p - path] = 0;
636 newlevel = 1;
637 }
638 path = *p == '\\' ? p + 1 : p;
639 rootlevel = 2;
640 }
641 if (rootlevel == 2) // root path starts from share name
642 {
643 p = ph->fsphStrChr(path, '\\');
644 if (!p)
645 {
646 p = path + StrLen(path);
647 }
648 if (StrLen(tmp->share_name) != (p - path)
649 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
650 {
651 StrNCpy(tmp->share_name, path, p - path);
652 tmp->share_name[p - path] = 0;
653 newlevel = 1;
654 }
655 path = *p == '\\' ? p + 1 : p;
656 }
657 if (newlevel)
658 {
659 // reconnect to server here
660 unsigned long action;
661 smb_request req = {0};
662 smb_response resp = {0};
663
664 req.request = SMBREQ_DISCONNECT;
665 req.param = pConn->mem;
666 req.length = 0;
667 req.paramlen = 0;
668
669 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
670
671 req.request = SMBREQ_CONNECT;
672 req.param = pConn->mem;
673 req.length = pRes->memlen;
674 req.paramlen = sizeof(pConn->srv);
675
676 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
677 if (rc || action < sizeof(resp) || resp.rc)
678 {
679 APIRET rc2;
680 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
681 MemCpy(tmp, &pRes->srv, sizeof(pRes->srv));
682 rc2 = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
683 // TODO: what to do if the reconnect will fail ?
684 }
685 else
686 {
687 MemCpy(&pConn->srv, tmp, sizeof(pConn->srv));
688 }
689 }
690 }
691#endif
692 StrCpy(result, "\\");
693 StrNCat(result, path, CCHMAXPATH);
694
695 return rc;
696}
697
698
699// -------------------------------------------------------------
700
701/* check if the requested resource is available */
702static int checkMountResource( Resource* pRes)
703{
704 int rc;
705 unsigned long action;
706 cli_state* cli = NULL;
707 smbwrp_file file;
708
709 debug_printf("checkMountResource in tid#%d\n", _gettid());
710 rc = smbwrp_connect( pRes, &cli);
711/* changed to real error codes SCS
712 if (rc)
713 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_ACCESS_DENIED); */
714 switch (rc) {
715 case 0:
716 rc = NO_ERROR;
717 break;
718 case 1:
719 case 10:
720 case 11:
721 rc = ERROR_BAD_NET_NAME;
722 break;
723 case 2:
724 rc = ERROR_INIT_ROUTINE_FAILED;
725 break;
726 case 3:
727 rc = ERROR_BAD_NET_RESP;
728 break;
729 case 4:
730 rc = ERROR_NETWORK_BUSY;
731 break;
732 case 6:
733 rc = ERROR_NETWORK_ACCESS_DENIED;
734 break;
735 case 7:
736 rc = ERROR_BAD_NETPATH;
737 break;
738 default:
739 rc = ERROR_UNEXP_NET_ERR;
740 break;
741 } /* endswitch */
742
743 smbwrp_disconnect( pRes, cli);
744
745 return rc;
746}
747
748int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
749{
750 int rc = NO_ERROR;
751 unsigned long objany = OBJ_ANY;
752 Resource *pRes = NULL;
753
754 log("NdpMountResource in\n");
755
756 // init code
757 smbwrp_init();
758
759 /* since samba plugin support only 1 type of resources we do not need */
760 /* to check what the found type really is */
761 pRes = malloc( sizeof(Resource));
762 if (pRes == NULL)
763 {
764 rc = ERROR_NOT_ENOUGH_MEMORY;
765 }
766 else
767 {
768 MemSet(pRes, 0, sizeof(Resource));
769 //pRes->objany = objany;
770 // parse init string
771 rc = initResource (pRes, properties);
772 // try to connect to resource (check type) only if thread!=1, so ndctl startup
773 // is not slowed down by network connections.
774 // ndctl does mounting on main thread (#1)
775 // nd/ndpm do not use main thread
776 if (!rc && _gettid()!=1)
777 rc = checkMountResource( pRes);
778 if (!rc)
779 {
780 // store resource data
781 *presource = (HRESOURCE)pRes;
782 }
783 else
784 {
785 free(pRes);
786 }
787 }
788 log("NdpMountResource rc=%d\n", rc);
789 return rc;
790}
791
792// -------------------------------------------------------------
793
794int APIENTRY NdpFreeResource (HRESOURCE resource)
795{
796 Resource *pRes = (Resource *)resource;
797 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
798 free(pRes);
799 log("NdpFreeResource %d\n", NO_ERROR);
800 return NO_ERROR;
801}
802
803// -------------------------------------------------------------
804
805int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
806{
807 Resource *pRes = (Resource *)resource;
808 Resource *pRes2 = (Resource *)resource2;
809 int rc = ND_RSRC_DIFFERENT;
810
811 log("NdpRsrcCompare in\n");
812 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
813 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
814 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
815 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
816 {
817 // resources are equal
818 rc = ND_RSRC_EQUAL;
819 }
820
821 log("NdpRsrcCompare %d\n", rc);
822
823 return rc;
824}
825
826int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
827{
828 // do nothing
829 log("NdpRsrcUpdate %d\n", NO_ERROR);
830 return NO_ERROR;
831}
832
833int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
834{
835 Resource *pRes = (Resource *)resource;
836 int rc = NO_ERROR;
837 char s[4096];
838
839 log("NdpRsrcQueryInfo in\n");
840
841 switch (pRes->rootlevel)
842 {
843 case 0:
844 {
845 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
846 } break;
847 case 1:
848 {
849 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
850 } break;
851 case 2:
852 {
853 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);
854 } break;
855 default:
856 {
857 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);
858 } break;
859 }
860 *poutlen = StrLen(s) + 1;
861 if (*poutlen > insize)
862 {
863 rc = ERROR_BUFFER_OVERFLOW;
864 }
865 else
866 {
867 MemCpy(pdata, s, *poutlen);
868 }
869
870 log("NdpRsrcQueryInfo %d\n", rc);
871
872 return rc;
873}
874
875int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
876{
877 ULONG ulDummy = 0;
878 /* just return the resource info string */
879 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
880}
881
882int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
883{
884 Resource *pRes = (Resource *)resource;
885 int rc = NO_ERROR, rc1;
886 unsigned long action = 0;
887 smbwrp_file file;
888 cli_state* cli = NULL;
889 FSALLOCATE fsa;
890
891 log("NdpRsrcQueryFSAllocate %08x\n", pfsa);
892
893 if (!pfsa)
894 {
895 return NO_ERROR;
896 }
897
898 debug_printf("checkMountResource in tid#%d\n", _gettid());
899 rc = smbwrp_connect( pRes, &cli);
900 if (rc)
901 {
902 log("NdpCreateConnection failed rc=%d\n", rc);
903 pfsa->cSectorUnit = 1;
904 pfsa->cUnit = 123456;
905 pfsa->cUnitAvail = 123456;
906 pfsa->cbSector = 2048;
907 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_ACCESS_DENIED);
908 return rc;
909 }
910
911 rc = smbwrp_dskattr( cli, &fsa);
912 if (rc)
913 {
914 pfsa->cSectorUnit = 1;
915 pfsa->cUnit = 123456;
916 pfsa->cUnitAvail = 123456;
917 pfsa->cbSector = 2048;
918 //rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
919 }
920 else
921 {
922 pfsa->cSectorUnit = fsa.cSectorUnit;
923 pfsa->cUnit = fsa.cUnit;
924 pfsa->cUnitAvail = fsa.cUnitAvail;
925 pfsa->cbSector = fsa.cbSector;
926 }
927
928 smbwrp_disconnect( pRes, cli);
929
930 log("NdpRsrcQueryFSAllocate %d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
931 return rc;
932}
933
934// -------------------------------------------------------------
935
936int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
937{
938 int rc = 0;
939 Resource * pRes = (Resource *)resource;
940 unsigned long action;
941 Connection *pConn = NULL;
942
943 log("NdpCreateConnection in\n");
944
945 pConn = malloc( sizeof(Connection));
946 if (pConn == NULL)
947 {
948 rc = ERROR_NOT_ENOUGH_MEMORY;
949 }
950 if (rc)
951 {
952 log("NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
953 return rc;
954 }
955 MemSet(pConn, 0, sizeof(Connection));
956 pConn->pRes = pRes;
957 pConn->file.fd = -1;
958
959 log("NdpCreateConnection send CONNECT\n");
960 rc = smbwrp_connect( pRes, &pConn->cli);
961 if (rc)
962 {
963 free(pConn);
964 pConn = NULL;
965 rc = (rc == 7 ? ERROR_BAD_DEV_TYPE : ERROR_INVALID_PARAMETER);
966 }
967
968 *pconn = (HCONNECTION)pConn;
969 log("NdpCreateConnection %d\n", rc);
970 return rc;
971}
972
973// -------------------------------------------------------------
974
975int APIENTRY NdpFreeConnection (HCONNECTION conn)
976{
977 Connection *pConn = (Connection *)conn;
978 Resource *pRes = pConn->pRes;
979 int rc;
980
981 log("NdpFreeConnection in\n");
982 if (pConn->file.fd >= 0)
983 {
984 rc = smbwrp_close( pConn->cli, &pConn->file);
985 pConn->file.fd = -1;
986 }
987
988 smbwrp_disconnect( pRes, pConn->cli);
989
990 free(pConn);
991 log("NdpFreeConnection %d\n", NO_ERROR);
992 return NO_ERROR;
993}
994
995// -------------------------------------------------------------
996
997/*
998 * NdpQueryPathInfo is the most important function :) netdrive always calls
999 * the function before every operation to find out the path status: does it exist, is it a file, does a
1000 * parent directory exist, etc.
1001 * Plugin must return one of the following error codes:
1002 * NO_ERROR - path exists and the path information have been successfully retrieved.
1003 * ERROR_FILE_NOT_FOUND - all but the last component of the path exist and the
1004 * path without the last component is a directory. dir1_ok\dir2_ok\does_not_exist.
1005 * the wildcard can not exist, so the plugin returns FILE_NOT_FOUND, if the parent
1006 * directory exist.
1007 * ERROR_PATH_NOT_FOUND - any of not last path components does not exist, or all
1008 * but the last component exist and is a file: \dir_ok\dir2_ok\file_ok\non_existing.
1009 * ERROR_REM_NOT_LIST - resource is temporarily unavailable for some reasons.
1010 * Any other error codes means an internal plugin error, not related to the status
1011 * of the path queried.
1012 */
1013int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
1014{
1015 Connection *pConn = (Connection *)conn;
1016 Resource *pRes = pConn->pRes;
1017 smbwrp_fileinfo finfo;
1018 int rc = 0;
1019 unsigned long action;
1020 char path[CCHMAXPATH+1] = {0};
1021 int retry = 0;
1022
1023 log("NdpQueryPathInfo in <%s>, retry = %d\n", szPath, retry);
1024
1025 // is wildcard is specified, we suppose parent dir exist, so exit immediately
1026 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
1027 {
1028 return ERROR_FILE_NOT_FOUND;
1029 }
1030
1031
1032 do {
1033
1034 rc = pathparser(pRes, pConn, szPath, path);
1035 log("NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
1036 switch (rc)
1037 {
1038 case NO_ERROR :
1039 case ERROR_FILE_NOT_FOUND:
1040 case ERROR_PATH_NOT_FOUND:
1041 case ERROR_ACCESS_DENIED:
1042 case ERROR_INVALID_PARAMETER:
1043 {
1044 break;
1045 }
1046 default :
1047 {
1048 rc = ERROR_PATH_NOT_FOUND;
1049 }
1050 }
1051 if (rc)
1052 {
1053 break;
1054 }
1055 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1056 log("NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
1057 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1058 if (rc)
1059 {
1060 // remote server not available for first time?
1061 if (rc == ERROR_REM_NOT_LIST && retry == 0)
1062 {
1063 // free current cli resources
1064 smbwrp_disconnect( pRes, pConn->cli);
1065 // reconnect
1066 smbwrp_connect( pRes, &pConn->cli);
1067 // try file list again
1068 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1069 log("NdpQueryPathInfo remote connection lost, retry rc = %d\n", rc);
1070 }
1071 switch (rc)
1072 {
1073 case NO_ERROR :
1074 case ERROR_FILE_NOT_FOUND:
1075 case ERROR_PATH_NOT_FOUND:
1076 case ERROR_ACCESS_DENIED:
1077 case ERROR_INVALID_PARAMETER:
1078 case ERROR_REM_NOT_LIST:
1079 break;
1080 default :
1081 {
1082 rc = ERROR_PATH_NOT_FOUND;
1083 }
1084 }
1085 }
1086 else
1087 {
1088 finfo.easize = -1;
1089 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1090 }
1091 if (rc == ERROR_FILE_NOT_FOUND)
1092 {
1093 // now try the upper path
1094 char * p = ph->fsphStrChr(finfo.fname, '\\');
1095 if (p && p > finfo.fname)
1096 {
1097 *p = 0;
1098 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1099 if (rc)
1100 {
1101 log("NdpQueryPathInfo upper path in <%s>, retry = %d\n", finfo.fname, retry);
1102 rc = rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER;
1103 }
1104 }
1105 }
1106 } while (0);
1107 log("NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
1108
1109 return rc;
1110}
1111
1112// -------------------------------------------------------------
1113
1114int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1115{
1116 Connection *pConn = (Connection *)conn;
1117 Resource *pRes = pConn->pRes;
1118 int rc = NO_ERROR, count = 0;
1119 unsigned long action;
1120 char *mask = "*";
1121 char dir[CCHMAXPATH+1] = {0};
1122 char path[CCHMAXPATH+1] = {0};
1123 smbwrp_fileinfo * data;
1124 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1125 filelist_state state;
1126 char * p;
1127
1128 debug_printf("NdpFindStart in\n");
1129
1130 StrNCpy(dir, szPath, sizeof(dir) - 1);
1131 if (pel)
1132 {
1133 mask = pel->name;
1134 dir[StrLen(szPath) - pel->length] = 0;
1135 }
1136 action = StrLen(dir) - 1;
1137 if (dir[action] == '\\')
1138 {
1139 dir[action] = 0;
1140 }
1141 rc = pathparser(pRes, pConn, dir, path);
1142 if (rc)
1143 {
1144 return rc;
1145 }
1146 action = StrLen(path) - 1;
1147 if (path[action] != '\\')
1148 {
1149 StrNCat(path, "\\", sizeof(path) - 1);
1150 }
1151 StrCpy(dir, path);
1152 StrNCat(path, mask, sizeof(path) - 1);
1153
1154 // this structure will be used by libsmb callbacks, so we store here all we need
1155 // to fill netdrive structures
1156 state.pConn = pConn;
1157 state.plist = plist;
1158 state.ulAttribute = ulAttribute;
1159 strcpy( state.dir, dir);
1160 strcpy( state.dir_mask, mask);
1161 strcpy( state.mask, path);
1162 p = getlastslash(state.mask);
1163 if (p)
1164 {
1165 *(p + 1) = '*';
1166 *(p + 2) = 0;
1167 }
1168 else
1169 {
1170 strcpy(state.mask, "\\*");
1171 }
1172 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1173 // we need to handle reconnection also here, because NdpQueryPathInfo
1174 // could be called with '*' and exit then immediately (without calling libsmb)
1175 if (rc == ERROR_REM_NOT_LIST)
1176 {
1177 // free current cli resources
1178 smbwrp_disconnect( pRes, pConn->cli);
1179 // reconnect
1180 smbwrp_connect( pRes, &pConn->cli);
1181 // try file list again next loop
1182 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1183 log("NdpFindStart remote connection lost, retry rc = %d\n", rc);
1184 }
1185
1186 log("NdpFindStart <%s> (%s) cnt %d %d\n", szPath, path, count, rc);
1187
1188 return rc;
1189}
1190
1191int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1192{
1193// log("NdpDeletePathInfo %d\n", 0);
1194 return NO_ERROR;
1195}
1196
1197int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1198{
1199 log("NdpRefresh <%s> %d\n", path, 0);
1200 return NO_ERROR;
1201}
1202
1203int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1204{
1205 // The plugin do not have to deallocate anything
1206 // because resource data did not contain any pointers
1207 // to plugins data.
1208 // Data stored by fsphSetResourceData will be
1209 // deallocated by NetDrive.
1210
1211 log("NdpDicardresourceData %d\n", 0);
1212 return NO_ERROR;
1213}
1214
1215int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1216{
1217 Connection *pConn = (Connection *)conn;
1218 Resource *pRes = pConn->pRes;
1219 int rc = 0;
1220 unsigned long action;
1221 char path[CCHMAXPATH+1] = {0};
1222 smbwrp_fileinfo finfo;
1223
1224 debug_printf("NdpSetPathInfo in FIXME\n");
1225
1226 do {
1227 rc = pathparser(pRes, pConn, szPathName, path);
1228 if (rc)
1229 {
1230 break;
1231 }
1232
1233 MemSet(&finfo, 0, sizeof(finfo));
1234
1235 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1236 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
1237 finfo.attr = pfi->stat.attrFile & 0x37;
1238 rc = smbwrp_setattr(pConn->cli, &finfo);
1239 } while (0);
1240 log("NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
1241
1242 return rc;
1243}
1244
1245int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1246{
1247 int rc = 0;
1248 FEA * pfea;
1249 FEA * pfeadest;
1250 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1251
1252 size = pFEASrc->cbList;
1253 pfea = pFEASrc->list;
1254 pfeadest = pFEAList->list;
1255 dsize = pFEAList->cbList;
1256//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1257 while (done < size)
1258 {
1259 char * name = (char *)(pfea + 1);
1260 int insert = 1;
1261 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1262 {
1263 GEA * pgea = pGEAList->list;
1264 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1265 insert = 0;
1266 while (done < size)
1267 {
1268//log("comp <%s> <%s>\n", name, pgea->szName);
1269 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1270 {
1271 insert = 1;
1272 break;
1273 }
1274 done += pgea->cbName + 2;
1275 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1276 }
1277 }
1278 if (insert)
1279 {
1280 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1281 if (ddone <= dsize)
1282 {
1283 pfeadest->cbName = pfea->cbName;
1284 pfeadest->cbValue = pfea->cbValue;
1285 pfeadest->fEA = 0;
1286 StrCpy((char *)(pfeadest + 1), name);
1287 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1288 pfeadest = (FEA *)((char *)pFEAList + ddone);
1289 }
1290 }
1291 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1292//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);
1293 pfea = (FEA *)((char *)pFEASrc + done);
1294 }
1295 pFEAList->cbList = ddone;
1296 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1297 {
1298 rc = ERROR_BUFFER_OVERFLOW;
1299 }
1300 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1301 return rc;
1302}
1303
1304int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1305{
1306 Connection *pConn = (Connection *)conn;
1307 Resource *pRes = pConn->pRes;
1308 int rc = 0;
1309 unsigned long action;
1310 char * path = NULL;
1311 FEALIST * pFEASrc;
1312 NDDATABUF fdata = {0};
1313 smbwrp_fileinfo *finfo;
1314 char pBuffer[64*1024];
1315
1316 if (!pfi || !pfi->pszName || !pFEAList)
1317 {
1318 return ERROR_EAS_NOT_SUPPORTED;
1319 }
1320 if (!pRes->easupport)
1321 {
1322 return ERROR_EAS_NOT_SUPPORTED;
1323 }
1324
1325 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1326 if (rc || !fdata.ulSize || !fdata.pData)
1327 {
1328 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1329 return ERROR_EAS_NOT_SUPPORTED;
1330 }
1331 finfo = (smbwrp_fileinfo *)fdata.pData;
1332 path = finfo->fname;
1333
1334 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1335
1336 do {
1337 rc = smbwrp_listea( pConn->cli, path, pBuffer, sizeof( pBuffer));
1338 pFEASrc = (FEALIST*) pBuffer;
1339 if (rc)
1340 {
1341 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1342 switch (rc)
1343 {
1344 case ERROR_FILE_NOT_FOUND :
1345 case ERROR_PATH_NOT_FOUND :
1346 {
1347 pFEAList->cbList = sizeof(pFEAList->cbList);
1348 rc = NO_ERROR;
1349 } break;
1350 case ERROR_BUFFER_OVERFLOW :
1351 {
1352 pFEAList->cbList = pFEASrc->cbList;
1353 } break;
1354 default :
1355 {
1356 rc = ERROR_EAS_NOT_SUPPORTED;
1357 }
1358 }
1359 }
1360 else
1361 {
1362 rc = buildFEALIST((FEALIST *)pFEASrc, pGEAList, pFEAList);
1363 }
1364 } while (0);
1365 log("NdpEAQuery <%s> %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList);
1366
1367 return rc;
1368}
1369
1370int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1371{
1372 Connection *pConn = (Connection *)conn;
1373 Resource *pRes = pConn->pRes;
1374 int rc = 0;
1375 char * path;
1376 unsigned long action;
1377 NDDATABUF fdata = {0};
1378 smbwrp_fileinfo *finfo;
1379
1380 log("NdpEASet in\n");
1381
1382 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1383 {
1384 return ERROR_EAS_NOT_SUPPORTED;
1385 }
1386 if (!pRes->easupport)
1387 {
1388 return ERROR_EAS_NOT_SUPPORTED;
1389 }
1390
1391 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1392 if (rc || !fdata.ulSize || !fdata.pData)
1393 {
1394 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1395 return ERROR_EAS_NOT_SUPPORTED;
1396 }
1397 finfo = (smbwrp_fileinfo *)fdata.pData;
1398 path = finfo->fname;
1399
1400 do {
1401 // got FEA there
1402 FEA * pfea;
1403 unsigned long done = sizeof(long);
1404 pfea = pFEAList->list;
1405 while (done < pFEAList->cbList)
1406 {
1407 rc = smbwrp_setea(pConn->cli, path, (char*)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1408 if (rc)
1409 {
1410 break;
1411 }
1412 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1413 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1414 }
1415 } while (0);
1416 log("NdpEASet %d\n", rc);
1417
1418 return rc;
1419}
1420
1421int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1422{
1423 Connection *pConn = (Connection *)conn;
1424 Resource *pRes = pConn->pRes;
1425 int rc = 0;
1426 unsigned long action;
1427 char * path = NULL;
1428 FEALIST * pfealist;
1429 NDDATABUF fdata = {0};
1430 smbwrp_fileinfo *finfo;
1431 char pBuffer[64*1024];
1432 int easize;
1433
1434 if (!pfi || !pulEASize)
1435 {
1436 return ERROR_EAS_NOT_SUPPORTED;
1437 }
1438 if (!pRes->easupport)
1439 {
1440 return ERROR_EAS_NOT_SUPPORTED;
1441 }
1442
1443 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1444 if (rc || !fdata.ulSize || !fdata.pData)
1445 {
1446 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1447 return ERROR_EAS_NOT_SUPPORTED;
1448 }
1449 finfo = (smbwrp_fileinfo *)fdata.pData;
1450 easize = finfo->easize;
1451 finfo->easize = -1;
1452 path = finfo->fname;
1453 if (easize >= 0)
1454 {
1455 *pulEASize = easize;
1456 log("NdpEASize <%s> cached %d\n", path, easize);
1457 return NO_ERROR;
1458 }
1459
1460 log("NdpEASize in <%s> \n", path);
1461
1462 do {
1463 rc = smbwrp_listea(pConn->cli, path, pBuffer, sizeof( pBuffer));
1464 pfealist = (FEALIST*)pBuffer;
1465 if (rc)
1466 {
1467 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1468 switch (rc)
1469 {
1470 case ERROR_FILE_NOT_FOUND :
1471 case ERROR_PATH_NOT_FOUND :
1472 {
1473 pfealist->cbList = sizeof(pfealist->cbList);
1474 } /* Fall through */
1475 case ERROR_BUFFER_OVERFLOW :
1476 {
1477 rc = NO_ERROR;
1478 } break;
1479 default :
1480 {
1481 rc = ERROR_EAS_NOT_SUPPORTED;
1482 }
1483 }
1484 }
1485 *pulEASize = pfealist->cbList;
1486 } while (0);
1487 log("NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
1488
1489 return rc;
1490}
1491
1492int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1493{
1494 Connection *pConn = (Connection *)conn;
1495 Resource *pRes = pConn->pRes;
1496 int rc = 0;
1497 unsigned long action;
1498 char path[CCHMAXPATH+1] = {0};
1499
1500 log("NdpSetCurrentDir in\n");
1501
1502 do {
1503 rc = pathparser(pRes, pConn, szPath, path);
1504 if (rc)
1505 {
1506 break;
1507 }
1508
1509 rc = smbwrp_chdir(&pRes->srv, pConn->cli, path);
1510 } while (0);
1511 log("NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
1512
1513 return rc;
1514}
1515
1516int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1517{
1518 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1519 return ERROR_CANNOT_COPY;
1520}
1521
1522int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1523{
1524 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1525 return ERROR_CANNOT_COPY;
1526}
1527
1528int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1529{
1530 Connection *pConn = (Connection *)conn;
1531 Resource *pRes = pConn->pRes;
1532 int rc = 0;
1533 unsigned long action;
1534 char path[CCHMAXPATH+1] = {0};
1535
1536 log("NdpForceDelete in\n");
1537
1538 do {
1539 rc = pathparser(pRes, pConn, szFile, path);
1540 if (rc)
1541 {
1542 break;
1543 }
1544
1545 rc = smbwrp_unlink(pConn->cli, path);
1546 } while (0);
1547 log("NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
1548
1549 return rc;
1550}
1551
1552int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1553{
1554 Connection *pConn = (Connection *)conn;
1555 Resource *pRes = pConn->pRes;
1556 int rc = 0;
1557 unsigned long action;
1558 char path[CCHMAXPATH+1] = {0};
1559
1560 log("NdpCreateDir in\n");
1561
1562 do {
1563 rc = pathparser(pRes, pConn, szDirName, path);
1564 if (rc)
1565 {
1566 break;
1567 }
1568
1569 rc = smbwrp_mkdir(pConn->cli, path);
1570 } while (0);
1571 log("NdpCreateDir <%s> (%s) %d\n", szDirName, path, rc);
1572
1573 return rc;
1574}
1575
1576int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1577{
1578 Connection *pConn = (Connection *)conn;
1579 Resource *pRes = pConn->pRes;
1580 int rc = 0;
1581 unsigned long action;
1582 char path[CCHMAXPATH+1] = {0};
1583
1584 log("NdpDeleteDir in\n");
1585
1586 do {
1587 rc = pathparser(pRes, pConn, szDir, path);
1588 if (rc)
1589 {
1590 break;
1591 }
1592
1593 rc = smbwrp_rmdir(pConn->cli, path);
1594 } while (0);
1595 log("NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
1596
1597 return rc;
1598}
1599
1600int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1601{
1602 Connection *pConn = (Connection *)conn;
1603 Resource *pRes = pConn->pRes;
1604 int rc = 0;
1605 unsigned long action;
1606 char src[CCHMAXPATH+1] = {0};
1607 int l1, l2;
1608 char * p = szDst;
1609
1610 log("NdpMove in from <%s> to <%s>\n", szSrc, szDst);
1611
1612 do
1613 {
1614 rc = pathparser(pRes, pConn, szSrc, src);
1615 if (rc)
1616 {
1617 break;
1618 }
1619 l1 = StrLen(szSrc);
1620 l2 = StrLen(src);
1621 if (l1 > l2)
1622 {
1623 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1624 {
1625 // the file moved accross different shares or servers or workgroups
1626 rc = ERROR_WRITE_PROTECT;
1627 break;
1628 }
1629 p = szDst + l1 - l2 + 1;
1630 }
1631 //pConn->mem[CCHMAXPATH + 1] = '\\';
1632 rc = smbwrp_rename(pConn->cli, src, p);
1633 } while (0);
1634 log("NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
1635
1636 return rc;
1637}
1638
1639int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1640{
1641 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1642 return ERROR_WRITE_PROTECT;
1643}
1644
1645
1646int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1647{
1648 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1649}
1650
1651int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1652{
1653 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1654}
1655
1656int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1657{
1658 Resource *pRes = pConn->pRes;
1659 unsigned long action;
1660 int rc = 0;
1661 char path[CCHMAXPATH+1] = {0};
1662
1663 log("smbopen in %d\n", pConn->file.fd);
1664
1665 do {
1666 if (pConn->file.fd > 0)
1667 {
1668 rc = ERROR_TOO_MANY_OPEN_FILES;
1669 break;
1670 }
1671
1672 rc = pathparser(pRes, pConn, szFileName, path);
1673 if (rc)
1674 {
1675 break;
1676 }
1677
1678 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1679 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1680 flags |= O_BINARY;
1681 switch (ulOpenMode & 3)
1682 {
1683 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1684 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1685 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1686 default : flags |= O_RDWR;
1687 }
1688 pConn->file.openmode = flags;
1689 pConn->file.openattr = ulAttribute & 0x37;
1690 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1691 rc = smbwrp_open(pConn->cli, &pConn->file);
1692 } while (0);
1693 log("smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
1694 if (!rc && pFEAList)
1695 {
1696 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1697 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1698 }
1699
1700 return rc;
1701}
1702
1703int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1704{
1705 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1706}
1707
1708int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1709{
1710 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1711}
1712
1713int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1714{
1715// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1716 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1717}
1718
1719int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1720{
1721 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1722}
1723
1724int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1725{
1726 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1727 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1728}
1729
1730int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1731{
1732 Connection *pConn = (Connection *)conn;
1733 Resource *pRes = pConn->pRes;
1734 int rc = 0;
1735 unsigned long action;
1736
1737 smbwrp_fileinfo finfo;
1738 char path[CCHMAXPATH+1] = {0};
1739
1740 log("NdpSetFileAttribute in\n");
1741 do {
1742 rc = pathparser(pRes, pConn, szFileName, path);
1743 if (rc)
1744 {
1745 break;
1746 }
1747
1748 MemSet(&finfo, 0, sizeof(finfo));
1749 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1750 finfo.attr = usAttr & 0x37;
1751 rc = smbwrp_setattr(pConn->cli, &finfo);
1752 } while (0);
1753 log("NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
1754
1755 return rc;
1756}
1757
1758int APIENTRY NdpFlush (HRESOURCE resource)
1759{
1760 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1761 return ERROR_NOT_SUPPORTED;
1762}
1763
1764int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1765{
1766 log("NdpIOCTL <%s> %d\n", path, function);
1767
1768 if (in && insize > 4096)
1769 {
1770 char out[4096];
1771 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1772 *poutlen = strlen(out);
1773 strcpy (in, out);
1774 return NO_ERROR;
1775 }
1776
1777 return ERROR_NOT_SUPPORTED;
1778}
1779
1780int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1781{
1782 Connection *pConn = (Connection *)conn;
1783 Resource *pRes = pConn->pRes;
1784 int rc = 0;
1785 unsigned long action;
1786 smbwrp_fileinfo finfo;
1787
1788 debug_printf("NdpFileQueryInfo in\n");
1789 do {
1790 if (pConn->file.fd < 0 || !*pConn->file.fname)
1791 {
1792 rc = ERROR_INVALID_HANDLE;
1793 break;
1794 }
1795 StrNCpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
1796 rc = smbwrp_fgetattr(pConn->cli, &pConn->file, &finfo);
1797 if (!rc)
1798 {
1799 finfo.easize = -1;
1800 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1801 }
1802 } while (0);
1803 log("NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
1804
1805 return rc;
1806}
1807
1808int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1809{
1810 Connection *pConn = (Connection *)conn;
1811 Resource *pRes = pConn->pRes;
1812 int rc = 0;
1813 unsigned long action;
1814 char pBuffer[64*1024];
1815 FEALIST * pFEASrc;
1816
1817 if (!pFEAList)
1818 {
1819 return ERROR_EAS_NOT_SUPPORTED;
1820 }
1821 if (!pRes->easupport)
1822 {
1823 return ERROR_EAS_NOT_SUPPORTED;
1824 }
1825
1826 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
1827 do {
1828 if (pConn->file.fd < 0)
1829 {
1830 rc = ERROR_INVALID_HANDLE;
1831 break;
1832 }
1833 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof( pBuffer));
1834 pFEASrc = (FEALIST *) pBuffer;
1835 if (rc)
1836 {
1837 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1838 switch (rc)
1839 {
1840 case ERROR_FILE_NOT_FOUND :
1841 case ERROR_PATH_NOT_FOUND :
1842 {
1843 pFEAList->cbList = sizeof(pFEAList->cbList);
1844 rc = NO_ERROR;
1845 } break;
1846 case ERROR_BUFFER_OVERFLOW :
1847 {
1848 pFEAList->cbList = pFEASrc->cbList;
1849 } break;
1850 default :
1851 {
1852 rc = ERROR_EAS_NOT_SUPPORTED;
1853 }
1854 }
1855 }
1856 else
1857 {
1858 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1859 }
1860 } while (0);
1861 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);
1862
1863 return rc;
1864}
1865
1866int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1867{
1868 Connection *pConn = (Connection *)conn;
1869 Resource *pRes = pConn->pRes;
1870 int rc = 0;
1871 unsigned long action;
1872
1873 log("NdpFileEASet in\n");
1874
1875 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1876 {
1877 return ERROR_EAS_NOT_SUPPORTED;
1878 }
1879 if (!pRes->easupport)
1880 {
1881 return ERROR_EAS_NOT_SUPPORTED;
1882 }
1883
1884 do {
1885 // got FEA there
1886 FEA * pfea;
1887 unsigned long done = sizeof(long);
1888 if (pConn->file.fd < 0)
1889 {
1890 rc = ERROR_INVALID_HANDLE;
1891 break;
1892 }
1893
1894 pfea = pFEAList->list;
1895 while (done < pFEAList->cbList)
1896 {
1897 rc = smbwrp_fsetea(pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1898 if (rc)
1899 {
1900 break;
1901 }
1902 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1903 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1904 }
1905
1906 } while (0);
1907 log("NdpFileEASet %d\n", rc);
1908
1909 return rc;
1910}
1911
1912int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1913{
1914 Connection *pConn = (Connection *)conn;
1915 Resource *pRes = pConn->pRes;
1916 int rc = 0;
1917 unsigned long action;
1918 char path[CCHMAXPATH+1] = {0};
1919 FEALIST * pFEAList;
1920 char pBuffer[64*1024];
1921
1922 if (!pulEASize)
1923 {
1924 return ERROR_EAS_NOT_SUPPORTED;
1925 }
1926 if (!pRes->easupport)
1927 {
1928 return ERROR_EAS_NOT_SUPPORTED;
1929 }
1930
1931 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
1932 do {
1933 if (pConn->file.fd < 0)
1934 {
1935 rc = ERROR_INVALID_HANDLE;
1936 break;
1937 }
1938 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof(pBuffer));
1939 pFEAList = (FEALIST*) pBuffer;
1940 if (rc)
1941 {
1942 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1943 switch (rc)
1944 {
1945 case ERROR_FILE_NOT_FOUND :
1946 case ERROR_PATH_NOT_FOUND :
1947 {
1948 pFEAList->cbList = sizeof(pFEAList->cbList);
1949 } /* Fall through */
1950 case ERROR_BUFFER_OVERFLOW :
1951 {
1952 rc = NO_ERROR;
1953 } break;
1954 default :
1955 {
1956 rc = ERROR_EAS_NOT_SUPPORTED;
1957 }
1958 }
1959 }
1960 *pulEASize = pFEAList->cbList;
1961 } while (0);
1962 log("NdpFileEASize %d %d\n", *pulEASize, rc);
1963
1964 return rc;
1965}
1966
1967int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
1968{
1969 Connection *pConn = (Connection *)conn;
1970 Resource *pRes = pConn->pRes;
1971 int rc = 0;
1972 unsigned long action, attrFile;
1973
1974 debug_printf("NdpFileSetInfo in\n");
1975 do {
1976 if (pConn->file.fd < 0 || !*pConn->file.fname)
1977 {
1978 rc = ERROR_INVALID_HANDLE;
1979 break;
1980 }
1981 attrFile = pfi->stat.attrFile;
1982 // deferred setinfo - on closing the file
1983 pConn->file.openattr = attrFile;
1984 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
1985 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
1986 } while (0);
1987 log("NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
1988
1989 return NO_ERROR;
1990}
1991
1992int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
1993{
1994 Connection *pConn = (Connection *)conn;
1995 Resource *pRes = pConn->pRes;
1996 int rc = 0;
1997 unsigned long action;
1998
1999 log("NdpFileSetFilePtrl in\n");
2000
2001 do {
2002 if (pConn->file.fd < 0)
2003 {
2004 rc = ERROR_INVALID_HANDLE;
2005 break;
2006 }
2007
2008 rc = smbwrp_lseek(pConn->cli, &pConn->file, ulMethod, llOffset);
2009 if (!rc)
2010 *pllActual = pConn->file.offset;
2011
2012 } while (0);
2013 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
2014
2015 return rc;
2016}
2017
2018int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2019{
2020 LONGLONG llActual;
2021 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2022 *pulActual = llActual & 0xFFFFFFFF;
2023 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2024 return rc;
2025}
2026
2027int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2028{
2029 Connection *pConn = (Connection *)conn;
2030 Resource *pRes = pConn->pRes;
2031 int rc = 0;
2032 unsigned long action;
2033
2034 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2035
2036 do {
2037 if (pConn->file.fd < 0)
2038 {
2039 rc = ERROR_INVALID_HANDLE;
2040 break;
2041 }
2042
2043 rc = smbwrp_close(pConn->cli, &pConn->file);
2044
2045 } while (0);
2046 log("NdpFileClose %d %d\n", pConn->file.fd, rc);
2047
2048 pConn->file.fd = -1;
2049 return rc;
2050}
2051
2052int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2053{
2054 log("NdpFileCommit %d\n", NO_ERROR);
2055 return NO_ERROR;
2056}
2057
2058
2059int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2060{
2061 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2062 log("NdpFileNewSize %ld %d\n", ulLen, rc);
2063 return rc;
2064}
2065
2066int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2067{
2068 Connection *pConn = (Connection *)conn;
2069 Resource *pRes = pConn->pRes;
2070 int rc = 0;
2071 unsigned long action;
2072
2073 log("NdpFileNewSizeL in\n");
2074
2075 do {
2076 if (pConn->file.fd < 0)
2077 {
2078 rc = ERROR_INVALID_HANDLE;
2079 break;
2080 }
2081
2082 rc = smbwrp_setfilesize(pConn->cli, &pConn->file, llLen);
2083
2084 } while (0);
2085 log("NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
2086
2087 return rc;
2088}
2089
2090int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2091{
2092 Connection *pConn = (Connection *)conn;
2093 Resource *pRes = pConn->pRes;
2094 int rc = 0;
2095 unsigned long done = 0;
2096 unsigned long onedone;
2097 unsigned long action;
2098
2099 log("NdpFileRead in\n");
2100
2101 do {
2102 if (pConn->file.fd < 0)
2103 {
2104 rc = ERROR_INVALID_HANDLE;
2105 break;
2106 }
2107 rc = smbwrp_read(pConn->cli, &pConn->file, pBuffer, ulRead, pulActual);
2108 //*pulActual = ulRead;
2109 //DosSleep(0);
2110
2111 } while (0);
2112 log("NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
2113
2114 return rc;
2115}
2116
2117int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2118{
2119 Connection *pConn = (Connection *)conn;
2120 Resource *pRes = pConn->pRes;
2121 int rc = 0;
2122 unsigned long done = 0;
2123 unsigned long onedone;
2124 unsigned long action;
2125
2126 log("NdpFileWrite in\n");
2127
2128 do {
2129 if (pConn->file.fd < 0)
2130 {
2131 rc = ERROR_INVALID_HANDLE;
2132 break;
2133 }
2134 rc = smbwrp_write(pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
2135
2136 } while (0);
2137 log("NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
2138
2139 return rc;
2140}
2141
Note: See TracBrowser for help on using the repository browser.