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.

466 lines
12 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. DWORD dwTempSize = 0;
  93. INT rc = 0;
  94. if( !StringLength ) {
  95. //
  96. // StringLength is just the
  97. // number of characters in the string
  98. //
  99. StringLength = wcslen( pUnicode );
  100. }
  101. //
  102. // Include one for the NULL
  103. //
  104. StringLength++;
  105. //
  106. // Unfortunately, WideCharToMultiByte doesn't do conversion in place,
  107. // so allocate a temporary buffer, which we can then copy:
  108. //
  109. if( pAnsi == (LPSTR)pUnicode )
  110. {
  111. // Allocate enough memory anyway (in case of the far easten language
  112. // the conversion needs that much
  113. dwTempSize = ((1 + StringLength) * 2);
  114. pTempBuf = (LPSTR) LocalAlloc( LPTR, dwTempSize );
  115. if (!pTempBuf) {
  116. return 0;
  117. }
  118. pAnsi = pTempBuf;
  119. }
  120. if( pAnsi )
  121. {
  122. rc = WideCharToMultiByte( CP_ACP,
  123. 0,
  124. pUnicode,
  125. StringLength,
  126. pAnsi,
  127. StringLength * 2,
  128. NULL,
  129. NULL );
  130. }
  131. /* If pTempBuf is non-null, we must copy the resulting string
  132. * so that it looks as if we did it in place:
  133. */
  134. if( pTempBuf && ( rc > 0 ) )
  135. {
  136. pAnsi = (LPSTR)pUnicode;
  137. StringCbCopyA( pAnsi, dwTempSize, pTempBuf );
  138. LocalFree( pTempBuf );
  139. }
  140. return rc;
  141. }
  142. LPWSTR
  143. AllocateUnicodeString(
  144. LPSTR pAnsiString
  145. )
  146. {
  147. LPWSTR pUnicodeString;
  148. if (!pAnsiString)
  149. return NULL;
  150. pUnicodeString = (LPWSTR) LocalAlloc(LPTR, strlen(pAnsiString) * sizeof(WCHAR) +
  151. sizeof(WCHAR));
  152. if (pUnicodeString)
  153. AnsiToUnicodeString(pAnsiString, pUnicodeString, 0);
  154. return pUnicodeString;
  155. }
  156. //======================================================================
  157. // HTML HELPER FUNCTIONS
  158. //======================================================================
  159. /********************************************************************************
  160. Name:
  161. htmlSendRedirect
  162. Description:
  163. Send a redirect to the client to let the client request the server again
  164. Arguments:
  165. pAllInfo: Pointer to the ALLINFO structure
  166. lpszURL: The redirect URL. It is the unicode version of the URL.
  167. Its content will be modified!!!
  168. Return Value:
  169. TRUE if succeed, FASE otherwise.
  170. ********************************************************************************/
  171. BOOL htmlSendRedirect(PALLINFO pAllInfo, LPTSTR lpszURL)
  172. {
  173. DWORD dwLen;
  174. if (lpszURL && (dwLen = UnicodeToAnsiString (lpszURL, (LPSTR) lpszURL, NULL))) {
  175. return pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID,
  176. HSE_REQ_SEND_URL_REDIRECT_RESP,
  177. (LPVOID) lpszURL,
  178. &dwLen,
  179. NULL);
  180. }
  181. else
  182. return FALSE;
  183. }
  184. unsigned long GetIPAddr (LPSTR lpName)
  185. {
  186. struct hostent * hp;
  187. struct sockaddr_in dest,from;
  188. if (! (hp = gethostbyname(lpName))) {
  189. return inet_addr(lpName);
  190. }
  191. memcpy (&(dest.sin_addr),hp->h_addr,hp->h_length);
  192. return dest.sin_addr.S_un.S_addr;
  193. }
  194. /********************************************************************************
  195. Name:
  196. EncodeFriendlyName
  197. Description:
  198. Encode the friendly name to avoid special characters
  199. Arguments:
  200. lpText: the normal text string
  201. Return Value:
  202. Pointer to the HTML string. The caller is responsible to free the pointer.
  203. NULL is returned if no enougth memory
  204. ********************************************************************************/
  205. LPTSTR EncodeFriendlyName (LPCTSTR lpText)
  206. {
  207. DWORD dwLen;
  208. LPTSTR lpHTMLStr = NULL;
  209. dwLen = 0;
  210. if (!EncodePrinterName (lpText, NULL, &dwLen) &&
  211. GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  212. (lpHTMLStr = (LPTSTR) LocalAlloc (LPTR, dwLen * sizeof (TCHAR))) &&
  213. EncodePrinterName (lpText, lpHTMLStr, &dwLen))
  214. return lpHTMLStr;
  215. else {
  216. LocalFree (lpHTMLStr);
  217. return NULL;
  218. }
  219. }
  220. /********************************************************************************
  221. Name:
  222. DecodeFriendlyName
  223. Description:
  224. Decode the frienly name to get rid of %xx pattern.
  225. Arguments:
  226. lpText: the encoded printer friendly name
  227. Return Value:
  228. Pointer to the decoded friendly name.
  229. ********************************************************************************/
  230. LPTSTR DecodeFriendlyName (LPTSTR lpStr)
  231. {
  232. LPTSTR lpParsedStr = lpStr;
  233. LPTSTR lpUnparsedStr = lpStr;
  234. TCHAR d1, d2;
  235. if (!lpStr) return lpStr;
  236. while (*lpUnparsedStr) {
  237. switch (*lpUnparsedStr) {
  238. case '~':
  239. // To take care the case when the DecodeString ends with %
  240. if (! (d1 = *++lpUnparsedStr) || (! (d2 = *++lpUnparsedStr)))
  241. break;
  242. lpUnparsedStr++;
  243. *lpParsedStr++ = AscToHex (d1) * 16 + AscToHex (d2);
  244. break;
  245. default:
  246. *lpParsedStr++ = *lpUnparsedStr++;
  247. }
  248. }
  249. *lpParsedStr = NULL;
  250. return lpStr;
  251. }
  252. BOOL IsClientHttpProvider (PALLINFO pAllInfo)
  253. {
  254. EXTENSION_CONTROL_BLOCK *pECB;
  255. DWORD dwVersion = 0;
  256. char buf[64];
  257. DWORD dwSize = sizeof (buf);
  258. // This string is copied from ../inetpp/globals.c
  259. const char c_szUserAgent[] = "Internet Print Provider";
  260. pECB = pAllInfo->pECB;
  261. // Check the UserAgent variable at first to see the IE version
  262. if (pECB->GetServerVariable (pECB->ConnID, "HTTP_USER_AGENT", buf, &dwSize))
  263. return !strcmp (buf, c_szUserAgent);
  264. else
  265. return FALSE;
  266. }
  267. BOOL htmlSendHeader(PALLINFO pAllInfo, LPTSTR lpszHeader, LPTSTR lpszContent)
  268. {
  269. LPSTR lpszAnsiHeader = NULL;
  270. LPSTR lpszAnsiContent = NULL;
  271. BOOL bRet = FALSE;
  272. DWORD dwSize = 0;
  273. if (!lpszHeader || !lpszContent) {
  274. goto Cleanup;
  275. }
  276. lpszAnsiHeader = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszHeader)) * sizeof (TCHAR));
  277. if (lpszContent)
  278. lpszAnsiContent = (LPSTR) LocalAlloc (LPTR, (1 + lstrlen (lpszContent)) * sizeof (TCHAR));
  279. if (!lpszAnsiHeader || !lpszAnsiContent) {
  280. goto Cleanup;
  281. }
  282. // Make sure the conversion routines actually converted some characters
  283. //
  284. dwSize = UnicodeToAnsiString(lpszHeader, lpszAnsiHeader, 0);
  285. if (dwSize > 0)
  286. {
  287. dwSize = UnicodeToAnsiString(lpszContent, lpszAnsiContent, 0);
  288. if (dwSize > 0)
  289. {
  290. bRet = pAllInfo->pECB->ServerSupportFunction(pAllInfo->pECB->ConnID,
  291. HSE_REQ_SEND_RESPONSE_HEADER,
  292. (LPVOID) lpszAnsiHeader,
  293. &dwSize,
  294. (LPDWORD) lpszAnsiContent);
  295. }
  296. }
  297. Cleanup:
  298. LocalFree (lpszAnsiHeader);
  299. LocalFree (lpszAnsiContent);
  300. return bRet;
  301. }
  302. BOOL htmlSend500Header(PALLINFO pAllInfo, DWORD dwError)
  303. {
  304. TCHAR szStatusPattern [] = TEXT ("500 %d");
  305. LPTSTR lpszHeader = NULL;
  306. DWORD bRet = FALSE;
  307. DWORD dwSize = 0;
  308. LPTSTR pszErrorContent = GetString(pAllInfo, IDS_ERROR_500CONTENT);
  309. dwSize = sizeof (szStatusPattern) + (sizeof (TCHAR) * 40);
  310. if (! (lpszHeader = (LPTSTR) LocalAlloc (LPTR, dwSize)))
  311. goto Cleanup;
  312. else
  313. {
  314. StringCbPrintf(lpszHeader, dwSize, szStatusPattern, dwError);
  315. bRet = htmlSendHeader(pAllInfo, lpszHeader, pszErrorContent);
  316. }
  317. Cleanup:
  318. if (lpszHeader) {
  319. LocalFree (lpszHeader);
  320. }
  321. return bRet;
  322. }
  323. /********************************************************************************
  324. Name:
  325. ProcessErrorMessage
  326. Description:
  327. Do the authentication if the error is Permission denied, show the error
  328. meesage otherwise
  329. Arguments:
  330. pAllInfo: Pointer to the infor struction
  331. dwError(optional): Error code, if not provided, dwError in
  332. the pAllInfo is used
  333. Return Value:
  334. HSE_STATUS_SUCCESS if ok.
  335. ********************************************************************************/
  336. DWORD ProcessErrorMessage (PALLINFO pAllInfo, DWORD dwError)
  337. {
  338. DWORD dwRet = HSE_STATUS_ERROR;
  339. if (!pAllInfo) {
  340. return dwRet;
  341. }
  342. if (dwError != ERROR_SUCCESS)
  343. pAllInfo->dwError = dwError;
  344. SetLastError (pAllInfo->dwError);
  345. if (pAllInfo->dwError == ERROR_ACCESS_DENIED ||
  346. pAllInfo->dwError == ERROR_INVALID_OWNER) {
  347. if (AuthenticateUser(pAllInfo))
  348. dwRet = HSE_STATUS_SUCCESS;
  349. } else {
  350. if (htmlSend500Header(pAllInfo, dwError))
  351. dwRet = HSE_STATUS_SUCCESS;
  352. }
  353. return dwRet;
  354. }
  355. LPTSTR AllocStr( LPCTSTR pStr )
  356. {
  357. LPTSTR pMem = NULL;
  358. DWORD cbStr;
  359. if( !pStr )
  360. return NULL;
  361. cbStr = lstrlen( pStr )*sizeof(TCHAR) + sizeof(TCHAR);
  362. if( pMem = (LPTSTR)LocalAlloc( LPTR, cbStr ))
  363. StringCbCopy( pMem, cbStr, pStr );
  364. return pMem;
  365. }