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
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mpr
);
39 /* Data structures representing network service providers. Assumes only one
40 * thread creates them, and that they are constant for the life of the process
41 * (and therefore doesn't synchronize access).
42 * FIXME: only basic provider data and enumeration-related data are implemented
43 * so far, need to implement the rest too.
45 typedef struct _WNetProvider
53 PF_NPOpenEnum openEnum
;
54 PF_NPEnumResource enumResource
;
55 PF_NPCloseEnum closeEnum
;
56 PF_NPGetResourceInformation getResourceInformation
;
57 } WNetProvider
, *PWNetProvider
;
59 typedef struct _WNetProviderTable
64 WNetProvider table
[1];
65 } WNetProviderTable
, *PWNetProviderTable
;
67 #define WNET_ENUMERATOR_TYPE_NULL 0
68 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
69 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
70 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
72 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
73 * the enumeration; it represents one of the following types:
74 * - a 'null' enumeration, one that contains no members
75 * - a global enumeration, one that's executed across all providers
76 * - a provider-specific enumeration, one that's only executed by a single
78 * - a context enumeration. I know this contradicts what I just said about
79 * there being no correspondence between the scope and the type, but it's
80 * necessary for the special case that a "Entire Network" entry needs to
81 * be enumerated in an enumeration of the context scope. Thus an enumeration
82 * of the context scope results in a context type enumerator, which morphs
83 * into a global enumeration (so the enumeration continues across all
86 typedef struct _WNetEnumerator
96 } WNetEnumerator
, *PWNetEnumerator
;
98 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
100 /* Returns an index (into the global WNetProviderTable) of the provider with
101 * the given name, or BAD_PROVIDER_INDEX if not found.
103 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
);
105 static PWNetProviderTable providerTable
;
108 * Global provider table functions
111 static void _tryLoadProvider(PCWSTR provider
)
113 static const WCHAR servicePrefix
[] = { 'S','y','s','t','e','m','\\',
114 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
115 'S','e','r','v','i','c','e','s','\\',0 };
116 static const WCHAR serviceFmt
[] = { '%','s','%','s','\\',
117 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
118 WCHAR serviceName
[MAX_PATH
];
121 TRACE("%s\n", debugstr_w(provider
));
122 snprintfW(serviceName
, sizeof(serviceName
) / sizeof(WCHAR
), serviceFmt
,
123 servicePrefix
, provider
);
124 serviceName
[sizeof(serviceName
) / sizeof(WCHAR
) - 1] = '\0';
125 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, serviceName
, 0, KEY_READ
, &hKey
) ==
128 static const WCHAR szProviderPath
[] = { 'P','r','o','v','i','d','e','r',
130 WCHAR providerPath
[MAX_PATH
];
131 DWORD type
, size
= sizeof(providerPath
);
133 if (RegQueryValueExW(hKey
, szProviderPath
, NULL
, &type
,
134 (LPBYTE
)providerPath
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
136 static const WCHAR szProviderName
[] = { 'N','a','m','e',0 };
140 RegQueryValueExW(hKey
, szProviderName
, NULL
, NULL
, NULL
, &size
);
143 name
= HeapAlloc(GetProcessHeap(), 0, size
);
144 if (RegQueryValueExW(hKey
, szProviderName
, NULL
, &type
,
145 (LPBYTE
)name
, &size
) != ERROR_SUCCESS
|| type
!= REG_SZ
)
147 HeapFree(GetProcessHeap(), 0, name
);
153 HMODULE hLib
= LoadLibraryW(providerPath
);
157 PF_NPGetCaps getCaps
= (PF_NPGetCaps
)GetProcAddress(hLib
,
160 TRACE("loaded lib %p\n", hLib
);
163 PWNetProvider provider
=
164 &providerTable
->table
[providerTable
->numProviders
];
166 provider
->hLib
= hLib
;
167 provider
->name
= name
;
168 TRACE("name is %s\n", debugstr_w(name
));
169 provider
->getCaps
= getCaps
;
170 provider
->dwSpecVersion
= getCaps(WNNC_SPEC_VERSION
);
171 provider
->dwNetType
= getCaps(WNNC_NET_TYPE
);
172 TRACE("net type is 0x%08x\n", provider
->dwNetType
);
173 provider
->dwEnumScopes
= getCaps(WNNC_ENUMERATION
);
174 if (provider
->dwEnumScopes
)
176 TRACE("supports enumeration\n");
177 provider
->openEnum
= (PF_NPOpenEnum
)
178 GetProcAddress(hLib
, "NPOpenEnum");
179 TRACE("openEnum is %p\n", provider
->openEnum
);
180 provider
->enumResource
= (PF_NPEnumResource
)
181 GetProcAddress(hLib
, "NPEnumResource");
182 TRACE("enumResource is %p\n",
183 provider
->enumResource
);
184 provider
->closeEnum
= (PF_NPCloseEnum
)
185 GetProcAddress(hLib
, "NPCloseEnum");
186 TRACE("closeEnum is %p\n", provider
->closeEnum
);
187 provider
->getResourceInformation
= (PF_NPGetResourceInformation
)
188 GetProcAddress(hLib
, "NPGetResourceInformation");
189 TRACE("getResourceInformation is %p\n",
190 provider
->getResourceInformation
);
191 if (!provider
->openEnum
|| !provider
->enumResource
192 || !provider
->closeEnum
)
194 provider
->openEnum
= NULL
;
195 provider
->enumResource
= NULL
;
196 provider
->closeEnum
= NULL
;
197 provider
->dwEnumScopes
= 0;
198 WARN("Couldn't load enumeration functions\n");
201 providerTable
->numProviders
++;
205 WARN("Provider %s didn't export NPGetCaps\n",
206 debugstr_w(provider
));
207 HeapFree(GetProcessHeap(), 0, name
);
213 WARN("Couldn't load library %s for provider %s\n",
214 debugstr_w(providerPath
), debugstr_w(provider
));
215 HeapFree(GetProcessHeap(), 0, name
);
220 WARN("Couldn't get provider name for provider %s\n",
221 debugstr_w(provider
));
225 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath
));
229 WARN("Couldn't open service key for provider %s\n",
230 debugstr_w(provider
));
233 void wnetInit(HINSTANCE hInstDll
)
235 static const WCHAR providerOrderKey
[] = { 'S','y','s','t','e','m','\\',
236 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
237 'C','o','n','t','r','o','l','\\',
238 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
239 'O','r','d','e','r',0 };
240 static const WCHAR providerOrder
[] = { 'P','r','o','v','i','d','e','r',
241 'O','r','d','e','r',0 };
244 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, providerOrderKey
, 0, KEY_READ
, &hKey
)
249 RegQueryValueExW(hKey
, providerOrder
, NULL
, NULL
, NULL
, &size
);
252 PWSTR providers
= HeapAlloc(GetProcessHeap(), 0, size
);
258 if (RegQueryValueExW(hKey
, providerOrder
, NULL
, &type
,
259 (LPBYTE
)providers
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
264 TRACE("provider order is %s\n", debugstr_w(providers
));
265 /* first count commas as a heuristic for how many to
266 * allocate space for */
267 for (ptr
= providers
, numToAllocate
= 1; ptr
; )
269 ptr
= strchrW(ptr
, ',');
276 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
277 sizeof(WNetProviderTable
)
278 + (numToAllocate
- 1) * sizeof(WNetProvider
));
282 int entireNetworkLen
;
283 LPCWSTR stringresource
;
285 entireNetworkLen
= LoadStringW(hInstDll
,
286 IDS_ENTIRENETWORK
, (LPWSTR
)&stringresource
, 0);
287 providerTable
->entireNetwork
= HeapAlloc(
288 GetProcessHeap(), 0, (entireNetworkLen
+ 1) *
290 if (providerTable
->entireNetwork
)
292 memcpy(providerTable
->entireNetwork
, stringresource
, entireNetworkLen
*sizeof(WCHAR
));
293 providerTable
->entireNetwork
[entireNetworkLen
] = 0;
295 providerTable
->numAllocated
= numToAllocate
;
296 for (ptr
= providers
; ptr
; )
299 ptr
= strchrW(ptr
, ',');
302 _tryLoadProvider(ptrPrev
);
306 HeapFree(GetProcessHeap(), 0, providers
);
319 for (i
= 0; i
< providerTable
->numProviders
; i
++)
321 HeapFree(GetProcessHeap(), 0, providerTable
->table
[i
].name
);
322 FreeModule(providerTable
->table
[i
].hLib
);
324 HeapFree(GetProcessHeap(), 0, providerTable
->entireNetwork
);
325 HeapFree(GetProcessHeap(), 0, providerTable
);
326 providerTable
= NULL
;
330 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
)
332 DWORD ret
= BAD_PROVIDER_INDEX
;
334 if (providerTable
&& providerTable
->numProviders
)
338 for (i
= 0; i
< providerTable
->numProviders
&&
339 ret
== BAD_PROVIDER_INDEX
; i
++)
340 if (!strcmpW(lpProvider
, providerTable
->table
[i
].name
))
350 static LPNETRESOURCEW
_copyNetResourceForEnumW(LPNETRESOURCEW lpNet
)
356 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW
));
362 ret
->lpLocalName
= ret
->lpComment
= ret
->lpProvider
= NULL
;
363 if (lpNet
->lpRemoteName
)
365 len
= strlenW(lpNet
->lpRemoteName
) + 1;
366 ret
->lpRemoteName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
367 if (ret
->lpRemoteName
)
368 strcpyW(ret
->lpRemoteName
, lpNet
->lpRemoteName
);
377 static void _freeEnumNetResource(LPNETRESOURCEW lpNet
)
381 HeapFree(GetProcessHeap(), 0, lpNet
->lpRemoteName
);
382 HeapFree(GetProcessHeap(), 0, lpNet
);
386 static PWNetEnumerator
_createNullEnumerator(void)
388 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
389 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
392 ret
->enumType
= WNET_ENUMERATOR_TYPE_NULL
;
396 static PWNetEnumerator
_createGlobalEnumeratorW(DWORD dwScope
, DWORD dwType
,
397 DWORD dwUsage
, LPNETRESOURCEW lpNet
)
399 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
400 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
404 ret
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
405 ret
->dwScope
= dwScope
;
406 ret
->dwType
= dwType
;
407 ret
->dwUsage
= dwUsage
;
408 ret
->lpNet
= _copyNetResourceForEnumW(lpNet
);
413 static PWNetEnumerator
_createProviderEnumerator(DWORD dwScope
, DWORD dwType
,
414 DWORD dwUsage
, DWORD index
, HANDLE handle
)
418 if (!providerTable
|| index
>= providerTable
->numProviders
)
422 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
425 ret
->enumType
= WNET_ENUMERATOR_TYPE_PROVIDER
;
426 ret
->providerIndex
= index
;
427 ret
->dwScope
= dwScope
;
428 ret
->dwType
= dwType
;
429 ret
->dwUsage
= dwUsage
;
430 ret
->handle
= handle
;
436 static PWNetEnumerator
_createContextEnumerator(DWORD dwScope
, DWORD dwType
,
439 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
440 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
444 ret
->enumType
= WNET_ENUMERATOR_TYPE_CONTEXT
;
445 ret
->dwScope
= dwScope
;
446 ret
->dwType
= dwType
;
447 ret
->dwUsage
= dwUsage
;
452 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
453 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
454 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
455 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
456 * if not all members of the array could be thunked, and something else on
459 static DWORD
_thunkNetResourceArrayWToA(const NETRESOURCEW
*lpNetArrayIn
,
460 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
462 DWORD i
, numToThunk
, totalBytes
, ret
;
466 return WN_BAD_POINTER
;
468 return WN_BAD_POINTER
;
472 return WN_BAD_POINTER
;
474 return WN_BAD_POINTER
;
476 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
478 const NETRESOURCEW
*lpNet
= lpNetArrayIn
+ i
;
480 totalBytes
+= sizeof(NETRESOURCEA
);
481 if (lpNet
->lpLocalName
)
482 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpLocalName
,
483 -1, NULL
, 0, NULL
, NULL
);
484 if (lpNet
->lpRemoteName
)
485 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpRemoteName
,
486 -1, NULL
, 0, NULL
, NULL
);
487 if (lpNet
->lpComment
)
488 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpComment
,
489 -1, NULL
, 0, NULL
, NULL
);
490 if (lpNet
->lpProvider
)
491 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpProvider
,
492 -1, NULL
, 0, NULL
, NULL
);
493 if (totalBytes
< *lpBufferSize
)
496 strNext
= (LPSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEA
));
497 for (i
= 0; i
< numToThunk
; i
++)
499 LPNETRESOURCEA lpNetOut
= (LPNETRESOURCEA
)lpBuffer
+ i
;
500 const NETRESOURCEW
*lpNetIn
= lpNetArrayIn
+ i
;
502 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEA
));
503 /* lie about string lengths, we already verified how many
504 * we have space for above
506 if (lpNetIn
->lpLocalName
)
508 lpNetOut
->lpLocalName
= strNext
;
509 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpLocalName
, -1,
510 lpNetOut
->lpLocalName
, *lpBufferSize
, NULL
, NULL
);
512 if (lpNetIn
->lpRemoteName
)
514 lpNetOut
->lpRemoteName
= strNext
;
515 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpRemoteName
, -1,
516 lpNetOut
->lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
518 if (lpNetIn
->lpComment
)
520 lpNetOut
->lpComment
= strNext
;
521 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpComment
, -1,
522 lpNetOut
->lpComment
, *lpBufferSize
, NULL
, NULL
);
524 if (lpNetIn
->lpProvider
)
526 lpNetOut
->lpProvider
= strNext
;
527 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpProvider
, -1,
528 lpNetOut
->lpProvider
, *lpBufferSize
, NULL
, NULL
);
531 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
532 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
537 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
538 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
539 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
540 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
541 * if not all members of the array could be thunked, and something else on
544 static DWORD
_thunkNetResourceArrayAToW(const NETRESOURCEA
*lpNetArrayIn
,
545 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
547 DWORD i
, numToThunk
, totalBytes
, ret
;
551 return WN_BAD_POINTER
;
553 return WN_BAD_POINTER
;
557 return WN_BAD_POINTER
;
559 return WN_BAD_POINTER
;
561 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
563 const NETRESOURCEA
*lpNet
= lpNetArrayIn
+ i
;
565 totalBytes
+= sizeof(NETRESOURCEW
);
566 if (lpNet
->lpLocalName
)
567 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpLocalName
,
568 -1, NULL
, 0) * sizeof(WCHAR
);
569 if (lpNet
->lpRemoteName
)
570 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpRemoteName
,
571 -1, NULL
, 0) * sizeof(WCHAR
);
572 if (lpNet
->lpComment
)
573 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpComment
,
574 -1, NULL
, 0) * sizeof(WCHAR
);
575 if (lpNet
->lpProvider
)
576 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpProvider
,
577 -1, NULL
, 0) * sizeof(WCHAR
);
578 if (totalBytes
< *lpBufferSize
)
581 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEW
));
582 for (i
= 0; i
< numToThunk
; i
++)
584 LPNETRESOURCEW lpNetOut
= (LPNETRESOURCEW
)lpBuffer
+ i
;
585 const NETRESOURCEA
*lpNetIn
= lpNetArrayIn
+ i
;
587 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEW
));
588 /* lie about string lengths, we already verified how many
589 * we have space for above
591 if (lpNetIn
->lpLocalName
)
593 lpNetOut
->lpLocalName
= strNext
;
594 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpLocalName
,
595 -1, lpNetOut
->lpLocalName
, *lpBufferSize
);
597 if (lpNetIn
->lpRemoteName
)
599 lpNetOut
->lpRemoteName
= strNext
;
600 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpRemoteName
,
601 -1, lpNetOut
->lpRemoteName
, *lpBufferSize
);
603 if (lpNetIn
->lpComment
)
605 lpNetOut
->lpComment
= strNext
;
606 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpComment
,
607 -1, lpNetOut
->lpComment
, *lpBufferSize
);
609 if (lpNetIn
->lpProvider
)
611 lpNetOut
->lpProvider
= strNext
;
612 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpProvider
,
613 -1, lpNetOut
->lpProvider
, *lpBufferSize
);
616 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
617 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
622 /*********************************************************************
623 * WNetOpenEnumA [MPR.@]
625 * See comments for WNetOpenEnumW.
627 DWORD WINAPI
WNetOpenEnumA( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
628 LPNETRESOURCEA lpNet
, LPHANDLE lphEnum
)
632 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
633 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
636 ret
= WN_BAD_POINTER
;
637 else if (!providerTable
|| providerTable
->numProviders
== 0)
646 LPNETRESOURCEW lpNetWide
= NULL
;
648 DWORD size
= sizeof(buf
), count
= 1;
649 BOOL allocated
= FALSE
;
651 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, buf
, &size
);
652 if (ret
== WN_MORE_DATA
)
654 lpNetWide
= HeapAlloc(GetProcessHeap(), 0,
658 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, lpNetWide
,
663 ret
= WN_OUT_OF_MEMORY
;
665 else if (ret
== WN_SUCCESS
)
666 lpNetWide
= (LPNETRESOURCEW
)buf
;
667 if (ret
== WN_SUCCESS
)
668 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, lpNetWide
,
671 HeapFree(GetProcessHeap(), 0, lpNetWide
);
674 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, NULL
, lphEnum
);
678 TRACE("Returning %d\n", ret
);
682 /*********************************************************************
683 * WNetOpenEnumW [MPR.@]
685 * Network enumeration has way too many parameters, so I'm not positive I got
686 * them right. What I've got so far:
688 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
689 * all the network providers should be enumerated.
691 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
692 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
693 * lpProvider is set, all the network providers should be enumerated.
694 * (This means the enumeration is a list of network providers, not that the
695 * enumeration is passed on to the providers.)
697 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
698 * resource matches the "Entire Network" resource (no remote name, no
699 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
700 * enumeration is done on every network provider.
702 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
703 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
704 * only to the given network provider.
706 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
707 * no lpProvider is set, enumeration will be tried on every network provider,
708 * in the order in which they're loaded.
710 * - The LPNETRESOURCE should be disregarded for scopes besides
711 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
712 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
714 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
715 * resource in the enumerated list, as well as any machines in your
716 * workgroup. The machines in your workgroup come from doing a
717 * RESOURCE_CONTEXT enumeration of every Network Provider.
719 DWORD WINAPI
WNetOpenEnumW( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
720 LPNETRESOURCEW lpNet
, LPHANDLE lphEnum
)
724 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
725 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
728 ret
= WN_BAD_POINTER
;
729 else if (!providerTable
|| providerTable
->numProviders
== 0)
738 case RESOURCE_GLOBALNET
:
741 if (lpNet
->lpProvider
)
743 DWORD index
= _findProviderIndexW(lpNet
->lpProvider
);
745 if (index
!= BAD_PROVIDER_INDEX
)
747 if (providerTable
->table
[index
].openEnum
&&
748 providerTable
->table
[index
].dwEnumScopes
& WNNC_ENUM_GLOBAL
)
752 ret
= providerTable
->table
[index
].openEnum(
753 dwScope
, dwType
, dwUsage
, lpNet
, &handle
);
754 if (ret
== WN_SUCCESS
)
756 *lphEnum
= _createProviderEnumerator(
757 dwScope
, dwType
, dwUsage
, index
, handle
);
758 ret
= *lphEnum
? WN_SUCCESS
:
763 ret
= WN_NOT_SUPPORTED
;
766 ret
= WN_BAD_PROVIDER
;
768 else if (lpNet
->lpRemoteName
)
770 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
771 dwType
, dwUsage
, lpNet
);
772 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
776 if (lpNet
->lpComment
&& !strcmpW(lpNet
->lpComment
,
777 providerTable
->entireNetwork
))
779 /* comment matches the "Entire Network", enumerate
780 * global scope of every provider
782 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
783 dwType
, dwUsage
, lpNet
);
787 /* this is the same as not having passed lpNet */
788 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
789 dwType
, dwUsage
, NULL
);
791 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
796 *lphEnum
= _createGlobalEnumeratorW(dwScope
, dwType
,
798 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
801 case RESOURCE_CONTEXT
:
802 *lphEnum
= _createContextEnumerator(dwScope
, dwType
, dwUsage
);
803 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
805 case RESOURCE_REMEMBERED
:
806 case RESOURCE_CONNECTED
:
807 *lphEnum
= _createNullEnumerator();
808 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
811 WARN("unknown scope 0x%08x\n", dwScope
);
817 TRACE("Returning %d\n", ret
);
821 /*********************************************************************
822 * WNetEnumResourceA [MPR.@]
824 DWORD WINAPI
WNetEnumResourceA( HANDLE hEnum
, LPDWORD lpcCount
,
825 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
829 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
832 ret
= WN_BAD_POINTER
;
834 ret
= WN_BAD_POINTER
;
836 ret
= WN_BAD_POINTER
;
837 else if (!lpBufferSize
)
838 ret
= WN_BAD_POINTER
;
839 else if (*lpBufferSize
< sizeof(NETRESOURCEA
))
841 *lpBufferSize
= sizeof(NETRESOURCEA
);
846 DWORD localCount
= *lpcCount
, localSize
= *lpBufferSize
;
847 LPVOID localBuffer
= HeapAlloc(GetProcessHeap(), 0, localSize
);
851 ret
= WNetEnumResourceW(hEnum
, &localCount
, localBuffer
,
853 if (ret
== WN_SUCCESS
|| (ret
== WN_MORE_DATA
&& localCount
!= -1))
855 /* FIXME: this isn't necessarily going to work in the case of
856 * WN_MORE_DATA, because our enumerator may have moved on to
857 * the next provider. MSDN states that a large (16KB) buffer
858 * size is the appropriate usage of this function, so
859 * hopefully it won't be an issue.
861 ret
= _thunkNetResourceArrayWToA(localBuffer
, &localCount
,
862 lpBuffer
, lpBufferSize
);
863 *lpcCount
= localCount
;
865 HeapFree(GetProcessHeap(), 0, localBuffer
);
868 ret
= WN_OUT_OF_MEMORY
;
872 TRACE("Returning %d\n", ret
);
876 static DWORD
_countProviderBytesW(PWNetProvider provider
)
882 ret
= sizeof(NETRESOURCEW
);
883 ret
+= 2 * (strlenW(provider
->name
) + 1) * sizeof(WCHAR
);
890 static DWORD
_enumerateProvidersW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
891 LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
896 return WN_BAD_POINTER
;
897 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
900 return WN_BAD_POINTER
;
902 return WN_BAD_POINTER
;
904 return WN_BAD_POINTER
;
905 if (*lpBufferSize
< sizeof(NETRESOURCEA
))
908 if (!providerTable
|| enumerator
->providerIndex
>=
909 providerTable
->numProviders
)
910 ret
= WN_NO_MORE_ENTRIES
;
913 DWORD bytes
= 0, count
= 0, countLimit
, i
;
914 LPNETRESOURCEW resource
;
917 countLimit
= *lpcCount
== -1 ?
918 providerTable
->numProviders
- enumerator
->providerIndex
: *lpcCount
;
919 while (count
< countLimit
&& bytes
< *lpBufferSize
)
921 DWORD bytesNext
= _countProviderBytesW(
922 &providerTable
->table
[count
+ enumerator
->providerIndex
]);
924 if (bytes
+ bytesNext
< *lpBufferSize
)
930 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ count
* sizeof(NETRESOURCEW
));
931 for (i
= 0, resource
= lpBuffer
; i
< count
; i
++, resource
++)
933 resource
->dwScope
= RESOURCE_GLOBALNET
;
934 resource
->dwType
= RESOURCETYPE_ANY
;
935 resource
->dwDisplayType
= RESOURCEDISPLAYTYPE_NETWORK
;
936 resource
->dwUsage
= RESOURCEUSAGE_CONTAINER
|
937 RESOURCEUSAGE_RESERVED
;
938 resource
->lpLocalName
= NULL
;
939 resource
->lpRemoteName
= strNext
;
940 strcpyW(resource
->lpRemoteName
,
941 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
942 strNext
+= strlenW(resource
->lpRemoteName
) + 1;
943 resource
->lpComment
= NULL
;
944 resource
->lpProvider
= strNext
;
945 strcpyW(resource
->lpProvider
,
946 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
947 strNext
+= strlenW(resource
->lpProvider
) + 1;
949 enumerator
->providerIndex
+= count
;
951 ret
= count
> 0 ? WN_SUCCESS
: WN_MORE_DATA
;
953 TRACE("Returning %d\n", ret
);
957 /* Advances the enumerator (assumed to be a global enumerator) to the next
958 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
959 * not open a handle with the next provider.
960 * If the existing handle is NULL, may leave the enumerator unchanged, since
961 * the current provider may support the desired scope.
962 * If the existing handle is not NULL, closes it before moving on.
963 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
964 * provider, and another error on failure.
966 static DWORD
_globalEnumeratorAdvance(PWNetEnumerator enumerator
)
969 return WN_BAD_POINTER
;
970 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
972 if (!providerTable
|| enumerator
->providerIndex
>=
973 providerTable
->numProviders
)
974 return WN_NO_MORE_ENTRIES
;
976 if (enumerator
->providerDone
)
979 enumerator
->providerDone
= FALSE
;
980 if (enumerator
->handle
)
982 providerTable
->table
[enumerator
->providerIndex
].closeEnum(
984 enumerator
->handle
= NULL
;
985 enumerator
->providerIndex
++;
987 if (enumerator
->dwScope
== RESOURCE_CONNECTED
)
988 dwEnum
= WNNC_ENUM_LOCAL
;
989 else if (enumerator
->dwScope
== RESOURCE_GLOBALNET
)
990 dwEnum
= WNNC_ENUM_GLOBAL
;
991 else if (enumerator
->dwScope
== RESOURCE_CONTEXT
)
992 dwEnum
= WNNC_ENUM_CONTEXT
;
993 for (; enumerator
->providerIndex
< providerTable
->numProviders
&&
994 !(providerTable
->table
[enumerator
->providerIndex
].dwEnumScopes
995 & dwEnum
); enumerator
->providerIndex
++)
998 return enumerator
->providerIndex
< providerTable
->numProviders
?
999 WN_SUCCESS
: WN_NO_MORE_ENTRIES
;
1002 /* "Passes through" call to the next provider that supports the enumeration
1004 * FIXME: if one call to a provider's enumerator succeeds while there's still
1005 * space in lpBuffer, I don't call to the next provider. The caller may not
1006 * expect that it should call EnumResourceW again with a return value of
1007 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1008 * may have to be moved around a bit, ick.
1010 static DWORD
_enumerateGlobalPassthroughW(PWNetEnumerator enumerator
,
1011 LPDWORD lpcCount
, LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1016 return WN_BAD_POINTER
;
1017 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1018 return WN_BAD_VALUE
;
1020 return WN_BAD_POINTER
;
1022 return WN_BAD_POINTER
;
1024 return WN_BAD_POINTER
;
1025 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1026 return WN_MORE_DATA
;
1028 ret
= _globalEnumeratorAdvance(enumerator
);
1029 if (ret
== WN_SUCCESS
)
1031 ret
= providerTable
->table
[enumerator
->providerIndex
].
1032 openEnum(enumerator
->dwScope
, enumerator
->dwType
,
1033 enumerator
->dwUsage
, enumerator
->lpNet
,
1034 &enumerator
->handle
);
1035 if (ret
== WN_SUCCESS
)
1037 ret
= providerTable
->table
[enumerator
->providerIndex
].
1038 enumResource(enumerator
->handle
, lpcCount
, lpBuffer
,
1040 if (ret
!= WN_MORE_DATA
)
1041 enumerator
->providerDone
= TRUE
;
1044 TRACE("Returning %d\n", ret
);
1048 static DWORD
_enumerateGlobalW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1049 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1054 return WN_BAD_POINTER
;
1055 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1056 return WN_BAD_VALUE
;
1058 return WN_BAD_POINTER
;
1060 return WN_BAD_POINTER
;
1062 return WN_BAD_POINTER
;
1063 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1064 return WN_MORE_DATA
;
1066 return WN_NO_NETWORK
;
1068 switch (enumerator
->dwScope
)
1070 case RESOURCE_GLOBALNET
:
1071 if (enumerator
->lpNet
)
1072 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
,
1073 lpBuffer
, lpBufferSize
);
1075 ret
= _enumerateProvidersW(enumerator
, lpcCount
, lpBuffer
,
1078 case RESOURCE_CONTEXT
:
1079 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
, lpBuffer
,
1083 WARN("unexpected scope 0x%08x\n", enumerator
->dwScope
);
1084 ret
= WN_NO_MORE_ENTRIES
;
1086 TRACE("Returning %d\n", ret
);
1090 static DWORD
_enumerateProviderW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1091 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1094 return WN_BAD_POINTER
;
1095 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_PROVIDER
)
1096 return WN_BAD_VALUE
;
1097 if (!enumerator
->handle
)
1098 return WN_BAD_VALUE
;
1100 return WN_BAD_POINTER
;
1102 return WN_BAD_POINTER
;
1104 return WN_BAD_POINTER
;
1106 return WN_NO_NETWORK
;
1107 if (enumerator
->providerIndex
>= providerTable
->numProviders
)
1108 return WN_NO_MORE_ENTRIES
;
1109 if (!providerTable
->table
[enumerator
->providerIndex
].enumResource
)
1110 return WN_BAD_VALUE
;
1111 return providerTable
->table
[enumerator
->providerIndex
].enumResource(
1112 enumerator
->handle
, lpcCount
, lpBuffer
, lpBufferSize
);
1115 static DWORD
_enumerateContextW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1116 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1119 size_t cchEntireNetworkLen
, bytesNeeded
;
1122 return WN_BAD_POINTER
;
1123 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_CONTEXT
)
1124 return WN_BAD_VALUE
;
1126 return WN_BAD_POINTER
;
1128 return WN_BAD_POINTER
;
1130 return WN_BAD_POINTER
;
1132 return WN_NO_NETWORK
;
1134 cchEntireNetworkLen
= strlenW(providerTable
->entireNetwork
) + 1;
1135 bytesNeeded
= sizeof(NETRESOURCEW
) + cchEntireNetworkLen
* sizeof(WCHAR
);
1136 if (*lpBufferSize
< bytesNeeded
)
1138 *lpBufferSize
= bytesNeeded
;
1143 LPNETRESOURCEW lpNet
= lpBuffer
;
1145 lpNet
->dwScope
= RESOURCE_GLOBALNET
;
1146 lpNet
->dwType
= enumerator
->dwType
;
1147 lpNet
->dwDisplayType
= RESOURCEDISPLAYTYPE_ROOT
;
1148 lpNet
->dwUsage
= RESOURCEUSAGE_CONTAINER
;
1149 lpNet
->lpLocalName
= NULL
;
1150 lpNet
->lpRemoteName
= NULL
;
1151 lpNet
->lpProvider
= NULL
;
1152 /* odd, but correct: put comment at end of buffer, so it won't get
1153 * overwritten by subsequent calls to a provider's enumResource
1155 lpNet
->lpComment
= (LPWSTR
)((LPBYTE
)lpBuffer
+ *lpBufferSize
-
1156 (cchEntireNetworkLen
* sizeof(WCHAR
)));
1157 strcpyW(lpNet
->lpComment
, providerTable
->entireNetwork
);
1160 if (ret
== WN_SUCCESS
)
1162 DWORD bufferSize
= *lpBufferSize
- bytesNeeded
;
1164 /* "Entire Network" entry enumerated--morph this into a global
1165 * enumerator. enumerator->lpNet continues to be NULL, since it has
1166 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1168 enumerator
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
1169 ret
= _enumerateGlobalW(enumerator
, lpcCount
,
1170 (LPBYTE
)lpBuffer
+ bytesNeeded
, &bufferSize
);
1171 if (ret
== WN_SUCCESS
)
1173 /* reflect the fact that we already enumerated "Entire Network" */
1175 *lpBufferSize
= bufferSize
+ bytesNeeded
;
1179 /* the provider enumeration failed, but we already succeeded in
1180 * enumerating "Entire Network"--leave type as global to allow a
1181 * retry, but indicate success with a count of one.
1185 *lpBufferSize
= bytesNeeded
;
1188 TRACE("Returning %d\n", ret
);
1192 /*********************************************************************
1193 * WNetEnumResourceW [MPR.@]
1195 DWORD WINAPI
WNetEnumResourceW( HANDLE hEnum
, LPDWORD lpcCount
,
1196 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1200 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
1203 ret
= WN_BAD_POINTER
;
1205 ret
= WN_BAD_POINTER
;
1207 ret
= WN_BAD_POINTER
;
1208 else if (!lpBufferSize
)
1209 ret
= WN_BAD_POINTER
;
1210 else if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1212 *lpBufferSize
= sizeof(NETRESOURCEW
);
1217 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1219 switch (enumerator
->enumType
)
1221 case WNET_ENUMERATOR_TYPE_NULL
:
1222 ret
= WN_NO_MORE_ENTRIES
;
1224 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1225 ret
= _enumerateGlobalW(enumerator
, lpcCount
, lpBuffer
,
1228 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1229 ret
= _enumerateProviderW(enumerator
, lpcCount
, lpBuffer
,
1232 case WNET_ENUMERATOR_TYPE_CONTEXT
:
1233 ret
= _enumerateContextW(enumerator
, lpcCount
, lpBuffer
,
1237 WARN("bogus enumerator type!\n");
1238 ret
= WN_NO_NETWORK
;
1243 TRACE("Returning %d\n", ret
);
1247 /*********************************************************************
1248 * WNetCloseEnum [MPR.@]
1250 DWORD WINAPI
WNetCloseEnum( HANDLE hEnum
)
1254 TRACE( "(%p)\n", hEnum
);
1258 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1260 switch (enumerator
->enumType
)
1262 case WNET_ENUMERATOR_TYPE_NULL
:
1265 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1266 if (enumerator
->lpNet
)
1267 _freeEnumNetResource(enumerator
->lpNet
);
1268 if (enumerator
->handle
)
1269 providerTable
->table
[enumerator
->providerIndex
].
1270 closeEnum(enumerator
->handle
);
1273 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1274 if (enumerator
->handle
)
1275 providerTable
->table
[enumerator
->providerIndex
].
1276 closeEnum(enumerator
->handle
);
1280 WARN("bogus enumerator type!\n");
1281 ret
= WN_BAD_HANDLE
;
1283 HeapFree(GetProcessHeap(), 0, hEnum
);
1286 ret
= WN_BAD_HANDLE
;
1289 TRACE("Returning %d\n", ret
);
1293 /*********************************************************************
1294 * WNetGetResourceInformationA [MPR.@]
1296 * See WNetGetResourceInformationW
1298 DWORD WINAPI
WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource
,
1299 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1304 TRACE( "(%p, %p, %p, %p)\n",
1305 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1307 if (!providerTable
|| providerTable
->numProviders
== 0)
1308 ret
= WN_NO_NETWORK
;
1309 else if (lpNetResource
)
1311 LPNETRESOURCEW lpNetResourceW
= NULL
;
1312 DWORD size
= 1024, count
= 1;
1315 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1316 ret
= _thunkNetResourceArrayAToW(lpNetResource
, &count
, lpNetResourceW
, &size
);
1317 if (ret
== WN_MORE_DATA
)
1319 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1320 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1322 ret
= _thunkNetResourceArrayAToW(lpNetResource
,
1323 &count
, lpNetResourceW
, &size
);
1325 ret
= WN_OUT_OF_MEMORY
;
1327 if (ret
== WN_SUCCESS
)
1329 LPWSTR lpSystemW
= NULL
;
1332 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1335 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1336 lpBufferW
, &size
, &lpSystemW
);
1337 if (ret
== WN_MORE_DATA
)
1339 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1340 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1342 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1343 lpBufferW
, &size
, &lpSystemW
);
1345 ret
= WN_OUT_OF_MEMORY
;
1347 if (ret
== WN_SUCCESS
)
1349 ret
= _thunkNetResourceArrayWToA(lpBufferW
,
1350 &count
, lpBuffer
, cbBuffer
);
1351 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1352 lpNetResourceW
= lpBufferW
;
1353 size
= sizeof(NETRESOURCEA
);
1354 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpRemoteName
,
1355 -1, NULL
, 0, NULL
, NULL
);
1356 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpProvider
,
1357 -1, NULL
, 0, NULL
, NULL
);
1359 len
= WideCharToMultiByte(CP_ACP
, 0, lpSystemW
,
1360 -1, NULL
, 0, NULL
, NULL
);
1361 if ((len
) && ( size
+ len
< *cbBuffer
))
1363 *lplpSystem
= (char*)lpBuffer
+ *cbBuffer
- len
;
1364 WideCharToMultiByte(CP_ACP
, 0, lpSystemW
, -1,
1365 *lplpSystem
, len
, NULL
, NULL
);
1372 ret
= WN_OUT_OF_MEMORY
;
1373 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1376 ret
= WN_OUT_OF_MEMORY
;
1377 HeapFree(GetProcessHeap(), 0, lpSystemW
);
1379 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1382 ret
= WN_NO_NETWORK
;
1386 TRACE("Returning %d\n", ret
);
1390 /*********************************************************************
1391 * WNetGetResourceInformationW [MPR.@]
1393 * WNetGetResourceInformationW function identifies the network provider
1394 * that owns the resource and gets information about the type of the resource.
1397 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1398 * defines a network resource.
1399 * lpBuffer [ O] the pointer to buffer, containing result. It
1400 * contains NETRESOURCEW structure and strings to
1401 * which the members of the NETRESOURCEW structure
1403 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1405 * lplpSystem [ O] the pointer to string in the output buffer,
1406 * containing the part of the resource name without
1407 * names of the server and share.
1410 * NO_ERROR if the function succeeds. System error code if the function fails.
1413 DWORD WINAPI
WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource
,
1414 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1415 LPWSTR
*lplpSystem
)
1417 DWORD ret
= WN_NO_NETWORK
;
1420 TRACE( "(%p, %p, %p, %p)\n",
1421 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1424 ret
= WN_OUT_OF_MEMORY
;
1425 else if (providerTable
!= NULL
)
1427 /* FIXME: For function value of a variable is indifferent, it does
1428 * search of all providers in a network.
1430 for (index
= 0; index
< providerTable
->numProviders
; index
++)
1432 if(providerTable
->table
[index
].getCaps(WNNC_DIALOG
) &
1433 WNNC_DLG_GETRESOURCEINFORMATION
)
1435 if (providerTable
->table
[index
].getResourceInformation
)
1436 ret
= providerTable
->table
[index
].getResourceInformation(
1437 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1439 ret
= WN_NO_NETWORK
;
1440 if (ret
== WN_SUCCESS
)
1450 /*********************************************************************
1451 * WNetGetResourceParentA [MPR.@]
1453 DWORD WINAPI
WNetGetResourceParentA( LPNETRESOURCEA lpNetResource
,
1454 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1456 FIXME( "(%p, %p, %p): stub\n",
1457 lpNetResource
, lpBuffer
, lpBufferSize
);
1459 SetLastError(WN_NO_NETWORK
);
1460 return WN_NO_NETWORK
;
1463 /*********************************************************************
1464 * WNetGetResourceParentW [MPR.@]
1466 DWORD WINAPI
WNetGetResourceParentW( LPNETRESOURCEW lpNetResource
,
1467 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1469 FIXME( "(%p, %p, %p): stub\n",
1470 lpNetResource
, lpBuffer
, lpBufferSize
);
1472 SetLastError(WN_NO_NETWORK
);
1473 return WN_NO_NETWORK
;
1479 * Connection Functions
1482 /*********************************************************************
1483 * WNetAddConnectionA [MPR.@]
1485 DWORD WINAPI
WNetAddConnectionA( LPCSTR lpRemoteName
, LPCSTR lpPassword
,
1486 LPCSTR lpLocalName
)
1488 FIXME( "(%s, %p, %s): stub\n",
1489 debugstr_a(lpRemoteName
), lpPassword
, debugstr_a(lpLocalName
) );
1491 SetLastError(WN_NO_NETWORK
);
1492 return WN_NO_NETWORK
;
1495 /*********************************************************************
1496 * WNetAddConnectionW [MPR.@]
1498 DWORD WINAPI
WNetAddConnectionW( LPCWSTR lpRemoteName
, LPCWSTR lpPassword
,
1499 LPCWSTR lpLocalName
)
1501 FIXME( "(%s, %p, %s): stub\n",
1502 debugstr_w(lpRemoteName
), lpPassword
, debugstr_w(lpLocalName
) );
1504 SetLastError(WN_NO_NETWORK
);
1505 return WN_NO_NETWORK
;
1508 /*********************************************************************
1509 * WNetAddConnection2A [MPR.@]
1511 DWORD WINAPI
WNetAddConnection2A( LPNETRESOURCEA lpNetResource
,
1512 LPCSTR lpPassword
, LPCSTR lpUserID
,
1515 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1516 lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
);
1518 SetLastError(WN_NO_NETWORK
);
1519 return WN_NO_NETWORK
;
1522 /*********************************************************************
1523 * WNetAddConnection2W [MPR.@]
1525 DWORD WINAPI
WNetAddConnection2W( LPNETRESOURCEW lpNetResource
,
1526 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1529 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1530 lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
);
1532 SetLastError(WN_NO_NETWORK
);
1533 return WN_NO_NETWORK
;
1536 /*********************************************************************
1537 * WNetAddConnection3A [MPR.@]
1539 DWORD WINAPI
WNetAddConnection3A( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1540 LPCSTR lpPassword
, LPCSTR lpUserID
,
1543 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1544 hwndOwner
, lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
);
1546 SetLastError(WN_NO_NETWORK
);
1547 return WN_NO_NETWORK
;
1550 /*********************************************************************
1551 * WNetAddConnection3W [MPR.@]
1553 DWORD WINAPI
WNetAddConnection3W( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1554 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1557 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1558 hwndOwner
, lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
);
1560 SetLastError(WN_NO_NETWORK
);
1561 return WN_NO_NETWORK
;
1564 /*****************************************************************
1565 * WNetUseConnectionA [MPR.@]
1567 DWORD WINAPI
WNetUseConnectionA( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1568 LPCSTR lpPassword
, LPCSTR lpUserID
, DWORD dwFlags
,
1569 LPSTR lpAccessName
, LPDWORD lpBufferSize
,
1572 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1573 hwndOwner
, lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
,
1574 debugstr_a(lpAccessName
), lpBufferSize
, lpResult
);
1576 SetLastError(WN_NO_NETWORK
);
1577 return WN_NO_NETWORK
;
1580 /*****************************************************************
1581 * WNetUseConnectionW [MPR.@]
1583 DWORD WINAPI
WNetUseConnectionW( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1584 LPCWSTR lpPassword
, LPCWSTR lpUserID
, DWORD dwFlags
,
1585 LPWSTR lpAccessName
, LPDWORD lpBufferSize
,
1588 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1589 hwndOwner
, lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
,
1590 debugstr_w(lpAccessName
), lpBufferSize
, lpResult
);
1592 SetLastError(WN_NO_NETWORK
);
1593 return WN_NO_NETWORK
;
1596 /*********************************************************************
1597 * WNetCancelConnectionA [MPR.@]
1599 DWORD WINAPI
WNetCancelConnectionA( LPCSTR lpName
, BOOL fForce
)
1601 FIXME( "(%s, %d), stub\n", debugstr_a(lpName
), fForce
);
1606 /*********************************************************************
1607 * WNetCancelConnectionW [MPR.@]
1609 DWORD WINAPI
WNetCancelConnectionW( LPCWSTR lpName
, BOOL fForce
)
1611 FIXME( "(%s, %d), stub\n", debugstr_w(lpName
), fForce
);
1616 /*********************************************************************
1617 * WNetCancelConnection2A [MPR.@]
1619 DWORD WINAPI
WNetCancelConnection2A( LPCSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1621 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName
), dwFlags
, fForce
);
1626 /*********************************************************************
1627 * WNetCancelConnection2W [MPR.@]
1629 DWORD WINAPI
WNetCancelConnection2W( LPCWSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1631 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName
), dwFlags
, fForce
);
1636 /*****************************************************************
1637 * WNetRestoreConnectionA [MPR.@]
1639 DWORD WINAPI
WNetRestoreConnectionA( HWND hwndOwner
, LPCSTR lpszDevice
)
1641 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_a(lpszDevice
) );
1643 SetLastError(WN_NO_NETWORK
);
1644 return WN_NO_NETWORK
;
1647 /*****************************************************************
1648 * WNetRestoreConnectionW [MPR.@]
1650 DWORD WINAPI
WNetRestoreConnectionW( HWND hwndOwner
, LPCWSTR lpszDevice
)
1652 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_w(lpszDevice
) );
1654 SetLastError(WN_NO_NETWORK
);
1655 return WN_NO_NETWORK
;
1658 /**************************************************************************
1659 * WNetGetConnectionA [MPR.@]
1662 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1663 * - WN_NOT_CONNECTED drive is a local drive
1664 * - WN_MORE_DATA buffer isn't big enough
1665 * - WN_SUCCESS success (net path in buffer)
1667 * FIXME: need to test return values under different errors
1669 DWORD WINAPI
WNetGetConnectionA( LPCSTR lpLocalName
,
1670 LPSTR lpRemoteName
, LPDWORD lpBufferSize
)
1675 ret
= WN_BAD_POINTER
;
1676 else if (!lpBufferSize
)
1677 ret
= WN_BAD_POINTER
;
1678 else if (!lpRemoteName
&& *lpBufferSize
)
1679 ret
= WN_BAD_POINTER
;
1682 int len
= MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, NULL
, 0);
1686 PWSTR wideLocalName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1690 WCHAR wideRemoteStatic
[MAX_PATH
];
1691 DWORD wideRemoteSize
= sizeof(wideRemoteStatic
) / sizeof(WCHAR
);
1693 MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, wideLocalName
, len
);
1695 /* try once without memory allocation */
1696 ret
= WNetGetConnectionW(wideLocalName
, wideRemoteStatic
,
1698 if (ret
== WN_SUCCESS
)
1700 int len
= WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1701 -1, NULL
, 0, NULL
, NULL
);
1703 if (len
<= *lpBufferSize
)
1705 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
, -1,
1706 lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1711 *lpBufferSize
= len
;
1715 else if (ret
== WN_MORE_DATA
)
1717 PWSTR wideRemote
= HeapAlloc(GetProcessHeap(), 0,
1718 wideRemoteSize
* sizeof(WCHAR
));
1722 ret
= WNetGetConnectionW(wideLocalName
, wideRemote
,
1724 if (ret
== WN_SUCCESS
)
1726 if (len
<= *lpBufferSize
)
1728 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1729 -1, lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1734 *lpBufferSize
= len
;
1738 HeapFree(GetProcessHeap(), 0, wideRemote
);
1741 ret
= WN_OUT_OF_MEMORY
;
1743 HeapFree(GetProcessHeap(), 0, wideLocalName
);
1746 ret
= WN_OUT_OF_MEMORY
;
1749 ret
= WN_BAD_LOCALNAME
;
1753 TRACE("Returning %d\n", ret
);
1757 /**************************************************************************
1758 * WNetGetConnectionW [MPR.@]
1760 * FIXME: need to test return values under different errors
1762 DWORD WINAPI
WNetGetConnectionW( LPCWSTR lpLocalName
,
1763 LPWSTR lpRemoteName
, LPDWORD lpBufferSize
)
1767 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName
), lpRemoteName
,
1771 ret
= WN_BAD_POINTER
;
1772 else if (!lpBufferSize
)
1773 ret
= WN_BAD_POINTER
;
1774 else if (!lpRemoteName
&& *lpBufferSize
)
1775 ret
= WN_BAD_POINTER
;
1776 else if (!lpLocalName
[0])
1777 ret
= WN_BAD_LOCALNAME
;
1780 if (lpLocalName
[1] == ':')
1782 switch(GetDriveTypeW(lpLocalName
))
1786 static const WCHAR unc
[] = { 'u','n','c','\\' };
1787 WCHAR rremote
[MAX_PATH
], *remote
= rremote
;
1788 if (!QueryDosDeviceW( lpLocalName
, remote
, MAX_PATH
)) remote
[0] = 0;
1789 else if (!strncmpW(remote
, unc
, 4))
1794 else if (remote
[0] != '\\' || remote
[1] != '\\')
1795 FIXME("Don't know how to convert %s to an unc\n", debugstr_w(remote
));
1797 if (strlenW(remote
) + 1 > *lpBufferSize
)
1799 *lpBufferSize
= strlenW(remote
) + 1;
1804 strcpyW( lpRemoteName
, remote
);
1805 *lpBufferSize
= strlenW(lpRemoteName
) + 1;
1810 case DRIVE_REMOVABLE
:
1813 TRACE("file is local\n");
1814 ret
= WN_NOT_CONNECTED
;
1817 ret
= WN_BAD_LOCALNAME
;
1821 ret
= WN_BAD_LOCALNAME
;
1825 TRACE("Returning %d\n", ret
);
1829 /**************************************************************************
1830 * WNetSetConnectionA [MPR.@]
1832 DWORD WINAPI
WNetSetConnectionA( LPCSTR lpName
, DWORD dwProperty
,
1835 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName
), dwProperty
, pvValue
);
1837 SetLastError(WN_NO_NETWORK
);
1838 return WN_NO_NETWORK
;
1841 /**************************************************************************
1842 * WNetSetConnectionW [MPR.@]
1844 DWORD WINAPI
WNetSetConnectionW( LPCWSTR lpName
, DWORD dwProperty
,
1847 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName
), dwProperty
, pvValue
);
1849 SetLastError(WN_NO_NETWORK
);
1850 return WN_NO_NETWORK
;
1853 /*****************************************************************
1854 * WNetGetUniversalNameA [MPR.@]
1856 DWORD WINAPI
WNetGetUniversalNameA ( LPCSTR lpLocalPath
, DWORD dwInfoLevel
,
1857 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1861 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1862 debugstr_a(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1864 switch (dwInfoLevel
)
1866 case UNIVERSAL_NAME_INFO_LEVEL
:
1868 LPUNIVERSAL_NAME_INFOA info
= lpBuffer
;
1870 size
= sizeof(*info
) + lstrlenA(lpLocalPath
) + 1;
1871 if (*lpBufferSize
< size
)
1876 info
->lpUniversalName
= (char *)info
+ sizeof(*info
);
1877 lstrcpyA(info
->lpUniversalName
, lpLocalPath
);
1878 *lpBufferSize
= size
;
1882 case REMOTE_NAME_INFO_LEVEL
:
1883 err
= WN_NO_NETWORK
;
1895 /*****************************************************************
1896 * WNetGetUniversalNameW [MPR.@]
1898 DWORD WINAPI
WNetGetUniversalNameW ( LPCWSTR lpLocalPath
, DWORD dwInfoLevel
,
1899 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1903 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1904 debugstr_w(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1906 switch (dwInfoLevel
)
1908 case UNIVERSAL_NAME_INFO_LEVEL
:
1910 LPUNIVERSAL_NAME_INFOW info
= lpBuffer
;
1912 size
= sizeof(*info
) + (lstrlenW(lpLocalPath
) + 1) * sizeof(WCHAR
);
1913 if (*lpBufferSize
< size
)
1918 info
->lpUniversalName
= (LPWSTR
)((char *)info
+ sizeof(*info
));
1919 lstrcpyW(info
->lpUniversalName
, lpLocalPath
);
1920 *lpBufferSize
= size
;
1924 case REMOTE_NAME_INFO_LEVEL
:
1925 err
= WN_NO_NETWORK
;
1933 if (err
!= WN_NO_ERROR
) SetLastError(err
);
1943 /**************************************************************************
1944 * WNetGetUserA [MPR.@]
1946 * FIXME: we should not return ourselves, but the owner of the drive lpName
1948 DWORD WINAPI
WNetGetUserA( LPCSTR lpName
, LPSTR lpUserID
, LPDWORD lpBufferSize
)
1950 if (GetUserNameA( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1951 return GetLastError();
1954 /*****************************************************************
1955 * WNetGetUserW [MPR.@]
1957 * FIXME: we should not return ourselves, but the owner of the drive lpName
1959 DWORD WINAPI
WNetGetUserW( LPCWSTR lpName
, LPWSTR lpUserID
, LPDWORD lpBufferSize
)
1961 if (GetUserNameW( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1962 return GetLastError();
1965 /*********************************************************************
1966 * WNetConnectionDialog [MPR.@]
1968 DWORD WINAPI
WNetConnectionDialog( HWND hwnd
, DWORD dwType
)
1970 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
1972 SetLastError(WN_NO_NETWORK
);
1973 return WN_NO_NETWORK
;
1976 /*********************************************************************
1977 * WNetConnectionDialog1A [MPR.@]
1979 DWORD WINAPI
WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct
)
1981 FIXME( "(%p): stub\n", lpConnDlgStruct
);
1983 SetLastError(WN_NO_NETWORK
);
1984 return WN_NO_NETWORK
;
1987 /*********************************************************************
1988 * WNetConnectionDialog1W [MPR.@]
1990 DWORD WINAPI
WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct
)
1992 FIXME( "(%p): stub\n", lpConnDlgStruct
);
1994 SetLastError(WN_NO_NETWORK
);
1995 return WN_NO_NETWORK
;
1998 /*********************************************************************
1999 * WNetDisconnectDialog [MPR.@]
2001 DWORD WINAPI
WNetDisconnectDialog( HWND hwnd
, DWORD dwType
)
2003 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2005 SetLastError(WN_NO_NETWORK
);
2006 return WN_NO_NETWORK
;
2009 /*********************************************************************
2010 * WNetDisconnectDialog1A [MPR.@]
2012 DWORD WINAPI
WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct
)
2014 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2016 SetLastError(WN_NO_NETWORK
);
2017 return WN_NO_NETWORK
;
2020 /*********************************************************************
2021 * WNetDisconnectDialog1W [MPR.@]
2023 DWORD WINAPI
WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct
)
2025 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2027 SetLastError(WN_NO_NETWORK
);
2028 return WN_NO_NETWORK
;
2031 /*********************************************************************
2032 * WNetGetLastErrorA [MPR.@]
2034 DWORD WINAPI
WNetGetLastErrorA( LPDWORD lpError
,
2035 LPSTR lpErrorBuf
, DWORD nErrorBufSize
,
2036 LPSTR lpNameBuf
, DWORD nNameBufSize
)
2038 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2039 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2041 SetLastError(WN_NO_NETWORK
);
2042 return WN_NO_NETWORK
;
2045 /*********************************************************************
2046 * WNetGetLastErrorW [MPR.@]
2048 DWORD WINAPI
WNetGetLastErrorW( LPDWORD lpError
,
2049 LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
2050 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
2052 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2053 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2055 SetLastError(WN_NO_NETWORK
);
2056 return WN_NO_NETWORK
;
2059 /*********************************************************************
2060 * WNetGetNetworkInformationA [MPR.@]
2062 DWORD WINAPI
WNetGetNetworkInformationA( LPCSTR lpProvider
,
2063 LPNETINFOSTRUCT lpNetInfoStruct
)
2067 TRACE( "(%s, %p)\n", debugstr_a(lpProvider
), lpNetInfoStruct
);
2070 ret
= WN_BAD_POINTER
;
2075 len
= MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, NULL
, 0);
2078 LPWSTR wideProvider
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2082 MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, wideProvider
,
2084 ret
= WNetGetNetworkInformationW(wideProvider
, lpNetInfoStruct
);
2085 HeapFree(GetProcessHeap(), 0, wideProvider
);
2088 ret
= WN_OUT_OF_MEMORY
;
2091 ret
= GetLastError();
2095 TRACE("Returning %d\n", ret
);
2099 /*********************************************************************
2100 * WNetGetNetworkInformationW [MPR.@]
2102 DWORD WINAPI
WNetGetNetworkInformationW( LPCWSTR lpProvider
,
2103 LPNETINFOSTRUCT lpNetInfoStruct
)
2107 TRACE( "(%s, %p)\n", debugstr_w(lpProvider
), lpNetInfoStruct
);
2110 ret
= WN_BAD_POINTER
;
2111 else if (!lpNetInfoStruct
)
2112 ret
= WN_BAD_POINTER
;
2113 else if (lpNetInfoStruct
->cbStructure
< sizeof(NETINFOSTRUCT
))
2117 if (providerTable
&& providerTable
->numProviders
)
2119 DWORD providerIndex
= _findProviderIndexW(lpProvider
);
2121 if (providerIndex
!= BAD_PROVIDER_INDEX
)
2123 lpNetInfoStruct
->cbStructure
= sizeof(NETINFOSTRUCT
);
2124 lpNetInfoStruct
->dwProviderVersion
=
2125 providerTable
->table
[providerIndex
].dwSpecVersion
;
2126 lpNetInfoStruct
->dwStatus
= NO_ERROR
;
2127 lpNetInfoStruct
->dwCharacteristics
= 0;
2128 lpNetInfoStruct
->dwHandle
= 0;
2129 lpNetInfoStruct
->wNetType
=
2130 HIWORD(providerTable
->table
[providerIndex
].dwNetType
);
2131 lpNetInfoStruct
->dwPrinters
= -1;
2132 lpNetInfoStruct
->dwDrives
= -1;
2136 ret
= WN_BAD_PROVIDER
;
2139 ret
= WN_NO_NETWORK
;
2143 TRACE("Returning %d\n", ret
);
2147 /*****************************************************************
2148 * WNetGetProviderNameA [MPR.@]
2150 DWORD WINAPI
WNetGetProviderNameA( DWORD dwNetType
,
2151 LPSTR lpProvider
, LPDWORD lpBufferSize
)
2155 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_a(lpProvider
),
2159 ret
= WN_BAD_POINTER
;
2160 else if (!lpBufferSize
)
2161 ret
= WN_BAD_POINTER
;
2168 ret
= WN_NO_NETWORK
;
2169 for (i
= 0; i
< providerTable
->numProviders
&&
2170 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2173 if (i
< providerTable
->numProviders
)
2175 DWORD sizeNeeded
= WideCharToMultiByte(CP_ACP
, 0,
2176 providerTable
->table
[i
].name
, -1, NULL
, 0, NULL
, NULL
);
2178 if (*lpBufferSize
< sizeNeeded
)
2180 *lpBufferSize
= sizeNeeded
;
2185 WideCharToMultiByte(CP_ACP
, 0, providerTable
->table
[i
].name
,
2186 -1, lpProvider
, *lpBufferSize
, NULL
, NULL
);
2188 /* FIXME: is *lpBufferSize set to the number of characters
2194 ret
= WN_NO_NETWORK
;
2198 TRACE("Returning %d\n", ret
);
2202 /*****************************************************************
2203 * WNetGetProviderNameW [MPR.@]
2205 DWORD WINAPI
WNetGetProviderNameW( DWORD dwNetType
,
2206 LPWSTR lpProvider
, LPDWORD lpBufferSize
)
2210 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_w(lpProvider
),
2214 ret
= WN_BAD_POINTER
;
2215 else if (!lpBufferSize
)
2216 ret
= WN_BAD_POINTER
;
2223 ret
= WN_NO_NETWORK
;
2224 for (i
= 0; i
< providerTable
->numProviders
&&
2225 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2228 if (i
< providerTable
->numProviders
)
2230 DWORD sizeNeeded
= strlenW(providerTable
->table
[i
].name
) + 1;
2232 if (*lpBufferSize
< sizeNeeded
)
2234 *lpBufferSize
= sizeNeeded
;
2239 strcpyW(lpProvider
, providerTable
->table
[i
].name
);
2241 /* FIXME: is *lpBufferSize set to the number of characters
2247 ret
= WN_NO_NETWORK
;
2251 TRACE("Returning %d\n", ret
);