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

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

Use kBuild to drive the build system, it makes life easier.

  • 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\n", 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.