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.

1099 lines
28 KiB

  1. // Copyright (c) 1997-2002 Microsoft Corporation
  2. //
  3. // Module:
  4. //
  5. // Network Security Utilities
  6. // nsustring.c
  7. //
  8. // Abstract:
  9. //
  10. // Wrappers for strsafe.h and safe string functions
  11. //
  12. // Author:
  13. //
  14. // RaymondS 1 February-2002
  15. //
  16. // Environment:
  17. //
  18. // User mode
  19. //
  20. // Revision History:
  21. #include <precomp.h>
  22. #include "NsuString.h"
  23. #include "strsafe.h"
  24. // Description:
  25. //
  26. // Copies not more than cchDest characters from pszSrc to pszDest, including the null
  27. // terminator. If the length of pszSrc is more than cchDest, ERROR_INSUFFICIENT_BUFFER
  28. // is returned but cchDest characters from pszSrc are still copied to pszDest.
  29. // Always null terminates pszDest.
  30. //
  31. // Arguments:
  32. //
  33. // pszDest - destination string.
  34. // cchDest - maximum number of characters to copy including null character.
  35. // pszSrc - souce string.
  36. //
  37. // Return Value:
  38. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid. pszDest unchanged.
  39. // ERROR_INSUFFICIENT_BUFFER - if length of pszSrc is greater than cchDest.
  40. // ERROR_SUCCESS
  41. // Other WIN32 errors possible.
  42. //
  43. DWORD
  44. NsuStringCopyW(
  45. OUT LPWSTR pszDest,
  46. IN size_t cchDest,
  47. IN LPCWSTR pszSrc
  48. )
  49. {
  50. HRESULT hr = S_OK;
  51. hr = StringCchCopyW(
  52. pszDest,
  53. cchDest,
  54. pszSrc
  55. );
  56. return HRESULT_CODE(hr);
  57. }
  58. // Description:
  59. //
  60. // See NsuStringCopyW.
  61. //
  62. DWORD
  63. NsuStringCopyA(
  64. OUT LPSTR pszDest,
  65. IN size_t cchDest,
  66. IN LPCSTR pszSrc
  67. )
  68. {
  69. HRESULT hr = S_OK;
  70. hr = StringCchCopyA(
  71. pszDest,
  72. cchDest,
  73. pszSrc
  74. );
  75. return HRESULT_CODE(hr);
  76. }
  77. // Description:
  78. //
  79. // Converts pszSrc from MBCS to an Unicode string and pass the result back in *ppszDest.
  80. // *ppszDest is allocated enough space to store the output string.
  81. // Always null terminates *ppszDest.
  82. // Use NsuFree to free the allocate string.
  83. //
  84. // Arguments:
  85. //
  86. // ppszDest - pointer to output string that is returned.
  87. // cchLimit - specifies the maximum size of the output string to allocate including
  88. // the NULL character.
  89. // Pass 0 if no maximum should be enforced. if cchLimit is
  90. // less than the required output string buffer, only cchLimit characters
  91. // are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
  92. //
  93. // Return Value:
  94. //
  95. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
  96. // ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string lenghth.
  97. // ERROR_SUCCESS
  98. // Other WIN32 errors
  99. //
  100. DWORD
  101. NsuStringCopyAtoWAlloc(
  102. OUT LPWSTR* ppszDest,
  103. IN size_t cchLimit,
  104. IN LPCSTR pszSrc
  105. )
  106. {
  107. DWORD dwError = ERROR_SUCCESS;
  108. LPWSTR lpWideCharStr = NULL;
  109. int cchWideChar = 0;
  110. cchWideChar = MultiByteToWideChar(
  111. CP_ACP, // ANSI Code page
  112. 0, // No special options
  113. pszSrc, // string to map
  114. -1, // Assume string is null terminated.
  115. NULL, // wide-character buffer
  116. 0 // size of buffer
  117. );
  118. if (cchWideChar <= 0) {
  119. dwError = GetLastError();
  120. NSU_BAIL_ON_ERROR(dwError);
  121. } else if (cchLimit && (size_t) cchWideChar > cchLimit) {
  122. cchWideChar = cchLimit;
  123. }
  124. lpWideCharStr = NsuAlloc(
  125. cchWideChar * sizeof(WCHAR),
  126. 0
  127. );
  128. NSU_BAIL_ON_NULL(lpWideCharStr, dwError);
  129. cchWideChar = MultiByteToWideChar(
  130. CP_ACP, // ANSI Code page
  131. 0, // No special options
  132. pszSrc, // string to map
  133. -1, // Assume string is null terminated.
  134. lpWideCharStr, // wide-character buffer
  135. cchWideChar // size of buffer
  136. );
  137. if (cchWideChar == 0) {
  138. dwError = GetLastError();
  139. // If ERROR_INSUFFICIENT_BUFFER user set limit
  140. // so just null terminate.
  141. if (dwError == ERROR_INSUFFICIENT_BUFFER && cchWideChar) {
  142. lpWideCharStr[cchLimit-1] = L'\0';
  143. } else {
  144. NSU_BAIL_ON_ERROR(dwError);
  145. }
  146. }
  147. *ppszDest = lpWideCharStr;
  148. return dwError;
  149. NSU_CLEANUP:
  150. if (lpWideCharStr) {
  151. // Don't want to overwrite dwError so ignore NsuFree errors
  152. //
  153. (VOID) NsuFree0(&lpWideCharStr);
  154. }
  155. *ppszDest = NULL;
  156. return dwError;
  157. }
  158. // Description:
  159. //
  160. // Converts pszSrc from Unicode string to an MBCS and passes the result in *ppszDest.
  161. // *ppszDest is allocated enough space to store the output string.
  162. // Always null terminates *ppszDest.
  163. // Use NsuFree to free the allocate string.
  164. //
  165. // Arguments:
  166. //
  167. // ppszDest - pointer to output string that is returned.
  168. // cbLimit - specifies the maximum size of the output string to allocate including
  169. // the NULL character.
  170. // Pass 0 if no maximum should be enforced. if cbLimit is
  171. // less than the required output string buffer, only cbLimit bytes
  172. // are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
  173. //
  174. // Return Value:
  175. //
  176. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid. *ppszDest set to NULL.
  177. // ERROR_INSUFFICIENT_BUFFER - cbLimit is less than required output string length.
  178. // ERROR_SUCCESS
  179. // Other WIN32 errors possible. *ppszDest set to NULL.
  180. //
  181. DWORD
  182. NsuStringCopyWtoAAlloc(
  183. OUT LPSTR* ppszDest,
  184. IN size_t cbLimit,
  185. IN LPCWSTR pszSrc
  186. )
  187. {
  188. DWORD dwError = ERROR_SUCCESS;
  189. int cbMultiByte = 0;
  190. LPSTR lpMultiByteStr = NULL;
  191. cbMultiByte = WideCharToMultiByte(
  192. CP_ACP, // code page
  193. 0, // performance and mapping flags
  194. pszSrc, // string to map
  195. -1, // assume null termination
  196. NULL, // buffer for new string
  197. 0, // find out size of buffer
  198. NULL, // default for unmappable chars
  199. NULL // set when default char used
  200. );
  201. if (cbMultiByte <= 0) {
  202. dwError = GetLastError();
  203. NSU_BAIL_ON_ERROR(dwError);
  204. } else if (cbLimit && (size_t) cbMultiByte > cbLimit) {
  205. cbMultiByte = cbLimit;
  206. }
  207. lpMultiByteStr = NsuAlloc(
  208. cbMultiByte,
  209. 0
  210. );
  211. NSU_BAIL_ON_NULL(lpMultiByteStr, dwError);
  212. cbMultiByte = WideCharToMultiByte(
  213. CP_ACP, // code page
  214. 0, // performance and mapping flags
  215. pszSrc, // string to map
  216. -1, // assume null termination
  217. lpMultiByteStr, // buffer for new string
  218. cbMultiByte, // size of buffer
  219. NULL, // default for unmappable chars
  220. NULL // set when default char used
  221. );
  222. if (cbMultiByte == 0) {
  223. dwError = GetLastError();
  224. // If ERROR_INSUFFICIENT_BUFFER user set limit
  225. // so just null terminate.
  226. if (dwError == ERROR_INSUFFICIENT_BUFFER && cbLimit) {
  227. lpMultiByteStr[cbLimit-1] = '\0';
  228. } else {
  229. NSU_BAIL_ON_ERROR(dwError);
  230. }
  231. }
  232. *ppszDest = lpMultiByteStr;
  233. return dwError;
  234. NSU_CLEANUP:
  235. if (lpMultiByteStr) {
  236. // Don't want to overwrite dwError so ignore NsuFree errors
  237. //
  238. (VOID) NsuFree0(&lpMultiByteStr);
  239. }
  240. *ppszDest = NULL;
  241. return dwError;
  242. }
  243. // Description:
  244. //
  245. // Converts pszSrc from MBCS to an Unicode string and pass the result back in pszDest.
  246. // Always null terminates pszDest.
  247. // Use NsuFree to free the allocated string.
  248. //
  249. // Arguments:
  250. //
  251. // ppszDest - pointer to output string that is returned.
  252. // cchDest - maximum number of characters to place in pszDest including null character.
  253. // If cchDest is less than the required output string buffer, only cchDest bytes
  254. // are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
  255. // pszSrc � source string.
  256. //
  257. // Return Value:
  258. //
  259. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
  260. // ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string lenghth.
  261. // ERROR_SUCCESS
  262. // Other WIN32 errors
  263. //
  264. DWORD
  265. NsuStringCopyAtoW(
  266. OUT LPWSTR pszDest,
  267. IN size_t cchDest,
  268. IN LPCSTR pszSrc
  269. )
  270. {
  271. DWORD dwError = ERROR_SUCCESS;
  272. int cchWideChar = 0;
  273. cchWideChar = MultiByteToWideChar(
  274. CP_ACP, // ANSI Code page
  275. 0, // No special options
  276. pszSrc, // string to map
  277. -1, // Assume string is null terminated.
  278. pszDest, // wide-character buffer
  279. cchDest // size of buffer
  280. );
  281. if (cchWideChar == 0) {
  282. dwError = GetLastError();
  283. // If ERROR_INSUFFICIENT_BUFFER just null terminate.
  284. if (dwError == ERROR_INSUFFICIENT_BUFFER && cchDest) {
  285. pszDest[cchDest-1] = L'\0';
  286. }
  287. }
  288. return dwError;
  289. }
  290. // Description:
  291. //
  292. // Converts pszSrc from Unicode string to an MBCS and puts the result in pszDest.
  293. // Always null terminates pszDest.
  294. //
  295. // Arguments:
  296. //
  297. //
  298. // pszDest - destination string.
  299. // cchDest - maximum number of characters to place in pszDest including null character.
  300. // If cchDest is less than the required output string buffer, only cchDest bytes
  301. // are converted, and ERROR_INSUFFICIENT_BUFFER is returned.
  302. // pszSrc � source string.
  303. //
  304. // Return Value:
  305. //
  306. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid. *ppszDest set to NULL.
  307. // ERROR_INSUFFICIENT_BUFFER - cchDest is less than required output string length.
  308. // ERROR_SUCCESS
  309. // Other WIN32 errors possible.
  310. //
  311. DWORD
  312. NsuStringCopyWtoA(
  313. OUT LPSTR pszDest,
  314. IN size_t cbDest,
  315. IN LPCWSTR pszSrc
  316. )
  317. {
  318. DWORD dwError = ERROR_SUCCESS;
  319. int cbMultiByte = 0;
  320. cbMultiByte = WideCharToMultiByte(
  321. CP_ACP, // code page
  322. 0, // performance and mapping flags
  323. pszSrc, // string to map
  324. -1, // assume null termination
  325. pszDest, // buffer for new string
  326. cbDest, // size of buffer
  327. NULL, // default for unmappable chars
  328. NULL // set when default char used
  329. );
  330. if (cbMultiByte == 0) {
  331. dwError = GetLastError();
  332. // If ERROR_INSUFFICIENT_BUFFER just null terminate.
  333. if (dwError == ERROR_INSUFFICIENT_BUFFER && cbDest) {
  334. pszDest[cbDest-1] = '\0';
  335. }
  336. }
  337. return dwError;
  338. }
  339. // Description:
  340. //
  341. // Makes a duplicate deep memory copy of pszSrc and returns the result in *ppszDest.
  342. // *ppszDest is allocated enough space to store the output string.
  343. // Always null terminates *ppszDest.
  344. // Use NsuFree to free the allocate string.
  345. //
  346. // Arguments:
  347. //
  348. // ppszDest - pointer to output string that is returned.
  349. // cchLimit - specifies the maximum size of the output string to allocate including
  350. // the NULL character.
  351. // Pass 0 if no maximum should be enforced. if cchLimit is
  352. // less than the required output string buffer, only cchLimit characters
  353. // are duplicated, and ERROR_INSUFFICIENT_BUFFER is returned.
  354. //
  355. // Return Value:
  356. //
  357. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid. pszDest unchanged.
  358. // ERROR_INSUFFICIENT_BUFFER - cchLimit is less than required output string length.
  359. // ERROR_SUCCESS
  360. // Other WIN32 errors possible.
  361. //
  362. DWORD
  363. NsuStringDupW(
  364. OUT LPWSTR* ppszDest,
  365. IN size_t cchLimit,
  366. IN LPCWSTR pszSrc
  367. )
  368. {
  369. DWORD dwError = ERROR_SUCCESS;
  370. size_t cchToCopy = 0;
  371. LPWSTR pszDest = NULL;
  372. dwError = NsuStringLenW(
  373. pszSrc,
  374. &cchToCopy
  375. );
  376. NSU_BAIL_ON_ERROR(dwError);
  377. cchToCopy++;
  378. if (cchLimit && cchToCopy >= cchLimit) {
  379. cchToCopy = cchLimit;
  380. }
  381. pszDest = NsuAlloc(
  382. cchToCopy * sizeof(WCHAR),
  383. 0
  384. );
  385. NSU_BAIL_ON_NULL(pszDest, dwError);
  386. dwError = NsuStringCopyW(
  387. pszDest,
  388. cchToCopy,
  389. pszSrc
  390. );
  391. // ERROR_INSUFFICIENT_BUFFER is expected if user
  392. // set a limit on the length of duplicate.
  393. //
  394. if (dwError != ERROR_INSUFFICIENT_BUFFER) {
  395. NSU_BAIL_ON_ERROR(dwError);
  396. }
  397. *ppszDest = pszDest;
  398. return dwError;
  399. NSU_CLEANUP:
  400. if (pszDest) {
  401. // Don't want to overwrite dwError so ignore NsuFree errors
  402. //
  403. (VOID) NsuFree0(
  404. &pszDest
  405. );
  406. }
  407. *ppszDest = NULL;
  408. return dwError;
  409. }
  410. // Description:
  411. //
  412. // See NsuStringDupW
  413. //
  414. DWORD
  415. WINAPI
  416. NsuStringDupA(
  417. OUT LPSTR* ppszDest,
  418. IN size_t cchLimit,
  419. IN LPCSTR pszSrc
  420. )
  421. {
  422. DWORD dwError = ERROR_SUCCESS;
  423. size_t cchToCopy = 0;
  424. LPSTR pszDest = NULL;
  425. dwError = NsuStringLenA(
  426. pszSrc,
  427. &cchToCopy
  428. );
  429. NSU_BAIL_ON_ERROR(dwError);
  430. cchToCopy++;
  431. if (cchLimit && cchToCopy >= cchLimit) {
  432. cchToCopy = cchLimit;
  433. }
  434. pszDest = NsuAlloc(
  435. cchToCopy,
  436. 0
  437. );
  438. NSU_BAIL_ON_NULL(pszDest, dwError);
  439. dwError = NsuStringCopyA(
  440. pszDest,
  441. cchToCopy,
  442. pszSrc
  443. );
  444. // ERROR_INSUFFICIENT_BUFFER is expected if user
  445. // set a limit on the length of duplicate.
  446. //
  447. if (dwError != ERROR_INSUFFICIENT_BUFFER) {
  448. NSU_BAIL_ON_ERROR(dwError);
  449. }
  450. *ppszDest = pszDest;
  451. return dwError;
  452. NSU_CLEANUP:
  453. if (pszDest) {
  454. // Ignoring errors from NsuFree because want to return
  455. // original cause of bailing out.
  456. //
  457. (VOID) NsuFree0(
  458. &pszDest
  459. );
  460. }
  461. *ppszDest = NULL;
  462. return dwError;
  463. }
  464. // Description:
  465. //
  466. // Concatenates characters from pszSrc to pszDest and makes sure that the
  467. // the resulting is not longer than cchDest characters, including
  468. // the NULL character.
  469. // If not enough space was available in pszDest to concatanenate the whole of pszSrc,
  470. // ERROR_INSUFFICIENT_BUFFER is returned but as much as the space that was available in pszDest
  471. // is filled with characters from pszSrc.
  472. // Always null terminates pszDest.
  473. //
  474. // Arguments:
  475. //
  476. // pszDest - destination string.
  477. // cchDest - maximum number length allowed for resulting string including null character.
  478. // pszSrc - souce string.
  479. //
  480. // Return Value:
  481. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
  482. // ERROR_INSUFFICIENT_BUFFER - if not enough space in pszDest to cat the whole of pszSrc.
  483. // ERROR_SUCCESS
  484. // Other WIN32 errors possible.
  485. //
  486. DWORD
  487. NsuStringCatW(
  488. OUT LPWSTR pszDest,
  489. IN size_t cchDest,
  490. IN LPCWSTR pszSrc
  491. )
  492. {
  493. HRESULT hr = S_OK;
  494. hr = StringCchCatW(
  495. pszDest,
  496. cchDest,
  497. pszSrc
  498. );
  499. return HRESULT_CODE(hr);
  500. }
  501. // Description:
  502. //
  503. // See NsuStringCatW
  504. //
  505. DWORD
  506. NsuStringCatA(
  507. OUT LPSTR pszDest,
  508. IN size_t cchDest,
  509. IN LPCSTR pszSrc
  510. )
  511. {
  512. HRESULT hr = S_OK;
  513. hr = StringCchCatA(
  514. pszDest,
  515. cchDest,
  516. pszSrc
  517. );
  518. return HRESULT_CODE(hr);
  519. }
  520. // Description:
  521. //
  522. // Safe version of sprintf. Formats and writes a string to pszDest
  523. // sure that the result is not longer than cchDest characters, including
  524. // the NULL character.
  525. // If more space is required than cchDest characteters, ERROR_INSUFFICIENT_BUFFER
  526. // is returned but cchDest characters are always written to pszDest.
  527. // Always null terminates pszDest.
  528. //
  529. // Arguments:
  530. //
  531. // pszDest - destination string.
  532. // cchDest - maximum number length allowed for resulting string including null character.
  533. // pszFormat - printf-style format string.
  534. // Optional arguments to format and write to pszDest.
  535. //
  536. // Return Value:
  537. // ERROR_INVALID_PARAMETER - if one of the parameters is invalid.
  538. // ERROR_INSUFFICIENT_BUFFER - if length of the is greater than cchDest.
  539. // ERROR_SUCCESS
  540. // Other WIN32 errors possible.
  541. //
  542. DWORD
  543. NsuStringSprintW(
  544. OUT LPWSTR pszDest,
  545. IN size_t cchDest,
  546. IN LPCWSTR pszFormat,
  547. ...
  548. )
  549. {
  550. HRESULT hr = S_OK;
  551. va_list pArguments = NULL;
  552. va_start(pArguments, pszFormat);
  553. hr = StringCchVPrintfW(
  554. pszDest,
  555. cchDest,
  556. pszFormat,
  557. pArguments
  558. );
  559. va_end(pArguments);
  560. return HRESULT_CODE(hr);
  561. }
  562. // Description:
  563. //
  564. // See NsuStringPrintA
  565. //
  566. DWORD
  567. NsuStringSprintA(
  568. OUT LPSTR pszDest,
  569. IN size_t cchDest,
  570. IN LPCSTR pszFormat,
  571. ...
  572. )
  573. {
  574. HRESULT hr = S_OK;
  575. va_list pArguments = NULL;
  576. va_start(pArguments, pszFormat);
  577. hr = StringCchVPrintfA(
  578. pszDest,
  579. cchDest,
  580. pszFormat,
  581. pArguments
  582. );
  583. va_end(pArguments);
  584. return HRESULT_CODE(hr);
  585. }
  586. // Description:
  587. //
  588. // Fail Safe version of NsuStringSprint. Formats and writes a string to pszDest
  589. // sure that the result is not longer than cchDest characters, including
  590. // the NULL character.
  591. // If more space is required than cchDest characteters, no error
  592. // is returned but cchDest characters are always written to pszDest.
  593. // Always null terminates pszDest.
  594. // This function differs from the normal NsuStringSprint in that it does not return an error code,
  595. // and if the function fails for some reason, pszDest will be set to an empty string.
  596. //
  597. // Arguments:
  598. //
  599. // pszDest - destination string.
  600. // cchDest - maximum number length allowed for resulting string including null character.
  601. // pszFormat - printf-style format string.
  602. // Optional arguments to format and write to pszDest.
  603. //
  604. // Return Value:
  605. // None
  606. VOID
  607. NsuStringSprintFailSafeW(
  608. OUT LPWSTR pszDest,
  609. IN size_t cchDest,
  610. IN LPCWSTR pszFormat,
  611. ...
  612. )
  613. {
  614. HRESULT hr = S_OK;
  615. va_list pArguments = NULL;
  616. va_start(pArguments, pszFormat);
  617. if (cchDest) {
  618. hr = StringCchVPrintfW(
  619. pszDest,
  620. cchDest,
  621. pszFormat,
  622. pArguments
  623. );
  624. } else {
  625. hr = STRSAFE_E_INVALID_PARAMETER;
  626. NSU_BAIL_OUT;
  627. }
  628. va_end(pArguments);
  629. if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) {
  630. NSU_BAIL_OUT;
  631. }
  632. return;
  633. NSU_CLEANUP:
  634. if (cchDest) {
  635. pszDest[0] = L'\0';
  636. }
  637. return;
  638. }
  639. // Description:
  640. //
  641. // See NsuStringPrintFailSafeA
  642. //
  643. VOID
  644. NsuStringSprintFailSafeA(
  645. OUT LPSTR pszDest,
  646. IN size_t cchDest,
  647. IN LPCSTR pszFormat,
  648. ...
  649. )
  650. {
  651. HRESULT hr = S_OK;
  652. va_list pArguments = NULL;
  653. va_start(pArguments, pszFormat);
  654. if (cchDest) {
  655. hr = StringCchVPrintfA(
  656. pszDest,
  657. cchDest,
  658. pszFormat,
  659. pArguments
  660. );
  661. } else {
  662. hr = STRSAFE_E_INVALID_PARAMETER;
  663. NSU_BAIL_OUT;
  664. }
  665. va_end(pArguments);
  666. if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) {
  667. NSU_BAIL_OUT;
  668. }
  669. return;
  670. NSU_CLEANUP:
  671. if (cchDest) {
  672. pszDest[0] = '\0';
  673. }
  674. return;
  675. }
  676. // Description:
  677. //
  678. // Fail Safe version of NsuStringSprint that accepts a va_list of arguments.
  679. // Formats and writes a string to pszDest sure that the result is not longer
  680. // than cchDest characters, including the NULL character.
  681. // If more space is required than cchDest characteters, no error
  682. // is returned but cchDest characters are always written to pszDest.
  683. // Always null terminates pszDest.
  684. //
  685. // Arguments:
  686. //
  687. // pszDest - destination string.
  688. // cchDest - maximum number length allowed for resulting string including null character.
  689. // pszFormat - printf-style format string.
  690. // vaArguments - Arguments to format and write to pszDest.
  691. //
  692. // Return Value:
  693. // None
  694. //
  695. VOID
  696. NsuStringVSprintFailSafeW(
  697. OUT LPWSTR pszDest,
  698. IN size_t cchDest,
  699. IN LPCWSTR pszFormat,
  700. IN va_list vaArguments
  701. )
  702. {
  703. HRESULT hr = S_OK;
  704. if (cchDest) {
  705. hr = StringCchVPrintfW(
  706. pszDest,
  707. cchDest,
  708. pszFormat,
  709. vaArguments
  710. );
  711. } else {
  712. hr = STRSAFE_E_INVALID_PARAMETER;
  713. NSU_BAIL_OUT;
  714. }
  715. if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) {
  716. NSU_BAIL_OUT;
  717. }
  718. return;
  719. NSU_CLEANUP:
  720. if (cchDest) {
  721. pszDest[0] = L'\0';
  722. }
  723. return;
  724. }
  725. // Description:
  726. //
  727. // See NsuStringVPrintFailSafeW
  728. //
  729. VOID
  730. NsuStringVSprintFailSafeA(
  731. OUT LPSTR pszDest,
  732. IN size_t cchDest,
  733. IN LPCSTR pszFormat,
  734. IN va_list vaArguments
  735. )
  736. {
  737. HRESULT hr = S_OK;
  738. if (cchDest) {
  739. hr = StringCchVPrintfA(
  740. pszDest,
  741. cchDest,
  742. pszFormat,
  743. vaArguments
  744. );
  745. } else {
  746. hr = STRSAFE_E_INVALID_PARAMETER;
  747. NSU_BAIL_OUT;
  748. }
  749. if (hr != STRSAFE_E_INSUFFICIENT_BUFFER && FAILED(hr)) {
  750. NSU_BAIL_OUT;
  751. }
  752. return;
  753. NSU_CLEANUP:
  754. if (cchDest) {
  755. pszDest[0] = '\0';
  756. }
  757. return;
  758. }
  759. // Description:
  760. //
  761. // Safe version of strlen, that will not Access Violate if
  762. // passed a bad pointer or a non-null terminated string.
  763. // A non-null terminated string is detected by making
  764. // sure we do not read past the string into memory we do not own.
  765. //
  766. //
  767. // Arguments:
  768. //
  769. // pszStr - Input string.
  770. // pcchStrLen - pointer to variable in which to return string length.
  771. //
  772. // Return Value:
  773. // ERROR_INVALID_PARAMETER - if pszStr points to an invalid string.
  774. // ERROR_SUCCESS
  775. //
  776. DWORD
  777. NsuStringLenW(
  778. IN LPCWSTR pszStr,
  779. OUT size_t* pcchStrLen
  780. )
  781. {
  782. BOOL fBadStr = TRUE;
  783. DWORD dwError = ERROR_SUCCESS;
  784. size_t cchStrLen = 0;
  785. if (!pszStr) {
  786. dwError = ERROR_INVALID_PARAMETER;
  787. NSU_BAIL_ON_ERROR(dwError);
  788. }
  789. __try {
  790. cchStrLen = wcslen(pszStr);
  791. } __except(EXCEPTION_EXECUTE_HANDLER) {
  792. dwError = ERROR_INVALID_PARAMETER;
  793. }
  794. NSU_BAIL_ON_ERROR(dwError);
  795. *pcchStrLen = cchStrLen;
  796. return dwError;
  797. NSU_CLEANUP:
  798. *pcchStrLen = 0;
  799. return dwError;
  800. }
  801. // Description:
  802. //
  803. // See NsuStringLenW
  804. //
  805. DWORD
  806. NsuStringLenA(
  807. IN LPCSTR pszStr,
  808. OUT size_t* pcbStrLen
  809. )
  810. {
  811. BOOL fBadStr = TRUE;
  812. DWORD dwError = ERROR_SUCCESS;
  813. size_t cbStrLen;
  814. if (!pszStr) {
  815. dwError = ERROR_INVALID_PARAMETER;
  816. NSU_BAIL_ON_ERROR(dwError);
  817. }
  818. __try {
  819. cbStrLen = strlen(pszStr);
  820. } __except(EXCEPTION_EXECUTE_HANDLER) {
  821. dwError = ERROR_INVALID_PARAMETER;
  822. }
  823. NSU_BAIL_ON_ERROR(dwError);
  824. *pcbStrLen = cbStrLen;
  825. return dwError;
  826. NSU_CLEANUP:
  827. *pcbStrLen = 0;
  828. return dwError;
  829. }
  830. // Description:
  831. //
  832. // Safe string searching routine that will not Access Violate if
  833. // passed bad pointers or non-null terminated strings.
  834. // pszStartOfMatch is a pointer to the start of the first match
  835. // of the string to search for in the string to search.
  836. //
  837. //
  838. // Arguments:
  839. //
  840. // pszStrToSearch - Input string to search in.
  841. // pszStrToFind - Input string to search for.
  842. // bIsCaseSensitive - if true, perform case sensitive search
  843. // pszStartOfMatch - pointer to first occurrance of pszStrToFind
  844. // within pszStrToSearch
  845. //
  846. // Return Value:
  847. // ERROR_INVALID_PARAMETER - if either input string points to an invalid string.
  848. // ERROR_SUCCESS
  849. //
  850. DWORD
  851. WINAPI
  852. NsuStringFindW(
  853. IN LPCWSTR pszStrToSearch,
  854. IN LPCWSTR pszStrToFind,
  855. IN BOOL bIsCaseSensitive,
  856. OUT LPCWSTR* ppszStartOfMatch
  857. )
  858. {
  859. DWORD dwError = ERROR_SUCCESS;
  860. size_t uiSearchLen;
  861. size_t uiFindLen;
  862. size_t i;
  863. *ppszStartOfMatch = 0;
  864. NsuStringLenW(pszStrToSearch, &uiSearchLen);
  865. NSU_BAIL_ON_ERROR(dwError);
  866. NsuStringLenW(pszStrToFind, &uiFindLen);
  867. NSU_BAIL_ON_ERROR(dwError);
  868. i = 0;
  869. if (bIsCaseSensitive)
  870. {
  871. while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen))
  872. {
  873. if (wcsncmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0)
  874. {
  875. *ppszStartOfMatch = &pszStrToSearch[i];
  876. }
  877. ++i;
  878. }
  879. }
  880. else
  881. {
  882. while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen))
  883. {
  884. if (_wcsnicmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0)
  885. {
  886. *ppszStartOfMatch = &pszStrToSearch[i];
  887. }
  888. ++i;
  889. }
  890. }
  891. NSU_CLEANUP:
  892. return dwError;
  893. }
  894. // Description:
  895. //
  896. // See NsuStringFindW
  897. //
  898. DWORD
  899. WINAPI
  900. NsuStringFindA(
  901. IN LPCSTR pszStrToSearch,
  902. IN LPCSTR pszStrToFind,
  903. IN BOOL bIsCaseSensitive,
  904. OUT LPCSTR* ppszStartOfMatch
  905. )
  906. {
  907. DWORD dwError = ERROR_SUCCESS;
  908. size_t uiSearchLen;
  909. size_t uiFindLen;
  910. size_t i;
  911. *ppszStartOfMatch = 0;
  912. NsuStringLenA(pszStrToSearch, &uiSearchLen);
  913. NSU_BAIL_ON_ERROR(dwError);
  914. NsuStringLenA(pszStrToFind, &uiFindLen);
  915. NSU_BAIL_ON_ERROR(dwError);
  916. i = 0;
  917. if (bIsCaseSensitive)
  918. {
  919. while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen))
  920. {
  921. if (strncmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0)
  922. {
  923. *ppszStartOfMatch = &pszStrToSearch[i];
  924. }
  925. ++i;
  926. }
  927. }
  928. else
  929. {
  930. while ((*ppszStartOfMatch == 0) && ((uiSearchLen - i) >= uiFindLen))
  931. {
  932. if (_strnicmp(&pszStrToSearch[i], pszStrToFind, uiFindLen) == 0)
  933. {
  934. *ppszStartOfMatch = &pszStrToSearch[i];
  935. }
  936. ++i;
  937. }
  938. }
  939. NSU_CLEANUP:
  940. return dwError;
  941. }