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

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

Map errno smb errors to OS/2 error codes. Minor build system rework.

  • Property svn:eol-style set to native
File size: 47.3 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 return rc;
859 }
860
861 rc = smbwrp_dskattr( cli, &fsa);
862 if (rc)
863 {
864 pfsa->cSectorUnit = 1;
865 pfsa->cUnit = 123456;
866 pfsa->cUnitAvail = 123456;
867 pfsa->cbSector = 2048;
868 //rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
869 }
870 else
871 {
872 pfsa->cSectorUnit = fsa.cSectorUnit;
873 pfsa->cUnit = fsa.cUnit;
874 pfsa->cUnitAvail = fsa.cUnitAvail;
875 pfsa->cbSector = fsa.cbSector;
876 }
877
878 smbwrp_disconnect( pRes, cli);
879
880 log("NdpRsrcQueryFSAllocate %d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
881 return rc;
882}
883
884// -------------------------------------------------------------
885
886int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
887{
888 int rc = 0;
889 Resource * pRes = (Resource *)resource;
890 unsigned long action;
891 Connection *pConn = NULL;
892
893 log("NdpCreateConnection in\n");
894
895 pConn = malloc( sizeof(Connection));
896 if (pConn == NULL)
897 {
898 rc = ERROR_NOT_ENOUGH_MEMORY;
899 }
900 if (rc)
901 {
902 log("NdpCreateConnection ERROR_NOT_ENOUGH_MEMORY %d\n", rc);
903 return rc;
904 }
905 MemSet(pConn, 0, sizeof(Connection));
906 pConn->pRes = pRes;
907 pConn->file.fd = -1;
908
909 log("NdpCreateConnection send CONNECT\n");
910 rc = smbwrp_connect( pRes, &pConn->cli);
911 if (rc)
912 {
913 free(pConn);
914 pConn = NULL;
915 }
916
917 *pconn = (HCONNECTION)pConn;
918 log("NdpCreateConnection %d\n", rc);
919 return rc;
920}
921
922// -------------------------------------------------------------
923
924int APIENTRY NdpFreeConnection (HCONNECTION conn)
925{
926 Connection *pConn = (Connection *)conn;
927 Resource *pRes = pConn->pRes;
928 int rc;
929
930 log("NdpFreeConnection in\n");
931 if (pConn->file.fd >= 0)
932 {
933 rc = smbwrp_close( pConn->cli, &pConn->file);
934 pConn->file.fd = -1;
935 }
936
937 smbwrp_disconnect( pRes, pConn->cli);
938
939 free(pConn);
940 log("NdpFreeConnection %d\n", NO_ERROR);
941 return NO_ERROR;
942}
943
944// -------------------------------------------------------------
945
946int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
947{
948 Connection *pConn = (Connection *)conn;
949 Resource *pRes = pConn->pRes;
950 smbwrp_fileinfo finfo;
951 int rc = 0;
952 unsigned long action;
953 char path[CCHMAXPATH+1] = {0};
954 int retry = 0;
955
956 do
957 {
958 log("NdpQueryPathInfo in <%s>, retry = %d\n", szPath, retry);
959
960 do {
961
962 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
963 {
964 rc = ERROR_FILE_NOT_FOUND;
965 break;
966 }
967
968 rc = pathparser(pRes, pConn, szPath, path);
969 log("NdpQueryPathInfo pathparser for <%s> rc=%d\n", path, rc);
970 switch (rc)
971 {
972 case NO_ERROR :
973 case ERROR_FILE_NOT_FOUND:
974 case ERROR_PATH_NOT_FOUND:
975 case ERROR_ACCESS_DENIED:
976 case ERROR_INVALID_PARAMETER:
977 {
978 break;
979 }
980 default :
981 {
982 rc = ERROR_PATH_NOT_FOUND;
983 }
984 }
985 if (rc)
986 {
987 break;
988 }
989 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
990 log("NdpQueryPathInfo smbwrp_getattr for <%s>\n", path);
991 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
992 if (rc)
993 {
994 switch (rc)
995 {
996 case NO_ERROR :
997 case ERROR_FILE_NOT_FOUND:
998 case ERROR_PATH_NOT_FOUND:
999 case ERROR_ACCESS_DENIED:
1000 case ERROR_INVALID_PARAMETER:
1001 break;
1002 default :
1003 {
1004 rc = ERROR_PATH_NOT_FOUND;
1005 }
1006 }
1007 rc =rc ? rc : ERROR_INVALID_PARAMETER;
1008 }
1009 else
1010 {
1011 finfo.easize = -1;
1012 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1013 }
1014 if (rc == ERROR_FILE_NOT_FOUND)
1015 {
1016 // now try the upper path
1017 char * p = ph->fsphStrChr(finfo.fname, '\\');
1018 if (p && p > finfo.fname)
1019 {
1020 *p = 0;
1021 rc = smbwrp_getattr( &pRes->srv, pConn->cli, &finfo);
1022 if (rc)
1023 {
1024 rc = rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER;
1025 }
1026 }
1027 }
1028 } while (0);
1029 log("NdpQueryPathInfo <%s> (%s) %d\n", szPath, path, rc);
1030 retry = rc && !retry;
1031
1032 } while (retry);
1033
1034 return rc;
1035}
1036
1037// -------------------------------------------------------------
1038
1039int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
1040{
1041 Connection *pConn = (Connection *)conn;
1042 Resource *pRes = pConn->pRes;
1043 int rc = NO_ERROR, count = 0;
1044 unsigned long action;
1045 char *mask = "*";
1046 char dir[CCHMAXPATH+1] = {0};
1047 char path[CCHMAXPATH+1] = {0};
1048 smbwrp_fileinfo * data;
1049 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1050 filelist_state state;
1051 char * p;
1052
1053 debug_printf("NdpFindStart in\n");
1054
1055 StrNCpy(dir, szPath, sizeof(dir) - 1);
1056 if (pel)
1057 {
1058 mask = pel->name;
1059 dir[StrLen(szPath) - pel->length] = 0;
1060 }
1061 action = StrLen(dir) - 1;
1062 if (dir[action] == '\\')
1063 {
1064 dir[action] = 0;
1065 }
1066 rc = pathparser(pRes, pConn, dir, path);
1067 if (rc)
1068 {
1069 return rc;
1070 }
1071 action = StrLen(path) - 1;
1072 if (path[action] != '\\')
1073 {
1074 StrNCat(path, "\\", sizeof(path) - 1);
1075 }
1076 StrCpy(dir, path);
1077 StrNCat(path, mask, sizeof(path) - 1);
1078
1079 // this structure will be used by libsmb callbacks, so we store here all we need
1080 // to fill netdrive structures
1081 state.pConn = pConn;
1082 state.plist = plist;
1083 state.ulAttribute = ulAttribute;
1084 strcpy( state.dir, dir);
1085 strcpy( state.dir_mask, mask);
1086 strcpy( state.mask, path);
1087 p = getlastslash(state.mask);
1088 if (p)
1089 {
1090 *(p + 1) = '*';
1091 *(p + 2) = 0;
1092 }
1093 else
1094 {
1095 strcpy(state.mask, "\\*");
1096 }
1097 rc = smbwrp_filelist( &pRes->srv, pConn->cli, &state);
1098
1099 log("NdpFindStart <%s> (%s) cnt %d %d\n", szPath, path, count, rc);
1100
1101 return rc;
1102}
1103
1104int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1105{
1106// log("NdpDeletePathInfo %d\n", 0);
1107 return NO_ERROR;
1108}
1109
1110int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1111{
1112 log("NdpRefresh <%s> %d\n", path, 0);
1113 return NO_ERROR;
1114}
1115
1116int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1117{
1118 // The plugin do not have to deallocate anything
1119 // because resource data did not contain any pointers
1120 // to plugins data.
1121 // Data stored by fsphSetResourceData will be
1122 // deallocated by NetDrive.
1123
1124 log("NdpDicardresourceData %d\n", 0);
1125 return NO_ERROR;
1126}
1127
1128int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1129{
1130 Connection *pConn = (Connection *)conn;
1131 Resource *pRes = pConn->pRes;
1132 int rc = 0;
1133 unsigned long action;
1134 char path[CCHMAXPATH+1] = {0};
1135 smbwrp_fileinfo finfo;
1136
1137 debug_printf("NdpSetPathInfo in FIXME\n");
1138
1139 do {
1140 rc = pathparser(pRes, pConn, szPathName, path);
1141 if (rc)
1142 {
1143 break;
1144 }
1145
1146 MemSet(&finfo, 0, sizeof(finfo));
1147
1148 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1149 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(finfo.mtime));
1150 finfo.attr = pfi->stat.attrFile & 0x37;
1151 rc = smbwrp_setattr(pConn->cli, &finfo);
1152 } while (0);
1153 log("NdpSetPathInfo <%s> (%s) %d\n", szPathName, path, rc);
1154
1155 return rc;
1156}
1157
1158int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1159{
1160 int rc = 0;
1161 FEA * pfea;
1162 FEA * pfeadest;
1163 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1164
1165 size = pFEASrc->cbList;
1166 pfea = pFEASrc->list;
1167 pfeadest = pFEAList->list;
1168 dsize = pFEAList->cbList;
1169//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1170 while (done < size)
1171 {
1172 char * name = (char *)(pfea + 1);
1173 int insert = 1;
1174 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1175 {
1176 GEA * pgea = pGEAList->list;
1177 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1178 insert = 0;
1179 while (done < size)
1180 {
1181//log("comp <%s> <%s>\n", name, pgea->szName);
1182 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1183 {
1184 insert = 1;
1185 break;
1186 }
1187 done += pgea->cbName + 2;
1188 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1189 }
1190 }
1191 if (insert)
1192 {
1193 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1194 if (ddone <= dsize)
1195 {
1196 pfeadest->cbName = pfea->cbName;
1197 pfeadest->cbValue = pfea->cbValue;
1198 pfeadest->fEA = 0;
1199 StrCpy((char *)(pfeadest + 1), name);
1200 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1201 pfeadest = (FEA *)((char *)pFEAList + ddone);
1202 }
1203 }
1204 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1205//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);
1206 pfea = (FEA *)((char *)pFEASrc + done);
1207 }
1208 pFEAList->cbList = ddone;
1209 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1210 {
1211 rc = ERROR_BUFFER_OVERFLOW;
1212 }
1213 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1214 return rc;
1215}
1216
1217int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1218{
1219 Connection *pConn = (Connection *)conn;
1220 Resource *pRes = pConn->pRes;
1221 int rc = 0;
1222 unsigned long action;
1223 char * path = NULL;
1224 FEALIST * pFEASrc;
1225 NDDATABUF fdata = {0};
1226 smbwrp_fileinfo *finfo;
1227 char pBuffer[64*1024];
1228
1229 if (!pfi || !pfi->pszName || !pFEAList)
1230 {
1231 return ERROR_EAS_NOT_SUPPORTED;
1232 }
1233 if (!pRes->easupport)
1234 {
1235 return ERROR_EAS_NOT_SUPPORTED;
1236 }
1237
1238 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1239 if (rc || !fdata.ulSize || !fdata.pData)
1240 {
1241 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1242 return ERROR_EAS_NOT_SUPPORTED;
1243 }
1244 finfo = (smbwrp_fileinfo *)fdata.pData;
1245 path = finfo->fname;
1246
1247 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1248
1249 do {
1250 rc = smbwrp_listea( pConn->cli, path, pBuffer, sizeof( pBuffer));
1251 pFEASrc = (FEALIST*) pBuffer;
1252 if (rc)
1253 {
1254 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1255 switch (rc)
1256 {
1257 case ERROR_FILE_NOT_FOUND :
1258 case ERROR_PATH_NOT_FOUND :
1259 {
1260 pFEAList->cbList = sizeof(pFEAList->cbList);
1261 rc = NO_ERROR;
1262 } break;
1263 case ERROR_BUFFER_OVERFLOW :
1264 {
1265 pFEAList->cbList = pFEASrc->cbList;
1266 } break;
1267 default :
1268 {
1269 rc = ERROR_EAS_NOT_SUPPORTED;
1270 }
1271 }
1272 }
1273 else
1274 {
1275 rc = buildFEALIST((FEALIST *)pFEASrc, pGEAList, pFEAList);
1276 }
1277 } while (0);
1278 log("NdpEAQuery <%s> %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList);
1279
1280 return rc;
1281}
1282
1283int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1284{
1285 Connection *pConn = (Connection *)conn;
1286 Resource *pRes = pConn->pRes;
1287 int rc = 0;
1288 char * path;
1289 unsigned long action;
1290 NDDATABUF fdata = {0};
1291 smbwrp_fileinfo *finfo;
1292
1293 log("NdpEASet in\n");
1294
1295 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1296 {
1297 return ERROR_EAS_NOT_SUPPORTED;
1298 }
1299 if (!pRes->easupport)
1300 {
1301 return ERROR_EAS_NOT_SUPPORTED;
1302 }
1303
1304 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1305 if (rc || !fdata.ulSize || !fdata.pData)
1306 {
1307 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1308 return ERROR_EAS_NOT_SUPPORTED;
1309 }
1310 finfo = (smbwrp_fileinfo *)fdata.pData;
1311 path = finfo->fname;
1312
1313 do {
1314 // got FEA there
1315 FEA * pfea;
1316 unsigned long done = sizeof(long);
1317 pfea = pFEAList->list;
1318 while (done < pFEAList->cbList)
1319 {
1320 rc = smbwrp_setea(pConn->cli, path, (char*)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1321 if (rc)
1322 {
1323 break;
1324 }
1325 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1326 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1327 }
1328 } while (0);
1329 log("NdpEASet %d\n", rc);
1330
1331 return rc;
1332}
1333
1334int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1335{
1336 Connection *pConn = (Connection *)conn;
1337 Resource *pRes = pConn->pRes;
1338 int rc = 0;
1339 unsigned long action;
1340 char * path = NULL;
1341 FEALIST * pfealist;
1342 NDDATABUF fdata = {0};
1343 smbwrp_fileinfo *finfo;
1344 char pBuffer[64*1024];
1345 int easize;
1346
1347 if (!pfi || !pulEASize)
1348 {
1349 return ERROR_EAS_NOT_SUPPORTED;
1350 }
1351 if (!pRes->easupport)
1352 {
1353 return ERROR_EAS_NOT_SUPPORTED;
1354 }
1355
1356 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1357 if (rc || !fdata.ulSize || !fdata.pData)
1358 {
1359 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1360 return ERROR_EAS_NOT_SUPPORTED;
1361 }
1362 finfo = (smbwrp_fileinfo *)fdata.pData;
1363 easize = finfo->easize;
1364 finfo->easize = -1;
1365 path = finfo->fname;
1366 if (easize >= 0)
1367 {
1368 *pulEASize = easize;
1369 log("NdpEASize <%s> cached %d\n", path, easize);
1370 return NO_ERROR;
1371 }
1372
1373 log("NdpEASize in <%s> \n", path);
1374
1375 do {
1376 rc = smbwrp_listea(pConn->cli, path, pBuffer, sizeof( pBuffer));
1377 pfealist = (FEALIST*)pBuffer;
1378 if (rc)
1379 {
1380 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1381 switch (rc)
1382 {
1383 case ERROR_FILE_NOT_FOUND :
1384 case ERROR_PATH_NOT_FOUND :
1385 {
1386 pfealist->cbList = sizeof(pfealist->cbList);
1387 } /* Fall through */
1388 case ERROR_BUFFER_OVERFLOW :
1389 {
1390 rc = NO_ERROR;
1391 } break;
1392 default :
1393 {
1394 rc = ERROR_EAS_NOT_SUPPORTED;
1395 }
1396 }
1397 }
1398 *pulEASize = pfealist->cbList;
1399 } while (0);
1400 log("NdpEASize <%s> %d %d\n", pfi->pszName, *pulEASize, rc);
1401
1402 return rc;
1403}
1404
1405int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1406{
1407 Connection *pConn = (Connection *)conn;
1408 Resource *pRes = pConn->pRes;
1409 int rc = 0;
1410 unsigned long action;
1411 char path[CCHMAXPATH+1] = {0};
1412
1413 log("NdpSetCurrentDir in\n");
1414
1415 do {
1416 rc = pathparser(pRes, pConn, szPath, path);
1417 if (rc)
1418 {
1419 break;
1420 }
1421
1422 rc = smbwrp_chdir(&pRes->srv, pConn->cli, path);
1423 } while (0);
1424 log("NdpSetCurrentDir <%s> (%s) %d\n", szPath, path, rc);
1425
1426 return rc;
1427}
1428
1429int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1430{
1431 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1432 return ERROR_CANNOT_COPY;
1433}
1434
1435int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1436{
1437 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1438 return ERROR_CANNOT_COPY;
1439}
1440
1441int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1442{
1443 Connection *pConn = (Connection *)conn;
1444 Resource *pRes = pConn->pRes;
1445 int rc = 0;
1446 unsigned long action;
1447 char path[CCHMAXPATH+1] = {0};
1448
1449 log("NdpForceDelete in\n");
1450
1451 do {
1452 rc = pathparser(pRes, pConn, szFile, path);
1453 if (rc)
1454 {
1455 break;
1456 }
1457
1458 rc = smbwrp_unlink(pConn->cli, path);
1459 } while (0);
1460 log("NdpForceDelete <%s> (%s) %d\n", szFile, path, rc);
1461
1462 return rc;
1463}
1464
1465int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1466{
1467 Connection *pConn = (Connection *)conn;
1468 Resource *pRes = pConn->pRes;
1469 int rc = 0;
1470 unsigned long action;
1471 char path[CCHMAXPATH+1] = {0};
1472
1473 log("NdpCreateDir in\n");
1474
1475 do {
1476 rc = pathparser(pRes, pConn, szDirName, path);
1477 if (rc)
1478 {
1479 break;
1480 }
1481
1482 rc = smbwrp_mkdir(pConn->cli, path);
1483 } while (0);
1484 log("NdpCreateDir <%s> (%s) %d\n", szDirName, path, rc);
1485
1486 return rc;
1487}
1488
1489int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1490{
1491 Connection *pConn = (Connection *)conn;
1492 Resource *pRes = pConn->pRes;
1493 int rc = 0;
1494 unsigned long action;
1495 char path[CCHMAXPATH+1] = {0};
1496
1497 log("NdpDeleteDir in\n");
1498
1499 do {
1500 rc = pathparser(pRes, pConn, szDir, path);
1501 if (rc)
1502 {
1503 break;
1504 }
1505
1506 rc = smbwrp_rmdir(pConn->cli, path);
1507 } while (0);
1508 log("NdpDeleteDir <%s> (%s) %d\n", szDir, path, rc);
1509
1510 return rc;
1511}
1512
1513int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1514{
1515 Connection *pConn = (Connection *)conn;
1516 Resource *pRes = pConn->pRes;
1517 int rc = 0;
1518 unsigned long action;
1519 char src[CCHMAXPATH+1] = {0};
1520 int l1, l2;
1521 char * p = szDst;
1522
1523 log("NdpMove in from <%s> to <%s>\n", szSrc, szDst);
1524
1525 do
1526 {
1527 rc = pathparser(pRes, pConn, szSrc, src);
1528 if (rc)
1529 {
1530 break;
1531 }
1532 l1 = StrLen(szSrc);
1533 l2 = StrLen(src);
1534 if (l1 > l2)
1535 {
1536 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1537 {
1538 // the file moved accross different shares or servers or workgroups
1539 rc = ERROR_WRITE_PROTECT;
1540 break;
1541 }
1542 p = szDst + l1 - l2 + 1;
1543 }
1544 //pConn->mem[CCHMAXPATH + 1] = '\\';
1545 rc = smbwrp_rename(pConn->cli, src, p);
1546 } while (0);
1547 log("NdpMove <%s> -> <%s> (%s) %d\n", szSrc, szDst, src, rc);
1548
1549 return rc;
1550}
1551
1552int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1553{
1554 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1555 return ERROR_WRITE_PROTECT;
1556}
1557
1558
1559int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1560{
1561 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1562}
1563
1564int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1565{
1566 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1567}
1568
1569int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1570{
1571 Resource *pRes = pConn->pRes;
1572 unsigned long action;
1573 int rc = 0;
1574 char path[CCHMAXPATH+1] = {0};
1575
1576 log("smbopen in %d\n", pConn->file.fd);
1577
1578 do {
1579 if (pConn->file.fd > 0)
1580 {
1581 rc = ERROR_TOO_MANY_OPEN_FILES;
1582 break;
1583 }
1584
1585 rc = pathparser(pRes, pConn, szFileName, path);
1586 if (rc)
1587 {
1588 break;
1589 }
1590
1591 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1592 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1593 flags |= O_BINARY;
1594 switch (ulOpenMode & 3)
1595 {
1596 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1597 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1598 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1599 default : flags |= O_RDWR;
1600 }
1601 pConn->file.openmode = flags;
1602 pConn->file.openattr = ulAttribute & 0x37;
1603 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1604 rc = smbwrp_open(pConn->cli, &pConn->file);
1605 } while (0);
1606 log("smbopen <%s> (%s) %08x %08x %08x %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->file.fd);
1607 if (!rc && pFEAList)
1608 {
1609 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1610 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1611 }
1612
1613 return rc;
1614}
1615
1616int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1617{
1618 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1619}
1620
1621int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1622{
1623 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1624}
1625
1626int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1627{
1628// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1629 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1630}
1631
1632int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1633{
1634 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1635}
1636
1637int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1638{
1639 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1640 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1641}
1642
1643int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1644{
1645 Connection *pConn = (Connection *)conn;
1646 Resource *pRes = pConn->pRes;
1647 int rc = 0;
1648 unsigned long action;
1649
1650 smbwrp_fileinfo finfo;
1651 char path[CCHMAXPATH+1] = {0};
1652
1653 log("NdpSetFileAttribute in\n");
1654 do {
1655 rc = pathparser(pRes, pConn, szFileName, path);
1656 if (rc)
1657 {
1658 break;
1659 }
1660
1661 MemSet(&finfo, 0, sizeof(finfo));
1662 StrNCpy(finfo.fname, path, sizeof(finfo.fname) - 1);
1663 finfo.attr = usAttr & 0x37;
1664 rc = smbwrp_setattr(pConn->cli, &finfo);
1665 } while (0);
1666 log("NdpSetFileAttribute <%s> (%s) %04x %d\n", szFileName, path, usAttr, rc);
1667
1668 return rc;
1669}
1670
1671int APIENTRY NdpFlush (HRESOURCE resource)
1672{
1673 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1674 return ERROR_NOT_SUPPORTED;
1675}
1676
1677int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1678{
1679 log("NdpIOCTL <%s> %d\n", path, function);
1680
1681 if (in && insize > 4096)
1682 {
1683 char out[4096];
1684 sprintf (out, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
1685 *poutlen = strlen(out);
1686 strcpy (in, out);
1687 return NO_ERROR;
1688 }
1689
1690 return ERROR_NOT_SUPPORTED;
1691}
1692
1693int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1694{
1695 Connection *pConn = (Connection *)conn;
1696 Resource *pRes = pConn->pRes;
1697 int rc = 0;
1698 unsigned long action;
1699 smbwrp_fileinfo finfo;
1700
1701 debug_printf("NdpFileQueryInfo in\n");
1702 do {
1703 if (pConn->file.fd < 0 || !*pConn->file.fname)
1704 {
1705 rc = ERROR_INVALID_HANDLE;
1706 break;
1707 }
1708 StrNCpy(finfo.fname, pConn->file.fname, sizeof(finfo.fname) - 1);
1709 rc = smbwrp_fgetattr(pConn->cli, &pConn->file, &finfo);
1710 if (!rc)
1711 {
1712 finfo.easize = -1;
1713 getfindinfoL(pConn, plist, &finfo, 0, NULL);
1714 }
1715 } while (0);
1716 log("NdpFileQueryInfo <%s> %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc);
1717
1718 return rc;
1719}
1720
1721int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1722{
1723 Connection *pConn = (Connection *)conn;
1724 Resource *pRes = pConn->pRes;
1725 int rc = 0;
1726 unsigned long action;
1727 char pBuffer[64*1024];
1728 FEALIST * pFEASrc;
1729
1730 if (!pFEAList)
1731 {
1732 return ERROR_EAS_NOT_SUPPORTED;
1733 }
1734 if (!pRes->easupport)
1735 {
1736 return ERROR_EAS_NOT_SUPPORTED;
1737 }
1738
1739 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
1740 do {
1741 if (pConn->file.fd < 0)
1742 {
1743 rc = ERROR_INVALID_HANDLE;
1744 break;
1745 }
1746 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof( pBuffer));
1747 pFEASrc = (FEALIST *) pBuffer;
1748 if (rc)
1749 {
1750 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1751 switch (rc)
1752 {
1753 case ERROR_FILE_NOT_FOUND :
1754 case ERROR_PATH_NOT_FOUND :
1755 {
1756 pFEAList->cbList = sizeof(pFEAList->cbList);
1757 rc = NO_ERROR;
1758 } break;
1759 case ERROR_BUFFER_OVERFLOW :
1760 {
1761 pFEAList->cbList = pFEASrc->cbList;
1762 } break;
1763 default :
1764 {
1765 rc = ERROR_EAS_NOT_SUPPORTED;
1766 }
1767 }
1768 }
1769 else
1770 {
1771 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1772 }
1773 } while (0);
1774 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);
1775
1776 return rc;
1777}
1778
1779int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
1780{
1781 Connection *pConn = (Connection *)conn;
1782 Resource *pRes = pConn->pRes;
1783 int rc = 0;
1784 unsigned long action;
1785
1786 log("NdpFileEASet in\n");
1787
1788 if (!pFEAList || pFEAList->cbList <= sizeof(long))
1789 {
1790 return ERROR_EAS_NOT_SUPPORTED;
1791 }
1792 if (!pRes->easupport)
1793 {
1794 return ERROR_EAS_NOT_SUPPORTED;
1795 }
1796
1797 do {
1798 // got FEA there
1799 FEA * pfea;
1800 unsigned long done = sizeof(long);
1801 if (pConn->file.fd < 0)
1802 {
1803 rc = ERROR_INVALID_HANDLE;
1804 break;
1805 }
1806
1807 pfea = pFEAList->list;
1808 while (done < pFEAList->cbList)
1809 {
1810 rc = smbwrp_fsetea(pConn->cli, &pConn->file, (char *)(pfea + 1), pfea->cbValue ? (char *)(pfea + 1) + pfea->cbName + 1: NULL, pfea->cbValue);
1811 if (rc)
1812 {
1813 break;
1814 }
1815 pfea = (FEA *)((char *)(pfea + 1) + pfea->cbName + 1 + pfea->cbValue);
1816 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1817 }
1818
1819 } while (0);
1820 log("NdpFileEASet %d\n", rc);
1821
1822 return rc;
1823}
1824
1825int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
1826{
1827 Connection *pConn = (Connection *)conn;
1828 Resource *pRes = pConn->pRes;
1829 int rc = 0;
1830 unsigned long action;
1831 char path[CCHMAXPATH+1] = {0};
1832 FEALIST * pFEAList;
1833 char pBuffer[64*1024];
1834
1835 if (!pulEASize)
1836 {
1837 return ERROR_EAS_NOT_SUPPORTED;
1838 }
1839 if (!pRes->easupport)
1840 {
1841 return ERROR_EAS_NOT_SUPPORTED;
1842 }
1843
1844 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
1845 do {
1846 if (pConn->file.fd < 0)
1847 {
1848 rc = ERROR_INVALID_HANDLE;
1849 break;
1850 }
1851 rc = smbwrp_flistea(pConn->cli, &pConn->file, pBuffer, sizeof(pBuffer));
1852 pFEAList = (FEALIST*) pBuffer;
1853 if (rc)
1854 {
1855 //rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1856 switch (rc)
1857 {
1858 case ERROR_FILE_NOT_FOUND :
1859 case ERROR_PATH_NOT_FOUND :
1860 {
1861 pFEAList->cbList = sizeof(pFEAList->cbList);
1862 } /* Fall through */
1863 case ERROR_BUFFER_OVERFLOW :
1864 {
1865 rc = NO_ERROR;
1866 } break;
1867 default :
1868 {
1869 rc = ERROR_EAS_NOT_SUPPORTED;
1870 }
1871 }
1872 }
1873 *pulEASize = pFEAList->cbList;
1874 } while (0);
1875 log("NdpFileEASize %d %d\n", *pulEASize, rc);
1876
1877 return rc;
1878}
1879
1880int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
1881{
1882 Connection *pConn = (Connection *)conn;
1883 Resource *pRes = pConn->pRes;
1884 int rc = 0;
1885 unsigned long action, attrFile;
1886
1887 debug_printf("NdpFileSetInfo in\n");
1888 do {
1889 if (pConn->file.fd < 0 || !*pConn->file.fname)
1890 {
1891 rc = ERROR_INVALID_HANDLE;
1892 break;
1893 }
1894 attrFile = pfi->stat.attrFile;
1895 // deferred setinfo - on closing the file
1896 pConn->file.openattr = attrFile;
1897 fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, &(pConn->file.mtime));
1898 debug_printf("NdpFileSetInfo mtime %d\n", pConn->file.mtime);
1899 } while (0);
1900 log("NdpFileSetInfo <%s> %08x %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc);
1901
1902 return NO_ERROR;
1903}
1904
1905int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
1906{
1907 Connection *pConn = (Connection *)conn;
1908 Resource *pRes = pConn->pRes;
1909 int rc = 0;
1910 unsigned long action;
1911
1912 log("NdpFileSetFilePtrl in\n");
1913
1914 do {
1915 if (pConn->file.fd < 0)
1916 {
1917 rc = ERROR_INVALID_HANDLE;
1918 break;
1919 }
1920
1921 rc = smbwrp_lseek(pConn->cli, &pConn->file, ulMethod, llOffset);
1922 if (!rc)
1923 *pllActual = pConn->file.offset;
1924
1925 } while (0);
1926 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc);
1927
1928 return rc;
1929}
1930
1931int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
1932{
1933 LONGLONG llActual;
1934 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
1935 *pulActual = llActual & 0xFFFFFFFF;
1936 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
1937 return rc;
1938}
1939
1940int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
1941{
1942 Connection *pConn = (Connection *)conn;
1943 Resource *pRes = pConn->pRes;
1944 int rc = 0;
1945 unsigned long action;
1946
1947 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
1948
1949 do {
1950 if (pConn->file.fd < 0)
1951 {
1952 rc = ERROR_INVALID_HANDLE;
1953 break;
1954 }
1955
1956 rc = smbwrp_close(pConn->cli, &pConn->file);
1957
1958 } while (0);
1959 log("NdpFileClose %d %d\n", pConn->file.fd, rc);
1960
1961 pConn->file.fd = -1;
1962 return rc;
1963}
1964
1965int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
1966{
1967 log("NdpFileCommit %d\n", NO_ERROR);
1968 return NO_ERROR;
1969}
1970
1971
1972int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
1973{
1974 int rc = NdpFileNewSizeL(conn, handle, ulLen);
1975 log("NdpFileNewSize %ld %d\n", ulLen, rc);
1976 return rc;
1977}
1978
1979int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
1980{
1981 Connection *pConn = (Connection *)conn;
1982 Resource *pRes = pConn->pRes;
1983 int rc = 0;
1984 unsigned long action;
1985
1986 log("NdpFileNewSizeL in\n");
1987
1988 do {
1989 if (pConn->file.fd < 0)
1990 {
1991 rc = ERROR_INVALID_HANDLE;
1992 break;
1993 }
1994
1995 rc = smbwrp_setfilesize(pConn->cli, &pConn->file, llLen);
1996
1997 } while (0);
1998 log("NdpFileNewSizeL <%s> %lld %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc);
1999
2000 return rc;
2001}
2002
2003int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2004{
2005 Connection *pConn = (Connection *)conn;
2006 Resource *pRes = pConn->pRes;
2007 int rc = 0;
2008 unsigned long done = 0;
2009 unsigned long onedone;
2010 unsigned long action;
2011
2012 log("NdpFileRead in\n");
2013
2014 do {
2015 if (pConn->file.fd < 0)
2016 {
2017 rc = ERROR_INVALID_HANDLE;
2018 break;
2019 }
2020 rc = smbwrp_read(pConn->cli, &pConn->file, pBuffer, ulRead, pulActual);
2021 //*pulActual = ulRead;
2022 //DosSleep(0);
2023
2024 } while (0);
2025 log("NdpFileRead <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc);
2026
2027 return rc;
2028}
2029
2030int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2031{
2032 Connection *pConn = (Connection *)conn;
2033 Resource *pRes = pConn->pRes;
2034 int rc = 0;
2035 unsigned long done = 0;
2036 unsigned long onedone;
2037 unsigned long action;
2038
2039 log("NdpFileWrite in\n");
2040
2041 do {
2042 if (pConn->file.fd < 0)
2043 {
2044 rc = ERROR_INVALID_HANDLE;
2045 break;
2046 }
2047 rc = smbwrp_write(pConn->cli, &pConn->file, pBuffer, ulWrite, pulActual);
2048
2049 } while (0);
2050 log("NdpFileWrite <%s> %lu %lu %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc);
2051
2052 return rc;
2053}
2054
Note: See TracBrowser for help on using the repository browser.