Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

792 lines
19 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. srvtrans.c
  5. Abstract:
  6. Implements transaction smb packets
  7. Author:
  8. Ahmed Mohamed (ahmedm) 1-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "srv.h"
  12. typedef struct {
  13. HANDLE handle;
  14. WIN32_FIND_DATA *last;
  15. ULONG cookie;
  16. USHORT Sid;
  17. USHORT info_level;
  18. USHORT base_size;
  19. USHORT add_res_key;
  20. }dm_t;
  21. static CRITICAL_SECTION dLock;
  22. #define DirTableSz 1024
  23. static dm_t *DirTable[DirTableSz];
  24. #define SET_REQ(x, type, p) { \
  25. x = (type) (p)->in.pParameters; \
  26. (p)->in.pParameters += sizeof(*x); \
  27. }
  28. // XXX: need to handle padding
  29. void*
  30. ADD_RESP_PARAMS(
  31. Packet_t * msg,
  32. Trans2_t * trans2,
  33. PVOID resp,
  34. USHORT size
  35. )
  36. {
  37. PUCHAR p;
  38. if (trans2->out.ParameterBytesLeft < size) return 0;
  39. if (trans2->out.pResp->DataCount) {
  40. PUCHAR d = (PUCHAR)msg->out.smb;
  41. d += trans2->out.pResp->DataOffset;
  42. // need to use MoveMemory due to possible overlap
  43. RtlMoveMemory((PVOID)(d + size),
  44. (PVOID)d, trans2->out.pResp->DataCount);
  45. // we up the data offset below
  46. }
  47. p = (PUCHAR)msg->out.smb;
  48. p += trans2->out.pResp->ParameterOffset +
  49. trans2->out.pResp->ParameterCount;
  50. if (resp) RtlCopyMemory((PVOID)p, (PVOID)resp, (ULONG)size);
  51. trans2->out.pResp->ParameterCount += size;
  52. trans2->out.pResp->TotalParameterCount += size;
  53. *(trans2->out.pByteCount) += size;
  54. trans2->out.pResp->DataOffset += size;
  55. msg->out.valid += size;
  56. trans2->out.ParameterBytesLeft -= size;
  57. return p;
  58. }
  59. void*
  60. ADD_RESP_DATA(
  61. Packet_t * msg,
  62. Trans2_t * trans2,
  63. PVOID resp,
  64. USHORT size
  65. )
  66. {
  67. PUCHAR d;
  68. if (trans2->out.DataBytesLeft < size) {
  69. return 0;
  70. }
  71. d = (PUCHAR)msg->out.smb;
  72. d += (trans2->out.pResp->DataOffset +
  73. trans2->out.pResp->DataCount);
  74. if (resp != NULL) {
  75. RtlCopyMemory((PVOID)d, (PVOID)resp, (ULONG)size);
  76. }
  77. trans2->out.pResp->DataCount += size;
  78. trans2->out.pResp->TotalDataCount += size;
  79. *(trans2->out.pByteCount) += size;
  80. msg->out.valid += size;
  81. trans2->out.DataBytesLeft -= size;
  82. return d;
  83. }
  84. ////
  85. BOOL
  86. Trans2Unknown(
  87. Packet_t * msg,
  88. Trans2_t * trans2
  89. )
  90. {
  91. SrvLogError(("DOSERROR: (------ CANNOT HANDLE THIS TRANS2 FUNCTION ------)\n"));
  92. SET_DOSERROR(msg, SERVER, NO_SUPPORT);
  93. return FALSE;
  94. }
  95. BOOL
  96. Trans2QueryFsInfo(
  97. Packet_t * msg,
  98. Trans2_t * trans2
  99. )
  100. {
  101. PVOID fshdl;
  102. USHORT tid = msg->in.smb->Tid;
  103. USHORT uid = msg->in.smb->Uid;
  104. PVOID fsctx = SRV_GET_FS_HANDLE(msg);
  105. FsDispatchTable* pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  106. fs_attr_t fsattr;
  107. DWORD error;
  108. PREQ_QUERY_FS_INFORMATION pReq;
  109. SET_REQ(pReq, PREQ_QUERY_FS_INFORMATION, trans2);
  110. if (!pDisp) {
  111. SrvLogError(("DOSERROR: no such uid\n"));
  112. SET_DOSERROR(msg, SERVER, BAD_UID);
  113. return FALSE;
  114. }
  115. error = pDisp->FsStatfs(fshdl, &fsattr);
  116. if (error) {
  117. SrvLogError(("WIN32ERROR: statfs error 0x%08X\n", error));
  118. SET_WIN32ERROR(msg, error);
  119. return FALSE;
  120. }
  121. SrvLog(("statfs %s level %d %d\n",
  122. fsattr.fs_name,
  123. pReq->InformationLevel,
  124. trans2->out.pResp->WordCount));
  125. trans2->out.pResp->WordCount--;
  126. switch (pReq->InformationLevel) {
  127. case SMB_INFO_ALLOCATION: {
  128. FSALLOCATE Resp;
  129. Resp.idFileSystem = 0;
  130. Resp.cSectorUnit = fsattr.sectors_per_unit;
  131. Resp.cbSector = (USHORT)fsattr.bytes_per_sector;
  132. Resp.cUnit = (ULONG)fsattr.total_units;
  133. Resp.cUnitAvail = (ULONG)fsattr.free_units;
  134. SrvLog(("statfs %u %u\n", Resp.cUnit, Resp.cUnitAvail));
  135. ADD_RESP_DATA(msg, trans2, &Resp, sizeof(FSALLOCATE));
  136. return TRUE;
  137. }
  138. case SMB_INFO_VOLUME: {
  139. FSINFO Resp;
  140. const int maxlen = sizeof(Resp.vol.szVolLabel);
  141. Resp.ulVsn = 0xFADB;
  142. Resp.vol.cch = min(lstrlen(fsattr.fs_name), maxlen);
  143. lstrcpyn(Resp.vol.szVolLabel, fsattr.fs_name, maxlen);
  144. SrvLog(("statfs name %s %d %d, %d\n",
  145. fsattr.fs_name, Resp.vol.cch,
  146. sizeof(FSINFO), sizeof(*msg->out.smb)));
  147. ADD_RESP_DATA(msg, trans2, &Resp, sizeof(FSINFO));
  148. return TRUE;
  149. }
  150. case SMB_QUERY_FS_VOLUME_INFO: {
  151. const int name_len = lstrlen(fsattr.fs_name);
  152. const USHORT size = sizeof(FILE_FS_VOLUME_INFORMATION) + name_len + 2;
  153. PFILE_FS_VOLUME_INFORMATION pResp =
  154. (PFILE_FS_VOLUME_INFORMATION)xmalloc(size);
  155. pResp->VolumeCreationTime.QuadPart = 0;
  156. pResp->VolumeSerialNumber = 0xFEED;
  157. pResp->VolumeLabelLength = name_len * sizeof(WCHAR);
  158. // sprintf((char*)pResp->VolumeLabel, "%S", fsattr.fs_name);
  159. strcpy((char *)pResp->VolumeLabel, fsattr.fs_name);
  160. ADD_RESP_DATA(msg, trans2, pResp, size);
  161. xfree(pResp);
  162. return TRUE;
  163. }
  164. default:
  165. SrvLogError(("DOSERROR: <COULD NOT UNDERSTAND INFO LEVEL>\n"));
  166. SET_DOSERROR(msg, SERVER, NO_SUPPORT);
  167. return FALSE;
  168. }
  169. }
  170. void
  171. Trans2Init()
  172. {
  173. int i;
  174. InitializeCriticalSection(&dLock);
  175. memset(DirTable, 0, sizeof(DirTable));
  176. }
  177. dm_t *
  178. dm_alloc()
  179. {
  180. int i;
  181. dm_t *dm;
  182. dm = (dm_t *) malloc(sizeof(*dm));
  183. if (dm == NULL)
  184. return NULL;
  185. dm->handle = INVALID_HANDLE_VALUE;
  186. dm->last = NULL;
  187. EnterCriticalSection(&dLock);
  188. for (i = 0; i < DirTableSz; i++) {
  189. if (DirTable[i] == NULL) {
  190. dm->Sid = (USHORT) i;
  191. DirTable[i] = dm;
  192. break;
  193. }
  194. }
  195. LeaveCriticalSection(&dLock);
  196. if (i == DirTableSz) {
  197. free((char *) dm);
  198. dm = NULL;
  199. }
  200. return dm;
  201. }
  202. void
  203. dm_init(dm_t *p, USHORT _info_level, USHORT _add_res_key)
  204. {
  205. p->info_level = _info_level;
  206. p->add_res_key = _add_res_key;
  207. p->base_size = p->add_res_key ? sizeof(ULONG):0;
  208. switch (p->info_level) {
  209. case SMB_INFO_STANDARD:
  210. p->base_size += sizeof(SMB_FIND_BUFFER);
  211. break;
  212. case SMB_INFO_QUERY_EA_SIZE:
  213. p->base_size += sizeof(SMB_FIND_BUFFER2);
  214. break;
  215. case SMB_INFO_QUERY_EAS_FROM_LIST:
  216. case SMB_FIND_FILE_DIRECTORY_INFO:
  217. case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
  218. case SMB_FIND_FILE_NAMES_INFO:
  219. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  220. default:
  221. p->base_size = 0;
  222. }
  223. }
  224. void
  225. dm_free(dm_t *dm)
  226. {
  227. EnterCriticalSection(&dLock);
  228. ASSERT(DirTable[dm->Sid] == dm);
  229. DirTable[dm->Sid] = NULL;
  230. LeaveCriticalSection(&dLock);
  231. if (dm->last) {
  232. free((char *) dm->last);
  233. }
  234. if (dm->handle != INVALID_HANDLE_VALUE) {
  235. // printf("Closing srch hdl %x\n", dm->handle);
  236. FindClose(dm->handle);
  237. }
  238. free((char *)dm);
  239. }
  240. dm_t *
  241. dm_find(USHORT Sid)
  242. {
  243. dm_t *dm;
  244. if (Sid >= DirTableSz) {
  245. return NULL;
  246. }
  247. // no need to get lock
  248. dm = DirTable[Sid];
  249. ASSERT(dm != NULL);
  250. ASSERT(dm->Sid == Sid);
  251. return dm;
  252. }
  253. DWORD
  254. dm_close(USHORT Sid)
  255. {
  256. dm_t *dm;
  257. dm = dm_find(Sid);
  258. if (dm == NULL) {
  259. return ERROR_INVALID_HANDLE;
  260. }
  261. dm_free(dm);
  262. return ERROR_SUCCESS;
  263. }
  264. void
  265. dm_addentry(dm_t *dm, void* p, WIN32_FIND_DATA *entry, USHORT name_len)
  266. {
  267. if (dm->add_res_key) {
  268. PULONG pl = (PULONG)p;
  269. *pl = dm->cookie;
  270. pl++;
  271. p = pl;
  272. }
  273. switch (dm->info_level) {
  274. case SMB_INFO_STANDARD: {
  275. PSMB_FIND_BUFFER pResp = (PSMB_FIND_BUFFER) p;
  276. time64_to_smb_datetime((TIME64 *)&entry->ftCreationTime,
  277. &pResp->CreationDate.Ushort,
  278. &pResp->CreationTime.Ushort);
  279. time64_to_smb_datetime((TIME64 *)&entry->ftLastAccessTime,
  280. &pResp->LastAccessDate.Ushort,
  281. &pResp->LastAccessTime.Ushort);
  282. time64_to_smb_datetime((TIME64 *)&entry->ftLastWriteTime,
  283. &pResp->LastWriteDate.Ushort,
  284. &pResp->LastWriteTime.Ushort);
  285. pResp->DataSize = entry->nFileSizeLow;
  286. pResp->AllocationSize = pResp->DataSize;
  287. pResp->Attributes = attribs_to_smb_attribs(entry->dwFileAttributes);
  288. pResp->FileNameLength = (UCHAR) name_len;
  289. RtlCopyMemory(pResp->FileName, entry->cFileName, name_len + 1);
  290. return;
  291. }
  292. case SMB_INFO_QUERY_EA_SIZE: {
  293. PSMB_FIND_BUFFER2 pResp = (PSMB_FIND_BUFFER2) p;
  294. time64_to_smb_datetime((TIME64 *)&entry->ftCreationTime,
  295. &pResp->CreationDate.Ushort,
  296. &pResp->CreationTime.Ushort);
  297. time64_to_smb_datetime((TIME64 *)&entry->ftLastAccessTime,
  298. &pResp->LastAccessDate.Ushort,
  299. &pResp->LastAccessTime.Ushort);
  300. time64_to_smb_datetime((TIME64 *)&entry->ftLastWriteTime,
  301. &pResp->LastWriteDate.Ushort,
  302. &pResp->LastWriteTime.Ushort);
  303. pResp->DataSize = entry->nFileSizeLow;
  304. pResp->AllocationSize = pResp->DataSize;
  305. pResp->Attributes = attribs_to_smb_attribs(entry->dwFileAttributes);
  306. pResp->EaSize = 0;
  307. pResp->FileNameLength = (UCHAR)name_len;
  308. RtlCopyMemory(pResp->FileName, entry->cFileName, name_len + 1);
  309. return;
  310. }
  311. case SMB_INFO_QUERY_EAS_FROM_LIST:
  312. case SMB_FIND_FILE_DIRECTORY_INFO:
  313. case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
  314. case SMB_FIND_FILE_NAMES_INFO:
  315. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  316. default:
  317. return;
  318. }
  319. }
  320. DWORD
  321. bad_info_level(
  322. Packet_t * msg
  323. )
  324. {
  325. SrvLogError(("DOSERROR: <COULD NOT UNDERSTAND INFO LEVEL>\n"));
  326. return ERROR_INVALID_FUNCTION;
  327. }
  328. BOOL
  329. Trans2FindFirst2(
  330. Packet_t * msg,
  331. Trans2_t * trans2
  332. )
  333. {
  334. PVOID fshdl;
  335. USHORT tid;
  336. USHORT uid;
  337. PVOID fsctx;
  338. FsDispatchTable* pDisp;
  339. dm_t *dm;
  340. WCHAR wfull_path[MAXPATH];
  341. char *path, full_path[MAXPATH];
  342. DWORD error;
  343. WIN32_FIND_DATA entry;
  344. PVOID d = 0;
  345. PRESP_FIND_FIRST2 pResp;
  346. PREQ_FIND_FIRST2 pReq;
  347. if (msg == NULL || trans2 == NULL)
  348. return FALSE;
  349. tid = msg->in.smb->Tid;
  350. uid = msg->in.smb->Uid;
  351. fsctx = SRV_GET_FS_HANDLE(msg);
  352. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  353. SET_REQ(pReq, PREQ_FIND_FIRST2, trans2);
  354. if (!pDisp) {
  355. SrvLogError(("DOSERROR: bad uid %d\n", uid));
  356. SET_DOSERROR(msg, SERVER, BAD_UID);
  357. return FALSE;
  358. }
  359. dm = dm_alloc();
  360. if (!dm) {
  361. SrvLogError(("DOSERROR:dm_alloc failed\n"));
  362. SET_WIN32ERROR(msg, ERROR_TOO_MANY_OPEN_FILES);
  363. return FALSE;
  364. }
  365. dm_init(dm, pReq->InformationLevel,
  366. pReq->Flags & SMB_FIND_RETURN_RESUME_KEYS);
  367. if (!dm->base_size) {
  368. dm_free(dm);
  369. SET_WIN32ERROR(msg, bad_info_level(msg));
  370. return FALSE;
  371. }
  372. path = (char*)pReq->Buffer;
  373. // todo: Instead of using findfirst(), read whole directory and
  374. // store it locally in a temperary buffer. That way I don't have
  375. // to deal with a handle failing in the middle. Or, ensure that all
  376. // reads happen on a consistent local replica.
  377. // build our path
  378. pDisp->FsGetRoot(fshdl, wfull_path);
  379. // convert to ascii
  380. full_path[0] = '\0';
  381. error = wcstombs(full_path, wfull_path, wcslen(wfull_path));
  382. full_path[error] = '\0';
  383. strcat(full_path, path);
  384. pResp = (PRESP_FIND_FIRST2)
  385. ADD_RESP_PARAMS(msg, trans2, 0, sizeof(RESP_FIND_FIRST2));
  386. if (!pResp) {
  387. SrvLogError(("DOSERROR: not enough buffer space...\n"));
  388. SET_DOSERROR(msg, SERVER, ERROR);
  389. return FALSE;
  390. }
  391. dm->handle = FindFirstFile(full_path, &entry);
  392. if (dm->handle == INVALID_HANDLE_VALUE) {
  393. error = GetLastError();
  394. SrvLogError(("DOSERROR: could not find filter in '%s' %d\n",full_path, error));
  395. SET_DOSERROR(msg, SERVER, FILE_SPECS);
  396. return FALSE;
  397. }
  398. // entry number 0
  399. dm->cookie = 0;
  400. pResp->SearchCount = 0;
  401. dm->last = &entry;
  402. while (msg->out.size > msg->out.valid) {
  403. DWORD name_len;
  404. USHORT len;
  405. len = dm->base_size + lstrlen(entry.cFileName);
  406. if (len <= (msg->out.size - msg->out.valid)) {
  407. d = ADD_RESP_DATA(msg, trans2, 0, len);
  408. dm_addentry(dm, d, &entry, len - dm->base_size);
  409. dm->cookie++;
  410. pResp->SearchCount++;
  411. if (FindNextFile(dm->handle, &entry) == 0) {
  412. error = GetLastError();
  413. dm->last = NULL;
  414. break;
  415. }
  416. } else {
  417. // we are out of space
  418. break;
  419. }
  420. }
  421. if (dm->last != NULL) {
  422. WIN32_FIND_DATA *p;
  423. // we ran out of buffer space, we need to safe this entry in our dm
  424. dm->last = NULL;
  425. p = (WIN32_FIND_DATA *) malloc(sizeof(*p));
  426. if (p != NULL) {
  427. memcpy(p, &entry, sizeof(entry));
  428. dm->last = p;
  429. } else {
  430. // todo: should return failure here
  431. ;
  432. }
  433. }
  434. // -- common --
  435. pResp->EndOfSearch = (error == 18)?1:0;
  436. pResp->LastNameOffset = (pResp->EndOfSearch)?(((USHORT)((char*)d -
  437. (char*)msg->out.smb)) -
  438. trans2->out.pResp->DataOffset):0;
  439. pResp->EaErrorOffset = 0;
  440. if ((pReq->Flags & SMB_FIND_CLOSE_AFTER_REQUEST) ||
  441. ((pReq->Flags & SMB_FIND_CLOSE_AT_EOS) && pResp->EndOfSearch)) {
  442. pResp->Sid = 0xFFFF;
  443. dm_free(dm);
  444. } else {
  445. pResp->Sid = dm->Sid;
  446. }
  447. return TRUE;
  448. }
  449. BOOL
  450. Trans2FindNext2(
  451. Packet_t * msg,
  452. Trans2_t * trans2
  453. )
  454. {
  455. PVOID fshdl;
  456. USHORT tid;
  457. USHORT uid;
  458. PVOID fsctx;
  459. FsDispatchTable* pDisp;
  460. DWORD error;
  461. dm_t *dm;
  462. PVOID d;
  463. PRESP_FIND_NEXT2 pResp;
  464. PREQ_FIND_NEXT2 pReq;
  465. if (msg == NULL || trans2 == NULL)
  466. return FALSE;
  467. tid = msg->in.smb->Tid;
  468. uid = msg->in.smb->Uid;
  469. fsctx = SRV_GET_FS_HANDLE(msg);
  470. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  471. SET_REQ(pReq, PREQ_FIND_NEXT2, trans2);
  472. if (!pDisp) {
  473. SrvLogError(("DOSERROR: bad uid %d\n", uid));
  474. SET_DOSERROR(msg, SERVER, BAD_UID);
  475. return FALSE;
  476. }
  477. dm = dm_find(pReq->Sid);
  478. if (dm == NULL) {
  479. SrvLogError(("DOSERROR: could not find sid\n"));
  480. SET_DOSERROR(msg, DOS, BAD_FID);
  481. return FALSE;
  482. }
  483. dm_init(dm, pReq->InformationLevel,
  484. pReq->Flags & SMB_FIND_RETURN_RESUME_KEYS);
  485. if (!dm->base_size) {
  486. SET_WIN32ERROR(msg, bad_info_level(msg));
  487. return FALSE;
  488. }
  489. pResp = (PRESP_FIND_NEXT2)
  490. ADD_RESP_PARAMS(msg, trans2, 0, sizeof(RESP_FIND_NEXT2));
  491. if (!pResp) {
  492. SrvLogError(("DOSERROR: not enough buffer space...\n"));
  493. SET_DOSERROR(msg, SERVER, ERROR);
  494. return FALSE;
  495. }
  496. if (!(pReq->Flags & SMB_FIND_CONTINUE_FROM_LAST))
  497. dm->cookie = pReq->ResumeKey;
  498. pResp->SearchCount = 0;
  499. while (msg->out.size > msg->out.valid) {
  500. if (dm->last) {
  501. USHORT len;
  502. len = lstrlen(dm->last->cFileName) + dm->base_size;
  503. if (len <= (msg->out.size - msg->out.valid)) {
  504. d = ADD_RESP_DATA(msg, trans2, 0, len);
  505. dm_addentry(dm, d, dm->last, len - dm->base_size);
  506. dm->cookie++;
  507. pResp->SearchCount++;
  508. } else {
  509. break;
  510. }
  511. }
  512. if (FindNextFile(dm->handle, dm->last) == 0) {
  513. error = GetLastError();
  514. free((char *)dm->last);
  515. dm->last = NULL;
  516. break;
  517. }
  518. }
  519. // -- common --
  520. pResp->EndOfSearch = (error == 18)?1:0;
  521. pResp->LastNameOffset = (pResp->EndOfSearch)?(((USHORT)((char*)d -
  522. (char*)msg->out.smb)) -
  523. trans2->out.pResp->DataOffset):0;
  524. pResp->EaErrorOffset = 0;
  525. if (pResp->EndOfSearch) {
  526. dm_free(dm);
  527. }
  528. return TRUE;
  529. }
  530. BOOL
  531. Trans2QueryPathInfo(
  532. Packet_t * msg,
  533. Trans2_t * trans2
  534. )
  535. {
  536. PVOID fshdl;
  537. USHORT tid;
  538. USHORT uid;
  539. PVOID fsctx;
  540. FsDispatchTable* pDisp;
  541. PREQ_QUERY_PATH_INFORMATION pReq;
  542. PCHAR file_name;
  543. LPWSTR name;
  544. int name_len;
  545. DWORD error;
  546. fattr_t attribs;
  547. if (msg == NULL)
  548. return FALSE;
  549. tid = msg->in.smb->Tid;
  550. uid = msg->in.smb->Uid;
  551. fsctx = SRV_GET_FS_HANDLE(msg);
  552. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  553. SET_REQ(pReq, PREQ_QUERY_PATH_INFORMATION, trans2);
  554. if (!pDisp) {
  555. SrvLogError(("Srv: no such uid\n"));
  556. SET_DOSERROR(msg, SERVER, BAD_UID);
  557. return FALSE;
  558. }
  559. file_name = (PCHAR)pReq->Buffer;
  560. // convert to unicode
  561. SRV_ASCII_TO_WCHAR(name, name_len, file_name, lstrlen(file_name));
  562. if (name != NULL)
  563. error = pDisp->FsLookup(fshdl, name, (USHORT) name_len, &attribs);
  564. else
  565. error = ERROR_NOT_ENOUGH_MEMORY;
  566. SRV_ASCII_FREE(name);
  567. if (error) {
  568. SrvLogError(("Srv: lookup error 0x%08X\n", error));
  569. SET_WIN32ERROR(msg, error);
  570. ADD_RESP_DATA(msg, trans2, NULL, 0);
  571. return FALSE;
  572. }
  573. switch(pReq->InformationLevel) {
  574. case SMB_INFO_STANDARD: {
  575. USHORT len = sizeof(SMB_FIND_BUFFER) - sizeof(UCHAR) - sizeof(CHAR);
  576. PSMB_FIND_BUFFER pResp = (PSMB_FIND_BUFFER) xmalloc(len);
  577. if (pResp == NULL) {
  578. SET_WIN32ERROR(msg, ERROR_NOT_ENOUGH_MEMORY);
  579. ADD_RESP_DATA(msg, trans2, NULL, 0);
  580. return FALSE;
  581. }
  582. time64_to_smb_datetime(&attribs.create_time,
  583. &pResp->CreationDate.Ushort,
  584. &pResp->CreationTime.Ushort);
  585. time64_to_smb_datetime(&attribs.access_time,
  586. &pResp->LastAccessDate.Ushort,
  587. &pResp->LastAccessTime.Ushort);
  588. time64_to_smb_datetime(&attribs.mod_time,
  589. &pResp->LastWriteDate.Ushort,
  590. &pResp->LastWriteTime.Ushort);
  591. pResp->DataSize = (ULONG)attribs.file_size;
  592. pResp->AllocationSize = (ULONG)attribs.alloc_size;
  593. pResp->Attributes = attribs_to_smb_attribs(attribs.attributes);
  594. ADD_RESP_DATA(msg, trans2, pResp, len);
  595. xfree(pResp);
  596. return TRUE;
  597. }
  598. case SMB_INFO_QUERY_EA_SIZE: {
  599. USHORT len = sizeof(SMB_FIND_BUFFER2) - sizeof(UCHAR) - sizeof(CHAR);
  600. PSMB_FIND_BUFFER2 pResp = (PSMB_FIND_BUFFER2) xmalloc(len);
  601. if (pResp == NULL) {
  602. SET_WIN32ERROR(msg, ERROR_NOT_ENOUGH_MEMORY);
  603. ADD_RESP_DATA(msg, trans2, NULL, 0);
  604. return FALSE;
  605. }
  606. time64_to_smb_datetime(&attribs.create_time,
  607. &pResp->CreationDate.Ushort,
  608. &pResp->CreationTime.Ushort);
  609. time64_to_smb_datetime(&attribs.access_time,
  610. &pResp->LastAccessDate.Ushort,
  611. &pResp->LastAccessTime.Ushort);
  612. time64_to_smb_datetime(&attribs.mod_time,
  613. &pResp->LastWriteDate.Ushort,
  614. &pResp->LastWriteTime.Ushort);
  615. pResp->DataSize = (ULONG)attribs.file_size;
  616. pResp->AllocationSize = (ULONG)attribs.alloc_size;
  617. pResp->Attributes = attribs_to_smb_attribs(attribs.attributes);
  618. pResp->EaSize = 0;
  619. ADD_RESP_DATA(msg, trans2, pResp, len);
  620. xfree(pResp);
  621. return TRUE;
  622. }
  623. case SMB_INFO_QUERY_EAS_FROM_LIST:
  624. case SMB_FIND_FILE_DIRECTORY_INFO:
  625. case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
  626. case SMB_FIND_FILE_NAMES_INFO:
  627. case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
  628. default: {
  629. SrvLogError(("Srv: unsupported info level %d>\n"
  630. ,pReq->InformationLevel));
  631. SET_DOSERROR(msg, SERVER, NO_SUPPORT);
  632. return FALSE;
  633. }
  634. }
  635. }
  636. BOOL
  637. Trans2SetPathInfo(
  638. Packet_t * msg,
  639. Trans2_t * trans2
  640. )
  641. {
  642. return Trans2Unknown(msg, trans2);
  643. }
  644. BOOL
  645. Trans2QueryFileInfo(
  646. Packet_t * msg,
  647. Trans2_t * trans2
  648. )
  649. {
  650. return Trans2Unknown(msg, trans2);
  651. }
  652. BOOL
  653. Trans2SetFileInfo(
  654. Packet_t * msg,
  655. Trans2_t * trans2
  656. )
  657. {
  658. return Trans2Unknown(msg, trans2);
  659. }
  660. BOOL
  661. Trans2GetDfsReferral(
  662. Packet_t * msg,
  663. Trans2_t * trans2
  664. )
  665. {
  666. return Trans2Unknown(msg, trans2);
  667. }