Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

823 lines
26 KiB

  1. /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name :
  4. stblsclt.c
  5. Abstract :
  6. This file contains the routines for support of stubless clients in
  7. object interfaces.
  8. Note:
  9. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  10. IMPORTANT!
  11. THIS FILE IS PLATFORM SPECIFIC AND DUPLICATE AMONG ALL PLATFORMS. CHANING
  12. ONE FILE MEANS CHANGE ALL OF THEM!!!
  13. Author :
  14. David Kays dkays February 1995.
  15. Revision History :
  16. Yong Qu YongQu Oct. 1998 change to platform specific and allow unlimited
  17. vtbl & delegation vtbl
  18. ---------------------------------------------------------------------*/
  19. #define USE_STUBLESS_PROXY
  20. #define CINTERFACE
  21. #include <stdarg.h>
  22. #include "ndrp.h"
  23. #include "hndl.h"
  24. #include "interp2.h"
  25. #include "ndrtypes.h"
  26. #include "ndrole.h"
  27. #include "mulsyntx.h"
  28. #include "rpcproxy.h"
  29. #pragma code_seg(".orpc")
  30. typedef unsigned short ushort;
  31. #define NUMBER_OF_BLOCKS_PER_ALLOC 4
  32. // for dynamically generated vtbl
  33. #define NUMBER_OF_METHODS_PER_BLOCK 56
  34. #define NUMBER_OF_FORWARDING_METHODS_PER_BLOCK 48
  35. // pointed to array of masm macro. don't need to generate the buffer everytime.
  36. #define CB_METHOD 4
  37. // vtbl jmp talble
  38. const BYTE CASM_GENERATESTUBLESS[] =
  39. {
  40. 0x33, 0xC9, // xor eax,eax
  41. 0x8A, 0xC8, // move al,cl
  42. 0x81, 0xC1, 00,00,04,00, // method id
  43. 0xFF, 0x25, 00,00,00,00 // long jmp to ObjectStubless@0
  44. };
  45. const BYTE CASM_GENERATEFORWARD[] =
  46. {
  47. 0x8b, 0x4c, 0x24, 0x04, // mov ecx, [esp+4]
  48. 0x8b, 0x49, 0x10, // mov ecx, [ecx+a]
  49. 0x89, 0x4c, 0x24, 0x4, // mov [esp+4], ecx
  50. 0x8b, 0x09, // mov ecx, [ecx]
  51. 0x66, 0x98, // cbw
  52. 0x98, // cwde
  53. 5, 00, 10, 00, 00, // add eax, 0x1000
  54. 0xc1, 0xe0, 0x02, // shl eax, 0x2
  55. 0x8b, 0x04, 0x01, // mov eax, [eax+ecx]
  56. 0xff, 0xe0 // jmp eax
  57. };
  58. typedef struct tagStublessProcBuffer
  59. {
  60. BYTE pMethodsa[NUMBER_OF_METHODS_PER_BLOCK/2][CB_METHOD];
  61. struct tagStublessProcBuffer* pNext;
  62. BYTE pAsm[sizeof(CASM_GENERATESTUBLESS)];
  63. BYTE pMethodsb[NUMBER_OF_METHODS_PER_BLOCK/2][CB_METHOD];
  64. } StublessProcBuffer, *PStublessProcBuffer;
  65. static StublessProcBuffer * g_pStublessProcBuffer = NULL;
  66. typedef struct tagForwardProcBuffer
  67. {
  68. BYTE pMethodsa[NUMBER_OF_FORWARDING_METHODS_PER_BLOCK/2][CB_METHOD];
  69. struct tagForwardProcBuffer* pNext;
  70. BYTE pAsm[sizeof(CASM_GENERATEFORWARD)];
  71. BYTE pMethodsb[NUMBER_OF_FORWARDING_METHODS_PER_BLOCK/2][CB_METHOD];
  72. } ForwardProcBuffer, *PForwardProcBuffer;
  73. static ForwardProcBuffer * g_pForwardProcBuffer = NULL;
  74. extern void ** ProxyForwardVtbl;
  75. EXTERN_C void ObjectStubless(void);
  76. void ReleaseTemplateForwardVtbl(void ** pVtbl);
  77. void ReleaseTemplateVtbl(void ** pVtbl);
  78. static DWORD g_ObjectStubless = (DWORD)ObjectStubless;
  79. extern ULONG g_dwVtblSize,g_dwForwardVtblSize;
  80. extern "C"
  81. {
  82. long
  83. ObjectStublessClient(
  84. void * ParamAddress,
  85. long Method
  86. );
  87. void ObjectStublessClient3(void);
  88. void ObjectStublessClient4(void);
  89. void ObjectStublessClient5(void);
  90. void ObjectStublessClient6(void);
  91. void ObjectStublessClient7(void);
  92. void ObjectStublessClient8(void);
  93. void ObjectStublessClient9(void);
  94. void ObjectStublessClient10(void);
  95. void ObjectStublessClient11(void);
  96. void ObjectStublessClient12(void);
  97. void ObjectStublessClient13(void);
  98. void ObjectStublessClient14(void);
  99. void ObjectStublessClient15(void);
  100. void ObjectStublessClient16(void);
  101. void ObjectStublessClient17(void);
  102. void ObjectStublessClient18(void);
  103. void ObjectStublessClient19(void);
  104. void ObjectStublessClient20(void);
  105. void ObjectStublessClient21(void);
  106. void ObjectStublessClient22(void);
  107. void ObjectStublessClient23(void);
  108. void ObjectStublessClient24(void);
  109. void ObjectStublessClient25(void);
  110. void ObjectStublessClient26(void);
  111. void ObjectStublessClient27(void);
  112. void ObjectStublessClient28(void);
  113. void ObjectStublessClient29(void);
  114. void ObjectStublessClient30(void);
  115. void ObjectStublessClient31(void);
  116. void ObjectStublessClient32(void);
  117. void ObjectStublessClient33(void);
  118. void ObjectStublessClient34(void);
  119. void ObjectStublessClient35(void);
  120. void ObjectStublessClient36(void);
  121. void ObjectStublessClient37(void);
  122. void ObjectStublessClient38(void);
  123. void ObjectStublessClient39(void);
  124. void ObjectStublessClient40(void);
  125. void ObjectStublessClient41(void);
  126. void ObjectStublessClient42(void);
  127. void ObjectStublessClient43(void);
  128. void ObjectStublessClient44(void);
  129. void ObjectStublessClient45(void);
  130. void ObjectStublessClient46(void);
  131. void ObjectStublessClient47(void);
  132. void ObjectStublessClient48(void);
  133. void ObjectStublessClient49(void);
  134. void ObjectStublessClient50(void);
  135. void ObjectStublessClient51(void);
  136. void ObjectStublessClient52(void);
  137. void ObjectStublessClient53(void);
  138. void ObjectStublessClient54(void);
  139. void ObjectStublessClient55(void);
  140. void ObjectStublessClient56(void);
  141. void ObjectStublessClient57(void);
  142. void ObjectStublessClient58(void);
  143. void ObjectStublessClient59(void);
  144. void ObjectStublessClient60(void);
  145. void ObjectStublessClient61(void);
  146. void ObjectStublessClient62(void);
  147. void ObjectStublessClient63(void);
  148. void ObjectStublessClient64(void);
  149. void ObjectStublessClient65(void);
  150. void ObjectStublessClient66(void);
  151. void ObjectStublessClient67(void);
  152. void ObjectStublessClient68(void);
  153. void ObjectStublessClient69(void);
  154. void ObjectStublessClient70(void);
  155. void ObjectStublessClient71(void);
  156. void ObjectStublessClient72(void);
  157. void ObjectStublessClient73(void);
  158. void ObjectStublessClient74(void);
  159. void ObjectStublessClient75(void);
  160. void ObjectStublessClient76(void);
  161. void ObjectStublessClient77(void);
  162. void ObjectStublessClient78(void);
  163. void ObjectStublessClient79(void);
  164. void ObjectStublessClient80(void);
  165. void ObjectStublessClient81(void);
  166. void ObjectStublessClient82(void);
  167. void ObjectStublessClient83(void);
  168. void ObjectStublessClient84(void);
  169. void ObjectStublessClient85(void);
  170. void ObjectStublessClient86(void);
  171. void ObjectStublessClient87(void);
  172. void ObjectStublessClient88(void);
  173. void ObjectStublessClient89(void);
  174. void ObjectStublessClient90(void);
  175. void ObjectStublessClient91(void);
  176. void ObjectStublessClient92(void);
  177. void ObjectStublessClient93(void);
  178. void ObjectStublessClient94(void);
  179. void ObjectStublessClient95(void);
  180. void ObjectStublessClient96(void);
  181. void ObjectStublessClient97(void);
  182. void ObjectStublessClient98(void);
  183. void ObjectStublessClient99(void);
  184. void ObjectStublessClient100(void);
  185. void ObjectStublessClient101(void);
  186. void ObjectStublessClient102(void);
  187. void ObjectStublessClient103(void);
  188. void ObjectStublessClient104(void);
  189. void ObjectStublessClient105(void);
  190. void ObjectStublessClient106(void);
  191. void ObjectStublessClient107(void);
  192. void ObjectStublessClient108(void);
  193. void ObjectStublessClient109(void);
  194. void ObjectStublessClient110(void);
  195. void ObjectStublessClient111(void);
  196. void ObjectStublessClient112(void);
  197. void ObjectStublessClient113(void);
  198. void ObjectStublessClient114(void);
  199. void ObjectStublessClient115(void);
  200. void ObjectStublessClient116(void);
  201. void ObjectStublessClient117(void);
  202. void ObjectStublessClient118(void);
  203. void ObjectStublessClient119(void);
  204. void ObjectStublessClient120(void);
  205. void ObjectStublessClient121(void);
  206. void ObjectStublessClient122(void);
  207. void ObjectStublessClient123(void);
  208. void ObjectStublessClient124(void);
  209. void ObjectStublessClient125(void);
  210. void ObjectStublessClient126(void);
  211. void ObjectStublessClient127(void);
  212. extern void * const g_StublessClientVtbl[128] =
  213. {
  214. IUnknown_QueryInterface_Proxy,
  215. IUnknown_AddRef_Proxy,
  216. IUnknown_Release_Proxy,
  217. ObjectStublessClient3,
  218. ObjectStublessClient4,
  219. ObjectStublessClient5,
  220. ObjectStublessClient6,
  221. ObjectStublessClient7,
  222. ObjectStublessClient8,
  223. ObjectStublessClient9,
  224. ObjectStublessClient10,
  225. ObjectStublessClient11,
  226. ObjectStublessClient12,
  227. ObjectStublessClient13,
  228. ObjectStublessClient14,
  229. ObjectStublessClient15,
  230. ObjectStublessClient16,
  231. ObjectStublessClient17,
  232. ObjectStublessClient18,
  233. ObjectStublessClient19,
  234. ObjectStublessClient20,
  235. ObjectStublessClient21,
  236. ObjectStublessClient22,
  237. ObjectStublessClient23,
  238. ObjectStublessClient24,
  239. ObjectStublessClient25,
  240. ObjectStublessClient26,
  241. ObjectStublessClient27,
  242. ObjectStublessClient28,
  243. ObjectStublessClient29,
  244. ObjectStublessClient30,
  245. ObjectStublessClient31,
  246. ObjectStublessClient32,
  247. ObjectStublessClient33,
  248. ObjectStublessClient34,
  249. ObjectStublessClient35,
  250. ObjectStublessClient36,
  251. ObjectStublessClient37,
  252. ObjectStublessClient38,
  253. ObjectStublessClient39,
  254. ObjectStublessClient40,
  255. ObjectStublessClient41,
  256. ObjectStublessClient42,
  257. ObjectStublessClient43,
  258. ObjectStublessClient44,
  259. ObjectStublessClient45,
  260. ObjectStublessClient46,
  261. ObjectStublessClient47,
  262. ObjectStublessClient48,
  263. ObjectStublessClient49,
  264. ObjectStublessClient50,
  265. ObjectStublessClient51,
  266. ObjectStublessClient52,
  267. ObjectStublessClient53,
  268. ObjectStublessClient54,
  269. ObjectStublessClient55,
  270. ObjectStublessClient56,
  271. ObjectStublessClient57,
  272. ObjectStublessClient58,
  273. ObjectStublessClient59,
  274. ObjectStublessClient60,
  275. ObjectStublessClient61,
  276. ObjectStublessClient62,
  277. ObjectStublessClient63,
  278. ObjectStublessClient64,
  279. ObjectStublessClient65,
  280. ObjectStublessClient66,
  281. ObjectStublessClient67,
  282. ObjectStublessClient68,
  283. ObjectStublessClient69,
  284. ObjectStublessClient70,
  285. ObjectStublessClient71,
  286. ObjectStublessClient72,
  287. ObjectStublessClient73,
  288. ObjectStublessClient74,
  289. ObjectStublessClient75,
  290. ObjectStublessClient76,
  291. ObjectStublessClient77,
  292. ObjectStublessClient78,
  293. ObjectStublessClient79,
  294. ObjectStublessClient80,
  295. ObjectStublessClient81,
  296. ObjectStublessClient82,
  297. ObjectStublessClient83,
  298. ObjectStublessClient84,
  299. ObjectStublessClient85,
  300. ObjectStublessClient86,
  301. ObjectStublessClient87,
  302. ObjectStublessClient88,
  303. ObjectStublessClient89,
  304. ObjectStublessClient90,
  305. ObjectStublessClient91,
  306. ObjectStublessClient92,
  307. ObjectStublessClient93,
  308. ObjectStublessClient94,
  309. ObjectStublessClient95,
  310. ObjectStublessClient96,
  311. ObjectStublessClient97,
  312. ObjectStublessClient98,
  313. ObjectStublessClient99,
  314. ObjectStublessClient100,
  315. ObjectStublessClient101,
  316. ObjectStublessClient102,
  317. ObjectStublessClient103,
  318. ObjectStublessClient104,
  319. ObjectStublessClient105,
  320. ObjectStublessClient106,
  321. ObjectStublessClient107,
  322. ObjectStublessClient108,
  323. ObjectStublessClient109,
  324. ObjectStublessClient110,
  325. ObjectStublessClient111,
  326. ObjectStublessClient112,
  327. ObjectStublessClient113,
  328. ObjectStublessClient114,
  329. ObjectStublessClient115,
  330. ObjectStublessClient116,
  331. ObjectStublessClient117,
  332. ObjectStublessClient118,
  333. ObjectStublessClient119,
  334. ObjectStublessClient120,
  335. ObjectStublessClient121,
  336. ObjectStublessClient122,
  337. ObjectStublessClient123,
  338. ObjectStublessClient124,
  339. ObjectStublessClient125,
  340. ObjectStublessClient126,
  341. ObjectStublessClient127
  342. };
  343. }
  344. void ** StublessClientVtbl = (void **)g_StublessClientVtbl;
  345. long
  346. ObjectStublessClient(
  347. void * ParamAddress,
  348. long Method
  349. )
  350. {
  351. PMIDL_STUBLESS_PROXY_INFO ProxyInfo;
  352. CInterfaceProxyHeader * ProxyHeader;
  353. PFORMAT_STRING ProcFormat;
  354. unsigned short ProcFormatOffset;
  355. CLIENT_CALL_RETURN Return;
  356. long ParamSize;
  357. void * This;
  358. This = *((void **)ParamAddress);
  359. ProxyHeader = (CInterfaceProxyHeader *)
  360. (*((char **)This) - sizeof(CInterfaceProxyHeader));
  361. ProxyInfo = (PMIDL_STUBLESS_PROXY_INFO) ProxyHeader->pStublessProxyInfo;
  362. #if defined(BUILD_NDR64)
  363. if ( ProxyInfo->pStubDesc->mFlags & RPCFLG_HAS_MULTI_SYNTAXES )
  364. {
  365. NDR_PROC_CONTEXT ProcContext;
  366. HRESULT hr;
  367. Ndr64ClientInitializeContext(
  368. NdrpGetSyntaxType( ProxyInfo->pTransferSyntax),
  369. ProxyInfo,
  370. Method,
  371. &ProcContext,
  372. (uchar*)ParamAddress );
  373. if ( ProcContext.IsAsync )
  374. {
  375. if ( Method & 0x1 )
  376. hr = MulNdrpBeginDcomAsyncClientCall( ProxyInfo,
  377. Method,
  378. &ProcContext,
  379. ParamAddress );
  380. else
  381. hr = MulNdrpFinishDcomAsyncClientCall(ProxyInfo,
  382. Method,
  383. &ProcContext,
  384. ParamAddress );
  385. Return.Simple = hr;
  386. }
  387. else
  388. Return = NdrpClientCall3(This,
  389. ProxyInfo,
  390. Method,
  391. NULL, // return value
  392. &ProcContext,
  393. (uchar*)ParamAddress);
  394. ParamSize = ProcContext.StackSize;
  395. goto Finish;
  396. }
  397. #endif
  398. ProcFormatOffset = ProxyInfo->FormatStringOffset[Method];
  399. ProcFormat = &ProxyInfo->ProcFormatString[ProcFormatOffset];
  400. ParamSize = (long)
  401. ( (ProcFormat[1] & Oi_HAS_RPCFLAGS) ?
  402. *((ushort *)&ProcFormat[8]) : *((ushort *)&ProcFormat[4]) );
  403. if ( MIDL_VERSION_3_0_39 <= ProxyInfo->pStubDesc->MIDLVersion )
  404. {
  405. // Since MIDL 3.0.39 we have a proc flag that indicates
  406. // which interpeter to call. This is because the NDR version
  407. // may be bigger than 1.1 for other reasons.
  408. if ( ProcFormat[1] & Oi_OBJ_USE_V2_INTERPRETER )
  409. {
  410. if ( MIDL_VERSION_5_0_136 <= ProxyInfo->pStubDesc->MIDLVersion
  411. &&
  412. ((PNDR_DCOM_OI2_PROC_HEADER) ProcFormat)->Oi2Flags.HasAsyncUuid )
  413. {
  414. Return = NdrDcomAsyncClientCall( ProxyInfo->pStubDesc,
  415. ProcFormat,
  416. ParamAddress );
  417. }
  418. else
  419. {
  420. Return = NdrClientCall2( ProxyInfo->pStubDesc,
  421. ProcFormat,
  422. ParamAddress );
  423. }
  424. }
  425. else
  426. {
  427. Return = NdrClientCall( ProxyInfo->pStubDesc,
  428. ProcFormat,
  429. ParamAddress );
  430. }
  431. }
  432. else
  433. {
  434. // Prior to that, the NDR version (on per file basis)
  435. // was the only indication of -Oi2.
  436. if ( ProxyInfo->pStubDesc->Version <= NDR_VERSION_1_1 )
  437. {
  438. Return = NdrClientCall( ProxyInfo->pStubDesc,
  439. ProcFormat,
  440. ParamAddress );
  441. Return.Simple = E_FAIL;
  442. }
  443. else
  444. {
  445. Return = NdrClientCall2( ProxyInfo->pStubDesc,
  446. ProcFormat,
  447. ParamAddress );
  448. }
  449. }
  450. #if defined(BUILD_NDR64)
  451. Finish:
  452. #endif
  453. //
  454. // Return the size of the parameter stack minus 4 bytes for the HRESULT
  455. // return in ecx. The ObjectStublessClient* routines need this to pop
  456. // the stack the correct number of bytes. We don't have to worry about
  457. // this on RISC platforms since the caller pops any argument stack space
  458. // needed .
  459. //
  460. _asm { mov ecx, ParamSize }
  461. _asm { sub ecx, 4 }
  462. return (long) Return.Simple;
  463. }
  464. //+---------------------------------------------------------------------------
  465. //
  466. // Function: CreateStublessProcBuffer
  467. //
  468. // Synopsis: Create a StublessClientProcBuffer for vtbl to point to. starting from g_dwVtblSize,
  469. // till the larger of numMethods and maximum vtbls created in the block
  470. //
  471. // Arguments: USHORT numMethods // number of methods in this interface
  472. // StublessProcBuffer **pTail // the last pNext in the allocated block
  473. //
  474. // Note: in x86, we are using short move & short jmps such that each method entry is 4 bytes.
  475. // this force we to have two method table in each block
  476. // in alpha, each entry has to be 8 bytes (2 instructions) so we can just have one
  477. // method table in a block.
  478. //
  479. // Returns:
  480. // pointer to ProcBuffer if succeeded;
  481. // NULL if failed. GetLastError() to retrieve error.
  482. //
  483. //----------------------------------------------------------------------------
  484. HRESULT CreateStublessProcBuffer(IN ULONG numMethods,
  485. OUT void *** lpTempVtbl)
  486. {
  487. // pointer to the last "pNext" pointer in vtbl link list: only increase, never release.
  488. static StublessProcBuffer** pVtblTail = NULL;
  489. ULONG i,j,k,iBlock = 0;
  490. ULONG nMethodsToAlloc = numMethods - g_dwVtblSize;
  491. StublessProcBuffer InitBuffer, *pStart = NULL, **pTail = NULL, *pBuf = NULL;
  492. DWORD* lpdwTemp, dwStartMethod = g_dwVtblSize ;
  493. LPBYTE lpByte;
  494. BYTE lDist;
  495. ULONG dwNewLength;
  496. void ** TempVtbl = NULL;
  497. HRESULT hr;
  498. // get number of blocks need to be allocated
  499. iBlock = nMethodsToAlloc / (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK);
  500. if (nMethodsToAlloc % (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK) != 0)
  501. iBlock++;
  502. // size of new vtbl tempplate.
  503. dwNewLength = g_dwVtblSize + iBlock * (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_METHODS_PER_BLOCK);
  504. TempVtbl = (void **)I_RpcAllocate(dwNewLength * sizeof(void *) + sizeof(LONG));
  505. if (NULL == TempVtbl)
  506. return E_OUTOFMEMORY;
  507. *(LONG*)TempVtbl = 1; // ref count
  508. TempVtbl = (void **)((LPBYTE)TempVtbl + sizeof(LONG));
  509. memcpy(TempVtbl,StublessClientVtbl,g_dwVtblSize*sizeof(void *));
  510. // the template other StublessProcBuffers copy from.
  511. if (NULL == g_pStublessProcBuffer)
  512. {
  513. BYTE nRelativeID = 0;
  514. memset(&InitBuffer,0,sizeof(StublessProcBuffer));
  515. memcpy(InitBuffer.pAsm,CASM_GENERATESTUBLESS,sizeof(CASM_GENERATESTUBLESS));
  516. *((DWORD *)&InitBuffer.pAsm[12]) = (DWORD)&g_ObjectStubless;
  517. lpByte = (LPBYTE)InitBuffer.pMethodsa;
  518. lDist = CB_METHOD * NUMBER_OF_METHODS_PER_BLOCK / 2;
  519. for (i = 0; i < NUMBER_OF_METHODS_PER_BLOCK / 2; i++)
  520. {
  521. *lpByte++ = 0xB0; // _asm mov al
  522. *lpByte++ = nRelativeID++;
  523. *lpByte++ = 0xEB; // _asm jmp
  524. *lpByte++ = lDist;
  525. lDist -=CB_METHOD; // goes further and further
  526. }
  527. lpByte = (LPBYTE)InitBuffer.pMethodsb;
  528. lDist = sizeof(CASM_GENERATESTUBLESS) + CB_METHOD;
  529. lDist = -lDist;
  530. for (i = 0; i < NUMBER_OF_METHODS_PER_BLOCK /2 ; i++)
  531. {
  532. *lpByte++ = 0xB0; // _asm mov al
  533. *lpByte++ = nRelativeID++;
  534. *lpByte++ = 0xEB; // _asm jmp
  535. *lpByte++ = lDist;
  536. lDist -=CB_METHOD; // goes further and further
  537. }
  538. }
  539. else
  540. memcpy(&InitBuffer,g_pStublessProcBuffer,sizeof(StublessProcBuffer));
  541. for (i = 0; i < iBlock; i++)
  542. {
  543. // we need to create a buffer
  544. pBuf = (StublessProcBuffer *)I_RpcAllocate(NUMBER_OF_BLOCKS_PER_ALLOC * sizeof(StublessProcBuffer) );
  545. if (NULL == pBuf)
  546. {
  547. hr = E_OUTOFMEMORY;
  548. goto Cleanup;
  549. }
  550. // remember the starting block of all the block in the call.
  551. if (NULL == pStart)
  552. pStart = pBuf;
  553. if (pTail)
  554. *pTail = pBuf; // link up the link list.
  555. for (j = 0; j < NUMBER_OF_BLOCKS_PER_ALLOC; j++)
  556. {
  557. memcpy(&pBuf[j],&InitBuffer,sizeof(StublessProcBuffer));
  558. if (j < NUMBER_OF_BLOCKS_PER_ALLOC -1 )
  559. pBuf[j].pNext = &pBuf[j+1];
  560. else
  561. {
  562. pTail = &(pBuf[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext);
  563. *pTail = NULL;
  564. }
  565. // adjust the starting methodid in this block
  566. lpdwTemp = (DWORD *)& (pBuf[j].pAsm[6]);
  567. *lpdwTemp = dwStartMethod;
  568. for (k = 0; k < NUMBER_OF_METHODS_PER_BLOCK / 2; k++)
  569. TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsa[k];
  570. for (k = 0; k < NUMBER_OF_METHODS_PER_BLOCK / 2; k++)
  571. TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsb[k];
  572. }
  573. }
  574. if (NULL == g_pStublessProcBuffer)
  575. g_pStublessProcBuffer = pStart;
  576. else
  577. *pVtblTail = pStart;
  578. *lpTempVtbl = TempVtbl;
  579. pVtblTail = pTail;
  580. g_dwVtblSize = dwNewLength;
  581. return S_OK;
  582. Cleanup:
  583. while (pStart)
  584. {
  585. pTail = &pStart[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext;
  586. I_RpcFree(pStart);
  587. pStart = *pTail;
  588. }
  589. if (TempVtbl)
  590. I_RpcFree(TempVtbl);
  591. return hr;
  592. }
  593. //+---------------------------------------------------------------------------
  594. //
  595. // Function: CreateForwardProcBuffer
  596. //
  597. // Synopsis: Create a StublessClientProcBuffer for vtbl to point to. starting from g_dwVtblSize,
  598. // till the larger of numMethods and maximum vtbls created in the block
  599. //
  600. // Arguments: USHORT numMethods // number of methods in this interface
  601. // StublessProcBuffer **pTail // the last pNext in the allocated block
  602. //
  603. // Note: in x86, we are using short move & short jmps such that each method entry is 4 bytes.
  604. // this force we to have two method table in each block
  605. // in alpha, each entry has to be 8 bytes (2 instructions) so we can just have one
  606. // method table in a block.
  607. //
  608. // Returns:
  609. // pointer to ProcBuffer if succeeded;
  610. // NULL if failed. GetLastError() to retrieve error.
  611. //
  612. //----------------------------------------------------------------------------
  613. HRESULT CreateForwardProcBuffer(ULONG numMethods, void ***lpTempVtbl)
  614. {
  615. // pointer to the last "pNext" pointer in vtbl link list: only increase, never release.
  616. static ForwardProcBuffer** pVtblTail = NULL;
  617. ULONG i,j,k,iBlock = 0;
  618. ULONG nMethodsToAlloc = numMethods - g_dwForwardVtblSize;
  619. ForwardProcBuffer InitBuffer, *pStart = NULL, **pTail = NULL, *pBuf = NULL;
  620. DWORD* lpdwTemp, dwStartMethod = g_dwForwardVtblSize ;
  621. LPBYTE lpByte;
  622. BYTE lDist;
  623. ULONG dwNewLength;
  624. void ** TempVtbl;
  625. HRESULT hr;
  626. // get number of blocks need to be allocated
  627. iBlock = nMethodsToAlloc / (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK);
  628. if (nMethodsToAlloc % (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK) != 0)
  629. iBlock++;
  630. // size of new vtbl tempplate.
  631. dwNewLength = g_dwForwardVtblSize + iBlock * (NUMBER_OF_BLOCKS_PER_ALLOC * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK);
  632. TempVtbl = (void **)I_RpcAllocate(dwNewLength * sizeof(void *) + sizeof(LONG));
  633. if (NULL == TempVtbl)
  634. return E_OUTOFMEMORY;
  635. *(LONG*)TempVtbl = 1; // ref count
  636. TempVtbl = (void **)((LPBYTE)TempVtbl + sizeof(LONG));
  637. memcpy(TempVtbl,ProxyForwardVtbl,g_dwForwardVtblSize*sizeof(void *));
  638. // the template other StublessProcBuffers copy from.
  639. if (NULL == g_pForwardProcBuffer)
  640. {
  641. BYTE nRelativeID = 0;
  642. memset(&InitBuffer,0,sizeof(ForwardProcBuffer));
  643. memcpy(&InitBuffer.pAsm,CASM_GENERATEFORWARD,sizeof(CASM_GENERATEFORWARD));
  644. lpByte = (LPBYTE)InitBuffer.pMethodsa;
  645. lDist = CB_METHOD * NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2;
  646. for (i = 0; i < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; i++)
  647. {
  648. *lpByte++ = 0xB0; // _asm mov al
  649. *lpByte++ = nRelativeID++;
  650. *lpByte++ = 0xEB; // _asm jmp
  651. *lpByte++ = lDist;
  652. lDist -=CB_METHOD; // goes further and further
  653. }
  654. lpByte = (LPBYTE)InitBuffer.pMethodsb;
  655. lDist = sizeof(CASM_GENERATEFORWARD) + CB_METHOD;
  656. lDist = -lDist;
  657. for (i = 0; i < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK /2 ; i++)
  658. {
  659. *lpByte++ = 0xB0; // _asm mov al
  660. *lpByte++ = nRelativeID++;
  661. *lpByte++ = 0xEB; // _asm jmp
  662. *lpByte++ = lDist;
  663. lDist -=CB_METHOD; // goes further and further
  664. }
  665. }
  666. else
  667. memcpy(&InitBuffer,g_pForwardProcBuffer,sizeof(ForwardProcBuffer));
  668. for (i = 0; i < iBlock; i++)
  669. {
  670. // we need to create a buffer
  671. pBuf = (ForwardProcBuffer *)I_RpcAllocate(NUMBER_OF_BLOCKS_PER_ALLOC * sizeof(ForwardProcBuffer) );
  672. if (NULL == pBuf)
  673. {
  674. hr = E_OUTOFMEMORY;
  675. goto Cleanup;
  676. }
  677. // remember the starting block of all the block in the call.
  678. if (NULL == pStart)
  679. pStart = pBuf;
  680. if (pTail)
  681. *pTail = pBuf; // link up the link list.
  682. for (j = 0; j < NUMBER_OF_BLOCKS_PER_ALLOC; j++)
  683. {
  684. memcpy(&pBuf[j],&InitBuffer,sizeof(ForwardProcBuffer));
  685. if (j < NUMBER_OF_BLOCKS_PER_ALLOC -1 )
  686. pBuf[j].pNext = &pBuf[j+1];
  687. else
  688. {
  689. pTail = &(pBuf[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext);
  690. *pTail = NULL;
  691. }
  692. // adjust the starting methodid in this block
  693. lpdwTemp = (DWORD *)& (pBuf[j].pAsm[17]);
  694. *lpdwTemp = dwStartMethod;
  695. for (k = 0; k < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; k++)
  696. TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsa[k];
  697. for (k = 0; k < NUMBER_OF_FORWARDING_METHODS_PER_BLOCK / 2; k++)
  698. TempVtbl[dwStartMethod++] = (void *)pBuf[j].pMethodsb[k];
  699. }
  700. }
  701. if (NULL == g_pForwardProcBuffer)
  702. g_pForwardProcBuffer = pStart;
  703. else
  704. *pVtblTail = pStart;
  705. *lpTempVtbl = TempVtbl;
  706. pVtblTail = pTail;
  707. g_dwForwardVtblSize = dwNewLength;
  708. return S_OK;
  709. Cleanup:
  710. while (pStart)
  711. {
  712. pTail = &pStart[NUMBER_OF_BLOCKS_PER_ALLOC-1].pNext;
  713. I_RpcFree(pStart);
  714. pStart = *pTail;
  715. }
  716. if (TempVtbl)
  717. I_RpcFree(TempVtbl);
  718. return hr;
  719. }