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.

2243 lines
54 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. srvcom.c
  5. Abstract:
  6. Implements com smb packets
  7. Author:
  8. Ahmed Mohamed (ahmedm) 1-Feb-2000
  9. Revision History:
  10. --*/
  11. #include "srv.h"
  12. #define UPDATE_OUT_LEN(msg, resp_type, resp) \
  13. (msg->out.valid += SIZEOF_SMB_PARAMS(resp_type, resp->ByteCount))
  14. #define UPDATE_FOR_NEXT_ANDX(msg, req_type, req, resp_type, resp) { \
  15. resp->AndXCommand = req->AndXCommand; \
  16. resp->AndXReserved = 0; \
  17. resp->AndXOffset = UPDATE_OUT_LEN(msg, resp_type, resp); \
  18. msg->in.command = req->AndXCommand; \
  19. msg->in.offset += SIZEOF_SMB_PARAMS(req_type, req->ByteCount); \
  20. }
  21. #define SET_REQ(type, name, msg) \
  22. name = ((type)(((PUCHAR) msg->in.smb)+msg->in.offset))
  23. #define SET_RESP(type, name, msg) \
  24. name = ((type)(((PUCHAR) msg->out.smb)+msg->out.valid))
  25. #define SET_TYPE(type, name) \
  26. type name
  27. extern DWORD dm_close(USHORT);
  28. BOOL
  29. SrvComUnknown(
  30. Packet_t * msg
  31. )
  32. {
  33. if (msg == NULL)
  34. return FALSE;
  35. SrvLog(("(------ CANNOT HANDLE THIS COMMAND %x ------)\n",
  36. msg->in.command));
  37. SET_DOSERROR(msg, SERVER, NO_SUPPORT);
  38. return TRUE;
  39. }
  40. #define SRV_DIALECT_STRING "LM1.2X002"
  41. BOOL
  42. SrvComNegotiate(
  43. Packet_t * msg
  44. )
  45. {
  46. LPCSTR szDialect = NULL;
  47. int offset;
  48. USHORT dialect;
  49. BOOL found;
  50. EndPoint_t *ep;
  51. SET_TYPE(PREQ_NEGOTIATE, pReq);
  52. if (msg == NULL)
  53. return FALSE;
  54. ep = msg->endpoint;
  55. SET_REQ(PREQ_NEGOTIATE, pReq, msg);
  56. offset = sizeof(UCHAR);
  57. dialect = 0;
  58. found = FALSE;
  59. while (offset < pReq->ByteCount) {
  60. szDialect = (LPCSTR)NEXT_LOCATION(pReq, REQ_NEGOTIATE, offset);
  61. if (!lstrcmp(szDialect, SRV_DIALECT_STRING)) {
  62. SrvLog(("Using dialect %s\n", szDialect));
  63. found = TRUE;
  64. break;
  65. }
  66. dialect++;
  67. offset += lstrlen(szDialect) + 1 + sizeof(UCHAR);
  68. }
  69. if (found) {
  70. SET_TYPE(PRESP_NEGOTIATE, pResp);
  71. SET_RESP(PRESP_NEGOTIATE, pResp, msg);
  72. // LM1.2X002
  73. msg->out.smb->Flags |= SMB_FLAGS_LOCK_AND_READ_OK;
  74. // spew back the dialect we want...
  75. pResp->WordCount = 13;
  76. pResp->DialectIndex = dialect;
  77. pResp->SecurityMode = NEGOTIATE_ENCRYPT_PASSWORDS|NEGOTIATE_USER_SECURITY;
  78. pResp->MaxBufferSize = (USHORT)msg->out.size;
  79. pResp->MaxMpxCount = (USHORT)SRV_NUM_WORKERS;
  80. pResp->MaxNumberVcs = 1;
  81. pResp->RawMode = 0;
  82. pResp->SessionKey = 1;
  83. pResp->ServerTime.Ushort = 0;
  84. pResp->ServerDate.Ushort = 0;
  85. pResp->ServerTimeZone = 0;
  86. pResp->EncryptionKeyLength = 0;
  87. pResp->Reserved = 0;
  88. pResp->ByteCount = 0;
  89. {
  90. UINT sz;
  91. found = LsaGetChallenge(ep->SrvCtx->LsaHandle,
  92. ep->SrvCtx->LsaPack,
  93. ep->ChallengeBuffer,
  94. sizeof(ep->ChallengeBuffer),
  95. &sz);
  96. if (found == TRUE) {
  97. pResp->ByteCount = (SHORT) sz;
  98. pResp->EncryptionKeyLength = (SHORT) sz;
  99. ep->ChallengeBufferSz = sz;
  100. memcpy(pResp->Buffer, ep->ChallengeBuffer, sz);
  101. UPDATE_OUT_LEN(msg, RESP_NEGOTIATE, pResp);
  102. }
  103. }
  104. }
  105. if (!found) {
  106. // spew back an error to the client...
  107. SET_TYPE(PRESP_OLD_NEGOTIATE, pOldResp);
  108. SET_RESP(PRESP_OLD_NEGOTIATE, pOldResp, msg);
  109. pOldResp->WordCount = 1;
  110. pOldResp->DialectIndex = 0xFFFF;
  111. pOldResp->ByteCount = 0;
  112. msg->out.valid += sizeof(PRESP_OLD_NEGOTIATE);
  113. UPDATE_OUT_LEN(msg, RESP_OLD_NEGOTIATE, pOldResp);
  114. }
  115. return TRUE;
  116. }
  117. BOOL
  118. SrvComSessionSetupAndx(
  119. Packet_t * msg
  120. )
  121. {
  122. PCHAR szAccountName = NULL;
  123. PCHAR szDomainName = NULL;
  124. PCHAR pAccountPassword = NULL;
  125. int offset = 0;
  126. int pwdlen;
  127. BOOL found;
  128. DWORD error;
  129. HANDLE token;
  130. LUID logonid;
  131. EndPoint_t *ep;
  132. SET_TYPE(PRESP_SESSION_SETUP_ANDX, pResp);
  133. SET_TYPE(PREQ_SESSION_SETUP_ANDX, pReq);
  134. if (msg == NULL)
  135. return FALSE;
  136. ep = msg->endpoint;
  137. SET_RESP(PRESP_SESSION_SETUP_ANDX, pResp, msg);
  138. SET_REQ(PREQ_SESSION_SETUP_ANDX, pReq, msg);
  139. pResp->WordCount = 3;
  140. pResp->Action = 0;
  141. pResp->ByteCount = 0;
  142. if (pReq->WordCount == 12)
  143. return FALSE;
  144. SrvLog(("MxBuf: %x MxMpx: %d Key: %x Count: %d\n", pReq->MaxBufferSize,
  145. pReq->MaxMpxCount, pReq->SessionKey, pReq->ByteCount));
  146. SrvLog(("Count: %d Pwd %d\n", pReq->ByteCount, pReq->PasswordLength));
  147. if (pReq->WordCount == 13) {
  148. PREQ_NT_SESSION_SETUP_ANDX pNtReq = (PREQ_NT_SESSION_SETUP_ANDX) pReq;
  149. if (pNtReq->ByteCount > offset) {
  150. pAccountPassword = (PCHAR)
  151. NEXT_LOCATION(pNtReq, REQ_NT_SESSION_SETUP_ANDX, offset);
  152. offset += pNtReq->CaseInsensitivePasswordLength;
  153. offset += pNtReq->CaseSensitivePasswordLength;
  154. }
  155. if (pNtReq->ByteCount > offset) {
  156. szAccountName = (PCHAR)
  157. NEXT_LOCATION(pNtReq, REQ_NT_SESSION_SETUP_ANDX, offset);
  158. offset += lstrlen(szAccountName) + 1;
  159. }
  160. pwdlen = pNtReq->CaseInsensitivePasswordLength;
  161. }
  162. else if (pReq->WordCount == 10) {
  163. if (pReq->ByteCount > offset) {
  164. pAccountPassword = (PCHAR)
  165. NEXT_LOCATION(pReq, REQ_SESSION_SETUP_ANDX, offset);
  166. offset += pReq->PasswordLength;
  167. }
  168. if (pReq->ByteCount > offset) {
  169. szAccountName = (PCHAR)
  170. NEXT_LOCATION(pReq, REQ_SESSION_SETUP_ANDX, offset);
  171. offset += lstrlen(szAccountName) + 1;
  172. }
  173. if (pReq->ByteCount > offset) {
  174. szDomainName = (PCHAR)
  175. NEXT_LOCATION(pReq, REQ_SESSION_SETUP_ANDX, offset);
  176. offset += lstrlen(szDomainName) + 1;
  177. }
  178. pwdlen = pReq->PasswordLength;
  179. }
  180. SrvLog(("setup username: %s\n", szAccountName));
  181. SrvLog(("setup domainname: %s\n", szDomainName));
  182. found = LsaValidateLogon(ep->SrvCtx->LsaHandle,
  183. ep->SrvCtx->LsaPack,
  184. ep->ChallengeBuffer, ep->ChallengeBufferSz,
  185. pAccountPassword, pwdlen,
  186. szAccountName, szDomainName,
  187. &logonid, &token);
  188. if (found == TRUE) {
  189. // we need to remember the token and use it for all io operations
  190. error = FsLogonUser(ep->SrvCtx->FsCtx, token, logonid,
  191. &msg->out.smb->Uid);
  192. if (error != ERROR_SUCCESS) {
  193. SrvLog(("DOSERROR: user logon failed %d\n", error));
  194. SET_DOSERROR(msg, SERVER, TOO_MANY_UIDS);
  195. } else {
  196. // remember logon for this endpoint
  197. ep->LogonId = logonid;
  198. msg->in.smb->Uid = msg->out.smb->Uid;
  199. SrvLog(("Setting up uid %d\n", msg->out.smb->Uid));
  200. }
  201. } else {
  202. SrvLogError(("DOSERROR: could not authenticate user\n"));
  203. SET_DOSERROR(msg, SERVER, BAD_PASSWORD);
  204. }
  205. if (pReq->WordCount == 10) {
  206. UPDATE_FOR_NEXT_ANDX(msg,
  207. REQ_SESSION_SETUP_ANDX, pReq,
  208. RESP_SESSION_SETUP_ANDX, pResp);
  209. } else {
  210. UPDATE_FOR_NEXT_ANDX(msg,
  211. REQ_NT_SESSION_SETUP_ANDX, pReq,
  212. RESP_SESSION_SETUP_ANDX, pResp);
  213. }
  214. return SrvDispatch(msg);
  215. }
  216. BOOL
  217. SrvComTreeConnectAndx(
  218. Packet_t * msg
  219. )
  220. {
  221. PUCHAR pPassword = NULL;
  222. PCHAR szPath = NULL;
  223. PCHAR szService = NULL;
  224. int offset = 0;
  225. DWORD error;
  226. SET_TYPE(PREQ_TREE_CONNECT_ANDX, pReq);
  227. SET_TYPE(PRESP_TREE_CONNECT_ANDX, pResp);
  228. if (msg == NULL)
  229. return FALSE;
  230. SET_REQ(PREQ_TREE_CONNECT_ANDX, pReq, msg);
  231. SET_RESP(PRESP_TREE_CONNECT_ANDX, pResp, msg);
  232. SrvLog(("TreeConnect pwdlen %d cnt %d\n", pReq->PasswordLength, pReq->ByteCount));
  233. if (pReq->ByteCount > offset) {
  234. pPassword = (PUCHAR)
  235. NEXT_LOCATION(pReq, REQ_TREE_CONNECT_ANDX, offset);
  236. offset += pReq->PasswordLength;
  237. }
  238. if (pReq->ByteCount > offset) {
  239. szPath = (PCHAR)
  240. NEXT_LOCATION(pReq, REQ_TREE_CONNECT_ANDX, offset);
  241. offset += lstrlen(szPath) + 1;
  242. }
  243. if (pReq->ByteCount > offset) {
  244. szService = (PCHAR)
  245. NEXT_LOCATION(pReq, REQ_TREE_CONNECT_ANDX, offset);
  246. }
  247. if (szPath != NULL) {
  248. PCHAR s = strrchr(szPath, '\\');
  249. if (s != NULL) {
  250. szPath = s + 1;
  251. }
  252. SrvLog(("Path %s\n", szPath));
  253. }
  254. if (szService != NULL) {
  255. szService[4] = '\0';
  256. SrvLog(("Service %s\n", szService));
  257. }
  258. if (szPath != NULL) {
  259. // convert name to unicode
  260. int wsz;
  261. LPWSTR wpath;
  262. SRV_ASCII_TO_WCHAR(wpath, wsz, szPath, strlen(szPath));
  263. if (wpath)
  264. // Get tree id
  265. error = FsMount(msg->endpoint->SrvCtx->FsCtx,
  266. wpath, msg->in.smb->Uid, &msg->out.smb->Tid);
  267. else
  268. error = ERROR_NOT_ENOUGH_MEMORY;
  269. SRV_ASCII_FREE(wpath);
  270. } else {
  271. error = ERROR_PATH_NOT_FOUND;
  272. }
  273. // it turns out that we can get away with an older-style reply...hehe
  274. pResp->AndXCommand = 0xff;
  275. pResp->AndXReserved = 0;
  276. pResp->WordCount = 2;
  277. if (error == ERROR_SUCCESS) {
  278. pResp->ByteCount = 3;
  279. strcpy((char*)pResp->Buffer, "A:");
  280. SrvLog(("FsMount tid %d\n", msg->out.smb->Tid));
  281. } else {
  282. pResp->ByteCount = 0;
  283. SrvLogError(("WIN32ERROR: FsMount error 0x%08X\n", error));
  284. SET_WIN32ERROR(msg, error);
  285. }
  286. UPDATE_FOR_NEXT_ANDX(msg,
  287. REQ_TREE_CONNECT_ANDX, pReq,
  288. RESP_TREE_CONNECT_ANDX, pResp);
  289. return SrvDispatch(msg);
  290. }
  291. BOOL
  292. SrvComNoAndx(
  293. Packet_t * msg
  294. )
  295. {
  296. return TRUE;
  297. }
  298. BOOL
  299. SrvComTrans(
  300. Packet_t * msg
  301. )
  302. {
  303. return SrvComUnknown(msg);
  304. }
  305. BOOL
  306. SrvComTrans2(
  307. Packet_t * msg
  308. )
  309. {
  310. PUSHORT pSetup;
  311. int iSetup;
  312. Trans2_t t2b;
  313. SET_TYPE(PREQ_TRANSACTION, pReq);
  314. SET_TYPE(PRESP_TRANSACTION, pResp);
  315. if (msg == NULL)
  316. return FALSE;
  317. SET_REQ(PREQ_TRANSACTION, pReq, msg);
  318. SET_RESP(PRESP_TRANSACTION, pResp, msg);
  319. pSetup = (PUSHORT) NEXT_LOCATION(pReq, REQ_TRANSACTION, 0);
  320. for (iSetup = 0; iSetup < pReq->SetupCount; iSetup++)
  321. SrvLog(("Setup[0x%02x] : 0x%04x (%s)\n",
  322. iSetup, pSetup[iSetup],
  323. SrvUnparseTrans2(pSetup[iSetup])));
  324. if (pReq->SetupCount > 1) {
  325. SrvLog(("SetupCount > 1!!!\n"));
  326. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  327. return TRUE;
  328. }
  329. RtlZeroMemory(pResp, sizeof(RESP_TRANSACTION));
  330. pResp->WordCount = 10 + pReq->SetupCount;
  331. pResp->SetupCount = pReq->SetupCount;
  332. RtlCopyMemory((PUSHORT) NEXT_LOCATION(pResp, RESP_TRANSACTION, 0),
  333. pSetup, pResp->SetupCount*sizeof(USHORT));
  334. t2b.in.pReq = pReq;
  335. t2b.in.pParameters = ((PUCHAR)msg->in.smb) + pReq->ParameterOffset;
  336. t2b.in.pData = ((PUCHAR)msg->in.smb) + pReq->DataOffset;
  337. t2b.out.pResp = pResp;
  338. t2b.out.ParameterBytesLeft = pReq->MaxParameterCount;
  339. t2b.out.DataBytesLeft = pReq->MaxDataCount;
  340. t2b.out.pByteCount =
  341. (PUSHORT)NEXT_LOCATION(pResp, RESP_TRANSACTION,
  342. pResp->SetupCount*sizeof(USHORT));
  343. *(t2b.out.pByteCount) = 0;
  344. // initialize parameter and data offset. xxx: todo: need pad
  345. pResp->ParameterOffset = (USHORT) (((PUCHAR)pResp) - (PUCHAR)(msg->out.smb));
  346. pResp->ParameterOffset += sizeof(*pResp);
  347. pResp->ParameterOffset += SIZEOF_TRANS2_RESP_HEADER(pResp);
  348. pResp->DataOffset = pResp->ParameterOffset;
  349. // we increment:
  350. // pResp->WordCount
  351. // pResp->TotalParameterCount
  352. // pResp->TotalDataCount
  353. // pResp->ParameterCount
  354. // pResp->ParameterOffset
  355. // pResp->ParameterDisplacement -- not really, since we do not honor max
  356. // pResp->DataCount
  357. // pResp->DataOffset
  358. // pResp->DataDisplacement -- not really, since we do not honor max
  359. // *(t2b.out.pByteCount)
  360. msg->out.valid += sizeof(RESP_TRANSACTION) + sizeof(USHORT);
  361. // dispatch each transaction...
  362. for (iSetup = 0; iSetup < pReq->SetupCount; iSetup++) {
  363. msg->out.valid += sizeof(USHORT);
  364. msg->in.command = pSetup[iSetup];
  365. if (!Trans2Dispatch(msg, &t2b)) {
  366. // someone bellow us set an error, so we need to stop the loop
  367. // and return TRUE so the packet gets sent.
  368. break;
  369. }
  370. }
  371. SrvLog(("Trans2 %d %d %d %d %d %d %d %d %d %d\n",
  372. pResp->WordCount, pResp->SetupCount,
  373. pResp->TotalParameterCount,
  374. pResp->TotalDataCount,
  375. pResp->ParameterCount,
  376. pResp->ParameterOffset,
  377. pResp->DataCount,
  378. pResp->DataOffset,
  379. *((PUSHORT) pResp->Buffer),
  380. 1[((PUSHORT) pResp->Buffer)]));
  381. // need to set length stuff
  382. return TRUE;
  383. }
  384. BOOL
  385. SrvComQueryInformation(
  386. Packet_t * msg
  387. )
  388. {
  389. PVOID fshdl;
  390. USHORT tid;
  391. USHORT uid;
  392. PVOID fsctx;
  393. FsDispatchTable* pDisp;
  394. DWORD error;
  395. PCHAR file_name;
  396. fattr_t attribs;
  397. USHORT sz;
  398. SET_TYPE(PREQ_QUERY_INFORMATION, pReq);
  399. SET_TYPE(PRESP_QUERY_INFORMATION, pResp);
  400. if (msg == NULL)
  401. return FALSE;
  402. tid = msg->in.smb->Tid;
  403. uid = msg->in.smb->Uid;
  404. fsctx = SRV_GET_FS_HANDLE(msg);
  405. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  406. SET_REQ(PREQ_QUERY_INFORMATION, pReq, msg);
  407. SET_RESP(PRESP_QUERY_INFORMATION, pResp, msg);
  408. pResp->WordCount = 10;
  409. pResp->ByteCount = 0;
  410. if (!pDisp) {
  411. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  412. SET_DOSERROR(msg, SERVER, BAD_UID);
  413. return TRUE;
  414. }
  415. if (pReq->ByteCount < 2) {
  416. SrvLogError(("DOSERROR: ByteCount < 2\n"));
  417. SET_DOSERROR(msg, SERVER, ERROR); // OK?
  418. return TRUE;
  419. }
  420. file_name = (PCHAR)NEXT_LOCATION(pReq,
  421. REQ_QUERY_INFORMATION,
  422. sizeof(UCHAR));
  423. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  424. if (pReq->ByteCount > sz)
  425. sz = pReq->ByteCount - sz;
  426. else
  427. sz = 1;
  428. if (sz == 0)
  429. file_name = "";
  430. {
  431. // convert name to unicode
  432. int wsz;
  433. LPWSTR wfile_name;
  434. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  435. if (wfile_name)
  436. error = pDisp->FsLookup(fshdl, wfile_name, (USHORT)wsz, &attribs);
  437. else
  438. error = ERROR_NOT_ENOUGH_MEMORY;
  439. SRV_ASCII_FREE(wfile_name);
  440. }
  441. if (error) {
  442. SrvLog(("WIN32ERROR: lookup error 0x%08X\n", error));
  443. SET_WIN32ERROR(msg, error);
  444. UPDATE_OUT_LEN(msg, RESP_QUERY_INFORMATION, pResp);
  445. return TRUE;
  446. }
  447. pResp->FileAttributes = attribs_to_smb_attribs(attribs.attributes);
  448. pResp->LastWriteTimeInSeconds = time64_to_smb_timedate(&attribs.mod_time);
  449. RtlZeroMemory(pResp->Reserved, sizeof(pResp->Reserved));
  450. pResp->FileSize = (ULONG) attribs.file_size;
  451. UPDATE_OUT_LEN(msg, RESP_QUERY_INFORMATION, pResp);
  452. return TRUE;
  453. }
  454. BOOL
  455. SrvComSetInformation(
  456. Packet_t * msg
  457. )
  458. {
  459. PVOID fshdl;
  460. USHORT tid;
  461. USHORT uid;
  462. PVOID fsctx;
  463. FsDispatchTable* pDisp;
  464. fattr_t attribs;
  465. DWORD error;
  466. PCHAR file_name;
  467. USHORT sz;
  468. SET_TYPE(PREQ_SET_INFORMATION, pReq);
  469. SET_TYPE(PRESP_SET_INFORMATION, pResp);
  470. if (msg == NULL)
  471. return FALSE;
  472. tid = msg->in.smb->Tid;
  473. uid = msg->in.smb->Uid;
  474. fsctx = SRV_GET_FS_HANDLE(msg);
  475. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  476. SET_REQ(PREQ_SET_INFORMATION, pReq, msg);
  477. SET_RESP(PRESP_SET_INFORMATION, pResp, msg);
  478. pResp->WordCount = 0;
  479. pResp->ByteCount = 0;
  480. if (!pDisp) {
  481. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  482. SET_DOSERROR(msg, SERVER, BAD_UID);
  483. return TRUE;
  484. }
  485. if (pReq->ByteCount < 2) {
  486. SrvLogError(("DOSERROR: ByteCount < 2\n"));
  487. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  488. return TRUE;
  489. }
  490. file_name = (PCHAR)NEXT_LOCATION(pReq,
  491. REQ_SET_INFORMATION,
  492. sizeof(UCHAR));
  493. attribs.file_size = INVALID_UINT64;
  494. attribs.alloc_size = INVALID_UINT64;
  495. attribs.access_time = INVALID_TIME64;
  496. attribs.create_time = INVALID_TIME64;
  497. attribs.mod_time = INVALID_TIME64;
  498. if (pReq->LastWriteTimeInSeconds)
  499. attribs.mod_time = smb_timedate_to_time64(pReq->LastWriteTimeInSeconds);
  500. attribs.attributes = smb_attribs_to_attribs(pReq->FileAttributes);
  501. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  502. if (pReq->ByteCount > sz)
  503. sz = pReq->ByteCount - sz;
  504. else
  505. sz = 1;
  506. if (sz == 0)
  507. file_name = "";
  508. {
  509. // convert name to unicode
  510. int wsz;
  511. LPWSTR wfile_name;
  512. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  513. if (wfile_name)
  514. error = pDisp->FsSetAttr2(fshdl, wfile_name, (USHORT)wsz, &attribs);
  515. else
  516. error = ERROR_NOT_ENOUGH_MEMORY;
  517. SRV_ASCII_FREE(wfile_name);
  518. }
  519. if (error) {
  520. SrvLog(("WIN32ERROR: set_attr error 0x%08X\n", error));
  521. SET_WIN32ERROR(msg, error);
  522. }
  523. UPDATE_OUT_LEN(msg, RESP_SET_INFORMATION, pResp);
  524. return TRUE;
  525. }
  526. BOOL
  527. SrvComCheckDirectory(
  528. Packet_t * msg
  529. )
  530. {
  531. PVOID fshdl;
  532. USHORT tid;
  533. USHORT uid;
  534. PVOID fsctx;
  535. FsDispatchTable* pDisp;
  536. fattr_t attribs;
  537. DWORD error;
  538. PCHAR file_name;
  539. USHORT sz;
  540. SET_TYPE(PREQ_CHECK_DIRECTORY, pReq);
  541. SET_TYPE(PRESP_CHECK_DIRECTORY, pResp);
  542. if (msg == NULL)
  543. return FALSE;
  544. tid = msg->in.smb->Tid;
  545. uid = msg->in.smb->Uid;
  546. fsctx = SRV_GET_FS_HANDLE(msg);
  547. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  548. SET_REQ(PREQ_CHECK_DIRECTORY, pReq, msg);
  549. SET_RESP(PRESP_CHECK_DIRECTORY, pResp, msg);
  550. pResp->WordCount = 0;
  551. pResp->ByteCount = 0;
  552. if (!pDisp) {
  553. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  554. SET_DOSERROR(msg, SERVER, BAD_UID);
  555. return TRUE;
  556. }
  557. if (pReq->ByteCount < 2) {
  558. SrvLogError(("DOSERROR: ByteCount < 2\n"));
  559. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  560. return TRUE;
  561. }
  562. file_name = (PCHAR)NEXT_LOCATION(pReq,
  563. REQ_QUERY_INFORMATION,
  564. sizeof(UCHAR));
  565. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  566. if (pReq->ByteCount > sz)
  567. sz = pReq->ByteCount - sz;
  568. else
  569. sz = 1;
  570. if (sz == 0)
  571. file_name = "";
  572. {
  573. // convert name to unicode
  574. int wsz;
  575. LPWSTR wfile_name;
  576. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  577. if (wfile_name)
  578. error = pDisp->FsLookup(fshdl, wfile_name, (USHORT)wsz, &attribs);
  579. else
  580. error = ERROR_NOT_ENOUGH_MEMORY;
  581. SRV_ASCII_FREE(wfile_name);
  582. }
  583. if (error) {
  584. SrvLog(("ERROR: lookup error 0x%08X\n", error));
  585. SET_WIN32ERROR(msg, error);
  586. } else if (!(attribs.attributes & ATTR_DIRECTORY)) {
  587. SrvLog(("ERROR: lookup error 0x%08X\n", error));
  588. SET_DOSERROR(msg, DOS, BAD_PATH);
  589. }
  590. UPDATE_OUT_LEN(msg, RESP_CHECK_DIRECTORY, pResp);
  591. return TRUE;
  592. }
  593. BOOL
  594. SrvComFindClose2(
  595. Packet_t * msg
  596. )
  597. {
  598. PVOID fshdl;
  599. USHORT tid;
  600. USHORT uid;
  601. PVOID fsctx;
  602. FsDispatchTable* pDisp;
  603. DWORD error;
  604. SET_TYPE(PREQ_FIND_CLOSE2, pReq);
  605. SET_TYPE(PRESP_FIND_CLOSE2, pResp);
  606. if (msg == NULL)
  607. return FALSE;
  608. tid = msg->in.smb->Tid;
  609. uid = msg->in.smb->Uid;
  610. fsctx = SRV_GET_FS_HANDLE(msg);
  611. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  612. SET_REQ(PREQ_FIND_CLOSE2, pReq, msg);
  613. SET_RESP(PRESP_FIND_CLOSE2, pResp, msg);
  614. pResp->WordCount = 0;
  615. pResp->ByteCount = 0;
  616. if (!pDisp) {
  617. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  618. SET_DOSERROR(msg, SERVER, BAD_UID);
  619. return TRUE;
  620. }
  621. if (pReq->WordCount != 1) {
  622. SrvLogError(("DOSERROR: WordCount != 1\n"));
  623. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  624. return TRUE;
  625. }
  626. error = dm_close(pReq->Sid);
  627. if (error) {
  628. SrvLog(("WIN32ERROR: findclose2 error 0x%08X\n", error));
  629. SET_WIN32ERROR(msg, error);
  630. return TRUE;
  631. }
  632. UPDATE_OUT_LEN(msg, RESP_FIND_CLOSE2, pResp);
  633. return TRUE;
  634. }
  635. BOOL
  636. SrvComFindNotifyClose(
  637. Packet_t * msg
  638. )
  639. {
  640. PVOID fshdl;
  641. USHORT tid;
  642. USHORT uid;
  643. PVOID fsctx;
  644. FsDispatchTable* pDisp;
  645. DWORD error;
  646. SET_TYPE(PREQ_FIND_NOTIFY_CLOSE, pReq);
  647. SET_TYPE(PRESP_FIND_NOTIFY_CLOSE, pResp);
  648. if (msg == NULL)
  649. return FALSE;
  650. tid = msg->in.smb->Tid;
  651. uid = msg->in.smb->Uid;
  652. fsctx = SRV_GET_FS_HANDLE(msg);
  653. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  654. SET_REQ(PREQ_FIND_NOTIFY_CLOSE, pReq, msg);
  655. SET_RESP(PRESP_FIND_NOTIFY_CLOSE, pResp, msg);
  656. pResp->WordCount = 0;
  657. pResp->ByteCount = 0;
  658. if (!pDisp) {
  659. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  660. SET_DOSERROR(msg, SERVER, BAD_UID);
  661. return TRUE;
  662. }
  663. if (pReq->WordCount != 1) {
  664. SrvLogError(("DOSERROR: WordCount != 1 got %d handle %x\n", pReq->WordCount, pReq->Handle));
  665. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  666. return TRUE;
  667. }
  668. error = dm_close(pReq->Handle);
  669. if (error) {
  670. SrvLog(("WIN32ERROR: notifyclose error 0x%08X\n", error));
  671. SET_WIN32ERROR(msg, error);
  672. return TRUE;
  673. }
  674. UPDATE_OUT_LEN(msg, RESP_FIND_NOTIFY_CLOSE, pResp);
  675. return TRUE;
  676. }
  677. BOOL
  678. SrvComDelete(
  679. Packet_t * msg
  680. )
  681. {
  682. PVOID fshdl;
  683. USHORT tid;
  684. USHORT uid;
  685. PVOID fsctx;
  686. FsDispatchTable* pDisp;
  687. PCHAR file_name;
  688. DWORD error;
  689. USHORT sz;
  690. SET_TYPE(PREQ_DELETE, pReq);
  691. SET_TYPE(PRESP_DELETE, pResp);
  692. if (msg == NULL)
  693. return FALSE;
  694. tid = msg->in.smb->Tid;
  695. uid = msg->in.smb->Uid;
  696. fsctx = SRV_GET_FS_HANDLE(msg);
  697. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  698. SET_REQ(PREQ_DELETE, pReq, msg);
  699. SET_RESP(PRESP_DELETE, pResp, msg);
  700. pResp->WordCount = 0;
  701. pResp->ByteCount = 0;
  702. if (!pDisp) {
  703. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  704. SET_DOSERROR(msg, SERVER, BAD_UID);
  705. return TRUE;
  706. }
  707. if (pReq->ByteCount < 2) {
  708. SrvLogError(("DOSERROR: ByteCount < 2\n"));
  709. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  710. return TRUE;
  711. }
  712. file_name = (PCHAR)NEXT_LOCATION(pReq,
  713. REQ_DELETE,
  714. sizeof(UCHAR));
  715. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  716. if (pReq->ByteCount > sz)
  717. sz = pReq->ByteCount - sz;
  718. else
  719. sz = 1;
  720. if (sz == 0)
  721. file_name = "";
  722. {
  723. // convert name to unicode
  724. int wsz;
  725. LPWSTR wfile_name;
  726. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  727. if (wfile_name)
  728. error = pDisp->FsRemove(fshdl, wfile_name, (USHORT)wsz);
  729. else
  730. error = ERROR_NOT_ENOUGH_MEMORY;
  731. SRV_ASCII_FREE(wfile_name);
  732. }
  733. if (error) {
  734. SrvLog(("WIN32EROR: remove error 0x%08X\n", error));
  735. SET_WIN32ERROR(msg, error);
  736. }
  737. UPDATE_OUT_LEN(msg, RESP_DELETE, pResp);
  738. return TRUE;
  739. }
  740. BOOL
  741. SrvComRename(
  742. Packet_t * msg
  743. )
  744. {
  745. PVOID fshdl;
  746. USHORT tid;
  747. USHORT uid;
  748. PVOID fsctx;
  749. FsDispatchTable* pDisp;
  750. DWORD error;
  751. PCHAR to_name, from_name;
  752. SET_TYPE(PREQ_RENAME, pReq);
  753. SET_TYPE(PRESP_RENAME, pResp);
  754. if (msg == NULL)
  755. return FALSE;
  756. tid = msg->in.smb->Tid;
  757. uid = msg->in.smb->Uid;
  758. fsctx = SRV_GET_FS_HANDLE(msg);
  759. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  760. SET_REQ(PREQ_RENAME, pReq, msg);
  761. SET_RESP(PRESP_RENAME, pResp, msg);
  762. pResp->WordCount = 0;
  763. pResp->ByteCount = 0;
  764. if (!pDisp) {
  765. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  766. SET_DOSERROR(msg, SERVER, BAD_UID);
  767. return TRUE;
  768. }
  769. if (pReq->ByteCount < 4) {
  770. SrvLogError(("DOSERROR: ByteCount < 4\n"));
  771. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  772. return TRUE;
  773. }
  774. from_name = (PCHAR)NEXT_LOCATION(pReq,
  775. REQ_RENAME,
  776. sizeof(UCHAR));
  777. to_name = (PCHAR)NEXT_LOCATION(pReq,
  778. REQ_RENAME,
  779. 2*sizeof(UCHAR)+
  780. lstrlen(from_name)+1);
  781. SrvLog(("Rename: attrib %x\n", pReq->SearchAttributes));
  782. {
  783. // convert name to unicode
  784. int wfsz, wtsz;
  785. LPWSTR wfrom_name, wto_name;
  786. SRV_ASCII_TO_WCHAR(wfrom_name, wfsz, from_name, lstrlen(from_name));
  787. SRV_ASCII_TO_WCHAR(wto_name, wtsz, to_name, lstrlen(to_name));
  788. if (wfrom_name && wto_name)
  789. error = pDisp->FsRename(fshdl, wfrom_name, (USHORT)wfsz,
  790. wto_name, (USHORT) wtsz);
  791. else
  792. error = ERROR_NOT_ENOUGH_MEMORY;
  793. SRV_ASCII_FREE(wfrom_name);
  794. SRV_ASCII_FREE(wto_name);
  795. }
  796. if (error) {
  797. SrvLog(("WIN32ERROR: rename error 0x%08X\n", error));
  798. SET_WIN32ERROR(msg, error);
  799. }
  800. UPDATE_OUT_LEN(msg, RESP_RENAME, pResp);
  801. return TRUE;
  802. }
  803. BOOL
  804. SrvComCreateDirectory(
  805. Packet_t * msg
  806. )
  807. {
  808. DWORD error;
  809. PVOID fshdl;
  810. USHORT tid;
  811. USHORT uid;
  812. PVOID fsctx;
  813. FsDispatchTable* pDisp;
  814. SET_TYPE(PREQ_CREATE_DIRECTORY, pReq);
  815. SET_TYPE(PRESP_CREATE_DIRECTORY, pResp);
  816. if (msg == NULL)
  817. return FALSE;
  818. tid = msg->in.smb->Tid;
  819. uid = msg->in.smb->Uid;
  820. fsctx = SRV_GET_FS_HANDLE(msg);
  821. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  822. SET_REQ(PREQ_CREATE_DIRECTORY, pReq, msg);
  823. SET_RESP(PRESP_CREATE_DIRECTORY, pResp, msg);
  824. pResp->WordCount = 0;
  825. pResp->ByteCount = 0;
  826. if (!pDisp) {
  827. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  828. SET_DOSERROR(msg, SERVER, BAD_UID);
  829. return TRUE;
  830. }
  831. if (pReq->ByteCount >= 2) {
  832. USHORT sz;
  833. PCHAR file_name = (PCHAR)NEXT_LOCATION(pReq,
  834. REQ_CREATE_DIRECTORY,
  835. sizeof(UCHAR));
  836. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  837. if (pReq->ByteCount > sz)
  838. sz = pReq->ByteCount - sz;
  839. else
  840. sz = 1;
  841. {
  842. // convert name to unicode
  843. int wsz;
  844. LPWSTR wfile_name;
  845. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  846. if (wfile_name)
  847. error = pDisp->FsMkdir(fshdl, wfile_name, (USHORT)wsz, 0);
  848. else
  849. error = ERROR_NOT_ENOUGH_MEMORY;
  850. SRV_ASCII_FREE(wfile_name);
  851. }
  852. } else {
  853. error = ERROR_BAD_NETPATH;
  854. }
  855. if (error) {
  856. SrvLog(("WIN32ERROR: mkdir error 0x%08X\n", error));
  857. SET_WIN32ERROR(msg, error);
  858. }
  859. UPDATE_OUT_LEN(msg, RESP_CREATE_DIRECTORY, pResp);
  860. return TRUE;
  861. }
  862. BOOL
  863. SrvComDeleteDirectory(
  864. Packet_t * msg
  865. )
  866. {
  867. PVOID fshdl;
  868. USHORT tid;
  869. USHORT uid;
  870. PVOID fsctx;
  871. FsDispatchTable* pDisp;
  872. DWORD error;
  873. PCHAR file_name;
  874. USHORT sz;
  875. SET_TYPE(PREQ_DELETE_DIRECTORY, pReq);
  876. SET_TYPE(PRESP_DELETE_DIRECTORY, pResp);
  877. if (msg == NULL)
  878. return FALSE;
  879. tid = msg->in.smb->Tid;
  880. uid = msg->in.smb->Uid;
  881. fsctx = SRV_GET_FS_HANDLE(msg);
  882. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  883. SET_REQ(PREQ_DELETE_DIRECTORY, pReq, msg);
  884. SET_RESP(PRESP_DELETE_DIRECTORY, pResp, msg);
  885. pResp->WordCount = 0;
  886. pResp->ByteCount = 0;
  887. if (!pDisp) {
  888. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  889. SET_DOSERROR(msg, SERVER, BAD_UID);
  890. return TRUE;
  891. }
  892. if (pReq->ByteCount < 2) {
  893. SrvLogError(("DOSERROR: ByteCount < 2\n"));
  894. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  895. return TRUE;
  896. }
  897. file_name = (PCHAR)NEXT_LOCATION(pReq,
  898. REQ_DELETE_DIRECTORY,
  899. sizeof(UCHAR));
  900. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  901. if (pReq->ByteCount > sz)
  902. sz = pReq->ByteCount - sz;
  903. else
  904. sz = 1;
  905. {
  906. // convert name to unicode
  907. int wsz;
  908. LPWSTR wfile_name;
  909. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  910. if (wfile_name)
  911. error = pDisp->FsRmdir(fshdl, wfile_name, (USHORT)wsz);
  912. else
  913. error = ERROR_NOT_ENOUGH_MEMORY;
  914. SRV_ASCII_FREE(wfile_name);
  915. }
  916. if (error) {
  917. SrvLog(("WIN32ERROR: rmdir error 0x%08X\n", error));
  918. SET_WIN32ERROR(msg, error);
  919. }
  920. UPDATE_OUT_LEN(msg, RESP_DELETE_DIRECTORY, pResp);
  921. return TRUE;
  922. }
  923. BOOL
  924. SrvComOpenAndx(
  925. Packet_t * msg
  926. )
  927. {
  928. PVOID fshdl;
  929. USHORT tid;
  930. USHORT uid;
  931. PVOID fsctx;
  932. FsDispatchTable* pDisp;
  933. PCHAR file_name;
  934. BOOL additional_info;
  935. UINT32 flags;
  936. fattr_t attr;
  937. DWORD error;
  938. USHORT sz;
  939. UINT32 action;
  940. SET_TYPE(PREQ_OPEN_ANDX, pReq);
  941. SET_TYPE(PRESP_OPEN_ANDX, pResp);
  942. if (msg == NULL)
  943. return FALSE;
  944. tid = msg->in.smb->Tid;
  945. uid = msg->in.smb->Uid;
  946. fsctx = SRV_GET_FS_HANDLE(msg);
  947. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  948. SET_REQ(PREQ_OPEN_ANDX, pReq, msg);
  949. SET_RESP(PRESP_OPEN_ANDX, pResp, msg);
  950. pResp->WordCount = 15;
  951. pResp->AndXCommand = 0xff;
  952. pResp->AndXReserved = 0;
  953. pResp->FileType = 0;
  954. pResp->DeviceState = 0;
  955. // XXX - for actual Action value, need to do a lookup beforehand...
  956. pResp->Action = 0;
  957. // XXX - is ServerFid = 0 really ok? It seems like it never gets used...
  958. pResp->ServerFid = 0;
  959. pResp->Reserved = 0;
  960. pResp->ByteCount = 0;
  961. if (!pDisp) {
  962. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  963. SET_DOSERROR(msg, SERVER, BAD_UID);
  964. return TRUE;
  965. }
  966. if (pReq->WordCount != 15) {
  967. SrvLogError(("DOSERROR: WordCount != 15\n"));
  968. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  969. return TRUE;
  970. }
  971. file_name = (PCHAR)NEXT_LOCATION(pReq,
  972. REQ_OPEN_ANDX,
  973. sizeof(UCHAR));
  974. SrvLog(("OpenX: Flags %x Access %x Srch %x Attr %x Open %x Size %x\n",
  975. pReq->Flags, pReq->DesiredAccess, pReq->SearchAttributes,
  976. pReq->FileAttributes, pReq->OpenFunction, pReq->AllocationSize));
  977. additional_info = (pReq->Flags & SMB_OPEN_QUERY_INFORMATION);
  978. flags = smb_access_to_flags(pReq->DesiredAccess) | smb_openfunc_to_flags(pReq->OpenFunction);
  979. if (!(flags & FS_DISP_MASK)) {
  980. // XXX --- error!!!
  981. SrvLog(("DOSERROR: nothing to do!!!!\n"));
  982. SET_DOSERROR(msg, SERVER, ERROR); // ok
  983. return TRUE;
  984. }
  985. attr.file_size = INVALID_UINT64;
  986. attr.alloc_size = INVALID_UINT64;
  987. attr.create_time = smb_timedate_to_time64(pReq->CreationTimeInSeconds);
  988. attr.access_time = INVALID_TIME64;
  989. attr.mod_time = INVALID_TIME64;
  990. attr.attributes = smb_attribs_to_attribs(pReq->FileAttributes);
  991. if (*file_name == '\\') {
  992. file_name++;
  993. }
  994. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  995. if (pReq->ByteCount > sz)
  996. sz = pReq->ByteCount - sz;
  997. else
  998. sz = 1;
  999. if (sz == 0)
  1000. file_name = "";
  1001. {
  1002. // convert name to unicode
  1003. int wsz;
  1004. LPWSTR wfile_name;
  1005. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  1006. if (wfile_name) {
  1007. fhandle_t fid;
  1008. error = pDisp->FsCreate(fshdl,
  1009. wfile_name, (USHORT)wsz,
  1010. flags,
  1011. &attr,
  1012. &fid,
  1013. &action);
  1014. pResp->Fid = fid;
  1015. } else {
  1016. error = ERROR_NOT_ENOUGH_MEMORY;
  1017. }
  1018. SRV_ASCII_FREE(wfile_name);
  1019. }
  1020. if (error) {
  1021. SrvLog(("WIN32ERROR: create error 0x%08X\n", error));
  1022. SET_WIN32ERROR(msg, error);
  1023. UPDATE_OUT_LEN(msg, RESP_OPEN_ANDX, pResp);
  1024. return TRUE;
  1025. }
  1026. if (additional_info) {
  1027. error = pDisp->FsGetAttr(fshdl, pResp->Fid, &attr);
  1028. if (error) {
  1029. SrvLog(("WIN32ERROR: get_attr error 0x%08X\n", error));
  1030. SET_WIN32ERROR(msg, error);
  1031. return TRUE;
  1032. }
  1033. pResp->FileAttributes = attribs_to_smb_attribs(attr.attributes);
  1034. pResp->LastWriteTimeInSeconds = time64_to_smb_timedate(&attr.mod_time);
  1035. pResp->DataSize = (ULONG) attr.file_size;
  1036. } else {
  1037. pResp->FileAttributes = 0;
  1038. pResp->LastWriteTimeInSeconds = 0;
  1039. pResp->DataSize = 0;
  1040. }
  1041. pResp->WordCount = 15;
  1042. pResp->GrantedAccess = pReq->DesiredAccess & SMB_DA_FCB_MASK;
  1043. if (!(action & ACCESS_WRITE)) {
  1044. if ((pResp->GrantedAccess & SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_WRITE) {
  1045. pResp->GrantedAccess &= ~SMB_DA_ACCESS_WRITE;
  1046. }
  1047. if ((pResp->GrantedAccess & SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_READ_WRITE) {
  1048. pResp->GrantedAccess &= ~SMB_DA_ACCESS_READ_WRITE;
  1049. }
  1050. }
  1051. pResp->Action = action & ~FS_ACCESS_MASK;
  1052. SrvLog(("GrantAccess 0x%x DesiredAccess %x addition %d sz %d\n", pResp->GrantedAccess,
  1053. pReq->DesiredAccess, additional_info, pResp->DataSize));
  1054. UPDATE_FOR_NEXT_ANDX(msg,
  1055. REQ_OPEN_ANDX, pReq,
  1056. RESP_OPEN_ANDX, pResp);
  1057. return SrvDispatch(msg);
  1058. }
  1059. BOOL
  1060. SrvComOpen(
  1061. Packet_t * msg
  1062. )
  1063. {
  1064. PVOID fshdl;
  1065. USHORT tid;
  1066. USHORT uid;
  1067. PVOID fsctx;
  1068. FsDispatchTable* pDisp;
  1069. UINT32 flags;
  1070. fattr_t attr;
  1071. DWORD error;
  1072. UINT32 action;
  1073. USHORT sz;
  1074. PCHAR file_name;
  1075. SET_TYPE(PREQ_OPEN, pReq);
  1076. SET_TYPE(PRESP_OPEN, pResp);
  1077. if (msg == NULL)
  1078. return FALSE;
  1079. tid = msg->in.smb->Tid;
  1080. uid = msg->in.smb->Uid;
  1081. fsctx = SRV_GET_FS_HANDLE(msg);
  1082. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1083. SET_REQ(PREQ_OPEN, pReq, msg);
  1084. SET_RESP(PRESP_OPEN, pResp, msg);
  1085. pResp->WordCount = 7;
  1086. // XXX - is ServerFid = 0 really ok? It seems like it never gets used...
  1087. pResp->Fid = 0xffff;
  1088. pResp->ByteCount = 0;
  1089. if (!pDisp) {
  1090. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1091. SET_DOSERROR(msg, SERVER, BAD_UID);
  1092. return TRUE;
  1093. }
  1094. if (pReq->WordCount != 2) {
  1095. SrvLogError(("DOSERROR: WordCount != 2\n"));
  1096. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1097. return TRUE;
  1098. }
  1099. file_name = (PCHAR)NEXT_LOCATION(pReq,
  1100. REQ_OPEN,
  1101. sizeof(UCHAR));
  1102. flags = DISP_OPEN_EXISTING | smb_access_to_flags(pReq->DesiredAccess);
  1103. if (*file_name == '\\') {
  1104. file_name++;
  1105. }
  1106. sz = (USHORT) (((char *)file_name) - ((char *)&pReq->Buffer[0]));
  1107. if (pReq->ByteCount > sz)
  1108. sz = pReq->ByteCount - sz;
  1109. else
  1110. sz = 1;
  1111. if (sz == 0)
  1112. file_name = "";
  1113. {
  1114. // convert name to unicode
  1115. int wsz;
  1116. LPWSTR wfile_name;
  1117. SRV_ASCII_TO_WCHAR(wfile_name, wsz, file_name, sz);
  1118. if (wfile_name) {
  1119. fhandle_t fid;
  1120. error = pDisp->FsCreate(fshdl,
  1121. wfile_name, (USHORT)wsz,
  1122. flags,
  1123. NULL,
  1124. &fid,
  1125. &action);
  1126. pResp->Fid = fid;
  1127. } else {
  1128. error = ERROR_NOT_ENOUGH_MEMORY;
  1129. }
  1130. SRV_ASCII_FREE(wfile_name);
  1131. }
  1132. if (error) {
  1133. SrvLog(("WIN32ERROR: create error 0x%08X\n", error));
  1134. SET_WIN32ERROR(msg, error);
  1135. UPDATE_OUT_LEN(msg, RESP_OPEN, pResp);
  1136. return TRUE;
  1137. }
  1138. error = pDisp->FsGetAttr(fshdl, pResp->Fid, &attr);
  1139. if (error) {
  1140. SrvLog(("WIN32ERROR: get_attr error 0x%08X\n", error));
  1141. SET_WIN32ERROR(msg, error);
  1142. UPDATE_OUT_LEN(msg, RESP_OPEN, pResp);
  1143. return TRUE;
  1144. }
  1145. pResp->FileAttributes = attribs_to_smb_attribs(attr.attributes);
  1146. pResp->LastWriteTimeInSeconds = time64_to_smb_timedate(&attr.mod_time);
  1147. pResp->DataSize = (ULONG)attr.file_size;
  1148. pResp->GrantedAccess = pReq->DesiredAccess & SMB_DA_FCB_MASK;
  1149. if (!(action & ACCESS_WRITE)) {
  1150. if ((pResp->GrantedAccess & SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_WRITE) {
  1151. pResp->GrantedAccess &= ~SMB_DA_ACCESS_WRITE;
  1152. }
  1153. if ((pResp->GrantedAccess & SMB_DA_ACCESS_MASK) == SMB_DA_ACCESS_READ_WRITE) {
  1154. pResp->GrantedAccess &= ~SMB_DA_ACCESS_READ_WRITE;
  1155. }
  1156. }
  1157. SrvLog(("GrantAccess 0x%x DesiredAccess %x sz %d\n", pResp->GrantedAccess,
  1158. pReq->DesiredAccess, pResp->DataSize));
  1159. UPDATE_OUT_LEN(msg, RESP_OPEN, pResp);
  1160. return TRUE;
  1161. }
  1162. BOOL
  1163. SrvComWrite(
  1164. Packet_t * msg
  1165. )
  1166. {
  1167. PVOID fshdl;
  1168. USHORT tid;
  1169. USHORT uid;
  1170. PVOID fsctx;
  1171. FsDispatchTable* pDisp;
  1172. ULONG offset;
  1173. DWORD error;
  1174. USHORT count, actual_count;
  1175. void *data;
  1176. SET_TYPE(PREQ_WRITE, pReq);
  1177. SET_TYPE(PRESP_WRITE, pResp);
  1178. if (msg == NULL)
  1179. return FALSE;
  1180. tid = msg->in.smb->Tid;
  1181. uid = msg->in.smb->Uid;
  1182. fsctx = SRV_GET_FS_HANDLE(msg);
  1183. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1184. SET_REQ(PREQ_WRITE, pReq, msg);
  1185. SET_RESP(PRESP_WRITE, pResp, msg);
  1186. if (!pDisp) {
  1187. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1188. SET_DOSERROR(msg, SERVER, BAD_UID);
  1189. return TRUE;
  1190. }
  1191. if (pReq->WordCount != 5) {
  1192. SrvLogError(("DOSERROR: WordCount != 5\n"));
  1193. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1194. return TRUE;
  1195. }
  1196. count = pReq->Count;
  1197. offset = pReq->Offset;
  1198. // NOTE -- it turns out that the BufferFormat and DataLength fields
  1199. // do not exist!
  1200. data = (void*)NEXT_LOCATION(pReq,
  1201. REQ_WRITE,
  1202. 0);
  1203. actual_count = count;
  1204. error = pDisp->FsWrite(fshdl, pReq->Fid, offset, &actual_count, data, NULL);
  1205. if (error) {
  1206. SrvLog(("WIN32ERROR: write error 0x%08X\n", error));
  1207. SET_WIN32ERROR(msg, error);
  1208. }
  1209. pResp->WordCount = 1;
  1210. pResp->Count = actual_count;
  1211. pResp->ByteCount = 0;
  1212. UPDATE_OUT_LEN(msg, RESP_WRITE, pResp);
  1213. return TRUE;
  1214. }
  1215. BOOL
  1216. SrvComClose(
  1217. Packet_t * msg
  1218. )
  1219. {
  1220. PVOID fshdl;
  1221. USHORT tid;
  1222. USHORT uid;
  1223. PVOID fsctx;
  1224. FsDispatchTable* pDisp;
  1225. DWORD error;
  1226. SET_TYPE(PREQ_CLOSE, pReq);
  1227. SET_TYPE(PRESP_CLOSE, pResp);
  1228. if (msg == NULL)
  1229. return FALSE;
  1230. tid = msg->in.smb->Tid;
  1231. uid = msg->in.smb->Uid;
  1232. fsctx = SRV_GET_FS_HANDLE(msg);
  1233. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1234. SET_REQ(PREQ_CLOSE, pReq, msg);
  1235. SET_RESP(PRESP_CLOSE, pResp, msg);
  1236. if (!pDisp) {
  1237. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1238. SET_DOSERROR(msg, SERVER, BAD_UID);
  1239. return TRUE;
  1240. }
  1241. error = pDisp->FsClose(fshdl, pReq->Fid);
  1242. if (error) {
  1243. SrvLog(("WIN32ERROR: close error 0x%08X\n", error));
  1244. SET_WIN32ERROR(msg, error);
  1245. }
  1246. pResp->WordCount = 0;
  1247. pResp->ByteCount = 0;
  1248. UPDATE_OUT_LEN(msg, RESP_CLOSE, pResp);
  1249. return TRUE;
  1250. }
  1251. void
  1252. WINAPI
  1253. SrvReadContinue(PVOID p, UINT32 status, UINT32 length)
  1254. {
  1255. Packet_t *msg = (Packet_t *) p;
  1256. SET_TYPE(PREQ_READ_ANDX, pReq);
  1257. SET_TYPE(PRESP_READ_ANDX, pResp);
  1258. DWORD consumed;
  1259. if (msg == NULL)
  1260. return;
  1261. SET_REQ(PREQ_READ_ANDX, pReq, msg);
  1262. SET_RESP(PRESP_READ_ANDX, pResp, msg);
  1263. consumed = (DWORD)(pResp->Buffer - (PUCHAR)msg->out.smb);
  1264. if (status == ERROR_SUCCESS) {
  1265. pResp->WordCount = 12;
  1266. pResp->Remaining = 0;
  1267. pResp->DataCompactionMode = 0;
  1268. pResp->Reserved = 0;
  1269. pResp->Reserved2 = 0;
  1270. RtlZeroMemory(pResp->Reserved3, sizeof(pResp->Reserved3));
  1271. pResp->DataLength = (USHORT) length;
  1272. pResp->DataOffset = (USHORT) consumed;
  1273. pResp->ByteCount = (USHORT) length;
  1274. UPDATE_FOR_NEXT_ANDX(msg,
  1275. REQ_READ_ANDX, pReq,
  1276. RESP_READ_ANDX, pResp);
  1277. if (msg->in.command != 0xFF)
  1278. SrvDispatch(msg);
  1279. } else {
  1280. SrvLog(("WIN32ERROR: read error 0x%08X\n", status));
  1281. SET_WIN32ERROR(msg, status);
  1282. pResp->ByteCount = 0;
  1283. UPDATE_OUT_LEN(msg, RESP_READ_ANDX, pResp);
  1284. }
  1285. SrvFinalize(msg);
  1286. }
  1287. BOOL
  1288. SrvComReadAndx(
  1289. Packet_t * msg
  1290. )
  1291. {
  1292. PVOID fshdl;
  1293. USHORT tid;
  1294. USHORT uid;
  1295. PVOID fsctx;
  1296. FsDispatchTable* pDisp;
  1297. DWORD consumed;
  1298. DWORD remaining;
  1299. USHORT MinCount;
  1300. USHORT MaxCount;
  1301. USHORT actual_count;
  1302. ULONG offset;
  1303. DWORD error;
  1304. SET_TYPE(PREQ_READ_ANDX, pReq);
  1305. SET_TYPE(PRESP_READ_ANDX, pResp);
  1306. if (msg == NULL)
  1307. return FALSE;
  1308. tid = msg->in.smb->Tid;
  1309. uid = msg->in.smb->Uid;
  1310. fsctx = SRV_GET_FS_HANDLE(msg);
  1311. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1312. SET_REQ(PREQ_READ_ANDX, pReq, msg);
  1313. SET_RESP(PRESP_READ_ANDX, pResp, msg);
  1314. if (!pDisp) {
  1315. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1316. SET_DOSERROR(msg, SERVER, BAD_UID);
  1317. return TRUE;
  1318. }
  1319. if (pReq->WordCount != 10) {
  1320. SrvLogError(("DOSERROR: WordCount != 10\n"));
  1321. SET_DOSERROR(msg, SERVER, ERROR); // ok
  1322. return TRUE;
  1323. }
  1324. consumed = (DWORD)(pResp->Buffer - (PUCHAR)msg->out.smb);
  1325. remaining = msg->out.size - consumed;
  1326. MinCount = pReq->MinCount;
  1327. MaxCount = pReq->MaxCount;
  1328. offset = pReq->Offset;
  1329. SrvLog(("Fid %d MaxCount = %d, MinCount = %d\n", pReq->Fid, MaxCount, MinCount));
  1330. if (MaxCount > remaining) {
  1331. SrvLog(("DOSERROR: MaxCount (%d) > remaining (%d)\n", MaxCount, remaining));
  1332. SET_DOSERROR(msg, SERVER, ERROR); // XXX -- ok?
  1333. return TRUE;
  1334. }
  1335. actual_count = MaxCount;
  1336. msg->tag = ERROR_IO_PENDING;
  1337. msg->completion = SrvReadContinue;
  1338. error = pDisp->FsRead(fshdl, pReq->Fid, offset, &actual_count, pResp->Buffer, (PVOID)msg);
  1339. if (error) {
  1340. if (error == ERROR_IO_PENDING) {
  1341. return ERROR_IO_PENDING;
  1342. }
  1343. SrvLog(("WIN32ERROR: read error 0x%08X\n", error));
  1344. SET_WIN32ERROR(msg, error);
  1345. pResp->ByteCount = 0;
  1346. UPDATE_OUT_LEN(msg, RESP_READ_ANDX, pResp);
  1347. return TRUE;
  1348. }
  1349. msg->tag = 0;
  1350. pResp->WordCount = 12;
  1351. pResp->Remaining = 0;
  1352. pResp->DataCompactionMode = 0;
  1353. pResp->Reserved = 0;
  1354. pResp->Reserved2 = 0;
  1355. RtlZeroMemory(pResp->Reserved3, sizeof(pResp->Reserved3));
  1356. pResp->DataLength = actual_count;
  1357. pResp->DataOffset = (USHORT) consumed;
  1358. pResp->ByteCount = actual_count;
  1359. UPDATE_FOR_NEXT_ANDX(msg,
  1360. REQ_READ_ANDX, pReq,
  1361. RESP_READ_ANDX, pResp);
  1362. return SrvDispatch(msg);
  1363. }
  1364. BOOL
  1365. SrvComQueryInformation2(
  1366. Packet_t * msg
  1367. )
  1368. {
  1369. PVOID fshdl;
  1370. USHORT tid;
  1371. USHORT uid;
  1372. PVOID fsctx;
  1373. FsDispatchTable* pDisp;
  1374. fattr_t attribs;
  1375. DWORD error;
  1376. SET_TYPE(PREQ_QUERY_INFORMATION2, pReq);
  1377. SET_TYPE(PRESP_QUERY_INFORMATION2, pResp);
  1378. if (msg == NULL)
  1379. return FALSE;
  1380. tid = msg->in.smb->Tid;
  1381. uid = msg->in.smb->Uid;
  1382. fsctx = SRV_GET_FS_HANDLE(msg);
  1383. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1384. SET_REQ(PREQ_QUERY_INFORMATION2, pReq, msg);
  1385. SET_RESP(PRESP_QUERY_INFORMATION2, pResp, msg);
  1386. pResp->WordCount = 11;
  1387. pResp->ByteCount = 0;
  1388. if (!pDisp) {
  1389. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1390. SET_DOSERROR(msg, SERVER, BAD_UID);
  1391. return TRUE;
  1392. }
  1393. if (pReq->WordCount != 1) {
  1394. SrvLogError(("DOSERROR: WordCount != 1\n"));
  1395. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1396. return TRUE;
  1397. }
  1398. error = pDisp->FsGetAttr(fshdl, pReq->Fid, &attribs);
  1399. if (error) {
  1400. SrvLog(("WIN32ERROR: get_attr error 0x%08X\n", error));
  1401. SET_WIN32ERROR(msg, error);
  1402. UPDATE_OUT_LEN(msg, RESP_QUERY_INFORMATION2, pResp);
  1403. return TRUE;
  1404. }
  1405. RtlZeroMemory(&pResp->CreationDate, sizeof(USHORT) * 6);
  1406. time64_to_smb_datetime(&attribs.create_time,
  1407. &pResp->CreationDate.Ushort,
  1408. &pResp->CreationTime.Ushort);
  1409. time64_to_smb_datetime(&attribs.access_time,
  1410. &pResp->LastAccessDate.Ushort,
  1411. &pResp->LastAccessTime.Ushort);
  1412. time64_to_smb_datetime(&attribs.mod_time,
  1413. &pResp->LastWriteDate.Ushort,
  1414. &pResp->LastWriteTime.Ushort);
  1415. pResp->FileDataSize = (ULONG) attribs.file_size;
  1416. pResp->FileAllocationSize = (ULONG)attribs.alloc_size;
  1417. pResp->FileAttributes = attribs_to_smb_attribs(attribs.attributes);
  1418. UPDATE_OUT_LEN(msg, RESP_QUERY_INFORMATION2, pResp);
  1419. return TRUE;
  1420. }
  1421. BOOL
  1422. SrvComSetInformation2(
  1423. Packet_t * msg
  1424. )
  1425. {
  1426. PVOID fshdl;
  1427. USHORT tid;
  1428. USHORT uid;
  1429. PVOID fsctx;
  1430. FsDispatchTable* pDisp;
  1431. fattr_t attribs;
  1432. DWORD error;
  1433. SET_TYPE(PREQ_SET_INFORMATION2, pReq);
  1434. SET_TYPE(PRESP_SET_INFORMATION2, pResp);
  1435. if (msg == NULL)
  1436. return FALSE;
  1437. tid = msg->in.smb->Tid;
  1438. uid = msg->in.smb->Uid;
  1439. fsctx = SRV_GET_FS_HANDLE(msg);
  1440. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1441. SET_REQ(PREQ_SET_INFORMATION2, pReq, msg);
  1442. SET_RESP(PRESP_SET_INFORMATION2, pResp, msg);
  1443. if (!pDisp) {
  1444. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1445. SET_DOSERROR(msg, SERVER, BAD_UID);
  1446. return TRUE;
  1447. }
  1448. if (pReq->WordCount != 7) {
  1449. SrvLogError(("DOSERROR: WordCount != 7\n"));
  1450. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1451. return TRUE;
  1452. }
  1453. attribs.file_size = INVALID_UINT64;
  1454. attribs.alloc_size = INVALID_UINT64;
  1455. attribs.access_time = INVALID_TIME64;
  1456. attribs.create_time = INVALID_TIME64;
  1457. attribs.mod_time = INVALID_TIME64;
  1458. attribs.attributes = INVALID_UINT32;
  1459. if (pReq->CreationDate.Ushort || pReq->CreationTime.Ushort) {
  1460. smb_datetime_to_time64(pReq->CreationDate.Ushort,
  1461. pReq->CreationTime.Ushort,
  1462. &attribs.create_time);
  1463. }
  1464. if (pReq->LastAccessDate.Ushort || pReq->LastAccessTime.Ushort) {
  1465. smb_datetime_to_time64(pReq->LastAccessDate.Ushort,
  1466. pReq->LastAccessTime.Ushort,
  1467. &attribs.access_time);
  1468. }
  1469. if (pReq->LastWriteDate.Ushort || pReq->LastWriteTime.Ushort) {
  1470. smb_datetime_to_time64(pReq->LastWriteDate.Ushort,
  1471. pReq->LastWriteTime.Ushort,
  1472. &attribs.mod_time);
  1473. }
  1474. error = pDisp->FsSetAttr(fshdl, pReq->Fid, &attribs);
  1475. if (error) {
  1476. SrvLog(("WIN32ERROR: set_attr error 0x%08X\n", error));
  1477. SET_WIN32ERROR(msg, error);
  1478. }
  1479. pResp->WordCount = 0;
  1480. pResp->ByteCount = 0;
  1481. UPDATE_OUT_LEN(msg, RESP_SET_INFORMATION2, pResp);
  1482. return TRUE;
  1483. }
  1484. void
  1485. WINAPI
  1486. SrvLockContinue(PVOID p, UINT32 status, UINT32 length)
  1487. {
  1488. Packet_t *msg = (Packet_t *) p;
  1489. SET_TYPE(PREQ_LOCKING_ANDX, pReq);
  1490. SET_TYPE(PRESP_LOCKING_ANDX, pResp);
  1491. DWORD consumed;
  1492. if (msg == NULL)
  1493. return;
  1494. SET_REQ(PREQ_LOCKING_ANDX, pReq, msg);
  1495. SET_RESP(PRESP_LOCKING_ANDX, pResp, msg);
  1496. consumed = (DWORD)(pResp->Buffer - (PUCHAR)msg->out.smb);
  1497. pResp->WordCount = 2;
  1498. pResp->ByteCount = 0;
  1499. UPDATE_FOR_NEXT_ANDX(msg,
  1500. REQ_LOCKING_ANDX, pReq,
  1501. RESP_LOCKING_ANDX, pResp);
  1502. if (status == ERROR_SUCCESS) {
  1503. if (msg->in.command != 0xFF)
  1504. SrvDispatch(msg);
  1505. } else {
  1506. SrvLog(("WIN32ERROR: read error 0x%08X\n", status));
  1507. SET_WIN32ERROR(msg, status);
  1508. }
  1509. SrvFinalize(msg);
  1510. }
  1511. BOOL
  1512. SrvComLockingAndx(
  1513. Packet_t * msg
  1514. )
  1515. {
  1516. PVOID fshdl;
  1517. USHORT tid;
  1518. USHORT uid;
  1519. PVOID fsctx;
  1520. FsDispatchTable* pDisp;
  1521. int i;
  1522. ULONG flags;
  1523. int offset;
  1524. PLOCKING_ANDX_RANGE pUnlocks, pLocks;
  1525. BOOL bShared;
  1526. USHORT nulocks, nlocks;
  1527. DWORD error;
  1528. SET_TYPE(PREQ_LOCKING_ANDX, pReq);
  1529. SET_TYPE(PRESP_LOCKING_ANDX, pResp);
  1530. if (msg == NULL)
  1531. return FALSE;
  1532. tid = msg->in.smb->Tid;
  1533. uid = msg->in.smb->Uid;
  1534. fsctx = SRV_GET_FS_HANDLE(msg);
  1535. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1536. SET_REQ(PREQ_LOCKING_ANDX, pReq, msg);
  1537. SET_RESP(PRESP_LOCKING_ANDX, pResp, msg);
  1538. if (pReq->WordCount != 8) {
  1539. SrvLogError(("DOSERROR: WordCount != 8\n"));
  1540. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1541. return TRUE;
  1542. }
  1543. if (!pDisp) {
  1544. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1545. SET_DOSERROR(msg, SERVER, BAD_UID);
  1546. return TRUE;
  1547. }
  1548. bShared = pReq->LockType; // & LOCKING_ANDX_SHARED_LOCK;
  1549. nulocks= pReq->NumberOfUnlocks;
  1550. nlocks = pReq->NumberOfLocks;
  1551. pLocks = NULL;
  1552. pUnlocks = NULL;
  1553. offset = 0;
  1554. if (pReq->ByteCount > offset) {
  1555. pUnlocks = (PLOCKING_ANDX_RANGE)
  1556. NEXT_LOCATION(pReq, REQ_LOCKING_ANDX, offset);
  1557. offset += (pReq->NumberOfUnlocks * sizeof(LOCKING_ANDX_RANGE));
  1558. }
  1559. if (pReq->ByteCount > offset) {
  1560. pLocks = (PLOCKING_ANDX_RANGE)
  1561. NEXT_LOCATION(pReq, REQ_LOCKING_ANDX, offset);
  1562. }
  1563. flags = 0;
  1564. if (pReq->Timeout != 0) {
  1565. flags |= 0x1; // wait
  1566. }
  1567. if (pReq->LockType & LOCKING_ANDX_SHARED_LOCK) {
  1568. flags |= 0x2; // shared
  1569. }
  1570. SET_WIN32ERROR(msg, ERROR_INVALID_PARAMETER);
  1571. if (pLocks != NULL) {
  1572. for (i = 0; i < nlocks; i++) {
  1573. SrvLog(("Lock: %d pid %d offset %d len %d flags %x (%x,%d)\n", i,
  1574. pLocks[i].Pid, pLocks[i].Offset, pLocks[i].Length, flags,
  1575. pReq->LockType, pReq->Timeout));
  1576. msg->tag = ERROR_IO_PENDING;
  1577. msg->completion = SrvLockContinue;
  1578. error = pDisp->FsLock(fshdl, pReq->Fid,
  1579. pLocks[i].Offset, pLocks[i].Length,
  1580. flags,
  1581. (PVOID) msg);
  1582. if (error == ERROR_IO_PENDING) {
  1583. return ERROR_IO_PENDING;
  1584. }
  1585. SET_WIN32ERROR(msg, error);
  1586. }
  1587. }
  1588. if (pUnlocks != NULL) {
  1589. for (i = 0; i < nulocks; i++) {
  1590. SrvLog(("Unlock: %d pid %d offset %d len %d\n", i,
  1591. pUnlocks[i].Pid, pUnlocks[i].Offset, pUnlocks[i].Length));
  1592. error = pDisp->FsUnlock(fshdl, pReq->Fid,
  1593. pUnlocks[i].Offset, pUnlocks[i].Length);
  1594. SET_WIN32ERROR(msg, error);
  1595. }
  1596. }
  1597. pResp->WordCount = 2;
  1598. pResp->ByteCount = 0;
  1599. UPDATE_FOR_NEXT_ANDX(msg,
  1600. REQ_LOCKING_ANDX, pReq,
  1601. RESP_LOCKING_ANDX, pResp);
  1602. return SrvDispatch(msg);
  1603. }
  1604. BOOL
  1605. SrvComSeek(
  1606. Packet_t * msg
  1607. )
  1608. {
  1609. PVOID fshdl;
  1610. USHORT tid;
  1611. USHORT uid;
  1612. PVOID fsctx;
  1613. FsDispatchTable* pDisp;
  1614. ULONG offset;
  1615. fattr_t attribs;
  1616. DWORD error;
  1617. BOOL bStart;
  1618. USHORT mode;
  1619. SET_TYPE(PREQ_SEEK, pReq);
  1620. SET_TYPE(PRESP_SEEK, pResp);
  1621. if (msg == NULL)
  1622. return FALSE;
  1623. tid = msg->in.smb->Tid;
  1624. uid = msg->in.smb->Uid;
  1625. fsctx = SRV_GET_FS_HANDLE(msg);
  1626. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1627. SET_REQ(PREQ_SEEK, pReq, msg);
  1628. SET_RESP(PRESP_SEEK, pResp, msg);
  1629. pResp->WordCount = 2;
  1630. pResp->ByteCount = 0;
  1631. if (!pDisp) {
  1632. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1633. SET_DOSERROR(msg, SERVER, BAD_UID);
  1634. return TRUE;
  1635. }
  1636. if (pReq->WordCount != 4) {
  1637. SrvLogError(("DOSERROR: WordCount != 4\n"));
  1638. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1639. return TRUE;
  1640. }
  1641. mode = pReq->Mode;
  1642. if (mode && (mode != 2)) {
  1643. SrvLog(("DOSERROR: only support modes 0 & 2 (not %d)\n", mode));
  1644. SET_DOSERROR(msg, SERVER, ERROR);
  1645. return TRUE;
  1646. }
  1647. bStart = !mode;
  1648. offset = pReq->Offset;
  1649. error = pDisp->FsGetAttr(fshdl, pReq->Fid, &attribs);
  1650. if (error) {
  1651. SrvLog(("WIN32ERROR: get_attr error 0x%08X\n", error));
  1652. SET_WIN32ERROR(msg, error);
  1653. return TRUE;
  1654. }
  1655. pResp->Offset = 0;
  1656. UPDATE_OUT_LEN(msg, RESP_SEEK, pResp);
  1657. return TRUE;
  1658. }
  1659. BOOL
  1660. SrvComFlush(
  1661. Packet_t * msg
  1662. )
  1663. {
  1664. PVOID fshdl;
  1665. USHORT tid;
  1666. USHORT uid;
  1667. PVOID fsctx;
  1668. FsDispatchTable* pDisp;
  1669. DWORD error;
  1670. SET_TYPE(PREQ_FLUSH, pReq);
  1671. SET_TYPE(PRESP_FLUSH, pResp);
  1672. if (msg == NULL)
  1673. return FALSE;
  1674. tid = msg->in.smb->Tid;
  1675. uid = msg->in.smb->Uid;
  1676. fsctx = SRV_GET_FS_HANDLE(msg);
  1677. pDisp = FsGetHandle(fsctx, tid, uid, &fshdl);
  1678. SET_REQ(PREQ_FLUSH, pReq, msg);
  1679. SET_RESP(PRESP_FLUSH, pResp, msg);
  1680. if (pReq->WordCount != 1) {
  1681. SrvLogError(("DOSERROR: WordCount != 1\n"));
  1682. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1683. return TRUE;
  1684. }
  1685. if (pReq->ByteCount != 0) {
  1686. SrvLogError(("DOSERROR: ByteCount != 0\n"));
  1687. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1688. return TRUE;
  1689. }
  1690. if (!pDisp) {
  1691. SrvLogError(("DOSERROR: could not find dispatch table for uid %d\n", uid));
  1692. SET_DOSERROR(msg, SERVER, BAD_UID);
  1693. return TRUE;
  1694. }
  1695. error = pDisp->FsFlush(fshdl, pReq->Fid);
  1696. if (error) {
  1697. SrvLog(("WIN32ERROR: flush error 0x%08X\n", error));
  1698. SET_WIN32ERROR(msg, error);
  1699. }
  1700. pResp->WordCount = 0;
  1701. pResp->ByteCount = 0;
  1702. UPDATE_OUT_LEN(msg, RESP_FLUSH, pResp);
  1703. return TRUE;
  1704. }
  1705. BOOL
  1706. SrvComLogoffAndx(
  1707. Packet_t * msg
  1708. )
  1709. {
  1710. USHORT tid;
  1711. USHORT uid;
  1712. PVOID fsctx;
  1713. SET_TYPE(PREQ_LOGOFF_ANDX, pReq);
  1714. SET_TYPE(PRESP_LOGOFF_ANDX, pResp);
  1715. if (msg == NULL)
  1716. return FALSE;
  1717. tid = msg->in.smb->Tid;
  1718. uid = msg->in.smb->Uid;
  1719. fsctx = SRV_GET_FS_HANDLE(msg);
  1720. SET_REQ(PREQ_LOGOFF_ANDX, pReq, msg);
  1721. SET_RESP(PRESP_LOGOFF_ANDX, pResp, msg);
  1722. memcpy(pResp, pReq, sizeof(PRESP_LOGOFF_ANDX));
  1723. FsDisMount(fsctx, uid, tid);
  1724. UPDATE_OUT_LEN(msg, RESP_LOGOFF_ANDX, pResp);
  1725. return TRUE;
  1726. }
  1727. BOOL
  1728. SrvComTreeDisconnect(
  1729. Packet_t * msg
  1730. )
  1731. {
  1732. USHORT uid;
  1733. USHORT tid;
  1734. PVOID fsctx;
  1735. SET_TYPE(PREQ_TREE_DISCONNECT, pReq);
  1736. SET_TYPE(PRESP_TREE_DISCONNECT, pResp);
  1737. if (msg == NULL)
  1738. return FALSE;
  1739. uid = msg->in.smb->Uid;
  1740. tid = msg->in.smb->Tid;
  1741. fsctx = SRV_GET_FS_HANDLE(msg);
  1742. SET_REQ(PREQ_TREE_DISCONNECT, pReq, msg);
  1743. SET_RESP(PRESP_TREE_DISCONNECT, pResp, msg);
  1744. pResp->WordCount = 0;
  1745. pResp->ByteCount = 0;
  1746. FsDisMount(fsctx, uid, tid);
  1747. UPDATE_OUT_LEN(msg, RESP_TREE_DISCONNECT, pResp);
  1748. return TRUE;
  1749. }
  1750. BOOL
  1751. SrvComSearch(
  1752. Packet_t * msg
  1753. )
  1754. {
  1755. PVOID fshdl;
  1756. USHORT tid;
  1757. USHORT uid;
  1758. SET_TYPE(PREQ_SEARCH, pReq);
  1759. SET_TYPE(PRESP_SEARCH, pResp);
  1760. if (msg == NULL)
  1761. return FALSE;
  1762. tid = msg->in.smb->Tid;
  1763. uid = msg->in.smb->Uid;
  1764. SET_REQ(PREQ_SEARCH, pReq, msg);
  1765. SET_RESP(PRESP_SEARCH, pResp, msg);
  1766. // this call is not supported in our dialect, so no worries.
  1767. UPDATE_OUT_LEN(msg, RESP_SEARCH, pResp);
  1768. return TRUE;
  1769. }
  1770. BOOL
  1771. SrvComIoctl(
  1772. Packet_t * msg
  1773. )
  1774. {
  1775. SET_TYPE(PREQ_IOCTL, pReq);
  1776. SET_TYPE(PRESP_IOCTL, pResp);
  1777. if (msg == NULL)
  1778. return FALSE;
  1779. SET_REQ(PREQ_IOCTL, pReq, msg);
  1780. SET_RESP(PRESP_IOCTL, pResp, msg);
  1781. if (pReq->WordCount != 14) {
  1782. SrvLogError(("DOSERROR: WordCount != 1\n"));
  1783. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1784. return TRUE;
  1785. }
  1786. SrvLog(("Ioctl: fid %d category %d function %d tpc %d tdc %d mpc %d mdc %d pc %d po %d dc %d do %d bc %d\n",
  1787. pReq->Fid,
  1788. pReq->Category,
  1789. pReq->Function,
  1790. pReq->TotalParameterCount,
  1791. pReq->TotalDataCount,
  1792. pReq->MaxParameterCount,
  1793. pReq->MaxDataCount,
  1794. pReq->ParameterCount,
  1795. pReq->DataCount,
  1796. pReq->DataOffset,
  1797. pReq->ByteCount));
  1798. memset((char *)pResp, 0, sizeof(*pResp));
  1799. pResp->WordCount = 8;
  1800. UPDATE_OUT_LEN(msg, RESP_IOCTL, pResp);
  1801. return TRUE;
  1802. }
  1803. BOOL
  1804. SrvComEcho(
  1805. Packet_t * msg
  1806. )
  1807. {
  1808. SET_TYPE(PREQ_ECHO, pReq);
  1809. SET_TYPE(PRESP_ECHO, pResp);
  1810. if (msg == NULL)
  1811. return FALSE;
  1812. SET_REQ(PREQ_ECHO, pReq, msg);
  1813. SET_RESP(PRESP_ECHO, pResp, msg);
  1814. if (pReq->WordCount != 1) {
  1815. SrvLogError(("DOSERROR: WordCount != 1\n"));
  1816. SET_DOSERROR(msg, SERVER, ERROR); // ok?
  1817. return TRUE;
  1818. }
  1819. SrvLog(("Echo: count %d bytecount %d\n", pReq->EchoCount, pReq->ByteCount));
  1820. pResp->WordCount = 1;
  1821. pResp->SequenceNumber = 1;
  1822. pResp->ByteCount = pReq->ByteCount;
  1823. memcpy(pResp->Buffer, pReq->Buffer, pReq->ByteCount);
  1824. UPDATE_OUT_LEN(msg, RESP_ECHO, pResp);
  1825. return TRUE;
  1826. }