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.

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