[WS2_32] Implement WSCGetProviderPath()
authorPierre Schweitzer <pierre@reactos.org>
Sat, 23 Feb 2019 09:57:06 +0000 (10:57 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Sat, 23 Feb 2019 09:57:30 +0000 (10:57 +0100)
dll/win32/ws2_32/inc/ws2_32p.h
dll/win32/ws2_32/src/enumprot.c

index 5e7f5d6..968c6ce 100644 (file)
@@ -232,6 +232,16 @@ typedef struct _PROTOCOL_ENUM_CONTEXT
     INT ErrorCode;
 } PROTOCOL_ENUM_CONTEXT, *PPROTOCOL_ENUM_CONTEXT;
 
+typedef struct _PROVIDER_ENUM_CONTEXT
+{
+    GUID ProviderId;
+    LPWSTR ProviderDllPath;
+    INT ProviderDllPathLen;
+    DWORD FoundPathLen;
+    DWORD Found;
+    INT ErrorCode;
+} PROVIDER_ENUM_CONTEXT, *PPROVIDER_ENUM_CONTEXT;
+
 typedef struct _WS_BUFFER
 {
     ULONG_PTR Position;
index 4d04ea3..a47b290 100644 (file)
@@ -4,6 +4,7 @@
  * FILE:        dll/win32/ws2_32_new/src/enumprot.c
  * PURPOSE:     Protocol Enumeration
  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
+ *              Pierre Schweitzer
  */
 
 /* INCLUDES ******************************************************************/
@@ -98,6 +99,39 @@ ProtocolEnumerationProc(PVOID EnumContext,
     return TRUE;
 }
 
+BOOL
+WSAAPI
+ProviderEnumerationProc(PVOID EnumContext,
+                        PNSCATALOG_ENTRY Entry)
+{
+    INT PathLen;
+    PPROVIDER_ENUM_CONTEXT Context = (PPROVIDER_ENUM_CONTEXT)EnumContext;
+
+    /* Check if this provider matches */
+    if (IsEqualGUID(&Entry->ProviderId, &Context->ProviderId))
+    {
+        /* Get the information about the provider */
+        PathLen = wcslen(Entry->DllPath) + 1;
+        Context->FoundPathLen = PathLen;
+        Context->Found = 1;
+
+        /* If we have enough room, copy path */
+        if (PathLen <= Context->ProviderDllPathLen)
+        {
+            wcscpy(Context->ProviderDllPath, Entry->DllPath);
+        }
+
+        /* Stop enumeration */
+        return FALSE;
+    }
+    else
+    {
+        /* Continue enumeration */
+        return TRUE;
+    }
+
+}
+
 PTCATALOG
 WSAAPI
 OpenInitializedCatalog(VOID)
@@ -284,7 +318,7 @@ WSAProviderConfigChange(IN OUT LPHANDLE lpNotificationHandle,
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 INT
 WSPAPI
@@ -293,8 +327,82 @@ WSCGetProviderPath(IN LPGUID lpProviderId,
                    IN OUT LPINT lpProviderDllPathLen,
                    OUT LPINT lpErrno)
 {
+    PWSTHREAD Thread;
+    PWSPROCESS Process;
+    PNSCATALOG Catalog;
+    INT ErrorCode, PathLen;
+    PROVIDER_ENUM_CONTEXT Context;
+
     DPRINT("WSCGetProviderPath: %p %p %p %p\n", lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno);
-    UNIMPLEMENTED;
-    SetLastError(WSAEINVAL);
-    return SOCKET_ERROR;
+
+    /* Enter prolog */
+    if ((ErrorCode = WsApiProlog(&Process, &Thread)) != ERROR_SUCCESS)
+    {
+        /* FIXME: if WSANOTINITIALISED, we should init
+         * and perform the search!
+         */
+
+        /* Leave now */
+        *lpErrno = ErrorCode;
+        return SOCKET_ERROR;
+    }
+
+    /* Get the catalog */
+    Catalog = WsProcGetNsCatalog(Process);
+
+    /* Setup the context */
+    Context.ProviderId = *lpProviderId;
+    Context.ProviderDllPath = lpszProviderDllPath;
+    Context.ProviderDllPathLen = *lpProviderDllPathLen;
+    Context.FoundPathLen = 0;
+    Context.Found = 0;
+    Context.ErrorCode = ERROR_SUCCESS;
+
+    ErrorCode = ERROR_SUCCESS;
+
+    /* Enumerate the catalog */
+    WsNcEnumerateCatalogItems(Catalog, ProviderEnumerationProc, &Context);
+
+    /* Check the error code */
+    if (Context.ErrorCode == ERROR_SUCCESS)
+    {
+        /* Check if provider was found */
+        if (Context.Found)
+        {
+            PathLen = Context.FoundPathLen;
+
+            /* Check whether buffer is too small
+             * If it isn't, return length without null char
+             * (see ProviderEnumerationProc)
+             */
+            if (Context.FoundPathLen <= *lpProviderDllPathLen)
+            {
+                PathLen = Context.FoundPathLen - 1;
+            }
+            else
+            {
+                ErrorCode = WSAEFAULT;
+            }
+
+            /* Set returned/required length */
+            *lpProviderDllPathLen = PathLen;
+        }
+        else
+        {
+            ErrorCode = WSAEINVAL;
+        }
+    }
+    else
+    {
+        ErrorCode = Context.ErrorCode;
+    }
+
+    /* Do we have to return failure? */
+    if (ErrorCode != ERROR_SUCCESS)
+    {
+        *lpErrno = ErrorCode;
+        return SOCKET_ERROR;
+    }
+
+    return 0;
 }