Leaked source code of windows server 2003
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.

1615 lines
38 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. ftpapiw.cxx
  5. Abstract:
  6. Wide-character versions of Windows Internet Client DLL FTP APIs and
  7. Internet subordinate functions
  8. Contents:
  9. FtpFindFirstFileW
  10. FtpGetFileW
  11. FtpPutFileW
  12. FtpDeleteFileW
  13. FtpRenameFileW
  14. FtpOpenFileW
  15. FtpCreateDirectoryW
  16. FtpRemoveDirectoryW
  17. FtpSetCurrentDirectoryW
  18. FtpGetCurrentDirectoryW
  19. FtpCommandW
  20. Author:
  21. Heath Hunnicutt [t-heathh] 13-Jul-1994
  22. Environment:
  23. Win32(s) user-level DLL
  24. Revision History:
  25. 09-Mar-1995 rfirth
  26. moved from unicode.c
  27. 21-Jul-1994 t-heathh
  28. Created
  29. --*/
  30. #include <wininetp.h>
  31. #include "ftpapih.h"
  32. #include <w95wraps.h>
  33. #define DEFAULT_TRANSFER_BUFFER_LENGTH (4 K)
  34. #define ALLOWED_FTP_FLAGS (INTERNET_FLAGS_MASK \
  35. | FTP_TRANSFER_TYPE_MASK \
  36. )
  37. //
  38. // functions
  39. //
  40. BOOL
  41. TransformFtpFindDataToW(LPWIN32_FIND_DATAA pfdA, LPWIN32_FIND_DATAW pfdW)
  42. {
  43. pfdW->dwFileAttributes = pfdA->dwFileAttributes;
  44. pfdW->ftCreationTime = pfdA->ftCreationTime;
  45. pfdW->ftLastAccessTime = pfdA->ftLastAccessTime;
  46. pfdW->ftLastWriteTime = pfdA->ftLastWriteTime;
  47. pfdW->nFileSizeHigh = pfdA->nFileSizeHigh;
  48. pfdW->nFileSizeLow = pfdA->nFileSizeLow;
  49. pfdW->dwReserved0 = pfdA->dwReserved0;
  50. pfdW->dwReserved1 = pfdA->dwReserved1;
  51. MultiByteToWideChar(CP_ACP, 0, pfdA->cFileName, -1, pfdW->cFileName, MAX_PATH);
  52. MultiByteToWideChar(CP_ACP, 0, pfdA->cAlternateFileName, -1, pfdW->cAlternateFileName, 14);
  53. return TRUE;
  54. }
  55. INTERNETAPI_(HINTERNET) FtpFindFirstFileW(
  56. IN HINTERNET hFtpSession,
  57. IN LPCWSTR lpszSearchFile,
  58. OUT LPWIN32_FIND_DATAW pffdOutput,
  59. IN DWORD dwFlags,
  60. IN DWORD_PTR dwContext
  61. )
  62. /*++
  63. Routine Description:
  64. description-of-function.
  65. Arguments:
  66. hFtpSession -
  67. lpszSearchFile -
  68. pffdOutput -
  69. dwFlags -
  70. dwContext -
  71. Return Value:
  72. HINTERNET
  73. --*/
  74. {
  75. DEBUG_ENTER_API((DBG_API,
  76. Handle,
  77. "FtpFindFirstFileW",
  78. "%#x, %.80wq, %#x, %#x, %#x",
  79. hFtpSession,
  80. lpszSearchFile,
  81. pffdOutput,
  82. dwFlags,
  83. dwContext
  84. ));
  85. DWORD dwErr = ERROR_SUCCESS;
  86. MEMORYPACKET mpSearchFile;
  87. HANDLE hInternet = NULL;
  88. WIN32_FIND_DATAA fdA;
  89. if (!pffdOutput
  90. || IsBadWritePtr(pffdOutput, sizeof(*pffdOutput))
  91. || (lpszSearchFile && (IsBadStringPtrW(lpszSearchFile, INTERNET_MAX_PATH_LENGTH + 1))))
  92. {
  93. dwErr = ERROR_INVALID_PARAMETER;
  94. goto cleanup;
  95. }
  96. if (lpszSearchFile)
  97. {
  98. ALLOC_MB(lpszSearchFile,0,mpSearchFile);
  99. if (!mpSearchFile.psStr)
  100. {
  101. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  102. goto cleanup;
  103. }
  104. UNICODE_TO_ANSI(lpszSearchFile,mpSearchFile);
  105. }
  106. hInternet = FtpFindFirstFileA(hFtpSession,mpSearchFile.psStr,&fdA,dwFlags,dwContext);
  107. if (hInternet)
  108. {
  109. TransformFtpFindDataToW(&fdA, pffdOutput);
  110. }
  111. cleanup:
  112. if (dwErr!=ERROR_SUCCESS)
  113. {
  114. SetLastError(dwErr);
  115. DEBUG_ERROR(API, dwErr);
  116. }
  117. DEBUG_LEAVE_API(hInternet);
  118. return hInternet;
  119. }
  120. INTERNETAPI_(BOOL) FtpGetFileW(
  121. IN HINTERNET hFtpSession,
  122. IN LPCWSTR lpszRemoteFile,
  123. IN LPCWSTR lpszNewFile,
  124. IN BOOL fFailIfExists,
  125. IN DWORD dwFlagsAndAttributes,
  126. IN DWORD dwFlags,
  127. IN DWORD_PTR dwContext
  128. )
  129. /*++
  130. Routine Description:
  131. description-of-function.
  132. Arguments:
  133. hFtpSession -
  134. lpszRemoteFile -
  135. lpszNewFile -
  136. fFailIfExists -
  137. dwFlagsAndAttributes -
  138. dwFlags -
  139. dwContext -
  140. Return Value:
  141. BOOL
  142. --*/
  143. {
  144. DEBUG_ENTER_API((DBG_API,
  145. Bool,
  146. "FtpGetFileW",
  147. "%#x, %wq, %wq, %B, %#x, %#x, %#x",
  148. hFtpSession,
  149. lpszRemoteFile,
  150. lpszNewFile,
  151. fFailIfExists,
  152. dwFlagsAndAttributes,
  153. dwFlags,
  154. dwContext
  155. ));
  156. LPINTERNET_THREAD_INFO lpThreadInfo;
  157. DWORD error;
  158. BOOL success;
  159. DWORD nestingLevel = 0;
  160. HINTERNET hSessionMapped = NULL;
  161. HINTERNET hFileMapped = NULL;
  162. BOOL fDeref = TRUE;
  163. if (!GlobalDataInitialized) {
  164. error = ERROR_INTERNET_NOT_INITIALIZED;
  165. goto done;
  166. }
  167. //
  168. // we need the INTERNET_THREAD_INFO
  169. //
  170. lpThreadInfo = InternetGetThreadInfo();
  171. if (lpThreadInfo == NULL) {
  172. INET_ASSERT(FALSE);
  173. error = ERROR_INTERNET_INTERNAL_ERROR;
  174. goto quit;
  175. }
  176. _InternetIncNestingCount();
  177. nestingLevel = 1;
  178. //
  179. // map the connect handle
  180. //
  181. error = MapHandleToAddress(hFtpSession, (LPVOID *)&hSessionMapped, FALSE);
  182. if ((error != ERROR_SUCCESS) && (hSessionMapped == NULL)) {
  183. goto quit;
  184. }
  185. //
  186. // set the context and handle info and clear last error variables
  187. //
  188. _InternetSetObjectHandle(lpThreadInfo, hFtpSession, hSessionMapped);
  189. _InternetSetContext(lpThreadInfo, dwContext);
  190. _InternetClearLastError(lpThreadInfo);
  191. //
  192. // quit now if the handle is invalid
  193. //
  194. if (error != ERROR_SUCCESS) {
  195. goto quit;
  196. }
  197. //
  198. // validate the handle
  199. //
  200. BOOL isLocal;
  201. BOOL isAsync;
  202. error = RIsHandleLocal(hSessionMapped,
  203. &isLocal,
  204. &isAsync,
  205. TypeFtpConnectHandle
  206. );
  207. if (error != ERROR_SUCCESS) {
  208. goto quit;
  209. }
  210. //
  211. // if we're in the async thread context then we've already validated the
  212. // parameters, so skip this stage
  213. //
  214. if (!lpThreadInfo->IsAsyncWorkerThread
  215. || (lpThreadInfo->NestedRequests > 1)) {
  216. //
  217. // validate parameters
  218. //
  219. if (IsBadStringPtrW(lpszRemoteFile, INTERNET_MAX_PATH_LENGTH + 1)
  220. || (*lpszRemoteFile == L'\0')
  221. || IsBadStringPtrW(lpszNewFile, INTERNET_MAX_PATH_LENGTH + 1)
  222. || (*lpszNewFile == L'\0')
  223. || (((dwFlags & FTP_TRANSFER_TYPE_MASK) != 0)
  224. ? (((dwFlags & FTP_TRANSFER_TYPE_MASK) != FTP_TRANSFER_TYPE_ASCII)
  225. && ((dwFlags & FTP_TRANSFER_TYPE_MASK) != FTP_TRANSFER_TYPE_BINARY))
  226. : FALSE)
  227. || ((dwFlags & ~ALLOWED_FTP_FLAGS) != 0)) {
  228. error = ERROR_INVALID_PARAMETER;
  229. goto quit;
  230. }
  231. //
  232. // use default transfer type if so requested
  233. //
  234. if ((dwFlags & FTP_TRANSFER_TYPE_MASK) == 0) {
  235. dwFlags |= FTP_TRANSFER_TYPE_BINARY;
  236. }
  237. //
  238. // if we're performing async I/O AND this we are not in the context of
  239. // an async worker thread AND the app supplied a non-zero context value
  240. // then we can make an async request
  241. //
  242. if (!lpThreadInfo->IsAsyncWorkerThread
  243. && isAsync
  244. && (dwContext != INTERNET_NO_CALLBACK)) {
  245. //
  246. // create an asynchronous request block (ARB) and copy the parameters
  247. //
  248. // MakeAsyncRequest
  249. CFsm_FtpGetFile * pFsm;
  250. pFsm = new CFsm_FtpGetFile(hFtpSession, dwContext, lpszRemoteFile, lpszNewFile, fFailIfExists,
  251. dwFlagsAndAttributes, dwFlags);
  252. if (pFsm != NULL &&
  253. pFsm->GetError() == ERROR_SUCCESS)
  254. {
  255. error = pFsm->QueueWorkItem();
  256. if ( error == ERROR_IO_PENDING ) {
  257. fDeref = FALSE;
  258. }
  259. }
  260. else
  261. {
  262. error = ERROR_NOT_ENOUGH_MEMORY;
  263. if ( pFsm )
  264. {
  265. error = pFsm->GetError();
  266. delete pFsm;
  267. pFsm = NULL;
  268. }
  269. }
  270. //
  271. // if we're here then ERROR_SUCCESS cannot have been returned from
  272. // the above calls
  273. //
  274. INET_ASSERT(error != ERROR_SUCCESS);
  275. DEBUG_PRINT(FTP,
  276. INFO,
  277. ("processing request asynchronously: error = %d\n",
  278. error
  279. ));
  280. goto quit;
  281. }
  282. }
  283. //
  284. // initialize variables in case of early exit
  285. //
  286. HANDLE hLocalFile;
  287. HINTERNET hRemoteFile;
  288. LPBYTE transferBuffer;
  289. hLocalFile = INVALID_HANDLE_VALUE;
  290. hRemoteFile = NULL;
  291. transferBuffer = NULL;
  292. //
  293. // first off, allocate a buffer for the transfer(s) below. The caller can
  294. // now influence the buffer size used by setting the appropriate option
  295. // for this handle. If we fail to get the value then revert to the default
  296. // size of 4K. We want to reduce the number of RPC calls we make
  297. //
  298. DWORD optionLength;
  299. DWORD transferBufferLength;
  300. optionLength = sizeof(transferBufferLength);
  301. if (!InternetQueryOption(hFtpSession,
  302. INTERNET_OPTION_READ_BUFFER_SIZE,
  303. (LPVOID)&transferBufferLength,
  304. &optionLength
  305. )) {
  306. transferBufferLength = DEFAULT_TRANSFER_BUFFER_LENGTH;
  307. }
  308. transferBuffer = (LPBYTE)ALLOCATE_FIXED_MEMORY(transferBufferLength);
  309. if (transferBuffer == NULL) {
  310. goto last_error_exit;
  311. }
  312. //
  313. // open/create local file
  314. //
  315. hLocalFile = CreateFileW(lpszNewFile,
  316. GENERIC_WRITE,
  317. 0,
  318. NULL,
  319. fFailIfExists ? CREATE_NEW : CREATE_ALWAYS,
  320. dwFlagsAndAttributes | FILE_FLAG_SEQUENTIAL_SCAN,
  321. NULL // need NULL for Win95, handle to file with attributes to copy
  322. );
  323. if (hLocalFile == INVALID_HANDLE_VALUE) {
  324. goto last_error_exit;
  325. }
  326. //
  327. // open file at FTP server
  328. //
  329. hRemoteFile = FtpOpenFileW(hFtpSession,
  330. lpszRemoteFile,
  331. GENERIC_READ,
  332. dwFlags,
  333. dwContext
  334. );
  335. if (hRemoteFile == NULL) {
  336. goto last_error_exit;
  337. }
  338. //
  339. // since we are going under the API, map the file handle
  340. //
  341. error = MapHandleToAddress(hRemoteFile, (LPVOID *)&hFileMapped, FALSE);
  342. if ((error != ERROR_SUCCESS) && (hFileMapped == NULL)) {
  343. goto cleanup;
  344. }
  345. //
  346. // transfer remote file to local (i.e. download it)
  347. //
  348. do {
  349. DWORD bytesRead;
  350. //
  351. // let app invalidate out
  352. //
  353. if (((HANDLE_OBJECT *)hFileMapped)->IsInvalidated()
  354. || ((HANDLE_OBJECT *)hSessionMapped)->IsInvalidated()) {
  355. error = ERROR_INTERNET_OPERATION_CANCELLED;
  356. goto cleanup;
  357. }
  358. success = FtpReadFile(hFileMapped,
  359. transferBuffer,
  360. transferBufferLength,
  361. &bytesRead
  362. );
  363. if (success) {
  364. if (bytesRead != 0) {
  365. DWORD bytesWritten;
  366. success = WriteFile(hLocalFile,
  367. transferBuffer,
  368. bytesRead,
  369. &bytesWritten,
  370. NULL
  371. );
  372. } else {
  373. //
  374. // done
  375. //
  376. error = ERROR_SUCCESS;
  377. goto cleanup;
  378. }
  379. }
  380. } while (success);
  381. last_error_exit:
  382. error = GetLastError();
  383. cleanup:
  384. if (transferBuffer != NULL) {
  385. FREE_MEMORY((HLOCAL)transferBuffer);
  386. }
  387. //
  388. // close local file
  389. //
  390. if (hLocalFile != INVALID_HANDLE_VALUE) {
  391. CloseHandle(hLocalFile);
  392. //
  393. // if we failed, but created the local file then delete it
  394. //
  395. if ((error != ERROR_SUCCESS) && (hLocalFile != INVALID_HANDLE_VALUE)) {
  396. DeleteFileW(lpszNewFile);
  397. }
  398. }
  399. //
  400. // close remote file
  401. //
  402. if (hRemoteFile != NULL) {
  403. _InternetCloseHandle(hRemoteFile);
  404. }
  405. //
  406. // BUGBUG [arthurbi] SetContext should not be called from here,
  407. // InternetCloseHandle should not reset the context as its
  408. // doing right now, and this needs to be investigated more,
  409. // as for now we're workaround this problem by calling SetContext
  410. //
  411. _InternetSetContext(lpThreadInfo, dwContext);
  412. quit:
  413. if (hFileMapped != NULL) {
  414. INET_ASSERT(fDeref);
  415. DereferenceObject((LPVOID)hFileMapped);
  416. }
  417. if (hSessionMapped != NULL && fDeref) {
  418. DereferenceObject((LPVOID)hSessionMapped);
  419. }
  420. _InternetDecNestingCount(nestingLevel);;
  421. done:
  422. if (error != ERROR_SUCCESS) {
  423. SetLastError(error);
  424. success = FALSE;
  425. DEBUG_ERROR(API, error);
  426. } else {
  427. success = TRUE;
  428. }
  429. DEBUG_LEAVE_API(success);
  430. return success;
  431. }
  432. INTERNETAPI_(BOOL) FtpPutFileW(
  433. IN HINTERNET hFtpSession,
  434. IN LPCWSTR lpszLocalFile,
  435. IN LPCWSTR lpszNewRemoteFile,
  436. IN DWORD dwFlags,
  437. IN DWORD_PTR dwContext
  438. )
  439. /*++
  440. Routine Description:
  441. description-of-function.
  442. Arguments:
  443. hFtpSession -
  444. lpszLocalFile -
  445. lpszNewRemoteFile -
  446. dwFlags -
  447. dwContext -
  448. Return Value:
  449. BOOL
  450. --*/
  451. {
  452. DEBUG_ENTER_API((DBG_API,
  453. Bool,
  454. "FtpPutFileW",
  455. "%#x, %wq, %wq, %#x, %#x",
  456. hFtpSession,
  457. lpszLocalFile,
  458. lpszNewRemoteFile,
  459. dwFlags,
  460. dwContext
  461. ));
  462. LPINTERNET_THREAD_INFO lpThreadInfo;
  463. DWORD error;
  464. BOOL success;
  465. DWORD nestingLevel = 0;
  466. HINTERNET hSessionMapped = NULL;
  467. HINTERNET hFileMapped = NULL;
  468. BOOL fDeref = TRUE;
  469. if (!GlobalDataInitialized) {
  470. error = ERROR_INTERNET_NOT_INITIALIZED;
  471. goto done;
  472. }
  473. //
  474. // we need the INTERNET_THREAD_INFO
  475. //
  476. lpThreadInfo = InternetGetThreadInfo();
  477. if (lpThreadInfo == NULL) {
  478. INET_ASSERT(FALSE);
  479. error = ERROR_INTERNET_INTERNAL_ERROR;
  480. goto quit;
  481. }
  482. _InternetIncNestingCount();
  483. nestingLevel = 1;
  484. //
  485. // map the connect handle
  486. //
  487. error = MapHandleToAddress(hFtpSession, (LPVOID *)&hSessionMapped, FALSE);
  488. if ((error != ERROR_SUCCESS) && (hSessionMapped == NULL)) {
  489. goto quit;
  490. }
  491. //
  492. // set the context and handle info and clear last error variables
  493. //
  494. _InternetSetObjectHandle(lpThreadInfo, hFtpSession, hSessionMapped);
  495. _InternetSetContext(lpThreadInfo, dwContext);
  496. _InternetClearLastError(lpThreadInfo);
  497. //
  498. // quit now if the handle is invalid
  499. //
  500. if (error != ERROR_SUCCESS) {
  501. goto quit;
  502. }
  503. //
  504. // validate the handle
  505. //
  506. BOOL isLocal;
  507. BOOL isAsync;
  508. error = RIsHandleLocal(hSessionMapped,
  509. &isLocal,
  510. &isAsync,
  511. TypeFtpConnectHandle
  512. );
  513. if (error != ERROR_SUCCESS) {
  514. goto quit;
  515. }
  516. //
  517. // if we're in the async thread context then we've already validated the
  518. // parameters, so skip this stage
  519. //
  520. if (!lpThreadInfo->IsAsyncWorkerThread
  521. || (lpThreadInfo->NestedRequests > 1)) {
  522. //
  523. // validate parameters
  524. //
  525. if (IsBadStringPtrW(lpszNewRemoteFile, INTERNET_MAX_PATH_LENGTH + 1)
  526. || (*lpszNewRemoteFile == L'\0')
  527. || IsBadStringPtrW(lpszLocalFile, INTERNET_MAX_PATH_LENGTH + 1)
  528. || (*lpszLocalFile == L'\0')
  529. || (((dwFlags & FTP_TRANSFER_TYPE_MASK) != 0)
  530. ? (((dwFlags & FTP_TRANSFER_TYPE_MASK) != FTP_TRANSFER_TYPE_ASCII)
  531. && ((dwFlags & FTP_TRANSFER_TYPE_MASK) != FTP_TRANSFER_TYPE_BINARY))
  532. : FALSE)
  533. || ((dwFlags & ~ALLOWED_FTP_FLAGS) != 0)) {
  534. error = ERROR_INVALID_PARAMETER;
  535. goto quit;
  536. }
  537. //
  538. // use default transfer type if so requested
  539. //
  540. if ((dwFlags & FTP_TRANSFER_TYPE_MASK) == 0) {
  541. dwFlags |= FTP_TRANSFER_TYPE_BINARY;
  542. }
  543. // in offline mode modifications are disallowed
  544. // someday we will do internet briefcase but not today
  545. if ((((INTERNET_CONNECT_HANDLE_OBJECT *)hSessionMapped)->
  546. GetInternetOpenFlags() | dwFlags) &
  547. INTERNET_FLAG_OFFLINE) {
  548. error = ERROR_WRITE_PROTECT;
  549. goto quit;
  550. }
  551. //
  552. // if we're performing async I/O AND this we are not in the context of
  553. // an async worker thread AND the app supplied a non-zero context value
  554. // then we can make an async request
  555. //
  556. if (!lpThreadInfo->IsAsyncWorkerThread
  557. && isAsync
  558. && (dwContext != INTERNET_NO_CALLBACK)) {
  559. // MakeAsyncRequest
  560. CFsm_FtpPutFile * pFsm;
  561. pFsm = new CFsm_FtpPutFile(hFtpSession, dwContext, lpszLocalFile, lpszNewRemoteFile, dwFlags);
  562. if (pFsm != NULL &&
  563. pFsm->GetError() == ERROR_SUCCESS)
  564. {
  565. error = pFsm->QueueWorkItem();
  566. if ( error == ERROR_IO_PENDING ) {
  567. fDeref = FALSE;
  568. }
  569. }
  570. else
  571. {
  572. error = ERROR_NOT_ENOUGH_MEMORY;
  573. if ( pFsm )
  574. {
  575. error = pFsm->GetError();
  576. delete pFsm;
  577. pFsm = NULL;
  578. }
  579. }
  580. //
  581. // if we're here then ERROR_SUCCESS cannot have been returned from
  582. // the above calls
  583. //
  584. INET_ASSERT(error != ERROR_SUCCESS);
  585. DEBUG_PRINT(FTP,
  586. INFO,
  587. ("processing request asynchronously: error = %d\n",
  588. error
  589. ));
  590. goto quit;
  591. }
  592. }
  593. //
  594. // initialize variables in case of early exit
  595. //
  596. HANDLE hLocalFile;
  597. HINTERNET hRemoteFile;
  598. LPBYTE transferBuffer;
  599. hLocalFile = INVALID_HANDLE_VALUE;
  600. hRemoteFile = NULL;
  601. transferBuffer = NULL;
  602. //
  603. // first off, allocate a buffer for the transfer(s) below. The caller can
  604. // now influence the buffer size used by setting the appropriate option
  605. // for this handle. If we fail to get the value then revert to the default
  606. // size of 4K. We want to reduce the number of RPC calls we make
  607. //
  608. DWORD optionLength;
  609. DWORD transferBufferLength;
  610. optionLength = sizeof(transferBufferLength);
  611. if (!InternetQueryOption(hFtpSession,
  612. INTERNET_OPTION_WRITE_BUFFER_SIZE,
  613. (LPVOID)&transferBufferLength,
  614. &optionLength
  615. )) {
  616. transferBufferLength = DEFAULT_TRANSFER_BUFFER_LENGTH;
  617. }
  618. transferBuffer = (LPBYTE)ALLOCATE_FIXED_MEMORY(transferBufferLength);
  619. if (transferBuffer == NULL) {
  620. goto last_error_exit;
  621. }
  622. //
  623. // open local file
  624. //
  625. hLocalFile = CreateFileW(lpszLocalFile,
  626. GENERIC_READ,
  627. FILE_SHARE_READ,
  628. NULL,
  629. OPEN_EXISTING,
  630. FILE_FLAG_SEQUENTIAL_SCAN,
  631. NULL // need NULL for Win95, handle to file with attributes to copy
  632. );
  633. if (hLocalFile == INVALID_HANDLE_VALUE) {
  634. goto last_error_exit;
  635. }
  636. //
  637. // open file at FTP server
  638. //
  639. hRemoteFile = FtpOpenFileW(hFtpSession,
  640. lpszNewRemoteFile,
  641. GENERIC_WRITE,
  642. dwFlags,
  643. dwContext
  644. );
  645. if (hRemoteFile == NULL) {
  646. goto last_error_exit;
  647. }
  648. //
  649. // since we are going under the API, map the file handle
  650. //
  651. error = MapHandleToAddress(hRemoteFile, (LPVOID *)&hFileMapped, FALSE);
  652. if ((error != ERROR_SUCCESS) && (hFileMapped == NULL)) {
  653. goto cleanup;
  654. }
  655. //
  656. // transfer local file to remote (i.e. upload it)
  657. //
  658. do {
  659. DWORD bytesRead;
  660. //
  661. // let app invalidate out
  662. //
  663. if (((HANDLE_OBJECT *)hFileMapped)->IsInvalidated()
  664. || ((HANDLE_OBJECT *)hSessionMapped)->IsInvalidated()) {
  665. error = ERROR_INTERNET_OPERATION_CANCELLED;
  666. goto cleanup;
  667. }
  668. success = ReadFile(hLocalFile,
  669. transferBuffer,
  670. transferBufferLength,
  671. &bytesRead,
  672. NULL
  673. );
  674. if (success) {
  675. if (bytesRead != 0) {
  676. DWORD bytesWritten;
  677. success = FtpWriteFile(hFileMapped,
  678. transferBuffer,
  679. bytesRead,
  680. &bytesWritten
  681. );
  682. } else {
  683. //
  684. // ensure last error is really no error
  685. //
  686. error = ERROR_SUCCESS;
  687. goto cleanup;
  688. }
  689. }
  690. } while (success);
  691. last_error_exit:
  692. error = GetLastError();
  693. cleanup:
  694. if (transferBuffer != NULL) {
  695. FREE_MEMORY((HLOCAL)transferBuffer);
  696. }
  697. //
  698. // close local file
  699. //
  700. if (hLocalFile != INVALID_HANDLE_VALUE) {
  701. CloseHandle(hLocalFile);
  702. }
  703. //
  704. // close remote file
  705. //
  706. if (hRemoteFile != NULL) {
  707. _InternetCloseHandle(hRemoteFile);
  708. }
  709. //
  710. // BUGBUG [arthurbi] SetContext should not be called from here,
  711. // InternetCloseHandle should not reset the context as its
  712. // doing right now, and this needs to be investigated more,
  713. // as for now we're workaround this problem by calling SetContext
  714. //
  715. _InternetSetContext(lpThreadInfo, dwContext);
  716. quit:
  717. SetLastError(ERROR_SUCCESS); // a-thkesa. from win CE code BUG: WinSE 23985
  718. if (hFileMapped != NULL) {
  719. DereferenceObject((LPVOID)hFileMapped);
  720. }
  721. if (hSessionMapped != NULL && fDeref) {
  722. DereferenceObject((LPVOID)hSessionMapped);
  723. }
  724. _InternetDecNestingCount(nestingLevel);;
  725. done:
  726. // a-thkesa Becuase 23985 fix returns ERROR_INTERNET_EXTENDED_ERROR
  727. if(ERROR_INTERNET_EXTENDED_ERROR == GetLastError()){
  728. success = FALSE;
  729. }
  730. else if (error != ERROR_SUCCESS) {
  731. SetLastError(error);
  732. success = FALSE;
  733. DEBUG_ERROR(API, error);
  734. } else {
  735. success = TRUE;
  736. }
  737. DEBUG_LEAVE_API(success);
  738. return success;
  739. }
  740. INTERNETAPI_(BOOL) FtpGetFileEx(
  741. IN HINTERNET hFtpSession,
  742. IN LPCSTR lpszRemoteFile,
  743. IN LPCWSTR lpszNewFile,
  744. IN BOOL fFailIfExists,
  745. IN DWORD dwFlagsAndAttributes,
  746. IN DWORD dwFlags,
  747. IN DWORD_PTR dwContext
  748. )
  749. {
  750. DEBUG_ENTER_API((DBG_API,
  751. Bool,
  752. "FtpGetFileEx",
  753. "%#x, %sq, %wq, %B, %#x, %#x, %#x",
  754. hFtpSession,
  755. lpszRemoteFile,
  756. lpszNewFile,
  757. fFailIfExists,
  758. dwFlagsAndAttributes,
  759. dwFlags,
  760. dwContext
  761. ));
  762. DWORD cc, dwErr = ERROR_SUCCESS;
  763. BOOL fResult = FALSE;
  764. PWSTR pwszRemoteFile = NULL;
  765. cc = MultiByteToWideChar(CP_ACP, 0, lpszRemoteFile, -1, NULL, 0);
  766. pwszRemoteFile = (LPWSTR)ALLOCATE_FIXED_MEMORY((cc*sizeof(WCHAR)));
  767. if (!pwszRemoteFile)
  768. {
  769. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  770. goto cleanup;
  771. }
  772. MultiByteToWideChar(CP_ACP, 0, lpszRemoteFile, -1, pwszRemoteFile, cc);
  773. fResult = FtpGetFileW(hFtpSession,pwszRemoteFile,lpszNewFile,fFailIfExists,
  774. dwFlagsAndAttributes,dwFlags,dwContext);
  775. cleanup:
  776. if (pwszRemoteFile)
  777. {
  778. FREE_MEMORY(pwszRemoteFile);
  779. }
  780. if (dwErr!=ERROR_SUCCESS)
  781. {
  782. SetLastError(dwErr);
  783. DEBUG_ERROR(API, dwErr);
  784. }
  785. DEBUG_LEAVE_API(fResult);
  786. return fResult;
  787. }
  788. INTERNETAPI_(BOOL) FtpPutFileEx(
  789. IN HINTERNET hFtpSession,
  790. IN LPCWSTR lpszLocalFile,
  791. IN LPCSTR lpszNewRemoteFile,
  792. IN DWORD dwFlags,
  793. IN DWORD_PTR dwContext
  794. )
  795. {
  796. DEBUG_ENTER_API((DBG_API,
  797. Bool,
  798. "FtpPutFileEx",
  799. "%#x, %wq, %sq, %#x, %#x",
  800. hFtpSession,
  801. lpszLocalFile,
  802. lpszNewRemoteFile,
  803. dwFlags,
  804. dwContext
  805. ));
  806. DWORD cc, dwErr = ERROR_SUCCESS;
  807. BOOL fResult = FALSE;
  808. PWSTR pwszRemoteFile = NULL;
  809. cc = MultiByteToWideChar(CP_ACP, 0, lpszNewRemoteFile, -1, NULL, 0);
  810. pwszRemoteFile = (LPWSTR)ALLOCATE_FIXED_MEMORY((cc*sizeof(WCHAR)));
  811. if (!pwszRemoteFile)
  812. {
  813. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  814. goto cleanup;
  815. }
  816. MultiByteToWideChar(CP_ACP, 0, lpszNewRemoteFile, -1, pwszRemoteFile, cc);
  817. fResult = FtpPutFileW(hFtpSession,lpszLocalFile,pwszRemoteFile,dwFlags,dwContext);
  818. cleanup:
  819. if (pwszRemoteFile)
  820. {
  821. FREE_MEMORY(pwszRemoteFile);
  822. }
  823. if (dwErr!=ERROR_SUCCESS)
  824. {
  825. SetLastError(dwErr);
  826. DEBUG_ERROR(API, dwErr);
  827. }
  828. DEBUG_LEAVE_API(fResult);
  829. return fResult;
  830. }
  831. INTERNETAPI_(BOOL) FtpDeleteFileW(
  832. IN HINTERNET hFtpSession,
  833. IN LPCWSTR lpszFileName
  834. )
  835. /*++
  836. Routine Description:
  837. description-of-function.
  838. Arguments:
  839. hFtpSession -
  840. lpszFileName -
  841. Return Value:
  842. BOOL
  843. --*/
  844. {
  845. DEBUG_ENTER_API((DBG_API,
  846. Bool,
  847. "FtpDeleteFileW",
  848. "%#x, %wq",
  849. hFtpSession,
  850. lpszFileName
  851. ));
  852. DWORD dwErr = ERROR_SUCCESS;
  853. BOOL fResult = FALSE;
  854. MEMORYPACKET mpFile;
  855. if (!lpszFileName
  856. || (IsBadStringPtrW(lpszFileName, INTERNET_MAX_PATH_LENGTH + 1))
  857. || (*lpszFileName == L'\0'))
  858. {
  859. dwErr = ERROR_INVALID_PARAMETER;
  860. goto cleanup;
  861. }
  862. ALLOC_MB(lpszFileName,0,mpFile);
  863. if (!mpFile.psStr)
  864. {
  865. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  866. goto cleanup;
  867. }
  868. UNICODE_TO_ANSI(lpszFileName,mpFile);
  869. fResult = FtpDeleteFileA(hFtpSession,mpFile.psStr);
  870. cleanup:
  871. if (dwErr!=ERROR_SUCCESS)
  872. {
  873. SetLastError(dwErr);
  874. DEBUG_ERROR(API, dwErr);
  875. }
  876. DEBUG_LEAVE_API(fResult);
  877. return fResult;
  878. }
  879. INTERNETAPI_(BOOL) FtpRenameFileW(
  880. IN HINTERNET hFtpSession,
  881. IN LPCWSTR lpszExisting,
  882. IN LPCWSTR lpszNew
  883. )
  884. /*++
  885. Routine Description:
  886. description-of-function.
  887. Arguments:
  888. hFtpSession -
  889. lpszExisting -
  890. lpszNew -
  891. Return Value:
  892. BOOL
  893. --*/
  894. {
  895. DEBUG_ENTER_API((DBG_API,
  896. Bool,
  897. "FtpRenameFileW",
  898. "%#x, %wq, %wq",
  899. hFtpSession,
  900. lpszExisting,
  901. lpszNew
  902. ));
  903. DWORD dwErr = ERROR_SUCCESS;
  904. BOOL fResult = FALSE;
  905. MEMORYPACKET mpExisting, mpNew;
  906. if (!(lpszExisting && lpszNew)
  907. || (IsBadStringPtrW(lpszExisting, INTERNET_MAX_PATH_LENGTH + 1))
  908. || (IsBadStringPtrW(lpszNew, INTERNET_MAX_PATH_LENGTH + 1)))
  909. {
  910. dwErr = ERROR_INVALID_PARAMETER;
  911. goto cleanup;
  912. }
  913. ALLOC_MB(lpszExisting,0,mpExisting);
  914. ALLOC_MB(lpszNew,0,mpNew);
  915. if (!(mpExisting.psStr && mpNew.psStr))
  916. {
  917. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  918. goto cleanup;
  919. }
  920. UNICODE_TO_ANSI(lpszExisting,mpExisting);
  921. UNICODE_TO_ANSI(lpszNew,mpNew);
  922. fResult = FtpRenameFileA(hFtpSession,mpExisting.psStr,mpNew.psStr);
  923. cleanup:
  924. if (dwErr!=ERROR_SUCCESS)
  925. {
  926. SetLastError(dwErr);
  927. DEBUG_ERROR(API, dwErr);
  928. }
  929. DEBUG_LEAVE_API(fResult);
  930. return fResult;
  931. }
  932. INTERNETAPI_(HINTERNET) FtpOpenFileW(
  933. IN HINTERNET hFtpSession,
  934. IN LPCWSTR lpszFileName,
  935. IN DWORD dwAccess,
  936. IN DWORD dwFlags,
  937. IN DWORD_PTR dwContext
  938. )
  939. /*++
  940. Routine Description:
  941. description-of-function.
  942. Arguments:
  943. hFtpSession -
  944. lpszFileName -
  945. dwAccess -
  946. dwFlags -
  947. dwContext -
  948. Return Value:
  949. HINTERNET
  950. --*/
  951. {
  952. DEBUG_ENTER_API((DBG_API,
  953. Handle,
  954. "FtpOpenFileW",
  955. "%#x, %wq, %#x, %#x, %#x",
  956. hFtpSession,
  957. lpszFileName,
  958. dwAccess,
  959. dwFlags,
  960. dwContext
  961. ));
  962. DWORD dwErr = ERROR_SUCCESS;
  963. HINTERNET hInternet = NULL;
  964. MEMORYPACKET mpFile;
  965. if (!lpszFileName
  966. || (IsBadStringPtrW(lpszFileName, INTERNET_MAX_PATH_LENGTH + 1)))
  967. {
  968. dwErr = ERROR_INVALID_PARAMETER;
  969. goto cleanup;
  970. }
  971. ALLOC_MB(lpszFileName,0,mpFile);
  972. if (!mpFile.psStr)
  973. {
  974. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  975. goto cleanup;
  976. }
  977. UNICODE_TO_ANSI(lpszFileName,mpFile);
  978. hInternet = FtpOpenFileA(hFtpSession,mpFile.psStr,dwAccess,dwFlags,dwContext);
  979. cleanup:
  980. if (dwErr!=ERROR_SUCCESS)
  981. {
  982. SetLastError(dwErr);
  983. DEBUG_ERROR(API, dwErr);
  984. }
  985. DEBUG_LEAVE_API(hInternet);
  986. return hInternet;
  987. }
  988. INTERNETAPI_(BOOL) FtpCreateDirectoryW(
  989. IN HINTERNET hFtpSession,
  990. IN LPCWSTR pwszDir
  991. )
  992. /*++
  993. Routine Description:
  994. description-of-function.
  995. Arguments:
  996. hFtpSession -
  997. pwszDir -
  998. Return Value:
  999. BOOL
  1000. --*/
  1001. {
  1002. DEBUG_ENTER_API((DBG_API,
  1003. Bool,
  1004. "FtpCreateDirectoryW",
  1005. "%#x, %wq",
  1006. hFtpSession,
  1007. pwszDir
  1008. ));
  1009. DWORD dwErr = ERROR_SUCCESS;
  1010. BOOL fResult = FALSE;
  1011. MEMORYPACKET mpDir;
  1012. if (!pwszDir
  1013. || (IsBadStringPtrW(pwszDir, INTERNET_MAX_PATH_LENGTH + 1)
  1014. || (*pwszDir == L'\0')))
  1015. {
  1016. dwErr = ERROR_INVALID_PARAMETER;
  1017. goto cleanup;
  1018. }
  1019. ALLOC_MB(pwszDir,0,mpDir);
  1020. if (!mpDir.psStr)
  1021. {
  1022. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1023. goto cleanup;
  1024. }
  1025. UNICODE_TO_ANSI(pwszDir,mpDir);
  1026. fResult = FtpCreateDirectoryA(hFtpSession,mpDir.psStr);
  1027. cleanup:
  1028. if (dwErr!=ERROR_SUCCESS)
  1029. {
  1030. SetLastError(dwErr);
  1031. DEBUG_ERROR(API, dwErr);
  1032. }
  1033. DEBUG_LEAVE_API(fResult);
  1034. return fResult;
  1035. }
  1036. INTERNETAPI_(BOOL) FtpRemoveDirectoryW(
  1037. IN HINTERNET hFtpSession,
  1038. IN LPCWSTR pwszDir
  1039. )
  1040. /*++
  1041. Routine Description:
  1042. description-of-function.
  1043. Arguments:
  1044. hFtpSession -
  1045. pwszDir -
  1046. Return Value:
  1047. BOOL
  1048. --*/
  1049. {
  1050. DEBUG_ENTER_API((DBG_API,
  1051. Bool,
  1052. "FtpRemoveDirectoryW",
  1053. "%#x, %wq",
  1054. hFtpSession,
  1055. pwszDir
  1056. ));
  1057. DWORD dwErr = ERROR_SUCCESS;
  1058. BOOL fResult = FALSE;
  1059. MEMORYPACKET mpDir;
  1060. if (!pwszDir
  1061. || (IsBadStringPtrW(pwszDir, INTERNET_MAX_PATH_LENGTH + 1)))
  1062. {
  1063. dwErr = ERROR_INVALID_PARAMETER;
  1064. goto cleanup;
  1065. }
  1066. ALLOC_MB(pwszDir,0,mpDir);
  1067. if (!mpDir.psStr)
  1068. {
  1069. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1070. goto cleanup;
  1071. }
  1072. UNICODE_TO_ANSI(pwszDir,mpDir);
  1073. fResult = FtpRemoveDirectoryA(hFtpSession,mpDir.psStr);
  1074. cleanup:
  1075. if (dwErr!=ERROR_SUCCESS)
  1076. {
  1077. SetLastError(dwErr);
  1078. DEBUG_ERROR(API, dwErr);
  1079. }
  1080. DEBUG_LEAVE_API(fResult);
  1081. return fResult;
  1082. }
  1083. INTERNETAPI_(BOOL) FtpSetCurrentDirectoryW(
  1084. IN HINTERNET hFtpSession,
  1085. IN LPCWSTR pwszDir
  1086. )
  1087. /*++
  1088. Routine Description:
  1089. description-of-function.
  1090. Arguments:
  1091. hFtpSession -
  1092. pwszDir -
  1093. Return Value:
  1094. BOOL
  1095. --*/
  1096. {
  1097. DEBUG_ENTER_API((DBG_API,
  1098. Bool,
  1099. "FtpSetCurrentDirectoryW",
  1100. "%#x, %wq",
  1101. hFtpSession,
  1102. pwszDir
  1103. ));
  1104. DWORD dwErr = ERROR_SUCCESS;
  1105. BOOL fResult = FALSE;
  1106. MEMORYPACKET mpDir;
  1107. if (!pwszDir
  1108. || (IsBadStringPtrW(pwszDir, INTERNET_MAX_PATH_LENGTH + 1)))
  1109. {
  1110. dwErr = ERROR_INVALID_PARAMETER;
  1111. goto cleanup;
  1112. }
  1113. ALLOC_MB(pwszDir,0,mpDir);
  1114. if (!mpDir.psStr)
  1115. {
  1116. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1117. goto cleanup;
  1118. }
  1119. UNICODE_TO_ANSI(pwszDir,mpDir);
  1120. fResult = FtpSetCurrentDirectoryA(hFtpSession,mpDir.psStr);
  1121. cleanup:
  1122. if (dwErr!=ERROR_SUCCESS)
  1123. {
  1124. SetLastError(dwErr);
  1125. DEBUG_ERROR(API, dwErr);
  1126. }
  1127. DEBUG_LEAVE_API(fResult);
  1128. return fResult;
  1129. }
  1130. INTERNETAPI_(BOOL) FtpGetCurrentDirectoryW(
  1131. IN HINTERNET hFtpSession,
  1132. OUT LPWSTR lpszCurrentDirectory,
  1133. IN OUT LPDWORD lpdwCurrentDirectory
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. description-of-function.
  1138. Arguments:
  1139. hFtpSession -
  1140. lpszCurrentDirectory -
  1141. lpdwCurrentDirectory -
  1142. Return Value:
  1143. BOOL
  1144. --*/
  1145. {
  1146. DEBUG_ENTER_API((DBG_API,
  1147. Bool,
  1148. "FtpGetCurrentDirectoryW",
  1149. "%#x, %#x, %#x [%d]",
  1150. hFtpSession,
  1151. lpszCurrentDirectory,
  1152. lpdwCurrentDirectory,
  1153. lpdwCurrentDirectory ? *lpdwCurrentDirectory : 0
  1154. ));
  1155. DWORD dwErr = ERROR_SUCCESS;
  1156. BOOL fResult = FALSE;
  1157. MEMORYPACKET mpDir;
  1158. if (!lpdwCurrentDirectory
  1159. || IsBadWritePtr(lpdwCurrentDirectory, sizeof(*lpdwCurrentDirectory))
  1160. || (lpszCurrentDirectory && IsBadWritePtr(lpszCurrentDirectory, *lpdwCurrentDirectory)))
  1161. {
  1162. dwErr = ERROR_INVALID_PARAMETER;
  1163. goto cleanup;
  1164. }
  1165. if (lpszCurrentDirectory)
  1166. {
  1167. mpDir.dwSize = mpDir.dwAlloc = *lpdwCurrentDirectory*sizeof(CHAR);
  1168. mpDir.psStr = (LPSTR)ALLOC_BYTES(mpDir.dwAlloc);
  1169. if (!mpDir.psStr)
  1170. {
  1171. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1172. goto cleanup;
  1173. }
  1174. }
  1175. else
  1176. {
  1177. *lpdwCurrentDirectory = 0;
  1178. }
  1179. fResult = FtpGetCurrentDirectoryA(hFtpSession,mpDir.psStr,&mpDir.dwSize);
  1180. if (fResult)
  1181. {
  1182. DWORD cc = MultiByteToWideChar(CP_ACP, 0, mpDir.psStr, -1, NULL, 0);
  1183. if (*lpdwCurrentDirectory>=cc)
  1184. {
  1185. *lpdwCurrentDirectory = MultiByteToWideChar(CP_ACP, 0, mpDir.psStr, -1,
  1186. lpszCurrentDirectory, *lpdwCurrentDirectory);
  1187. }
  1188. else
  1189. {
  1190. *lpdwCurrentDirectory = cc*sizeof(WCHAR);
  1191. dwErr = ERROR_INSUFFICIENT_BUFFER;
  1192. fResult = FALSE;
  1193. }
  1194. }
  1195. else
  1196. {
  1197. if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
  1198. {
  1199. *lpdwCurrentDirectory = mpDir.dwSize*sizeof(WCHAR);
  1200. }
  1201. }
  1202. cleanup:
  1203. if (dwErr!=ERROR_SUCCESS)
  1204. {
  1205. SetLastError(dwErr);
  1206. DEBUG_ERROR(API, dwErr);
  1207. }
  1208. DEBUG_LEAVE_API(fResult);
  1209. return fResult;
  1210. }
  1211. INTERNETAPI_(BOOL) FtpCommandW(
  1212. IN HINTERNET hFtpSession,
  1213. IN BOOL fExpectResponse,
  1214. IN DWORD dwFlags,
  1215. IN LPCWSTR lpszCommand,
  1216. IN DWORD_PTR dwContext,
  1217. OUT HINTERNET *phFtpCommand OPTIONAL
  1218. )
  1219. /*++
  1220. Routine Description:
  1221. description-of-function.
  1222. Arguments:
  1223. hFtpSession -
  1224. fExpectResponse -
  1225. dwFlags -
  1226. lpszCommand -
  1227. dwContext -
  1228. phFtpCommand -
  1229. Return Value:
  1230. BOOL
  1231. --*/
  1232. {
  1233. DEBUG_ENTER_API((DBG_API,
  1234. Bool,
  1235. "FtpCommandW",
  1236. "%#x, %B, %#x, %wq, %#x, %x",
  1237. hFtpSession,
  1238. fExpectResponse,
  1239. dwFlags,
  1240. lpszCommand,
  1241. dwContext,
  1242. phFtpCommand
  1243. ));
  1244. MEMORYPACKET mpCommand;
  1245. DWORD dwErr = ERROR_SUCCESS;
  1246. BOOL fResult = FALSE;
  1247. if (!lpszCommand
  1248. || IsBadStringPtrW(lpszCommand, INTERNET_MAX_URL_LENGTH)
  1249. || (phFtpCommand && IsBadWritePtr(phFtpCommand, sizeof(*phFtpCommand))))
  1250. {
  1251. dwErr = ERROR_INVALID_PARAMETER;
  1252. goto cleanup;
  1253. }
  1254. ALLOC_MB(lpszCommand, 0, mpCommand);
  1255. if (!mpCommand.psStr)
  1256. {
  1257. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1258. goto cleanup;
  1259. }
  1260. UNICODE_TO_ANSI(lpszCommand, mpCommand);
  1261. fResult = FtpCommandA(hFtpSession, fExpectResponse, dwFlags, mpCommand.psStr, dwContext, phFtpCommand);
  1262. cleanup:
  1263. if (dwErr!=ERROR_SUCCESS)
  1264. {
  1265. SetLastError(dwErr);
  1266. DEBUG_ERROR(API, dwErr);
  1267. }
  1268. DEBUG_LEAVE_API(fResult);
  1269. return fResult;
  1270. }