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
27 #define WINE_MOUNTMGR_EXTENSIONS
28 #include <ddk/mountmgr.h>
29 #include <wine/unicode.h>
31 /* Data structures representing network service providers. Assumes only one
32 * thread creates them, and that they are constant for the life of the process
33 * (and therefore doesn't synchronize access).
34 * FIXME: only basic provider data and enumeration-related data are implemented
35 * so far, need to implement the rest too.
37 typedef struct _WNetProvider
45 PF_NPOpenEnum openEnum
;
46 PF_NPEnumResource enumResource
;
47 PF_NPCloseEnum closeEnum
;
48 PF_NPGetResourceInformation getResourceInformation
;
49 } WNetProvider
, *PWNetProvider
;
51 typedef struct _WNetProviderTable
56 WNetProvider table
[1];
57 } WNetProviderTable
, *PWNetProviderTable
;
59 #define WNET_ENUMERATOR_TYPE_NULL 0
60 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
61 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
62 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
64 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
65 * the enumeration; it represents one of the following types:
66 * - a 'null' enumeration, one that contains no members
67 * - a global enumeration, one that's executed across all providers
68 * - a provider-specific enumeration, one that's only executed by a single
70 * - a context enumeration. I know this contradicts what I just said about
71 * there being no correspondence between the scope and the type, but it's
72 * necessary for the special case that a "Entire Network" entry needs to
73 * be enumerated in an enumeration of the context scope. Thus an enumeration
74 * of the context scope results in a context type enumerator, which morphs
75 * into a global enumeration (so the enumeration continues across all
78 typedef struct _WNetEnumerator
88 } WNetEnumerator
, *PWNetEnumerator
;
90 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
92 /* Returns an index (into the global WNetProviderTable) of the provider with
93 * the given name, or BAD_PROVIDER_INDEX if not found.
95 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
);
97 static PWNetProviderTable providerTable
;
100 * Global provider table functions
103 static void _tryLoadProvider(PCWSTR provider
)
105 static const WCHAR servicePrefix
[] = { 'S','y','s','t','e','m','\\',
106 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
107 'S','e','r','v','i','c','e','s','\\',0 };
108 static const WCHAR serviceFmt
[] = { '%','s','%','s','\\',
109 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
110 WCHAR serviceName
[MAX_PATH
];
113 TRACE("%s\n", debugstr_w(provider
));
114 snprintfW(serviceName
, sizeof(serviceName
) / sizeof(WCHAR
), serviceFmt
,
115 servicePrefix
, provider
);
116 serviceName
[sizeof(serviceName
) / sizeof(WCHAR
) - 1] = '\0';
117 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, serviceName
, 0, KEY_READ
, &hKey
) ==
120 static const WCHAR szProviderPath
[] = { 'P','r','o','v','i','d','e','r',
122 WCHAR providerPath
[MAX_PATH
];
123 DWORD type
, size
= sizeof(providerPath
);
125 if (RegQueryValueExW(hKey
, szProviderPath
, NULL
, &type
,
126 (LPBYTE
)providerPath
, &size
) == ERROR_SUCCESS
&& (type
== REG_SZ
|| type
== REG_EXPAND_SZ
))
128 static const WCHAR szProviderName
[] = { 'N','a','m','e',0 };
131 if (type
== REG_EXPAND_SZ
)
133 WCHAR path
[MAX_PATH
];
134 if (ExpandEnvironmentStringsW(providerPath
, path
, MAX_PATH
)) lstrcpyW( providerPath
, path
);
138 RegQueryValueExW(hKey
, szProviderName
, NULL
, NULL
, NULL
, &size
);
141 name
= HeapAlloc(GetProcessHeap(), 0, size
);
142 if (RegQueryValueExW(hKey
, szProviderName
, NULL
, &type
,
143 (LPBYTE
)name
, &size
) != ERROR_SUCCESS
|| type
!= REG_SZ
)
145 HeapFree(GetProcessHeap(), 0, name
);
151 HMODULE hLib
= LoadLibraryW(providerPath
);
155 PF_NPGetCaps getCaps
= (PF_NPGetCaps
)GetProcAddress(hLib
,
158 TRACE("loaded lib %p\n", hLib
);
161 PWNetProvider provider
=
162 &providerTable
->table
[providerTable
->numProviders
];
164 provider
->hLib
= hLib
;
165 provider
->name
= name
;
166 TRACE("name is %s\n", debugstr_w(name
));
167 provider
->getCaps
= getCaps
;
168 provider
->dwSpecVersion
= getCaps(WNNC_SPEC_VERSION
);
169 provider
->dwNetType
= getCaps(WNNC_NET_TYPE
);
170 TRACE("net type is 0x%08x\n", provider
->dwNetType
);
171 provider
->dwEnumScopes
= getCaps(WNNC_ENUMERATION
);
172 if (provider
->dwEnumScopes
)
174 TRACE("supports enumeration\n");
175 provider
->openEnum
= (PF_NPOpenEnum
)
176 GetProcAddress(hLib
, "NPOpenEnum");
177 TRACE("openEnum is %p\n", provider
->openEnum
);
178 provider
->enumResource
= (PF_NPEnumResource
)
179 GetProcAddress(hLib
, "NPEnumResource");
180 TRACE("enumResource is %p\n",
181 provider
->enumResource
);
182 provider
->closeEnum
= (PF_NPCloseEnum
)
183 GetProcAddress(hLib
, "NPCloseEnum");
184 TRACE("closeEnum is %p\n", provider
->closeEnum
);
185 provider
->getResourceInformation
= (PF_NPGetResourceInformation
)
186 GetProcAddress(hLib
, "NPGetResourceInformation");
187 TRACE("getResourceInformation is %p\n",
188 provider
->getResourceInformation
);
189 if (!provider
->openEnum
|| !provider
->enumResource
190 || !provider
->closeEnum
)
192 provider
->openEnum
= NULL
;
193 provider
->enumResource
= NULL
;
194 provider
->closeEnum
= NULL
;
195 provider
->dwEnumScopes
= 0;
196 WARN("Couldn't load enumeration functions\n");
199 providerTable
->numProviders
++;
203 WARN("Provider %s didn't export NPGetCaps\n",
204 debugstr_w(provider
));
205 HeapFree(GetProcessHeap(), 0, name
);
211 WARN("Couldn't load library %s for provider %s\n",
212 debugstr_w(providerPath
), debugstr_w(provider
));
213 HeapFree(GetProcessHeap(), 0, name
);
218 WARN("Couldn't get provider name for provider %s\n",
219 debugstr_w(provider
));
223 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath
));
227 WARN("Couldn't open service key for provider %s\n",
228 debugstr_w(provider
));
231 void wnetInit(HINSTANCE hInstDll
)
233 static const WCHAR providerOrderKey
[] = { 'S','y','s','t','e','m','\\',
234 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
235 'C','o','n','t','r','o','l','\\',
236 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
237 'O','r','d','e','r',0 };
238 static const WCHAR providerOrder
[] = { 'P','r','o','v','i','d','e','r',
239 'O','r','d','e','r',0 };
242 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, providerOrderKey
, 0, KEY_READ
, &hKey
)
247 RegQueryValueExW(hKey
, providerOrder
, NULL
, NULL
, NULL
, &size
);
250 PWSTR providers
= HeapAlloc(GetProcessHeap(), 0, size
);
256 if (RegQueryValueExW(hKey
, providerOrder
, NULL
, &type
,
257 (LPBYTE
)providers
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
262 TRACE("provider order is %s\n", debugstr_w(providers
));
263 /* first count commas as a heuristic for how many to
264 * allocate space for */
265 for (ptr
= providers
, numToAllocate
= 1; ptr
; )
267 ptr
= strchrW(ptr
, ',');
274 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
275 sizeof(WNetProviderTable
)
276 + (numToAllocate
- 1) * sizeof(WNetProvider
));
280 int entireNetworkLen
;
281 LPCWSTR stringresource
;
283 entireNetworkLen
= LoadStringW(hInstDll
,
284 IDS_ENTIRENETWORK
, (LPWSTR
)&stringresource
, 0);
285 providerTable
->entireNetwork
= HeapAlloc(
286 GetProcessHeap(), 0, (entireNetworkLen
+ 1) *
288 if (providerTable
->entireNetwork
)
290 memcpy(providerTable
->entireNetwork
, stringresource
, entireNetworkLen
*sizeof(WCHAR
));
291 providerTable
->entireNetwork
[entireNetworkLen
] = 0;
293 providerTable
->numAllocated
= numToAllocate
;
294 for (ptr
= providers
; ptr
; )
297 ptr
= strchrW(ptr
, ',');
300 _tryLoadProvider(ptrPrev
);
304 HeapFree(GetProcessHeap(), 0, providers
);
317 for (i
= 0; i
< providerTable
->numProviders
; i
++)
319 HeapFree(GetProcessHeap(), 0, providerTable
->table
[i
].name
);
320 FreeModule(providerTable
->table
[i
].hLib
);
322 HeapFree(GetProcessHeap(), 0, providerTable
->entireNetwork
);
323 HeapFree(GetProcessHeap(), 0, providerTable
);
324 providerTable
= NULL
;
328 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
)
330 DWORD ret
= BAD_PROVIDER_INDEX
;
332 if (providerTable
&& providerTable
->numProviders
)
336 for (i
= 0; i
< providerTable
->numProviders
&&
337 ret
== BAD_PROVIDER_INDEX
; i
++)
338 if (!strcmpW(lpProvider
, providerTable
->table
[i
].name
))
348 static LPNETRESOURCEW
_copyNetResourceForEnumW(LPNETRESOURCEW lpNet
)
354 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW
));
360 ret
->lpLocalName
= ret
->lpComment
= ret
->lpProvider
= NULL
;
361 if (lpNet
->lpRemoteName
)
363 len
= strlenW(lpNet
->lpRemoteName
) + 1;
364 ret
->lpRemoteName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
365 if (ret
->lpRemoteName
)
366 strcpyW(ret
->lpRemoteName
, lpNet
->lpRemoteName
);
375 static void _freeEnumNetResource(LPNETRESOURCEW lpNet
)
379 HeapFree(GetProcessHeap(), 0, lpNet
->lpRemoteName
);
380 HeapFree(GetProcessHeap(), 0, lpNet
);
384 static PWNetEnumerator
_createNullEnumerator(void)
386 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
387 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
390 ret
->enumType
= WNET_ENUMERATOR_TYPE_NULL
;
394 static PWNetEnumerator
_createGlobalEnumeratorW(DWORD dwScope
, DWORD dwType
,
395 DWORD dwUsage
, LPNETRESOURCEW lpNet
)
397 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
398 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
402 ret
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
403 ret
->dwScope
= dwScope
;
404 ret
->dwType
= dwType
;
405 ret
->dwUsage
= dwUsage
;
406 ret
->lpNet
= _copyNetResourceForEnumW(lpNet
);
411 static PWNetEnumerator
_createProviderEnumerator(DWORD dwScope
, DWORD dwType
,
412 DWORD dwUsage
, DWORD index
, HANDLE handle
)
416 if (!providerTable
|| index
>= providerTable
->numProviders
)
420 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
423 ret
->enumType
= WNET_ENUMERATOR_TYPE_PROVIDER
;
424 ret
->providerIndex
= index
;
425 ret
->dwScope
= dwScope
;
426 ret
->dwType
= dwType
;
427 ret
->dwUsage
= dwUsage
;
428 ret
->handle
= handle
;
434 static PWNetEnumerator
_createContextEnumerator(DWORD dwScope
, DWORD dwType
,
437 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
438 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
442 ret
->enumType
= WNET_ENUMERATOR_TYPE_CONTEXT
;
443 ret
->dwScope
= dwScope
;
444 ret
->dwType
= dwType
;
445 ret
->dwUsage
= dwUsage
;
450 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
451 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
452 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
453 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
454 * if not all members of the array could be thunked, and something else on
457 static DWORD
_thunkNetResourceArrayWToA(const NETRESOURCEW
*lpNetArrayIn
,
458 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
460 DWORD i
, numToThunk
, totalBytes
, ret
;
464 return WN_BAD_POINTER
;
466 return WN_BAD_POINTER
;
470 return WN_BAD_POINTER
;
472 return WN_BAD_POINTER
;
474 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
476 const NETRESOURCEW
*lpNet
= lpNetArrayIn
+ i
;
478 totalBytes
+= sizeof(NETRESOURCEA
);
479 if (lpNet
->lpLocalName
)
480 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpLocalName
,
481 -1, NULL
, 0, NULL
, NULL
);
482 if (lpNet
->lpRemoteName
)
483 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpRemoteName
,
484 -1, NULL
, 0, NULL
, NULL
);
485 if (lpNet
->lpComment
)
486 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpComment
,
487 -1, NULL
, 0, NULL
, NULL
);
488 if (lpNet
->lpProvider
)
489 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpProvider
,
490 -1, NULL
, 0, NULL
, NULL
);
491 if (totalBytes
< *lpBufferSize
)
494 strNext
= (LPSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEA
));
495 for (i
= 0; i
< numToThunk
; i
++)
497 LPNETRESOURCEA lpNetOut
= (LPNETRESOURCEA
)lpBuffer
+ i
;
498 const NETRESOURCEW
*lpNetIn
= lpNetArrayIn
+ i
;
500 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEA
));
501 /* lie about string lengths, we already verified how many
502 * we have space for above
504 if (lpNetIn
->lpLocalName
)
506 lpNetOut
->lpLocalName
= strNext
;
507 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpLocalName
, -1,
508 lpNetOut
->lpLocalName
, *lpBufferSize
, NULL
, NULL
);
510 if (lpNetIn
->lpRemoteName
)
512 lpNetOut
->lpRemoteName
= strNext
;
513 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpRemoteName
, -1,
514 lpNetOut
->lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
516 if (lpNetIn
->lpComment
)
518 lpNetOut
->lpComment
= strNext
;
519 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpComment
, -1,
520 lpNetOut
->lpComment
, *lpBufferSize
, NULL
, NULL
);
522 if (lpNetIn
->lpProvider
)
524 lpNetOut
->lpProvider
= strNext
;
525 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpProvider
, -1,
526 lpNetOut
->lpProvider
, *lpBufferSize
, NULL
, NULL
);
529 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
530 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
535 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
536 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
537 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
538 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
539 * if not all members of the array could be thunked, and something else on
542 static DWORD
_thunkNetResourceArrayAToW(const NETRESOURCEA
*lpNetArrayIn
,
543 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
545 DWORD i
, numToThunk
, totalBytes
, ret
;
549 return WN_BAD_POINTER
;
551 return WN_BAD_POINTER
;
555 return WN_BAD_POINTER
;
557 return WN_BAD_POINTER
;
559 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
561 const NETRESOURCEA
*lpNet
= lpNetArrayIn
+ i
;
563 totalBytes
+= sizeof(NETRESOURCEW
);
564 if (lpNet
->lpLocalName
)
565 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpLocalName
,
566 -1, NULL
, 0) * sizeof(WCHAR
);
567 if (lpNet
->lpRemoteName
)
568 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpRemoteName
,
569 -1, NULL
, 0) * sizeof(WCHAR
);
570 if (lpNet
->lpComment
)
571 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpComment
,
572 -1, NULL
, 0) * sizeof(WCHAR
);
573 if (lpNet
->lpProvider
)
574 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpProvider
,
575 -1, NULL
, 0) * sizeof(WCHAR
);
576 if (totalBytes
< *lpBufferSize
)
579 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEW
));
580 for (i
= 0; i
< numToThunk
; i
++)
582 LPNETRESOURCEW lpNetOut
= (LPNETRESOURCEW
)lpBuffer
+ i
;
583 const NETRESOURCEA
*lpNetIn
= lpNetArrayIn
+ i
;
585 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEW
));
586 /* lie about string lengths, we already verified how many
587 * we have space for above
589 if (lpNetIn
->lpLocalName
)
591 lpNetOut
->lpLocalName
= strNext
;
592 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpLocalName
,
593 -1, lpNetOut
->lpLocalName
, *lpBufferSize
);
595 if (lpNetIn
->lpRemoteName
)
597 lpNetOut
->lpRemoteName
= strNext
;
598 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpRemoteName
,
599 -1, lpNetOut
->lpRemoteName
, *lpBufferSize
);
601 if (lpNetIn
->lpComment
)
603 lpNetOut
->lpComment
= strNext
;
604 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpComment
,
605 -1, lpNetOut
->lpComment
, *lpBufferSize
);
607 if (lpNetIn
->lpProvider
)
609 lpNetOut
->lpProvider
= strNext
;
610 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpProvider
,
611 -1, lpNetOut
->lpProvider
, *lpBufferSize
);
614 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
615 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
620 /*********************************************************************
621 * WNetOpenEnumA [MPR.@]
623 * See comments for WNetOpenEnumW.
625 DWORD WINAPI
WNetOpenEnumA( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
626 LPNETRESOURCEA lpNet
, LPHANDLE lphEnum
)
630 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
631 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
634 ret
= WN_BAD_POINTER
;
635 else if (!providerTable
|| providerTable
->numProviders
== 0)
644 LPNETRESOURCEW lpNetWide
= NULL
;
646 DWORD size
= sizeof(buf
), count
= 1;
647 BOOL allocated
= FALSE
;
649 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, buf
, &size
);
650 if (ret
== WN_MORE_DATA
)
652 lpNetWide
= HeapAlloc(GetProcessHeap(), 0,
656 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, lpNetWide
,
661 ret
= WN_OUT_OF_MEMORY
;
663 else if (ret
== WN_SUCCESS
)
664 lpNetWide
= (LPNETRESOURCEW
)buf
;
665 if (ret
== WN_SUCCESS
)
666 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, lpNetWide
,
669 HeapFree(GetProcessHeap(), 0, lpNetWide
);
672 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, NULL
, lphEnum
);
676 TRACE("Returning %d\n", ret
);
680 /*********************************************************************
681 * WNetOpenEnumW [MPR.@]
683 * Network enumeration has way too many parameters, so I'm not positive I got
684 * them right. What I've got so far:
686 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
687 * all the network providers should be enumerated.
689 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
690 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
691 * lpProvider is set, all the network providers should be enumerated.
692 * (This means the enumeration is a list of network providers, not that the
693 * enumeration is passed on to the providers.)
695 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
696 * resource matches the "Entire Network" resource (no remote name, no
697 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
698 * enumeration is done on every network provider.
700 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
701 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
702 * only to the given network provider.
704 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
705 * no lpProvider is set, enumeration will be tried on every network provider,
706 * in the order in which they're loaded.
708 * - The LPNETRESOURCE should be disregarded for scopes besides
709 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
710 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
712 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
713 * resource in the enumerated list, as well as any machines in your
714 * workgroup. The machines in your workgroup come from doing a
715 * RESOURCE_CONTEXT enumeration of every Network Provider.
717 DWORD WINAPI
WNetOpenEnumW( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
718 LPNETRESOURCEW lpNet
, LPHANDLE lphEnum
)
722 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
723 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
726 ret
= WN_BAD_POINTER
;
727 else if (!providerTable
|| providerTable
->numProviders
== 0)
736 case RESOURCE_GLOBALNET
:
739 if (lpNet
->lpProvider
)
741 DWORD index
= _findProviderIndexW(lpNet
->lpProvider
);
743 if (index
!= BAD_PROVIDER_INDEX
)
745 if (providerTable
->table
[index
].openEnum
&&
746 providerTable
->table
[index
].dwEnumScopes
& WNNC_ENUM_GLOBAL
)
750 ret
= providerTable
->table
[index
].openEnum(
751 dwScope
, dwType
, dwUsage
, lpNet
, &handle
);
752 if (ret
== WN_SUCCESS
)
754 *lphEnum
= _createProviderEnumerator(
755 dwScope
, dwType
, dwUsage
, index
, handle
);
756 ret
= *lphEnum
? WN_SUCCESS
:
761 ret
= WN_NOT_SUPPORTED
;
764 ret
= WN_BAD_PROVIDER
;
766 else if (lpNet
->lpRemoteName
)
768 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
769 dwType
, dwUsage
, lpNet
);
770 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
774 if (lpNet
->lpComment
&& !strcmpW(lpNet
->lpComment
,
775 providerTable
->entireNetwork
))
777 /* comment matches the "Entire Network", enumerate
778 * global scope of every provider
780 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
781 dwType
, dwUsage
, lpNet
);
785 /* this is the same as not having passed lpNet */
786 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
787 dwType
, dwUsage
, NULL
);
789 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
794 *lphEnum
= _createGlobalEnumeratorW(dwScope
, dwType
,
796 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
799 case RESOURCE_CONTEXT
:
800 *lphEnum
= _createContextEnumerator(dwScope
, dwType
, dwUsage
);
801 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
803 case RESOURCE_REMEMBERED
:
804 case RESOURCE_CONNECTED
:
805 *lphEnum
= _createNullEnumerator();
806 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
809 WARN("unknown scope 0x%08x\n", dwScope
);
815 TRACE("Returning %d\n", ret
);
819 /*********************************************************************
820 * WNetEnumResourceA [MPR.@]
822 DWORD WINAPI
WNetEnumResourceA( HANDLE hEnum
, LPDWORD lpcCount
,
823 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
827 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
830 ret
= WN_BAD_POINTER
;
832 ret
= WN_BAD_POINTER
;
834 ret
= WN_BAD_POINTER
;
835 else if (!lpBufferSize
)
836 ret
= WN_BAD_POINTER
;
837 else if (*lpBufferSize
< sizeof(NETRESOURCEA
))
839 *lpBufferSize
= sizeof(NETRESOURCEA
);
844 DWORD localCount
= *lpcCount
, localSize
= *lpBufferSize
;
845 LPVOID localBuffer
= HeapAlloc(GetProcessHeap(), 0, localSize
);
849 ret
= WNetEnumResourceW(hEnum
, &localCount
, localBuffer
,
851 if (ret
== WN_SUCCESS
|| (ret
== WN_MORE_DATA
&& localCount
!= -1))
853 /* FIXME: this isn't necessarily going to work in the case of
854 * WN_MORE_DATA, because our enumerator may have moved on to
855 * the next provider. MSDN states that a large (16KB) buffer
856 * size is the appropriate usage of this function, so
857 * hopefully it won't be an issue.
859 ret
= _thunkNetResourceArrayWToA(localBuffer
, &localCount
,
860 lpBuffer
, lpBufferSize
);
861 *lpcCount
= localCount
;
863 HeapFree(GetProcessHeap(), 0, localBuffer
);
866 ret
= WN_OUT_OF_MEMORY
;
870 TRACE("Returning %d\n", ret
);
874 static DWORD
_countProviderBytesW(PWNetProvider provider
)
880 ret
= sizeof(NETRESOURCEW
);
881 ret
+= 2 * (strlenW(provider
->name
) + 1) * sizeof(WCHAR
);
888 static DWORD
_enumerateProvidersW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
889 LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
894 return WN_BAD_POINTER
;
895 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
898 return WN_BAD_POINTER
;
900 return WN_BAD_POINTER
;
902 return WN_BAD_POINTER
;
903 if (*lpBufferSize
< sizeof(NETRESOURCEA
))
906 if (!providerTable
|| enumerator
->providerIndex
>=
907 providerTable
->numProviders
)
908 ret
= WN_NO_MORE_ENTRIES
;
911 DWORD bytes
= 0, count
= 0, countLimit
, i
;
912 LPNETRESOURCEW resource
;
915 countLimit
= *lpcCount
== -1 ?
916 providerTable
->numProviders
- enumerator
->providerIndex
: *lpcCount
;
917 while (count
< countLimit
&& bytes
< *lpBufferSize
)
919 DWORD bytesNext
= _countProviderBytesW(
920 &providerTable
->table
[count
+ enumerator
->providerIndex
]);
922 if (bytes
+ bytesNext
< *lpBufferSize
)
928 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ count
* sizeof(NETRESOURCEW
));
929 for (i
= 0, resource
= lpBuffer
; i
< count
; i
++, resource
++)
931 resource
->dwScope
= RESOURCE_GLOBALNET
;
932 resource
->dwType
= RESOURCETYPE_ANY
;
933 resource
->dwDisplayType
= RESOURCEDISPLAYTYPE_NETWORK
;
934 resource
->dwUsage
= RESOURCEUSAGE_CONTAINER
|
935 RESOURCEUSAGE_RESERVED
;
936 resource
->lpLocalName
= NULL
;
937 resource
->lpRemoteName
= strNext
;
938 strcpyW(resource
->lpRemoteName
,
939 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
940 strNext
+= strlenW(resource
->lpRemoteName
) + 1;
941 resource
->lpComment
= NULL
;
942 resource
->lpProvider
= strNext
;
943 strcpyW(resource
->lpProvider
,
944 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
945 strNext
+= strlenW(resource
->lpProvider
) + 1;
947 enumerator
->providerIndex
+= count
;
949 ret
= count
> 0 ? WN_SUCCESS
: WN_MORE_DATA
;
951 TRACE("Returning %d\n", ret
);
955 /* Advances the enumerator (assumed to be a global enumerator) to the next
956 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
957 * not open a handle with the next provider.
958 * If the existing handle is NULL, may leave the enumerator unchanged, since
959 * the current provider may support the desired scope.
960 * If the existing handle is not NULL, closes it before moving on.
961 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
962 * provider, and another error on failure.
964 static DWORD
_globalEnumeratorAdvance(PWNetEnumerator enumerator
)
967 return WN_BAD_POINTER
;
968 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
970 if (!providerTable
|| enumerator
->providerIndex
>=
971 providerTable
->numProviders
)
972 return WN_NO_MORE_ENTRIES
;
974 if (enumerator
->providerDone
)
977 enumerator
->providerDone
= FALSE
;
978 if (enumerator
->handle
)
980 providerTable
->table
[enumerator
->providerIndex
].closeEnum(
982 enumerator
->handle
= NULL
;
983 enumerator
->providerIndex
++;
985 if (enumerator
->dwScope
== RESOURCE_CONNECTED
)
986 dwEnum
= WNNC_ENUM_LOCAL
;
987 else if (enumerator
->dwScope
== RESOURCE_GLOBALNET
)
988 dwEnum
= WNNC_ENUM_GLOBAL
;
989 else if (enumerator
->dwScope
== RESOURCE_CONTEXT
)
990 dwEnum
= WNNC_ENUM_CONTEXT
;
991 for (; enumerator
->providerIndex
< providerTable
->numProviders
&&
992 !(providerTable
->table
[enumerator
->providerIndex
].dwEnumScopes
993 & dwEnum
); enumerator
->providerIndex
++)
996 return enumerator
->providerIndex
< providerTable
->numProviders
?
997 WN_SUCCESS
: WN_NO_MORE_ENTRIES
;
1000 /* "Passes through" call to the next provider that supports the enumeration
1002 * FIXME: if one call to a provider's enumerator succeeds while there's still
1003 * space in lpBuffer, I don't call to the next provider. The caller may not
1004 * expect that it should call EnumResourceW again with a return value of
1005 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1006 * may have to be moved around a bit, ick.
1008 static DWORD
_enumerateGlobalPassthroughW(PWNetEnumerator enumerator
,
1009 LPDWORD lpcCount
, LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1014 return WN_BAD_POINTER
;
1015 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1016 return WN_BAD_VALUE
;
1018 return WN_BAD_POINTER
;
1020 return WN_BAD_POINTER
;
1022 return WN_BAD_POINTER
;
1023 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1024 return WN_MORE_DATA
;
1026 ret
= _globalEnumeratorAdvance(enumerator
);
1027 if (ret
== WN_SUCCESS
)
1029 ret
= providerTable
->table
[enumerator
->providerIndex
].
1030 openEnum(enumerator
->dwScope
, enumerator
->dwType
,
1031 enumerator
->dwUsage
, enumerator
->lpNet
,
1032 &enumerator
->handle
);
1033 if (ret
== WN_SUCCESS
)
1035 ret
= providerTable
->table
[enumerator
->providerIndex
].
1036 enumResource(enumerator
->handle
, lpcCount
, lpBuffer
,
1038 if (ret
!= WN_MORE_DATA
)
1039 enumerator
->providerDone
= TRUE
;
1042 TRACE("Returning %d\n", ret
);
1046 static DWORD
_enumerateGlobalW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1047 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1052 return WN_BAD_POINTER
;
1053 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1054 return WN_BAD_VALUE
;
1056 return WN_BAD_POINTER
;
1058 return WN_BAD_POINTER
;
1060 return WN_BAD_POINTER
;
1061 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1062 return WN_MORE_DATA
;
1064 return WN_NO_NETWORK
;
1066 switch (enumerator
->dwScope
)
1068 case RESOURCE_GLOBALNET
:
1069 if (enumerator
->lpNet
)
1070 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
,
1071 lpBuffer
, lpBufferSize
);
1073 ret
= _enumerateProvidersW(enumerator
, lpcCount
, lpBuffer
,
1076 case RESOURCE_CONTEXT
:
1077 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
, lpBuffer
,
1081 WARN("unexpected scope 0x%08x\n", enumerator
->dwScope
);
1082 ret
= WN_NO_MORE_ENTRIES
;
1084 TRACE("Returning %d\n", ret
);
1088 static DWORD
_enumerateProviderW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1089 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1092 return WN_BAD_POINTER
;
1093 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_PROVIDER
)
1094 return WN_BAD_VALUE
;
1095 if (!enumerator
->handle
)
1096 return WN_BAD_VALUE
;
1098 return WN_BAD_POINTER
;
1100 return WN_BAD_POINTER
;
1102 return WN_BAD_POINTER
;
1104 return WN_NO_NETWORK
;
1105 if (enumerator
->providerIndex
>= providerTable
->numProviders
)
1106 return WN_NO_MORE_ENTRIES
;
1107 if (!providerTable
->table
[enumerator
->providerIndex
].enumResource
)
1108 return WN_BAD_VALUE
;
1109 return providerTable
->table
[enumerator
->providerIndex
].enumResource(
1110 enumerator
->handle
, lpcCount
, lpBuffer
, lpBufferSize
);
1113 static DWORD
_enumerateContextW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1114 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1117 size_t cchEntireNetworkLen
, bytesNeeded
;
1120 return WN_BAD_POINTER
;
1121 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_CONTEXT
)
1122 return WN_BAD_VALUE
;
1124 return WN_BAD_POINTER
;
1126 return WN_BAD_POINTER
;
1128 return WN_BAD_POINTER
;
1130 return WN_NO_NETWORK
;
1132 cchEntireNetworkLen
= strlenW(providerTable
->entireNetwork
) + 1;
1133 bytesNeeded
= sizeof(NETRESOURCEW
) + cchEntireNetworkLen
* sizeof(WCHAR
);
1134 if (*lpBufferSize
< bytesNeeded
)
1136 *lpBufferSize
= bytesNeeded
;
1141 LPNETRESOURCEW lpNet
= lpBuffer
;
1143 lpNet
->dwScope
= RESOURCE_GLOBALNET
;
1144 lpNet
->dwType
= enumerator
->dwType
;
1145 lpNet
->dwDisplayType
= RESOURCEDISPLAYTYPE_ROOT
;
1146 lpNet
->dwUsage
= RESOURCEUSAGE_CONTAINER
;
1147 lpNet
->lpLocalName
= NULL
;
1148 lpNet
->lpRemoteName
= NULL
;
1149 lpNet
->lpProvider
= NULL
;
1150 /* odd, but correct: put comment at end of buffer, so it won't get
1151 * overwritten by subsequent calls to a provider's enumResource
1153 lpNet
->lpComment
= (LPWSTR
)((LPBYTE
)lpBuffer
+ *lpBufferSize
-
1154 (cchEntireNetworkLen
* sizeof(WCHAR
)));
1155 strcpyW(lpNet
->lpComment
, providerTable
->entireNetwork
);
1158 if (ret
== WN_SUCCESS
)
1160 DWORD bufferSize
= *lpBufferSize
- bytesNeeded
;
1162 /* "Entire Network" entry enumerated--morph this into a global
1163 * enumerator. enumerator->lpNet continues to be NULL, since it has
1164 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1166 enumerator
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
1167 ret
= _enumerateGlobalW(enumerator
, lpcCount
,
1168 (LPBYTE
)lpBuffer
+ bytesNeeded
, &bufferSize
);
1169 if (ret
== WN_SUCCESS
)
1171 /* reflect the fact that we already enumerated "Entire Network" */
1173 *lpBufferSize
= bufferSize
+ bytesNeeded
;
1177 /* the provider enumeration failed, but we already succeeded in
1178 * enumerating "Entire Network"--leave type as global to allow a
1179 * retry, but indicate success with a count of one.
1183 *lpBufferSize
= bytesNeeded
;
1186 TRACE("Returning %d\n", ret
);
1190 /*********************************************************************
1191 * WNetEnumResourceW [MPR.@]
1193 DWORD WINAPI
WNetEnumResourceW( HANDLE hEnum
, LPDWORD lpcCount
,
1194 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1198 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
1201 ret
= WN_BAD_POINTER
;
1203 ret
= WN_BAD_POINTER
;
1205 ret
= WN_BAD_POINTER
;
1206 else if (!lpBufferSize
)
1207 ret
= WN_BAD_POINTER
;
1208 else if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1210 *lpBufferSize
= sizeof(NETRESOURCEW
);
1215 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1217 switch (enumerator
->enumType
)
1219 case WNET_ENUMERATOR_TYPE_NULL
:
1220 ret
= WN_NO_MORE_ENTRIES
;
1222 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1223 ret
= _enumerateGlobalW(enumerator
, lpcCount
, lpBuffer
,
1226 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1227 ret
= _enumerateProviderW(enumerator
, lpcCount
, lpBuffer
,
1230 case WNET_ENUMERATOR_TYPE_CONTEXT
:
1231 ret
= _enumerateContextW(enumerator
, lpcCount
, lpBuffer
,
1235 WARN("bogus enumerator type!\n");
1236 ret
= WN_NO_NETWORK
;
1241 TRACE("Returning %d\n", ret
);
1245 /*********************************************************************
1246 * WNetCloseEnum [MPR.@]
1248 DWORD WINAPI
WNetCloseEnum( HANDLE hEnum
)
1252 TRACE( "(%p)\n", hEnum
);
1256 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1258 switch (enumerator
->enumType
)
1260 case WNET_ENUMERATOR_TYPE_NULL
:
1263 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1264 if (enumerator
->lpNet
)
1265 _freeEnumNetResource(enumerator
->lpNet
);
1266 if (enumerator
->handle
)
1267 providerTable
->table
[enumerator
->providerIndex
].
1268 closeEnum(enumerator
->handle
);
1271 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1272 if (enumerator
->handle
)
1273 providerTable
->table
[enumerator
->providerIndex
].
1274 closeEnum(enumerator
->handle
);
1278 WARN("bogus enumerator type!\n");
1279 ret
= WN_BAD_HANDLE
;
1281 HeapFree(GetProcessHeap(), 0, hEnum
);
1284 ret
= WN_BAD_HANDLE
;
1287 TRACE("Returning %d\n", ret
);
1291 /*********************************************************************
1292 * WNetGetResourceInformationA [MPR.@]
1294 * See WNetGetResourceInformationW
1296 DWORD WINAPI
WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource
,
1297 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1302 TRACE( "(%p, %p, %p, %p)\n",
1303 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1305 if (!providerTable
|| providerTable
->numProviders
== 0)
1306 ret
= WN_NO_NETWORK
;
1307 else if (lpNetResource
)
1309 LPNETRESOURCEW lpNetResourceW
= NULL
;
1310 DWORD size
= 1024, count
= 1;
1313 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1314 ret
= _thunkNetResourceArrayAToW(lpNetResource
, &count
, lpNetResourceW
, &size
);
1315 if (ret
== WN_MORE_DATA
)
1317 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1318 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1320 ret
= _thunkNetResourceArrayAToW(lpNetResource
,
1321 &count
, lpNetResourceW
, &size
);
1323 ret
= WN_OUT_OF_MEMORY
;
1325 if (ret
== WN_SUCCESS
)
1327 LPWSTR lpSystemW
= NULL
;
1330 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1333 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1334 lpBufferW
, &size
, &lpSystemW
);
1335 if (ret
== WN_MORE_DATA
)
1337 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1338 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1340 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1341 lpBufferW
, &size
, &lpSystemW
);
1343 ret
= WN_OUT_OF_MEMORY
;
1345 if (ret
== WN_SUCCESS
)
1347 ret
= _thunkNetResourceArrayWToA(lpBufferW
,
1348 &count
, lpBuffer
, cbBuffer
);
1349 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1350 lpNetResourceW
= lpBufferW
;
1351 size
= sizeof(NETRESOURCEA
);
1352 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpRemoteName
,
1353 -1, NULL
, 0, NULL
, NULL
);
1354 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpProvider
,
1355 -1, NULL
, 0, NULL
, NULL
);
1357 len
= WideCharToMultiByte(CP_ACP
, 0, lpSystemW
,
1358 -1, NULL
, 0, NULL
, NULL
);
1359 if ((len
) && ( size
+ len
< *cbBuffer
))
1361 *lplpSystem
= (char*)lpBuffer
+ *cbBuffer
- len
;
1362 WideCharToMultiByte(CP_ACP
, 0, lpSystemW
, -1,
1363 *lplpSystem
, len
, NULL
, NULL
);
1370 ret
= WN_OUT_OF_MEMORY
;
1371 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1374 ret
= WN_OUT_OF_MEMORY
;
1375 HeapFree(GetProcessHeap(), 0, lpSystemW
);
1377 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1380 ret
= WN_NO_NETWORK
;
1384 TRACE("Returning %d\n", ret
);
1388 /*********************************************************************
1389 * WNetGetResourceInformationW [MPR.@]
1391 * WNetGetResourceInformationW function identifies the network provider
1392 * that owns the resource and gets information about the type of the resource.
1395 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1396 * defines a network resource.
1397 * lpBuffer [ O] the pointer to buffer, containing result. It
1398 * contains NETRESOURCEW structure and strings to
1399 * which the members of the NETRESOURCEW structure
1401 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1403 * lplpSystem [ O] the pointer to string in the output buffer,
1404 * containing the part of the resource name without
1405 * names of the server and share.
1408 * NO_ERROR if the function succeeds. System error code if the function fails.
1411 DWORD WINAPI
WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource
,
1412 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1413 LPWSTR
*lplpSystem
)
1415 DWORD ret
= WN_NO_NETWORK
;
1418 TRACE( "(%p, %p, %p, %p)\n",
1419 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1422 ret
= WN_OUT_OF_MEMORY
;
1423 else if (providerTable
!= NULL
)
1425 /* FIXME: For function value of a variable is indifferent, it does
1426 * search of all providers in a network.
1428 for (index
= 0; index
< providerTable
->numProviders
; index
++)
1430 if(providerTable
->table
[index
].getCaps(WNNC_DIALOG
) &
1431 WNNC_DLG_GETRESOURCEINFORMATION
)
1433 if (providerTable
->table
[index
].getResourceInformation
)
1434 ret
= providerTable
->table
[index
].getResourceInformation(
1435 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1437 ret
= WN_NO_NETWORK
;
1438 if (ret
== WN_SUCCESS
)
1448 /*********************************************************************
1449 * WNetGetResourceParentA [MPR.@]
1451 DWORD WINAPI
WNetGetResourceParentA( LPNETRESOURCEA lpNetResource
,
1452 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1454 FIXME( "(%p, %p, %p): stub\n",
1455 lpNetResource
, lpBuffer
, lpBufferSize
);
1457 SetLastError(WN_NO_NETWORK
);
1458 return WN_NO_NETWORK
;
1461 /*********************************************************************
1462 * WNetGetResourceParentW [MPR.@]
1464 DWORD WINAPI
WNetGetResourceParentW( LPNETRESOURCEW lpNetResource
,
1465 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1467 FIXME( "(%p, %p, %p): stub\n",
1468 lpNetResource
, lpBuffer
, lpBufferSize
);
1470 SetLastError(WN_NO_NETWORK
);
1471 return WN_NO_NETWORK
;
1477 * Connection Functions
1480 /*********************************************************************
1481 * WNetAddConnectionA [MPR.@]
1483 DWORD WINAPI
WNetAddConnectionA( LPCSTR lpRemoteName
, LPCSTR lpPassword
,
1484 LPCSTR lpLocalName
)
1486 NETRESOURCEA resourcesA
;
1488 memset(&resourcesA
, 0, sizeof(resourcesA
));
1489 resourcesA
.lpRemoteName
= (LPSTR
)lpRemoteName
;
1490 resourcesA
.lpLocalName
= (LPSTR
)lpLocalName
;
1491 return WNetUseConnectionA(NULL
, &resourcesA
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1494 /*********************************************************************
1495 * WNetAddConnectionW [MPR.@]
1497 DWORD WINAPI
WNetAddConnectionW( LPCWSTR lpRemoteName
, LPCWSTR lpPassword
,
1498 LPCWSTR lpLocalName
)
1500 NETRESOURCEW resourcesW
;
1502 memset(&resourcesW
, 0, sizeof(resourcesW
));
1503 resourcesW
.lpRemoteName
= (LPWSTR
)lpRemoteName
;
1504 resourcesW
.lpLocalName
= (LPWSTR
)lpLocalName
;
1505 return WNetUseConnectionW(NULL
, &resourcesW
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1508 /*********************************************************************
1509 * WNetAddConnection2A [MPR.@]
1511 DWORD WINAPI
WNetAddConnection2A( LPNETRESOURCEA lpNetResource
,
1512 LPCSTR lpPassword
, LPCSTR lpUserID
,
1515 return WNetUseConnectionA(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1519 /*********************************************************************
1520 * WNetAddConnection2W [MPR.@]
1522 DWORD WINAPI
WNetAddConnection2W( LPNETRESOURCEW lpNetResource
,
1523 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1526 return WNetUseConnectionW(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1530 /*********************************************************************
1531 * WNetAddConnection3A [MPR.@]
1533 DWORD WINAPI
WNetAddConnection3A( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1534 LPCSTR lpPassword
, LPCSTR lpUserID
,
1537 return WNetUseConnectionA(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1538 dwFlags
, NULL
, 0, NULL
);
1541 /*********************************************************************
1542 * WNetAddConnection3W [MPR.@]
1544 DWORD WINAPI
WNetAddConnection3W( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1545 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1548 return WNetUseConnectionW(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1549 dwFlags
, NULL
, 0, NULL
);
1552 /*****************************************************************
1553 * WNetUseConnectionA [MPR.@]
1555 DWORD WINAPI
WNetUseConnectionA( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1556 LPCSTR lpPassword
, LPCSTR lpUserID
, DWORD dwFlags
,
1557 LPSTR lpAccessName
, LPDWORD lpBufferSize
,
1560 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1561 hwndOwner
, lpNetResource
, lpPassword
, debugstr_a(lpUserID
), dwFlags
,
1562 debugstr_a(lpAccessName
), lpBufferSize
, lpResult
);
1564 SetLastError(WN_NO_NETWORK
);
1565 return WN_NO_NETWORK
;
1568 /*****************************************************************
1569 * WNetUseConnectionW [MPR.@]
1571 DWORD WINAPI
WNetUseConnectionW( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1572 LPCWSTR lpPassword
, LPCWSTR lpUserID
, DWORD dwFlags
,
1573 LPWSTR lpAccessName
, LPDWORD lpBufferSize
,
1576 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1577 hwndOwner
, lpNetResource
, lpPassword
, debugstr_w(lpUserID
), dwFlags
,
1578 debugstr_w(lpAccessName
), lpBufferSize
, lpResult
);
1580 SetLastError(WN_NO_NETWORK
);
1581 return WN_NO_NETWORK
;
1584 /*********************************************************************
1585 * WNetCancelConnectionA [MPR.@]
1587 DWORD WINAPI
WNetCancelConnectionA( LPCSTR lpName
, BOOL fForce
)
1589 FIXME( "(%s, %d), stub\n", debugstr_a(lpName
), fForce
);
1594 /*********************************************************************
1595 * WNetCancelConnectionW [MPR.@]
1597 DWORD WINAPI
WNetCancelConnectionW( LPCWSTR lpName
, BOOL fForce
)
1599 FIXME( "(%s, %d), stub\n", debugstr_w(lpName
), fForce
);
1604 /*********************************************************************
1605 * WNetCancelConnection2A [MPR.@]
1607 DWORD WINAPI
WNetCancelConnection2A( LPCSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1609 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName
), dwFlags
, fForce
);
1614 /*********************************************************************
1615 * WNetCancelConnection2W [MPR.@]
1617 DWORD WINAPI
WNetCancelConnection2W( LPCWSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1619 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName
), dwFlags
, fForce
);
1624 /*****************************************************************
1625 * WNetRestoreConnectionA [MPR.@]
1627 DWORD WINAPI
WNetRestoreConnectionA( HWND hwndOwner
, LPCSTR lpszDevice
)
1629 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_a(lpszDevice
) );
1631 SetLastError(WN_NO_NETWORK
);
1632 return WN_NO_NETWORK
;
1635 /*****************************************************************
1636 * WNetRestoreConnectionW [MPR.@]
1638 DWORD WINAPI
WNetRestoreConnectionW( HWND hwndOwner
, LPCWSTR lpszDevice
)
1640 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_w(lpszDevice
) );
1642 SetLastError(WN_NO_NETWORK
);
1643 return WN_NO_NETWORK
;
1646 /**************************************************************************
1647 * WNetGetConnectionA [MPR.@]
1650 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1651 * - WN_NOT_CONNECTED drive is a local drive
1652 * - WN_MORE_DATA buffer isn't big enough
1653 * - WN_SUCCESS success (net path in buffer)
1655 * FIXME: need to test return values under different errors
1657 DWORD WINAPI
WNetGetConnectionA( LPCSTR lpLocalName
,
1658 LPSTR lpRemoteName
, LPDWORD lpBufferSize
)
1663 ret
= WN_BAD_POINTER
;
1664 else if (!lpBufferSize
)
1665 ret
= WN_BAD_POINTER
;
1666 else if (!lpRemoteName
&& *lpBufferSize
)
1667 ret
= WN_BAD_POINTER
;
1670 int len
= MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, NULL
, 0);
1674 PWSTR wideLocalName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1678 WCHAR wideRemoteStatic
[MAX_PATH
];
1679 DWORD wideRemoteSize
= sizeof(wideRemoteStatic
) / sizeof(WCHAR
);
1681 MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, wideLocalName
, len
);
1683 /* try once without memory allocation */
1684 ret
= WNetGetConnectionW(wideLocalName
, wideRemoteStatic
,
1686 if (ret
== WN_SUCCESS
)
1688 int len
= WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1689 -1, NULL
, 0, NULL
, NULL
);
1691 if (len
<= *lpBufferSize
)
1693 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
, -1,
1694 lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1699 *lpBufferSize
= len
;
1703 else if (ret
== WN_MORE_DATA
)
1705 PWSTR wideRemote
= HeapAlloc(GetProcessHeap(), 0,
1706 wideRemoteSize
* sizeof(WCHAR
));
1710 ret
= WNetGetConnectionW(wideLocalName
, wideRemote
,
1712 if (ret
== WN_SUCCESS
)
1714 if (len
<= *lpBufferSize
)
1716 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1717 -1, lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1722 *lpBufferSize
= len
;
1726 HeapFree(GetProcessHeap(), 0, wideRemote
);
1729 ret
= WN_OUT_OF_MEMORY
;
1731 HeapFree(GetProcessHeap(), 0, wideLocalName
);
1734 ret
= WN_OUT_OF_MEMORY
;
1737 ret
= WN_BAD_LOCALNAME
;
1741 TRACE("Returning %d\n", ret
);
1745 /* find the network connection for a given drive; helper for WNetGetConnection */
1746 static DWORD
get_drive_connection( WCHAR letter
, LPWSTR remote
, LPDWORD size
)
1749 struct mountmgr_unix_drive
*data
= (struct mountmgr_unix_drive
*)buffer
;
1751 DWORD ret
= WN_NOT_CONNECTED
;
1752 DWORD bytes_returned
;
1754 if ((mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
,
1755 FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
,
1756 0, 0 )) == INVALID_HANDLE_VALUE
)
1758 ERR( "failed to open mount manager err %u\n", GetLastError() );
1761 memset( data
, 0, sizeof(*data
) );
1762 data
->letter
= letter
;
1763 if (DeviceIoControl( mgr
, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
, data
, sizeof(*data
),
1764 data
, sizeof(buffer
), &bytes_returned
, NULL
))
1766 char *p
, *mount_point
= buffer
+ data
->mount_point_offset
;
1769 if (data
->mount_point_offset
&& !strncmp( mount_point
, "unc/", 4 ))
1772 mount_point
[0] = '\\';
1773 for (p
= mount_point
; *p
; p
++) if (*p
== '/') *p
= '\\';
1775 len
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, NULL
, 0 );
1783 *size
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, remote
, *size
);
1792 /**************************************************************************
1793 * WNetGetConnectionW [MPR.@]
1795 * FIXME: need to test return values under different errors
1797 DWORD WINAPI
WNetGetConnectionW( LPCWSTR lpLocalName
,
1798 LPWSTR lpRemoteName
, LPDWORD lpBufferSize
)
1802 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName
), lpRemoteName
,
1806 ret
= WN_BAD_POINTER
;
1807 else if (!lpBufferSize
)
1808 ret
= WN_BAD_POINTER
;
1809 else if (!lpRemoteName
&& *lpBufferSize
)
1810 ret
= WN_BAD_POINTER
;
1811 else if (!lpLocalName
[0])
1812 ret
= WN_BAD_LOCALNAME
;
1815 if (lpLocalName
[1] == ':')
1817 switch(GetDriveTypeW(lpLocalName
))
1820 ret
= get_drive_connection( lpLocalName
[0], lpRemoteName
, lpBufferSize
);
1822 case DRIVE_REMOVABLE
:
1825 TRACE("file is local\n");
1826 ret
= WN_NOT_CONNECTED
;
1829 ret
= WN_BAD_LOCALNAME
;
1833 ret
= WN_BAD_LOCALNAME
;
1837 TRACE("Returning %d\n", ret
);
1841 /**************************************************************************
1842 * WNetSetConnectionA [MPR.@]
1844 DWORD WINAPI
WNetSetConnectionA( LPCSTR lpName
, DWORD dwProperty
,
1847 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName
), dwProperty
, pvValue
);
1849 SetLastError(WN_NO_NETWORK
);
1850 return WN_NO_NETWORK
;
1853 /**************************************************************************
1854 * WNetSetConnectionW [MPR.@]
1856 DWORD WINAPI
WNetSetConnectionW( LPCWSTR lpName
, DWORD dwProperty
,
1859 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName
), dwProperty
, pvValue
);
1861 SetLastError(WN_NO_NETWORK
);
1862 return WN_NO_NETWORK
;
1865 /*****************************************************************
1866 * WNetGetUniversalNameA [MPR.@]
1868 DWORD WINAPI
WNetGetUniversalNameA ( LPCSTR lpLocalPath
, DWORD dwInfoLevel
,
1869 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1873 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1874 debugstr_a(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1876 switch (dwInfoLevel
)
1878 case UNIVERSAL_NAME_INFO_LEVEL
:
1880 LPUNIVERSAL_NAME_INFOA info
= lpBuffer
;
1882 if (GetDriveTypeA(lpLocalPath
) != DRIVE_REMOTE
)
1884 err
= ERROR_NOT_CONNECTED
;
1888 size
= sizeof(*info
) + lstrlenA(lpLocalPath
) + 1;
1889 if (*lpBufferSize
< size
)
1894 info
->lpUniversalName
= (char *)info
+ sizeof(*info
);
1895 lstrcpyA(info
->lpUniversalName
, lpLocalPath
);
1899 case REMOTE_NAME_INFO_LEVEL
:
1900 err
= WN_NO_NETWORK
;
1912 /*****************************************************************
1913 * WNetGetUniversalNameW [MPR.@]
1915 DWORD WINAPI
WNetGetUniversalNameW ( LPCWSTR lpLocalPath
, DWORD dwInfoLevel
,
1916 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1920 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1921 debugstr_w(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
1923 switch (dwInfoLevel
)
1925 case UNIVERSAL_NAME_INFO_LEVEL
:
1927 LPUNIVERSAL_NAME_INFOW info
= lpBuffer
;
1929 if (GetDriveTypeW(lpLocalPath
) != DRIVE_REMOTE
)
1931 err
= ERROR_NOT_CONNECTED
;
1935 size
= sizeof(*info
) + (lstrlenW(lpLocalPath
) + 1) * sizeof(WCHAR
);
1936 if (*lpBufferSize
< size
)
1941 info
->lpUniversalName
= (LPWSTR
)((char *)info
+ sizeof(*info
));
1942 lstrcpyW(info
->lpUniversalName
, lpLocalPath
);
1946 case REMOTE_NAME_INFO_LEVEL
:
1947 err
= WN_NOT_CONNECTED
;
1955 if (err
!= WN_NO_ERROR
) SetLastError(err
);
1965 /**************************************************************************
1966 * WNetGetUserA [MPR.@]
1968 * FIXME: we should not return ourselves, but the owner of the drive lpName
1970 DWORD WINAPI
WNetGetUserA( LPCSTR lpName
, LPSTR lpUserID
, LPDWORD lpBufferSize
)
1972 if (GetUserNameA( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1973 return GetLastError();
1976 /*****************************************************************
1977 * WNetGetUserW [MPR.@]
1979 * FIXME: we should not return ourselves, but the owner of the drive lpName
1981 DWORD WINAPI
WNetGetUserW( LPCWSTR lpName
, LPWSTR lpUserID
, LPDWORD lpBufferSize
)
1983 if (GetUserNameW( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
1984 return GetLastError();
1987 /*********************************************************************
1988 * WNetConnectionDialog [MPR.@]
1990 DWORD WINAPI
WNetConnectionDialog( HWND hwnd
, DWORD dwType
)
1992 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
1994 SetLastError(WN_NO_NETWORK
);
1995 return WN_NO_NETWORK
;
1998 /*********************************************************************
1999 * WNetConnectionDialog1A [MPR.@]
2001 DWORD WINAPI
WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct
)
2003 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2005 SetLastError(WN_NO_NETWORK
);
2006 return WN_NO_NETWORK
;
2009 /*********************************************************************
2010 * WNetConnectionDialog1W [MPR.@]
2012 DWORD WINAPI
WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct
)
2014 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2016 SetLastError(WN_NO_NETWORK
);
2017 return WN_NO_NETWORK
;
2020 /*********************************************************************
2021 * WNetDisconnectDialog [MPR.@]
2023 DWORD WINAPI
WNetDisconnectDialog( HWND hwnd
, DWORD dwType
)
2025 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2027 SetLastError(WN_NO_NETWORK
);
2028 return WN_NO_NETWORK
;
2031 /*********************************************************************
2032 * WNetDisconnectDialog1A [MPR.@]
2034 DWORD WINAPI
WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct
)
2036 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2038 SetLastError(WN_NO_NETWORK
);
2039 return WN_NO_NETWORK
;
2042 /*********************************************************************
2043 * WNetDisconnectDialog1W [MPR.@]
2045 DWORD WINAPI
WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct
)
2047 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2049 SetLastError(WN_NO_NETWORK
);
2050 return WN_NO_NETWORK
;
2053 /*********************************************************************
2054 * WNetGetLastErrorA [MPR.@]
2056 DWORD WINAPI
WNetGetLastErrorA( LPDWORD lpError
,
2057 LPSTR lpErrorBuf
, DWORD nErrorBufSize
,
2058 LPSTR lpNameBuf
, DWORD nNameBufSize
)
2060 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2061 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2063 SetLastError(WN_NO_NETWORK
);
2064 return WN_NO_NETWORK
;
2067 /*********************************************************************
2068 * WNetGetLastErrorW [MPR.@]
2070 DWORD WINAPI
WNetGetLastErrorW( LPDWORD lpError
,
2071 LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
2072 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
2074 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2075 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2077 SetLastError(WN_NO_NETWORK
);
2078 return WN_NO_NETWORK
;
2081 /*********************************************************************
2082 * WNetGetNetworkInformationA [MPR.@]
2084 DWORD WINAPI
WNetGetNetworkInformationA( LPCSTR lpProvider
,
2085 LPNETINFOSTRUCT lpNetInfoStruct
)
2089 TRACE( "(%s, %p)\n", debugstr_a(lpProvider
), lpNetInfoStruct
);
2092 ret
= WN_BAD_POINTER
;
2097 len
= MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, NULL
, 0);
2100 LPWSTR wideProvider
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2104 MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, wideProvider
,
2106 ret
= WNetGetNetworkInformationW(wideProvider
, lpNetInfoStruct
);
2107 HeapFree(GetProcessHeap(), 0, wideProvider
);
2110 ret
= WN_OUT_OF_MEMORY
;
2113 ret
= GetLastError();
2117 TRACE("Returning %d\n", ret
);
2121 /*********************************************************************
2122 * WNetGetNetworkInformationW [MPR.@]
2124 DWORD WINAPI
WNetGetNetworkInformationW( LPCWSTR lpProvider
,
2125 LPNETINFOSTRUCT lpNetInfoStruct
)
2129 TRACE( "(%s, %p)\n", debugstr_w(lpProvider
), lpNetInfoStruct
);
2132 ret
= WN_BAD_POINTER
;
2133 else if (!lpNetInfoStruct
)
2134 ret
= WN_BAD_POINTER
;
2135 else if (lpNetInfoStruct
->cbStructure
< sizeof(NETINFOSTRUCT
))
2139 if (providerTable
&& providerTable
->numProviders
)
2141 DWORD providerIndex
= _findProviderIndexW(lpProvider
);
2143 if (providerIndex
!= BAD_PROVIDER_INDEX
)
2145 lpNetInfoStruct
->cbStructure
= sizeof(NETINFOSTRUCT
);
2146 lpNetInfoStruct
->dwProviderVersion
=
2147 providerTable
->table
[providerIndex
].dwSpecVersion
;
2148 lpNetInfoStruct
->dwStatus
= NO_ERROR
;
2149 lpNetInfoStruct
->dwCharacteristics
= 0;
2150 lpNetInfoStruct
->dwHandle
= 0;
2151 lpNetInfoStruct
->wNetType
=
2152 HIWORD(providerTable
->table
[providerIndex
].dwNetType
);
2153 lpNetInfoStruct
->dwPrinters
= -1;
2154 lpNetInfoStruct
->dwDrives
= -1;
2158 ret
= WN_BAD_PROVIDER
;
2161 ret
= WN_NO_NETWORK
;
2165 TRACE("Returning %d\n", ret
);
2169 /*****************************************************************
2170 * WNetGetProviderNameA [MPR.@]
2172 DWORD WINAPI
WNetGetProviderNameA( DWORD dwNetType
,
2173 LPSTR lpProvider
, LPDWORD lpBufferSize
)
2177 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_a(lpProvider
),
2181 ret
= WN_BAD_POINTER
;
2182 else if (!lpBufferSize
)
2183 ret
= WN_BAD_POINTER
;
2190 ret
= WN_NO_NETWORK
;
2191 for (i
= 0; i
< providerTable
->numProviders
&&
2192 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2195 if (i
< providerTable
->numProviders
)
2197 DWORD sizeNeeded
= WideCharToMultiByte(CP_ACP
, 0,
2198 providerTable
->table
[i
].name
, -1, NULL
, 0, NULL
, NULL
);
2200 if (*lpBufferSize
< sizeNeeded
)
2202 *lpBufferSize
= sizeNeeded
;
2207 WideCharToMultiByte(CP_ACP
, 0, providerTable
->table
[i
].name
,
2208 -1, lpProvider
, *lpBufferSize
, NULL
, NULL
);
2210 /* FIXME: is *lpBufferSize set to the number of characters
2216 ret
= WN_NO_NETWORK
;
2220 TRACE("Returning %d\n", ret
);
2224 /*****************************************************************
2225 * WNetGetProviderNameW [MPR.@]
2227 DWORD WINAPI
WNetGetProviderNameW( DWORD dwNetType
,
2228 LPWSTR lpProvider
, LPDWORD lpBufferSize
)
2232 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_w(lpProvider
),
2236 ret
= WN_BAD_POINTER
;
2237 else if (!lpBufferSize
)
2238 ret
= WN_BAD_POINTER
;
2245 ret
= WN_NO_NETWORK
;
2246 for (i
= 0; i
< providerTable
->numProviders
&&
2247 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2250 if (i
< providerTable
->numProviders
)
2252 DWORD sizeNeeded
= strlenW(providerTable
->table
[i
].name
) + 1;
2254 if (*lpBufferSize
< sizeNeeded
)
2256 *lpBufferSize
= sizeNeeded
;
2261 strcpyW(lpProvider
, providerTable
->table
[i
].name
);
2263 /* FIXME: is *lpBufferSize set to the number of characters
2269 ret
= WN_NO_NETWORK
;
2273 TRACE("Returning %d\n", ret
);