source: branches/client-3.0/src/ndpsmb.c

Last change on this file was 1014, checked in by Paul Smedley, 8 years ago

Update rc codes for EA Set/query fucntions, fixes some wps copy issues to shares that don't support EA, but the share has EA support enabled

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