4 * Copyright 1999 Ulrich Weigand
5 * Copyright 2004 Juan Lang
6 * Copyright 2007 Maarten Lankhorst
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mpr
);
38 /* Data structures representing network service providers. Assumes only one
39 * thread creates them, and that they are constant for the life of the process
40 * (and therefore doesn't synchronize access).
41 * FIXME: only basic provider data and enumeration-related data are implemented
42 * so far, need to implement the rest too.
44 typedef struct _WNetProvider
52 PF_NPOpenEnum openEnum
;
53 PF_NPEnumResource enumResource
;
54 PF_NPCloseEnum closeEnum
;
55 PF_NPGetResourceInformation getResourceInformation
;
56 } WNetProvider
, *PWNetProvider
;
58 typedef struct _WNetProviderTable
63 WNetProvider table
[1];
64 } WNetProviderTable
, *PWNetProviderTable
;
66 #define WNET_ENUMERATOR_TYPE_NULL 0
67 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
68 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
69 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
71 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
72 * the enumeration; it represents one of the following types:
73 * - a 'null' enumeration, one that contains no members
74 * - a global enumeration, one that's executed across all providers
75 * - a provider-specific enumeration, one that's only executed by a single
77 * - a context enumeration. I know this contradicts what I just said about
78 * there being no correspondence between the scope and the type, but it's
79 * necessary for the special case that a "Entire Network" entry needs to
80 * be enumerated in an enumeration of the context scope. Thus an enumeration
81 * of the context scope results in a context type enumerator, which morphs
82 * into a global enumeration (so the enumeration continues across all
85 typedef struct _WNetEnumerator
95 } WNetEnumerator
, *PWNetEnumerator
;
97 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
99 /* Returns an index (into the global WNetProviderTable) of the provider with
100 * the given name, or BAD_PROVIDER_INDEX if not found.
102 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
);
104 static PWNetProviderTable providerTable
;
107 * Global provider table functions
110 static void _tryLoadProvider(PCWSTR provider
)
112 static const WCHAR servicePrefix
[] = { 'S','y','s','t','e','m','\\',
113 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
114 'S','e','r','v','i','c','e','s','\\',0 };
115 static const WCHAR serviceFmt
[] = { '%','s','%','s','\\',
116 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
117 WCHAR serviceName
[MAX_PATH
];
120 TRACE("%s\n", debugstr_w(provider
));
121 snprintfW(serviceName
, sizeof(serviceName
) / sizeof(WCHAR
), serviceFmt
,
122 servicePrefix
, provider
);
123 serviceName
[sizeof(serviceName
) / sizeof(WCHAR
) - 1] = '\0';
124 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, serviceName
, 0, KEY_READ
, &hKey
) ==
127 static const WCHAR szProviderPath
[] = { 'P','r','o','v','i','d','e','r',
129 WCHAR providerPath
[MAX_PATH
];
130 DWORD type
, size
= sizeof(providerPath
);
132 if (RegQueryValueExW(hKey
, szProviderPath
, NULL
, &type
,
133 (LPBYTE
)providerPath
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
135 static const WCHAR szProviderName
[] = { 'N','a','m','e',0 };
139 RegQueryValueExW(hKey
, szProviderName
, NULL
, NULL
, NULL
, &size
);
142 name
= HeapAlloc(GetProcessHeap(), 0, size
);
143 if (RegQueryValueExW(hKey
, szProviderName
, NULL
, &type
,
144 (LPBYTE
)name
, &size
) != ERROR_SUCCESS
|| type
!= REG_SZ
)
146 HeapFree(GetProcessHeap(), 0, name
);
152 HMODULE hLib
= LoadLibraryW(providerPath
);
156 PF_NPGetCaps getCaps
= (PF_NPGetCaps
)GetProcAddress(hLib
,
159 TRACE("loaded lib %p\n", hLib
);
162 PWNetProvider provider
=
163 &providerTable
->table
[providerTable
->numProviders
];
165 provider
->hLib
= hLib
;
166 provider
->name
= name
;
167 TRACE("name is %s\n", debugstr_w(name
));
168 provider
->getCaps
= getCaps
;
169 provider
->dwSpecVersion
= getCaps(WNNC_SPEC_VERSION
);
170 provider
->dwNetType
= getCaps(WNNC_NET_TYPE
);
171 TRACE("net type is 0x%08x\n", provider
->dwNetType
);
172 provider
->dwEnumScopes
= getCaps(WNNC_ENUMERATION
);
173 if (provider
->dwEnumScopes
)
175 TRACE("supports enumeration\n");
176 provider
->openEnum
= (PF_NPOpenEnum
)
177 GetProcAddress(hLib
, "NPOpenEnum");
178 TRACE("openEnum is %p\n", provider
->openEnum
);
179 provider
->enumResource
= (PF_NPEnumResource
)
180 GetProcAddress(hLib
, "NPEnumResource");
181 TRACE("enumResource is %p\n",
182 provider
->enumResource
);
183 provider
->closeEnum
= (PF_NPCloseEnum
)
184 GetProcAddress(hLib
, "NPCloseEnum");
185 TRACE("closeEnum is %p\n", provider
->closeEnum
);
186 provider
->getResourceInformation
= (PF_NPGetResourceInformation
)
187 GetProcAddress(hLib
, "NPGetResourceInformation");
188 TRACE("getResourceInformation is %p\n",
189 provider
->getResourceInformation
);
190 if (!provider
->openEnum
|| !provider
->enumResource
191 || !provider
->closeEnum
)
193 provider
->openEnum
= NULL
;
194 provider
->enumResource
= NULL
;
195 provider
->closeEnum
= NULL
;
196 provider
->dwEnumScopes
= 0;
197 WARN("Couldn't load enumeration functions\n");
200 providerTable
->numProviders
++;
204 WARN("Provider %s didn't export NPGetCaps\n",
205 debugstr_w(provider
));
206 HeapFree(GetProcessHeap(), 0, name
);
212 WARN("Couldn't load library %s for provider %s\n",
213 debugstr_w(providerPath
), debugstr_w(provider
));
214 HeapFree(GetProcessHeap(), 0, name
);
219 WARN("Couldn't get provider name for provider %s\n",
220 debugstr_w(provider
));
224 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath
));
228 WARN("Couldn't open service key for provider %s\n",
229 debugstr_w(provider
));
232 void wnetInit(HINSTANCE hInstDll
)
234 static const WCHAR providerOrderKey
[] = { 'S','y','s','t','e','m','\\',
235 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
236 'C','o','n','t','r','o','l','\\',
237 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
238 'O','r','d','e','r',0 };
239 static const WCHAR providerOrder
[] = { 'P','r','o','v','i','d','e','r',
240 'O','r','d','e','r',0 };
243 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, providerOrderKey
, 0, KEY_READ
, &hKey
)
248 RegQueryValueExW(hKey
, providerOrder
, NULL
, NULL
, NULL
, &size
);
251 PWSTR providers
= HeapAlloc(GetProcessHeap(), 0, size
);
257 if (RegQueryValueExW(hKey
, providerOrder
, NULL
, &type
,
258 (LPBYTE
)providers
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
263 TRACE("provider order is %s\n", debugstr_w(providers
));
264 /* first count commas as a heuristic for how many to
265 * allocate space for */
266 for (ptr
= providers
, numToAllocate
= 1; ptr
; )
268 ptr
= strchrW(ptr
, ',');
275 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
276 sizeof(WNetProviderTable
)
277 + (numToAllocate
- 1) * sizeof(WNetProvider
));
281 int entireNetworkLen
;
282 LPCWSTR stringresource
;
284 entireNetworkLen
= LoadStringW(hInstDll
,
285 IDS_ENTIRENETWORK
, (LPWSTR
)&stringresource
, 0);
286 providerTable
->entireNetwork
= HeapAlloc(
287 GetProcessHeap(), 0, (entireNetworkLen
+ 1) *
289 if (providerTable
->entireNetwork
)
291 memcpy(providerTable
->entireNetwork
, stringresource
, entireNetworkLen
*sizeof(WCHAR
));
292 providerTable
->entireNetwork
[entireNetworkLen
] = 0;
294 providerTable
->numAllocated
= numToAllocate
;
295 for (ptr
= providers
; ptr
; )
298 ptr
= strchrW(ptr
, ',');
301 _tryLoadProvider(ptrPrev
);
305 HeapFree(GetProcessHeap(), 0, providers
);
318 for (i
= 0; i
< providerTable
->numProviders
; i
++)
320 HeapFree(GetProcessHeap(), 0, providerTable
->table
[i
].name
);
321 FreeModule(providerTable
->table
[i
].hLib
);
323 HeapFree(GetProcessHeap(), 0, providerTable
->entireNetwork
);
324 HeapFree(GetProcessHeap(), 0, providerTable
);
325 providerTable
= NULL
;
329 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
)
331 DWORD ret
= BAD_PROVIDER_INDEX
;
333 if (providerTable
&& providerTable
->numProviders
)
337 for (i
= 0; i
< providerTable
->numProviders
&&
338 ret
== BAD_PROVIDER_INDEX
; i
++)
339 if (!strcmpW(lpProvider
, providerTable
->table
[i
].name
))
349 static LPNETRESOURCEW
_copyNetResourceForEnumW(LPNETRESOURCEW lpNet
)
355 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW
));
361 ret
->lpLocalName
= ret
->lpComment
= ret
->lpProvider
= NULL
;
362 if (lpNet
->lpRemoteName
)
364 len
= strlenW(lpNet
->lpRemoteName
) + 1;
365 ret
->lpRemoteName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
366 if (ret
->lpRemoteName
)
367 strcpyW(ret
->lpRemoteName
, lpNet
->lpRemoteName
);
376 static void _freeEnumNetResource(LPNETRESOURCEW lpNet
)
380 HeapFree(GetProcessHeap(), 0, lpNet
->lpRemoteName
);
381 HeapFree(GetProcessHeap(), 0, lpNet
);
385 static PWNetEnumerator
_createNullEnumerator(void)
387 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
388 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
391 ret
->enumType
= WNET_ENUMERATOR_TYPE_NULL
;
395 static PWNetEnumerator
_createGlobalEnumeratorW(DWORD dwScope
, DWORD dwType
,
396 DWORD dwUsage
, LPNETRESOURCEW lpNet
)
398 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
399 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
403 ret
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
404 ret
->dwScope
= dwScope
;
405 ret
->dwType
= dwType
;
406 ret
->dwUsage
= dwUsage
;
407 ret
->lpNet
= _copyNetResourceForEnumW(lpNet
);
412 static PWNetEnumerator
_createProviderEnumerator(DWORD dwScope
, DWORD dwType
,
413 DWORD dwUsage
, DWORD index
, HANDLE handle
)
417 if (!providerTable
|| index
>= providerTable
->numProviders
)
421 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
424 ret
->enumType
= WNET_ENUMERATOR_TYPE_PROVIDER
;
425 ret
->providerIndex
= index
;
426 ret
->dwScope
= dwScope
;
427 ret
->dwType
= dwType
;
428 ret
->dwUsage
= dwUsage
;
429 ret
->handle
= handle
;
435 static PWNetEnumerator
_createContextEnumerator(DWORD dwScope
, DWORD dwType
,
438 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
439 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
443 ret
->enumType
= WNET_ENUMERATOR_TYPE_CONTEXT
;
444 ret
->dwScope
= dwScope
;
445 ret
->dwType
= dwType
;
446 ret
->dwUsage
= dwUsage
;
451 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
452 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
453 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
454 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
455 * if not all members of the array could be thunked, and something else on
458 static DWORD
_thunkNetResourceArrayWToA(const NETRESOURCEW
*lpNetArrayIn
,
459 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
461 DWORD i
, numToThunk
, totalBytes
, ret
;
465 return WN_BAD_POINTER
;
467 return WN_BAD_POINTER
;
471 return WN_BAD_POINTER
;
473 return WN_BAD_POINTER
;
475 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
477 const NETRESOURCEW
*lpNet
= lpNetArrayIn
+ i
;
479 totalBytes
+= sizeof(NETRESOURCEA
);
480 if (lpNet
->lpLocalName
)
481 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpLocalName
,
482 -1, NULL
, 0, NULL
, NULL
);
483 if (lpNet
->lpRemoteName
)
484 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpRemoteName
,
485 -1, NULL
, 0, NULL
, NULL
);
486 if (lpNet
->lpComment
)
487 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpComment
,
488 -1, NULL
, 0, NULL
, NULL
);
489 if (lpNet
->lpProvider
)
490 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpProvider
,
491 -1, NULL
, 0, NULL
, NULL
);
492 if (totalBytes
< *lpBufferSize
)
495 strNext
= (LPSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEA
));
496 for (i
= 0; i
< numToThunk
; i
++)
498 LPNETRESOURCEA lpNetOut
= (LPNETRESOURCEA
)lpBuffer
+ i
;
499 const NETRESOURCEW
*lpNetIn
= lpNetArrayIn
+ i
;
501 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEA
));
502 /* lie about string lengths, we already verified how many
503 * we have space for above
505 if (lpNetIn
->lpLocalName
)
507 lpNetOut
->lpLocalName
= strNext
;
508 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpLocalName
, -1,
509 lpNetOut
->lpLocalName
, *lpBufferSize
, NULL
, NULL
);
511 if (lpNetIn
->lpRemoteName
)
513 lpNetOut
->lpRemoteName
= strNext
;
514 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpRemoteName
, -1,
515 lpNetOut
->lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
517 if (lpNetIn
->lpComment
)
519 lpNetOut
->lpComment
= strNext
;
520 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpComment
, -1,
521 lpNetOut
->lpComment
, *lpBufferSize
, NULL
, NULL
);
523 if (lpNetIn
->lpProvider
)
525 lpNetOut
->lpProvider
= strNext
;
526 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpProvider
, -1,
527 lpNetOut
->lpProvider
, *lpBufferSize
, NULL
, NULL
);
530 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
531 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
536 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
537 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
538 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
539 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
540 * if not all members of the array could be thunked, and something else on
543 static DWORD
_thunkNetResourceArrayAToW(const NETRESOURCEA
*lpNetArrayIn
,
544 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
546 DWORD i
, numToThunk
, totalBytes
, ret
;
550 return WN_BAD_POINTER
;
552 return WN_BAD_POINTER
;
556 return WN_BAD_POINTER
;
558 return WN_BAD_POINTER
;
560 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
562 const NETRESOURCEA
*lpNet
= lpNetArrayIn
+ i
;
564 totalBytes
+= sizeof(NETRESOURCEW
);
565 if (lpNet
->lpLocalName
)
566 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpLocalName
,
567 -1, NULL
, 0) * sizeof(WCHAR
);
568 if (lpNet
->lpRemoteName
)
569 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpRemoteName
,
570 -1, NULL
, 0) * sizeof(WCHAR
);
571 if (lpNet
->lpComment
)
572 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpComment
,
573 -1, NULL
, 0) * sizeof(WCHAR
);
574 if (lpNet
->lpProvider
)
575 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpProvider
,
576 -1, NULL
, 0) * sizeof(WCHAR
);
577 if (totalBytes
< *lpBufferSize
)
580 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEW
));
581 for (i
= 0; i
< numToThunk
; i
++)
583 LPNETRESOURCEW lpNetOut
= (LPNETRESOURCEW
)lpBuffer
+ i
;
584 const NETRESOURCEA
*lpNetIn
= lpNetArrayIn
+ i
;
586 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEW
));
587 /* lie about string lengths, we already verified how many
588 * we have space for above
590 if (lpNetIn
->lpLocalName
)
592 lpNetOut
->lpLocalName
= strNext
;
593 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpLocalName
,
594 -1, lpNetOut
->lpLocalName
, *lpBufferSize
);
596 if (lpNetIn
->lpRemoteName
)
598 lpNetOut
->lpRemoteName
= strNext
;
599 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpRemoteName
,
600 -1, lpNetOut
->lpRemoteName
, *lpBufferSize
);
602 if (lpNetIn
->lpComment
)
604 lpNetOut
->lpComment
= strNext
;
605 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpComment
,
606 -1, lpNetOut
->lpComment
, *lpBufferSize
);
608 if (lpNetIn
->lpProvider
)
610 lpNetOut
->lpProvider
= strNext
;
611 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpProvider
,
612 -1, lpNetOut
->lpProvider
, *lpBufferSize
);
615 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
616 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
621 /*********************************************************************
622 * WNetOpenEnumA [MPR.@]
624 * See comments for WNetOpenEnumW.
626 DWORD WINAPI
WNetOpenEnumA( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
627 LPNETRESOURCEA lpNet
, LPHANDLE lphEnum
)
631 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
632 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
635 ret
= WN_BAD_POINTER
;
636 else if (!providerTable
|| providerTable
->numProviders
== 0)
642 LPNETRESOURCEW lpNetWide
= NULL
;
644 DWORD size
= sizeof(buf
), count
= 1;
645 BOOL allocated
= FALSE
;
647 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, buf
, &size
);
648 if (ret
== WN_MORE_DATA
)
650 lpNetWide
= HeapAlloc(GetProcessHeap(), 0,
654 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, lpNetWide
,
659 ret
= WN_OUT_OF_MEMORY
;
661 else if (ret
== WN_SUCCESS
)
662 lpNetWide
= (LPNETRESOURCEW
)buf
;
663 if (ret
== WN_SUCCESS
)
664 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, lpNetWide
,
667 HeapFree(GetProcessHeap(), 0, lpNetWide
);
670 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, NULL
, lphEnum
);
674 TRACE("Returning %d\n", ret
);
678 /*********************************************************************
679 * WNetOpenEnumW [MPR.@]
681 * Network enumeration has way too many parameters, so I'm not positive I got
682 * them right. What I've got so far:
684 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
685 * all the network providers should be enumerated.
687 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
688 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
689 * lpProvider is set, all the network providers should be enumerated.
690 * (This means the enumeration is a list of network providers, not that the
691 * enumeration is passed on to the providers.)
693 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
694 * resource matches the "Entire Network" resource (no remote name, no
695 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
696 * enumeration is done on every network provider.
698 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
699 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
700 * only to the given network provider.
702 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
703 * no lpProvider is set, enumeration will be tried on every network provider,
704 * in the order in which they're loaded.
706 * - The LPNETRESOURCE should be disregarded for scopes besides
707 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
708 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
710 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
711 * resource in the enumerated list, as well as any machines in your
712 * workgroup. The machines in your workgroup come from doing a
713 * RESOURCE_CONTEXT enumeration of every Network Provider.
715 DWORD WINAPI
WNetOpenEnumW( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
716 LPNETRESOURCEW lpNet
, LPHANDLE lphEnum
)
720 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
721 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
724 ret
= WN_BAD_POINTER
;
725 else if (!providerTable
|| providerTable
->numProviders
== 0)
731 case RESOURCE_GLOBALNET
:
734 if (lpNet
->lpProvider
)
736 DWORD index
= _findProviderIndexW(lpNet
->lpProvider
);
738 if (index
!= BAD_PROVIDER_INDEX
)
740 if (providerTable
->table
[index
].openEnum
&&
741 providerTable
->table
[index
].dwEnumScopes
& WNNC_ENUM_GLOBAL
)
745 ret
= providerTable
->table
[index
].openEnum(
746 dwScope
, dwType
, dwUsage
, lpNet
, &handle
);
747 if (ret
== WN_SUCCESS
)
750 (HANDLE
)_createProviderEnumerator(
751 dwScope
, dwType
, dwUsage
, index
, handle
);
752 ret
= *lphEnum
? WN_SUCCESS
:
757 ret
= WN_NOT_SUPPORTED
;
760 ret
= WN_BAD_PROVIDER
;
762 else if (lpNet
->lpRemoteName
)
764 *lphEnum
= (HANDLE
)_createGlobalEnumeratorW(dwScope
,
765 dwType
, dwUsage
, lpNet
);
766 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
770 if (lpNet
->lpComment
&& !strcmpW(lpNet
->lpComment
,
771 providerTable
->entireNetwork
))
773 /* comment matches the "Entire Network", enumerate
774 * global scope of every provider
776 *lphEnum
= (HANDLE
)_createGlobalEnumeratorW(dwScope
,
777 dwType
, dwUsage
, lpNet
);
781 /* this is the same as not having passed lpNet */
782 *lphEnum
= (HANDLE
)_createGlobalEnumeratorW(dwScope
,
783 dwType
, dwUsage
, NULL
);
785 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
790 *lphEnum
= (HANDLE
)_createGlobalEnumeratorW(dwScope
, dwType
,
792 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
795 case RESOURCE_CONTEXT
:
796 *lphEnum
= (HANDLE
)_createContextEnumerator(dwScope
, dwType
,
798 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
800 case RESOURCE_REMEMBERED
:
801 case RESOURCE_CONNECTED
:
802 *lphEnum
= (HANDLE
)_createNullEnumerator();
803 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
806 WARN("unknown scope 0x%08x\n", dwScope
);
812 TRACE("Returning %d\n", ret
);
816 /*********************************************************************
817 * WNetEnumResourceA [MPR.@]
819 DWORD WINAPI
WNetEnumResourceA( HANDLE hEnum
, LPDWORD lpcCount
,
820 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
824 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
827 ret
= WN_BAD_POINTER
;
829 ret
= WN_BAD_POINTER
;
831 ret
= WN_BAD_POINTER
;
832 else if (!lpBufferSize
)
833 ret
= WN_BAD_POINTER
;
834 else if (*lpBufferSize
< sizeof(NETRESOURCEA
))
836 *lpBufferSize
= sizeof(NETRESOURCEA
);
841 DWORD localCount
= *lpcCount
, localSize
= *lpBufferSize
;
842 LPVOID localBuffer
= HeapAlloc(GetProcessHeap(), 0, localSize
);
846 ret
= WNetEnumResourceW(hEnum
, &localCount
, localBuffer
,
848 if (ret
== WN_SUCCESS
|| (ret
== WN_MORE_DATA
&& localCount
!= -1))
850 /* FIXME: this isn't necessarily going to work in the case of
851 * WN_MORE_DATA, because our enumerator may have moved on to
852 * the next provider. MSDN states that a large (16KB) buffer
853 * size is the appropriate usage of this function, so
854 * hopefully it won't be an issue.
856 ret
= _thunkNetResourceArrayWToA((LPNETRESOURCEW
)localBuffer
,
857 &localCount
, lpBuffer
, lpBufferSize
);
858 *lpcCount
= localCount
;
860 HeapFree(GetProcessHeap(), 0, localBuffer
);
863 ret
= WN_OUT_OF_MEMORY
;
867 TRACE("Returning %d\n", ret
);
871 static DWORD
_countProviderBytesW(PWNetProvider provider
)
877 ret
= sizeof(NETRESOURCEW
);
878 ret
+= 2 * (strlenW(provider
->name
) + 1) * sizeof(WCHAR
);
885 static DWORD
_enumerateProvidersW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
886 LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
891 return WN_BAD_POINTER
;
892 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
895 return WN_BAD_POINTER
;
897 return WN_BAD_POINTER
;
899 return WN_BAD_POINTER
;
900 if (*lpBufferSize
< sizeof(NETRESOURCEA
))
903 if (!providerTable
|| enumerator
->providerIndex
>=
904 providerTable
->numProviders
)
905 ret
= WN_NO_MORE_ENTRIES
;
908 DWORD bytes
= 0, count
= 0, countLimit
, i
;
909 LPNETRESOURCEW resource
;
912 countLimit
= *lpcCount
== -1 ?
913 providerTable
->numProviders
- enumerator
->providerIndex
: *lpcCount
;
914 while (count
< countLimit
&& bytes
< *lpBufferSize
)
916 DWORD bytesNext
= _countProviderBytesW(
917 &providerTable
->table
[count
+ enumerator
->providerIndex
]);
919 if (bytes
+ bytesNext
< *lpBufferSize
)
925 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ count
* sizeof(NETRESOURCEW
));
926 for (i
= 0, resource
= (LPNETRESOURCEW
)lpBuffer
; i
< count
;
929 resource
->dwScope
= RESOURCE_GLOBALNET
;
930 resource
->dwType
= RESOURCETYPE_ANY
;
931 resource
->dwDisplayType
= RESOURCEDISPLAYTYPE_NETWORK
;
932 resource
->dwUsage
= RESOURCEUSAGE_CONTAINER
|
933 RESOURCEUSAGE_RESERVED
;
934 resource
->lpLocalName
= NULL
;
935 resource
->lpRemoteName
= strNext
;
936 strcpyW(resource
->lpRemoteName
,
937 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
938 strNext
+= strlenW(resource
->lpRemoteName
) + 1;
939 resource
->lpComment
= NULL
;
940 resource
->lpProvider
= strNext
;
941 strcpyW(resource
->lpProvider
,
942 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
943 strNext
+= strlenW(resource
->lpProvider
) + 1;
945 enumerator
->providerIndex
+= count
;
947 ret
= count
> 0 ? WN_SUCCESS
: WN_MORE_DATA
;
949 TRACE("Returning %d\n", ret
);
953 /* Advances the enumerator (assumed to be a global enumerator) to the next
954 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
955 * not open a handle with the next provider.
956 * If the existing handle is NULL, may leave the enumerator unchanged, since
957 * the current provider may support the desired scope.
958 * If the existing handle is not NULL, closes it before moving on.
959 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
960 * provider, and another error on failure.
962 static DWORD
_globalEnumeratorAdvance(PWNetEnumerator enumerator
)
965 return WN_BAD_POINTER
;
966 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
968 if (!providerTable
|| enumerator
->providerIndex
>=
969 providerTable
->numProviders
)
970 return WN_NO_MORE_ENTRIES
;
972 if (enumerator
->providerDone
)
975 enumerator
->providerDone
= FALSE
;
976 if (enumerator
->handle
)
978 providerTable
->table
[enumerator
->providerIndex
].closeEnum(
980 enumerator
->handle
= NULL
;
981 enumerator
->providerIndex
++;
983 if (enumerator
->dwScope
== RESOURCE_CONNECTED
)
984 dwEnum
= WNNC_ENUM_LOCAL
;
985 else if (enumerator
->dwScope
== RESOURCE_GLOBALNET
)
986 dwEnum
= WNNC_ENUM_GLOBAL
;
987 else if (enumerator
->dwScope
== RESOURCE_CONTEXT
)
988 dwEnum
= WNNC_ENUM_CONTEXT
;
989 for (; enumerator
->providerIndex
< providerTable
->numProviders
&&
990 !(providerTable
->table
[enumerator
->providerIndex
].dwEnumScopes
991 & dwEnum
); enumerator
->providerIndex
++)
994 return enumerator
->providerIndex
< providerTable
->numProviders
?
995 WN_SUCCESS
: WN_NO_MORE_ENTRIES
;
998 /* "Passes through" call to the next provider that supports the enumeration
1000 * FIXME: if one call to a provider's enumerator succeeds while there's still
1001 * space in lpBuffer, I don't call to the next provider. The caller may not
1002 * expect that it should call EnumResourceW again with a return value of
1003 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1004 * may have to be moved around a bit, ick.
1006 static DWORD
_enumerateGlobalPassthroughW(PWNetEnumerator enumerator
,
1007 LPDWORD lpcCount
, LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1012 return WN_BAD_POINTER
;
1013 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1014 return WN_BAD_VALUE
;
1016 return WN_BAD_POINTER
;
1018 return WN_BAD_POINTER
;
1020 return WN_BAD_POINTER
;
1021 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1022 return WN_MORE_DATA
;
1024 ret
= _globalEnumeratorAdvance(enumerator
);
1025 if (ret
== WN_SUCCESS
)
1027 ret
= providerTable
->table
[enumerator
->providerIndex
].
1028 openEnum(enumerator
->dwScope
, enumerator
->dwType
,
1029 enumerator
->dwUsage
, enumerator
->lpNet
,
1030 &enumerator
->handle
);
1031 if (ret
== WN_SUCCESS
)
1033 ret
= providerTable
->table
[enumerator
->providerIndex
].
1034 enumResource(enumerator
->handle
, lpcCount
, lpBuffer
,
1036 if (ret
!= WN_MORE_DATA
)
1037 enumerator
->providerDone
= TRUE
;
1040 TRACE("Returning %d\n", ret
);
1044 static DWORD
_enumerateGlobalW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1045 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1050 return WN_BAD_POINTER
;
1051 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1052 return WN_BAD_VALUE
;
1054 return WN_BAD_POINTER
;
1056 return WN_BAD_POINTER
;
1058 return WN_BAD_POINTER
;
1059 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1060 return WN_MORE_DATA
;
1062 return WN_NO_NETWORK
;
1064 switch (enumerator
->dwScope
)
1066 case RESOURCE_GLOBALNET
:
1067 if (enumerator
->lpNet
)
1068 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
,
1069 lpBuffer
, lpBufferSize
);
1071 ret
= _enumerateProvidersW(enumerator
, lpcCount
, lpBuffer
,
1074 case RESOURCE_CONTEXT
:
1075 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
, lpBuffer
,
1079 WARN("unexpected scope 0x%08x\n", enumerator
->dwScope
);
1080 ret
= WN_NO_MORE_ENTRIES
;
1082 TRACE("Returning %d\n", ret
);
1086 static DWORD
_enumerateProviderW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1087 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1090 return WN_BAD_POINTER
;
1091 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_PROVIDER
)
1092 return WN_BAD_VALUE
;
1093 if (!enumerator
->handle
)
1094 return WN_BAD_VALUE
;
1096 return WN_BAD_POINTER
;
1098 return WN_BAD_POINTER
;
1100 return WN_BAD_POINTER
;
1102 return WN_NO_NETWORK
;
1103 if (enumerator
->providerIndex
>= providerTable
->numProviders
)
1104 return WN_NO_MORE_ENTRIES
;
1105 if (!providerTable
->table
[enumerator
->providerIndex
].enumResource
)
1106 return WN_BAD_VALUE
;
1107 return providerTable
->table
[enumerator
->providerIndex
].enumResource(
1108 enumerator
->handle
, lpcCount
, lpBuffer
, lpBufferSize
);
1111 static DWORD
_enumerateContextW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1112 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1115 size_t cchEntireNetworkLen
, bytesNeeded
;
1118 return WN_BAD_POINTER
;
1119 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_CONTEXT
)
1120 return WN_BAD_VALUE
;
1122 return WN_BAD_POINTER
;
1124 return WN_BAD_POINTER
;
1126 return WN_BAD_POINTER
;
1128 return WN_NO_NETWORK
;
1130 cchEntireNetworkLen
= strlenW(providerTable
->entireNetwork
) + 1;
1131 bytesNeeded
= sizeof(NETRESOURCEW
) + cchEntireNetworkLen
* sizeof(WCHAR
);
1132 if (*lpBufferSize
< bytesNeeded
)
1134 *lpBufferSize
= bytesNeeded
;
1139 LPNETRESOURCEW lpNet
= (LPNETRESOURCEW
)lpBuffer
;
1141 lpNet
->dwScope
= RESOURCE_GLOBALNET
;
1142 lpNet
->dwType
= enumerator
->dwType
;
1143 lpNet
->dwDisplayType
= RESOURCEDISPLAYTYPE_ROOT
;
1144 lpNet
->dwUsage
= RESOURCEUSAGE_CONTAINER
;
1145 lpNet
->lpLocalName
= NULL
;
1146 lpNet
->lpRemoteName
= NULL
;
1147 lpNet
->lpProvider
= NULL
;
1148 /* odd, but correct: put comment at end of buffer, so it won't get
1149 * overwritten by subsequent calls to a provider's enumResource
1151 lpNet
->lpComment
= (LPWSTR
)((LPBYTE
)lpBuffer
+ *lpBufferSize
-
1152 (cchEntireNetworkLen
* sizeof(WCHAR
)));
1153 strcpyW(lpNet
->lpComment
, providerTable
->entireNetwork
);
1156 if (ret
== WN_SUCCESS
)
1158 DWORD bufferSize
= *lpBufferSize
- bytesNeeded
;
1160 /* "Entire Network" entry enumerated--morph this into a global
1161 * enumerator. enumerator->lpNet continues to be NULL, since it has
1162 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1164 enumerator
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
1165 ret
= _enumerateGlobalW(enumerator
, lpcCount
,
1166 (LPBYTE
)lpBuffer
+ bytesNeeded
, &bufferSize
);
1167 if (ret
== WN_SUCCESS
)
1169 /* reflect the fact that we already enumerated "Entire Network" */
1171 *lpBufferSize
= bufferSize
+ bytesNeeded
;
1175 /* the provider enumeration failed, but we already succeeded in
1176 * enumerating "Entire Network"--leave type as global to allow a
1177 * retry, but indicate success with a count of one.
1181 *lpBufferSize
= bytesNeeded
;
1184 TRACE("Returning %d\n", ret
);
1188 /*********************************************************************
1189 * WNetEnumResourceW [MPR.@]
1191 DWORD WINAPI
WNetEnumResourceW( HANDLE hEnum
, LPDWORD lpcCount
,
1192 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1196 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
1199 ret
= WN_BAD_POINTER
;
1201 ret
= WN_BAD_POINTER
;
1203 ret
= WN_BAD_POINTER
;
1204 else if (!lpBufferSize
)
1205 ret
= WN_BAD_POINTER
;
1206 else if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1208 *lpBufferSize
= sizeof(NETRESOURCEW
);
1213 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1215 switch (enumerator
->enumType
)
1217 case WNET_ENUMERATOR_TYPE_NULL
:
1218 ret
= WN_NO_MORE_ENTRIES
;
1220 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1221 ret
= _enumerateGlobalW(enumerator
, lpcCount
, lpBuffer
,
1224 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1225 ret
= _enumerateProviderW(enumerator
, lpcCount
, lpBuffer
,
1228 case WNET_ENUMERATOR_TYPE_CONTEXT
:
1229 ret
= _enumerateContextW(enumerator
, lpcCount
, lpBuffer
,
1233 WARN("bogus enumerator type!\n");
1234 ret
= WN_NO_NETWORK
;
1239 TRACE("Returning %d\n", ret
);
1243 /*********************************************************************
1244 * WNetCloseEnum [MPR.@]
1246 DWORD WINAPI
WNetCloseEnum( HANDLE hEnum
)
1250 TRACE( "(%p)\n", hEnum
);
1254 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1256 switch (enumerator
->enumType
)
1258 case WNET_ENUMERATOR_TYPE_NULL
:
1261 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1262 if (enumerator
->lpNet
)
1263 _freeEnumNetResource(enumerator
->lpNet
);
1264 if (enumerator
->handle
)
1265 providerTable
->table
[enumerator
->providerIndex
].
1266 closeEnum(enumerator
->handle
);
1269 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1270 if (enumerator
->handle
)
1271 providerTable
->table
[enumerator
->providerIndex
].
1272 closeEnum(enumerator
->handle
);
1276 WARN("bogus enumerator type!\n");
1277 ret
= WN_BAD_HANDLE
;
1279 HeapFree(GetProcessHeap(), 0, hEnum
);
1282 ret
= WN_BAD_HANDLE
;
1285 TRACE("Returning %d\n", ret
);
1289 /*********************************************************************
1290 * WNetGetResourceInformationA [MPR.@]
1292 * See WNetGetResourceInformationW
1294 DWORD WINAPI
WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource
,
1295 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1300 TRACE( "(%p, %p, %p, %p)\n",
1301 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1303 if (!providerTable
|| providerTable
->numProviders
== 0)
1304 ret
= WN_NO_NETWORK
;
1305 else if (lpNetResource
)
1307 LPNETRESOURCEW lpNetResourceW
= NULL
;
1308 DWORD size
= 1024, count
= 1;
1311 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1312 ret
= _thunkNetResourceArrayAToW(lpNetResource
, &count
, lpNetResourceW
, &size
);
1313 if (ret
== WN_MORE_DATA
)
1315 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1316 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1318 ret
= _thunkNetResourceArrayAToW(lpNetResource
,
1319 &count
, lpNetResourceW
, &size
);
1321 ret
= WN_OUT_OF_MEMORY
;
1323 if (ret
== WN_SUCCESS
)
1325 LPWSTR lpSystemW
= NULL
;
1328 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1331 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1332 lpBufferW
, &size
, &lpSystemW
);
1333 if (ret
== WN_MORE_DATA
)
1335 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1336 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1338 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1339 lpBufferW
, &size
, &lpSystemW
);
1341 ret
= WN_OUT_OF_MEMORY
;
1343 if (ret
== WN_SUCCESS
)
1345 ret
= _thunkNetResourceArrayWToA(lpBufferW
,
1346 &count
, lpBuffer
, cbBuffer
);
1347 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1348 lpNetResourceW
= lpBufferW
;
1349 size
= sizeof(NETRESOURCEA
);
1350 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpRemoteName
,
1351 -1, NULL
, 0, NULL
, NULL
);
1352 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpProvider
,
1353 -1, NULL
, 0, NULL
, NULL
);
1355 len
= WideCharToMultiByte(CP_ACP
, 0, lpSystemW
,
1356 -1, NULL
, 0, NULL
, NULL
);
1357 if ((len
) && ( size
+ len
< *cbBuffer
))
1359 *lplpSystem
= (char*)lpBuffer
+ *cbBuffer
- len
;
1360 WideCharToMultiByte(CP_ACP
, 0, lpSystemW
, -1,
1361 *lplpSystem
, len
, NULL
, NULL
);
1368 ret
= WN_OUT_OF_MEMORY
;
1369 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1372 ret
= WN_OUT_OF_MEMORY
;
1373 HeapFree(GetProcessHeap(), 0, lpSystemW
);
1375 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1378 ret
= WN_NO_NETWORK
;
1382 TRACE("Returning %d\n", ret
);
1386 /*********************************************************************
1387 * WNetGetResourceInformationW [MPR.@]
1389 * WNetGetResourceInformationW function identifies the network provider
1390 * that owns the resource and gets information about the type of the resource.
1393 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1394 * defines a network resource.
1395 * lpBuffer [ O] the pointer to buffer, containing result. It
1396 * contains NETRESOURCEW structure and strings to
1397 * which the members of the NETRESOURCEW structure
1399 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1401 * lplpSystem [ O] the pointer to string in the output buffer,
1402 * containing the part of the resource name without
1403 * names of the server and share.
1406 * NO_ERROR if the function succeeds. System error code if the function fails.
1409 DWORD WINAPI
WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource
,
1410 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1411 LPWSTR
*lplpSystem
)
1413 DWORD ret
= WN_NO_NETWORK
;
1416 TRACE( "(%p, %p, %p, %p)\n",
1417 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1420 ret
= WN_OUT_OF_MEMORY
;
1423 /* FIXME: For function value of a variable is indifferent, it does
1424 * search of all providers in a network.
1426 for (index
= 0; index
< providerTable
->numProviders
; index
++)
1428 if(providerTable
->table
[index
].getCaps(WNNC_DIALOG
) &
1429 WNNC_DLG_GETRESOURCEINFORMATION
)
1431 if (providerTable
->table
[index
].getResourceInformation
)
1432 ret
= providerTable
->table
[index
].getResourceInformation(
1433 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1435 ret
= WN_NO_NETWORK
;
1436 if (ret
== WN_SUCCESS
)
1446 /*********************************************************************
1447 * WNetGetResourceParentA [MPR.@]
1449 DWORD WINAPI
WNetGetResourceParentA( LPNETRESOURCEA lpNetResource
,
1450 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1452 FIXME( "(%p, %p, %p): stub\n",
1453 lpNetResource
, lpBuffer
, lpBufferSize
);
1455 SetLastError(WN_NO_NETWORK
);
1456 return WN_NO_NETWORK
;
1459 /*********************************************************************
1460 * WNetGetResourceParentW [MPR.@]
1462 DWORD WINAPI
WNetGetResourceParentW( LPNETRESOURCEW lpNetResource
,
1463 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1465 FIXME( "(%p, %p, %p): stub\n",
1466 lpNetResource
, lpBuffer
, lpBufferSize
);
1468 SetLastError(WN_NO_NETWORK
);
1469 return WN_NO_NETWORK
;
1475 * Connection Functions
1478 /*********************************************************************
1479 * WNetAddConnectionA [MPR.@]
1481 DWORD WINAPI
WNetAddConnectionA( LPCSTR lpRemoteName
, LPCSTR lpPassword
,
1482 LPCSTR lpLocalName
)
1484 FIXME( "(%s, %p, %s): stub\n",
1485 debugstr_a(lpRemoteName
), lpPassword
, debugstr_a(lpLocalName
) );
1487 SetLastError(WN_NO_NETWORK
);
1488 return WN_NO_NETWORK
;
1491 /*********************************************************************
1492 * WNetAddConnectionW [MPR.@]
1494 DWORD WINAPI
WNetAddConnectionW( LPCWSTR lpRemoteName
, LPCWSTR lpPassword
,
1495 LPCWSTR lpLocalName
)
1497 FIXME( "(%s, %p, %s): stub\n",
1498 debugstr_w(lpRemoteName
), lpPassword
, debugstr_w(lpLocalName
) );
1500 SetLastError(WN_NO_NETWORK
);
1501 return WN_NO_NETWORK
;
1504 /*********************************************************************
1505 * WNetAddConnection2A [MPR.@]
1507 DWORD WINAPI
WNetAddConnection2A( LPNETRESOURCEA lpNetResource
,
1508 LPCSTR lpPassword
, LPCSTR lpUserID
,
1511 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1512 lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
);
1514 SetLastError(WN_NO_NETWORK
);
1515 return WN_NO_NETWORK
;
1518 /*********************************************************************
1519 * WNetAddConnection2W [MPR.@]
1521 DWORD WINAPI
WNetAddConnection2W( LPNETRESOURCEW lpNetResource
,
1522 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1525 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1526 lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
);
1528 SetLastError(WN_NO_NETWORK
);
1529 return WN_NO_NETWORK
;
1532 /*********************************************************************
1533 * WNetAddConnection3A [MPR.@]
1535 DWORD WINAPI
WNetAddConnection3A( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1536 LPCSTR lpPassword
, LPCSTR lpUserID
,
1539 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1540 hwndOwner
, lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
);
1542 SetLastError(WN_NO_NETWORK
);
1543 return WN_NO_NETWORK
;
1546 /*********************************************************************
1547 * WNetAddConnection3W [MPR.@]
1549 DWORD WINAPI
WNetAddConnection3W( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1550 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1553 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1554 hwndOwner
, lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
);
1556 SetLastError(WN_NO_NETWORK
);
1557 return WN_NO_NETWORK
;
1560 /*****************************************************************
1561 * WNetUseConnectionA [MPR.@]
1563 DWORD WINAPI
WNetUseConnectionA( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1564 LPCSTR lpPassword
, LPCSTR lpUserID
, DWORD dwFlags
,
1565 LPSTR lpAccessName
, LPDWORD lpBufferSize
,
1568 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1569 hwndOwner
, lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
,
1570 debugstr_a(lpAccessName
), lpBufferSize
, lpResult
);
1572 SetLastError(WN_NO_NETWORK
);
1573 return WN_NO_NETWORK
;
1576 /*****************************************************************
1577 * WNetUseConnectionW [MPR.@]
1579 DWORD WINAPI
WNetUseConnectionW( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1580 LPCWSTR lpPassword
, LPCWSTR lpUserID
, DWORD dwFlags
,
1581 LPWSTR lpAccessName
, LPDWORD lpBufferSize
,
1584 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1585 hwndOwner
, lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
,
1586 debugstr_w(lpAccessName
), lpBufferSize
, lpResult
);
1588 SetLastError(WN_NO_NETWORK
);
1589 return WN_NO_NETWORK
;
1592 /*********************************************************************
1593 * WNetCancelConnectionA [MPR.@]
1595 DWORD WINAPI
WNetCancelConnectionA( LPCSTR lpName
, BOOL fForce
)
1597 FIXME( "(%s, %d), stub\n", debugstr_a(lpName
), fForce
);
1602 /*********************************************************************
1603 * WNetCancelConnectionW [MPR.@]
1605 DWORD WINAPI
WNetCancelConnectionW( LPCWSTR lpName
, BOOL fForce
)
1607 FIXME( "(%s, %d), stub\n", debugstr_w(lpName
), fForce
);
1612 /*********************************************************************
1613 * WNetCancelConnection2A [MPR.@]
1615 DWORD WINAPI
WNetCancelConnection2A( LPCSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1617 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName
), dwFlags
, fForce
);
1622 /*********************************************************************
1623 * WNetCancelConnection2W [MPR.@]
1625 DWORD WINAPI
WNetCancelConnection2W( LPCWSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1627 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName
), dwFlags
, fForce
);
1632 /*****************************************************************
1633 * WNetRestoreConnectionA [MPR.@]
1635 DWORD WINAPI
WNetRestoreConnectionA( HWND hwndOwner
, LPCSTR lpszDevice
)
1637 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_a(lpszDevice
) );
1639 SetLastError(WN_NO_NETWORK
);
1640 return WN_NO_NETWORK
;
1643 /*****************************************************************
1644 * WNetRestoreConnectionW [MPR.@]
1646 DWORD WINAPI
WNetRestoreConnectionW( HWND hwndOwner
, LPCWSTR lpszDevice
)
1648 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_w(lpszDevice
) );
1650 SetLastError(WN_NO_NETWORK
);
1651 return WN_NO_NETWORK
;
1654 /**************************************************************************
1655 * WNetGetConnectionA [MPR.@]
1658 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1659 * - WN_NOT_CONNECTED drive is a local drive
1660 * - WN_MORE_DATA buffer isn't big enough
1661 * - WN_SUCCESS success (net path in buffer)
1663 * FIXME: need to test return values under different errors
1665 DWORD WINAPI
WNetGetConnectionA( LPCSTR lpLocalName
,
1666 LPSTR lpRemoteName
, LPDWORD lpBufferSize
)
1671 ret
= WN_BAD_POINTER
;
1672 else if (!lpBufferSize
)
1673 ret
= WN_BAD_POINTER
;
1674 else if (!lpRemoteName
&& *lpBufferSize
)
1675 ret
= WN_BAD_POINTER
;
1678 int len
= MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, NULL
, 0);
1682 PWSTR wideLocalName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1686 WCHAR wideRemoteStatic
[MAX_PATH
];
1687 DWORD wideRemoteSize
= sizeof(wideRemoteStatic
) / sizeof(WCHAR
);
1689 MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, wideLocalName
, len
);
1691 /* try once without memory allocation */
1692 ret
= WNetGetConnectionW(wideLocalName
, wideRemoteStatic
,
1694 if (ret
== WN_SUCCESS
)
1696 int len
= WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1697 -1, NULL
, 0, NULL
, NULL
);
1699 if (len
<= *lpBufferSize
)
1701 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
, -1,
1702 lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1707 *lpBufferSize
= len
;
1711 else if (ret
== WN_MORE_DATA
)
1713 PWSTR wideRemote
= HeapAlloc(GetProcessHeap(), 0,
1714 wideRemoteSize
* sizeof(WCHAR
));
1718 ret
= WNetGetConnectionW(wideLocalName
, wideRemote
,
1720 if (ret
== WN_SUCCESS
)
1722 if (len
<= *lpBufferSize
)
1724 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1725 -1, lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1730 *lpBufferSize
= len
;
1734 HeapFree(GetProcessHeap(), 0, wideRemote
);
1737 ret
= WN_OUT_OF_MEMORY
;
1739 HeapFree(GetProcessHeap(), 0, wideLocalName
);
1742 ret
= WN_OUT_OF_MEMORY
;
1745 ret
= WN_BAD_LOCALNAME
;
1749 TRACE("Returning %d\n", ret
);
1753 /**************************************************************************
1754 * WNetGetConnectionW [MPR.@]
1756 * FIXME: need to test return values under different errors
1758 DWORD WINAPI
WNetGetConnectionW( LPCWSTR lpLocalName
,
1759 LPWSTR lpRemoteName
, LPDWORD lpBufferSize
)
1763 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName
), lpRemoteName
,
1767 ret
= WN_BAD_POINTER
;
1768 else if (!lpBufferSize
)
1769 ret
= WN_BAD_POINTER
;
1770 else if (!lpRemoteName
&& *lpBufferSize
)
1771 ret
= WN_BAD_POINTER
;
1772 else if (!lpLocalName
[0])
1773 ret
= WN_BAD_LOCALNAME
;
1776 if (lpLocalName
[1] == ':')
1778 switch(GetDriveTypeW(lpLocalName
))
1782 static const WCHAR unc
[] = { 'u','n','c','\\' };
1783 WCHAR rremote
[MAX_PATH
], *remote
= rremote
;
1784 if (!QueryDosDeviceW( lpLocalName
, remote
, MAX_PATH
)) remote
[0] = 0;
1785 else if (!strncmpW(remote
, unc
, 4))
1790 else if (remote
[0] != '\\' || remote
[1] != '\\')
1791 FIXME("Don't know how to convert %s to an unc\n", debugstr_w(remote
));
1793 if (strlenW(remote
) + 1 > *lpBufferSize
)
1795 *lpBufferSize
= strlenW(remote
) + 1;
1800 strcpyW( lpRemoteName
, remote
);
1801 *lpBufferSize
= strlenW(lpRemoteName
) + 1;
1806 case DRIVE_REMOVABLE
:
1809 TRACE("file is local\n");
1810 ret
= WN_NOT_CONNECTED
;
1813 ret
= WN_BAD_LOCALNAME
;
1817 ret
= WN_BAD_LOCALNAME
;
1821 TRACE("Returning %d\n", ret
);
1825 /**************************************************************************
1826 * WNetSetConnectionA [MPR.@]
1828 DWORD WINAPI
WNetSetConnectionA( LPCSTR lpName
, DWORD dwProperty
,
1831 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName
), dwProperty
, pvValue
);
1833 SetLastError(WN_NO_NETWORK
);
1834 return WN_NO_NETWORK
;
1837 /**************************************************************************
1838 * WNetSetConnectionW [MPR.@]
1840 DWORD WINAPI
WNetSetConnectionW( LPCWSTR lpName
, DWORD dwProperty
,
1843 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName
), dwProperty
, pvValue
);
1845 SetLastError(WN_NO_NETWORK
);
1846 return WN_NO_NETWORK
;
1849 /*****************************************************************
1850 * WNetGetUniversalNameA [MPR.@]
1852 DWORD WINAPI
WNetGetUniversalNameA ( LPCSTR lpLocalPath
, DWORD dwInfoLevel
,
1853 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1857 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1858 debugstr_a(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1860 switch (dwInfoLevel
)
1862 case UNIVERSAL_NAME_INFO_LEVEL
:
1864 LPUNIVERSAL_NAME_INFOA info
= (LPUNIVERSAL_NAME_INFOA
)lpBuffer
;
1866 size
= sizeof(*info
) + lstrlenA(lpLocalPath
) + 1;
1867 if (*lpBufferSize
< size
)
1872 info
->lpUniversalName
= (char *)info
+ sizeof(*info
);
1873 lstrcpyA(info
->lpUniversalName
, lpLocalPath
);
1874 *lpBufferSize
= size
;
1878 case REMOTE_NAME_INFO_LEVEL
:
1879 err
= WN_NO_NETWORK
;
1891 /*****************************************************************
1892 * WNetGetUniversalNameW [MPR.@]
1894 DWORD WINAPI
WNetGetUniversalNameW ( LPCWSTR lpLocalPath
, DWORD dwInfoLevel
,
1895 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1899 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1900 debugstr_w(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1902 switch (dwInfoLevel
)
1904 case UNIVERSAL_NAME_INFO_LEVEL
:
1906 LPUNIVERSAL_NAME_INFOW info
= (LPUNIVERSAL_NAME_INFOW
)lpBuffer
;
1908 size
= sizeof(*info
) + (lstrlenW(lpLocalPath
) + 1) * sizeof(WCHAR
);
1909 if (*lpBufferSize
< size
)
1914 info
->lpUniversalName
= (LPWSTR
)((char *)info
+ sizeof(*info
));
1915 lstrcpyW(info
->lpUniversalName
, lpLocalPath
);
1916 *lpBufferSize
= size
;
1920 case REMOTE_NAME_INFO_LEVEL
:
1921 err
= WN_NO_NETWORK
;
1939 /**************************************************************************
1940 * WNetGetUserA [MPR.@]
1942 * FIXME: we should not return ourselves, but the owner of the drive lpName
1944 DWORD WINAPI
WNetGetUserA( LPCSTR lpName
, LPSTR lpUserID
, LPDWORD lpBufferSize
)
1946 if (GetUserNameA( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1947 return GetLastError();
1950 /*****************************************************************
1951 * WNetGetUserW [MPR.@]
1953 * FIXME: we should not return ourselves, but the owner of the drive lpName
1955 DWORD WINAPI
WNetGetUserW( LPCWSTR lpName
, LPWSTR lpUserID
, LPDWORD lpBufferSize
)
1957 if (GetUserNameW( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1958 return GetLastError();
1961 /*********************************************************************
1962 * WNetConnectionDialog [MPR.@]
1964 DWORD WINAPI
WNetConnectionDialog( HWND hwnd
, DWORD dwType
)
1966 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
1968 SetLastError(WN_NO_NETWORK
);
1969 return WN_NO_NETWORK
;
1972 /*********************************************************************
1973 * WNetConnectionDialog1A [MPR.@]
1975 DWORD WINAPI
WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct
)
1977 FIXME( "(%p): stub\n", lpConnDlgStruct
);
1979 SetLastError(WN_NO_NETWORK
);
1980 return WN_NO_NETWORK
;
1983 /*********************************************************************
1984 * WNetConnectionDialog1W [MPR.@]
1986 DWORD WINAPI
WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct
)
1988 FIXME( "(%p): stub\n", lpConnDlgStruct
);
1990 SetLastError(WN_NO_NETWORK
);
1991 return WN_NO_NETWORK
;
1994 /*********************************************************************
1995 * WNetDisconnectDialog [MPR.@]
1997 DWORD WINAPI
WNetDisconnectDialog( HWND hwnd
, DWORD dwType
)
1999 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2001 SetLastError(WN_NO_NETWORK
);
2002 return WN_NO_NETWORK
;
2005 /*********************************************************************
2006 * WNetDisconnectDialog1A [MPR.@]
2008 DWORD WINAPI
WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct
)
2010 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2012 SetLastError(WN_NO_NETWORK
);
2013 return WN_NO_NETWORK
;
2016 /*********************************************************************
2017 * WNetDisconnectDialog1W [MPR.@]
2019 DWORD WINAPI
WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct
)
2021 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2023 SetLastError(WN_NO_NETWORK
);
2024 return WN_NO_NETWORK
;
2027 /*********************************************************************
2028 * WNetGetLastErrorA [MPR.@]
2030 DWORD WINAPI
WNetGetLastErrorA( LPDWORD lpError
,
2031 LPSTR lpErrorBuf
, DWORD nErrorBufSize
,
2032 LPSTR lpNameBuf
, DWORD nNameBufSize
)
2034 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2035 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2037 SetLastError(WN_NO_NETWORK
);
2038 return WN_NO_NETWORK
;
2041 /*********************************************************************
2042 * WNetGetLastErrorW [MPR.@]
2044 DWORD WINAPI
WNetGetLastErrorW( LPDWORD lpError
,
2045 LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
2046 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
2048 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2049 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2051 SetLastError(WN_NO_NETWORK
);
2052 return WN_NO_NETWORK
;
2055 /*********************************************************************
2056 * WNetGetNetworkInformationA [MPR.@]
2058 DWORD WINAPI
WNetGetNetworkInformationA( LPCSTR lpProvider
,
2059 LPNETINFOSTRUCT lpNetInfoStruct
)
2063 TRACE( "(%s, %p)\n", debugstr_a(lpProvider
), lpNetInfoStruct
);
2066 ret
= WN_BAD_POINTER
;
2071 len
= MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, NULL
, 0);
2074 LPWSTR wideProvider
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2078 MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, wideProvider
,
2080 ret
= WNetGetNetworkInformationW(wideProvider
, lpNetInfoStruct
);
2081 HeapFree(GetProcessHeap(), 0, wideProvider
);
2084 ret
= WN_OUT_OF_MEMORY
;
2087 ret
= GetLastError();
2091 TRACE("Returning %d\n", ret
);
2095 /*********************************************************************
2096 * WNetGetNetworkInformationW [MPR.@]
2098 DWORD WINAPI
WNetGetNetworkInformationW( LPCWSTR lpProvider
,
2099 LPNETINFOSTRUCT lpNetInfoStruct
)
2103 TRACE( "(%s, %p)\n", debugstr_w(lpProvider
), lpNetInfoStruct
);
2106 ret
= WN_BAD_POINTER
;
2107 else if (!lpNetInfoStruct
)
2108 ret
= WN_BAD_POINTER
;
2109 else if (lpNetInfoStruct
->cbStructure
< sizeof(NETINFOSTRUCT
))
2113 if (providerTable
&& providerTable
->numProviders
)
2115 DWORD providerIndex
= _findProviderIndexW(lpProvider
);
2117 if (providerIndex
!= BAD_PROVIDER_INDEX
)
2119 lpNetInfoStruct
->cbStructure
= sizeof(NETINFOSTRUCT
);
2120 lpNetInfoStruct
->dwProviderVersion
=
2121 providerTable
->table
[providerIndex
].dwSpecVersion
;
2122 lpNetInfoStruct
->dwStatus
= NO_ERROR
;
2123 lpNetInfoStruct
->dwCharacteristics
= 0;
2124 lpNetInfoStruct
->dwHandle
= (ULONG_PTR
)NULL
;
2125 lpNetInfoStruct
->wNetType
=
2126 HIWORD(providerTable
->table
[providerIndex
].dwNetType
);
2127 lpNetInfoStruct
->dwPrinters
= -1;
2128 lpNetInfoStruct
->dwDrives
= -1;
2132 ret
= WN_BAD_PROVIDER
;
2135 ret
= WN_NO_NETWORK
;
2139 TRACE("Returning %d\n", ret
);
2143 /*****************************************************************
2144 * WNetGetProviderNameA [MPR.@]
2146 DWORD WINAPI
WNetGetProviderNameA( DWORD dwNetType
,
2147 LPSTR lpProvider
, LPDWORD lpBufferSize
)
2151 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_a(lpProvider
),
2155 ret
= WN_BAD_POINTER
;
2156 else if (!lpBufferSize
)
2157 ret
= WN_BAD_POINTER
;
2164 ret
= WN_NO_NETWORK
;
2165 for (i
= 0; i
< providerTable
->numProviders
&&
2166 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2169 if (i
< providerTable
->numProviders
)
2171 DWORD sizeNeeded
= WideCharToMultiByte(CP_ACP
, 0,
2172 providerTable
->table
[i
].name
, -1, NULL
, 0, NULL
, NULL
);
2174 if (*lpBufferSize
< sizeNeeded
)
2176 *lpBufferSize
= sizeNeeded
;
2181 WideCharToMultiByte(CP_ACP
, 0, providerTable
->table
[i
].name
,
2182 -1, lpProvider
, *lpBufferSize
, NULL
, NULL
);
2184 /* FIXME: is *lpBufferSize set to the number of characters
2190 ret
= WN_NO_NETWORK
;
2194 TRACE("Returning %d\n", ret
);
2198 /*****************************************************************
2199 * WNetGetProviderNameW [MPR.@]
2201 DWORD WINAPI
WNetGetProviderNameW( DWORD dwNetType
,
2202 LPWSTR lpProvider
, LPDWORD lpBufferSize
)
2206 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_w(lpProvider
),
2210 ret
= WN_BAD_POINTER
;
2211 else if (!lpBufferSize
)
2212 ret
= WN_BAD_POINTER
;
2219 ret
= WN_NO_NETWORK
;
2220 for (i
= 0; i
< providerTable
->numProviders
&&
2221 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2224 if (i
< providerTable
->numProviders
)
2226 DWORD sizeNeeded
= strlenW(providerTable
->table
[i
].name
) + 1;
2228 if (*lpBufferSize
< sizeNeeded
)
2230 *lpBufferSize
= sizeNeeded
;
2235 strcpyW(lpProvider
, providerTable
->table
[i
].name
);
2237 /* FIXME: is *lpBufferSize set to the number of characters
2243 ret
= WN_NO_NETWORK
;
2247 TRACE("Returning %d\n", ret
);