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.

1636 lines
36 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: xfer.cxx
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "precomp.h"
  11. #include "ssdp.h"
  12. error_status_t
  13. MapWinsockErrorToWin32(
  14. error_status_t status
  15. );
  16. DWORD
  17. MdWork(
  18. WCHAR *arg
  19. );
  20. DWORD
  21. ReportFileError( DWORD mc,
  22. WCHAR * file,
  23. DWORD error
  24. )
  25. {
  26. DWORD dwEventStatus = 0;
  27. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  28. if (!dwEventStatus)
  29. {
  30. TCHAR ErrorDescription[ERROR_DESCRIPTION_LENGTH];
  31. if (!FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS |
  32. FORMAT_MESSAGE_FROM_SYSTEM,
  33. 0, // ignored
  34. error,
  35. 0, // try default language ids
  36. ErrorDescription,
  37. ERROR_DESCRIPTION_LENGTH,
  38. 0 // ignored
  39. ))
  40. {
  41. wsprintf(ErrorDescription, L"0x%x", ErrorDescription);
  42. }
  43. WCHAR * Strings[2];
  44. Strings[0] = file;
  45. Strings[1] = ErrorDescription;
  46. dwEventStatus = EventLog.ReportError(CAT_IRXFER, mc, 2, Strings);
  47. }
  48. return dwEventStatus;
  49. }
  50. #if 0
  51. DWORD FILE_TRANSFER::Init()
  52. {
  53. DWORD Status = 0;
  54. ActiveTransferMutex = new MUTEX( &Status );
  55. if (!ActiveTransferMutex)
  56. {
  57. Status = ERROR_NOT_ENOUGH_MEMORY;
  58. }
  59. if (Status)
  60. {
  61. goto lErr;
  62. }
  63. ArrayLength = 2;
  64. ActiveTransfers = new PFILE_TRANSFER[ ArrayLength ];
  65. if (!ActiveTransfers)
  66. {
  67. Status = ERROR_NOT_ENOUGH_MEMORY;
  68. goto lErr;
  69. }
  70. memset(ActiveTransfers, 0, sizeof(PFILE_TRANSFER) * ArrayLength);
  71. return 0;
  72. lErr:
  73. delete ActiveTransfers;
  74. delete ActiveTransferMutex;
  75. return Status;
  76. }
  77. #endif
  78. FILE_TRANSFER::FILE_TRANSFER( )
  79. {
  80. _refs = 1;
  81. _event = 0;
  82. _socket = INVALID_SOCKET;
  83. _cookie = 0;
  84. m_StopListening=FALSE;
  85. // for sock.c
  86. _fWriteable = FALSE;
  87. // for xfer.c
  88. _dataFileRecv.hFile = INVALID_HANDLE_VALUE;
  89. // for progress.c
  90. _fCancelled = FALSE;
  91. _fInUiReceiveList = FALSE;
  92. _CurrentPercentage = 0;
  93. _files = 0;
  94. _mutex = 0;
  95. _dataXferRecv.dwFileSent = 0;
  96. DbgLog2(SEV_INFO, "[0] %p: refs = %d\n", this, _refs);
  97. }
  98. FILE_TRANSFER::~FILE_TRANSFER()
  99. {
  100. if (_socket != INVALID_SOCKET)
  101. {
  102. //
  103. // Drain any remaining receive data to ensure our sent data is sent across the link.
  104. //
  105. #if 0
  106. int bytes;
  107. do
  108. {
  109. bytes = recv( _socket, (char *) _buffer, cbSOCK_BUFFER_SIZE, 0 );
  110. }
  111. while ( bytes != 0 && bytes != SOCKET_ERROR );
  112. #endif
  113. closesocket( _socket );
  114. _socket = INVALID_SOCKET;
  115. }
  116. if (_event)
  117. {
  118. CloseHandle( _event );
  119. _event = 0;
  120. }
  121. if (_fInUiReceiveList)
  122. {
  123. ReceiveFinished( rpcBinding, _cookie, 0 );
  124. }
  125. DeleteCriticalSection(&m_Lock);
  126. }
  127. unsigned long __stdcall
  128. SendFilesWrapper( PVOID arg )
  129. {
  130. PFILE_TRANSFER(arg)->Send();
  131. return 0;
  132. }
  133. #if 0
  134. BOOL
  135. FILE_TRANSFER::Shutdown()
  136. {
  137. unsigned i;
  138. if (IrFileTransfer1 != NULL) {
  139. IrFileTransfer1->StopListening();
  140. }
  141. if (IrFileTransfer2 != NULL) {
  142. IrFileTransfer2->StopListening();
  143. }
  144. do
  145. {
  146. for (i=0; i < ArrayLength; ++i)
  147. {
  148. if (ActiveTransfers[i])
  149. {
  150. Sleep(1000);
  151. break;
  152. }
  153. }
  154. }
  155. while ( i < ArrayLength );
  156. return TRUE;
  157. }
  158. BOOL
  159. FILE_TRANSFER::AreThereActiveTransfers()
  160. {
  161. CLAIM_MUTEX Lock(ActiveTransferMutex);
  162. unsigned i;
  163. for (i=0; i < ArrayLength; ++i)
  164. {
  165. if (ActiveTransfers[i] &&
  166. ActiveTransfers[i]->_state != ACCEPTING)
  167. {
  168. return TRUE;
  169. }
  170. }
  171. return FALSE;
  172. }
  173. #endif
  174. void
  175. FILE_TRANSFER::BeginSend(
  176. DWORD DeviceId,
  177. OBEX_DEVICE_TYPE DeviceType,
  178. error_status_t * pStatus,
  179. FAILURE_LOCATION * pLocation
  180. )
  181. {
  182. DWORD status;
  183. DWORD dwFiles = 0L;
  184. DWORD dwFolders = 0L;
  185. __int64 dwTotalSize = 0L;
  186. status = Sock_EstablishConnection( DeviceId,DeviceType );
  187. if( status )
  188. {
  189. *pLocation = locConnect;
  190. goto lExit;
  191. }
  192. status = _GetObjListStats( _files, &dwFiles, &dwFolders, &dwTotalSize );
  193. if (status)
  194. {
  195. *pLocation = locFileOpen;
  196. goto lExit;
  197. }
  198. _dataXferRecv.dwTotalSize = (DWORD) dwTotalSize;
  199. if( 0 == dwFiles && 0 == dwFolders )
  200. goto lExit; // nothing to send
  201. status = Obex_Connect( dwTotalSize );
  202. if (status)
  203. {
  204. *pLocation = locConnect;
  205. goto lExit;
  206. }
  207. _Send_StartXfer( dwTotalSize, 0 );
  208. DWORD ThreadId;
  209. HANDLE ThreadHandle;
  210. ThreadHandle = CreateThread( 0,
  211. 0,
  212. SendFilesWrapper,
  213. this,
  214. 0,
  215. &ThreadId
  216. );
  217. if (!ThreadHandle)
  218. {
  219. *pLocation = locStartup;
  220. status = GetLastError();
  221. goto lExit;
  222. }
  223. CloseHandle( ThreadHandle );
  224. lExit:
  225. if (status)
  226. {
  227. DecrementRefCount();
  228. }
  229. *pStatus = status;
  230. }
  231. void
  232. FILE_TRANSFER::Send()
  233. {
  234. error_status_t status = 0;
  235. wchar_t * szObj;
  236. //
  237. // Protect ourselves from login or logout notifications while using the token.
  238. //
  239. {
  240. CLAIM_MUTEX Lock( g_Mutex );
  241. if (g_UserToken == 0)
  242. {
  243. //
  244. // the send was aborted due to logging out.
  245. //
  246. return;
  247. }
  248. if (!ImpersonateLoggedOnUser(g_UserToken))
  249. {
  250. DWORD dwEventStatus = 0;
  251. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  252. if (!dwEventStatus)
  253. {
  254. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_SEND_IMP_FAILED, GetLastError());
  255. }
  256. DbgLog1(SEV_ERROR, "can't impersonate, %d", GetLastError());
  257. return;
  258. }
  259. }
  260. //
  261. // Avoid idle-time shutdowns. If the call fails, we want to continue anyway.
  262. //
  263. SetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
  264. // send the files one at a time
  265. for( szObj = _files; *szObj != 0; szObj += lstrlen(szObj)+1 )
  266. {
  267. DbgLog1( SEV_INFO, "Sending %S", szObj );
  268. UpdateSendProgress( rpcBinding,
  269. _cookie,
  270. szObj,
  271. _dataXferRecv.dwTotalSize,
  272. _completedFilesSize,
  273. &status
  274. );
  275. if( DirectoryExists(szObj) )
  276. {
  277. status = _SendFolder( szObj );
  278. }
  279. else
  280. {
  281. status = _SendFile( szObj );
  282. }
  283. if( status || g_fShutdown)
  284. {
  285. break;
  286. }
  287. }
  288. //
  289. // Re-enable idle-time shutdowns.
  290. //
  291. SetThreadExecutionState( ES_CONTINUOUS );
  292. //
  293. // Make sure we show 100% for a completed transfer.
  294. //
  295. if (!status)
  296. {
  297. UpdateSendProgress( rpcBinding,
  298. _cookie,
  299. _dataFileRecv.szFileName,
  300. _dataXferRecv.dwTotalSize,
  301. _dataXferRecv.dwTotalSize,
  302. &status
  303. );
  304. }
  305. if (status != ERROR_CANCELLED)
  306. {
  307. // don't overwrite the error unless there isn't one
  308. error_status_t errTemp;
  309. _Send_EndXfer();
  310. errTemp = Obex_Disconnect( status );
  311. if( !status )
  312. {
  313. status = errTemp;
  314. }
  315. }
  316. RevertToSelf();
  317. if( status )
  318. {
  319. // status = MapWinsockErrorToWin32( status );
  320. OneSendFileFailed( rpcBinding, _cookie, szObj, status, locFileSend, &status );
  321. }
  322. SendComplete( rpcBinding, _cookie, _dataXferRecv.dwTotalSent, &status );
  323. RemoveFromTransferList(this);
  324. DecrementRefCount();
  325. }
  326. error_status_t
  327. MapWinsockErrorToWin32(
  328. error_status_t status
  329. )
  330. {
  331. if (status)
  332. {
  333. DbgLog2(SEV_ERROR, "mapping error 0x%x (%d)", status, status);
  334. }
  335. if (status < WSABASEERR || status > WSABASEERR + 1000)
  336. {
  337. return status;
  338. }
  339. switch (status)
  340. {
  341. case WSAECONNREFUSED:
  342. return ERROR_CONNECTION_REFUSED;
  343. default:
  344. return ERROR_REQUEST_ABORTED;
  345. }
  346. }
  347. error_status_t
  348. _GetObjListStats(
  349. LPWSTR lpszObjList,
  350. LPDWORD lpdwFiles,
  351. LPDWORD lpdwFolders,
  352. __int64 * lpdwTotalSize
  353. )
  354. {
  355. error_status_t status = 0;
  356. LPWSTR szObj;
  357. HANDLE hFile;
  358. //
  359. // Protect ourselves from login or logout notifications while using the token.
  360. //
  361. {
  362. CLAIM_MUTEX Lock( g_Mutex );
  363. if (g_UserToken == 0)
  364. {
  365. //
  366. // the send was aborted due to logging out.
  367. //
  368. return ERROR_NOT_LOGGED_ON;
  369. }
  370. if (!ImpersonateLoggedOnUser(g_UserToken))
  371. {
  372. DWORD dwEventStatus = 0;
  373. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  374. if (!dwEventStatus)
  375. {
  376. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_SEND_IMP_FAILED, GetLastError());
  377. }
  378. DbgLog1(SEV_ERROR, "can't impersonate, %d", GetLastError());
  379. return GetLastError();
  380. }
  381. }
  382. // get (a) number of files, (b) total file size
  383. for( szObj = lpszObjList; *szObj != 0; szObj += lstrlen(szObj)+1 )
  384. {
  385. hFile = CreateFile(
  386. szObj,
  387. GENERIC_READ,
  388. FILE_SHARE_READ,
  389. NULL,
  390. OPEN_EXISTING,
  391. FILE_ATTRIBUTE_NORMAL,
  392. NULL
  393. );
  394. if( INVALID_HANDLE_VALUE == hFile )
  395. {
  396. // if it's a directory, get the total size of its files
  397. if( DirectoryExists(szObj) )
  398. {
  399. *lpdwTotalSize += GetDirectorySize( szObj );
  400. (*lpdwFolders)++;
  401. continue;
  402. }
  403. else
  404. {
  405. DbgLog2(SEV_ERROR, "open file \'%S\' failed %d", szObj, GetLastError());
  406. RevertToSelf();
  407. ReportFileError( MC_IRXFER_OPEN_FAILED, szObj, GetLastError() );
  408. return GetLastError();
  409. }
  410. }
  411. *lpdwTotalSize += GetFileSize( hFile, NULL );
  412. (*lpdwFiles)++;
  413. CloseHandle( hFile );
  414. }
  415. RevertToSelf();
  416. return 0;
  417. }
  418. BOOL
  419. FILE_TRANSFER::Xfer_Init(
  420. wchar_t * files,
  421. unsigned length,
  422. OBEX_DIALECT dialect,
  423. OBEX_DEVICE_TYPE DeviceType,
  424. BOOL CreateSocket,
  425. SOCKET ListenSocket
  426. )
  427. {
  428. unsigned Timeout = 500;
  429. DWORD status = 0;
  430. m_ListenSocket=ListenSocket;
  431. _dialect = dialect;
  432. InitializeCriticalSection(&m_Lock);
  433. if (length)
  434. {
  435. _xferType = xferSEND;
  436. _files = new wchar_t[ length ];
  437. if (!_files)
  438. {
  439. goto cleanup;
  440. }
  441. memcpy(_files, files, sizeof(wchar_t) * length );
  442. }
  443. else
  444. {
  445. _xferType = xferRECV;
  446. _files = 0;
  447. }
  448. _mutex = new MUTEX( &status );
  449. if (!_mutex)
  450. {
  451. goto cleanup;
  452. }
  453. _dataXferRecv.fXferInProgress = FALSE;
  454. m_DeviceType=DeviceType;
  455. if (CreateSocket) {
  456. if (DeviceType == TYPE_IRDA) {
  457. _socket = socket( AF_IRDA, SOCK_STREAM, 0);
  458. } else {
  459. _socket = socket( AF_INET, SOCK_STREAM, 0);
  460. }
  461. if (!_socket) {
  462. goto cleanup;
  463. }
  464. setsockopt( _socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &Timeout, sizeof(Timeout));
  465. } else {
  466. _socket = INVALID_SOCKET;
  467. }
  468. _event = CreateEvent( NULL, // no security
  469. TRUE, // manual-reset
  470. FALSE, // initially not set
  471. NULL // no name
  472. );
  473. if (!_event)
  474. {
  475. goto cleanup;
  476. }
  477. _state = BLANK;
  478. _overlapped.hEvent = _event;
  479. _buffers.buf = (char *) _buffer;
  480. _buffers.len = cbSOCK_BUFFER_SIZE;
  481. _guard = GUARD_MAGIC;
  482. if ( !Obex_Init())
  483. {
  484. goto cleanup;
  485. }
  486. #if 0
  487. if ( !Activate())
  488. {
  489. goto cleanup;
  490. }
  491. #endif
  492. return TRUE;
  493. cleanup:
  494. if (_files)
  495. {
  496. delete _files;
  497. }
  498. if (_mutex)
  499. {
  500. delete _mutex;
  501. }
  502. if (_socket != INVALID_SOCKET )
  503. {
  504. closesocket( _socket );
  505. }
  506. if (_event)
  507. {
  508. CloseHandle( _event );
  509. }
  510. return FALSE;
  511. }
  512. error_status_t
  513. FILE_TRANSFER::Xfer_ConnStart()
  514. {
  515. _uObjsReceived = 0;
  516. _dataXferRecv.fXferInProgress = TRUE;
  517. _dataXferRecv.dwTotalSize = 0;
  518. _dataXferRecv.dwTotalSent = 0;
  519. return _SetReceiveFolder( NULL );
  520. }
  521. VOID FILE_TRANSFER::Xfer_ConnEnd( VOID )
  522. {
  523. _dataXferRecv.fXferInProgress = FALSE;
  524. }
  525. error_status_t
  526. FILE_TRANSFER::Xfer_SetPath(
  527. LPWSTR szPath
  528. )
  529. {
  530. error_status_t status = 0;
  531. if( !szPath || lstrlen(szPath) == 0 )
  532. {
  533. // set default receive folder
  534. return _SetReceiveFolder( NULL );
  535. }
  536. if( lstrcmp(szPath, szPREVDIR) == 0 )
  537. {
  538. // pop up a level
  539. WCHAR sz[MAX_PATH];
  540. lstrcpy( sz, _szRecvFolder );
  541. // remove trailing backslash
  542. if(bHasTrailingSlash(sz))
  543. sz[lstrlen(sz)-1] = cNIL;
  544. // strip last folder off path
  545. StripFile( sz );
  546. return _SetReceiveFolder( sz );
  547. }
  548. // format szPath and append it to the current receive folder
  549. WCHAR szRFF[MAX_PATH];
  550. LPWSTR lpsz;
  551. // remove preceding backslashes
  552. while( *szPath == cBACKSLASH )
  553. szPath++;
  554. // remove anything after a backslash
  555. lpsz = szPath;
  556. while( *lpsz != cNIL && *lpsz != cBACKSLASH )
  557. lpsz++;
  558. *lpsz = cNIL;
  559. lstrcpy( szRFF, _szRecvFolder );
  560. GetUniqueName( szRFF, szPath, FALSE );
  561. _uObjsReceived++;
  562. return _SetReceiveFolder( szRFF );
  563. }
  564. VOID FILE_TRANSFER::Xfer_FileInit( VOID )
  565. {
  566. _dataXferRecv.dwFileSize = 0;
  567. _dataXferRecv.dwFileSent = 0;
  568. FillMemory( &_dataFileRecv.filetime, sizeof(_dataFileRecv.filetime), (BYTE)-1 );
  569. lstrcpy( _dataFileRecv.szFileName, L"" );
  570. lstrcpy( _dataFileRecv.szFileSave, L"" );
  571. lstrcpy( _dataFileRecv.szFileTemp, L"" );
  572. }
  573. error_status_t
  574. FILE_TRANSFER::Xfer_FileSetName( LPWSTR szName )
  575. {
  576. lstrcpy( _dataFileRecv.szFileName, szName );
  577. return _FileStart();
  578. }
  579. BOOL FILE_TRANSFER::Xfer_FileSetSize( BYTE4 b4Size )
  580. {
  581. _dataXferRecv.dwFileSize = b4Size;
  582. return ( IsRoomForFile(_dataXferRecv.dwFileSize, _szRecvFolder) );
  583. }
  584. error_status_t
  585. FILE_TRANSFER::Xfer_FileWriteBody(
  586. LPVOID lpvData,
  587. BYTE2 b2Size,
  588. BOOL fFinal
  589. )
  590. {
  591. error_status_t status = 0;
  592. DWORD dwSize = b2Size;
  593. DWORD dwBytesWritten;
  594. DbgLog1( SEV_FUNCTION, "Xfer_WriteBody: %ld bytes", dwSize );
  595. // has this file been opened yet?
  596. if( INVALID_HANDLE_VALUE == _dataFileRecv.hFile )
  597. {
  598. ASSERT( 0 );
  599. return ERROR_CANTOPEN;
  600. }
  601. // write the data to the file
  602. while( dwSize > 0 )
  603. {
  604. BOOL fRet;
  605. fRet = WriteFile( _dataFileRecv.hFile,
  606. lpvData,
  607. dwSize,
  608. &dwBytesWritten,
  609. NULL
  610. );
  611. if( !fRet )
  612. {
  613. status = GetLastError();
  614. break;
  615. }
  616. lpvData = (LPVOID)( (DWORD_PTR)lpvData + dwBytesWritten );
  617. dwSize -= dwBytesWritten;
  618. _dataXferRecv.dwTotalSent += dwBytesWritten;
  619. _dataXferRecv.dwFileSent += dwBytesWritten;
  620. }
  621. if( fFinal )
  622. {
  623. if (!status)
  624. {
  625. status = _FileEnd( TRUE );
  626. }
  627. else
  628. {
  629. _FileEnd( TRUE );
  630. }
  631. }
  632. return status;
  633. }
  634. VOID FILE_TRANSFER::Xfer_FileAbort( VOID )
  635. {
  636. _FileEnd( FALSE );
  637. }
  638. error_status_t
  639. FILE_TRANSFER::_FileStart()
  640. {
  641. WCHAR szFullPath[MAX_PATH];
  642. WCHAR szBaseFile[MAX_PATH];
  643. if (IsWorkstationLocked())
  644. {
  645. DbgLog1(SEV_ERROR, "rejecting file %S because the workstation is locked", _dataFileRecv.szFileName );
  646. return ERROR_ACCESS_DENIED;
  647. }
  648. //
  649. // Protect ourselves from login or logout notifications while using the token.
  650. //
  651. {
  652. CLAIM_MUTEX Lock( g_Mutex );
  653. if (g_UserToken == 0)
  654. {
  655. //
  656. // the send was aborted due to logging out.
  657. //
  658. return ERROR_NOT_LOGGED_ON;
  659. }
  660. if (!ImpersonateLoggedOnUser(g_UserToken))
  661. {
  662. DWORD dwEventStatus = 0;
  663. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  664. if (!dwEventStatus)
  665. {
  666. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_MOVE_FAILED, GetLastError());
  667. }
  668. DbgLog1(SEV_ERROR, "move: can't impersonate, %d", GetLastError());
  669. return GetLastError();
  670. }
  671. }
  672. // get path of file
  673. lstrcpy( szFullPath, _szRecvFolder );
  674. // strip path to get the base filename
  675. lstrcpy( szBaseFile, _dataFileRecv.szFileName );
  676. StripPath( szBaseFile );
  677. GetUniqueName( szFullPath, szBaseFile, TRUE );
  678. lstrcpy( _dataFileRecv.szFileSave, szFullPath );
  679. DbgLog1( SEV_INFO, "Save file: [%S]", szFullPath );
  680. GetTempPath( sizeof(szBaseFile)/sizeof(WCHAR), szBaseFile );
  681. GetTempFileName( szBaseFile, TEMP_FILE_PREFIX, 0, szFullPath );
  682. lstrcpy( _dataFileRecv.szFileTemp, szFullPath );
  683. DbgLog1( SEV_INFO, "Temp file: [%S]", szFullPath );
  684. {
  685. wchar_t RFF[1+MAX_PATH];
  686. GetReceivedFilesFolder(RFF, MAX_PATH);
  687. wchar_t * PromptPath = _dataFileRecv.szFileSave + lstrlen(RFF);
  688. DbgLog2( SEV_INFO, "need to ask permission: \n new file = [%S]\n prompt file = [%S]",
  689. _dataFileRecv.szFileSave,
  690. PromptPath );
  691. error_status_t status = GetPermission( rpcBinding, _cookie, PromptPath, FALSE );
  692. if (status)
  693. {
  694. DbgLog2( SEV_ERROR, "permission check failed, cookie %p error %d", (void *) _cookie, status );
  695. return status;
  696. }
  697. }
  698. //
  699. // Create the temporary file.
  700. //
  701. _dataFileRecv.hFile = CreateFile(
  702. szFullPath,
  703. GENERIC_WRITE,
  704. 0L,
  705. NULL,
  706. OPEN_ALWAYS,
  707. FILE_ATTRIBUTE_NORMAL,
  708. NULL
  709. );
  710. RevertToSelf();
  711. if ( INVALID_HANDLE_VALUE == _dataFileRecv.hFile )
  712. {
  713. ReportFileError( MC_IRXFER_OPEN_FAILED, szFullPath, GetLastError() );
  714. return GetLastError();
  715. }
  716. return 0;
  717. }
  718. error_status_t
  719. FILE_TRANSFER::_FileEnd( BOOL fSave )
  720. {
  721. error_status_t status = 0;
  722. // set the date stamp
  723. if( _dataFileRecv.filetime.dwLowDateTime != (DWORD)-1
  724. || _dataFileRecv.filetime.dwHighDateTime != (DWORD)-1 )
  725. {
  726. if( INVALID_HANDLE_VALUE != _dataFileRecv.hFile )
  727. SetFileTime( _dataFileRecv.hFile, NULL, NULL, &_dataFileRecv.filetime );
  728. }
  729. if( INVALID_HANDLE_VALUE != _dataFileRecv.hFile )
  730. {
  731. CloseHandle( _dataFileRecv.hFile );
  732. _dataFileRecv.hFile = INVALID_HANDLE_VALUE;
  733. }
  734. if( fSave )
  735. {
  736. _uObjsReceived++;
  737. //
  738. // Protect ourselves from login or logout notifications while using the token.
  739. //
  740. {
  741. CLAIM_MUTEX Lock( g_Mutex );
  742. if (g_UserToken == 0)
  743. {
  744. //
  745. // the send was aborted due to logging out.
  746. //
  747. return ERROR_NOT_LOGGED_ON;
  748. }
  749. if (!ImpersonateLoggedOnUser(g_UserToken))
  750. {
  751. DWORD dwEventStatus = 0;
  752. EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
  753. if (!dwEventStatus)
  754. {
  755. EventLog.ReportError(CAT_IRXFER, MC_IRXFER_MOVE_FAILED, GetLastError());
  756. }
  757. DbgLog1(SEV_ERROR, "move: can't impersonate, %d", GetLastError());
  758. return GetLastError();
  759. }
  760. }
  761. if (!MoveFile( _dataFileRecv.szFileTemp, _dataFileRecv.szFileSave ))
  762. {
  763. status = GetLastError();
  764. ReportFileError( MC_IRXFER_MOVE_FAILED, _dataFileRecv.szFileSave, status );
  765. DbgLog3(SEV_ERROR, "%d moving %S -> %S", status, _dataFileRecv.szFileTemp, _dataFileRecv.szFileSave);
  766. }
  767. else
  768. {
  769. DbgLog2(SEV_INFO, "moved %S -> %S", _dataFileRecv.szFileTemp, _dataFileRecv.szFileSave);
  770. }
  771. RevertToSelf();
  772. }
  773. else
  774. {
  775. DeleteFile( _dataFileRecv.szFileTemp );
  776. }
  777. Xfer_FileInit();
  778. return status;
  779. }
  780. error_status_t
  781. FILE_TRANSFER::_SetReceiveFolder(
  782. LPWSTR szFolder
  783. )
  784. {
  785. error_status_t status = 0;
  786. WCHAR sz[MAX_PATH];
  787. DbgLog1( SEV_FUNCTION, "_SetReceiveFolder: [%S]", (szFolder?szFolder : L"NULL") );
  788. if (IsWorkstationLocked())
  789. {
  790. DbgLog1(SEV_ERROR, "rejecting directory %S because the workstation is locked", szFolder );
  791. return ERROR_ACCESS_DENIED;
  792. }
  793. GetReceivedFilesFolder( sz, sizeof(sz) );
  794. //
  795. // Make sure the requested folder is within the root RFF, for security reasons.
  796. //
  797. if( szFolder && lstrlen(szFolder) > 0 )
  798. {
  799. if( 0 == wcsncmp(sz, szFolder, lstrlen(sz)) )
  800. {
  801. lstrcpy( _szRecvFolder, szFolder );
  802. }
  803. else
  804. {
  805. // can't go outside the RFF tree; use the root RFF.
  806. //
  807. lstrcpy( _szRecvFolder, sz );
  808. }
  809. }
  810. else
  811. {
  812. lstrcpy( _szRecvFolder, sz );
  813. }
  814. // always end path with a backslash '\'
  815. if( bNoTrailingSlash(_szRecvFolder) )
  816. lstrcat( _szRecvFolder, szBACKSLASH );
  817. //
  818. // Get permission to create this directory, unless we have not yet called ReceiveInProgress.
  819. // This latter will be true only during the connect. This seems harmless: a malicious
  820. // client can only create a couple of empty directories in my desktop w/o authorization.
  821. //
  822. if (_fInUiReceiveList)
  823. {
  824. wchar_t * PromptPath = _szRecvFolder + lstrlen(sz);
  825. DbgLog2( SEV_INFO, "need to ask permission: \n new dir = [%S]\n prompt dir = [%S]",
  826. _szRecvFolder,
  827. PromptPath );
  828. status = GetPermission( rpcBinding, _cookie, PromptPath, TRUE );
  829. if (status)
  830. {
  831. DbgLog1( SEV_ERROR, "permission check failed %d", status );
  832. return status;
  833. }
  834. }
  835. DbgLog1( SEV_INFO, "Setting Receive Folder: [%S]", _szRecvFolder );
  836. if( !DirectoryExists( _szRecvFolder ) )
  837. {
  838. status = MdWork( _szRecvFolder );
  839. if (status)
  840. {
  841. ReportFileError( MC_IRXFER_CREATE_DIR_FAILED, _szRecvFolder, status );
  842. }
  843. }
  844. DbgLog1( SEV_FUNCTION, "_SetReceiveFolder leave %d", status);
  845. return status;
  846. }
  847. VOID
  848. FILE_TRANSFER::_Send_StartXfer( __int64 dwTotalSize,
  849. LPWSTR szDst
  850. )
  851. {
  852. _dataXferRecv.fXferInProgress = TRUE;
  853. _dataXferRecv.dwTotalSize = dwTotalSize;
  854. _dataXferRecv.dwTotalSent = 0;
  855. _completedFilesSize = 0;
  856. }
  857. VOID FILE_TRANSFER::_Send_EndXfer( VOID )
  858. {
  859. _dataXferRecv.fXferInProgress = FALSE;
  860. }
  861. error_status_t
  862. FILE_TRANSFER::_SendFile(
  863. LPWSTR wszFile
  864. )
  865. {
  866. error_status_t status = 0;
  867. DWORD dwFileTime = (DWORD)-1;
  868. HANDLE hFile;
  869. FILETIME filetime;
  870. DbgLog1(SEV_FUNCTION, "_SendFile( %S )", wszFile);
  871. lstrcpy( _dataFileRecv.szFileName, wszFile );
  872. hFile = CreateFileW(
  873. wszFile,
  874. GENERIC_READ,
  875. FILE_SHARE_READ,
  876. NULL,
  877. OPEN_EXISTING,
  878. FILE_ATTRIBUTE_NORMAL,
  879. NULL
  880. );
  881. if( INVALID_HANDLE_VALUE == hFile )
  882. goto lExit;
  883. if( !GetFileTime(hFile, NULL, NULL, &filetime) )
  884. goto lExit;
  885. _dataXferRecv.dwFileSize = GetFileSize( hFile, NULL );
  886. _dataXferRecv.dwFileSent = 0;
  887. status = Obex_PutBegin( wszFile, _dataXferRecv.dwFileSize, &filetime );
  888. ExitOnErr( status );
  889. status = _PutFileBody( hFile, wszFile );
  890. ExitOnErr( status );
  891. _completedFilesSize += _dataXferRecv.dwFileSize;
  892. lExit:
  893. DbgLog1( SEV_FUNCTION, "_SendFile leave [%d]", status );
  894. CloseHandle( hFile );
  895. return status;
  896. }
  897. error_status_t
  898. FILE_TRANSFER::_SendFolder(
  899. LPWSTR wszFolder
  900. )
  901. {
  902. error_status_t status = 0;
  903. BOOL bContinue;
  904. HANDLE hFind = INVALID_HANDLE_VALUE;
  905. WCHAR wszDir[MAX_PATH];
  906. WCHAR wszSpec[MAX_PATH];
  907. WIN32_FIND_DATAW findData;
  908. // send this directory so it's created
  909. status = Obex_SetPath( wszFolder );
  910. ExitOnErr( status );
  911. // get base directory ending with backslash
  912. lstrcpy( wszDir, wszFolder );
  913. if( bNoTrailingSlash(wszDir) )
  914. lstrcatW( wszDir, szBACKSLASH );
  915. // form search string
  916. lstrcpyW( wszSpec, wszDir );
  917. lstrcatW( wszSpec, L"*.*" );
  918. hFind = FindFirstFileW( wszSpec, &findData );
  919. bContinue = ( hFind != INVALID_HANDLE_VALUE );
  920. while( bContinue )
  921. {
  922. WCHAR wszObj[cbMAX_SZ];
  923. lstrcpyW( wszObj, wszDir );
  924. lstrcatW( wszObj, findData.cFileName );
  925. if( findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
  926. {
  927. // weed out "." and ".."
  928. if( *(findData.cFileName) != cPERIOD )
  929. {
  930. status = _SendFolder( wszObj );
  931. }
  932. }
  933. else
  934. {
  935. status = _SendFile( wszObj );
  936. }
  937. if( status )
  938. break;
  939. bContinue = FindNextFileW( hFind, &findData );
  940. }
  941. // pop out of this directory
  942. {
  943. error_status_t errTemp = Obex_SetPath( NULL );
  944. // only set the error if there isn't one already
  945. if( !status )
  946. status = errTemp;
  947. }
  948. ExitOnErr( status );
  949. lExit:
  950. if ( hFind != INVALID_HANDLE_VALUE )
  951. {
  952. FindClose( hFind );
  953. }
  954. return status;
  955. }
  956. // if we have a file size of 0, we still want to write a
  957. // blank body once, hence fPutOnce
  958. error_status_t
  959. FILE_TRANSFER::_PutFileBody( HANDLE hFile, wchar_t FileName[] )
  960. {
  961. error_status_t status = 0;
  962. BOOL fPutOnce = FALSE;
  963. DWORD dwRead;
  964. BYTE1 b1Send[cbSOCK_BUFFER_SIZE];
  965. DWORD Extra = sizeof(b1Send) % (_dataRecv.b2MaxPacket-16);
  966. DbgLog( SEV_FUNCTION, "_PutFileBody" );
  967. while( !status && !g_fShutdown)
  968. {
  969. BOOL fRet = ReadFile(
  970. hFile,
  971. b1Send,
  972. sizeof(b1Send) - Extra,
  973. &dwRead,
  974. NULL
  975. );
  976. if( !fRet )
  977. return GetLastError();
  978. if( dwRead == 0 && fPutOnce )
  979. break;
  980. _dataXferRecv.dwTotalSent += dwRead;
  981. _dataXferRecv.dwFileSent += dwRead;
  982. // NOTE: casting dwRead from 4 bytes to 2 bytes requires
  983. // cbSOCK_BUFFER_SIZE to fit into 2 bytes
  984. status = Obex_PutBody( FileName,
  985. b1Send,
  986. (BYTE2)dwRead,
  987. _dataXferRecv.dwFileSent == _dataXferRecv.dwFileSize
  988. );
  989. fPutOnce = TRUE;
  990. }
  991. DbgLog1( SEV_FUNCTION, "_PutFileBody leave [%d]", status );
  992. return status;
  993. }
  994. VOID FILE_TRANSFER::Xfer_SetSize( BYTE4 b4Size )
  995. {
  996. _dataXferRecv.dwTotalSize = b4Size;
  997. }
  998. #if 0
  999. PFILE_TRANSFER * FILE_TRANSFER::ActiveTransfers = 0;
  1000. unsigned FILE_TRANSFER::ArrayLength = 0;
  1001. MUTEX * FILE_TRANSFER::ActiveTransferMutex = 0;
  1002. BOOL
  1003. FILE_TRANSFER::Activate()
  1004. {
  1005. CLAIM_MUTEX Lock(ActiveTransferMutex);
  1006. unsigned i;
  1007. for (i=0; i < ArrayLength; ++i)
  1008. {
  1009. if (ActiveTransfers[i] == 0)
  1010. {
  1011. ActiveTransfers[i] = this;
  1012. return TRUE;
  1013. }
  1014. }
  1015. PFILE_TRANSFER * NewArray = new PFILE_TRANSFER[ 2 * ArrayLength ];
  1016. if (!NewArray)
  1017. {
  1018. return FALSE;
  1019. }
  1020. memcpy(NewArray, ActiveTransfers, sizeof(PFILE_TRANSFER) * ArrayLength);
  1021. memset(NewArray+ArrayLength, 0, sizeof(PFILE_TRANSFER) * ArrayLength);
  1022. NewArray[ArrayLength] = this;
  1023. delete ActiveTransfers;
  1024. ActiveTransfers = NewArray;
  1025. ArrayLength *= 2;
  1026. return TRUE;
  1027. }
  1028. void
  1029. FILE_TRANSFER::Deactivate()
  1030. {
  1031. CLAIM_MUTEX Lock(ActiveTransferMutex);
  1032. unsigned i;
  1033. for (i=0; i < ArrayLength; ++i)
  1034. {
  1035. if (ActiveTransfers[i] == this)
  1036. {
  1037. ActiveTransfers[i] = 0;
  1038. }
  1039. }
  1040. }
  1041. FILE_TRANSFER *
  1042. FILE_TRANSFER::FromCookie(
  1043. __int64 cookie
  1044. )
  1045. {
  1046. CLAIM_MUTEX Lock(ActiveTransferMutex);
  1047. unsigned i;
  1048. for (i=0; i < ArrayLength; ++i)
  1049. {
  1050. if( ActiveTransfers[i] &&
  1051. // ActiveTransfers[i]->_xferType == xferSEND &&
  1052. ActiveTransfers[i]->_cookie == cookie)
  1053. {
  1054. if ( ActiveTransfers[i]->_fCancelled)
  1055. {
  1056. return 0;
  1057. }
  1058. ActiveTransfers[i]->IncrementRefCount();
  1059. return ActiveTransfers[i];
  1060. }
  1061. }
  1062. return 0;
  1063. }
  1064. #endif
  1065. void
  1066. FILE_TRANSFER::RecordDeviceName(
  1067. SOCKADDR_IRDA * s
  1068. )
  1069. {
  1070. char buffer[sizeof(DEVICELIST) + 8*sizeof(IRDA_DEVICE_INFO)];
  1071. DEVICELIST * list = (DEVICELIST *) buffer;
  1072. int size = sizeof(buffer);
  1073. if (SOCKET_ERROR == getsockopt( _socket, SOL_IRLMP, IRLMP_ENUMDEVICES, buffer, &size))
  1074. {
  1075. wcscpy( _DeviceName, g_UnknownDeviceName );
  1076. return;
  1077. }
  1078. for (unsigned i=0; i < list->numDevice; ++i)
  1079. {
  1080. if (0 == memcmp(list->Device[i].irdaDeviceID, s->irdaDeviceID, sizeof(s->irdaDeviceID)))
  1081. {
  1082. wchar_t * UnicodeDeviceName = SzToWsz(list->Device[i].irdaDeviceName);
  1083. if (!UnicodeDeviceName)
  1084. {
  1085. break;
  1086. }
  1087. wcscpy( _DeviceName, UnicodeDeviceName );
  1088. MemFree( UnicodeDeviceName );
  1089. return;
  1090. }
  1091. }
  1092. wcscpy( _DeviceName, g_UnknownDeviceName );
  1093. }
  1094. void
  1095. FILE_TRANSFER::RecordIpDeviceName(
  1096. sockaddr_in * Address
  1097. )
  1098. {
  1099. char* IpAddressString;
  1100. HOSTENT* HostName;
  1101. //
  1102. // try to resolve the address
  1103. //
  1104. HostName=gethostbyaddr((char*)&Address->sin_addr,sizeof(Address->sin_addr),AF_INET);
  1105. if (HostName != NULL) {
  1106. IpAddressString=HostName->h_name;
  1107. } else {
  1108. //
  1109. // could not resolve the ip address
  1110. //
  1111. IpAddressString=inet_ntoa(Address->sin_addr);
  1112. }
  1113. wchar_t * UnicodeDeviceName = SzToWsz(IpAddressString);
  1114. if (UnicodeDeviceName != NULL) {
  1115. wcscpy( _DeviceName, UnicodeDeviceName );
  1116. MemFree( UnicodeDeviceName );
  1117. return;
  1118. }
  1119. wcscpy( _DeviceName, g_UnknownDeviceName );
  1120. return;
  1121. }
  1122. //
  1123. // Code that I took from CMD.EXE
  1124. //
  1125. #define COLON ':'
  1126. #define NULLC '\0'
  1127. #define BSLASH '\\'
  1128. BOOL IsValidDrv(TCHAR drv);
  1129. /**************** START OF SPECIFICATIONS ***********************/
  1130. /* */
  1131. /* SUBROUTINE NAME: MdWork */
  1132. /* */
  1133. /* DESCRIPTIVE NAME: Make a directory */
  1134. /* */
  1135. /* FUNCTION: MdWork creates a new directory. */
  1136. /* */
  1137. /* INPUT: arg - a pointer to a NULL terminated string of the */
  1138. /* new directory to create. */
  1139. /* */
  1140. /* EXIT-NORMAL: returns zero if the directory is made */
  1141. /* successfully */
  1142. /* */
  1143. /* EXIT-ERROR: returns an error code otherwise */
  1144. /* */
  1145. /* EFFECTS: None. */
  1146. /* */
  1147. /**************** END OF SPECIFICATIONS *************************/
  1148. DWORD
  1149. MdWork(
  1150. WCHAR *arg
  1151. )
  1152. {
  1153. ULONG Status;
  1154. WCHAR *lpw;
  1155. WCHAR TempBuffer[MAX_PATH];
  1156. /* Check if drive is valid because Dosmkdir does not
  1157. return invalid drive @@5 */
  1158. if ((arg[1] == COLON) && !IsValidDrv(*arg))
  1159. {
  1160. return ERROR_INVALID_DRIVE;
  1161. }
  1162. if (!GetFullPathName(arg, MAX_PATH, TempBuffer, &lpw))
  1163. {
  1164. return GetLastError();
  1165. }
  1166. if (CreateDirectory( arg, NULL ))
  1167. {
  1168. return 0;
  1169. }
  1170. Status = GetLastError();
  1171. if (Status == ERROR_ALREADY_EXISTS)
  1172. {
  1173. return 0;
  1174. }
  1175. else if (Status != ERROR_PATH_NOT_FOUND)
  1176. {
  1177. return Status;
  1178. }
  1179. //
  1180. // loop over input path and create any needed intermediary directories.
  1181. //
  1182. // Find the point in the string to begin the creation. Note, for UNC
  1183. // names, we must skip the machine and the share
  1184. //
  1185. if (TempBuffer[1] == COLON) {
  1186. //
  1187. // Skip D:\
  1188. //
  1189. lpw = TempBuffer+3;
  1190. } else if (TempBuffer[0] == BSLASH && TempBuffer[1] == BSLASH) {
  1191. //
  1192. // Skip \\server\share\
  1193. //
  1194. lpw = TempBuffer+2;
  1195. while (*lpw && *lpw != BSLASH) {
  1196. lpw++;
  1197. }
  1198. if (*lpw) {
  1199. lpw++;
  1200. }
  1201. while (*lpw && *lpw != BSLASH) {
  1202. lpw++;
  1203. }
  1204. if (*lpw) {
  1205. lpw++;
  1206. }
  1207. } else {
  1208. //
  1209. // For some reason, GetFullPath has given us something we can't understand
  1210. //
  1211. return ERROR_CANNOT_MAKE;
  1212. }
  1213. //
  1214. // Walk through the components creating them
  1215. //
  1216. while (*lpw) {
  1217. //
  1218. // Move forward until the next path separator
  1219. //
  1220. while (*lpw && *lpw != BSLASH) {
  1221. lpw++;
  1222. }
  1223. //
  1224. // If we've encountered a path character, then attempt to
  1225. // make the given path.
  1226. //
  1227. if (*lpw == BSLASH) {
  1228. *lpw = NULLC;
  1229. if (!CreateDirectory( TempBuffer, NULL )) {
  1230. Status = GetLastError();
  1231. if (Status != ERROR_ALREADY_EXISTS) {
  1232. return ERROR_CANNOT_MAKE;
  1233. }
  1234. }
  1235. *lpw++ = BSLASH;
  1236. }
  1237. }
  1238. if (!CreateDirectory( TempBuffer, NULL )) {
  1239. Status = GetLastError( );
  1240. if (Status != ERROR_ALREADY_EXISTS) {
  1241. return Status;
  1242. }
  1243. }
  1244. return 0;
  1245. }
  1246. /*** IsValidDrv - Check drive validity
  1247. *
  1248. * Purpose:
  1249. * Check validity of passed drive letter.
  1250. *
  1251. * int IsValidDrv(WCHAR drv)
  1252. *
  1253. * Args:
  1254. * drv - The letter of the drive to check
  1255. *
  1256. * Returns:
  1257. * TRUE if drive is valid
  1258. * FALSE if not
  1259. *
  1260. * Notes:
  1261. *
  1262. */
  1263. BOOL
  1264. IsValidDrv(WCHAR drv)
  1265. {
  1266. WCHAR temp[4];
  1267. temp[ 0 ] = drv;
  1268. temp[ 1 ] = COLON;
  1269. temp[ 2 ] = BSLASH;
  1270. temp[ 3 ] = NULLC;
  1271. //
  1272. // return of 0 or 1 mean can't determine or root
  1273. // does not exists.
  1274. //
  1275. if (GetDriveType(temp) <= 1)
  1276. return( FALSE );
  1277. else {
  1278. return( TRUE );
  1279. }
  1280. }