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

Last change on this file since 150 was 150, checked in by Yuri Dario, 17 years ago

Handle automatic reconnection, fixes for return codes.

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