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

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

Fix for Ticket #88

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