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.

845 lines
26 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. diansicv.c
  5. Abstract:
  6. Routine to convert device installer data structures between
  7. ANSI and Unicode.
  8. Author:
  9. Ted Miller (tedm) 19-July-1996
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. DWORD
  15. pSetupDiDevInstParamsAnsiToUnicode(
  16. IN PSP_DEVINSTALL_PARAMS_A AnsiDevInstParams,
  17. OUT PSP_DEVINSTALL_PARAMS_W UnicodeDevInstParams
  18. )
  19. /*++
  20. Routine Description:
  21. This routine converts an SP_DEVINSTALL_PARAMS_A structure to
  22. an SP_DEVINSTALL_PARAMS_W, guarding against bogus pointers
  23. passed in the by the caller.
  24. Arguments:
  25. AnsiDevInstParams - supplies ANSI device installation parameters
  26. to be converted to unicode.
  27. UnicodeDevInstParams - if successful, receives Unicode equivalent of
  28. AnsiDevInstParams.
  29. Return Value:
  30. NO_ERROR - conversion successful.
  31. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  32. It is not believed that, given valid arguments, text conversion itself
  33. can fail, since all ANSI chars always have Unicode equivalents.
  34. --*/
  35. {
  36. DWORD rc;
  37. try {
  38. if(AnsiDevInstParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) {
  39. rc = ERROR_INVALID_USER_BUFFER;
  40. leave;
  41. }
  42. //
  43. // Fixed part of structure.
  44. //
  45. MYASSERT(offsetof(SP_DEVINSTALL_PARAMS_A,DriverPath) == offsetof(SP_DEVINSTALL_PARAMS_W,DriverPath));
  46. CopyMemory(UnicodeDevInstParams,
  47. AnsiDevInstParams,
  48. offsetof(SP_DEVINSTALL_PARAMS_W,DriverPath)
  49. );
  50. UnicodeDevInstParams->cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
  51. //
  52. // Convert the single string in the structure. To make things easier
  53. // we'll just convert the entire buffer. There's no potential for
  54. // overflow.
  55. //
  56. rc = GLE_FN_CALL(0,
  57. MultiByteToWideChar(
  58. CP_ACP,
  59. MB_PRECOMPOSED,
  60. AnsiDevInstParams->DriverPath,
  61. sizeof(AnsiDevInstParams->DriverPath),
  62. UnicodeDevInstParams->DriverPath,
  63. SIZECHARS(UnicodeDevInstParams->DriverPath))
  64. );
  65. } except(pSetupExceptionFilter(GetExceptionCode())) {
  66. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  67. }
  68. return rc;
  69. }
  70. DWORD
  71. pSetupDiDevInstParamsUnicodeToAnsi(
  72. IN PSP_DEVINSTALL_PARAMS_W UnicodeDevInstParams,
  73. OUT PSP_DEVINSTALL_PARAMS_A AnsiDevInstParams
  74. )
  75. /*++
  76. Routine Description:
  77. This routine converts an SP_DEVINSTALL_PARAMS_W structure to
  78. an SP_DEVINSTALL_PARAMS_A, guarding against bogus pointers
  79. passed in the by the caller.
  80. Arguments:
  81. UnicodeDevInstParams - supplies Unicode device installation parameters
  82. to be converted to ANSI.
  83. AnsiDevInstParams - if successful, receives Ansi equivalent of
  84. UnicodeDevInstParams.
  85. Return Value:
  86. NO_ERROR - conversion successful.
  87. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  88. Unicode chars that can't be represented in the current system ANSI codepage
  89. will be replaced with a system default in the ANSI structure.
  90. --*/
  91. {
  92. DWORD rc;
  93. UCHAR AnsiString[MAX_PATH*2];
  94. HRESULT hr;
  95. MYASSERT(UnicodeDevInstParams->cbSize == sizeof(SP_DEVINSTALL_PARAMS_W));
  96. try {
  97. if(AnsiDevInstParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) {
  98. rc = ERROR_INVALID_USER_BUFFER;
  99. leave;
  100. }
  101. //
  102. // Fixed part of structure.
  103. //
  104. MYASSERT(offsetof(SP_DEVINSTALL_PARAMS_A,DriverPath) == offsetof(SP_DEVINSTALL_PARAMS_W,DriverPath));
  105. CopyMemory(AnsiDevInstParams,
  106. UnicodeDevInstParams,
  107. offsetof(SP_DEVINSTALL_PARAMS_W,DriverPath)
  108. );
  109. AnsiDevInstParams->cbSize = sizeof(SP_DEVINSTALL_PARAMS_A);
  110. //
  111. // Convert the single string in the structure. Unfortunately there is
  112. // potential for overflow because some Unicode chars could convert to
  113. // double-byte ANSI characters -- but the string in the ANSI structure
  114. // is only MAX_PATH *bytes* (not MAX_PATH double-byte *characters*)
  115. // long.
  116. //
  117. rc = GLE_FN_CALL(0,
  118. WideCharToMultiByte(
  119. CP_ACP,
  120. 0,
  121. UnicodeDevInstParams->DriverPath,
  122. SIZECHARS(UnicodeDevInstParams->DriverPath),
  123. AnsiString,
  124. sizeof(AnsiString),
  125. NULL,
  126. NULL)
  127. );
  128. if(rc != NO_ERROR) {
  129. leave;
  130. }
  131. //
  132. // Copy converted string into caller's structure, limiting
  133. // its length to avoid overflow.
  134. //
  135. hr = StringCchCopyA(AnsiDevInstParams->DriverPath,
  136. sizeof(AnsiDevInstParams->DriverPath),
  137. AnsiString
  138. );
  139. if(FAILED(hr)) {
  140. rc = HRESULT_CODE(hr);
  141. }
  142. } except(pSetupExceptionFilter(GetExceptionCode())) {
  143. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  144. }
  145. return rc;
  146. }
  147. DWORD
  148. pSetupDiSelDevParamsAnsiToUnicode(
  149. IN PSP_SELECTDEVICE_PARAMS_A AnsiSelDevParams,
  150. OUT PSP_SELECTDEVICE_PARAMS_W UnicodeSelDevParams
  151. )
  152. /*++
  153. Routine Description:
  154. This routine converts an SP_SELECTDEVICE_PARAMS_A structure to
  155. an SP_SELECTDEVICE_PARAMS_W, guarding against bogus pointers
  156. passed in the by the caller.
  157. Arguments:
  158. AnsiSelDevParams - supplies ANSI device selection parameters
  159. to be converted to unicode.
  160. UnicodeSelDevParams - if successful, receives Unicode equivalent of
  161. AnsiSelDevParams.
  162. Return Value:
  163. NO_ERROR - conversion successful.
  164. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  165. It is not believed that, given valid arguments, text conversion itself
  166. can fail, since all ANSI chars always have Unicode equivalents.
  167. --*/
  168. {
  169. DWORD rc;
  170. try {
  171. if(AnsiSelDevParams->ClassInstallHeader.cbSize != sizeof(SP_CLASSINSTALL_HEADER)) {
  172. rc = ERROR_INVALID_USER_BUFFER;
  173. leave;
  174. }
  175. //
  176. // Fixed part of structure.
  177. //
  178. MYASSERT(offsetof(SP_SELECTDEVICE_PARAMS_A,Title) == offsetof(SP_SELECTDEVICE_PARAMS_W,Title));
  179. CopyMemory(
  180. UnicodeSelDevParams,
  181. AnsiSelDevParams,
  182. offsetof(SP_SELECTDEVICE_PARAMS_W,Title)
  183. );
  184. //
  185. // Convert the strings in the structure. To make things easier
  186. // we'll just convert the entire buffers. There's no potential for
  187. // overflow.
  188. //
  189. rc = GLE_FN_CALL(0,
  190. MultiByteToWideChar(
  191. CP_ACP,
  192. MB_PRECOMPOSED,
  193. AnsiSelDevParams->Title,
  194. sizeof(AnsiSelDevParams->Title),
  195. UnicodeSelDevParams->Title,
  196. SIZECHARS(UnicodeSelDevParams->Title))
  197. );
  198. if(rc != NO_ERROR) {
  199. leave;
  200. }
  201. rc = GLE_FN_CALL(0,
  202. MultiByteToWideChar(
  203. CP_ACP,
  204. MB_PRECOMPOSED,
  205. AnsiSelDevParams->Instructions,
  206. sizeof(AnsiSelDevParams->Instructions),
  207. UnicodeSelDevParams->Instructions,
  208. SIZECHARS(UnicodeSelDevParams->Instructions))
  209. );
  210. if(rc != NO_ERROR) {
  211. leave;
  212. }
  213. rc = GLE_FN_CALL(0,
  214. MultiByteToWideChar(
  215. CP_ACP,
  216. MB_PRECOMPOSED,
  217. AnsiSelDevParams->ListLabel,
  218. sizeof(AnsiSelDevParams->ListLabel),
  219. UnicodeSelDevParams->ListLabel,
  220. SIZECHARS(UnicodeSelDevParams->ListLabel))
  221. );
  222. if(rc != NO_ERROR) {
  223. leave;
  224. }
  225. rc = GLE_FN_CALL(0,
  226. MultiByteToWideChar(
  227. CP_ACP,
  228. MB_PRECOMPOSED,
  229. AnsiSelDevParams->SubTitle,
  230. sizeof(AnsiSelDevParams->SubTitle),
  231. UnicodeSelDevParams->SubTitle,
  232. SIZECHARS(UnicodeSelDevParams->SubTitle))
  233. );
  234. } except(pSetupExceptionFilter(GetExceptionCode())) {
  235. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  236. }
  237. return rc;
  238. }
  239. DWORD
  240. pSetupDiSelDevParamsUnicodeToAnsi(
  241. IN PSP_SELECTDEVICE_PARAMS_W UnicodeSelDevParams,
  242. OUT PSP_SELECTDEVICE_PARAMS_A AnsiSelDevParams
  243. )
  244. /*++
  245. Routine Description:
  246. This routine converts an SP_SELECTDEVICE_PARAMS_W structure to
  247. an SP_SELECTDEVICE_PARAMS_A, guarding against bogus pointers
  248. passed in the by the caller. It is assumed that the ANSI output buffer is
  249. of sufficient size, and that its ClassInstallHeader.cbSize field is
  250. initialized correctly.
  251. Arguments:
  252. UnicodeSelDevParams - supplies Unicode device selection parameters
  253. to be converted to ANSI.
  254. AnsiSelDevParams - if successful, receives Ansi equivalent of
  255. UnicodeSelDevParams.
  256. Return Value:
  257. NO_ERROR - conversion successful.
  258. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  259. Unicode chars that can't be represented in the current system ANSI codepage
  260. will be replaced with a system default in the ANSI structure.
  261. --*/
  262. {
  263. DWORD rc;
  264. UCHAR AnsiTitle[MAX_TITLE_LEN*2];
  265. UCHAR AnsiInstructions[MAX_INSTRUCTION_LEN*2];
  266. UCHAR AnsiListLabel[MAX_LABEL_LEN*2];
  267. UCHAR AnsiSubTitle[MAX_SUBTITLE_LEN*2];
  268. HRESULT hr;
  269. MYASSERT(UnicodeSelDevParams->ClassInstallHeader.cbSize == sizeof(SP_CLASSINSTALL_HEADER));
  270. MYASSERT(AnsiSelDevParams->ClassInstallHeader.cbSize == sizeof(SP_CLASSINSTALL_HEADER));
  271. try {
  272. //
  273. // Fixed part of structure.
  274. //
  275. MYASSERT(offsetof(SP_SELECTDEVICE_PARAMS_A,Title) == offsetof(SP_SELECTDEVICE_PARAMS_W,Title));
  276. CopyMemory(
  277. AnsiSelDevParams,
  278. UnicodeSelDevParams,
  279. offsetof(SP_SELECTDEVICE_PARAMS_W,Title)
  280. );
  281. ZeroMemory(AnsiSelDevParams->Reserved,sizeof(AnsiSelDevParams->Reserved));
  282. //
  283. // Convert the strings in the structure. Unfortunately there is
  284. // potential for overflow because some Unicode chars could convert to
  285. // double-byte ANSI characters -- but the strings in the ANSI structure
  286. // are sized in *bytes* (not double-byte *characters*).
  287. //
  288. rc = GLE_FN_CALL(0,
  289. WideCharToMultiByte(
  290. CP_ACP,
  291. 0,
  292. UnicodeSelDevParams->Title,
  293. SIZECHARS(UnicodeSelDevParams->Title),
  294. AnsiTitle,
  295. sizeof(AnsiTitle),
  296. NULL,
  297. NULL)
  298. );
  299. if(rc != NO_ERROR) {
  300. leave;
  301. }
  302. rc = GLE_FN_CALL(0,
  303. WideCharToMultiByte(
  304. CP_ACP,
  305. 0,
  306. UnicodeSelDevParams->Instructions,
  307. SIZECHARS(UnicodeSelDevParams->Instructions),
  308. AnsiInstructions,
  309. sizeof(AnsiInstructions),
  310. NULL,
  311. NULL)
  312. );
  313. if(rc != NO_ERROR) {
  314. leave;
  315. }
  316. rc = GLE_FN_CALL(0,
  317. WideCharToMultiByte(
  318. CP_ACP,
  319. 0,
  320. UnicodeSelDevParams->ListLabel,
  321. SIZECHARS(UnicodeSelDevParams->ListLabel),
  322. AnsiListLabel,
  323. sizeof(AnsiListLabel),
  324. NULL,
  325. NULL)
  326. );
  327. if(rc != NO_ERROR) {
  328. leave;
  329. }
  330. rc = GLE_FN_CALL(0,
  331. WideCharToMultiByte(
  332. CP_ACP,
  333. 0,
  334. UnicodeSelDevParams->SubTitle,
  335. SIZECHARS(UnicodeSelDevParams->SubTitle),
  336. AnsiSubTitle,
  337. sizeof(AnsiSubTitle),
  338. NULL,
  339. NULL)
  340. );
  341. if(rc != NO_ERROR) {
  342. leave;
  343. }
  344. //
  345. // Copy converted strings into caller's structure, limiting lengths to
  346. // avoid overflow.
  347. //
  348. #undef CPYANS
  349. #define CPYANS(field) StringCchCopyA(AnsiSelDevParams->field, \
  350. sizeof(AnsiSelDevParams->field), \
  351. Ansi##field)
  352. if(FAILED(hr = CPYANS(Title)) ||
  353. FAILED(hr = CPYANS(Instructions)) ||
  354. FAILED(hr = CPYANS(ListLabel)) ||
  355. FAILED(hr = CPYANS(SubTitle))) {
  356. rc = HRESULT_CODE(hr);
  357. }
  358. } except(pSetupExceptionFilter(GetExceptionCode())) {
  359. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  360. }
  361. return rc;
  362. }
  363. DWORD
  364. pSetupDiDrvInfoDataAnsiToUnicode(
  365. IN PSP_DRVINFO_DATA_A AnsiDrvInfoData,
  366. OUT PSP_DRVINFO_DATA_W UnicodeDrvInfoData
  367. )
  368. /*++
  369. Routine Description:
  370. This routine converts an SP_DRVINFO_DATA_A structure to
  371. an SP_DRVINFO_DATA_W, guarding against bogus pointers
  372. passed in the by the caller.
  373. Arguments:
  374. AnsiDrvInfoData - supplies ANSI structure to be converted to unicode.
  375. UnicodeDrvInfoData - if successful, receives Unicode equivalent of
  376. AnsiDrvInfoData.
  377. Return Value:
  378. NO_ERROR - conversion successful.
  379. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  380. It is not believed that, given valid arguments, text conversion itself
  381. can fail, since all ANSI chars always have Unicode equivalents.
  382. --*/
  383. {
  384. DWORD rc;
  385. try {
  386. if((AnsiDrvInfoData->cbSize != sizeof(SP_DRVINFO_DATA_A)) &&
  387. (AnsiDrvInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A))) {
  388. rc = ERROR_INVALID_USER_BUFFER;
  389. leave;
  390. }
  391. //
  392. // Fixed part of structure.
  393. //
  394. MYASSERT(offsetof(SP_DRVINFO_DATA_A,Description) == offsetof(SP_DRVINFO_DATA_W,Description));
  395. ZeroMemory(UnicodeDrvInfoData, sizeof(SP_DRVINFO_DATA_W));
  396. CopyMemory(
  397. UnicodeDrvInfoData,
  398. AnsiDrvInfoData,
  399. offsetof(SP_DRVINFO_DATA_W,Description)
  400. );
  401. UnicodeDrvInfoData->cbSize = sizeof(SP_DRVINFO_DATA_W);
  402. //
  403. // Convert the strings in the structure. To make things easier we'll
  404. // just convert the entire buffers. There's no potential for overflow.
  405. //
  406. rc = GLE_FN_CALL(0,
  407. MultiByteToWideChar(
  408. CP_ACP,
  409. MB_PRECOMPOSED,
  410. AnsiDrvInfoData->Description,
  411. sizeof(AnsiDrvInfoData->Description),
  412. UnicodeDrvInfoData->Description,
  413. SIZECHARS(UnicodeDrvInfoData->Description))
  414. );
  415. if(rc != NO_ERROR) {
  416. leave;
  417. }
  418. rc = GLE_FN_CALL(0,
  419. MultiByteToWideChar(
  420. CP_ACP,
  421. MB_PRECOMPOSED,
  422. AnsiDrvInfoData->MfgName,
  423. sizeof(AnsiDrvInfoData->MfgName),
  424. UnicodeDrvInfoData->MfgName,
  425. SIZECHARS(UnicodeDrvInfoData->MfgName))
  426. );
  427. if(rc != NO_ERROR) {
  428. leave;
  429. }
  430. rc = GLE_FN_CALL(0,
  431. MultiByteToWideChar(
  432. CP_ACP,
  433. MB_PRECOMPOSED,
  434. AnsiDrvInfoData->ProviderName,
  435. sizeof(AnsiDrvInfoData->ProviderName),
  436. UnicodeDrvInfoData->ProviderName,
  437. SIZECHARS(UnicodeDrvInfoData->ProviderName))
  438. );
  439. if(rc != NO_ERROR) {
  440. leave;
  441. }
  442. //
  443. // Successfully converted all strings to unicode. Set the final two
  444. // fields (DriverDate and DriverVersion) unless the caller supplied us
  445. // with a version 1 structure.
  446. //
  447. if(AnsiDrvInfoData->cbSize == sizeof(SP_DRVINFO_DATA_A)) {
  448. UnicodeDrvInfoData->DriverDate = AnsiDrvInfoData->DriverDate;
  449. UnicodeDrvInfoData->DriverVersion = AnsiDrvInfoData->DriverVersion;
  450. }
  451. } except(pSetupExceptionFilter(GetExceptionCode())) {
  452. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  453. }
  454. return rc;
  455. }
  456. DWORD
  457. pSetupDiDrvInfoDataUnicodeToAnsi(
  458. IN PSP_DRVINFO_DATA_W UnicodeDrvInfoData,
  459. OUT PSP_DRVINFO_DATA_A AnsiDrvInfoData
  460. )
  461. /*++
  462. Routine Description:
  463. This routine converts an SP_DRVINFO_DATA_W structure to
  464. an SP_DRVINFO_DATA_A, guarding against bogus pointers
  465. passed in the by the caller.
  466. Arguments:
  467. UnicodeDrvInfoData - supplies Unicode structure to be converted
  468. to ANSI.
  469. AnsiDrvInfoData - if successful, receives Ansi equivalent of
  470. UnicodeDrvInfoData.
  471. Return Value:
  472. NO_ERROR - conversion successful.
  473. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  474. Unicode chars that can't be represented in the current system ANSI codepage
  475. will be replaced with a system default in the ANSI structure.
  476. --*/
  477. {
  478. DWORD rc;
  479. UCHAR AnsiDescription[LINE_LEN*2];
  480. UCHAR AnsiMfgName[LINE_LEN*2];
  481. UCHAR AnsiProviderName[LINE_LEN*2];
  482. HRESULT hr;
  483. MYASSERT(UnicodeDrvInfoData->cbSize == sizeof(SP_DRVINFO_DATA_W));
  484. try {
  485. if((AnsiDrvInfoData->cbSize != sizeof(SP_DRVINFO_DATA_A)) &&
  486. (AnsiDrvInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A))) {
  487. rc = ERROR_INVALID_USER_BUFFER;
  488. leave;
  489. }
  490. //
  491. // Copy over the DriverType and the Reserved field.
  492. //
  493. AnsiDrvInfoData->DriverType = UnicodeDrvInfoData->DriverType;
  494. AnsiDrvInfoData->Reserved = UnicodeDrvInfoData->Reserved;
  495. //
  496. // Convert the strings in the structure. Unfortunately there is
  497. // potential for overflow because some Unicode chars could convert
  498. // to double-byte ANSI characters -- but the strings in the ANSI
  499. // structure are sized in *bytes* (not double-byte *characters*).
  500. //
  501. rc = GLE_FN_CALL(0,
  502. WideCharToMultiByte(
  503. CP_ACP,
  504. 0,
  505. UnicodeDrvInfoData->Description,
  506. SIZECHARS(UnicodeDrvInfoData->Description),
  507. AnsiDescription,
  508. sizeof(AnsiDescription),
  509. NULL,
  510. NULL)
  511. );
  512. if(rc != NO_ERROR) {
  513. leave;
  514. }
  515. rc = GLE_FN_CALL(0,
  516. WideCharToMultiByte(
  517. CP_ACP,
  518. 0,
  519. UnicodeDrvInfoData->MfgName,
  520. SIZECHARS(UnicodeDrvInfoData->MfgName),
  521. AnsiMfgName,
  522. sizeof(AnsiMfgName),
  523. NULL,
  524. NULL)
  525. );
  526. if(rc != NO_ERROR) {
  527. leave;
  528. }
  529. rc = GLE_FN_CALL(0,
  530. WideCharToMultiByte(
  531. CP_ACP,
  532. 0,
  533. UnicodeDrvInfoData->ProviderName,
  534. SIZECHARS(UnicodeDrvInfoData->ProviderName),
  535. AnsiProviderName,
  536. sizeof(AnsiProviderName),
  537. NULL,
  538. NULL)
  539. );
  540. if(rc != NO_ERROR) {
  541. leave;
  542. }
  543. //
  544. // Copy converted strings into caller's structure, limiting lengths to
  545. // avoid overflow.
  546. //
  547. #undef CPYANS
  548. #define CPYANS(field) StringCchCopyA(AnsiDrvInfoData->field, \
  549. sizeof(AnsiDrvInfoData->field), \
  550. Ansi##field)
  551. if(FAILED(hr = CPYANS(Description)) ||
  552. FAILED(hr = CPYANS(MfgName)) ||
  553. FAILED(hr = CPYANS(ProviderName))) {
  554. rc = HRESULT_CODE(hr);
  555. leave;
  556. }
  557. //
  558. // Successfully converted/transferred all the unicode strings back to
  559. // ANSI. Now, set the final two fields (DriverDate and DriverVersion)
  560. // unless the caller supplied us with a version 1 structure.
  561. //
  562. if(AnsiDrvInfoData->cbSize == sizeof(SP_DRVINFO_DATA_A)) {
  563. AnsiDrvInfoData->DriverDate = UnicodeDrvInfoData->DriverDate;
  564. AnsiDrvInfoData->DriverVersion = UnicodeDrvInfoData->DriverVersion;
  565. }
  566. } except(pSetupExceptionFilter(GetExceptionCode())) {
  567. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  568. }
  569. return rc;
  570. }
  571. DWORD
  572. pSetupDiDevInfoSetDetailDataUnicodeToAnsi(
  573. IN PSP_DEVINFO_LIST_DETAIL_DATA_W UnicodeDevInfoSetDetails,
  574. OUT PSP_DEVINFO_LIST_DETAIL_DATA_A AnsiDevInfoSetDetails
  575. )
  576. /*++
  577. Routine Description:
  578. This routine converts an SP_DEVINFO_LIST_DETAIL_DATA_W structure
  579. to an SP_DEVINFO_LIST_DETAIL_DATA_A, guarding against bogus pointers
  580. passed in the by the caller.
  581. Arguments:
  582. UnicodeDevInfoSetDetails - supplies Unicode structure to be converted
  583. to ANSI.
  584. AnsiDevInfoSetDetails - if successful, receives Ansi equivalent of
  585. UnicodeDevInfoSetDetails.
  586. Return Value:
  587. NO_ERROR - conversion successful.
  588. ERROR_INVALID_PARAMETER - one of the arguments was not a valid pointer.
  589. Unicode chars that can't be represented in the current system ANSI codepage
  590. will be replaced with a system default in the ANSI structure.
  591. --*/
  592. {
  593. DWORD rc;
  594. UCHAR AnsiRemoteMachineName[SP_MAX_MACHINENAME_LENGTH * 2];
  595. HRESULT hr;
  596. MYASSERT(UnicodeDevInfoSetDetails->cbSize == sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W));
  597. rc = NO_ERROR;
  598. try {
  599. if(AnsiDevInfoSetDetails->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A)) {
  600. rc = ERROR_INVALID_USER_BUFFER;
  601. leave;
  602. }
  603. //
  604. // Fixed part of structure.
  605. //
  606. MYASSERT(offsetof(SP_DEVINFO_LIST_DETAIL_DATA_A, RemoteMachineName) ==
  607. offsetof(SP_DEVINFO_LIST_DETAIL_DATA_W, RemoteMachineName)
  608. );
  609. CopyMemory(AnsiDevInfoSetDetails,
  610. UnicodeDevInfoSetDetails,
  611. offsetof(SP_DEVINFO_LIST_DETAIL_DATA_W, RemoteMachineName)
  612. );
  613. AnsiDevInfoSetDetails->cbSize = sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A);
  614. //
  615. // Convert the strings in the structure. Unfortunately there is
  616. // potential for overflow because some Unicode chars could convert to
  617. // double-byte ANSI characters -- but the strings in the ANSI structure
  618. // are sized in *bytes* (not double-byte *characters*).
  619. //
  620. rc = GLE_FN_CALL(0,
  621. WideCharToMultiByte(
  622. CP_ACP,
  623. 0,
  624. UnicodeDevInfoSetDetails->RemoteMachineName,
  625. SIZECHARS(UnicodeDevInfoSetDetails->RemoteMachineName),
  626. AnsiRemoteMachineName,
  627. sizeof(AnsiRemoteMachineName),
  628. NULL,
  629. NULL)
  630. );
  631. if(rc != NO_ERROR) {
  632. leave;
  633. }
  634. //
  635. // Copy converted string into caller's structure, limiting lengths to
  636. // avoid overflow.
  637. //
  638. hr = StringCchCopyA(AnsiDevInfoSetDetails->RemoteMachineName,
  639. sizeof(AnsiDevInfoSetDetails->RemoteMachineName),
  640. AnsiRemoteMachineName
  641. );
  642. if(FAILED(hr)) {
  643. rc = HRESULT_CODE(hr);
  644. }
  645. } except(pSetupExceptionFilter(GetExceptionCode())) {
  646. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  647. }
  648. return rc;
  649. }