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.

1030 lines
23 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. resource.c
  5. Abstract:
  6. This module contains functions to load resources
  7. Author:
  8. 29-Aug-1995 Tue 12:29:27 created -by- Daniel Chou (danielc)
  9. [Environment:]
  10. NT Windows - Common Printer Driver UI DLL.
  11. [Notes:]
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #define DBG_CPSUIFILENAME DbgResource
  17. #define DBG_GETSTR0 0x00000001
  18. #define DBG_GETSTR1 0x00000002
  19. #define DBG_GETICON 0x00000004
  20. #define DBG_COMPOSESTR 0x00000008
  21. #define DBG_ADD_SPACE 0x00000010
  22. #define DBG_ADD_WCHAR 0x00000020
  23. #define DBG_AMPERCENT 0x00000040
  24. DEFINE_DBGVAR(0);
  25. extern HINSTANCE hInstDLL;
  26. //
  27. // Remove Ampercent will remove a '&' sign, if two '&' signs (ie. '&&') then
  28. // only one is removed, ALSO if a '(&X)' (ie. SPACE + & + Left Parenthesis +
  29. // Single Character + Right Parenthesis) then it consider to be a Localization
  30. // hot key indicator, then the whole ' (&X)' will be removed
  31. //
  32. #define REMOVE_AMPERCENT(CHTYPE) \
  33. { \
  34. CHTYPE *pOrg; \
  35. CHTYPE *pCopy; \
  36. UINT cRemoved; \
  37. CHTYPE ch; \
  38. \
  39. \
  40. cRemoved = 0; \
  41. pOrg = \
  42. pCopy = pStr; \
  43. \
  44. CPSUIDBG(DBG_AMPERCENT, ("RemoveAmpercent (ORG)='%ws'", pOrg)); \
  45. \
  46. do { \
  47. \
  48. while ((ch = *pStr++) && (ch != (CHTYPE)'&')) { \
  49. \
  50. if (cRemoved) { \
  51. \
  52. *pCopy = ch; \
  53. } \
  54. \
  55. ++pCopy; \
  56. } \
  57. \
  58. if (ch) { \
  59. \
  60. ++cRemoved; \
  61. \
  62. if (*pStr == (CHTYPE)'&') { \
  63. \
  64. *pCopy++ = *pStr++; \
  65. \
  66. } else if ((*(pCopy - 1) == (CHTYPE)'(') && \
  67. (*(pStr + 1) == (CHTYPE)')')) { \
  68. \
  69. cRemoved += 3; \
  70. ch = (CHTYPE)')'; \
  71. pCopy -= 1; \
  72. pStr += 2; \
  73. \
  74. if ((*pStr == (CHTYPE)' ') && \
  75. ((pCopy == pOrg) || \
  76. ((pCopy > pOrg) && \
  77. (*(pCopy - 1) == (CHTYPE)' ')))) { \
  78. \
  79. CPSUIDBG(DBG_AMPERCENT, ("Extra SPACE")); \
  80. \
  81. if (pCopy == pOrg) { \
  82. \
  83. ++pStr; \
  84. \
  85. } else { \
  86. \
  87. --pCopy; \
  88. } \
  89. \
  90. ++cRemoved; \
  91. } \
  92. } \
  93. } \
  94. \
  95. } while (ch); \
  96. \
  97. if (cRemoved) { \
  98. \
  99. *pCopy = (CHTYPE)'\0'; \
  100. \
  101. CPSUIDBG(DBG_AMPERCENT, (" RemoveAmpercent (%3ld)='%ws'", \
  102. cRemoved, pOrg)); \
  103. } \
  104. \
  105. return(cRemoved); \
  106. }
  107. UINT
  108. RemoveAmpersandA(
  109. LPSTR pStr
  110. )
  111. /*++
  112. Routine Description:
  113. This function remove ampersand from a string, the string must be writable
  114. Arguments:
  115. pStr - string to be serarch and remove the ampersand if found
  116. Return Value:
  117. UINT, count of ampersands removed
  118. Author:
  119. 19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
  120. Revision History:
  121. --*/
  122. {
  123. REMOVE_AMPERCENT(CHAR);
  124. }
  125. UINT
  126. RemoveAmpersandW(
  127. LPWSTR pStr
  128. )
  129. /*++
  130. Routine Description:
  131. This function remove ampersand from a string, the string must be writable
  132. Arguments:
  133. pwStr - string to be serarch and remove the ampersand if found
  134. Return Value:
  135. UINT, count of ampersands removed
  136. Author:
  137. 19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
  138. Revision History:
  139. --*/
  140. {
  141. REMOVE_AMPERCENT(WCHAR);
  142. }
  143. UINT
  144. DupAmpersandW(
  145. LPWSTR pwStr,
  146. INT cChar,
  147. INT cMaxChar
  148. )
  149. /*++
  150. Routine Description:
  151. This function remove ampersand from a string, the string must be writable
  152. Arguments:
  153. pwStr - string to be serarch and remove the ampersand if found
  154. Return Value:
  155. UINT, count of ampersands removed
  156. Author:
  157. 19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
  158. Revision History:
  159. --*/
  160. {
  161. LPWSTR pw;
  162. LPWSTR pwCopy;
  163. INT i;
  164. INT cAdd = 0;
  165. if (((i = cChar) > 0) && ((cMaxChar -= cChar) > 0)) {
  166. pw = pwStr;
  167. while ((i--) && (cAdd < cMaxChar)) {
  168. if (*pw++ == L'&') {
  169. ++cAdd;
  170. }
  171. }
  172. if (cAdd) {
  173. pw = pwStr + cChar;
  174. pwCopy = pw + cAdd;
  175. CPSUIASSERT(0, "DupAmpersandW(): pwStr[%u] is not NULL",
  176. *pw == L'\0', IntToPtr(cChar));
  177. while (pwCopy >= pwStr) {
  178. if ((*pwCopy-- = *pw--) == L'&') {
  179. *pwCopy-- = L'&';
  180. }
  181. }
  182. }
  183. }
  184. return((UINT)cAdd);
  185. }
  186. UINT
  187. GetString(
  188. PGSBUF pGSBuf,
  189. LPTSTR pStr
  190. )
  191. /*++
  192. Routine Description:
  193. This function load the string either from caller (ANSI or UNICODE) or
  194. from common UI DLL, if the pStr is valid then it will just it, after
  195. getting the correct string, it will convert it to UNICODE as needed
  196. Arguments:
  197. pGSBuf - Pointer to GSBUF structure and following structure must set
  198. pTVWnd - Pointer to the TVWND which has all then information
  199. needed.
  200. pBuf - Pointer to the begining of the buffer (LPWSTR)
  201. pEndBuf - Pointer to the end of the buffer
  202. pStr - Pointer to the string to be converted
  203. Return Value:
  204. UINT - Count of character stored in the pBuf not include the NULL
  205. terminator, if the pBuf only has one character left then it
  206. always store a NULL and return 0
  207. Author:
  208. 29-Aug-1995 Tue 12:30:49 created -by- Daniel Chou (danielc)
  209. First version
  210. 31-Aug-1995 Thu 10:58:04 updated -by- Daniel Chou (danielc)
  211. Re-write to do UNICODE conversion and ANSI call checking
  212. 05-Feb-1996 Mon 12:20:28 updated -by- Daniel Chou (danielc)
  213. Fix the bug when UNICODE we do lstrcpy without checking the buffer
  214. size.
  215. Revision History:
  216. --*/
  217. {
  218. LPWSTR pBuf;
  219. WORD Flags;
  220. GSBUF GSBuf = *pGSBuf;
  221. UINT RemoveAmpersandOff = 0;
  222. INT cChar;
  223. INT Len = 0;
  224. //
  225. // Make pBuf pointed to the first available character
  226. //
  227. pBuf = pGSBuf->pBuf;
  228. Flags = pGSBuf->Flags;
  229. CPSUIASSERT(0, "GetString(pBuf=NULL)", pBuf, 0);
  230. if (pGSBuf->pEndBuf) {
  231. cChar = (INT)(pGSBuf->pEndBuf - pBuf);
  232. } else {
  233. cChar = MAX_RES_STR_CHARS;
  234. }
  235. //
  236. // Check if we have room to convert the string, make sure we reduced the
  237. // cChar by one for the NULL terminator
  238. //
  239. if ((pStr == NULL) || (cChar < 2)) {
  240. if (pStr) {
  241. CPSUIWARN(("GetString: pStr=%08lx, Buffer cChar=%ld too smaller",
  242. pStr, cChar));
  243. }
  244. *pBuf = L'\0';
  245. return(0);
  246. }
  247. if (pGSBuf->chPreAdd != L'\0') {
  248. CPSUIDBG(DBG_GETSTR0, ("GetString(): Pre-Add Char = '%wc'",
  249. pGSBuf->chPreAdd));
  250. //
  251. // If we pre-add character first then do it now
  252. //
  253. if ((*pBuf++ = pGSBuf->chPreAdd) == L'&') {
  254. RemoveAmpersandOff = 1;
  255. }
  256. cChar--;
  257. pGSBuf->chPreAdd = L'\0';
  258. }
  259. if (--cChar < 1) {
  260. CPSUIDBG(DBG_GETSTR1, ("GetString()=Only has one character for SPACE"));
  261. NULL;
  262. } else if (!VALID_PTR(pStr)) {
  263. HINSTANCE hInst;
  264. WORD ResID;
  265. //
  266. // Apperantly this is the resource ID, the LoadString() will not
  267. // write exceed the cChar included the NULL terminator according to
  268. // the Win32 help file. At here we know we either have to convert
  269. // the ASCII string to UNICODE or we load the UNICODE string to the
  270. // buffer already
  271. //
  272. ResID = LOWORD(LODWORD(pStr));
  273. CPSUIDBGBLK({
  274. if ((ResID >= IDI_CPSUI_ICONID_FIRST) &&
  275. (ResID <= IDI_CPSUI_ICONID_LAST)) {
  276. CPSUIERR(("ResID=%ld is in icon ID range, change it", ResID));
  277. ResID = ResID - IDI_CPSUI_ICONID_FIRST + IDS_CPSUI_STRID_FIRST;
  278. }
  279. })
  280. if ((ResID >= IDS_CPSUI_STRID_FIRST) &&
  281. (ResID <= IDS_CPSUI_STRID_LAST)) {
  282. hInst = hInstDLL;
  283. if (Flags & GBF_INT_NO_PREFIX) {
  284. Flags &= ~GBF_PREFIX_OK;
  285. }
  286. } else {
  287. hInst = (Flags & GBF_IDS_INT_CPSUI) ? hInstDLL : pGSBuf->hInst;
  288. CPSUIASSERT(0, "GetString(hInst=NULL, %08lx)", pStr, 0);
  289. }
  290. //
  291. // Now loaded from common UI DLL directly to the user buffer
  292. //
  293. if (Len = LoadString(hInst, ResID, pBuf, cChar)) {
  294. pBuf += Len;
  295. } else {
  296. pBuf = pGSBuf->pBuf;
  297. CPSUIERR(("LoadString(ID=%ld) FAILED", ResID));
  298. }
  299. } else if ((Flags & GBF_COPYWSTR) ||
  300. (!(Flags & GBF_ANSI_CALL))) {
  301. //
  302. // We have UNICODE string but may need to put into the buffer
  303. //
  304. if (Len = lstrlen(pStr)) {
  305. if (Len > cChar) {
  306. Len = cChar;
  307. }
  308. CopyMemory(pBuf, pStr, sizeof(WCHAR) * Len);
  309. pBuf += Len;
  310. }
  311. } else {
  312. //
  313. // We are loading the ANSI string
  314. //
  315. if (Len = lstrlenA((LPSTR)pStr)) {
  316. if (Len = MultiByteToWideChar(CP_ACP,
  317. 0,
  318. (LPCSTR)pStr,
  319. Len,
  320. pBuf,
  321. cChar)) {
  322. pBuf += Len;
  323. } else {
  324. //
  325. // Conversion is not complete so make sure it NULL terminated
  326. //
  327. pBuf = pGSBuf->pBuf;
  328. CPSUIWARN(("GetString: pstr='%hs', Buffer reach limit=%ld, Len=%ld",
  329. pStr, cChar, Len));
  330. }
  331. CPSUIDBG(DBG_GETSTR0, ("Convert to UNICODE, Len=%d, cChar=%d",
  332. Len, cChar));
  333. }
  334. }
  335. //
  336. // Save the new index back and return the len to the caller
  337. //
  338. *pBuf = L'\0';
  339. Len = (INT)(pBuf - pGSBuf->pBuf);
  340. if (!(Flags & GBF_PREFIX_OK)) {
  341. Len -= RemoveAmpersandW(pGSBuf->pBuf + RemoveAmpersandOff);
  342. }
  343. if (Flags & GBF_DUP_PREFIX) {
  344. Len += DupAmpersandW(pGSBuf->pBuf,
  345. Len,
  346. (INT)(UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf));
  347. }
  348. CPSUIDBG(DBG_GETSTR1, ("GetString()=%ws (%d/%d)", pGSBuf->pBuf, Len, cChar));
  349. CPSUIASSERT(0, "GetString() : Len != Real Len (%ld)",
  350. Len == lstrlen(pGSBuf->pBuf), IntToPtr(lstrlen(pGSBuf->pBuf)));
  351. pGSBuf->pBuf += Len;
  352. return((UINT)Len);
  353. }
  354. UINT
  355. GSBufAddNumber(
  356. PGSBUF pGSBuf,
  357. DWORD Number,
  358. BOOL Sign
  359. )
  360. /*++
  361. Routine Description:
  362. Convert a number to a string with the limitation of GSBUF
  363. Arguments:
  364. pGSBuf - Pointer to GSBUF structure and following structure must set
  365. pTVWnd - Pointer to the TVWND which has all then information
  366. needed.
  367. pBuf - Pointer to the begining of the buffer (LPWSTR)
  368. pEndBuf - Pointer to the end of the buffer
  369. Number - LONG number to be converted
  370. Sign - if TRUE then Number is a sign long number else it is a unsigned
  371. DWORD
  372. Return Value:
  373. UINT total bytes converted to the string
  374. Author:
  375. 21-Feb-1996 Wed 12:17:00 created -by- Daniel Chou (danielc)
  376. Revision History:
  377. --*/
  378. {
  379. WCHAR wBuf[50];
  380. UINT cChar;
  381. UINT Len = 0;
  382. if ((cChar = (INT)(pGSBuf->pEndBuf - pGSBuf->pBuf - 1)) > 0) {
  383. StringCchPrintfW(wBuf, COUNT_ARRAY(wBuf), (Sign) ? L"%ld" : L"%lu", Number);
  384. if((Len = lstrlenW(wBuf)) > 0) {
  385. if (Len > cChar) {
  386. Len = cChar;
  387. }
  388. CopyMemory(pGSBuf->pBuf, wBuf, sizeof(WCHAR) * Len);
  389. pGSBuf->pBuf += Len;
  390. *(pGSBuf->pBuf) = L'\0';
  391. }
  392. }
  393. return Len;
  394. }
  395. UINT
  396. GSBufAddWChar(
  397. PGSBUF pGSBuf,
  398. UINT IntCharStrID,
  399. UINT Count
  400. )
  401. /*++
  402. Routine Description:
  403. Add a single character to the GSBuf
  404. Arguments:
  405. pGSBuf - Pointer to GSBUF structure and following structure must set
  406. pTVWnd - Pointer to the TVWND which has all then information
  407. needed.
  408. pBuf - Pointer to the begining of the buffer (LPWSTR)
  409. pEndBuf - Pointer to the end of the buffer
  410. wch - a single character to be added
  411. Return Value:
  412. BOOLEAN, true if succeed else false
  413. Author:
  414. 21-Feb-1996 Wed 12:00:24 created -by- Daniel Chou (danielc)
  415. Revision History:
  416. --*/
  417. {
  418. WCHAR wCh[2];
  419. UINT cAvai;
  420. if ((Count) &&
  421. ((cAvai = (UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf)) > 1) &&
  422. (LoadString(hInstDLL, IntCharStrID, wCh, COUNT_ARRAY(wCh)))) {
  423. CPSUIDBG(DBG_ADD_WCHAR, ("GSBufAddWChar(%08lx, %u, %u)=%u of '%wc'",
  424. pGSBuf, IntCharStrID, Count,
  425. (Count > (cAvai - 1)) ? cAvai - 1 : Count, wCh[0]));
  426. if (Count > (cAvai -= 1)) {
  427. Count = cAvai;
  428. }
  429. cAvai = Count;
  430. while (cAvai--) {
  431. *(pGSBuf->pBuf)++ = wCh[0];
  432. }
  433. *(pGSBuf->pBuf) = L'\0';
  434. return(Count);
  435. } else {
  436. CPSUIERR(("GSBufAddWChar(%08lx, %u, %u) FAILED",
  437. pGSBuf, IntCharStrID, Count));
  438. return(0);
  439. }
  440. }
  441. UINT
  442. GSBufAddSpace(
  443. PGSBUF pGSBuf,
  444. UINT Count
  445. )
  446. /*++
  447. Routine Description:
  448. Arguments:
  449. Return Value:
  450. Author:
  451. 20-Jul-1996 Sat 00:59:47 created -by- Daniel Chou (danielc)
  452. Revision History:
  453. --*/
  454. {
  455. static WCHAR wSpace[2] = { 0, 0 };
  456. UINT cAvai;
  457. if (wSpace[0] == L'\0') {
  458. LoadString(hInstDLL,
  459. IDS_INT_CPSUI_SPACE_CHAR,
  460. wSpace,
  461. COUNT_ARRAY(wSpace));
  462. }
  463. if ((wSpace[0] != L'\0') &&
  464. (Count) &&
  465. ((cAvai = (UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf)) > 1)) {
  466. CPSUIDBG(DBG_ADD_SPACE, ("GSBufAddSpace(%08lx, %u)=%u of '%wc'",
  467. pGSBuf, Count,
  468. (Count > (cAvai - 1)) ? cAvai - 1 : Count, wSpace[0]));
  469. if (Count > (cAvai -= 1)) {
  470. Count = cAvai;
  471. }
  472. cAvai = Count;
  473. while (cAvai--) {
  474. *(pGSBuf->pBuf)++ = wSpace[0];
  475. }
  476. *(pGSBuf->pBuf) = L'\0';
  477. return(Count);
  478. } else {
  479. CPSUIERR(("GSBufAddSpace(%08lx, %u) FAILED", pGSBuf, Count));
  480. return(0);
  481. }
  482. }
  483. UINT
  484. GetStringBuffer(
  485. HINSTANCE hInst,
  486. WORD GBFlags,
  487. WCHAR chPreAdd,
  488. LPTSTR pStr,
  489. LPWSTR pBuf,
  490. UINT cwBuf
  491. )
  492. /*++
  493. Routine Description:
  494. Arguments:
  495. Return Value:
  496. Author:
  497. 07-Sep-1995 Thu 10:45:09 created -by- Daniel Chou (danielc)
  498. Revision History:
  499. --*/
  500. {
  501. GSBUF GSBuf;
  502. GSBuf.hInst = hInst;
  503. GSBuf.Flags = GBFlags;
  504. GSBuf.pBuf = (LPWSTR)pBuf;
  505. GSBuf.pEndBuf = (LPWSTR)pBuf + cwBuf;
  506. GSBuf.chPreAdd = chPreAdd;
  507. return(GetString(&GSBuf, pStr));
  508. }
  509. LONG
  510. LoadCPSUIString(
  511. LPTSTR pStr,
  512. UINT cStr,
  513. UINT StrResID,
  514. BOOL AnsiCall
  515. )
  516. /*++
  517. Routine Description:
  518. Arguments:
  519. Return Value:
  520. Author:
  521. 08-Feb-1996 Thu 13:36:12 created -by- Daniel Chou (danielc)
  522. Revision History:
  523. --*/
  524. {
  525. if ((pStr) && (cStr)) {
  526. UINT Len = 0;
  527. if ((StrResID >= IDS_CPSUI_STRID_FIRST) &&
  528. (StrResID <= IDS_CPSUI_STRID_LAST)) {
  529. if (AnsiCall) {
  530. if (Len = LoadStringA(hInstDLL, StrResID, (LPSTR)pStr, cStr)) {
  531. Len -= RemoveAmpersandA((LPSTR)pStr);
  532. }
  533. } else {
  534. if (Len = LoadString(hInstDLL, StrResID, (LPWSTR)pStr, cStr)) {
  535. Len -= RemoveAmpersandW((LPWSTR)pStr);
  536. }
  537. }
  538. }
  539. return((LONG)Len);
  540. } else {
  541. return(-1);
  542. }
  543. }
  544. UINT
  545. ComposeStrData(
  546. HINSTANCE hInst,
  547. WORD GBFlags,
  548. LPWSTR pBuf,
  549. UINT cwBuf,
  550. UINT IntFormatStrID,
  551. LPTSTR pStr,
  552. DWORD dw1,
  553. DWORD dw2
  554. )
  555. /*++
  556. Routine Description:
  557. Arguments:
  558. Return Value:
  559. Author:
  560. 19-Jul-1996 Fri 17:11:19 created -by- Daniel Chou (danielc)
  561. Revision History:
  562. --*/
  563. {
  564. TCHAR szFormat[MAX_RES_STR_CHARS * 3];
  565. LPTSTR pData;
  566. LPTSTR pFinal;
  567. UINT Count;
  568. UINT i;
  569. UINT cb;
  570. ZeroMemory(szFormat, sizeof(szFormat));
  571. if ((IntFormatStrID) &&
  572. (i = LoadString(hInstDLL,
  573. IntFormatStrID,
  574. (LPTSTR)szFormat,
  575. MAX_RES_STR_CHARS))) {
  576. cb = ARRAYSIZE(szFormat) - i - 1;
  577. pData = szFormat + i + 1;
  578. if (!pStr) {
  579. //
  580. // Skip the pStr if it passed as NULL
  581. //
  582. StringCchPrintf(pFinal = pData, cb, szFormat, dw1, dw2);
  583. Count = lstrlen(pFinal);
  584. } else {
  585. i = GetStringBuffer(hInst,
  586. (WORD)(GBFlags | GBF_INT_NO_PREFIX),
  587. (WCHAR)0,
  588. pStr,
  589. pData,
  590. MAX_RES_STR_CHARS);
  591. cb = cb - i - 1;
  592. pFinal = pData + i + 1;
  593. StringCchPrintf(pFinal, cb, szFormat, pData, dw1, dw2);
  594. Count = lstrlen(pFinal);
  595. }
  596. if (Count > (cwBuf - 1)) {
  597. Count = cwBuf - 1;
  598. szFormat[Count] = '\0';
  599. }
  600. CopyMemory(pBuf, pFinal, (Count + 1) * sizeof(TCHAR));
  601. CPSUIDBG(DBG_COMPOSESTR, ("ComposeString('%ws', '%ws', %lu, %lu)='%ws' [%u]",
  602. szFormat, pData, dw1, dw2, pBuf, Count));
  603. } else {
  604. Count = GetStringBuffer(hInst, GBFlags, (WCHAR)0, pStr, pBuf, cwBuf);
  605. CPSUIDBG(DBG_COMPOSESTR, ("ComposeString(%08lx, %lu, %lu)=FAILED, '%ws' [%u]",
  606. pStr, dw1, dw2, pBuf, Count));
  607. }
  608. return(Count);
  609. }