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.

885 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996-1998 Microsoft Corporation
  3. Module Name:
  4. fileqcb.c
  5. Abstract:
  6. Routines to call out to file queue callbacks, translating
  7. character types as necessary.
  8. Author:
  9. Ted Miller (tedm) Feb-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Define structure that describes, for a given structure, how to
  16. // thunk it back and forth between ANSI and Unicode.
  17. //
  18. typedef struct _STRUCT_THUNK_DATA {
  19. //
  20. // Size of the structure
  21. //
  22. unsigned StructureSize;
  23. //
  24. // Offsets of members that are pointers to strings
  25. // that need conversion before calling the callback function.
  26. // A -1 terminates the list.
  27. //
  28. int StringMemberOffsets[5];
  29. //
  30. // Offsets of DWORD members that need to be copied back from
  31. // the temporary structure back into the caller's one.
  32. //
  33. int OutputDwordOffsets[2];
  34. //
  35. // Offsets of strings that need to be converted in place
  36. // after the callback has occurred.
  37. //
  38. int OutputStringOffsets[2];
  39. } STRUCT_THUNK_DATA, *PSTRUCT_THUNK_DATA;
  40. //
  41. // Define enum for data types we care about for the setup message
  42. // notification mechanism.
  43. //
  44. typedef enum {
  45. FileMsgFilepaths, // FILEPATHS
  46. FileMsgSourcemedia, // SOURCE_MEDIA
  47. FileMsgCabinetinfo, // CABINET_INFO
  48. FileMsgFileincabinfo, // FILE_IN_CABINET_INFO
  49. FileMsgControlStatus, // SP_REGISTER_CONTROL_STATUS
  50. FileMsgNone, // No translation (special case)
  51. FileMsgString, // Plain string (special case)
  52. FileMsgStringOut // String written by callback (special case)
  53. } FileMsgStruct;
  54. //
  55. // Instantiate structure thunk data for structures we care about.
  56. //
  57. STRUCT_THUNK_DATA StructThunkData[] = {
  58. //
  59. // FILEPATHS structure
  60. //
  61. {
  62. sizeof(FILEPATHS),
  63. {
  64. offsetof(FILEPATHS,Target),
  65. offsetof(FILEPATHS,Source),
  66. -1
  67. },
  68. { offsetof(FILEPATHS,Win32Error),-1 }, { -1 }
  69. },
  70. //
  71. // SOURCE_MEDIA structure
  72. //
  73. {
  74. sizeof(SOURCE_MEDIA),
  75. {
  76. offsetof(SOURCE_MEDIA,Tagfile),
  77. offsetof(SOURCE_MEDIA,Description),
  78. offsetof(SOURCE_MEDIA,SourcePath),
  79. offsetof(SOURCE_MEDIA,SourceFile),
  80. -1
  81. },
  82. { -1 }, { -1 }
  83. },
  84. //
  85. // CABINET_INFO structure
  86. //
  87. {
  88. sizeof(CABINET_INFO),
  89. {
  90. offsetof(CABINET_INFO,CabinetPath),
  91. offsetof(CABINET_INFO,CabinetFile),
  92. offsetof(CABINET_INFO,DiskName),
  93. -1
  94. },
  95. { -1 }, { -1 }
  96. },
  97. //
  98. // FILE_IN_CABINET_INFO structure
  99. //
  100. {
  101. sizeof(FILE_IN_CABINET_INFO),
  102. {
  103. offsetof(FILE_IN_CABINET_INFO,NameInCabinet),
  104. -1
  105. },
  106. { offsetof(FILE_IN_CABINET_INFO,Win32Error),-1 },
  107. { offsetof(FILE_IN_CABINET_INFO,FullTargetName),-1 }
  108. },
  109. //
  110. // SP_REGISTER_CONTROL_STATUS structure
  111. //
  112. {
  113. sizeof(SP_REGISTER_CONTROL_STATUS),
  114. {
  115. offsetof(SP_REGISTER_CONTROL_STATUS,FileName),
  116. -1
  117. },
  118. { -1 }, { -1 }
  119. }
  120. };
  121. //
  122. // Define structure that describes how to translate messages
  123. // from ANSI<-->Unicode for all notification messages that we send out.
  124. // and special return codes
  125. //
  126. typedef struct _MSG_THUNK_DATA {
  127. DWORD Notification;
  128. BOOL UseMask;
  129. FileMsgStruct Param1Type;
  130. FileMsgStruct Param2Type;
  131. UINT ExceptionReturn;
  132. } MSG_THUNK_DATA, *PMSG_THUNK_DATA;
  133. //
  134. // Instantiate message thunk data.
  135. // Entries marked as FILEOP_RETURN_STATUS indicate that the return value is a
  136. // windows error code.
  137. //
  138. MSG_THUNK_DATA MsgThunkData[] =
  139. {
  140. { SPFILENOTIFY_STARTQUEUE, FALSE,FileMsgNone ,FileMsgNone ,FALSE },
  141. { SPFILENOTIFY_ENDQUEUE, FALSE,FileMsgNone ,FileMsgNone ,0 },
  142. { SPFILENOTIFY_STARTSUBQUEUE, FALSE,FileMsgNone ,FileMsgNone ,FALSE },
  143. { SPFILENOTIFY_ENDSUBQUEUE, FALSE,FileMsgNone ,FileMsgNone ,FALSE },
  144. { SPFILENOTIFY_STARTDELETE, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  145. { SPFILENOTIFY_ENDDELETE, FALSE,FileMsgFilepaths ,FileMsgNone ,0 },
  146. { SPFILENOTIFY_DELETEERROR, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  147. { SPFILENOTIFY_STARTRENAME, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  148. { SPFILENOTIFY_ENDRENAME, FALSE,FileMsgFilepaths ,FileMsgNone ,0 },
  149. { SPFILENOTIFY_RENAMEERROR, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  150. { SPFILENOTIFY_STARTCOPY, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  151. { SPFILENOTIFY_ENDCOPY, FALSE,FileMsgFilepaths ,FileMsgNone ,0 },
  152. { SPFILENOTIFY_COPYERROR, FALSE,FileMsgFilepaths ,FileMsgStringOut,FILEOP_ABORT },
  153. { SPFILENOTIFY_NEEDMEDIA, FALSE,FileMsgSourcemedia ,FileMsgStringOut,FILEOP_ABORT },
  154. { SPFILENOTIFY_QUEUESCAN, FALSE,FileMsgString ,FileMsgNone ,FILEOP_RETURN_STATUS},
  155. { SPFILENOTIFY_QUEUESCAN_EX, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_RETURN_STATUS},
  156. { SPFILENOTIFY_CABINETINFO, FALSE,FileMsgCabinetinfo ,FileMsgNone ,FILEOP_RETURN_STATUS},
  157. { SPFILENOTIFY_FILEINCABINET, FALSE,FileMsgFileincabinfo,FileMsgString ,FILEOP_INTERNAL_FAILED},
  158. { SPFILENOTIFY_NEEDNEWCABINET, FALSE,FileMsgCabinetinfo ,FileMsgStringOut,FILEOP_RETURN_STATUS},
  159. { SPFILENOTIFY_FILEEXTRACTED, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_RETURN_STATUS},
  160. { SPFILENOTIFY_FILEOPDELAYED, FALSE,FileMsgFilepaths ,FileMsgNone ,0 },
  161. { SPFILENOTIFY_STARTBACKUP, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  162. { SPFILENOTIFY_ENDBACKUP, FALSE,FileMsgFilepaths ,FileMsgNone ,0 },
  163. { SPFILENOTIFY_BACKUPERROR, FALSE,FileMsgFilepaths ,FileMsgNone ,FILEOP_ABORT },
  164. { SPFILENOTIFY_STARTREGISTRATION, FALSE,FileMsgControlStatus,FileMsgNone ,FILEOP_ABORT },
  165. { SPFILENOTIFY_ENDREGISTRATION, FALSE,FileMsgControlStatus,FileMsgNone ,FILEOP_ABORT },
  166. { SPFILENOTIFY_LANGMISMATCH
  167. | SPFILENOTIFY_TARGETEXISTS
  168. | SPFILENOTIFY_TARGETNEWER, TRUE ,FileMsgFilepaths ,FileMsgNone ,FALSE }
  169. };
  170. //
  171. // Forward references.
  172. //
  173. BOOL
  174. pSetupConvertMsgHandlerArgs(
  175. IN UINT Notification,
  176. IN UINT_PTR Param1,
  177. IN UINT_PTR Param2,
  178. OUT PUINT_PTR NewParam1,
  179. OUT PUINT_PTR NewParam2,
  180. IN BOOL ToAnsi,
  181. OUT PMSG_THUNK_DATA *ThunkData
  182. );
  183. BOOL
  184. pThunkSetupMsgParam(
  185. IN FileMsgStruct StructType,
  186. IN UINT_PTR Param,
  187. OUT UINT_PTR *NewParam,
  188. IN BOOL ToAnsi
  189. );
  190. VOID
  191. pUnthunkSetupMsgParam(
  192. IN FileMsgStruct StructType,
  193. IN OUT UINT_PTR OriginalParam,
  194. IN OUT UINT_PTR ThunkedParam,
  195. IN BOOL FreeOnly,
  196. IN BOOL ThunkedToAnsi
  197. );
  198. UINT
  199. pGetCallbackErrorReturn(
  200. IN UINT Notification,
  201. IN DWORD ReturnStatus
  202. )
  203. /*++
  204. Routine Description:
  205. Determine return value for given notification and given ReturnStatus.
  206. Arguments:
  207. Notification - supplies notification
  208. Return Value:
  209. Return code specific to the notification.
  210. --*/
  211. {
  212. unsigned u;
  213. PMSG_THUNK_DATA thunkData;
  214. BOOL KnownMessage;
  215. MYASSERT(ReturnStatus);
  216. //
  217. // Locate the msg-specific thunk data descriptor.
  218. //
  219. KnownMessage = FALSE;
  220. for(u=0; !KnownMessage && (u<(sizeof(MsgThunkData)/sizeof(MsgThunkData[0]))); u++) {
  221. thunkData = &MsgThunkData[u];
  222. if(thunkData->UseMask) {
  223. KnownMessage = ((thunkData->Notification & Notification) != 0);
  224. } else {
  225. KnownMessage = (thunkData->Notification == Notification);
  226. }
  227. }
  228. SetLastError(ReturnStatus);
  229. if (!KnownMessage) {
  230. MYASSERT(KnownMessage);
  231. SetLastError(ReturnStatus);
  232. return 0;
  233. } else if(thunkData->ExceptionReturn == FILEOP_RETURN_STATUS) {
  234. return ReturnStatus;
  235. } else {
  236. return thunkData->ExceptionReturn;
  237. }
  238. }
  239. #ifdef UNICODE
  240. UINT
  241. pSetupCallMsgHandler(
  242. IN PSETUP_LOG_CONTEXT LogContext,
  243. IN PVOID MsgHandler,
  244. IN BOOL MsgHandlerIsNativeCharWidth,
  245. IN PVOID Context,
  246. IN UINT Notification,
  247. IN UINT_PTR Param1,
  248. IN UINT_PTR Param2
  249. )
  250. /*++
  251. Routine Description:
  252. Call out to a SP_FILE_CALLBACK routine, translating arguments from
  253. Unicode to ANSI as necessary, and marshalling data back into Unicode
  254. as necessary.
  255. Conversions and marshalling occur only for messages we recognize
  256. (ie, that are in the MsgThunkData array). Unrecognized messages
  257. are assumed to be private and are passed through unchanged.
  258. If a Unicode->ANSI conversion fails due to an out of memory condition,
  259. this routine sets last error to ERROR_NOT_ENOUGH_MEMORY and returns
  260. the value specified in the relevent MsgThunkData structure.
  261. Arguments:
  262. LogContext - context for logging errors
  263. MsgHandler - supplies pointer to callback routine. Can be either
  264. a routine expecting ANSI args or Unicode args, as specified
  265. by MsgHandlerIsNativeCharWidth.
  266. MsgHandlerIsNativeCharWidth - supplies flag indicating whether callback
  267. functionexpects Unicode (TRUE) or ANSI (FALSE) arguments.
  268. Context - supplies context data meaningful to the callback
  269. routine. Not interpreted by this routine, merely passed on.
  270. Notification - supplies notification code to be passed to the callback.
  271. Param1 - supplies first notification-specific parameter to be passed
  272. to the callback.
  273. Param2 - supplies second notification-specific parameter to be passed
  274. to the callback.
  275. Return Value:
  276. Return code specific to the notification.
  277. --*/
  278. {
  279. PSP_FILE_CALLBACK_A MsgHandlerA;
  280. PSP_FILE_CALLBACK_W MsgHandlerW;
  281. UINT rc,ec;
  282. UINT_PTR Param1A,Param2A;
  283. BOOL b;
  284. PMSG_THUNK_DATA ThunkData;
  285. //
  286. // If already unicode, nothing to do, just call the msghandler.
  287. //
  288. if(MsgHandlerIsNativeCharWidth) {
  289. MsgHandlerW = (PSP_FILE_CALLBACK_W)MsgHandler;
  290. try {
  291. SetLastError(NO_ERROR);
  292. rc = MsgHandlerW(Context,Notification,Param1,Param2);
  293. } except(EXCEPTION_EXECUTE_HANDLER) {
  294. WriteLogEntry(
  295. LogContext,
  296. SETUP_LOG_ERROR,
  297. MSG_LOG_QUEUE_CALLBACK_FAILED,
  298. NULL,
  299. GetExceptionCode());
  300. rc = pGetCallbackErrorReturn(Notification,ERROR_INVALID_DATA);
  301. }
  302. return rc;
  303. }
  304. //
  305. // Optimization: if we are going to call the ANSI version of the
  306. // default queue callback routine SetupDefaultQueueCallbackA(),
  307. // we can avoid converting the args, since they'll just be converted
  308. // right back again by that API as a prelude to calling the
  309. // actual implementation SetupDefaultQueueCallbackW().
  310. //
  311. if(MsgHandler == SetupDefaultQueueCallbackA) {
  312. SetLastError(NO_ERROR);
  313. return(SetupDefaultQueueCallbackW(Context,Notification,Param1,Param2));
  314. }
  315. //
  316. // Target callback function is expecting ANSI arguments.
  317. //
  318. b = pSetupConvertMsgHandlerArgs(
  319. Notification,
  320. Param1,
  321. Param2,
  322. &Param1A,
  323. &Param2A,
  324. TRUE,
  325. &ThunkData
  326. );
  327. if(!b) {
  328. return pGetCallbackErrorReturn(Notification,ERROR_NOT_ENOUGH_MEMORY);
  329. }
  330. //
  331. // Agrs are ready; call out to the ANSI callback.
  332. //
  333. MsgHandlerA = MsgHandler;
  334. try {
  335. SetLastError(NO_ERROR);
  336. rc = MsgHandlerA(Context,Notification,Param1A,Param2A);
  337. } except(EXCEPTION_EXECUTE_HANDLER) {
  338. WriteLogEntry(
  339. LogContext,
  340. SETUP_LOG_ERROR,
  341. MSG_LOG_QUEUE_CALLBACK_FAILED,
  342. NULL,
  343. GetExceptionCode());
  344. rc = pGetCallbackErrorReturn(Notification,ERROR_INVALID_DATA);
  345. }
  346. ec = GetLastError();
  347. //
  348. // Free the temporary thunk structs and marshall data back into
  349. // the original structures as necessary.
  350. //
  351. if(ThunkData) {
  352. pUnthunkSetupMsgParam(ThunkData->Param1Type,Param1,Param1A,FALSE,TRUE);
  353. pUnthunkSetupMsgParam(ThunkData->Param2Type,Param2,Param2A,FALSE,TRUE);
  354. }
  355. SetLastError(ec);
  356. return(rc);
  357. }
  358. UINT
  359. pSetupCallDefaultMsgHandler(
  360. IN PVOID Context,
  361. IN UINT Notification,
  362. IN UINT_PTR Param1,
  363. IN UINT_PTR Param2
  364. )
  365. {
  366. UINT_PTR Param1U,Param2U;
  367. BOOL b;
  368. PMSG_THUNK_DATA ThunkData;
  369. UINT rc,ec;
  370. //
  371. // Thunk args to Unicode.
  372. //
  373. b = pSetupConvertMsgHandlerArgs(
  374. Notification,
  375. Param1,
  376. Param2,
  377. &Param1U,
  378. &Param2U,
  379. FALSE,
  380. &ThunkData
  381. );
  382. if(!b) {
  383. return pGetCallbackErrorReturn(Notification,ERROR_NOT_ENOUGH_MEMORY);
  384. }
  385. //
  386. // Agrs are ready; call the default queue callback.
  387. //
  388. rc = SetupDefaultQueueCallbackW(Context,Notification,Param1U,Param2U);
  389. ec = GetLastError();
  390. //
  391. // Free the temporary thunk structs and marshall data back into
  392. // the original structures as necessary.
  393. //
  394. if(ThunkData) {
  395. pUnthunkSetupMsgParam(ThunkData->Param1Type,Param1,Param1U,FALSE,FALSE);
  396. pUnthunkSetupMsgParam(ThunkData->Param2Type,Param2,Param2U,FALSE,FALSE);
  397. }
  398. SetLastError(ec);
  399. return(rc);
  400. }
  401. BOOL
  402. pSetupConvertMsgHandlerArgs(
  403. IN UINT Notification,
  404. IN UINT_PTR Param1,
  405. IN UINT_PTR Param2,
  406. OUT PUINT_PTR NewParam1,
  407. OUT PUINT_PTR NewParam2,
  408. IN BOOL ToAnsi,
  409. OUT PMSG_THUNK_DATA *ThunkData
  410. )
  411. /*++
  412. Routine Description:
  413. Locate thunk description data for a given notification and convert
  414. parameters from Unicode to ANSI or ANSI to Unicode.
  415. Arguments:
  416. Notification - supplies notification code to be passed to the callback.
  417. Param1 - supplies first notification-specific parameter to be passed
  418. to the callback, which is to be converted.
  419. Param2 - supplies second notification-specific parameter to be passed
  420. to the callback, which is to be converted.
  421. NewParam1 - receives first notification-specific parameter to be passed
  422. to the callback.
  423. NewParam2 - receives second notification-specific parameter to be passed
  424. to the callback.
  425. ToAnsi - supplies flag indicating whether parameters are to be converted
  426. from ANSI to Unicode or Unicode to ANSI.
  427. ThunkData - if the Notification is recognized, receives a pointer to
  428. the MSG_THUNK_DATA for the given Notification. If not recognized,
  429. receives NULL.
  430. Return Value:
  431. Boolean value indicating whether conversion was successful.
  432. If FALSE, the caller can assume out of memory.
  433. --*/
  434. {
  435. unsigned u;
  436. PMSG_THUNK_DATA thunkData;
  437. BOOL KnownMessage;
  438. //
  439. // Locate the msg-specific thunk data descriptor.
  440. //
  441. KnownMessage = FALSE;
  442. for(u=0; !KnownMessage && (u<(sizeof(MsgThunkData)/sizeof(MsgThunkData[0]))); u++) {
  443. thunkData = &MsgThunkData[u];
  444. if(thunkData->UseMask) {
  445. KnownMessage = ((thunkData->Notification & Notification) != 0);
  446. } else {
  447. KnownMessage = (thunkData->Notification == Notification);
  448. }
  449. }
  450. if(!KnownMessage) {
  451. //
  452. // Unknown message; must be private. Just pass args on as-is.
  453. //
  454. *NewParam1 = Param1;
  455. *NewParam2 = Param2;
  456. *ThunkData = NULL;
  457. } else {
  458. //
  459. // Got a message we understand. Thunk it.
  460. //
  461. *ThunkData = thunkData;
  462. if(!pThunkSetupMsgParam(thunkData->Param1Type,Param1,NewParam1,ToAnsi)) {
  463. return(FALSE);
  464. }
  465. if(!pThunkSetupMsgParam(thunkData->Param2Type,Param2,NewParam2,ToAnsi)) {
  466. pUnthunkSetupMsgParam(thunkData->Param1Type,Param1,*NewParam1,TRUE,ToAnsi);
  467. return(FALSE);
  468. }
  469. }
  470. return(TRUE);
  471. }
  472. BOOL
  473. pThunkSetupMsgParam(
  474. IN FileMsgStruct StructType,
  475. IN UINT_PTR Param,
  476. OUT UINT_PTR *NewParam,
  477. IN BOOL ToAnsi
  478. )
  479. /*++
  480. Routine Description:
  481. Convert a parameter to a setup notification callback from ANSI to
  482. Unicode or Unicode to ANSI as necessary. Allocates all required memory
  483. and performs conversions.
  484. Arguments:
  485. StructType - supplies type of data represented by Param.
  486. Param - supplies parameter to be converted.
  487. NewParam - receives new parameter. Caller should free via
  488. pUnthunkSetupMsgParam when done.
  489. ToAnsi - if FALSE, Param is to be converted from ANSI to Unicode.
  490. If TRUE, Param is to be converted from Unicode to ANSI.
  491. Return Value:
  492. Boolean value indicating whether conversion occured successfully.
  493. If FALSE, the caller can assume out of memory.
  494. --*/
  495. {
  496. unsigned u,v;
  497. PUCHAR newStruct;
  498. PVOID OldString;
  499. PVOID NewString;
  500. //
  501. // Handle special cases here.
  502. //
  503. switch(StructType) {
  504. case FileMsgNone:
  505. *NewParam = Param;
  506. return(TRUE);
  507. case FileMsgStringOut:
  508. //
  509. // Callee will write string data which we will convert later.
  510. //
  511. if(*NewParam = (UINT_PTR)MyMalloc(MAX_PATH * (ToAnsi ? sizeof(CHAR) : sizeof(WCHAR)))) {
  512. if(ToAnsi) {
  513. *(PCHAR)(*NewParam) = 0;
  514. } else {
  515. *(PWCHAR)(*NewParam) = 0;
  516. }
  517. }
  518. return(*NewParam != 0);
  519. case FileMsgString:
  520. if(ToAnsi) {
  521. *NewParam = (UINT_PTR)pSetupUnicodeToAnsi((PCWSTR)Param);
  522. } else {
  523. *NewParam = (UINT_PTR)pSetupAnsiToUnicode((PCSTR)Param);
  524. }
  525. return(*NewParam != 0);
  526. }
  527. newStruct = MyMalloc(StructThunkData[StructType].StructureSize);
  528. if(!newStruct) {
  529. return(FALSE);
  530. }
  531. CopyMemory(newStruct,(PVOID)Param,StructThunkData[StructType].StructureSize);
  532. for(u=0; StructThunkData[StructType].StringMemberOffsets[u] != -1; u++) {
  533. OldString = *(PVOID *)((PUCHAR)Param + StructThunkData[StructType].StringMemberOffsets[u]);
  534. if(OldString) {
  535. if(ToAnsi) {
  536. NewString = pSetupUnicodeToAnsi(OldString);
  537. } else {
  538. NewString = pSetupAnsiToUnicode(OldString);
  539. }
  540. if(!NewString) {
  541. for(v=0; v<u; v++) {
  542. MyFree(*(PVOID *)(newStruct + StructThunkData[StructType].StringMemberOffsets[v]));
  543. }
  544. MyFree(newStruct);
  545. return(FALSE);
  546. }
  547. *(PVOID *)(newStruct + StructThunkData[StructType].StringMemberOffsets[u]) = NewString;
  548. }
  549. }
  550. *NewParam = (UINT_PTR)newStruct;
  551. return(TRUE);
  552. }
  553. VOID
  554. pUnthunkSetupMsgParam(
  555. IN FileMsgStruct StructType,
  556. IN OUT UINT_PTR OriginalParam,
  557. IN OUT UINT_PTR ThunkedParam,
  558. IN BOOL FreeOnly,
  559. IN BOOL ThunkedToAnsi
  560. )
  561. /*++
  562. Routine Description:
  563. Marshal data output by a callback function back into the original
  564. Unicode or ANSI structure. Also, free the temporary structure and all
  565. its resources.
  566. Arguments:
  567. StructType - supplies type of data being operated on.
  568. OriginalParam - supplies original parameter. DWORD fields and
  569. in-place strings in this structure will be updated by this routine.
  570. ThunkedParam - supplies temporary ANSI or Unicode parameter.
  571. FreeOnly - if TRUE, no marshalling occurs but ThunkedParam will be freed.
  572. Return Value:
  573. None.
  574. --*/
  575. {
  576. unsigned u;
  577. PVOID String;
  578. PVOID SourceString;
  579. DWORD d;
  580. //
  581. // Special cases here.
  582. //
  583. switch(StructType) {
  584. case FileMsgNone:
  585. //
  586. // Nothing to do for this one.
  587. //
  588. return;
  589. case FileMsgStringOut:
  590. //
  591. // Callee wrote string data; convert as appropriate.
  592. //
  593. if(!FreeOnly) {
  594. if(ThunkedToAnsi) {
  595. MultiByteToWideChar(
  596. CP_ACP,
  597. 0,
  598. (PCSTR)ThunkedParam,
  599. -1,
  600. (PWCHAR)OriginalParam,
  601. MAX_PATH
  602. );
  603. } else {
  604. WideCharToMultiByte(
  605. CP_ACP,
  606. 0,
  607. (PCWSTR)ThunkedParam,
  608. -1,
  609. (PCHAR)OriginalParam,
  610. MAX_PATH,
  611. NULL,
  612. NULL
  613. );
  614. }
  615. }
  616. MyFree((PVOID)ThunkedParam);
  617. return;
  618. case FileMsgString:
  619. //
  620. // Simple string.
  621. //
  622. MyFree((PVOID)ThunkedParam);
  623. return;
  624. }
  625. //
  626. // Free all strings.
  627. //
  628. for(u=0; StructThunkData[StructType].StringMemberOffsets[u] != -1; u++) {
  629. String = *(PVOID *)((PUCHAR)ThunkedParam + StructThunkData[StructType].StringMemberOffsets[u]);
  630. if(String) {
  631. MyFree(String);
  632. }
  633. }
  634. //
  635. // Marshall data back to Unicode structure
  636. //
  637. if(!FreeOnly) {
  638. //
  639. // Copy DWORD data from the thunk struct back to the original struct.
  640. //
  641. for(u=0; StructThunkData[StructType].OutputDwordOffsets[u] != -1; u++) {
  642. d = *(DWORD *)((PUCHAR)ThunkedParam + StructThunkData[StructType].OutputDwordOffsets[u]);
  643. *(DWORD *)((PUCHAR)OriginalParam + StructThunkData[StructType].OutputDwordOffsets[u]) = d;
  644. }
  645. //
  646. // Convert output strings.
  647. //
  648. for(u=0; StructThunkData[StructType].OutputStringOffsets[u] != -1; u++) {
  649. SourceString = (PUCHAR)ThunkedParam + StructThunkData[StructType].OutputStringOffsets[u];
  650. String = (PUCHAR)OriginalParam + StructThunkData[StructType].OutputStringOffsets[u];
  651. if(ThunkedToAnsi) {
  652. MultiByteToWideChar(
  653. CP_ACP,
  654. 0,
  655. SourceString,
  656. -1,
  657. String,
  658. MAX_PATH
  659. );
  660. } else {
  661. WideCharToMultiByte(
  662. CP_ACP,
  663. 0,
  664. SourceString,
  665. -1,
  666. String,
  667. MAX_PATH,
  668. NULL,
  669. NULL
  670. );
  671. }
  672. }
  673. }
  674. MyFree((PVOID)ThunkedParam);
  675. }
  676. #else
  677. UINT
  678. pSetupCallMsgHandler(
  679. IN PSETUP_LOG_CONTEXT LogContext,
  680. IN PVOID MsgHandler,
  681. IN BOOL MsgHandlerIsNativeCharWidth,
  682. IN PVOID Context,
  683. IN UINT Notification,
  684. IN UINT_PTR Param1,
  685. IN UINT_PTR Param2
  686. )
  687. {
  688. PSP_FILE_CALLBACK_A msghandler;
  689. UINT result = 0;
  690. UNREFERENCED_PARAMETER(MsgHandlerIsNativeCharWidth);
  691. MYASSERT(MsgHandlerIsNativeCharWidth);
  692. //
  693. // ANSI version has no thunking
  694. //
  695. try {
  696. msghandler = (PSP_FILE_CALLBACK_A)MsgHandler;
  697. result = msghandler(Context,Notification,Param1,Param2);
  698. } except(EXCEPTION_EXECUTE_HANDLER) {
  699. WriteLogEntry(
  700. LogContext,
  701. SETUP_LOG_ERROR,
  702. MSG_LOG_QUEUE_CALLBACK_FAILED,
  703. NULL,
  704. GetExceptionCode());
  705. result = pGetCallbackErrorReturn(Notification,ERROR_INVALID_DATA);
  706. }
  707. return result;
  708. }
  709. #endif