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.

1169 lines
32 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: COMLOCAL.CXX (16 bit target)
  7. //
  8. // Contents: CompObj APIs
  9. //
  10. // Functions:
  11. //
  12. // History: 16-Dec-93 JohannP Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <headers.cxx>
  16. #pragma hdrstop
  17. #include <ole2ver.h>
  18. #include <ole2sp.h>
  19. #include <olecoll.h>
  20. #include <map_kv.h>
  21. #include "comlocal.hxx"
  22. #include "map_htsk.h"
  23. #include "etask.hxx"
  24. #include "call32.hxx"
  25. #include "apilist.hxx"
  26. UINT v_pidHighWord = 1; // incremented each time used
  27. IMalloc FAR* v_pMallocShared = NULL; // is not addrefed
  28. // Note: bug 3698
  29. // MsPub is not calling CoInitialize befor calling OpenStorage to
  30. // preview templates. This pointer has an addref!
  31. // When this pointer is not NULL CoGetMalloc was called prior to CoInitialize
  32. // The pointer is transfered as soon as CoInitialize is called by any task.
  33. IMalloc FAR* v_pMallocPreShared = NULL;
  34. BOOL SetupSharedAllocator(Etask FAR& etask);
  35. //+---------------------------------------------------------------------------
  36. //
  37. // Function: TaskAlloc, private
  38. //
  39. // Synopsis: Allocates task memory
  40. //
  41. // Arguments: [cb] - Number of bytes to allocate
  42. //
  43. // Returns: Pointer to memory or NULL
  44. //
  45. // History: 03-Mar-94 DrewB Created
  46. //
  47. //----------------------------------------------------------------------------
  48. LPVOID __loadds FAR PASCAL TaskAlloc(ULONG cb)
  49. {
  50. HRESULT hr;
  51. LPMALLOC lpMalloc = NULL;
  52. LPVOID lpv;
  53. hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
  54. if (FAILED(GetScode(hr)) )
  55. {
  56. lpv = NULL;
  57. }
  58. else
  59. {
  60. thkAssert(lpMalloc != NULL && "CoGetMalloc pMalloce is NULL\n");
  61. lpv = lpMalloc->Alloc(cb);
  62. lpMalloc->Release();
  63. }
  64. return lpv;
  65. }
  66. //+---------------------------------------------------------------------------
  67. //
  68. // Function: TaskFree, private
  69. //
  70. // Synopsis: Free task memory
  71. //
  72. // Arguments: [pv] - Memory
  73. //
  74. // History: 03-Mar-94 DrewB Created
  75. //
  76. //----------------------------------------------------------------------------
  77. void __loadds FAR PASCAL TaskFree(LPVOID pv)
  78. {
  79. HRESULT hr;
  80. LPMALLOC lpMalloc;
  81. hr = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
  82. if (SUCCEEDED(GetScode(hr)))
  83. {
  84. lpMalloc->Free(pv);
  85. lpMalloc->Release();
  86. }
  87. }
  88. //+---------------------------------------------------------------------------
  89. //
  90. // Method: SetupSharedAllocator
  91. //
  92. // Synopsis: Allocats the shared allocator and
  93. // initializes the etask shared allocator
  94. //
  95. // Arguments: [etask] --
  96. //
  97. // Returns:
  98. //
  99. // History: 2-03-95 JohannP (Johann Posch) Created
  100. //
  101. // Notes: call by CoInitialize and DllEntryPoint
  102. //
  103. //----------------------------------------------------------------------------
  104. BOOL SetupSharedAllocator(Etask FAR& etask)
  105. {
  106. // we must ensure we have a shared allocator now since that is where the
  107. // etask map wiil be stored; if another process already created it, use it;
  108. // this is so we always use the same shared pool of memory for all
  109. // processes (so the DidAlloc method returns 1 for the same call from
  110. // different process); the pointer refers to shared memory within
  111. // the blocks managed by the IMalloc implementation and the
  112. // vtable is always valid on Windows; the global pointer carries
  113. // no ref count on its own; changes might be requires on
  114. // other platforms.
  115. if (v_pMallocPreShared != NULL)
  116. {
  117. // Note: fix for bug 3698;l MsPub not calling CoInitialize
  118. // transfer addref from preshared to task entry
  119. etask.m_pMallocShared = v_pMallocPreShared;
  120. v_pMallocShared = v_pMallocPreShared;
  121. v_pMallocPreShared = NULL;
  122. }
  123. else if (v_pMallocShared != NULL)
  124. {
  125. (etask.m_pMallocShared = v_pMallocShared)->AddRef();
  126. }
  127. else
  128. {
  129. // sets pMalloc to NULL on error
  130. CoCreateStandardMalloc(MEMCTX_SHARED, &etask.m_pMallocShared);
  131. v_pMallocShared = etask.m_pMallocShared;
  132. thkAssert(v_pMallocShared != NULL && "SetupSharedAllocator failed!");
  133. }
  134. return (v_pMallocShared != NULL) ? TRUE : FALSE;
  135. }
  136. //+---------------------------------------------------------------------------
  137. //
  138. // Function: CoInitialize, Split
  139. //
  140. // Synopsis:
  141. //
  142. // Effects:
  143. //
  144. // Arguments: [pMalloc] --
  145. //
  146. // Requires:
  147. //
  148. // Returns:
  149. //
  150. // Signals:
  151. //
  152. // Modifies:
  153. //
  154. // Algorithm:
  155. //
  156. // History: 2-28-94 kevinro Created
  157. // 3-08-94 BobDay Added code from \\ole\slm\...\compobj.cpp
  158. //
  159. // Notes:
  160. //
  161. //----------------------------------------------------------------------------
  162. // initialize compobj; errors: S_FALSE, E_OUTOFMEMORY
  163. STDAPI CoInitialize(IMalloc FAR* pMalloc)
  164. {
  165. LPMALLOC pmlNull = NULL;
  166. HRESULT hresult;
  167. HTASK htask;
  168. Etask etask;
  169. thkDebugOut((DEB_ITRACE, "CoInitialize\n"));
  170. thkDebugOut((DEB_APIS16, "CoInitilaize called on Process (%X) \n", GetCurrentProcess()));
  171. // if already init, bump count and return S_FALSE
  172. if ( IsEtaskInit(htask, etask)
  173. && IsValidInterface((etask.m_pMalloc)) )
  174. {
  175. if ( etask.m_inits != ETASK_FAKE_INIT )
  176. {
  177. etask.m_inits++;
  178. thkVerify(SetEtask(htask, etask));
  179. return ResultFromScode(S_FALSE);
  180. }
  181. //
  182. // CoInitialize has been called after we've done a fake call for them
  183. // we can just take over their allocator and get rid of our fake one.
  184. //
  185. if ( pMalloc != NULL )
  186. {
  187. etask.m_pMalloc->Release(); // Get rid of the old task allocator
  188. etask.m_pMalloc = pMalloc;
  189. etask.m_pMalloc->AddRef();
  190. }
  191. else
  192. {
  193. //
  194. // It would be nice if we could assert that the fake task
  195. // allocator was a default task allocator. i.e. no operation
  196. // were really needed!
  197. //
  198. }
  199. //
  200. // "We need to have a way to clean up any fake calls to
  201. // CoInitialize. Should the application go away after using one of
  202. // the apis that caused us to do a fake CoInitialize in the first
  203. // place, and should the application exit without really making a
  204. // call to CoInitialize eventually, then we wouldn't know enough to
  205. // clean up... I think this is ok for now. Most apps do call
  206. // CoInitialize eventually."
  207. //
  208. etask.m_inits = 1;
  209. thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
  210. thkVerify(SetEtask(htask, etask));
  211. return ResultFromScode(S_OK);
  212. }
  213. // set/create task malloc
  214. if (pMalloc != NULL)
  215. {
  216. VDATEIFACE( pMalloc );
  217. (etask.m_pMalloc = pMalloc)->AddRef();
  218. }
  219. else
  220. {
  221. if ((hresult = CoCreateStandardMalloc(MEMCTX_TASK,
  222. &etask.m_pMalloc)) != NOERROR)
  223. return hresult;
  224. }
  225. thkAssert(etask.m_pMalloc != NULL); // now have task allocator in all cases
  226. // set up the shared allocator
  227. if ( etask.m_pMallocShared == NULL
  228. && SetupSharedAllocator(etask) == FALSE)
  229. {
  230. etask.m_pMalloc->Release(); // was created or AddRef'd above
  231. return ResultFromScode(E_OUTOFMEMORY);
  232. }
  233. // now have shared allocator in all cases
  234. thkAssert(etask.m_pMallocShared != NULL);
  235. // init remaining entries and add entry to table for this app/task pair;
  236. // leave maps null for now (they are allocated on demand)
  237. etask.m_pMallocSBlock = NULL;
  238. etask.m_pMallocPrivate = NULL;
  239. etask.m_pid = MAKELONG(GetCurrentProcess(),v_pidHighWord++);
  240. etask.m_inits = 1;
  241. etask.m_oleinits = 0;
  242. etask.m_reserved = 0;
  243. etask.m_pDlls = NULL;
  244. etask.m_pMapToServerCO = NULL;
  245. etask.m_pMapToHandlerCO = NULL;
  246. etask.m_pArraySH = NULL;
  247. etask.m_pCThrd = NULL;
  248. etask.m_hwndClip = NULL;
  249. etask.m_hwndDde = NULL;
  250. etask.m_punkState = NULL;
  251. if (!SetEtask(htask, etask))
  252. {
  253. ReleaseEtask(NULL, etask);
  254. thkAssert(0 && "CompObj: CoInitialize SetEtask failed.");
  255. return ResultFromScode(E_OUTOFMEMORY);
  256. }
  257. // Initialize the thunk manager for this apartment.
  258. if (SUCCEEDED(hresult = CallThkMgrInitialize()))
  259. {
  260. //
  261. // Now transition into 32-bit world to give it a chance for
  262. // initialization at this time.
  263. //
  264. // Never pass the 16-bit allocator on to 32-bits
  265. pMalloc = NULL;
  266. hresult = (HRESULT)CallObjectInWOW(THK_API_METHOD(THK_API_CoInitialize),
  267. PASCAL_STACK_PTR(pMalloc) );
  268. }
  269. if (FAILED(GetScode(hresult)))
  270. {
  271. ReleaseEtask(htask, etask);
  272. }
  273. return hresult;
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // Function: CoUninitialize, Split
  278. //
  279. // Synopsis:
  280. //
  281. // Effects:
  282. //
  283. // Arguments: [void] --
  284. //
  285. // Requires:
  286. //
  287. // Returns:
  288. //
  289. // Signals:
  290. //
  291. // Modifies:
  292. //
  293. // Algorithm:
  294. //
  295. // History: 2-28-94 kevinro Created
  296. // 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
  297. //
  298. // Notes:
  299. //
  300. //----------------------------------------------------------------------------
  301. STDAPI_(void) CoUninitialize(void)
  302. {
  303. HTASK htask;
  304. Etask etask;
  305. thkDebugOut((DEB_ITRACE, "CoUninitialize\n"));
  306. thkDebugOut((DEB_APIS16, "CoUninitilaize called on Process (%X) \n", GetCurrentProcess()));
  307. if (!IsEtaskInit(htask, etask))
  308. return;
  309. // if not last uninit, just decrement count and return.
  310. if (etask.m_inits != 1)
  311. {
  312. //
  313. // If a fake init, then just ignore as if we haven't ever init'd
  314. //
  315. if ( etask.m_inits == ETASK_FAKE_INIT )
  316. {
  317. //
  318. // Some slimy app doesn't call CoInitialize but does eventually
  319. // call CoUninitialize. Lets find them if they do!
  320. //
  321. thkAssert(FALSE &&
  322. "CoUninitialize called after fake CoInitialize\n");
  323. }
  324. else
  325. {
  326. etask.m_inits--;
  327. thkVerify(SetEtask(htask, etask));
  328. }
  329. return ;
  330. }
  331. // Some applications pass on module handle of loaded dlls.
  332. // As a result LibMain and WEP is not called in the same process.
  333. // To prevent premature unloading of OleThk32.dll call
  334. // SetReleaseDLL(FALSE)
  335. SetReleaseDLL(FALSE);
  336. //
  337. // Now transition into 32-bit world to give it a chance for
  338. // initialization at this time.
  339. //
  340. CallObjectInWOW(THK_API_METHOD(THK_API_CoUninitialize), NULL );
  341. // Reset dll unloading - see above
  342. SetReleaseDLL(TRUE);
  343. CoFreeAllLibraries();
  344. //
  345. // We do not uninitialize the thunk manager at this point. The app may attempt
  346. // to call additional API's after CoUninitialize. For example, Lotus 1-2-3
  347. // is known to do this, as is Publisher. The thunk manager will clean up
  348. // as part of its thread detach.
  349. //
  350. // the last thing is to remove the allocator and delete the etask for us;
  351. // must lookup again in case contents changed.
  352. if (LookupEtask(htask, etask))
  353. ReleaseEtask(htask, etask);
  354. thkDebugOut((DEB_APIS16, "CoUninitilaize on Process (%X) done.\n", GetCurrentProcess()));
  355. thkDebugOut((DEB_ITRACE, "CoUninitialize exit\n"));
  356. // Note: some apps check the return value if the void function CoUninitialize
  357. // and they fail if it is not NULL like WinOffice Setup 4.3
  358. // Please don't take it out.
  359. _asm mov ax,0;
  360. _asm mov dx,0;
  361. }
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Function: CoGetMalloc, Local
  365. //
  366. // Synopsis:
  367. //
  368. // Effects:
  369. //
  370. // Arguments: [dwMemContext] --
  371. // [ppMalloc] --
  372. //
  373. // Requires:
  374. //
  375. // Returns:
  376. //
  377. // Signals:
  378. //
  379. // Modifies:
  380. //
  381. // Algorithm:
  382. //
  383. // History: 2-28-94 kevinro Created
  384. // 10-Mar-94 BobDay Copied & Merged with compobj.cpp 16-bit
  385. //
  386. // Notes:
  387. //
  388. //----------------------------------------------------------------------------
  389. // return pMalloc for the current task; errors: E_INVALIDARG,
  390. // CO_E_NOTINITIALIZED, E_OUTOFMEMORY (not for task or shared allocators)
  391. STDAPI CoGetMalloc(DWORD dwContext, IMalloc FAR* FAR* ppMalloc)
  392. {
  393. Etask etask;
  394. HTASK htask;
  395. thkDebugOut((DEB_ITRACE, " CoGetMalloc\n"));
  396. VDATEPTROUT( ppMalloc, IMalloc FAR* );
  397. // NOTE: we set *ppMalloc to NULL only in the error cases below
  398. // MOre work here!
  399. // need this for the bootstrap case
  400. if (dwContext == MEMCTX_SHARED)
  401. {
  402. if (v_pMallocShared != NULL)
  403. {
  404. *ppMalloc = v_pMallocShared;
  405. goto Exit;
  406. }
  407. // pMallocShared is NULL -- CoInitialize was not called yet.
  408. if (v_pMallocPreShared == NULL)
  409. {
  410. CoCreateStandardMalloc(MEMCTX_SHARED, &v_pMallocPreShared);
  411. if (v_pMallocPreShared != NULL)
  412. {
  413. *ppMalloc = v_pMallocPreShared;
  414. goto Exit;
  415. }
  416. else
  417. {
  418. *ppMalloc = NULL;
  419. return ResultFromScode(CO_E_NOTINITIALIZED);
  420. }
  421. }
  422. else
  423. {
  424. *ppMalloc = v_pMallocPreShared;
  425. goto Exit;
  426. }
  427. }
  428. //
  429. // Clip Art Gallery will call pStream->Stat before calling CoInitialize.
  430. // This causes the thunk logic to allocation 16bit memory which will
  431. // fail at this point. The below code to auto-initialize should this
  432. // happen. (Really just a hack for Clip Art Gallery).
  433. //
  434. if ( !IsEtaskInit(htask, etask)
  435. || !IsValidInterface((etask.m_pMalloc)) )
  436. {
  437. if (FAILED(CoInitialize(NULL)))
  438. {
  439. *ppMalloc = NULL;
  440. return ResultFromScode(CO_E_NOTINITIALIZED);
  441. }
  442. thkVerify(LookupEtask( htask, etask ));
  443. etask.m_inits = ETASK_FAKE_INIT;
  444. thkVerify(SetEtask(htask, etask));
  445. }
  446. // shared always available if initialized; no need to handle here
  447. thkAssert(dwContext != MEMCTX_SHARED);
  448. if (dwContext == MEMCTX_TASK)
  449. {
  450. thkAssert(etask.m_pMalloc != NULL);
  451. *ppMalloc = etask.m_pMalloc;
  452. }
  453. else
  454. {
  455. // invalid context
  456. thkAssert(!"Unknown memctx in CoGetMalloc");
  457. *ppMalloc = NULL;
  458. return ResultFromScode(E_INVALIDARG);
  459. }
  460. Exit: // have non-null *ppMalloc
  461. thkAssert(*ppMalloc != NULL);
  462. (*ppMalloc)->AddRef();
  463. return NOERROR;
  464. }
  465. //+---------------------------------------------------------------------------
  466. //
  467. // Function: CoGetState, Local
  468. //
  469. // Synopsis: Retrieves task-specific state
  470. //
  471. // Arguments: [ppunk] - IUnknown pointer to fill in
  472. //
  473. // Returns: Appropriate status code
  474. //
  475. // History: 26-Jul-94 DrewB Created
  476. //
  477. // Notes: Private API for OLE automation
  478. //
  479. //----------------------------------------------------------------------------
  480. STDAPI CoGetState(IUnknown FAR * FAR *ppunk)
  481. {
  482. Etask etask;
  483. HTASK htask;
  484. thkDebugOut((DEB_APIS16, "CoGetState called\n"));
  485. if (IsBadWritePtr(ppunk, sizeof(IUnknown *)))
  486. {
  487. thkDebugOut((DEB_APIS16, "CoGetState failed\n"));
  488. return ResultFromScode(E_INVALIDARG);
  489. }
  490. if (!LookupEtask(htask, etask) || etask.m_punkState == NULL )
  491. {
  492. *ppunk = NULL;
  493. thkDebugOut((DEB_APIS16, "CoGetState failed\n"));
  494. return ResultFromScode(S_FALSE);
  495. }
  496. if ( !IsValidInterface((etask.m_punkState)) )
  497. {
  498. *ppunk = NULL;
  499. etask.m_punkState = NULL;
  500. thkDebugOut((DEB_APIS16, "CoGetState failed (invalid interface)\n"));
  501. return ResultFromScode(S_FALSE);
  502. }
  503. *ppunk = etask.m_punkState;
  504. etask.m_punkState->AddRef();
  505. thkDebugOut((DEB_APIS16, "CoGetState done %p\n", *ppunk));
  506. return NOERROR;
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // Function: CoSetState, Local
  511. //
  512. // Synopsis: Sets task-specific state
  513. //
  514. // Arguments: [punk] - State to set
  515. //
  516. // Returns: Appropriate status code
  517. //
  518. // History: 26-Jul-94 DrewB Created
  519. //
  520. // Notes: Private API for OLE automation
  521. //
  522. //----------------------------------------------------------------------------
  523. STDAPI CoSetState(IUnknown FAR *punk)
  524. {
  525. Etask etask;
  526. HTASK htask;
  527. IUnknown FAR *punkStateOld;
  528. thkDebugOut((DEB_APIS16, "CoSetState called %p\n", punk));
  529. if (punk != NULL && !IsValidInterface(punk))
  530. {
  531. thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk));
  532. return ResultFromScode(E_INVALIDARG);
  533. }
  534. if (!IsEtaskInit(htask, etask))
  535. {
  536. thkDebugOut((DEB_APIS16, "CoSetState called %p failed\n", punk));
  537. return ResultFromScode(S_FALSE);
  538. }
  539. if (punk != NULL)
  540. {
  541. punk->AddRef();
  542. }
  543. punkStateOld = etask.m_punkState;
  544. etask.m_punkState = punk;
  545. thkVerify(SetEtask(htask, etask));
  546. if (punkStateOld != NULL && IsValidInterface(punkStateOld))
  547. {
  548. punkStateOld->Release();
  549. }
  550. thkDebugOut((DEB_APIS16, "CoSetState called %p done\n", punk));
  551. return NOERROR;
  552. }
  553. //+---------------------------------------------------------------------------
  554. //
  555. // Function: CoGetCurrentProcess, Local
  556. //
  557. //----------------------------------------------------------------------------
  558. // returns a unique value for the current task; this routine is
  559. // necessary because htask values from Window get reused periodically.
  560. STDAPI_(DWORD) CoGetCurrentProcess(void)
  561. {
  562. HTASK htask;
  563. Etask etask;
  564. thkDebugOut((DEB_ITRACE, " CoGetCurrentProcess\n"));
  565. if (!IsEtaskInit(htask, etask))
  566. return 0;
  567. return etask.m_pid;
  568. }
  569. //+---------------------------------------------------------------------------
  570. //
  571. // Function: CoBuildVersion, Local
  572. //
  573. //----------------------------------------------------------------------------
  574. STDAPI_(DWORD) CoBuildVersion(VOID)
  575. {
  576. thkDebugOut((DEB_ITRACE, " CoBuildVersion\n"));
  577. // We must return 23 as our major version number to remain
  578. // compatible with shipped OLE 2.01
  579. // OLE 2.01 shipped with minor version 640
  580. // We return a number slightly higher to differentiate
  581. // our product while indicating compatibility
  582. return MAKELONG(700, 23);
  583. }
  584. //+---------------------------------------------------------------------------
  585. //
  586. // Function: CoMarshalHresult, Local
  587. //
  588. // History: Taken straight from OLE2 sources
  589. //
  590. //----------------------------------------------------------------------------
  591. STDAPI CoMarshalHresult(LPSTREAM pstm, HRESULT hresult)
  592. {
  593. HRESULT hr;
  594. thkDebugOut((DEB_ITRACE, "CoMarshalHresult\n"));
  595. if (!IsValidInterface(pstm))
  596. {
  597. hr = ResultFromScode(E_INVALIDARG);
  598. }
  599. else
  600. {
  601. SCODE sc;
  602. ULONG cb;
  603. sc = GetScode(hresult);
  604. hr = pstm->Write(&sc, sizeof(sc), &cb);
  605. if (SUCCEEDED(GetScode(hr)) && cb != sizeof(sc))
  606. {
  607. hr = ResultFromScode(STG_E_WRITEFAULT);
  608. }
  609. }
  610. return hr;
  611. }
  612. //+---------------------------------------------------------------------------
  613. //
  614. // Function: CoUnmarshalHresult, Local
  615. //
  616. // History: Taken straight from OLE2 sources
  617. //
  618. //----------------------------------------------------------------------------
  619. STDAPI CoUnmarshalHresult(LPSTREAM pstm, HRESULT FAR * phresult)
  620. {
  621. HRESULT hr;
  622. thkDebugOut((DEB_ITRACE, "CoUnmarshalHresult\n"));
  623. if (!IsValidPtrOut(phresult, sizeof(HRESULT)))
  624. {
  625. hr = ResultFromScode(E_INVALIDARG);
  626. }
  627. else
  628. {
  629. *phresult = 0;
  630. if (!IsValidInterface(pstm))
  631. {
  632. hr = ResultFromScode(E_INVALIDARG);
  633. }
  634. else
  635. {
  636. SCODE sc;
  637. ULONG cb;
  638. hr = pstm->Read(&sc, sizeof(sc), &cb);
  639. if (SUCCEEDED(GetScode(hr)))
  640. {
  641. if (cb != sizeof(sc))
  642. {
  643. hr = ResultFromScode(STG_E_READFAULT);
  644. }
  645. else
  646. {
  647. *phresult = ResultFromScode(sc);
  648. }
  649. }
  650. }
  651. }
  652. return hr;
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // Function: IsEqualGUID, Local
  657. //
  658. // History: Taken straight from OLE2 sources
  659. //
  660. //----------------------------------------------------------------------------
  661. #pragma intrinsic(_fmemcmp)
  662. STDAPI_(BOOL) IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
  663. {
  664. //thkDebugOut((DEB_ITRACE, "IsEqualGUID\n"));
  665. return !_fmemcmp(&rguid1, &rguid2, sizeof(GUID));
  666. }
  667. #pragma function(_fmemcmp)
  668. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  669. //+---------------------------------------------------------------------------
  670. //
  671. // Function: HexStringToDword, private
  672. //
  673. // History: Straight from OLE2 sources
  674. //
  675. //----------------------------------------------------------------------------
  676. static BOOL HexStringToDword(LPCSTR FAR& lpsz, DWORD FAR& Value, int cDigits,
  677. char chDelim)
  678. {
  679. int Count;
  680. Value = 0;
  681. for (Count = 0; Count < cDigits; Count++, lpsz++)
  682. {
  683. if (*lpsz >= '0' && *lpsz <= '9')
  684. {
  685. Value = (Value << 4) + *lpsz - '0';
  686. }
  687. else if (*lpsz >= 'A' && *lpsz <= 'F')
  688. {
  689. Value = (Value << 4) + *lpsz - 'A' + 10;
  690. }
  691. else if (*lpsz >= 'a' && *lpsz <= 'f')
  692. {
  693. Value = (Value << 4) + *lpsz - 'a' + 10;
  694. }
  695. else
  696. {
  697. return(FALSE);
  698. }
  699. }
  700. if (chDelim != 0)
  701. {
  702. return *lpsz++ == chDelim;
  703. }
  704. else
  705. {
  706. return TRUE;
  707. }
  708. }
  709. //+---------------------------------------------------------------------------
  710. //
  711. // Function: GUIDFromString, private
  712. //
  713. // History: Straight from OLE2 sources
  714. //
  715. //----------------------------------------------------------------------------
  716. STDAPI_(BOOL) GUIDFromString(LPCSTR lpsz, LPGUID pguid)
  717. {
  718. DWORD dw;
  719. if (*lpsz++ != '{')
  720. return FALSE;
  721. if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
  722. return FALSE;
  723. if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
  724. return FALSE;
  725. pguid->Data2 = (WORD)dw;
  726. if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
  727. return FALSE;
  728. pguid->Data3 = (WORD)dw;
  729. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  730. return FALSE;
  731. pguid->Data4[0] = (BYTE)dw;
  732. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
  733. return FALSE;
  734. pguid->Data4[1] = (BYTE)dw;
  735. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  736. return FALSE;
  737. pguid->Data4[2] = (BYTE)dw;
  738. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  739. return FALSE;
  740. pguid->Data4[3] = (BYTE)dw;
  741. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  742. return FALSE;
  743. pguid->Data4[4] = (BYTE)dw;
  744. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  745. return FALSE;
  746. pguid->Data4[5] = (BYTE)dw;
  747. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  748. return FALSE;
  749. pguid->Data4[6] = (BYTE)dw;
  750. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '}'))
  751. return FALSE;
  752. pguid->Data4[7] = (BYTE)dw;
  753. return TRUE;
  754. }
  755. //+---------------------------------------------------------------------------
  756. //
  757. // Function: StringFromCLSID, Local
  758. //
  759. // History: Straight from OLE2 sources
  760. //
  761. //----------------------------------------------------------------------------
  762. #define CLSIDSTR_MAX (GUIDSTR_MAX)
  763. STDAPI StringFromCLSID(REFCLSID rclsid, LPSTR FAR* lplpsz)
  764. {
  765. SCODE sc;
  766. char *psz;
  767. thkDebugOut((DEB_ITRACE, "StringFromCLSID\n"));
  768. psz = NULL;
  769. do
  770. {
  771. if (!IsValidPtrOut(lplpsz, sizeof(LPSTR)))
  772. {
  773. sc = E_INVALIDARG;
  774. break;
  775. }
  776. *lplpsz = NULL;
  777. if (!IsValidPtrIn(&rclsid, sizeof(CLSID)))
  778. {
  779. sc = E_INVALIDARG;
  780. break;
  781. }
  782. psz = (char *)TaskAlloc(CLSIDSTR_MAX);
  783. if (psz == NULL)
  784. {
  785. sc = E_OUTOFMEMORY;
  786. break;
  787. }
  788. if (StringFromGUID2(rclsid, psz, CLSIDSTR_MAX) == 0)
  789. {
  790. sc = E_INVALIDARG;
  791. TaskFree(psz);
  792. break;
  793. }
  794. *lplpsz = psz;
  795. sc = S_OK;
  796. } while (FALSE);
  797. return ResultFromScode(sc);
  798. }
  799. //+---------------------------------------------------------------------------
  800. //
  801. // Function: StringFromIID, Local
  802. //
  803. // History: Straight from OLE2 sources
  804. //
  805. //----------------------------------------------------------------------------
  806. STDAPI StringFromIID(REFIID rclsid, LPSTR FAR* lplpsz)
  807. {
  808. SCODE sc;
  809. char *psz;
  810. thkDebugOut((DEB_ITRACE, "StringFromIID\n"));
  811. do
  812. {
  813. if (!IsValidPtrOut(lplpsz, sizeof(LPSTR)))
  814. {
  815. sc = E_INVALIDARG;
  816. break;
  817. }
  818. *lplpsz = NULL;
  819. if (!IsValidPtrIn(&rclsid, sizeof(IID)))
  820. {
  821. sc = E_INVALIDARG;
  822. break;
  823. }
  824. psz = (char *)TaskAlloc(GUIDSTR_MAX);
  825. if (psz == NULL)
  826. {
  827. sc = E_OUTOFMEMORY;
  828. break;
  829. }
  830. if (StringFromGUID2(rclsid, psz, GUIDSTR_MAX) == 0)
  831. {
  832. sc = E_INVALIDARG;
  833. TaskFree(psz);
  834. break;
  835. }
  836. *lplpsz = psz;
  837. sc = S_OK;
  838. } while (FALSE);
  839. return ResultFromScode(sc);
  840. }
  841. //+---------------------------------------------------------------------------
  842. //
  843. // Function: IIDFromString, Local
  844. //
  845. // History: Straight from OLE2 sources
  846. //
  847. //----------------------------------------------------------------------------
  848. STDAPI IIDFromString(LPSTR lpsz, LPIID lpiid)
  849. {
  850. SCODE sc;
  851. thkDebugOut((DEB_ITRACE, "IIDFromString\n"));
  852. sc = S_OK;
  853. if (!IsValidPtrOut(lpiid, sizeof(IID)))
  854. {
  855. sc = E_INVALIDARG;
  856. }
  857. else if (lpsz == NULL)
  858. {
  859. *lpiid = IID_NULL;
  860. }
  861. else if (!IsValidPtrIn(lpsz, sizeof(LPSTR)))
  862. {
  863. sc = E_INVALIDARG;
  864. }
  865. else if (!GUIDFromString(lpsz, lpiid))
  866. {
  867. sc = CO_E_IIDSTRING;
  868. }
  869. return ResultFromScode(sc);
  870. }
  871. //+---------------------------------------------------------------------------
  872. //
  873. // Function: StringFromGUID2, Local
  874. //
  875. // History: Straight from OLE2 sources
  876. //
  877. //----------------------------------------------------------------------------
  878. STDAPI_(int) StringFromGUID2(REFGUID rguid, LPSTR lpsz, int cbMax)
  879. {
  880. thkDebugOut((DEB_ITRACE, "StringFromGUID2\n"));
  881. if (cbMax < GUIDSTR_MAX)
  882. {
  883. return 0;
  884. }
  885. wsprintf(lpsz, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  886. rguid.Data1, rguid.Data2, rguid.Data3,
  887. rguid.Data4[0], rguid.Data4[1],
  888. rguid.Data4[2], rguid.Data4[3],
  889. rguid.Data4[4], rguid.Data4[5],
  890. rguid.Data4[6], rguid.Data4[7]);
  891. return GUIDSTR_MAX;
  892. }
  893. // The following two APIs are now macros but must still be exported
  894. // so use PASCAL-form names to avoid problems with the macros
  895. //+---------------------------------------------------------------------------
  896. //
  897. // Function: GETSCODE, Local
  898. //
  899. // History: Straight from OLE2 sources
  900. //
  901. //----------------------------------------------------------------------------
  902. STDAPI_(SCODE) GETSCODE(HRESULT hr)
  903. {
  904. return GetScode(hr);
  905. }
  906. //+---------------------------------------------------------------------------
  907. //
  908. // Function: RESULTFROMSCODE, Local
  909. //
  910. // History: Straight from OLE2 sources
  911. //
  912. //----------------------------------------------------------------------------
  913. STDAPI RESULTFROMSCODE(SCODE sc)
  914. {
  915. return ResultFromScode(sc);
  916. }
  917. //+---------------------------------------------------------------------------
  918. //
  919. // Function: PropagateResult, Local
  920. //
  921. // History: Straight from OLE2 sources
  922. //
  923. //----------------------------------------------------------------------------
  924. STDAPI PropagateResult(HRESULT hrPrev, SCODE scNew)
  925. {
  926. thkDebugOut((DEB_ITRACE, "PropagateResult\n"));
  927. return (HRESULT)((scNew & 0x800FFFFF) | ((DWORD)hrPrev & 0x7FF00000)
  928. + 0x100000);
  929. }
  930. //+---------------------------------------------------------------------------
  931. //
  932. // Function: FnAssert, Local
  933. //
  934. // History: Straight from OLE2 sources
  935. //
  936. //----------------------------------------------------------------------------
  937. #if DBG == 1
  938. static char lpBuffer[512];
  939. static char lpLocBuffer[256];
  940. #endif
  941. STDAPI FnAssert( LPSTR lpstrExpr,
  942. LPSTR lpstrMsg,
  943. LPSTR lpstrFileName,
  944. UINT iLine )
  945. {
  946. #if DBG == 1
  947. int iResult;
  948. wsprintf(lpBuffer, "Assertion \"%s\" failed! %s", lpstrExpr, lpstrMsg);
  949. wsprintf(lpLocBuffer, "File %s, line %d; (A=exit; R=break; I=continue)",
  950. lpstrFileName, iLine);
  951. iResult = MessageBox(NULL, lpLocBuffer, lpBuffer,
  952. MB_ABORTRETRYIGNORE | MB_SYSTEMMODAL);
  953. if (iResult == IDRETRY)
  954. {
  955. DebugBreak();
  956. }
  957. else if (iResult == IDABORT)
  958. {
  959. CoFreeAllLibraries();
  960. FatalAppExit(0, "Assertion failure");
  961. }
  962. #endif
  963. return NOERROR;
  964. }
  965. //
  966. // NOTE- These APIs are exported by the .DEF file, but are not documented,
  967. // nor is there any code in the 16-bit world to deal with them. Each of these
  968. // needs to be investigated to determine what we need to do to implement them.
  969. //
  970. // LRPCDISPATCH
  971. // REMCONNECTTOOBJECT
  972. // REMCREATEREMOTEHANDLER
  973. // REMALLOCOID
  974. // LRPCFREEMONITORDATA
  975. // TIMERCALLBACKPROC
  976. // COSETACKSTATE
  977. // COGETCLASSEXT
  978. // LRPCCALL
  979. // LRPCREGISTERMONITOR
  980. // CLSIDFROMOLE1CLASS
  981. // COOPENCLASSKEY
  982. // LRPCGETTHREADWINDOW
  983. // LRPCREVOKEMONITOR
  984. // COHANDLEINCOMINGCALL
  985. // REMGETINFOFORCID
  986. //
  987. // The below stubs probably don't clean up the stack properly either!!!
  988. #define UNDEFINED_DEF_ENTRY(x) STDAPI x ( void ) \
  989. { return ResultFromScode(E_NOTIMPL); }
  990. UNDEFINED_DEF_ENTRY( LRPCDISPATCH )
  991. UNDEFINED_DEF_ENTRY( REMCONNECTTOOBJECT )
  992. UNDEFINED_DEF_ENTRY( REMCREATEREMOTEHANDLER )
  993. UNDEFINED_DEF_ENTRY( REMALLOCOID )
  994. UNDEFINED_DEF_ENTRY( LRPCFREEMONITORDATA )
  995. UNDEFINED_DEF_ENTRY( TIMERCALLBACKPROC )
  996. UNDEFINED_DEF_ENTRY( COSETACKSTATE )
  997. UNDEFINED_DEF_ENTRY( COGETCLASSEXT )
  998. UNDEFINED_DEF_ENTRY( LRPCCALL )
  999. UNDEFINED_DEF_ENTRY( LRPCREGISTERMONITOR )
  1000. UNDEFINED_DEF_ENTRY( CLSIDFROMOLE1CLASS )
  1001. UNDEFINED_DEF_ENTRY( COOPENCLASSKEY )
  1002. UNDEFINED_DEF_ENTRY( LRPCGETTHREADWINDOW )
  1003. UNDEFINED_DEF_ENTRY( LRPCREVOKEMONITOR )
  1004. UNDEFINED_DEF_ENTRY( COHANDLEINCOMINGCALL )
  1005. UNDEFINED_DEF_ENTRY( REMGETINFOFORCID )
  1006. UNDEFINED_DEF_ENTRY( OLE1CLASSFROMCLSID2 )
  1007. UNDEFINED_DEF_ENTRY( REMLOOKUPSHUNK )
  1008. UNDEFINED_DEF_ENTRY( REMFREEOID )