d3d8: Hold the lock in IDirect3DIndexBuffer8 methods.
[wine.git] / dlls / mpr / wnet.c
blob9a6a9ef1b67c810c41cf2f681696594bba3f5f0d
1 /*
2 * MPR WNet functions
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
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winnls.h"
27 #include "winnetwk.h"
28 #include "npapi.h"
29 #include "winreg.h"
30 #include "winuser.h"
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33 #include "mprres.h"
34 #include "wnetpriv.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(mpr);
38 /* Data structures representing network service providers. Assumes only one
39 * thread creates them, and that they are constant for the life of the process
40 * (and therefore doesn't synchronize access).
41 * FIXME: only basic provider data and enumeration-related data are implemented
42 * so far, need to implement the rest too.
44 typedef struct _WNetProvider
46 HMODULE hLib;
47 PWSTR name;
48 PF_NPGetCaps getCaps;
49 DWORD dwSpecVersion;
50 DWORD dwNetType;
51 DWORD dwEnumScopes;
52 PF_NPOpenEnum openEnum;
53 PF_NPEnumResource enumResource;
54 PF_NPCloseEnum closeEnum;
55 } WNetProvider, *PWNetProvider;
57 typedef struct _WNetProviderTable
59 LPWSTR entireNetwork;
60 DWORD numAllocated;
61 DWORD numProviders;
62 WNetProvider table[1];
63 } WNetProviderTable, *PWNetProviderTable;
65 #define WNET_ENUMERATOR_TYPE_NULL 0
66 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
67 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
68 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
70 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
71 * the enumeration; it represents one of the following types:
72 * - a 'null' enumeration, one that contains no members
73 * - a global enumeration, one that's executed across all providers
74 * - a provider-specific enumeration, one that's only executed by a single
75 * provider
76 * - a context enumeration. I know this contradicts what I just said about
77 * there being no correspondence between the scope and the type, but it's
78 * necessary for the special case that a "Entire Network" entry needs to
79 * be enumerated in an enumeration of the context scope. Thus an enumeration
80 * of the context scope results in a context type enumerator, which morphs
81 * into a global enumeration (so the enumeration continues across all
82 * providers).
84 typedef struct _WNetEnumerator
86 DWORD enumType;
87 DWORD providerIndex;
88 HANDLE handle;
89 BOOL providerDone;
90 DWORD dwScope;
91 DWORD dwType;
92 DWORD dwUsage;
93 LPNETRESOURCEW lpNet;
94 } WNetEnumerator, *PWNetEnumerator;
96 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
98 /* Returns an index (into the global WNetProviderTable) of the provider with
99 * the given name, or BAD_PROVIDER_INDEX if not found.
101 static DWORD _findProviderIndexW(LPCWSTR lpProvider);
103 static PWNetProviderTable providerTable;
106 * Global provider table functions
109 static void _tryLoadProvider(PCWSTR provider)
111 static const WCHAR servicePrefix[] = { 'S','y','s','t','e','m','\\',
112 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
113 'S','e','r','v','i','c','e','s','\\',0 };
114 static const WCHAR serviceFmt[] = { '%','s','%','s','\\',
115 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
116 WCHAR serviceName[MAX_PATH];
117 HKEY hKey;
119 TRACE("%s\n", debugstr_w(provider));
120 snprintfW(serviceName, sizeof(serviceName) / sizeof(WCHAR), serviceFmt,
121 servicePrefix, provider);
122 serviceName[sizeof(serviceName) / sizeof(WCHAR) - 1] = '\0';
123 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, serviceName, 0, KEY_READ, &hKey) ==
124 ERROR_SUCCESS)
126 static const WCHAR szProviderPath[] = { 'P','r','o','v','i','d','e','r',
127 'P','a','t','h',0 };
128 WCHAR providerPath[MAX_PATH];
129 DWORD type, size = sizeof(providerPath);
131 if (RegQueryValueExW(hKey, szProviderPath, NULL, &type,
132 (LPBYTE)providerPath, &size) == ERROR_SUCCESS && type == REG_SZ)
134 static const WCHAR szProviderName[] = { 'N','a','m','e',0 };
135 PWSTR name = NULL;
137 size = 0;
138 RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size);
139 if (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);
146 name = NULL;
149 if (name)
151 HMODULE hLib = LoadLibraryW(providerPath);
153 if (hLib)
155 PF_NPGetCaps getCaps = (PF_NPGetCaps)GetProcAddress(hLib,
156 "NPGetCaps");
158 TRACE("loaded lib %p\n", hLib);
159 if (getCaps)
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 if (!provider->openEnum || !provider->enumResource
186 || !provider->closeEnum)
188 provider->openEnum = NULL;
189 provider->enumResource = NULL;
190 provider->closeEnum = NULL;
191 provider->dwEnumScopes = 0;
192 WARN("Couldn't load enumeration functions\n");
195 providerTable->numProviders++;
197 else
199 WARN("Provider %s didn't export NPGetCaps\n",
200 debugstr_w(provider));
201 HeapFree(GetProcessHeap(), 0, name);
202 FreeLibrary(hLib);
205 else
207 WARN("Couldn't load library %s for provider %s\n",
208 debugstr_w(providerPath), debugstr_w(provider));
209 HeapFree(GetProcessHeap(), 0, name);
212 else
214 WARN("Couldn't get provider name for provider %s\n",
215 debugstr_w(provider));
218 else
219 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath));
220 RegCloseKey(hKey);
222 else
223 WARN("Couldn't open service key for provider %s\n",
224 debugstr_w(provider));
227 void wnetInit(HINSTANCE hInstDll)
229 static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\',
230 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
231 'C','o','n','t','r','o','l','\\',
232 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
233 'O','r','d','e','r',0 };
234 static const WCHAR providerOrder[] = { 'P','r','o','v','i','d','e','r',
235 'O','r','d','e','r',0 };
236 HKEY hKey;
238 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, providerOrderKey, 0, KEY_READ, &hKey)
239 == ERROR_SUCCESS)
241 DWORD size = 0;
243 RegQueryValueExW(hKey, providerOrder, NULL, NULL, NULL, &size);
244 if (size)
246 PWSTR providers = HeapAlloc(GetProcessHeap(), 0, size);
248 if (providers)
250 DWORD type;
252 if (RegQueryValueExW(hKey, providerOrder, NULL, &type,
253 (LPBYTE)providers, &size) == ERROR_SUCCESS && type == REG_SZ)
255 PWSTR ptr;
256 DWORD numToAllocate;
258 TRACE("provider order is %s\n", debugstr_w(providers));
259 /* first count commas as a heuristic for how many to
260 * allocate space for */
261 for (ptr = providers, numToAllocate = 1; ptr; )
263 ptr = strchrW(ptr, ',');
264 if (ptr) {
265 numToAllocate++;
266 ptr++;
269 providerTable =
270 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
271 sizeof(WNetProviderTable)
272 + (numToAllocate - 1) * sizeof(WNetProvider));
273 if (providerTable)
275 PWSTR ptrPrev;
276 int entireNetworkLen;
278 entireNetworkLen = LoadStringW(hInstDll,
279 IDS_ENTIRENETWORK, NULL, 0);
280 providerTable->entireNetwork = HeapAlloc(
281 GetProcessHeap(), 0, (entireNetworkLen + 1) *
282 sizeof(WCHAR));
283 if (providerTable->entireNetwork)
284 LoadStringW(hInstDll, IDS_ENTIRENETWORK,
285 providerTable->entireNetwork,
286 entireNetworkLen + 1);
287 providerTable->numAllocated = numToAllocate;
288 for (ptr = providers; ptr; )
290 ptrPrev = ptr;
291 ptr = strchrW(ptr, ',');
292 if (ptr)
293 *ptr++ = '\0';
294 _tryLoadProvider(ptrPrev);
298 HeapFree(GetProcessHeap(), 0, providers);
301 RegCloseKey(hKey);
305 void wnetFree(void)
307 if (providerTable)
309 DWORD i;
311 for (i = 0; i < providerTable->numProviders; i++)
313 HeapFree(GetProcessHeap(), 0, providerTable->table[i].name);
314 FreeModule(providerTable->table[i].hLib);
316 HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork);
317 HeapFree(GetProcessHeap(), 0, providerTable);
318 providerTable = NULL;
322 static DWORD _findProviderIndexW(LPCWSTR lpProvider)
324 DWORD ret = BAD_PROVIDER_INDEX;
326 if (providerTable && providerTable->numProviders)
328 DWORD i;
330 for (i = 0; i < providerTable->numProviders &&
331 ret == BAD_PROVIDER_INDEX; i++)
332 if (!strcmpW(lpProvider, providerTable->table[i].name))
333 ret = i;
335 return ret;
339 * Browsing Functions
342 static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet)
344 LPNETRESOURCEW ret;
346 if (lpNet)
348 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW));
349 if (ret)
351 size_t len;
353 memcpy(ret, lpNet, sizeof(ret));
354 ret->lpLocalName = ret->lpComment = ret->lpProvider = NULL;
355 if (lpNet->lpRemoteName)
357 len = strlenW(lpNet->lpRemoteName) + 1;
358 ret->lpRemoteName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
359 if (ret->lpRemoteName)
360 strcpyW(ret->lpRemoteName, lpNet->lpRemoteName);
364 else
365 ret = NULL;
366 return ret;
369 static void _freeEnumNetResource(LPNETRESOURCEW lpNet)
371 if (lpNet)
373 HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName);
374 HeapFree(GetProcessHeap(), 0, lpNet);
378 static PWNetEnumerator _createNullEnumerator(void)
380 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
381 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
383 if (ret)
384 ret->enumType = WNET_ENUMERATOR_TYPE_NULL;
385 return ret;
388 static PWNetEnumerator _createGlobalEnumeratorW(DWORD dwScope, DWORD dwType,
389 DWORD dwUsage, LPNETRESOURCEW lpNet)
391 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
392 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
394 if (ret)
396 ret->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
397 ret->dwScope = dwScope;
398 ret->dwType = dwType;
399 ret->dwUsage = dwUsage;
400 ret->lpNet = _copyNetResourceForEnumW(lpNet);
402 return ret;
405 static PWNetEnumerator _createProviderEnumerator(DWORD dwScope, DWORD dwType,
406 DWORD dwUsage, DWORD index, HANDLE handle)
408 PWNetEnumerator ret;
410 if (!providerTable || index >= providerTable->numProviders)
411 ret = NULL;
412 else
414 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
415 if (ret)
417 ret->enumType = WNET_ENUMERATOR_TYPE_PROVIDER;
418 ret->providerIndex = index;
419 ret->dwScope = dwScope;
420 ret->dwType = dwType;
421 ret->dwUsage = dwUsage;
422 ret->handle = handle;
425 return ret;
428 static PWNetEnumerator _createContextEnumerator(DWORD dwScope, DWORD dwType,
429 DWORD dwUsage)
431 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
432 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
434 if (ret)
436 ret->enumType = WNET_ENUMERATOR_TYPE_CONTEXT;
437 ret->dwScope = dwScope;
438 ret->dwType = dwType;
439 ret->dwUsage = dwUsage;
441 return ret;
444 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
445 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
446 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
447 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
448 * if not all members of the array could be thunked, and something else on
449 * failure.
451 static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn,
452 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
454 DWORD i, numToThunk, totalBytes, ret;
455 LPSTR strNext;
457 if (!lpNetArrayIn)
458 return WN_BAD_POINTER;
459 if (!lpcCount)
460 return WN_BAD_POINTER;
461 if (*lpcCount == -1)
462 return WN_BAD_VALUE;
463 if (!lpBuffer)
464 return WN_BAD_POINTER;
465 if (!lpBufferSize)
466 return WN_BAD_POINTER;
468 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
470 const NETRESOURCEW *lpNet = lpNetArrayIn + i;
472 totalBytes += sizeof(NETRESOURCEA);
473 if (lpNet->lpLocalName)
474 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpLocalName,
475 -1, NULL, 0, NULL, NULL);
476 if (lpNet->lpRemoteName)
477 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpRemoteName,
478 -1, NULL, 0, NULL, NULL);
479 if (lpNet->lpComment)
480 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpComment,
481 -1, NULL, 0, NULL, NULL);
482 if (lpNet->lpProvider)
483 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpProvider,
484 -1, NULL, 0, NULL, NULL);
485 if (totalBytes < *lpBufferSize)
486 numToThunk = i + 1;
488 strNext = (LPSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEA));
489 for (i = 0; i < numToThunk; i++)
491 LPNETRESOURCEA lpNetOut = (LPNETRESOURCEA)lpBuffer + i;
492 const NETRESOURCEW *lpNetIn = lpNetArrayIn + i;
494 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEA));
495 /* lie about string lengths, we already verified how many
496 * we have space for above
498 if (lpNetIn->lpLocalName)
500 lpNetOut->lpLocalName = strNext;
501 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpLocalName, -1,
502 lpNetOut->lpLocalName, *lpBufferSize, NULL, NULL);
504 if (lpNetIn->lpRemoteName)
506 lpNetOut->lpRemoteName = strNext;
507 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpRemoteName, -1,
508 lpNetOut->lpRemoteName, *lpBufferSize, NULL, NULL);
510 if (lpNetIn->lpComment)
512 lpNetOut->lpComment = strNext;
513 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpComment, -1,
514 lpNetOut->lpComment, *lpBufferSize, NULL, NULL);
516 if (lpNetIn->lpProvider)
518 lpNetOut->lpProvider = strNext;
519 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpProvider, -1,
520 lpNetOut->lpProvider, *lpBufferSize, NULL, NULL);
523 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
524 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
525 *lpcCount, ret);
526 return ret;
529 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
530 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
531 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
532 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
533 * if not all members of the array could be thunked, and something else on
534 * failure.
536 static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn,
537 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
539 DWORD i, numToThunk, totalBytes, ret;
540 LPWSTR strNext;
542 if (!lpNetArrayIn)
543 return WN_BAD_POINTER;
544 if (!lpcCount)
545 return WN_BAD_POINTER;
546 if (*lpcCount == -1)
547 return WN_BAD_VALUE;
548 if (!lpBuffer)
549 return WN_BAD_POINTER;
550 if (!lpBufferSize)
551 return WN_BAD_POINTER;
553 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
555 const NETRESOURCEA *lpNet = lpNetArrayIn + i;
557 totalBytes += sizeof(NETRESOURCEW);
558 if (lpNet->lpLocalName)
559 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpLocalName,
560 -1, NULL, 0) * sizeof(WCHAR);
561 if (lpNet->lpRemoteName)
562 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpRemoteName,
563 -1, NULL, 0) * sizeof(WCHAR);
564 if (lpNet->lpComment)
565 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpComment,
566 -1, NULL, 0) * sizeof(WCHAR);
567 if (lpNet->lpProvider)
568 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpProvider,
569 -1, NULL, 0) * sizeof(WCHAR);
570 if (totalBytes < *lpBufferSize)
571 numToThunk = i + 1;
573 strNext = (LPWSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEW));
574 for (i = 0; i < numToThunk; i++)
576 LPNETRESOURCEW lpNetOut = (LPNETRESOURCEW)lpBuffer + i;
577 const NETRESOURCEA *lpNetIn = lpNetArrayIn + i;
579 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEW));
580 /* lie about string lengths, we already verified how many
581 * we have space for above
583 if (lpNetIn->lpLocalName)
585 lpNetOut->lpLocalName = strNext;
586 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpLocalName,
587 -1, lpNetOut->lpLocalName, *lpBufferSize);
589 if (lpNetIn->lpRemoteName)
591 lpNetOut->lpRemoteName = strNext;
592 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpRemoteName,
593 -1, lpNetOut->lpRemoteName, *lpBufferSize);
595 if (lpNetIn->lpComment)
597 lpNetOut->lpComment = strNext;
598 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpComment,
599 -1, lpNetOut->lpComment, *lpBufferSize);
601 if (lpNetIn->lpProvider)
603 lpNetOut->lpProvider = strNext;
604 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpProvider,
605 -1, lpNetOut->lpProvider, *lpBufferSize);
608 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
609 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
610 *lpcCount, ret);
611 return ret;
614 /*********************************************************************
615 * WNetOpenEnumA [MPR.@]
617 * See comments for WNetOpenEnumW.
619 DWORD WINAPI WNetOpenEnumA( DWORD dwScope, DWORD dwType, DWORD dwUsage,
620 LPNETRESOURCEA lpNet, LPHANDLE lphEnum )
622 DWORD ret;
624 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
625 dwScope, dwType, dwUsage, lpNet, lphEnum );
627 if (!lphEnum)
628 ret = WN_BAD_POINTER;
629 else if (!providerTable || providerTable->numProviders == 0)
630 ret = WN_NO_NETWORK;
631 else
633 if (lpNet)
635 LPNETRESOURCEW lpNetWide = NULL;
636 BYTE buf[1024];
637 DWORD size = sizeof(buf), count = 1;
638 BOOL allocated = FALSE;
640 ret = _thunkNetResourceArrayAToW(lpNet, &count, buf, &size);
641 if (ret == WN_MORE_DATA)
643 lpNetWide = HeapAlloc(GetProcessHeap(), 0,
644 size);
645 if (lpNetWide)
647 ret = _thunkNetResourceArrayAToW(lpNet, &count, lpNetWide,
648 &size);
649 allocated = TRUE;
651 else
652 ret = WN_OUT_OF_MEMORY;
654 else if (ret == WN_SUCCESS)
655 lpNetWide = (LPNETRESOURCEW)buf;
656 if (ret == WN_SUCCESS)
657 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, lpNetWide,
658 lphEnum);
659 if (allocated)
660 HeapFree(GetProcessHeap(), 0, lpNetWide);
662 else
663 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, NULL, lphEnum);
665 if (ret)
666 SetLastError(ret);
667 TRACE("Returning %d\n", ret);
668 return ret;
671 /*********************************************************************
672 * WNetOpenEnumW [MPR.@]
674 * Network enumeration has way too many parameters, so I'm not positive I got
675 * them right. What I've got so far:
677 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
678 * all the network providers should be enumerated.
680 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
681 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
682 * lpProvider is set, all the network providers should be enumerated.
683 * (This means the enumeration is a list of network providers, not that the
684 * enumeration is passed on to the providers.)
686 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
687 * resource matches the "Entire Network" resource (no remote name, no
688 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
689 * enumeration is done on every network provider.
691 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
692 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
693 * only to the given network provider.
695 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
696 * no lpProvider is set, enumeration will be tried on every network provider,
697 * in the order in which they're loaded.
699 * - The LPNETRESOURCE should be disregarded for scopes besides
700 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
701 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
703 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
704 * resource in the enumerated list, as well as any machines in your
705 * workgroup. The machines in your workgroup come from doing a
706 * RESOURCE_CONTEXT enumeration of every Network Provider.
708 DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage,
709 LPNETRESOURCEW lpNet, LPHANDLE lphEnum )
711 DWORD ret;
713 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
714 dwScope, dwType, dwUsage, lpNet, lphEnum );
716 if (!lphEnum)
717 ret = WN_BAD_POINTER;
718 else if (!providerTable || providerTable->numProviders == 0)
719 ret = WN_NO_NETWORK;
720 else
722 switch (dwScope)
724 case RESOURCE_GLOBALNET:
725 if (lpNet)
727 if (lpNet->lpProvider)
729 DWORD index = _findProviderIndexW(lpNet->lpProvider);
731 if (index != BAD_PROVIDER_INDEX)
733 if (providerTable->table[index].openEnum &&
734 providerTable->table[index].dwEnumScopes & dwScope)
736 HANDLE handle;
738 ret = providerTable->table[index].openEnum(
739 dwScope, dwType, dwUsage, lpNet, &handle);
740 if (ret == WN_SUCCESS)
742 *lphEnum =
743 (HANDLE)_createProviderEnumerator(
744 dwScope, dwType, dwUsage, index, handle);
745 ret = *lphEnum ? WN_SUCCESS :
746 WN_OUT_OF_MEMORY;
749 else
750 ret = WN_NOT_SUPPORTED;
752 else
753 ret = WN_BAD_PROVIDER;
755 else if (lpNet->lpRemoteName)
757 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
758 dwType, dwUsage, lpNet);
759 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
761 else
763 if (lpNet->lpComment && !strcmpW(lpNet->lpComment,
764 providerTable->entireNetwork))
766 /* comment matches the "Entire Network", enumerate
767 * global scope of every provider
769 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
770 dwType, dwUsage, lpNet);
772 else
774 /* this is the same as not having passed lpNet */
775 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
776 dwType, dwUsage, NULL);
778 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
781 else
783 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope, dwType,
784 dwUsage, lpNet);
785 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
787 break;
788 case RESOURCE_CONTEXT:
789 *lphEnum = (HANDLE)_createContextEnumerator(dwScope, dwType,
790 dwUsage);
791 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
792 break;
793 case RESOURCE_REMEMBERED:
794 case RESOURCE_CONNECTED:
795 *lphEnum = (HANDLE)_createNullEnumerator();
796 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
797 break;
798 default:
799 WARN("unknown scope 0x%08x\n", dwScope);
800 ret = WN_BAD_VALUE;
803 if (ret)
804 SetLastError(ret);
805 TRACE("Returning %d\n", ret);
806 return ret;
809 /*********************************************************************
810 * WNetEnumResourceA [MPR.@]
812 DWORD WINAPI WNetEnumResourceA( HANDLE hEnum, LPDWORD lpcCount,
813 LPVOID lpBuffer, LPDWORD lpBufferSize )
815 DWORD ret;
817 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
819 if (!hEnum)
820 ret = WN_BAD_POINTER;
821 else if (!lpcCount)
822 ret = WN_BAD_POINTER;
823 else if (!lpBuffer)
824 ret = WN_BAD_POINTER;
825 else if (!lpBufferSize)
826 ret = WN_BAD_POINTER;
827 else if (*lpBufferSize < sizeof(NETRESOURCEA))
829 *lpBufferSize = sizeof(NETRESOURCEA);
830 ret = WN_MORE_DATA;
832 else
834 DWORD localCount = *lpcCount, localSize = *lpBufferSize;
835 LPVOID localBuffer = HeapAlloc(GetProcessHeap(), 0, localSize);
837 if (localBuffer)
839 ret = WNetEnumResourceW(hEnum, &localCount, localBuffer,
840 &localSize);
841 if (ret == WN_SUCCESS || (ret == WN_MORE_DATA && localCount != -1))
843 /* FIXME: this isn't necessarily going to work in the case of
844 * WN_MORE_DATA, because our enumerator may have moved on to
845 * the next provider. MSDN states that a large (16KB) buffer
846 * size is the appropriate usage of this function, so
847 * hopefully it won't be an issue.
849 ret = _thunkNetResourceArrayWToA((LPNETRESOURCEW)localBuffer,
850 &localCount, lpBuffer, lpBufferSize);
851 *lpcCount = localCount;
853 HeapFree(GetProcessHeap(), 0, localBuffer);
855 else
856 ret = WN_OUT_OF_MEMORY;
858 if (ret)
859 SetLastError(ret);
860 TRACE("Returning %d\n", ret);
861 return ret;
864 static DWORD _countProviderBytesW(PWNetProvider provider)
866 DWORD ret;
868 if (provider)
870 ret = sizeof(NETRESOURCEW);
871 ret += 2 * (strlenW(provider->name) + 1) * sizeof(WCHAR);
873 else
874 ret = 0;
875 return ret;
878 static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount,
879 LPVOID lpBuffer, const DWORD *lpBufferSize)
881 DWORD ret;
883 if (!enumerator)
884 return WN_BAD_POINTER;
885 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
886 return WN_BAD_VALUE;
887 if (!lpcCount)
888 return WN_BAD_POINTER;
889 if (!lpBuffer)
890 return WN_BAD_POINTER;
891 if (!lpBufferSize)
892 return WN_BAD_POINTER;
893 if (*lpBufferSize < sizeof(NETRESOURCEA))
894 return WN_MORE_DATA;
896 if (!providerTable || enumerator->providerIndex >=
897 providerTable->numProviders)
898 ret = WN_NO_MORE_ENTRIES;
899 else
901 DWORD bytes = 0, count = 0, countLimit, i;
902 LPNETRESOURCEW resource;
903 LPWSTR strNext;
905 countLimit = *lpcCount == -1 ?
906 providerTable->numProviders - enumerator->providerIndex : *lpcCount;
907 while (count < countLimit && bytes < *lpBufferSize)
909 DWORD bytesNext = _countProviderBytesW(
910 &providerTable->table[count + enumerator->providerIndex]);
912 if (bytes + bytesNext < *lpBufferSize)
914 bytes += bytesNext;
915 count++;
918 strNext = (LPWSTR)((LPBYTE)lpBuffer + count * sizeof(NETRESOURCEW));
919 for (i = 0, resource = (LPNETRESOURCEW)lpBuffer; i < count;
920 i++, resource++)
922 resource->dwScope = RESOURCE_GLOBALNET;
923 resource->dwType = RESOURCETYPE_ANY;
924 resource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
925 resource->dwUsage = RESOURCEUSAGE_CONTAINER |
926 RESOURCEUSAGE_RESERVED;
927 resource->lpLocalName = NULL;
928 resource->lpRemoteName = strNext;
929 strcpyW(resource->lpRemoteName,
930 providerTable->table[i + enumerator->providerIndex].name);
931 strNext += strlenW(resource->lpRemoteName) + 1;
932 resource->lpComment = NULL;
933 resource->lpProvider = strNext;
934 strcpyW(resource->lpProvider,
935 providerTable->table[i + enumerator->providerIndex].name);
936 strNext += strlenW(resource->lpProvider) + 1;
938 enumerator->providerIndex += count;
939 *lpcCount = count;
940 ret = count > 0 ? WN_SUCCESS : WN_MORE_DATA;
942 TRACE("Returning %d\n", ret);
943 return ret;
946 /* Advances the enumerator (assumed to be a global enumerator) to the next
947 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
948 * not open a handle with the next provider.
949 * If the existing handle is NULL, may leave the enumerator unchanged, since
950 * the current provider may support the desired scope.
951 * If the existing handle is not NULL, closes it before moving on.
952 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
953 * provider, and another error on failure.
955 static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator)
957 if (!enumerator)
958 return WN_BAD_POINTER;
959 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
960 return WN_BAD_VALUE;
961 if (!providerTable || enumerator->providerIndex >=
962 providerTable->numProviders)
963 return WN_NO_MORE_ENTRIES;
965 if (enumerator->providerDone)
967 enumerator->providerDone = FALSE;
968 if (enumerator->handle)
970 providerTable->table[enumerator->providerIndex].closeEnum(
971 enumerator->handle);
972 enumerator->handle = NULL;
973 enumerator->providerIndex++;
975 for (; enumerator->providerIndex < providerTable->numProviders &&
976 !(enumerator->dwScope & providerTable->table
977 [enumerator->providerIndex].dwEnumScopes);
978 enumerator->providerIndex++)
981 return enumerator->providerIndex < providerTable->numProviders ?
982 WN_SUCCESS : WN_NO_MORE_ENTRIES;
985 /* "Passes through" call to the next provider that supports the enumeration
986 * type.
987 * FIXME: if one call to a provider's enumerator succeeds while there's still
988 * space in lpBuffer, I don't call to the next provider. The caller may not
989 * expect that it should call EnumResourceW again with a return value of
990 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
991 * may have to be moved around a bit, ick.
993 static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator,
994 LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
996 DWORD ret;
998 if (!enumerator)
999 return WN_BAD_POINTER;
1000 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1001 return WN_BAD_VALUE;
1002 if (!lpcCount)
1003 return WN_BAD_POINTER;
1004 if (!lpBuffer)
1005 return WN_BAD_POINTER;
1006 if (!lpBufferSize)
1007 return WN_BAD_POINTER;
1008 if (*lpBufferSize < sizeof(NETRESOURCEW))
1009 return WN_MORE_DATA;
1011 ret = _globalEnumeratorAdvance(enumerator);
1012 if (ret == WN_SUCCESS)
1014 ret = providerTable->table[enumerator->providerIndex].
1015 openEnum(enumerator->dwScope, enumerator->dwType,
1016 enumerator->dwUsage, enumerator->lpNet,
1017 &enumerator->handle);
1018 if (ret == WN_SUCCESS)
1020 ret = providerTable->table[enumerator->providerIndex].
1021 enumResource(enumerator->handle, lpcCount, lpBuffer,
1022 lpBufferSize);
1023 if (ret != WN_MORE_DATA)
1024 enumerator->providerDone = TRUE;
1027 TRACE("Returning %d\n", ret);
1028 return ret;
1031 static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1032 LPVOID lpBuffer, LPDWORD lpBufferSize)
1034 DWORD ret;
1036 if (!enumerator)
1037 return WN_BAD_POINTER;
1038 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1039 return WN_BAD_VALUE;
1040 if (!lpcCount)
1041 return WN_BAD_POINTER;
1042 if (!lpBuffer)
1043 return WN_BAD_POINTER;
1044 if (!lpBufferSize)
1045 return WN_BAD_POINTER;
1046 if (*lpBufferSize < sizeof(NETRESOURCEW))
1047 return WN_MORE_DATA;
1048 if (!providerTable)
1049 return WN_NO_NETWORK;
1051 switch (enumerator->dwScope)
1053 case RESOURCE_GLOBALNET:
1054 if (enumerator->lpNet)
1055 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount,
1056 lpBuffer, lpBufferSize);
1057 else
1058 ret = _enumerateProvidersW(enumerator, lpcCount, lpBuffer,
1059 lpBufferSize);
1060 break;
1061 case RESOURCE_CONTEXT:
1062 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, lpBuffer,
1063 lpBufferSize);
1064 break;
1065 default:
1066 WARN("unexpected scope 0x%08x\n", enumerator->dwScope);
1067 ret = WN_NO_MORE_ENTRIES;
1069 TRACE("Returning %d\n", ret);
1070 return ret;
1073 static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1074 LPVOID lpBuffer, LPDWORD lpBufferSize)
1076 if (!enumerator)
1077 return WN_BAD_POINTER;
1078 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_PROVIDER)
1079 return WN_BAD_VALUE;
1080 if (!enumerator->handle)
1081 return WN_BAD_VALUE;
1082 if (!lpcCount)
1083 return WN_BAD_POINTER;
1084 if (!lpBuffer)
1085 return WN_BAD_POINTER;
1086 if (!lpBufferSize)
1087 return WN_BAD_POINTER;
1088 if (!providerTable)
1089 return WN_NO_NETWORK;
1090 if (enumerator->providerIndex >= providerTable->numProviders)
1091 return WN_NO_MORE_ENTRIES;
1092 if (!providerTable->table[enumerator->providerIndex].enumResource)
1093 return WN_BAD_VALUE;
1094 return providerTable->table[enumerator->providerIndex].enumResource(
1095 enumerator->handle, lpcCount, lpBuffer, lpBufferSize);
1098 static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1099 LPVOID lpBuffer, LPDWORD lpBufferSize)
1101 DWORD ret;
1102 size_t cchEntireNetworkLen, bytesNeeded;
1104 if (!enumerator)
1105 return WN_BAD_POINTER;
1106 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONTEXT)
1107 return WN_BAD_VALUE;
1108 if (!lpcCount)
1109 return WN_BAD_POINTER;
1110 if (!lpBuffer)
1111 return WN_BAD_POINTER;
1112 if (!lpBufferSize)
1113 return WN_BAD_POINTER;
1114 if (!providerTable)
1115 return WN_NO_NETWORK;
1117 cchEntireNetworkLen = strlenW(providerTable->entireNetwork) + 1;
1118 bytesNeeded = sizeof(NETRESOURCEW) + cchEntireNetworkLen * sizeof(WCHAR);
1119 if (*lpBufferSize < bytesNeeded)
1121 *lpBufferSize = bytesNeeded;
1122 ret = WN_MORE_DATA;
1124 else
1126 LPNETRESOURCEW lpNet = (LPNETRESOURCEW)lpBuffer;
1128 lpNet->dwScope = RESOURCE_GLOBALNET;
1129 lpNet->dwType = enumerator->dwType;
1130 lpNet->dwDisplayType = RESOURCEDISPLAYTYPE_ROOT;
1131 lpNet->dwUsage = RESOURCEUSAGE_CONTAINER;
1132 lpNet->lpLocalName = NULL;
1133 lpNet->lpRemoteName = NULL;
1134 lpNet->lpProvider = NULL;
1135 /* odd, but correct: put comment at end of buffer, so it won't get
1136 * overwritten by subsequent calls to a provider's enumResource
1138 lpNet->lpComment = (LPWSTR)((LPBYTE)lpBuffer + *lpBufferSize -
1139 (cchEntireNetworkLen * sizeof(WCHAR)));
1140 strcpyW(lpNet->lpComment, providerTable->entireNetwork);
1141 ret = WN_SUCCESS;
1143 if (ret == WN_SUCCESS)
1145 DWORD bufferSize = *lpBufferSize - bytesNeeded;
1147 /* "Entire Network" entry enumerated--morph this into a global
1148 * enumerator. enumerator->lpNet continues to be NULL, since it has
1149 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1151 enumerator->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
1152 ret = _enumerateGlobalW(enumerator, lpcCount,
1153 (LPBYTE)lpBuffer + bytesNeeded, &bufferSize);
1154 if (ret == WN_SUCCESS)
1156 /* reflect the fact that we already enumerated "Entire Network" */
1157 lpcCount++;
1158 *lpBufferSize = bufferSize + bytesNeeded;
1160 else
1162 /* the provider enumeration failed, but we already succeeded in
1163 * enumerating "Entire Network"--leave type as global to allow a
1164 * retry, but indicate success with a count of one.
1166 ret = WN_SUCCESS;
1167 *lpcCount = 1;
1168 *lpBufferSize = bytesNeeded;
1171 TRACE("Returning %d\n", ret);
1172 return ret;
1175 /*********************************************************************
1176 * WNetEnumResourceW [MPR.@]
1178 DWORD WINAPI WNetEnumResourceW( HANDLE hEnum, LPDWORD lpcCount,
1179 LPVOID lpBuffer, LPDWORD lpBufferSize )
1181 DWORD ret;
1183 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
1185 if (!hEnum)
1186 ret = WN_BAD_POINTER;
1187 else if (!lpcCount)
1188 ret = WN_BAD_POINTER;
1189 else if (!lpBuffer)
1190 ret = WN_BAD_POINTER;
1191 else if (!lpBufferSize)
1192 ret = WN_BAD_POINTER;
1193 else if (*lpBufferSize < sizeof(NETRESOURCEW))
1195 *lpBufferSize = sizeof(NETRESOURCEW);
1196 ret = WN_MORE_DATA;
1198 else
1200 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1202 switch (enumerator->enumType)
1204 case WNET_ENUMERATOR_TYPE_NULL:
1205 ret = WN_NO_MORE_ENTRIES;
1206 break;
1207 case WNET_ENUMERATOR_TYPE_GLOBAL:
1208 ret = _enumerateGlobalW(enumerator, lpcCount, lpBuffer,
1209 lpBufferSize);
1210 break;
1211 case WNET_ENUMERATOR_TYPE_PROVIDER:
1212 ret = _enumerateProviderW(enumerator, lpcCount, lpBuffer,
1213 lpBufferSize);
1214 break;
1215 case WNET_ENUMERATOR_TYPE_CONTEXT:
1216 ret = _enumerateContextW(enumerator, lpcCount, lpBuffer,
1217 lpBufferSize);
1218 break;
1219 default:
1220 WARN("bogus enumerator type!\n");
1221 ret = WN_NO_NETWORK;
1224 if (ret)
1225 SetLastError(ret);
1226 TRACE("Returning %d\n", ret);
1227 return ret;
1230 /*********************************************************************
1231 * WNetCloseEnum [MPR.@]
1233 DWORD WINAPI WNetCloseEnum( HANDLE hEnum )
1235 DWORD ret;
1237 TRACE( "(%p)\n", hEnum );
1239 if (hEnum)
1241 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1243 switch (enumerator->enumType)
1245 case WNET_ENUMERATOR_TYPE_NULL:
1246 ret = WN_SUCCESS;
1247 break;
1248 case WNET_ENUMERATOR_TYPE_GLOBAL:
1249 if (enumerator->lpNet)
1250 _freeEnumNetResource(enumerator->lpNet);
1251 if (enumerator->handle)
1252 providerTable->table[enumerator->providerIndex].
1253 closeEnum(enumerator->handle);
1254 ret = WN_SUCCESS;
1255 break;
1256 case WNET_ENUMERATOR_TYPE_PROVIDER:
1257 if (enumerator->handle)
1258 providerTable->table[enumerator->providerIndex].
1259 closeEnum(enumerator->handle);
1260 ret = WN_SUCCESS;
1261 break;
1262 default:
1263 WARN("bogus enumerator type!\n");
1264 ret = WN_BAD_HANDLE;
1266 HeapFree(GetProcessHeap(), 0, hEnum);
1268 else
1269 ret = WN_BAD_HANDLE;
1270 if (ret)
1271 SetLastError(ret);
1272 TRACE("Returning %d\n", ret);
1273 return ret;
1276 /*********************************************************************
1277 * WNetGetResourceInformationA [MPR.@]
1279 DWORD WINAPI WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource,
1280 LPVOID lpBuffer, LPDWORD cbBuffer,
1281 LPSTR *lplpSystem )
1283 FIXME( "(%p, %p, %p, %p): stub\n",
1284 lpNetResource, lpBuffer, cbBuffer, lplpSystem );
1286 SetLastError(WN_NO_NETWORK);
1287 return WN_NO_NETWORK;
1290 /*********************************************************************
1291 * WNetGetResourceInformationW [MPR.@]
1293 DWORD WINAPI WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource,
1294 LPVOID lpBuffer, LPDWORD cbBuffer,
1295 LPWSTR *lplpSystem )
1297 FIXME( "(%p, %p, %p, %p): stub\n",
1298 lpNetResource, lpBuffer, cbBuffer, lplpSystem );
1300 SetLastError(WN_NO_NETWORK);
1301 return WN_NO_NETWORK;
1304 /*********************************************************************
1305 * WNetGetResourceParentA [MPR.@]
1307 DWORD WINAPI WNetGetResourceParentA( LPNETRESOURCEA lpNetResource,
1308 LPVOID lpBuffer, LPDWORD lpBufferSize )
1310 FIXME( "(%p, %p, %p): stub\n",
1311 lpNetResource, lpBuffer, lpBufferSize );
1313 SetLastError(WN_NO_NETWORK);
1314 return WN_NO_NETWORK;
1317 /*********************************************************************
1318 * WNetGetResourceParentW [MPR.@]
1320 DWORD WINAPI WNetGetResourceParentW( LPNETRESOURCEW lpNetResource,
1321 LPVOID lpBuffer, LPDWORD lpBufferSize )
1323 FIXME( "(%p, %p, %p): stub\n",
1324 lpNetResource, lpBuffer, lpBufferSize );
1326 SetLastError(WN_NO_NETWORK);
1327 return WN_NO_NETWORK;
1333 * Connection Functions
1336 /*********************************************************************
1337 * WNetAddConnectionA [MPR.@]
1339 DWORD WINAPI WNetAddConnectionA( LPCSTR lpRemoteName, LPCSTR lpPassword,
1340 LPCSTR lpLocalName )
1342 FIXME( "(%s, %p, %s): stub\n",
1343 debugstr_a(lpRemoteName), lpPassword, debugstr_a(lpLocalName) );
1345 SetLastError(WN_NO_NETWORK);
1346 return WN_NO_NETWORK;
1349 /*********************************************************************
1350 * WNetAddConnectionW [MPR.@]
1352 DWORD WINAPI WNetAddConnectionW( LPCWSTR lpRemoteName, LPCWSTR lpPassword,
1353 LPCWSTR lpLocalName )
1355 FIXME( "(%s, %p, %s): stub\n",
1356 debugstr_w(lpRemoteName), lpPassword, debugstr_w(lpLocalName) );
1358 SetLastError(WN_NO_NETWORK);
1359 return WN_NO_NETWORK;
1362 /*********************************************************************
1363 * WNetAddConnection2A [MPR.@]
1365 DWORD WINAPI WNetAddConnection2A( LPNETRESOURCEA lpNetResource,
1366 LPCSTR lpPassword, LPCSTR lpUserID,
1367 DWORD dwFlags )
1369 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1370 lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
1372 SetLastError(WN_NO_NETWORK);
1373 return WN_NO_NETWORK;
1376 /*********************************************************************
1377 * WNetAddConnection2W [MPR.@]
1379 DWORD WINAPI WNetAddConnection2W( LPNETRESOURCEW lpNetResource,
1380 LPCWSTR lpPassword, LPCWSTR lpUserID,
1381 DWORD dwFlags )
1383 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1384 lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
1386 SetLastError(WN_NO_NETWORK);
1387 return WN_NO_NETWORK;
1390 /*********************************************************************
1391 * WNetAddConnection3A [MPR.@]
1393 DWORD WINAPI WNetAddConnection3A( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
1394 LPCSTR lpPassword, LPCSTR lpUserID,
1395 DWORD dwFlags )
1397 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1398 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
1400 SetLastError(WN_NO_NETWORK);
1401 return WN_NO_NETWORK;
1404 /*********************************************************************
1405 * WNetAddConnection3W [MPR.@]
1407 DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
1408 LPCWSTR lpPassword, LPCWSTR lpUserID,
1409 DWORD dwFlags )
1411 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1412 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
1414 SetLastError(WN_NO_NETWORK);
1415 return WN_NO_NETWORK;
1418 /*****************************************************************
1419 * WNetUseConnectionA [MPR.@]
1421 DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
1422 LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags,
1423 LPSTR lpAccessName, LPDWORD lpBufferSize,
1424 LPDWORD lpResult )
1426 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1427 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags,
1428 debugstr_a(lpAccessName), lpBufferSize, lpResult );
1430 SetLastError(WN_NO_NETWORK);
1431 return WN_NO_NETWORK;
1434 /*****************************************************************
1435 * WNetUseConnectionW [MPR.@]
1437 DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
1438 LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags,
1439 LPWSTR lpAccessName, LPDWORD lpBufferSize,
1440 LPDWORD lpResult )
1442 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1443 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags,
1444 debugstr_w(lpAccessName), lpBufferSize, lpResult );
1446 SetLastError(WN_NO_NETWORK);
1447 return WN_NO_NETWORK;
1450 /*********************************************************************
1451 * WNetCancelConnectionA [MPR.@]
1453 DWORD WINAPI WNetCancelConnectionA( LPCSTR lpName, BOOL fForce )
1455 FIXME( "(%s, %d), stub\n", debugstr_a(lpName), fForce );
1457 return WN_SUCCESS;
1460 /*********************************************************************
1461 * WNetCancelConnectionW [MPR.@]
1463 DWORD WINAPI WNetCancelConnectionW( LPCWSTR lpName, BOOL fForce )
1465 FIXME( "(%s, %d), stub\n", debugstr_w(lpName), fForce );
1467 return WN_SUCCESS;
1470 /*********************************************************************
1471 * WNetCancelConnection2A [MPR.@]
1473 DWORD WINAPI WNetCancelConnection2A( LPCSTR lpName, DWORD dwFlags, BOOL fForce )
1475 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName), dwFlags, fForce );
1477 return WN_SUCCESS;
1480 /*********************************************************************
1481 * WNetCancelConnection2W [MPR.@]
1483 DWORD WINAPI WNetCancelConnection2W( LPCWSTR lpName, DWORD dwFlags, BOOL fForce )
1485 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName), dwFlags, fForce );
1487 return WN_SUCCESS;
1490 /*****************************************************************
1491 * WNetRestoreConnectionA [MPR.@]
1493 DWORD WINAPI WNetRestoreConnectionA( HWND hwndOwner, LPCSTR lpszDevice )
1495 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_a(lpszDevice) );
1497 SetLastError(WN_NO_NETWORK);
1498 return WN_NO_NETWORK;
1501 /*****************************************************************
1502 * WNetRestoreConnectionW [MPR.@]
1504 DWORD WINAPI WNetRestoreConnectionW( HWND hwndOwner, LPCWSTR lpszDevice )
1506 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_w(lpszDevice) );
1508 SetLastError(WN_NO_NETWORK);
1509 return WN_NO_NETWORK;
1512 /**************************************************************************
1513 * WNetGetConnectionA [MPR.@]
1515 * RETURNS
1516 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1517 * - WN_NOT_CONNECTED drive is a local drive
1518 * - WN_MORE_DATA buffer isn't big enough
1519 * - WN_SUCCESS success (net path in buffer)
1521 * FIXME: need to test return values under different errors
1523 DWORD WINAPI WNetGetConnectionA( LPCSTR lpLocalName,
1524 LPSTR lpRemoteName, LPDWORD lpBufferSize )
1526 DWORD ret;
1528 if (!lpLocalName)
1529 ret = WN_BAD_POINTER;
1530 else if (!lpBufferSize)
1531 ret = WN_BAD_POINTER;
1532 else if (!lpRemoteName && *lpBufferSize)
1533 ret = WN_BAD_POINTER;
1534 else
1536 int len = MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, NULL, 0);
1538 if (len)
1540 PWSTR wideLocalName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1542 if (wideLocalName)
1544 WCHAR wideRemoteStatic[MAX_PATH];
1545 DWORD wideRemoteSize = sizeof(wideRemoteStatic) / sizeof(WCHAR);
1547 MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, wideLocalName, len);
1549 /* try once without memory allocation */
1550 ret = WNetGetConnectionW(wideLocalName, wideRemoteStatic,
1551 &wideRemoteSize);
1552 if (ret == WN_SUCCESS)
1554 int len = WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
1555 -1, NULL, 0, NULL, NULL);
1557 if (len <= *lpBufferSize)
1559 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, -1,
1560 lpRemoteName, *lpBufferSize, NULL, NULL);
1561 ret = WN_SUCCESS;
1563 else
1565 *lpBufferSize = len;
1566 ret = WN_MORE_DATA;
1569 else if (ret == WN_MORE_DATA)
1571 PWSTR wideRemote = HeapAlloc(GetProcessHeap(), 0,
1572 wideRemoteSize * sizeof(WCHAR));
1574 if (wideRemote)
1576 ret = WNetGetConnectionW(wideLocalName, wideRemote,
1577 &wideRemoteSize);
1578 if (ret == WN_SUCCESS)
1580 if (len <= *lpBufferSize)
1582 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
1583 -1, lpRemoteName, *lpBufferSize, NULL, NULL);
1584 ret = WN_SUCCESS;
1586 else
1588 *lpBufferSize = len;
1589 ret = WN_MORE_DATA;
1592 HeapFree(GetProcessHeap(), 0, wideRemote);
1594 else
1595 ret = WN_OUT_OF_MEMORY;
1597 HeapFree(GetProcessHeap(), 0, wideLocalName);
1599 else
1600 ret = WN_OUT_OF_MEMORY;
1602 else
1603 ret = WN_BAD_LOCALNAME;
1605 if (ret)
1606 SetLastError(ret);
1607 TRACE("Returning %d\n", ret);
1608 return ret;
1611 /**************************************************************************
1612 * WNetGetConnectionW [MPR.@]
1614 * FIXME: need to test return values under different errors
1616 DWORD WINAPI WNetGetConnectionW( LPCWSTR lpLocalName,
1617 LPWSTR lpRemoteName, LPDWORD lpBufferSize )
1619 DWORD ret;
1621 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName), lpRemoteName,
1622 lpBufferSize);
1624 if (!lpLocalName)
1625 ret = WN_BAD_POINTER;
1626 else if (!lpBufferSize)
1627 ret = WN_BAD_POINTER;
1628 else if (!lpRemoteName && *lpBufferSize)
1629 ret = WN_BAD_POINTER;
1630 else if (!lpLocalName[0])
1631 ret = WN_BAD_LOCALNAME;
1632 else
1634 if (lpLocalName[1] == ':')
1636 switch(GetDriveTypeW(lpLocalName))
1638 case DRIVE_REMOTE:
1640 static const WCHAR unc[] = { 'u','n','c','\\' };
1641 WCHAR rremote[MAX_PATH], *remote = rremote;
1642 if (!QueryDosDeviceW( lpLocalName, remote, MAX_PATH )) remote[0] = 0;
1643 else if (!strncmpW(remote, unc, 4))
1645 remote += 2;
1646 remote[0] = '\\';
1648 else if (remote[0] != '\\' || remote[1] != '\\')
1649 FIXME("Don't know how to convert %s to an unc\n", debugstr_w(remote));
1651 if (strlenW(remote) + 1 > *lpBufferSize)
1653 *lpBufferSize = strlenW(remote) + 1;
1654 ret = WN_MORE_DATA;
1656 else
1658 strcpyW( lpRemoteName, remote );
1659 *lpBufferSize = strlenW(lpRemoteName) + 1;
1660 ret = WN_SUCCESS;
1662 break;
1664 case DRIVE_REMOVABLE:
1665 case DRIVE_FIXED:
1666 case DRIVE_CDROM:
1667 TRACE("file is local\n");
1668 ret = WN_NOT_CONNECTED;
1669 break;
1670 default:
1671 ret = WN_BAD_LOCALNAME;
1674 else
1675 ret = WN_BAD_LOCALNAME;
1677 if (ret)
1678 SetLastError(ret);
1679 TRACE("Returning %d\n", ret);
1680 return ret;
1683 /**************************************************************************
1684 * WNetSetConnectionA [MPR.@]
1686 DWORD WINAPI WNetSetConnectionA( LPCSTR lpName, DWORD dwProperty,
1687 LPVOID pvValue )
1689 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName), dwProperty, pvValue );
1691 SetLastError(WN_NO_NETWORK);
1692 return WN_NO_NETWORK;
1695 /**************************************************************************
1696 * WNetSetConnectionW [MPR.@]
1698 DWORD WINAPI WNetSetConnectionW( LPCWSTR lpName, DWORD dwProperty,
1699 LPVOID pvValue )
1701 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName), dwProperty, pvValue );
1703 SetLastError(WN_NO_NETWORK);
1704 return WN_NO_NETWORK;
1707 /*****************************************************************
1708 * WNetGetUniversalNameA [MPR.@]
1710 DWORD WINAPI WNetGetUniversalNameA ( LPCSTR lpLocalPath, DWORD dwInfoLevel,
1711 LPVOID lpBuffer, LPDWORD lpBufferSize )
1713 DWORD err, size;
1715 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1716 debugstr_a(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
1718 switch (dwInfoLevel)
1720 case UNIVERSAL_NAME_INFO_LEVEL:
1722 LPUNIVERSAL_NAME_INFOA info = (LPUNIVERSAL_NAME_INFOA)lpBuffer;
1724 size = sizeof(*info) + lstrlenA(lpLocalPath) + 1;
1725 if (*lpBufferSize < size)
1727 err = WN_MORE_DATA;
1728 break;
1730 info->lpUniversalName = (char *)info + sizeof(*info);
1731 lstrcpyA(info->lpUniversalName, lpLocalPath);
1732 *lpBufferSize = size;
1733 err = WN_NO_ERROR;
1734 break;
1736 case REMOTE_NAME_INFO_LEVEL:
1737 err = WN_NO_NETWORK;
1738 break;
1740 default:
1741 err = WN_BAD_VALUE;
1742 break;
1745 SetLastError(err);
1746 return err;
1749 /*****************************************************************
1750 * WNetGetUniversalNameW [MPR.@]
1752 DWORD WINAPI WNetGetUniversalNameW ( LPCWSTR lpLocalPath, DWORD dwInfoLevel,
1753 LPVOID lpBuffer, LPDWORD lpBufferSize )
1755 DWORD err, size;
1757 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1758 debugstr_w(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
1760 switch (dwInfoLevel)
1762 case UNIVERSAL_NAME_INFO_LEVEL:
1764 LPUNIVERSAL_NAME_INFOW info = (LPUNIVERSAL_NAME_INFOW)lpBuffer;
1766 size = sizeof(*info) + (lstrlenW(lpLocalPath) + 1) * sizeof(WCHAR);
1767 if (*lpBufferSize < size)
1769 err = WN_MORE_DATA;
1770 break;
1772 info->lpUniversalName = (LPWSTR)((char *)info + sizeof(*info));
1773 lstrcpyW(info->lpUniversalName, lpLocalPath);
1774 *lpBufferSize = size;
1775 err = WN_NO_ERROR;
1776 break;
1778 case REMOTE_NAME_INFO_LEVEL:
1779 err = WN_NO_NETWORK;
1780 break;
1782 default:
1783 err = WN_BAD_VALUE;
1784 break;
1787 SetLastError(err);
1788 return err;
1794 * Other Functions
1797 /**************************************************************************
1798 * WNetGetUserA [MPR.@]
1800 * FIXME: we should not return ourselves, but the owner of the drive lpName
1802 DWORD WINAPI WNetGetUserA( LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize )
1804 if (GetUserNameA( lpUserID, lpBufferSize )) return WN_SUCCESS;
1805 return GetLastError();
1808 /*****************************************************************
1809 * WNetGetUserW [MPR.@]
1811 * FIXME: we should not return ourselves, but the owner of the drive lpName
1813 DWORD WINAPI WNetGetUserW( LPCWSTR lpName, LPWSTR lpUserID, LPDWORD lpBufferSize )
1815 if (GetUserNameW( lpUserID, lpBufferSize )) return WN_SUCCESS;
1816 return GetLastError();
1819 /*********************************************************************
1820 * WNetConnectionDialog [MPR.@]
1822 DWORD WINAPI WNetConnectionDialog( HWND hwnd, DWORD dwType )
1824 FIXME( "(%p, %08X): stub\n", hwnd, dwType );
1826 SetLastError(WN_NO_NETWORK);
1827 return WN_NO_NETWORK;
1830 /*********************************************************************
1831 * WNetConnectionDialog1A [MPR.@]
1833 DWORD WINAPI WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct )
1835 FIXME( "(%p): stub\n", lpConnDlgStruct );
1837 SetLastError(WN_NO_NETWORK);
1838 return WN_NO_NETWORK;
1841 /*********************************************************************
1842 * WNetConnectionDialog1W [MPR.@]
1844 DWORD WINAPI WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct )
1846 FIXME( "(%p): stub\n", lpConnDlgStruct );
1848 SetLastError(WN_NO_NETWORK);
1849 return WN_NO_NETWORK;
1852 /*********************************************************************
1853 * WNetDisconnectDialog [MPR.@]
1855 DWORD WINAPI WNetDisconnectDialog( HWND hwnd, DWORD dwType )
1857 FIXME( "(%p, %08X): stub\n", hwnd, dwType );
1859 SetLastError(WN_NO_NETWORK);
1860 return WN_NO_NETWORK;
1863 /*********************************************************************
1864 * WNetDisconnectDialog1A [MPR.@]
1866 DWORD WINAPI WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct )
1868 FIXME( "(%p): stub\n", lpConnDlgStruct );
1870 SetLastError(WN_NO_NETWORK);
1871 return WN_NO_NETWORK;
1874 /*********************************************************************
1875 * WNetDisconnectDialog1W [MPR.@]
1877 DWORD WINAPI WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct )
1879 FIXME( "(%p): stub\n", lpConnDlgStruct );
1881 SetLastError(WN_NO_NETWORK);
1882 return WN_NO_NETWORK;
1885 /*********************************************************************
1886 * WNetGetLastErrorA [MPR.@]
1888 DWORD WINAPI WNetGetLastErrorA( LPDWORD lpError,
1889 LPSTR lpErrorBuf, DWORD nErrorBufSize,
1890 LPSTR lpNameBuf, DWORD nNameBufSize )
1892 FIXME( "(%p, %p, %d, %p, %d): stub\n",
1893 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
1895 SetLastError(WN_NO_NETWORK);
1896 return WN_NO_NETWORK;
1899 /*********************************************************************
1900 * WNetGetLastErrorW [MPR.@]
1902 DWORD WINAPI WNetGetLastErrorW( LPDWORD lpError,
1903 LPWSTR lpErrorBuf, DWORD nErrorBufSize,
1904 LPWSTR lpNameBuf, DWORD nNameBufSize )
1906 FIXME( "(%p, %p, %d, %p, %d): stub\n",
1907 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
1909 SetLastError(WN_NO_NETWORK);
1910 return WN_NO_NETWORK;
1913 /*********************************************************************
1914 * WNetGetNetworkInformationA [MPR.@]
1916 DWORD WINAPI WNetGetNetworkInformationA( LPCSTR lpProvider,
1917 LPNETINFOSTRUCT lpNetInfoStruct )
1919 DWORD ret;
1921 TRACE( "(%s, %p)\n", debugstr_a(lpProvider), lpNetInfoStruct );
1923 if (!lpProvider)
1924 ret = WN_BAD_POINTER;
1925 else
1927 int len;
1929 len = MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, NULL, 0);
1930 if (len)
1932 LPWSTR wideProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1934 if (wideProvider)
1936 MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, wideProvider,
1937 len);
1938 ret = WNetGetNetworkInformationW(wideProvider, lpNetInfoStruct);
1939 HeapFree(GetProcessHeap(), 0, wideProvider);
1941 else
1942 ret = WN_OUT_OF_MEMORY;
1944 else
1945 ret = GetLastError();
1947 if (ret)
1948 SetLastError(ret);
1949 TRACE("Returning %d\n", ret);
1950 return ret;
1953 /*********************************************************************
1954 * WNetGetNetworkInformationW [MPR.@]
1956 DWORD WINAPI WNetGetNetworkInformationW( LPCWSTR lpProvider,
1957 LPNETINFOSTRUCT lpNetInfoStruct )
1959 DWORD ret;
1961 TRACE( "(%s, %p)\n", debugstr_w(lpProvider), lpNetInfoStruct );
1963 if (!lpProvider)
1964 ret = WN_BAD_POINTER;
1965 else if (!lpNetInfoStruct)
1966 ret = WN_BAD_POINTER;
1967 else if (lpNetInfoStruct->cbStructure < sizeof(NETINFOSTRUCT))
1968 ret = WN_BAD_VALUE;
1969 else
1971 if (providerTable && providerTable->numProviders)
1973 DWORD providerIndex = _findProviderIndexW(lpProvider);
1975 if (providerIndex != BAD_PROVIDER_INDEX)
1977 lpNetInfoStruct->cbStructure = sizeof(NETINFOSTRUCT);
1978 lpNetInfoStruct->dwProviderVersion =
1979 providerTable->table[providerIndex].dwSpecVersion;
1980 lpNetInfoStruct->dwStatus = NO_ERROR;
1981 lpNetInfoStruct->dwCharacteristics = 0;
1982 lpNetInfoStruct->dwHandle = (ULONG_PTR)NULL;
1983 lpNetInfoStruct->wNetType =
1984 HIWORD(providerTable->table[providerIndex].dwNetType);
1985 lpNetInfoStruct->dwPrinters = -1;
1986 lpNetInfoStruct->dwDrives = -1;
1987 ret = WN_SUCCESS;
1989 else
1990 ret = WN_BAD_PROVIDER;
1992 else
1993 ret = WN_NO_NETWORK;
1995 if (ret)
1996 SetLastError(ret);
1997 TRACE("Returning %d\n", ret);
1998 return ret;
2001 /*****************************************************************
2002 * WNetGetProviderNameA [MPR.@]
2004 DWORD WINAPI WNetGetProviderNameA( DWORD dwNetType,
2005 LPSTR lpProvider, LPDWORD lpBufferSize )
2007 DWORD ret;
2009 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_a(lpProvider),
2010 lpBufferSize);
2012 if (!lpProvider)
2013 ret = WN_BAD_POINTER;
2014 else if (!lpBufferSize)
2015 ret = WN_BAD_POINTER;
2016 else
2018 if (providerTable)
2020 DWORD i;
2022 ret = WN_NO_NETWORK;
2023 for (i = 0; i < providerTable->numProviders &&
2024 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
2025 i++)
2027 if (i < providerTable->numProviders)
2029 DWORD sizeNeeded = WideCharToMultiByte(CP_ACP, 0,
2030 providerTable->table[i].name, -1, NULL, 0, NULL, NULL);
2032 if (*lpBufferSize < sizeNeeded)
2034 *lpBufferSize = sizeNeeded;
2035 ret = WN_MORE_DATA;
2037 else
2039 WideCharToMultiByte(CP_ACP, 0, providerTable->table[i].name,
2040 -1, lpProvider, *lpBufferSize, NULL, NULL);
2041 ret = WN_SUCCESS;
2042 /* FIXME: is *lpBufferSize set to the number of characters
2043 * copied? */
2047 else
2048 ret = WN_NO_NETWORK;
2050 if (ret)
2051 SetLastError(ret);
2052 TRACE("Returning %d\n", ret);
2053 return ret;
2056 /*****************************************************************
2057 * WNetGetProviderNameW [MPR.@]
2059 DWORD WINAPI WNetGetProviderNameW( DWORD dwNetType,
2060 LPWSTR lpProvider, LPDWORD lpBufferSize )
2062 DWORD ret;
2064 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_w(lpProvider),
2065 lpBufferSize);
2067 if (!lpProvider)
2068 ret = WN_BAD_POINTER;
2069 else if (!lpBufferSize)
2070 ret = WN_BAD_POINTER;
2071 else
2073 if (providerTable)
2075 DWORD i;
2077 ret = WN_NO_NETWORK;
2078 for (i = 0; i < providerTable->numProviders &&
2079 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
2080 i++)
2082 if (i < providerTable->numProviders)
2084 DWORD sizeNeeded = strlenW(providerTable->table[i].name) + 1;
2086 if (*lpBufferSize < sizeNeeded)
2088 *lpBufferSize = sizeNeeded;
2089 ret = WN_MORE_DATA;
2091 else
2093 strcpyW(lpProvider, providerTable->table[i].name);
2094 ret = WN_SUCCESS;
2095 /* FIXME: is *lpBufferSize set to the number of characters
2096 * copied? */
2100 else
2101 ret = WN_NO_NETWORK;
2103 if (ret)
2104 SetLastError(ret);
2105 TRACE("Returning %d\n", ret);
2106 return ret;