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.

525 lines
14 KiB

  1. /*****************************************************************************\
  2. * MODULE: inetinfo.cxx
  3. *
  4. *
  5. * PURPOSE: Handles the data pumping to the client via IIS
  6. *
  7. * Copyright (C) 1996-1997 Microsoft Corporation
  8. *
  9. * History:
  10. * 01/16/96 eriksn Created based on ISAPI sample DLL
  11. * 07/15/96 babakj Moved to a separate file
  12. * 05/12/97 weihaic ASP template support
  13. *
  14. \*****************************************************************************/
  15. #include "pch.h"
  16. #include "printers.h"
  17. static char c_szRemoteHost[] = "REMOTE_HOST";
  18. static char c_szServerName[] = "SERVER_NAME";
  19. /* AnsiToUnicodeString
  20. *
  21. * Parameters:
  22. *
  23. * pAnsi - A valid source ANSI string.
  24. *
  25. * pUnicode - A pointer to a buffer large enough to accommodate
  26. * the converted string.
  27. *
  28. * StringLength - The length of the source ANSI string.
  29. * If 0 , the string is assumed to be
  30. * null-terminated.
  31. *
  32. * Return:
  33. *
  34. * The return value from MultiByteToWideChar, the number of
  35. * wide characters returned.
  36. *
  37. *
  38. */
  39. INT AnsiToUnicodeString( LPSTR pAnsi, LPWSTR pUnicode, UINT StringLength )
  40. {
  41. INT iReturn;
  42. if( StringLength == 0 )
  43. StringLength = strlen( pAnsi );
  44. iReturn = MultiByteToWideChar(CP_ACP,
  45. MB_PRECOMPOSED,
  46. pAnsi,
  47. StringLength + 1,
  48. pUnicode,
  49. StringLength + 1 );
  50. //
  51. // Ensure NULL termination.
  52. //
  53. pUnicode[StringLength] = 0;
  54. return iReturn;
  55. }
  56. /* UnicodeToAnsiString
  57. *
  58. * Parameters:
  59. *
  60. * pUnicode - A valid source Unicode string.
  61. *
  62. * pANSI - A pointer to a buffer large enough to accommodate
  63. * the converted string.
  64. *
  65. * StringLength - The length of the source Unicode string.
  66. * If 0 , the string is assumed to be
  67. * null-terminated.
  68. *
  69. *
  70. * Notes:
  71. * Added the #ifdef DBCS directive for MS-KK, if compiled
  72. * with DBCS enabled, we will allocate twice the size of the
  73. * buffer including the null terminator to take care of double
  74. * byte character strings - KrishnaG
  75. *
  76. * pUnicode is truncated to StringLength characters.
  77. *
  78. * Return:
  79. *
  80. * The return value from WideCharToMultiByte, the number of
  81. * multi-byte characters returned.
  82. *
  83. *
  84. */
  85. INT
  86. UnicodeToAnsiString(
  87. LPWSTR pUnicode,
  88. LPSTR pAnsi,
  89. UINT StringLength)
  90. {
  91. LPSTR pTempBuf = NULL;
  92. INT rc = 0;
  93. if( !StringLength ) {
  94. //
  95. // StringLength is just the
  96. // number of characters in the string
  97. //
  98. StringLength = wcslen( pUnicode );
  99. }
  100. //
  101. // WideCharToMultiByte doesn't NULL terminate if we're copying
  102. // just part of the string, so terminate here.
  103. //
  104. //if (pUnicode[StringLength])
  105. // pUnicode[StringLength] = 0;
  106. //
  107. // Include one for the NULL
  108. //
  109. StringLength++;
  110. //
  111. // Unfortunately, WideCharToMultiByte doesn't do conversion in place,
  112. // so allocate a temporary buffer, which we can then copy:
  113. //
  114. if( pAnsi == (LPSTR)pUnicode )
  115. {
  116. // Allocate enough memory anyway (in case of the far easten language
  117. // the conversion needs that much
  118. pTempBuf = (LPSTR) LocalAlloc( LPTR, (1 + StringLength) * 2 );
  119. if (!pTempBuf) {
  120. return 0;
  121. }
  122. pAnsi = pTempBuf;
  123. }
  124. if( pAnsi )
  125. {
  126. rc = WideCharToMultiByte( CP_ACP,
  127. 0,
  128. pUnicode,
  129. StringLength,
  130. pAnsi,
  131. StringLength * 2,
  132. NULL,
  133. NULL );
  134. }
  135. /* If pTempBuf is non-null, we must copy the resulting string
  136. * so that it looks as if we did it in place:
  137. */
  138. if( pTempBuf && ( rc > 0 ) )
  139. {
  140. pAnsi = (LPSTR)pUnicode;
  141. strcpy( pAnsi, pTempBuf );
  142. LocalFree( pTempBuf );
  143. }
  144. return rc;
  145. }
  146. LPWSTR
  147. AllocateUnicodeString(
  148. LPSTR pAnsiString
  149. )
  150. {
  151. LPWSTR pUnicodeString;
  152. if (!pAnsiString)
  153. return NULL;
  154. pUnicodeString = (LPWSTR) LocalAlloc(LPTR, strlen(pAnsiString) * sizeof(WCHAR) +
  155. sizeof(WCHAR));
  156. if (pUnicodeString)
  157. AnsiToUnicodeString(pAnsiString, pUnicodeString, 0);
  158. return pUnicodeString;
  159. }
  160. //======================================================================
  161. // HTML HELPER FUNCTIONS
  162. //======================================================================
  163. ///////////////////////////////////////////////////////////////////////////////////////
  164. //
  165. // Server communications: First we send a HSE_REQ_SEND_RESPONSE_HEADER.
  166. // Then we do WriteClient if we have leftover data.
  167. //
  168. // This routune allows a string to be written to the client using printf syntax.
  169. //
  170. ///////////////////////////////////////////////////////////////////////////////////////
  171. /********************************************************************************
  172. Name:
  173. htmlSendRedirect
  174. Description:
  175. Send a redirect to the client to let the client request the server again
  176. Arguments:
  177. pAllInfo: Pointer to the ALLINFO structure
  178. lpszURL: The redirect URL. It is the unicode version of the URL.
  179. Its content will be modified!!!
  180. Return Value:
  181. TRUE if succeed, FASE otherwise.
  182. ********************************************************************************/
  183. BOOL htmlSendRedirect(PALLINFO pAllInfo, LPTSTR lpszURL)
  184. {
  185. DWORD dwLen;
  186. if (lpszURL && (dwLen = UnicodeToAnsiString (lpszURL, (LPSTR) lpszURL, NULL))) {
  187. return pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID,
  188. HSE_REQ_SEND_URL_REDIRECT_RESP,
  189. (LPVOID) lpszURL,
  190. &dwLen,
  191. NULL);
  192. }
  193. else
  194. return FALSE;
  195. }
  196. unsigned long GetIPAddr (LPSTR lpName)
  197. {
  198. struct hostent * hp;
  199. struct sockaddr_in dest,from;
  200. if (! (hp = gethostbyname(lpName))) {
  201. return inet_addr(lpName);
  202. }
  203. memcpy (&(dest.sin_addr),hp->h_addr,hp->h_length);
  204. return dest.sin_addr.S_un.S_addr;
  205. }
  206. #if 0
  207. BOOL IsClientSameAsServer(EXTENSION_CONTROL_BLOCK *pECB)
  208. {
  209. LPSTR lpServer = NULL;
  210. LPSTR lpClient = NULL;
  211. DWORD dwSize = 32;
  212. BOOL bRet = FALSE;
  213. DWORD dwClient;
  214. DWORD dwServer;
  215. if (! (lpClient = (LPSTR) LocalAlloc (LPTR, dwSize))) goto Cleanup;
  216. if (!pECB->GetServerVariable (pECB->ConnID, c_szRemoteHost, lpClient, &dwSize))
  217. if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) {
  218. LocalFree (lpClient);
  219. lpClient = NULL;
  220. if ( !(lpClient = (LPSTR) LocalAlloc (LPTR, dwSize)) ||
  221. !pECB->GetServerVariable (pECB->ConnID, c_szRemoteHost, lpClient, &dwSize))
  222. goto Cleanup;;
  223. }
  224. else
  225. goto Cleanup;
  226. if (! (lpServer = (LPSTR) LocalAlloc (LPTR, dwSize))) goto Cleanup;
  227. if (!pECB->GetServerVariable (pECB->ConnID, c_szServerName, lpServer, &dwSize))
  228. if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) {
  229. LocalFree (lpServer);
  230. lpServer = NULL;
  231. if (!(lpServer = (LPSTR) LocalAlloc (LPTR, dwSize)) ||
  232. !pECB->GetServerVariable (pECB->ConnID, c_szServerName, lpServer, &dwSize))
  233. goto Cleanup;
  234. }
  235. else
  236. goto Cleanup;
  237. bRet = GetIPAddr (lpClient) == GetIPAddr (lpServer);
  238. Cleanup:
  239. LocalFree (lpClient);
  240. LocalFree (lpServer);
  241. return bRet;
  242. }
  243. #endif
  244. /********************************************************************************
  245. Name:
  246. EncodeFriendlyName
  247. Description:
  248. Encode the friendly name to avoid special characters
  249. Arguments:
  250. lpText: the normal text string
  251. Return Value:
  252. Pointer to the HTML string. The caller is responsible to free the pointer.
  253. NULL is returned if no enougth memory
  254. ********************************************************************************/
  255. LPTSTR EncodeFriendlyName (LPCTSTR lpText)
  256. {
  257. DWORD dwLen;
  258. LPTSTR lpHTMLStr = NULL;
  259. dwLen = 0;
  260. if (!EncodePrinterName (lpText, NULL, &dwLen) &&
  261. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  262. (lpHTMLStr = (LPTSTR) LocalAlloc (LPTR, dwLen * sizeof (TCHAR))) &&
  263. EncodePrinterName (lpText, lpHTMLStr, &dwLen))
  264. return lpHTMLStr;
  265. else {
  266. LocalFree (lpHTMLStr);
  267. return NULL;
  268. }
  269. }
  270. /********************************************************************************
  271. Name:
  272. DecodeFriendlyName
  273. Description:
  274. Decode the frienly name to get rid of %xx pattern.
  275. Arguments:
  276. lpText: the encoded printer friendly name
  277. Return Value:
  278. Pointer to the decoded friendly name.
  279. ********************************************************************************/
  280. LPTSTR DecodeFriendlyName (LPTSTR lpStr)
  281. {
  282. LPTSTR lpParsedStr = lpStr;
  283. LPTSTR lpUnparsedStr = lpStr;
  284. TCHAR d1, d2;
  285. if (!lpStr) return lpStr;
  286. while (*lpUnparsedStr) {
  287. switch (*lpUnparsedStr) {
  288. case '~':
  289. // To take care the case when the DecodeString ends with %
  290. if (! (d1 = *++lpUnparsedStr) || (! (d2 = *++lpUnparsedStr)))
  291. break;
  292. lpUnparsedStr++;
  293. *lpParsedStr++ = AscToHex (d1) * 16 + AscToHex (d2);
  294. break;
  295. default:
  296. *lpParsedStr++ = *lpUnparsedStr++;
  297. }
  298. }
  299. *lpParsedStr = NULL;
  300. return lpStr;
  301. }
  302. BOOL IsClientHttpProvider (PALLINFO pAllInfo)
  303. {
  304. EXTENSION_CONTROL_BLOCK *pECB;
  305. DWORD dwVersion = 0;
  306. char buf[64];
  307. DWORD dwSize = sizeof (buf);
  308. // This string is copied from ../inetpp/globals.c
  309. const char c_szUserAgent[] = "Internet Print Provider";
  310. pECB = pAllInfo->pECB;
  311. // Check the UserAgent variable at first to see the IE version
  312. if (pECB->GetServerVariable (pECB->ConnID, "HTTP_USER_AGENT", buf, &dwSize))
  313. return !strcmp (buf, c_szUserAgent);
  314. else
  315. return FALSE;
  316. }
  317. BOOL htmlSendHeader(PALLINFO pAllInfo, LPTSTR lpszHeader, LPTSTR lpszContent)
  318. {
  319. LPSTR lpszAnsiHeader = NULL;
  320. LPSTR lpszAnsiContent = NULL;
  321. BOOL bRet = FALSE;
  322. DWORD dwSize = 0;
  323. lpszAnsiHeader = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszHeader)) * sizeof (TCHAR));
  324. if (lpszContent)
  325. lpszAnsiContent = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszContent)) * sizeof (TCHAR));
  326. if (!lpszAnsiHeader || !lpszAnsiContent) {
  327. goto Cleanup;
  328. }
  329. UnicodeToAnsiString(lpszHeader, lpszAnsiHeader, 0);
  330. if (lpszContent)
  331. dwSize = UnicodeToAnsiString(lpszContent, lpszAnsiContent, 0);
  332. bRet = pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID,
  333. HSE_REQ_SEND_RESPONSE_HEADER,
  334. (LPVOID) lpszAnsiHeader,
  335. &dwSize,
  336. (LPDWORD) lpszAnsiContent);
  337. Cleanup:
  338. LocalFree (lpszAnsiHeader);
  339. LocalFree (lpszAnsiContent);
  340. return bRet;
  341. }
  342. BOOL htmlSend500Header(PALLINFO pAllInfo, DWORD dwError)
  343. {
  344. TCHAR szStatusPattern [] = TEXT ("500 %d");
  345. LPTSTR lpszHeader = NULL;
  346. DWORD bRet = FALSE;
  347. LPTSTR pszErrorContent = GetString(pAllInfo, IDS_ERROR_500CONTENT);
  348. if (! (lpszHeader = (LPTSTR) LocalAlloc (LPTR,
  349. sizeof (szStatusPattern) + sizeof (TCHAR) * 40)))
  350. goto Cleanup;
  351. else {
  352. wsprintf (lpszHeader, szStatusPattern, dwError);
  353. bRet = htmlSendHeader(pAllInfo, lpszHeader, pszErrorContent);
  354. }
  355. Cleanup:
  356. if (lpszHeader) {
  357. LocalFree (lpszHeader);
  358. }
  359. return bRet;
  360. }
  361. /********************************************************************************
  362. Name:
  363. ProcessErrorMessage
  364. Description:
  365. Do the authentication if the error is Permission denied, show the error
  366. meesage otherwise
  367. Arguments:
  368. pAllInfo: Pointer to the infor struction
  369. dwError(optional): Error code, if not provided, dwError in
  370. the pAllInfo is used
  371. Return Value:
  372. HSE_STATUS_SUCCESS if ok.
  373. ********************************************************************************/
  374. DWORD ProcessErrorMessage (PALLINFO pAllInfo, DWORD dwError)
  375. {
  376. DWORD dwRet = HSE_STATUS_ERROR;
  377. if (!pAllInfo) {
  378. return dwRet;
  379. }
  380. if (dwError != ERROR_SUCCESS)
  381. pAllInfo->dwError = dwError;
  382. SetLastError (pAllInfo->dwError);
  383. if (pAllInfo->dwError == ERROR_ACCESS_DENIED ||
  384. pAllInfo->dwError == ERROR_INVALID_OWNER) {
  385. if (AuthenticateUser(pAllInfo))
  386. dwRet = HSE_STATUS_SUCCESS;
  387. } else {
  388. #if 0
  389. if (IsClientHttpProvider (pAllInfo)) {
  390. // This piece will not be needed when IPP port validation (OpenPrinter) is done by Chris.
  391. LPTSTR pszErrorContent = GetString(pAllInfo, IDS_ERROR_501CONTENT);
  392. return htmlSendHeader (pAllInfo,
  393. TEXT ("501 Function not supported"),
  394. pszErrorContent);
  395. }
  396. else {
  397. #endif
  398. if (htmlSend500Header(pAllInfo, dwError))
  399. dwRet = HSE_STATUS_SUCCESS;
  400. }
  401. return dwRet;
  402. }
  403. LPTSTR AllocStr( LPCTSTR pStr )
  404. {
  405. LPTSTR pMem = NULL;
  406. DWORD cbStr;
  407. if( !pStr )
  408. return NULL;
  409. cbStr = lstrlen( pStr )*sizeof(TCHAR) + sizeof(TCHAR);
  410. if( pMem = (LPTSTR)LocalAlloc( LPTR, cbStr ))
  411. CopyMemory( pMem, pStr, cbStr );
  412. return pMem;
  413. }