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.

1262 lines
33 KiB

  1. /*****************************************************************************\
  2. * MODULE: webutil.cxx
  3. *
  4. * PURPOSE: functions to handle printer name encoding
  5. *
  6. * Copyright (C) 1996-1997 Microsoft Corporation
  7. *
  8. * History:
  9. * 02/26/98 weihaic Added DecodePrinterName/EncodePrinterName
  10. * GetWebpnpUrl
  11. * 04/23/97 weihaic Created based on spooler/inersrv/inetio.cxx
  12. *
  13. \*****************************************************************************/
  14. #include "spllibp.hxx"
  15. #pragma hdrstop
  16. #include "splcom.h"
  17. #ifdef DEBUG
  18. DWORD g_cbIppMem = 0;
  19. #endif
  20. /*****************************************************************************\
  21. * web_WCtoMB (Local Routine)
  22. *
  23. * Converts Wide-Char to Multi-Byte string. This routine specifies a codepage
  24. * for translation.
  25. *
  26. \*****************************************************************************/
  27. LPSTR web_WCtoMB(
  28. UINT uCP,
  29. LPCWSTR lpszWC,
  30. LPDWORD lpcbSize)
  31. {
  32. DWORD cbSize;
  33. LPSTR lpszMB = NULL;
  34. //
  35. // Get the size necessary to hold a multibyte string.
  36. //
  37. cbSize = WideCharToMultiByte(uCP, 0, lpszWC, -1, NULL, 0, NULL, NULL);
  38. if (cbSize) {
  39. if (lpszMB = (LPSTR)webAlloc(cbSize)) {
  40. WideCharToMultiByte(uCP, 0, lpszWC, -1, lpszMB, cbSize, NULL, NULL);
  41. //
  42. // If a size-return is requested, then return
  43. // the bytes-occupied (no terminator).
  44. //
  45. if (lpcbSize)
  46. *lpcbSize = --cbSize;
  47. }
  48. }
  49. return lpszMB;
  50. }
  51. /*****************************************************************************\
  52. * web_WCtoUtf8 (Local Routine)
  53. * web_Utf8toWC (Local Routine)
  54. *
  55. * Converts Wide-Char to Multi-Byte string. This routine is used for ansi
  56. * 9X platforms since the CP_UTF8 codepage isn't supported.
  57. *
  58. \*****************************************************************************/
  59. #define ASCII 0x007f // ascii range.
  60. #define UTF8_2_MAX 0x07ff // max UTF8 2byte seq (32 * 64 = 2048)
  61. #define UTF8_1ST_OF_2 0xc0 // 110x xxxx
  62. #define UTF8_1ST_OF_3 0xe0 // 1110 xxxx
  63. #define UTF8_TRAIL 0x80 // 10xx xxxx
  64. #define HIGER_6_BIT(u) ((u) >> 12) //
  65. #define MIDDLE_6_BIT(u) (((u) & 0x0fc0) >> 6) //
  66. #define LOWER_6_BIT(u) ((u) & 0x003f) //
  67. #define BIT7(a) ((a) & 0x80) //
  68. #define BIT6(a) ((a) & 0x40) //
  69. #define SIZEOF_UTF8 (sizeof(WCHAR) + sizeof(CHAR))
  70. LPSTR web_WCtoUtf8(
  71. LPCWSTR lpszSrc,
  72. DWORD cchSrc,
  73. LPDWORD lpcbSize)
  74. {
  75. LPSTR lpszU8;
  76. LPCWSTR lpszWC;
  77. LPSTR lpszDst = NULL;
  78. DWORD cchDst = 0;
  79. //
  80. // Allocate our buffer for the translation.
  81. //
  82. if (cchSrc && (lpszDst = (LPSTR)webAlloc(cchSrc * SIZEOF_UTF8))) {
  83. for (lpszU8 = lpszDst, lpszWC = lpszSrc; cchSrc; lpszWC++, cchSrc--) {
  84. if (*lpszWC <= ASCII) {
  85. *lpszU8++ = (CHAR)*lpszWC;
  86. cchDst++;
  87. } else if (*lpszWC <= UTF8_2_MAX) {
  88. //
  89. // Use upper 5 bits in first byte.
  90. // Use lower 6 bits in second byte.
  91. //
  92. *lpszU8++ = (UTF8_1ST_OF_2 | (*lpszWC >> 6));
  93. *lpszU8++ = (UTF8_TRAIL | LOWER_6_BIT(*lpszWC));
  94. cchDst+=2;
  95. } else {
  96. //
  97. // Use upper 4 bits in first byte.
  98. // Use middle 6 bits in second byte.
  99. // Use lower 6 bits in third byte.
  100. //
  101. *lpszU8++ = (UTF8_1ST_OF_3 | (*lpszWC >> 12));
  102. *lpszU8++ = (UTF8_TRAIL | MIDDLE_6_BIT(*lpszWC));
  103. *lpszU8++ = (UTF8_TRAIL | LOWER_6_BIT(*lpszWC));
  104. cchDst+=3;
  105. }
  106. }
  107. } else {
  108. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  109. }
  110. //
  111. // Return our buffer-size.
  112. //
  113. *lpcbSize = cchDst;
  114. return lpszDst;
  115. }
  116. LPWSTR web_Utf8toWC(
  117. LPCSTR lpszSrc,
  118. DWORD cchSrc)
  119. {
  120. LPCSTR lpszU8;
  121. LPWSTR lpszWC;
  122. int nTB;
  123. CHAR cU8;
  124. LPWSTR lpszDst = NULL;
  125. if (cchSrc && (lpszDst = (LPWSTR)webAlloc((cchSrc + 1) * sizeof(WCHAR)))) {
  126. for (lpszU8 = lpszSrc, lpszWC = lpszDst, nTB = 0; cchSrc ; cchSrc--) {
  127. if (BIT7(*lpszU8) == 0) {
  128. //
  129. // Ascii.
  130. //
  131. *lpszWC++ = (WCHAR)*lpszU8;
  132. } else if (BIT6(*lpszU8) == 0) {
  133. if (nTB != 0) {
  134. //
  135. // Decrement the trail byte counter.
  136. //
  137. nTB--;
  138. //
  139. // Make room for the trail byte and add the trail byte
  140. // value.
  141. //
  142. *lpszWC <<= 6;
  143. *lpszWC |= LOWER_6_BIT(*lpszU8);
  144. if (nTB == 0)
  145. lpszWC++;
  146. }
  147. } else {
  148. //
  149. // Found a lead byte.
  150. //
  151. if (nTB > 0) {
  152. //
  153. // Error - previous sequence not finished.
  154. //
  155. nTB = 0;
  156. lpszWC++;
  157. } else {
  158. //
  159. // Calculate the number of bytes to follow.
  160. // Look for the first 0 from left to right.
  161. //
  162. for (cU8 = *lpszU8; BIT7(cU8) != 0; ) {
  163. cU8 <<= 1;
  164. nTB++;
  165. }
  166. //
  167. // Store the value from the first byte and decrement
  168. // the number of bytes to follow.
  169. //
  170. *lpszWC = (cU8 >> nTB--);
  171. }
  172. }
  173. lpszU8++;
  174. }
  175. }
  176. return lpszDst;
  177. }
  178. /*****************************************************************************\
  179. * web_MBtoWC (Local Routine)
  180. *
  181. * Converts Multi-Byte to Wide-Char string. This specifies a translation
  182. * codepage. The (cchMB) does not include the null-terminator, so we need
  183. *
  184. \*****************************************************************************/
  185. LPWSTR web_MBtoWC(
  186. UINT uCP,
  187. LPCSTR lpszMB,
  188. DWORD cchMB)
  189. {
  190. DWORD cch;
  191. LPWSTR lpszWC = NULL;
  192. //
  193. // Get the size necessary to hold a widechar string.
  194. //
  195. cch = MultiByteToWideChar(uCP, 0, lpszMB, cchMB, NULL, 0);
  196. if (cch) {
  197. cch = ((cchMB == (DWORD)-1) ? cch : cch + 1);
  198. if (lpszWC = (LPWSTR)webAlloc(cch * sizeof(WCHAR))) {
  199. MultiByteToWideChar(uCP, 0, lpszMB, cchMB, lpszWC, cch);
  200. }
  201. }
  202. return lpszWC;
  203. }
  204. /*****************************************************************************\
  205. * webMBtoTC (Local Routine)
  206. *
  207. * Converts Multi-Byte to a TChar string.
  208. *
  209. \*****************************************************************************/
  210. LPTSTR webMBtoTC(
  211. UINT uCP,
  212. LPSTR lpszUT,
  213. DWORD cch)
  214. {
  215. LPTSTR lpszTC = NULL;
  216. #ifdef UNICODE
  217. if (lpszUT != NULL)
  218. lpszTC = web_MBtoWC(uCP, lpszUT, cch);
  219. return lpszTC;
  220. #else
  221. LPWSTR lpszWC = NULL;
  222. //
  223. // First convert the string to unicode so we can go through
  224. // the translation process.
  225. //
  226. if (lpszUT != NULL) {
  227. if (uCP == CP_UTF8) {
  228. DWORD cbSize = 0;
  229. lpszWC = web_Utf8toWC(lpszUT, cch);
  230. if (lpszWC) {
  231. lpszTC = web_WCtoMB(CP_ACP, lpszWC, &cbSize);
  232. webFree(lpszWC);
  233. }
  234. } else {
  235. if ( lpszTC = (LPSTR)webAlloc(cch+1) ) {
  236. memcpy( lpszTC, lpszUT, cch);
  237. lpszTC[cch] = '\0';
  238. }
  239. }
  240. }
  241. return lpszTC;
  242. #endif
  243. }
  244. /*****************************************************************************\
  245. * webTCtoMB (Local Routine)
  246. *
  247. * Converts a TChar to a Multi-Byte string.
  248. *
  249. \*****************************************************************************/
  250. LPSTR webTCtoMB(
  251. UINT uCP,
  252. LPCTSTR lpszTC,
  253. LPDWORD lpcbSize)
  254. {
  255. LPWSTR lpszWC;
  256. LPSTR lpszUT = NULL;
  257. *lpcbSize = 0;
  258. if (lpszTC != NULL) {
  259. #ifdef UNICODE
  260. if (lpszWC = webAllocStr(lpszTC)) {
  261. lpszUT = web_WCtoMB(uCP, lpszWC, lpcbSize);
  262. #else
  263. //
  264. // Convert to unicode then back again so we can go
  265. // through the code-page translation.
  266. //
  267. if (lpszWC = web_MBtoWC(CP_ACP, lpszTC, (DWORD)-1)) {
  268. DWORD cch = webStrSize(lpszTC);
  269. if (uCP == CP_UTF8)
  270. lpszUT = web_WCtoUtf8(lpszWC, cch, lpcbSize);
  271. else
  272. lpszUT = web_WCtoMB(uCP, lpszWC, lpcbSize);
  273. #endif
  274. webFree(lpszWC);
  275. }
  276. }
  277. return lpszUT;
  278. }
  279. /*****************************************************************************\
  280. * webStrSize (Local Routine)
  281. *
  282. * Returns bytes occupied by string (including NULL terminator).
  283. *
  284. \*****************************************************************************/
  285. DWORD webStrSize(
  286. LPCTSTR lpszStr)
  287. {
  288. return (lpszStr ? ((lstrlen(lpszStr) + 1) * sizeof(TCHAR)) : 0);
  289. }
  290. /*****************************************************************************\
  291. * webAlloc (Local Routine)
  292. *
  293. * Allocates a block of memory.
  294. *
  295. \*****************************************************************************/
  296. LPVOID webAlloc(
  297. DWORD cbSize)
  298. {
  299. PDWORD_PTR lpdwPtr;
  300. #ifdef DEBUG
  301. if (cbSize && (lpdwPtr = (LPDWORD)new BYTE[cbSize + sizeof(DWORD_PTR)])) {
  302. ZeroMemory(lpdwPtr, cbSize + sizeof(DWORD_PTR));
  303. *lpdwPtr = cbSize;
  304. g_cbIppMem += cbSize;
  305. return (LPVOID)(lpdwPtr + 1);
  306. }
  307. #else
  308. if (cbSize && (lpdwPtr = (PDWORD_PTR) new BYTE[cbSize])) {
  309. ZeroMemory(lpdwPtr, cbSize);
  310. return (LPVOID)lpdwPtr;
  311. }
  312. #endif
  313. return NULL;
  314. }
  315. /*****************************************************************************\
  316. * webFree (Local Routine)
  317. *
  318. * Deletes the memory-block allocated via webAlloc().
  319. *
  320. \*****************************************************************************/
  321. BOOL webFree(
  322. LPVOID lpMem)
  323. {
  324. if (lpMem) {
  325. #ifdef DEBUG
  326. DWORD cbSize;
  327. lpMem = ((LPDWORD)lpMem) - 1;
  328. cbSize = *((LPDWORD)lpMem);
  329. g_cbIppMem -= cbSize;
  330. #endif
  331. delete [] lpMem;
  332. return TRUE;
  333. }
  334. return FALSE;
  335. }
  336. /*****************************************************************************\
  337. * webRealloc (Local Routine)
  338. *
  339. * Reallocates a block of memory. Only for expanding memory NOT safe
  340. * for contracting memory.
  341. *
  342. \*****************************************************************************/
  343. LPVOID webRealloc(
  344. LPVOID lpMem,
  345. DWORD cbOldSize,
  346. DWORD cbNewSize)
  347. {
  348. LPVOID lpNew;
  349. if (lpNew = (LPVOID)webAlloc(cbNewSize)) {
  350. CopyMemory(lpNew, lpMem, cbOldSize);
  351. webFree(lpMem);
  352. }
  353. return lpNew;
  354. }
  355. /*****************************************************************************\
  356. * webAllocStr (Local Routine)
  357. *
  358. * Allocates a string.
  359. *
  360. \*****************************************************************************/
  361. LPTSTR webAllocStr(
  362. LPCTSTR lpszStr)
  363. {
  364. LPTSTR lpszMem;
  365. DWORD cbSize;
  366. if (lpszStr == NULL)
  367. return NULL;
  368. cbSize = webStrSize(lpszStr);
  369. if (lpszMem = (LPTSTR)webAlloc(cbSize))
  370. memcpy(lpszMem, lpszStr, cbSize);
  371. return lpszMem;
  372. }
  373. /*****************************************************************************\
  374. * webFindRChar
  375. *
  376. * Searches for the first occurence of (cch) in a string in reverse order.
  377. *
  378. \*****************************************************************************/
  379. LPTSTR webFindRChar(
  380. LPTSTR lpszStr,
  381. TCHAR cch)
  382. {
  383. int nLimit;
  384. if (nLimit = lstrlen(lpszStr)) {
  385. lpszStr += nLimit;
  386. while ((*lpszStr != cch) && nLimit--)
  387. lpszStr--;
  388. if (nLimit >= 0)
  389. return lpszStr;
  390. }
  391. return NULL;
  392. }
  393. /*****************************************************************************\
  394. * webAtoI
  395. *
  396. * Convert Ascii to Integer.
  397. *
  398. \*****************************************************************************/
  399. DWORD webAtoI(
  400. LPTSTR pszInt)
  401. {
  402. DWORD dwRet = 0;
  403. while ((*pszInt >= TEXT('0')) && (*pszInt <= TEXT('9')))
  404. dwRet = (dwRet * 10) + *pszInt++ - TEXT('0');
  405. return dwRet;
  406. }
  407. BOOL
  408. IsWebServerInstalled(
  409. LPCTSTR pszServer
  410. )
  411. {
  412. HANDLE hServer;
  413. DWORD dwDontCare, dwW3SvcInstalled, dwLastError;
  414. PRINTER_DEFAULTS Defaults = {NULL, NULL, 0};
  415. if ( !OpenPrinter((LPTSTR)pszServer, &hServer, &Defaults) )
  416. return FALSE;
  417. dwLastError = GetPrinterData(hServer,
  418. SPLREG_W3SVCINSTALLED,
  419. &dwDontCare,
  420. (LPBYTE)&dwW3SvcInstalled,
  421. sizeof(dwW3SvcInstalled),
  422. &dwDontCare);
  423. ClosePrinter(hServer);
  424. return dwLastError == ERROR_SUCCESS && dwW3SvcInstalled != 0;
  425. }
  426. /********************************************************************************
  427. Name:
  428. EncodePrinterName
  429. Description:
  430. Encode the printer name to avoid special characters, also encode any chars
  431. with ASC code between 0x80 and 0xffff. This is to avoid the conversion betwwen
  432. different codepages when the client and the server have different language
  433. packages.
  434. Arguments:
  435. lpText: the normal text string
  436. lpHTMLStr: the buf provided by the caller to store the encoded string
  437. if it is NULL, the function will return a FALSE
  438. lpdwSize: Pointer to the size of the buffer (in characters)
  439. Return Value:
  440. If the function succeeds, the return value is TRUE;
  441. If the function fails, the return value is FALSE. To get extended error
  442. information, call GetLastError.
  443. ********************************************************************************/
  444. BOOL EncodePrinterName (LPCTSTR lpText, LPTSTR lpHTMLStr, LPDWORD lpdwSize)
  445. {
  446. #define MAXLEN_PER_CHAR 6
  447. #define BIN2ASC(bCode,lpHTMLStr) *lpHTMLStr++ = HexToAsc ((bCode) >> 4);\
  448. *lpHTMLStr++ = HexToAsc ((bCode) & 0xf)
  449. DWORD dwLen;
  450. BYTE bCode;
  451. if (!lpText || !lpdwSize) {
  452. SetLastError (ERROR_INVALID_DATA);
  453. return FALSE;
  454. }
  455. dwLen = MAXLEN_PER_CHAR * lstrlen (lpText) + 1;
  456. if (!lpHTMLStr || *lpdwSize < dwLen) {
  457. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  458. *lpdwSize = dwLen;
  459. return FALSE;
  460. }
  461. while (*lpText) {
  462. if ((DWORD) (*lpText) > 0xff ) {
  463. //
  464. // Encode as ~0hhll hh is the high byte, ll is the low byte
  465. //
  466. *lpHTMLStr++ = TEXT ('~');
  467. *lpHTMLStr++ = TEXT ('0');
  468. //
  469. // Get the high byte
  470. //
  471. bCode = (*lpText & 0xff00) >> 8;
  472. BIN2ASC(bCode,lpHTMLStr);
  473. //
  474. // Get the low byte
  475. //
  476. bCode = (*lpText & 0xff);
  477. BIN2ASC(bCode,lpHTMLStr);
  478. }
  479. else if ((DWORD) (*lpText) > 0x7f) {
  480. //
  481. // Encode as ~xx
  482. //
  483. *lpHTMLStr++ = TEXT ('~');
  484. bCode = *lpText & 0xff;
  485. BIN2ASC(bCode,lpHTMLStr);
  486. }
  487. else {
  488. if (! _istalnum( *lpText)) {
  489. *lpHTMLStr++ = TEXT ('~');
  490. BIN2ASC(*lpText,lpHTMLStr);
  491. }
  492. else {
  493. *lpHTMLStr++ = *lpText;
  494. }
  495. }
  496. lpText++;
  497. }
  498. *lpHTMLStr = NULL;
  499. return TRUE;
  500. }
  501. /********************************************************************************
  502. Name:
  503. DncodePrinterName
  504. Description:
  505. Dncode the printer name encoded in from EncodePrinterName
  506. Arguments:
  507. lpText: the normal text string
  508. lpHTMLStr: the buf provided by the caller to store the encoded string
  509. if it is NULL, the function will return a FALSE
  510. lpdwSize: Pointer to the size of the buffer (in characters)
  511. Return Value:
  512. If the function succeeds, the return value is TRUE;
  513. If the function fails, the return value is FALSE. To get extended error
  514. information, call GetLastError.
  515. ********************************************************************************/
  516. BOOL DecodePrinterName (LPCTSTR pPrinterName, LPTSTR pDecodedName, LPDWORD lpdwSize)
  517. {
  518. LPTSTR lpParsedStr = pDecodedName;
  519. LPCTSTR lpUnparsedStr = pPrinterName;
  520. TCHAR chMark = TEXT ('~');
  521. TCHAR chZero = TEXT ('0');
  522. BOOL bRet = TRUE;
  523. DWORD dwLen;
  524. TCHAR b1, b2, b3, b4;
  525. //
  526. // Verify that we're getting non-Null input pointers
  527. //
  528. if ((!pPrinterName) || (!lpdwSize)) {
  529. SetLastError (ERROR_INVALID_DATA);
  530. return FALSE;
  531. }
  532. dwLen = lstrlen (pPrinterName) + 1;
  533. if (!pDecodedName || *lpdwSize < dwLen) {
  534. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  535. *lpdwSize = dwLen;
  536. return FALSE;
  537. }
  538. while (*lpUnparsedStr) {
  539. if (*lpUnparsedStr == chMark) {
  540. if (! (b1 = *++lpUnparsedStr)) {
  541. SetLastError (ERROR_INVALID_DATA);
  542. bRet = FALSE;
  543. break;
  544. }
  545. if (b1 == chZero) {
  546. //
  547. // Decode ~0hhll
  548. //
  549. if ( !(b1 = *++lpUnparsedStr) ||
  550. !(b2 = *++lpUnparsedStr) ||
  551. !(b3 = *++lpUnparsedStr) ||
  552. !(b4 = *++lpUnparsedStr)) {
  553. SetLastError (ERROR_INVALID_DATA);
  554. bRet = FALSE;
  555. break;
  556. }
  557. lpUnparsedStr++;
  558. *lpParsedStr++ = (AscToHex (b1) << 12) |
  559. (AscToHex (b2) << 8) |
  560. (AscToHex (b3) << 4) |
  561. AscToHex (b4);
  562. }
  563. else {
  564. //
  565. // To take care the case when the DecodeString ends with %
  566. //
  567. if (! (b2 = *++lpUnparsedStr)) {
  568. SetLastError (ERROR_INVALID_DATA);
  569. bRet = FALSE;
  570. break;
  571. }
  572. lpUnparsedStr++;
  573. *lpParsedStr++ = (AscToHex (b1) << 4) | AscToHex (b2);
  574. }
  575. }
  576. else {
  577. *lpParsedStr++ = *lpUnparsedStr++;
  578. }
  579. }
  580. *lpParsedStr = NULL;
  581. return bRet;
  582. }
  583. /********************************************************************************
  584. Name:
  585. AscToHex
  586. Description:
  587. Convert a hex character to the corresponding value (0-0xf);
  588. Arguments:
  589. c: The character
  590. Return Value:
  591. 0xff if the character is not a hex digit
  592. the corresponding numberical value otherwise
  593. ********************************************************************************/
  594. BYTE AscToHex (TCHAR c)
  595. {
  596. UINT uValue = 0xff;
  597. if (_istxdigit (c))
  598. {
  599. if (_istdigit (c))
  600. {
  601. uValue = c - TEXT('0');
  602. }
  603. else
  604. {
  605. uValue = _totlower (c) - TEXT('a') + 10;
  606. }
  607. }
  608. return (BYTE)uValue;
  609. }
  610. /********************************************************************************
  611. Name:
  612. HexToAsc
  613. Description:
  614. Convert a hex character to the corresponding value (0-0xf);
  615. Arguments:
  616. b: The byte (0 to F)
  617. Return Value:
  618. 0 if the character is out of range
  619. the corresponding ASCII of the hex number
  620. ********************************************************************************/
  621. TCHAR HexToAsc( INT b )
  622. {
  623. UINT uValue = 0;
  624. if (0 <= b && b <= 0xf)
  625. {
  626. if (b < 0xa)
  627. {
  628. uValue = TEXT('0') + b;
  629. }
  630. else
  631. {
  632. uValue = TEXT('a') + b - 10;
  633. }
  634. }
  635. return (TCHAR)uValue;
  636. }
  637. /********************************************************************************
  638. Name:
  639. EncodeString
  640. Description:
  641. Convert the normal text string to HTML text string by replace special
  642. characters such as ", <, > with the corresponding HTML code
  643. Arguments:
  644. lpText: the normal text string
  645. bURL: TRUE for encoding a URL string. FALSE otherwise.
  646. Return Value:
  647. Pointer to the HTML string. The caller is responsible to call LocalFree to
  648. free the pointer. NULL is returned if no enougth memory
  649. ********************************************************************************/
  650. LPTSTR EncodeString (LPCTSTR lpText, BOOL bURL)
  651. {
  652. DWORD dwLen;
  653. DWORD dwMaxLen = bURL?3:6; // The maximum length of the encoding characters.
  654. // if it is URL, we enocde it with %xx, so the max len is 3
  655. // otherwise the max len of HTML char is 5,
  656. // it happens when " is encoded (&quot;)
  657. LPTSTR lpHTMLStr = NULL;
  658. if (!lpText || !(dwLen = lstrlen (lpText))) return NULL;
  659. //
  660. // To make life simpler, we allocate the necessary buffer at once instead of
  661. // calling realloc later. Since the encoded string is always freed after it is dumped
  662. // to the client, and the length of the string is limited to the nax length of the URL
  663. // so the modification does not pose extra burden on the system memroy.
  664. //
  665. dwLen = dwMaxLen * dwLen + 1;
  666. if (! (lpHTMLStr = (LPTSTR) LocalAlloc (LPTR, dwLen * sizeof (TCHAR))))
  667. return NULL;
  668. if (bURL) {
  669. LPTSTR lpDst = lpHTMLStr;
  670. while (*lpText) {
  671. switch (*lpText) {
  672. case TEXT ('<'):
  673. case TEXT ('>'):
  674. case TEXT ('"'):
  675. case TEXT ('&'):
  676. case TEXT (' '):
  677. case TEXT ('?'):
  678. *lpDst++ = TEXT ('%');
  679. *lpDst++ = HexToAsc ((*lpText & 0xf0) >> 4);
  680. *lpDst++ = HexToAsc (*lpText & 0x0f);
  681. break;
  682. default:
  683. *lpDst++ = *lpText;
  684. break;
  685. }
  686. lpText++;
  687. }
  688. }
  689. else {
  690. TCHAR szDestChar[3] = {0, 0};
  691. LPTSTR lpChar;
  692. DWORD dwIndex = 0;
  693. while (*lpText) {
  694. switch (*lpText) {
  695. case TEXT ('<'): lpChar = TEXT ("&lt;"); break;
  696. case TEXT ('>'): lpChar = TEXT ("&gt;"); break;
  697. case TEXT ('"'): lpChar = TEXT ("&quot;"); break;
  698. case TEXT ('&'): lpChar = TEXT ("&amp;"); break;
  699. default:
  700. szDestChar[0] = *lpText;
  701. szDestChar[1] = 0;
  702. lpChar = szDestChar;
  703. }
  704. StringCchCopy(lpHTMLStr + dwIndex, dwLen-dwIndex, lpChar);
  705. dwIndex += lstrlen (lpChar);
  706. lpText++;
  707. }
  708. }
  709. return lpHTMLStr;
  710. }
  711. /********************************************************************************
  712. Name:
  713. GetWebpnpUrl
  714. Description:
  715. Given the server name and the printer name, return the Url for webpnp
  716. Currently, the URL is
  717. http://servername/encoded printername/.printer[querystrings]
  718. Arguments:
  719. pszServer: The server name
  720. pszPrinterName: The printer name (unicode string)
  721. pszQueryString: The querystring (optional)
  722. pszURL: The output URL buffer
  723. lpdwSize: The size of the URL buffer (in Character)
  724. Return Value:
  725. If the function succeeds, the return value is TRUE;
  726. If the function fails, the return value is FALSE. To get extended error
  727. information, call GetLastError.
  728. ********************************************************************************/
  729. BOOL GetWebpnpUrl (LPCTSTR pszServer, LPCTSTR pszPrinterName, LPCTSTR pszQueryString,
  730. BOOL bSecure, LPTSTR pszURL, LPDWORD lpdwSize)
  731. {
  732. static TCHAR szHttp[] = TEXT ("http://");
  733. static TCHAR szHttps[] = TEXT ("https://");
  734. static TCHAR szSlash[] = TEXT ("/printers/"); //Remove scripts in the URL . Previous value: TEXT ("/scripts/");
  735. static TCHAR szPrinter[] = TEXT ("/.printer");
  736. LPTSTR pszEncodedName = NULL;
  737. DWORD dwEncodedSize = 0;
  738. DWORD dwSize = 0;
  739. DWORD bRet = FALSE;
  740. size_t cUrlLen = static_cast<size_t>(*lpdwSize);
  741. if (!pszPrinterName || !lpdwSize) {
  742. SetLastError (ERROR_INVALID_DATA);
  743. return FALSE;
  744. }
  745. //
  746. // Calculate buffer size
  747. //
  748. EncodePrinterName (pszPrinterName, NULL, &dwEncodedSize);
  749. if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) {
  750. return FALSE;
  751. }
  752. dwSize = (DWORD)(2 + dwEncodedSize
  753. + COUNTOF (szHttps) + COUNTOF (szSlash) + COUNTOF (szPrinter)
  754. + ((pszServer)? lstrlen (pszServer):0)
  755. + ((pszQueryString)?lstrlen (pszQueryString):0));
  756. if (!pszURL || dwSize > *lpdwSize ) {
  757. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  758. *lpdwSize = dwSize;
  759. return FALSE;
  760. }
  761. if (! (pszEncodedName = (LPTSTR) LocalAlloc (LPTR, sizeof (TCHAR) * dwEncodedSize)))
  762. goto Cleanup;
  763. if (!EncodePrinterName (pszPrinterName, pszEncodedName, &dwEncodedSize))
  764. goto Cleanup;
  765. if (pszServer) {
  766. if (bSecure) {
  767. StringCchCopy (pszURL, cUrlLen, szHttps);
  768. } else {
  769. StringCchCopy (pszURL, cUrlLen, szHttp);
  770. }
  771. StringCchCat (pszURL, cUrlLen, pszServer);
  772. }
  773. StringCchCat (pszURL, cUrlLen, szSlash);
  774. StringCchCat (pszURL, cUrlLen, pszEncodedName);
  775. StringCchCat (pszURL, cUrlLen, szPrinter);
  776. if (pszQueryString) {
  777. StringCchCat (pszURL, cUrlLen, TEXT ("?"));
  778. StringCchCat (pszURL, cUrlLen, pszQueryString);
  779. }
  780. bRet = TRUE;
  781. Cleanup:
  782. if (pszEncodedName) {
  783. LocalFree (pszEncodedName);
  784. }
  785. return bRet;
  786. }
  787. /********************************************************************************
  788. Name:
  789. GetWebUIUrl
  790. Description:
  791. Given the server name and the printer name, return the Url for webpnp
  792. Currently, the URL is
  793. http://servername/printers/ipp_0004.asp?epirnter=encoded printername
  794. Arguments:
  795. pszServer: The server name
  796. pszPrinterName: The printer name (unicode string)
  797. pszURL: The output URL buffer
  798. lpdwSize: The size of the URL buffer (in Character)
  799. Return Value:
  800. If the function succeeds, the return value is TRUE;
  801. If the function fails, the return value is FALSE. To get extended error
  802. information, call GetLastError.
  803. ********************************************************************************/
  804. BOOL GetWebUIUrl (LPCTSTR pszServer, LPCTSTR pszPrinterName, LPTSTR pszURL,
  805. LPDWORD lpdwSize)
  806. {
  807. static TCHAR szHttp[] = TEXT ("http://");
  808. static TCHAR szPrinter[] = TEXT ("/printers/ipp_0004.asp?eprinter=");
  809. LPTSTR pszEncodedName = NULL;
  810. DWORD dwEncodedSize = 0;
  811. DWORD dwSize = 0;
  812. DWORD bRet = FALSE;
  813. size_t cUrlLen = static_cast<size_t>(*lpdwSize);
  814. if (!pszPrinterName || !lpdwSize) {
  815. SetLastError (ERROR_INVALID_DATA);
  816. return FALSE;
  817. }
  818. //
  819. // Calculate buffer size
  820. //
  821. EncodePrinterName (pszPrinterName, NULL, &dwEncodedSize);
  822. if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) {
  823. return FALSE;
  824. }
  825. dwSize = (DWORD)(2 + dwEncodedSize
  826. + COUNTOF (szHttp) + COUNTOF (szPrinter)
  827. + ((pszServer)? lstrlen (pszServer):0));
  828. if (!pszURL || dwSize > *lpdwSize ) {
  829. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  830. *lpdwSize = dwSize;
  831. return FALSE;
  832. }
  833. if (! (pszEncodedName = (LPTSTR) LocalAlloc (LPTR, sizeof (TCHAR) * dwEncodedSize)))
  834. goto Cleanup;
  835. if (!EncodePrinterName (pszPrinterName, pszEncodedName, &dwEncodedSize))
  836. goto Cleanup;
  837. if (pszServer) {
  838. StringCchCopy (pszURL, cUrlLen, szHttp);
  839. StringCchCat (pszURL, cUrlLen, pszServer);
  840. }
  841. StringCchCat(pszURL, cUrlLen, szPrinter);
  842. StringCchCat(pszURL, cUrlLen, pszEncodedName);
  843. bRet = TRUE;
  844. Cleanup:
  845. if (pszEncodedName) {
  846. LocalFree (pszEncodedName);
  847. }
  848. return bRet;
  849. }
  850. /********************************************************************************
  851. Name:
  852. AssignString
  853. Description:
  854. Perform an assign operation
  855. l = r
  856. Return Value:
  857. If the function succeeds, the return value is TRUE;
  858. If the function fails, the return value is FALSE. To get extended error
  859. information, call GetLastError.
  860. ********************************************************************************/
  861. BOOL AssignString (
  862. LPTSTR &l,
  863. LPCTSTR r)
  864. {
  865. if (l) {
  866. LocalFree (l);
  867. l = NULL;
  868. }
  869. if (!r) {
  870. return TRUE;
  871. }
  872. else if (l = (LPTSTR) LocalAlloc (LPTR, (1 + lstrlen (r)) * sizeof (TCHAR))) {
  873. StringCchCopy( l, 1+lstrlen(r), r);
  874. return TRUE;
  875. }
  876. return FALSE;
  877. }
  878. /****************************************************************** Method ***\
  879. * CWebLst::CWebLst (Constructor)
  880. *
  881. * Initializes the CWebLst object.
  882. *
  883. \*****************************************************************************/
  884. CWebLst::CWebLst(VOID)
  885. {
  886. m_cbMax = WEBLST_BLKSIZE;
  887. m_cbLst = 0;
  888. m_pbLst = (PBYTE)webAlloc(m_cbMax);
  889. m_pbPtr = m_pbLst;
  890. m_cItems = 0;
  891. }
  892. /****************************************************************** Method ***\
  893. * CWebLst::~CWebLst (Destructor)
  894. *
  895. * Free up the CWebLst object.
  896. *
  897. \*****************************************************************************/
  898. CWebLst::~CWebLst(VOID)
  899. {
  900. webFree(m_pbLst);
  901. }
  902. /****************************************************************** Method ***\
  903. * CWebLst::Add
  904. *
  905. * Add an item to our list.
  906. *
  907. \*****************************************************************************/
  908. BOOL CWebLst::Add(
  909. PCTSTR lpszName)
  910. {
  911. PBYTE pbNew;
  912. DWORD cbPtr;
  913. DWORD cbNew;
  914. DWORD cbStr;
  915. BOOL bRet = FALSE;
  916. if (m_pbLst) {
  917. //
  918. // Reallocate the buffer is a bigger size is necessary.
  919. //
  920. cbStr = webStrSize(lpszName);
  921. if ((m_cbLst + cbStr) > m_cbMax) {
  922. cbNew = m_cbMax + WEBLST_BLKSIZE;
  923. cbPtr = (DWORD)(m_pbPtr - m_pbLst);
  924. if (pbNew = (PBYTE)webRealloc(m_pbLst, m_cbMax, cbNew)) {
  925. m_cbMax = cbNew;
  926. m_pbLst = pbNew;
  927. m_pbPtr = m_pbLst + (DWORD_PTR)cbPtr;
  928. } else {
  929. goto AddEnd;
  930. }
  931. }
  932. //
  933. // Copy the item.
  934. //
  935. memcpy(m_pbPtr, lpszName, cbStr);
  936. m_cbLst += cbStr;
  937. m_pbPtr += cbStr;
  938. m_cItems++;
  939. bRet = TRUE;
  940. }
  941. AddEnd:
  942. return bRet;
  943. }
  944. /****************************************************************** Method ***\
  945. * CWebLst::Count
  946. *
  947. * Returns a count of items.
  948. *
  949. \*****************************************************************************/
  950. DWORD CWebLst::Count(VOID)
  951. {
  952. return m_cItems;
  953. }
  954. /****************************************************************** Method ***\
  955. * CWebLst::Get
  956. *
  957. * Retrieve current string.
  958. *
  959. \*****************************************************************************/
  960. PCTSTR CWebLst::Get(VOID)
  961. {
  962. return (m_cItems ? (PCTSTR)m_pbPtr : NULL);
  963. }
  964. /****************************************************************** Method ***\
  965. * CWebLst::Next
  966. *
  967. *
  968. \*****************************************************************************/
  969. BOOL CWebLst::Next(VOID)
  970. {
  971. m_pbPtr += webStrSize((PCTSTR)m_pbPtr);
  972. return (*m_pbPtr ? TRUE : FALSE);
  973. }
  974. /****************************************************************** Method ***\
  975. * CWebLst::Reset
  976. *
  977. *
  978. \*****************************************************************************/
  979. VOID CWebLst::Reset(VOID)
  980. {
  981. m_pbPtr = m_pbLst;
  982. }