1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32/src/startup.c 5 * PURPOSE: Startup/Cleanup Support 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ws2_32.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* DATA **********************************************************************/ 17 18 PWS_SOCK_POST_ROUTINE WsSockPostRoutine = NULL; 19 CRITICAL_SECTION WsStartupLock; 20 21 #define WsStartupLock() EnterCriticalSection(&WsStartupLock) 22 #define WsStartupUnlock() LeaveCriticalSection(&WsStartupLock) 23 24 /* FUNCTIONS *****************************************************************/ 25 26 VOID 27 WSAAPI 28 WsCreateStartupSynchronization(VOID) 29 { 30 /* Initialize the startup lock */ 31 InitializeCriticalSection(&WsStartupLock); 32 } 33 34 VOID 35 WSAAPI 36 WsDestroyStartupSynchronization(VOID) 37 { 38 /* Destroy the startup lock */ 39 DeleteCriticalSection(&WsStartupLock); 40 } 41 42 /* 43 * @implemented 44 */ 45 BOOL 46 WSAAPI 47 WSApSetPostRoutine(PVOID Routine) 48 { 49 /* Set the post routine */ 50 DPRINT("WSApSetPostRoutine: %p\n", Routine); 51 WsSockPostRoutine = (PWS_SOCK_POST_ROUTINE)Routine; 52 return ERROR_SUCCESS; 53 } 54 55 /* 56 * @implemented 57 */ 58 INT 59 WSAAPI 60 WSACleanup(VOID) 61 { 62 PWSPROCESS Process; 63 PWSTHREAD Thread; 64 INT ErrorCode; 65 LONG RefCount; 66 DPRINT("WSACleanup\n"); 67 68 /* Enter startup lock */ 69 WsStartupLock(); 70 71 /* Enter prolog */ 72 if ((ErrorCode = WsApiProlog(&Process, &Thread)) == ERROR_SUCCESS) 73 { 74 /* Decrement process reference count and check if it's zero */ 75 if (!(RefCount = InterlockedDecrement(&Process->RefCount))) 76 { 77 /* It's zero, destroy the process structure */ 78 WsProcDelete(Process); 79 } 80 else if (RefCount == 1 && WsAsyncThreadInitialized) 81 { 82 /* Kill async thread */ 83 WsAsyncTerminateThread(); 84 } 85 86 DPRINT("WSACleanup RefCount = %ld\n", RefCount); 87 /* Return success */ 88 ErrorCode = ERROR_SUCCESS; 89 90 /* Clear last error */ 91 SetLastError(ERROR_SUCCESS); 92 } 93 else 94 { 95 DPRINT("WSACleanup uninitialized\n"); 96 /* Weren't initialized */ 97 SetLastError(ErrorCode); 98 ErrorCode = SOCKET_ERROR; 99 } 100 101 /* Release startup lock */ 102 WsStartupUnlock(); 103 104 /* Done */ 105 return ErrorCode; 106 } 107 108 /* 109 * @implemented 110 */ 111 INT 112 WINAPI 113 WSAStartup(IN WORD wVersionRequested, 114 OUT LPWSADATA lpWSAData) 115 { 116 WORD VersionReturned = 0; 117 DWORD ErrorCode = ERROR_SUCCESS; 118 PWSPROCESS CurrentProcess; 119 DPRINT("WSAStartup: %wx %d.%d\n", wVersionRequested, LOBYTE(wVersionRequested), HIBYTE(wVersionRequested)); 120 121 /* Make sure that we went through DLL Init */ 122 if (!WsDllHandle) return WSASYSNOTREADY; 123 124 /* Check which version is being requested */ 125 switch (LOBYTE(wVersionRequested)) 126 { 127 case 0: 128 129 /* We don't support this unknown version */ 130 ErrorCode = WSAVERNOTSUPPORTED; 131 VersionReturned = MAKEWORD(2, 2); 132 break; 133 134 case 1: 135 /* We support only 1.0 and 1.1 */ 136 if (HIBYTE(wVersionRequested) <= 1) 137 { 138 /* Caller wants 1.0, return it */ 139 VersionReturned = MAKEWORD(1, HIBYTE(wVersionRequested)); 140 } 141 else 142 { 143 /* The only other version we support is 1.1 */ 144 VersionReturned = MAKEWORD(1, 1); 145 } 146 break; 147 148 case 2: 149 /* We support only 2.0, 2.1 and 2.2 */ 150 if (HIBYTE(wVersionRequested) <= 2) 151 { 152 /* Caller wants 2.0-2.2, return it */ 153 VersionReturned = MAKEWORD(2, HIBYTE(wVersionRequested)); 154 } 155 else 156 { 157 /* The highest version we support is 2.2 */ 158 VersionReturned = MAKEWORD(2, 2); 159 } 160 break; 161 162 default: 163 164 /* Return 2.2 */ 165 VersionReturned = MAKEWORD(2, 2); 166 break; 167 } 168 169 if (lpWSAData == NULL) 170 { 171 SetLastError(WSANOTINITIALISED); 172 return ErrorCode == ERROR_SUCCESS ? WSAEFAULT : ErrorCode; 173 } 174 175 /* Return the Version Requested, unless error */ 176 lpWSAData->wVersion = VersionReturned; 177 178 /* We support Winsock 2.2 */ 179 lpWSAData->wHighVersion = MAKEWORD(2,2); 180 lstrcpy(lpWSAData->szDescription, "WinSock 2.0"); 181 lstrcpy(lpWSAData->szSystemStatus, "Running"); 182 183 /* 184 * On Winsock 1, the following values are returned. 185 * Taken straight from a Winsock Test app on Windows. 186 */ 187 if (LOBYTE(wVersionRequested) == 1) 188 { 189 lpWSAData->iMaxSockets = 32767; 190 lpWSAData->iMaxUdpDg = 65467; 191 } 192 else 193 { 194 lpWSAData->iMaxSockets = 0; 195 lpWSAData->iMaxUdpDg = 0; 196 } 197 198 /* Requested invalid version (0) */ 199 if (ErrorCode != ERROR_SUCCESS) 200 { 201 SetLastError(WSANOTINITIALISED); 202 return ErrorCode; 203 } 204 205 /* Enter the startup synchronization lock */ 206 WsStartupLock(); 207 208 /* Now setup all our objects */ 209 while (TRUE) 210 { 211 /* Make sure we don't already have a process */ 212 CurrentProcess = WsGetProcess(); 213 if (CurrentProcess) break; 214 215 /* Setup the process object support */ 216 ErrorCode = WsProcStartup(); 217 if (ErrorCode != ERROR_SUCCESS) break; 218 219 /* Setup the process object support */ 220 ErrorCode = WsSockStartup(); 221 if (ErrorCode != ERROR_SUCCESS) break; 222 223 /* Setup the process object support */ 224 ErrorCode = WsThreadStartup(); 225 if (ErrorCode != ERROR_SUCCESS) break; 226 227 /* Try getting the process now */ 228 CurrentProcess = WsGetProcess(); 229 if (!CurrentProcess) 230 { 231 /* Something is weird... */ 232 ErrorCode = WSASYSNOTREADY; 233 break; 234 } 235 } 236 237 /* Check if all worked */ 238 if (ErrorCode == ERROR_SUCCESS) 239 { 240 /* Set the requested version */ 241 WsProcSetVersion(CurrentProcess, wVersionRequested); 242 243 /* Increase the reference count */ 244 InterlockedIncrement(&CurrentProcess->RefCount); 245 DPRINT("WSAStartup RefCount = %ld\n", CurrentProcess->RefCount); 246 247 /* Clear last error */ 248 SetLastError(ERROR_SUCCESS); 249 } 250 else 251 { 252 SetLastError(WSANOTINITIALISED); 253 } 254 255 /* Leave the startup lock */ 256 WsStartupUnlock(); 257 258 /* Return any Error */ 259 return ErrorCode; 260 } 261