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.

1284 lines
36 KiB

  1. /*++
  2. Copyright (c) 2000-2002 Microsoft Corporation
  3. Module Name:
  4. ClientApi.c
  5. Abstract:
  6. User-mode interface to HTTP.SYS: Client-side APIs
  7. Author:
  8. Rajesh Sundaram (rajeshsu) 1-Aug-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include <stdio.h>
  13. //
  14. // Private macros.
  15. //
  16. #define HTTP_PREFIX_W L"HTTP://"
  17. #define HTTP_PREFIX_LENGTH (sizeof(HTTP_PREFIX_W) - sizeof(WCHAR))
  18. #define HTTPS_PREFIX_W L"HTTPS://"
  19. #define HTTPS_PREFIX_LENGTH (sizeof(HTTPS_PREFIX_W) - sizeof(WCHAR))
  20. #define HTTP_DEFAULT_PORT 80
  21. #define HTTPS_DEFAULT_PORT 443
  22. //
  23. // Ssl stream filter stuff.
  24. //
  25. WCHAR g_StrmFilt[] = L"strmfilt.dll";
  26. LONG g_bStrmFiltLoaded = 0;
  27. HMODULE g_hStrmFilt = NULL;
  28. FARPROC g_pStrmFiltInitialize = NULL;
  29. FARPROC g_pStrmFiltStart = NULL;
  30. FARPROC g_pStrmFiltStop = NULL;
  31. FARPROC g_pStrmFiltTerminate = NULL;
  32. extern CRITICAL_SECTION g_InitCritSec;
  33. #ifndef DBG
  34. #define DbgCriticalSectionOwned(pcs) (TRUE)
  35. #else
  36. /***************************************************************************++
  37. Routine Description:
  38. This routine determines if the calling thread owns a critical section.
  39. Arguments:
  40. pcs - Pointer to CRITICAL_SECTION.
  41. Return Value:
  42. BOOLEAN
  43. --***************************************************************************/
  44. BOOLEAN
  45. DbgCriticalSectionOwned(
  46. PCRITICAL_SECTION pcs
  47. )
  48. {
  49. #define HANDLE_TO_DWORD(Handle) ((DWORD)PtrToUlong(Handle))
  50. if (pcs->LockCount >= 0 &&
  51. HANDLE_TO_DWORD(pcs->OwningThread) == GetCurrentThreadId())
  52. {
  53. return TRUE;
  54. }
  55. return FALSE;
  56. }
  57. #endif
  58. /***************************************************************************++
  59. Routine Description:
  60. This function resolves a name to an IP.
  61. Arguments:
  62. pServerName - The name to be resolved.
  63. ServerNameLength - Length of the name (in WCHAR).
  64. Return Value:
  65. DWORD - Completion status.
  66. --***************************************************************************/
  67. DWORD
  68. ResolveName(
  69. IN PWCHAR pServerName,
  70. IN USHORT ServerNameLength,
  71. IN USHORT PortNumber,
  72. OUT PTRANSPORT_ADDRESS *pTransportAddress,
  73. OUT PUSHORT TransportAddressLength
  74. )
  75. {
  76. LPSTR pBuffer;
  77. ULONG BufferLen;
  78. struct addrinfo *pAi, *pTempAi;
  79. ULONG AiLen, AiCount;
  80. DWORD dwResult;
  81. PTA_ADDRESS CurrentAddress;
  82. //
  83. // We need space to store the ANSI version of the name.
  84. //
  85. BufferLen = WideCharToMultiByte(
  86. CP_ACP,
  87. 0,
  88. pServerName,
  89. ServerNameLength,
  90. NULL,
  91. 0,
  92. NULL,
  93. NULL);
  94. if(!BufferLen)
  95. {
  96. return ERROR_INVALID_PARAMETER;
  97. }
  98. //
  99. // Account for '\0'
  100. //
  101. BufferLen = BufferLen + 1;
  102. pBuffer = RtlAllocateHeap(RtlProcessHeap(),
  103. 0,
  104. BufferLen
  105. );
  106. if(!pBuffer)
  107. {
  108. return ERROR_NOT_ENOUGH_MEMORY;
  109. }
  110. //
  111. // Convert the name to ANSI.
  112. //
  113. if(WideCharToMultiByte(CP_ACP,
  114. 0,
  115. pServerName,
  116. ServerNameLength,
  117. pBuffer,
  118. BufferLen-1,
  119. NULL,
  120. NULL) == 0)
  121. {
  122. dwResult = GetLastError();
  123. RtlFreeHeap(RtlProcessHeap(),
  124. 0,
  125. pBuffer);
  126. return dwResult;
  127. }
  128. //
  129. // NULL terminate it.
  130. //
  131. *(pBuffer + BufferLen - 1) = 0;
  132. //
  133. // Resolve it.
  134. //
  135. if((dwResult = getaddrinfo(pBuffer, NULL, 0, &pAi)) != 0)
  136. {
  137. RtlFreeHeap(RtlProcessHeap(),
  138. 0,
  139. pBuffer);
  140. return dwResult;
  141. }
  142. else
  143. {
  144. //
  145. // Compute size of all entries returned by getaddrinfo
  146. //
  147. pTempAi = pAi;
  148. AiLen = 0;
  149. AiCount = 0;
  150. while(pAi != NULL)
  151. {
  152. if(pAi->ai_family == PF_INET || pAi->ai_family == AF_INET6)
  153. {
  154. AiCount ++;
  155. //
  156. // ai_addrlength includes the size of the AddressType,
  157. // but TA_ADDRESS expects AddressLength to exclude this.
  158. //
  159. AiLen = AiLen +
  160. ((ULONG)pAi->ai_addrlen -
  161. RTL_FIELD_SIZE(TA_ADDRESS, AddressType));
  162. }
  163. pAi = pAi->ai_next;
  164. }
  165. if(AiCount == 0)
  166. {
  167. // No addresses found.
  168. return ERROR_INVALID_PARAMETER;
  169. }
  170. AiLen += ((AiCount * FIELD_OFFSET(TA_ADDRESS, Address)) +
  171. FIELD_OFFSET(TRANSPORT_ADDRESS, Address));
  172. if(BufferLen >= AiLen)
  173. {
  174. *pTransportAddress = (PTRANSPORT_ADDRESS) pBuffer;
  175. }
  176. else
  177. {
  178. RtlFreeHeap(RtlProcessHeap(),
  179. 0,
  180. pBuffer
  181. );
  182. *pTransportAddress = (PTRANSPORT_ADDRESS)
  183. RtlAllocateHeap(RtlProcessHeap(),
  184. 0,
  185. AiLen
  186. );
  187. if(!*pTransportAddress)
  188. {
  189. freeaddrinfo(pAi);
  190. return ERROR_NOT_ENOUGH_MEMORY;
  191. }
  192. }
  193. //
  194. // Convert this to a Transport Address.
  195. //
  196. pAi = pTempAi;
  197. (*pTransportAddress)->TAAddressCount = AiCount;
  198. CurrentAddress = (*pTransportAddress)->Address;
  199. while(pAi != NULL)
  200. {
  201. switch(pAi->ai_family)
  202. {
  203. case PF_INET:
  204. case PF_INET6:
  205. //
  206. // ai_addrlength includes the size of the AddressType,
  207. // but TA_ADDRESS expects AddressLength to exclude this.
  208. //
  209. CurrentAddress->AddressLength =
  210. (USHORT)
  211. pAi->ai_addrlen -
  212. RTL_FIELD_SIZE(TA_ADDRESS, AddressType);
  213. CurrentAddress->AddressType = pAi->ai_addr->sa_family;
  214. RtlCopyMemory(
  215. &CurrentAddress->Address,
  216. pAi->ai_addr->sa_data,
  217. CurrentAddress->AddressLength
  218. );
  219. if(PF_INET == pAi->ai_family)
  220. {
  221. ((TDI_ADDRESS_IP *)
  222. CurrentAddress->Address)->sin_port =
  223. htons(PortNumber);
  224. }
  225. else
  226. {
  227. ((TDI_ADDRESS_IP6 *)
  228. CurrentAddress->Address)->sin6_port =
  229. htons(PortNumber);
  230. }
  231. CurrentAddress = (PTA_ADDRESS)
  232. (CurrentAddress->Address +
  233. CurrentAddress->AddressLength);
  234. break;
  235. default:
  236. break;
  237. }
  238. pAi = pAi->ai_next;
  239. }
  240. *TransportAddressLength = (USHORT) AiLen;
  241. freeaddrinfo(pTempAi);
  242. }
  243. return NO_ERROR;
  244. }
  245. /***************************************************************************++
  246. Routine Description:
  247. This function takes in a string (of the form "Hostname[:PortNumber]"),
  248. performs DNS lookup on "Hostname". Returns a TRANSPORT_ADDRESS
  249. containing the resolved Host address and port number.
  250. Hostname can be:
  251. hostname (e.g. foo.bar.com) or
  252. IPv4 address (e.g. 128.101.35.201) or
  253. IPv6 address (e.g. [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210])
  254. This Function is a HACK and will go away when we do DNS in the kernel.
  255. Arguments:
  256. pServerLocationStr - (Input) Hostname:PortNumber string
  257. ServerLocationStrLength - (Input) Server Location string length
  258. pTransportAddress - (Output) Transport address (and port) of Server
  259. TransportAddressLength - (Output) Length of the structure pointed to by
  260. pTransportAddress
  261. Return Value:
  262. DWORD - Completion status.
  263. --***************************************************************************/
  264. DWORD
  265. ProcessHostAndPort(
  266. IN PWCHAR pServerLocationStr,
  267. IN USHORT ServerLocationStrLength,
  268. IN USHORT DefaultPort,
  269. OUT PTRANSPORT_ADDRESS *pTransportAddress,
  270. OUT PUSHORT pTransportAddressLength
  271. )
  272. {
  273. DWORD Status;
  274. ULONG PortNumber = 0;
  275. PWSTR ptr;
  276. PWSTR pEndStr = pServerLocationStr +
  277. (ServerLocationStrLength/sizeof(WCHAR));
  278. PWSTR pStartHostname = pServerLocationStr;
  279. PWSTR pEndHostname = pEndStr; // may change due to presence of port #
  280. //
  281. // Empty Host String?
  282. //
  283. if (pEndStr == pServerLocationStr)
  284. return ERROR_INVALID_PARAMETER;
  285. //
  286. // check if the HostStr contains IPv6 address (RFC 2732)
  287. //
  288. if (*pServerLocationStr == L'[')
  289. {
  290. // skip '['
  291. pStartHostname = pServerLocationStr + 1;
  292. // find the matching ']'
  293. for (ptr = pServerLocationStr+1; ptr != pEndStr && *ptr != L']'; ptr++)
  294. /* do nothing */;
  295. // missing ']'?
  296. if (ptr == pEndStr)
  297. return ERROR_INVALID_PARAMETER;
  298. // IPv6 host address ends here
  299. pEndHostname = ptr;
  300. // skip ']'
  301. ptr++;
  302. if (ptr != pEndStr && *ptr != L':')
  303. return ERROR_INVALID_PARAMETER;
  304. }
  305. else // Host name or IPv4 address is present
  306. {
  307. pStartHostname = pServerLocationStr;
  308. // Check if a port number is present
  309. for (ptr = pServerLocationStr; ptr != pEndStr && *ptr != L':'; ptr++)
  310. /* do nothing */;
  311. pEndHostname = ptr;
  312. }
  313. // If a port number is present...grab it.
  314. if (ptr != pEndStr)
  315. {
  316. ASSERT(*ptr == L':');
  317. for (ptr++; ptr != pEndStr; ptr++)
  318. {
  319. if (!iswdigit(*ptr))
  320. {
  321. // Junk instead of digits
  322. return ERROR_INVALID_PARAMETER;
  323. }
  324. PortNumber = 10*PortNumber + (ULONG)(*ptr - L'0');
  325. // Port numbers are only 16 bit wide
  326. if (PortNumber >= (ULONG)(1<<16))
  327. {
  328. return ERROR_INVALID_PARAMETER;
  329. }
  330. }
  331. }
  332. if(PortNumber == 0)
  333. {
  334. PortNumber = DefaultPort;
  335. }
  336. Status = ResolveName(pStartHostname,
  337. (USHORT) (pEndHostname-pStartHostname),
  338. (USHORT)PortNumber,
  339. pTransportAddress,
  340. pTransportAddressLength
  341. );
  342. return Status;
  343. }
  344. /****************************************************************************++
  345. Routine Description:
  346. Loads dymanically linked library strmfilt.dll.
  347. If the library is already loaded, it returns NO_ERROR
  348. Arguments:
  349. None.
  350. Return Value:
  351. NO_ERROR - Library was loaded (now or previously) successfully
  352. Other errors as encountered.
  353. --****************************************************************************/
  354. DWORD
  355. LoadStrmFilt(
  356. VOID
  357. )
  358. {
  359. LONG OldValue;
  360. HRESULT hr;
  361. DWORD Error;
  362. //
  363. // Quick check outside the lock to see if the library is already loaded.
  364. //
  365. if (g_bStrmFiltLoaded)
  366. {
  367. return NO_ERROR;
  368. }
  369. //
  370. // Make sure there is no other thread trying to load the library.
  371. //
  372. EnterCriticalSection(&g_InitCritSec);
  373. if (g_bStrmFiltLoaded == 0)
  374. {
  375. //
  376. // Library is not loaded. Proceed to load StrmFilt.dll.
  377. //
  378. g_hStrmFilt = LoadLibrary(g_StrmFilt);
  379. if (g_hStrmFilt == NULL)
  380. {
  381. Error = GetLastError();
  382. goto Quit;
  383. }
  384. //
  385. // Get addresses of the following procedures:
  386. // StreamFilterClientInitialize, StreamFilterClientTerminate
  387. // StreamFilterClientStart, StreamFilterClientStop
  388. //
  389. g_pStrmFiltInitialize = GetProcAddress(g_hStrmFilt,
  390. "StreamFilterClientInitialize");
  391. if (g_pStrmFiltInitialize == NULL)
  392. {
  393. Error = GetLastError();
  394. goto Unload;
  395. }
  396. g_pStrmFiltStart = GetProcAddress(g_hStrmFilt, "StreamFilterClientStart");
  397. if (g_pStrmFiltStart == NULL)
  398. {
  399. Error = GetLastError();
  400. goto Unload;
  401. }
  402. g_pStrmFiltStop = GetProcAddress(g_hStrmFilt, "StreamFilterClientStop");
  403. if (g_pStrmFiltStop == NULL)
  404. {
  405. Error = GetLastError();
  406. goto Unload;
  407. }
  408. g_pStrmFiltTerminate = GetProcAddress(g_hStrmFilt,
  409. "StreamFilterClientTerminate");
  410. if (g_pStrmFiltTerminate == NULL)
  411. {
  412. Error = GetLastError();
  413. goto Unload;
  414. }
  415. //
  416. // Try to initialize StrmFilt.
  417. //
  418. hr = (HRESULT)g_pStrmFiltInitialize();
  419. if (SUCCEEDED(hr))
  420. {
  421. //
  422. // StrmFilt initialized suceessfully. Now try to start it.
  423. //
  424. hr = (HRESULT)g_pStrmFiltStart();
  425. if (FAILED(hr))
  426. {
  427. //
  428. // Could not start StrmFilt. Terminate it!
  429. //
  430. g_pStrmFiltTerminate();
  431. }
  432. }
  433. if (FAILED(hr))
  434. {
  435. Error = (DWORD)hr;
  436. goto Unload;
  437. }
  438. //
  439. // Remember that StrmFilt has been loaded and initialized.
  440. // Atomically set bStrmFilt to 1. The reason for atomic operation
  441. // is that g_bStrmFiltLoaded can be read without a lock.
  442. //
  443. OldValue = InterlockedExchange(&g_bStrmFiltLoaded, 1);
  444. //
  445. // g_bStrmFiltLoaded is always set to 1 under g_InitCritSec.
  446. //
  447. ASSERT(OldValue == 0);
  448. }
  449. //
  450. // This is the normal case, when everything went OK.
  451. //
  452. LeaveCriticalSection(&g_InitCritSec);
  453. return NO_ERROR;
  454. //
  455. // Erroneous cases come here.
  456. //
  457. Unload:
  458. //
  459. // Set these function pointers so that they aren't be used.
  460. //
  461. g_pStrmFiltInitialize = NULL;
  462. g_pStrmFiltStart = NULL;
  463. g_pStrmFiltStop = NULL;
  464. g_pStrmFiltTerminate = NULL;
  465. //
  466. // Unload strmfilt.dll.
  467. //
  468. ASSERT(g_hStrmFilt);
  469. FreeLibrary(g_hStrmFilt);
  470. g_hStrmFilt = NULL;
  471. Quit:
  472. LeaveCriticalSection(&g_InitCritSec);
  473. return Error;
  474. }
  475. /****************************************************************************++
  476. Routine Description:
  477. Unloads strmfilt.dll, if loaded previously.
  478. This routine is called inside g_InitCritSec critical section.
  479. Arguments:
  480. None.
  481. Return Value:
  482. NO_ERROR if strmfilt.dll successfully unloaded.
  483. Other errors as encountered.
  484. --****************************************************************************/
  485. DWORD
  486. UnloadStrmFilt(
  487. VOID
  488. )
  489. {
  490. LONG OldValue;
  491. ASSERT(DbgCriticalSectionOwned(&g_InitCritSec));
  492. OldValue = InterlockedExchange(&g_bStrmFiltLoaded, 0);
  493. //
  494. // Has strmfilt been initialized before?
  495. //
  496. if (OldValue == 0)
  497. {
  498. return ERROR_NOT_FOUND;
  499. }
  500. ASSERT(OldValue == 1);
  501. //
  502. // Sanity checks.
  503. //
  504. ASSERT(g_pStrmFiltInitialize);
  505. ASSERT(g_pStrmFiltStart);
  506. ASSERT(g_pStrmFiltStop);
  507. ASSERT(g_pStrmFiltTerminate);
  508. //
  509. // Stop StreamFilter and terminate it.
  510. //
  511. g_pStrmFiltStop();
  512. g_pStrmFiltTerminate();
  513. //
  514. // Set these function pointers so that they aren't used.
  515. //
  516. g_pStrmFiltInitialize = NULL;
  517. g_pStrmFiltStart = NULL;
  518. g_pStrmFiltStop = NULL;
  519. g_pStrmFiltTerminate = NULL;
  520. //
  521. // Unload strmfilt.dll.
  522. //
  523. ASSERT(g_hStrmFilt);
  524. FreeLibrary(g_hStrmFilt);
  525. g_hStrmFilt = NULL;
  526. return NO_ERROR;
  527. }
  528. /***************************************************************************++
  529. Routine Description:
  530. This is the first api that an application uses before it can talk to a
  531. server. This call creates a NT FileHandle for the origin server
  532. Arguments:
  533. ServerNameLength - The Length of server name
  534. pServerName - The Full URI (starts with http[s]://servername/...)
  535. dwServerFlags - Flags
  536. pConfigInfo - Array of config objects
  537. pReserved - Must be NULL
  538. pServerHandle - The File Handle
  539. Return Value:
  540. ULONG - Completion status.
  541. --***************************************************************************/
  542. ULONG
  543. WINAPI
  544. HttpInitializeServerContext(
  545. IN USHORT ServerNameLength,
  546. IN PWCHAR pServerName,
  547. IN USHORT ProxyLength OPTIONAL,
  548. IN PWCHAR pProxy OPTIONAL,
  549. IN ULONG ServerFlags OPTIONAL,
  550. IN PVOID pReserved,
  551. OUT PHANDLE pServerHandle
  552. )
  553. {
  554. NTSTATUS Status;
  555. ULONG Win32Status;
  556. PTRANSPORT_ADDRESS pTransportAddress;
  557. USHORT TransportAddressLength = 0;
  558. DWORD CreateDisposition;
  559. PWCHAR pServerNameStart = NULL;
  560. USHORT DefaultPort;
  561. if(ServerFlags != 0 || pReserved != NULL)
  562. {
  563. return ERROR_INVALID_PARAMETER;
  564. }
  565. CreateDisposition = FILE_CREATE;
  566. //
  567. // Process the scheme name. We need at least one character after the
  568. // http:// or https://, so the comparision is > instead of >=
  569. //
  570. if(ServerNameLength > HTTP_PREFIX_LENGTH)
  571. {
  572. if (_wcsnicmp(pServerName,
  573. HTTP_PREFIX_W,
  574. HTTP_PREFIX_LENGTH/sizeof(WCHAR)) == 0)
  575. {
  576. pServerNameStart = pServerName +
  577. (HTTP_PREFIX_LENGTH/sizeof(WCHAR));
  578. DefaultPort = HTTP_DEFAULT_PORT;
  579. }
  580. else if(ServerNameLength > HTTPS_PREFIX_LENGTH)
  581. {
  582. if (_wcsnicmp(pServerName,
  583. HTTPS_PREFIX_W,
  584. HTTPS_PREFIX_LENGTH/sizeof(WCHAR)) == 0)
  585. {
  586. pServerNameStart = pServerName +
  587. (HTTPS_PREFIX_LENGTH/sizeof(WCHAR));
  588. //
  589. // If an HTTPS server is being initialized, load strmfilt.dll
  590. //
  591. DefaultPort = HTTPS_DEFAULT_PORT;
  592. Win32Status = LoadStrmFilt();
  593. if (Win32Status != NO_ERROR)
  594. {
  595. return Win32Status;
  596. }
  597. }
  598. else
  599. {
  600. // neither http:// nor https://
  601. return ERROR_INVALID_PARAMETER;
  602. }
  603. }
  604. else
  605. {
  606. // Not enough space to compare https://
  607. return ERROR_INVALID_PARAMETER;
  608. }
  609. }
  610. else
  611. {
  612. // Not enough space to compare http://
  613. return ERROR_INVALID_PARAMETER;
  614. }
  615. ASSERT(pServerNameStart != NULL);
  616. //
  617. // We don't do DNS in the kernel yet, so for now, we'll do DNS resolution
  618. // in user mode and pass the IP address across the boundary. This hack
  619. // has to be removed when we get DNS support in the kernel.
  620. //
  621. if(ProxyLength)
  622. {
  623. // The user has supplied a proxy, we don't have to resolve the
  624. // server name.
  625. //
  626. DefaultPort = HTTP_DEFAULT_PORT;
  627. if((Win32Status = ProcessHostAndPort(pProxy,
  628. ProxyLength,
  629. DefaultPort,
  630. &pTransportAddress,
  631. &TransportAddressLength
  632. ))
  633. != NO_ERROR)
  634. {
  635. return Win32Status;
  636. }
  637. }
  638. else
  639. {
  640. PWCHAR pServerNameEnd;
  641. PWCHAR pUriEnd = pServerName + (ServerNameLength / sizeof(WCHAR));
  642. //
  643. // At this point pUri points to the first thing after the scheme. Walk
  644. // through the URI until either we hit the end or find a terminating /.
  645. //
  646. // By the comparision above, we are guaranteed to have at least one
  647. // character
  648. ASSERT(pUriEnd != pServerNameStart);
  649. pServerNameEnd = pServerNameStart;
  650. while(*pServerNameEnd != L'/')
  651. {
  652. pServerNameEnd ++;
  653. // See if we still have URI left to examine.
  654. if (pServerNameEnd == pUriEnd)
  655. {
  656. break;
  657. }
  658. }
  659. // Check for a zero server name -
  660. if(pServerNameStart == pServerNameEnd)
  661. {
  662. return ERROR_INVALID_PARAMETER;
  663. }
  664. if((Win32Status =
  665. ProcessHostAndPort(
  666. pServerNameStart,
  667. (USHORT) (pServerNameEnd - pServerNameStart) * sizeof(WCHAR),
  668. DefaultPort,
  669. &pTransportAddress,
  670. &TransportAddressLength)) != NO_ERROR)
  671. {
  672. return Win32Status;
  673. }
  674. }
  675. Status = HttpApiOpenDriverHelper(
  676. pServerHandle,
  677. pServerName, // URI
  678. ServerNameLength,
  679. pProxy, // Proxy
  680. ProxyLength,
  681. pTransportAddress,
  682. TransportAddressLength,
  683. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, // Acces
  684. HttpApiServerHandleType,
  685. 0, // Object Name
  686. 0, // Options
  687. CreateDisposition, // createDisposition
  688. NULL
  689. );
  690. //
  691. // If we couldn't open the driver because it's not running, then try
  692. // to start the driver & retry the open.
  693. //
  694. if (Status == STATUS_OBJECT_NAME_NOT_FOUND ||
  695. Status == STATUS_OBJECT_PATH_NOT_FOUND)
  696. {
  697. if (HttpApiTryToStartDriver(HTTP_SERVICE_NAME))
  698. {
  699. Status = HttpApiOpenDriverHelper(
  700. pServerHandle,
  701. pServerName, // URI
  702. ServerNameLength,
  703. pProxy, // Proxy
  704. ProxyLength,
  705. pTransportAddress,
  706. TransportAddressLength,
  707. GENERIC_READ | GENERIC_WRITE |
  708. SYNCHRONIZE, // Desired Acces
  709. HttpApiServerHandleType,
  710. 0, // Object Name
  711. 0, // Options
  712. CreateDisposition, // createDisposition
  713. NULL
  714. );
  715. }
  716. }
  717. //
  718. // Need to free the pTransportAddress
  719. //
  720. RtlFreeHeap(RtlProcessHeap(),
  721. 0,
  722. pTransportAddress
  723. );
  724. return HttpApiNtStatusToWin32Status( Status );
  725. }
  726. /***************************************************************************++
  727. Routine Description:
  728. Sends an HTTP request.
  729. Arguments:
  730. ServerHandle - Supplies the handle corresponding to a particular
  731. server.
  732. This is the handle as returned by
  733. HttpInitializeServerContext.
  734. pHttpRequest - The HTTP request.
  735. HttpRequestFlags - The Request Flags.
  736. pConfig - Config information for this request.
  737. pOverlapped - Overlapped structure for Overlapped I/O.
  738. ResponseBufferLength - Contains the response buffer length.
  739. ResponseBuffer - A pointer to a buffer to return the response.
  740. pBytesReceived - The # of bytes that actually got written.
  741. pRequestID - A pointer to a request identifier - This will return an
  742. ID that can be used in subsequent calls.
  743. Return Value:
  744. ULONG - Completion status.
  745. --***************************************************************************/
  746. ULONG
  747. WINAPI
  748. HttpSendHttpRequest(
  749. IN HANDLE ServerHandle,
  750. IN PHTTP_REQUEST pHttpRequest,
  751. IN ULONG HttpRequestFlags,
  752. IN USHORT RequestConfigCount OPTIONAL,
  753. IN PHTTP_REQUEST_CONFIG pRequestConfig OPTIONAL,
  754. IN LPOVERLAPPED pOverlapped OPTIONAL,
  755. IN ULONG ResponseBufferLength OPTIONAL,
  756. OUT PHTTP_RESPONSE pResponseBuffer OPTIONAL,
  757. IN ULONG Reserved, // must be 0
  758. OUT PVOID pReserved, // must be NULL
  759. OUT PULONG pBytesReceived OPTIONAL,
  760. OUT PHTTP_REQUEST_ID pRequestID
  761. )
  762. {
  763. HTTP_SEND_REQUEST_INPUT_INFO HttpSendRequestInput;
  764. if(Reserved != 0 || pReserved != NULL)
  765. {
  766. return ERROR_INVALID_PARAMETER;
  767. }
  768. RtlZeroMemory(&HttpSendRequestInput,
  769. sizeof(HTTP_SEND_REQUEST_INPUT_INFO));
  770. HTTP_SET_NULL_ID(pRequestID);
  771. HttpSendRequestInput.pHttpRequestId = pRequestID;
  772. HttpSendRequestInput.pHttpRequest = pHttpRequest;
  773. HttpSendRequestInput.HttpRequestFlags = HttpRequestFlags;
  774. HttpSendRequestInput.pRequestConfig = pRequestConfig;
  775. HttpSendRequestInput.RequestConfigCount = RequestConfigCount;
  776. HttpSendRequestInput.pBytesTaken = pBytesReceived;
  777. return HttpApiDeviceControl(
  778. ServerHandle, // FileHandle
  779. pOverlapped, // Overlapped
  780. IOCTL_HTTP_SEND_REQUEST, // IO Control code
  781. &HttpSendRequestInput, // InputBuffer
  782. sizeof(HttpSendRequestInput), // InputBufferLength
  783. pResponseBuffer, // Output Buffer
  784. ResponseBufferLength, // Output Buffer length
  785. pBytesReceived
  786. );
  787. }
  788. /***************************************************************************++
  789. Routine Description:
  790. Sends additional entity bodies.
  791. Arguments:
  792. ServerHandle - Supplies the handle corresponding to a particular
  793. server.
  794. This is the handle as returned by
  795. HttpInitializeServerContext.
  796. RequestID - The request ID that was returned by HttpSendRequest.
  797. Flags - The Request Flags.
  798. pOverlapped - Overlapped structure for Overlapped I/O.
  799. EntityBodyLength - The count of entity bodies.
  800. pHttpEntityBody - The pointer to the entity bodies.
  801. ID that can be used in subsequent calls.
  802. Return Value:
  803. ULONG - Completion status.
  804. --***************************************************************************/
  805. ULONG
  806. WINAPI
  807. HttpSendRequestEntityBody(
  808. IN HANDLE ServerHandle,
  809. IN HTTP_REQUEST_ID RequestID,
  810. IN ULONG Flags,
  811. IN USHORT EntityBodyCount,
  812. IN PHTTP_DATA_CHUNK pHttpEntityBody,
  813. IN LPOVERLAPPED pOverlapped OPTIONAL
  814. )
  815. {
  816. HTTP_SEND_REQUEST_ENTITY_BODY_INFO HttpEntity;
  817. RtlZeroMemory(&HttpEntity, sizeof(HTTP_SEND_REQUEST_ENTITY_BODY_INFO));
  818. HttpEntity.EntityChunkCount = EntityBodyCount;
  819. HttpEntity.Flags = Flags;
  820. HttpEntity.RequestID = RequestID;
  821. HttpEntity.pHttpEntityChunk = pHttpEntityBody;
  822. return HttpApiDeviceControl(
  823. ServerHandle, // FileHandle
  824. pOverlapped, // Overlapped
  825. IOCTL_HTTP_SEND_REQUEST_ENTITY_BODY, // IO Control code
  826. &HttpEntity, // InputBuffer
  827. sizeof(HttpEntity), // InputBufferLength
  828. NULL, // ResponseBuffer
  829. 0, // Output Buffer length
  830. NULL // Bytes received.
  831. );
  832. }
  833. /***************************************************************************++
  834. Routine Description:
  835. Receives the response
  836. Arguments:
  837. ServerHandle - Supplies the handle corresponding to a particular
  838. server.This is the handle as returned by
  839. HttpInitializeServerContext.
  840. RequestID - The request ID that was returned by HttpSendRequest.
  841. Flags - The Request Flags.
  842. pOverlapped - Overlapped structure for Overlapped I/O.
  843. EntityBodyLength - The count of entity bodies.
  844. pHttpEntityBody - The pointer to the entity bodies.
  845. ID that can be used in subsequent calls.
  846. Return Value:
  847. ULONG - Completion status.
  848. --***************************************************************************/
  849. ULONG
  850. WINAPI
  851. HttpReceiveHttpResponse(
  852. IN HANDLE ServerHandle,
  853. IN HTTP_REQUEST_ID RequestID,
  854. IN ULONG Flags,
  855. IN ULONG ResponseBufferLength,
  856. OUT PHTTP_RESPONSE pResponseBuffer,
  857. IN ULONG Reserved, // must be 0
  858. OUT PVOID pReserved, // must be NULL
  859. OUT PULONG pBytesReceived OPTIONAL,
  860. IN LPOVERLAPPED pOverlapped OPTIONAL
  861. )
  862. {
  863. HTTP_RECEIVE_RESPONSE_INFO HttpResponse;
  864. if(Reserved != 0 || pReserved != NULL)
  865. {
  866. return ERROR_INVALID_PARAMETER;
  867. }
  868. RtlZeroMemory(&HttpResponse, sizeof(HTTP_RECEIVE_RESPONSE_INFO));
  869. HttpResponse.RequestID = RequestID;
  870. HttpResponse.Flags = Flags;
  871. HttpResponse.pBytesTaken = pBytesReceived;
  872. return HttpApiDeviceControl(
  873. ServerHandle, // FileHandle
  874. pOverlapped, // Overlapped
  875. IOCTL_HTTP_RECEIVE_RESPONSE, // IO Control code
  876. &HttpResponse, // InputBuffer
  877. sizeof(HttpResponse), // InputBufferLength
  878. pResponseBuffer, // Output Buffer
  879. ResponseBufferLength, // Output Buffer length
  880. pBytesReceived // Bytes received.
  881. );
  882. }
  883. /***************************************************************************++
  884. Routine Description:
  885. Sets server config
  886. Arguments:
  887. ServerHandle - Supplies the handle corresponding to a particular server.
  888. This is the handle as returned by
  889. HttpInitializeServerContext.
  890. pConfig - The Config object
  891. Return Value:
  892. ULONG - Completion status.
  893. --***************************************************************************/
  894. ULONG
  895. WINAPI
  896. HttpSetServerContextInformation(
  897. IN HANDLE ServerHandle,
  898. IN HTTP_SERVER_CONFIG_ID ConfigId,
  899. IN PVOID pInputBuffer,
  900. IN ULONG InputBufferLength,
  901. IN LPOVERLAPPED pOverlapped
  902. )
  903. {
  904. HTTP_SERVER_CONTEXT_INFORMATION Info;
  905. Info.ConfigID = ConfigId;
  906. Info.pInputBuffer = pInputBuffer;
  907. Info.InputBufferLength = InputBufferLength;
  908. Info.pBytesTaken = NULL;
  909. return HttpApiDeviceControl(
  910. ServerHandle,
  911. pOverlapped,
  912. IOCTL_HTTP_SET_SERVER_CONTEXT_INFORMATION,
  913. &Info,
  914. sizeof(Info),
  915. NULL,
  916. 0,
  917. NULL
  918. );
  919. }
  920. /***************************************************************************++
  921. Routine Description:
  922. Query server config
  923. Arguments:
  924. ServerHandle - Supplies the handle corresponding to a particular server.
  925. This is the handle as returned by
  926. HttpInitializeServerContext.
  927. pConfig - The Config object
  928. Return Value:
  929. ULONG - Completion status.
  930. --***************************************************************************/
  931. ULONG
  932. WINAPI
  933. HttpQueryServerContextInformation(
  934. IN HANDLE ServerHandle,
  935. IN HTTP_SERVER_CONFIG_ID ConfigId,
  936. IN PVOID pReserved1,
  937. IN ULONG Reserved2,
  938. OUT PVOID pOutputBuffer,
  939. IN ULONG OutputBufferLength,
  940. OUT PULONG pReturnLength,
  941. IN LPOVERLAPPED pOverlapped
  942. )
  943. {
  944. HTTP_SERVER_CONTEXT_INFORMATION Info;
  945. if(pReserved1 != NULL || Reserved2 != 0)
  946. {
  947. return ERROR_INVALID_PARAMETER;
  948. }
  949. Info.ConfigID = ConfigId;
  950. Info.pInputBuffer = NULL;
  951. Info.InputBufferLength = 0;
  952. Info.pBytesTaken = pReturnLength;
  953. return HttpApiDeviceControl(
  954. ServerHandle,
  955. pOverlapped,
  956. IOCTL_HTTP_QUERY_SERVER_CONTEXT_INFORMATION,
  957. &Info,
  958. sizeof(Info),
  959. pOutputBuffer,
  960. OutputBufferLength,
  961. pReturnLength
  962. );
  963. }
  964. /***************************************************************************++
  965. Routine Description:
  966. Cancels a request
  967. Arguments:
  968. ServerHandle - Supplies the handle corresponding to a particular
  969. server.This is the handle as returned by
  970. HttpInitializeServerContext.
  971. RequestID - The request ID that was returned by HttpSendRequest.
  972. pOverlapped - Overlapped structure.
  973. Return Value:
  974. ULONG - Completion status.
  975. --***************************************************************************/
  976. ULONG
  977. WINAPI
  978. HttpCancelHttpRequest(
  979. IN HANDLE ServerHandle,
  980. IN HTTP_REQUEST_ID RequestID,
  981. IN ULONG Flags,
  982. IN LPOVERLAPPED pOverlapped OPTIONAL
  983. )
  984. {
  985. HTTP_RECEIVE_RESPONSE_INFO HttpResponse;
  986. RtlZeroMemory(&HttpResponse, sizeof(HTTP_RECEIVE_RESPONSE_INFO));
  987. HttpResponse.RequestID = RequestID;
  988. HttpResponse.Flags = Flags;
  989. return HttpApiDeviceControl(
  990. ServerHandle, // FileHandle
  991. pOverlapped, // Overlapped
  992. IOCTL_HTTP_CANCEL_REQUEST, // IO Control code
  993. &HttpResponse, // InputBuffer
  994. sizeof(HttpResponse), // InputBufferLength
  995. NULL,
  996. 0,
  997. NULL
  998. );
  999. }