4 * Copyright 1999 Corel Corporation
13 #include <sys/types.h>
14 #ifdef HAVE_SYS_SOCKET_H
15 # include <sys/socket.h>
21 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(wininet
);
29 #define MAX_IDLE_WORKER 1000*60*1
30 #define MAX_WORKER_THREADS 10
32 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
33 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
38 CHAR response
[MAX_REPLY_LEN
];
39 } WITHREADERROR
, *LPWITHREADERROR
;
41 INTERNET_SCHEME
GetInternetScheme(LPSTR lpszScheme
);
42 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
);
43 VOID
INTERNET_ExecuteWork();
45 DWORD g_dwTlsErrIndex
= TLS_OUT_OF_INDEXES
;
47 DWORD dwNumIdleThreads
;
48 HANDLE hEventArray
[2];
49 #define hQuitEvent hEventArray[0]
50 #define hWorkEvent hEventArray[1]
51 CRITICAL_SECTION csQueue
;
52 LPWORKREQUEST lpHeadWorkQueue
;
53 LPWORKREQUEST lpWorkQueueTail
;
55 /***********************************************************************
56 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
59 * hinstDLL [I] handle to the 'dlls' instance
61 * lpvReserved [I] reserverd, must be NULL
69 WININET_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
71 TRACE("%x,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
74 case DLL_PROCESS_ATTACH
:
76 g_dwTlsErrIndex
= TlsAlloc();
78 if (g_dwTlsErrIndex
== TLS_OUT_OF_INDEXES
)
81 hQuitEvent
= CreateEventA(0, TRUE
, FALSE
, NULL
);
82 hWorkEvent
= CreateEventA(0, FALSE
, FALSE
, NULL
);
83 InitializeCriticalSection(&csQueue
);
88 case DLL_THREAD_ATTACH
:
90 LPWITHREADERROR lpwite
= HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR
));
94 TlsSetValue(g_dwTlsErrIndex
, (LPVOID
)lpwite
);
98 case DLL_THREAD_DETACH
:
99 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
100 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
103 case DLL_PROCESS_DETACH
:
105 if (g_dwTlsErrIndex
!= TLS_OUT_OF_INDEXES
)
107 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex
));
108 TlsFree(g_dwTlsErrIndex
);
111 SetEvent(hQuitEvent
);
113 CloseHandle(hQuitEvent
);
114 CloseHandle(hWorkEvent
);
116 DeleteCriticalSection(&csQueue
);
124 /***********************************************************************
125 * InternetOpenA (WININET.113)
127 * Per-application initialization of wininet
130 * HINTERNET on success
134 INTERNETAPI HINTERNET WINAPI
InternetOpenA(LPCSTR lpszAgent
,
135 DWORD dwAccessType
, LPCSTR lpszProxy
,
136 LPCSTR lpszProxyBypass
, DWORD dwFlags
)
138 LPWININETAPPINFOA lpwai
= NULL
;
142 /* Clear any error information */
143 INTERNET_SetLastError(0);
145 lpwai
= HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA
));
147 INTERNET_SetLastError(ERROR_OUTOFMEMORY
);
150 memset(lpwai
, 0, sizeof(WININETAPPINFOA
));
151 lpwai
->hdr
.htype
= WH_HINIT
;
152 lpwai
->hdr
.lpwhparent
= NULL
;
153 lpwai
->hdr
.dwFlags
= dwFlags
;
154 if (NULL
!= lpszAgent
)
155 lpwai
->lpszAgent
= strdup(lpszAgent
);
156 if (NULL
!= lpszProxy
)
157 lpwai
->lpszProxy
= strdup(lpszProxy
);
158 if (NULL
!= lpszProxyBypass
)
159 lpwai
->lpszProxyBypass
= strdup(lpszProxyBypass
);
160 lpwai
->dwAccessType
= dwAccessType
;
163 return (HINTERNET
)lpwai
;
167 /***********************************************************************
168 * InternetGetLastResponseInfoA (WININET.108)
170 * Return last wininet error description on the calling thread
173 * TRUE on success of writting to buffer
177 BOOL WINAPI
InternetGetLastResponseInfoA(LPDWORD lpdwError
,
178 LPSTR lpszBuffer
, LPDWORD lpdwBufferLength
)
180 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
184 *lpdwError
= lpwite
->dwError
;
187 strncpy(lpszBuffer
, lpwite
->response
, *lpdwBufferLength
);
188 *lpdwBufferLength
= strlen(lpszBuffer
);
191 *lpdwBufferLength
= 0;
197 /***********************************************************************
198 * InternetGetConnectedState (WININET.103)
200 * Return connected state
204 * if lpdwStatus is not null, return the status (off line,
205 * modem, lan...) in it.
206 * FALSE if not connected
208 BOOL WINAPI
InternetGetConnectedState(LPDWORD lpdwStatus
, DWORD dwReserved
)
215 /***********************************************************************
216 * InternetConnectA (WININET.93)
218 * Open a ftp, gopher or http session
221 * HINTERNET a session handle on success
225 INTERNETAPI HINTERNET WINAPI
InternetConnectA(HINTERNET hInternet
,
226 LPCSTR lpszServerName
, INTERNET_PORT nServerPort
,
227 LPCSTR lpszUserName
, LPCSTR lpszPassword
,
228 DWORD dwService
, DWORD dwFlags
, DWORD dwContext
)
230 HINTERNET rc
= (HINTERNET
) NULL
;
234 /* Clear any error information */
235 INTERNET_SetLastError(0);
239 case INTERNET_SERVICE_FTP
:
240 rc
= FTP_Connect(hInternet
, lpszServerName
, nServerPort
,
241 lpszUserName
, lpszPassword
, dwFlags
, dwContext
);
244 case INTERNET_SERVICE_HTTP
:
247 case INTERNET_SERVICE_GOPHER
:
255 /***********************************************************************
256 * InternetFindNextFileA (WININET.102)
258 * Continues a file search from a previous call to FindFirstFile
265 BOOL WINAPI
InternetFindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
267 LPWININETAPPINFOA hIC
= NULL
;
268 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
272 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
274 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
278 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
279 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
)
281 WORKREQUEST workRequest
;
283 workRequest
.asyncall
= INTERNETFINDNEXTA
;
284 workRequest
.HFTPSESSION
= (DWORD
)hFind
;
285 workRequest
.LPFINDFILEDATA
= (DWORD
)lpvFindData
;
287 return INTERNET_AsyncCall(&workRequest
);
291 return INTERNET_FindNextFileA(hFind
, lpvFindData
);
295 /***********************************************************************
296 * INTERNET_FindNextFileA (Internal)
298 * Continues a file search from a previous call to FindFirstFile
305 BOOL WINAPI
INTERNET_FindNextFileA(HINTERNET hFind
, LPVOID lpvFindData
)
307 BOOL bSuccess
= TRUE
;
308 LPWININETAPPINFOA hIC
= NULL
;
309 LPWIN32_FIND_DATAA lpFindFileData
;
310 LPWININETFINDNEXTA lpwh
= (LPWININETFINDNEXTA
) hFind
;
314 if (NULL
== lpwh
|| lpwh
->hdr
.htype
!= WH_HFINDNEXT
)
316 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
320 /* Clear any error information */
321 INTERNET_SetLastError(0);
323 if (lpwh
->hdr
.lpwhparent
->htype
!= WH_HFTPSESSION
)
325 FIXME("Only FTP find next supported\n");
326 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE
);
330 TRACE("index(%d) size(%ld)\n", lpwh
->index
, lpwh
->size
);
332 lpFindFileData
= (LPWIN32_FIND_DATAA
) lpvFindData
;
333 ZeroMemory(lpFindFileData
, sizeof(WIN32_FIND_DATAA
));
335 if (lpwh
->index
>= lpwh
->size
)
337 INTERNET_SetLastError(ERROR_NO_MORE_FILES
);
342 FTP_ConvertFileProp(&lpwh
->lpafp
[lpwh
->index
], lpFindFileData
);
345 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData
->cFileName
, lpFindFileData
->nFileSizeLow
);
349 hIC
= GET_HWININET_FROM_LPWININETFINDNEXT(lpwh
);
350 if (hIC
->hdr
.dwFlags
& INTERNET_FLAG_ASYNC
&& hIC
->lpfnStatusCB
)
352 INTERNET_ASYNC_RESULT iar
;
354 iar
.dwResult
= (DWORD
)bSuccess
;
355 iar
.dwError
= bSuccess
? ERROR_SUCCESS
: INTERNET_GetLastError();
357 hIC
->lpfnStatusCB(hFind
, lpwh
->hdr
.dwContext
, INTERNET_STATUS_REQUEST_COMPLETE
,
358 &iar
, sizeof(INTERNET_ASYNC_RESULT
));
365 /***********************************************************************
366 * InternetCloseHandle (WININET.89)
368 * Continues a file search from a previous call to FindFirstFile
375 BOOL WINAPI
InternetCloseHandle(HINTERNET hInternet
)
378 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hInternet
;
384 /* Clear any error information */
385 INTERNET_SetLastError(0);
390 case WH_HHTTPSESSION
:
394 retval
= FTP_CloseSessionHandle((LPWININETFTPSESSIONA
) lpwh
);
398 retval
= FTP_CloseFindNextHandle((LPWININETFINDNEXTA
) lpwh
);
409 /***********************************************************************
410 * InternetCrackUrlA (WININET.95)
412 * Break up URL into its components
419 BOOL WINAPI
InternetCrackUrlA(LPCSTR lpszUrl
, DWORD dwUrlLength
, DWORD dwFlags
,
420 LPURL_COMPONENTSA lpUrlComponents
)
424 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
427 char* szScheme
= NULL
;
431 char* szUrlPath
= NULL
;
432 char* szParam
= NULL
;
433 char* szNetLoc
= NULL
;
441 /* Find out if the URI is absolute... */
442 BOOL bIsAbsolute
= FALSE
;
444 char* ap
= (char*)lpszUrl
;
448 while( (cAlphanum
= *ap
) != '\0' )
450 if( ((cAlphanum
>= 'a') && (cAlphanum
<= 'z')) ||
451 ((cAlphanum
>= 'A') && (cAlphanum
<= 'Z')) ||
452 ((cAlphanum
>= '0') && (cAlphanum
<= '9')) )
457 if( (cAlphanum
== ':') && (ap
- lpszUrl
>= 2) )
467 FIXME!!!! This should work on relative urls too!*/
470 /* Get scheme first... */
471 nSchemeLen
= cp
- lpszUrl
;
472 szScheme
= strdup( lpszUrl
);
473 szScheme
[ nSchemeLen
] = '\0';
475 /* Eat ':' in protocol... */
478 /* Parse <params>... */
479 szParam
= strpbrk( lpszUrl
, ";" );
480 if( szParam
!= NULL
)
483 /* Eat ';' in Params... */
485 sParam
= strdup( szParam
);
489 /* Skip over slashes...*/
501 /* Parse the <net-loc>...*/
502 if( GetInternetScheme( szScheme
) == INTERNET_SCHEME_FILE
)
504 szUrlPath
= strdup( cp
);
505 nUrlLen
= strlen( szUrlPath
);
506 if( nUrlLen
>= 2 && szUrlPath
[ 1 ] == '|' )
507 szUrlPath
[ 1 ] = ':';
512 szUrlPath
= strpbrk(cp
, "/");
513 if( szUrlPath
!= NULL
)
514 nUrlLen
= strlen( szUrlPath
);
516 /* Find the end of our net-loc... */
517 nNetLocLen
= strcspn( cp
, "/" );
518 szNetLoc
= strdup( cp
);
519 szNetLoc
[ nNetLocLen
] = '\0';
520 if( szNetLoc
!= NULL
)
524 /* [<user>[<:password>]@]<host>[:<port>] */
525 /* First find the user and password if they exist...*/
527 szHost
= strchr( szNetLoc
, '@' );
530 /* username and password not specified... */
532 nHostLen
= nNetLocLen
;
536 int nUserPassLen
= nNetLocLen
- nHostLen
- 1;
537 char* szUserPass
= strdup( szNetLoc
);
538 /* Get username and/or password... */
539 /* Eat '@' in domain... */
541 nHostLen
= strlen( szHost
);
543 szUserPass
[ nUserPassLen
] = '\0';
544 if( szUserPass
!= NULL
)
546 szPass
= strpbrk( szUserPass
, ":" );
549 /* Eat ':' in UserPass... */
551 nPassLen
= strlen( szPass
);
552 nUserLen
= nUserPassLen
- nPassLen
- 1;
553 szUser
= strdup( szUserPass
);
554 szUser
[ nUserLen
] = '\0';
558 /* password not specified... */
559 szUser
= strdup( szUserPass
);
560 nUserLen
= strlen( szUser
);
565 /* <host><:port>...*/
566 /* Then get the port if it exists... */
567 lpszPort
= strpbrk( szHost
, ":" );
569 if( lpszPort
!= NULL
)
571 char* szPort
= lpszPort
+ 1;
574 nPortLen
= strlen( szPort
);
575 nPort
= atoi( szPort
);
578 nHostLen
= strlen(szHost
);
583 /* Relative URI... */
591 /***********************************************************************
592 * InternetAttemptConnect (WININET.81)
594 * Attempt to make a connection to the internet
597 * ERROR_SUCCESS on success
598 * Error value on failure
601 INTERNETAPI DWORD WINAPI
InternetAttemptConnect(DWORD dwReserved
)
604 return ERROR_SUCCESS
;
608 /***********************************************************************
609 * InternetCanonicalizeUrlA (WININET.85)
611 * Escape unsafe characters and spaces
618 BOOL WINAPI
InternetCanonicalizeUrlA(LPCSTR lpszUrl
, LPSTR lpszBuffer
,
619 LPDWORD lpdwBufferLength
, DWORD dwFlags
)
621 BOOL bSuccess
= FALSE
;
627 strncpy(lpszBuffer
, lpszUrl
, *lpdwBufferLength
);
628 *lpdwBufferLength
= strlen(lpszBuffer
);
636 /***********************************************************************
637 * InternetSetStatusCallback (WININET.133)
639 * Sets up a callback function which is called as progress is made
640 * during an operation.
643 * Previous callback or NULL on success
644 * INTERNET_INVALID_STATUS_CALLBACK on failure
647 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI
InternetSetStatusCallback(
648 HINTERNET hInternet
,INTERNET_STATUS_CALLBACK lpfnIntCB
)
650 INTERNET_STATUS_CALLBACK retVal
;
651 LPWININETAPPINFOA lpwai
= (LPWININETAPPINFOA
)hInternet
;
653 TRACE("0x%08lx\n", (ULONG
)hInternet
);
654 if (lpwai
->hdr
.htype
!= WH_HINIT
)
655 return INTERNET_INVALID_STATUS_CALLBACK
;
657 retVal
= lpwai
->lpfnStatusCB
;
658 lpwai
->lpfnStatusCB
= lpfnIntCB
;
664 /***********************************************************************
665 * InternetWriteFile (WININET.138)
667 * Write data to an open internet file
674 BOOL WINAPI
InternetWriteFile(HINTERNET hFile
, LPCVOID lpBuffer
,
675 DWORD dwNumOfBytesToWrite
, LPDWORD lpdwNumOfBytesWritten
)
678 int nSocket
= INVALID_SOCKET
;
679 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
688 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
692 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
699 if (INVALID_SOCKET
!= nSocket
)
701 *lpdwNumOfBytesWritten
= INTERNET_WriteDataToStream(nSocket
, lpBuffer
, dwNumOfBytesToWrite
);
702 if (*lpdwNumOfBytesWritten
< 0)
703 *lpdwNumOfBytesWritten
= 0;
712 /***********************************************************************
713 * InternetReadFile (WININET.121)
715 * Read data from an open internet file
722 BOOL WINAPI
InternetReadFile(HINTERNET hFile
, LPVOID lpBuffer
,
723 DWORD dwNumOfBytesToRead
, LPDWORD dwNumOfBytesRead
)
726 int nSocket
= INVALID_SOCKET
;
727 LPWININETHANDLEHEADER lpwh
= (LPWININETHANDLEHEADER
) hFile
;
736 nSocket
= ((LPWININETHTTPREQA
)hFile
)->nSocketFD
;
740 nSocket
= ((LPWININETFILE
)hFile
)->nDataSocket
;
747 if (INVALID_SOCKET
!= nSocket
)
749 *dwNumOfBytesRead
= INTERNET_ReadDataFromStream(nSocket
, lpBuffer
, dwNumOfBytesToRead
);
750 if (*dwNumOfBytesRead
< 0)
751 *dwNumOfBytesRead
= 0;
760 /***********************************************************************
761 * GetInternetScheme (internal)
767 * INTERNET_SCHEME_UNKNOWN on failure
770 INTERNET_SCHEME
GetInternetScheme(LPSTR lpszScheme
)
773 return INTERNET_SCHEME_UNKNOWN
;
775 if( (strcmp("ftp", lpszScheme
) == 0) ||
776 (strcmp("FTP", lpszScheme
) == 0) )
777 return INTERNET_SCHEME_FTP
;
778 else if( (strcmp("gopher", lpszScheme
) == 0) ||
779 (strcmp("GOPHER", lpszScheme
) == 0) )
780 return INTERNET_SCHEME_GOPHER
;
781 else if( (strcmp("http", lpszScheme
) == 0) ||
782 (strcmp("HTTP", lpszScheme
) == 0) )
783 return INTERNET_SCHEME_HTTP
;
784 else if( (strcmp("https", lpszScheme
) == 0) ||
785 (strcmp("HTTPS", lpszScheme
) == 0) )
786 return INTERNET_SCHEME_HTTPS
;
787 else if( (strcmp("file", lpszScheme
) == 0) ||
788 (strcmp("FILE", lpszScheme
) == 0) )
789 return INTERNET_SCHEME_FILE
;
790 else if( (strcmp("news", lpszScheme
) == 0) ||
791 (strcmp("NEWS", lpszScheme
) == 0) )
792 return INTERNET_SCHEME_NEWS
;
793 else if( (strcmp("mailto", lpszScheme
) == 0) ||
794 (strcmp("MAILTO", lpszScheme
) == 0) )
795 return INTERNET_SCHEME_MAILTO
;
797 return INTERNET_SCHEME_UNKNOWN
;
801 /***********************************************************************
802 * INTERNET_WriteDataToStream (internal)
804 * Send data to server
808 * number of characters sent on success
811 int INTERNET_WriteDataToStream(int nDataSocket
, LPCVOID Buffer
, DWORD BytesToWrite
)
813 if (INVALID_SOCKET
== nDataSocket
)
816 return send(nDataSocket
, Buffer
, BytesToWrite
, 0);
820 /***********************************************************************
821 * INTERNET_ReadDataFromStream (internal)
823 * Read data from http server
827 * number of characters sent on success
830 int INTERNET_ReadDataFromStream(int nDataSocket
, LPVOID Buffer
, DWORD BytesToRead
)
832 if (INVALID_SOCKET
== nDataSocket
)
835 return recv(nDataSocket
, Buffer
, BytesToRead
, 0);
839 /***********************************************************************
840 * INTERNET_SetLastError (internal)
842 * Set last thread specific error
847 void INTERNET_SetLastError(DWORD dwError
)
849 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
851 SetLastError(dwError
);
852 lpwite
->dwError
= dwError
;
856 /***********************************************************************
857 * INTERNET_GetLastError (internal)
859 * Get last thread specific error
864 DWORD
INTERNET_GetLastError()
866 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
867 return lpwite
->dwError
;
871 /***********************************************************************
872 * INTERNET_WorkerThreadFunc (internal)
874 * Worker thread execution function
879 DWORD
INTERNET_WorkerThreadFunc(LPVOID
*lpvParam
)
885 dwWaitRes
= WaitForMultipleObjects(2, hEventArray
, FALSE
, MAX_IDLE_WORKER
);
887 if (dwWaitRes
== WAIT_OBJECT_0
+ 1)
888 INTERNET_ExecuteWork();
892 InterlockedIncrement(&dwNumIdleThreads
);
895 InterlockedDecrement(&dwNumIdleThreads
);
896 InterlockedDecrement(&dwNumThreads
);
897 TRACE("Worker thread exiting\n");
902 /***********************************************************************
903 * INTERNET_InsertWorkRequest (internal)
905 * Insert work request into queue
910 BOOL
INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest
)
912 BOOL bSuccess
= FALSE
;
913 LPWORKREQUEST lpNewRequest
;
917 lpNewRequest
= HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST
));
920 memcpy(lpNewRequest
, lpWorkRequest
, sizeof(WORKREQUEST
));
921 lpNewRequest
->prev
= NULL
;
923 EnterCriticalSection(&csQueue
);
925 lpNewRequest
->next
= lpWorkQueueTail
;
927 lpWorkQueueTail
->prev
= lpNewRequest
;
928 lpWorkQueueTail
= lpNewRequest
;
929 if (!lpHeadWorkQueue
)
930 lpHeadWorkQueue
= lpWorkQueueTail
;
932 LeaveCriticalSection(&csQueue
);
941 /***********************************************************************
942 * INTERNET_GetWorkRequest (internal)
944 * Retrieves work request from queue
949 BOOL
INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest
)
951 BOOL bSuccess
= FALSE
;
952 LPWORKREQUEST lpRequest
= NULL
;
956 EnterCriticalSection(&csQueue
);
960 lpRequest
= lpHeadWorkQueue
;
961 lpHeadWorkQueue
= lpHeadWorkQueue
->prev
;
962 if (lpRequest
== lpWorkQueueTail
)
963 lpWorkQueueTail
= lpHeadWorkQueue
;
966 LeaveCriticalSection(&csQueue
);
970 memcpy(lpWorkRequest
, lpRequest
, sizeof(WORKREQUEST
));
971 HeapFree(GetProcessHeap(), 0, lpRequest
);
979 /***********************************************************************
980 * INTERNET_AsyncCall (internal)
982 * Retrieves work request from queue
987 BOOL
INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest
)
991 BOOL bSuccess
= FALSE
;
995 if (InterlockedDecrement(&dwNumIdleThreads
) < 0)
997 InterlockedIncrement(&dwNumIdleThreads
);
999 if (InterlockedIncrement(&dwNumThreads
) > MAX_WORKER_THREADS
||
1000 !(hThread
= CreateThread(NULL
, 0,
1001 (LPTHREAD_START_ROUTINE
)INTERNET_WorkerThreadFunc
, NULL
, 0, &dwTID
)))
1003 InterlockedDecrement(&dwNumThreads
);
1004 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED
);
1008 TRACE("Created new thread\n");
1012 INTERNET_InsertWorkRequest(lpWorkRequest
);
1013 SetEvent(hWorkEvent
);
1021 /***********************************************************************
1022 * INTERNET_ExecuteWork (internal)
1027 VOID
INTERNET_ExecuteWork()
1029 WORKREQUEST workRequest
;
1033 if (INTERNET_GetWorkRequest(&workRequest
))
1035 switch (workRequest
.asyncall
)
1038 FTP_FtpPutFileA((HINTERNET
)workRequest
.HFTPSESSION
, (LPCSTR
)workRequest
.LPSZLOCALFILE
,
1039 (LPCSTR
)workRequest
.LPSZNEWREMOTEFILE
, workRequest
.DWFLAGS
, workRequest
.DWCONTEXT
);
1040 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZLOCALFILE
);
1041 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWREMOTEFILE
);
1044 case FTPSETCURRENTDIRECTORYA
:
1045 FTP_FtpSetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1046 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1047 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1050 case FTPCREATEDIRECTORYA
:
1051 FTP_FtpCreateDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1052 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1053 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1056 case FTPFINDFIRSTFILEA
:
1057 FTP_FtpFindFirstFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1058 (LPCSTR
)workRequest
.LPSZSEARCHFILE
,
1059 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
, workRequest
.DWFLAGS
,
1060 workRequest
.DWCONTEXT
);
1061 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSEARCHFILE
);
1064 case FTPGETCURRENTDIRECTORYA
:
1065 FTP_FtpGetCurrentDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1066 (LPSTR
)workRequest
.LPSZDIRECTORY
, (LPDWORD
)workRequest
.LPDWDIRECTORY
);
1070 FTP_FtpOpenFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1071 (LPCSTR
)workRequest
.LPSZFILENAME
,
1072 workRequest
.FDWACCESS
,
1073 workRequest
.DWFLAGS
,
1074 workRequest
.DWCONTEXT
);
1075 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1079 FTP_FtpGetFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1080 (LPCSTR
)workRequest
.LPSZREMOTEFILE
,
1081 (LPCSTR
)workRequest
.LPSZNEWFILE
,
1082 (BOOL
)workRequest
.FFAILIFEXISTS
,
1083 workRequest
.DWLOCALFLAGSATTRIBUTE
,
1084 workRequest
.DWFLAGS
,
1085 workRequest
.DWCONTEXT
);
1086 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZREMOTEFILE
);
1087 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZNEWFILE
);
1090 case FTPDELETEFILEA
:
1091 FTP_FtpDeleteFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1092 (LPCSTR
)workRequest
.LPSZFILENAME
);
1093 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZFILENAME
);
1096 case FTPREMOVEDIRECTORYA
:
1097 FTP_FtpRemoveDirectoryA((HINTERNET
)workRequest
.HFTPSESSION
,
1098 (LPCSTR
)workRequest
.LPSZDIRECTORY
);
1099 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDIRECTORY
);
1102 case FTPRENAMEFILEA
:
1103 FTP_FtpRenameFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1104 (LPCSTR
)workRequest
.LPSZSRCFILE
,
1105 (LPCSTR
)workRequest
.LPSZDESTFILE
);
1106 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZSRCFILE
);
1107 HeapFree(GetProcessHeap(), 0, (LPVOID
)workRequest
.LPSZDESTFILE
);
1110 case INTERNETFINDNEXTA
:
1111 INTERNET_FindNextFileA((HINTERNET
)workRequest
.HFTPSESSION
,
1112 (LPWIN32_FIND_DATAA
)workRequest
.LPFINDFILEDATA
);
1119 /***********************************************************************
1120 * INTERNET_GetResponseBuffer
1125 LPSTR
INTERNET_GetResponseBuffer()
1127 LPWITHREADERROR lpwite
= (LPWITHREADERROR
)TlsGetValue(g_dwTlsErrIndex
);
1128 return lpwite
->response
;