1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32/src/enumprot.c 5 * PURPOSE: Protocol Enumeration 6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net) 7 * Pierre Schweitzer 8 */ 9 10 /* INCLUDES ******************************************************************/ 11 12 #include <ws2_32.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* FUNCTIONS *****************************************************************/ 18 19 BOOL 20 WSAAPI 21 CheckProtocolMatch(IN LPINT ProtocolSet, 22 IN LPWSAPROTOCOL_INFOW ProtocolInfo) 23 { 24 BOOL Return = FALSE; 25 DWORD i = 0; 26 INT ProtocolId; 27 28 /* Make sure we have a set */ 29 if (ProtocolSet) 30 { 31 /* Get the first ID */ 32 ProtocolId = ProtocolSet[i]; 33 34 /* Loop the list */ 35 while (ProtocolId != 0 && ProtocolInfo->iProtocol != 0) 36 { 37 /* Check if it's within ranges */ 38 if ((ProtocolId >= ProtocolInfo->iProtocol) && 39 (ProtocolId <= (ProtocolInfo->iProtocol + 40 ProtocolInfo->iProtocolMaxOffset))) 41 { 42 /* Found it */ 43 Return = TRUE; 44 break; 45 } 46 47 /* Move on */ 48 i++; 49 ProtocolId = ProtocolSet[i]; 50 } 51 } 52 else 53 { 54 /* Assume match */ 55 Return = TRUE; 56 } 57 58 /* Return result */ 59 return Return; 60 } 61 62 VOID 63 WSAAPI 64 ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo, 65 IN PPROTOCOL_ENUM_CONTEXT Context) 66 { 67 /* Check if we'll have space */ 68 if ((Context->BufferUsed + sizeof(*ProtocolInfo)) <= 69 (Context->BufferLength)) 70 { 71 /* Copy the data */ 72 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 73 Context->BufferUsed), 74 ProtocolInfo, 75 sizeof(*ProtocolInfo)); 76 77 /* Increase the count */ 78 Context->Count++; 79 } 80 } 81 82 BOOL 83 WSAAPI 84 ProtocolEnumerationProc(PVOID EnumContext, 85 PTCATALOG_ENTRY Entry) 86 { 87 PPROTOCOL_ENUM_CONTEXT Context = (PPROTOCOL_ENUM_CONTEXT)EnumContext; 88 LPWSAPROTOCOL_INFOW ProtocolInfo = &Entry->ProtocolInfo; 89 90 /* Check if this protocol matches */ 91 if (CheckProtocolMatch(Context->Protocols, ProtocolInfo)) 92 { 93 /* Copy the information */ 94 ProtocolInfoFromContext(ProtocolInfo, Context); 95 Context->BufferUsed += sizeof(*ProtocolInfo); 96 } 97 98 /* Continue enumeration */ 99 return TRUE; 100 } 101 102 BOOL 103 WSAAPI 104 ProviderEnumerationProc(PVOID EnumContext, 105 PNSCATALOG_ENTRY Entry) 106 { 107 INT PathLen; 108 PPROVIDER_ENUM_CONTEXT Context = (PPROVIDER_ENUM_CONTEXT)EnumContext; 109 110 /* Check if this provider matches */ 111 if (IsEqualGUID(&Entry->ProviderId, &Context->ProviderId)) 112 { 113 /* Get the information about the provider */ 114 PathLen = wcslen(Entry->DllPath) + 1; 115 Context->FoundPathLen = PathLen; 116 Context->Found = 1; 117 118 /* If we have enough room, copy path */ 119 if (PathLen <= Context->ProviderDllPathLen) 120 { 121 wcscpy(Context->ProviderDllPath, Entry->DllPath); 122 } 123 124 /* Stop enumeration */ 125 return FALSE; 126 } 127 else 128 { 129 /* Continue enumeration */ 130 return TRUE; 131 } 132 133 } 134 135 PTCATALOG 136 WSAAPI 137 OpenInitializedCatalog(VOID) 138 { 139 PTCATALOG Catalog; 140 HKEY WsKey; 141 142 /* Allocate the catalog */ 143 Catalog = WsTcAllocate(); 144 if (Catalog) 145 { 146 /* Open the WS Key */ 147 WsKey = WsOpenRegistryRoot(); 148 149 /* Initialize the catalog */ 150 WsTcInitializeFromRegistry(Catalog, WsKey, NULL); 151 152 /* Close the key */ 153 RegCloseKey(WsKey); 154 } 155 156 /* Return it */ 157 return Catalog; 158 } 159 160 /* 161 * @implemented 162 */ 163 INT 164 WSPAPI 165 WSCEnumProtocols(IN LPINT lpiProtocols, 166 OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, 167 IN OUT LPDWORD lpdwBufferLength, 168 OUT LPINT lpErrno) 169 { 170 INT Status; 171 PTCATALOG Catalog; 172 PROTOCOL_ENUM_CONTEXT Context; 173 DPRINT("WSCEnumProtocols: %p\n", lpiProtocols); 174 175 /* Create a catalog object from the current one */ 176 Catalog = OpenInitializedCatalog(); 177 if (!Catalog) 178 { 179 /* Fail if we couldn't */ 180 *lpErrno = WSAENOBUFS; 181 return SOCKET_ERROR; 182 } 183 184 /* Setup the context */ 185 Context.Protocols = lpiProtocols; 186 Context.ProtocolBuffer = lpProtocolBuffer; 187 Context.BufferLength = lpProtocolBuffer ? *lpdwBufferLength : 0; 188 Context.BufferUsed = 0; 189 Context.Count = 0; 190 Context.ErrorCode = ERROR_SUCCESS; 191 192 /* Enumerate the catalog */ 193 WsTcEnumerateCatalogItems(Catalog, ProtocolEnumerationProc, &Context); 194 195 /* Get status */ 196 Status = Context.Count; 197 198 /* Check the error code */ 199 if (Context.ErrorCode == ERROR_SUCCESS) 200 { 201 /* Check if enough space was available */ 202 if (Context.BufferLength < Context.BufferUsed) 203 { 204 /* Fail and tell them how much we need */ 205 *lpdwBufferLength = Context.BufferUsed; 206 *lpErrno = WSAENOBUFS; 207 Status = SOCKET_ERROR; 208 } 209 } 210 else 211 { 212 /* Failure, normalize error */ 213 Status = SOCKET_ERROR; 214 *lpErrno = Context.ErrorCode; 215 } 216 217 /* Delete the catalog object */ 218 WsTcDelete(Catalog); 219 220 /* Return */ 221 return Status; 222 } 223 224 /* 225 * @implemented 226 */ 227 INT 228 WSAAPI 229 WSAEnumProtocolsA(IN LPINT lpiProtocols, 230 OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer, 231 IN OUT LPDWORD lpdwBufferLength) 232 { 233 INT error, i, count; 234 LPWSAPROTOCOL_INFOW protocolInfoW; 235 DWORD size; 236 DPRINT("WSAEnumProtocolsA: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength); 237 if (!lpdwBufferLength) 238 { 239 SetLastError(WSAENOBUFS); 240 return SOCKET_ERROR; 241 } 242 count = WSCEnumProtocols(lpiProtocols, NULL, &size, &error); 243 if (!lpProtocolBuffer || *lpdwBufferLength < (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA)) 244 { 245 *lpdwBufferLength = (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA); 246 SetLastError(WSAENOBUFS); 247 return SOCKET_ERROR; 248 } 249 protocolInfoW = HeapAlloc(WsSockHeap, 0, size); 250 count = WSCEnumProtocols(lpiProtocols, protocolInfoW, &size, &error); 251 if (SOCKET_ERROR == count) 252 { 253 HeapFree(WsSockHeap, 0, protocolInfoW); 254 SetLastError(error); 255 return SOCKET_ERROR; 256 } 257 *lpdwBufferLength = 0; 258 for (i = 0; i < count; i++) 259 { 260 /* Copy the data */ 261 RtlMoveMemory(&lpProtocolBuffer[i], 262 &protocolInfoW[i], 263 sizeof(lpProtocolBuffer[0])-sizeof(lpProtocolBuffer[0].szProtocol)); 264 wcstombs(lpProtocolBuffer[i].szProtocol, protocolInfoW[i].szProtocol, sizeof(lpProtocolBuffer[0].szProtocol)); 265 *lpdwBufferLength += sizeof(WSAPROTOCOL_INFOA); 266 } 267 HeapFree(WsSockHeap, 0, protocolInfoW); 268 return i; 269 } 270 271 /* 272 * @implemented 273 */ 274 INT 275 WSAAPI 276 WSAEnumProtocolsW(IN LPINT lpiProtocols, 277 OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, 278 IN OUT LPDWORD lpdwBufferLength) 279 { 280 INT error, count; 281 DPRINT("WSAEnumProtocolsW: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength); 282 count = WSCEnumProtocols(lpiProtocols, lpProtocolBuffer, lpdwBufferLength, &error); 283 if (SOCKET_ERROR == count) 284 { 285 SetLastError(error); 286 return SOCKET_ERROR; 287 } 288 return count; 289 } 290 291 292 /* 293 * @implemented 294 */ 295 INT 296 WSPAPI 297 WPUGetProviderPath(IN LPGUID lpProviderId, 298 OUT LPWSTR lpszProviderDllPath, 299 IN OUT LPINT lpProviderDllPathLen, 300 OUT LPINT lpErrno) 301 { 302 return WSCGetProviderPath(lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno); 303 } 304 305 /* 306 * @implemented 307 */ 308 INT 309 WSAAPI 310 WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle, 311 IN LPWSAOVERLAPPED lpOverlapped, 312 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 313 { 314 DPRINT("WSAProviderConfigChange: %p\n", lpNotificationHandle); 315 UNIMPLEMENTED; 316 SetLastError(WSAEINVAL); 317 return SOCKET_ERROR; 318 } 319 320 /* 321 * @implemented 322 */ 323 INT 324 WSPAPI 325 WSCGetProviderPath(IN LPGUID lpProviderId, 326 OUT LPWSTR lpszProviderDllPath, 327 IN OUT LPINT lpProviderDllPathLen, 328 OUT LPINT lpErrno) 329 { 330 PWSTHREAD Thread; 331 PWSPROCESS Process; 332 PNSCATALOG Catalog; 333 INT ErrorCode, PathLen; 334 PROVIDER_ENUM_CONTEXT Context; 335 336 DPRINT("WSCGetProviderPath: %p %p %p %p\n", lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno); 337 338 /* Enter prolog */ 339 if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS) 340 { 341 /* FIXME: if WSANOTINITIALISED, we should init 342 * and perform the search! 343 */ 344 345 /* Leave now */ 346 *lpErrno = ErrorCode; 347 return SOCKET_ERROR; 348 } 349 350 /* Get the catalog */ 351 Catalog = WsProcGetNsCatalog(Process); 352 353 _SEH2_TRY 354 { 355 /* Setup the context */ 356 Context.ProviderId = *lpProviderId; 357 Context.ProviderDllPath = lpszProviderDllPath; 358 Context.ProviderDllPathLen = *lpProviderDllPathLen; 359 Context.FoundPathLen = 0; 360 Context.Found = 0; 361 Context.ErrorCode = ERROR_SUCCESS; 362 363 ErrorCode = ERROR_SUCCESS; 364 365 /* Enumerate the catalog */ 366 WsNcEnumerateCatalogItems(Catalog, ProviderEnumerationProc, &Context); 367 368 /* Check the error code */ 369 if (Context.ErrorCode == ERROR_SUCCESS) 370 { 371 /* Check if provider was found */ 372 if (Context.Found) 373 { 374 PathLen = Context.FoundPathLen; 375 376 /* Check whether buffer is too small 377 * If it isn't, return length without null char 378 * (see ProviderEnumerationProc) 379 */ 380 if (Context.FoundPathLen <= *lpProviderDllPathLen) 381 { 382 PathLen = Context.FoundPathLen - 1; 383 } 384 else 385 { 386 ErrorCode = WSAEFAULT; 387 } 388 389 /* Set returned/required length */ 390 *lpProviderDllPathLen = PathLen; 391 } 392 else 393 { 394 ErrorCode = WSAEINVAL; 395 } 396 } 397 else 398 { 399 ErrorCode = Context.ErrorCode; 400 } 401 } 402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 403 { 404 ErrorCode = WSAEFAULT; 405 } 406 _SEH2_END; 407 408 /* Do we have to return failure? */ 409 if (ErrorCode != ERROR_SUCCESS) 410 { 411 *lpErrno = ErrorCode; 412 return SOCKET_ERROR; 413 } 414 415 return 0; 416 } 417