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.

2100 lines
48 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. util.cxx
  5. Abstract:
  6. Contains utility functions
  7. Contents:
  8. new
  9. delete
  10. NewString
  11. CatString
  12. ResizeBuffer
  13. _memrchr
  14. strnistr
  15. PrivateStrChr
  16. PlatformType
  17. PlatformSupport
  18. GetTimeoutValue
  19. ProbeReadBuffer
  20. ProbeWriteBuffer
  21. ProbeAndSetDword
  22. ProbeString
  23. LoadDllEntryPoints
  24. UnloadDllEntryPoints
  25. MapInternetError
  26. CalculateHashValue
  27. GetCurrentGmtTime
  28. GetFileExtensionFromUrl
  29. FTtoString
  30. PrintFileTimeInInternetFormat
  31. CertHashToStr
  32. ConvertSecurityInfoIntoCertInfoStruct
  33. UnicodeToUtf8
  34. CountUnicodeToUtf8
  35. ConvertUnicodeToUtf8
  36. StringContainsHighAnsi
  37. Author:
  38. Richard L Firth (rfirth) 31-Oct-1994
  39. Revision History:
  40. 31-Oct-1994 rfirth
  41. Created
  42. --*/
  43. #include <wininetp.h>
  44. #if !defined(PAGE_SIZE)
  45. #define PAGE_SIZE 4096
  46. #endif
  47. #define DEFAULT_MAX_EXTENSION_LENGTH 8
  48. //
  49. // private prototypes
  50. //
  51. #ifndef WINHTTP_FOR_MSXML
  52. //
  53. // functions
  54. //
  55. void * __cdecl operator new(size_t Size) {
  56. return (void *)ALLOCATE_FIXED_MEMORY((UINT)Size);
  57. }
  58. void __cdecl operator delete(void * Pointer) {
  59. FREE_MEMORY((HLOCAL)Pointer);
  60. }
  61. #endif //!WINHTTP_FOR_MSXML
  62. #ifdef USE_ROCKALL
  63. #ifdef New
  64. #undef New
  65. #define SIZE_DIFF 1
  66. #if INET_DEBUG
  67. # include <DebugHeap.hpp>
  68. # define ROCKALL_HEAP DEBUG_HEAP
  69. #else
  70. # include <SmpHeap.hpp>
  71. # define ROCKALL_HEAP SMP_HEAP
  72. #endif
  73. ROCKALL_HEAP * s_pRockAllHeap;
  74. BYTE s_RockAllHeapStaticBuffer[sizeof(ROCKALL_HEAP)];
  75. void INITIALIZE_MEMORY_MANAGER()
  76. {
  77. s_pRockAllHeap = (ROCKALL_HEAP *) s_RockAllHeapStaticBuffer;
  78. s_pRockAllHeap->ROCKALL_HEAP::ROCKALL_HEAP();
  79. }
  80. void TERMINATE_MEMORY_MANAGER(BOOL bReport)
  81. {
  82. if (s_pRockAllHeap)
  83. {
  84. #if INET_DEBUG
  85. if (bReport)
  86. {
  87. s_pRockAllHeap->HeapLeaks();
  88. }
  89. #endif
  90. s_pRockAllHeap->ROCKALL_HEAP::~ROCKALL_HEAP();
  91. s_pRockAllHeap = NULL;
  92. ZeroMemory(s_RockAllHeapStaticBuffer, sizeof(s_RockAllHeapStaticBuffer));
  93. }
  94. }
  95. void *
  96. ALLOCATOR(int Flags, int Size)
  97. {
  98. INET_ASSERT(s_pRockAllHeap && "Heap not initialized!");
  99. return s_pRockAllHeap->New(Size, NULL, ((Flags & LMEM_ZEROINIT) ? true : false));
  100. }
  101. void *
  102. DEALLOCATOR(void * hLocal)
  103. {
  104. INET_ASSERT(s_pRockAllHeap && "Heap not initialized!");
  105. DWORD error = GetLastError();
  106. void * p = (s_pRockAllHeap->Delete(hLocal) ? NULL : hLocal);
  107. SetLastError(error);
  108. return p;
  109. }
  110. void *
  111. REALLOCATOR(void * hLocal, int Size, int Flags)
  112. {
  113. INET_ASSERT(s_pRockAllHeap && "Heap not initialized!");
  114. return s_pRockAllHeap->Resize(hLocal,
  115. Size,
  116. ((Flags & LMEM_MOVEABLE) ? SIZE_DIFF : 0),
  117. NULL,
  118. false,
  119. ((Flags & LMEM_ZEROINIT) ? true : false));
  120. }
  121. int
  122. MEMORYSIZER(void * hLocal)
  123. {
  124. int Size;
  125. INET_ASSERT(s_pRockAllHeap && "Heap not initialized!");
  126. s_pRockAllHeap->Details(hLocal, &Size);
  127. return Size;
  128. }
  129. #endif
  130. #endif
  131. LPSTR
  132. NewString(
  133. IN LPCSTR lpszIn,
  134. IN DWORD dwLen
  135. )
  136. /*++
  137. Routine Description:
  138. kind of version of strdup() but using LocalAlloc to allocate memory
  139. Arguments:
  140. String - pointer to string to make copy of
  141. Return Value:
  142. LPSTR
  143. Success - pointer to duplicated string
  144. Failure - NULL
  145. --*/
  146. {
  147. int len = (dwLen ? dwLen : strlen(lpszIn));
  148. LPSTR lpszOut;
  149. if (lpszOut = (LPSTR)ALLOCATE_FIXED_MEMORY(len+1)) {
  150. memcpy(lpszOut, lpszIn, len);
  151. *(lpszOut + len) = '\0';
  152. }
  153. return lpszOut;
  154. }
  155. LPWSTR
  156. NewStringW(
  157. IN LPCWSTR lpszIn,
  158. IN DWORD dwLen
  159. )
  160. /*++
  161. Routine Description:
  162. kind of version of strdup() but using LocalAlloc to allocate memory
  163. Arguments:
  164. String - pointer to string to make copy of
  165. Return Value:
  166. LPSTR
  167. Success - pointer to duplicated string
  168. Failure - NULL
  169. --*/
  170. {
  171. int len = (dwLen ? dwLen : lstrlenW(lpszIn));
  172. LPWSTR lpszOut;
  173. if (lpszOut = (LPWSTR)ALLOCATE_FIXED_MEMORY((sizeof(WCHAR)*(len+1)))) {
  174. memcpy(lpszOut, lpszIn, len*sizeof(WCHAR));
  175. *(lpszOut + len) = L'\0';
  176. }
  177. return lpszOut;
  178. }
  179. /*++
  180. Routine Description:
  181. kind of version of strcat() but using LocalAlloc to allocate memory
  182. Arguments:
  183. strings to concatenate
  184. Return Value:
  185. LPSTR
  186. Success - pointer to duplicated string
  187. Failure - NULL
  188. --*/
  189. LPSTR
  190. CatString (
  191. IN LPCSTR lpszLeft,
  192. IN LPCSTR lpszRight
  193. )
  194. {
  195. int cbLeft = strlen(lpszLeft);
  196. int cbRight = strlen(lpszRight) + 1; // include null termination
  197. LPSTR lpszOut;
  198. if (lpszOut = (LPSTR) ALLOCATE_FIXED_MEMORY (cbLeft + cbRight)) {
  199. memcpy (lpszOut, lpszLeft, cbLeft);
  200. memcpy (lpszOut + cbLeft, lpszRight, cbRight);
  201. }
  202. return lpszOut;
  203. }
  204. HLOCAL
  205. ResizeBuffer(
  206. IN HLOCAL BufferHandle,
  207. IN DWORD Size,
  208. IN BOOL Moveable
  209. )
  210. /*++
  211. Routine Description:
  212. Allocate, reallocate or free a buffer. If the buffer is moveable memory
  213. then it must be unlocked. If reallocating, the buffer can be grown or
  214. shrunk, depending on the current and required sizes
  215. Caveat Programmer:
  216. Regardless of whether a pre-existing buffer is moveable or fixed memory,
  217. it will be reallocated with the LMEM_MOVEABLE flag, possibly causing the
  218. output pointer to be different from the pre-existing pointer
  219. Arguments:
  220. BufferHandle - current handle of memory buffer. If NULL, a buffer will
  221. be allocated
  222. Size - size of buffer to allocate (or shrink to). If 0, the
  223. buffer will be freed
  224. Moveable - if TRUE and allocating memory then allocates a moveable
  225. memory buffer, else fixed
  226. Return Value:
  227. HLOCAL
  228. Success - handle of moveable memory buffer
  229. Failure - NULL;
  230. --*/
  231. {
  232. INET_ASSERT(!Moveable);
  233. if (BufferHandle == NULL) {
  234. //
  235. // don't allocate anything if no size - LocalAlloc() will return pointer
  236. // to memory object marked as discarded if we request a zero-length
  237. // moveable buffer. But I know that if Size is also 0, I don't want a
  238. // buffer at all, discarded or otherwise
  239. //
  240. if (Size != 0) {
  241. BufferHandle = ALLOCATE_MEMORY(Moveable ? LMEM_MOVEABLE : LMEM_FIXED, Size);
  242. }
  243. } else if (Size == 0) {
  244. BufferHandle = FREE_MEMORY(BufferHandle);
  245. INET_ASSERT(BufferHandle == NULL);
  246. } else {
  247. BufferHandle = REALLOCATE_MEMORY(BufferHandle, Size, LMEM_MOVEABLE);
  248. }
  249. return BufferHandle;
  250. }
  251. LPSTR
  252. _memrchr(
  253. IN LPSTR lpString,
  254. IN CHAR cTarget,
  255. IN INT iLength
  256. )
  257. /*++
  258. Routine Description:
  259. Reverse find character in string
  260. Arguments:
  261. lpString - pointer to string in which to locate character
  262. cTarget - target character to find
  263. iLength - length of string
  264. Return Value:
  265. LPSTR - pointer to located character or NULL
  266. --*/
  267. {
  268. for (--iLength; (iLength >= 0) && (lpString[iLength] != cTarget); --iLength) {
  269. //
  270. // empty loop
  271. //
  272. }
  273. return (iLength < 0) ? NULL : &lpString[iLength];
  274. }
  275. LPSTR
  276. strnistr(
  277. IN LPSTR str1,
  278. IN LPSTR str2,
  279. IN DWORD Length
  280. )
  281. /*++
  282. Routine Description:
  283. Case-insensitive search for substring
  284. Arguments:
  285. str1 - string to search in
  286. str2 - substring to find
  287. Length - of str1
  288. Return Value:
  289. LPSTR - pointer to located str2 in str1 or NULL
  290. --*/
  291. {
  292. if (!*str2) {
  293. return str1;
  294. }
  295. for (LPSTR cp = str1; *cp && Length; ++cp, --Length) {
  296. LPSTR s1 = cp;
  297. LPSTR s2 = str2;
  298. DWORD l2 = Length;
  299. while (*s1 && *s2 && l2 && (toupper(*s1) == toupper(*s2))) {
  300. ++s1;
  301. ++s2;
  302. --l2;
  303. }
  304. if (!*s2) {
  305. return cp;
  306. }
  307. if (!l2) {
  308. break;
  309. }
  310. }
  311. return NULL;
  312. }
  313. LPSTR
  314. FASTCALL
  315. PrivateStrChr(
  316. IN LPCSTR lpStart,
  317. IN WORD wMatch
  318. )
  319. /*++
  320. Routine Description:
  321. Find first occurrence of character in string
  322. Private implimentation of StrChrA, this code is based on
  323. a code snipet from ShlWapi, but by placing it here,
  324. we can remove the extra NLS support that was needed
  325. in SHLWAPI. This piece of code is over twice as fast
  326. as the call into SHLWAPI.
  327. Arguments:
  328. lpStart - points to start of null terminated string
  329. wMatch - the character to match
  330. Return Value:
  331. LPSTR - ptr to the first occurrence of ch in str, NULL if not found.
  332. --*/
  333. {
  334. for ( ; *lpStart; lpStart++)
  335. {
  336. if ((BYTE)*lpStart == LOBYTE(wMatch)) {
  337. return((LPSTR)lpStart);
  338. }
  339. }
  340. return (NULL);
  341. }
  342. DWORD
  343. GetTickCountWrap()
  344. {
  345. #ifdef DEBUG_GETTICKCOUNT
  346. static BOOL fInit = FALSE;
  347. static DWORD dwDelta = 0;
  348. static DWORD dwBasis = 0;
  349. if (!fInit)
  350. {
  351. HKEY clientKey;
  352. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  353. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
  354. 0, // reserved
  355. KEY_QUERY_VALUE,
  356. &clientKey))
  357. {
  358. DWORD dwSize = sizeof(dwDelta);
  359. RegQueryValueEx(clientKey, "RollOverDelta", NULL, NULL, (LPBYTE)&dwDelta, &dwSize);
  360. }
  361. dwBasis = GetTickCount();
  362. fInit = TRUE;
  363. }
  364. DWORD dwResult = GetTickCount() - dwBasis + dwDelta;
  365. return dwResult;
  366. #else
  367. return GetTickCount();
  368. #endif
  369. }
  370. DWORD
  371. PlatformType(
  372. IN OUT LPDWORD lpdwVersion5os
  373. )
  374. /*++
  375. Routine Description:
  376. Returns the platform type based on the operating system information. We use
  377. our own platform types
  378. Arguments:
  379. lpdwVersion5os - optional pointer to value, set to TRUE if we on NT 5
  380. Return Value:
  381. DWORD
  382. Failure - PLATFORM_TYPE_UNKNOWN
  383. either GetVersionEx() failed, or we are running on an
  384. unrecognized operating system
  385. Success - PLATFORM_TYPE_WIN95
  386. The world's favourite desktop O/S
  387. PLATFORM_TYPE_WINNT
  388. The world's best O/S on top of anything
  389. --*/
  390. {
  391. #ifndef UNIX
  392. OSVERSIONINFO versionInfo;
  393. *lpdwVersion5os = FALSE;
  394. versionInfo.dwOSVersionInfoSize = sizeof(versionInfo);
  395. if (GetVersionEx(&versionInfo)) {
  396. switch (versionInfo.dwPlatformId) {
  397. case VER_PLATFORM_WIN32_WINDOWS:
  398. if(versionInfo.dwMinorVersion >= 90) {
  399. GlobalPlatformMillennium = TRUE;
  400. }
  401. return PLATFORM_TYPE_WIN95;
  402. case VER_PLATFORM_WIN32_NT:
  403. if ( lpdwVersion5os &&
  404. versionInfo.dwMajorVersion >= 5 ) {
  405. *lpdwVersion5os = TRUE;
  406. }
  407. return PLATFORM_TYPE_WINNT;
  408. }
  409. }
  410. return PLATFORM_TYPE_UNKNOWN;
  411. #else
  412. return PLATFORM_TYPE_UNIX;
  413. #endif /* UNIX */
  414. }
  415. //
  416. //DWORD
  417. //PlatformSupport(
  418. // VOID
  419. // )
  420. //
  421. ///*++
  422. //
  423. //Routine Description:
  424. //
  425. // Returns a bitmap of capabilities supported by this operating system
  426. //
  427. //Arguments:
  428. //
  429. // None.
  430. //
  431. //Return Value:
  432. //
  433. // DWORD
  434. //
  435. //--*/
  436. //
  437. //{
  438. // switch (PlatformType()) {
  439. // case PLATFORM_TYPE_WINNT:
  440. // return PLATFORM_SUPPORTS_UNICODE;
  441. // }
  442. // return 0;
  443. //}
  444. DWORD
  445. GetTimeoutValue(
  446. IN DWORD TimeoutOption
  447. )
  448. /*++
  449. Routine Description:
  450. Gets a timeout value. The timeout is retrieved from the current handle. If
  451. it is not available in the current handle then the parent handle is checked
  452. (actually the current handle is derived from the parent, so this doesn't
  453. really do anything). If the value is still not available, then the global
  454. default is used
  455. Arguments:
  456. TimeoutOption - WINHTTP_OPTION_ value used to specify the timeout value
  457. Return Value:
  458. DWORD
  459. Requested timeout value
  460. --*/
  461. {
  462. HINTERNET hInternet;
  463. DWORD timeout;
  464. DWORD error;
  465. HINTERNET_HANDLE_TYPE handleType;
  466. hInternet = InternetGetMappedObjectHandle();
  467. if (hInternet)
  468. {
  469. error = ((HANDLE_OBJECT*)hInternet)->IsValid(TypeWildHandle);
  470. if (error == ERROR_SUCCESS)
  471. {
  472. error = RGetHandleType(hInternet, &handleType);
  473. if (error == ERROR_SUCCESS)
  474. {
  475. switch(handleType)
  476. {
  477. case TypeHttpRequestHandle:
  478. //no error possible here
  479. timeout = ((HTTP_REQUEST_HANDLE_OBJECT*)hInternet)->GetTimeout(TimeoutOption);
  480. break;
  481. case TypeHttpConnectHandle:
  482. //no timeouts on this handle
  483. //go up to parent
  484. hInternet = (HINTERNET)GetRootHandle((INTERNET_HANDLE_OBJECT *)hInternet);
  485. //fall through
  486. case TypeInternetHandle:
  487. //either there was an error in allocing memory for OPTIONAL_PARAMS struct
  488. //or the option may not have been set
  489. //in either case, force the global timeout choice by setting an error (not propagated)
  490. if (! ((INTERNET_HANDLE_OBJECT*)hInternet)->GetTimeout(TimeoutOption, &timeout) )
  491. error = E_FAIL;
  492. break;
  493. default:
  494. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  495. break;
  496. }
  497. }
  498. }
  499. }
  500. if ( !hInternet || (error != ERROR_SUCCESS))
  501. {
  502. //should this ever happen?
  503. INET_ASSERT(FALSE);
  504. switch (TimeoutOption) {
  505. case WINHTTP_OPTION_RESOLVE_TIMEOUT:
  506. timeout = GlobalResolveTimeout;
  507. break;
  508. case WINHTTP_OPTION_CONNECT_TIMEOUT:
  509. timeout = GlobalConnectTimeout;
  510. break;
  511. case WINHTTP_OPTION_CONNECT_RETRIES:
  512. timeout = GlobalConnectRetries;
  513. break;
  514. case WINHTTP_OPTION_SEND_TIMEOUT:
  515. timeout = GlobalSendTimeout;
  516. break;
  517. case WINHTTP_OPTION_RECEIVE_TIMEOUT:
  518. timeout = GlobalReceiveTimeout;
  519. break;
  520. default:
  521. error = ERROR_WINHTTP_INCORRECT_HANDLE_TYPE;
  522. timeout = 0;
  523. break;
  524. }
  525. }
  526. return timeout;
  527. }
  528. DWORD
  529. ProbeReadBuffer(
  530. IN LPVOID lpBuffer,
  531. IN DWORD dwBufferLength
  532. )
  533. /*++
  534. Routine Description:
  535. Probes a buffer for readability. Used as part of API parameter validation,
  536. this function tests the first and last locations in a buffer. This is not
  537. as strict as the IsBadXPtr() Windows APIs, but it means we don't have to
  538. test every location in the buffer
  539. Arguments:
  540. lpBuffer - pointer to buffer to test
  541. dwBufferLength - length of buffer
  542. Return Value:
  543. DWORD
  544. Success - ERROR_SUCCESS
  545. Failure - ERROR_INVALID_PARAMETER
  546. --*/
  547. {
  548. DWORD error;
  549. //
  550. // the buffer can be NULL if the probe length is 0. Otherwise, its an error
  551. //
  552. if (lpBuffer == NULL) {
  553. error = (dwBufferLength == 0) ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
  554. } else if (dwBufferLength != 0) {
  555. __try {
  556. LPBYTE p;
  557. LPBYTE end;
  558. volatile BYTE b;
  559. p = (LPBYTE)lpBuffer;
  560. end = p + dwBufferLength - 1;
  561. b = *end;
  562. //
  563. // visit every page in the buffer - it doesn't matter that we may
  564. // test a character in the middle of a page
  565. //
  566. for (; p < end; p += PAGE_SIZE) {
  567. b = *p;
  568. }
  569. error = ERROR_SUCCESS;
  570. } __except(EXCEPTION_EXECUTE_HANDLER) {
  571. error = ERROR_INVALID_PARAMETER;
  572. }
  573. ENDEXCEPT
  574. } else {
  575. //
  576. // zero-length buffer
  577. //
  578. error = ERROR_INVALID_PARAMETER;
  579. }
  580. return error;
  581. }
  582. DWORD
  583. ProbeWriteBuffer(
  584. IN LPVOID lpBuffer,
  585. IN DWORD dwBufferLength
  586. )
  587. /*++
  588. Routine Description:
  589. Probes a buffer for writeability. Used as part of API parameter validation,
  590. this function tests the first and last locations in a buffer. This is not
  591. as strict as the IsBadXPtr() Windows APIs, but it means we don't have to
  592. test every location in the buffer
  593. Arguments:
  594. lpBuffer - pointer to buffer to test
  595. dwBufferLength - length of buffer
  596. Return Value:
  597. DWORD
  598. Success - ERROR_SUCCESS
  599. Failure - ERROR_INVALID_PARAMETER
  600. --*/
  601. {
  602. DWORD error;
  603. //
  604. // the buffer can be NULL if the probe length is 0. Otherwise, its an error
  605. //
  606. if (lpBuffer == NULL) {
  607. error = (dwBufferLength == 0) ? ERROR_SUCCESS : ERROR_INVALID_PARAMETER;
  608. } else if (dwBufferLength != 0) {
  609. __try {
  610. LPBYTE p;
  611. LPBYTE end;
  612. volatile BYTE b;
  613. p = (LPBYTE)lpBuffer;
  614. end = p + dwBufferLength - 1;
  615. b = *end;
  616. *end = b;
  617. //
  618. // visit every page in the buffer - it doesn't matter that we may
  619. // test a character in the middle of a page
  620. //
  621. for (; p < end; p += PAGE_SIZE) {
  622. b = *p;
  623. *p = b;
  624. }
  625. error = ERROR_SUCCESS;
  626. } __except(EXCEPTION_EXECUTE_HANDLER) {
  627. error = ERROR_INVALID_PARAMETER;
  628. }
  629. ENDEXCEPT
  630. } else {
  631. //
  632. // zero-length buffer
  633. //
  634. error = ERROR_SUCCESS;
  635. }
  636. return error;
  637. }
  638. DWORD
  639. ProbeAndSetDword(
  640. IN LPDWORD lpDword,
  641. IN DWORD dwValue
  642. )
  643. /*++
  644. Routine Description:
  645. Probes a single DWORD buffer for writeability, and as a side-effect sets it
  646. to a default value. Used as part of API parameter validation
  647. Arguments:
  648. lpDword - pointer to DWORD buffer to test
  649. dwValue - default value to set
  650. Return Value:
  651. DWORD
  652. Success - ERROR_SUCCESS
  653. Failure - ERROR_INVALID_PARAMETER
  654. --*/
  655. {
  656. DWORD error;
  657. __try {
  658. *lpDword = dwValue;
  659. error = ERROR_SUCCESS;
  660. } __except(EXCEPTION_EXECUTE_HANDLER) {
  661. error = ERROR_INVALID_PARAMETER;
  662. }
  663. ENDEXCEPT
  664. return error;
  665. }
  666. DWORD
  667. ProbeString(
  668. IN LPSTR lpString,
  669. OUT LPDWORD lpdwStringLength
  670. )
  671. /*++
  672. Routine Description:
  673. Probes a string buffer for readability, and returns the length of the string
  674. Arguments:
  675. lpString - pointer to string to check
  676. lpdwStringLength - returned length of string
  677. Return Value:
  678. DWORD
  679. Success - ERROR_SUCCESS
  680. Failure - ERROR_INVALID_PARAMETER
  681. --*/
  682. {
  683. DWORD error;
  684. DWORD length;
  685. //
  686. // initialize string length and return code
  687. //
  688. length = 0;
  689. error = ERROR_SUCCESS;
  690. //
  691. // the buffer can be NULL
  692. //
  693. if (lpString != NULL) {
  694. __try {
  695. //
  696. // unfortunately, for a string, we have to visit every location in
  697. // the buffer to find the terminator
  698. //
  699. while (*lpString != '\0') {
  700. ++length;
  701. ++lpString;
  702. }
  703. } __except(EXCEPTION_EXECUTE_HANDLER) {
  704. error = ERROR_INVALID_PARAMETER;
  705. }
  706. ENDEXCEPT
  707. }
  708. *lpdwStringLength = length;
  709. return error;
  710. }
  711. DWORD
  712. ProbeStringW(
  713. IN LPWSTR lpString,
  714. OUT LPDWORD lpdwStringLength
  715. )
  716. /*++
  717. Routine Description:
  718. Probes a wide string buffer for readability, and returns the length of the string
  719. Arguments:
  720. lpString - pointer to string to check
  721. lpdwStringLength - returned length of string
  722. Return Value:
  723. DWORD
  724. Success - ERROR_SUCCESS
  725. Failure - ERROR_INVALID_PARAMETER
  726. --*/
  727. {
  728. DWORD error;
  729. DWORD length;
  730. //
  731. // initialize string length and return code
  732. //
  733. length = 0;
  734. error = ERROR_SUCCESS;
  735. //
  736. // the buffer can be NULL
  737. //
  738. if (lpString != NULL) {
  739. __try {
  740. //
  741. // unfortunately, for a string, we have to visit every location in
  742. // the buffer to find the terminator
  743. //
  744. while (*lpString != '\0') {
  745. ++length;
  746. ++lpString;
  747. }
  748. } __except(EXCEPTION_EXECUTE_HANDLER) {
  749. error = ERROR_INVALID_PARAMETER;
  750. }
  751. ENDEXCEPT
  752. }
  753. *lpdwStringLength = length;
  754. return error;
  755. }
  756. DWORD
  757. LoadDllEntryPoints(
  758. IN OUT LPDLL_INFO lpDllInfo,
  759. IN DWORD dwFlags
  760. )
  761. /*++
  762. Routine Description:
  763. Dynamically loads a DLL and the entry points described in lpDllEntryPoints
  764. Assumes: 1. Any thread serialization taken care of by caller
  765. 2. Module handle, entry point addresses and reference count
  766. already set to 0 if this is first time the DLL_INFO is
  767. being used to load the DLL
  768. Arguments:
  769. lpDllInfo - pointer to DLL_INFO structure containing all info about DLL
  770. and entry points to load
  771. dwFlags - flags controlling how this function operates:
  772. LDEP_PARTIAL_LOAD_OK
  773. - not fatal if we can't load all entry points
  774. Return Value:
  775. DWORD
  776. Success - ERROR_SUCCESS
  777. Failure - Win32 error
  778. --*/
  779. {
  780. DEBUG_ENTER((DBG_UTIL,
  781. Dword,
  782. "LoadDllEntryPoints",
  783. "%x [%q, %d], %#x",
  784. lpDllInfo,
  785. lpDllInfo->lpszDllName,
  786. lpDllInfo->dwNumberOfEntryPoints,
  787. dwFlags
  788. ));
  789. DWORD error = ERROR_SUCCESS;
  790. if (lpDllInfo->hModule == NULL) {
  791. DWORD dwMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  792. HMODULE hDll = LoadLibrary(lpDllInfo->lpszDllName);
  793. if (hDll != NULL) {
  794. lpDllInfo->hModule = hDll;
  795. lpDllInfo->LoadCount = 1;
  796. for (DWORD i = 0; i < lpDllInfo->dwNumberOfEntryPoints; ++i) {
  797. FARPROC proc = GetProcAddress(
  798. hDll,
  799. lpDllInfo->lpEntryPoints[i].lpszProcedureName
  800. );
  801. *lpDllInfo->lpEntryPoints[i].lplpfnProcedure = proc;
  802. if ((proc == NULL) && !(dwFlags & LDEP_PARTIAL_LOAD_OK)) {
  803. error = GetLastError();
  804. UnloadDllEntryPoints(lpDllInfo, TRUE);
  805. break;
  806. }
  807. }
  808. } else {
  809. error = GetLastError();
  810. }
  811. SetErrorMode(dwMode);
  812. } else {
  813. DEBUG_PRINT(UTIL,
  814. INFO,
  815. ("info for %q already loaded\n",
  816. lpDllInfo->lpszDllName
  817. ));
  818. InterlockedIncrement(&lpDllInfo->LoadCount);
  819. }
  820. DEBUG_LEAVE(error);
  821. return error;
  822. }
  823. DWORD
  824. UnloadDllEntryPoints(
  825. IN OUT LPDLL_INFO lpDllInfo,
  826. IN BOOL bForce
  827. )
  828. /*++
  829. Routine Description:
  830. Undoes the work of LoadDllEntryPoints()
  831. Assumes: 1. Any thread serialization taken care of by caller
  832. Arguments:
  833. lpDllInfo - pointer to DLL_INFO structure containing all info about DLL
  834. and (loaded) entry points
  835. bForce - TRUE if the DLL will be unloaded irrespective of the usage
  836. count
  837. Return Value:
  838. DWORD
  839. Success - ERROR_SUCCESS
  840. Failure - Win32 error
  841. --*/
  842. {
  843. DEBUG_ENTER((DBG_UTIL,
  844. Dword,
  845. "UnloadDllEntryPoints",
  846. "%x [%q, %d], %B",
  847. lpDllInfo,
  848. lpDllInfo->lpszDllName,
  849. lpDllInfo->dwNumberOfEntryPoints,
  850. bForce
  851. ));
  852. DWORD error = ERROR_SUCCESS;
  853. if (bForce) {
  854. lpDllInfo->LoadCount = 0;
  855. } else if (InterlockedDecrement(&lpDllInfo->LoadCount) == 0) {
  856. bForce = TRUE;
  857. }
  858. if (bForce && (lpDllInfo->hModule != NULL)) {
  859. if (!FreeLibrary(lpDllInfo->hModule)) {
  860. error = GetLastError();
  861. }
  862. //
  863. // even if FreeLibrary() failed we clear out the load info
  864. //
  865. lpDllInfo->hModule = NULL;
  866. for (DWORD i = 0; i < lpDllInfo->dwNumberOfEntryPoints; ++i) {
  867. *lpDllInfo->lpEntryPoints[i].lplpfnProcedure = NULL;
  868. }
  869. }
  870. DEBUG_LEAVE(error);
  871. return error;
  872. }
  873. #ifndef CERT_E_WRONG_USAGE
  874. # define CERT_E_WRONG_USAGE _HRESULT_TYPEDEF_(0x800B0110)
  875. #endif
  876. DWORD
  877. MapInternetError(
  878. IN DWORD dwErrorCode,
  879. IN LPDWORD lpdwStatus /* = NULL */
  880. )
  881. /*++
  882. Routine Description:
  883. Maps a winsock/RPC/transport error into a more user-friendly WinInet error,
  884. and stores the original error in the per-thread context so that the app can
  885. retrieve it if it really cares
  886. N.B. We should no longer be receiving winsock errors directly at the WinInet
  887. interface. They are available via InternetGetLastResponseInfo()
  888. Arguments:
  889. dwErrorCode - original (winsock) error code to map
  890. Return Value:
  891. DWORD
  892. Mapped error code, or the orignal error if its not one that we handle
  893. --*/
  894. {
  895. LPINTERNET_THREAD_INFO lpThreadInfo;
  896. DWORD dwStatus = 0;
  897. DEBUG_ENTER((DBG_UTIL,
  898. Dword,
  899. "MapInternetError",
  900. "%#x [%s]",
  901. dwErrorCode,
  902. InternetMapError(dwErrorCode)
  903. ));
  904. lpThreadInfo = InternetGetThreadInfo();
  905. if (lpThreadInfo) {
  906. lpThreadInfo->dwMappedErrorCode = dwErrorCode;
  907. }
  908. switch (dwErrorCode) {
  909. case SEC_E_INSUFFICIENT_MEMORY :
  910. dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  911. break;
  912. case SEC_E_INVALID_HANDLE :
  913. case SEC_E_UNSUPPORTED_FUNCTION :
  914. case SEC_E_TARGET_UNKNOWN :
  915. case SEC_E_INTERNAL_ERROR :
  916. case SEC_E_SECPKG_NOT_FOUND :
  917. case SEC_E_NOT_OWNER :
  918. case SEC_E_CANNOT_INSTALL :
  919. case SEC_E_INVALID_TOKEN :
  920. case SEC_E_CANNOT_PACK :
  921. case SEC_E_QOP_NOT_SUPPORTED :
  922. case SEC_E_NO_IMPERSONATION :
  923. case SEC_E_LOGON_DENIED :
  924. case SEC_E_UNKNOWN_CREDENTIALS :
  925. case SEC_E_NO_CREDENTIALS :
  926. case SEC_E_MESSAGE_ALTERED :
  927. case SEC_E_OUT_OF_SEQUENCE :
  928. case SEC_E_NO_AUTHENTICATING_AUTHORITY:
  929. case SEC_I_CONTINUE_NEEDED :
  930. case SEC_I_COMPLETE_NEEDED :
  931. case SEC_I_COMPLETE_AND_CONTINUE :
  932. case SEC_I_LOCAL_LOGON :
  933. case SEC_E_BAD_PKGID :
  934. case SEC_E_CONTEXT_EXPIRED :
  935. case SEC_E_INCOMPLETE_MESSAGE :
  936. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  937. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR;
  938. break;
  939. // Cert and Encryption errors
  940. case CERT_E_EXPIRED:
  941. case CERT_E_VALIDITYPERIODNESTING:
  942. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  943. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID;
  944. break;
  945. case CERT_E_UNTRUSTEDROOT:
  946. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  947. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA;
  948. break;
  949. case CERT_E_CN_NO_MATCH:
  950. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  951. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID;
  952. break;
  953. case CRYPT_E_REVOKED:
  954. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  955. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED;
  956. break;
  957. // ignore revocation if the certificate does not have a CDP
  958. case CRYPT_E_NO_REVOCATION_CHECK:
  959. dwErrorCode = ERROR_SUCCESS;
  960. break;
  961. case CRYPT_E_REVOCATION_OFFLINE:
  962. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  963. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED;
  964. break;
  965. case CERT_E_ROLE:
  966. case CERT_E_PATHLENCONST:
  967. case CERT_E_CRITICAL:
  968. case CERT_E_PURPOSE:
  969. case CERT_E_ISSUERCHAINING:
  970. case CERT_E_MALFORMED:
  971. case CERT_E_CHAINING:
  972. // We can't allow connection if server doesn't have a server auth certificate.
  973. // To force CERT_E_WRONG_USAGE to error out we map it to the error below.
  974. // In the future we need to map it to it's own non-recoverable error, so we can
  975. // give the user a specific error message.
  976. case CERT_E_WRONG_USAGE:
  977. dwErrorCode = ERROR_WINHTTP_SECURE_FAILURE;
  978. dwStatus = WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT;
  979. break;
  980. case WSAEINTR:
  981. case WSAEBADF:
  982. case WSAEACCES:
  983. case WSAEFAULT:
  984. case WSAEINVAL:
  985. case WSAEMFILE:
  986. case WSAEADDRINUSE:
  987. case WSAEADDRNOTAVAIL:
  988. dwErrorCode = ERROR_WINHTTP_INTERNAL_ERROR;
  989. break;
  990. case WSAENOTSOCK:
  991. //
  992. // typically, if we see this error its because we tried to use a closed
  993. // socket handle
  994. //
  995. dwErrorCode = ERROR_WINHTTP_OPERATION_CANCELLED;
  996. break;
  997. case WSAEWOULDBLOCK:
  998. case WSAEINPROGRESS:
  999. case WSAEALREADY:
  1000. case WSAEDESTADDRREQ:
  1001. case WSAEPROTOTYPE:
  1002. case WSAENOPROTOOPT:
  1003. case WSAEPROTONOSUPPORT:
  1004. case WSAESOCKTNOSUPPORT:
  1005. case WSAEOPNOTSUPP:
  1006. case WSAEISCONN:
  1007. case WSAETOOMANYREFS:
  1008. case WSAELOOP:
  1009. case WSAENAMETOOLONG:
  1010. case WSAENOTEMPTY:
  1011. case WSAEPROCLIM:
  1012. case WSAEUSERS:
  1013. case WSAEDQUOT:
  1014. case WSAESTALE:
  1015. case WSAEREMOTE:
  1016. case WSAEDISCON:
  1017. case WSASYSNOTREADY:
  1018. case WSAVERNOTSUPPORTED:
  1019. case WSANOTINITIALISED:
  1020. //
  1021. // currently unmapped errors
  1022. //
  1023. break;
  1024. case WSAEMSGSIZE:
  1025. dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
  1026. break;
  1027. case WSAEPFNOSUPPORT:
  1028. case WSAEAFNOSUPPORT:
  1029. dwErrorCode = ERROR_NOT_SUPPORTED;
  1030. break;
  1031. case WSAECONNABORTED:
  1032. case WSAESHUTDOWN:
  1033. case WSAECONNRESET:
  1034. case WSAENETRESET:
  1035. dwErrorCode = ERROR_WINHTTP_CONNECTION_ERROR;
  1036. break;
  1037. case WSAENOBUFS:
  1038. dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  1039. break;
  1040. case WSAETIMEDOUT:
  1041. dwErrorCode = ERROR_WINHTTP_TIMEOUT;
  1042. break;
  1043. case WSAENETDOWN:
  1044. case WSAECONNREFUSED:
  1045. case WSAENETUNREACH:
  1046. case WSAENOTCONN:
  1047. dwErrorCode = ERROR_WINHTTP_CANNOT_CONNECT;
  1048. break;
  1049. case WSAEHOSTDOWN:
  1050. case WSAEHOSTUNREACH:
  1051. case WSAHOST_NOT_FOUND:
  1052. case WSATRY_AGAIN:
  1053. case WSANO_RECOVERY:
  1054. case WSANO_DATA:
  1055. dwErrorCode = ERROR_WINHTTP_NAME_NOT_RESOLVED;
  1056. break;
  1057. default:
  1058. DEBUG_PRINT(UTIL,
  1059. WARNING,
  1060. ("MapInternetError(): unmapped error code %d [%#x]\n",
  1061. dwErrorCode,
  1062. dwErrorCode
  1063. ));
  1064. break;
  1065. }
  1066. if (lpdwStatus)
  1067. {
  1068. *lpdwStatus = dwStatus;
  1069. DEBUG_PRINT(UTIL,
  1070. INFO,
  1071. ("MapInternetError(): mapped status flag %#x\n",
  1072. *lpdwStatus
  1073. ));
  1074. }
  1075. DEBUG_LEAVE(dwErrorCode);
  1076. return dwErrorCode;
  1077. }
  1078. DWORD
  1079. CalculateHashValue(
  1080. IN LPSTR lpszString
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. Calculate a hash number given a string
  1085. Arguments:
  1086. lpszString - string to hash
  1087. Return Value:
  1088. DWORD
  1089. --*/
  1090. {
  1091. DWORD hashValue = 0;
  1092. DWORD position = 1;
  1093. while (*lpszString) {
  1094. hashValue += *lpszString * position;
  1095. ++lpszString;
  1096. ++position;
  1097. }
  1098. return hashValue;
  1099. }
  1100. VOID GetCurrentGmtTime(
  1101. LPFILETIME lpFt
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine returns the current GMT time
  1106. Arguments:
  1107. lpFt FILETIME strucutre in which this is returned
  1108. Returns:
  1109. Comments:
  1110. --*/
  1111. {
  1112. SYSTEMTIME sSysT;
  1113. GetSystemTime(&sSysT);
  1114. SystemTimeToFileTime(&sSysT, lpFt);
  1115. }
  1116. LPTSTR
  1117. FTtoString(
  1118. IN FILETIME *pftTime)
  1119. /*++
  1120. FTtoString:
  1121. This routine converts a given FILETIME structure to a string representing
  1122. the given date and time in the local format.
  1123. Arguments:
  1124. pftTime supplies the FILETIME structure to convert.
  1125. Return Value:
  1126. NULL - Memory allocation failure.
  1127. Otherwise, the address of the string, allocated via LocalAlloc.
  1128. Author:
  1129. Doug Barlow (dbarlow) 4/12/1996
  1130. --*/
  1131. {
  1132. LONG cchTotal, cchNeeded;
  1133. SYSTEMTIME stTime, stLocal;
  1134. LPTSTR szDateTime = NULL;
  1135. //
  1136. // Convert the FILETIME to a SYSTEMTIME.
  1137. //
  1138. if (!FileTimeToSystemTime(pftTime, &stTime))
  1139. goto ErrorExit;
  1140. //
  1141. // For now, leave it in GMT time, function not implimented in Win'95.
  1142. //
  1143. //if ( IsPlatformWinNT() )
  1144. //{
  1145. // if (!SystemTimeToTzSpecificLocalTime(NULL, &stTime, &stLocal))
  1146. // goto ErrorExit;
  1147. //}
  1148. //else
  1149. {
  1150. stLocal = stTime;
  1151. }
  1152. //
  1153. // Calculate how long the date string will be.
  1154. //
  1155. cchTotal =
  1156. GetDateFormat(
  1157. LOCALE_SYSTEM_DEFAULT,
  1158. DATE_SHORTDATE,
  1159. &stLocal,
  1160. NULL,
  1161. NULL,
  1162. 0);
  1163. if (0 >= cchTotal)
  1164. goto ErrorExit;
  1165. cchNeeded =
  1166. GetTimeFormat(
  1167. LOCALE_SYSTEM_DEFAULT,
  1168. 0,
  1169. &stLocal,
  1170. NULL,
  1171. NULL,
  1172. 0);
  1173. if (0 >= cchNeeded)
  1174. goto ErrorExit;
  1175. cchTotal += cchNeeded;
  1176. cchTotal += 4 * sizeof(TCHAR); // space, trailing NULL, and two extra.
  1177. szDateTime = (LPTSTR)ALLOCATE_MEMORY(LMEM_FIXED, cchTotal);
  1178. if (NULL == szDateTime)
  1179. goto ErrorExit;
  1180. //
  1181. // Fill in the time string.
  1182. //
  1183. cchNeeded =
  1184. GetDateFormat(
  1185. LOCALE_SYSTEM_DEFAULT,
  1186. DATE_SHORTDATE,
  1187. &stLocal,
  1188. NULL,
  1189. szDateTime,
  1190. cchTotal);
  1191. if (0 >= cchNeeded)
  1192. goto ErrorExit;
  1193. lstrcat(szDateTime, TEXT(" "));
  1194. cchNeeded = lstrlen(szDateTime);
  1195. cchNeeded =
  1196. GetTimeFormat(
  1197. LOCALE_SYSTEM_DEFAULT,
  1198. 0,
  1199. &stLocal,
  1200. NULL,
  1201. &szDateTime[cchNeeded],
  1202. cchTotal - cchNeeded);
  1203. if (0 >= cchNeeded)
  1204. goto ErrorExit;
  1205. return szDateTime;
  1206. ErrorExit:
  1207. if (NULL != szDateTime)
  1208. FREE_MEMORY(szDateTime);
  1209. return NULL;
  1210. }
  1211. BOOL
  1212. CertHashToStr(
  1213. IN LPSTR lpMD5Hash,
  1214. IN DWORD dwMD5HashSize,
  1215. IN OUT LPSTR *lplpszHashStr
  1216. )
  1217. /*++
  1218. Routine Description:
  1219. Converts a set of bytes into a neatly formated string of ':' (colon) seperated
  1220. hex digits that can be shown to the user.
  1221. Arguments:
  1222. lpMD5Hash - ptr to set of hash bytes
  1223. dwMD5HashSize - size of lpMD5Hash
  1224. lplpszHashStr - ptr to ptr where newly allocated return string will be stored.
  1225. Return Value:
  1226. BOOL
  1227. --*/
  1228. {
  1229. DWORD dwStrSize = (2*dwMD5HashSize) + dwMD5HashSize;
  1230. LPSTR lpszHashStr;
  1231. *lplpszHashStr = new CHAR[dwStrSize];
  1232. if ( *lplpszHashStr == NULL )
  1233. {
  1234. return FALSE;
  1235. }
  1236. lpszHashStr = *lplpszHashStr;
  1237. for ( DWORD i = 0 ; i < dwMD5HashSize; i++ )
  1238. {
  1239. unsigned char uHashByte;
  1240. if ( i != 0 )
  1241. {
  1242. *lpszHashStr = ':';
  1243. lpszHashStr++;
  1244. }
  1245. uHashByte = (unsigned char) * ( ((unsigned char * ) lpMD5Hash) + i);
  1246. wsprintf( lpszHashStr, "%02X", uHashByte);
  1247. lpszHashStr += 2;
  1248. }
  1249. INET_ASSERT( *lpszHashStr == '\0' );
  1250. return TRUE;
  1251. }
  1252. //
  1253. // private functions
  1254. //
  1255. DWORD
  1256. ConvertSecurityInfoIntoCertInfoStruct(
  1257. IN LPINTERNET_SECURITY_INFO pSecInfo,
  1258. OUT INTERNET_CERTIFICATE_INFO *pCertificate,
  1259. IN OUT DWORD *pcbCertificate
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. Converts an X509 Certificate Structure into a WININET struct
  1264. used for storing the same info.
  1265. Arguments:
  1266. hContext - Context handle of the active SSPI session.
  1267. pCertInfo - Pointer to Structure where info is returned in.
  1268. Return Value:
  1269. DWORD
  1270. ERROR_SUCCESS - if cert cannot be converted
  1271. ERROR_NOT_ENOUGH_MEMORY
  1272. --*/
  1273. {
  1274. DWORD error = ERROR_SUCCESS;
  1275. PCERT_INFO pCertInfo = NULL;
  1276. DWORD cbCert = sizeof(INTERNET_CERTIFICATE_INFO),
  1277. cbSubject = 0,
  1278. cbIssuer = 0;
  1279. BOOL fCanAlloc = FALSE;
  1280. if(pSecInfo == NULL)
  1281. {
  1282. error = ERROR_WINHTTP_INTERNAL_ERROR;
  1283. goto quit;
  1284. }
  1285. if(pCertificate == NULL || *pcbCertificate == 0)
  1286. {
  1287. *pcbCertificate = sizeof(INTERNET_CERTIFICATE_INFO);
  1288. goto quit;
  1289. }
  1290. if(*pcbCertificate < sizeof(INTERNET_CERTIFICATE_INFO) )
  1291. {
  1292. error = ERROR_WINHTTP_INTERNAL_ERROR;
  1293. goto quit;
  1294. }
  1295. ZeroMemory(pCertificate, sizeof(INTERNET_CERTIFICATE_INFO));
  1296. fCanAlloc = TRUE;
  1297. if(pSecInfo->pCertificate &&
  1298. pSecInfo->pCertificate->pCertInfo )
  1299. {
  1300. pCertInfo = pSecInfo->pCertificate->pCertInfo;
  1301. //
  1302. // Now Convert Structures from SSPI format to WININET style.
  1303. // While in the process, we'll role them all into one
  1304. // big structure that we'll return to the user.
  1305. //
  1306. cbSubject = CertNameToStr(pSecInfo->pCertificate->dwCertEncodingType,
  1307. &pCertInfo->Subject,
  1308. CERT_SIMPLE_NAME_STR |
  1309. CERT_NAME_STR_CRLF_FLAG |
  1310. CERT_NAME_STR_NO_PLUS_FLAG,
  1311. NULL,
  1312. 0);
  1313. if ( cbSubject > 0 )
  1314. {
  1315. // freed by caller outside of wininet
  1316. pCertificate->lpszSubjectInfo = (LPSTR) LocalAlloc(LPTR, cbSubject);
  1317. if ( pCertificate->lpszSubjectInfo == NULL )
  1318. {
  1319. error = ERROR_NOT_ENOUGH_MEMORY;
  1320. goto quit;
  1321. }
  1322. CertNameToStr(pSecInfo->pCertificate->dwCertEncodingType,
  1323. &pCertInfo->Subject,
  1324. CERT_SIMPLE_NAME_STR |
  1325. CERT_NAME_STR_CRLF_FLAG |
  1326. CERT_NAME_STR_NO_PLUS_FLAG ,
  1327. pCertificate->lpszSubjectInfo,
  1328. cbSubject);
  1329. }
  1330. cbIssuer = CertNameToStr(pSecInfo->pCertificate->dwCertEncodingType,
  1331. &pCertInfo->Issuer,
  1332. CERT_SIMPLE_NAME_STR |
  1333. CERT_NAME_STR_CRLF_FLAG |
  1334. CERT_NAME_STR_NO_PLUS_FLAG,
  1335. NULL,
  1336. 0);
  1337. if ( cbIssuer > 0 )
  1338. {
  1339. // freed by caller outside of wininet
  1340. pCertificate->lpszIssuerInfo = (LPSTR) LocalAlloc(LPTR, cbIssuer);
  1341. if ( pCertificate->lpszIssuerInfo == NULL )
  1342. {
  1343. error = ERROR_NOT_ENOUGH_MEMORY;
  1344. goto quit;
  1345. }
  1346. CertNameToStr(pSecInfo->pCertificate->dwCertEncodingType,
  1347. &pCertInfo->Issuer,
  1348. CERT_SIMPLE_NAME_STR |
  1349. CERT_NAME_STR_CRLF_FLAG |
  1350. CERT_NAME_STR_NO_PLUS_FLAG ,
  1351. pCertificate->lpszIssuerInfo,
  1352. cbIssuer);
  1353. }
  1354. CopyMemory(
  1355. (PVOID) &pCertificate->ftStart,
  1356. (PVOID) &pCertInfo->NotBefore,
  1357. sizeof(FILETIME)
  1358. );
  1359. CopyMemory(
  1360. (PVOID) &pCertificate->ftExpiry,
  1361. (PVOID) &pCertInfo->NotAfter,
  1362. sizeof(FILETIME)
  1363. );
  1364. }
  1365. /*if(pSecInfo->dwProtocol)
  1366. {
  1367. DWORD dwProtocolID;
  1368. TCHAR lpszProtocol[100];
  1369. ATTR_MAP ProtocolAttrMap[] =
  1370. {
  1371. {SP_PROT_SSL2_CLIENT, IDS_PROTOCOL_SSL2},
  1372. {SP_PROT_SSL3_CLIENT, IDS_PROTOCOL_SSL3},
  1373. {SP_PROT_PCT1_CLIENT, IDS_PROTOCOL_PCT1},
  1374. {SP_PROT_TLS1_CLIENT, IDS_PROTOCOL_TLS1}
  1375. };
  1376. for(j=0; j < sizeof(ProtocolAttrMap)/sizeof(ProtocolAttrMap[0]); j++)
  1377. {
  1378. if(ProtocolAttrMap[j].dwAttr == pSecInfo->dwProtocol)
  1379. {
  1380. dwProtocolID = ProtocolAttrMap[j].dwStringID;
  1381. break;
  1382. }
  1383. }
  1384. if(LoadString(GlobalDllHandle,
  1385. dwProtocolID,
  1386. lpszProtocol,
  1387. sizeof(lpszProtocol)/sizeof(lpszProtocol[0])))
  1388. {
  1389. pCertificate->lpszProtocolName = NewString(lpszProtocol);
  1390. }
  1391. } */
  1392. pCertificate->dwKeySize = pSecInfo->dwCipherStrength;
  1393. quit:
  1394. if ( error != ERROR_SUCCESS &&
  1395. fCanAlloc
  1396. )
  1397. {
  1398. if ( pCertificate->lpszSubjectInfo )
  1399. {
  1400. LocalFree(pCertificate->lpszSubjectInfo);
  1401. pCertificate->lpszSubjectInfo = NULL;
  1402. }
  1403. if ( pCertificate->lpszIssuerInfo )
  1404. {
  1405. LocalFree(pCertificate->lpszIssuerInfo);
  1406. pCertificate->lpszIssuerInfo = NULL;
  1407. }
  1408. }
  1409. return error;
  1410. }
  1411. #ifdef DONT_USE_IERT
  1412. /***
  1413. *char *StrTokEx(pstring, control) - tokenize string with delimiter in control
  1414. *
  1415. *Purpose:
  1416. * StrTokEx considers the string to consist of a sequence of zero or more
  1417. * text tokens separated by spans of one or more control chars. the first
  1418. * call, with string specified, returns a pointer to the first char of the
  1419. * first token, and will write a null char into pstring immediately
  1420. * following the returned token. when no tokens remain
  1421. * in pstring a NULL pointer is returned. remember the control chars with a
  1422. * bit map, one bit per ascii char. the null char is always a control char.
  1423. *
  1424. *Entry:
  1425. * char **pstring - ptr to ptr to string to tokenize
  1426. * char *control - string of characters to use as delimiters
  1427. *
  1428. *Exit:
  1429. * returns pointer to first token in string,
  1430. * returns NULL when no more tokens remain.
  1431. * pstring points to the beginning of the next token.
  1432. *
  1433. *WARNING!!!
  1434. * upon exit, the first delimiter in the input string will be replaced with '\0'
  1435. *
  1436. *******************************************************************************/
  1437. char * StrTokEx (char ** pstring, const char * control)
  1438. {
  1439. unsigned char *str;
  1440. const unsigned char *ctrl = (const unsigned char *)control;
  1441. unsigned char map[32];
  1442. int count;
  1443. char *tokenstr;
  1444. if(*pstring == NULL)
  1445. return NULL;
  1446. /* Clear control map */
  1447. for (count = 0; count < 32; count++)
  1448. map[count] = 0;
  1449. /* Set bits in delimiter table */
  1450. do
  1451. {
  1452. map[*ctrl >> 3] |= (1 << (*ctrl & 7));
  1453. } while (*ctrl++);
  1454. /* Initialize str. */
  1455. str = (unsigned char *)*pstring;
  1456. /* Find beginning of token (skip over leading delimiters). Note that
  1457. * there is no token if this loop sets str to point to the terminal
  1458. * null (*str == '\0') */
  1459. while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
  1460. str++;
  1461. tokenstr = (char *)str;
  1462. /* Find the end of the token. If it is not the end of the string,
  1463. * put a null there. */
  1464. for ( ; *str ; str++ )
  1465. {
  1466. if ( map[*str >> 3] & (1 << (*str & 7)) )
  1467. {
  1468. *str++ = '\0';
  1469. break;
  1470. }
  1471. }
  1472. /* string now points to beginning of next token */
  1473. *pstring = (char *)str;
  1474. /* Determine if a token has been found. */
  1475. if ( tokenstr == (char *)str )
  1476. return NULL;
  1477. else
  1478. return tokenstr;
  1479. }
  1480. /***
  1481. * double StrToDbl(const char *str, char **strStop) - convert string to double
  1482. *
  1483. * Purpose:
  1484. * To convert a string into a double. This function supports
  1485. * simple double representations like '1.234', '.5678'. It also support
  1486. * the a killobyte computaion by appending 'k' to the end of the string
  1487. * as in '1.5k' or '.5k'. The results would then become 1536 and 512.5.
  1488. *
  1489. * Return:
  1490. * The double representation of the string.
  1491. * strStop points to the character that caused the scan to stop.
  1492. *
  1493. *******************************************************************************/
  1494. double StrToDbl(const char *str, char **strStop)
  1495. {
  1496. double dbl = 0;
  1497. char *psz;
  1498. int iMult = 1;
  1499. int iKB = 1;
  1500. int iVal = 0;
  1501. BOOL bHaveDot = FALSE;
  1502. psz = (char*)str;
  1503. while(*psz)
  1504. {
  1505. if((*psz >= '0') && (*psz <= '9'))
  1506. {
  1507. iVal = (iVal * 10) + (*psz - '0');
  1508. if(bHaveDot)
  1509. iMult *= 10;
  1510. }
  1511. else if((*psz == '.') && !bHaveDot)
  1512. {
  1513. bHaveDot = TRUE;
  1514. }
  1515. else if((*psz == 'k') || (*psz == 'K'))
  1516. {
  1517. iKB = 1024;
  1518. psz++;
  1519. break;
  1520. }
  1521. else
  1522. {
  1523. break;
  1524. }
  1525. psz++;
  1526. }
  1527. *strStop = psz;
  1528. dbl = (double) (iVal * iKB) / iMult;
  1529. return(dbl);
  1530. }
  1531. #endif // DONT_USE_IERT
  1532. /*
  1533. * WideCharToAsciiString
  1534. *
  1535. * Purpose:
  1536. * Create an ascii string from a wide-char string.
  1537. * Output ascii string is allocated using New, so use delete[] to free.
  1538. *
  1539. */
  1540. DWORD
  1541. WideCharToAscii(PCWSTR pszW, char ** ppszA)
  1542. {
  1543. DWORD cchA;
  1544. DWORD cchW;
  1545. *ppszA = NULL;
  1546. if (!pszW)
  1547. return ERROR_SUCCESS;
  1548. cchW = lstrlenW(pszW);
  1549. // Determine how big the ascii string will be
  1550. cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, NULL, 0, NULL, NULL);
  1551. *ppszA = new char[cchA + 1];
  1552. if (!*ppszA)
  1553. return ERROR_NOT_ENOUGH_MEMORY;
  1554. // Determine how big the ascii string will be
  1555. cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, *ppszA, cchA, NULL, NULL);
  1556. (*ppszA)[cchA] = '\0';
  1557. return ERROR_SUCCESS;
  1558. }
  1559. DWORD
  1560. AsciiToWideChar_UsingGlobalAlloc(const char * pszA, LPWSTR * ppszW)
  1561. {
  1562. DWORD cchA;
  1563. DWORD cchW;
  1564. *ppszW = NULL;
  1565. if (!pszA)
  1566. return ERROR_SUCCESS;
  1567. cchA = lstrlenA(pszA);
  1568. // Determine how big the widechar string will be
  1569. cchW = MultiByteToWideChar(CP_ACP, 0, pszA, cchA, NULL, 0);
  1570. *ppszW = (PWSTR) GlobalAlloc(GPTR, (cchW + 1) * sizeof(WCHAR));
  1571. if (!*ppszW)
  1572. return ERROR_NOT_ENOUGH_MEMORY;
  1573. cchW = MultiByteToWideChar(CP_ACP, 0, pszA, cchA, *ppszW, cchW * sizeof(WCHAR));
  1574. (*ppszW)[cchW] = 0;
  1575. return ERROR_SUCCESS;
  1576. }