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.

705 lines
14 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. _tcscat(pszString, 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. _tcscat(*ppszFullPath, _T("\\"));
  429. _tcscat(*ppszFullPath, pszFile);
  430. }
  431. else
  432. {
  433. Error = GetLastError();
  434. FreeSplMem(*ppszFullPath);
  435. *ppszFullPath = NULL;
  436. }
  437. }
  438. }
  439. }
  440. return Error;
  441. }
  442. /*++
  443. Routine Name:
  444. StatusFromHResult
  445. Description:
  446. This function returns a win32 error code from an HRESULT if possible and
  447. it failed, if it is not a win32 error code, it just returns the error code,
  448. otherwise it returns ERROR_SUCCESS.
  449. Arguments:
  450. hr - The HRESULT.
  451. Returns:
  452. The status equivalent of the hresult.
  453. --*/
  454. EXTERN_C
  455. DWORD
  456. StatusFromHResult(
  457. IN HRESULT hr
  458. )
  459. {
  460. DWORD Status = ERROR_SUCCESS;
  461. if (FAILED(hr))
  462. {
  463. if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
  464. {
  465. Status = HRESULT_CODE(hr);
  466. }
  467. else
  468. {
  469. //
  470. // Kind of wacky, should we have a table here for reasonably translatable HResults?
  471. //
  472. Status = hr;
  473. }
  474. }
  475. return Status;
  476. }
  477. /*++
  478. Routine Name:
  479. BoolFromHResult
  480. Description:
  481. This function take an HRESULT input, if the HRESULT is a failure, it sets
  482. the last error and returns false, otherwise it returns TRUE.
  483. Arguments:
  484. hr - The HRESULT.
  485. Returns:
  486. A BOOLEAN, Sets the last error
  487. --*/
  488. EXTERN_C
  489. BOOL
  490. BoolFromHResult(
  491. IN HRESULT hr
  492. )
  493. {
  494. DWORD Status = StatusFromHResult(hr);
  495. if (Status != ERROR_SUCCESS)
  496. {
  497. SetLastError(Status);
  498. }
  499. return Status == ERROR_SUCCESS;
  500. }
  501. /*++
  502. Routine Name:
  503. BoolFromStatus
  504. Description:
  505. This function sets the last error to the given win32 error code if it is not
  506. error success. It returns the corresponding error result.
  507. Arguments:
  508. Status - The Win32 error code.
  509. Returns:
  510. A BOOLEAN, Sets the last error
  511. --*/
  512. EXTERN_C
  513. BOOL
  514. BoolFromStatus(
  515. IN DWORD Status
  516. )
  517. {
  518. BOOL bRet = TRUE;
  519. if (ERROR_SUCCESS != Status)
  520. {
  521. SetLastError(Status);
  522. bRet = FALSE;
  523. }
  524. return bRet;
  525. }