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.

867 lines
19 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. common.cxx
  6. Abstract:
  7. common functions across all spooler components
  8. Author:
  9. Steve Kiraly (SteveKi)
  10. Revision History:
  11. Felix Maxa (AMaxa) 19 Apr 2001
  12. Added StrCatSystemPath
  13. --*/
  14. #include "spllibp.hxx"
  15. #pragma hdrstop
  16. #include "splcom.h"
  17. extern "C"
  18. DWORD
  19. WINAPIV
  20. StrCatAlloc(
  21. IN OUT LPCTSTR *ppszString,
  22. ...
  23. )
  24. /*++
  25. Description:
  26. This routine concatenates a set of null terminated strings
  27. and returns a pointer to the new string. It's the callers
  28. responsibility to release the returned string with a call
  29. to FreeSplMem(); The last argument must be a NULL
  30. to signify the end of the argument list.
  31. Arguments:
  32. ppszString - pointer where to return pointer to newly created
  33. string which is the concatenation of the passed
  34. in strings.
  35. ... - variable number of string to concatenate.
  36. Returns:
  37. ERROR_SUCCESS if new concatenated string is returned,
  38. or ERROR_XXX if an error occurred.
  39. Notes:
  40. The caller must pass valid strings as arguments to this routine,
  41. if an integer or other parameter is passed the routine will either
  42. crash or fail abnormally. Since this is an internal routine
  43. we are not in try except block for performance reasons.
  44. Usage
  45. --*/
  46. {
  47. UINT uTotalLen = 0;
  48. DWORD dwRetval = ERROR_INVALID_PARAMETER;
  49. LPTSTR pszString = NULL;
  50. LPCTSTR pszTemp = NULL;
  51. va_list pArgs;
  52. //
  53. // Validate the pointer where to return the buffer.
  54. //
  55. if (ppszString)
  56. {
  57. dwRetval = ERROR_SUCCESS;
  58. //
  59. // Keep the callers from getting random value on failure.
  60. //
  61. *ppszString = NULL;
  62. //
  63. // Get pointer to argument frame.
  64. //
  65. va_start(pArgs, ppszString);
  66. //
  67. // Tally up all the strings.
  68. //
  69. for ( ; ; )
  70. {
  71. //
  72. // Get pointer to the next argument.
  73. //
  74. pszTemp = va_arg(pArgs, LPCTSTR);
  75. if (!pszTemp)
  76. {
  77. break;
  78. }
  79. //
  80. // Sum all the string lengths.
  81. //
  82. uTotalLen = uTotalLen + _tcslen(pszTemp);
  83. }
  84. //
  85. // Need space for the null terminator.
  86. //
  87. uTotalLen = uTotalLen + 1;
  88. //
  89. // Allocate the space for the sum of all the strings.
  90. //
  91. pszString = (LPTSTR)AllocSplMem(uTotalLen * sizeof(TCHAR));
  92. if (pszString)
  93. {
  94. *pszString = L'\0';
  95. //
  96. // Reset the pointer to the argument frame.
  97. //
  98. va_start(pArgs, ppszString);
  99. //
  100. // Concatenate all the strings.
  101. //
  102. for ( ; ; )
  103. {
  104. pszTemp = va_arg(pArgs, LPCTSTR);
  105. if (!pszTemp)
  106. {
  107. break;
  108. }
  109. StringCchCat(pszString, uTotalLen, pszTemp);
  110. }
  111. //
  112. // Copy back the string pointer to the caller.
  113. //
  114. *ppszString = pszString;
  115. }
  116. else
  117. {
  118. dwRetval = ERROR_NOT_ENOUGH_MEMORY;
  119. }
  120. va_end(pArgs);
  121. }
  122. //
  123. // Set the last error in case the caller forgets to.
  124. //
  125. if (dwRetval != ERROR_SUCCESS)
  126. {
  127. SetLastError(dwRetval);
  128. }
  129. return dwRetval;
  130. }
  131. extern "C"
  132. DWORD
  133. WINAPIV
  134. StrNCatBuff(
  135. IN LPTSTR pszBuffer,
  136. IN UINT cchBuffer,
  137. ...
  138. )
  139. /*++
  140. Description:
  141. This routine concatenates a set of null terminated strings
  142. into the provided buffer. The last argument must be a NULL
  143. to signify the end of the argument list.
  144. Arguments:
  145. pszBuffer - pointer buffer where to place the concatenated
  146. string.
  147. cchBuffer - character count of the provided buffer including
  148. the null terminator.
  149. ... - variable number of string to concatenate.
  150. Returns:
  151. ERROR_SUCCESS if new concatenated string is returned,
  152. or ERROR_XXX if an error occurred.
  153. Notes:
  154. The caller must pass valid strings as arguments to this routine,
  155. if an integer or other parameter is passed the routine will either
  156. crash or fail abnormally. Since this is an internal routine
  157. we are not in try except block for performance reasons.
  158. --*/
  159. {
  160. DWORD dwRetval = ERROR_INVALID_PARAMETER;
  161. LPCTSTR pszTemp = NULL;
  162. LPTSTR pszDest = NULL;
  163. va_list pArgs;
  164. //
  165. // Validate the pointer where to return the buffer.
  166. //
  167. if (pszBuffer && cchBuffer)
  168. {
  169. //
  170. // Assume success.
  171. //
  172. dwRetval = ERROR_SUCCESS;
  173. //
  174. // Get pointer to argument frame.
  175. //
  176. va_start(pArgs, cchBuffer);
  177. //
  178. // Get temp destination pointer.
  179. //
  180. pszDest = pszBuffer;
  181. //
  182. // Insure we have space for the null terminator.
  183. //
  184. cchBuffer--;
  185. //
  186. // Collect all the arguments.
  187. //
  188. for ( ; ; )
  189. {
  190. //
  191. // Get pointer to the next argument.
  192. //
  193. pszTemp = va_arg(pArgs, LPCTSTR);
  194. if (!pszTemp)
  195. {
  196. break;
  197. }
  198. //
  199. // Copy the data into the destination buffer.
  200. //
  201. for ( ; cchBuffer; cchBuffer-- )
  202. {
  203. if (!(*pszDest = *pszTemp))
  204. {
  205. break;
  206. }
  207. pszDest++, pszTemp++;
  208. }
  209. //
  210. // If were unable to write all the strings to the buffer,
  211. // set the error code and nuke the incomplete copied strings.
  212. //
  213. if (!cchBuffer && pszTemp && *pszTemp)
  214. {
  215. dwRetval = ERROR_INVALID_PARAMETER;
  216. *pszBuffer = _T('\0');
  217. break;
  218. }
  219. }
  220. //
  221. // Terminate the buffer always.
  222. //
  223. *pszDest = _T('\0');
  224. va_end(pArgs);
  225. }
  226. //
  227. // Set the last error in case the caller forgets to.
  228. //
  229. if (dwRetval != ERROR_SUCCESS)
  230. {
  231. SetLastError(dwRetval);
  232. }
  233. return dwRetval;
  234. }
  235. extern "C"
  236. LPTSTR
  237. WINAPI
  238. SubChar(
  239. IN LPCTSTR pszIn,
  240. IN TCHAR cIn,
  241. IN TCHAR cOut
  242. )
  243. /*++
  244. Routine Description:
  245. Replaces all instances of cIn in pszIn with cOut.
  246. Arguments:
  247. pszIn - input string
  248. cIn - character to replace with cOut
  249. cOut - character that replaces cIn
  250. Return Value:
  251. If successful, returns a pointer to an allocated buffer containing the
  252. output string. If the return value is NULL, SubChar has fails and
  253. GetLastError() will return the error.
  254. Notes:
  255. An output buffer is allocated (and contains NULL) even if pszOut is NULL.
  256. --*/
  257. {
  258. LPTSTR pszReturn = NULL;
  259. LPTSTR pszOut = NULL;
  260. if (cIn && pszIn)
  261. {
  262. if ((pszOut = pszReturn = (LPTSTR) AllocSplMem((_tcslen(pszIn) + 1)*sizeof(TCHAR))))
  263. {
  264. for (; *pszIn ; ++pszIn, ++pszOut)
  265. {
  266. *pszOut = (*pszIn == cIn) ? cOut : *pszIn;
  267. }
  268. *pszOut = *pszIn;
  269. }
  270. }
  271. else
  272. {
  273. SetLastError(ERROR_INVALID_PARAMETER);
  274. }
  275. return pszReturn;
  276. }
  277. /*++
  278. Routine Name:
  279. GetLastErrorAsHResult
  280. Routine Description:
  281. Returns the last error as an HRESULT assuming a failure.
  282. Arguments:
  283. None
  284. Return Value:
  285. An HRESULT.
  286. --*/
  287. EXTERN_C
  288. HRESULT
  289. GetLastErrorAsHResult(
  290. VOID
  291. )
  292. {
  293. return HResultFromWin32(GetLastError());
  294. }
  295. /*++
  296. Routine Name:
  297. GetFileNamePart
  298. Routine Description:
  299. Get the file name portion of a path.
  300. Arguments:
  301. pszFullPath - Full path to a file
  302. ppszFileName - File name
  303. Return Value:
  304. An HRESULT
  305. --*/
  306. EXTERN_C
  307. HRESULT
  308. GetFileNamePart(
  309. IN PCWSTR pszFullPath,
  310. OUT PCWSTR *ppszFileName
  311. )
  312. {
  313. HRESULT hRetval = E_FAIL;
  314. WCHAR szfname[_MAX_FNAME] = {0};
  315. hRetval = pszFullPath && ppszFileName ? S_OK : E_INVALIDARG;
  316. if (SUCCEEDED(hRetval))
  317. {
  318. _wsplitpath(pszFullPath, NULL, NULL, szfname, NULL);
  319. *ppszFileName = wcsstr(pszFullPath, szfname);
  320. }
  321. return hRetval;
  322. }
  323. /*++
  324. Routine Name:
  325. GetLastErrorAsHResultAndFail
  326. Routine Description:
  327. This routine gets the last error as HRESULT, and if there was no last error,
  328. returns E_UNEXPECTED.
  329. Arguments:
  330. None
  331. Return Value:
  332. An HRESULT
  333. --*/
  334. EXTERN_C
  335. HRESULT
  336. GetLastErrorAsHResultAndFail(
  337. void
  338. )
  339. {
  340. HRESULT hRetval = E_FAIL;
  341. hRetval = GetLastErrorAsHResult();
  342. if (S_OK == hRetval)
  343. {
  344. hRetval = E_UNEXPECTED;
  345. }
  346. return hRetval;
  347. }
  348. /*++
  349. Routine Name:
  350. HResultFromWin32
  351. Routine Description:
  352. Returns the last error as an HRESULT assuming a failure.
  353. Arguments:
  354. dwError - Win32 error code
  355. Return Value:
  356. An HRESULT
  357. --*/
  358. EXTERN_C
  359. HRESULT
  360. HResultFromWin32(
  361. IN DWORD dwError
  362. )
  363. {
  364. return HRESULT_FROM_WIN32(dwError);
  365. }
  366. /*++
  367. Description:
  368. This routine allocates a string which is the concatenation:
  369. Directory\pszFile. Directory is Windir, SystemRoot, CurrentDir,
  370. SystemWindowsDir, depending on the edir input argument.
  371. Arguments:
  372. pszFile - file name
  373. eDir - enumeration, tells the function what directory to concatenate
  374. ppszFullPath - pointer where to return pointer to newly created string
  375. Returns:
  376. ERROR_SUCCESS if new concatenated string is returned,
  377. or ERROR_XXX if an error occurred.
  378. Notes:
  379. The caller must use FreeSplMem to free the string returned by this function
  380. --*/
  381. EXTERN_C
  382. DWORD
  383. WINAPI
  384. StrCatSystemPath(
  385. IN LPCTSTR pszFile,
  386. IN EStrCatDir eDir,
  387. OUT LPTSTR *ppszFullPath
  388. )
  389. {
  390. DWORD Error = ERROR_INVALID_PARAMETER;
  391. //
  392. // Validate arguments
  393. //
  394. if (pszFile && ppszFullPath)
  395. {
  396. DWORD cchNeeded;
  397. *ppszFullPath = NULL;
  398. //
  399. // Get the number of chars needed to hold the system directory. The returned
  400. // number accounts for the NULL terminator. GetCurrentDirectory is different than
  401. // the other function, because if takes the size of the buffer as the first
  402. // argument.
  403. //
  404. cchNeeded = eDir == kWindowsDir ? GetWindowsDirectory(NULL, 0) :
  405. eDir == kSystemWindowsDir ? GetSystemWindowsDirectory(NULL, 0) :
  406. eDir == kSystemDir ? GetSystemDirectory(NULL, 0) :
  407. GetCurrentDirectory(0, NULL);
  408. Error = cchNeeded ? ERROR_SUCCESS : GetLastError();
  409. if (Error == ERROR_SUCCESS)
  410. {
  411. //
  412. // Calculate the size of the buffer needed. Note that cchNeeded already
  413. // includes the NULL terminator.
  414. // length(directory) + whack + length(pszFile)
  415. //
  416. cchNeeded = cchNeeded + 1 + _tcslen(pszFile);
  417. *ppszFullPath = static_cast<LPTSTR>(AllocSplMem(cchNeeded * sizeof(TCHAR)));
  418. Error = *ppszFullPath ? ERROR_SUCCESS : GetLastError();
  419. if (Error == ERROR_SUCCESS)
  420. {
  421. DWORD cchTemp;
  422. cchTemp = eDir == kWindowsDir ? GetWindowsDirectory(*ppszFullPath, cchNeeded) :
  423. eDir == kSystemWindowsDir ? GetSystemWindowsDirectory(*ppszFullPath, cchNeeded) :
  424. eDir == kSystemDir ? GetSystemDirectory(*ppszFullPath, cchNeeded) :
  425. GetCurrentDirectory(cchNeeded, *ppszFullPath);
  426. if (cchTemp)
  427. {
  428. StringCchCat(*ppszFullPath, cchNeeded, _T("\\"));
  429. StringCchCat(*ppszFullPath, cchNeeded, pszFile);
  430. }
  431. else
  432. {
  433. Error = GetLastError();
  434. FreeSplMem(*ppszFullPath);
  435. *ppszFullPath = NULL;
  436. }
  437. }
  438. }
  439. }
  440. return Error;
  441. }
  442. /*++
  443. Description:
  444. This routine converts a unicode string to an ansi string. The caller
  445. must free the ansi string using "delete [] pszAnsi".
  446. Arguments:
  447. pszUnicode - pointer to NULL terminated unicode string
  448. ppszAnsi - pointer where to return pointer to newly created string
  449. Returns:
  450. S_OK - operation was successful and *ppszAnsi can be used
  451. or any other HRESULT if an error occurred.
  452. --*/
  453. EXTERN_C
  454. HRESULT
  455. UnicodeToAnsiWithAlloc(
  456. IN LPCWSTR pszUnicode,
  457. OUT LPSTR *ppszAnsi
  458. )
  459. {
  460. HRESULT hr = E_INVALIDARG;
  461. if (ppszAnsi)
  462. {
  463. *ppszAnsi = NULL;
  464. hr = S_OK;
  465. if (pszUnicode)
  466. {
  467. INT rc;
  468. rc = WideCharToMultiByte(CP_THREAD_ACP,
  469. 0,
  470. pszUnicode,
  471. -1,
  472. NULL,
  473. 0,
  474. NULL,
  475. NULL);
  476. if (rc)
  477. {
  478. *ppszAnsi = new CHAR[rc];
  479. if (*ppszAnsi)
  480. {
  481. rc = WideCharToMultiByte(CP_THREAD_ACP,
  482. 0,
  483. pszUnicode,
  484. -1,
  485. *ppszAnsi,
  486. rc,
  487. NULL,
  488. NULL);
  489. if (!rc)
  490. {
  491. hr = GetLastErrorAsHResult();
  492. delete [] *ppszAnsi;
  493. }
  494. }
  495. else
  496. {
  497. hr = E_OUTOFMEMORY;
  498. }
  499. }
  500. else
  501. {
  502. hr = GetLastErrorAsHResult();
  503. }
  504. }
  505. }
  506. return hr;
  507. }
  508. /*++
  509. Description:
  510. This routine converts an ansi string to a unicode string. The caller
  511. must free the unicode string using "delete [] pszUnicode".
  512. Arguments:
  513. pszAnsi - pointer to NULL terminated ansi string
  514. ppszUnicode - pointer where to return pointer to newly created string
  515. Returns:
  516. S_OK - operation was successful and *ppszUnicode can be used
  517. or any other HRESULT if an error occurred.
  518. --*/
  519. EXTERN_C
  520. HRESULT
  521. AnsiToUnicodeWithAlloc(
  522. IN LPCSTR pszAnsi,
  523. OUT LPWSTR *ppszUnicode
  524. )
  525. {
  526. HRESULT hr = E_INVALIDARG;
  527. if (ppszUnicode)
  528. {
  529. *ppszUnicode = NULL;
  530. hr = S_OK;
  531. if (pszAnsi)
  532. {
  533. INT rc;
  534. rc = MultiByteToWideChar(CP_ACP,
  535. MB_PRECOMPOSED,
  536. pszAnsi,
  537. -1,
  538. NULL,
  539. 0);
  540. if (rc)
  541. {
  542. *ppszUnicode = new WCHAR[rc];
  543. if (*ppszUnicode)
  544. {
  545. rc = MultiByteToWideChar(CP_ACP,
  546. MB_PRECOMPOSED,
  547. pszAnsi,
  548. -1,
  549. *ppszUnicode,
  550. rc);
  551. if (!rc)
  552. {
  553. hr = GetLastErrorAsHResult();
  554. delete [] *ppszUnicode;
  555. }
  556. }
  557. else
  558. {
  559. hr = E_OUTOFMEMORY;
  560. }
  561. }
  562. else
  563. {
  564. hr = GetLastErrorAsHResult();
  565. }
  566. }
  567. }
  568. return hr;
  569. }
  570. /*++
  571. Routine Name:
  572. StatusFromHResult
  573. Description:
  574. This function returns a win32 error code from an HRESULT if possible and
  575. it failed, if it is not a win32 error code, it just returns the error code,
  576. otherwise it returns ERROR_SUCCESS.
  577. Arguments:
  578. hr - The HRESULT.
  579. Returns:
  580. The status equivalent of the hresult.
  581. --*/
  582. EXTERN_C
  583. DWORD
  584. StatusFromHResult(
  585. IN HRESULT hr
  586. )
  587. {
  588. DWORD Status = ERROR_SUCCESS;
  589. if (FAILED(hr))
  590. {
  591. if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
  592. {
  593. Status = HRESULT_CODE(hr);
  594. }
  595. else
  596. {
  597. //
  598. // Kind of wacky, should we have a table here for reasonably translatable HResults?
  599. //
  600. Status = hr;
  601. }
  602. }
  603. return Status;
  604. }
  605. /*++
  606. Routine Name:
  607. BoolFromHResult
  608. Description:
  609. This function take an HRESULT input, if the HRESULT is a failure, it sets
  610. the last error and returns false, otherwise it returns TRUE.
  611. Arguments:
  612. hr - The HRESULT.
  613. Returns:
  614. A BOOLEAN, Sets the last error
  615. --*/
  616. EXTERN_C
  617. BOOL
  618. BoolFromHResult(
  619. IN HRESULT hr
  620. )
  621. {
  622. DWORD Status = StatusFromHResult(hr);
  623. if (Status != ERROR_SUCCESS)
  624. {
  625. SetLastError(Status);
  626. }
  627. return Status == ERROR_SUCCESS;
  628. }
  629. /*++
  630. Routine Name:
  631. BoolFromStatus
  632. Description:
  633. This function sets the last error to the given win32 error code if it is not
  634. error success. It returns the corresponding error result.
  635. Arguments:
  636. Status - The Win32 error code.
  637. Returns:
  638. A BOOLEAN, Sets the last error
  639. --*/
  640. EXTERN_C
  641. BOOL
  642. BoolFromStatus(
  643. IN DWORD Status
  644. )
  645. {
  646. BOOL bRet = TRUE;
  647. if (ERROR_SUCCESS != Status)
  648. {
  649. SetLastError(Status);
  650. bRet = FALSE;
  651. }
  652. return bRet;
  653. }