source: trunk/samba-3.0.25pre1/source/ndpsmb/ndpsmb.c@ 7

Last change on this file since 7 was 7, checked in by Yuri Dario, 18 years ago

Fixes EA handling, closes ticket:5.

  • Property svn:eol-style set to native
File size: 60.6 KB
Line 
1#define NDPL_LARGEFILES
2#define INCL_LONGLONG
3#include <ndextpl2.h>
4#include <smbwrp.h>
5#include <smbcd.h>
6
7#define NULL ((void *)0)
8
9#include <mydebug.h>
10
11int StrLen(char * s)
12{
13 char * p;
14 if (!s)
15 {
16 return 0;
17 }
18 for (p = s; *p; p++);
19 return (p - s);
20}
21
22char * StrNCat(char *dst, const char *src, int count)
23{
24 int i;
25 if (!dst || !src || count <= 0)
26 {
27 return dst;
28 }
29 for (i = 0; dst[i]; i++);
30 for (;i < count && *src; i++, src++)
31 {
32 dst[i] = *src;
33 }
34 dst[i] = 0;
35 return dst;
36}
37
38char * StrNCpy(char *dst, const char *src, int count)
39{
40 if (!dst || !src || count <= 0)
41 {
42 return dst;
43 }
44 *dst = 0;
45 return StrNCat(dst, src, count);
46}
47
48char * StrCpy(char *dst, const char *src)
49{
50 char * p;
51 if (!dst || !src)
52 {
53 return dst;
54 }
55 p = dst;
56 while (*p++ = *src++);
57 return dst;
58}
59
60char * StrCat(char *dst, const char *src)
61{
62 int i;
63 if (!dst || !src)
64 {
65 return dst;
66 }
67 for (i = 0; dst[i]; i++);
68 for (; *src; i++, src++)
69 {
70 dst[i] = *src;
71 }
72 dst[i] = 0;
73 return dst;
74}
75
76void * MemCpy(void * dst, const void * src, int len)
77{
78 int i;
79 if (!src || !dst || len <= 0)
80 {
81 return dst;
82 }
83 for (i = 0; i < len; i++)
84 {
85 ((char *)dst)[i] = ((char *)src)[i];
86 }
87 return dst;
88}
89
90void *MemSet(void *dst, char c, int len)
91{
92 int i;
93 if (!dst || len <= 0)
94 {
95 return dst;
96 }
97 for (i = 0; i < len; i++)
98 {
99 ((char *)dst)[i] = c;
100 }
101 return dst;
102}
103
104/* uppercased type of resource */
105const char *NdpTypes[] =
106{
107 "SMBFS",
108 NULL
109}
110;
111
112/* Properties of supported resource types */
113
114/* Properties of resource */
115static const NDPROPERTYINFO smbProperties[] =
116{
117 {ND_PROP_STRING, 0, "WORKGROUP", ""},
118 {ND_PROP_STRING, 0, "SERVER", ""},
119 {ND_PROP_STRING, 0, "SHARE", ""},
120 {ND_PROP_STRING, 0, "USER", "guest"},
121 {ND_PROP_STRING, 0, "PASSWORD", ""},
122 {ND_PROP_STRING, 0, "MASTER", "WORKGROUP"},
123 { ND_PROP_ULONG, 0, "MASTERTYPE", "1"},
124 { ND_PROP_ULONG, 0, "MEMLEN", "2"},
125 {ND_PROP_STRING, 0, "LOGFILE", ""},
126 { ND_PROP_ULONG, 0, "LOGLEVEL", "0"},
127 { ND_PROP_ULONG, 0, "EASUPPORT", "1"},
128 {ND_PROP_STRING, 0, NULL, NULL}
129};
130
131
132/* Exported array of properties */
133const NDPROPERTYINFO *NdpPropertiesInfo[] =
134{
135 smbProperties
136};
137
138
139static PLUGINHELPERTABLE2L *ph;
140static int ifL;
141
142int APIENTRY NdpPluginLoad (PLUGINHELPERTABLE2L *pPHT)
143{
144 int rc;
145 HPIPE pipe;
146 unsigned long action;
147 ph = pPHT;
148 ifL = 0;
149/*
150 if (ph->cb < sizeof (PLUGINHELPERTABLE2))
151 {
152 return ERROR_INVALID_FUNCTION;
153 }
154*/
155 if (ph->cb >= sizeof (PLUGINHELPERTABLE2L))
156 {
157 ifL = 1;
158 }
159 log("Working with %s bit fileio NDFS\n", ifL ? "64" : "32");
160 return NO_ERROR;
161}
162
163
164int APIENTRY NdpPluginFree (void)
165{
166 return NO_ERROR;
167}
168
169typedef struct _Resource
170{
171 /* NetDrive information */
172 NDPROPERTYHANDLE properties; /* access handle for the properties */
173 int rootlevel;
174 unsigned long memlen;
175 unsigned long objany;
176 smbwrp_server srv;
177 char logfile[CCHMAXPATH + 1];
178 char loglevel;
179 int easupport;
180} Resource;
181
182typedef struct _Connection
183{
184 Resource *pRes;
185 HPIPE pipe;
186 char * mem;
187 int clientpid;
188 int rc;
189 smbwrp_server srv;
190 smbwrp_file file;
191} Connection;
192
193int openpipe(Resource * pRes, HPIPE * ppipe)
194{
195 HPIPE pipe = 0;
196 unsigned long rc = 0, action;
197
198 if (!pRes)
199 {
200 return ERROR_INVALID_PARAMETER;
201 }
202
203 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
204 log("DosOpen1 rc %d\n", rc);
205 if (rc)
206 {
207 unsigned long sid = 0, pid = 0;
208 STARTDATA sd;
209 char params[CCHMAXPATH * 2] = {0};
210
211 MemSet(&sd, 0, sizeof(sd));
212 sd.Length = sizeof(sd);
213 sd.Related = SSF_RELATED_INDEPENDENT;
214 sd.FgBg = SSF_FGBG_BACK;
215 sd.PgmName = EXECNAME;
216 if (pRes->loglevel)
217 {
218 char level[2];
219 level[0] = pRes->loglevel + '0';
220 level[1] = 0;
221 StrNCat(params, " -d ", sizeof(params) - 1);
222 StrNCat(params, level, sizeof(params) - 1);
223 }
224 if (*pRes->logfile)
225 {
226 StrNCat(params, " -l ", sizeof(params) - 1);
227 StrNCat(params, pRes->logfile, sizeof(params) - 1);
228 }
229 log("params <%s>\n", params);
230 sd.PgmInputs = *params ? params : NULL;
231 sd.SessionType = SSF_TYPE_WINDOWABLEVIO;
232 rc = DosStartSession(&sd, &sid, &pid);
233 log("smbcd startsession pid %d sid %d rc %d\n", pid, sid, rc);
234 if (rc == ERROR_SMG_INVALID_CALL)
235 {
236 // ndfs started ndctl detached, so we have to use dosexecpgm
237 char failed[CCHMAXPATH + 1] = {0};
238 RESULTCODES res = {0};
239 char * p = params;
240 StrCpy(p, EXECNAME);
241 p += StrLen(p) + 1;
242 if (*pRes->logfile)
243 {
244 StrCpy(p, "-l ");
245 StrNCat(p, pRes->logfile, sizeof(params) - (p - (char *)params));
246 p += StrLen(p) + 1;
247 if (pRes->loglevel)
248 {
249 char level[2];
250 level[0] = pRes->loglevel + '0';
251 level[1] = 0;
252 StrCpy(p, "-d ");
253 StrNCat(p, level, sizeof(params) - (p - (char *)params));
254 p += StrLen(p) + 1;
255 }
256 }
257 else
258 {
259 StrCpy(p, "-q");
260 p += StrLen(p) + 1;
261 }
262 *p = 0;
263 rc = DosExecPgm(failed, sizeof(failed), EXEC_BACKGROUND, params, NULL, &res, EXECNAME);
264 log("smbcd DosExecPgm codeTerminate %d codeResult %d rc %d\n", res.codeTerminate, res.codeResult, rc);
265 }
266 if (!rc)
267 {
268 DosSleep(500);
269 rc = DosOpen(PIPENAME, &pipe, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE, NULL);
270 log("DosOpen2 rc %d\n", rc);
271 }
272 }
273 if (!rc)
274 {
275 if (ppipe)
276 {
277 *ppipe = pipe;
278 }
279 else
280 {
281 DosClose(pipe);
282 }
283 }
284 return rc;
285}
286
287
288void getfindinfo(Connection * pConn, FILEFINDBUF3 * stat, smbwrp_fileinfo * finfo)
289{
290 char * name = ph->fsphStrRChr(finfo->fname, '\\');
291 if (name)
292 {
293 name++;
294 }
295 else
296 {
297 name = finfo->fname;
298 }
299 if (!*name)
300 {
301 name = pConn->srv.share_name;
302 }
303 StrNCpy(stat->achName, name, CCHMAXPATHCOMP - 1);
304 stat->cbFile = finfo->size;
305 stat->cbFileAlloc = stat->cbFile;
306 stat->oNextEntryOffset = 0ul;
307 stat->cchName = StrLen(stat->achName);
308 stat->attrFile = (finfo->attr & 0x37);
309
310 ph->fsphUnixTimeToDosDate(finfo->mtime, &stat->fdateLastWrite, &stat->ftimeLastWrite);
311 ph->fsphUnixTimeToDosDate(finfo->ctime, &stat->fdateCreation, &stat->ftimeCreation);
312 ph->fsphUnixTimeToDosDate(finfo->atime, &stat->fdateLastAccess, &stat->ftimeLastAccess);
313}
314
315int getfindinfoL(Connection * pConn, void * plist, smbwrp_fileinfo * finfo, ULONG ulAttribute, char * mask)
316{
317 FILESTATUS3L stat = {0};
318 char * name = ph->fsphStrRChr(finfo->fname, '\\');
319 if (name)
320 {
321 name++;
322 }
323 else
324 {
325 name = finfo->fname;
326 }
327 if (!*name)
328 {
329 name = pConn->srv.share_name;
330 }
331 if (mask && (!ph->fsphAttrMatch(ulAttribute, finfo->attr & 0x37) || !ph->fsphWildMatch(mask, name, ND_IGNORE_CASE)))
332 {
333 return 0;
334 }
335
336 stat.cbFile = finfo->size;
337 stat.cbFileAlloc = stat.cbFile;
338 stat.attrFile = (finfo->attr & 0x37);
339
340 ph->fsphUnixTimeToDosDate(finfo->mtime, &stat.fdateLastWrite, &stat.ftimeLastWrite);
341 ph->fsphUnixTimeToDosDate(finfo->ctime, &stat.fdateCreation, &stat.ftimeCreation);
342 ph->fsphUnixTimeToDosDate(finfo->atime, &stat.fdateLastAccess, &stat.ftimeLastAccess);
343
344 ph->fsphAddFile32L(plist, &stat, name, StrLen(name), finfo, sizeof(*finfo), 0);
345 return 1;
346}
347
348
349/* accept parameters in form
350 * [filename][;name=filename]
351 */
352int initResource (Resource *pRes)
353{
354 int rc = NO_ERROR;
355 unsigned long t;
356 const unsigned char * q = NULL;
357 HPIPE pipe;
358
359 pRes->memlen = 1 << 18;
360 pRes->rootlevel = 0;
361 *pRes->logfile = 0;
362 pRes->loglevel = 0;
363 pRes->easupport = 1;
364
365 t = 0, q = NULL;
366 rc = ph->fsphQueryStringProperty (pRes->properties, "WORKGROUP", &q, &t);
367 if (!rc && t && *q)
368 {
369 StrNCpy(pRes->srv.workgroup, q, sizeof(pRes->srv.workgroup) - 1);
370 pRes->rootlevel = 1;
371 }
372
373 t = 0, q = NULL;
374 rc = ph->fsphQueryStringProperty (pRes->properties, "SERVER", &q, &t);
375 if (!rc && t && *q)
376 {
377 StrNCpy(pRes->srv.server_name, q, sizeof(pRes->srv.server_name) - 1);
378 pRes->rootlevel = 2;
379 }
380
381 t = 0, q = NULL;
382 rc = ph->fsphQueryStringProperty (pRes->properties, "SHARE", &q, &t);
383 if (!rc && t && *q)
384 {
385 StrNCpy(pRes->srv.share_name, q, sizeof(pRes->srv.share_name) - 1);
386 pRes->rootlevel = 3;
387 }
388
389 t = 0, q = NULL;
390 rc = ph->fsphQueryStringProperty (pRes->properties, "USER", &q, &t);
391 if (!rc && t && *q)
392 {
393 StrNCpy(pRes->srv.username, q, sizeof(pRes->srv.username) - 1);
394 }
395
396 t = 0, q = NULL;
397 rc = ph->fsphQueryStringProperty (pRes->properties, "PASSWORD", &q, &t);
398 if (!rc && t && *q)
399 {
400 StrNCpy(pRes->srv.password, q, sizeof(pRes->srv.password) - 1);
401 }
402
403 t = 0, q = NULL;
404 rc = ph->fsphQueryStringProperty (pRes->properties, "MASTER", &q, &t);
405 if (!rc && t && *q)
406 {
407 StrNCpy(pRes->srv.master, q, sizeof(pRes->srv.master) - 1);
408 }
409
410 t = 0, q = NULL;
411 rc = ph->fsphQueryStringProperty (pRes->properties, "LOGFILE", &q, &t);
412 if (!rc && t && *q)
413 {
414 StrNCpy(pRes->logfile, q, sizeof(pRes->logfile) - 1);
415 }
416
417 t = 0;
418 rc = ph->fsphQueryUlongProperty (pRes->properties, "LOGLEVEL", &t);
419 if (!rc)
420 {
421 if (t > 9)
422 {
423 t = 9;
424 rc = ERROR_INVALID_PARAMETER;
425 }
426 pRes->loglevel = t;
427 }
428
429 t = 0;
430 rc = ph->fsphQueryUlongProperty (pRes->properties, "MASTERTYPE", &t);
431 if (!rc)
432 {
433 if (t > 1)
434 {
435 rc = ERROR_INVALID_PARAMETER;
436 }
437 else
438 {
439 pRes->srv.ifmastergroup = t;
440 }
441 }
442
443 t = 0;
444 rc = ph->fsphQueryUlongProperty (pRes->properties, "EASUPPORT", &t);
445 if (!rc)
446 {
447 if (t > 1)
448 {
449 rc = ERROR_INVALID_PARAMETER;
450 }
451 else
452 {
453 pRes->easupport = t;
454 }
455 }
456
457 t = 0;
458 rc = ph->fsphQueryUlongProperty (pRes->properties, "MEMLEN", &t);
459 if (!rc)
460 {
461 if (t <= (pRes->easupport ? 1 : 0) || t > 10)
462 {
463 rc = ERROR_INVALID_PARAMETER;
464 }
465 else
466 {
467 pRes->memlen = t * 65536;
468 }
469 }
470
471 return rc;
472}
473
474int checkconnection(Connection * pConn)
475{
476 int rc = NO_ERROR;
477 unsigned long action;
478 smb_request req = {0};
479 smb_response resp = {0};
480 if (!pConn)
481 {
482 return ERROR_INVALID_PARAMETER;
483 }
484 log("checkconnection pconnrc %d pipe %d\n", pConn->rc, pConn->pipe);
485 if (!pConn->rc)
486 {
487 unsigned long state = 0;
488 rc = DosQueryNPHState(pConn->pipe, &state);
489 log("DosQueryNPHstate(pConn->pipe) = %d (%08x)\n", pConn->rc, pConn->pipe, rc, state);
490 if (!rc)
491 {
492 return pConn->rc;
493 }
494 }
495 // there were error on pipe, reopen it and restore connection
496 if (pConn->pipe)
497 {
498 DosClose(pConn->pipe);
499 pConn->pipe = 0;
500 }
501 rc = openpipe(pConn->pRes, &pConn->pipe);
502 if (rc)
503 {
504 log("checkconnection openpipe %d\n", rc);
505 pConn->pipe = 0;
506 DosSleep(1000);
507 return ERROR_PIPE_NOT_CONNECTED;
508 }
509 do {
510 req.request = SMBREQ_INIT;
511 req.param = (char *)0xFFFFFFFF;
512 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
513 if (pConn->rc || action < sizeof(resp) || resp.rc)
514 {
515 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
516 break;
517 }
518 pConn->clientpid = resp.value & 0xFFFF;
519 // client daemon pid changed
520 pConn->rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
521 if (pConn->rc)
522 {
523 rc = pConn->rc;
524 break;
525 }
526
527 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
528 req.request = SMBREQ_CONNECT;
529 req.param = pConn->mem;
530 req.paramlen = sizeof(pConn->srv);
531 req.length = req.paramlen;
532
533 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
534 if (pConn->rc || action < sizeof(resp) || resp.rc)
535 {
536 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
537 break;
538 }
539 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
540 rc = NO_ERROR;
541 } while (0);
542
543 if (pConn->rc && pConn->pipe)
544 {
545 DosClose(pConn->pipe);
546 pConn->pipe = 0;
547 }
548 return rc;
549}
550
551int iftestpath(char * path)
552{
553 char * p = path;
554 if (!path)
555 {
556 return 0;
557 }
558 while ((p = ph->fsphStrChr(p, 'A')) != NULL)
559 {
560 if (ph->fsphStrNCmp(p, "A.+,;=[].B", 10) == 0)
561 {
562 return 1;
563 }
564 p++;
565 }
566 return 0;
567}
568
569int pathparser(Resource *pRes, Connection * pConn, char * path, char * result)
570{
571 int rootlevel;
572 int rc = NO_ERROR;
573 if (!pRes || !path || !result)
574 {
575 return ERROR_INVALID_PARAMETER;
576 }
577 // handle special case when someone wants to test support of LFN or smth similar
578 if (iftestpath(path))
579 {
580 StrCpy(result, "\\A.+,;=[].B");
581 return NO_ERROR;
582 }
583 rootlevel = pRes->rootlevel;
584 if (*path == '\\') path++;
585 if (rootlevel < 3)
586 {
587 char * p;
588 int newlevel = 0;
589 smbwrp_server * tmp = (smbwrp_server *)pConn->mem;
590 MemCpy(tmp, &pConn->srv, sizeof(pConn->srv));
591 if (rootlevel == 0)
592 {
593 p = ph->fsphStrChr(path, '\\');
594 if (!p)
595 {
596 p = path + StrLen(path);
597 }
598 if (StrLen(tmp->workgroup) != p - path
599 || (p == path || ph->fsphStrNICmp(path, tmp->workgroup, p - path)))
600 {
601 StrNCpy(tmp->workgroup, path, p - path);
602 tmp->workgroup[p - path] = 0;
603 newlevel = 1;
604 }
605 path = *p == '\\' ? p + 1 : p;
606 rootlevel = 1;
607 }
608 if (rootlevel == 1) // root path starts from server name
609 {
610 p = ph->fsphStrChr(path, '\\');
611 if (!p)
612 {
613 p = path + StrLen(path);
614 }
615 if (StrLen(tmp->server_name) != p - path
616 || (p == path || ph->fsphStrNICmp(path, tmp->server_name, p - path)))
617 {
618 StrNCpy(tmp->server_name, path, p - path);
619 tmp->server_name[p - path] = 0;
620 newlevel = 1;
621 }
622 path = *p == '\\' ? p + 1 : p;
623 rootlevel = 2;
624 }
625 if (rootlevel == 2) // root path starts from share name
626 {
627 p = ph->fsphStrChr(path, '\\');
628 if (!p)
629 {
630 p = path + StrLen(path);
631 }
632 if (StrLen(tmp->share_name) != (p - path)
633 || (p == path || ph->fsphStrNICmp(path, tmp->share_name, p - path)))
634 {
635 StrNCpy(tmp->share_name, path, p - path);
636 tmp->share_name[p - path] = 0;
637 newlevel = 1;
638 }
639 path = *p == '\\' ? p + 1 : p;
640 }
641 if (newlevel)
642 {
643 // reconnect to server here
644 unsigned long action;
645 smb_request req = {0};
646 smb_response resp = {0};
647
648 req.request = SMBREQ_DISCONNECT;
649 req.param = pConn->mem;
650 req.length = 0;
651 req.paramlen = 0;
652
653 DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
654
655 req.request = SMBREQ_CONNECT;
656 req.param = pConn->mem;
657 req.length = pRes->memlen;
658 req.paramlen = sizeof(pConn->srv);
659
660 rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
661 if (rc || action < sizeof(resp) || resp.rc)
662 {
663 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
664 MemCpy(tmp, &pRes->srv, sizeof(pRes->srv));
665 DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
666 // TODO: what to do if the reconnect will fail ?
667 }
668 else
669 {
670 MemCpy(&pConn->srv, tmp, sizeof(pConn->srv));
671 }
672 }
673 }
674 StrCpy(result, "\\");
675 StrNCat(result, path, CCHMAXPATH);
676 return rc;
677}
678
679int APIENTRY NdpFreeResource (HRESOURCE resource)
680{
681 Resource *pRes = (Resource *)resource;
682 MemSet(&pRes->srv, 0, sizeof(pRes->srv));
683 DosFreeMem(pRes);
684 log("NdpFreeResource %d\n", NO_ERROR);
685 return NO_ERROR;
686}
687
688
689int APIENTRY NdpMountResource (HRESOURCE *presource, int type, NDPROPERTYHANDLE properties)
690{
691 int rc = NO_ERROR;
692 unsigned long objany = OBJ_ANY;
693 Resource *pRes = NULL;
694 /* since we support only 1 type of resources we do not need */
695 /* to check what the found type really is */
696 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE | objany);
697 if (rc == ERROR_INVALID_PARAMETER)
698 {
699 objany = 0;
700 rc = DosAllocMem((void **)&pRes, sizeof(Resource), PAG_COMMIT | PAG_READ | PAG_WRITE);
701 }
702 if (!rc && pRes == NULL)
703 {
704 rc = ERROR_NOT_ENOUGH_MEMORY;
705 }
706 if (!rc)
707 {
708 MemSet(pRes, 0, sizeof(Resource));
709 pRes->properties = properties;
710 pRes->objany = objany;
711 rc = initResource (pRes);
712 if (rc == NO_ERROR)
713 {
714 *presource = (HRESOURCE)pRes;
715 }
716 else
717 {
718 NdpFreeResource((HRESOURCE)pRes);
719 }
720 }
721 log("NdpMountResource %d\n", rc);
722 return rc;
723}
724
725int APIENTRY NdpCreateConnection (HRESOURCE resource, HCONNECTION *pconn)
726{
727 int rc;
728 Resource * pRes = (Resource *)resource;
729 unsigned long action;
730 smb_request req = {0};
731 smb_response resp = {0};
732 Connection *pConn = NULL;
733
734 log("NdpCreateConnection in\n");
735
736 rc = DosAllocMem((void **)&pConn, sizeof(Connection), PAG_COMMIT | PAG_READ | PAG_WRITE | pRes->objany);
737 if (!rc && pConn == NULL)
738 {
739 rc = ERROR_NOT_ENOUGH_MEMORY;
740 }
741 if (rc)
742 {
743 log("NdpCreateConnection %d\n", rc);
744 return rc;
745 }
746 MemSet(pConn, 0, sizeof(Connection));
747 pConn->pRes = pRes;
748 pConn->file.fd = -1;
749
750 do {
751 rc = openpipe(pRes, &pConn->pipe);
752 if (rc)
753 {
754 pConn->pipe = 0;
755 break;
756 }
757
758 req.request = SMBREQ_INIT;
759 req.param = (char *)0xFFFFFFFF;
760 rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
761 if (rc || action < sizeof(resp) || resp.rc)
762 {
763 return rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
764 }
765 pConn->clientpid = resp.value & 0xFFFF;
766
767 rc = DosAllocSharedMem((PPVOID)&pConn->mem, NULL, pRes->memlen, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE | pRes->objany);
768 if (rc)
769 {
770 break;
771 }
772 rc = DosGiveSharedMem(pConn->mem, pConn->clientpid, PAG_READ | PAG_WRITE);
773 if (rc)
774 {
775 break;
776 }
777
778 MemCpy(pConn->mem, &pRes->srv, sizeof(pRes->srv));
779 req.request = SMBREQ_CONNECT;
780 req.param = pConn->mem;
781 req.paramlen = sizeof(pConn->srv);
782 req.length = req.paramlen;
783
784 rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
785 if (rc || action < sizeof(resp) || resp.rc)
786 {
787 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
788 }
789 else
790 {
791 MemCpy(&pConn->srv, pConn->mem, sizeof(pConn->srv));
792 }
793 } while (0);
794 if (rc)
795 {
796 if (pConn->mem)
797 {
798 DosFreeMem(pConn->mem);
799 }
800 if (pConn->pipe)
801 {
802 DosClose(pConn->pipe);
803 }
804 MemSet(pConn, 0, sizeof(*pConn));
805 DosFreeMem(pConn);
806 pConn = NULL;
807 }
808
809 *pconn = (HCONNECTION)pConn;
810 log("NdpCreateConnection %d %d\n", rc, resp.rc);
811 return rc;
812}
813
814
815int APIENTRY NdpFreeConnection (HCONNECTION conn)
816{
817 Connection *pConn = (Connection *)conn;
818 Resource *pRes = pConn->pRes;
819
820 log("NdpFreeConnection in\n");
821 if (pConn->mem)
822 {
823 smb_request req = {0};
824 smb_response resp = {0};
825 unsigned long action;
826 if (pConn->file.fd >= 0)
827 {
828 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
829 req.request = SMBREQ_CLOSE;
830 req.param = pConn->mem;
831 req.length = sizeof(pConn->file);
832 req.paramlen = sizeof(pConn->file);
833
834 DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
835 pConn->file.fd = -1;
836 }
837
838 req.request = SMBREQ_DISCONNECT;
839 req.param = pConn->mem;
840 req.length = 0;
841 req.paramlen = 0;
842
843 DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
844
845 DosFreeMem(pConn->mem);
846 DosClose(pConn->pipe);
847 MemSet(pConn, 0, sizeof(*pConn));
848 }
849
850 DosFreeMem(pConn);
851 log("NdpFreeConnection %d\n", NO_ERROR);
852 return NO_ERROR;
853}
854
855int APIENTRY NdpRsrcCompare (HRESOURCE resource, HRESOURCE resource2)
856{
857 Resource *pRes = (Resource *)resource;
858 Resource *pRes2 = (Resource *)resource2;
859 int rc = ND_RSRC_DIFFERENT;
860
861 log("NdpRsrcCompare in\n");
862
863 if (ph->fsphStrICmp(pRes->srv.server_name, pRes2->srv.server_name) == 0
864 && ph->fsphStrICmp(pRes->srv.share_name, pRes2->srv.share_name) == 0
865 && ph->fsphStrICmp(pRes->srv.username, pRes2->srv.username) == 0
866 && ph->fsphStrICmp(pRes->srv.workgroup, pRes2->srv.workgroup) == 0)
867 {
868 // resources are equal
869 rc = ND_RSRC_EQUAL;
870 }
871
872 log("NdpRsrcCompare %d\n", rc);
873
874 return rc;
875}
876
877int APIENTRY NdpRsrcUpdate (HRESOURCE resource, HRESOURCE resource2)
878{
879 // do nothing
880 log("NdpRsrcUpdate %d\n", NO_ERROR);
881 return NO_ERROR;
882}
883
884int APIENTRY NdpRsrcQueryInfo (HRESOURCE resource, ULONG *pulFlags, void *pdata, ULONG insize, ULONG *poutlen)
885{
886 Resource *pRes = (Resource *)resource;
887 int rc = NO_ERROR;
888 char s[4096];
889
890 log("NdpRsrcQueryInfo in\n");
891
892 switch (pRes->rootlevel)
893 {
894 case 0:
895 {
896 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s \\\\@%s", ifL ? "64" : "32", pRes->srv.username);
897 } break;
898 case 1:
899 {
900 ph->fsph_snprintf(s, sizeof(s) - 1, "SMBFS%s %s: \\\\@%s", ifL ? "64" : "32", pRes->srv.workgroup, pRes->srv.username);
901 } break;
902 case 2:
903 {
904 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);
905 } break;
906 default:
907 {
908 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);
909 } break;
910 }
911 *poutlen = StrLen(s) + 1;
912 if (*poutlen > insize)
913 {
914 rc = ERROR_BUFFER_OVERFLOW;
915 }
916 else
917 {
918 MemCpy(pdata, s, *poutlen);
919 }
920
921 log("NdpRsrcQueryInfo %d\n", rc);
922
923 return rc;
924}
925
926int APIENTRY NdpRsrcQueryFSAttach (HRESOURCE resource, void *pdata, ULONG insize, ULONG *poutlen)
927{
928 ULONG ulDummy = 0;
929 /* just return the resource info string */
930 return NdpRsrcQueryInfo (resource, &ulDummy, pdata, insize, poutlen);
931}
932
933int APIENTRY NdpRsrcQueryFSAllocate (HRESOURCE resource, NDFSALLOCATE *pfsa)
934{
935 int rc = NO_ERROR, rc1;
936
937 Connection *pConn = 0;
938 smb_request req = {0};
939 smb_response resp = {0};
940 unsigned long action = 0;
941
942 log("NdpRsrcQueryFSAllocate %08x\n", pfsa);
943
944 if (!pfsa)
945 {
946 return NO_ERROR;
947 }
948
949
950 rc = NdpCreateConnection (resource, (HCONNECTION *)&pConn);
951 if (rc)
952 {
953 log("NdpCreateConnection failed rc=%d\n", rc);
954 pfsa->cSectorUnit = 1;
955 pfsa->cUnit = 123456;
956 pfsa->cUnitAvail = 123456;
957 pfsa->cbSector = 2048;
958 return rc;
959 }
960
961 MemSet(pConn->mem, 0, sizeof(FSALLOCATE));
962 req.request = SMBREQ_DSKATTR;
963 req.param = pConn->mem;
964 req.paramlen = sizeof(FSALLOCATE);
965 req.length = req.paramlen;
966
967 rc = DosTransactNPipe( pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
968 if (rc || action < sizeof(resp) || resp.rc)
969 {
970 pfsa->cSectorUnit = 1;
971 pfsa->cUnit = 123456;
972 pfsa->cUnitAvail = 123456;
973 pfsa->cbSector = 2048;
974 rc = rc ? rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
975 }
976 else
977 {
978 FSALLOCATE * fsa = (FSALLOCATE *)pConn->mem;
979 pfsa->cSectorUnit = fsa->cSectorUnit;
980 pfsa->cUnit = fsa->cUnit;
981 pfsa->cUnitAvail = fsa->cUnitAvail;
982 pfsa->cbSector = fsa->cbSector;
983 }
984
985 rc1 = NdpFreeConnection((HCONNECTION)pConn);
986
987 log("NdpRsrcQueryFSAllocate %d/%d/%d (cUnit = %d/cUnitAvail = %d/cbSector = %d)\n", rc, resp.rc, rc1, pfsa->cUnit, pfsa->cUnitAvail, pfsa->cbSector);
988 return rc;
989}
990
991int APIENTRY NdpFindStart (HCONNECTION conn, void *plist, NDFILEINFOL *pfiparent, char *szPath, ULONG ulAttribute)
992{
993 Connection *pConn = (Connection *)conn;
994 Resource *pRes = pConn->pRes;
995 int rc = NO_ERROR, count = 0;
996 unsigned long action;
997 smb_request req = {0};
998 smb_response resp = {0};
999 char *mask = "*";
1000 char dir[CCHMAXPATH+1] = {0};
1001 char path[CCHMAXPATH+1] = {0};
1002 char fullname[CCHMAXPATH+1] = {0};
1003 smbwrp_fileinfo * data;
1004 NDPATHELEMENT *pel = ph->fsphNameElem(0);
1005
1006 log("NdpFindStart in\n");
1007 do
1008 {
1009 rc = checkconnection(pConn);
1010 if (rc)
1011 {
1012 break;
1013 }
1014
1015 StrNCpy(dir, szPath, sizeof(dir) - 1);
1016 if (pel)
1017 {
1018 mask = pel->name;
1019 dir[StrLen(szPath) - pel->length] = 0;
1020 }
1021 action = StrLen(dir) - 1;
1022 if (dir[action] == '\\')
1023 {
1024 dir[action] = 0;
1025 }
1026 rc = pathparser(pRes, pConn, dir, path);
1027 if (rc)
1028 {
1029 break;
1030 }
1031 action = StrLen(path) - 1;
1032 if (path[action] != '\\')
1033 {
1034 StrNCat(path, "\\", sizeof(path) - 1);
1035 }
1036 StrCpy(dir, path);
1037 StrNCat(path, mask, sizeof(path) - 1);
1038
1039 MemCpy(pConn->mem, &pConn->srv, sizeof(pConn->srv));
1040 StrCpy(pConn->mem + sizeof(pConn->srv), path);
1041 req.request = SMBREQ_FILELIST;
1042 req.param = pConn->mem;
1043 req.paramlen = sizeof(pConn->srv) + CCHMAXPATH + 1;
1044 req.length = pRes->memlen;
1045 data = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->srv) + CCHMAXPATH + 1);
1046
1047 do {
1048 int i;
1049 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1050 if (pConn->rc || action < sizeof(resp)
1051 || (resp.rc && resp.rc != ERROR_MORE_DATA))
1052 {
1053 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1054 break;
1055 }
1056log("NdpFindStart %d %d %d\n", pConn->rc, resp.rc, resp.length / sizeof(smbwrp_fileinfo));
1057 if (ifL)
1058 {
1059 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1060 {
1061 smbwrp_fileinfo * finfo = data + i;
1062log("NdpFindStart found <%s> %d\n", finfo->fname, finfo->easize);
1063 StrCpy(fullname, dir);
1064 StrCat(fullname, finfo->fname);
1065 StrCpy(finfo->fname, fullname);
1066 count += getfindinfoL(pConn, plist, finfo, ulAttribute, mask);
1067 }
1068 }
1069 else
1070 {
1071 FILEFINDBUF3 buf = {0};
1072 for (i = 0; i < resp.length / sizeof(smbwrp_fileinfo); i++)
1073 {
1074 smbwrp_fileinfo * finfo = data + i;
1075 getfindinfo(pConn, &buf, finfo);
1076
1077 if (ph->fsphAttrMatch(ulAttribute, buf.attrFile)
1078 && ph->fsphWildMatch(mask, buf.achName, ND_IGNORE_CASE))
1079 {
1080 StrCpy(fullname, dir);
1081 StrCat(fullname, finfo->fname);
1082 StrCpy(finfo->fname, fullname);
1083 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1084 count++;
1085 }
1086 }
1087 }
1088 } while (resp.rc == ERROR_MORE_DATA);
1089 } while (0);
1090
1091 log("NdpFindStart <%s> (%s) cnt %d %d %d\n", szPath, path, count, rc, pConn->rc);
1092 return rc;
1093}
1094
1095int APIENTRY NdpQueryPathInfo (HCONNECTION conn, void *plist, char *szPath)
1096{
1097 Connection *pConn = (Connection *)conn;
1098 Resource *pRes = pConn->pRes;
1099 int rc = 0;
1100 unsigned long action;
1101 smb_request req = {0};
1102 smb_response resp = {0};
1103 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1104 char path[CCHMAXPATH+1] = {0};
1105
1106 log("NdpQueryInfo in <%s>\n", szPath);
1107
1108 do {
1109 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
1110 {
1111 rc = ERROR_FILE_NOT_FOUND;
1112 break;
1113 }
1114
1115 rc = checkconnection(pConn);
1116 if (rc)
1117 {
1118 break;
1119 }
1120
1121 rc = pathparser(pRes, pConn, szPath, path);
1122 switch (rc)
1123 {
1124 case NO_ERROR :
1125 case ERROR_FILE_NOT_FOUND:
1126 case ERROR_PATH_NOT_FOUND:
1127 case ERROR_ACCESS_DENIED:
1128 case ERROR_INVALID_PARAMETER:
1129 {
1130 break;
1131 }
1132 default :
1133 {
1134 rc = ERROR_PATH_NOT_FOUND;
1135 }
1136 }
1137 if (rc)
1138 {
1139 break;
1140 }
1141 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1142 req.request = SMBREQ_GETINFO;
1143 req.param = pConn->mem;
1144 req.paramlen = sizeof(*finfo);
1145 req.length = req.paramlen;
1146 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1147 if (pConn->rc || action < sizeof(resp) || resp.rc)
1148 {
1149 switch (resp.rc)
1150 {
1151 case NO_ERROR :
1152 case ERROR_FILE_NOT_FOUND:
1153 case ERROR_PATH_NOT_FOUND:
1154 case ERROR_ACCESS_DENIED:
1155 case ERROR_INVALID_PARAMETER:
1156 break;
1157 default :
1158 {
1159 resp.rc = ERROR_PATH_NOT_FOUND;
1160 }
1161 }
1162 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1163 }
1164 else
1165 {
1166 finfo->easize = -1;
1167 if (ifL)
1168 {
1169 getfindinfoL(pConn, plist, finfo, 0, NULL);
1170 }
1171 else
1172 {
1173 int trc;
1174 FILEFINDBUF3 buf = {0};
1175 getfindinfo(pConn, &buf, finfo);
1176 trc = ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1177 log("NdpQueryInfo got info <%s> attr %08x size %d namelen %d date %lu %lu. Plist 0x%08x rc = %d\n", buf.achName, buf.attrFile, buf.cbFile, buf.cchName, buf.fdateLastWrite, buf.ftimeLastWrite, plist, trc);
1178 }
1179 }
1180 if (rc == ERROR_FILE_NOT_FOUND)
1181 {
1182 // now try the upper path
1183 char * p = ph->fsphStrChr(finfo->fname, '\\');
1184 if (p && p > finfo->fname)
1185 {
1186 *p = 0;
1187 rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1188 if (pConn->rc || action < sizeof(resp) || resp.rc)
1189 {
1190 rc = pConn->rc ? pConn->rc : (resp.rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER);
1191 }
1192 }
1193 }
1194 } while (0);
1195
1196 log("NdpQueryInfo <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1197 return rc;
1198}
1199
1200int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1201{
1202// log("NdpDeletePathInfo %d\n", 0);
1203 return NO_ERROR;
1204}
1205
1206int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1207{
1208 log("NdpRefresh <%s> %d\n", path, 0);
1209 return NO_ERROR;
1210}
1211
1212int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1213{
1214 // The plugin do not have to deallocate anything
1215 // because resource data did not contain any pointers
1216 // to plugins data.
1217 // Data stored by fsphSetResourceData will be
1218 // deallocated by NetDrive.
1219
1220 log("NdpDicardresourceData %d\n", 0);
1221 return NO_ERROR;
1222}
1223
1224int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1225{
1226 Connection *pConn = (Connection *)conn;
1227 Resource *pRes = pConn->pRes;
1228 int rc = 0;
1229 unsigned long action;
1230 smb_request req = {0};
1231 smb_response resp = {0};
1232 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1233 char path[CCHMAXPATH+1] = {0};
1234
1235 log("NdpSetPathInfo in\n");
1236 do {
1237 rc = checkconnection(pConn);
1238 if (rc)
1239 {
1240 break;
1241 }
1242
1243 rc = pathparser(pRes, pConn, szPathName, path);
1244 if (rc)
1245 {
1246 break;
1247 }
1248
1249 MemSet(finfo, 0, sizeof(*finfo));
1250
1251 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1252 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(finfo->mtime));
1253 if (ifL)
1254 {
1255 finfo->attr = pfi->stat.attrFile & 0x37;
1256 }
1257 else
1258 {
1259 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
1260 finfo->attr = stat->attrFile & 0x37;
1261 }
1262 req.request = SMBREQ_SETINFO;
1263 req.param = pConn->mem;
1264 req.paramlen = sizeof(*finfo);
1265 req.length = req.paramlen;
1266 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1267 if (pConn->rc || action < sizeof(resp) || resp.rc)
1268 {
1269 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1270 }
1271 } while (0);
1272 log("NdpSetPathInfo <%s> (%s) %d %d\n", szPathName, path, rc, pConn->rc);
1273 return rc;
1274}
1275
1276int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1277{
1278 int rc = 0;
1279 FEA * pfea;
1280 FEA * pfeadest;
1281 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1282
1283 size = pFEASrc->cbList;
1284 pfea = pFEASrc->list;
1285 pfeadest = pFEAList->list;
1286 dsize = pFEAList->cbList;
1287//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1288 while (done < size)
1289 {
1290 char * name = (char *)(pfea + 1);
1291 int insert = 1;
1292 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1293 {
1294 GEA * pgea = pGEAList->list;
1295 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1296 insert = 0;
1297 while (done < size)
1298 {
1299//log("comp <%s> <%s>\n", name, pgea->szName);
1300 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1301 {
1302 insert = 1;
1303 break;
1304 }
1305 done += pgea->cbName + 2;
1306 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1307 }
1308 }
1309 if (insert)
1310 {
1311 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1312 if (ddone <= dsize)
1313 {
1314 pfeadest->cbName = pfea->cbName;
1315 pfeadest->cbValue = pfea->cbValue;
1316 pfeadest->fEA = 0;
1317 StrCpy((char *)(pfeadest + 1), name);
1318 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1319 pfeadest = (FEA *)((char *)pFEAList + ddone);
1320 }
1321 }
1322 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1323//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);
1324 pfea = (FEA *)((char *)pFEASrc + done);
1325 }
1326 pFEAList->cbList = ddone;
1327 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1328 {
1329 rc = ERROR_BUFFER_OVERFLOW;
1330 }
1331 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1332 return rc;
1333}
1334
1335int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1336{
1337 Connection *pConn = (Connection *)conn;
1338 Resource *pRes = pConn->pRes;
1339 int rc = 0;
1340 unsigned long action;
1341 smb_request req = {0};
1342 smb_response resp = {0};
1343 char * path = NULL;
1344 FEALIST * pFEASrc;
1345 NDDATABUF fdata = {0};
1346 smbwrp_fileinfo *finfo;
1347
1348 if (!pfi || !pfi->pszName || !pFEAList)
1349 {
1350 return ERROR_EAS_NOT_SUPPORTED;
1351 }
1352 if (!pRes->easupport)
1353 {
1354 return ERROR_EAS_NOT_SUPPORTED;
1355 }
1356
1357 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1358 if (rc || !fdata.ulSize || !fdata.pData)
1359 {
1360 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1361 return ERROR_EAS_NOT_SUPPORTED;
1362 }
1363 finfo = (smbwrp_fileinfo *)fdata.pData;
1364 path = finfo->fname;
1365
1366 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1367 do {
1368 rc = checkconnection(pConn);
1369 if (rc)
1370 {
1371 break;
1372 }
1373
1374 StrNCpy(pConn->mem, path, CCHMAXPATH);
1375 req.request = SMBREQ_LISTEA;
1376 req.param = pConn->mem;
1377 req.paramlen = CCHMAXPATH + 1;
1378 req.length = pRes->memlen - req.paramlen;
1379 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
1380 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1381 if (pConn->rc || action < sizeof(resp) || resp.rc)
1382 {
1383 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1384 switch (rc)
1385 {
1386 case ERROR_FILE_NOT_FOUND :
1387 case ERROR_PATH_NOT_FOUND :
1388 {
1389 pFEAList->cbList = sizeof(pFEAList->cbList);
1390 rc = NO_ERROR;
1391 } break;
1392 case ERROR_BUFFER_OVERFLOW :
1393 {
1394 pFEAList->cbList = pFEASrc->cbList;
1395 } break;
1396 default :
1397 {
1398 rc = ERROR_EAS_NOT_SUPPORTED;
1399 }
1400 }
1401 }
1402 else
1403 {
1404 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1405 }
1406 } while (0);
1407 log("NdpEAQuery <%s> %d %d %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList, pConn->rc, resp.rc);
1408 return rc;
1409}
1410
1411int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1412{
1413 Connection *pConn = (Connection *)conn;
1414 Resource *pRes = pConn->pRes;
1415 int rc = 0;
1416 smb_request req = {0};
1417 smb_response resp = {0};
1418 char * path;
1419 unsigned long action;
1420 NDDATABUF fdata = {0};
1421 smbwrp_fileinfo *finfo;
1422
1423 log("NdpEASet in\n");
1424
1425 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1426 {
1427 return ERROR_EAS_NOT_SUPPORTED;
1428 }
1429 if (!pRes->easupport)
1430 {
1431 return ERROR_EAS_NOT_SUPPORTED;
1432 }
1433
1434 if (pFEAList->cbList > pRes->memlen)
1435 {
1436 return ERROR_NOT_ENOUGH_MEMORY;
1437 }
1438
1439 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1440 if (rc || !fdata.ulSize || !fdata.pData)
1441 {
1442 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1443 return ERROR_EAS_NOT_SUPPORTED;
1444 }
1445 finfo = (smbwrp_fileinfo *)fdata.pData;
1446 path = finfo->fname;
1447
1448 do {
1449 rc = checkconnection(pConn);
1450 if (rc)
1451 {
1452 break;
1453 }
1454
1455 StrNCpy(pConn->mem, path, CCHMAXPATH);
1456 MemCpy(pConn->mem + CCHMAXPATH + 1, pFEAList, pFEAList->cbList);
1457 req.request = SMBREQ_SETEA;
1458 req.param = pConn->mem;
1459 req.paramlen = pFEAList->cbList + CCHMAXPATH + 1;
1460 req.length = req.paramlen;
1461 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1462 if (pConn->rc || action < sizeof(resp) || resp.rc)
1463 {
1464 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1465 }
1466 } while (0);
1467 log("NdpEASet %d\n", rc);
1468 return rc;
1469}
1470
1471int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1472{
1473 Connection *pConn = (Connection *)conn;
1474 Resource *pRes = pConn->pRes;
1475 int rc = 0;
1476 unsigned long action;
1477 smb_request req = {0};
1478 smb_response resp = {0};
1479 char * path = NULL;
1480 FEALIST * pfealist;
1481 NDDATABUF fdata = {0};
1482 smbwrp_fileinfo *finfo;
1483 int easize;
1484
1485 if (!pfi || !pulEASize)
1486 {
1487 return ERROR_EAS_NOT_SUPPORTED;
1488 }
1489 if (!pRes->easupport)
1490 {
1491 return ERROR_EAS_NOT_SUPPORTED;
1492 }
1493
1494 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1495 if (rc || !fdata.ulSize || !fdata.pData)
1496 {
1497 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1498 return ERROR_EAS_NOT_SUPPORTED;
1499 }
1500 finfo = (smbwrp_fileinfo *)fdata.pData;
1501 easize = finfo->easize;
1502 finfo->easize = -1;
1503 path = finfo->fname;
1504 if (easize >= 0)
1505 {
1506 *pulEASize = easize;
1507 log("NdpEASize <%s> cached %d\n", path, easize);
1508 return NO_ERROR;
1509 }
1510
1511 log("NdpEASize in <%s> \n", path);
1512 do {
1513 rc = checkconnection(pConn);
1514 if (rc)
1515 {
1516 break;
1517 }
1518
1519 StrNCpy(pConn->mem, path, CCHMAXPATH);
1520 req.request = SMBREQ_LISTEA;
1521 req.param = pConn->mem;
1522 req.paramlen = CCHMAXPATH + 1;
1523 req.length = pRes->memlen - req.paramlen;
1524 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
1525 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1526 if (pConn->rc || action < sizeof(resp) || resp.rc)
1527 {
1528 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1529 switch (rc)
1530 {
1531 case ERROR_FILE_NOT_FOUND :
1532 case ERROR_PATH_NOT_FOUND :
1533 {
1534 pfealist->cbList = sizeof(pfealist->cbList);
1535 } /* Fall through */
1536 case ERROR_BUFFER_OVERFLOW :
1537 {
1538 rc = NO_ERROR;
1539 } break;
1540 default :
1541 {
1542 rc = ERROR_EAS_NOT_SUPPORTED;
1543 }
1544 }
1545 }
1546 *pulEASize = pfealist->cbList;
1547 } while (0);
1548 log("NdpEASize <%s> %d %d %d %d\n", pfi->pszName, *pulEASize, rc, pConn->rc, resp.rc);
1549 return rc;
1550}
1551
1552int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1553{
1554 Connection *pConn = (Connection *)conn;
1555 Resource *pRes = pConn->pRes;
1556 smb_request req = {0};
1557 smb_response resp = {0};
1558 int rc = 0;
1559 unsigned long action;
1560 char path[CCHMAXPATH+1] = {0};
1561
1562 log("NdpSetCurrentDir in\n");
1563 do {
1564 rc = checkconnection(pConn);
1565 if (rc)
1566 {
1567 break;
1568 }
1569
1570 rc = pathparser(pRes, pConn, szPath, path);
1571 if (rc)
1572 {
1573 break;
1574 }
1575
1576 StrNCpy(pConn->mem, path, CCHMAXPATH);
1577 req.request = SMBREQ_CHDIR;
1578 req.param = pConn->mem;
1579 req.paramlen = CCHMAXPATH + 1;
1580 req.length = req.paramlen;
1581 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1582 if (pConn->rc || action < sizeof(resp) || resp.rc)
1583 {
1584 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1585 }
1586 } while (0);
1587 log("NdpSetCurrentDir <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1588 return rc;
1589}
1590
1591int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1592{
1593 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1594 return ERROR_CANNOT_COPY;
1595}
1596
1597int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1598{
1599 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1600 return ERROR_CANNOT_COPY;
1601}
1602
1603int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1604{
1605 Connection *pConn = (Connection *)conn;
1606 Resource *pRes = pConn->pRes;
1607 smb_request req = {0};
1608 smb_response resp = {0};
1609 int rc = 0;
1610 unsigned long action;
1611 char path[CCHMAXPATH+1] = {0};
1612
1613 log("NdpForceDelete in\n");
1614 do {
1615 rc = checkconnection(pConn);
1616 if (rc)
1617 {
1618 break;
1619 }
1620
1621 rc = pathparser(pRes, pConn, szFile, path);
1622 if (rc)
1623 {
1624 break;
1625 }
1626
1627 StrNCpy(pConn->mem, path, CCHMAXPATH);
1628 req.request = SMBREQ_UNLINK;
1629 req.param = pConn->mem;
1630 req.paramlen = CCHMAXPATH + 1;
1631 req.length = req.paramlen;
1632 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1633 if (pConn->rc || action < sizeof(resp) || resp.rc)
1634 {
1635 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1636 }
1637 } while (0);
1638 log("NdpForceDelete <%s> (%s) %d %d\n", szFile, path, rc, pConn->rc);
1639 return rc;
1640}
1641
1642int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1643{
1644 Connection *pConn = (Connection *)conn;
1645 Resource *pRes = pConn->pRes;
1646 smb_request req = {0};
1647 smb_response resp = {0};
1648 int rc = 0;
1649 unsigned long action;
1650 char path[CCHMAXPATH+1] = {0};
1651
1652 log("NdpCreateDir in\n");
1653 do {
1654 rc = checkconnection(pConn);
1655 if (rc)
1656 {
1657 break;
1658 }
1659
1660 rc = pathparser(pRes, pConn, szDirName, path);
1661 if (rc)
1662 {
1663 break;
1664 }
1665
1666 StrNCpy(pConn->mem, path, CCHMAXPATH);
1667 req.request = SMBREQ_MKDIR;
1668 req.param = pConn->mem;
1669 req.paramlen = CCHMAXPATH + 1;
1670 req.length = req.paramlen;
1671 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1672 if (pConn->rc || action < sizeof(resp) || resp.rc)
1673 {
1674 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1675 }
1676 } while (0);
1677 log("NdpCreateDir <%s> (%s) %d %d\n", szDirName, path, rc, pConn->rc);
1678 return rc;
1679}
1680
1681int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1682{
1683 Connection *pConn = (Connection *)conn;
1684 Resource *pRes = pConn->pRes;
1685 smb_request req = {0};
1686 smb_response resp = {0};
1687 int rc = 0;
1688 unsigned long action;
1689 char path[CCHMAXPATH+1] = {0};
1690
1691 log("NdpDeleteDir in\n");
1692 do {
1693 rc = checkconnection(pConn);
1694 if (rc)
1695 {
1696 break;
1697 }
1698
1699 rc = pathparser(pRes, pConn, szDir, path);
1700 if (rc)
1701 {
1702 break;
1703 }
1704
1705 StrNCpy(pConn->mem, path, CCHMAXPATH);
1706 req.request = SMBREQ_RMDIR;
1707 req.param = pConn->mem;
1708 req.paramlen = CCHMAXPATH + 1;
1709 req.length = req.paramlen;
1710 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1711 if (pConn->rc || action < sizeof(resp) || resp.rc)
1712 {
1713 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1714 }
1715 } while (0);
1716 log("NdpDeleteDir <%s> (%s) %d %d\n", szDir, path, rc, pConn->rc);
1717 return rc;
1718}
1719
1720int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1721{
1722 Connection *pConn = (Connection *)conn;
1723 Resource *pRes = pConn->pRes;
1724 smb_request req = {0};
1725 smb_response resp = {0};
1726 int rc = 0;
1727 unsigned long action;
1728 char src[CCHMAXPATH+1] = {0};
1729 int l1, l2;
1730 char * p = szDst;
1731
1732 log("NdpMove in\n");
1733 do
1734 {
1735 rc = checkconnection(pConn);
1736 if (rc)
1737 {
1738 break;
1739 }
1740
1741 rc = pathparser(pRes, pConn, szSrc, src);
1742 if (rc)
1743 {
1744 break;
1745 }
1746 l1 = StrLen(szSrc);
1747 l2 = StrLen(src);
1748 if (l1 > l2)
1749 {
1750 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1751 {
1752 // the file moved accross different shares or servers or workgroups
1753 rc = ERROR_WRITE_PROTECT;
1754 break;
1755 }
1756 p = szDst + l1 - l2 + 1;
1757 }
1758 StrNCpy(pConn->mem, src, CCHMAXPATH);
1759 pConn->mem[CCHMAXPATH + 1] = '\\';
1760 StrNCpy(pConn->mem + CCHMAXPATH + 2, p, CCHMAXPATH - 1);
1761 req.request = SMBREQ_RENAME;
1762 req.param = pConn->mem;
1763 req.paramlen = 2 * (CCHMAXPATH + 1);
1764 req.length = req.paramlen;
1765 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1766 if (pConn->rc || action < sizeof(resp) || resp.rc)
1767 {
1768 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1769 }
1770 } while (0);
1771 log("NdpMove <%s> -> <%s> (%s) %d %d\n", szSrc, szDst, src, rc, pConn->rc);
1772
1773 return rc;
1774}
1775
1776int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1777{
1778 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1779 return ERROR_WRITE_PROTECT;
1780}
1781
1782
1783int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1784{
1785 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1786}
1787
1788int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1789{
1790 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1791}
1792
1793int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1794{
1795 Resource *pRes = pConn->pRes;
1796 smb_request req = {0};
1797 smb_response resp = {0};
1798 unsigned long action;
1799 int rc = 0;
1800 char path[CCHMAXPATH+1] = {0};
1801
1802 log("smbopen in %d\n", pConn->file.fd);
1803 do {
1804 if (pConn->file.fd > 0)
1805 {
1806 rc = ERROR_TOO_MANY_OPEN_FILES;
1807 break;
1808 }
1809
1810 rc = checkconnection(pConn);
1811 if (rc)
1812 {
1813 break;
1814 }
1815
1816 rc = pathparser(pRes, pConn, szFileName, path);
1817 if (rc)
1818 {
1819 break;
1820 }
1821
1822 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1823 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1824 flags |= O_BINARY;
1825 switch (ulOpenMode & 3)
1826 {
1827 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
1828 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
1829 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
1830 default : flags |= O_RDWR;
1831 }
1832 pConn->file.openmode = flags;
1833 pConn->file.openattr = ulAttribute & 0x37;
1834 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
1835 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
1836 req.request = SMBREQ_OPEN;
1837 req.param = pConn->mem;
1838 req.paramlen = sizeof(pConn->file);
1839 req.length = req.paramlen;
1840 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1841 if (pConn->rc || action < sizeof(resp) || resp.rc)
1842 {
1843 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1844 }
1845 else
1846 {
1847 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
1848 }
1849 } while (0);
1850 log("smbopen <%s> (%s) %08x %08x %08x %d %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->rc, pConn->file.fd);
1851 if (!rc && pFEAList)
1852 {
1853 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
1854 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
1855 }
1856
1857 return rc;
1858}
1859
1860int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1861{
1862 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1863}
1864
1865int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1866{
1867 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
1868}
1869
1870int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1871{
1872// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
1873 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1874}
1875
1876int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1877{
1878 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
1879}
1880
1881int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
1882{
1883 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
1884 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
1885}
1886
1887int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
1888{
1889 Connection *pConn = (Connection *)conn;
1890 Resource *pRes = pConn->pRes;
1891 int rc = 0;
1892 unsigned long action;
1893 smb_request req = {0};
1894 smb_response resp = {0};
1895 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1896 char path[CCHMAXPATH+1] = {0};
1897
1898 log("NdpSetFileAttribute in\n");
1899 do {
1900 rc = checkconnection(pConn);
1901 if (rc)
1902 {
1903 break;
1904 }
1905
1906 rc = pathparser(pRes, pConn, szFileName, path);
1907 if (rc)
1908 {
1909 break;
1910 }
1911
1912 MemSet(finfo, 0, sizeof(*finfo));
1913
1914 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1915 finfo->attr = usAttr & 0x37;
1916 req.request = SMBREQ_SETINFO;
1917 req.param = pConn->mem;
1918 req.paramlen = sizeof(*finfo);
1919 req.length = req.paramlen;
1920 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1921 if (pConn->rc || action < sizeof(resp) || resp.rc)
1922 {
1923 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1924 }
1925 } while (0);
1926 log("NdpSetFileAttribute <%s> (%s) %04x %d %d\n", szFileName, path, usAttr, rc, pConn->rc);
1927 return rc;
1928}
1929
1930int APIENTRY NdpFlush (HRESOURCE resource)
1931{
1932 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
1933 return ERROR_NOT_SUPPORTED;
1934}
1935
1936int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
1937{
1938 log("NdpIOCTL <%s> %d %d\n", path, function, ERROR_NOT_SUPPORTED);
1939 return ERROR_NOT_SUPPORTED;
1940}
1941
1942int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
1943{
1944 Connection *pConn = (Connection *)conn;
1945 Resource *pRes = pConn->pRes;
1946 int rc = 0;
1947 unsigned long action;
1948 smb_request req = {0};
1949 smb_response resp = {0};
1950 FILEFINDBUF3 buf;
1951 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->file));
1952
1953 log("NdpFileQueryInfo in\n");
1954 do {
1955 if (pConn->file.fd < 0 || !*pConn->file.fname)
1956 {
1957 rc = ERROR_INVALID_HANDLE;
1958 break;
1959 }
1960 if (pConn->rc)
1961 {
1962 rc = ERROR_PIPE_NOT_CONNECTED;
1963 break;
1964 }
1965
1966 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
1967 StrNCpy(finfo->fname, pConn->file.fname, sizeof(finfo->fname) - 1);
1968 req.request = SMBREQ_FGETINFO;
1969 req.param = pConn->mem;
1970 req.paramlen = sizeof(pConn->file);
1971 req.length = req.paramlen + sizeof(*finfo);
1972 rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
1973 if (pConn->rc || action < sizeof(resp) || resp.rc)
1974 {
1975 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1976 }
1977 else
1978 {
1979 finfo->easize = -1;
1980 if (ifL)
1981 {
1982 getfindinfoL(pConn, plist, finfo, 0, NULL);
1983 }
1984 else
1985 {
1986 getfindinfo(pConn, &buf, finfo);
1987 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1988 }
1989 }
1990 } while (0);
1991 log("NdpFileQueryInfo <%s> %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc, pConn->rc);
1992
1993 return rc;
1994}
1995
1996int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
1997{
1998 Connection *pConn = (Connection *)conn;
1999 Resource *pRes = pConn->pRes;
2000 int rc = 0;
2001 unsigned long action;
2002 smb_request req = {0};
2003 smb_response resp = {0};
2004 FEALIST * pFEASrc;
2005
2006 if (!pFEAList)
2007 {
2008 return ERROR_EAS_NOT_SUPPORTED;
2009 }
2010 if (!pRes->easupport)
2011 {
2012 return ERROR_EAS_NOT_SUPPORTED;
2013 }
2014
2015 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
2016 do {
2017 if (pConn->file.fd < 0)
2018 {
2019 rc = ERROR_INVALID_HANDLE;
2020 break;
2021 }
2022 if (pConn->rc)
2023 {
2024 rc = ERROR_PIPE_NOT_CONNECTED;
2025 break;
2026 }
2027
2028 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2029 req.request = SMBREQ_FLISTEA;
2030 req.param = pConn->mem;
2031 req.paramlen = sizeof(pConn->file);
2032 req.length = pRes->memlen - req.paramlen;
2033 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
2034 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2035 if (pConn->rc || action < sizeof(resp) || resp.rc)
2036 {
2037 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2038 switch (rc)
2039 {
2040 case ERROR_FILE_NOT_FOUND :
2041 case ERROR_PATH_NOT_FOUND :
2042 {
2043 pFEAList->cbList = sizeof(pFEAList->cbList);
2044 rc = NO_ERROR;
2045 } break;
2046 case ERROR_BUFFER_OVERFLOW :
2047 {
2048 pFEAList->cbList = pFEASrc->cbList;
2049 } break;
2050 default :
2051 {
2052 rc = ERROR_EAS_NOT_SUPPORTED;
2053 }
2054 }
2055 }
2056 else
2057 {
2058 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
2059 }
2060 } while (0);
2061 log("NdpFileEAQuery out <%s>/%d pFEASrc->cbList=%d pFEAList->cbList=%d rc=%d %d %d\n", pConn->file.fname, pConn->file.fd, pFEASrc->cbList, pFEAList->cbList, rc, pConn->rc, resp.rc);
2062 return rc;
2063}
2064
2065int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
2066{
2067 Connection *pConn = (Connection *)conn;
2068 Resource *pRes = pConn->pRes;
2069 int rc = 0;
2070 smb_request req = {0};
2071 smb_response resp = {0};
2072 unsigned long action;
2073
2074 log("NdpFileEASet in\n");
2075
2076 if (!pFEAList || pFEAList->cbList <= sizeof(long))
2077 {
2078 return ERROR_EAS_NOT_SUPPORTED;
2079 }
2080 if (!pRes->easupport)
2081 {
2082 return ERROR_EAS_NOT_SUPPORTED;
2083 }
2084 if (pFEAList->cbList > pRes->memlen)
2085 {
2086 return ERROR_NOT_ENOUGH_MEMORY;
2087 }
2088
2089 do {
2090 if (pConn->file.fd < 0)
2091 {
2092 rc = ERROR_INVALID_HANDLE;
2093 break;
2094 }
2095 if (pConn->rc)
2096 {
2097 rc = ERROR_PIPE_NOT_CONNECTED;
2098 break;
2099 }
2100
2101 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2102 MemCpy(pConn->mem + sizeof(pConn->file), pFEAList, pFEAList->cbList);
2103 req.request = SMBREQ_FSETEA;
2104 req.param = pConn->mem;
2105 req.paramlen = pFEAList->cbList + sizeof(pConn->file);
2106 req.length = req.paramlen;
2107
2108 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2109 if (pConn->rc || action < sizeof(resp) || resp.rc)
2110 {
2111 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2112 }
2113 } while (0);
2114 log("NdpFileEASet %d\n", rc);
2115 return rc;
2116}
2117
2118int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
2119{
2120 Connection *pConn = (Connection *)conn;
2121 Resource *pRes = pConn->pRes;
2122 int rc = 0;
2123 unsigned long action;
2124 smb_request req = {0};
2125 smb_response resp = {0};
2126 char path[CCHMAXPATH+1] = {0};
2127 FEALIST * pfealist;
2128
2129 if (!pulEASize)
2130 {
2131 return ERROR_EAS_NOT_SUPPORTED;
2132 }
2133 if (!pRes->easupport)
2134 {
2135 return ERROR_EAS_NOT_SUPPORTED;
2136 }
2137
2138 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
2139 do {
2140 if (pConn->file.fd < 0)
2141 {
2142 rc = ERROR_INVALID_HANDLE;
2143 break;
2144 }
2145 if (pConn->rc)
2146 {
2147 rc = ERROR_PIPE_NOT_CONNECTED;
2148 break;
2149 }
2150
2151 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2152 req.request = SMBREQ_FLISTEA;
2153 req.param = pConn->mem;
2154 req.paramlen = sizeof(pConn->file);
2155 req.length = pRes->memlen - req.paramlen;
2156 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
2157 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2158 if (pConn->rc || action < sizeof(resp) || resp.rc)
2159 {
2160 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2161 switch (rc)
2162 {
2163 case ERROR_FILE_NOT_FOUND :
2164 case ERROR_PATH_NOT_FOUND :
2165 {
2166 pfealist->cbList = sizeof(pfealist->cbList);
2167 } /* Fall through */
2168 case ERROR_BUFFER_OVERFLOW :
2169 {
2170 rc = NO_ERROR;
2171 } break;
2172 default :
2173 {
2174 rc = ERROR_EAS_NOT_SUPPORTED;
2175 }
2176 }
2177 }
2178 *pulEASize = pfealist->cbList;
2179 } while (0);
2180 log("NdpFileEASize %d %d %d %d\n", *pulEASize, rc, pConn->rc, resp.rc);
2181 return rc;
2182}
2183
2184int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2185{
2186 Connection *pConn = (Connection *)conn;
2187 Resource *pRes = pConn->pRes;
2188 int rc = 0;
2189 unsigned long action, attrFile;
2190 smb_request req = {0};
2191 smb_response resp = {0};
2192 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2193
2194 log("NdpFileSetInfo in\n");
2195 do {
2196 if (pConn->file.fd < 0 || !*pConn->file.fname)
2197 {
2198 rc = ERROR_INVALID_HANDLE;
2199 break;
2200 }
2201 if (pConn->rc)
2202 {
2203 rc = ERROR_PIPE_NOT_CONNECTED;
2204 break;
2205 }
2206 if (ifL)
2207 {
2208 attrFile = pfi->stat.attrFile;
2209 }
2210 else
2211 {
2212 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
2213 attrFile = stat->attrFile;
2214 }
2215 // deferred setinfo - on closing the file
2216 pConn->file.openattr = attrFile;
2217 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(pConn->file.mtime));
2218 } while (0);
2219 log("NdpFileSetInfo <%s> %08x %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc, pConn->rc);
2220 return NO_ERROR;
2221}
2222
2223int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2224{
2225 Connection *pConn = (Connection *)conn;
2226 Resource *pRes = pConn->pRes;
2227 int rc = 0;
2228 unsigned long action;
2229 smb_request req = {0};
2230 smb_response resp = {0};
2231
2232 log("NdpFileSetFilePtrl in\n");
2233 do {
2234 if (pConn->file.fd < 0)
2235 {
2236 rc = ERROR_INVALID_HANDLE;
2237 break;
2238 }
2239 if (pConn->rc)
2240 {
2241 rc = ERROR_PIPE_NOT_CONNECTED;
2242 break;
2243 }
2244
2245 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2246 *(unsigned long *)(pConn->mem + sizeof(pConn->file)) = ulMethod;
2247 *(long long *)(pConn->mem + sizeof(pConn->file) + sizeof(long)) = llOffset;
2248 req.request = SMBREQ_LSEEK;
2249 req.param = pConn->mem;
2250 req.paramlen = sizeof(pConn->file) + sizeof(long) + sizeof(long long);
2251 req.length = req.paramlen;
2252 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2253 if (pConn->rc || action < sizeof(resp) || resp.rc)
2254 {
2255 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2256 }
2257 else
2258 {
2259 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2260 *pllActual = pConn->file.offset;
2261 }
2262 } while (0);
2263 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc, pConn->rc);
2264
2265 return rc;
2266}
2267
2268int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2269{
2270 LONGLONG llActual;
2271 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2272 *pulActual = llActual & 0xFFFFFFFF;
2273 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2274 return rc;
2275}
2276
2277int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2278{
2279 Connection *pConn = (Connection *)conn;
2280 Resource *pRes = pConn->pRes;
2281 int rc = 0;
2282 unsigned long action;
2283 smb_request req = {0};
2284 smb_response resp = {0};
2285
2286 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2287
2288 do {
2289 if (pConn->file.fd < 0)
2290 {
2291 rc = ERROR_INVALID_HANDLE;
2292 break;
2293 }
2294 if (pConn->rc)
2295 {
2296 rc = ERROR_PIPE_NOT_CONNECTED;
2297 break;
2298 }
2299
2300 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2301 req.request = SMBREQ_CLOSE;
2302 req.param = pConn->mem;
2303 req.length = pRes->memlen;
2304 req.paramlen = sizeof(pConn->file);
2305 req.length = req.paramlen;
2306 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2307 if (pConn->rc || action < sizeof(resp) || resp.rc)
2308 {
2309 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2310 }
2311 else
2312 {
2313 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2314 }
2315 } while (0);
2316 log("NdpFileClose %d %d %d\n", pConn->file.fd, rc, pConn->rc);
2317 pConn->file.fd = -1;
2318 return rc;
2319}
2320
2321int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2322{
2323 log("NdpFileCommit %d\n", NO_ERROR);
2324 return NO_ERROR;
2325}
2326
2327
2328int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2329{
2330 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2331 log("NdpFileNewSize %ld %d\n", ulLen, rc);
2332 return rc;
2333}
2334
2335int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2336{
2337 Connection *pConn = (Connection *)conn;
2338 Resource *pRes = pConn->pRes;
2339 int rc = 0;
2340 unsigned long action;
2341 smb_request req = {0};
2342 smb_response resp = {0};
2343
2344 log("NdpFileNewSizeL in\n");
2345 do {
2346 if (pConn->file.fd < 0)
2347 {
2348 rc = ERROR_INVALID_HANDLE;
2349 break;
2350 }
2351 if (pConn->rc)
2352 {
2353 rc = ERROR_PIPE_NOT_CONNECTED;
2354 break;
2355 }
2356
2357 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2358 *(long long *)(pConn->mem + sizeof(pConn->file)) = llLen;
2359
2360 req.request = SMBREQ_NEWSIZE;
2361 req.param = pConn->mem;
2362 req.paramlen = sizeof(pConn->file) + sizeof(long long);
2363 req.length = req.paramlen;
2364
2365 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2366 if (pConn->rc || action < sizeof(resp) || resp.rc)
2367 {
2368 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2369 }
2370 else
2371 {
2372 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2373 }
2374 } while (0);
2375 log("NdpFileNewSizeL <%s> %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc, pConn->rc);
2376 return rc;
2377}
2378
2379int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2380{
2381 Connection *pConn = (Connection *)conn;
2382 Resource *pRes = pConn->pRes;
2383 int rc = 0;
2384 unsigned long done = 0;
2385 unsigned long onedone;
2386 unsigned long action;
2387 smb_request req = {0};
2388 smb_response resp = {0};
2389
2390 log("NdpFileRead in\n");
2391// log("NdpFileRead <%s> %lu\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead);
2392
2393 do {
2394 if (pConn->file.fd < 0)
2395 {
2396 rc = ERROR_INVALID_HANDLE;
2397 break;
2398 }
2399 if (pConn->rc)
2400 {
2401 rc = ERROR_PIPE_NOT_CONNECTED;
2402 break;
2403 }
2404
2405 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2406 req.request = SMBREQ_READ;
2407 req.param = pConn->mem;
2408 req.paramlen = sizeof(pConn->file);
2409
2410 while (done < ulRead)
2411 {
2412 req.length = req.paramlen + (pRes->memlen - req.paramlen < (ulRead - done) ? pRes->memlen - req.paramlen : (ulRead - done));
2413
2414 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2415 if (pConn->rc || action < sizeof(resp) || resp.rc)
2416 {
2417 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2418 break;
2419 }
2420 if (resp.value == 0)
2421 {
2422 break;
2423 }
2424 onedone = resp.value > req.length ? req.length : resp.value;
2425 MemCpy((char *)pBuffer + done, pConn->mem + sizeof(pConn->file), onedone);
2426 done += onedone;
2427 }
2428 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2429 *pulActual = done;
2430 } while (0);
2431 log("NdpFileRead <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc, pConn->rc);
2432
2433 return rc;
2434}
2435
2436int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2437{
2438 Connection *pConn = (Connection *)conn;
2439 Resource *pRes = pConn->pRes;
2440 int rc = 0;
2441 unsigned long done = 0;
2442 unsigned long onedone;
2443 unsigned long action;
2444 smb_request req = {0};
2445 smb_response resp = {0};
2446
2447 log("NdpFileWrite in\n");
2448 do {
2449 if (pConn->file.fd < 0)
2450 {
2451 rc = ERROR_INVALID_HANDLE;
2452 break;
2453 }
2454 if (pConn->rc)
2455 {
2456 rc = ERROR_PIPE_NOT_CONNECTED;
2457 break;
2458 }
2459
2460 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2461 req.request = SMBREQ_WRITE;
2462 req.param = pConn->mem;
2463 req.paramlen = sizeof(pConn->file);
2464
2465 while (done < ulWrite)
2466 {
2467 req.length = pRes->memlen - req.paramlen < (ulWrite - done) ? pRes->memlen - req.paramlen : (ulWrite - done);
2468 MemCpy(pConn->mem + sizeof(pConn->file), (char *)pBuffer + done, req.length);
2469 req.length += req.paramlen;
2470
2471 pConn->rc = DosTransactNPipe(pConn->pipe, &req, sizeof(req), &resp, sizeof(resp), &action);
2472 if (pConn->rc || action < sizeof(resp) || resp.rc)
2473 {
2474 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2475 break;
2476 }
2477 done += resp.value & 0xFFFFFFFF;
2478 if (resp.value < req.length)
2479 {
2480 break;
2481 }
2482 }
2483 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2484 *pulActual = done;
2485 } while (0);
2486 log("NdpFileWrite <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc, pConn->rc);
2487
2488 return rc;
2489}
Note: See TracBrowser for help on using the repository browser.