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

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

Merged daemon code, now the plugin calls directly samba client library (still using smbrp code).

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