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.

1104 lines
32 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1997
  4. *
  5. * TITLE: ItAlloc.Cpp
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 10 July, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implements mapped memory allocation for ImageIn devices.
  15. *
  16. *******************************************************************************/
  17. #include <stdio.h>
  18. #include <objbase.h>
  19. #include <aclapi.h>
  20. #include <sddl.h>
  21. #include "wia.h"
  22. #include "wiapriv.h"
  23. //
  24. // Macro definitions
  25. //
  26. #define TMPFILE_ACE_ADD TEXT("(A;OI;FA;;;LS)")
  27. #ifdef DEBUG
  28. #define DPRINT(x) OutputDebugString(TEXT("ITALLOC:") TEXT(x) TEXT("\r\n"));
  29. #else
  30. #define DPRINT(x)
  31. #endif
  32. /**************************************************************************\
  33. * proxyReadPropLong
  34. *
  35. * Read property long helper.
  36. *
  37. * Arguments:
  38. *
  39. * pIUnknown - Pointer to WIA item
  40. * propid - Property ID
  41. * plVal - Pointer to returned LONG
  42. *
  43. * Return Value:
  44. *
  45. * Status
  46. *
  47. * History:
  48. *
  49. * 1/19/1999 Original Version
  50. *
  51. \**************************************************************************/
  52. HRESULT WINAPI proxyReadPropLong(
  53. IUnknown *pIUnknown,
  54. PROPID propid,
  55. LONG *plVal)
  56. {
  57. IWiaPropertyStorage *pIWiaPropStg;
  58. if (!pIUnknown) {
  59. return E_INVALIDARG;
  60. }
  61. HRESULT hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIWiaPropStg);
  62. if (FAILED(hr)) {
  63. return hr;
  64. }
  65. PROPSPEC PropSpec[1];
  66. PROPVARIANT PropVar[1];
  67. UINT cbSize;
  68. memset(PropVar, 0, sizeof(PropVar));
  69. PropSpec[0].ulKind = PRSPEC_PROPID;
  70. PropSpec[0].propid = propid;
  71. hr = pIWiaPropStg->ReadMultiple(1, PropSpec, PropVar);
  72. if (SUCCEEDED(hr)) {
  73. *plVal = PropVar[0].lVal;
  74. }
  75. else {
  76. DPRINT("proxyReadPropLong, ReadMultiple failed\n");
  77. }
  78. pIWiaPropStg->Release();
  79. return hr;
  80. }
  81. /**************************************************************************\
  82. * proxyWritePropLong
  83. *
  84. * Read property long helper.
  85. *
  86. * Arguments:
  87. *
  88. * pItem - Pointer to WIA item
  89. * propid - Property ID
  90. * lVal - LONG value to write
  91. *
  92. * Return Value:
  93. *
  94. * Status
  95. *
  96. * History:
  97. *
  98. * 1/19/1999 Original Version
  99. *
  100. \**************************************************************************/
  101. HRESULT WINAPI proxyWritePropLong(
  102. IWiaDataTransfer* pIUnknown,
  103. PROPID propid,
  104. LONG lVal)
  105. {
  106. IWiaPropertyStorage *pIWiaPropStg;
  107. if (!pIUnknown) {
  108. return E_INVALIDARG;
  109. }
  110. HRESULT hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIWiaPropStg);
  111. if (FAILED(hr)) {
  112. DPRINT("proxyWritePropLong, QI for IID_IWiaPropertyStorage failed\n");
  113. return hr;
  114. }
  115. PROPSPEC propspec[1];
  116. PROPVARIANT propvar[1];
  117. propspec[0].ulKind = PRSPEC_PROPID;
  118. propspec[0].propid = propid;
  119. propvar[0].vt = VT_I4;
  120. propvar[0].lVal = lVal;
  121. hr = pIWiaPropStg->WriteMultiple(1, propspec, propvar, 2);
  122. if (FAILED(hr)) {
  123. DPRINT("proxyWritePropLong, WriteMultiple failed\n");
  124. }
  125. pIWiaPropStg->Release();
  126. return hr;
  127. }
  128. /**************************************************************************\
  129. * proxyReadPropGuid
  130. *
  131. * Read property GUID helper.
  132. *
  133. * Arguments:
  134. *
  135. * pIUnknown - Pointer to WIA item
  136. * propid - Property ID
  137. * plVal - Pointer to returned GUID
  138. *
  139. * Return Value:
  140. *
  141. * Status
  142. *
  143. * History:
  144. *
  145. * 1/19/1999 Original Version
  146. *
  147. \**************************************************************************/
  148. HRESULT WINAPI proxyReadPropGuid(
  149. IUnknown *pIUnknown,
  150. PROPID propid,
  151. GUID *plVal)
  152. {
  153. HRESULT hr = E_FAIL;
  154. IWiaPropertyStorage *pIWiaPropStg = NULL;
  155. PROPSPEC PropSpec[1];
  156. PROPVARIANT PropVar[1];
  157. UINT cbSize;
  158. if (!pIUnknown) {
  159. return E_INVALIDARG;
  160. }
  161. hr = pIUnknown->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIWiaPropStg);
  162. if (FAILED(hr)) {
  163. DPRINT("proxyReadPropGuid, QI failed\n");
  164. return hr;
  165. }
  166. memset(PropVar, 0, sizeof(PropVar));
  167. PropSpec[0].ulKind = PRSPEC_PROPID;
  168. PropSpec[0].propid = propid;
  169. hr = pIWiaPropStg->ReadMultiple(1, PropSpec, PropVar);
  170. if (SUCCEEDED(hr)) {
  171. *plVal = *(PropVar[0].puuid);
  172. }
  173. else {
  174. DPRINT("proxyReadPropGuid, QI failed\n");
  175. }
  176. pIWiaPropStg->Release();
  177. return hr;
  178. }
  179. //
  180. // IWiaDataTransfer
  181. //
  182. HRESULT GetRemoteStatus(
  183. IWiaDataTransfer* idt,
  184. BOOL* pbRemote,
  185. ULONG* pulMinBufferSize,
  186. ULONG* pulItemSize)
  187. {
  188. //
  189. // find out if parent device is remote or local
  190. //
  191. // !!! this will be a bit SLOW !!!
  192. //
  193. IWiaItem *pWiaItem = NULL, *pWiaItemRoot = NULL;
  194. IWiaPropertyStorage *pIWiaPropStg = NULL;
  195. HRESULT hr;
  196. *pbRemote = FALSE;
  197. hr = idt->QueryInterface(IID_IWiaItem, (void **)&pWiaItem);
  198. if (hr == S_OK) {
  199. //
  200. // Read the minimum buffer size
  201. //
  202. if (pulMinBufferSize != NULL) {
  203. hr = pWiaItem->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIWiaPropStg);
  204. if (SUCCEEDED(hr)) {
  205. PROPSPEC PSpec[2] = {
  206. {PRSPEC_PROPID, WIA_IPA_MIN_BUFFER_SIZE},
  207. {PRSPEC_PROPID, WIA_IPA_ITEM_SIZE}
  208. };
  209. PROPVARIANT PVar[2];
  210. memset(PVar, 0, sizeof(PVar));
  211. hr = pIWiaPropStg->ReadMultiple(sizeof(PSpec)/sizeof(PROPSPEC),
  212. PSpec,
  213. PVar);
  214. if (SUCCEEDED(hr)) {
  215. if (hr == S_FALSE) {
  216. //
  217. // Property was not found
  218. //
  219. DPRINT("GetRemoteStatus, properties not found\n");
  220. goto Cleanup;
  221. }
  222. //
  223. // Fill in the minimum buffer size
  224. //
  225. *pulMinBufferSize = PVar[0].lVal;
  226. *pulItemSize = PVar[1].lVal;
  227. } else {
  228. //
  229. // Error reading property
  230. //
  231. DPRINT("GetRemoteStatus, Error reading MIN_BUFFER_SIZE\n");
  232. goto Cleanup;
  233. }
  234. FreePropVariantArray(sizeof(PVar)/sizeof(PVar[0]), PVar);
  235. pIWiaPropStg->Release();
  236. } else {
  237. DPRINT("GetRemoteStatus, QI for IID_IWiaPropertyStorage failed\n");
  238. goto Cleanup;
  239. }
  240. }
  241. hr = pWiaItem->GetRootItem(&pWiaItemRoot);
  242. if (hr == S_OK) {
  243. hr = pWiaItemRoot->QueryInterface(IID_IWiaPropertyStorage, (void **)&pIWiaPropStg);
  244. if (hr == S_OK) {
  245. PROPSPEC PropSpec[2] = {{PRSPEC_PROPID, WIA_DIP_SERVER_NAME},
  246. {PRSPEC_PROPID, WIA_IPA_FULL_ITEM_NAME}};
  247. PROPVARIANT PropVar[2];
  248. memset(PropVar, 0, sizeof(PropVar));
  249. hr = pIWiaPropStg->ReadMultiple(sizeof(PropSpec)/sizeof(PROPSPEC),
  250. PropSpec,
  251. PropVar);
  252. if (hr == S_OK) {
  253. if (wcscmp(L"local", PropVar[0].bstrVal) != 0) {
  254. *pbRemote = TRUE;
  255. }
  256. }
  257. FreePropVariantArray(sizeof(PropVar)/sizeof(PropVar[0]), PropVar);
  258. } else {
  259. DPRINT("QI for IID_WiaPropertyStorage failed");
  260. }
  261. }
  262. }
  263. Cleanup:
  264. if(pIWiaPropStg) pIWiaPropStg->Release();
  265. if(pWiaItem) pWiaItem->Release();
  266. if(pWiaItemRoot) pWiaItemRoot->Release();
  267. return hr;
  268. }
  269. /*******************************************************************************
  270. *
  271. * RemoteBandedDataTransfer
  272. *
  273. * DESCRIPTION:
  274. *
  275. *
  276. * PARAMETERS:
  277. *
  278. *******************************************************************************/
  279. HRESULT RemoteBandedDataTransfer(
  280. IWiaDataTransfer __RPC_FAR *This,
  281. PWIA_DATA_TRANSFER_INFO pWiaDataTransInfo,
  282. IWiaDataCallback *pIWiaDataCallback,
  283. ULONG ulBufferSize)
  284. {
  285. HRESULT hr = E_FAIL;
  286. IWiaItemInternal *pIWiaItemInternal = NULL;
  287. STGMEDIUM medium = { TYMED_NULL, 0 };
  288. BYTE *pBuffer = NULL;
  289. ULONG cbTransferred;
  290. LONG Message;
  291. LONG Offset;
  292. LONG Status;
  293. LONG PercentComplete;
  294. LONG ulBytesPerLine;
  295. hr = proxyReadPropLong(This, WIA_IPA_BYTES_PER_LINE, &ulBytesPerLine);
  296. if(FAILED(hr)) {
  297. DPRINT("IWiaDataCallback_RemoteFileTransfer failed getting WIA_IPA_BYTES_PER_LINE\n");
  298. goto Cleanup;
  299. }
  300. //
  301. // Make sure the transfer buffer has integral number of lines
  302. // (if we know bytes per line)
  303. //
  304. if(ulBytesPerLine != 0 && ulBufferSize % ulBytesPerLine)
  305. {
  306. ulBufferSize -= ulBufferSize % ulBytesPerLine;
  307. }
  308. //
  309. // Prepare for remote transfer -- allocate buffer and get
  310. // IWiaItemInternal
  311. //
  312. pBuffer = (BYTE *)LocalAlloc(LPTR, ulBufferSize);
  313. if(pBuffer == NULL) goto Cleanup;
  314. hr = This->QueryInterface(IID_IWiaItemInternal, (void **) &pIWiaItemInternal);
  315. if(FAILED(hr)) {
  316. DPRINT("IWiaItemInternal QI failed\n");
  317. goto Cleanup;
  318. }
  319. //
  320. // Start transfer on the server side
  321. //
  322. hr = pIWiaItemInternal->idtStartRemoteDataTransfer(&medium);
  323. if(FAILED(hr)) {
  324. DPRINT("RemoteBandedTransfer:idtStartRemoteDataTransfer failed\n");
  325. goto Cleanup;
  326. }
  327. for(;;) {
  328. //
  329. // Call the server and pass any results to the client application, handling any transmission errors
  330. //
  331. hr = pIWiaItemInternal->idtRemoteDataTransfer(ulBufferSize, &cbTransferred, pBuffer, &Offset, &Message, &Status, &PercentComplete);
  332. if(FAILED(hr)) {
  333. DPRINT("pIWiaItemInternal->idtRemoteDataTransfer() failed\n");
  334. break;
  335. }
  336. hr = pIWiaDataCallback->BandedDataCallback(Message, Status, PercentComplete, Offset, cbTransferred, 0, cbTransferred, pBuffer);
  337. if(FAILED(hr)) {
  338. DPRINT("pWiaDataCallback->BandedDataCallback() failed\n");
  339. break;
  340. }
  341. if(hr == S_FALSE) {
  342. DPRINT("pWiaDataCallback->BandedDataCallback() returned FALSE, cancelling\n");
  343. pIWiaItemInternal->idtCancelRemoteDataTransfer();
  344. while(Message != IT_MSG_TERMINATION) {
  345. if(FAILED(pIWiaItemInternal->idtRemoteDataTransfer(ulBufferSize, &cbTransferred,
  346. pBuffer, &Offset, &Message, &Status, &PercentComplete)))
  347. {
  348. DPRINT("pIWiaItemInternal->idtRemoteDataTransfer() failed\n");
  349. break;
  350. }
  351. }
  352. break;
  353. }
  354. //
  355. // This we are garanteed to get at the end of the transfer
  356. //
  357. if(Message == IT_MSG_TERMINATION)
  358. break;
  359. }
  360. //
  361. // Give server a chance to stop the transfer and free any resources
  362. //
  363. if(FAILED(pIWiaItemInternal->idtStopRemoteDataTransfer())) {
  364. DPRINT("pIWiaItemInternal->idtStopRemoteDataTransfer() failed\n");
  365. }
  366. Cleanup:
  367. if(pIWiaItemInternal) pIWiaItemInternal->Release();
  368. if(pBuffer) LocalFree(pBuffer);
  369. return hr;
  370. }
  371. /*******************************************************************************
  372. *
  373. * IWiaDataTransfer_idtGetBandedData_Proxy
  374. *
  375. * DESCRIPTION:
  376. * Data transfer using shared memory buffer when possible.
  377. *
  378. * PARAMETERS:
  379. *
  380. *******************************************************************************/
  381. HRESULT __stdcall IWiaDataTransfer_idtGetBandedData_Proxy(
  382. IWiaDataTransfer __RPC_FAR *This,
  383. PWIA_DATA_TRANSFER_INFO pWiaDataTransInfo,
  384. IWiaDataCallback *pIWiaDataCallback)
  385. {
  386. HRESULT hr = S_OK;
  387. HANDLE hTransferBuffer;
  388. PBYTE pTransferBuffer = NULL;
  389. BOOL bAppSection;
  390. ULONG ulNumBuffers;
  391. ULONG ulMinBufferSize;
  392. ULONG ulItemSize;
  393. //
  394. // Do parameter validation
  395. //
  396. if(!pIWiaDataCallback) {
  397. return E_INVALIDARG;
  398. }
  399. if (!pWiaDataTransInfo) {
  400. DPRINT("IWiaDataTransfer_idtGetBandedData_Proxy, Can't determine remote status\n");
  401. return hr;
  402. }
  403. //
  404. // The size specified by the client must match the proxy's version
  405. //
  406. if (pWiaDataTransInfo->ulSize != sizeof(WIA_DATA_TRANSFER_INFO)) {
  407. return (E_INVALIDARG);
  408. }
  409. //
  410. // The reserved parameters must be ZERO
  411. //
  412. if ((pWiaDataTransInfo->ulReserved1) ||
  413. (pWiaDataTransInfo->ulReserved2) ||
  414. (pWiaDataTransInfo->ulReserved3)) {
  415. return (E_INVALIDARG);
  416. }
  417. //
  418. // determine if this is a local or remote case
  419. //
  420. BOOL bRemote;
  421. hr = GetRemoteStatus(This, &bRemote, &ulMinBufferSize, &ulItemSize);
  422. if (hr != S_OK) {
  423. DPRINT("IWiaDataTransfer_idtGetBandedData_Proxy, Can't determine remote status\n");
  424. return hr;
  425. }
  426. if (pWiaDataTransInfo->ulBufferSize < ulMinBufferSize) {
  427. pWiaDataTransInfo->ulBufferSize = ulMinBufferSize;
  428. }
  429. if (pWiaDataTransInfo->bDoubleBuffer) {
  430. ulNumBuffers = 2;
  431. } else {
  432. ulNumBuffers = 1;
  433. }
  434. pWiaDataTransInfo->ulReserved3 = ulNumBuffers;
  435. hr = RemoteBandedDataTransfer(This, pWiaDataTransInfo, pIWiaDataCallback, ulMinBufferSize);
  436. return hr;
  437. }
  438. /*******************************************************************************
  439. *
  440. * IWiaDataTransfer_idtGetBandedData_Stub
  441. *
  442. * DESCRIPTION:
  443. * User Stub for the call_as idtGetBandedDataEx
  444. *
  445. * PARAMETERS:
  446. *
  447. *******************************************************************************/
  448. HRESULT __stdcall IWiaDataTransfer_idtGetBandedData_Stub(
  449. IWiaDataTransfer __RPC_FAR *This,
  450. PWIA_DATA_TRANSFER_INFO pWiaDataTransInfo,
  451. IWiaDataCallback *pIWiaDataCallback)
  452. {
  453. return (This->idtGetBandedData(pWiaDataTransInfo,
  454. pIWiaDataCallback));
  455. }
  456. /**************************************************************************\
  457. * IWiaDataCallback_BandedDataCallback_Proxy
  458. *
  459. * server callback proxy, just a pass-through
  460. *
  461. * Arguments:
  462. *
  463. *
  464. *
  465. * Return Value:
  466. *
  467. * Status
  468. *
  469. * History:
  470. *
  471. * 1/6/1999 Original Version
  472. *
  473. \**************************************************************************/
  474. HRESULT IWiaDataCallback_BandedDataCallback_Proxy(
  475. IWiaDataCallback __RPC_FAR *This,
  476. LONG lMessage,
  477. LONG lStatus,
  478. LONG lPercentComplete,
  479. LONG lOffset,
  480. LONG lLength,
  481. LONG lReserved,
  482. LONG lResLength,
  483. BYTE *pbBuffer)
  484. {
  485. HRESULT hr = IWiaDataCallback_RemoteBandedDataCallback_Proxy(This,
  486. lMessage,
  487. lStatus,
  488. lPercentComplete,
  489. lOffset,
  490. lLength,
  491. lReserved,
  492. lResLength,
  493. pbBuffer);
  494. return hr;
  495. }
  496. /**************************************************************************\
  497. * IWiaDataCallback_BandedDataCallback_Stub
  498. *
  499. * Obsolete: Hide from the client (receiver of this call) the fact that the buffer
  500. * they see might be the shared memory window or it might be a standard
  501. * marshaled buffer (remote case)
  502. *
  503. * Arguments:
  504. *
  505. *
  506. *
  507. * Return Value:
  508. *
  509. * Status
  510. *
  511. * History:
  512. *
  513. * 1/6/1999 Original Version
  514. *
  515. \**************************************************************************/
  516. HRESULT IWiaDataCallback_BandedDataCallback_Stub(
  517. IWiaDataCallback __RPC_FAR *This,
  518. LONG lMessage,
  519. LONG lStatus,
  520. LONG lPercentComplete,
  521. LONG lOffset,
  522. LONG lLength,
  523. LONG lReserved,
  524. LONG lResLength,
  525. BYTE *pbBuffer)
  526. {
  527. //
  528. // 64bit fix. XP client code:
  529. //
  530. // //
  531. // // pass transfer buffer back to client in pbBuffer
  532. // //
  533. // //
  534. // if (pbBuffer == NULL) {
  535. //
  536. // // NOTE: Possible problem here!!!!!!
  537. // // The caller had to cast a pointer (possibly 64bit) as ULONG (32bit)
  538. // // to fit into ulReserved field
  539. //
  540. // // TO FIX: Use the IWiaItemInternal interface to get transfer info
  541. //
  542. // pbBuffer = (BYTE *)ULongToPtr(lReserved);
  543. // }
  544. //
  545. //
  546. // This should no longer be needed, since the we now use
  547. // normal COM marhsalling, and no shared memory buffer.
  548. // The shared memory window could not work on 64bit
  549. // because a 32bit field was being used to store a
  550. // 64bit pointer on Win64.
  551. //
  552. HRESULT hr = This->BandedDataCallback(lMessage,
  553. lStatus,
  554. lPercentComplete,
  555. lOffset,
  556. lLength,
  557. lReserved,
  558. lResLength,
  559. pbBuffer);
  560. return hr;
  561. }
  562. HRESULT FileDataTransfer(IWiaDataTransfer __RPC_FAR *This,
  563. LPSTGMEDIUM pMedium,
  564. IWiaDataCallback *pIWiaDataCallback,
  565. ULONG tymed,
  566. ULONG ulminBufferSize,
  567. ULONG ulItemSize)
  568. {
  569. HRESULT hr = S_OK;
  570. TCHAR tszFileNameBuffer[MAX_PATH] = { 0 };
  571. BOOL bWeAllocatedString = FALSE;
  572. HANDLE hFile = INVALID_HANDLE_VALUE;
  573. IWiaItemInternal *pIWiaItemInternal = NULL;
  574. BYTE *pTransferBuffer = NULL;
  575. ULONG ulTransferBufferSize = 0x8000; // 32K transfer buffer
  576. ULONG cbTransferred;
  577. LONG Message;
  578. LONG Offset;
  579. LONG Status;
  580. LONG PercentComplete;
  581. BOOL bKeepFile = FALSE;
  582. PSECURITY_DESCRIPTOR pSD = NULL;
  583. PACL pAcl = NULL, pNewAcl = NULL;
  584. PSID pLocalService = NULL;
  585. BOOL bAdjustedSecurity = FALSE;
  586. pTransferBuffer = (BYTE *)LocalAlloc(LPTR, ulTransferBufferSize);
  587. if(pTransferBuffer == NULL) {
  588. hr = HRESULT_FROM_WIN32(::GetLastError());
  589. DPRINT("IWiaDataCallback_RemoteFileTransfer failed to allocate transfer buffer\n");
  590. goto Cleanup;
  591. }
  592. //
  593. // Check whether a filename has been specified. If not, generate a tempory one.
  594. // NOTE: We do this on the CLIENT-SIDE so we get the client's temp path.
  595. //
  596. if (!pMedium->lpszFileName) {
  597. DWORD dwRet = GetTempPath(MAX_PATH, tszFileNameBuffer);
  598. if ((dwRet == 0) || (dwRet > MAX_PATH)) {
  599. hr = HRESULT_FROM_WIN32(::GetLastError());
  600. DPRINT("GetTempPath failed");
  601. goto Cleanup;
  602. }
  603. if (!GetTempFileName(tszFileNameBuffer,
  604. TEXT("WIA"),
  605. 0,
  606. tszFileNameBuffer))
  607. {
  608. hr = HRESULT_FROM_WIN32(::GetLastError());
  609. DPRINT("GetTempFileName failed");
  610. goto Cleanup;
  611. }
  612. } else {
  613. //
  614. // Copy the filename into tszFileNameBuffer. This will be used if we
  615. // have to delete the file when the transfer fails.
  616. //
  617. #ifndef UNICODE
  618. //
  619. // Convert from UNICODE to ANSI
  620. //
  621. if (!WideCharToMultiByte(CP_ACP, 0, pMedium->lpszFileName, -1, tszFileNameBuffer, MAX_PATH, NULL, NULL)) {
  622. hr = HRESULT_FROM_WIN32(::GetLastError());
  623. DPRINT("WideCharToMultiByte failed");
  624. goto Cleanup;
  625. }
  626. #else
  627. lstrcpynW(tszFileNameBuffer, pMedium->lpszFileName, MAX_PATH);
  628. #endif
  629. }
  630. //
  631. // Try to create the file here, so we don't waste time by allocating memory
  632. // for the filename if it fails.
  633. // NOTE: We create the file here on the client-side. We can close the file straight
  634. // away, but we want to have it created with client's credentials. It will simply be
  635. // opened on the server-side.
  636. //
  637. hFile = CreateFile(tszFileNameBuffer,
  638. GENERIC_READ | GENERIC_WRITE,
  639. FILE_SHARE_WRITE,
  640. NULL,
  641. CREATE_ALWAYS,
  642. FILE_ATTRIBUTE_NORMAL | SECURITY_ANONYMOUS | SECURITY_SQOS_PRESENT,
  643. NULL);
  644. if (hFile == INVALID_HANDLE_VALUE) {
  645. hr = HRESULT_FROM_WIN32(::GetLastError());
  646. DPRINT("Failed to create file");
  647. goto Cleanup;
  648. } else {
  649. //
  650. // Check that this is a file
  651. //
  652. if (GetFileType(hFile) != FILE_TYPE_DISK)
  653. {
  654. hr = E_INVALIDARG;
  655. DPRINT("WIA will only transfer to files of type FILE_TYPE_DISK.");
  656. goto Cleanup;
  657. }
  658. //
  659. // close file handle, adjust security
  660. //
  661. SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
  662. EXPLICIT_ACCESS ea = { 0 };
  663. DWORD dwResult;
  664. CloseHandle(hFile);
  665. hFile = INVALID_HANDLE_VALUE;
  666. dwResult = GetNamedSecurityInfo(
  667. tszFileNameBuffer,
  668. SE_FILE_OBJECT,
  669. DACL_SECURITY_INFORMATION,
  670. NULL,
  671. NULL,
  672. &pAcl,
  673. NULL,
  674. &pSD);
  675. if(dwResult == ERROR_SUCCESS && pAcl != NULL) {
  676. if(AllocateAndInitializeSid(&SIDAuthNT, 1,
  677. SECURITY_LOCAL_SERVICE_RID,
  678. 0,
  679. 0, 0, 0, 0, 0, 0,
  680. &pLocalService) && pLocalService)
  681. {
  682. ea.grfAccessPermissions = FILE_ALL_ACCESS;
  683. ea.grfAccessMode = SET_ACCESS;
  684. ea.grfInheritance = NO_INHERITANCE;
  685. ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
  686. ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
  687. ea.Trustee.ptstrName = (LPTSTR) pLocalService;
  688. dwResult = SetEntriesInAcl(1, &ea, pAcl, &pNewAcl);
  689. if(dwResult == ERROR_SUCCESS && pNewAcl != NULL)
  690. {
  691. dwResult = SetNamedSecurityInfo(tszFileNameBuffer,
  692. SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
  693. NULL, NULL, pNewAcl, NULL);
  694. if(dwResult == ERROR_SUCCESS) {
  695. bAdjustedSecurity = TRUE;
  696. } else {
  697. DPRINT("Failure to update file DACL");
  698. }
  699. } else {
  700. DPRINT("Failure to set ACE in the file DACL");
  701. }
  702. } else {
  703. DPRINT("Failure to allocate and LocalService SID");
  704. }
  705. } else {
  706. DPRINT("Failure to retrieve file security information");
  707. }
  708. }
  709. if (!pMedium->lpszFileName) {
  710. //
  711. // Assign the file name to pMedium
  712. //
  713. DWORD length = lstrlen(tszFileNameBuffer) + 1;
  714. pMedium->lpszFileName = (LPOLESTR)CoTaskMemAlloc(length * sizeof(WCHAR));
  715. if (!pMedium->lpszFileName) {
  716. hr = E_OUTOFMEMORY;
  717. DPRINT("Failed to allocate temp file name");
  718. goto Cleanup;
  719. }
  720. bWeAllocatedString = TRUE;
  721. #ifndef UNICODE
  722. //
  723. // Do conversion from ANSI to UNICODE
  724. //
  725. if (!MultiByteToWideChar(CP_ACP, 0, tszFileNameBuffer, -1, pMedium->lpszFileName, length)) {
  726. hr = HRESULT_FROM_WIN32(::GetLastError());
  727. goto Cleanup;
  728. }
  729. #else
  730. lstrcpyW(pMedium->lpszFileName, tszFileNameBuffer);
  731. #endif
  732. }
  733. //
  734. // We unconditionally set the STGMEDIUM's tymed to TYMED_FILE. This is because
  735. // COM wont marshall the filename if it's is TYMED_MULTIPAGE_FILE, since
  736. // it doesn't recognize it. This is OK, since the service doesn't use
  737. // pMedium->tymed.
  738. //
  739. pMedium->tymed = TYMED_FILE;
  740. //
  741. // Finally, we're ready to do the transfer
  742. //
  743. hr = This->QueryInterface(IID_IWiaItemInternal, (void **) &pIWiaItemInternal);
  744. if(FAILED(hr)) {
  745. DPRINT("IWiaDataCallback_RemoteFileTransfer failed to obtain IWiaItemInternal\n");
  746. goto Cleanup;
  747. }
  748. //
  749. // Start transfer on the server side
  750. //
  751. hr = pIWiaItemInternal->idtStartRemoteDataTransfer(pMedium);
  752. if(FAILED(hr)) {
  753. DPRINT("IWiaDataCallback_RemoteFileTransfer idtStartRemoteDataTransfer() failed\n");
  754. goto Cleanup;
  755. }
  756. for(;;) {
  757. //
  758. // Call the server and pass any results to the client application, handling any transmission errors
  759. //
  760. hr = pIWiaItemInternal->idtRemoteDataTransfer(ulTransferBufferSize,
  761. &cbTransferred, pTransferBuffer, &Offset, &Message, &Status,
  762. &PercentComplete);
  763. if(FAILED(hr)) {
  764. //
  765. // special case: multipage file transfer that resulted in
  766. // paper handling error
  767. //
  768. if(tymed == TYMED_MULTIPAGE_FILE &&
  769. (hr == WIA_ERROR_PAPER_JAM || hr == WIA_ERROR_PAPER_EMPTY || hr == WIA_ERROR_PAPER_PROBLEM))
  770. {
  771. // make note not to delete file and store hr so we can
  772. // return it to the app
  773. bKeepFile = TRUE;
  774. }
  775. DPRINT("IWiaDataCallback_RemoteFileTransfer idtRemoteDataTransfer() failed\n");
  776. break;
  777. }
  778. //
  779. // If there is app-provided callback, call it
  780. //
  781. if(pIWiaDataCallback) {
  782. hr = pIWiaDataCallback->BandedDataCallback(Message,
  783. Status, PercentComplete, Offset, cbTransferred,
  784. 0, cbTransferred, pTransferBuffer);
  785. if(FAILED(hr)) {
  786. DPRINT("pWiaDataCallback->BandedDataCallback() failed\n");
  787. break;
  788. }
  789. if(hr == S_FALSE) {
  790. DPRINT("pWiaDataCallback->BandedDataCallback() returned FALSE, cancelling\n");
  791. pIWiaItemInternal->idtCancelRemoteDataTransfer();
  792. while(Message != IT_MSG_TERMINATION) {
  793. if(FAILED(pIWiaItemInternal->idtRemoteDataTransfer(ulTransferBufferSize,
  794. &cbTransferred, pTransferBuffer, &Offset, &Message, &Status,
  795. &PercentComplete)))
  796. {
  797. DPRINT("pIWiaItemInternal->idtRemoteDataTransfer() failed\n");
  798. break;
  799. }
  800. }
  801. break;
  802. }
  803. }
  804. //
  805. // This we are garanteed to get at the end of the transfer
  806. //
  807. if(Message == IT_MSG_TERMINATION)
  808. break;
  809. }
  810. //
  811. // Give server a chance to stop the transfer and free any resources
  812. //
  813. if(FAILED(pIWiaItemInternal->idtStopRemoteDataTransfer())) {
  814. DPRINT("IWiaDataCallback_RemoteFileTransfer idtStopDataTransfer() failed\n");
  815. }
  816. Cleanup:
  817. if(pIWiaItemInternal) pIWiaItemInternal->Release();
  818. if (hFile && (hFile != INVALID_HANDLE_VALUE))
  819. {
  820. CloseHandle(hFile);
  821. hFile = INVALID_HANDLE_VALUE;
  822. }
  823. //
  824. // Remove the temporary file if the transfer failed, and we must free the filename string if we
  825. // allocated.
  826. // NOTE: We only delete the file if we were the ones that generated the name i.e. it's a temporary
  827. // file.
  828. //
  829. if (FAILED(hr) && bWeAllocatedString)
  830. {
  831. // special case: multipage file transfers that
  832. // resulted in paper jam or empty feeder or other paper
  833. // problem
  834. if(!bKeepFile) {
  835. DeleteFile(tszFileNameBuffer);
  836. }
  837. CoTaskMemFree(pMedium->lpszFileName);
  838. pMedium->lpszFileName = NULL;
  839. }
  840. if(bAdjustedSecurity) {
  841. SetNamedSecurityInfo(tszFileNameBuffer, SE_FILE_OBJECT,
  842. DACL_SECURITY_INFORMATION, NULL, NULL, pAcl, NULL);
  843. }
  844. if(pSD) LocalFree(pSD);
  845. if(pNewAcl) LocalFree(pNewAcl);
  846. if(pLocalService) LocalFree(pLocalService);
  847. if(pTransferBuffer) LocalFree(pTransferBuffer);
  848. return hr;
  849. }
  850. /*******************************************************************************
  851. * IWiaDataCallback_idtGetData_Proxy
  852. *
  853. * DESCRIPTION:
  854. * Allocates a shared memory buffer for image transfer.
  855. *
  856. * PARAMETERS:
  857. *
  858. *******************************************************************************/
  859. HRESULT IWiaDataTransfer_idtGetData_Proxy(
  860. IWiaDataTransfer __RPC_FAR *This,
  861. LPSTGMEDIUM pMedium,
  862. IWiaDataCallback *pIWiaDataCallback)
  863. {
  864. HRESULT hr = S_OK;
  865. LONG tymed;
  866. ULONG ulminBufferSize = 0;
  867. ULONG ulItemSize = 0;
  868. BOOL bRemote;
  869. //
  870. // !!!perf: should do all server stuf with 1 call
  871. // this includes QIs, get root item, read props
  872. //
  873. hr = proxyReadPropLong(This, WIA_IPA_TYMED, &tymed);
  874. if (hr != S_OK) {
  875. DPRINT("IWiaDataTransfer_idtGetData_Proxy, failed to read WIA_IPA_TYMED\n");
  876. return hr;
  877. }
  878. //
  879. // find out if the transfer is remote
  880. //
  881. hr = GetRemoteStatus(This, &bRemote, &ulminBufferSize, &ulItemSize);
  882. if (hr != S_OK) {
  883. DPRINT("IWiaDataTransfer_idtGetData_Proxy, Can't determine remote status\n");
  884. return hr;
  885. }
  886. if (tymed != TYMED_FILE && tymed != TYMED_MULTIPAGE_FILE) {
  887. //
  888. // remote callback data transfer
  889. //
  890. if(pIWiaDataCallback)
  891. {
  892. hr = RemoteBandedDataTransfer(This,
  893. NULL,
  894. pIWiaDataCallback,
  895. ulminBufferSize);
  896. }
  897. else
  898. {
  899. hr = E_INVALIDARG;
  900. }
  901. } else {
  902. hr = FileDataTransfer(This,
  903. pMedium,
  904. pIWiaDataCallback,
  905. tymed,
  906. ulminBufferSize,
  907. ulItemSize);
  908. }
  909. return hr;
  910. }
  911. /*******************************************************************************
  912. * IWiaDataCallback_idtGetData_Stub
  913. *
  914. * DESCRIPTION:
  915. * Allocates a shared memory buffer for image transfer.
  916. *
  917. * PARAMETERS:
  918. *
  919. *******************************************************************************/
  920. HRESULT IWiaDataTransfer_idtGetData_Stub(
  921. IWiaDataTransfer __RPC_FAR *This,
  922. LPSTGMEDIUM pMedium,
  923. IWiaDataCallback *pIWiaDataCallback)
  924. {
  925. return (This->idtGetData(pMedium, pIWiaDataCallback));
  926. }