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

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

Fix compiler warnings.

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