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

Last change on this file since 116 was 116, checked in by Paul Smedley, 18 years ago

Encrypt samba password in Netdrive control files

  • Property svn:eol-style set to native
File size: 64.9 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';
389 }
390
391 if ('a' <= c && c <= 'f')
392 {
393 return c - 'a';
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
1281 log("NdpQueryInfo in <%s>\n", szPath);
1282
1283 do {
1284 if (ph->fsphStrChr(szPath, '*') || ph->fsphStrChr(szPath, '?'))
1285 {
1286 rc = ERROR_FILE_NOT_FOUND;
1287 break;
1288 }
1289
1290 rc = checkconnection(pConn);
1291 if (rc)
1292 {
1293 break;
1294 }
1295
1296 rc = pathparser(pRes, pConn, szPath, path);
1297 switch (rc)
1298 {
1299 case NO_ERROR :
1300 case ERROR_FILE_NOT_FOUND:
1301 case ERROR_PATH_NOT_FOUND:
1302 case ERROR_ACCESS_DENIED:
1303 case ERROR_INVALID_PARAMETER:
1304 {
1305 break;
1306 }
1307 default :
1308 {
1309 rc = ERROR_PATH_NOT_FOUND;
1310 }
1311 }
1312 if (rc)
1313 {
1314 break;
1315 }
1316 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1317 req.request = SMBREQ_GETINFO;
1318 req.param = pConn->mem;
1319 req.paramlen = sizeof(*finfo);
1320 req.length = req.paramlen;
1321 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1322 if (pConn->rc || action < sizeof(resp) || resp.rc)
1323 {
1324 switch (resp.rc)
1325 {
1326 case NO_ERROR :
1327 case ERROR_FILE_NOT_FOUND:
1328 case ERROR_PATH_NOT_FOUND:
1329 case ERROR_ACCESS_DENIED:
1330 case ERROR_INVALID_PARAMETER:
1331 break;
1332 default :
1333 {
1334 resp.rc = ERROR_PATH_NOT_FOUND;
1335 }
1336 }
1337 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1338 }
1339 else
1340 {
1341 finfo->easize = -1;
1342 if (ifL)
1343 {
1344 getfindinfoL(pConn, plist, finfo, 0, NULL);
1345 }
1346 else
1347 {
1348 int trc;
1349 FILEFINDBUF3 buf = {0};
1350 getfindinfo(pConn, &buf, finfo);
1351 trc = ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
1352 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);
1353 }
1354 }
1355 if (rc == ERROR_FILE_NOT_FOUND)
1356 {
1357 // now try the upper path
1358 char * p = ph->fsphStrChr(finfo->fname, '\\');
1359 if (p && p > finfo->fname)
1360 {
1361 *p = 0;
1362 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1363 if (pConn->rc || action < sizeof(resp) || resp.rc)
1364 {
1365 rc = pConn->rc ? pConn->rc : (resp.rc ? ERROR_PATH_NOT_FOUND : ERROR_INVALID_PARAMETER);
1366 }
1367 }
1368 }
1369 } while (0);
1370
1371 log("NdpQueryInfo <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1372 return rc;
1373}
1374
1375int APIENTRY NdpDeletePathInfo (HRESOURCE resource, NDFILEINFOL *pfi)
1376{
1377// log("NdpDeletePathInfo %d\n", 0);
1378 return NO_ERROR;
1379}
1380
1381int APIENTRY NdpRefresh (HCONNECTION conn, char *path, int tree)
1382{
1383 log("NdpRefresh <%s> %d\n", path, 0);
1384 return NO_ERROR;
1385}
1386
1387int APIENTRY NdpDiscardResourceData (HRESOURCE resource, NDDATABUF *pdatabuf)
1388{
1389 // The plugin do not have to deallocate anything
1390 // because resource data did not contain any pointers
1391 // to plugins data.
1392 // Data stored by fsphSetResourceData will be
1393 // deallocated by NetDrive.
1394
1395 log("NdpDicardresourceData %d\n", 0);
1396 return NO_ERROR;
1397}
1398
1399int APIENTRY NdpSetPathInfo (HCONNECTION conn, NDFILEINFOL *pfi, char *szPathName)
1400{
1401 Connection *pConn = (Connection *)conn;
1402 Resource *pRes = pConn->pRes;
1403 int rc = 0;
1404 unsigned long action;
1405 smb_request req = {0};
1406 smb_response resp = {0};
1407 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
1408 char path[CCHMAXPATH+1] = {0};
1409
1410 log("NdpSetPathInfo in\n");
1411 do {
1412 rc = checkconnection(pConn);
1413 if (rc)
1414 {
1415 break;
1416 }
1417
1418 rc = pathparser(pRes, pConn, szPathName, path);
1419 if (rc)
1420 {
1421 break;
1422 }
1423
1424 MemSet(finfo, 0, sizeof(*finfo));
1425
1426 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
1427 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(finfo->mtime));
1428 if (ifL)
1429 {
1430 finfo->attr = pfi->stat.attrFile & 0x37;
1431 }
1432 else
1433 {
1434 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
1435 finfo->attr = stat->attrFile & 0x37;
1436 }
1437 req.request = SMBREQ_SETINFO;
1438 req.param = pConn->mem;
1439 req.paramlen = sizeof(*finfo);
1440 req.length = req.paramlen;
1441 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1442 if (pConn->rc || action < sizeof(resp) || resp.rc)
1443 {
1444 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1445 }
1446 } while (0);
1447 log("NdpSetPathInfo <%s> (%s) %d %d\n", szPathName, path, rc, pConn->rc);
1448 return rc;
1449}
1450
1451int buildFEALIST(FEALIST *pFEASrc, GEALIST *pGEAList, FEALIST *pFEAList)
1452{
1453 int rc = 0;
1454 FEA * pfea;
1455 FEA * pfeadest;
1456 unsigned long size, done = sizeof(pFEAList->cbList), dsize, ddone = sizeof(pFEAList->cbList);
1457
1458 size = pFEASrc->cbList;
1459 pfea = pFEASrc->list;
1460 pfeadest = pFEAList->list;
1461 dsize = pFEAList->cbList;
1462//log("buildFEALIST in destsize %d srcsize %d pGEAList=%08x pGEAList->cbList=%d\n", dsize, ddone, size, pGEAList, pGEAList ? pGEAList->cbList : 0);
1463 while (done < size)
1464 {
1465 char * name = (char *)(pfea + 1);
1466 int insert = 1;
1467 if (pGEAList && pGEAList->cbList > sizeof(pGEAList->cbList))
1468 {
1469 GEA * pgea = pGEAList->list;
1470 unsigned long size = pGEAList->cbList - sizeof(pGEAList->cbList), done = 0;
1471 insert = 0;
1472 while (done < size)
1473 {
1474//log("comp <%s> <%s>\n", name, pgea->szName);
1475 if (!ph->fsphStrNCmp(name, pgea->szName, pgea->cbName))
1476 {
1477 insert = 1;
1478 break;
1479 }
1480 done += pgea->cbName + 2;
1481 pgea = (GEA *)((char *)pgea + pgea->cbName + 2);
1482 }
1483 }
1484 if (insert)
1485 {
1486 ddone += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1487 if (ddone <= dsize)
1488 {
1489 pfeadest->cbName = pfea->cbName;
1490 pfeadest->cbValue = pfea->cbValue;
1491 pfeadest->fEA = 0;
1492 StrCpy((char *)(pfeadest + 1), name);
1493 MemCpy((char *)(pfeadest + 1) + pfea->cbName + 1, (char *)(pfea + 1) + pfea->cbName + 1, pfea->cbValue);
1494 pfeadest = (FEA *)((char *)pFEAList + ddone);
1495 }
1496 }
1497 done += sizeof(FEA) + pfea->cbName + 1 + pfea->cbValue;
1498//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);
1499 pfea = (FEA *)((char *)pFEASrc + done);
1500 }
1501 pFEAList->cbList = ddone;
1502 if (ddone > dsize && dsize > sizeof(pFEAList->cbList))
1503 {
1504 rc = ERROR_BUFFER_OVERFLOW;
1505 }
1506 log("buildFEALIST rc=%d destsize=%d destdone=%d srcsize=%d pGEAList=%08x\n", rc, dsize, ddone, size, pGEAList);
1507 return rc;
1508}
1509
1510int APIENTRY NdpEAQuery (HCONNECTION conn, GEALIST *pGEAList, NDFILEINFOL *pfi, FEALIST *pFEAList)
1511{
1512 Connection *pConn = (Connection *)conn;
1513 Resource *pRes = pConn->pRes;
1514 int rc = 0;
1515 unsigned long action;
1516 smb_request req = {0};
1517 smb_response resp = {0};
1518 char * path = NULL;
1519 FEALIST * pFEASrc;
1520 NDDATABUF fdata = {0};
1521 smbwrp_fileinfo *finfo;
1522
1523 if (!pfi || !pfi->pszName || !pFEAList)
1524 {
1525 return ERROR_EAS_NOT_SUPPORTED;
1526 }
1527 if (!pRes->easupport)
1528 {
1529 return ERROR_EAS_NOT_SUPPORTED;
1530 }
1531
1532 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1533 if (rc || !fdata.ulSize || !fdata.pData)
1534 {
1535 log("NdpEAQuery: ph->fsphGetFileInfoData = %d/%d %08x\n", rc, fdata.ulSize, fdata.pData);
1536 return ERROR_EAS_NOT_SUPPORTED;
1537 }
1538 finfo = (smbwrp_fileinfo *)fdata.pData;
1539 path = finfo->fname;
1540
1541 log("NdpEAQuery in <%s> %08x %d\n", path, pGEAList, pGEAList ? pGEAList->cbList : 0);
1542 do {
1543 rc = checkconnection(pConn);
1544 if (rc)
1545 {
1546 break;
1547 }
1548
1549 StrNCpy(pConn->mem, path, CCHMAXPATH);
1550 req.request = SMBREQ_LISTEA;
1551 req.param = pConn->mem;
1552 req.paramlen = CCHMAXPATH + 1;
1553 req.length = pRes->memlen - req.paramlen;
1554 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
1555 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1556 if (pConn->rc || action < sizeof(resp) || resp.rc)
1557 {
1558 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1559 switch (rc)
1560 {
1561 case ERROR_FILE_NOT_FOUND :
1562 case ERROR_PATH_NOT_FOUND :
1563 {
1564 pFEAList->cbList = sizeof(pFEAList->cbList);
1565 rc = NO_ERROR;
1566 } break;
1567 case ERROR_BUFFER_OVERFLOW :
1568 {
1569 pFEAList->cbList = pFEASrc->cbList;
1570 } break;
1571 default :
1572 {
1573 rc = ERROR_EAS_NOT_SUPPORTED;
1574 }
1575 }
1576 }
1577 else
1578 {
1579 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
1580 }
1581 } while (0);
1582 log("NdpEAQuery <%s> %d %d %d %d %d\n", pfi->pszName, rc, pFEASrc->cbList, pFEAList->cbList, pConn->rc, resp.rc);
1583 return rc;
1584}
1585
1586int APIENTRY NdpEASet (HCONNECTION conn, FEALIST *pFEAList, NDFILEINFOL *pfi)
1587{
1588 Connection *pConn = (Connection *)conn;
1589 Resource *pRes = pConn->pRes;
1590 int rc = 0;
1591 smb_request req = {0};
1592 smb_response resp = {0};
1593 char * path;
1594 unsigned long action;
1595 NDDATABUF fdata = {0};
1596 smbwrp_fileinfo *finfo;
1597
1598 log("NdpEASet in\n");
1599
1600 if (!pfi || !pfi->pszName || !pFEAList || pFEAList->cbList <= sizeof(long))
1601 {
1602 return ERROR_EAS_NOT_SUPPORTED;
1603 }
1604 if (!pRes->easupport)
1605 {
1606 return ERROR_EAS_NOT_SUPPORTED;
1607 }
1608
1609 if (pFEAList->cbList > pRes->memlen)
1610 {
1611 return ERROR_NOT_ENOUGH_MEMORY;
1612 }
1613
1614 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1615 if (rc || !fdata.ulSize || !fdata.pData)
1616 {
1617 log("NdpEASet: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1618 return ERROR_EAS_NOT_SUPPORTED;
1619 }
1620 finfo = (smbwrp_fileinfo *)fdata.pData;
1621 path = finfo->fname;
1622
1623 do {
1624 rc = checkconnection(pConn);
1625 if (rc)
1626 {
1627 break;
1628 }
1629
1630 StrNCpy(pConn->mem, path, CCHMAXPATH);
1631 MemCpy(pConn->mem + CCHMAXPATH + 1, pFEAList, pFEAList->cbList);
1632 req.request = SMBREQ_SETEA;
1633 req.param = pConn->mem;
1634 req.paramlen = pFEAList->cbList + CCHMAXPATH + 1;
1635 req.length = req.paramlen;
1636 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1637 if (pConn->rc || action < sizeof(resp) || resp.rc)
1638 {
1639 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1640 }
1641 } while (0);
1642 log("NdpEASet %d\n", rc);
1643 return rc;
1644}
1645
1646int APIENTRY NdpEASize (HCONNECTION conn, NDFILEINFOL *pfi, ULONG *pulEASize)
1647{
1648 Connection *pConn = (Connection *)conn;
1649 Resource *pRes = pConn->pRes;
1650 int rc = 0;
1651 unsigned long action;
1652 smb_request req = {0};
1653 smb_response resp = {0};
1654 char * path = NULL;
1655 FEALIST * pfealist;
1656 NDDATABUF fdata = {0};
1657 smbwrp_fileinfo *finfo;
1658 int easize;
1659
1660 if (!pfi || !pulEASize)
1661 {
1662 return ERROR_EAS_NOT_SUPPORTED;
1663 }
1664 if (!pRes->easupport)
1665 {
1666 return ERROR_EAS_NOT_SUPPORTED;
1667 }
1668
1669 rc = ph->fsphGetFileInfoData(pfi, &fdata, 0);
1670 if (rc || !fdata.ulSize || !fdata.pData)
1671 {
1672 log("NdpEASize: ph->fsphGetFileInfoData = %d/%d/%08x\n", rc, fdata.ulSize, fdata.pData);
1673 return ERROR_EAS_NOT_SUPPORTED;
1674 }
1675 finfo = (smbwrp_fileinfo *)fdata.pData;
1676 easize = finfo->easize;
1677 finfo->easize = -1;
1678 path = finfo->fname;
1679 if (easize >= 0)
1680 {
1681 *pulEASize = easize;
1682 log("NdpEASize <%s> cached %d\n", path, easize);
1683 return NO_ERROR;
1684 }
1685
1686 log("NdpEASize in <%s> \n", path);
1687 do {
1688 rc = checkconnection(pConn);
1689 if (rc)
1690 {
1691 break;
1692 }
1693
1694 StrNCpy(pConn->mem, path, CCHMAXPATH);
1695 req.request = SMBREQ_LISTEA;
1696 req.param = pConn->mem;
1697 req.paramlen = CCHMAXPATH + 1;
1698 req.length = pRes->memlen - req.paramlen;
1699 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
1700 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1701 if (pConn->rc || action < sizeof(resp) || resp.rc)
1702 {
1703 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1704 switch (rc)
1705 {
1706 case ERROR_FILE_NOT_FOUND :
1707 case ERROR_PATH_NOT_FOUND :
1708 {
1709 pfealist->cbList = sizeof(pfealist->cbList);
1710 } /* Fall through */
1711 case ERROR_BUFFER_OVERFLOW :
1712 {
1713 rc = NO_ERROR;
1714 } break;
1715 default :
1716 {
1717 rc = ERROR_EAS_NOT_SUPPORTED;
1718 }
1719 }
1720 }
1721 *pulEASize = pfealist->cbList;
1722 } while (0);
1723 log("NdpEASize <%s> %d %d %d %d\n", pfi->pszName, *pulEASize, rc, pConn->rc, resp.rc);
1724 return rc;
1725}
1726
1727int APIENTRY NdpSetCurrentDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szPath)
1728{
1729 Connection *pConn = (Connection *)conn;
1730 Resource *pRes = pConn->pRes;
1731 smb_request req = {0};
1732 smb_response resp = {0};
1733 int rc = 0;
1734 unsigned long action;
1735 char path[CCHMAXPATH+1] = {0};
1736
1737 log("NdpSetCurrentDir in\n");
1738 do {
1739 rc = checkconnection(pConn);
1740 if (rc)
1741 {
1742 break;
1743 }
1744
1745 rc = pathparser(pRes, pConn, szPath, path);
1746 if (rc)
1747 {
1748 break;
1749 }
1750
1751 StrNCpy(pConn->mem, path, CCHMAXPATH);
1752 req.request = SMBREQ_CHDIR;
1753 req.param = pConn->mem;
1754 req.paramlen = CCHMAXPATH + 1;
1755 req.length = req.paramlen;
1756 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1757 if (pConn->rc || action < sizeof(resp) || resp.rc)
1758 {
1759 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1760 }
1761 } while (0);
1762 log("NdpSetCurrentDir <%s> (%s) %d %d\n", szPath, path, rc, pConn->rc);
1763 return rc;
1764}
1765
1766int APIENTRY NdpCopy (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1767{
1768 log("NdpCopy <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1769 return ERROR_CANNOT_COPY;
1770}
1771
1772int APIENTRY NdpCopy2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, ULONG ulOption)
1773{
1774 log("NdpCopy2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_CANNOT_COPY);
1775 return ERROR_CANNOT_COPY;
1776}
1777
1778int APIENTRY NdpForceDelete (HCONNECTION conn, NDFILEINFOL *pfi, char *szFile)
1779{
1780 Connection *pConn = (Connection *)conn;
1781 Resource *pRes = pConn->pRes;
1782 smb_request req = {0};
1783 smb_response resp = {0};
1784 int rc = 0;
1785 unsigned long action;
1786 char path[CCHMAXPATH+1] = {0};
1787
1788 log("NdpForceDelete in\n");
1789 do {
1790 rc = checkconnection(pConn);
1791 if (rc)
1792 {
1793 break;
1794 }
1795
1796 rc = pathparser(pRes, pConn, szFile, path);
1797 if (rc)
1798 {
1799 break;
1800 }
1801
1802 StrNCpy(pConn->mem, path, CCHMAXPATH);
1803 req.request = SMBREQ_UNLINK;
1804 req.param = pConn->mem;
1805 req.paramlen = CCHMAXPATH + 1;
1806 req.length = req.paramlen;
1807 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1808 if (pConn->rc || action < sizeof(resp) || resp.rc)
1809 {
1810 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1811 }
1812 } while (0);
1813 log("NdpForceDelete <%s> (%s) %d %d\n", szFile, path, rc, pConn->rc);
1814 return rc;
1815}
1816
1817int APIENTRY NdpCreateDir (HCONNECTION conn, NDFILEINFOL *pfiparent, char *szDirName, FEALIST *pFEAList)
1818{
1819 Connection *pConn = (Connection *)conn;
1820 Resource *pRes = pConn->pRes;
1821 smb_request req = {0};
1822 smb_response resp = {0};
1823 int rc = 0;
1824 unsigned long action;
1825 char path[CCHMAXPATH+1] = {0};
1826
1827 log("NdpCreateDir in\n");
1828 do {
1829 rc = checkconnection(pConn);
1830 if (rc)
1831 {
1832 break;
1833 }
1834
1835 rc = pathparser(pRes, pConn, szDirName, path);
1836 if (rc)
1837 {
1838 break;
1839 }
1840
1841 StrNCpy(pConn->mem, path, CCHMAXPATH);
1842 req.request = SMBREQ_MKDIR;
1843 req.param = pConn->mem;
1844 req.paramlen = CCHMAXPATH + 1;
1845 req.length = req.paramlen;
1846 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1847 if (pConn->rc || action < sizeof(resp) || resp.rc)
1848 {
1849 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1850 }
1851 } while (0);
1852 log("NdpCreateDir <%s> (%s) %d %d\n", szDirName, path, rc, pConn->rc);
1853 return rc;
1854}
1855
1856int APIENTRY NdpDeleteDir (HCONNECTION conn, NDFILEINFOL *pfi, char *szDir)
1857{
1858 Connection *pConn = (Connection *)conn;
1859 Resource *pRes = pConn->pRes;
1860 smb_request req = {0};
1861 smb_response resp = {0};
1862 int rc = 0;
1863 unsigned long action;
1864 char path[CCHMAXPATH+1] = {0};
1865
1866 log("NdpDeleteDir in\n");
1867 do {
1868 rc = checkconnection(pConn);
1869 if (rc)
1870 {
1871 break;
1872 }
1873
1874 rc = pathparser(pRes, pConn, szDir, path);
1875 if (rc)
1876 {
1877 break;
1878 }
1879
1880 StrNCpy(pConn->mem, path, CCHMAXPATH);
1881 req.request = SMBREQ_RMDIR;
1882 req.param = pConn->mem;
1883 req.paramlen = CCHMAXPATH + 1;
1884 req.length = req.paramlen;
1885 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1886 if (pConn->rc || action < sizeof(resp) || resp.rc)
1887 {
1888 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1889 }
1890 } while (0);
1891 log("NdpDeleteDir <%s> (%s) %d %d\n", szDir, path, rc, pConn->rc);
1892 return rc;
1893}
1894
1895int APIENTRY NdpMove (HCONNECTION conn, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1896{
1897 Connection *pConn = (Connection *)conn;
1898 Resource *pRes = pConn->pRes;
1899 smb_request req = {0};
1900 smb_response resp = {0};
1901 int rc = 0;
1902 unsigned long action;
1903 char src[CCHMAXPATH+1] = {0};
1904 int l1, l2;
1905 char * p = szDst;
1906
1907 log("NdpMove in\n");
1908 do
1909 {
1910 rc = checkconnection(pConn);
1911 if (rc)
1912 {
1913 break;
1914 }
1915
1916 rc = pathparser(pRes, pConn, szSrc, src);
1917 if (rc)
1918 {
1919 break;
1920 }
1921 l1 = StrLen(szSrc);
1922 l2 = StrLen(src);
1923 if (l1 > l2)
1924 {
1925 if (ph->fsphStrNICmp(szSrc, szDst, l1 - l2))
1926 {
1927 // the file moved accross different shares or servers or workgroups
1928 rc = ERROR_WRITE_PROTECT;
1929 break;
1930 }
1931 p = szDst + l1 - l2 + 1;
1932 }
1933 StrNCpy(pConn->mem, src, CCHMAXPATH);
1934 pConn->mem[CCHMAXPATH + 1] = '\\';
1935 StrNCpy(pConn->mem + CCHMAXPATH + 2, p, CCHMAXPATH - 1);
1936 req.request = SMBREQ_RENAME;
1937 req.param = pConn->mem;
1938 req.paramlen = 2 * (CCHMAXPATH + 1);
1939 req.length = req.paramlen;
1940 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
1941 if (pConn->rc || action < sizeof(resp) || resp.rc)
1942 {
1943 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
1944 }
1945 } while (0);
1946 log("NdpMove <%s> -> <%s> (%s) %d %d\n", szSrc, szDst, src, rc, pConn->rc);
1947
1948 return rc;
1949}
1950
1951int APIENTRY NdpMove2 (HCONNECTION conn, HRESOURCE resDst, NDFILEINFOL *pfiDst, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc)
1952{
1953 log("NdpMove2 <%s> -> <%s> %d\n", szSrc, szDst, ERROR_WRITE_PROTECT);
1954 return ERROR_WRITE_PROTECT;
1955}
1956
1957
1958int APIENTRY NdpChangeCase (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1959{
1960 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1961}
1962
1963int APIENTRY NdpRename (HCONNECTION conn, char *szDst, NDFILEINFOL *pfiSrc, char *szSrc, char *szNewName, ULONG ulNameLen)
1964{
1965 return NdpMove (conn, pfiSrc, szDst, pfiSrc, szSrc);
1966}
1967
1968int smbopen(Connection *pConn, char *szFileName, int flags, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
1969{
1970 Resource *pRes = pConn->pRes;
1971 smb_request req = {0};
1972 smb_response resp = {0};
1973 unsigned long action;
1974 int rc = 0;
1975 char path[CCHMAXPATH+1] = {0};
1976
1977 log("smbopen in %d\n", pConn->file.fd);
1978 do {
1979 if (pConn->file.fd > 0)
1980 {
1981 rc = ERROR_TOO_MANY_OPEN_FILES;
1982 break;
1983 }
1984
1985 rc = checkconnection(pConn);
1986 if (rc)
1987 {
1988 break;
1989 }
1990
1991 rc = pathparser(pRes, pConn, szFileName, path);
1992 if (rc)
1993 {
1994 break;
1995 }
1996
1997 StrNCpy(pConn->file.fullname, szFileName, sizeof(pConn->file.fullname) - 1);
1998 StrNCpy(pConn->file.fname, path, sizeof(pConn->file.fname) - 1);
1999 flags |= O_BINARY;
2000 switch (ulOpenMode & 3)
2001 {
2002 case OPEN_ACCESS_READONLY : flags |= O_RDONLY; break;
2003 case OPEN_ACCESS_WRITEONLY : flags |= O_WRONLY; break;
2004 case OPEN_ACCESS_READWRITE : flags |= O_RDWR; break;
2005 default : flags |= O_RDWR;
2006 }
2007 pConn->file.openmode = flags;
2008 pConn->file.openattr = ulAttribute & 0x37;
2009 pConn->file.denymode = (ulOpenMode & 0x70) >> 4;
2010 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2011 req.request = SMBREQ_OPEN;
2012 req.param = pConn->mem;
2013 req.paramlen = sizeof(pConn->file);
2014 req.length = req.paramlen;
2015 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2016 if (pConn->rc || action < sizeof(resp) || resp.rc)
2017 {
2018 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2019 }
2020 else
2021 {
2022 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2023 }
2024 } while (0);
2025 log("smbopen <%s> (%s) %08x %08x %08x %d %d. file = %d\n", szFileName, path, flags, ulOpenMode, ulAttribute, rc, pConn->rc, pConn->file.fd);
2026 if (!rc && pFEAList)
2027 {
2028 int rc1 = NdpFileEASet((HCONNECTION)pConn, (NDFILEHANDLE)0, pFEAList);
2029 log("smbopen NdpFileEASet %d. pFEAList->cbList %d\n", rc1, pFEAList->cbList);
2030 }
2031
2032 return rc;
2033}
2034
2035int APIENTRY NdpOpenReplace (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2036{
2037 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
2038}
2039
2040int APIENTRY NdpOpenReplaceL(HCONNECTION conn, NDFILEINFO *pfi, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2041{
2042 return smbopen((Connection *)conn, szFileName, O_TRUNC, ulOpenMode, ulAttribute, pFEAList);
2043}
2044
2045int APIENTRY NdpOpenCreate (HCONNECTION conn, NDFILEINFOL *pfiparent, NDFILEHANDLE *phandle, char *szFileName, ULONG ulSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2046{
2047// return smbopen((Connection *)conn, szFileName, O_CREAT, ulOpenMode, ulAttribute);
2048 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
2049}
2050
2051int APIENTRY NdpOpenCreateL(HCONNECTION conn, NDFILEINFO *pfiparent, NDFILEHANDLE *phandle, char *szFileName, LONGLONG llSize, ULONG ulOpenMode, ULONG ulAttribute, FEALIST *pFEAList)
2052{
2053 return smbopen((Connection *)conn, szFileName, O_CREAT | O_EXCL, ulOpenMode, ulAttribute, pFEAList);
2054}
2055
2056int APIENTRY NdpOpenExisting (HCONNECTION conn, NDFILEINFOL *pfi, NDFILEHANDLE *phandle, char *szFileName, ULONG ulOpenMode, USHORT *pfNeedEA)
2057{
2058 if (pfNeedEA) *pfNeedEA = 0; // wtf is this ?
2059 return smbopen((Connection *)conn, szFileName, 0, ulOpenMode, 0, NULL);
2060}
2061
2062int APIENTRY NdpSetFileAttribute (HCONNECTION conn, NDFILEINFOL *pfi, char *szFileName, USHORT usAttr)
2063{
2064 Connection *pConn = (Connection *)conn;
2065 Resource *pRes = pConn->pRes;
2066 int rc = 0;
2067 unsigned long action;
2068 smb_request req = {0};
2069 smb_response resp = {0};
2070 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2071 char path[CCHMAXPATH+1] = {0};
2072
2073 log("NdpSetFileAttribute in\n");
2074 do {
2075 rc = checkconnection(pConn);
2076 if (rc)
2077 {
2078 break;
2079 }
2080
2081 rc = pathparser(pRes, pConn, szFileName, path);
2082 if (rc)
2083 {
2084 break;
2085 }
2086
2087 MemSet(finfo, 0, sizeof(*finfo));
2088
2089 StrNCpy(finfo->fname, path, sizeof(finfo->fname) - 1);
2090 finfo->attr = usAttr & 0x37;
2091 req.request = SMBREQ_SETINFO;
2092 req.param = pConn->mem;
2093 req.paramlen = sizeof(*finfo);
2094 req.length = req.paramlen;
2095 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2096 if (pConn->rc || action < sizeof(resp) || resp.rc)
2097 {
2098 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2099 }
2100 } while (0);
2101 log("NdpSetFileAttribute <%s> (%s) %04x %d %d\n", szFileName, path, usAttr, rc, pConn->rc);
2102 return rc;
2103}
2104
2105int APIENTRY NdpFlush (HRESOURCE resource)
2106{
2107 log("NdpFlush %d\n", ERROR_NOT_SUPPORTED);
2108 return ERROR_NOT_SUPPORTED;
2109}
2110
2111int APIENTRY NdpIOCTL (int type, HRESOURCE resource, char *path, int function, void *in, ULONG insize, PULONG poutlen)
2112{
2113 log("NdpIOCTL <%s> %d\n", path, function);
2114
2115 if (in && insize > 4096)
2116 {
2117 sprintf (in, "SAMBA IOCTL function = %d, parms [%s] insize = %d, *poutlen = %d", function, in, insize, *poutlen);
2118 *poutlen = insize;
2119 return NO_ERROR;
2120 }
2121
2122 return ERROR_NOT_SUPPORTED;
2123}
2124
2125int APIENTRY NdpFileQueryInfo (HCONNECTION conn, NDFILEHANDLE handle, void *plist)
2126{
2127 Connection *pConn = (Connection *)conn;
2128 Resource *pRes = pConn->pRes;
2129 int rc = 0;
2130 unsigned long action;
2131 smb_request req = {0};
2132 smb_response resp = {0};
2133 FILEFINDBUF3 buf;
2134 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)(pConn->mem + sizeof(pConn->file));
2135
2136 log("NdpFileQueryInfo in\n");
2137 do {
2138 if (pConn->file.fd < 0 || !*pConn->file.fname)
2139 {
2140 rc = ERROR_INVALID_HANDLE;
2141 break;
2142 }
2143 if (pConn->rc)
2144 {
2145 rc = ERROR_PIPE_NOT_CONNECTED;
2146 break;
2147 }
2148
2149 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2150 StrNCpy(finfo->fname, pConn->file.fname, sizeof(finfo->fname) - 1);
2151 req.request = SMBREQ_FGETINFO;
2152 req.param = pConn->mem;
2153 req.paramlen = sizeof(pConn->file);
2154 req.length = req.paramlen + sizeof(*finfo);
2155 rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2156 if (pConn->rc || action < sizeof(resp) || resp.rc)
2157 {
2158 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2159 }
2160 else
2161 {
2162 finfo->easize = -1;
2163 if (ifL)
2164 {
2165 getfindinfoL(pConn, plist, finfo, 0, NULL);
2166 }
2167 else
2168 {
2169 getfindinfo(pConn, &buf, finfo);
2170 ph->fsphAddFileFind32(plist, &buf, finfo, sizeof(*finfo), 0);
2171 }
2172 }
2173 } while (0);
2174 log("NdpFileQueryInfo <%s> %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, rc, pConn->rc);
2175
2176 return rc;
2177}
2178
2179int APIENTRY NdpFileEAQuery (HCONNECTION conn, NDFILEHANDLE handle, GEALIST *pGEAList, FEALIST *pFEAList)
2180{
2181 Connection *pConn = (Connection *)conn;
2182 Resource *pRes = pConn->pRes;
2183 int rc = 0;
2184 unsigned long action;
2185 smb_request req = {0};
2186 smb_response resp = {0};
2187 FEALIST * pFEASrc;
2188
2189 if (!pFEAList)
2190 {
2191 return ERROR_EAS_NOT_SUPPORTED;
2192 }
2193 if (!pRes->easupport)
2194 {
2195 return ERROR_EAS_NOT_SUPPORTED;
2196 }
2197
2198 log("NdpFileEAQuery in <%s>/%d pGEAList=%08x\n", pConn->file.fname, pConn->file.fd, pGEAList);
2199 do {
2200 if (pConn->file.fd < 0)
2201 {
2202 rc = ERROR_INVALID_HANDLE;
2203 break;
2204 }
2205 if (pConn->rc)
2206 {
2207 rc = ERROR_PIPE_NOT_CONNECTED;
2208 break;
2209 }
2210
2211 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2212 req.request = SMBREQ_FLISTEA;
2213 req.param = pConn->mem;
2214 req.paramlen = sizeof(pConn->file);
2215 req.length = pRes->memlen - req.paramlen;
2216 pFEASrc = (FEALIST *)(pConn->mem + req.paramlen);
2217 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2218 if (pConn->rc || action < sizeof(resp) || resp.rc)
2219 {
2220 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2221 switch (rc)
2222 {
2223 case ERROR_FILE_NOT_FOUND :
2224 case ERROR_PATH_NOT_FOUND :
2225 {
2226 pFEAList->cbList = sizeof(pFEAList->cbList);
2227 rc = NO_ERROR;
2228 } break;
2229 case ERROR_BUFFER_OVERFLOW :
2230 {
2231 pFEAList->cbList = pFEASrc->cbList;
2232 } break;
2233 default :
2234 {
2235 rc = ERROR_EAS_NOT_SUPPORTED;
2236 }
2237 }
2238 }
2239 else
2240 {
2241 rc = buildFEALIST(pFEASrc, pGEAList, pFEAList);
2242 }
2243 } while (0);
2244 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);
2245 return rc;
2246}
2247
2248int APIENTRY NdpFileEASet (HCONNECTION conn, NDFILEHANDLE handle, FEALIST *pFEAList)
2249{
2250 Connection *pConn = (Connection *)conn;
2251 Resource *pRes = pConn->pRes;
2252 int rc = 0;
2253 smb_request req = {0};
2254 smb_response resp = {0};
2255 unsigned long action;
2256
2257 log("NdpFileEASet in\n");
2258
2259 if (!pFEAList || pFEAList->cbList <= sizeof(long))
2260 {
2261 return ERROR_EAS_NOT_SUPPORTED;
2262 }
2263 if (!pRes->easupport)
2264 {
2265 return ERROR_EAS_NOT_SUPPORTED;
2266 }
2267 if (pFEAList->cbList > pRes->memlen)
2268 {
2269 return ERROR_NOT_ENOUGH_MEMORY;
2270 }
2271
2272 do {
2273 if (pConn->file.fd < 0)
2274 {
2275 rc = ERROR_INVALID_HANDLE;
2276 break;
2277 }
2278 if (pConn->rc)
2279 {
2280 rc = ERROR_PIPE_NOT_CONNECTED;
2281 break;
2282 }
2283
2284 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2285 MemCpy(pConn->mem + sizeof(pConn->file), pFEAList, pFEAList->cbList);
2286 req.request = SMBREQ_FSETEA;
2287 req.param = pConn->mem;
2288 req.paramlen = pFEAList->cbList + sizeof(pConn->file);
2289 req.length = req.paramlen;
2290
2291 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2292 if (pConn->rc || action < sizeof(resp) || resp.rc)
2293 {
2294 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2295 }
2296 } while (0);
2297 log("NdpFileEASet %d\n", rc);
2298 return rc;
2299}
2300
2301int APIENTRY NdpFileEASize (HCONNECTION conn, NDFILEHANDLE handle, ULONG *pulEASize)
2302{
2303 Connection *pConn = (Connection *)conn;
2304 Resource *pRes = pConn->pRes;
2305 int rc = 0;
2306 unsigned long action;
2307 smb_request req = {0};
2308 smb_response resp = {0};
2309 char path[CCHMAXPATH+1] = {0};
2310 FEALIST * pfealist;
2311
2312 if (!pulEASize)
2313 {
2314 return ERROR_EAS_NOT_SUPPORTED;
2315 }
2316 if (!pRes->easupport)
2317 {
2318 return ERROR_EAS_NOT_SUPPORTED;
2319 }
2320
2321 log("NdpFileEASize in <%s>/%d \n", pConn->file.fname, pConn->file.fd);
2322 do {
2323 if (pConn->file.fd < 0)
2324 {
2325 rc = ERROR_INVALID_HANDLE;
2326 break;
2327 }
2328 if (pConn->rc)
2329 {
2330 rc = ERROR_PIPE_NOT_CONNECTED;
2331 break;
2332 }
2333
2334 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2335 req.request = SMBREQ_FLISTEA;
2336 req.param = pConn->mem;
2337 req.paramlen = sizeof(pConn->file);
2338 req.length = pRes->memlen - req.paramlen;
2339 pfealist = (FEALIST *)(pConn->mem + req.paramlen);
2340 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2341 if (pConn->rc || action < sizeof(resp) || resp.rc)
2342 {
2343 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2344 switch (rc)
2345 {
2346 case ERROR_FILE_NOT_FOUND :
2347 case ERROR_PATH_NOT_FOUND :
2348 {
2349 pfealist->cbList = sizeof(pfealist->cbList);
2350 } /* Fall through */
2351 case ERROR_BUFFER_OVERFLOW :
2352 {
2353 rc = NO_ERROR;
2354 } break;
2355 default :
2356 {
2357 rc = ERROR_EAS_NOT_SUPPORTED;
2358 }
2359 }
2360 }
2361 *pulEASize = pfealist->cbList;
2362 } while (0);
2363 log("NdpFileEASize %d %d %d %d\n", *pulEASize, rc, pConn->rc, resp.rc);
2364 return rc;
2365}
2366
2367int APIENTRY NdpFileSetInfo (HCONNECTION conn, NDFILEHANDLE handle, NDFILEINFOL *pfi)
2368{
2369 Connection *pConn = (Connection *)conn;
2370 Resource *pRes = pConn->pRes;
2371 int rc = 0;
2372 unsigned long action, attrFile;
2373 smb_request req = {0};
2374 smb_response resp = {0};
2375 smbwrp_fileinfo * finfo = (smbwrp_fileinfo *)pConn->mem;
2376
2377 log("NdpFileSetInfo in\n");
2378 do {
2379 if (pConn->file.fd < 0 || !*pConn->file.fname)
2380 {
2381 rc = ERROR_INVALID_HANDLE;
2382 break;
2383 }
2384 if (pConn->rc)
2385 {
2386 rc = ERROR_PIPE_NOT_CONNECTED;
2387 break;
2388 }
2389 if (ifL)
2390 {
2391 attrFile = pfi->stat.attrFile;
2392 }
2393 else
2394 {
2395 FILESTATUS3 * stat = (FILESTATUS3 *)&(pfi->stat);
2396 attrFile = stat->attrFile;
2397 }
2398 // deferred setinfo - on closing the file
2399 pConn->file.openattr = attrFile;
2400 ph->fsphDosDateToUnixTime(pfi->stat.fdateLastWrite, pfi->stat.ftimeLastWrite, (unsigned long *)&(pConn->file.mtime));
2401 } while (0);
2402 log("NdpFileSetInfo <%s> %08x %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, attrFile, rc, pConn->rc);
2403 return NO_ERROR;
2404}
2405
2406int APIENTRY NdpFileSetFilePtrL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llOffset, ULONG ulMethod, LONGLONG *pllActual)
2407{
2408 Connection *pConn = (Connection *)conn;
2409 Resource *pRes = pConn->pRes;
2410 int rc = 0;
2411 unsigned long action;
2412 smb_request req = {0};
2413 smb_response resp = {0};
2414
2415 log("NdpFileSetFilePtrl in\n");
2416 do {
2417 if (pConn->file.fd < 0)
2418 {
2419 rc = ERROR_INVALID_HANDLE;
2420 break;
2421 }
2422 if (pConn->rc)
2423 {
2424 rc = ERROR_PIPE_NOT_CONNECTED;
2425 break;
2426 }
2427
2428 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2429 *(unsigned long *)(pConn->mem + sizeof(pConn->file)) = ulMethod;
2430 *(long long *)(pConn->mem + sizeof(pConn->file) + sizeof(long)) = llOffset;
2431 req.request = SMBREQ_LSEEK;
2432 req.param = pConn->mem;
2433 req.paramlen = sizeof(pConn->file) + sizeof(long) + sizeof(long long);
2434 req.length = req.paramlen;
2435 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2436 if (pConn->rc || action < sizeof(resp) || resp.rc)
2437 {
2438 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2439 }
2440 else
2441 {
2442 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2443 *pllActual = pConn->file.offset;
2444 }
2445 } while (0);
2446 log("NdpFileSetFilePtrL <%s> %lld %lu %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llOffset, ulMethod, *pllActual, rc, pConn->rc);
2447
2448 return rc;
2449}
2450
2451int APIENTRY NdpFileSetFilePtr (HCONNECTION conn, NDFILEHANDLE handle, LONG lOffset, ULONG ulMethod, ULONG *pulActual)
2452{
2453 LONGLONG llActual;
2454 int rc = NdpFileSetFilePtrL(conn, handle, lOffset, ulMethod, &llActual);
2455 *pulActual = llActual & 0xFFFFFFFF;
2456 log("NdpFileSetFilePtr %ld %lu %ld %d\n", lOffset, ulMethod, *pulActual, rc);
2457 return rc;
2458}
2459
2460int APIENTRY NdpFileClose (HCONNECTION conn, NDFILEHANDLE handle)
2461{
2462 Connection *pConn = (Connection *)conn;
2463 Resource *pRes = pConn->pRes;
2464 int rc = 0;
2465 unsigned long action;
2466 smb_request req = {0};
2467 smb_response resp = {0};
2468
2469 log("NdpFileClose in %d <%s>\n", pConn->file.fd, pConn->file.fd < 0 ? "!null!" : pConn->file.fname);
2470
2471 do {
2472 if (pConn->file.fd < 0)
2473 {
2474 rc = ERROR_INVALID_HANDLE;
2475 break;
2476 }
2477 if (pConn->rc)
2478 {
2479 rc = ERROR_PIPE_NOT_CONNECTED;
2480 break;
2481 }
2482
2483 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2484 req.request = SMBREQ_CLOSE;
2485 req.param = pConn->mem;
2486 req.length = pRes->memlen;
2487 req.paramlen = sizeof(pConn->file);
2488 req.length = req.paramlen;
2489 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2490 if (pConn->rc || action < sizeof(resp) || resp.rc)
2491 {
2492 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2493 }
2494 else
2495 {
2496 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2497 }
2498 } while (0);
2499 log("NdpFileClose %d %d %d\n", pConn->file.fd, rc, pConn->rc);
2500 pConn->file.fd = -1;
2501 return rc;
2502}
2503
2504int APIENTRY NdpFileCommit (HCONNECTION conn, NDFILEHANDLE handle)
2505{
2506 log("NdpFileCommit %d\n", NO_ERROR);
2507 return NO_ERROR;
2508}
2509
2510
2511int APIENTRY NdpFileNewSize (HCONNECTION conn, NDFILEHANDLE handle, ULONG ulLen)
2512{
2513 int rc = NdpFileNewSizeL(conn, handle, ulLen);
2514 log("NdpFileNewSize %ld %d\n", ulLen, rc);
2515 return rc;
2516}
2517
2518int APIENTRY NdpFileNewSizeL(HCONNECTION conn, NDFILEHANDLE handle, LONGLONG llLen)
2519{
2520 Connection *pConn = (Connection *)conn;
2521 Resource *pRes = pConn->pRes;
2522 int rc = 0;
2523 unsigned long action;
2524 smb_request req = {0};
2525 smb_response resp = {0};
2526
2527 log("NdpFileNewSizeL in\n");
2528 do {
2529 if (pConn->file.fd < 0)
2530 {
2531 rc = ERROR_INVALID_HANDLE;
2532 break;
2533 }
2534 if (pConn->rc)
2535 {
2536 rc = ERROR_PIPE_NOT_CONNECTED;
2537 break;
2538 }
2539
2540 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2541 *(long long *)(pConn->mem + sizeof(pConn->file)) = llLen;
2542
2543 req.request = SMBREQ_NEWSIZE;
2544 req.param = pConn->mem;
2545 req.paramlen = sizeof(pConn->file) + sizeof(long long);
2546 req.length = req.paramlen;
2547
2548 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2549 if (pConn->rc || action < sizeof(resp) || resp.rc)
2550 {
2551 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2552 }
2553 else
2554 {
2555 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2556 }
2557 } while (0);
2558 log("NdpFileNewSizeL <%s> %lld %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, llLen, rc, pConn->rc);
2559 return rc;
2560}
2561
2562int APIENTRY NdpFileRead (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulRead, ULONG *pulActual)
2563{
2564 Connection *pConn = (Connection *)conn;
2565 Resource *pRes = pConn->pRes;
2566 int rc = 0;
2567 unsigned long done = 0;
2568 unsigned long onedone;
2569 unsigned long action;
2570 smb_request req = {0};
2571 smb_response resp = {0};
2572
2573 log("NdpFileRead in\n");
2574// log("NdpFileRead <%s> %lu\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead);
2575
2576 do {
2577 if (pConn->file.fd < 0)
2578 {
2579 rc = ERROR_INVALID_HANDLE;
2580 break;
2581 }
2582 if (pConn->rc)
2583 {
2584 rc = ERROR_PIPE_NOT_CONNECTED;
2585 break;
2586 }
2587
2588 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2589 req.request = SMBREQ_READ;
2590 req.param = pConn->mem;
2591 req.paramlen = sizeof(pConn->file);
2592
2593 while (done < ulRead)
2594 {
2595 req.length = req.paramlen + (pRes->memlen - req.paramlen < (ulRead - done) ? pRes->memlen - req.paramlen : (ulRead - done));
2596
2597 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2598 if (pConn->rc || action < sizeof(resp) || resp.rc)
2599 {
2600 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2601 break;
2602 }
2603 if (resp.value == 0)
2604 {
2605 break;
2606 }
2607 onedone = resp.value > req.length ? req.length : resp.value;
2608 MemCpy((char *)pBuffer + done, pConn->mem + sizeof(pConn->file), onedone);
2609 done += onedone;
2610 }
2611 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2612 *pulActual = done;
2613 } while (0);
2614 log("NdpFileRead <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulRead, *pulActual, rc, pConn->rc);
2615
2616 return rc;
2617}
2618
2619int APIENTRY NdpFileWrite (HCONNECTION conn, NDFILEHANDLE handle, void *pBuffer, ULONG ulWrite, ULONG *pulActual)
2620{
2621 Connection *pConn = (Connection *)conn;
2622 Resource *pRes = pConn->pRes;
2623 int rc = 0;
2624 unsigned long done = 0;
2625 unsigned long onedone;
2626 unsigned long action;
2627 smb_request req = {0};
2628 smb_response resp = {0};
2629
2630 log("NdpFileWrite in\n");
2631 do {
2632 if (pConn->file.fd < 0)
2633 {
2634 rc = ERROR_INVALID_HANDLE;
2635 break;
2636 }
2637 if (pConn->rc)
2638 {
2639 rc = ERROR_PIPE_NOT_CONNECTED;
2640 break;
2641 }
2642
2643 MemCpy(pConn->mem, &pConn->file, sizeof(pConn->file));
2644 req.request = SMBREQ_WRITE;
2645 req.param = pConn->mem;
2646 req.paramlen = sizeof(pConn->file);
2647
2648 while (done < ulWrite)
2649 {
2650 req.length = pRes->memlen - req.paramlen < (ulWrite - done) ? pRes->memlen - req.paramlen : (ulWrite - done);
2651 MemCpy(pConn->mem + sizeof(pConn->file), (char *)pBuffer + done, req.length);
2652 req.length += req.paramlen;
2653
2654 pConn->rc = _DosTransactNPipe(pConn, &req, sizeof(req), &resp, sizeof(resp), &action);
2655 if (pConn->rc || action < sizeof(resp) || resp.rc)
2656 {
2657 rc = pConn->rc ? pConn->rc : (resp.rc ? resp.rc : ERROR_INVALID_PARAMETER);
2658 break;
2659 }
2660 done += resp.value & 0xFFFFFFFF;
2661 if (resp.value < req.length)
2662 {
2663 break;
2664 }
2665 }
2666 MemCpy(&pConn->file, pConn->mem, sizeof(pConn->file));
2667 *pulActual = done;
2668 } while (0);
2669 log("NdpFileWrite <%s> %lu %lu %d %d\n", pConn->file.fd < 0 ? "!null!" : pConn->file.fname, ulWrite, *pulActual, rc, pConn->rc);
2670
2671 return rc;
2672}
Note: See TracBrowser for help on using the repository browser.