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.

1027 lines
39 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: ssend.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Server side sending stubs
  7. *
  8. * 07-06-91 ScottLu Created.
  9. \***************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #define CALLBACKPROC 1
  13. #define SERVERSIDE 1
  14. #include "callback.h"
  15. #define SENDSIDE 1
  16. #define CBBUFSIZE 512
  17. #define PADSIZE (sizeof(ULONG_PTR) - 1)
  18. /*
  19. * Callback setup and control macros
  20. */
  21. #define SMESSAGECALL(api) \
  22. LRESULT Sfn ## api( \
  23. PWND pwnd, \
  24. UINT msg, \
  25. WPARAM wParam, \
  26. LPARAM lParam, \
  27. ULONG_PTR xParam, \
  28. PROC xpfnProc, \
  29. DWORD dwSCMSFlags, \
  30. PSMS psms)
  31. #define SETUP(api) \
  32. api ## MSG m; \
  33. api ## MSG *mp = &m; \
  34. BYTE Buffer[CBBUFSIZE]; \
  35. PCALLBACKSTATUS pcbs; \
  36. ULONG cbCBStatus; \
  37. ULONG_PTR retval; \
  38. NTSTATUS Status;
  39. #define SETUPDC(api) \
  40. SETUP(api) \
  41. int iDC = 0; \
  42. HDC hdcUse; \
  43. HBITMAP hbmDCGray = NULL;
  44. #define SETUPPWND(api) \
  45. api ## MSG m; \
  46. api ## MSG *mp = &m; \
  47. BYTE Buffer[CBBUFSIZE]; \
  48. PCALLBACKSTATUS pcbs; \
  49. ULONG cbCBStatus; \
  50. ULONG_PTR retval; \
  51. NTSTATUS Status; \
  52. TL tlpwnd; \
  53. CALLBACKWND cbwin; \
  54. PTHREADINFO pti = PtiCurrent(); \
  55. PWND pwndClient = pwnd ? (PWND)((PBYTE)pwnd - pti->ulClientDelta) : NULL; \
  56. UserAssert(pti->ulClientDelta != 0);
  57. #define CALC_SIZE_IN(cb, pstr) \
  58. cb = (pstr)->Length + sizeof(WCHAR); \
  59. if ((pstr)->bAnsi && !fAnsiReceiver) \
  60. cb *= sizeof(WCHAR);
  61. #define CALC_SIZE_OUT(cb, pstr) \
  62. cb = (pstr)->MaximumLength + sizeof(WCHAR); \
  63. if ((pstr)->bAnsi && !fAnsiReceiver) \
  64. cb *= sizeof(WCHAR);
  65. #ifdef FE_SB // CALC_SIZE_OUT_STRING()
  66. #define CALC_SIZE_OUT_STRING(cb, pstr) \
  67. cb = (pstr)->MaximumLength + sizeof(WCHAR); \
  68. if (!(PtiCurrent()->TIF_flags & TIF_ANSILENGTH)) { \
  69. if ((pstr)->bAnsi && !fAnsiReceiver) \
  70. cb *= sizeof(WCHAR); \
  71. }
  72. #endif // FE_SB
  73. #ifdef FE_SB // CALC_SIZE_STRING_OUT()
  74. #define CALC_SIZE_STRING_OUT(cchText) \
  75. try { \
  76. (cchText) = CalcOutputStringSize(pcbs,(cchText),fAnsiSender,fAnsiReceiver); \
  77. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  78. (cchText) = 0; \
  79. MSGERROR(); \
  80. }
  81. #endif // FE_SB
  82. #define BEGINSEND(api) \
  83. mp = &m; \
  84. Buffer; \
  85. {
  86. #define BEGINSENDCAPTURE(api, cCapturePointers, cCaptureBytes, fInput) \
  87. if (cCapturePointers) { \
  88. mp = AllocCallbackMessage(sizeof(m), \
  89. (cCapturePointers), \
  90. (cCaptureBytes), \
  91. Buffer, \
  92. fInput); \
  93. if (mp == NULL) \
  94. goto errorexitnofreemp; \
  95. } else { \
  96. m.CaptureBuf.cbCallback = sizeof(m); \
  97. m.CaptureBuf.cbCapture = 0; \
  98. m.CaptureBuf.cCapturedPointers = 0; \
  99. mp = &m; \
  100. } \
  101. { \
  102. PTHREADINFO ptiCurrent = PtiCurrent(); \
  103. TL tlPool; \
  104. \
  105. if (mp != &m && (PVOID)mp != (PVOID)Buffer) \
  106. ThreadLockPool(ptiCurrent, mp, &tlPool);
  107. #define BEGINSENDCAPTUREVOIDDC(api, cCapturePointers, cCaptureBytes, fInput) \
  108. hdcUse = CreateCompatiblePublicDC(hdc,&hbmDCGray); \
  109. if (hdcUse == (HDC)NULL) { \
  110. return; \
  111. } \
  112. BEGINSENDCAPTURE(api, cCapturePointers, cCaptureBytes, fInput); \
  113. #define BEGINSENDCAPTUREDC(api, cCapturePointers, nCount, fInput) \
  114. hdcUse = CreateCompatiblePublicDC(hdc,&hbmDCGray); \
  115. if (hdcUse == (HDC)NULL) { \
  116. return FALSE; \
  117. } \
  118. BEGINSENDCAPTURE(api, cCapturePointers, max(pstrSrc->MaximumLength, \
  119. ((nCount + 1) * sizeof(WCHAR))), fInput); \
  120. #define LOCKPWND() \
  121. ThreadLock(pwnd, &tlpwnd); \
  122. try { \
  123. cbwin = pti->pClientInfo->CallbackWnd; \
  124. pti->pClientInfo->CallbackWnd.pwnd = pwndClient; \
  125. pti->pClientInfo->CallbackWnd.hwnd = HW(pwnd); \
  126. pti->pClientInfo->CallbackWnd.pActCtx = ((pwnd == NULL) ? NULL : pwnd->pActCtx); \
  127. } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
  128. ThreadUnlock(&tlpwnd); \
  129. MSGERROR(); \
  130. }
  131. #define UNLOCKPWND() \
  132. ThreadUnlock(&tlpwnd); \
  133. try { \
  134. pti->pClientInfo->CallbackWnd = cbwin; \
  135. } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { \
  136. MSGERROR(); \
  137. }
  138. #define MAKECALL(api) \
  139. UserAssert(!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)); \
  140. LeaveCrit(); \
  141. Status = KeUserModeCallback( \
  142. FI_ ## api, \
  143. mp, \
  144. sizeof(*mp), \
  145. &pcbs, \
  146. &cbCBStatus); \
  147. EnterCrit();
  148. #define MAKECALLCAPTURE(api) \
  149. UserAssert(!(PtiCurrent()->TIF_flags & TIF_INCLEANUP)); \
  150. LeaveCrit(); \
  151. Status = (DWORD)KeUserModeCallback( \
  152. FI_ ## api, \
  153. mp, \
  154. mp->CaptureBuf.cbCallback, \
  155. &pcbs, \
  156. &cbCBStatus); \
  157. EnterCrit();
  158. #define MAKECALLCAPTUREDC(api) \
  159. iDC = GreSaveDC(hdc); \
  160. MAKECALLCAPTURE(api) \
  161. GreRestoreDC(hdc, iDC); \
  162. iDC = 0; \
  163. if ((hdcUse != hdc) && NT_SUCCESS(Status)) { \
  164. GreBitBlt(hdc, \
  165. 0, \
  166. 0, \
  167. gpDispInfo->cxGray, \
  168. gpDispInfo->cyGray, \
  169. hdcUse, \
  170. 0, \
  171. 0, \
  172. SRCCOPY, \
  173. 0); \
  174. }
  175. #define CHECKRETURN() \
  176. if (!NT_SUCCESS(Status) || \
  177. cbCBStatus != sizeof(*pcbs)) { \
  178. goto errorexit; \
  179. } \
  180. try { \
  181. retval = ProbeAndReadStructure(&pcbs->retval, ULONG_PTR); \
  182. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  183. MSGERROR(); \
  184. }
  185. #define ENDSEND(type, error) \
  186. return (type)retval; \
  187. goto errorexit; \
  188. } \
  189. errorexit: \
  190. return (type)error
  191. #define CLEANUPSENDCAPTURECOMMONDC() \
  192. if(iDC) { \
  193. GreRestoreDC(hdc, iDC); \
  194. } \
  195. if (hdcUse != hdc) { \
  196. GreDeleteDC(hdcUse); \
  197. GreDeleteObject(hbmDCGray); \
  198. } \
  199. #define BEGIN_ENDSENDCAPTURE(type, error) \
  200. exit:
  201. #define _ENDSENDCAPTURE(type, error) \
  202. if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
  203. if (mp->CaptureBuf.pvVirtualAddress) { \
  204. NTSTATUS Status; \
  205. SIZE_T ulRegionSize = 0; \
  206. \
  207. Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
  208. &mp->CaptureBuf.pvVirtualAddress, \
  209. &ulRegionSize, \
  210. MEM_RELEASE); \
  211. UserAssert(NT_SUCCESS(Status)); \
  212. } \
  213. ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
  214. } \
  215. return (type)retval; \
  216. goto errorexit; \
  217. } \
  218. errorexit: \
  219. retval = error; \
  220. goto exit; \
  221. errorexitnofreemp:
  222. #define END_ENDSENDCAPTURE(type, error) \
  223. return (type)error
  224. #define ENDSENDCAPTUREDC(type, error) \
  225. BEGIN_ENDSENDCAPTURE(type, error); \
  226. CLEANUPSENDCAPTURECOMMONDC(); \
  227. _ENDSENDCAPTURE(type, error); \
  228. CLEANUPSENDCAPTURECOMMONDC(); \
  229. END_ENDSENDCAPTURE(type, error)
  230. #define ENDSENDCAPTURE(type, error) \
  231. BEGIN_ENDSENDCAPTURE(type, error); \
  232. _ENDSENDCAPTURE(type, error); \
  233. END_ENDSENDCAPTURE(type, error)
  234. #ifdef FE_SB // ENDSENDCAPTUREOUTSTRING()
  235. #define ENDSENDCAPTUREOUTSTRING(type, error) \
  236. exit: \
  237. if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
  238. if (mp->CaptureBuf.pvVirtualAddress) { \
  239. NTSTATUS Status; \
  240. SIZE_T ulRegionSize = 0; \
  241. \
  242. Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
  243. &mp->CaptureBuf.pvVirtualAddress, \
  244. &ulRegionSize, \
  245. MEM_RELEASE); \
  246. UserAssert(NT_SUCCESS(Status)); \
  247. } \
  248. ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
  249. } \
  250. if (bInflateWParam) \
  251. PtiCurrent()->TIF_flags &= ~TIF_ANSILENGTH; \
  252. return (type)retval; \
  253. goto errorexit; \
  254. } \
  255. errorexit: \
  256. retval = error; \
  257. goto exit; \
  258. errorexitnofreemp: \
  259. if (bInflateWParam) \
  260. PtiCurrent()->TIF_flags &= ~TIF_ANSILENGTH; \
  261. return (type)error
  262. #endif // FE_SB
  263. #define BEGIN_ENDSENDCAPTUREVOID() \
  264. errorexit:
  265. #define _ENDSENDCAPTUREVOID() \
  266. if (mp != &m && (PVOID)mp != (PVOID)Buffer) { \
  267. if (mp->CaptureBuf.pvVirtualAddress) { \
  268. NTSTATUS Status; \
  269. SIZE_T ulRegionSize = 0; \
  270. \
  271. Status = ZwFreeVirtualMemory(NtCurrentProcess(),\
  272. &mp->CaptureBuf.pvVirtualAddress, \
  273. &ulRegionSize, \
  274. MEM_RELEASE); \
  275. UserAssert(NT_SUCCESS(Status)); \
  276. } \
  277. ThreadUnlockAndFreePool(ptiCurrent, &tlPool); \
  278. } \
  279. return; \
  280. } \
  281. errorexitnofreemp:
  282. #define END_ENDSENDCAPTUREVOID() \
  283. return
  284. #define ENDSENDCAPTUREVOIDDC() \
  285. BEGIN_ENDSENDCAPTUREVOID(); \
  286. CLEANUPSENDCAPTURECOMMONDC(); \
  287. _ENDSENDCAPTUREVOID(); \
  288. CLEANUPSENDCAPTURECOMMONDC(); \
  289. END_ENDSENDCAPTUREVOID()
  290. #define ENDSENDCAPTUREVOID() \
  291. BEGIN_ENDSENDCAPTUREVOID(); \
  292. CLEANUPSENDCAPTURECOMMON(); \
  293. _ENDSENDCAPTUREVOID(); \
  294. CLEANUPSENDCAPTURECOMMON(); \
  295. END_ENDSENDCAPTUREVOID()
  296. #define ENDSENDVOID() \
  297. } \
  298. return
  299. #define MSGERROR() goto errorexit
  300. #ifdef FE_SB // CHECKRETURN1() & ENDSEND1()
  301. #define CHECKRETURN1() \
  302. if (!NT_SUCCESS(Status) || \
  303. cbCBStatus != sizeof(*pcbs)) { \
  304. goto errorexit1; \
  305. } \
  306. try { \
  307. retval = ProbeAndReadStructure(&pcbs->retval, ULONG_PTR); \
  308. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  309. MSGERROR(); \
  310. }
  311. #define ENDSEND1(type, error) \
  312. return (type)retval; \
  313. goto errorexit1; \
  314. } \
  315. errorexit1: \
  316. return (type)error
  317. #define MSGERROR1() goto errorexit1
  318. #endif // FE_SB
  319. /*
  320. * Callback IN parameter macros
  321. */
  322. #define MSGDATA() (mp)
  323. #define COPYSTRUCTOPT(x) \
  324. MSGDATA()->p ## x = (p ## x); \
  325. if (p ## x) MSGDATA()->x = *(p ## x);
  326. #define COPYCONSTRECTSTRUCTOPT(x) \
  327. MSGDATA()->p ## x = (LPRECT)(p ## x); \
  328. if (p ## x) MSGDATA()->x = *(p ## x);
  329. #define COPYBYTES(p, cb) \
  330. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
  331. goto errorexit;
  332. #define COPYBYTESOPT(p, cb) \
  333. if (p) { \
  334. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
  335. goto errorexit; \
  336. } else { \
  337. mp->p = NULL; \
  338. }
  339. #define LARGECOPYBYTES(p, cb) \
  340. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, p, cb, &mp->p))) \
  341. goto errorexit;
  342. #define LARGECOPYBYTES2(src, cb, dest) \
  343. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, src, cb, &mp->dest))) \
  344. goto errorexit;
  345. #define COPYSTRING(s) \
  346. mp->s.Length = (p ## s)->Length; \
  347. mp->s.MaximumLength = (p ## s)->MaximumLength; \
  348. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  349. (p ## s)->Buffer, \
  350. (p ## s)->Length + sizeof(WCHAR), \
  351. &mp->s.Buffer))) \
  352. goto errorexit;
  353. #define COPYSTRINGOPT(s) \
  354. if (p ## s) { \
  355. mp->s.Length = (p ## s)->Length; \
  356. mp->s.MaximumLength = (p ## s)->MaximumLength; \
  357. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  358. (p ## s)->Buffer, \
  359. (p ## s)->Length + sizeof(WCHAR), \
  360. &mp->s.Buffer))) \
  361. goto errorexit; \
  362. } else { \
  363. mp->s.Length = 0; \
  364. mp->s.Buffer = NULL; \
  365. }
  366. #define COPYSTRINGID(s) \
  367. mp->s.Length = (p ## s)->Length; \
  368. mp->s.MaximumLength = (p ## s)->MaximumLength; \
  369. if (mp->s.MaximumLength) { \
  370. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  371. (p ## s)->Buffer, \
  372. (p ## s)->Length + sizeof(WCHAR), \
  373. &mp->s.Buffer))) \
  374. goto errorexit; \
  375. } else { \
  376. mp->s.Buffer = (p ## s)->Buffer; \
  377. }
  378. #define LARGECOPYSTRINGLPWSTR(ps, psz) \
  379. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  380. (ps)->Buffer, \
  381. (ps)->Length + sizeof(WCHAR), \
  382. (PVOID *)&mp->psz))) \
  383. goto errorexit;
  384. #define LARGECOPYSTRINGLPSTR(ps, psz) \
  385. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  386. (ps)->Buffer, \
  387. (ps)->Length + 1, \
  388. (PVOID *)&mp->psz))) \
  389. goto errorexit;
  390. #define LARGECOPYSTRINGLPWSTRA(ps, psz) \
  391. if (!NT_SUCCESS(CaptureAnsiCallbackData(&mp->CaptureBuf, \
  392. (ps)->Buffer, \
  393. ((ps)->Length / sizeof(WCHAR)) + 1, \
  394. (PVOID *)&mp->psz))) \
  395. goto errorexit;
  396. #define LARGECOPYSTRINGLPSTRW(ps, psz) \
  397. if (!NT_SUCCESS(CaptureUnicodeCallbackData(&mp->CaptureBuf, \
  398. (ps)->Buffer, \
  399. ((ps)->Length + 1) * sizeof(WCHAR), \
  400. (PVOID *)&mp->psz))) \
  401. goto errorexit; \
  402. #define LARGECOPYSTRINGLPWSTROPT(ps, psz) \
  403. if (ps) { \
  404. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  405. (ps)->Buffer, \
  406. (ps)->Length + sizeof(WCHAR), \
  407. (PVOID *)&mp->psz))) \
  408. goto errorexit; \
  409. } else { \
  410. mp->psz = NULL; \
  411. }
  412. #define LARGECOPYSTRINGLPSTROPT(ps, psz) \
  413. if (ps) { \
  414. if (!NT_SUCCESS(CaptureCallbackData(&mp->CaptureBuf, \
  415. (ps)->Buffer, \
  416. (ps)->Length + sizeof(UCHAR), \
  417. (PVOID *)&mp->psz))) \
  418. goto errorexit; \
  419. } else { \
  420. mp->psz = NULL; \
  421. }
  422. #define LARGECOPYSTRINGLPWSTROPTA(ps, psz) \
  423. if (ps) { \
  424. if (!NT_SUCCESS(CaptureAnsiCallbackData(&mp->CaptureBuf, \
  425. (ps)->Buffer, \
  426. ((ps)->Length / sizeof(WCHAR)) + 1, \
  427. (PVOID *)&mp->psz))) \
  428. goto errorexit; \
  429. } else { \
  430. mp->psz = NULL; \
  431. }
  432. /*
  433. * Wrappers to determine whether copy out should be done.
  434. */
  435. #define BEGINCOPYOUT() \
  436. if ((psms == NULL || ((psms->flags & (SMF_SENDERDIED | SMF_REPLY)) == 0)) \
  437. && !(dwSCMSFlags & SCMS_FLAGS_INONLY)) {
  438. #define ENDCOPYOUT() \
  439. }
  440. /*
  441. * Callback OUT paramter macros
  442. */
  443. #define OUTSTRUCT(pstruct, type) \
  444. try { \
  445. *(pstruct) = ProbeAndReadStructure(((type *)pcbs->pOutput), type); \
  446. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  447. MSGERROR(); \
  448. }
  449. /*
  450. * flags field with mask (propagate back bits in mask only)
  451. */
  452. #define OUTBITMASK(pstruct, type, mask) \
  453. try { \
  454. type flags = ProbeAndReadStructure(((type *)pcbs->pOutput), type); \
  455. COPY_FLAG(*(pstruct), flags, mask); \
  456. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  457. MSGERROR(); \
  458. }
  459. #ifdef FE_SB // COPYOUTLPWSTRLIMIT()
  460. // should we insert IS_DBCS_ENABLED() in COPYOUTLPWSTRLIMIT ?
  461. #define COPYOUTLPWSTRLIMIT(pstr, cch) \
  462. try { \
  463. retval = CalcOutputStringSize(pcbs,(DWORD)retval,pstr->bAnsi,fAnsiReceiver); \
  464. CopyOutputString(pcbs, pstr, cch, fAnsiReceiver); \
  465. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  466. MSGERROR(); \
  467. }
  468. #else
  469. #define COPYOUTLPWSTRLIMIT(pstr, cch) \
  470. try { \
  471. CopyOutputString(pcbs, pstr, cch, fAnsiReceiver); \
  472. } except (W32ExceptionHandler(FALSE, RIP_ERROR)) { \
  473. MSGERROR(); \
  474. }
  475. #endif // FE_SB
  476. #define RESERVEBYTES(cb, dest, cbdest) \
  477. if (!NT_SUCCESS(AllocateCallbackData(&mp->CaptureBuf, \
  478. cb, (PVOID *)&mp->dest))) \
  479. goto errorexit; \
  480. mp->cbdest = cb;
  481. /***************************************************************************\
  482. * AllocCallbackMessage
  483. *
  484. * Allocates a callback message from pool memory and reserves space
  485. * for arguments to captured later.
  486. *
  487. * 03-13-95 JimA Created.
  488. \***************************************************************************/
  489. PVOID AllocCallbackMessage(
  490. DWORD cbBaseMsg,
  491. DWORD cPointers,
  492. SIZE_T cbCapture,
  493. PBYTE pStackBuffer,
  494. BOOL fInput)
  495. {
  496. PCAPTUREBUF pcb;
  497. if (cPointers == 0)
  498. return NULL;
  499. /*
  500. * Compute allocation sizes
  501. */
  502. cbBaseMsg = (cbBaseMsg + PADSIZE) & ~PADSIZE;
  503. cbBaseMsg += (cPointers * sizeof(PVOID));
  504. cbCapture = (cbCapture + (PADSIZE * cPointers)) & ~PADSIZE;
  505. /*
  506. * If the captured data is greater than a page, place it
  507. * in a section. Otherwise, put the message and the
  508. * data in a single block of pool
  509. */
  510. if (cbCapture > CALLBACKSTACKLIMIT) {
  511. NTSTATUS Status;
  512. /*
  513. * Allocate the message buffer
  514. */
  515. pcb = UserAllocPoolWithQuota(cbBaseMsg, TAG_CALLBACK);
  516. if (pcb == NULL)
  517. return NULL;
  518. /*
  519. * Allocate the virtual memory
  520. */
  521. pcb->pvVirtualAddress = NULL;
  522. Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
  523. &pcb->pvVirtualAddress, 0, &cbCapture,
  524. MEM_COMMIT, PAGE_READWRITE);
  525. if (!NT_SUCCESS(Status)) {
  526. RIPMSG2(RIP_WARNING, "AllocCallbackMessage: ZwAllocateVirtualMemory failed. Status:%#lx. Size:%#lx",
  527. Status, cbCapture);
  528. UserFreePool(pcb);
  529. return NULL;
  530. }
  531. pcb->pbFree = pcb->pvVirtualAddress;
  532. pcb->cbCallback = cbBaseMsg;
  533. } else {
  534. /*
  535. * If the message is too big to save on the stack, allocate
  536. * the buffer from pool.
  537. */
  538. if (cbBaseMsg + cbCapture > CBBUFSIZE) {
  539. pcb = UserAllocPoolWithQuota((ULONG)(cbBaseMsg + cbCapture), TAG_CALLBACK);
  540. if (pcb == NULL)
  541. return NULL;
  542. } else {
  543. pcb = (PCAPTUREBUF)pStackBuffer;
  544. }
  545. pcb->pbFree = (PBYTE)pcb + cbBaseMsg;
  546. pcb->pvVirtualAddress = NULL;
  547. /*
  548. * If this callback is passing data to the client, include the
  549. * captured data in the message. Otherwise, only pass the message.
  550. */
  551. if (fInput)
  552. pcb->cbCallback = cbBaseMsg + (ULONG)cbCapture;
  553. else
  554. pcb->cbCallback = cbBaseMsg;
  555. }
  556. /*
  557. * Initialize the capture buffer
  558. */
  559. pcb->cbCapture = (ULONG)cbCapture;
  560. pcb->cCapturedPointers = 0;
  561. pcb->offPointers = cbBaseMsg - (cPointers * sizeof(PVOID));
  562. return (PVOID)pcb;
  563. }
  564. /***************************************************************************\
  565. * CaptureCallbackData
  566. *
  567. * Captures data into a callback structure.
  568. *
  569. * 03-13-95 JimA Created.
  570. \***************************************************************************/
  571. NTSTATUS CaptureCallbackData(
  572. PCAPTUREBUF pcb,
  573. PVOID pData,
  574. DWORD cbData,
  575. PVOID *ppDest)
  576. {
  577. PBYTE pbBuffer;
  578. /*
  579. * If the data pointer is NULL, the out pointer will be
  580. * NULL
  581. */
  582. if (pData == NULL) {
  583. *ppDest = NULL;
  584. return STATUS_SUCCESS;
  585. }
  586. /*
  587. * Allocate space from the message buffer
  588. */
  589. if (cbData > pcb->cbCapture) {
  590. return STATUS_BUFFER_OVERFLOW;
  591. }
  592. pbBuffer = pcb->pbFree;
  593. pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
  594. try {
  595. RtlCopyMemory(pbBuffer, pData, cbData);
  596. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  597. return STATUS_ACCESS_VIOLATION;
  598. }
  599. /*
  600. * Fix up offsets to data. If the data is going into a section
  601. * use the real pointer and don't compute offsets.
  602. */
  603. if (pcb->pvVirtualAddress)
  604. *ppDest = pbBuffer;
  605. else {
  606. *ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
  607. ((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
  608. (DWORD)((PBYTE)ppDest - (PBYTE)pcb);
  609. }
  610. return STATUS_SUCCESS;
  611. }
  612. /***************************************************************************\
  613. * AllocateCallbackData
  614. *
  615. * Allocates space from a callback structure.
  616. *
  617. * 05-08-95 JimA Created.
  618. \***************************************************************************/
  619. NTSTATUS AllocateCallbackData(
  620. PCAPTUREBUF pcb,
  621. DWORD cbData,
  622. PVOID *ppDest)
  623. {
  624. PBYTE pbBuffer;
  625. /*
  626. * Allocate space from the message buffer
  627. */
  628. if (cbData > pcb->cbCapture) {
  629. return STATUS_BUFFER_OVERFLOW;
  630. }
  631. pbBuffer = pcb->pbFree;
  632. pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
  633. /*
  634. * Fix up offsets to data. If the data is going into a section
  635. * use the real pointer and don't compute offsets.
  636. */
  637. if (pcb->pvVirtualAddress)
  638. *ppDest = pbBuffer;
  639. else {
  640. *ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
  641. ((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
  642. (DWORD)((PBYTE)ppDest - (PBYTE)pcb);
  643. }
  644. return STATUS_SUCCESS;
  645. }
  646. /***************************************************************************\
  647. * CaptureAnsiCallbackData
  648. *
  649. * Converts Unicode to ANSI data and captures the result
  650. * into a callback structure.
  651. *
  652. * 03-13-95 JimA Created.
  653. \***************************************************************************/
  654. NTSTATUS CaptureAnsiCallbackData(
  655. PCAPTUREBUF pcb,
  656. PVOID pData,
  657. DWORD cbData,
  658. PVOID *ppDest)
  659. {
  660. PBYTE pbBuffer;
  661. ULONG nCharsInAnsiString;
  662. /*
  663. * If the data pointer is NULL, the out pointer will be
  664. * NULL
  665. */
  666. if (pData == NULL) {
  667. *ppDest = NULL;
  668. return STATUS_SUCCESS;
  669. }
  670. /*
  671. * Allocate space from the message buffer
  672. */
  673. #ifdef FE_SB // CaptureAnsiCallbackData()
  674. /*
  675. * Reserve enough space for DBCS.
  676. */
  677. if ((cbData * sizeof(WORD)) > pcb->cbCapture) {
  678. #else
  679. if (cbData > pcb->cbCapture) {
  680. #endif // FE_SB
  681. return STATUS_BUFFER_OVERFLOW;
  682. }
  683. pbBuffer = pcb->pbFree;
  684. /*
  685. * Convert the unicode string to ANSI
  686. */
  687. try {
  688. #ifdef FE_SB // CaptureAnsiCallbackData()
  689. /*
  690. * Enough space for keep DBCS string.
  691. */
  692. if (!NT_SUCCESS(RtlUnicodeToMultiByteN(
  693. (PCH)pbBuffer,
  694. IS_DBCS_ENABLED() ? cbData * DBCS_CHARSIZE : cbData,
  695. &nCharsInAnsiString,
  696. (PWCH)pData,
  697. cbData * sizeof(WCHAR)
  698. ))) {
  699. #else
  700. if (!NT_SUCCESS(RtlUnicodeToMultiByteN(
  701. (PCH)pbBuffer,
  702. cbData,
  703. &nCharsInAnsiString,
  704. (PWCH)pData,
  705. cbData * sizeof(WCHAR)
  706. ))) {
  707. #endif // FE_SB
  708. return STATUS_UNSUCCESSFUL;
  709. }
  710. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  711. return STATUS_ACCESS_VIOLATION;
  712. }
  713. /*
  714. * Translation succeeded.
  715. */
  716. #ifdef FE_SB // CaptureAnsiCallbackData()
  717. /*
  718. * nCharsInAnsiString is actual bytes wriiten in message area.
  719. */
  720. pcb->pbFree = pbBuffer + ((nCharsInAnsiString + PADSIZE) & ~PADSIZE);
  721. pcb->cbCapture -= nCharsInAnsiString;
  722. #else
  723. pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
  724. pcb->cbCapture -= cbData;
  725. #endif // FE_SB
  726. /*
  727. * Fix up offsets to data. If the data is going into a section
  728. * use the real pointer and don't compute offsets.
  729. */
  730. if (pcb->pvVirtualAddress)
  731. *ppDest = pbBuffer;
  732. else {
  733. *ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
  734. ((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
  735. (DWORD)((PBYTE)ppDest - (PBYTE)pcb);
  736. }
  737. return STATUS_SUCCESS;
  738. }
  739. /***************************************************************************\
  740. * CaptureUnicodeCallbackData
  741. *
  742. * Converts ANSI to Unicode data and captures the result
  743. * into a callback structure.
  744. *
  745. * 03-31-95 JimA Created.
  746. \***************************************************************************/
  747. NTSTATUS CaptureUnicodeCallbackData(
  748. PCAPTUREBUF pcb,
  749. PVOID pData,
  750. DWORD cbData,
  751. PVOID *ppDest)
  752. {
  753. PBYTE pbBuffer;
  754. ULONG nCharsInUnicodeString;
  755. /*
  756. * If the data pointer is NULL, the out pointer will be
  757. * NULL
  758. */
  759. if (pData == NULL) {
  760. *ppDest = NULL;
  761. return STATUS_SUCCESS;
  762. }
  763. /*
  764. * Allocate space from the message buffer
  765. */
  766. if (cbData > pcb->cbCapture) {
  767. return STATUS_BUFFER_OVERFLOW;
  768. }
  769. pbBuffer = pcb->pbFree;
  770. /*
  771. * Convert the ANSI string to unicode
  772. */
  773. try {
  774. if (!NT_SUCCESS(RtlMultiByteToUnicodeN(
  775. (PWCH)pbBuffer,
  776. cbData,
  777. &nCharsInUnicodeString,
  778. (PCH)pData,
  779. cbData / sizeof(WCHAR)
  780. ))) {
  781. return STATUS_UNSUCCESSFUL;
  782. }
  783. } except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
  784. return STATUS_ACCESS_VIOLATION;
  785. }
  786. /*
  787. * Translation succeeded.
  788. */
  789. pcb->pbFree = pbBuffer + ((cbData + PADSIZE) & ~PADSIZE);
  790. pcb->cbCapture -= cbData;
  791. /*
  792. * Fix up offsets to data. If the data is going into a section
  793. * use the real pointer and don't compute offsets.
  794. */
  795. if (pcb->pvVirtualAddress)
  796. *ppDest = pbBuffer;
  797. else {
  798. *ppDest = (PBYTE)(pbBuffer - (PBYTE)pcb);
  799. ((LPDWORD)((PBYTE)pcb + pcb->offPointers))[pcb->cCapturedPointers++] =
  800. (DWORD)((PBYTE)ppDest - (PBYTE)pcb);
  801. }
  802. return STATUS_SUCCESS;
  803. }
  804. /***************************************************************************\
  805. * CopyOutputString
  806. *
  807. * Copies a callback output string to the output buffer and performs
  808. * any necessary ANSI/Unicode translation.
  809. *
  810. * Copies up to cchLimit characters, possibly including a null terminator.
  811. *
  812. * A null terminator is placed in pstr->Buffer only if the number of (non-null)
  813. * characters obtained is less than cchLimit.
  814. * pstr->Length may be set larger than necessary: ie: it may sometimes indicate
  815. * a string longer than that which is null terminated. This is a deficiency in
  816. * the current implementation.
  817. *
  818. * 05-08-95 JimA Created.
  819. \***************************************************************************/
  820. VOID CopyOutputString(
  821. PCALLBACKSTATUS pcbs,
  822. PLARGE_STRING pstr,
  823. UINT cchLimit,
  824. BOOL fAnsi)
  825. {
  826. UINT cch;
  827. ProbeForRead(pcbs->pOutput, pcbs->cbOutput,
  828. fAnsi ? sizeof(BYTE) : sizeof(WORD));
  829. if (!pstr->bAnsi) {
  830. if (fAnsi) {
  831. cch = MBToWCS((LPSTR)pcbs->pOutput, (UINT)pcbs->retval,
  832. (LPWSTR *)&pstr->Buffer, cchLimit, FALSE);
  833. if (cch < cchLimit) {
  834. /*
  835. * Add a null terminator and ensure an accurate pstr->Length
  836. */
  837. ((LPWSTR)pstr->Buffer)[cch] = 0;
  838. cchLimit = cch;
  839. }
  840. } else {
  841. cchLimit = wcsncpycch(pstr->Buffer, (LPWSTR)pcbs->pOutput, cchLimit);
  842. // wcsncpy(pstr->Buffer, (LPWSTR)pcbs->pOutput, cchLimit);
  843. }
  844. pstr->Length = cchLimit * sizeof(WCHAR);
  845. } else {
  846. if (fAnsi) {
  847. cchLimit = strncpycch((LPSTR)pstr->Buffer,
  848. // strncpy((LPSTR)pstr->Buffer,
  849. (LPSTR)pcbs->pOutput, cchLimit);
  850. } else {
  851. cch = WCSToMB((LPWSTR)pcbs->pOutput, (UINT)pcbs->retval,
  852. (LPSTR *)&pstr->Buffer, cchLimit, FALSE);
  853. if (cch < cchLimit) {
  854. /*
  855. * Add a null terminator and ensure an accurate pstr->Length
  856. */
  857. ((LPSTR)pstr->Buffer)[cch] = 0;
  858. cchLimit = cch;
  859. }
  860. }
  861. pstr->Length = cchLimit;
  862. }
  863. }
  864. #ifdef FE_SB // CalcOutputStringSize()
  865. /***************************************************************************\
  866. * CalcOutputStringSize()
  867. *
  868. * Copies a callback output string to the output buffer and performs
  869. * any necessary ANSI/Unicode translation.
  870. *
  871. * 03-14-96 HideyukN Created.
  872. \***************************************************************************/
  873. DWORD CalcOutputStringSize(
  874. PCALLBACKSTATUS pcbs,
  875. DWORD cchText,
  876. BOOL fAnsiSender,
  877. BOOL fAnsiReceiver)
  878. {
  879. ULONG cch;
  880. ProbeForRead(pcbs->pOutput, pcbs->cbOutput,
  881. fAnsiReceiver ? sizeof(BYTE) : sizeof(WORD));
  882. if (!fAnsiSender) {
  883. if (fAnsiReceiver) {
  884. RtlMultiByteToUnicodeSize(&cch,(LPSTR)pcbs->pOutput,cchText);
  885. cch /= sizeof(WCHAR);
  886. } else {
  887. cch = cchText;
  888. }
  889. } else {
  890. if (fAnsiReceiver) {
  891. cch = cchText;
  892. } else {
  893. RtlUnicodeToMultiByteSize(&cch,(LPWSTR)pcbs->pOutput,cchText * sizeof(WCHAR));
  894. }
  895. }
  896. return ((DWORD)cch);
  897. }
  898. #endif // FE_SB
  899. /**************************************************************************\
  900. *
  901. * include the stub definition file
  902. *
  903. \**************************************************************************/
  904. #include "ntcb.h"