1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WinSock 2 API 4 * FILE: dll/win32/ws2_32_new/src/enumprot.c 5 * PURPOSE: Protocol Enumeration 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 /* FUNCTIONS *****************************************************************/ 17 18 BOOL 19 WSAAPI 20 CheckProtocolMatch(IN LPINT ProtocolSet, 21 IN LPWSAPROTOCOL_INFOW ProtocolInfo) 22 { 23 BOOL Return = FALSE; 24 DWORD i = 0; 25 INT ProtocolId; 26 27 /* Make sure we have a set */ 28 if (ProtocolSet) 29 { 30 /* Get the first ID */ 31 ProtocolId = ProtocolSet[i]; 32 33 /* Loop the list */ 34 while (ProtocolId != 0 && ProtocolInfo->iProtocol != 0) 35 { 36 /* Check if it's within ranges */ 37 if ((ProtocolId >= ProtocolInfo->iProtocol) && 38 (ProtocolId <= (ProtocolInfo->iProtocol + 39 ProtocolInfo->iProtocolMaxOffset))) 40 { 41 /* Found it */ 42 Return = TRUE; 43 break; 44 } 45 46 /* Move on */ 47 i++; 48 ProtocolId = ProtocolSet[i]; 49 } 50 } 51 else 52 { 53 /* Assume match */ 54 Return = TRUE; 55 } 56 57 /* Return result */ 58 return Return; 59 } 60 61 VOID 62 WSAAPI 63 ProtocolInfoFromContext(IN LPWSAPROTOCOL_INFOW ProtocolInfo, 64 IN PPROTOCOL_ENUM_CONTEXT Context) 65 { 66 /* Check if we'll have space */ 67 if ((Context->BufferUsed + sizeof(*ProtocolInfo)) <= 68 (Context->BufferLength)) 69 { 70 /* Copy the data */ 71 RtlMoveMemory((PVOID)((ULONG_PTR)Context->ProtocolBuffer + 72 Context->BufferUsed), 73 ProtocolInfo, 74 sizeof(*ProtocolInfo)); 75 76 /* Increase the count */ 77 Context->Count++; 78 } 79 } 80 81 BOOL 82 WSAAPI 83 ProtocolEnumerationProc(PVOID EnumContext, 84 PTCATALOG_ENTRY Entry) 85 { 86 PPROTOCOL_ENUM_CONTEXT Context = (PPROTOCOL_ENUM_CONTEXT)EnumContext; 87 LPWSAPROTOCOL_INFOW ProtocolInfo = &Entry->ProtocolInfo; 88 89 /* Check if this protocol matches */ 90 if (CheckProtocolMatch(Context->Protocols, ProtocolInfo)) 91 { 92 /* Copy the information */ 93 ProtocolInfoFromContext(ProtocolInfo, Context); 94 Context->BufferUsed += sizeof(*ProtocolInfo); 95 } 96 97 /* Continue enumeration */ 98 return TRUE; 99 } 100 101 PTCATALOG 102 WSAAPI 103 OpenInitializedCatalog(VOID) 104 { 105 PTCATALOG Catalog; 106 HKEY WsKey; 107 108 /* Allocate the catalog */ 109 Catalog = WsTcAllocate(); 110 if (Catalog) 111 { 112 /* Open the WS Key */ 113 WsKey = WsOpenRegistryRoot(); 114 115 /* Initialize the catalog */ 116 WsTcInitializeFromRegistry(Catalog, WsKey, NULL); 117 118 /* Close the key */ 119 RegCloseKey(WsKey); 120 } 121 122 /* Return it */ 123 return Catalog; 124 } 125 126 /* 127 * @implemented 128 */ 129 INT 130 WSPAPI 131 WSCEnumProtocols(IN LPINT lpiProtocols, 132 OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, 133 IN OUT LPDWORD lpdwBufferLength, 134 OUT LPINT lpErrno) 135 { 136 INT Status; 137 PTCATALOG Catalog; 138 PROTOCOL_ENUM_CONTEXT Context; 139 DPRINT("WSCEnumProtocols: %p\n", lpiProtocols); 140 141 /* Create a catalog object from the current one */ 142 Catalog = OpenInitializedCatalog(); 143 if (!Catalog) 144 { 145 /* Fail if we couldn't */ 146 *lpErrno = WSAENOBUFS; 147 return SOCKET_ERROR; 148 } 149 150 /* Setup the context */ 151 Context.Protocols = lpiProtocols; 152 Context.ProtocolBuffer = lpProtocolBuffer; 153 Context.BufferLength = lpProtocolBuffer ? *lpdwBufferLength : 0; 154 Context.BufferUsed = 0; 155 Context.Count = 0; 156 Context.ErrorCode = ERROR_SUCCESS; 157 158 /* Enumerate the catalog */ 159 WsTcEnumerateCatalogItems(Catalog, ProtocolEnumerationProc, &Context); 160 161 /* Get status */ 162 Status = Context.Count; 163 164 /* Check the error code */ 165 if (Context.ErrorCode == ERROR_SUCCESS) 166 { 167 /* Check if enough space was available */ 168 if (Context.BufferLength < Context.BufferUsed) 169 { 170 /* Fail and tell them how much we need */ 171 *lpdwBufferLength = Context.BufferUsed; 172 *lpErrno = WSAENOBUFS; 173 Status = SOCKET_ERROR; 174 } 175 } 176 else 177 { 178 /* Failure, normalize error */ 179 Status = SOCKET_ERROR; 180 *lpErrno = Context.ErrorCode; 181 } 182 183 /* Delete the catalog object */ 184 WsTcDelete(Catalog); 185 186 /* Return */ 187 return Status; 188 } 189 190 /* 191 * @implemented 192 */ 193 INT 194 WSAAPI 195 WSAEnumProtocolsA(IN LPINT lpiProtocols, 196 OUT LPWSAPROTOCOL_INFOA lpProtocolBuffer, 197 IN OUT LPDWORD lpdwBufferLength) 198 { 199 INT error, i, count; 200 LPWSAPROTOCOL_INFOW protocolInfoW; 201 DWORD size; 202 DPRINT("WSAEnumProtocolsA: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength); 203 if (!lpdwBufferLength) 204 { 205 SetLastError(WSAENOBUFS); 206 return SOCKET_ERROR; 207 } 208 count = WSCEnumProtocols(lpiProtocols, NULL, &size, &error); 209 if (!lpProtocolBuffer || *lpdwBufferLength < (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA)) 210 { 211 *lpdwBufferLength = (size/sizeof(WSAPROTOCOL_INFOW))*sizeof(WSAPROTOCOL_INFOA); 212 SetLastError(WSAENOBUFS); 213 return SOCKET_ERROR; 214 } 215 protocolInfoW = HeapAlloc(WsSockHeap, 0, size); 216 count = WSCEnumProtocols(lpiProtocols, protocolInfoW, &size, &error); 217 if (SOCKET_ERROR == count) 218 { 219 HeapFree(WsSockHeap, 0, protocolInfoW); 220 SetLastError(error); 221 return SOCKET_ERROR; 222 } 223 *lpdwBufferLength = 0; 224 for (i = 0; i < count; i++) 225 { 226 /* Copy the data */ 227 RtlMoveMemory(&lpProtocolBuffer[i], 228 &protocolInfoW[i], 229 sizeof(lpProtocolBuffer[0])-sizeof(lpProtocolBuffer[0].szProtocol)); 230 wcstombs(lpProtocolBuffer[i].szProtocol, protocolInfoW[i].szProtocol, sizeof(lpProtocolBuffer[0].szProtocol)); 231 *lpdwBufferLength += sizeof(WSAPROTOCOL_INFOA); 232 } 233 HeapFree(WsSockHeap, 0, protocolInfoW); 234 return i; 235 } 236 237 /* 238 * @implemented 239 */ 240 INT 241 WSAAPI 242 WSAEnumProtocolsW(IN LPINT lpiProtocols, 243 OUT LPWSAPROTOCOL_INFOW lpProtocolBuffer, 244 IN OUT LPDWORD lpdwBufferLength) 245 { 246 INT error, count; 247 DPRINT("WSAEnumProtocolsW: %p %p %p\n", lpiProtocols, lpProtocolBuffer, lpdwBufferLength); 248 count = WSCEnumProtocols(lpiProtocols, lpProtocolBuffer, lpdwBufferLength, &error); 249 if (SOCKET_ERROR == count) 250 { 251 SetLastError(error); 252 return SOCKET_ERROR; 253 } 254 return count; 255 } 256 257 258 /* 259 * @implemented 260 */ 261 INT 262 WSPAPI 263 WPUGetProviderPath(IN LPGUID lpProviderId, 264 OUT LPWSTR lpszProviderDllPath, 265 IN OUT LPINT lpProviderDllPathLen, 266 OUT LPINT lpErrno) 267 { 268 return WSCGetProviderPath(lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno); 269 } 270 271 /* 272 * @implemented 273 */ 274 INT 275 WSAAPI 276 WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle, 277 IN LPWSAOVERLAPPED lpOverlapped, 278 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) 279 { 280 DPRINT("WSAProviderConfigChange: %p\n", lpNotificationHandle); 281 UNIMPLEMENTED; 282 SetLastError(WSAEINVAL); 283 return SOCKET_ERROR; 284 } 285 286 /* 287 * @unimplemented 288 */ 289 INT 290 WSPAPI 291 WSCGetProviderPath(IN LPGUID lpProviderId, 292 OUT LPWSTR lpszProviderDllPath, 293 IN OUT LPINT lpProviderDllPathLen, 294 OUT LPINT lpErrno) 295 { 296 DPRINT("WSCGetProviderPath: %p %p %p %p\n", lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno); 297 UNIMPLEMENTED; 298 SetLastError(WSAEINVAL); 299 return SOCKET_ERROR; 300 } 301