source: branches/samba-3.0/source/ndpsmb/ndpsmb.c@ 122

Last change on this file since 122 was 122, checked in by Paul Smedley, 17 years ago

fromhex fix from Vitali

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