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.

1747 lines
47 KiB

  1. // avifps.cpp - proxy and stub code for IAVIFile & IAVIStream
  2. //
  3. //
  4. // Copyright (c) 1993 - 1995 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // History:
  7. // Created by DavidMay 6/19/93
  8. //
  9. //
  10. // What's in this file:
  11. //
  12. // Code to enable "standard marshalling" of the IAVIFile and IAVIStream
  13. // interfaces, consisting of the following classes:
  14. //
  15. // CPSFactory, derived from IPSFactory:
  16. // Proxy/stub factory, called from DllGetClassObject to create
  17. // the other classes.
  18. //
  19. // CPrxAVIStream, derived from IAVIStream:
  20. // This class serves as a stand-in for the interface in the app that's
  21. // calling it. Uses RPC to communicate with....
  22. //
  23. // CStubAVIStream, derived from IRpcStubBuffer:
  24. // This class in the called app receives requests from the proxy
  25. // and forwards them to the actual implementation of the IAVIStream.
  26. //
  27. // CPrxAVIFile & CStubAVIFile, just like the stream versions.
  28. //
  29. //
  30. // Also included:
  31. // The function TaskHasExistingProxies can be used by an application
  32. // before exiting to check whether any of its objects are being used
  33. // by other applications. This is done by keeping track of what active
  34. // stubs exist within a given task context.
  35. //
  36. #include <win32.h>
  37. #pragma warning(disable:4355)
  38. #include <vfw.h>
  39. #include "avifps.h"
  40. #include "debug.h"
  41. #include "olehack.h"
  42. #ifndef _WIN32
  43. #define PropagateResult(hrOld, scNew) ResultFromScode(scNew)
  44. #endif
  45. // when thunking between 16-bit ansi and 32-bit unicode apps, the
  46. // AVISTREAMINFO and AVIFILEINFO structures are different. What is transmitted
  47. // is a common format that includes space for both unicode and ansi strings.
  48. // ansi apps will not send or use the unicode strings. unicode apps will send
  49. // both.
  50. typedef struct _PS_STREAMINFO {
  51. DWORD fccType;
  52. DWORD fccHandler;
  53. DWORD dwFlags; /* Contains AVITF_* flags */
  54. DWORD dwCaps;
  55. WORD wPriority;
  56. WORD wLanguage;
  57. DWORD dwScale;
  58. DWORD dwRate; /* dwRate / dwScale == samples/second */
  59. DWORD dwStart;
  60. DWORD dwLength; /* In units above... */
  61. DWORD dwInitialFrames;
  62. DWORD dwSuggestedBufferSize;
  63. DWORD dwQuality;
  64. DWORD dwSampleSize;
  65. POINTS ptFrameTopLeft;
  66. POINTS ptFrameBottomRight;
  67. DWORD dwEditCount;
  68. DWORD dwFormatChangeCount;
  69. char szName[64];
  70. DWORD bHasUnicode;
  71. WCHAR szUnicodeName[64];
  72. } PS_STREAMINFO, FAR * LPPS_STREAMINFO;
  73. typedef struct _PS_FILEINFO {
  74. DWORD dwMaxBytesPerSec; // max. transfer rate
  75. DWORD dwFlags; // the ever-present flags
  76. DWORD dwCaps;
  77. DWORD dwStreams;
  78. DWORD dwSuggestedBufferSize;
  79. DWORD dwWidth;
  80. DWORD dwHeight;
  81. DWORD dwScale;
  82. DWORD dwRate; /* dwRate / dwScale == samples/second */
  83. DWORD dwLength;
  84. DWORD dwEditCount;
  85. char szFileType[64]; // descriptive string for file type?
  86. DWORD bHasUnicode;
  87. WCHAR szUnicodeType[64];
  88. } PS_FILEINFO, FAR * LPPS_FILEINFO;
  89. #ifndef _WIN32
  90. //
  91. // These constants are defined in the 32-bit UUID.LIB, but not
  92. // in any 16-bit LIB. They are stolen here from the .IDL files
  93. // in the TYPES project.
  94. //
  95. extern "C" {
  96. const IID IID_IRpcStubBuffer = {0xD5F56AFC,0x593b,0x101A,{0xB5,0x69,0x08,0x00,0x2B,0x2D,0xBF,0x7A}};
  97. const IID IID_IRpcProxyBuffer = {0xD5F56A34,0x593b,0x101A,{0xB5,0x69,0x08,0x00,0x2B,0x2D,0xBF,0x7A}};
  98. const IID IID_IPSFactoryBuffer = {0xD5F569D0,0x593b,0x101A,{0xB5,0x69,0x08,0x00,0x2B,0x2D,0xBF,0x7A}};
  99. }
  100. #endif
  101. // functions for proxy/stub usage tracking; see end of this file.
  102. void UnregisterStubUsage(void);
  103. void RegisterStubUsage(void);
  104. extern "C" BOOL FAR TaskHasExistingProxies(void);
  105. #if 0 // this function is actually in classobj.cpp,
  106. // but if this were a separate proxy/stub DLL, it would look like this.
  107. STDAPI DllGetClassObject(const CLSID FAR& rclsid,
  108. const IID FAR& riid,
  109. void FAR* FAR* ppv)
  110. {
  111. HRESULT hresult;
  112. DPF("DllGetClassObject\n");
  113. if (rclsid == CLSID_AVIStreamPS) {
  114. return (*ppv = (LPVOID)new CPSFactory()) != NULL
  115. ? NOERROR : ResultFromScode(E_OUTOFMEMORY);
  116. } else {
  117. return ResultFromScode(E_UNEXPECTED);
  118. }
  119. }
  120. #endif
  121. /*
  122. * IMPLEMENTATION of CPSFactory
  123. *
  124. *
  125. * Note: This Factory supports proxies and stubs for two separate
  126. * interfaces, IID_IAVIFile and IID_IAVIStream.
  127. */
  128. CPSFactory::CPSFactory(void)
  129. {
  130. m_refs = 1;
  131. }
  132. // controlling unknown for PSFactory
  133. STDMETHODIMP CPSFactory::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  134. {
  135. if (iid == IID_IUnknown || iid == IID_IPSFactoryBuffer)
  136. {
  137. *ppv = this;
  138. ++m_refs;
  139. return NOERROR;
  140. }
  141. else
  142. {
  143. *ppv = NULL;
  144. return ResultFromScode(E_NOINTERFACE);
  145. }
  146. }
  147. STDMETHODIMP_(ULONG) CPSFactory::AddRef(void)
  148. {
  149. return ++m_refs;
  150. }
  151. STDMETHODIMP_(ULONG) CPSFactory::Release(void)
  152. {
  153. if (--m_refs == 0)
  154. {
  155. delete this;
  156. return 0;
  157. }
  158. return m_refs;
  159. }
  160. // create proxy for given interface
  161. STDMETHODIMP CPSFactory::CreateProxy(IUnknown FAR* pUnkOuter, REFIID iid,
  162. IRpcProxyBuffer FAR* FAR* ppProxy, void FAR* FAR* ppv)
  163. {
  164. IRpcProxyBuffer FAR* pProxy;
  165. HRESULT hresult;
  166. *ppProxy = NULL;
  167. *ppv = NULL;
  168. if (pUnkOuter == NULL)
  169. return ResultFromScode(E_INVALIDARG);
  170. if (iid == IID_IAVIStream) {
  171. if ((pProxy = CPrxAVIStream::Create(pUnkOuter)) == NULL)
  172. return ResultFromScode(E_OUTOFMEMORY);
  173. } else if (iid == IID_IAVIFile) {
  174. if ((pProxy = CPrxAVIFile::Create(pUnkOuter)) == NULL)
  175. return ResultFromScode(E_OUTOFMEMORY);
  176. } else
  177. return ResultFromScode(E_NOINTERFACE);
  178. hresult = pProxy->QueryInterface(iid, ppv);
  179. if (hresult == NOERROR)
  180. *ppProxy = pProxy; // transfer ref to caller
  181. else
  182. pProxy->Release(); // free proxy just created
  183. return hresult;
  184. }
  185. // create stub for given interface
  186. STDMETHODIMP CPSFactory::CreateStub(REFIID iid, IUnknown FAR* pUnkServer, IRpcStubBuffer FAR* FAR* ppStub)
  187. {
  188. if (iid == IID_IAVIStream) {
  189. return CStubAVIStream::Create(pUnkServer, ppStub);
  190. } else if (iid == IID_IAVIFile) {
  191. return CStubAVIFile::Create(pUnkServer, ppStub);
  192. } else {
  193. *ppStub = NULL;
  194. return ResultFromScode(E_NOINTERFACE);
  195. }
  196. }
  197. /*
  198. * IMPLEMENTATION of CPrxAVIStream
  199. *
  200. */
  201. // create unconnected CPrxAVIStream; return controlling IProxy/IUnknokwn FAR*
  202. IRpcProxyBuffer FAR* CPrxAVIStream::Create(IUnknown FAR* pUnkOuter)
  203. {
  204. CPrxAVIStream FAR* pPrxAVIStream;
  205. if ((pPrxAVIStream = new CPrxAVIStream(pUnkOuter)) == NULL)
  206. return NULL;
  207. return &pPrxAVIStream->m_Proxy;
  208. }
  209. CPrxAVIStream::CPrxAVIStream(IUnknown FAR* pUnkOuter) : m_Proxy(this)
  210. {
  211. // NOTE: could assert here since we should always be aggregated
  212. if (pUnkOuter == NULL)
  213. pUnkOuter = &m_Proxy;
  214. m_refs = 1;
  215. m_pUnkOuter = pUnkOuter;
  216. m_pRpcChannelBuffer = NULL;
  217. m_sh.fccType = 0;
  218. InitOle(TRUE);
  219. DPF("PrxStream %p: Usage++=%lx\n", (DWORD_PTR) (LPVOID) this, 1L);
  220. }
  221. CPrxAVIStream::~CPrxAVIStream(void)
  222. {
  223. m_Proxy.Disconnect();
  224. TermOle();
  225. }
  226. // Methods for controlling unknown
  227. STDMETHODIMP CPrxAVIStream::CProxyImpl::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  228. {
  229. if (iid == IID_IUnknown || iid == IID_IRpcProxyBuffer)
  230. *ppv = (void FAR *)this;
  231. else if (iid == IID_IAVIStream)
  232. *ppv = (void FAR *)m_pPrxAVIStream;
  233. else {
  234. *ppv = NULL;
  235. return ResultFromScode(E_NOINTERFACE);
  236. }
  237. // simplest way to be correct: always addref the pointer we will return;
  238. // easy since all interfaces here are derived from IUnknown.
  239. ((IUnknown FAR*) *ppv)->AddRef();
  240. return NOERROR;
  241. }
  242. STDMETHODIMP_(ULONG) CPrxAVIStream::CProxyImpl::AddRef(void)
  243. {
  244. return ++m_pPrxAVIStream->m_refs;
  245. }
  246. STDMETHODIMP_(ULONG) CPrxAVIStream::CProxyImpl::Release(void)
  247. {
  248. if (--m_pPrxAVIStream->m_refs == 0)
  249. {
  250. delete m_pPrxAVIStream;
  251. return 0;
  252. }
  253. return m_pPrxAVIStream->m_refs;
  254. }
  255. // connect proxy to channel given
  256. STDMETHODIMP CPrxAVIStream::CProxyImpl::Connect(IRpcChannelBuffer FAR* pRpcChannelBuffer)
  257. {
  258. if (m_pPrxAVIStream->m_pRpcChannelBuffer != NULL)
  259. return ResultFromScode(E_UNEXPECTED);
  260. if (pRpcChannelBuffer == NULL)
  261. return ResultFromScode(E_INVALIDARG);
  262. (m_pPrxAVIStream->m_pRpcChannelBuffer = pRpcChannelBuffer)->AddRef();
  263. return NOERROR;
  264. }
  265. // disconnect proxy from any current channel
  266. STDMETHODIMP_(void) CPrxAVIStream::CProxyImpl::Disconnect(void)
  267. {
  268. if (m_pPrxAVIStream->m_pRpcChannelBuffer)
  269. {
  270. m_pPrxAVIStream->m_pRpcChannelBuffer->Release();
  271. m_pPrxAVIStream->m_pRpcChannelBuffer = NULL;
  272. }
  273. }
  274. // IUnknown methods for external interface(s); always delegate
  275. STDMETHODIMP CPrxAVIStream::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  276. {
  277. return m_pUnkOuter->QueryInterface(iid, ppv);
  278. }
  279. STDMETHODIMP_(ULONG) CPrxAVIStream::AddRef(void)
  280. {
  281. DPF("PrxStream %p: Usage++=%lx\n", (DWORD_PTR) (LPVOID) this, m_refs + 1);
  282. return m_pUnkOuter->AddRef();
  283. }
  284. STDMETHODIMP_(ULONG) CPrxAVIStream::Release(void)
  285. {
  286. DPF("PrxStream %p: Usage--=%lx\n", (DWORD_PTR) (LPVOID) this, m_refs - 1);
  287. return m_pUnkOuter->Release();
  288. }
  289. // IAVIStream interface methods
  290. STDMETHODIMP CPrxAVIStream::Create(LPARAM lParam1, LPARAM lParam2)
  291. {
  292. return ResultFromScode(E_NOTIMPL);
  293. }
  294. #ifdef _WIN32
  295. STDMETHODIMP CPrxAVIStream::Info(AVISTREAMINFOW FAR * psi, LONG lSize)
  296. #else
  297. STDMETHODIMP CPrxAVIStream::Info(AVISTREAMINFO FAR * psi, LONG lSize)
  298. #endif
  299. {
  300. HRESULT hrMarshal;
  301. HRESULT hrMethod = NOERROR;
  302. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  303. RPCOLEMESSAGE Message;
  304. _fmemset(&Message, 0, sizeof(Message));
  305. if (pChannel == NULL)
  306. return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  307. //
  308. // NOTE: We take advantage here of the fact that we assume the
  309. // stream is read-only and not being changed on the other end!
  310. //
  311. // To avoid some intertask calls, we assume that the result
  312. // of the Info() method will not change.
  313. //
  314. if (m_sh.fccType == 0) {
  315. // we might be talking to 16 or 32-bit stub, so we need to
  316. // exchange a common (superset) format and pick out the bits we need.
  317. // format in: lSize
  318. // format out: PS_STREAMINFO, hrMethod
  319. Message.cbBuffer = sizeof(lSize);
  320. Message.iMethod = IAVISTREAM_Info;
  321. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIStream)) != NOERROR)
  322. goto ErrExit;
  323. ((DWORD FAR *)Message.Buffer)[0] = sizeof(PS_STREAMINFO);
  324. if ((hrMarshal = pChannel->SendReceive(&Message,(ULONG*) &hrMethod)) != NOERROR) {
  325. ;
  326. ErrExit:
  327. return PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  328. }
  329. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  330. PS_STREAMINFO FAR * psinfo = (PS_STREAMINFO FAR *)
  331. ((LPBYTE)Message.Buffer + sizeof(HRESULT));
  332. // get the bits we want
  333. m_sh.fccType = psinfo->fccType;
  334. m_sh.fccHandler = psinfo->fccHandler;
  335. m_sh.dwFlags = psinfo->dwFlags; /* Contains AVITF_* flags */
  336. m_sh.dwCaps = psinfo->dwCaps;
  337. m_sh.wPriority = psinfo->wPriority;
  338. m_sh.wLanguage = psinfo->wLanguage;
  339. m_sh.dwScale = psinfo->dwScale;
  340. m_sh.dwRate = psinfo->dwRate; /* dwRate / dwScale == samples/second */
  341. m_sh.dwStart = psinfo->dwStart;
  342. m_sh.dwLength = psinfo->dwLength; /* In units above... */
  343. m_sh.dwInitialFrames = psinfo->dwInitialFrames;
  344. m_sh.dwSuggestedBufferSize = psinfo->dwSuggestedBufferSize;
  345. m_sh.dwQuality = psinfo->dwQuality;
  346. m_sh.dwSampleSize = psinfo->dwSampleSize;
  347. // RECTs are different sizes, so use POINTS (WORD point)
  348. m_sh.rcFrame.top = psinfo->ptFrameTopLeft.y;
  349. m_sh.rcFrame.left = psinfo->ptFrameTopLeft.x;
  350. m_sh.rcFrame.bottom = psinfo->ptFrameBottomRight.y;
  351. m_sh.rcFrame.right = psinfo->ptFrameBottomRight.x;
  352. m_sh.dwEditCount = psinfo->dwEditCount;
  353. m_sh.dwFormatChangeCount = psinfo->dwFormatChangeCount;
  354. #ifdef _WIN32
  355. // use unicode if we've been sent it
  356. if (psinfo->bHasUnicode) {
  357. _fmemcpy(m_sh.szName, psinfo->szUnicodeName, sizeof(m_sh.szName));
  358. } else {
  359. // need ansi->unicode thunk
  360. MultiByteToWideChar(
  361. CP_ACP, 0,
  362. psinfo->szName,
  363. -1,
  364. m_sh.szName,
  365. NUMELMS(m_sh.szName));
  366. }
  367. #else
  368. // we only use the ansi which is always sent
  369. _fmemcpy(m_sh.szName, psinfo->szName, sizeof(m_sh.szName));
  370. #endif
  371. pChannel->FreeBuffer(&Message);
  372. }
  373. _fmemcpy(psi, &m_sh, min((int) lSize, sizeof(m_sh)));
  374. return hrMethod;
  375. }
  376. STDMETHODIMP_(LONG) CPrxAVIStream::FindSample(LONG lPos, LONG lFlags)
  377. {
  378. HRESULT hrMarshal;
  379. HRESULT hrMethod;
  380. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  381. LONG lResult;
  382. if (pChannel == NULL)
  383. return -1; // !!! ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  384. RPCOLEMESSAGE Message;
  385. _fmemset(&Message, 0, sizeof(Message));
  386. // format in: lPos, lFlags
  387. // format out: hrMethod, lResult
  388. Message.cbBuffer = sizeof(lPos) + sizeof(lFlags);
  389. Message.iMethod = IAVISTREAM_FindSample;
  390. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIStream)) != NOERROR)
  391. goto ErrExit;
  392. ((DWORD FAR *)Message.Buffer)[0] = lPos;
  393. ((DWORD FAR *)Message.Buffer)[1] = lFlags;
  394. if ((hrMarshal = pChannel->SendReceive(&Message, (ULONG*) &hrMethod)) != NOERROR) {
  395. goto ErrExit;
  396. }
  397. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  398. lResult = ((LONG FAR *)Message.Buffer)[1];
  399. pChannel->FreeBuffer(&Message);
  400. DPF("Proxy: FindSample (%ld) returns (%ld)\n", lPos, lResult);
  401. return lResult; // !!! hrMethod;
  402. ErrExit:
  403. DPF("Proxy: FindSample returning error...\n");
  404. return -1; // !!! PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  405. }
  406. STDMETHODIMP CPrxAVIStream::ReadFormat(LONG lPos, LPVOID lpFormat, LONG FAR *lpcbFormat)
  407. {
  408. HRESULT hrMarshal;
  409. HRESULT hrMethod;
  410. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  411. if (pChannel == NULL)
  412. return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  413. // check that size is 0 if pointer is null
  414. if (lpFormat == NULL) {
  415. *lpcbFormat = 0;
  416. }
  417. // format in: dw, *lpcbFormat
  418. // format out: hrMethod, *lpcbFormat, format data
  419. RPCOLEMESSAGE Message;
  420. _fmemset(&Message, 0, sizeof(Message));
  421. Message.cbBuffer = sizeof(lPos) + sizeof(*lpcbFormat);
  422. Message.iMethod = IAVISTREAM_ReadFormat;
  423. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIStream)) != NOERROR)
  424. goto ErrExit;
  425. ((DWORD FAR *)Message.Buffer)[0] = lPos;
  426. ((DWORD FAR *)Message.Buffer)[1] = lpFormat ? *lpcbFormat : 0;
  427. if ((hrMarshal = pChannel->SendReceive(&Message, (ULONG*) &hrMethod)) != NOERROR) {
  428. goto ErrExit;
  429. }
  430. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  431. if (lpFormat && *lpcbFormat && hrMethod == NOERROR)
  432. hmemcpy(lpFormat, (LPBYTE) Message.Buffer + 2*sizeof(DWORD),
  433. min(*lpcbFormat, (long) ((DWORD FAR *) Message.Buffer)[1]));
  434. // write the size last, so we don't copy more than user's buffer
  435. *lpcbFormat = ((DWORD FAR *)Message.Buffer)[1];
  436. pChannel->FreeBuffer(&Message);
  437. return hrMethod;
  438. ErrExit:
  439. return PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  440. }
  441. STDMETHODIMP CPrxAVIStream::Read(
  442. LONG lStart,
  443. LONG lSamples,
  444. LPVOID lpBuffer,
  445. LONG cbBuffer,
  446. LONG FAR * plBytes,
  447. LONG FAR * plSamples)
  448. {
  449. HRESULT hrMarshal;
  450. HRESULT hrMethod;
  451. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  452. LONG lTemp;
  453. if (pChannel == NULL)
  454. return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  455. if (lpBuffer == NULL)
  456. cbBuffer = 0;
  457. // format on input: lPos, lLength, cb
  458. // format on output: hresult, samples, cb, frame
  459. RPCOLEMESSAGE Message;
  460. _fmemset(&Message, 0, sizeof(Message));
  461. Message.cbBuffer = sizeof(lStart) + sizeof(lSamples) + sizeof(cbBuffer);
  462. Message.iMethod = IAVISTREAM_Read;
  463. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIStream)) != NOERROR)
  464. goto ErrExit;
  465. ((DWORD FAR *)Message.Buffer)[0] = lStart;
  466. ((DWORD FAR *)Message.Buffer)[1] = lSamples;
  467. ((DWORD FAR *)Message.Buffer)[2] = lpBuffer ? cbBuffer : 0;
  468. if ((hrMarshal = pChannel->SendReceive(&Message, (ULONG*) &hrMethod)) != NOERROR) {
  469. goto ErrExit;
  470. }
  471. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  472. lTemp = ((DWORD FAR *)Message.Buffer)[1];
  473. if (plBytes)
  474. *plBytes = lTemp;
  475. if (plSamples)
  476. *plSamples = ((DWORD FAR *)Message.Buffer)[2];
  477. if (lpBuffer && lTemp && hrMethod == NOERROR)
  478. hmemcpy(lpBuffer, (LPBYTE) Message.Buffer + 3*sizeof(DWORD), lTemp);
  479. pChannel->FreeBuffer(&Message);
  480. return hrMethod;
  481. ErrExit:
  482. return PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  483. }
  484. //
  485. // All of the writing-related messages are not remoted....
  486. //
  487. STDMETHODIMP CPrxAVIStream::SetFormat(LONG lPos,LPVOID lpFormat,LONG cbFormat)
  488. {
  489. return ResultFromScode(E_NOTIMPL);
  490. }
  491. STDMETHODIMP CPrxAVIStream::Write(LONG lStart,
  492. LONG lSamples,
  493. LPVOID lpData,
  494. LONG cbData,
  495. DWORD dwFlags,
  496. LONG FAR *plSampWritten,
  497. LONG FAR *plBytesWritten)
  498. {
  499. return ResultFromScode(E_NOTIMPL);
  500. }
  501. STDMETHODIMP CPrxAVIStream::Delete(LONG lStart,LONG lSamples)
  502. {
  503. return ResultFromScode(E_NOTIMPL);
  504. }
  505. STDMETHODIMP CPrxAVIStream::ReadData(DWORD ckid, LPVOID lp, LONG FAR *lpcb)
  506. {
  507. // !!! This should really be remoted!
  508. return ResultFromScode(E_NOTIMPL);
  509. }
  510. STDMETHODIMP CPrxAVIStream::WriteData(DWORD ckid, LPVOID lp, LONG cb)
  511. {
  512. return ResultFromScode(E_NOTIMPL);
  513. }
  514. #ifdef _WIN32
  515. STDMETHODIMP CPrxAVIStream::SetInfo(AVISTREAMINFOW FAR *lpInfo, LONG cbInfo)
  516. {
  517. return ResultFromScode(E_NOTIMPL);
  518. }
  519. #else
  520. STDMETHODIMP CPrxAVIStream::Reserved1(void)
  521. {
  522. return ResultFromScode(E_NOTIMPL);
  523. }
  524. STDMETHODIMP CPrxAVIStream::Reserved2(void)
  525. {
  526. return ResultFromScode(E_NOTIMPL);
  527. }
  528. STDMETHODIMP CPrxAVIStream::Reserved3(void)
  529. {
  530. return ResultFromScode(E_NOTIMPL);
  531. }
  532. STDMETHODIMP CPrxAVIStream::Reserved4(void)
  533. {
  534. return ResultFromScode(E_NOTIMPL);
  535. }
  536. STDMETHODIMP CPrxAVIStream::Reserved5(void)
  537. {
  538. return ResultFromScode(E_NOTIMPL);
  539. }
  540. #endif
  541. /*
  542. * IMPLEMENTATION of CStubAVIStream
  543. *
  544. */
  545. // create connected interface stub
  546. HRESULT CStubAVIStream::Create(IUnknown FAR* pUnkObject, IRpcStubBuffer FAR* FAR* ppStub)
  547. {
  548. CStubAVIStream FAR* pStubAVIStream;
  549. *ppStub = NULL;
  550. if ((pStubAVIStream = new CStubAVIStream()) == NULL)
  551. return ResultFromScode(E_OUTOFMEMORY);
  552. HRESULT hresult;
  553. if ((hresult = pStubAVIStream->Connect(pUnkObject)) != NOERROR)
  554. {
  555. pStubAVIStream->Release();
  556. return hresult;
  557. }
  558. *ppStub = pStubAVIStream;
  559. return NOERROR;
  560. }
  561. CStubAVIStream::CStubAVIStream(void)
  562. {
  563. m_refs = 1; /// !!! ??? 0
  564. DPF("StubStream %p: Usage++=%lx (C)\n", (DWORD_PTR) (LPVOID) this, 1L);
  565. m_pAVIStream = NULL;
  566. RegisterStubUsage();
  567. InitOle(TRUE);
  568. }
  569. CStubAVIStream::~CStubAVIStream(void)
  570. {
  571. UnregisterStubUsage();
  572. Disconnect();
  573. TermOle();
  574. }
  575. // controling unknown methods for interface stub
  576. STDMETHODIMP CStubAVIStream::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  577. {
  578. if (iid == IID_IUnknown || iid == IID_IRpcStubBuffer)
  579. {
  580. *ppv = this;
  581. DPF("StubStream %p: Usage++=%lx (QI)\n", (DWORD_PTR) (LPVOID) this, m_refs + 1);
  582. ++m_refs;
  583. return NOERROR;
  584. }
  585. else
  586. {
  587. *ppv = NULL;
  588. return ResultFromScode(E_NOINTERFACE);
  589. }
  590. }
  591. STDMETHODIMP_(ULONG) CStubAVIStream::AddRef(void)
  592. {
  593. DPF("StubStream %p: Usage++=%lx\n", (DWORD_PTR) (LPVOID) this, m_refs + 1);
  594. return ++m_refs;
  595. }
  596. STDMETHODIMP_(ULONG) CStubAVIStream::Release(void)
  597. {
  598. DPF("StubStream %p: Usage--=%lx\n", (DWORD_PTR) (LPVOID) this, m_refs - 1);
  599. if (--m_refs == 0)
  600. {
  601. if (m_pAVIStream) {
  602. DPF("Releasing stream in funny place!\n");
  603. m_pAVIStream->Release();
  604. m_pAVIStream = NULL;
  605. }
  606. delete this;
  607. return 0;
  608. }
  609. return m_refs;
  610. }
  611. // connect interface stub to server object
  612. STDMETHODIMP CStubAVIStream::Connect(IUnknown FAR* pUnkObj)
  613. {
  614. HRESULT hr;
  615. if (m_pAVIStream)
  616. // call Disconnect first
  617. return ResultFromScode(E_UNEXPECTED);
  618. if (pUnkObj == NULL)
  619. return ResultFromScode(E_INVALIDARG);
  620. // NOTE: QI ensures out param is zero if error
  621. hr = pUnkObj->QueryInterface(IID_IAVIStream, (LPVOID FAR*)&m_pAVIStream);
  622. DPF("CStubAVIStream::Connect: Result = %lx, stream = %p\n", hr, (DWORD_PTR) m_pAVIStream);
  623. return hr;
  624. }
  625. // disconnect interface stub from server objec
  626. STDMETHODIMP_(void) CStubAVIStream::Disconnect(void)
  627. {
  628. DPF("CStubAVIStream::Disconnect\n");
  629. if (m_pAVIStream) {
  630. DPF("Disconnect: Releasing stream\n");
  631. m_pAVIStream->Release();
  632. m_pAVIStream = NULL;
  633. }
  634. }
  635. // remove method call
  636. STDMETHODIMP CStubAVIStream::Invoke
  637. (RPCOLEMESSAGE FAR *pMessage, IRpcChannelBuffer FAR *pChannel)
  638. {
  639. HRESULT hresult;
  640. HRESULT hrMethod;
  641. DPF("!AVISTREAM: Invoke: ");
  642. if (!m_pAVIStream) {
  643. DPF("!No stream!\n");
  644. return ResultFromScode(RPC_E_UNEXPECTED);
  645. }
  646. #if 0
  647. if (iid != IID_IAVIStream) {
  648. DPF("!Wrong interface\n");
  649. return ResultFromScode(RPC_E_UNEXPECTED);
  650. }
  651. #endif
  652. switch (pMessage->iMethod)
  653. {
  654. case IAVISTREAM_Info:
  655. // format on input: lSize
  656. // format on output: hresult, PS_STREAMINFO
  657. {
  658. DWORD lSize;
  659. #ifdef _WIN32
  660. AVISTREAMINFOW si;
  661. #else
  662. AVISTREAMINFO si;
  663. #endif
  664. DPF("!Info\n");
  665. // need to send a common ansi/unicode version with both strings
  666. PS_STREAMINFO psinfo;
  667. hrMethod = m_pAVIStream->Info(&si, sizeof(si));
  668. // copy all members
  669. psinfo.fccType = si.fccType;
  670. psinfo.fccHandler = si.fccHandler;
  671. psinfo.dwFlags = si.dwFlags; /* Contains AVITF_* flags */
  672. psinfo.dwCaps = si.dwCaps;
  673. psinfo.wPriority = si.wPriority;
  674. psinfo.wLanguage = si.wLanguage;
  675. psinfo.dwScale = si.dwScale;
  676. psinfo.dwRate = si.dwRate; /* dwRate / dwScale == samples/second */
  677. psinfo.dwStart = si.dwStart;
  678. psinfo.dwLength = si.dwLength; /* In units above... */
  679. psinfo.dwInitialFrames = si.dwInitialFrames;
  680. psinfo.dwSuggestedBufferSize = si.dwSuggestedBufferSize;
  681. psinfo.dwQuality = si.dwQuality;
  682. psinfo.dwSampleSize = si.dwSampleSize;
  683. psinfo.dwEditCount = si.dwEditCount;
  684. psinfo.dwFormatChangeCount = si.dwFormatChangeCount;
  685. // RECT is different size, so use POINTS
  686. psinfo.ptFrameTopLeft.x = (short) si.rcFrame.left;
  687. psinfo.ptFrameTopLeft.y = (short) si.rcFrame.top;
  688. psinfo.ptFrameBottomRight.x = (short) si.rcFrame.right;
  689. psinfo.ptFrameBottomRight.y = (short) si.rcFrame.bottom;
  690. #ifdef _WIN32
  691. // send both UNICODE and ansi
  692. hmemcpy(psinfo.szUnicodeName, si.szName, sizeof(psinfo.szUnicodeName));
  693. psinfo.bHasUnicode = TRUE;
  694. WideCharToMultiByte(CP_ACP, 0,
  695. si.szName,
  696. -1,
  697. psinfo.szName,
  698. NUMELMS(psinfo.szName),
  699. NULL, NULL);
  700. #else
  701. // just send ansi version for 16-bit stub
  702. psinfo.bHasUnicode = FALSE;
  703. hmemcpy(psinfo.szName, si.szName, sizeof(si.szName));
  704. #endif
  705. lSize = ((DWORD FAR *)pMessage->Buffer)[0];
  706. pMessage->cbBuffer = lSize + sizeof(hrMethod);
  707. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  708. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  709. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  710. hmemcpy((LPBYTE) pMessage->Buffer + sizeof(hrMethod),
  711. &psinfo,
  712. lSize);
  713. return NOERROR;
  714. }
  715. case IAVISTREAM_FindSample:
  716. // format on input: lPos, lFlags
  717. // format on output: hResult, lResult
  718. {
  719. LONG lPos, lFlags, lResult;
  720. lPos = ((DWORD FAR *)pMessage->Buffer)[0];
  721. lFlags = ((DWORD FAR *)pMessage->Buffer)[1];
  722. DPF("!FindSample (%ld)\n", lPos);
  723. lResult = m_pAVIStream->FindSample(lPos, lFlags);
  724. hrMethod = 0; // !!!
  725. pMessage->cbBuffer = sizeof(lResult) + sizeof(hrMethod);
  726. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  727. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  728. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  729. ((DWORD FAR *)pMessage->Buffer)[1] = lResult;
  730. return NOERROR;
  731. }
  732. case IAVISTREAM_ReadFormat:
  733. // format on input: lPos, cbFormat
  734. // format on output: hresult, cbFormat, format
  735. {
  736. LONG cbIn;
  737. LONG cb;
  738. DWORD lPos;
  739. LPVOID lp;
  740. lPos = ((DWORD FAR *)pMessage->Buffer)[0];
  741. cb = cbIn = ((DWORD FAR *)pMessage->Buffer)[1];
  742. DPF("!ReadFormat (%ld)\n", lPos);
  743. pMessage->cbBuffer = sizeof(cbIn) + cbIn + sizeof(hrMethod);
  744. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  745. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  746. lp = cbIn ? (LPBYTE) pMessage->Buffer + 2 * sizeof(DWORD) : NULL;
  747. hrMethod = m_pAVIStream->ReadFormat(lPos, lp, &cb);
  748. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  749. ((DWORD FAR *)pMessage->Buffer)[1] = cb;
  750. pMessage->cbBuffer = (ULONG)(sizeof(cbIn) + sizeof(hrMethod) +
  751. ((cb && cbIn) ? cb : 0));
  752. return NOERROR;
  753. }
  754. case IAVISTREAM_Read:
  755. // format on input: lPos, lSamples, cb
  756. // format on output: hresult, samples, cb, frame
  757. {
  758. LONG cb;
  759. LONG lPos, lSamples;
  760. LPVOID lp;
  761. lPos = ((DWORD FAR *)pMessage->Buffer)[0];
  762. lSamples = ((DWORD FAR *)pMessage->Buffer)[1];
  763. cb = ((DWORD FAR *)pMessage->Buffer)[2];
  764. DPF("!Read (%ld, %ld) ", lPos, lSamples);
  765. pMessage->cbBuffer = 3 * sizeof(DWORD) + cb;
  766. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  767. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  768. lp = cb ? (LPBYTE) pMessage->Buffer + 3 * sizeof(DWORD) : NULL;
  769. DPF("! %ld bytes ", cb);
  770. hrMethod = m_pAVIStream->Read(lPos, lSamples, lp, cb, &cb, &lSamples);
  771. DPF("! -> %ld bytes\n", cb);
  772. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  773. ((DWORD FAR *)pMessage->Buffer)[1] = cb;
  774. ((DWORD FAR *)pMessage->Buffer)[2] = lSamples;
  775. return NOERROR;
  776. }
  777. default:
  778. // unknown method
  779. DPF("!Unknown method (%d)\n", pMessage->iMethod);
  780. return ResultFromScode(RPC_E_UNEXPECTED);
  781. }
  782. }
  783. // return TRUE if we support given interface
  784. STDMETHODIMP_(IRpcStubBuffer FAR *) CStubAVIStream::IsIIDSupported(REFIID iid)
  785. {
  786. // if we are connected, we have already checked for this interface;
  787. // if we are not connected, it doesn't matter.
  788. return iid == IID_IAVIStream ? (IRpcStubBuffer *) this : 0;
  789. }
  790. // returns number of refs we have to object
  791. STDMETHODIMP_(ULONG) CStubAVIStream::CountRefs(void)
  792. {
  793. // return 1 if connected; 0 if not.
  794. return m_pAVIStream != NULL;
  795. }
  796. STDMETHODIMP CStubAVIStream::DebugServerQueryInterface(LPVOID FAR *ppv)
  797. {
  798. *ppv = m_pAVIStream;
  799. if (!m_pAVIStream) {
  800. DPF("!No stream!\n");
  801. return ResultFromScode(E_UNEXPECTED);
  802. }
  803. return NOERROR;
  804. }
  805. STDMETHODIMP_(void) CStubAVIStream::DebugServerRelease(LPVOID pv)
  806. {
  807. }
  808. /*
  809. * IMPLEMENTATION of CPrxAVIFile
  810. *
  811. */
  812. // create unconnected CPrxAVIFile; return controlling IProxy/IUnknokwn FAR*
  813. IRpcProxyBuffer FAR* CPrxAVIFile::Create(IUnknown FAR* pUnkOuter)
  814. {
  815. CPrxAVIFile FAR* pPrxAVIFile;
  816. if ((pPrxAVIFile = new CPrxAVIFile(pUnkOuter)) == NULL)
  817. return NULL;
  818. return &pPrxAVIFile->m_Proxy;
  819. }
  820. CPrxAVIFile::CPrxAVIFile(IUnknown FAR* pUnkOuter) : m_Proxy(this)
  821. {
  822. // NOTE: could assert here since we should always be aggregated
  823. if (pUnkOuter == NULL)
  824. pUnkOuter = &m_Proxy;
  825. m_refs = 1;
  826. m_pUnkOuter = pUnkOuter;
  827. m_pRpcChannelBuffer = NULL;
  828. m_fi.dwStreams = 0;
  829. }
  830. CPrxAVIFile::~CPrxAVIFile(void)
  831. {
  832. m_Proxy.Disconnect();
  833. }
  834. // Methods for controlling unknown
  835. STDMETHODIMP CPrxAVIFile::CProxyImpl::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  836. {
  837. if (iid == IID_IUnknown || iid == IID_IRpcProxyBuffer)
  838. *ppv = (void FAR *)this;
  839. else if (iid == IID_IAVIFile)
  840. *ppv = (void FAR *)m_pPrxAVIFile;
  841. else
  842. {
  843. *ppv = NULL;
  844. return ResultFromScode(E_NOINTERFACE);
  845. }
  846. // simplest way to be correct: always addref the pointer we will return;
  847. // easy since all interfaces here are derived from IUnknown.
  848. ((IUnknown FAR*) *ppv)->AddRef();
  849. return NOERROR;
  850. }
  851. STDMETHODIMP_(ULONG) CPrxAVIFile::CProxyImpl::AddRef(void)
  852. {
  853. return ++m_pPrxAVIFile->m_refs;
  854. }
  855. STDMETHODIMP_(ULONG) CPrxAVIFile::CProxyImpl::Release(void)
  856. {
  857. if (--m_pPrxAVIFile->m_refs == 0)
  858. {
  859. delete m_pPrxAVIFile;
  860. return 0;
  861. }
  862. return m_pPrxAVIFile->m_refs;
  863. }
  864. // connect proxy to channel given
  865. STDMETHODIMP CPrxAVIFile::CProxyImpl::Connect(IRpcChannelBuffer FAR* pChannelChannelBuffer)
  866. {
  867. if (m_pPrxAVIFile->m_pRpcChannelBuffer != NULL)
  868. return ResultFromScode(E_UNEXPECTED);
  869. if (pChannelChannelBuffer == NULL)
  870. return ResultFromScode(E_INVALIDARG);
  871. (m_pPrxAVIFile->m_pRpcChannelBuffer = pChannelChannelBuffer)->AddRef();
  872. return NOERROR;
  873. }
  874. // disconnect proxy from any current channel
  875. STDMETHODIMP_(void) CPrxAVIFile::CProxyImpl::Disconnect(void)
  876. {
  877. if (m_pPrxAVIFile->m_pRpcChannelBuffer)
  878. {
  879. m_pPrxAVIFile->m_pRpcChannelBuffer->Release();
  880. m_pPrxAVIFile->m_pRpcChannelBuffer = NULL;
  881. }
  882. }
  883. // IUnknown methods for external interface(s); always delegate
  884. STDMETHODIMP CPrxAVIFile::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  885. {
  886. return m_pUnkOuter->QueryInterface(iid, ppv);
  887. }
  888. STDMETHODIMP_(ULONG) CPrxAVIFile::AddRef(void)
  889. {
  890. return m_pUnkOuter->AddRef();
  891. }
  892. STDMETHODIMP_(ULONG) CPrxAVIFile::Release(void)
  893. {
  894. return m_pUnkOuter->Release();
  895. }
  896. // IAVIFile interface methods
  897. #ifdef _WIN32
  898. STDMETHODIMP CPrxAVIFile::Info(AVIFILEINFOW FAR * psi, LONG lSize)
  899. #else
  900. STDMETHODIMP CPrxAVIFile::Info(AVIFILEINFO FAR * psi, LONG lSize)
  901. #endif
  902. {
  903. HRESULT hrMarshal;
  904. HRESULT hrMethod = NOERROR;
  905. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  906. if (pChannel == NULL)
  907. return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  908. if (m_fi.dwStreams == 0) {
  909. RPCOLEMESSAGE Message;
  910. _fmemset(&Message, 0, sizeof(Message));
  911. // format in: lSize
  912. // format out: hrMethod, PS_FILEINFO
  913. Message.cbBuffer = sizeof(lSize);
  914. Message.iMethod = IAVIFILE_Info;
  915. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIFile)) != NOERROR)
  916. goto ErrExit;
  917. ((DWORD FAR *)Message.Buffer)[0] = sizeof(PS_FILEINFO);
  918. if ((hrMarshal = pChannel->SendReceive(&Message, (ULONG*) &hrMethod)) != NOERROR) {
  919. ;
  920. ErrExit:
  921. return PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  922. }
  923. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  924. PS_FILEINFO FAR * psinfo = (PS_FILEINFO FAR *)
  925. ((LPBYTE)Message.Buffer + sizeof(HRESULT));
  926. // get the bits we want
  927. m_fi.dwMaxBytesPerSec = psinfo->dwMaxBytesPerSec; // max. transfer rate
  928. m_fi.dwFlags = psinfo->dwFlags; // the ever-present flags
  929. m_fi.dwCaps = psinfo->dwCaps;
  930. m_fi.dwStreams = psinfo->dwStreams;
  931. m_fi.dwSuggestedBufferSize = psinfo->dwSuggestedBufferSize;
  932. m_fi.dwWidth = psinfo->dwWidth;
  933. m_fi.dwHeight = psinfo->dwHeight;
  934. m_fi.dwScale = psinfo->dwScale;
  935. m_fi.dwRate = psinfo->dwRate; /* dwRate / dwScale == samples/second */
  936. m_fi.dwLength = psinfo->dwLength;
  937. m_fi.dwEditCount = psinfo->dwEditCount;
  938. #ifdef _WIN32
  939. // use unicode if we've been sent it
  940. if (psinfo->bHasUnicode) {
  941. _fmemcpy(m_fi.szFileType,
  942. psinfo->szUnicodeType, sizeof(m_fi.szFileType));
  943. } else {
  944. // need ansi->unicode thunk
  945. MultiByteToWideChar(
  946. CP_ACP, 0,
  947. psinfo->szFileType,
  948. -1,
  949. m_fi.szFileType,
  950. NUMELMS(m_fi.szFileType));
  951. }
  952. #else
  953. // we only use the ansi which is always sent
  954. _fmemcpy(m_fi.szFileType, psinfo->szFileType, sizeof(m_fi.szFileType));
  955. #endif
  956. pChannel->FreeBuffer(&Message);
  957. }
  958. _fmemcpy(psi, &m_fi, min((int) lSize, sizeof(m_fi)));
  959. return hrMethod;
  960. }
  961. #ifndef _WIN32
  962. STDMETHODIMP CPrxAVIFile::Open(LPCTSTR szFile, UINT mode)
  963. {
  964. return ResultFromScode(E_NOTIMPL);
  965. }
  966. #endif
  967. STDMETHODIMP CPrxAVIFile::GetStream(PAVISTREAM FAR * ppStream,
  968. DWORD fccType,
  969. LONG lParam)
  970. {
  971. HRESULT hrMarshal;
  972. HRESULT hrMethod = NOERROR;
  973. IRpcChannelBuffer FAR* pChannel = m_pRpcChannelBuffer;
  974. if (pChannel == NULL)
  975. return ResultFromScode(RPC_E_CONNECTION_TERMINATED);
  976. RPCOLEMESSAGE Message;
  977. _fmemset(&Message, 0, sizeof(Message));
  978. // format in: fccType lParam
  979. // format out: returned interface (marshalled)
  980. Message.cbBuffer = sizeof(fccType) + sizeof(lParam);
  981. Message.iMethod = IAVIFILE_GetStream;
  982. if ((hrMarshal = pChannel->GetBuffer(&Message, IID_IAVIFile)) != NOERROR)
  983. goto ErrExit;
  984. ((DWORD FAR *)Message.Buffer)[0] = fccType;
  985. ((DWORD FAR *)Message.Buffer)[1] = lParam;
  986. if ((hrMarshal = pChannel->SendReceive(&Message, (ULONG*) &hrMethod)) != NOERROR) {
  987. ;
  988. ErrExit:
  989. return PropagateResult(hrMarshal, RPC_E_CLIENT_CANTMARSHAL_DATA);
  990. }
  991. hrMethod = ((HRESULT FAR *)Message.Buffer)[0];
  992. if (hrMethod == NOERROR) {
  993. HGLOBAL h;
  994. LPSTREAM pstm;
  995. h = GlobalAlloc(GHND, Message.cbBuffer - sizeof(hrMethod));
  996. hmemcpy(GlobalLock(h),
  997. (LPBYTE) Message.Buffer + sizeof(hrMethod),
  998. Message.cbBuffer - sizeof(hrMethod));
  999. CreateStreamOnHGlobal(h, FALSE, &pstm);
  1000. CoUnmarshalInterface(pstm, IID_IAVIStream, (LPVOID FAR *) ppStream);
  1001. pstm->Release();
  1002. pChannel->FreeBuffer(&Message);
  1003. }
  1004. return hrMethod;
  1005. }
  1006. STDMETHODIMP CPrxAVIFile::CreateStream(
  1007. PAVISTREAM FAR * ppStream,
  1008. #ifdef _WIN32
  1009. AVISTREAMINFOW FAR * psi)
  1010. #else
  1011. AVISTREAMINFO FAR * psi)
  1012. #endif
  1013. {
  1014. return ResultFromScode(E_NOTIMPL);
  1015. }
  1016. #ifndef _WIN32
  1017. STDMETHODIMP CPrxAVIFile::Save(
  1018. LPCTSTR szFile,
  1019. AVICOMPRESSOPTIONS FAR *lpOptions,
  1020. AVISAVECALLBACK lpfnCallback)
  1021. {
  1022. return ResultFromScode(E_NOTIMPL);
  1023. }
  1024. #endif
  1025. STDMETHODIMP CPrxAVIFile::ReadData(DWORD ckid, LPVOID lp, LONG FAR *lpcb)
  1026. {
  1027. return ResultFromScode(E_NOTIMPL);
  1028. }
  1029. STDMETHODIMP CPrxAVIFile::WriteData(DWORD ckid, LPVOID lp, LONG cb)
  1030. {
  1031. return ResultFromScode(E_NOTIMPL);
  1032. }
  1033. STDMETHODIMP CPrxAVIFile::EndRecord()
  1034. {
  1035. return ResultFromScode(E_NOTIMPL);
  1036. }
  1037. #ifdef _WIN32
  1038. STDMETHODIMP CPrxAVIFile::DeleteStream(DWORD fccType, LONG lParam)
  1039. {
  1040. return ResultFromScode(AVIERR_UNSUPPORTED);
  1041. }
  1042. #else
  1043. STDMETHODIMP CPrxAVIFile::Reserved1(void)
  1044. {
  1045. return ResultFromScode(E_NOTIMPL);
  1046. }
  1047. STDMETHODIMP CPrxAVIFile::Reserved2(void)
  1048. {
  1049. return ResultFromScode(E_NOTIMPL);
  1050. }
  1051. STDMETHODIMP CPrxAVIFile::Reserved3(void)
  1052. {
  1053. return ResultFromScode(E_NOTIMPL);
  1054. }
  1055. STDMETHODIMP CPrxAVIFile::Reserved4(void)
  1056. {
  1057. return ResultFromScode(E_NOTIMPL);
  1058. }
  1059. STDMETHODIMP CPrxAVIFile::Reserved5(void)
  1060. {
  1061. return ResultFromScode(E_NOTIMPL);
  1062. }
  1063. #endif
  1064. /*
  1065. * IMPLEMENTATION of CStubAVIFile
  1066. *
  1067. */
  1068. // create connected interface stub
  1069. HRESULT CStubAVIFile::Create(IUnknown FAR* pUnkObject, IRpcStubBuffer FAR* FAR* ppStub)
  1070. {
  1071. CStubAVIFile FAR* pStubAVIFile;
  1072. *ppStub = NULL;
  1073. if ((pStubAVIFile = new CStubAVIFile()) == NULL)
  1074. return ResultFromScode(E_OUTOFMEMORY);
  1075. HRESULT hresult;
  1076. if ((hresult = pStubAVIFile->Connect(pUnkObject)) != NOERROR)
  1077. {
  1078. pStubAVIFile->Release();
  1079. return hresult;
  1080. }
  1081. *ppStub = pStubAVIFile;
  1082. return NOERROR;
  1083. }
  1084. CStubAVIFile::CStubAVIFile(void)
  1085. {
  1086. m_refs = 1;
  1087. m_pAVIFile = NULL;
  1088. RegisterStubUsage();
  1089. }
  1090. CStubAVIFile::~CStubAVIFile(void)
  1091. {
  1092. UnregisterStubUsage();
  1093. Disconnect();
  1094. }
  1095. // controling unknown methods for interface stub
  1096. STDMETHODIMP CStubAVIFile::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  1097. {
  1098. if (iid == IID_IUnknown || iid == IID_IRpcStubBuffer)
  1099. {
  1100. *ppv = this;
  1101. ++m_refs;
  1102. return NOERROR;
  1103. }
  1104. else
  1105. {
  1106. *ppv = NULL;
  1107. return ResultFromScode(E_NOINTERFACE);
  1108. }
  1109. }
  1110. STDMETHODIMP_(ULONG) CStubAVIFile::AddRef(void)
  1111. {
  1112. return ++m_refs;
  1113. }
  1114. STDMETHODIMP_(ULONG) CStubAVIFile::Release(void)
  1115. {
  1116. if (--m_refs == 0)
  1117. {
  1118. delete this;
  1119. return 0;
  1120. }
  1121. return m_refs;
  1122. }
  1123. // connect interface stub to server object
  1124. STDMETHODIMP CStubAVIFile::Connect(IUnknown FAR* pUnkObj)
  1125. {
  1126. if (m_pAVIFile)
  1127. // call Disconnect first
  1128. return ResultFromScode(E_UNEXPECTED);
  1129. if (pUnkObj == NULL)
  1130. return ResultFromScode(E_INVALIDARG);
  1131. // NOTE: QI ensures out param is zero if error
  1132. return pUnkObj->QueryInterface(IID_IAVIFile, (LPVOID FAR*)&m_pAVIFile);
  1133. }
  1134. // disconnect interface stub from server objec
  1135. STDMETHODIMP_(void) CStubAVIFile::Disconnect(void)
  1136. {
  1137. if (m_pAVIFile) {
  1138. m_pAVIFile->Release();
  1139. m_pAVIFile = NULL;
  1140. }
  1141. }
  1142. // remove method call
  1143. STDMETHODIMP CStubAVIFile::Invoke
  1144. (RPCOLEMESSAGE FAR *pMessage, IRpcChannelBuffer FAR *pChannel)
  1145. {
  1146. HRESULT hresult;
  1147. HRESULT hrMethod;
  1148. if (!m_pAVIFile)
  1149. return ResultFromScode(RPC_E_UNEXPECTED);
  1150. #if 0
  1151. if (iid != IID_IAVIFile)
  1152. return ResultFromScode(RPC_E_UNEXPECTED);
  1153. #endif
  1154. switch (pMessage->iMethod)
  1155. {
  1156. case IAVIFILE_Info:
  1157. // format on input: lSize
  1158. // format on output: hresult, AVIFILEINFO
  1159. {
  1160. DWORD lSize;
  1161. #ifdef _WIN32
  1162. AVIFILEINFOW si;
  1163. #else
  1164. AVIFILEINFO si;
  1165. #endif
  1166. PS_FILEINFO psinfo;
  1167. hrMethod = m_pAVIFile->Info(&si, sizeof(si));
  1168. // copy all members
  1169. psinfo.dwMaxBytesPerSec = si.dwMaxBytesPerSec;
  1170. psinfo.dwFlags = si.dwFlags;
  1171. psinfo.dwCaps = si.dwCaps;
  1172. psinfo.dwStreams = si.dwStreams;
  1173. psinfo.dwSuggestedBufferSize = si.dwSuggestedBufferSize;
  1174. psinfo.dwWidth = si.dwWidth;
  1175. psinfo.dwHeight = si.dwHeight;
  1176. psinfo.dwScale = si.dwScale;
  1177. psinfo.dwRate = si.dwRate;
  1178. psinfo.dwLength = si.dwLength;
  1179. psinfo.dwEditCount = si.dwEditCount;
  1180. #ifdef _WIN32
  1181. // send both UNICODE and ansi
  1182. hmemcpy(psinfo.szUnicodeType, si.szFileType, NUMELMS(psinfo.szFileType));
  1183. psinfo.bHasUnicode = TRUE;
  1184. WideCharToMultiByte(CP_ACP, 0,
  1185. si.szFileType,
  1186. -1,
  1187. psinfo.szFileType,
  1188. NUMELMS(psinfo.szFileType),
  1189. NULL, NULL);
  1190. #else
  1191. // just send ansi version for 16-bit stub
  1192. psinfo.bHasUnicode = FALSE;
  1193. hmemcpy(psinfo.szFileType, si.szFileType, sizeof(si.szFileType));
  1194. #endif
  1195. lSize = ((DWORD FAR *)pMessage->Buffer)[0];
  1196. pMessage->cbBuffer = lSize + sizeof(hrMethod);
  1197. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  1198. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  1199. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  1200. hmemcpy((LPBYTE) pMessage->Buffer + sizeof(hrMethod),
  1201. &psinfo,
  1202. lSize);
  1203. return NOERROR;
  1204. }
  1205. case IAVIFILE_GetStream:
  1206. // format on input: fccType, lParam
  1207. // format on output: marshalled IAVIStream pointer
  1208. {
  1209. DWORD lParam, fccType;
  1210. PAVISTREAM ps;
  1211. HGLOBAL h;
  1212. DWORD dwDestCtx = 0;
  1213. LPVOID pvDestCtx = NULL;
  1214. DWORD cb;
  1215. LPSTREAM pstm;
  1216. fccType = ((DWORD FAR *)pMessage->Buffer)[0];
  1217. lParam = ((DWORD FAR *)pMessage->Buffer)[1];
  1218. hrMethod = m_pAVIFile->GetStream(&ps, fccType, lParam);
  1219. if (hrMethod == NOERROR) {
  1220. pChannel->GetDestCtx(&dwDestCtx, &pvDestCtx);
  1221. #ifdef _WIN32
  1222. cb = 0;
  1223. CoGetMarshalSizeMax(&cb, IID_IAVIStream, ps,
  1224. dwDestCtx, pvDestCtx, MSHLFLAGS_NORMAL);
  1225. #else
  1226. cb = 800; // !!!!!!!
  1227. #endif
  1228. h = GlobalAlloc(GHND, cb);
  1229. CreateStreamOnHGlobal(h, FALSE, &pstm);
  1230. CoMarshalInterface(pstm, IID_IAVIStream, ps,
  1231. dwDestCtx, pvDestCtx, MSHLFLAGS_NORMAL);
  1232. pstm->Release();
  1233. } else
  1234. cb = 0;
  1235. pMessage->cbBuffer = cb + sizeof(hrMethod);
  1236. if ((hresult = pChannel->GetBuffer(pMessage, IID_IAVIStream)) != NOERROR)
  1237. return PropagateResult(hresult, RPC_E_SERVER_CANTUNMARSHAL_DATA);
  1238. ((HRESULT FAR *)pMessage->Buffer)[0] = hrMethod;
  1239. if (cb) {
  1240. hmemcpy((LPBYTE) pMessage->Buffer + sizeof(hrMethod),
  1241. GlobalLock(h), cb);
  1242. GlobalUnlock(h);
  1243. GlobalFree(h);
  1244. }
  1245. return NOERROR;
  1246. }
  1247. default:
  1248. // unknown method
  1249. return ResultFromScode(RPC_E_UNEXPECTED);
  1250. }
  1251. }
  1252. // return TRUE if we support given interface
  1253. STDMETHODIMP_(IRpcStubBuffer FAR *) CStubAVIFile::IsIIDSupported(REFIID iid)
  1254. {
  1255. // if we are connected, we have already checked for this interface;
  1256. // if we are not connected, it doesn't matter.
  1257. return iid == IID_IAVIFile ? (IRpcStubBuffer *) this : 0;
  1258. }
  1259. // returns number of refs we have to object
  1260. STDMETHODIMP_(ULONG) CStubAVIFile::CountRefs(void)
  1261. {
  1262. // return 1 if connected; 0 if not.
  1263. return m_pAVIFile != NULL;
  1264. }
  1265. STDMETHODIMP CStubAVIFile::DebugServerQueryInterface(LPVOID FAR *ppv)
  1266. {
  1267. *ppv = m_pAVIFile;
  1268. if (!m_pAVIFile) {
  1269. DPF("!No File!\n");
  1270. return ResultFromScode(E_UNEXPECTED);
  1271. }
  1272. return NOERROR;
  1273. }
  1274. STDMETHODIMP_(void) CStubAVIFile::DebugServerRelease(LPVOID pv)
  1275. {
  1276. }
  1277. //
  1278. // The following functions exist to allow an application to determine
  1279. // if another application is using any of its objects.
  1280. //
  1281. // !!!!!! I don't know if this really works.
  1282. //
  1283. #define MAXTASKCACHE 64
  1284. HTASK ahtaskUsed[MAXTASKCACHE];
  1285. int aiRefCount[MAXTASKCACHE];
  1286. void RegisterStubUsage(void)
  1287. {
  1288. HTASK htask = GetCurrentTask();
  1289. int i;
  1290. for (i = 0; i < MAXTASKCACHE; i++) {
  1291. if (ahtaskUsed[i] == htask) {
  1292. ++aiRefCount[i];
  1293. return;
  1294. }
  1295. }
  1296. for (i = 0; i < MAXTASKCACHE; i++) {
  1297. if (ahtaskUsed[i] == NULL) {
  1298. ahtaskUsed[i] = htask;
  1299. aiRefCount[i] = 1;
  1300. return;
  1301. }
  1302. }
  1303. DPF("Ack: Proxy cache full!\n");
  1304. }
  1305. void UnregisterStubUsage(void)
  1306. {
  1307. HTASK htask = GetCurrentTask();
  1308. int i;
  1309. for (i = 0; i < MAXTASKCACHE; i++) {
  1310. if (ahtaskUsed[i] == htask) {
  1311. if (--aiRefCount[i] <= 0) {
  1312. ahtaskUsed[i] = NULL;
  1313. aiRefCount[i] = 0;
  1314. }
  1315. return;
  1316. }
  1317. }
  1318. DPF("Ack: Proxy not in cache!\n");
  1319. }
  1320. BOOL FAR TaskHasExistingProxies(void)
  1321. {
  1322. HTASK htask = GetCurrentTask();
  1323. int i;
  1324. for (i = 0; i < MAXTASKCACHE; i++) {
  1325. if (ahtaskUsed[i] == htask) {
  1326. return TRUE;
  1327. }
  1328. }
  1329. return FALSE;
  1330. }