ReactOS 0.4.15-dev-8428-g6910fa6
wnet.c
Go to the documentation of this file.
1/*
2 * MPR WNet functions
3 *
4 * Copyright 1999 Ulrich Weigand
5 * Copyright 2004 Juan Lang
6 * Copyright 2007 Maarten Lankhorst
7 * Copyright 2016-2018 Pierre Schweitzer
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <stdarg.h>
25#include "windef.h"
26#include "winbase.h"
27#include "winnls.h"
28#include "winioctl.h"
29#include "winnetwk.h"
30#include "npapi.h"
31#include "winreg.h"
32#include "winuser.h"
33#ifndef __REACTOS__
34#define WINE_MOUNTMGR_EXTENSIONS
35#include "ddk/mountmgr.h"
36#endif
37#include "wine/debug.h"
38#include "mprres.h"
39#include "wnetpriv.h"
40#ifdef __REACTOS__
41#include <wine/unicode.h>
42#endif
43
45
46/* Data structures representing network service providers. Assumes only one
47 * thread creates them, and that they are constant for the life of the process
48 * (and therefore doesn't synchronize access).
49 * FIXME: only basic provider data and enumeration-related data are implemented
50 * so far, need to implement the rest too.
51 */
52typedef struct _WNetProvider
53{
67#ifdef __REACTOS__
68 PF_NPGetConnection getConnection;
69#endif
71
72typedef struct _WNetProviderTable
73{
79
80#define WNET_ENUMERATOR_TYPE_GLOBAL 0
81#define WNET_ENUMERATOR_TYPE_PROVIDER 1
82#define WNET_ENUMERATOR_TYPE_CONTEXT 2
83#define WNET_ENUMERATOR_TYPE_CONNECTED 3
84#define WNET_ENUMERATOR_TYPE_REMEMBERED 4
85
86/* An WNet enumerator. Note that the type doesn't correspond to the scope of
87 * the enumeration; it represents one of the following types:
88 * - a global enumeration, one that's executed across all providers
89 * - a provider-specific enumeration, one that's only executed by a single
90 * provider
91 * - a context enumeration. I know this contradicts what I just said about
92 * there being no correspondence between the scope and the type, but it's
93 * necessary for the special case that a "Entire Network" entry needs to
94 * be enumerated in an enumeration of the context scope. Thus an enumeration
95 * of the context scope results in a context type enumerator, which morphs
96 * into a global enumeration (so the enumeration continues across all
97 * providers).
98 * - a remembered enumeration, not related to providers themselves, but it
99 * is a registry enumeration for saved connections
100 */
101typedef struct _WNetEnumerator
102{
110 union
111 {
114 struct
115 {
121
122#define BAD_PROVIDER_INDEX (DWORD)0xffffffff
123
124/* Returns an index (into the global WNetProviderTable) of the provider with
125 * the given name, or BAD_PROVIDER_INDEX if not found.
126 */
127static DWORD _findProviderIndexW(LPCWSTR lpProvider);
128
130
131/*
132 * Global provider table functions
133 */
134
135static void _tryLoadProvider(PCWSTR provider)
136{
137 static const WCHAR servicePrefix[] = { 'S','y','s','t','e','m','\\',
138 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
139 'S','e','r','v','i','c','e','s','\\',0 };
140 static const WCHAR serviceFmt[] = { '%','s','%','s','\\',
141 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
143 HKEY hKey;
144
145 TRACE("%s\n", debugstr_w(provider));
146 swprintf(serviceName, serviceFmt, servicePrefix, provider);
150 {
151 static const WCHAR szProviderPath[] = { 'P','r','o','v','i','d','e','r',
152 'P','a','t','h',0 };
153 WCHAR providerPath[MAX_PATH];
154 DWORD type, size = sizeof(providerPath);
155
156 if (RegQueryValueExW(hKey, szProviderPath, NULL, &type,
157 (LPBYTE)providerPath, &size) == ERROR_SUCCESS && (type == REG_SZ || type == REG_EXPAND_SZ))
158 {
159 static const WCHAR szProviderName[] = { 'N','a','m','e',0 };
160 PWSTR name = NULL;
161
162 if (type == REG_EXPAND_SZ)
163 {
165 if (ExpandEnvironmentStringsW(providerPath, path, MAX_PATH)) lstrcpyW( providerPath, path );
166 }
167
168 size = 0;
169 RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size);
170 if (size)
171 {
173 if (RegQueryValueExW(hKey, szProviderName, NULL, &type,
175 {
177 name = NULL;
178 }
179 }
180 if (name)
181 {
182 HMODULE hLib = LoadLibraryW(providerPath);
183
184 if (hLib)
185 {
186#define MPR_GETPROC(proc) ((PF_##proc)GetProcAddress(hLib, #proc))
187
189
190 TRACE("loaded lib %p\n", hLib);
191 if (getCaps)
192 {
193 DWORD connectCap;
194 PWNetProvider provider =
196
197 provider->hLib = hLib;
198 provider->name = name;
199 TRACE("name is %s\n", debugstr_w(name));
200 provider->getCaps = getCaps;
201 provider->dwSpecVersion = getCaps(WNNC_SPEC_VERSION);
202 provider->dwNetType = getCaps(WNNC_NET_TYPE);
203 TRACE("net type is 0x%08x\n", provider->dwNetType);
204 provider->dwEnumScopes = getCaps(WNNC_ENUMERATION);
205 if (provider->dwEnumScopes)
206 {
207 TRACE("supports enumeration\n");
208 provider->openEnum = MPR_GETPROC(NPOpenEnum);
209 TRACE("NPOpenEnum %p\n", provider->openEnum);
211 TRACE("NPEnumResource %p\n", provider->enumResource);
212 provider->closeEnum = MPR_GETPROC(NPCloseEnum);
213 TRACE("NPCloseEnum %p\n", provider->closeEnum);
215 TRACE("NPGetResourceInformation %p\n", provider->getResourceInformation);
216 if (!provider->openEnum ||
217 !provider->enumResource ||
218 !provider->closeEnum)
219 {
220 provider->openEnum = NULL;
221 provider->enumResource = NULL;
222 provider->closeEnum = NULL;
223 provider->dwEnumScopes = 0;
224 WARN("Couldn't load enumeration functions\n");
225 }
226 }
227 connectCap = getCaps(WNNC_CONNECTION);
228 if (connectCap & WNNC_CON_ADDCONNECTION)
230 if (connectCap & WNNC_CON_ADDCONNECTION3)
232 if (connectCap & WNNC_CON_CANCELCONNECTION)
234#ifdef __REACTOS__
235 if (connectCap & WNNC_CON_GETCONNECTIONS)
236 provider->getConnection = MPR_GETPROC(NPGetConnection);
237#endif
238 TRACE("NPAddConnection %p\n", provider->addConnection);
239 TRACE("NPAddConnection3 %p\n", provider->addConnection3);
240 TRACE("NPCancelConnection %p\n", provider->cancelConnection);
242 }
243 else
244 {
245 WARN("Provider %s didn't export NPGetCaps\n",
246 debugstr_w(provider));
248 FreeLibrary(hLib);
249 }
250
251#undef MPR_GETPROC
252 }
253 else
254 {
255 WARN("Couldn't load library %s for provider %s\n",
256 debugstr_w(providerPath), debugstr_w(provider));
258 }
259 }
260 else
261 {
262 WARN("Couldn't get provider name for provider %s\n",
263 debugstr_w(provider));
264 }
265 }
266 else
267 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath));
269 }
270 else
271 WARN("Couldn't open service key for provider %s\n",
272 debugstr_w(provider));
273}
274
275#ifdef __REACTOS__
276static void _restoreSavedConnection(HKEY connection, WCHAR * local)
277{
279 DWORD type, prov, index, size;
280
281 net.lpProvider = NULL;
282 net.lpRemoteName = NULL;
283 net.lpLocalName = NULL;
284
285 TRACE("Restoring: %S\n", local);
286
287 size = sizeof(DWORD);
288 if (RegQueryValueExW(connection, L"ConnectionType", NULL, &type, (BYTE *)&net.dwType, &size) != ERROR_SUCCESS)
289 return;
290
291 if (type != REG_DWORD || size != sizeof(DWORD))
292 return;
293
294 if (RegQueryValueExW(connection, L"ProviderName", NULL, &type, NULL, &size) != ERROR_SUCCESS)
295 return;
296
297 if (type != REG_SZ)
298 return;
299
300 net.lpProvider = HeapAlloc(GetProcessHeap(), 0, size);
301 if (!net.lpProvider)
302 return;
303
304 if (RegQueryValueExW(connection, L"ProviderName", NULL, NULL, (BYTE *)net.lpProvider, &size) != ERROR_SUCCESS)
305 goto cleanup;
306
307 size = sizeof(DWORD);
308 if (RegQueryValueExW(connection, L"ProviderType", NULL, &type, (BYTE *)&prov, &size) != ERROR_SUCCESS)
309 goto cleanup;
310
311 if (type != REG_DWORD || size != sizeof(DWORD))
312 goto cleanup;
313
314 index = _findProviderIndexW(net.lpProvider);
316 goto cleanup;
317
318 if (providerTable->table[index].dwNetType != prov)
319 goto cleanup;
320
321 if (RegQueryValueExW(connection, L"RemotePath", NULL, &type, NULL, &size) != ERROR_SUCCESS)
322 goto cleanup;
323
324 if (type != REG_SZ)
325 goto cleanup;
326
327 net.lpRemoteName = HeapAlloc(GetProcessHeap(), 0, size);
328 if (!net.lpRemoteName)
329 goto cleanup;
330
331 if (RegQueryValueExW(connection, L"RemotePath", NULL, NULL, (BYTE *)net.lpRemoteName, &size) != ERROR_SUCCESS)
332 goto cleanup;
333
334 size = strlenW(local);
335 net.lpLocalName = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR) + 2 * sizeof(WCHAR));
336 if (!net.lpLocalName)
337 goto cleanup;
338
339 strcpyW(net.lpLocalName, local);
340 net.lpLocalName[size] = ':';
341 net.lpLocalName[size + 1] = 0;
342
343 TRACE("Attempting connection\n");
344
346
347cleanup:
348 HeapFree(GetProcessHeap(), 0, net.lpProvider);
349 HeapFree(GetProcessHeap(), 0, net.lpRemoteName);
350 HeapFree(GetProcessHeap(), 0, net.lpLocalName);
351}
352#endif
353
354void wnetInit(HINSTANCE hInstDll)
355{
356 static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\',
357 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
358 'C','o','n','t','r','o','l','\\',
359 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
360 'O','r','d','e','r',0 };
361 static const WCHAR providerOrder[] = { 'P','r','o','v','i','d','e','r',
362 'O','r','d','e','r',0 };
363 HKEY hKey;
364
365 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, providerOrderKey, 0, KEY_READ, &hKey)
366 == ERROR_SUCCESS)
367 {
368 DWORD size = 0;
369
370 RegQueryValueExW(hKey, providerOrder, NULL, NULL, NULL, &size);
371 if (size)
372 {
374
375 if (providers)
376 {
377 DWORD type;
378
379 if (RegQueryValueExW(hKey, providerOrder, NULL, &type,
381 {
382 PWSTR ptr;
383 DWORD numToAllocate;
384
385 TRACE("provider order is %s\n", debugstr_w(providers));
386 /* first count commas as a heuristic for how many to
387 * allocate space for */
388 for (ptr = providers, numToAllocate = 1; ptr; )
389 {
390 ptr = wcschr(ptr, ',');
391 if (ptr) {
392 numToAllocate++;
393 ptr++;
394 }
395 }
398 sizeof(WNetProviderTable)
399 + (numToAllocate - 1) * sizeof(WNetProvider));
400 if (providerTable)
401 {
402 PWSTR ptrPrev;
403 int entireNetworkLen;
404 LPCWSTR stringresource;
405
406 entireNetworkLen = LoadStringW(hInstDll,
407 IDS_ENTIRENETWORK, (LPWSTR)&stringresource, 0);
409 GetProcessHeap(), 0, (entireNetworkLen + 1) *
410 sizeof(WCHAR));
412 {
413 memcpy(providerTable->entireNetwork, stringresource, entireNetworkLen*sizeof(WCHAR));
414 providerTable->entireNetwork[entireNetworkLen] = 0;
415 }
416 providerTable->numAllocated = numToAllocate;
417 for (ptr = providers; ptr; )
418 {
419 ptrPrev = ptr;
420 ptr = wcschr(ptr, ',');
421 if (ptr)
422 *ptr++ = '\0';
423 _tryLoadProvider(ptrPrev);
424 }
425 }
426 }
428 }
429 }
431 }
432
433#ifdef __REACTOS__
434 if (providerTable)
435 {
436 HKEY user_profile;
437
438 if (RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS)
439 {
441 WCHAR subkey[8] = {'N', 'e', 't', 'w', 'o', 'r', 'k', 0};
442
443 if (RegOpenKeyExW(user_profile, subkey, 0, KEY_READ, &network) == ERROR_SUCCESS)
444 {
445 DWORD size, max;
446
447 TRACE("Enumerating remembered connections\n");
448
450 {
451 WCHAR *local;
452
453 TRACE("There are %lu connections\n", max);
454
455 local = HeapAlloc(GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR));
456 if (local)
457 {
458 DWORD index;
459
460 for (index = 0; index < max; ++index)
461 {
462 DWORD len = size + 1;
463 HKEY connection;
464
465 TRACE("Trying connection %lu\n", index);
466
468 continue;
469
470 TRACE("It is %S\n", local);
471
472 if (RegOpenKeyExW(network, local, 0, KEY_READ, &connection) != ERROR_SUCCESS)
473 continue;
474
475 _restoreSavedConnection(connection, local);
476 RegCloseKey(connection);
477 }
478
480 }
481 }
482
484 }
485
486 RegCloseKey(user_profile);
487 }
488 }
489#endif
490}
491
492void wnetFree(void)
493{
494 if (providerTable)
495 {
496 DWORD i;
497
498 for (i = 0; i < providerTable->numProviders; i++)
499 {
502 }
506 }
507}
508
510{
512
514 {
515 DWORD i;
516
517 for (i = 0; i < providerTable->numProviders &&
519 if (!lstrcmpW(lpProvider, providerTable->table[i].name))
520 ret = i;
521 }
522 return ret;
523}
524
525/*
526 * Browsing Functions
527 */
528
530{
532
533 if (lpNet)
534 {
535 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW));
536 if (ret)
537 {
538 size_t len;
539
540 *ret = *lpNet;
541 ret->lpLocalName = ret->lpComment = ret->lpProvider = NULL;
542 if (lpNet->lpRemoteName)
543 {
544 len = lstrlenW(lpNet->lpRemoteName) + 1;
545 ret->lpRemoteName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
546 if (ret->lpRemoteName)
547 lstrcpyW(ret->lpRemoteName, lpNet->lpRemoteName);
548 }
549 }
550 }
551 else
552 ret = NULL;
553 return ret;
554}
555
557{
558 if (lpNet)
559 {
561 HeapFree(GetProcessHeap(), 0, lpNet);
562 }
563}
564
566 DWORD dwUsage, LPNETRESOURCEW lpNet)
567{
570
571 if (ret)
572 {
574 ret->dwScope = dwScope;
575 ret->dwType = dwType;
576 ret->dwUsage = dwUsage;
577 ret->specific.net = _copyNetResourceForEnumW(lpNet);
578 }
579 return ret;
580}
581
583 DWORD dwUsage, DWORD index, HANDLE handle)
584{
586
588 ret = NULL;
589 else
590 {
592 if (ret)
593 {
595 ret->providerIndex = index;
596 ret->dwScope = dwScope;
597 ret->dwType = dwType;
598 ret->dwUsage = dwUsage;
599 ret->handle = handle;
600 }
601 }
602 return ret;
603}
604
606 DWORD dwUsage)
607{
610
611 if (ret)
612 {
614 ret->dwScope = dwScope;
615 ret->dwType = dwType;
616 ret->dwUsage = dwUsage;
617 }
618 return ret;
619}
620
622 DWORD dwUsage)
623{
625 if (ret)
626 {
628 ret->dwScope = dwScope;
629 ret->dwType = dwType;
630 ret->dwUsage = dwUsage;
632 if (!ret->specific.handles)
633 {
635 ret = NULL;
636 }
637 }
638 return ret;
639}
640
642 HKEY remembered)
643{
645 if (ret)
646 {
648 ret->dwScope = dwScope;
649 ret->dwType = dwType;
650 ret->specific.remembered.registry = remembered;
651 }
652 return ret;
653}
654
655/* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
656 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
657 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
658 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
659 * if not all members of the array could be thunked, and something else on
660 * failure.
661 */
663 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
664{
665 DWORD i, numToThunk, totalBytes, ret;
666 LPSTR strNext;
667
668 if (!lpNetArrayIn)
669 return WN_BAD_POINTER;
670 if (!lpcCount)
671 return WN_BAD_POINTER;
672 if (*lpcCount == -1)
673 return WN_BAD_VALUE;
674 if (!lpBuffer)
675 return WN_BAD_POINTER;
676 if (!lpBufferSize)
677 return WN_BAD_POINTER;
678
679 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
680 {
681 const NETRESOURCEW *lpNet = lpNetArrayIn + i;
682
683 totalBytes += sizeof(NETRESOURCEA);
684 if (lpNet->lpLocalName)
685 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpLocalName,
686 -1, NULL, 0, NULL, NULL);
687 if (lpNet->lpRemoteName)
688 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpRemoteName,
689 -1, NULL, 0, NULL, NULL);
690 if (lpNet->lpComment)
691 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpComment,
692 -1, NULL, 0, NULL, NULL);
693 if (lpNet->lpProvider)
694 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpProvider,
695 -1, NULL, 0, NULL, NULL);
696 if (totalBytes < *lpBufferSize)
697 numToThunk = i + 1;
698 }
699 strNext = (LPSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEA));
700 for (i = 0; i < numToThunk; i++)
701 {
703 const NETRESOURCEW *lpNetIn = lpNetArrayIn + i;
704
705 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEA));
706 /* lie about string lengths, we already verified how many
707 * we have space for above
708 */
709 if (lpNetIn->lpLocalName)
710 {
711 lpNetOut->lpLocalName = strNext;
712 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpLocalName, -1,
713 lpNetOut->lpLocalName, *lpBufferSize, NULL, NULL);
714 }
715 if (lpNetIn->lpRemoteName)
716 {
717 lpNetOut->lpRemoteName = strNext;
718 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpRemoteName, -1,
719 lpNetOut->lpRemoteName, *lpBufferSize, NULL, NULL);
720 }
721 if (lpNetIn->lpComment)
722 {
723 lpNetOut->lpComment = strNext;
724 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpComment, -1,
725 lpNetOut->lpComment, *lpBufferSize, NULL, NULL);
726 }
727 if (lpNetIn->lpProvider)
728 {
729 lpNetOut->lpProvider = strNext;
730 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpProvider, -1,
731 lpNetOut->lpProvider, *lpBufferSize, NULL, NULL);
732 }
733 }
734 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
735 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
736 *lpcCount, ret);
737 return ret;
738}
739
740/* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
741 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
742 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
743 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
744 * if not all members of the array could be thunked, and something else on
745 * failure.
746 */
748 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
749{
750 DWORD i, numToThunk, totalBytes, ret;
751 LPWSTR strNext;
752
753 if (!lpNetArrayIn)
754 return WN_BAD_POINTER;
755 if (!lpcCount)
756 return WN_BAD_POINTER;
757 if (*lpcCount == -1)
758 return WN_BAD_VALUE;
759 if (!lpBuffer)
760 return WN_BAD_POINTER;
761 if (!lpBufferSize)
762 return WN_BAD_POINTER;
763
764 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++)
765 {
766 const NETRESOURCEA *lpNet = lpNetArrayIn + i;
767
768 totalBytes += sizeof(NETRESOURCEW);
769 if (lpNet->lpLocalName)
770 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpLocalName,
771 -1, NULL, 0) * sizeof(WCHAR);
772 if (lpNet->lpRemoteName)
773 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpRemoteName,
774 -1, NULL, 0) * sizeof(WCHAR);
775 if (lpNet->lpComment)
776 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpComment,
777 -1, NULL, 0) * sizeof(WCHAR);
778 if (lpNet->lpProvider)
779 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpProvider,
780 -1, NULL, 0) * sizeof(WCHAR);
781 if (totalBytes < *lpBufferSize)
782 numToThunk = i + 1;
783 }
784 strNext = (LPWSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEW));
785 for (i = 0; i < numToThunk; i++)
786 {
788 const NETRESOURCEA *lpNetIn = lpNetArrayIn + i;
789
790 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEW));
791 /* lie about string lengths, we already verified how many
792 * we have space for above
793 */
794 if (lpNetIn->lpLocalName)
795 {
796 lpNetOut->lpLocalName = strNext;
797 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpLocalName,
798 -1, lpNetOut->lpLocalName, *lpBufferSize);
799 }
800 if (lpNetIn->lpRemoteName)
801 {
802 lpNetOut->lpRemoteName = strNext;
803 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpRemoteName,
804 -1, lpNetOut->lpRemoteName, *lpBufferSize);
805 }
806 if (lpNetIn->lpComment)
807 {
808 lpNetOut->lpComment = strNext;
809 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpComment,
810 -1, lpNetOut->lpComment, *lpBufferSize);
811 }
812 if (lpNetIn->lpProvider)
813 {
814 lpNetOut->lpProvider = strNext;
815 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpProvider,
816 -1, lpNetOut->lpProvider, *lpBufferSize);
817 }
818 }
819 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS;
820 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk,
821 *lpcCount, ret);
822 return ret;
823}
824
825/*********************************************************************
826 * WNetOpenEnumA [MPR.@]
827 *
828 * See comments for WNetOpenEnumW.
829 */
830DWORD WINAPI WNetOpenEnumA( DWORD dwScope, DWORD dwType, DWORD dwUsage,
831 LPNETRESOURCEA lpNet, LPHANDLE lphEnum )
832{
833 DWORD ret;
834
835 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
836 dwScope, dwType, dwUsage, lpNet, lphEnum );
837
838 if (!lphEnum)
840 else if (!providerTable || providerTable->numProviders == 0)
841 {
842 *lphEnum = NULL;
844 }
845 else
846 {
847 if (lpNet)
848 {
849 LPNETRESOURCEW lpNetWide = NULL;
850 BYTE buf[1024];
851 DWORD size = sizeof(buf), count = 1;
852 BOOL allocated = FALSE;
853
855 if (ret == WN_MORE_DATA)
856 {
857 lpNetWide = HeapAlloc(GetProcessHeap(), 0,
858 size);
859 if (lpNetWide)
860 {
861 ret = _thunkNetResourceArrayAToW(lpNet, &count, lpNetWide,
862 &size);
863 allocated = TRUE;
864 }
865 else
867 }
868 else if (ret == WN_SUCCESS)
869 lpNetWide = (LPNETRESOURCEW)buf;
870 if (ret == WN_SUCCESS)
871 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, lpNetWide,
872 lphEnum);
873 if (allocated)
874 HeapFree(GetProcessHeap(), 0, lpNetWide);
875 }
876 else
877 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, NULL, lphEnum);
878 }
879 if (ret)
881 TRACE("Returning %d\n", ret);
882 return ret;
883}
884
885/*********************************************************************
886 * WNetOpenEnumW [MPR.@]
887 *
888 * Network enumeration has way too many parameters, so I'm not positive I got
889 * them right. What I've got so far:
890 *
891 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
892 * all the network providers should be enumerated.
893 *
894 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
895 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
896 * lpProvider is set, all the network providers should be enumerated.
897 * (This means the enumeration is a list of network providers, not that the
898 * enumeration is passed on to the providers.)
899 *
900 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
901 * resource matches the "Entire Network" resource (no remote name, no
902 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
903 * enumeration is done on every network provider.
904 *
905 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
906 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
907 * only to the given network provider.
908 *
909 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
910 * no lpProvider is set, enumeration will be tried on every network provider,
911 * in the order in which they're loaded.
912 *
913 * - The LPNETRESOURCE should be disregarded for scopes besides
914 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
915 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
916 *
917 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
918 * resource in the enumerated list, as well as any machines in your
919 * workgroup. The machines in your workgroup come from doing a
920 * RESOURCE_CONTEXT enumeration of every Network Provider.
921 */
922DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage,
923 LPNETRESOURCEW lpNet, LPHANDLE lphEnum )
924{
925 DWORD ret;
926
927 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
928 dwScope, dwType, dwUsage, lpNet, lphEnum );
929
930 if (!lphEnum)
932 else if (!providerTable || providerTable->numProviders == 0)
933 {
934 *lphEnum = NULL;
936 }
937 else
938 {
939 switch (dwScope)
940 {
942 if (lpNet)
943 {
944 if (lpNet->lpProvider)
945 {
947
949 {
952 {
954 PWSTR RemoteName = lpNet->lpRemoteName;
955
956 if ((lpNet->dwUsage & RESOURCEUSAGE_CONTAINER) &&
957 RemoteName && !lstrcmpW(RemoteName, lpNet->lpProvider))
958 lpNet->lpRemoteName = NULL;
959
961 dwScope, dwType, dwUsage, lpNet, &handle);
962 if (ret == WN_SUCCESS)
963 {
964 *lphEnum = _createProviderEnumerator(
965 dwScope, dwType, dwUsage, index, handle);
966 ret = *lphEnum ? WN_SUCCESS :
968 }
969
970 lpNet->lpRemoteName = RemoteName;
971 }
972 else
974 }
975 else
977 }
978 else if (lpNet->lpRemoteName)
979 {
980 *lphEnum = _createGlobalEnumeratorW(dwScope,
981 dwType, dwUsage, lpNet);
982 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
983 }
984 else
985 {
986 if (lpNet->lpComment && !lstrcmpW(lpNet->lpComment,
988 {
989 /* comment matches the "Entire Network", enumerate
990 * global scope of every provider
991 */
992 *lphEnum = _createGlobalEnumeratorW(dwScope,
993 dwType, dwUsage, lpNet);
994 }
995 else
996 {
997 /* this is the same as not having passed lpNet */
998 *lphEnum = _createGlobalEnumeratorW(dwScope,
999 dwType, dwUsage, NULL);
1000 }
1001 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
1002 }
1003 }
1004 else
1005 {
1006 *lphEnum = _createGlobalEnumeratorW(dwScope, dwType,
1007 dwUsage, lpNet);
1008 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
1009 }
1010 break;
1011 case RESOURCE_CONTEXT:
1012 *lphEnum = _createContextEnumerator(dwScope, dwType, dwUsage);
1013 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
1014 break;
1015 case RESOURCE_CONNECTED:
1016 *lphEnum = _createConnectedEnumerator(dwScope, dwType, dwUsage);
1017 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
1018 break;
1020 {
1021 HKEY remembered, user_profile;
1022
1024 if (RegOpenCurrentUser(KEY_READ, &user_profile) == ERROR_SUCCESS)
1025 {
1026 WCHAR subkey[8] = {'N', 'e', 't', 'w', 'o', 'r', 'k', 0};
1027
1028 if (RegOpenKeyExW(user_profile, subkey, 0, KEY_READ, &remembered) == ERROR_SUCCESS)
1029 {
1030 *lphEnum = _createRememberedEnumerator(dwScope, dwType, remembered);
1031 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY;
1032 }
1033
1034 RegCloseKey(user_profile);
1035 }
1036 }
1037 break;
1038 default:
1039 WARN("unknown scope 0x%08x\n", dwScope);
1040 ret = WN_BAD_VALUE;
1041 }
1042 }
1043 if (ret)
1045 TRACE("Returning %d\n", ret);
1046 return ret;
1047}
1048
1049/*********************************************************************
1050 * WNetEnumResourceA [MPR.@]
1051 */
1053 LPVOID lpBuffer, LPDWORD lpBufferSize )
1054{
1055 DWORD ret;
1056
1057 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
1058
1059 if (!hEnum)
1061 else if (!lpcCount)
1063 else if (!lpBuffer)
1065 else if (!lpBufferSize)
1067 else if (*lpBufferSize < sizeof(NETRESOURCEA))
1068 {
1069 *lpBufferSize = sizeof(NETRESOURCEA);
1070 ret = WN_MORE_DATA;
1071 }
1072 else
1073 {
1074 DWORD localCount = *lpcCount, localSize = *lpBufferSize;
1075 LPVOID localBuffer = HeapAlloc(GetProcessHeap(), 0, localSize);
1076
1077 if (localBuffer)
1078 {
1079 ret = WNetEnumResourceW(hEnum, &localCount, localBuffer,
1080 &localSize);
1081 if (ret == WN_SUCCESS || (ret == WN_MORE_DATA && localCount != -1))
1082 {
1083 /* FIXME: this isn't necessarily going to work in the case of
1084 * WN_MORE_DATA, because our enumerator may have moved on to
1085 * the next provider. MSDN states that a large (16KB) buffer
1086 * size is the appropriate usage of this function, so
1087 * hopefully it won't be an issue.
1088 */
1089 ret = _thunkNetResourceArrayWToA(localBuffer, &localCount,
1090 lpBuffer, lpBufferSize);
1091 *lpcCount = localCount;
1092 }
1093 HeapFree(GetProcessHeap(), 0, localBuffer);
1094 }
1095 else
1097 }
1098 if (ret)
1100 TRACE("Returning %d\n", ret);
1101 return ret;
1102}
1103
1105{
1106 DWORD ret;
1107
1108 if (provider)
1109 {
1110 ret = sizeof(NETRESOURCEW);
1111 ret += 2 * (lstrlenW(provider->name) + 1) * sizeof(WCHAR);
1112 }
1113 else
1114 ret = 0;
1115 return ret;
1116}
1117
1119 LPVOID lpBuffer, const DWORD *lpBufferSize)
1120{
1121 DWORD ret;
1122
1123 if (!enumerator)
1124 return WN_BAD_POINTER;
1125 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1126 return WN_BAD_VALUE;
1127 if (!lpcCount)
1128 return WN_BAD_POINTER;
1129 if (!lpBuffer)
1130 return WN_BAD_POINTER;
1131 if (!lpBufferSize)
1132 return WN_BAD_POINTER;
1133 if (*lpBufferSize < sizeof(NETRESOURCEA))
1134 return WN_MORE_DATA;
1135
1136 if (!providerTable || enumerator->providerIndex >=
1139 else
1140 {
1141 DWORD bytes = 0, count = 0, countLimit, i;
1143 LPWSTR strNext;
1144
1145 countLimit = *lpcCount == -1 ?
1146 providerTable->numProviders - enumerator->providerIndex : *lpcCount;
1147 while (count < countLimit && bytes < *lpBufferSize)
1148 {
1149 DWORD bytesNext = _countProviderBytesW(
1150 &providerTable->table[count + enumerator->providerIndex]);
1151
1152 if (bytes + bytesNext < *lpBufferSize)
1153 {
1154 bytes += bytesNext;
1155 count++;
1156 }
1157 }
1158 strNext = (LPWSTR)((LPBYTE)lpBuffer + count * sizeof(NETRESOURCEW));
1159 for (i = 0, resource = lpBuffer; i < count; i++, resource++)
1160 {
1161 resource->dwScope = RESOURCE_GLOBALNET;
1162 resource->dwType = RESOURCETYPE_ANY;
1163 resource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK;
1166 resource->lpLocalName = NULL;
1167 resource->lpRemoteName = strNext;
1168 lstrcpyW(resource->lpRemoteName,
1169 providerTable->table[i + enumerator->providerIndex].name);
1170 strNext += lstrlenW(resource->lpRemoteName) + 1;
1171 resource->lpComment = NULL;
1172 resource->lpProvider = strNext;
1173 lstrcpyW(resource->lpProvider,
1174 providerTable->table[i + enumerator->providerIndex].name);
1175 strNext += lstrlenW(resource->lpProvider) + 1;
1176 }
1177 enumerator->providerIndex += count;
1178 *lpcCount = count;
1179 ret = count > 0 ? WN_SUCCESS : WN_MORE_DATA;
1180 }
1181 TRACE("Returning %d\n", ret);
1182 return ret;
1183}
1184
1185/* Advances the enumerator (assumed to be a global enumerator) to the next
1186 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
1187 * not open a handle with the next provider.
1188 * If the existing handle is NULL, may leave the enumerator unchanged, since
1189 * the current provider may support the desired scope.
1190 * If the existing handle is not NULL, closes it before moving on.
1191 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
1192 * provider, and another error on failure.
1193 */
1195{
1196 if (!enumerator)
1197 return WN_BAD_POINTER;
1198 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1199 return WN_BAD_VALUE;
1200 if (!providerTable || enumerator->providerIndex >=
1202 return WN_NO_MORE_ENTRIES;
1203
1204 if (enumerator->providerDone)
1205 {
1206 DWORD dwEnum = 0;
1207 enumerator->providerDone = FALSE;
1208 if (enumerator->handle)
1209 {
1211 enumerator->handle);
1212 enumerator->handle = NULL;
1213 enumerator->providerIndex++;
1214 }
1215 if (enumerator->dwScope == RESOURCE_CONNECTED)
1216 dwEnum = WNNC_ENUM_LOCAL;
1217 else if (enumerator->dwScope == RESOURCE_GLOBALNET)
1218 dwEnum = WNNC_ENUM_GLOBAL;
1219 else if (enumerator->dwScope == RESOURCE_CONTEXT)
1220 dwEnum = WNNC_ENUM_CONTEXT;
1221 for (; enumerator->providerIndex < providerTable->numProviders &&
1223 & dwEnum); enumerator->providerIndex++)
1224 ;
1225 }
1226 return enumerator->providerIndex < providerTable->numProviders ?
1228}
1229
1230/* "Passes through" call to the next provider that supports the enumeration
1231 * type.
1232 * FIXME: if one call to a provider's enumerator succeeds while there's still
1233 * space in lpBuffer, I don't call to the next provider. The caller may not
1234 * expect that it should call EnumResourceW again with a return value of
1235 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1236 * may have to be moved around a bit, ick.
1237 */
1239 LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
1240{
1241 DWORD ret;
1242
1243 if (!enumerator)
1244 return WN_BAD_POINTER;
1245 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1246 return WN_BAD_VALUE;
1247 if (!lpcCount)
1248 return WN_BAD_POINTER;
1249 if (!lpBuffer)
1250 return WN_BAD_POINTER;
1251 if (!lpBufferSize)
1252 return WN_BAD_POINTER;
1253 if (*lpBufferSize < sizeof(NETRESOURCEW))
1254 return WN_MORE_DATA;
1255
1256 ret = _globalEnumeratorAdvance(enumerator);
1257 if (ret == WN_SUCCESS)
1258 {
1259 ret = providerTable->table[enumerator->providerIndex].
1260 openEnum(enumerator->dwScope, enumerator->dwType,
1261 enumerator->dwUsage, enumerator->specific.net,
1262 &enumerator->handle);
1263 if (ret == WN_SUCCESS)
1264 {
1265 ret = providerTable->table[enumerator->providerIndex].
1266 enumResource(enumerator->handle, lpcCount, lpBuffer,
1267 lpBufferSize);
1268 if (ret != WN_MORE_DATA)
1269 enumerator->providerDone = TRUE;
1270 }
1271 }
1272 TRACE("Returning %d\n", ret);
1273 return ret;
1274}
1275
1277 LPVOID lpBuffer, LPDWORD lpBufferSize)
1278{
1279 DWORD ret;
1280
1281 if (!enumerator)
1282 return WN_BAD_POINTER;
1283 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL)
1284 return WN_BAD_VALUE;
1285 if (!lpcCount)
1286 return WN_BAD_POINTER;
1287 if (!lpBuffer)
1288 return WN_BAD_POINTER;
1289 if (!lpBufferSize)
1290 return WN_BAD_POINTER;
1291 if (*lpBufferSize < sizeof(NETRESOURCEW))
1292 return WN_MORE_DATA;
1293 if (!providerTable)
1294 return WN_NO_NETWORK;
1295
1296 switch (enumerator->dwScope)
1297 {
1298 case RESOURCE_GLOBALNET:
1299 if (enumerator->specific.net)
1300 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount,
1301 lpBuffer, lpBufferSize);
1302 else
1303 ret = _enumerateProvidersW(enumerator, lpcCount, lpBuffer,
1304 lpBufferSize);
1305 break;
1306 case RESOURCE_CONTEXT:
1307 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, lpBuffer,
1308 lpBufferSize);
1309 break;
1310 default:
1311 WARN("unexpected scope 0x%08x\n", enumerator->dwScope);
1313 }
1314 TRACE("Returning %d\n", ret);
1315 return ret;
1316}
1317
1319 LPVOID lpBuffer, LPDWORD lpBufferSize)
1320{
1321 if (!enumerator)
1322 return WN_BAD_POINTER;
1323 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_PROVIDER)
1324 return WN_BAD_VALUE;
1325 if (!enumerator->handle)
1326 return WN_BAD_VALUE;
1327 if (!lpcCount)
1328 return WN_BAD_POINTER;
1329 if (!lpBuffer)
1330 return WN_BAD_POINTER;
1331 if (!lpBufferSize)
1332 return WN_BAD_POINTER;
1333 if (!providerTable)
1334 return WN_NO_NETWORK;
1335 if (enumerator->providerIndex >= providerTable->numProviders)
1336 return WN_NO_MORE_ENTRIES;
1337 if (!providerTable->table[enumerator->providerIndex].enumResource)
1338 return WN_BAD_VALUE;
1339 return providerTable->table[enumerator->providerIndex].enumResource(
1340 enumerator->handle, lpcCount, lpBuffer, lpBufferSize);
1341}
1342
1344 LPVOID lpBuffer, LPDWORD lpBufferSize)
1345{
1346 DWORD ret;
1347 size_t cchEntireNetworkLen, bytesNeeded;
1348
1349 if (!enumerator)
1350 return WN_BAD_POINTER;
1351 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONTEXT)
1352 return WN_BAD_VALUE;
1353 if (!lpcCount)
1354 return WN_BAD_POINTER;
1355 if (!lpBuffer)
1356 return WN_BAD_POINTER;
1357 if (!lpBufferSize)
1358 return WN_BAD_POINTER;
1359 if (!providerTable)
1360 return WN_NO_NETWORK;
1361
1362 cchEntireNetworkLen = lstrlenW(providerTable->entireNetwork) + 1;
1363 bytesNeeded = sizeof(NETRESOURCEW) + cchEntireNetworkLen * sizeof(WCHAR);
1364 if (*lpBufferSize < bytesNeeded)
1365 {
1366 *lpBufferSize = bytesNeeded;
1367 ret = WN_MORE_DATA;
1368 }
1369 else
1370 {
1371 LPNETRESOURCEW lpNet = lpBuffer;
1372
1373 lpNet->dwScope = RESOURCE_GLOBALNET;
1374 lpNet->dwType = enumerator->dwType;
1377 lpNet->lpLocalName = NULL;
1378 lpNet->lpRemoteName = NULL;
1379 lpNet->lpProvider = NULL;
1380 /* odd, but correct: put comment at end of buffer, so it won't get
1381 * overwritten by subsequent calls to a provider's enumResource
1382 */
1383 lpNet->lpComment = (LPWSTR)((LPBYTE)lpBuffer + *lpBufferSize -
1384 (cchEntireNetworkLen * sizeof(WCHAR)));
1386 ret = WN_SUCCESS;
1387 }
1388 if (ret == WN_SUCCESS)
1389 {
1390 DWORD bufferSize = *lpBufferSize - bytesNeeded;
1391
1392 /* "Entire Network" entry enumerated--morph this into a global
1393 * enumerator. enumerator->lpNet continues to be NULL, since it has
1394 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1395 */
1397 ret = _enumerateGlobalW(enumerator, lpcCount,
1398 (LPBYTE)lpBuffer + bytesNeeded, &bufferSize);
1399 if (ret == WN_SUCCESS)
1400 {
1401 /* reflect the fact that we already enumerated "Entire Network" */
1402 (*lpcCount)++;
1403 *lpBufferSize = bufferSize + bytesNeeded;
1404 }
1405 else
1406 {
1407 /* the provider enumeration failed, but we already succeeded in
1408 * enumerating "Entire Network"--leave type as global to allow a
1409 * retry, but indicate success with a count of one.
1410 */
1411 ret = WN_SUCCESS;
1412 *lpcCount = 1;
1413 *lpBufferSize = bytesNeeded;
1414 }
1415 }
1416 TRACE("Returning %d\n", ret);
1417 return ret;
1418}
1419
1421{
1422 DWORD len;
1423 WCHAR* local = *end;
1424
1425 len = lstrlenW(source) + 1;
1426 len *= sizeof(WCHAR);
1427 if (*left < len)
1428 return WN_MORE_DATA;
1429
1430 local -= (len / sizeof(WCHAR));
1432 *left -= len;
1433 *end = local;
1434
1435 return WN_SUCCESS;
1436}
1437
1438static DWORD _enumerateConnectedW(PWNetEnumerator enumerator, DWORD* user_count,
1439 void* user_buffer, DWORD* user_size)
1440{
1441 DWORD ret, index, count, total_count, size, i, left;
1442 void* end;
1443 NETRESOURCEW* curr, * buffer;
1444 HANDLE* handles;
1445
1446 if (!enumerator)
1447 return WN_BAD_POINTER;
1448 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONNECTED)
1449 return WN_BAD_VALUE;
1450 if (!user_count || !user_buffer || !user_size)
1451 return WN_BAD_POINTER;
1452 if (!providerTable)
1453 return WN_NO_NETWORK;
1454
1455 handles = enumerator->specific.handles;
1456 left = *user_size;
1457 size = *user_size;
1458 buffer = HeapAlloc(GetProcessHeap(), 0, *user_size);
1459 if (!buffer)
1460 return WN_NO_NETWORK;
1461
1462 curr = user_buffer;
1463 end = (char *)user_buffer + size;
1464 count = *user_count;
1465 total_count = 0;
1466
1468 for (index = 0; index < providerTable->numProviders; index++)
1469 {
1471 {
1472 if (handles[index] == 0)
1473 {
1474 ret = providerTable->table[index].openEnum(enumerator->dwScope,
1475 enumerator->dwType,
1476 enumerator->dwUsage,
1477 NULL, &handles[index]);
1478 if (ret != WN_SUCCESS)
1479 continue;
1480 }
1481
1483 &count, buffer,
1484 &size);
1485 total_count += count;
1486 if (ret == WN_MORE_DATA)
1487 break;
1488
1489 if (ret == WN_SUCCESS)
1490 {
1491 for (i = 0; i < count; ++i)
1492 {
1493 if (left < sizeof(NETRESOURCEW))
1494 {
1495 ret = WN_MORE_DATA;
1496 break;
1497 }
1498
1499 memcpy(curr, &buffer[i], sizeof(NETRESOURCEW));
1500 left -= sizeof(NETRESOURCEW);
1501
1502 ret = _copyStringToEnumW(buffer[i].lpLocalName, &left, &end);
1503 if (ret == WN_MORE_DATA)
1504 break;
1505 curr->lpLocalName = end;
1506
1507 ret = _copyStringToEnumW(buffer[i].lpRemoteName, &left, &end);
1508 if (ret == WN_MORE_DATA)
1509 break;
1510 curr->lpRemoteName = end;
1511
1512 ret = _copyStringToEnumW(buffer[i].lpProvider, &left, &end);
1513 if (ret == WN_MORE_DATA)
1514 break;
1515 curr->lpProvider = end;
1516
1517 ++curr;
1518 }
1519
1520 size = left;
1521 }
1522
1523 if (*user_count != -1)
1524 count = *user_count - total_count;
1525 else
1526 count = *user_count;
1527 }
1528 }
1529
1530 if (total_count == 0)
1532
1533 *user_count = total_count;
1535 ret = WN_SUCCESS;
1536
1538
1539 TRACE("Returning %d\n", ret);
1540 return ret;
1541}
1542
1543static const WCHAR connectionType[] = { 'C','o','n','n','e','c','t','i','o','n','T','y','p','e',0 };
1544static const WCHAR providerName[] = { 'P','r','o','v','i','d','e','r','N','a','m','e',0 };
1545static const WCHAR remotePath[] = { 'R','e','m','o','t','e','P','a','t','h',0 };
1546
1547static WCHAR *get_reg_str(HKEY hkey, const WCHAR *value, DWORD *len)
1548{
1549 DWORD type;
1550 WCHAR *ret = NULL;
1551
1552 if (!RegQueryValueExW(hkey, value, NULL, &type, NULL, len) && type == REG_SZ)
1553 {
1554 if (!(ret = HeapAlloc(GetProcessHeap(), 0, *len))) return NULL;
1555 RegQueryValueExW(hkey, value, 0, 0, (BYTE *)ret, len);
1556 }
1557
1558 return ret;
1559}
1560
1561static DWORD _enumeratorRememberedW(PWNetEnumerator enumerator, DWORD* user_count,
1562 void* user_buffer, DWORD* user_size)
1563{
1564 HKEY registry, connection;
1565 WCHAR buffer[255];
1566 LONG size_left;
1567 DWORD index, ret, type, len, size, registry_size, full_size = 0, total_count;
1568 NETRESOURCEW * net_buffer = user_buffer;
1569 WCHAR * str, * registry_string;
1570
1571 /* we will do the work in a single loop, so here is some things:
1572 * we write netresource at the begin of the user buffer
1573 * we write strings at the end of the user buffer
1574 */
1575 size_left = *user_size;
1576 total_count = 0;
1577 type = enumerator->dwType;
1578 registry = enumerator->specific.remembered.registry;
1579 str = (WCHAR *)((ULONG_PTR)user_buffer + *user_size - sizeof(WCHAR));
1580 for (index = enumerator->specific.remembered.index; ; ++index)
1581 {
1582 enumerator->specific.remembered.index = index;
1583
1584 if (*user_count != -1 && total_count == *user_count)
1585 {
1586 ret = WN_SUCCESS;
1587 break;
1588 }
1589
1592 if (ret != ERROR_SUCCESS)
1593 {
1595 break;
1596 }
1597
1598 if (RegOpenKeyExW(registry, buffer, 0, KEY_READ, &connection) != ERROR_SUCCESS)
1599 {
1600 continue;
1601 }
1602
1603 full_size = sizeof(NETRESOURCEW);
1604 size_left -= sizeof(NETRESOURCEW);
1605
1606 if (size_left > 0)
1607 {
1608 size = sizeof(DWORD);
1609 RegQueryValueExW(connection, connectionType, NULL, NULL, (BYTE *)&net_buffer->dwType, &size);
1610 if (type != RESOURCETYPE_ANY && net_buffer->dwType != type)
1611 {
1612 size_left += sizeof(NETRESOURCEW);
1613 RegCloseKey(connection);
1614 continue;
1615 }
1616
1617 net_buffer->dwScope = RESOURCE_REMEMBERED;
1619 net_buffer->dwUsage = RESOURCEUSAGE_CONNECTABLE;
1620 }
1621 else
1622 ret = WN_MORE_DATA;
1623
1624 /* FIXME: this only supports drive letters */
1625 full_size += 3 * sizeof(WCHAR);
1626 size_left -= 3 * sizeof(WCHAR);
1627 if (size_left > 0)
1628 {
1629 str -= 3;
1630 str[0] = buffer[0];
1631 str[1] = ':';
1632 str[2] = 0;
1633 net_buffer->lpLocalName = str;
1634 }
1635
1636 registry_size = 0;
1637 registry_string = get_reg_str(connection, providerName, &registry_size);
1638 if (registry_string)
1639 {
1640 full_size += registry_size;
1641 size_left -= registry_size;
1642
1643 if (size_left > 0)
1644 {
1645 str -= (registry_size / sizeof(WCHAR));
1646 lstrcpyW(str, registry_string);
1647 net_buffer->lpProvider = str;
1648 }
1649 else
1650 ret = WN_MORE_DATA;
1651
1652 HeapFree(GetProcessHeap(), 0, registry_string);
1653 }
1654
1655 registry_size = 0;
1656 registry_string = get_reg_str(connection, remotePath, &registry_size);
1657 if (registry_string)
1658 {
1659 full_size += registry_size;
1660 size_left -= registry_size;
1661
1662 if (size_left > 0)
1663 {
1664 str -= (registry_size / sizeof(WCHAR));
1665 lstrcpyW(str, registry_string);
1666 net_buffer->lpRemoteName = str;
1667 }
1668 else
1669 ret = WN_MORE_DATA;
1670
1671 HeapFree(GetProcessHeap(), 0, registry_string);
1672 }
1673
1674 RegCloseKey(connection);
1675
1676 net_buffer->lpComment = NULL;
1677
1678 if (size_left < 0)
1679 break;
1680
1681 ++total_count;
1682 ++net_buffer;
1683 }
1684
1685 if (total_count == 0)
1687
1688 *user_count = total_count;
1689
1691 ret = WN_SUCCESS;
1692
1693 if (ret == WN_MORE_DATA)
1694 *user_size = *user_size + full_size;
1695
1696 return ret;
1697}
1698
1699/*********************************************************************
1700 * WNetEnumResourceW [MPR.@]
1701 */
1703 LPVOID lpBuffer, LPDWORD lpBufferSize )
1704{
1705 DWORD ret;
1706
1707 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize );
1708
1709 if (!hEnum)
1711 else if (!lpcCount)
1713 else if (!lpBuffer)
1715 else if (!lpBufferSize)
1717 else if (*lpBufferSize < sizeof(NETRESOURCEW))
1718 {
1719 *lpBufferSize = sizeof(NETRESOURCEW);
1720 ret = WN_MORE_DATA;
1721 }
1722 else
1723 {
1724 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1725
1726 switch (enumerator->enumType)
1727 {
1729 ret = _enumerateGlobalW(enumerator, lpcCount, lpBuffer,
1730 lpBufferSize);
1731 break;
1733 ret = _enumerateProviderW(enumerator, lpcCount, lpBuffer,
1734 lpBufferSize);
1735 break;
1737 ret = _enumerateContextW(enumerator, lpcCount, lpBuffer,
1738 lpBufferSize);
1739 break;
1741 ret = _enumerateConnectedW(enumerator, lpcCount, lpBuffer,
1742 lpBufferSize);
1743 break;
1745 ret = _enumeratorRememberedW(enumerator, lpcCount, lpBuffer,
1746 lpBufferSize);
1747 break;
1748 default:
1749 WARN("bogus enumerator type!\n");
1751 }
1752 }
1753 if (ret)
1755 TRACE("Returning %d\n", ret);
1756 return ret;
1757}
1758
1759/*********************************************************************
1760 * WNetCloseEnum [MPR.@]
1761 */
1763{
1764 DWORD ret, index;
1765 HANDLE *handles;
1766
1767 TRACE( "(%p)\n", hEnum );
1768
1769 if (hEnum)
1770 {
1771 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum;
1772
1773 switch (enumerator->enumType)
1774 {
1776 if (enumerator->specific.net)
1777 _freeEnumNetResource(enumerator->specific.net);
1778 if (enumerator->handle)
1779 providerTable->table[enumerator->providerIndex].
1780 closeEnum(enumerator->handle);
1781 ret = WN_SUCCESS;
1782 break;
1784 if (enumerator->handle)
1785 providerTable->table[enumerator->providerIndex].
1786 closeEnum(enumerator->handle);
1787 ret = WN_SUCCESS;
1788 break;
1790 handles = enumerator->specific.handles;
1791 for (index = 0; index < providerTable->numProviders; index++)
1792 {
1795 }
1797 ret = WN_SUCCESS;
1798 break;
1800 RegCloseKey(enumerator->specific.remembered.registry);
1801 ret = WN_SUCCESS;
1802 break;
1803 default:
1804 WARN("bogus enumerator type!\n");
1806 }
1807 HeapFree(GetProcessHeap(), 0, hEnum);
1808 }
1809 else
1811 if (ret)
1813 TRACE("Returning %d\n", ret);
1814 return ret;
1815}
1816
1817/*********************************************************************
1818 * WNetGetResourceInformationA [MPR.@]
1819 *
1820 * See WNetGetResourceInformationW
1821 */
1823 LPVOID lpBuffer, LPDWORD cbBuffer,
1824 LPSTR *lplpSystem )
1825{
1826 DWORD ret;
1827
1828 TRACE( "(%p, %p, %p, %p)\n",
1829 lpNetResource, lpBuffer, cbBuffer, lplpSystem );
1830
1833 else if (lpNetResource)
1834 {
1835 LPNETRESOURCEW lpNetResourceW = NULL;
1836 DWORD size = 1024, count = 1;
1837 DWORD len;
1838
1839 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size);
1840 ret = _thunkNetResourceArrayAToW(lpNetResource, &count, lpNetResourceW, &size);
1841 if (ret == WN_MORE_DATA)
1842 {
1843 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1844 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size);
1845 if (lpNetResourceW)
1846 ret = _thunkNetResourceArrayAToW(lpNetResource,
1847 &count, lpNetResourceW, &size);
1848 else
1850 }
1851 if (ret == WN_SUCCESS)
1852 {
1853 LPWSTR lpSystemW = NULL;
1854 LPVOID lpBufferW;
1855 size = 1024;
1856 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size);
1857 if (lpBufferW)
1858 {
1859 ret = WNetGetResourceInformationW(lpNetResourceW,
1860 lpBufferW, &size, &lpSystemW);
1861 if (ret == WN_MORE_DATA)
1862 {
1863 HeapFree(GetProcessHeap(), 0, lpBufferW);
1864 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size);
1865 if (lpBufferW)
1866 ret = WNetGetResourceInformationW(lpNetResourceW,
1867 lpBufferW, &size, &lpSystemW);
1868 else
1870 }
1871 if (ret == WN_SUCCESS)
1872 {
1873 ret = _thunkNetResourceArrayWToA(lpBufferW,
1874 &count, lpBuffer, cbBuffer);
1875 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1876 lpNetResourceW = lpBufferW;
1877 size = sizeof(NETRESOURCEA);
1878 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpRemoteName,
1879 -1, NULL, 0, NULL, NULL);
1880 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpProvider,
1881 -1, NULL, 0, NULL, NULL);
1882
1883 len = WideCharToMultiByte(CP_ACP, 0, lpSystemW,
1884 -1, NULL, 0, NULL, NULL);
1885 if ((len) && ( size + len < *cbBuffer))
1886 {
1887 *lplpSystem = (char*)lpBuffer + *cbBuffer - len;
1888 WideCharToMultiByte(CP_ACP, 0, lpSystemW, -1,
1889 *lplpSystem, len, NULL, NULL);
1890 ret = WN_SUCCESS;
1891 }
1892 else
1893 ret = WN_MORE_DATA;
1894 }
1895 else
1897 HeapFree(GetProcessHeap(), 0, lpBufferW);
1898 }
1899 else
1901 HeapFree(GetProcessHeap(), 0, lpSystemW);
1902 }
1903 HeapFree(GetProcessHeap(), 0, lpNetResourceW);
1904 }
1905 else
1907
1908 if (ret)
1910 TRACE("Returning %d\n", ret);
1911 return ret;
1912}
1913
1914/*********************************************************************
1915 * WNetGetResourceInformationW [MPR.@]
1916 *
1917 * WNetGetResourceInformationW function identifies the network provider
1918 * that owns the resource and gets information about the type of the resource.
1919 *
1920 * PARAMS:
1921 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1922 * defines a network resource.
1923 * lpBuffer [ O] the pointer to buffer, containing result. It
1924 * contains NETRESOURCEW structure and strings to
1925 * which the members of the NETRESOURCEW structure
1926 * point.
1927 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1928 * in bytes.
1929 * lplpSystem [ O] the pointer to string in the output buffer,
1930 * containing the part of the resource name without
1931 * names of the server and share.
1932 *
1933 * RETURNS:
1934 * NO_ERROR if the function succeeds. System error code if the function fails.
1935 */
1936
1938 LPVOID lpBuffer, LPDWORD cbBuffer,
1939 LPWSTR *lplpSystem )
1940{
1942 DWORD index;
1943
1944 TRACE( "(%p, %p, %p, %p)\n",
1945 lpNetResource, lpBuffer, cbBuffer, lplpSystem);
1946
1947 if (!(lpBuffer))
1949 else if (providerTable != NULL)
1950 {
1951 /* FIXME: For function value of a variable is indifferent, it does
1952 * search of all providers in a network.
1953 */
1954 for (index = 0; index < providerTable->numProviders; index++)
1955 {
1958 {
1961 lpNetResource, lpBuffer, cbBuffer, lplpSystem);
1962 else
1964 if (ret == WN_SUCCESS)
1965 break;
1966 }
1967 }
1968 }
1969 if (ret)
1971 return ret;
1972}
1973
1974/*********************************************************************
1975 * WNetGetResourceParentA [MPR.@]
1976 */
1978 LPVOID lpBuffer, LPDWORD lpBufferSize )
1979{
1980 FIXME( "(%p, %p, %p): stub\n",
1981 lpNetResource, lpBuffer, lpBufferSize );
1982
1984 return WN_NO_NETWORK;
1985}
1986
1987/*********************************************************************
1988 * WNetGetResourceParentW [MPR.@]
1989 */
1991 LPVOID lpBuffer, LPDWORD lpBufferSize )
1992{
1993 FIXME( "(%p, %p, %p): stub\n",
1994 lpNetResource, lpBuffer, lpBufferSize );
1995
1997 return WN_NO_NETWORK;
1998}
1999
2000
2001
2002/*
2003 * Connection Functions
2004 */
2005
2006/*********************************************************************
2007 * WNetAddConnectionA [MPR.@]
2008 */
2009DWORD WINAPI WNetAddConnectionA( LPCSTR lpRemoteName, LPCSTR lpPassword,
2010 LPCSTR lpLocalName )
2011{
2012 NETRESOURCEA resourcesA;
2013
2014 memset(&resourcesA, 0, sizeof(resourcesA));
2015 resourcesA.lpRemoteName = (LPSTR)lpRemoteName;
2016 resourcesA.lpLocalName = (LPSTR)lpLocalName;
2017 return WNetUseConnectionA(NULL, &resourcesA, lpPassword, NULL, 0, NULL, 0, NULL);
2018}
2019
2020/*********************************************************************
2021 * WNetAddConnectionW [MPR.@]
2022 */
2024 LPCWSTR lpLocalName )
2025{
2026 NETRESOURCEW resourcesW;
2027
2028 memset(&resourcesW, 0, sizeof(resourcesW));
2029 resourcesW.lpRemoteName = (LPWSTR)lpRemoteName;
2030 resourcesW.lpLocalName = (LPWSTR)lpLocalName;
2031 return WNetUseConnectionW(NULL, &resourcesW, lpPassword, NULL, 0, NULL, 0, NULL);
2032}
2033
2034/*********************************************************************
2035 * WNetAddConnection2A [MPR.@]
2036 */
2038 LPCSTR lpPassword, LPCSTR lpUserID,
2039 DWORD dwFlags )
2040{
2041 return WNetUseConnectionA(NULL, lpNetResource, lpPassword, lpUserID, dwFlags,
2042 NULL, 0, NULL);
2043}
2044
2045/*********************************************************************
2046 * WNetAddConnection2W [MPR.@]
2047 */
2049 LPCWSTR lpPassword, LPCWSTR lpUserID,
2050 DWORD dwFlags )
2051{
2052 return WNetUseConnectionW(NULL, lpNetResource, lpPassword, lpUserID, dwFlags,
2053 NULL, 0, NULL);
2054}
2055
2056/*********************************************************************
2057 * WNetAddConnection3A [MPR.@]
2058 */
2060 LPCSTR lpPassword, LPCSTR lpUserID,
2061 DWORD dwFlags )
2062{
2063 return WNetUseConnectionA(hwndOwner, lpNetResource, lpPassword, lpUserID,
2064 dwFlags, NULL, 0, NULL);
2065}
2066
2067/*********************************************************************
2068 * WNetAddConnection3W [MPR.@]
2069 */
2071 LPCWSTR lpPassword, LPCWSTR lpUserID,
2072 DWORD dwFlags )
2073{
2074 return WNetUseConnectionW(hwndOwner, lpNetResource, lpPassword, lpUserID,
2075 dwFlags, NULL, 0, NULL);
2076}
2077
2079{
2082 NETRESOURCEA *resourceA; /* only set for WNetUseConnectionA */
2091};
2092
2094{
2095 if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
2096 {
2097 DWORD len;
2098
2099 if (local_name)
2101 else
2103
2104 if (++len > *ctxt->buffer_size)
2105 {
2106 *ctxt->buffer_size = len;
2107 return ERROR_MORE_DATA;
2108 }
2109 }
2110 else
2111 ctxt->accessname = NULL;
2112
2113 return ERROR_SUCCESS;
2114}
2115
2117{
2118 WCHAR *accessname = ctxt->accessname;
2119 if (local_name)
2120 {
2122 if (ctxt->result)
2123 *ctxt->result = CONNECT_LOCALDRIVE;
2124 }
2125 else
2127}
2128
2129static DWORD wnet_use_provider( struct use_connection_context *ctxt, NETRESOURCEW * netres, WNetProvider *provider, BOOLEAN redirect )
2130{
2131 DWORD caps, ret;
2132
2133 caps = provider->getCaps(WNNC_CONNECTION);
2135 return ERROR_BAD_PROVIDER;
2136
2138 do
2139 {
2140 if ((caps & WNNC_CON_ADDCONNECTION3) && provider->addConnection3)
2141 ret = provider->addConnection3(ctxt->hwndOwner, netres, ctxt->password, ctxt->userid, ctxt->flags);
2142 else if ((caps & WNNC_CON_ADDCONNECTION) && provider->addConnection)
2143 ret = provider->addConnection(netres, ctxt->password, ctxt->userid);
2144
2145 if (ret == WN_ALREADY_CONNECTED && redirect)
2146 netres->lpLocalName[0] -= 1;
2147 } while (redirect && ret == WN_ALREADY_CONNECTED && netres->lpLocalName[0] >= 'C');
2148
2149 if (ret == WN_SUCCESS && ctxt->accessname)
2150 ctxt->set_accessname(ctxt, netres->lpLocalName);
2151
2152 return ret;
2153}
2154
2155static const WCHAR providerType[] = { 'P','r','o','v','i','d','e','r','T','y','p','e',0 };
2156static const WCHAR userName[] = { 'U','s','e','r','N','a','m','e',0 };
2157
2159{
2160 WNetProvider *provider = NULL;
2162 BOOL redirect = FALSE;
2163 WCHAR letter[3] = {'Z', ':', 0};
2164 NETRESOURCEW netres;
2165
2167 return WN_NO_NETWORK;
2168
2169 if (!ctxt->resource)
2171 netres = *ctxt->resource;
2172
2173 if (!netres.lpLocalName && (ctxt->flags & CONNECT_REDIRECT))
2174 {
2175 if (netres.dwType != RESOURCETYPE_DISK && netres.dwType != RESOURCETYPE_PRINT)
2176 return ERROR_BAD_DEV_TYPE;
2177
2178 if (netres.dwType == RESOURCETYPE_PRINT)
2179 {
2180 FIXME("Local device selection is not implemented for printers.\n");
2181 return WN_NO_NETWORK;
2182 }
2183
2184 redirect = TRUE;
2185 netres.lpLocalName = letter;
2186 }
2187
2188 if (ctxt->flags & CONNECT_INTERACTIVE)
2189 return ERROR_BAD_NET_NAME;
2190
2191 if ((ret = ctxt->pre_set_accessname(ctxt, netres.lpLocalName)))
2192 return ret;
2193
2194 if (netres.lpProvider)
2195 {
2198 return ERROR_BAD_PROVIDER;
2199
2200 provider = &providerTable->table[index];
2201 ret = wnet_use_provider(ctxt, &netres, provider, redirect);
2202 }
2203 else
2204 {
2205 for (index = 0; index < providerTable->numProviders; index++)
2206 {
2207 provider = &providerTable->table[index];
2208 ret = wnet_use_provider(ctxt, &netres, provider, redirect);
2210 break;
2211 }
2212 }
2213
2214 if (ret == WN_SUCCESS && ctxt->flags & CONNECT_UPDATE_PROFILE)
2215 {
2216 HKEY user_profile;
2217
2218 if (netres.dwType == RESOURCETYPE_PRINT)
2219 {
2220 FIXME("Persistent connection are not supported for printers\n");
2221 return ret;
2222 }
2223
2224 if (RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS)
2225 {
2226 HKEY network;
2227 WCHAR subkey[10] = {'N', 'e', 't', 'w', 'o', 'r', 'k', '\\', netres.lpLocalName[0], 0};
2228
2229 if (RegCreateKeyExW(user_profile, subkey, 0, NULL, REG_OPTION_NON_VOLATILE,
2231 {
2232 DWORD dword_arg = RESOURCETYPE_DISK;
2233 DWORD len = (lstrlenW(provider->name) + 1) * sizeof(WCHAR);
2234 static const WCHAR empty[1] = {0};
2235
2236 RegSetValueExW(network, connectionType, 0, REG_DWORD, (const BYTE *)&dword_arg, sizeof(DWORD));
2237 RegSetValueExW(network, providerName, 0, REG_SZ, (const BYTE *)provider->name, len);
2238 RegSetValueExW(network, providerType, 0, REG_DWORD, (const BYTE *)&provider->dwNetType, sizeof(DWORD));
2239 len = (lstrlenW(netres.lpRemoteName) + 1) * sizeof(WCHAR);
2241 len = sizeof(empty);
2244 }
2245
2246 RegCloseKey(user_profile);
2247 }
2248 }
2249
2250 return ret;
2251}
2252
2253/*****************************************************************
2254 * WNetUseConnectionW [MPR.@]
2255 */
2258{
2259 struct use_connection_context ctxt;
2260
2261 TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n",
2264
2265 ctxt.hwndOwner = hwndOwner;
2266 ctxt.resource = resource;
2267 ctxt.resourceA = NULL;
2268 ctxt.password = (WCHAR*)password;
2269 ctxt.userid = (WCHAR*)userid;
2270 ctxt.flags = flags;
2271 ctxt.accessname = accessname;
2272 ctxt.buffer_size = buffer_size;
2273 ctxt.result = result;
2276
2277 return wnet_use_connection(&ctxt);
2278}
2279
2281{
2282 if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
2283 {
2284 DWORD len;
2285
2286 if (local_name)
2287 len = WideCharToMultiByte(CP_ACP, 0, local_name, -1, NULL, 0, NULL, NULL) - 1;
2288 else
2289 len = strlen(ctxt->resourceA->lpRemoteName);
2290
2291 if (++len > *ctxt->buffer_size)
2292 {
2293 *ctxt->buffer_size = len;
2294 return ERROR_MORE_DATA;
2295 }
2296 }
2297 else
2298 ctxt->accessname = NULL;
2299
2300 return ERROR_SUCCESS;
2301}
2302
2304{
2305 char *accessname = ctxt->accessname;
2306 if (local_name)
2307 {
2309 if (ctxt->result)
2310 *ctxt->result = CONNECT_LOCALDRIVE;
2311 }
2312 else
2314}
2315
2317{
2318 LPWSTR ret;
2319 INT len;
2320
2321 if (!str) return NULL;
2322 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
2323 ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2324 if (ret) MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
2325 return ret;
2326}
2327
2329{
2330 resourceW->dwScope = resourceA->dwScope;
2331 resourceW->dwType = resourceA->dwType;
2333 resourceW->dwUsage = resourceA->dwUsage;
2336 resourceW->lpComment = strdupAtoW(resourceA->lpComment);
2338}
2339
2341{
2342 HeapFree(GetProcessHeap(), 0, resource->lpLocalName);
2343 HeapFree(GetProcessHeap(), 0, resource->lpRemoteName);
2344 HeapFree(GetProcessHeap(), 0, resource->lpComment);
2345 HeapFree(GetProcessHeap(), 0, resource->lpProvider);
2346}
2347
2348/*****************************************************************
2349 * WNetUseConnectionA [MPR.@]
2350 */
2354{
2355 struct use_connection_context ctxt;
2356 NETRESOURCEW resourceW;
2357 DWORD ret;
2358
2359 TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n", hwndOwner, resource, password, debugstr_a(userid), flags,
2361
2362 netresource_a_to_w(resource, &resourceW);
2363
2364 ctxt.hwndOwner = hwndOwner;
2365 ctxt.resource = &resourceW;
2366 ctxt.resourceA = resource;
2368 ctxt.userid = strdupAtoW(userid);
2369 ctxt.flags = flags;
2370 ctxt.accessname = accessname;
2371 ctxt.buffer_size = buffer_size;
2372 ctxt.result = result;
2375
2376 ret = wnet_use_connection(&ctxt);
2377
2378 free_netresourceW(&resourceW);
2379 HeapFree(GetProcessHeap(), 0, ctxt.password);
2380 HeapFree(GetProcessHeap(), 0, ctxt.userid);
2381
2382 return ret;
2383}
2384
2385/*********************************************************************
2386 * WNetCancelConnectionA [MPR.@]
2387 */
2389{
2390 return WNetCancelConnection2A(lpName, 0, fForce);
2391}
2392
2393/*********************************************************************
2394 * WNetCancelConnectionW [MPR.@]
2395 */
2397{
2398 return WNetCancelConnection2W(lpName, 0, fForce);
2399}
2400
2401/*********************************************************************
2402 * WNetCancelConnection2A [MPR.@]
2403 */
2405{
2406 DWORD ret;
2408 if (!name)
2409 return ERROR_NOT_CONNECTED;
2410
2413
2414 return ret;
2415}
2416
2417/*********************************************************************
2418 * WNetCancelConnection2W [MPR.@]
2419 */
2421{
2423 DWORD index;
2424
2425 if (providerTable != NULL)
2426 {
2427 for (index = 0; index < providerTable->numProviders; index++)
2428 {
2431 {
2434 else
2436 if (ret == WN_SUCCESS || ret == WN_OPEN_FILES)
2437 break;
2438 }
2439 }
2440 }
2441
2443 {
2444 HKEY user_profile;
2445
2446 /* FIXME: Only remove it if that's a drive letter */
2447 if (iswalpha(lpName[0]) && lpName[1] == ':' &&
2449 {
2450 WCHAR subkey[10] = {'N', 'e', 't', 'w', 'o', 'r', 'k', '\\', lpName[0], 0};
2451
2452 RegDeleteKeyW(user_profile, subkey);
2453
2454 RegCloseKey(user_profile);
2455 }
2456 }
2457
2458 return ret;
2459}
2460
2461/*****************************************************************
2462 * WNetRestoreConnectionA [MPR.@]
2463 */
2465{
2466 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_a(lpszDevice) );
2467
2469 return WN_NO_NETWORK;
2470}
2471
2472/*****************************************************************
2473 * WNetRestoreConnectionW [MPR.@]
2474 */
2476{
2477 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_w(lpszDevice) );
2478
2480 return WN_NO_NETWORK;
2481}
2482
2483/**************************************************************************
2484 * WNetGetConnectionA [MPR.@]
2485 *
2486 * RETURNS
2487 * - WN_BAD_LOCALNAME lpLocalName makes no sense
2488 * - WN_NOT_CONNECTED drive is a local drive
2489 * - WN_MORE_DATA buffer isn't big enough
2490 * - WN_SUCCESS success (net path in buffer)
2491 *
2492 * FIXME: need to test return values under different errors
2493 */
2495 LPSTR lpRemoteName, LPDWORD lpBufferSize )
2496{
2497 DWORD ret;
2498
2499 if (!lpLocalName)
2501 else if (!lpBufferSize)
2503 else if (!lpRemoteName && *lpBufferSize)
2505 else
2506 {
2507 int len = MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, NULL, 0);
2508
2509 if (len)
2510 {
2511 PWSTR wideLocalName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2512
2513 if (wideLocalName)
2514 {
2515 WCHAR wideRemoteStatic[MAX_PATH];
2516 DWORD wideRemoteSize = ARRAY_SIZE(wideRemoteStatic);
2517
2518 MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, wideLocalName, len);
2519
2520 /* try once without memory allocation */
2521 ret = WNetGetConnectionW(wideLocalName, wideRemoteStatic,
2522 &wideRemoteSize);
2523 if (ret == WN_SUCCESS)
2524 {
2525 int len = WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
2526 -1, NULL, 0, NULL, NULL);
2527
2528 if (len <= *lpBufferSize)
2529 {
2530 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, -1,
2531 lpRemoteName, *lpBufferSize, NULL, NULL);
2532 ret = WN_SUCCESS;
2533 }
2534 else
2535 {
2536 *lpBufferSize = len;
2537 ret = WN_MORE_DATA;
2538 }
2539 }
2540 else if (ret == WN_MORE_DATA)
2541 {
2542 PWSTR wideRemote = HeapAlloc(GetProcessHeap(), 0,
2543 wideRemoteSize * sizeof(WCHAR));
2544
2545 if (wideRemote)
2546 {
2547 ret = WNetGetConnectionW(wideLocalName, wideRemote,
2548 &wideRemoteSize);
2549 if (ret == WN_SUCCESS)
2550 {
2551 if (len <= *lpBufferSize)
2552 {
2553 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic,
2554 -1, lpRemoteName, *lpBufferSize, NULL, NULL);
2555 ret = WN_SUCCESS;
2556 }
2557 else
2558 {
2559 *lpBufferSize = len;
2560 ret = WN_MORE_DATA;
2561 }
2562 }
2563 HeapFree(GetProcessHeap(), 0, wideRemote);
2564 }
2565 else
2567 }
2568 HeapFree(GetProcessHeap(), 0, wideLocalName);
2569 }
2570 else
2572 }
2573 else
2575 }
2576 if (ret)
2578 TRACE("Returning %d\n", ret);
2579 return ret;
2580}
2581
2582/* find the network connection for a given drive; helper for WNetGetConnection */
2584{
2585#ifndef __REACTOS__
2586 char buffer[1024];
2587 struct mountmgr_unix_drive *data = (struct mountmgr_unix_drive *)buffer;
2588 HANDLE mgr;
2590 DWORD bytes_returned;
2591
2594 0, 0 )) == INVALID_HANDLE_VALUE)
2595 {
2596 ERR( "failed to open mount manager err %u\n", GetLastError() );
2597 return ret;
2598 }
2599 memset( data, 0, sizeof(*data) );
2600 data->letter = letter;
2601 if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, data, sizeof(*data),
2602 data, sizeof(buffer), &bytes_returned, NULL ))
2603 {
2604 char *p, *mount_point = buffer + data->mount_point_offset;
2605 DWORD len;
2606
2607 if (data->mount_point_offset && !strncmp( mount_point, "unc/", 4 ))
2608 {
2609 mount_point += 2;
2610 mount_point[0] = '\\';
2611 for (p = mount_point; *p; p++) if (*p == '/') *p = '\\';
2612
2613 len = MultiByteToWideChar( CP_UNIXCP, 0, mount_point, -1, NULL, 0 );
2614 if (len > *size)
2615 {
2616 *size = len;
2617 ret = WN_MORE_DATA;
2618 }
2619 else
2620 {
2621 *size = MultiByteToWideChar( CP_UNIXCP, 0, mount_point, -1, remote, *size);
2622 ret = WN_SUCCESS;
2623 }
2624 }
2625 }
2626 CloseHandle( mgr );
2627 return ret;
2628#else
2630 DWORD index;
2631 WCHAR local[3] = {letter, ':', 0};
2632
2633 if (providerTable != NULL)
2634 {
2635 for (index = 0; index < providerTable->numProviders; index++)
2636 {
2639 {
2640 if (providerTable->table[index].getConnection)
2641 ret = providerTable->table[index].getConnection(
2642 local, remote, size);
2643 else
2645 if (ret == WN_SUCCESS || ret == WN_MORE_DATA)
2646 break;
2647 }
2648 }
2649 }
2650 if (ret)
2652 return ret;
2653#endif
2654}
2655
2656/**************************************************************************
2657 * WNetGetConnectionW [MPR.@]
2658 *
2659 * FIXME: need to test return values under different errors
2660 */
2662 LPWSTR lpRemoteName, LPDWORD lpBufferSize )
2663{
2664 DWORD ret;
2665
2666 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName), lpRemoteName,
2667 lpBufferSize);
2668
2669 if (!lpLocalName)
2671 else if (!lpBufferSize)
2673 else if (!lpRemoteName && *lpBufferSize)
2675 else if (!lpLocalName[0])
2677 else
2678 {
2679 if (lpLocalName[1] == ':')
2680 {
2681 switch(GetDriveTypeW(lpLocalName))
2682 {
2683 case DRIVE_REMOTE:
2684 ret = get_drive_connection( lpLocalName[0], lpRemoteName, lpBufferSize );
2685 break;
2686 case DRIVE_REMOVABLE:
2687 case DRIVE_FIXED:
2688 case DRIVE_CDROM:
2689 TRACE("file is local\n");
2691 break;
2692 default:
2694 }
2695 }
2696 else
2698 }
2699 if (ret)
2701 TRACE("Returning %d\n", ret);
2702 return ret;
2703}
2704
2705/**************************************************************************
2706 * WNetSetConnectionA [MPR.@]
2707 */
2709 LPVOID pvValue )
2710{
2711 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName), dwProperty, pvValue );
2712
2714 return WN_NO_NETWORK;
2715}
2716
2717/**************************************************************************
2718 * WNetSetConnectionW [MPR.@]
2719 */
2721 LPVOID pvValue )
2722{
2723 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName), dwProperty, pvValue );
2724
2726 return WN_NO_NETWORK;
2727}
2728
2729/*****************************************************************
2730 * WNetGetUniversalNameA [MPR.@]
2731 */
2733 LPVOID lpBuffer, LPDWORD lpBufferSize )
2734{
2735 DWORD err, size;
2736
2737 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2738 debugstr_a(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
2739
2740 switch (dwInfoLevel)
2741 {
2743 {
2745
2746 if (GetDriveTypeA(lpLocalPath) != DRIVE_REMOTE)
2747 {
2749 break;
2750 }
2751
2752 size = sizeof(*info) + lstrlenA(lpLocalPath) + 1;
2753 if (*lpBufferSize < size)
2754 {
2755 err = WN_MORE_DATA;
2756 break;
2757 }
2758 info->lpUniversalName = (char *)info + sizeof(*info);
2759 lstrcpyA(info->lpUniversalName, lpLocalPath);
2760 err = WN_NO_ERROR;
2761 break;
2762 }
2765 break;
2766
2767 default:
2768 err = WN_BAD_VALUE;
2769 break;
2770 }
2771
2773 return err;
2774}
2775
2776/*****************************************************************
2777 * WNetGetUniversalNameW [MPR.@]
2778 */
2780 LPVOID lpBuffer, LPDWORD lpBufferSize )
2781{
2782 DWORD err, size;
2783
2784 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2785 debugstr_w(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize);
2786
2787 switch (dwInfoLevel)
2788 {
2790 {
2792
2793 if (GetDriveTypeW(lpLocalPath) != DRIVE_REMOTE)
2794 {
2796 break;
2797 }
2798
2799 size = sizeof(*info) + (lstrlenW(lpLocalPath) + 1) * sizeof(WCHAR);
2800 if (*lpBufferSize < size)
2801 {
2802 *lpBufferSize = size;
2803 err = WN_MORE_DATA;
2804 break;
2805 }
2806 info->lpUniversalName = (LPWSTR)((char *)info + sizeof(*info));
2807 lstrcpyW(info->lpUniversalName, lpLocalPath);
2808 err = WN_NO_ERROR;
2809 break;
2810 }
2813 break;
2814
2815 default:
2816 err = WN_BAD_VALUE;
2817 break;
2818 }
2819
2821 return err;
2822}
2823
2824/*****************************************************************
2825 * WNetClearConnections [MPR.@]
2826 */
2828{
2830 PWSTR connection;
2831 DWORD ret, size, count;
2832 NETRESOURCEW * resources, * iter;
2833
2835 if (ret != WN_SUCCESS)
2836 {
2837 if (ret != WN_NO_NETWORK)
2838 {
2839 return ret;
2840 }
2841
2842 /* Means no provider, then, clearing is OK */
2843 return WN_SUCCESS;
2844 }
2845
2846 size = 0x1000;
2848 if (!resources)
2849 {
2851 return WN_OUT_OF_MEMORY;
2852 }
2853
2854 for (;;)
2855 {
2856 size = 0x1000;
2857 count = -1;
2858
2859 memset(resources, 0, size);
2861 if (ret == WN_SUCCESS || ret == WN_MORE_DATA)
2862 {
2863 for (iter = resources; count; count--, iter++)
2864 {
2865 if (iter->lpLocalName && iter->lpLocalName[0])
2866 connection = iter->lpLocalName;
2867 else
2868 connection = iter->lpRemoteName;
2869
2870 WNetCancelConnection2W(connection, 0, TRUE);
2871 }
2872 }
2873 else
2874 break;
2875 }
2876
2879
2880 return ret;
2881}
2882
2883
2884/*
2885 * Other Functions
2886 */
2887
2888/**************************************************************************
2889 * WNetGetUserA [MPR.@]
2890 *
2891 * FIXME: we should not return ourselves, but the owner of the drive lpName
2892 */
2894{
2895 if (GetUserNameA( lpUserID, lpBufferSize )) return WN_SUCCESS;
2896 return GetLastError();
2897}
2898
2899/*****************************************************************
2900 * WNetGetUserW [MPR.@]
2901 *
2902 * FIXME: we should not return ourselves, but the owner of the drive lpName
2903 */
2905{
2906 if (GetUserNameW( lpUserID, lpBufferSize )) return WN_SUCCESS;
2907 return GetLastError();
2908}
2909
2910/*********************************************************************
2911 * WNetConnectionDialog [MPR.@]
2912 */
2914{
2915 CONNECTDLGSTRUCTW conn_dlg;
2916 NETRESOURCEW net_res;
2917
2918 ZeroMemory(&conn_dlg, sizeof(conn_dlg));
2919 ZeroMemory(&net_res, sizeof(net_res));
2920
2921 conn_dlg.cbStructure = sizeof(conn_dlg);
2922 conn_dlg.lpConnRes = &net_res;
2923 conn_dlg.hwndOwner = hwnd;
2924 net_res.dwType = dwType;
2925
2926 return WNetConnectionDialog1W(&conn_dlg);
2927}
2928
2929/*********************************************************************
2930 * WNetConnectionDialog1A [MPR.@]
2931 */
2933{
2934 FIXME( "(%p): stub\n", lpConnDlgStruct );
2935
2937 return WN_NO_NETWORK;
2938}
2939
2940/*********************************************************************
2941 * WNetConnectionDialog1W [MPR.@]
2942 */
2944{
2945 FIXME( "(%p): stub\n", lpConnDlgStruct );
2946
2948 return WN_NO_NETWORK;
2949}
2950
2951/*********************************************************************
2952 * WNetDisconnectDialog [MPR.@]
2953 */
2955{
2956#ifdef __REACTOS__
2957 DWORD dwRet;
2958 HMODULE hDll = LoadLibraryW(L"netplwiz.dll");
2959 static BOOL (WINAPI *pSHDisconnectNetDrives)(PVOID);
2960 pSHDisconnectNetDrives = (VOID *) GetProcAddress(hDll, "SHDisconnectNetDrives");
2961
2962 dwRet = pSHDisconnectNetDrives(NULL);
2963
2964 FreeLibrary(hDll);
2965 return dwRet;
2966#else
2967 FIXME( "(%p, %08X): stub\n", hwnd, dwType );
2968
2970 return WN_NO_NETWORK;
2971#endif
2972}
2973
2974/*********************************************************************
2975 * WNetDisconnectDialog1A [MPR.@]
2976 */
2978{
2979 FIXME( "(%p): stub\n", lpConnDlgStruct );
2980
2982 return WN_NO_NETWORK;
2983}
2984
2985/*********************************************************************
2986 * WNetDisconnectDialog1W [MPR.@]
2987 */
2989{
2990 FIXME( "(%p): stub\n", lpConnDlgStruct );
2991
2993 return WN_NO_NETWORK;
2994}
2995
2996/*********************************************************************
2997 * WNetGetLastErrorA [MPR.@]
2998 */
3000 LPSTR lpErrorBuf, DWORD nErrorBufSize,
3001 LPSTR lpNameBuf, DWORD nNameBufSize )
3002{
3003 FIXME( "(%p, %p, %d, %p, %d): stub\n",
3004 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
3005
3007 return WN_NO_NETWORK;
3008}
3009
3010/*********************************************************************
3011 * WNetGetLastErrorW [MPR.@]
3012 */
3014 LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3015 LPWSTR lpNameBuf, DWORD nNameBufSize )
3016{
3017 FIXME( "(%p, %p, %d, %p, %d): stub\n",
3018 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize );
3019
3021 return WN_NO_NETWORK;
3022}
3023
3024/*********************************************************************
3025 * WNetGetNetworkInformationA [MPR.@]
3026 */
3028 LPNETINFOSTRUCT lpNetInfoStruct )
3029{
3030 DWORD ret;
3031
3032 TRACE( "(%s, %p)\n", debugstr_a(lpProvider), lpNetInfoStruct );
3033
3034 if (!lpProvider)
3036 else
3037 {
3038 int len;
3039
3040 len = MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, NULL, 0);
3041 if (len)
3042 {
3043 LPWSTR wideProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3044
3045 if (wideProvider)
3046 {
3047 MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, wideProvider,
3048 len);
3049 ret = WNetGetNetworkInformationW(wideProvider, lpNetInfoStruct);
3050 HeapFree(GetProcessHeap(), 0, wideProvider);
3051 }
3052 else
3054 }
3055 else
3056 ret = GetLastError();
3057 }
3058 if (ret)
3060 TRACE("Returning %d\n", ret);
3061 return ret;
3062}
3063
3064/*********************************************************************
3065 * WNetGetNetworkInformationW [MPR.@]
3066 */
3068 LPNETINFOSTRUCT lpNetInfoStruct )
3069{
3070 DWORD ret;
3071
3072 TRACE( "(%s, %p)\n", debugstr_w(lpProvider), lpNetInfoStruct );
3073
3074 if (!lpProvider)
3076 else if (!lpNetInfoStruct)
3078 else if (lpNetInfoStruct->cbStructure < sizeof(NETINFOSTRUCT))
3079 ret = WN_BAD_VALUE;
3080 else
3081 {
3083 {
3084 DWORD providerIndex = _findProviderIndexW(lpProvider);
3085
3086 if (providerIndex != BAD_PROVIDER_INDEX)
3087 {
3088 lpNetInfoStruct->cbStructure = sizeof(NETINFOSTRUCT);
3089 lpNetInfoStruct->dwProviderVersion =
3090 providerTable->table[providerIndex].dwSpecVersion;
3091 lpNetInfoStruct->dwStatus = NO_ERROR;
3092 lpNetInfoStruct->dwCharacteristics = 0;
3093 lpNetInfoStruct->dwHandle = 0;
3094 lpNetInfoStruct->wNetType =
3095 HIWORD(providerTable->table[providerIndex].dwNetType);
3096 lpNetInfoStruct->dwPrinters = -1;
3097 lpNetInfoStruct->dwDrives = -1;
3098 ret = WN_SUCCESS;
3099 }
3100 else
3102 }
3103 else
3105 }
3106 if (ret)
3108 TRACE("Returning %d\n", ret);
3109 return ret;
3110}
3111
3112/*****************************************************************
3113 * WNetGetProviderNameA [MPR.@]
3114 */
3116 LPSTR lpProvider, LPDWORD lpBufferSize )
3117{
3118 DWORD ret;
3119
3120 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_a(lpProvider),
3121 lpBufferSize);
3122
3123 if (!lpProvider)
3125 else if (!lpBufferSize)
3127 else
3128 {
3129 if (providerTable)
3130 {
3131 DWORD i;
3132
3134 for (i = 0; i < providerTable->numProviders &&
3135 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
3136 i++)
3137 ;
3138 if (i < providerTable->numProviders)
3139 {
3140 DWORD sizeNeeded = WideCharToMultiByte(CP_ACP, 0,
3141 providerTable->table[i].name, -1, NULL, 0, NULL, NULL);
3142
3143 if (*lpBufferSize < sizeNeeded)
3144 {
3145 *lpBufferSize = sizeNeeded;
3146 ret = WN_MORE_DATA;
3147 }
3148 else
3149 {
3151 -1, lpProvider, *lpBufferSize, NULL, NULL);
3152 ret = WN_SUCCESS;
3153 /* FIXME: is *lpBufferSize set to the number of characters
3154 * copied? */
3155 }
3156 }
3157 }
3158 else
3160 }
3161 if (ret)
3163 TRACE("Returning %d\n", ret);
3164 return ret;
3165}
3166
3167/*****************************************************************
3168 * WNetGetProviderNameW [MPR.@]
3169 */
3171 LPWSTR lpProvider, LPDWORD lpBufferSize )
3172{
3173 DWORD ret;
3174
3175 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_w(lpProvider),
3176 lpBufferSize);
3177
3178 if (!lpProvider)
3180 else if (!lpBufferSize)
3182 else
3183 {
3184 if (providerTable)
3185 {
3186 DWORD i;
3187
3189 for (i = 0; i < providerTable->numProviders &&
3190 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType);
3191 i++)
3192 ;
3193 if (i < providerTable->numProviders)
3194 {
3195 DWORD sizeNeeded = lstrlenW(providerTable->table[i].name) + 1;
3196
3197 if (*lpBufferSize < sizeNeeded)
3198 {
3199 *lpBufferSize = sizeNeeded;
3200 ret = WN_MORE_DATA;
3201 }
3202 else
3203 {
3204 lstrcpyW(lpProvider, providerTable->table[i].name);
3205 ret = WN_SUCCESS;
3206 /* FIXME: is *lpBufferSize set to the number of characters
3207 * copied? */
3208 }
3209 }
3210 }
3211 else
3213 }
3214 if (ret)
3216 TRACE("Returning %d\n", ret);
3217 return ret;
3218}
unsigned char BOOLEAN
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:33
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define RegCloseKey(hKey)
Definition: registry.h:49
const char ** registry
Definition: cffdrivr.c:690
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:175
#define NO_ERROR
Definition: dderror.h:5
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegOpenCurrentUser(IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3209
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1239
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
BOOL WINAPI GetUserNameW(LPWSTR lpszName, LPDWORD lpSize)
Definition: misc.c:291
BOOL WINAPI GetUserNameA(LPSTR lpszName, LPDWORD lpSize)
Definition: misc.c:246
static struct list providers
Definition: sip.c:564
static const WCHAR empty[]
Definition: main.c:47
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define CP_UNIXCP
Definition: compat.h:79
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define FreeLibrary(x)
Definition: compat.h:748
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CreateFileW
Definition: compat.h:741
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define LoadLibraryW(x)
Definition: compat.h:747
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
#define swprintf
Definition: precomp.h:40
static BSTR local_name(call_frame_t *frame, int ref)
Definition: engine.c:187
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define local
Definition: zutil.h:30
int connected
Definition: main.c:61
FxCmResList * resources
FxAutoRegKey hKey
size_t bufferSize
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define iswalpha(_c)
Definition: ctype.h:664
#define resource
Definition: kernel32.h:9
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define REG_SZ
Definition: layer.c:22
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define DRIVE_CDROM
Definition: machpc98.h:119
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static WCHAR password[]
Definition: url.c:33
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:37
#define IDS_ENTIRENETWORK
Definition: mprres.h:24
DWORD APIENTRY NPEnumResource(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: nfs41_np.c:773
DWORD APIENTRY NPGetCaps(DWORD nIndex)
Definition: nfs41_np.c:329
DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
Definition: nfs41_np.c:881
DWORD APIENTRY NPGetResourceInformation(__in LPNETRESOURCE lpNetResource, __out_bcount(*lpBufferSize) LPVOID lpBuffer, __inout LPDWORD lpBufferSize, __deref_out LPWSTR *lplpSystem)
Definition: nfs41_np.c:900
DWORD APIENTRY NPAddConnection(__in LPNETRESOURCE lpNetResource, __in_opt LPWSTR lpPassword, __in_opt LPWSTR lpUserName)
Definition: nfs41_np.c:419
DWORD APIENTRY NPOpenEnum(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCE lpNetResource, LPHANDLE lphEnum)
Definition: nfs41_np.c:729
DWORD APIENTRY NPGetConnection(__in LPWSTR lpLocalName, __out_bcount(*lpBufferSize) LPWSTR lpRemoteName, __inout LPDWORD lpBufferSize)
Definition: nfs41_np.c:674
DWORD APIENTRY NPCancelConnection(__in LPWSTR lpName, __in BOOL fForce)
Definition: nfs41_np.c:580
DWORD APIENTRY NPAddConnection3(__in HWND hwndOwner, __in LPNETRESOURCE lpNetResource, __in_opt LPWSTR lpPassword, __in_opt LPWSTR lpUserName, __in DWORD dwFlags)
Definition: nfs41_np.c:428
#define WNNC_NET_TYPE
Definition: npapi.h:24
#define WNNC_CON_GETCONNECTIONS
Definition: npapi.h:35
DWORD(APIENTRY * PF_NPEnumResource)(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: npapi.h:68
#define WNNC_DLG_GETRESOURCEINFORMATION
Definition: npapi.h:45
DWORD(APIENTRY * PF_NPGetConnection)(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
Definition: npapi.h:81
DWORD(APIENTRY * PF_NPAddConnection)(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
Definition: npapi.h:75
#define WNNC_DIALOG
Definition: npapi.h:38
DWORD(APIENTRY * PF_NPOpenEnum)(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum)
Definition: npapi.h:66
DWORD(APIENTRY * PF_NPGetCaps)(DWORD ndex)
Definition: npapi.h:59
#define WNNC_CON_CANCELCONNECTION
Definition: npapi.h:34
#define WNNC_CONNECTION
Definition: npapi.h:32
#define WNNC_ENUM_CONTEXT
Definition: npapi.h:54
#define WNNC_CON_ADDCONNECTION
Definition: npapi.h:33
#define WNNC_CON_ADDCONNECTION3
Definition: npapi.h:36
#define WNNC_SPEC_VERSION
Definition: npapi.h:22
DWORD(APIENTRY * PF_NPGetResourceInformation)(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPWSTR *lplpSystem)
Definition: npapi.h:71
#define WNNC_ENUM_GLOBAL
Definition: npapi.h:52
DWORD(APIENTRY * PF_NPAddConnection3)(HWND hwndOwner, LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
Definition: npapi.h:77
DWORD(APIENTRY * PF_NPCancelConnection)(LPWSTR lpName, BOOL fForce)
Definition: npapi.h:80
#define WNNC_ENUM_LOCAL
Definition: npapi.h:53
DWORD(APIENTRY * PF_NPCloseEnum)(HANDLE hEnum)
Definition: npapi.h:70
#define WNNC_ENUMERATION
Definition: npapi.h:51
#define BOOL
Definition: nt_native.h:43
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_READ
Definition: nt_native.h:1023
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define DWORD
Definition: nt_native.h:44
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
#define strlenW(s)
Definition: unicode.h:34
#define strcpyW(d, s)
Definition: unicode.h:35
#define err(...)
const WCHAR * str
#define REG_DWORD
Definition: sdbapi.c:596
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
LPNETRESOURCEW lpConnRes
Definition: winnetwk.h:196
DWORD cbStructure
Definition: winnetwk.h:227
DWORD dwProviderVersion
Definition: winnetwk.h:228
DWORD dwPrinters
Definition: winnetwk.h:233
DWORD dwDrives
Definition: winnetwk.h:234
DWORD dwCharacteristics
Definition: winnetwk.h:230
ULONG_PTR dwHandle
Definition: winnetwk.h:231
DWORD dwStatus
Definition: winnetwk.h:229
LPSTR lpLocalName
Definition: winnetwk.h:171
DWORD dwDisplayType
Definition: winnetwk.h:169
LPSTR lpComment
Definition: winnetwk.h:173
DWORD dwScope
Definition: winnetwk.h:167
LPSTR lpProvider
Definition: winnetwk.h:174
LPSTR lpRemoteName
Definition: winnetwk.h:172
DWORD dwUsage
Definition: winnetwk.h:170
DWORD dwType
Definition: winnetwk.h:168
DWORD dwType
Definition: winnetwk.h:178
DWORD dwDisplayType
Definition: winnetwk.h:179
LPWSTR lpComment
Definition: winnetwk.h:183
DWORD dwUsage
Definition: winnetwk.h:180
DWORD dwScope
Definition: winnetwk.h:177
LPWSTR lpLocalName
Definition: winnetwk.h:181
LPWSTR lpProvider
Definition: winnetwk.h:184
LPWSTR lpRemoteName
Definition: winnetwk.h:182
DWORD dwUsage
Definition: wnet.c:109
NETRESOURCEW * net
Definition: wnet.c:112
DWORD providerIndex
Definition: wnet.c:104
HKEY registry
Definition: wnet.c:116
DWORD dwType
Definition: wnet.c:108
DWORD dwScope
Definition: wnet.c:107
BOOL providerDone
Definition: wnet.c:106
DWORD index
Definition: wnet.c:117
union _WNetEnumerator::@473 specific
DWORD enumType
Definition: wnet.c:103
struct _WNetEnumerator::@473::@474 remembered
HANDLE * handles
Definition: wnet.c:113
HANDLE handle
Definition: wnet.c:105
LPWSTR entireNetwork
Definition: wnet.c:74
DWORD numAllocated
Definition: wnet.c:75
DWORD numProviders
Definition: wnet.c:76
WNetProvider table[1]
Definition: wnet.c:77
PF_NPOpenEnum openEnum
Definition: wnet.c:60
PF_NPAddConnection3 addConnection3
Definition: wnet.c:65
PF_NPCancelConnection cancelConnection
Definition: wnet.c:66
DWORD dwNetType
Definition: wnet.c:58
DWORD dwEnumScopes
Definition: wnet.c:59
PWSTR name
Definition: wnet.c:55
PF_NPCloseEnum closeEnum
Definition: wnet.c:62
PF_NPGetResourceInformation getResourceInformation
Definition: wnet.c:63
PF_NPEnumResource enumResource
Definition: wnet.c:61
PF_NPAddConnection addConnection
Definition: wnet.c:64
DWORD dwSpecVersion
Definition: wnet.c:57
HMODULE hLib
Definition: wnet.c:54
PF_NPGetCaps getCaps
Definition: wnet.c:56
Definition: name.c:39
DWORD * buffer_size
Definition: wnet.c:2087
void(* set_accessname)(struct use_connection_context *, WCHAR *)
Definition: wnet.c:2090
DWORD(* pre_set_accessname)(struct use_connection_context *, WCHAR *)
Definition: wnet.c:2089
NETRESOURCEA * resourceA
Definition: wnet.c:2082
NETRESOURCEW * resource
Definition: wnet.c:2081
#define max(a, b)
Definition: svc.c:63
static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
Definition: swimpl.c:888
data1 network
Definition: tftpd.cpp:49
char serviceName[]
Definition: tftpd.cpp:34
static TNetwork net
Definition: tncon.cpp:351
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
void * PVOID
Definition: typedefs.h:50
uint32_t * LPDWORD
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define HIWORD(l)
Definition: typedefs.h:247
static EFI_HANDLE * handles
Definition: uefidisk.c:62
Definition: pdh_main.c:94
int ret
#define ZeroMemory
Definition: winbase.h:1712
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define DRIVE_REMOTE
Definition: winbase.h:253
_In_ LPCSTR lpName
Definition: winbase.h:2789
#define DRIVE_FIXED
Definition: winbase.h:252
#define DRIVE_REMOVABLE
Definition: winbase.h:251
#define FreeModule(m)
Definition: winbase.h:2033
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define WINAPI
Definition: msvc.h:6
#define ERROR_BAD_DEV_TYPE
Definition: winerror.h:158
#define ERROR_BAD_PROVIDER
Definition: winerror.h:707
#define ERROR_NOT_CONNECTED
Definition: winerror.h:1201
#define ERROR_BAD_NET_NAME
Definition: winerror.h:159
#define WN_NOT_SUPPORTED
Definition: winnetwk.h:113
#define WN_BAD_LOCALNAME
Definition: winnetwk.h:136
#define RESOURCE_CONNECTED
Definition: winnetwk.h:58
#define CONNECT_INTERACTIVE
Definition: winnetwk.h:90
#define CONNECT_REDIRECT
Definition: winnetwk.h:94
struct _NETRESOURCEA * LPNETRESOURCEA
#define RESOURCEUSAGE_CONNECTABLE
Definition: winnetwk.h:68
#define RESOURCEDISPLAYTYPE_ROOT
Definition: winnetwk.h:82
#define WN_OUT_OF_MEMORY
Definition: winnetwk.h:125
#define WN_ALREADY_CONNECTED
Definition: winnetwk.h:137
#define RESOURCE_CONTEXT
Definition: winnetwk.h:62
#define WN_NO_ERROR
Definition: winnetwk.h:112
#define RESOURCEDISPLAYTYPE_GENERIC
Definition: winnetwk.h:75
#define CONNECT_UPDATE_PROFILE
Definition: winnetwk.h:87
#define REMOTE_NAME_INFO_LEVEL
Definition: winnetwk.h:152
struct _NETRESOURCEA NETRESOURCEA
#define RESOURCETYPE_DISK
Definition: winnetwk.h:64
#define WN_NOT_CONNECTED
Definition: winnetwk.h:132
#define WN_BAD_PROVIDER
Definition: winnetwk.h:141
struct _NETRESOURCEW NETRESOURCEW
#define UNIVERSAL_NAME_INFO_LEVEL
Definition: winnetwk.h:151
#define WN_MORE_DATA
Definition: winnetwk.h:117
#define CONNECT_LOCALDRIVE
Definition: winnetwk.h:95
#define WN_SUCCESS
Definition: winnetwk.h:111
#define RESOURCE_REMEMBERED
Definition: winnetwk.h:60
#define WN_OPEN_FILES
Definition: winnetwk.h:133
#define RESOURCETYPE_PRINT
Definition: winnetwk.h:65
struct _NETINFOSTRUCT NETINFOSTRUCT
#define WN_BAD_POINTER
Definition: winnetwk.h:118
#define RESOURCEDISPLAYTYPE_NETWORK
Definition: winnetwk.h:81
#define WN_NO_NETWORK
Definition: winnetwk.h:126
#define RESOURCEUSAGE_CONTAINER
Definition: winnetwk.h:69
#define WN_NO_MORE_ENTRIES
Definition: winnetwk.h:146
#define WN_BAD_HANDLE
Definition: winnetwk.h:129
#define WN_BAD_VALUE
Definition: winnetwk.h:119
#define RESOURCEUSAGE_RESERVED
Definition: winnetwk.h:74
#define WN_ACCESS_DENIED
Definition: winnetwk.h:122
#define RESOURCETYPE_ANY
Definition: winnetwk.h:63
struct _NETRESOURCEW * LPNETRESOURCEW
#define RESOURCE_GLOBALNET
Definition: winnetwk.h:59
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define RegQueryInfoKey
Definition: winreg.h:521
_In_ DWORD dwInfoLevel
Definition: winsvc.h:422
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
static PWNetEnumerator _createConnectedEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage)
Definition: wnet.c:621
DWORD WINAPI WNetRestoreConnectionW(HWND hwndOwner, LPCWSTR lpszDevice)
Definition: wnet.c:2475
DWORD WINAPI WNetRestoreConnectionA(HWND hwndOwner, LPCSTR lpszDevice)
Definition: wnet.c:2464
DWORD WINAPI WNetGetResourceParentA(LPNETRESOURCEA lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1977
DWORD WINAPI WNetAddConnectionA(LPCSTR lpRemoteName, LPCSTR lpPassword, LPCSTR lpLocalName)
Definition: wnet.c:2009
static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet)
Definition: wnet.c:529
DWORD WINAPI WNetCancelConnection2A(LPCSTR lpName, DWORD dwFlags, BOOL fForce)
Definition: wnet.c:2404
static const WCHAR remotePath[]
Definition: wnet.c:1545
DWORD WINAPI WNetDisconnectDialog1A(LPDISCDLGSTRUCTA lpConnDlgStruct)
Definition: wnet.c:2977
DWORD WINAPI WNetClearConnections(HWND owner)
Definition: wnet.c:2827
DWORD WINAPI WNetUseConnectionA(HWND hwndOwner, NETRESOURCEA *resource, LPCSTR password, LPCSTR userid, DWORD flags, LPSTR accessname, DWORD *buffer_size, DWORD *result)
Definition: wnet.c:2351
#define WNET_ENUMERATOR_TYPE_CONNECTED
Definition: wnet.c:83
static WCHAR * get_reg_str(HKEY hkey, const WCHAR *value, DWORD *len)
Definition: wnet.c:1547
static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn, const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:662
static void free_netresourceW(NETRESOURCEW *resource)
Definition: wnet.c:2340
static void _tryLoadProvider(PCWSTR provider)
Definition: wnet.c:135
static DWORD wnet_use_provider(struct use_connection_context *ctxt, NETRESOURCEW *netres, WNetProvider *provider, BOOLEAN redirect)
Definition: wnet.c:2129
DWORD WINAPI WNetConnectionDialog(HWND hwnd, DWORD dwType)
Definition: wnet.c:2913
static PWNetProviderTable providerTable
Definition: wnet.c:129
static PWNetEnumerator _createRememberedEnumerator(DWORD dwScope, DWORD dwType, HKEY remembered)
Definition: wnet.c:641
static DWORD _enumerateConnectedW(PWNetEnumerator enumerator, DWORD *user_count, void *user_buffer, DWORD *user_size)
Definition: wnet.c:1438
DWORD WINAPI WNetSetConnectionA(LPCSTR lpName, DWORD dwProperty, LPVOID pvValue)
Definition: wnet.c:2708
DWORD WINAPI WNetConnectionDialog1A(LPCONNECTDLGSTRUCTA lpConnDlgStruct)
Definition: wnet.c:2932
DWORD WINAPI WNetUseConnectionW(HWND hwndOwner, NETRESOURCEW *resource, LPCWSTR password, LPCWSTR userid, DWORD flags, LPWSTR accessname, DWORD *buffer_size, DWORD *result)
Definition: wnet.c:2256
DWORD WINAPI WNetGetConnectionA(LPCSTR lpLocalName, LPSTR lpRemoteName, LPDWORD lpBufferSize)
Definition: wnet.c:2494
static PWNetEnumerator _createProviderEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage, DWORD index, HANDLE handle)
Definition: wnet.c:582
DWORD WINAPI WNetAddConnection2W(LPNETRESOURCEW lpNetResource, LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2048
DWORD WINAPI WNetAddConnection2A(LPNETRESOURCEA lpNetResource, LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2037
#define MPR_GETPROC(proc)
#define WNET_ENUMERATOR_TYPE_PROVIDER
Definition: wnet.c:81
static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1276
DWORD WINAPI WNetGetProviderNameA(DWORD dwNetType, LPSTR lpProvider, LPDWORD lpBufferSize)
Definition: wnet.c:3115
static void netresource_a_to_w(NETRESOURCEA *resourceA, NETRESOURCEW *resourceW)
Definition: wnet.c:2328
DWORD WINAPI WNetConnectionDialog1W(LPCONNECTDLGSTRUCTW lpConnDlgStruct)
Definition: wnet.c:2943
DWORD WINAPI WNetGetResourceParentW(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1990
DWORD WINAPI WNetCancelConnectionW(LPCWSTR lpName, BOOL fForce)
Definition: wnet.c:2396
DWORD WINAPI WNetGetResourceInformationA(LPNETRESOURCEA lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPSTR *lplpSystem)
Definition: wnet.c:1822
#define WNET_ENUMERATOR_TYPE_GLOBAL
Definition: wnet.c:80
static void _freeEnumNetResource(LPNETRESOURCEW lpNet)
Definition: wnet.c:556
DWORD WINAPI WNetOpenEnumA(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEA lpNet, LPHANDLE lphEnum)
Definition: wnet.c:830
static DWORD _enumeratorRememberedW(PWNetEnumerator enumerator, DWORD *user_count, void *user_buffer, DWORD *user_size)
Definition: wnet.c:1561
static DWORD use_connection_pre_set_accessnameA(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2280
struct _WNetEnumerator WNetEnumerator
struct _WNetProviderTable * PWNetProviderTable
static PWNetEnumerator _createGlobalEnumeratorW(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNet)
Definition: wnet.c:565
DWORD WINAPI WNetEnumResourceA(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1052
static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator)
Definition: wnet.c:1194
DWORD WINAPI WNetGetLastErrorW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize, LPWSTR lpNameBuf, DWORD nNameBufSize)
Definition: wnet.c:3013
static PWNetEnumerator _createContextEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage)
Definition: wnet.c:605
static LPWSTR strdupAtoW(LPCSTR str)
Definition: wnet.c:2316
static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn, const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:747
DWORD WINAPI WNetGetConnectionW(LPCWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpBufferSize)
Definition: wnet.c:2661
static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:1118
static const WCHAR providerName[]
Definition: wnet.c:1544
struct _WNetProviderTable WNetProviderTable
DWORD WINAPI WNetGetNetworkInformationW(LPCWSTR lpProvider, LPNETINFOSTRUCT lpNetInfoStruct)
Definition: wnet.c:3067
DWORD WINAPI WNetGetNetworkInformationA(LPCSTR lpProvider, LPNETINFOSTRUCT lpNetInfoStruct)
Definition: wnet.c:3027
struct _WNetProvider WNetProvider
DWORD WINAPI WNetGetResourceInformationW(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPWSTR *lplpSystem)
Definition: wnet.c:1937
DWORD WINAPI WNetAddConnection3W(HWND hwndOwner, LPNETRESOURCEW lpNetResource, LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2070
static void use_connection_set_accessnameA(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2303
DWORD WINAPI WNetDisconnectDialog(HWND hwnd, DWORD dwType)
Definition: wnet.c:2954
#define WNET_ENUMERATOR_TYPE_REMEMBERED
Definition: wnet.c:84
DWORD WINAPI WNetCancelConnectionA(LPCSTR lpName, BOOL fForce)
Definition: wnet.c:2388
DWORD WINAPI WNetAddConnectionW(LPCWSTR lpRemoteName, LPCWSTR lpPassword, LPCWSTR lpLocalName)
Definition: wnet.c:2023
DWORD WINAPI WNetAddConnection3A(HWND hwndOwner, LPNETRESOURCEA lpNetResource, LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2059
DWORD WINAPI WNetEnumResourceW(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1702
DWORD WINAPI WNetGetProviderNameW(DWORD dwNetType, LPWSTR lpProvider, LPDWORD lpBufferSize)
Definition: wnet.c:3170
static DWORD use_connection_pre_set_accessnameW(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2093
DWORD WINAPI WNetCloseEnum(HANDLE hEnum)
Definition: wnet.c:1762
DWORD WINAPI WNetGetUserW(LPCWSTR lpName, LPWSTR lpUserID, LPDWORD lpBufferSize)
Definition: wnet.c:2904
struct _WNetEnumerator * PWNetEnumerator
void wnetFree(void)
Definition: wnet.c:492
DWORD WINAPI WNetCancelConnection2W(LPCWSTR lpName, DWORD dwFlags, BOOL fForce)
Definition: wnet.c:2420
static const WCHAR userName[]
Definition: wnet.c:2156
static void use_connection_set_accessnameW(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2116
#define WNET_ENUMERATOR_TYPE_CONTEXT
Definition: wnet.c:82
DWORD WINAPI WNetDisconnectDialog1W(LPDISCDLGSTRUCTW lpConnDlgStruct)
Definition: wnet.c:2988
static const WCHAR providerType[]
Definition: wnet.c:2155
DWORD WINAPI WNetOpenEnumW(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNet, LPHANDLE lphEnum)
Definition: wnet.c:922
static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1318
static const WCHAR connectionType[]
Definition: wnet.c:1543
static DWORD _countProviderBytesW(PWNetProvider provider)
Definition: wnet.c:1104
static DWORD _findProviderIndexW(LPCWSTR lpProvider)
Definition: wnet.c:509
void wnetInit(HINSTANCE hInstDll)
Definition: wnet.c:354
struct _WNetProvider * PWNetProvider
DWORD WINAPI WNetGetUserA(LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize)
Definition: wnet.c:2893
static DWORD get_drive_connection(WCHAR letter, LPWSTR remote, LPDWORD size)
Definition: wnet.c:2583
#define BAD_PROVIDER_INDEX
Definition: wnet.c:122
static DWORD _copyStringToEnumW(const WCHAR *source, DWORD *left, void **end)
Definition: wnet.c:1420
DWORD WINAPI WNetGetUniversalNameW(LPCWSTR lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:2779
DWORD WINAPI WNetSetConnectionW(LPCWSTR lpName, DWORD dwProperty, LPVOID pvValue)
Definition: wnet.c:2720
DWORD WINAPI WNetGetLastErrorA(LPDWORD lpError, LPSTR lpErrorBuf, DWORD nErrorBufSize, LPSTR lpNameBuf, DWORD nNameBufSize)
Definition: wnet.c:2999
DWORD WINAPI WNetGetUniversalNameA(LPCSTR lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:2732
static DWORD wnet_use_connection(struct use_connection_context *ctxt)
Definition: wnet.c:2158
static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1343
static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1238
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193