15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/service_providers_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Ws2spi.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetWinsockNamespaceProviders(
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WinsockNamespaceProviderList* namespace_list) {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find out how just how much memory is needed.  If we get the expected error,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the memory needed is written to size.
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = 0;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (WSAEnumNameSpaceProviders(&size, NULL) != SOCKET_ERROR ||
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetLastError() != WSAEFAULT) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> namespace_provider_bytes(new char[size]);
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSANAMESPACE_INFO* namespace_providers =
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<WSANAMESPACE_INFO*>(namespace_provider_bytes.get());
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_namespace_providers = WSAEnumNameSpaceProviders(&size,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          namespace_providers);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_namespace_providers == SOCKET_ERROR) {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_namespace_providers; ++i) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WinsockNamespaceProvider provider;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider.name = namespace_providers[i].lpszIdentifier;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider.active = TRUE == namespace_providers[i].fActive;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider.version = namespace_providers[i].dwVersion;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider.type = namespace_providers[i].dwNameSpace;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    namespace_list->push_back(provider);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetWinsockLayeredServiceProviders(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WinsockLayeredServiceProviderList* service_list) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find out how just how much memory is needed.  If we get the expected error,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the memory needed is written to size.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size = 0;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SOCKET_ERROR != WSCEnumProtocols(NULL, NULL, &size, &error) ||
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error != WSAENOBUFS) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> service_provider_bytes(new char[size]);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WSAPROTOCOL_INFOW* service_providers =
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<WSAPROTOCOL_INFOW*>(service_provider_bytes.get());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_service_providers = WSCEnumProtocols(NULL, service_providers, &size,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &error);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_service_providers == SOCKET_ERROR) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_service_providers; ++i) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WinsockLayeredServiceProvider service_provider;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_provider.name = service_providers[i].szProtocol;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_provider.version = service_providers[i].iVersion;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_provider.socket_type = service_providers[i].iSocketType;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_provider.socket_protocol = service_providers[i].iProtocol;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_provider.chain_length = service_providers[i].ProtocolChain.ChainLen;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(mmenke): Add categories under Vista and later.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // http://msdn.microsoft.com/en-us/library/ms742239%28v=VS.85%29.aspx
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t path[MAX_PATH];
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int path_length = arraysize(path);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0 == WSCGetProviderPath(&service_providers[i].ProviderId, path,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &path_length, &error)) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_provider.path = path;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_list->push_back(service_provider);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97