quartz: Only allocate 1 buffer in transform filter.
[wine/wine64.git] / dlls / mpr / wnet.c
blobbf4ddb858079c94543843645b0653478dfc81ffa
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 PF_NPGetResourceInformation getResourceInformation;
56 } WNetProvider, *PWNetProvider;
58 typedef struct _WNetProviderTable
60 LPWSTR entireNetwork;
61 DWORD numAllocated;
62 DWORD numProviders;
63 WNetProvider table[1];
64 } WNetProviderTable, *PWNetProviderTable;
66 #define WNET_ENUMERATOR_TYPE_NULL 0
67 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
68 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
69 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
71 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
72 * the enumeration; it represents one of the following types:
73 * - a 'null' enumeration, one that contains no members
74 * - a global enumeration, one that's executed across all providers
75 * - a provider-specific enumeration, one that's only executed by a single
76 * provider
77 * - a context enumeration. I know this contradicts what I just said about
78 * there being no correspondence between the scope and the type, but it's
79 * necessary for the special case that a "Entire Network" entry needs to
80 * be enumerated in an enumeration of the context scope. Thus an enumeration
81 * of the context scope results in a context type enumerator, which morphs
82 * into a global enumeration (so the enumeration continues across all
83 * providers).
85 typedef struct _WNetEnumerator
87 DWORD enumType;
88 DWORD providerIndex;
89 HANDLE handle;
90 BOOL providerDone;
91 DWORD dwScope;
92 DWORD dwType;
93 DWORD dwUsage;
94 LPNETRESOURCEW lpNet;
95 } WNetEnumerator, *PWNetEnumerator;
97 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
99 /* Returns an index (into the global WNetProviderTable) of the provider with
100 * the given name, or BAD_PROVIDER_INDEX if not found.
102 static DWORD _findProviderIndexW(LPCWSTR lpProvider);
104 static PWNetProviderTable providerTable;
107 * Global provider table functions
110 static void _tryLoadProvider(PCWSTR provider)
112 static const WCHAR servicePrefix[] = { 'S','y','s','t','e','m','\\',
113 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
114 'S','e','r','v','i','c','e','s','\\',0 };
115 static const WCHAR serviceFmt[] = { '%','s','%','s','\\',
116 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
117 WCHAR serviceName[MAX_PATH];
118 HKEY hKey;
120 TRACE("%s\n", debugstr_w(provider));
121 snprintfW(serviceName, sizeof(serviceName) / sizeof(WCHAR), serviceFmt,
122 servicePrefix, provider);
123 serviceName[sizeof(serviceName) / sizeof(WCHAR) - 1] = '\0';
124 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, serviceName, 0, KEY_READ, &hKey) ==
125 ERROR_SUCCESS)
127 static const WCHAR szProviderPath[] = { 'P','r','o','v','i','d','e','r',
128 'P','a','t','h',0 };
129 WCHAR providerPath[MAX_PATH];
130 DWORD type, size = sizeof(providerPath);
132 if (RegQueryValueExW(hKey, szProviderPath, NULL, &type,
133 (LPBYTE)providerPath, &size) == ERROR_SUCCESS && type == REG_SZ)
135 static const WCHAR szProviderName[] = { 'N','a','m','e',0 };
136 PWSTR name = NULL;
138 size = 0;
139 RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size);
140 if (size)
142 name = HeapAlloc(GetProcessHeap(), 0, size);
143 if (RegQueryValueExW(hKey, szProviderName, NULL, &type,
144 (LPBYTE)name, &size) != ERROR_SUCCESS || type != REG_SZ)
146 HeapFree(GetProcessHeap(), 0, name);
147 name = NULL;
150 if (name)
152 HMODULE hLib = LoadLibraryW(providerPath);
154 if (hLib)
156 PF_NPGetCaps getCaps = (PF_NPGetCaps)GetProcAddress(hLib,
157 "NPGetCaps");
159 TRACE("loaded lib %p\n", hLib);
160 if (getCaps)
162 PWNetProvider provider =
163 &providerTable->table[providerTable->numProviders];
165 provider->hLib = hLib;
166 provider->name = name;
167 TRACE("name is %s\n", debugstr_w(name));
168 provider->getCaps = getCaps;
169 provider->dwSpecVersion = getCaps(WNNC_SPEC_VERSION);
170 provider->dwNetType = getCaps(WNNC_NET_TYPE);
171 TRACE("net type is 0x%08x\n", provider->dwNetType);
172 provider->dwEnumScopes = getCaps(WNNC_ENUMERATION);
173 if (provider->dwEnumScopes)
175 TRACE("supports enumeration\n");
176 provider->openEnum = (PF_NPOpenEnum)
177 GetProcAddress(hLib, "NPOpenEnum");
178 TRACE("openEnum is %p\n", provider->openEnum);
179 provider->enumResource = (PF_NPEnumResource)
180 GetProcAddress(hLib, "NPEnumResource");
181 TRACE("enumResource is %p\n",
182 provider->enumResource);
183 provider->closeEnum = (PF_NPCloseEnum)
184 GetProcAddress(hLib, "NPCloseEnum");
185 TRACE("closeEnum is %p\n", provider->closeEnum);
186 provider->getResourceInformation = (PF_NPGetResourceInformation)
187 GetProcAddress(hLib, "NPGetResourceInformation");
188 TRACE("getResourceInformation is %p\n",
189 provider->getResourceInformation);
190 if (!provider->openEnum || !provider->enumResource
191 || !provider->closeEnum)
193 provider->openEnum = NULL;
194 provider->enumResource = NULL;
195 provider->closeEnum = NULL;
196 provider->dwEnumScopes = 0;
197 WARN("Couldn't load enumeration functions\n");
200 providerTable->numProviders++;
202 else
204 WARN("Provider %s didn't export NPGetCaps\n",
205 debugstr_w(provider));
206 HeapFree(GetProcessHeap(), 0, name);
207 FreeLibrary(hLib);
210 else
212 WARN("Couldn't load library %s for provider %s\n",
213 debugstr_w(providerPath), debugstr_w(provider));
214 HeapFree(GetProcessHeap(), 0, name);
217 else
219 WARN("Couldn't get provider name for provider %s\n",
220 debugstr_w(provider));
223 else
224 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath));
225 RegCloseKey(hKey);
227 else
228 WARN("Couldn't open service key for provider %s\n",
229 debugstr_w(provider));
232 void wnetInit(HINSTANCE hInstDll)
234 static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\',
235 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
236 'C','o','n','t','r','o','l','\\',
237 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
238 'O','r','d','e','r',0 };
239 static const WCHAR providerOrder[] = { 'P','r','o','v','i','d','e','r',
240 'O','r','d','e','r',0 };
241 HKEY hKey;
243 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, providerOrderKey, 0, KEY_READ, &hKey)
244 == ERROR_SUCCESS)
246 DWORD size = 0;
248 RegQueryValueExW(hKey, providerOrder, NULL, NULL, NULL, &size);
249 if (size)
251 PWSTR providers = HeapAlloc(GetProcessHeap(), 0, size);
253 if (providers)
255 DWORD type;
257 if (RegQueryValueExW(hKey, providerOrder, NULL, &type,
258 (LPBYTE)providers, &size) == ERROR_SUCCESS && type == REG_SZ)
260 PWSTR ptr;
261 DWORD numToAllocate;
263 TRACE("provider order is %s\n", debugstr_w(providers));
264 /* first count commas as a heuristic for how many to
265 * allocate space for */
266 for (ptr = providers, numToAllocate = 1; ptr; )
268 ptr = strchrW(ptr, ',');
269 if (ptr) {
270 numToAllocate++;
271 ptr++;
274 providerTable =
275 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
276 sizeof(WNetProviderTable)
277 + (numToAllocate - 1) * sizeof(WNetProvider));
278 if (providerTable)
280 PWSTR ptrPrev;
281 int entireNetworkLen;
282 LPCWSTR stringresource;
284 entireNetworkLen = LoadStringW(hInstDll,
285 IDS_ENTIRENETWORK, (LPWSTR)&stringresource, 0);
286 providerTable->entireNetwork = HeapAlloc(
287 GetProcessHeap(), 0, (entireNetworkLen + 1) *
288 sizeof(WCHAR));
289 if (providerTable->entireNetwork)
291 memcpy(providerTable->entireNetwork, stringresource, entireNetworkLen*sizeof(WCHAR));
292 providerTable->entireNetwork[entireNetworkLen] = 0;
294 providerTable->numAllocated = numToAllocate;
295 for (ptr = providers; ptr; )
297 ptrPrev = ptr;
298 ptr = strchrW(ptr, ',');
299 if (ptr)
300 *ptr++ = '\0';
301 _tryLoadProvider(ptrPrev);
305 HeapFree(GetProcessHeap(), 0, providers);
308 RegCloseKey(hKey);
312 void wnetFree(void)
314 if (providerTable)
316 DWORD i;
318 for (i = 0; i < providerTable->numProviders; i++)
320 HeapFree(GetProcessHeap(), 0, providerTable->table[i].name);
321 FreeModule(providerTable->table[i].hLib);
323 HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork);
324 HeapFree(GetProcessHeap(), 0, providerTable);
325 providerTable = NULL;
329 static DWORD _findProviderIndexW(LPCWSTR lpProvider)
331 DWORD ret = BAD_PROVIDER_INDEX;
333 if (providerTable && providerTable->numProviders)
335 DWORD i;
337 for (i = 0; i < providerTable->numProviders &&
338 ret == BAD_PROVIDER_INDEX; i++)
339 if (!strcmpW(lpProvider, providerTable->table[i].name))
340 ret = i;
342 return ret;
346 * Browsing Functions
349 static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet)
351 LPNETRESOURCEW ret;
353 if (lpNet)
355 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW));
356 if (ret)
358 size_t len;
360 *ret = *lpNet;
361 ret->lpLocalName = ret->lpComment = ret->lpProvider = NULL;
362 if (lpNet->lpRemoteName)
364 len = strlenW(lpNet->lpRemoteName) + 1;
365 ret->lpRemoteName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
366 if (ret->lpRemoteName)
367 strcpyW(ret->lpRemoteName, lpNet->lpRemoteName);
371 else
372 ret = NULL;
373 return ret;
376 static void _freeEnumNetResource(LPNETRESOURCEW lpNet)
378 if (lpNet)
380 HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName);
381 HeapFree(GetProcessHeap(), 0, lpNet);
385 static PWNetEnumerator _createNullEnumerator(void)
387 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
388 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
390 if (ret)
391 ret->enumType = WNET_ENUMERATOR_TYPE_NULL;
392 return ret;
395 static PWNetEnumerator _createGlobalEnumeratorW(DWORD dwScope, DWORD dwType,
396 DWORD dwUsage, LPNETRESOURCEW lpNet)
398 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
399 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
401 if (ret)
403 ret->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
404 ret->dwScope = dwScope;
405 ret->dwType = dwType;
406 ret->dwUsage = dwUsage;
407 ret->lpNet = _copyNetResourceForEnumW(lpNet);
409 return ret;
412 static PWNetEnumerator _createProviderEnumerator(DWORD dwScope, DWORD dwType,
413 DWORD dwUsage, DWORD index, HANDLE handle)
415 PWNetEnumerator ret;
417 if (!providerTable || index >= providerTable->numProviders)
418 ret = NULL;
419 else
421 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
422 if (ret)
424 ret->enumType = WNET_ENUMERATOR_TYPE_PROVIDER;
425 ret->providerIndex = index;
426 ret->dwScope = dwScope;
427 ret->dwType = dwType;
428 ret->dwUsage = dwUsage;
429 ret->handle = handle;
432 return ret;
435 static PWNetEnumerator _createContextEnumerator(DWORD dwScope, DWORD dwType,
436 DWORD dwUsage)
438 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(),
439 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator));
441 if (ret)
443 ret->enumType = WNET_ENUMERATOR_TYPE_CONTEXT;
444 ret->dwScope = dwScope;
445 ret->dwType = dwType;
446 ret->dwUsage = dwUsage;
448 return ret;
451 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
452 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
453 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
454 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
455 * if not all members of the array could be thunked, and something else on
456 * failure.
458 static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn,
459 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
461 DWORD i, numToThunk, totalBytes, ret;
462 LPSTR strNext;
464 if (!lpNetArrayIn)
465 return WN_BAD_POINTER;
466 if (!lpcCount)
467 return WN_BAD_POINTER;
468 if (*lpcCount == -1)
469 return WN_BAD_VALUE;
470 if (!lpBuffer)
471 return WN_BAD_POINTER;
472 if (!lpBufferSize)
473 return WN_BAD_POINTER;
475 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
477 const NETRESOURCEW *lpNet = lpNetArrayIn + i;
479 totalBytes += sizeof(NETRESOURCEA);
480 if (lpNet->lpLocalName)
481 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpLocalName,
482 -1, NULL, 0, NULL, NULL);
483 if (lpNet->lpRemoteName)
484 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpRemoteName,
485 -1, NULL, 0, NULL, NULL);
486 if (lpNet->lpComment)
487 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpComment,
488 -1, NULL, 0, NULL, NULL);
489 if (lpNet->lpProvider)
490 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpProvider,
491 -1, NULL, 0, NULL, NULL);
492 if (totalBytes < *lpBufferSize)
493 numToThunk = i + 1;
495 strNext = (LPSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEA));
496 for (i = 0; i < numToThunk; i++)
498 LPNETRESOURCEA lpNetOut = (LPNETRESOURCEA)lpBuffer + i;
499 const NETRESOURCEW *lpNetIn = lpNetArrayIn + i;
501 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEA));
502 /* lie about string lengths, we already verified how many
503 * we have space for above
505 if (lpNetIn->lpLocalName)
507 lpNetOut->lpLocalName = strNext;
508 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpLocalName, -1,
509 lpNetOut->lpLocalName, *lpBufferSize, NULL, NULL);
511 if (lpNetIn->lpRemoteName)
513 lpNetOut->lpRemoteName = strNext;
514 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpRemoteName, -1,
515 lpNetOut->lpRemoteName, *lpBufferSize, NULL, NULL);
517 if (lpNetIn->lpComment)
519 lpNetOut->lpComment = strNext;
520 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpComment, -1,
521 lpNetOut->lpComment, *lpBufferSize, NULL, NULL);
523 if (lpNetIn->lpProvider)
525 lpNetOut->lpProvider = strNext;
526 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpProvider, -1,
527 lpNetOut->lpProvider, *lpBufferSize, NULL, NULL);
530 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
531 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
532 *lpcCount, ret);
533 return ret;
536 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
537 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
538 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
539 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
540 * if not all members of the array could be thunked, and something else on
541 * failure.
543 static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn,
544 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
546 DWORD i, numToThunk, totalBytes, ret;
547 LPWSTR strNext;
549 if (!lpNetArrayIn)
550 return WN_BAD_POINTER;
551 if (!lpcCount)
552 return WN_BAD_POINTER;
553 if (*lpcCount == -1)
554 return WN_BAD_VALUE;
555 if (!lpBuffer)
556 return WN_BAD_POINTER;
557 if (!lpBufferSize)
558 return WN_BAD_POINTER;
560 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
562 const NETRESOURCEA *lpNet = lpNetArrayIn + i;
564 totalBytes += sizeof(NETRESOURCEW);
565 if (lpNet->lpLocalName)
566 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpLocalName,
567 -1, NULL, 0) * sizeof(WCHAR);
568 if (lpNet->lpRemoteName)
569 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpRemoteName,
570 -1, NULL, 0) * sizeof(WCHAR);
571 if (lpNet->lpComment)
572 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpComment,
573 -1, NULL, 0) * sizeof(WCHAR);
574 if (lpNet->lpProvider)
575 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpProvider,
576 -1, NULL, 0) * sizeof(WCHAR);
577 if (totalBytes < *lpBufferSize)
578 numToThunk = i + 1;
580 strNext = (LPWSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEW));
581 for (i = 0; i < numToThunk; i++)
583 LPNETRESOURCEW lpNetOut = (LPNETRESOURCEW)lpBuffer + i;
584 const NETRESOURCEA *lpNetIn = lpNetArrayIn + i;
586 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEW));
587 /* lie about string lengths, we already verified how many
588 * we have space for above
590 if (lpNetIn->lpLocalName)
592 lpNetOut->lpLocalName = strNext;
593 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpLocalName,
594 -1, lpNetOut->lpLocalName, *lpBufferSize);
596 if (lpNetIn->lpRemoteName)
598 lpNetOut->lpRemoteName = strNext;
599 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpRemoteName,
600 -1, lpNetOut->lpRemoteName, *lpBufferSize);
602 if (lpNetIn->lpComment)
604 lpNetOut->lpComment = strNext;
605 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpComment,
606 -1, lpNetOut->lpComment, *lpBufferSize);
608 if (lpNetIn->lpProvider)
610 lpNetOut->lpProvider = strNext;
611 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpProvider,
612 -1, lpNetOut->lpProvider, *lpBufferSize);
615 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
616 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
617 *lpcCount, ret);
618 return ret;
621 /*********************************************************************
622 * WNetOpenEnumA [MPR.@]
624 * See comments for WNetOpenEnumW.
626 DWORD WINAPI WNetOpenEnumA( DWORD dwScope, DWORD dwType, DWORD dwUsage,
627 LPNETRESOURCEA lpNet, LPHANDLE lphEnum )
629 DWORD ret;
631 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
632 dwScope, dwType, dwUsage, lpNet, lphEnum );
634 if (!lphEnum)
635 ret = WN_BAD_POINTER;
636 else if (!providerTable || providerTable->numProviders == 0)
637 ret = WN_NO_NETWORK;
638 else
640 if (lpNet)
642 LPNETRESOURCEW lpNetWide = NULL;
643 BYTE buf[1024];
644 DWORD size = sizeof(buf), count = 1;
645 BOOL allocated = FALSE;
647 ret = _thunkNetResourceArrayAToW(lpNet, &count, buf, &size);
648 if (ret == WN_MORE_DATA)
650 lpNetWide = HeapAlloc(GetProcessHeap(), 0,
651 size);
652 if (lpNetWide)
654 ret = _thunkNetResourceArrayAToW(lpNet, &count, lpNetWide,
655 &size);
656 allocated = TRUE;
658 else
659 ret = WN_OUT_OF_MEMORY;
661 else if (ret == WN_SUCCESS)
662 lpNetWide = (LPNETRESOURCEW)buf;
663 if (ret == WN_SUCCESS)
664 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, lpNetWide,
665 lphEnum);
666 if (allocated)
667 HeapFree(GetProcessHeap(), 0, lpNetWide);
669 else
670 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, NULL, lphEnum);
672 if (ret)
673 SetLastError(ret);
674 TRACE("Returning %d\n", ret);
675 return ret;
678 /*********************************************************************
679 * WNetOpenEnumW [MPR.@]
681 * Network enumeration has way too many parameters, so I'm not positive I got
682 * them right. What I've got so far:
684 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
685 * all the network providers should be enumerated.
687 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
688 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
689 * lpProvider is set, all the network providers should be enumerated.
690 * (This means the enumeration is a list of network providers, not that the
691 * enumeration is passed on to the providers.)
693 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
694 * resource matches the "Entire Network" resource (no remote name, no
695 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
696 * enumeration is done on every network provider.
698 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
699 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
700 * only to the given network provider.
702 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
703 * no lpProvider is set, enumeration will be tried on every network provider,
704 * in the order in which they're loaded.
706 * - The LPNETRESOURCE should be disregarded for scopes besides
707 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
708 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
710 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
711 * resource in the enumerated list, as well as any machines in your
712 * workgroup. The machines in your workgroup come from doing a
713 * RESOURCE_CONTEXT enumeration of every Network Provider.
715 DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage,
716 LPNETRESOURCEW lpNet, LPHANDLE lphEnum )
718 DWORD ret;
720 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
721 dwScope, dwType, dwUsage, lpNet, lphEnum );
723 if (!lphEnum)
724 ret = WN_BAD_POINTER;
725 else if (!providerTable || providerTable->numProviders == 0)
726 ret = WN_NO_NETWORK;
727 else
729 switch (dwScope)
731 case RESOURCE_GLOBALNET:
732 if (lpNet)
734 if (lpNet->lpProvider)
736 DWORD index = _findProviderIndexW(lpNet->lpProvider);
738 if (index != BAD_PROVIDER_INDEX)
740 if (providerTable->table[index].openEnum &&
741 providerTable->table[index].dwEnumScopes & WNNC_ENUM_GLOBAL)
743 HANDLE handle;
745 ret = providerTable->table[index].openEnum(
746 dwScope, dwType, dwUsage, lpNet, &handle);
747 if (ret == WN_SUCCESS)
749 *lphEnum =
750 (HANDLE)_createProviderEnumerator(
751 dwScope, dwType, dwUsage, index, handle);
752 ret = *lphEnum ? WN_SUCCESS :
753 WN_OUT_OF_MEMORY;
756 else
757 ret = WN_NOT_SUPPORTED;
759 else
760 ret = WN_BAD_PROVIDER;
762 else if (lpNet->lpRemoteName)
764 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
765 dwType, dwUsage, lpNet);
766 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
768 else
770 if (lpNet->lpComment && !strcmpW(lpNet->lpComment,
771 providerTable->entireNetwork))
773 /* comment matches the "Entire Network", enumerate
774 * global scope of every provider
776 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
777 dwType, dwUsage, lpNet);
779 else
781 /* this is the same as not having passed lpNet */
782 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope,
783 dwType, dwUsage, NULL);
785 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
788 else
790 *lphEnum = (HANDLE)_createGlobalEnumeratorW(dwScope, dwType,
791 dwUsage, lpNet);
792 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
794 break;
795 case RESOURCE_CONTEXT:
796 *lphEnum = (HANDLE)_createContextEnumerator(dwScope, dwType,
797 dwUsage);
798 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
799 break;
800 case RESOURCE_REMEMBERED:
801 case RESOURCE_CONNECTED:
802 *lphEnum = (HANDLE)_createNullEnumerator();
803 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
804 break;
805 default:
806 WARN("unknown scope 0x%08x\n", dwScope);
807 ret = WN_BAD_VALUE;
810 if (ret)
811 SetLastError(ret);
812 TRACE("Returning %d\n", ret);
813 return ret;
816 /*********************************************************************
817 * WNetEnumResourceA [MPR.@]
819 DWORD WINAPI WNetEnumResourceA( HANDLE hEnum, LPDWORD lpcCount,
820 LPVOID lpBuffer, LPDWORD lpBufferSize )
822 DWORD ret;
824 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
826 if (!hEnum)
827 ret = WN_BAD_POINTER;
828 else if (!lpcCount)
829 ret = WN_BAD_POINTER;
830 else if (!lpBuffer)
831 ret = WN_BAD_POINTER;
832 else if (!lpBufferSize)
833 ret = WN_BAD_POINTER;
834 else if (*lpBufferSize < sizeof(NETRESOURCEA))
836 *lpBufferSize = sizeof(NETRESOURCEA);
837 ret = WN_MORE_DATA;
839 else
841 DWORD localCount = *lpcCount, localSize = *lpBufferSize;
842 LPVOID localBuffer = HeapAlloc(GetProcessHeap(), 0, localSize);
844 if (localBuffer)
846 ret = WNetEnumResourceW(hEnum, &localCount, localBuffer,
847 &localSize);
848 if (ret == WN_SUCCESS || (ret == WN_MORE_DATA && localCount != -1))
850 /* FIXME: this isn't necessarily going to work in the case of
851 * WN_MORE_DATA, because our enumerator may have moved on to
852 * the next provider. MSDN states that a large (16KB) buffer
853 * size is the appropriate usage of this function, so
854 * hopefully it won't be an issue.
856 ret = _thunkNetResourceArrayWToA((LPNETRESOURCEW)localBuffer,
857 &localCount, lpBuffer, lpBufferSize);
858 *lpcCount = localCount;
860 HeapFree(GetProcessHeap(), 0, localBuffer);
862 else
863 ret = WN_OUT_OF_MEMORY;
865 if (ret)
866 SetLastError(ret);
867 TRACE("Returning %d\n", ret);
868 return ret;
871 static DWORD _countProviderBytesW(PWNetProvider provider)
873 DWORD ret;
875 if (provider)
877 ret = sizeof(NETRESOURCEW);
878 ret += 2 * (strlenW(provider->name) + 1) * sizeof(WCHAR);
880 else
881 ret = 0;
882 return ret;
885 static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount,
886 LPVOID lpBuffer, const DWORD *lpBufferSize)
888 DWORD ret;
890 if (!enumerator)
891 return WN_BAD_POINTER;
892 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
893 return WN_BAD_VALUE;
894 if (!lpcCount)
895 return WN_BAD_POINTER;
896 if (!lpBuffer)
897 return WN_BAD_POINTER;
898 if (!lpBufferSize)
899 return WN_BAD_POINTER;
900 if (*lpBufferSize < sizeof(NETRESOURCEA))
901 return WN_MORE_DATA;
903 if (!providerTable || enumerator->providerIndex >=
904 providerTable->numProviders)
905 ret = WN_NO_MORE_ENTRIES;
906 else
908 DWORD bytes = 0, count = 0, countLimit, i;
909 LPNETRESOURCEW resource;
910 LPWSTR strNext;
912 countLimit = *lpcCount == -1 ?
913 providerTable->numProviders - enumerator->providerIndex : *lpcCount;
914 while (count < countLimit && bytes < *lpBufferSize)
916 DWORD bytesNext = _countProviderBytesW(
917 &providerTable->table[count + enumerator->providerIndex]);
919 if (bytes + bytesNext < *lpBufferSize)
921 bytes += bytesNext;
922 count++;
925 strNext = (LPWSTR)((LPBYTE)lpBuffer + count * sizeof(NETRESOURCEW));
926 for (i = 0, resource = (LPNETRESOURCEW)lpBuffer; i < count;
927 i++, resource++)
929 resource->dwScope = RESOURCE_GLOBALNET;
930 resource->dwType = RESOURCETYPE_ANY;
931 resource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
932 resource->dwUsage = RESOURCEUSAGE_CONTAINER |
933 RESOURCEUSAGE_RESERVED;
934 resource->lpLocalName = NULL;
935 resource->lpRemoteName = strNext;
936 strcpyW(resource->lpRemoteName,
937 providerTable->table[i + enumerator->providerIndex].name);
938 strNext += strlenW(resource->lpRemoteName) + 1;
939 resource->lpComment = NULL;
940 resource->lpProvider = strNext;
941 strcpyW(resource->lpProvider,
942 providerTable->table[i + enumerator->providerIndex].name);
943 strNext += strlenW(resource->lpProvider) + 1;
945 enumerator->providerIndex += count;
946 *lpcCount = count;
947 ret = count > 0 ? WN_SUCCESS : WN_MORE_DATA;
949 TRACE("Returning %d\n", ret);
950 return ret;
953 /* Advances the enumerator (assumed to be a global enumerator) to the next
954 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
955 * not open a handle with the next provider.
956 * If the existing handle is NULL, may leave the enumerator unchanged, since
957 * the current provider may support the desired scope.
958 * If the existing handle is not NULL, closes it before moving on.
959 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
960 * provider, and another error on failure.
962 static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator)
964 if (!enumerator)
965 return WN_BAD_POINTER;
966 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
967 return WN_BAD_VALUE;
968 if (!providerTable || enumerator->providerIndex >=
969 providerTable->numProviders)
970 return WN_NO_MORE_ENTRIES;
972 if (enumerator->providerDone)
974 DWORD dwEnum = 0;
975 enumerator->providerDone = FALSE;
976 if (enumerator->handle)
978 providerTable->table[enumerator->providerIndex].closeEnum(
979 enumerator->handle);
980 enumerator->handle = NULL;
981 enumerator->providerIndex++;
983 if (enumerator->dwScope == RESOURCE_CONNECTED)
984 dwEnum = WNNC_ENUM_LOCAL;
985 else if (enumerator->dwScope == RESOURCE_GLOBALNET)
986 dwEnum = WNNC_ENUM_GLOBAL;
987 else if (enumerator->dwScope == RESOURCE_CONTEXT)
988 dwEnum = WNNC_ENUM_CONTEXT;
989 for (; enumerator->providerIndex < providerTable->numProviders &&
990 !(providerTable->table[enumerator->providerIndex].dwEnumScopes
991 & dwEnum); enumerator->providerIndex++)
994 return enumerator->providerIndex < providerTable->numProviders ?
995 WN_SUCCESS : WN_NO_MORE_ENTRIES;
998 /* "Passes through" call to the next provider that supports the enumeration
999 * type.
1000 * FIXME: if one call to a provider's enumerator succeeds while there's still
1001 * space in lpBuffer, I don't call to the next provider. The caller may not
1002 * expect that it should call EnumResourceW again with a return value of
1003 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1004 * may have to be moved around a bit, ick.
1006 static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator,
1007 LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
1009 DWORD ret;
1011 if (!enumerator)
1012 return WN_BAD_POINTER;
1013 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1014 return WN_BAD_VALUE;
1015 if (!lpcCount)
1016 return WN_BAD_POINTER;
1017 if (!lpBuffer)
1018 return WN_BAD_POINTER;
1019 if (!lpBufferSize)
1020 return WN_BAD_POINTER;
1021 if (*lpBufferSize < sizeof(NETRESOURCEW))
1022 return WN_MORE_DATA;
1024 ret = _globalEnumeratorAdvance(enumerator);
1025 if (ret == WN_SUCCESS)
1027 ret = providerTable->table[enumerator->providerIndex].
1028 openEnum(enumerator->dwScope, enumerator->dwType,
1029 enumerator->dwUsage, enumerator->lpNet,
1030 &enumerator->handle);
1031 if (ret == WN_SUCCESS)
1033 ret = providerTable->table[enumerator->providerIndex].
1034 enumResource(enumerator->handle, lpcCount, lpBuffer,
1035 lpBufferSize);
1036 if (ret != WN_MORE_DATA)
1037 enumerator->providerDone = TRUE;
1040 TRACE("Returning %d\n", ret);
1041 return ret;
1044 static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1045 LPVOID lpBuffer, LPDWORD lpBufferSize)
1047 DWORD ret;
1049 if (!enumerator)
1050 return WN_BAD_POINTER;
1051 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1052 return WN_BAD_VALUE;
1053 if (!lpcCount)
1054 return WN_BAD_POINTER;
1055 if (!lpBuffer)
1056 return WN_BAD_POINTER;
1057 if (!lpBufferSize)
1058 return WN_BAD_POINTER;
1059 if (*lpBufferSize < sizeof(NETRESOURCEW))
1060 return WN_MORE_DATA;
1061 if (!providerTable)
1062 return WN_NO_NETWORK;
1064 switch (enumerator->dwScope)
1066 case RESOURCE_GLOBALNET:
1067 if (enumerator->lpNet)
1068 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount,
1069 lpBuffer, lpBufferSize);
1070 else
1071 ret = _enumerateProvidersW(enumerator, lpcCount, lpBuffer,
1072 lpBufferSize);
1073 break;
1074 case RESOURCE_CONTEXT:
1075 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, lpBuffer,
1076 lpBufferSize);
1077 break;
1078 default:
1079 WARN("unexpected scope 0x%08x\n", enumerator->dwScope);
1080 ret = WN_NO_MORE_ENTRIES;
1082 TRACE("Returning %d\n", ret);
1083 return ret;
1086 static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1087 LPVOID lpBuffer, LPDWORD lpBufferSize)
1089 if (!enumerator)
1090 return WN_BAD_POINTER;
1091 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_PROVIDER)
1092 return WN_BAD_VALUE;
1093 if (!enumerator->handle)
1094 return WN_BAD_VALUE;
1095 if (!lpcCount)
1096 return WN_BAD_POINTER;
1097 if (!lpBuffer)
1098 return WN_BAD_POINTER;
1099 if (!lpBufferSize)
1100 return WN_BAD_POINTER;
1101 if (!providerTable)
1102 return WN_NO_NETWORK;
1103 if (enumerator->providerIndex >= providerTable->numProviders)
1104 return WN_NO_MORE_ENTRIES;
1105 if (!providerTable->table[enumerator->providerIndex].enumResource)
1106 return WN_BAD_VALUE;
1107 return providerTable->table[enumerator->providerIndex].enumResource(
1108 enumerator->handle, lpcCount, lpBuffer, lpBufferSize);
1111 static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount,
1112 LPVOID lpBuffer, LPDWORD lpBufferSize)
1114 DWORD ret;
1115 size_t cchEntireNetworkLen, bytesNeeded;
1117 if (!enumerator)
1118 return WN_BAD_POINTER;
1119 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONTEXT)
1120 return WN_BAD_VALUE;
1121 if (!lpcCount)
1122 return WN_BAD_POINTER;
1123 if (!lpBuffer)
1124 return WN_BAD_POINTER;
1125 if (!lpBufferSize)
1126 return WN_BAD_POINTER;
1127 if (!providerTable)
1128 return WN_NO_NETWORK;
1130 cchEntireNetworkLen = strlenW(providerTable->entireNetwork) + 1;
1131 bytesNeeded = sizeof(NETRESOURCEW) + cchEntireNetworkLen * sizeof(WCHAR);
1132 if (*lpBufferSize < bytesNeeded)
1134 *lpBufferSize = bytesNeeded;
1135 ret = WN_MORE_DATA;
1137 else
1139 LPNETRESOURCEW lpNet = (LPNETRESOURCEW)lpBuffer;
1141 lpNet->dwScope = RESOURCE_GLOBALNET;
1142 lpNet->dwType = enumerator->dwType;
1143 lpNet->dwDisplayType = RESOURCEDISPLAYTYPE_ROOT;
1144 lpNet->dwUsage = RESOURCEUSAGE_CONTAINER;
1145 lpNet->lpLocalName = NULL;
1146 lpNet->lpRemoteName = NULL;
1147 lpNet->lpProvider = NULL;
1148 /* odd, but correct: put comment at end of buffer, so it won't get
1149 * overwritten by subsequent calls to a provider's enumResource
1151 lpNet->lpComment = (LPWSTR)((LPBYTE)lpBuffer + *lpBufferSize -
1152 (cchEntireNetworkLen * sizeof(WCHAR)));
1153 strcpyW(lpNet->lpComment, providerTable->entireNetwork);
1154 ret = WN_SUCCESS;
1156 if (ret == WN_SUCCESS)
1158 DWORD bufferSize = *lpBufferSize - bytesNeeded;
1160 /* "Entire Network" entry enumerated--morph this into a global
1161 * enumerator. enumerator->lpNet continues to be NULL, since it has
1162 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1164 enumerator->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
1165 ret = _enumerateGlobalW(enumerator, lpcCount,
1166 (LPBYTE)lpBuffer + bytesNeeded, &bufferSize);
1167 if (ret == WN_SUCCESS)
1169 /* reflect the fact that we already enumerated "Entire Network" */
1170 lpcCount++;
1171 *lpBufferSize = bufferSize + bytesNeeded;
1173 else
1175 /* the provider enumeration failed, but we already succeeded in
1176 * enumerating "Entire Network"--leave type as global to allow a
1177 * retry, but indicate success with a count of one.
1179 ret = WN_SUCCESS;
1180 *lpcCount = 1;
1181 *lpBufferSize = bytesNeeded;
1184 TRACE("Returning %d\n", ret);
1185 return ret;
1188 /*********************************************************************
1189 * WNetEnumResourceW [MPR.@]
1191 DWORD WINAPI WNetEnumResourceW( HANDLE hEnum, LPDWORD lpcCount,
1192 LPVOID lpBuffer, LPDWORD lpBufferSize )
1194 DWORD ret;
1196 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
1198 if (!hEnum)
1199 ret = WN_BAD_POINTER;
1200 else if (!lpcCount)
1201 ret = WN_BAD_POINTER;
1202 else if (!lpBuffer)
1203 ret = WN_BAD_POINTER;
1204 else if (!lpBufferSize)
1205 ret = WN_BAD_POINTER;
1206 else if (*lpBufferSize < sizeof(NETRESOURCEW))
1208 *lpBufferSize = sizeof(NETRESOURCEW);
1209 ret = WN_MORE_DATA;
1211 else
1213 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1215 switch (enumerator->enumType)
1217 case WNET_ENUMERATOR_TYPE_NULL:
1218 ret = WN_NO_MORE_ENTRIES;
1219 break;
1220 case WNET_ENUMERATOR_TYPE_GLOBAL:
1221 ret = _enumerateGlobalW(enumerator, lpcCount, lpBuffer,
1222 lpBufferSize);
1223 break;
1224 case WNET_ENUMERATOR_TYPE_PROVIDER:
1225 ret = _enumerateProviderW(enumerator, lpcCount, lpBuffer,
1226 lpBufferSize);
1227 break;
1228 case WNET_ENUMERATOR_TYPE_CONTEXT:
1229 ret = _enumerateContextW(enumerator, lpcCount, lpBuffer,
1230 lpBufferSize);
1231 break;
1232 default:
1233 WARN("bogus enumerator type!\n");
1234 ret = WN_NO_NETWORK;
1237 if (ret)
1238 SetLastError(ret);
1239 TRACE("Returning %d\n", ret);
1240 return ret;
1243 /*********************************************************************
1244 * WNetCloseEnum [MPR.@]
1246 DWORD WINAPI WNetCloseEnum( HANDLE hEnum )
1248 DWORD ret;
1250 TRACE( "(%p)\n", hEnum );
1252 if (hEnum)
1254 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1256 switch (enumerator->enumType)
1258 case WNET_ENUMERATOR_TYPE_NULL:
1259 ret = WN_SUCCESS;
1260 break;
1261 case WNET_ENUMERATOR_TYPE_GLOBAL:
1262 if (enumerator->lpNet)
1263 _freeEnumNetResource(enumerator->lpNet);
1264 if (enumerator->handle)
1265 providerTable->table[enumerator->providerIndex].
1266 closeEnum(enumerator->handle);
1267 ret = WN_SUCCESS;
1268 break;
1269 case WNET_ENUMERATOR_TYPE_PROVIDER:
1270 if (enumerator->handle)
1271 providerTable->table[enumerator->providerIndex].
1272 closeEnum(enumerator->handle);
1273 ret = WN_SUCCESS;
1274 break;
1275 default:
1276 WARN("bogus enumerator type!\n");
1277 ret = WN_BAD_HANDLE;
1279 HeapFree(GetProcessHeap(), 0, hEnum);
1281 else
1282 ret = WN_BAD_HANDLE;
1283 if (ret)
1284 SetLastError(ret);
1285 TRACE("Returning %d\n", ret);
1286 return ret;
1289 /*********************************************************************
1290 * WNetGetResourceInformationA [MPR.@]
1292 * See WNetGetResourceInformationW
1294 DWORD WINAPI WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource,
1295 LPVOID lpBuffer, LPDWORD cbBuffer,
1296 LPSTR *lplpSystem )
1298 DWORD ret;
1300 TRACE( "(%p, %p, %p, %p)\n",
1301 lpNetResource, lpBuffer, cbBuffer, lplpSystem );
1303 if (!providerTable || providerTable->numProviders == 0)
1304 ret = WN_NO_NETWORK;
1305 else if (lpNetResource)
1307 LPNETRESOURCEW lpNetResourceW = NULL;
1308 DWORD size = 1024, count = 1;
1309 DWORD len;
1311 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size);
1312 ret = _thunkNetResourceArrayAToW(lpNetResource, &count, lpNetResourceW, &size);
1313 if (ret == WN_MORE_DATA)
1315 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1316 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size);
1317 if (lpNetResourceW)
1318 ret = _thunkNetResourceArrayAToW(lpNetResource,
1319 &count, lpNetResourceW, &size);
1320 else
1321 ret = WN_OUT_OF_MEMORY;
1323 if (ret == WN_SUCCESS)
1325 LPWSTR lpSystemW = NULL;
1326 LPVOID lpBufferW;
1327 size = 1024;
1328 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size);
1329 if (lpBufferW)
1331 ret = WNetGetResourceInformationW(lpNetResourceW,
1332 lpBufferW, &size, &lpSystemW);
1333 if (ret == WN_MORE_DATA)
1335 HeapFree(GetProcessHeap(), 0, lpBufferW);
1336 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size);
1337 if (lpBufferW)
1338 ret = WNetGetResourceInformationW(lpNetResourceW,
1339 lpBufferW, &size, &lpSystemW);
1340 else
1341 ret = WN_OUT_OF_MEMORY;
1343 if (ret == WN_SUCCESS)
1345 ret = _thunkNetResourceArrayWToA(lpBufferW,
1346 &count, lpBuffer, cbBuffer);
1347 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1348 lpNetResourceW = lpBufferW;
1349 size = sizeof(NETRESOURCEA);
1350 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpRemoteName,
1351 -1, NULL, 0, NULL, NULL);
1352 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpProvider,
1353 -1, NULL, 0, NULL, NULL);
1355 len = WideCharToMultiByte(CP_ACP, 0, lpSystemW,
1356 -1, NULL, 0, NULL, NULL);
1357 if ((len) && ( size + len < *cbBuffer))
1359 *lplpSystem = (char*)lpBuffer + *cbBuffer - len;
1360 WideCharToMultiByte(CP_ACP, 0, lpSystemW, -1,
1361 *lplpSystem, len, NULL, NULL);
1362 ret = WN_SUCCESS;
1364 else
1365 ret = WN_MORE_DATA;
1367 else
1368 ret = WN_OUT_OF_MEMORY;
1369 HeapFree(GetProcessHeap(), 0, lpBufferW);
1371 else
1372 ret = WN_OUT_OF_MEMORY;
1373 HeapFree(GetProcessHeap(), 0, lpSystemW);
1375 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1377 else
1378 ret = WN_NO_NETWORK;
1380 if (ret)
1381 SetLastError(ret);
1382 TRACE("Returning %d\n", ret);
1383 return ret;
1386 /*********************************************************************
1387 * WNetGetResourceInformationW [MPR.@]
1389 * WNetGetResourceInformationW function identifies the network provider
1390 * that owns the resource and gets information about the type of the resource.
1392 * PARAMS:
1393 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1394 * defines a network resource.
1395 * lpBuffer [ O] the pointer to buffer, containing result. It
1396 * contains NETRESOURCEW structure and strings to
1397 * which the members of the NETRESOURCEW structure
1398 * point.
1399 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1400 * in bytes.
1401 * lplpSystem [ O] the pointer to string in the output buffer,
1402 * containing the part of the resource name without
1403 * names of the server and share.
1405 * RETURNS:
1406 * NO_ERROR if the function succeeds. System error code if the function fails.
1409 DWORD WINAPI WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource,
1410 LPVOID lpBuffer, LPDWORD cbBuffer,
1411 LPWSTR *lplpSystem )
1413 DWORD ret = WN_NO_NETWORK;
1414 DWORD index;
1416 TRACE( "(%p, %p, %p, %p)\n",
1417 lpNetResource, lpBuffer, cbBuffer, lplpSystem);
1419 if (!(lpBuffer))
1420 ret = WN_OUT_OF_MEMORY;
1421 else
1423 /* FIXME: For function value of a variable is indifferent, it does
1424 * search of all providers in a network.
1426 for (index = 0; index < providerTable->numProviders; index++)
1428 if(providerTable->table[index].getCaps(WNNC_DIALOG) &
1429 WNNC_DLG_GETRESOURCEINFORMATION)
1431 if (providerTable->table[index].getResourceInformation)
1432 ret = providerTable->table[index].getResourceInformation(
1433 lpNetResource, lpBuffer, cbBuffer, lplpSystem);
1434 else
1435 ret = WN_NO_NETWORK;
1436 if (ret == WN_SUCCESS)
1437 break;
1441 if (ret)
1442 SetLastError(ret);
1443 return ret;
1446 /*********************************************************************
1447 * WNetGetResourceParentA [MPR.@]
1449 DWORD WINAPI WNetGetResourceParentA( LPNETRESOURCEA lpNetResource,
1450 LPVOID lpBuffer, LPDWORD lpBufferSize )
1452 FIXME( "(%p, %p, %p): stub\n",
1453 lpNetResource, lpBuffer, lpBufferSize );
1455 SetLastError(WN_NO_NETWORK);
1456 return WN_NO_NETWORK;
1459 /*********************************************************************
1460 * WNetGetResourceParentW [MPR.@]
1462 DWORD WINAPI WNetGetResourceParentW( LPNETRESOURCEW lpNetResource,
1463 LPVOID lpBuffer, LPDWORD lpBufferSize )
1465 FIXME( "(%p, %p, %p): stub\n",
1466 lpNetResource, lpBuffer, lpBufferSize );
1468 SetLastError(WN_NO_NETWORK);
1469 return WN_NO_NETWORK;
1475 * Connection Functions
1478 /*********************************************************************
1479 * WNetAddConnectionA [MPR.@]
1481 DWORD WINAPI WNetAddConnectionA( LPCSTR lpRemoteName, LPCSTR lpPassword,
1482 LPCSTR lpLocalName )
1484 FIXME( "(%s, %p, %s): stub\n",
1485 debugstr_a(lpRemoteName), lpPassword, debugstr_a(lpLocalName) );
1487 SetLastError(WN_NO_NETWORK);
1488 return WN_NO_NETWORK;
1491 /*********************************************************************
1492 * WNetAddConnectionW [MPR.@]
1494 DWORD WINAPI WNetAddConnectionW( LPCWSTR lpRemoteName, LPCWSTR lpPassword,
1495 LPCWSTR lpLocalName )
1497 FIXME( "(%s, %p, %s): stub\n",
1498 debugstr_w(lpRemoteName), lpPassword, debugstr_w(lpLocalName) );
1500 SetLastError(WN_NO_NETWORK);
1501 return WN_NO_NETWORK;
1504 /*********************************************************************
1505 * WNetAddConnection2A [MPR.@]
1507 DWORD WINAPI WNetAddConnection2A( LPNETRESOURCEA lpNetResource,
1508 LPCSTR lpPassword, LPCSTR lpUserID,
1509 DWORD dwFlags )
1511 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1512 lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
1514 SetLastError(WN_NO_NETWORK);
1515 return WN_NO_NETWORK;
1518 /*********************************************************************
1519 * WNetAddConnection2W [MPR.@]
1521 DWORD WINAPI WNetAddConnection2W( LPNETRESOURCEW lpNetResource,
1522 LPCWSTR lpPassword, LPCWSTR lpUserID,
1523 DWORD dwFlags )
1525 FIXME( "(%p, %p, %s, 0x%08X): stub\n",
1526 lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
1528 SetLastError(WN_NO_NETWORK);
1529 return WN_NO_NETWORK;
1532 /*********************************************************************
1533 * WNetAddConnection3A [MPR.@]
1535 DWORD WINAPI WNetAddConnection3A( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
1536 LPCSTR lpPassword, LPCSTR lpUserID,
1537 DWORD dwFlags )
1539 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1540 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags );
1542 SetLastError(WN_NO_NETWORK);
1543 return WN_NO_NETWORK;
1546 /*********************************************************************
1547 * WNetAddConnection3W [MPR.@]
1549 DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
1550 LPCWSTR lpPassword, LPCWSTR lpUserID,
1551 DWORD dwFlags )
1553 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n",
1554 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags );
1556 SetLastError(WN_NO_NETWORK);
1557 return WN_NO_NETWORK;
1560 /*****************************************************************
1561 * WNetUseConnectionA [MPR.@]
1563 DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource,
1564 LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags,
1565 LPSTR lpAccessName, LPDWORD lpBufferSize,
1566 LPDWORD lpResult )
1568 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1569 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags,
1570 debugstr_a(lpAccessName), lpBufferSize, lpResult );
1572 SetLastError(WN_NO_NETWORK);
1573 return WN_NO_NETWORK;
1576 /*****************************************************************
1577 * WNetUseConnectionW [MPR.@]
1579 DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource,
1580 LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags,
1581 LPWSTR lpAccessName, LPDWORD lpBufferSize,
1582 LPDWORD lpResult )
1584 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n",
1585 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags,
1586 debugstr_w(lpAccessName), lpBufferSize, lpResult );
1588 SetLastError(WN_NO_NETWORK);
1589 return WN_NO_NETWORK;
1592 /*********************************************************************
1593 * WNetCancelConnectionA [MPR.@]
1595 DWORD WINAPI WNetCancelConnectionA( LPCSTR lpName, BOOL fForce )
1597 FIXME( "(%s, %d), stub\n", debugstr_a(lpName), fForce );
1599 return WN_SUCCESS;
1602 /*********************************************************************
1603 * WNetCancelConnectionW [MPR.@]
1605 DWORD WINAPI WNetCancelConnectionW( LPCWSTR lpName, BOOL fForce )
1607 FIXME( "(%s, %d), stub\n", debugstr_w(lpName), fForce );
1609 return WN_SUCCESS;
1612 /*********************************************************************
1613 * WNetCancelConnection2A [MPR.@]
1615 DWORD WINAPI WNetCancelConnection2A( LPCSTR lpName, DWORD dwFlags, BOOL fForce )
1617 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName), dwFlags, fForce );
1619 return WN_SUCCESS;
1622 /*********************************************************************
1623 * WNetCancelConnection2W [MPR.@]
1625 DWORD WINAPI WNetCancelConnection2W( LPCWSTR lpName, DWORD dwFlags, BOOL fForce )
1627 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName), dwFlags, fForce );
1629 return WN_SUCCESS;
1632 /*****************************************************************
1633 * WNetRestoreConnectionA [MPR.@]
1635 DWORD WINAPI WNetRestoreConnectionA( HWND hwndOwner, LPCSTR lpszDevice )
1637 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_a(lpszDevice) );
1639 SetLastError(WN_NO_NETWORK);
1640 return WN_NO_NETWORK;
1643 /*****************************************************************
1644 * WNetRestoreConnectionW [MPR.@]
1646 DWORD WINAPI WNetRestoreConnectionW( HWND hwndOwner, LPCWSTR lpszDevice )
1648 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_w(lpszDevice) );
1650 SetLastError(WN_NO_NETWORK);
1651 return WN_NO_NETWORK;
1654 /**************************************************************************
1655 * WNetGetConnectionA [MPR.@]
1657 * RETURNS
1658 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1659 * - WN_NOT_CONNECTED drive is a local drive
1660 * - WN_MORE_DATA buffer isn't big enough
1661 * - WN_SUCCESS success (net path in buffer)
1663 * FIXME: need to test return values under different errors
1665 DWORD WINAPI WNetGetConnectionA( LPCSTR lpLocalName,
1666 LPSTR lpRemoteName, LPDWORD lpBufferSize )
1668 DWORD ret;
1670 if (!lpLocalName)
1671 ret = WN_BAD_POINTER;
1672 else if (!lpBufferSize)
1673 ret = WN_BAD_POINTER;
1674 else if (!lpRemoteName && *lpBufferSize)
1675 ret = WN_BAD_POINTER;
1676 else
1678 int len = MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, NULL, 0);
1680 if (len)
1682 PWSTR wideLocalName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1684 if (wideLocalName)
1686 WCHAR wideRemoteStatic[MAX_PATH];
1687 DWORD wideRemoteSize = sizeof(wideRemoteStatic) / sizeof(WCHAR);
1689 MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, wideLocalName, len);
1691 /* try once without memory allocation */
1692 ret = WNetGetConnectionW(wideLocalName, wideRemoteStatic,
1693 &wideRemoteSize);
1694 if (ret == WN_SUCCESS)
1696 int len = WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
1697 -1, NULL, 0, NULL, NULL);
1699 if (len <= *lpBufferSize)
1701 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, -1,
1702 lpRemoteName, *lpBufferSize, NULL, NULL);
1703 ret = WN_SUCCESS;
1705 else
1707 *lpBufferSize = len;
1708 ret = WN_MORE_DATA;
1711 else if (ret == WN_MORE_DATA)
1713 PWSTR wideRemote = HeapAlloc(GetProcessHeap(), 0,
1714 wideRemoteSize * sizeof(WCHAR));
1716 if (wideRemote)
1718 ret = WNetGetConnectionW(wideLocalName, wideRemote,
1719 &wideRemoteSize);
1720 if (ret == WN_SUCCESS)
1722 if (len <= *lpBufferSize)
1724 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
1725 -1, lpRemoteName, *lpBufferSize, NULL, NULL);
1726 ret = WN_SUCCESS;
1728 else
1730 *lpBufferSize = len;
1731 ret = WN_MORE_DATA;
1734 HeapFree(GetProcessHeap(), 0, wideRemote);
1736 else
1737 ret = WN_OUT_OF_MEMORY;
1739 HeapFree(GetProcessHeap(), 0, wideLocalName);
1741 else
1742 ret = WN_OUT_OF_MEMORY;
1744 else
1745 ret = WN_BAD_LOCALNAME;
1747 if (ret)
1748 SetLastError(ret);
1749 TRACE("Returning %d\n", ret);
1750 return ret;
1753 /**************************************************************************
1754 * WNetGetConnectionW [MPR.@]
1756 * FIXME: need to test return values under different errors
1758 DWORD WINAPI WNetGetConnectionW( LPCWSTR lpLocalName,
1759 LPWSTR lpRemoteName, LPDWORD lpBufferSize )
1761 DWORD ret;
1763 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName), lpRemoteName,
1764 lpBufferSize);
1766 if (!lpLocalName)
1767 ret = WN_BAD_POINTER;
1768 else if (!lpBufferSize)
1769 ret = WN_BAD_POINTER;
1770 else if (!lpRemoteName && *lpBufferSize)
1771 ret = WN_BAD_POINTER;
1772 else if (!lpLocalName[0])
1773 ret = WN_BAD_LOCALNAME;
1774 else
1776 if (lpLocalName[1] == ':')
1778 switch(GetDriveTypeW(lpLocalName))
1780 case DRIVE_REMOTE:
1782 static const WCHAR unc[] = { 'u','n','c','\\' };
1783 WCHAR rremote[MAX_PATH], *remote = rremote;
1784 if (!QueryDosDeviceW( lpLocalName, remote, MAX_PATH )) remote[0] = 0;
1785 else if (!strncmpW(remote, unc, 4))
1787 remote += 2;
1788 remote[0] = '\\';
1790 else if (remote[0] != '\\' || remote[1] != '\\')
1791 FIXME("Don't know how to convert %s to an unc\n", debugstr_w(remote));
1793 if (strlenW(remote) + 1 > *lpBufferSize)
1795 *lpBufferSize = strlenW(remote) + 1;
1796 ret = WN_MORE_DATA;
1798 else
1800 strcpyW( lpRemoteName, remote );
1801 *lpBufferSize = strlenW(lpRemoteName) + 1;
1802 ret = WN_SUCCESS;
1804 break;
1806 case DRIVE_REMOVABLE:
1807 case DRIVE_FIXED:
1808 case DRIVE_CDROM:
1809 TRACE("file is local\n");
1810 ret = WN_NOT_CONNECTED;
1811 break;
1812 default:
1813 ret = WN_BAD_LOCALNAME;
1816 else
1817 ret = WN_BAD_LOCALNAME;
1819 if (ret)
1820 SetLastError(ret);
1821 TRACE("Returning %d\n", ret);
1822 return ret;
1825 /**************************************************************************
1826 * WNetSetConnectionA [MPR.@]
1828 DWORD WINAPI WNetSetConnectionA( LPCSTR lpName, DWORD dwProperty,
1829 LPVOID pvValue )
1831 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName), dwProperty, pvValue );
1833 SetLastError(WN_NO_NETWORK);
1834 return WN_NO_NETWORK;
1837 /**************************************************************************
1838 * WNetSetConnectionW [MPR.@]
1840 DWORD WINAPI WNetSetConnectionW( LPCWSTR lpName, DWORD dwProperty,
1841 LPVOID pvValue )
1843 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName), dwProperty, pvValue );
1845 SetLastError(WN_NO_NETWORK);
1846 return WN_NO_NETWORK;
1849 /*****************************************************************
1850 * WNetGetUniversalNameA [MPR.@]
1852 DWORD WINAPI WNetGetUniversalNameA ( LPCSTR lpLocalPath, DWORD dwInfoLevel,
1853 LPVOID lpBuffer, LPDWORD lpBufferSize )
1855 DWORD err, size;
1857 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1858 debugstr_a(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
1860 switch (dwInfoLevel)
1862 case UNIVERSAL_NAME_INFO_LEVEL:
1864 LPUNIVERSAL_NAME_INFOA info = (LPUNIVERSAL_NAME_INFOA)lpBuffer;
1866 size = sizeof(*info) + lstrlenA(lpLocalPath) + 1;
1867 if (*lpBufferSize < size)
1869 err = WN_MORE_DATA;
1870 break;
1872 info->lpUniversalName = (char *)info + sizeof(*info);
1873 lstrcpyA(info->lpUniversalName, lpLocalPath);
1874 *lpBufferSize = size;
1875 err = WN_NO_ERROR;
1876 break;
1878 case REMOTE_NAME_INFO_LEVEL:
1879 err = WN_NO_NETWORK;
1880 break;
1882 default:
1883 err = WN_BAD_VALUE;
1884 break;
1887 SetLastError(err);
1888 return err;
1891 /*****************************************************************
1892 * WNetGetUniversalNameW [MPR.@]
1894 DWORD WINAPI WNetGetUniversalNameW ( LPCWSTR lpLocalPath, DWORD dwInfoLevel,
1895 LPVOID lpBuffer, LPDWORD lpBufferSize )
1897 DWORD err, size;
1899 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
1900 debugstr_w(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
1902 switch (dwInfoLevel)
1904 case UNIVERSAL_NAME_INFO_LEVEL:
1906 LPUNIVERSAL_NAME_INFOW info = (LPUNIVERSAL_NAME_INFOW)lpBuffer;
1908 size = sizeof(*info) + (lstrlenW(lpLocalPath) + 1) * sizeof(WCHAR);
1909 if (*lpBufferSize < size)
1911 err = WN_MORE_DATA;
1912 break;
1914 info->lpUniversalName = (LPWSTR)((char *)info + sizeof(*info));
1915 lstrcpyW(info->lpUniversalName, lpLocalPath);
1916 *lpBufferSize = size;
1917 err = WN_NO_ERROR;
1918 break;
1920 case REMOTE_NAME_INFO_LEVEL:
1921 err = WN_NO_NETWORK;
1922 break;
1924 default:
1925 err = WN_BAD_VALUE;
1926 break;
1929 SetLastError(err);
1930 return err;
1936 * Other Functions
1939 /**************************************************************************
1940 * WNetGetUserA [MPR.@]
1942 * FIXME: we should not return ourselves, but the owner of the drive lpName
1944 DWORD WINAPI WNetGetUserA( LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize )
1946 if (GetUserNameA( lpUserID, lpBufferSize )) return WN_SUCCESS;
1947 return GetLastError();
1950 /*****************************************************************
1951 * WNetGetUserW [MPR.@]
1953 * FIXME: we should not return ourselves, but the owner of the drive lpName
1955 DWORD WINAPI WNetGetUserW( LPCWSTR lpName, LPWSTR lpUserID, LPDWORD lpBufferSize )
1957 if (GetUserNameW( lpUserID, lpBufferSize )) return WN_SUCCESS;
1958 return GetLastError();
1961 /*********************************************************************
1962 * WNetConnectionDialog [MPR.@]
1964 DWORD WINAPI WNetConnectionDialog( HWND hwnd, DWORD dwType )
1966 FIXME( "(%p, %08X): stub\n", hwnd, dwType );
1968 SetLastError(WN_NO_NETWORK);
1969 return WN_NO_NETWORK;
1972 /*********************************************************************
1973 * WNetConnectionDialog1A [MPR.@]
1975 DWORD WINAPI WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct )
1977 FIXME( "(%p): stub\n", lpConnDlgStruct );
1979 SetLastError(WN_NO_NETWORK);
1980 return WN_NO_NETWORK;
1983 /*********************************************************************
1984 * WNetConnectionDialog1W [MPR.@]
1986 DWORD WINAPI WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct )
1988 FIXME( "(%p): stub\n", lpConnDlgStruct );
1990 SetLastError(WN_NO_NETWORK);
1991 return WN_NO_NETWORK;
1994 /*********************************************************************
1995 * WNetDisconnectDialog [MPR.@]
1997 DWORD WINAPI WNetDisconnectDialog( HWND hwnd, DWORD dwType )
1999 FIXME( "(%p, %08X): stub\n", hwnd, dwType );
2001 SetLastError(WN_NO_NETWORK);
2002 return WN_NO_NETWORK;
2005 /*********************************************************************
2006 * WNetDisconnectDialog1A [MPR.@]
2008 DWORD WINAPI WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct )
2010 FIXME( "(%p): stub\n", lpConnDlgStruct );
2012 SetLastError(WN_NO_NETWORK);
2013 return WN_NO_NETWORK;
2016 /*********************************************************************
2017 * WNetDisconnectDialog1W [MPR.@]
2019 DWORD WINAPI WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct )
2021 FIXME( "(%p): stub\n", lpConnDlgStruct );
2023 SetLastError(WN_NO_NETWORK);
2024 return WN_NO_NETWORK;
2027 /*********************************************************************
2028 * WNetGetLastErrorA [MPR.@]
2030 DWORD WINAPI WNetGetLastErrorA( LPDWORD lpError,
2031 LPSTR lpErrorBuf, DWORD nErrorBufSize,
2032 LPSTR lpNameBuf, DWORD nNameBufSize )
2034 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2035 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
2037 SetLastError(WN_NO_NETWORK);
2038 return WN_NO_NETWORK;
2041 /*********************************************************************
2042 * WNetGetLastErrorW [MPR.@]
2044 DWORD WINAPI WNetGetLastErrorW( LPDWORD lpError,
2045 LPWSTR lpErrorBuf, DWORD nErrorBufSize,
2046 LPWSTR lpNameBuf, DWORD nNameBufSize )
2048 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2049 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
2051 SetLastError(WN_NO_NETWORK);
2052 return WN_NO_NETWORK;
2055 /*********************************************************************
2056 * WNetGetNetworkInformationA [MPR.@]
2058 DWORD WINAPI WNetGetNetworkInformationA( LPCSTR lpProvider,
2059 LPNETINFOSTRUCT lpNetInfoStruct )
2061 DWORD ret;
2063 TRACE( "(%s, %p)\n", debugstr_a(lpProvider), lpNetInfoStruct );
2065 if (!lpProvider)
2066 ret = WN_BAD_POINTER;
2067 else
2069 int len;
2071 len = MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, NULL, 0);
2072 if (len)
2074 LPWSTR wideProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2076 if (wideProvider)
2078 MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, wideProvider,
2079 len);
2080 ret = WNetGetNetworkInformationW(wideProvider, lpNetInfoStruct);
2081 HeapFree(GetProcessHeap(), 0, wideProvider);
2083 else
2084 ret = WN_OUT_OF_MEMORY;
2086 else
2087 ret = GetLastError();
2089 if (ret)
2090 SetLastError(ret);
2091 TRACE("Returning %d\n", ret);
2092 return ret;
2095 /*********************************************************************
2096 * WNetGetNetworkInformationW [MPR.@]
2098 DWORD WINAPI WNetGetNetworkInformationW( LPCWSTR lpProvider,
2099 LPNETINFOSTRUCT lpNetInfoStruct )
2101 DWORD ret;
2103 TRACE( "(%s, %p)\n", debugstr_w(lpProvider), lpNetInfoStruct );
2105 if (!lpProvider)
2106 ret = WN_BAD_POINTER;
2107 else if (!lpNetInfoStruct)
2108 ret = WN_BAD_POINTER;
2109 else if (lpNetInfoStruct->cbStructure < sizeof(NETINFOSTRUCT))
2110 ret = WN_BAD_VALUE;
2111 else
2113 if (providerTable && providerTable->numProviders)
2115 DWORD providerIndex = _findProviderIndexW(lpProvider);
2117 if (providerIndex != BAD_PROVIDER_INDEX)
2119 lpNetInfoStruct->cbStructure = sizeof(NETINFOSTRUCT);
2120 lpNetInfoStruct->dwProviderVersion =
2121 providerTable->table[providerIndex].dwSpecVersion;
2122 lpNetInfoStruct->dwStatus = NO_ERROR;
2123 lpNetInfoStruct->dwCharacteristics = 0;
2124 lpNetInfoStruct->dwHandle = (ULONG_PTR)NULL;
2125 lpNetInfoStruct->wNetType =
2126 HIWORD(providerTable->table[providerIndex].dwNetType);
2127 lpNetInfoStruct->dwPrinters = -1;
2128 lpNetInfoStruct->dwDrives = -1;
2129 ret = WN_SUCCESS;
2131 else
2132 ret = WN_BAD_PROVIDER;
2134 else
2135 ret = WN_NO_NETWORK;
2137 if (ret)
2138 SetLastError(ret);
2139 TRACE("Returning %d\n", ret);
2140 return ret;
2143 /*****************************************************************
2144 * WNetGetProviderNameA [MPR.@]
2146 DWORD WINAPI WNetGetProviderNameA( DWORD dwNetType,
2147 LPSTR lpProvider, LPDWORD lpBufferSize )
2149 DWORD ret;
2151 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_a(lpProvider),
2152 lpBufferSize);
2154 if (!lpProvider)
2155 ret = WN_BAD_POINTER;
2156 else if (!lpBufferSize)
2157 ret = WN_BAD_POINTER;
2158 else
2160 if (providerTable)
2162 DWORD i;
2164 ret = WN_NO_NETWORK;
2165 for (i = 0; i < providerTable->numProviders &&
2166 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
2167 i++)
2169 if (i < providerTable->numProviders)
2171 DWORD sizeNeeded = WideCharToMultiByte(CP_ACP, 0,
2172 providerTable->table[i].name, -1, NULL, 0, NULL, NULL);
2174 if (*lpBufferSize < sizeNeeded)
2176 *lpBufferSize = sizeNeeded;
2177 ret = WN_MORE_DATA;
2179 else
2181 WideCharToMultiByte(CP_ACP, 0, providerTable->table[i].name,
2182 -1, lpProvider, *lpBufferSize, NULL, NULL);
2183 ret = WN_SUCCESS;
2184 /* FIXME: is *lpBufferSize set to the number of characters
2185 * copied? */
2189 else
2190 ret = WN_NO_NETWORK;
2192 if (ret)
2193 SetLastError(ret);
2194 TRACE("Returning %d\n", ret);
2195 return ret;
2198 /*****************************************************************
2199 * WNetGetProviderNameW [MPR.@]
2201 DWORD WINAPI WNetGetProviderNameW( DWORD dwNetType,
2202 LPWSTR lpProvider, LPDWORD lpBufferSize )
2204 DWORD ret;
2206 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_w(lpProvider),
2207 lpBufferSize);
2209 if (!lpProvider)
2210 ret = WN_BAD_POINTER;
2211 else if (!lpBufferSize)
2212 ret = WN_BAD_POINTER;
2213 else
2215 if (providerTable)
2217 DWORD i;
2219 ret = WN_NO_NETWORK;
2220 for (i = 0; i < providerTable->numProviders &&
2221 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
2222 i++)
2224 if (i < providerTable->numProviders)
2226 DWORD sizeNeeded = strlenW(providerTable->table[i].name) + 1;
2228 if (*lpBufferSize < sizeNeeded)
2230 *lpBufferSize = sizeNeeded;
2231 ret = WN_MORE_DATA;
2233 else
2235 strcpyW(lpProvider, providerTable->table[i].name);
2236 ret = WN_SUCCESS;
2237 /* FIXME: is *lpBufferSize set to the number of characters
2238 * copied? */
2242 else
2243 ret = WN_NO_NETWORK;
2245 if (ret)
2246 SetLastError(ret);
2247 TRACE("Returning %d\n", ret);
2248 return ret;