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.

381 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. inetapiu.cxx
  5. Abstract:
  6. Contains WinInet API utility & sub-API functions
  7. Contents:
  8. wInternetQueryDataAvailable
  9. Author:
  10. Richard L Firth (rfirth) 16-Feb-1996
  11. Environment:
  12. Win32 user-level
  13. Revision History:
  14. 16-Feb-1996 rfirth
  15. Created
  16. --*/
  17. #include <wininetp.h>
  18. #include "inetapiu.h"
  19. DWORD
  20. InbLocalEndCacheWrite(
  21. IN HINTERNET hFtpFile,
  22. IN LPSTR lpszFileExtension,
  23. IN BOOL fNormal
  24. );
  25. DWORD
  26. InbGopherLocalEndCacheWrite(
  27. IN HINTERNET hGopherFile,
  28. IN LPSTR lpszFileExtension,
  29. IN BOOL fNormal
  30. );
  31. //
  32. // functions
  33. //
  34. BOOL
  35. wInternetQueryDataAvailable(
  36. IN LPVOID hFileMapped,
  37. OUT LPDWORD lpdwNumberOfBytesAvailable,
  38. IN DWORD dwFlags,
  39. IN DWORD_PTR dwContext
  40. )
  41. /*++
  42. Routine Description:
  43. Part 2 of InternetQueryDataAvailabe. This function is called by the async
  44. worker thread in order to resume InternetQueryDataAvailable(), and by the
  45. app as the worker part of the API, post validation
  46. We can query available data for handle types that return data, either from
  47. a socket, or from a cache file:
  48. - HTTP request
  49. - FTP file
  50. - FTP find
  51. - FTP find HTML
  52. - gopher file
  53. - gopher find
  54. - gopher find HTML
  55. Arguments:
  56. hFileMapped - the mapped HINTERNET
  57. lpdwNumberOfBytesAvailable - where the number of bytes is returned
  58. dwFlags - flags controlling operation
  59. dwContext - context value for callbacks
  60. Return Value:
  61. DWORD
  62. Success - ERROR_SUCCESS
  63. Failure -
  64. --*/
  65. {
  66. DEBUG_ENTER((DBG_INET,
  67. Bool,
  68. "wInternetQueryDataAvailable",
  69. "%#x, %#x, %#x, %#x",
  70. hFileMapped,
  71. lpdwNumberOfBytesAvailable,
  72. dwFlags,
  73. dwContext
  74. ));
  75. LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
  76. DWORD error;
  77. HINTERNET_HANDLE_TYPE handleType;
  78. INET_ASSERT(hFileMapped);
  79. //
  80. // as usual, grab the per-thread info block
  81. //
  82. if (lpThreadInfo == NULL) {
  83. INET_ASSERT(FALSE);
  84. error = ERROR_INTERNET_INTERNAL_ERROR;
  85. goto quit;
  86. }
  87. //
  88. // if this is the async worker thread then set the context, handle, and
  89. // last-error info in the per-thread data block before we go any further
  90. // (we already did this on the sync path)
  91. //
  92. if (lpThreadInfo->IsAsyncWorkerThread) {
  93. _InternetSetContext(lpThreadInfo,
  94. ((INTERNET_HANDLE_OBJECT *)hFileMapped)->GetContext()
  95. );
  96. _InternetSetObjectHandle(lpThreadInfo,
  97. ((HANDLE_OBJECT *)hFileMapped)->GetPseudoHandle(),
  98. hFileMapped
  99. );
  100. _InternetClearLastError(lpThreadInfo);
  101. //
  102. // we should only be here in async mode if there was no data immediately
  103. // available
  104. //
  105. INET_ASSERT(!((INTERNET_HANDLE_OBJECT *)hFileMapped)->IsDataAvailable());
  106. }
  107. //
  108. // get the local handle for FTP & gopher
  109. //
  110. HINTERNET hLocal;
  111. error = RGetLocalHandle(hFileMapped, &hLocal);
  112. if (error != ERROR_SUCCESS) {
  113. goto quit;
  114. }
  115. //
  116. // we copy the number of bytes available to a local variable first, and
  117. // only update the caller's variable if we succeed
  118. //
  119. DWORD bytesAvailable;
  120. //
  121. // get the current data available, based on the handle type
  122. //
  123. switch (handleType = ((HANDLE_OBJECT *)hFileMapped)->GetHandleType()) {
  124. case TypeHttpRequestHandle:
  125. error = ((HTTP_REQUEST_HANDLE_OBJECT *)hFileMapped)
  126. ->QueryDataAvailable(&bytesAvailable);
  127. break;
  128. case TypeFtpFileHandle:
  129. case TypeFtpFindHandle:
  130. error = wFtpQueryDataAvailable(hLocal, &bytesAvailable);
  131. break;
  132. case TypeGopherFileHandle:
  133. case TypeGopherFindHandle:
  134. error = wGopherQueryDataAvailable(hLocal, &bytesAvailable);
  135. break;
  136. case TypeFtpFindHandleHtml:
  137. case TypeGopherFindHandleHtml:
  138. error = QueryHtmlDataAvailable(hFileMapped, &bytesAvailable);
  139. if (((INTERNET_CONNECT_HANDLE_OBJECT *)hFileMapped)->
  140. IsCacheWriteInProgress()) {
  141. DWORD errorCache = error;
  142. if ((errorCache == ERROR_SUCCESS) && (bytesAvailable == 0)) {
  143. errorCache = ERROR_NO_MORE_FILES;
  144. }
  145. if (errorCache != ERROR_SUCCESS) {
  146. if (handleType == TypeFtpFindHandleHtml) {
  147. InbLocalEndCacheWrite( hFileMapped,
  148. "htm",
  149. (errorCache == ERROR_NO_MORE_FILES)
  150. );
  151. }
  152. else {
  153. InbGopherLocalEndCacheWrite( hFileMapped,
  154. "htm",
  155. (errorCache == ERROR_NO_MORE_FILES)
  156. );
  157. }
  158. }
  159. }
  160. break;
  161. #ifdef EXTENDED_ERROR_HTML
  162. case TypeFtpFileHandleHtml:
  163. error = QueryHtmlDataAvailable(hFileMapped, &bytesAvailable);
  164. break;
  165. #endif
  166. default:
  167. error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
  168. break;
  169. }
  170. quit:
  171. BOOL success;
  172. if (error == ERROR_SUCCESS) {
  173. ((INTERNET_HANDLE_OBJECT *)hFileMapped)->SetAvailableDataLength(bytesAvailable);
  174. *lpdwNumberOfBytesAvailable = bytesAvailable;
  175. success = TRUE;
  176. DEBUG_PRINT(INET,
  177. INFO,
  178. ("%d bytes available\n",
  179. bytesAvailable
  180. ));
  181. DEBUG_PRINT_API(API,
  182. INFO,
  183. ("*lpdwNumberOfBytesAvailable (%#x) = %d\n",
  184. lpdwNumberOfBytesAvailable,
  185. bytesAvailable
  186. ));
  187. } else {
  188. success = FALSE;
  189. DEBUG_ERROR(INET, error);
  190. }
  191. SetLastError(error);
  192. DEBUG_LEAVE(success);
  193. return success;
  194. }
  195. STDAPI_(BOOL) ForceNexusLookupExW(
  196. IN BOOL fForce,
  197. IN PWSTR pwszRegUrl, // user supplied buffer ...
  198. IN OUT PDWORD pdwRegUrlLen, // ... and length (will be updated to actual length
  199. // on successful return)
  200. IN PWSTR pwszDARealm, // user supplied buffer ...
  201. IN OUT PDWORD pdwDARealmLen // ... and length (will be updated to actual length
  202. // on successful return)
  203. )
  204. {
  205. PP_CONTEXT hPP = 0;
  206. hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
  207. BOOL RetVal = ::PP_ForceNexusLookup (hPP,
  208. fForce,
  209. pwszRegUrl,
  210. pdwRegUrlLen,
  211. pwszDARealm,
  212. pdwDARealmLen );
  213. ::PP_FreeContext ( hPP );
  214. return RetVal;
  215. }
  216. STDAPI_(VOID) ForceNexusLookup(void)
  217. {
  218. PP_CONTEXT hPP = 0;
  219. hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
  220. ::PP_ForceNexusLookup (hPP,
  221. FALSE, // don't force connection establishment if nexus not reachable
  222. NULL,
  223. 0,
  224. NULL,
  225. 0 );
  226. ::PP_FreeContext ( hPP );
  227. }
  228. BOOL
  229. GetMD5Result(PSTR pszChallengeInfo, PSTR pszPassword, PBYTE pbHexHash);
  230. ///////////////
  231. // This routine gets the default passport password and does an MD5 hash of it with
  232. // the supplied ChallengeInfo and returns the result in hex string format.
  233. //
  234. // pwszRealm = realm to get the password for. If NULL, uses default. Ignored if pwszTarget is not null.
  235. //
  236. // pwszTarget = target to get the password for. If NULL, uses realm
  237. //
  238. // pbHexHash = output buffer to receive the MD5 result in hex string format,
  239. // MUST BE AT LEAST MD5DIGESTLEN * 2 + 1 IN SIZE
  240. //
  241. // Returns TRUE if success, FALSE if failure.
  242. //
  243. //
  244. STDAPI_(BOOL) CreateMD5SSOHash (
  245. IN PWSTR pszChallengeInfo,
  246. IN PWSTR pwszRealm,
  247. IN PWSTR pwszTarget,
  248. OUT PBYTE pbHexHash
  249. )
  250. {
  251. PP_CONTEXT hPP = 0;
  252. BOOL bRetVal = FALSE;
  253. hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
  254. if ( hPP )
  255. {
  256. WCHAR pszPassword[INTERNET_MAX_PASSWORD_LENGTH];
  257. // Check for cached creds in the session
  258. if (::PP_GetCachedCredential ( hPP, pwszRealm, pwszTarget, NULL, pszPassword) )
  259. {
  260. DWORD dwChallengeInfoLen = wcslen(pszChallengeInfo) + 1;
  261. PSTR pszChallengeInfoA = (PSTR) LocalAlloc (LPTR, dwChallengeInfoLen );
  262. DWORD dwPasswordLen = wcslen(pszPassword) + 1;
  263. PSTR pszPasswordA = (PSTR) LocalAlloc (LPTR, dwPasswordLen );
  264. if ( pszChallengeInfoA != NULL && pszPasswordA != NULL )
  265. {
  266. // convert to asci
  267. ::WideCharToMultiByte(CP_ACP, 0, pszChallengeInfo, -1, pszChallengeInfoA, dwChallengeInfoLen, NULL, NULL);
  268. ::WideCharToMultiByte(CP_ACP, 0, pszPassword, -1, pszPasswordA, dwPasswordLen, NULL, NULL);
  269. bRetVal = GetMD5Result ( pszChallengeInfoA, pszPasswordA, pbHexHash );
  270. ZeroMemory ( pszPassword, INTERNET_MAX_PASSWORD_LENGTH * sizeof(WCHAR) );
  271. ZeroMemory ( pszPasswordA, dwPasswordLen );
  272. }
  273. if ( pszChallengeInfoA )
  274. LocalFree ( pszChallengeInfoA );
  275. if ( pszPasswordA )
  276. LocalFree ( pszPasswordA );
  277. }
  278. ::PP_FreeContext ( hPP );
  279. }
  280. return bRetVal;
  281. }