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.

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