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