4 * Copyright 1999 Corel Corporation
11 #include <sys/types.h>
12 #include <sys/socket.h>
17 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(wininet);
25 #define MAX_IDLE_WORKER 1000*60*1
26 #define MAX_WORKER_THREADS 10
28 #define GET_HWININET_FROM_LPWININETFINDNEXT(lpwh) \
29 (LPWININETAPPINFOA)(((LPWININETFTPSESSIONA)(lpwh->hdr.lpwhparent))->hdr.lpwhparent)
34 CHAR response[MAX_REPLY_LEN];
35 } WITHREADERROR, *LPWITHREADERROR;
37 INTERNET_SCHEME GetInternetScheme(LPSTR lpszScheme);
38 BOOLAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData);
39 VOID INTERNET_ExecuteWork();
41 DWORD g_dwTlsErrIndex = TLS_OUT_OF_INDEXES;
43 DWORD dwNumIdleThreads;
44 HANDLE hEventArray[2];
45 #define hQuitEvent hEventArray[0]
46 #define hWorkEvent hEventArray[1]
47 CRITICAL_SECTION csQueue;
48 LPWORKREQUEST lpHeadWorkQueue;
49 LPWORKREQUEST lpWorkQueueTail;
51 /***********************************************************************
52 * WININET_LibMain [Internal] Initializes the internal 'WININET.DLL'.
55 * hinstDLL [I] handle to the 'dlls' instance
57 * lpvReserved [I] reserverd, must be NULL
65 WININET_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
67 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
70 case DLL_PROCESS_ATTACH:
72 g_dwTlsErrIndex = TlsAlloc();
74 if (g_dwTlsErrIndex == TLS_OUT_OF_INDEXES)
77 hQuitEvent = CreateEventA(0, TRUE, FALSE, NULL);
78 hWorkEvent = CreateEventA(0, FALSE, FALSE, NULL);
79 InitializeCriticalSection(&csQueue);
84 case DLL_THREAD_ATTACH:
86 LPWITHREADERROR lpwite = HeapAlloc(GetProcessHeap(), 0, sizeof(WITHREADERROR));
90 TlsSetValue(g_dwTlsErrIndex, (LPVOID)lpwite);
94 case DLL_THREAD_DETACH:
95 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
96 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
99 case DLL_PROCESS_DETACH:
101 if (g_dwTlsErrIndex != TLS_OUT_OF_INDEXES)
103 HeapFree(GetProcessHeap(), 0, TlsGetValue(g_dwTlsErrIndex));
104 TlsFree(g_dwTlsErrIndex);
107 SetEvent(hQuitEvent);
109 CloseHandle(hQuitEvent);
110 CloseHandle(hWorkEvent);
112 DeleteCriticalSection(&csQueue);
120 /***********************************************************************
121 * InternetOpenA (WININET.113)
123 * Per-application initialization of wininet
126 * HINTERNET on success
130 INTERNETAPI HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent,
131 DWORD dwAccessType, LPCSTR lpszProxy,
132 LPCSTR lpszProxyBypass, DWORD dwFlags)
134 LPWININETAPPINFOA lpwai = NULL;
138 /* Clear any error information */
139 INTERNET_SetLastError(0);
141 lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
143 INTERNET_SetLastError(ERROR_OUTOFMEMORY);
146 memset(lpwai, 0, sizeof(WININETAPPINFOA));
147 lpwai->hdr.htype = WH_HINIT;
148 lpwai->hdr.lpwhparent = NULL;
149 lpwai->hdr.dwFlags = dwFlags;
150 if (NULL != lpszAgent)
151 lpwai->lpszAgent = strdup(lpszAgent);
152 if (NULL != lpszProxy)
153 lpwai->lpszProxy = strdup(lpszProxy);
154 if (NULL != lpszProxyBypass)
155 lpwai->lpszProxyBypass = strdup(lpszProxyBypass);
156 lpwai->dwAccessType = dwAccessType;
159 return (HINTERNET)lpwai;
163 /***********************************************************************
164 * InternetGetLastResponseInfoA (WININET.108)
166 * Return last wininet error description on the calling thread
169 * TRUE on success of writting to buffer
173 BOOLAPI InternetGetLastResponseInfoA(LPDWORD lpdwError,
174 LPSTR lpszBuffer, LPDWORD lpdwBufferLength)
176 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
180 *lpdwError = lpwite->dwError;
183 strncpy(lpszBuffer, lpwite->response, *lpdwBufferLength);
184 *lpdwBufferLength = strlen(lpszBuffer);
187 *lpdwBufferLength = 0;
193 /***********************************************************************
194 * InternetConnectA (WININET.93)
196 * Open a ftp, gopher or http session
199 * HINTERNET a session handle on success
203 INTERNETAPI HINTERNET WINAPI InternetConnectA(HINTERNET hInternet,
204 LPCSTR lpszServerName, INTERNET_PORT nServerPort,
205 LPCSTR lpszUserName, LPCSTR lpszPassword,
206 DWORD dwService, DWORD dwFlags, DWORD dwContext)
208 HINTERNET rc = (HINTERNET) NULL;
212 /* Clear any error information */
213 INTERNET_SetLastError(0);
217 case INTERNET_SERVICE_FTP:
218 rc = FTP_Connect(hInternet, lpszServerName, nServerPort,
219 lpszUserName, lpszPassword, dwFlags, dwContext);
222 case INTERNET_SERVICE_HTTP:
225 case INTERNET_SERVICE_GOPHER:
233 /***********************************************************************
234 * InternetFindNextFileA (WININET.102)
236 * Continues a file search from a previous call to FindFirstFile
243 BOOLAPI InternetFindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
245 LPWININETAPPINFOA hIC = NULL;
246 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
250 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
252 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
256 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
257 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
259 WORKREQUEST workRequest;
261 workRequest.asyncall = INTERNETFINDNEXTA;
262 workRequest.HFTPSESSION = (DWORD)hFind;
263 workRequest.LPFINDFILEDATA = (DWORD)lpvFindData;
265 return INTERNET_AsyncCall(&workRequest);
269 return INTERNET_FindNextFileA(hFind, lpvFindData);
273 /***********************************************************************
274 * INTERNET_FindNextFileA (Internal)
276 * Continues a file search from a previous call to FindFirstFile
283 BOOLAPI INTERNET_FindNextFileA(HINTERNET hFind, LPVOID lpvFindData)
285 BOOL bSuccess = TRUE;
286 LPWININETAPPINFOA hIC = NULL;
287 LPWIN32_FIND_DATAA lpFindFileData;
288 LPWININETFINDNEXTA lpwh = (LPWININETFINDNEXTA) hFind;
292 if (NULL == lpwh || lpwh->hdr.htype != WH_HFINDNEXT)
294 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
298 /* Clear any error information */
299 INTERNET_SetLastError(0);
301 if (lpwh->hdr.lpwhparent->htype != WH_HFTPSESSION)
303 FIXME("Only FTP find next supported\n");
304 INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
308 TRACE("index(%d) size(%ld)\n", lpwh->index, lpwh->size);
310 lpFindFileData = (LPWIN32_FIND_DATAA) lpvFindData;
311 ZeroMemory(lpFindFileData, sizeof(WIN32_FIND_DATAA));
313 if (lpwh->index >= lpwh->size)
315 INTERNET_SetLastError(ERROR_NO_MORE_FILES);
320 FTP_ConvertFileProp(&lpwh->lpafp[lpwh->index], lpFindFileData);
323 TRACE("\nName: %s\nSize: %ld\n", lpFindFileData->cFileName, lpFindFileData->nFileSizeLow);
327 hIC = GET_HWININET_FROM_LPWININETFINDNEXT(lpwh);
328 if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC && hIC->lpfnStatusCB)
330 INTERNET_ASYNC_RESULT iar;
332 iar.dwResult = (DWORD)bSuccess;
333 iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
335 hIC->lpfnStatusCB(hFind, lpwh->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
336 &iar, sizeof(INTERNET_ASYNC_RESULT));
343 /***********************************************************************
344 * InternetCloseHandle (WININET.89)
346 * Continues a file search from a previous call to FindFirstFile
353 BOOLAPI InternetCloseHandle(HINTERNET hInternet)
356 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hInternet;
362 /* Clear any error information */
363 INTERNET_SetLastError(0);
368 case WH_HHTTPSESSION:
372 retval = FTP_CloseSessionHandle((LPWININETFTPSESSIONA) lpwh);
376 retval = FTP_CloseFindNextHandle((LPWININETFINDNEXTA) lpwh);
387 /***********************************************************************
388 * InternetCrackUrlA (WININET.95)
390 * Break up URL into its components
397 BOOLAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags,
398 LPURL_COMPONENTSA lpUrlComponents)
402 * <protocol>:[//<net_loc>][/path][;<params>][?<query>][#<fragment>]
405 char* szScheme = NULL;
409 char* szUrlPath = NULL;
410 char* szParam = NULL;
411 char* szNetLoc = NULL;
419 /* Find out if the URI is absolute... */
420 BOOL bIsAbsolute = FALSE;
422 char* ap = (char*)lpszUrl;
426 while( (cAlphanum = *ap) != '\0' )
428 if( ((cAlphanum >= 'a') && (cAlphanum <= 'z')) ||
429 ((cAlphanum >= 'A') && (cAlphanum <= 'Z')) ||
430 ((cAlphanum >= '0') && (cAlphanum <= '9')) )
435 if( (cAlphanum == ':') && (ap - lpszUrl >= 2) )
445 FIXME!!!! This should work on relative urls too!*/
448 /* Get scheme first... */
449 nSchemeLen = cp - lpszUrl;
450 szScheme = strdup( lpszUrl );
451 szScheme[ nSchemeLen ] = '\0';
453 /* Eat ':' in protocol... */
456 /* Parse <params>... */
457 szParam = strpbrk( lpszUrl, ";" );
458 if( szParam != NULL )
461 /* Eat ';' in Params... */
463 sParam = strdup( szParam );
467 /* Skip over slashes...*/
479 /* Parse the <net-loc>...*/
480 if( GetInternetScheme( szScheme ) == INTERNET_SCHEME_FILE )
482 szUrlPath = strdup( cp );
483 nUrlLen = strlen( szUrlPath );
484 if( nUrlLen >= 2 && szUrlPath[ 1 ] == '|' )
485 szUrlPath[ 1 ] = ':';
490 szUrlPath = strpbrk(cp, "/");
491 if( szUrlPath != NULL )
492 nUrlLen = strlen( szUrlPath );
494 /* Find the end of our net-loc... */
495 nNetLocLen = strcspn( cp, "/" );
496 szNetLoc = strdup( cp );
497 szNetLoc[ nNetLocLen ] = '\0';
498 if( szNetLoc != NULL )
502 /* [<user>[<:password>]@]<host>[:<port>] */
503 /* First find the user and password if they exist...*/
505 szHost = strchr( szNetLoc, '@' );
508 /* username and password not specified... */
510 nHostLen = nNetLocLen;
514 int nUserPassLen = nNetLocLen - nHostLen - 1;
515 char* szUserPass = strdup( szNetLoc );
516 /* Get username and/or password... */
517 /* Eat '@' in domain... */
519 nHostLen = strlen( szHost );
521 szUserPass[ nUserPassLen ] = '\0';
522 if( szUserPass != NULL )
524 szPass = strpbrk( szUserPass, ":" );
527 /* Eat ':' in UserPass... */
529 nPassLen = strlen( szPass );
530 nUserLen = nUserPassLen - nPassLen - 1;
531 szUser = strdup( szUserPass );
532 szUser[ nUserLen ] = '\0';
536 /* password not specified... */
537 szUser = strdup( szUserPass );
538 nUserLen = strlen( szUser );
543 /* <host><:port>...*/
544 /* Then get the port if it exists... */
545 lpszPort = strpbrk( szHost, ":" );
547 if( lpszPort != NULL )
549 char* szPort = lpszPort + 1;
552 nPortLen = strlen( szPort );
553 nPort = atoi( szPort );
556 nHostLen = strlen(szHost);
561 /* Relative URI... */
569 /***********************************************************************
570 * InternetAttemptConnect (WININET.81)
572 * Attempt to make a connection to the internet
575 * ERROR_SUCCESS on success
576 * Error value on failure
579 INTERNETAPI DWORD WINAPI InternetAttemptConnect(DWORD dwReserved)
582 return ERROR_SUCCESS;
586 /***********************************************************************
587 * InternetCanonicalizeUrlA (WININET.85)
589 * Escape unsafe characters and spaces
596 BOOLAPI InternetCanonicalizeUrlA(LPCSTR lpszUrl, LPSTR lpszBuffer,
597 LPDWORD lpdwBufferLength, DWORD dwFlags)
599 BOOL bSuccess = FALSE;
605 strncpy(lpszBuffer, lpszUrl, *lpdwBufferLength);
606 *lpdwBufferLength = strlen(lpszBuffer);
614 /***********************************************************************
615 * InternetSetStatusCallback (WININET.133)
617 * Sets up a callback function which is called as progress is made
618 * during an operation.
621 * Previous callback or NULL on success
622 * INTERNET_INVALID_STATUS_CALLBACK on failure
625 INTERNETAPI INTERNET_STATUS_CALLBACK WINAPI InternetSetStatusCallback(
626 HINTERNET hInternet ,INTERNET_STATUS_CALLBACK lpfnIntCB)
628 INTERNET_STATUS_CALLBACK retVal;
629 LPWININETAPPINFOA lpwai = (LPWININETAPPINFOA)hInternet;
631 TRACE("0x%08lx\n", (ULONG)hInternet);
632 if (lpwai->hdr.htype != WH_HINIT)
633 return INTERNET_INVALID_STATUS_CALLBACK;
635 retVal = lpwai->lpfnStatusCB;
636 lpwai->lpfnStatusCB = lpfnIntCB;
642 /***********************************************************************
643 * InternetWriteFile (WININET.138)
645 * Write data to an open internet file
652 BOOLAPI InternetWriteFile(HINTERNET hFile, LPCVOID lpBuffer ,
653 DWORD dwNumOfBytesToWrite, LPDWORD lpdwNumOfBytesWritten)
656 int nSocket = INVALID_SOCKET;
657 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
666 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
670 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
677 if (INVALID_SOCKET != nSocket)
679 *lpdwNumOfBytesWritten = INTERNET_WriteDataToStream(nSocket, lpBuffer, dwNumOfBytesToWrite);
680 if (*lpdwNumOfBytesWritten < 0)
681 *lpdwNumOfBytesWritten = 0;
690 /***********************************************************************
691 * InternetReadFile (WININET.121)
693 * Read data from an open internet file
700 BOOLAPI InternetReadFile(HINTERNET hFile, LPVOID lpBuffer,
701 DWORD dwNumOfBytesToRead, LPDWORD dwNumOfBytesRead)
704 int nSocket = INVALID_SOCKET;
705 LPWININETHANDLEHEADER lpwh = (LPWININETHANDLEHEADER) hFile;
714 nSocket = ((LPWININETHTTPREQA)hFile)->nSocketFD;
718 nSocket = ((LPWININETFILE)hFile)->nDataSocket;
725 if (INVALID_SOCKET != nSocket)
727 *dwNumOfBytesRead = INTERNET_ReadDataFromStream(nSocket, lpBuffer, dwNumOfBytesToRead);
728 if (*dwNumOfBytesRead < 0)
729 *dwNumOfBytesRead = 0;
738 /***********************************************************************
739 * GetInternetScheme (internal)
745 * INTERNET_SCHEME_UNKNOWN on failure
748 INTERNET_SCHEME GetInternetScheme(LPSTR lpszScheme)
751 return INTERNET_SCHEME_UNKNOWN;
753 if( (strcmp("ftp", lpszScheme) == 0) ||
754 (strcmp("FTP", lpszScheme) == 0) )
755 return INTERNET_SCHEME_FTP;
756 else if( (strcmp("gopher", lpszScheme) == 0) ||
757 (strcmp("GOPHER", lpszScheme) == 0) )
758 return INTERNET_SCHEME_GOPHER;
759 else if( (strcmp("http", lpszScheme) == 0) ||
760 (strcmp("HTTP", lpszScheme) == 0) )
761 return INTERNET_SCHEME_HTTP;
762 else if( (strcmp("https", lpszScheme) == 0) ||
763 (strcmp("HTTPS", lpszScheme) == 0) )
764 return INTERNET_SCHEME_HTTPS;
765 else if( (strcmp("file", lpszScheme) == 0) ||
766 (strcmp("FILE", lpszScheme) == 0) )
767 return INTERNET_SCHEME_FILE;
768 else if( (strcmp("news", lpszScheme) == 0) ||
769 (strcmp("NEWS", lpszScheme) == 0) )
770 return INTERNET_SCHEME_NEWS;
771 else if( (strcmp("mailto", lpszScheme) == 0) ||
772 (strcmp("MAILTO", lpszScheme) == 0) )
773 return INTERNET_SCHEME_MAILTO;
775 return INTERNET_SCHEME_UNKNOWN;
779 /***********************************************************************
780 * INTERNET_WriteDataToStream (internal)
782 * Send data to server
786 * number of characters sent on success
789 int INTERNET_WriteDataToStream(int nDataSocket, LPCVOID Buffer, DWORD BytesToWrite)
791 if (INVALID_SOCKET == nDataSocket)
794 return send(nDataSocket, Buffer, BytesToWrite, 0);
798 /***********************************************************************
799 * INTERNET_ReadDataFromStream (internal)
801 * Read data from http server
805 * number of characters sent on success
808 int INTERNET_ReadDataFromStream(int nDataSocket, LPVOID Buffer, DWORD BytesToRead)
810 if (INVALID_SOCKET == nDataSocket)
813 return recv(nDataSocket, Buffer, BytesToRead, 0);
817 /***********************************************************************
818 * INTERNET_SetLastError (internal)
820 * Set last thread specific error
825 void INTERNET_SetLastError(DWORD dwError)
827 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
829 SetLastError(dwError);
830 lpwite->dwError = dwError;
834 /***********************************************************************
835 * INTERNET_GetLastError (internal)
837 * Get last thread specific error
842 DWORD INTERNET_GetLastError()
844 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
845 return lpwite->dwError;
849 /***********************************************************************
850 * INTERNET_WorkerThreadFunc (internal)
852 * Worker thread execution function
857 DWORD INTERNET_WorkerThreadFunc(LPVOID *lpvParam)
863 dwWaitRes = WaitForMultipleObjects(2, hEventArray, FALSE, MAX_IDLE_WORKER);
865 if (dwWaitRes == WAIT_OBJECT_0 + 1)
866 INTERNET_ExecuteWork();
870 InterlockedIncrement(&dwNumIdleThreads);
873 InterlockedDecrement(&dwNumIdleThreads);
874 InterlockedDecrement(&dwNumThreads);
875 TRACE("Worker thread exiting\n");
880 /***********************************************************************
881 * INTERNET_InsertWorkRequest (internal)
883 * Insert work request into queue
888 BOOL INTERNET_InsertWorkRequest(LPWORKREQUEST lpWorkRequest)
890 BOOL bSuccess = FALSE;
891 LPWORKREQUEST lpNewRequest;
895 lpNewRequest = HeapAlloc(GetProcessHeap(), 0, sizeof(WORKREQUEST));
898 memcpy(lpNewRequest, lpWorkRequest, sizeof(WORKREQUEST));
899 lpNewRequest->prev = NULL;
901 EnterCriticalSection(&csQueue);
903 lpNewRequest->next = lpWorkQueueTail;
905 lpWorkQueueTail->prev = lpNewRequest;
906 lpWorkQueueTail = lpNewRequest;
907 if (!lpHeadWorkQueue)
908 lpHeadWorkQueue = lpWorkQueueTail;
910 LeaveCriticalSection(&csQueue);
919 /***********************************************************************
920 * INTERNET_GetWokkRequest (internal)
922 * Retrieves work request from queue
927 BOOL INTERNET_GetWorkRequest(LPWORKREQUEST lpWorkRequest)
929 BOOL bSuccess = FALSE;
930 LPWORKREQUEST lpRequest = NULL;
934 EnterCriticalSection(&csQueue);
938 lpRequest = lpHeadWorkQueue;
939 lpHeadWorkQueue = lpHeadWorkQueue->prev;
940 if (lpRequest == lpWorkQueueTail)
941 lpWorkQueueTail = lpHeadWorkQueue;
944 LeaveCriticalSection(&csQueue);
948 memcpy(lpWorkRequest, lpRequest, sizeof(WORKREQUEST));
949 HeapFree(GetProcessHeap(), 0, lpRequest);
957 /***********************************************************************
958 * INTERNET_AsyncCall (internal)
960 * Retrieves work request from queue
965 BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest)
969 BOOL bSuccess = FALSE;
973 if (InterlockedDecrement(&dwNumIdleThreads) < 0)
975 InterlockedIncrement(&dwNumIdleThreads);
977 if (InterlockedIncrement(&dwNumThreads) > MAX_WORKER_THREADS ||
978 !(hThread = CreateThread(NULL, 0,
979 (LPTHREAD_START_ROUTINE)INTERNET_WorkerThreadFunc, NULL, 0, &dwTID)))
981 InterlockedDecrement(&dwNumThreads);
982 INTERNET_SetLastError(ERROR_INTERNET_ASYNC_THREAD_FAILED);
986 TRACE("Created new thread\n");
990 INTERNET_InsertWorkRequest(lpWorkRequest);
991 SetEvent(hWorkEvent);
999 /***********************************************************************
1000 * INTERNET_ExecuteWork (internal)
1005 VOID INTERNET_ExecuteWork()
1007 WORKREQUEST workRequest;
1011 if (INTERNET_GetWorkRequest(&workRequest))
1013 switch (workRequest.asyncall)
1016 FTP_FtpPutFileA((HINTERNET)workRequest.HFTPSESSION, (LPCSTR)workRequest.LPSZLOCALFILE,
1017 (LPCSTR)workRequest.LPSZNEWREMOTEFILE, workRequest.DWFLAGS, workRequest.DWCONTEXT);
1018 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZLOCALFILE);
1019 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWREMOTEFILE);
1022 case FTPSETCURRENTDIRECTORYA:
1023 FTP_FtpSetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1024 (LPCSTR)workRequest.LPSZDIRECTORY);
1025 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1028 case FTPCREATEDIRECTORYA:
1029 FTP_FtpCreateDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1030 (LPCSTR)workRequest.LPSZDIRECTORY);
1031 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1034 case FTPFINDFIRSTFILEA:
1035 FTP_FtpFindFirstFileA((HINTERNET)workRequest.HFTPSESSION,
1036 (LPCSTR)workRequest.LPSZSEARCHFILE,
1037 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA, workRequest.DWFLAGS,
1038 workRequest.DWCONTEXT);
1039 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSEARCHFILE);
1042 case FTPGETCURRENTDIRECTORYA:
1043 FTP_FtpGetCurrentDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1044 (LPSTR)workRequest.LPSZDIRECTORY, (LPDWORD)workRequest.LPDWDIRECTORY);
1048 FTP_FtpOpenFileA((HINTERNET)workRequest.HFTPSESSION,
1049 (LPCSTR)workRequest.LPSZFILENAME,
1050 workRequest.FDWACCESS,
1051 workRequest.DWFLAGS,
1052 workRequest.DWCONTEXT);
1053 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1057 FTP_FtpGetFileA((HINTERNET)workRequest.HFTPSESSION,
1058 (LPCSTR)workRequest.LPSZREMOTEFILE,
1059 (LPCSTR)workRequest.LPSZNEWFILE,
1060 (BOOL)workRequest.FFAILIFEXISTS,
1061 workRequest.DWLOCALFLAGSATTRIBUTE,
1062 workRequest.DWFLAGS,
1063 workRequest.DWCONTEXT);
1064 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZREMOTEFILE);
1065 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZNEWFILE);
1068 case FTPDELETEFILEA:
1069 FTP_FtpDeleteFileA((HINTERNET)workRequest.HFTPSESSION,
1070 (LPCSTR)workRequest.LPSZFILENAME);
1071 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZFILENAME);
1074 case FTPREMOVEDIRECTORYA:
1075 FTP_FtpRemoveDirectoryA((HINTERNET)workRequest.HFTPSESSION,
1076 (LPCSTR)workRequest.LPSZDIRECTORY);
1077 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDIRECTORY);
1080 case FTPRENAMEFILEA:
1081 FTP_FtpRenameFileA((HINTERNET)workRequest.HFTPSESSION,
1082 (LPCSTR)workRequest.LPSZSRCFILE,
1083 (LPCSTR)workRequest.LPSZDESTFILE);
1084 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZSRCFILE);
1085 HeapFree(GetProcessHeap(), 0, (LPVOID)workRequest.LPSZDESTFILE);
1088 case INTERNETFINDNEXTA:
1089 INTERNET_FindNextFileA((HINTERNET)workRequest.HFTPSESSION,
1090 (LPWIN32_FIND_DATAA)workRequest.LPFINDFILEDATA);
1097 /***********************************************************************
1098 * INTERNET_GetResponseBuffer
1103 LPSTR INTERNET_GetResponseBuffer()
1105 LPWITHREADERROR lpwite = (LPWITHREADERROR)TlsGetValue(g_dwTlsErrIndex);
1106 return lpwite->response;