ReactOS  0.4.15-dev-488-gc7a1924
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  */
50 typedef struct _WNetProvider
51 {
65 #ifdef __REACTOS__
66  PF_NPGetConnection getConnection;
67 #endif
69 
70 typedef 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  */
99 typedef struct _WNetEnumerator
100 {
108  union
109  {
112  struct
113  {
116  } remembered;
117  } specific;
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  */
125 static DWORD _findProviderIndexW(LPCWSTR lpProvider);
126 
128 
129 /*
130  * Global provider table functions
131  */
132 
133 static 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);
145  serviceName[ARRAY_SIZE(serviceName) - 1] = '\0';
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,
172  (LPBYTE)name, &size) != ERROR_SUCCESS || type != REG_SZ)
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));
266  RegCloseKey(hKey);
267  }
268  else
269  WARN("Couldn't open service key for provider %s\n",
270  debugstr_w(provider));
271 }
272 
273 #ifdef __REACTOS__
274 static 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);
313  if (index == BAD_PROVIDER_INDEX)
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 
345 cleanup:
346  HeapFree(GetProcessHeap(), 0, net.lpProvider);
347  HeapFree(GetProcessHeap(), 0, net.lpRemoteName);
348  HeapFree(GetProcessHeap(), 0, net.lpLocalName);
349 }
350 #endif
351 
352 void 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  }
394  providerTable =
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  }
428  RegCloseKey(hKey);
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  {
438  HKEY network;
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 
490 void 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 &&
516  ret == BAD_PROVIDER_INDEX; i++)
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  {
558  HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName);
559  HeapFree(GetProcessHeap(), 0, lpNet);
560  }
561 }
562 
564  DWORD dwUsage, LPNETRESOURCEW lpNet)
565 {
568 
569  if (ret)
570  {
571  ret->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
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  {
611  ret->enumType = WNET_ENUMERATOR_TYPE_CONTEXT;
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;
629  ret->specific.handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HANDLE) * providerTable->numProviders);
630  if (!ret->specific.handles)
631  {
632  HeapFree(GetProcessHeap(), 0, ret);
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  */
660 static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn,
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  {
700  LPNETRESOURCEA lpNetOut = (LPNETRESOURCEA)lpBuffer + i;
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  */
745 static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn,
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  {
785  LPNETRESOURCEW lpNetOut = (LPNETRESOURCEW)lpBuffer + i;
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  */
828 DWORD 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;
841  ret = WN_NO_NETWORK;
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)
878  SetLastError(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  */
920 DWORD 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;
933  ret = WN_NO_NETWORK;
934  }
935  else
936  {
937  switch (dwScope)
938  {
939  case RESOURCE_GLOBALNET:
940  if (lpNet)
941  {
942  if (lpNet->lpProvider)
943  {
945 
946  if (index != BAD_PROVIDER_INDEX)
947  {
950  {
951  HANDLE handle;
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;
1017  case RESOURCE_REMEMBERED:
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)
1042  SetLastError(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)
1058  ret = WN_BAD_POINTER;
1059  else if (!lpcCount)
1060  ret = WN_BAD_POINTER;
1061  else if (!lpBuffer)
1062  ret = WN_BAD_POINTER;
1063  else if (!lpBufferSize)
1064  ret = WN_BAD_POINTER;
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)
1097  SetLastError(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;
1162  resource->dwUsage = RESOURCEUSAGE_CONTAINER |
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 
1274 static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount,
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 
1316 static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount,
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 
1341 static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount,
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  */
1394  enumerator->enumType = WNET_ENUMERATOR_TYPE_GLOBAL;
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));
1429  memcpy(local, source, len);
1430  *left -= len;
1431  *end = local;
1432 
1433  return WN_SUCCESS;
1434 }
1435 
1436 static 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;
1532  if (ret != WN_MORE_DATA && ret != WN_NO_MORE_ENTRIES)
1533  ret = WN_SUCCESS;
1534 
1536 
1537  TRACE("Returning %d\n", ret);
1538  return ret;
1539 }
1540 
1541 static const WCHAR connectionType[] = { 'C','o','n','n','e','c','t','i','o','n','T','y','p','e',0 };
1542 static const WCHAR providerName[] = { 'P','r','o','v','i','d','e','r','N','a','m','e',0 };
1543 static const WCHAR remotePath[] = { 'R','e','m','o','t','e','P','a','t','h',0 };
1544 
1545 static 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 
1559 static 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 
1588  len = ARRAY_SIZE(buffer);
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 
1688  if (ret != WN_MORE_DATA && ret != WN_NO_MORE_ENTRIES)
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)
1708  ret = WN_BAD_POINTER;
1709  else if (!lpcCount)
1710  ret = WN_BAD_POINTER;
1711  else if (!lpBuffer)
1712  ret = WN_BAD_POINTER;
1713  else if (!lpBufferSize)
1714  ret = WN_BAD_POINTER;
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");
1748  ret = WN_NO_NETWORK;
1749  }
1750  }
1751  if (ret)
1752  SetLastError(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");
1803  ret = WN_BAD_HANDLE;
1804  }
1805  HeapFree(GetProcessHeap(), 0, hEnum);
1806  }
1807  else
1808  ret = WN_BAD_HANDLE;
1809  if (ret)
1810  SetLastError(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 
1830  ret = WN_NO_NETWORK;
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
1904  ret = WN_NO_NETWORK;
1905 
1906  if (ret)
1907  SetLastError(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
1961  ret = WN_NO_NETWORK;
1962  if (ret == WN_SUCCESS)
1963  break;
1964  }
1965  }
1966  }
1967  if (ret)
1968  SetLastError(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  */
2007 DWORD 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  */
2021 DWORD WINAPI WNetAddConnectionW( LPCWSTR lpRemoteName, LPCWSTR lpPassword,
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 */
2084  void *accessname;
2089 };
2090 
2092 {
2093  if (ctxt->accessname && ctxt->buffer_size && *ctxt->buffer_size)
2094  {
2095  DWORD len;
2096 
2097  if (local_name)
2098  len = lstrlenW(local_name);
2099  else
2100  len = lstrlenW(ctxt->resource->lpRemoteName);
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 
2127 static 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 
2153 static const WCHAR providerType[] = { 'P','r','o','v','i','d','e','r','T','y','p','e',0 };
2154 static 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)
2168  return ERROR_INVALID_PARAMETER;
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  {
2195  if (index == BAD_PROVIDER_INDEX)
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);
2207  if (ret == WN_SUCCESS || ret == WN_ALREADY_CONNECTED)
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);
2238  RegSetValueExW(network, remotePath, 0, REG_SZ, (const BYTE *)netres.lpRemoteName, len);
2239  len = sizeof(empty);
2240  RegSetValueExW(network, userName, 0, REG_SZ, (const BYTE *)empty, len);
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;
2330  resourceW->dwDisplayType = resourceA->dwDisplayType;
2331  resourceW->dwUsage = resourceA->dwUsage;
2334  resourceW->lpComment = strdupAtoW(resourceA->lpComment);
2335  resourceW->lpProvider = strdupAtoW(resourceA->lpProvider);
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;
2365  ctxt.password = strdupAtoW(password);
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;
2405  WCHAR * name = strdupAtoW(lpName);
2406  if (!name)
2407  return ERROR_NOT_CONNECTED;
2408 
2409  ret = WNetCancelConnection2W(name, dwFlags, fForce);
2410  HeapFree(GetProcessHeap(), 0, name);
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
2433  ret = WN_NO_NETWORK;
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] == ':' &&
2446  RegOpenCurrentUser(KEY_ALL_ACCESS, &user_profile) == ERROR_SUCCESS)
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)
2498  ret = WN_BAD_POINTER;
2499  else if (!lpBufferSize)
2500  ret = WN_BAD_POINTER;
2501  else if (!lpRemoteName && *lpBufferSize)
2502  ret = WN_BAD_POINTER;
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)
2575  SetLastError(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];
2585  struct mountmgr_unix_drive *data = (struct mountmgr_unix_drive *)buffer;
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
2642  ret = WN_NO_NETWORK;
2643  if (ret == WN_SUCCESS || ret == WN_MORE_DATA)
2644  break;
2645  }
2646  }
2647  }
2648  if (ret)
2649  SetLastError(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)
2668  ret = WN_BAD_POINTER;
2669  else if (!lpBufferSize)
2670  ret = WN_BAD_POINTER;
2671  else if (!lpRemoteName && *lpBufferSize)
2672  ret = WN_BAD_POINTER;
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)
2698  SetLastError(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 
2770  SetLastError(err);
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  }
2810  err = WN_NO_NETWORK;
2811  break;
2812 
2813  default:
2814  err = WN_BAD_VALUE;
2815  break;
2816  }
2817 
2818  if (err != WN_NO_ERROR) SetLastError(err);
2819  return err;
2820 }
2821 
2822 /*****************************************************************
2823  * WNetClearConnections [MPR.@]
2824  */
2826 {
2827  HANDLE connected;
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  */
2891 DWORD WINAPI WNetGetUserA( LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize )
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)
3033  ret = WN_BAD_POINTER;
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)
3057  SetLastError(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)
3073  ret = WN_BAD_POINTER;
3074  else if (!lpNetInfoStruct)
3075  ret = WN_BAD_POINTER;
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
3099  ret = WN_BAD_PROVIDER;
3100  }
3101  else
3102  ret = WN_NO_NETWORK;
3103  }
3104  if (ret)
3105  SetLastError(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)
3122  ret = WN_BAD_POINTER;
3123  else if (!lpBufferSize)
3124  ret = WN_BAD_POINTER;
3125  else
3126  {
3127  if (providerTable)
3128  {
3129  DWORD i;
3130 
3131  ret = WN_NO_NETWORK;
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
3157  ret = WN_NO_NETWORK;
3158  }
3159  if (ret)
3160  SetLastError(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)
3177  ret = WN_BAD_POINTER;
3178  else if (!lpBufferSize)
3179  ret = WN_BAD_POINTER;
3180  else
3181  {
3182  if (providerTable)
3183  {
3184  DWORD i;
3185 
3186  ret = WN_NO_NETWORK;
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
3210  ret = WN_NO_NETWORK;
3211  }
3212  if (ret)
3213  SetLastError(ret);
3214  TRACE("Returning %d\n", ret);
3215  return ret;
3216 }
DWORD WINAPI WNetDisconnectDialog1W(LPDISCDLGSTRUCTW lpConnDlgStruct)
Definition: wnet.c:2986
static const WCHAR providerType[]
Definition: wnet.c:2153
PF_NPOpenEnum openEnum
Definition: wnet.c:58
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
DWORD APIENTRY NPGetResourceInformation(__in LPNETRESOURCE lpNetResource, __out_bcount(*lpBufferSize) LPVOID lpBuffer, __inout LPDWORD lpBufferSize, __deref_out LPWSTR *lplpSystem)
Definition: nfs41_np.c:898
DWORD WINAPI WNetSetConnectionA(LPCSTR lpName, DWORD dwProperty, LPVOID pvValue)
Definition: wnet.c:2706
static struct list providers
Definition: sip.c:564
struct _NETRESOURCEW NETRESOURCEW
#define WNNC_CON_ADDCONNECTION3
Definition: npapi.h:36
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
DWORD WINAPI WNetGetNetworkInformationA(LPCSTR lpProvider, LPNETINFOSTRUCT lpNetInfoStruct)
Definition: wnet.c:3025
struct _WNetProvider * PWNetProvider
DWORD dwDrives
Definition: winnetwk.h:234
const uint16_t * PCWSTR
Definition: typedefs.h:56
static void _freeEnumNetResource(LPNETRESOURCEW lpNet)
Definition: wnet.c:554
#define ERROR_BAD_PROVIDER
Definition: winerror.h:707
PWSTR name
Definition: wnet.c:53
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 max(a, b)
Definition: svc.c:63
DWORD WINAPI WNetGetResourceInformationW(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPWSTR *lplpSystem)
Definition: wnet.c:1935
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
DWORD dwType
Definition: winnetwk.h:168
PF_NPEnumResource enumResource
Definition: wnet.c:59
#define CloseHandle
Definition: compat.h:407
#define RESOURCEUSAGE_CONNECTABLE
Definition: winnetwk.h:68
#define CONNECT_UPDATE_PROFILE
Definition: winnetwk.h:87
UINT WINAPI GetDriveTypeA(IN LPCSTR lpRootPathName)
Definition: disk.c:468
#define WNNC_SPEC_VERSION
Definition: npapi.h:22
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
DWORD WINAPI WNetAddConnectionA(LPCSTR lpRemoteName, LPCSTR lpPassword, LPCSTR lpLocalName)
Definition: wnet.c:2007
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static struct object_header ** handles
Definition: handle.c:45
#define RegQueryInfoKey
Definition: winreg.h:521
DWORD WINAPI WNetGetConnectionW(LPCWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpBufferSize)
Definition: wnet.c:2659
DWORD dwScope
Definition: wnet.c:105
#define ERROR_SUCCESS
Definition: deptool.c:10
PF_NPAddConnection addConnection
Definition: wnet.c:62
DWORD WINAPI WNetDisconnectDialog1A(LPDISCDLGSTRUCTA lpConnDlgStruct)
Definition: wnet.c:2975
#define WideCharToMultiByte
Definition: compat.h:101
DWORD * buffer_size
Definition: wnet.c:2085
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
DWORD numProviders
Definition: wnet.c:74
HKEY registry
Definition: wnet.c:114
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
#define WN_SUCCESS
Definition: winnetwk.h:111
static PWNetProviderTable providerTable
Definition: wnet.c:127
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
DWORD WINAPI WNetGetProviderNameA(DWORD dwNetType, LPSTR lpProvider, LPDWORD lpBufferSize)
Definition: wnet.c:3113
static const WCHAR remotePath[]
Definition: wnet.c:1543
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define KEY_READ
Definition: nt_native.h:1023
#define WNNC_ENUMERATION
Definition: npapi.h:51
struct _WNetEnumerator * PWNetEnumerator
uint16_t * PWSTR
Definition: typedefs.h:55
DWORD dwProviderVersion
Definition: winnetwk.h:228
static DWORD _copyStringToEnumW(const WCHAR *source, DWORD *left, void **end)
Definition: wnet.c:1418
#define CP_ACP
Definition: compat.h:99
DWORD providerIndex
Definition: wnet.c:102
static PWNetEnumerator _createContextEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage)
Definition: wnet.c:603
static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet)
Definition: wnet.c:527
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
DWORD WINAPI WNetDisconnectDialog(HWND hwnd, DWORD dwType)
Definition: wnet.c:2952
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define ERROR_BAD_NET_NAME
Definition: winerror.h:159
#define IDS_ENTIRENETWORK
Definition: mprres.h:24
#define WARN(fmt,...)
Definition: debug.h:112
NETRESOURCEW * net
Definition: wnet.c:110
#define WNNC_CON_ADDCONNECTION
Definition: npapi.h:33
DWORD enumType
Definition: wnet.c:101
LONG WINAPI RegDeleteKeyW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey)
Definition: reg.c:1237
_In_ LPCSTR lpName
Definition: winbase.h:2752
LPSTR lpLocalName
Definition: winnetwk.h:171
#define RESOURCEUSAGE_RESERVED
Definition: winnetwk.h:74
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD(APIENTRY * PF_NPEnumResource)(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: npapi.h:68
#define ZeroMemory
Definition: winbase.h:1648
#define iswalpha(_c)
Definition: ctype.h:664
GLuint buffer
Definition: glext.h:5915
static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1341
DWORD(APIENTRY * PF_NPAddConnection)(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
Definition: npapi.h:75
GLuint GLuint end
Definition: gl.h:1545
#define WN_NOT_SUPPORTED
Definition: winnetwk.h:113
struct _NETRESOURCEA * LPNETRESOURCEA
#define WN_NOT_CONNECTED
Definition: winnetwk.h:132
DWORD dwUsage
Definition: wnet.c:107
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
struct _WNetEnumerator::@461::@462 remembered
struct _NETRESOURCEA NETRESOURCEA
DWORD dwDisplayType
Definition: winnetwk.h:169
DWORD WINAPI WNetAddConnectionW(LPCWSTR lpRemoteName, LPCWSTR lpPassword, LPCWSTR lpLocalName)
Definition: wnet.c:2021
int resource
Definition: rdpsnd_sgi.c:44
#define WNNC_DLG_GETRESOURCEINFORMATION
Definition: npapi.h:45
char * LPSTR
Definition: xmlstorage.h:182
static void use_connection_set_accessnameW(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2114
#define NO_ERROR
Definition: dderror.h:5
#define lstrlenW
Definition: compat.h:416
#define BOOL
Definition: nt_native.h:43
DWORD APIENTRY NPOpenEnum(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCE lpNetResource, LPHANDLE lphEnum)
Definition: nfs41_np.c:727
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:57
DWORD(APIENTRY * PF_NPGetConnection)(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
Definition: npapi.h:81
#define WN_NO_ERROR
Definition: winnetwk.h:112
#define WNNC_NET_TYPE
Definition: npapi.h:24
#define WN_BAD_VALUE
Definition: winnetwk.h:119
#define FILE_SHARE_READ
Definition: compat.h:125
#define DRIVE_REMOVABLE
Definition: winbase.h:248
#define IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
Definition: mountmgr.h:16
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:1091
DWORD WINAPI WNetCancelConnectionA(LPCSTR lpName, BOOL fForce)
Definition: wnet.c:2386
#define RESOURCEUSAGE_CONTAINER
Definition: winnetwk.h:69
#define RESOURCE_GLOBALNET
Definition: winnetwk.h:59
uint32_t ULONG_PTR
Definition: typedefs.h:64
static PWNetEnumerator _createGlobalEnumeratorW(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNet)
Definition: wnet.c:563
#define WN_ALREADY_CONNECTED
Definition: winnetwk.h:137
static PWNetEnumerator _createProviderEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage, DWORD index, HANDLE handle)
Definition: wnet.c:580
#define RESOURCE_CONNECTED
Definition: winnetwk.h:58
DWORD dwPrinters
Definition: winnetwk.h:233
DWORD dwStatus
Definition: winnetwk.h:229
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
WNetProvider table[1]
Definition: wnet.c:75
static DWORD _countProviderBytesW(PWNetProvider provider)
Definition: wnet.c:1102
struct _WNetProvider WNetProvider
#define DRIVE_REMOTE
Definition: winbase.h:250
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
static unsigned char bytes[4]
Definition: adnsresfilter.c:74
#define CONNECT_INTERACTIVE
Definition: winnetwk.h:90
#define DRIVE_CDROM
Definition: machpc98.h:115
DWORD WINAPI WNetAddConnection2A(LPNETRESOURCEA lpNetResource, LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2035
unsigned int BOOL
Definition: ntddk_ex.h:94
#define BAD_PROVIDER_INDEX
Definition: wnet.c:120
long LONG
Definition: pedump.c:60
#define WNET_ENUMERATOR_TYPE_GLOBAL
Definition: wnet.c:78
#define GENERIC_WRITE
Definition: nt_native.h:90
static struct resource resources[16]
static PWNetEnumerator _createConnectedEnumerator(DWORD dwScope, DWORD dwType, DWORD dwUsage)
Definition: wnet.c:619
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:111
LPWSTR entireNetwork
Definition: wnet.c:72
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
LPNETRESOURCEW lpConnRes
Definition: winnetwk.h:196
DWORD dwCharacteristics
Definition: winnetwk.h:230
static PVOID ptr
Definition: dispmode.c:27
#define RESOURCEDISPLAYTYPE_NETWORK
Definition: winnetwk.h:81
DWORD WINAPI WNetGetUserA(LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize)
Definition: wnet.c:2891
static void buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
Definition: swimpl.c:888
DWORD WINAPI WNetCancelConnection2A(LPCSTR lpName, DWORD dwFlags, BOOL fForce)
Definition: wnet.c:2402
DWORD WINAPI WNetGetLastErrorW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize, LPWSTR lpNameBuf, DWORD nNameBufSize)
Definition: wnet.c:3011
static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1316
DWORD APIENTRY NPCancelConnection(__in LPWSTR lpName, __in BOOL fForce)
Definition: nfs41_np.c:578
const WCHAR * str
struct _WNetProviderTable * PWNetProviderTable
unsigned char BOOLEAN
struct _NETRESOURCEW * LPNETRESOURCEW
#define LoadLibraryW(x)
Definition: compat.h:413
smooth NULL
Definition: ftsmooth.c:416
struct _NETINFOSTRUCT NETINFOSTRUCT
DWORD WINAPI WNetRestoreConnectionA(HWND hwndOwner, LPCSTR lpszDevice)
Definition: wnet.c:2462
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:11
DWORD WINAPI WNetAddConnection2W(LPNETRESOURCEW lpNetResource, LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2046
DWORD dwDisplayType
Definition: winnetwk.h:179
DWORD WINAPI WNetGetLastErrorA(LPDWORD lpError, LPSTR lpErrorBuf, DWORD nErrorBufSize, LPSTR lpNameBuf, DWORD nNameBufSize)
Definition: wnet.c:2997
#define WNET_ENUMERATOR_TYPE_CONNECTED
Definition: wnet.c:81
DWORD WINAPI WNetOpenEnumA(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEA lpNet, LPHANDLE lphEnum)
Definition: wnet.c:828
DWORD APIENTRY NPEnumResource(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: nfs41_np.c:771
const char ** registry
Definition: cffdrivr.c:690
GLuint index
Definition: glext.h:6031
const char * LPCSTR
Definition: xmlstorage.h:183
void * PVOID
Definition: retypes.h:9
data1 network
Definition: tftpd.cpp:49
#define ERROR_NOT_CONNECTED
Definition: winerror.h:1201
#define OPEN_EXISTING
Definition: compat.h:435
static WCHAR * get_reg_str(HKEY hkey, const WCHAR *value, DWORD *len)
Definition: wnet.c:1545
LPSTR lpProvider
Definition: winnetwk.h:174
static const WCHAR connectionType[]
Definition: wnet.c:1541
PF_NPCancelConnection cancelConnection
Definition: wnet.c:64
static DWORD _findProviderIndexW(LPCWSTR lpProvider)
Definition: wnet.c:507
NETRESOURCEW * resource
Definition: wnet.c:2079
DWORD dwScope
Definition: winnetwk.h:167
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define ERROR_BAD_DEV_TYPE
Definition: winerror.h:158
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:4895
PF_NPGetCaps getCaps
Definition: wnet.c:54
LPWSTR lpLocalName
Definition: winnetwk.h:181
char serviceName[]
Definition: tftpd.cpp:34
static PWNetEnumerator _createRememberedEnumerator(DWORD dwScope, DWORD dwType, HKEY remembered)
Definition: wnet.c:639
HANDLE * handles
Definition: wnet.c:111
BOOL WINAPI GetUserNameW(LPWSTR lpszName, LPDWORD lpSize)
Definition: misc.c:291
#define TRACE(s)
Definition: solgame.cpp:4
#define FreeLibrary(x)
Definition: compat.h:414
GLsizeiptr size
Definition: glext.h:5919
#define FreeModule(m)
Definition: winbase.h:1985
DWORD WINAPI WNetConnectionDialog1A(LPCONNECTDLGSTRUCTA lpConnDlgStruct)
Definition: wnet.c:2930
#define GetProcessHeap()
Definition: compat.h:404
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
void wnetFree(void)
Definition: wnet.c:490
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4116
#define CP_UNIXCP
Definition: compat.h:69
PF_NPCloseEnum closeEnum
Definition: wnet.c:60
#define CONNECT_REDIRECT
Definition: winnetwk.h:94
__wchar_t WCHAR
Definition: xmlstorage.h:180
DWORD(* pre_set_accessname)(struct use_connection_context *, WCHAR *)
Definition: wnet.c:2087
#define debugstr_a
Definition: kernel32.h:31
DWORD WINAPI WNetGetUserW(LPCWSTR lpName, LPWSTR lpUserID, LPDWORD lpBufferSize)
Definition: wnet.c:2902
HMODULE hLib
Definition: wnet.c:52
static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:1116
#define WN_NO_NETWORK
Definition: winnetwk.h:126
DWORD WINAPI WNetEnumResourceW(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1700
BOOL providerDone
Definition: wnet.c:104
void wnetInit(HINSTANCE hInstDll)
Definition: wnet.c:352
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
static DWORD wnet_use_connection(struct use_connection_context *ctxt)
Definition: wnet.c:2156
#define WINAPI
Definition: msvc.h:6
DWORD WINAPI WNetGetConnectionA(LPCSTR lpLocalName, LPSTR lpRemoteName, LPDWORD lpBufferSize)
Definition: wnet.c:2492
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
#define RESOURCEDISPLAYTYPE_GENERIC
Definition: winnetwk.h:75
#define REMOTE_NAME_INFO_LEVEL
Definition: winnetwk.h:152
#define WNNC_DIALOG
Definition: npapi.h:38
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WNNC_ENUM_LOCAL
Definition: npapi.h:53
GLint left
Definition: glext.h:7726
WINE_DEFAULT_DEBUG_CHANNEL(mpr)
DWORD dwSpecVersion
Definition: wnet.c:55
DWORD WINAPI WNetGetUniversalNameA(LPCSTR lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:2730
static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1274
#define RESOURCE_CONTEXT
Definition: winnetwk.h:62
#define WNNC_CONNECTION
Definition: npapi.h:32
#define SetLastError(x)
Definition: compat.h:418
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
DWORD WINAPI WNetAddConnection3W(HWND hwndOwner, LPNETRESOURCEW lpNetResource, LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2068
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
GLbitfield flags
Definition: glext.h:7161
static void free_netresourceW(NETRESOURCEW *resource)
Definition: wnet.c:2338
DWORD WINAPI WNetSetConnectionW(LPCWSTR lpName, DWORD dwProperty, LPVOID pvValue)
Definition: wnet.c:2718
static DWORD use_connection_pre_set_accessnameA(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2278
DWORD WINAPI WNetGetUniversalNameW(LPCWSTR lpLocalPath, DWORD dwInfoLevel, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:2777
LPSTR lpComment
Definition: winnetwk.h:173
DWORD(APIENTRY * PF_NPGetCaps)(DWORD ndex)
Definition: npapi.h:59
PF_NPGetResourceInformation getResourceInformation
Definition: wnet.c:61
DWORD dwEnumScopes
Definition: wnet.c:57
int ret
DWORD(APIENTRY * PF_NPCancelConnection)(LPWSTR lpName, BOOL fForce)
Definition: npapi.h:80
#define index(s, c)
Definition: various.h:29
DWORD dwUsage
Definition: winnetwk.h:170
static const WCHAR L[]
Definition: oid.c:1250
static void use_connection_set_accessnameA(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2301
DWORD APIENTRY NPGetConnection(__in LPWSTR lpLocalName, __out_bcount(*lpBufferSize) LPWSTR lpRemoteName, __inout LPDWORD lpBufferSize)
Definition: nfs41_np.c:672
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
static void netresource_a_to_w(NETRESOURCEA *resourceA, NETRESOURCEW *resourceW)
Definition: wnet.c:2326
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
struct _WNetProviderTable WNetProviderTable
#define WNET_ENUMERATOR_TYPE_CONTEXT
Definition: wnet.c:80
DWORD WINAPI WNetGetResourceInformationA(LPNETRESOURCEA lpNetResource, LPVOID lpBuffer, LPDWORD cbBuffer, LPSTR *lplpSystem)
Definition: wnet.c:1820
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
BOOL WINAPI GetUserNameA(LPSTR lpszName, LPDWORD lpSize)
Definition: misc.c:246
#define WN_BAD_POINTER
Definition: winnetwk.h:118
#define WN_BAD_PROVIDER
Definition: winnetwk.h:141
LPWSTR lpComment
Definition: winnetwk.h:183
#define GENERIC_READ
Definition: compat.h:124
DWORD WINAPI WNetCloseEnum(HANDLE hEnum)
Definition: wnet.c:1760
DWORD WINAPI WNetAddConnection3A(HWND hwndOwner, LPNETRESOURCEA lpNetResource, LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags)
Definition: wnet.c:2057
ULONG_PTR dwHandle
Definition: winnetwk.h:231
#define err(...)
#define WN_ACCESS_DENIED
Definition: winnetwk.h:122
LPWSTR lpRemoteName
Definition: winnetwk.h:182
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
_In_ DWORD dwInfoLevel
Definition: winsvc.h:422
DWORD WINAPI WNetUseConnectionW(HWND hwndOwner, NETRESOURCEW *resource, LPCWSTR password, LPCWSTR userid, DWORD flags, LPWSTR accessname, DWORD *buffer_size, DWORD *result)
Definition: wnet.c:2254
#define ERROR_MORE_DATA
Definition: dderror.h:13
PF_NPAddConnection3 addConnection3
Definition: wnet.c:63
unsigned char BYTE
Definition: xxhash.c:193
static TNetwork net
Definition: tncon.cpp:351
DWORD dwType
Definition: wnet.c:106
#define WN_OPEN_FILES
Definition: winnetwk.h:133
#define DRIVE_FIXED
Definition: winbase.h:249
DWORD WINAPI WNetCancelConnection2W(LPCWSTR lpName, DWORD dwFlags, BOOL fForce)
Definition: wnet.c:2418
#define RESOURCETYPE_DISK
Definition: winnetwk.h:64
DWORD WINAPI WNetGetProviderNameW(DWORD dwNetType, LPWSTR lpProvider, LPDWORD lpBufferSize)
Definition: wnet.c:3168
DWORD cbStructure
Definition: winnetwk.h:227
DWORD dwUsage
Definition: winnetwk.h:180
#define RESOURCE_REMEMBERED
Definition: winnetwk.h:60
static LPWSTR strdupAtoW(LPCSTR str)
Definition: wnet.c:2314
#define local
Definition: zutil.h:30
#define ERR(fmt,...)
Definition: debug.h:110
DWORD WINAPI WNetConnectionDialog(HWND hwnd, DWORD dwType)
Definition: wnet.c:2911
static DWORD _enumeratorRememberedW(PWNetEnumerator enumerator, DWORD *user_count, void *user_buffer, DWORD *user_size)
Definition: wnet.c:1559
int connected
Definition: main.c:61
DWORD(APIENTRY * PF_NPAddConnection3)(HWND hwndOwner, LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
Definition: npapi.h:77
#define MPR_GETPROC(proc)
#define WNNC_CON_CANCELCONNECTION
Definition: npapi.h:34
DWORD WINAPI WNetOpenEnumW(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNet, LPHANDLE lphEnum)
Definition: wnet.c:920
HANDLE handle
Definition: wnet.c:103
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
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
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define RESOURCETYPE_PRINT
Definition: winnetwk.h:65
#define lstrcpyW
Definition: compat.h:415
#define ARRAY_SIZE(a)
Definition: main.h:24
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn, const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:745
static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator)
Definition: wnet.c:1192
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
union _WNetEnumerator::@461 specific
DWORD APIENTRY NPAddConnection3(__in HWND hwndOwner, __in LPNETRESOURCE lpNetResource, __in_opt LPWSTR lpPassword, __in_opt LPWSTR lpUserName, __in DWORD dwFlags)
Definition: nfs41_np.c:426
static DWORD _enumerateConnectedW(PWNetEnumerator enumerator, DWORD *user_count, void *user_buffer, DWORD *user_size)
Definition: wnet.c:1436
DWORD dwScope
Definition: winnetwk.h:177
DWORD WINAPI WNetGetResourceParentA(LPNETRESOURCEA lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1975
BOOL empty
Definition: button.c:170
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define WNET_ENUMERATOR_TYPE_PROVIDER
Definition: wnet.c:79
DWORD WINAPI WNetGetNetworkInformationW(LPCWSTR lpProvider, LPNETINFOSTRUCT lpNetInfoStruct)
Definition: wnet.c:3065
static DWORD use_connection_pre_set_accessnameW(struct use_connection_context *ctxt, WCHAR *local_name)
Definition: wnet.c:2091
static void _tryLoadProvider(PCWSTR provider)
Definition: wnet.c:133
#define WN_NO_MORE_ENTRIES
Definition: winnetwk.h:146
DWORD(APIENTRY * PF_NPGetResourceInformation)(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD lpcbBuffer, LPWSTR *lplpSystem)
Definition: npapi.h:71
LPSTR lpRemoteName
Definition: winnetwk.h:172
#define MultiByteToWideChar
Definition: compat.h:100
#define CreateFileW
Definition: compat.h:409
static DWORD wnet_use_provider(struct use_connection_context *ctxt, NETRESOURCEW *netres, WNetProvider *provider, BOOLEAN redirect)
Definition: wnet.c:2127
static const WCHAR userName[]
Definition: wnet.c:2154
#define CONNECT_LOCALDRIVE
Definition: winnetwk.h:95
DWORD(APIENTRY * PF_NPOpenEnum)(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum)
Definition: npapi.h:66
#define WN_BAD_HANDLE
Definition: winnetwk.h:129
LONG WINAPI RegOpenCurrentUser(IN REGSAM samDesired, OUT PHKEY phkResult)
Definition: reg.c:3232
Definition: name.c:38
#define WN_OUT_OF_MEMORY
Definition: winnetwk.h:125
static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1236
#define WN_MORE_DATA
Definition: winnetwk.h:117
uint32_t * LPDWORD
Definition: typedefs.h:58
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define HIWORD(l)
Definition: typedefs.h:246
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
DWORD WINAPI WNetConnectionDialog1W(LPCONNECTDLGSTRUCTW lpConnDlgStruct)
Definition: wnet.c:2941
DWORD dwType
Definition: winnetwk.h:178
#define RESOURCETYPE_ANY
Definition: winnetwk.h:63
#define WNNC_ENUM_GLOBAL
Definition: npapi.h:52
DWORD dwNetType
Definition: wnet.c:56
char * cleanup(char *str)
Definition: wpickclick.c:99
LPWSTR lpProvider
Definition: winnetwk.h:184
#define GetProcAddress(x, y)
Definition: compat.h:419
#define RESOURCEDISPLAYTYPE_ROOT
Definition: winnetwk.h:82
DWORD index
Definition: wnet.c:115
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:2527
DWORD WINAPI WNetClearConnections(HWND owner)
Definition: wnet.c:2825
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
DWORD APIENTRY NPAddConnection(__in LPNETRESOURCE lpNetResource, __in_opt LPWSTR lpPassword, __in_opt LPWSTR lpUserName)
Definition: nfs41_np.c:417
DWORD WINAPI WNetEnumResourceA(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1050
static const WCHAR providerName[]
Definition: wnet.c:1542
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:596
DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
Definition: nfs41_np.c:879
static BSTR local_name(call_frame_t *frame, int ref)
Definition: engine.c:187
#define WNNC_ENUM_CONTEXT
Definition: npapi.h:54
struct _WNetEnumerator WNetEnumerator
#define HeapFree(x, y, z)
Definition: compat.h:403
NETRESOURCEA * resourceA
Definition: wnet.c:2080
#define UNIVERSAL_NAME_INFO_LEVEL
Definition: winnetwk.h:151
DWORD WINAPI WNetRestoreConnectionW(HWND hwndOwner, LPCWSTR lpszDevice)
Definition: wnet.c:2473
DWORD(APIENTRY * PF_NPCloseEnum)(HANDLE hEnum)
Definition: npapi.h:70
static DWORD get_drive_connection(WCHAR letter, LPWSTR remote, LPDWORD size)
Definition: wnet.c:2581
DWORD numAllocated
Definition: wnet.c:73
DWORD WINAPI WNetCancelConnectionW(LPCWSTR lpName, BOOL fForce)
Definition: wnet.c:2394
void(* set_accessname)(struct use_connection_context *, WCHAR *)
Definition: wnet.c:2088
DWORD WINAPI WNetGetResourceParentW(LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize)
Definition: wnet.c:1988
#define WN_BAD_LOCALNAME
Definition: winnetwk.h:136
DWORD APIENTRY NPGetCaps(DWORD nIndex)
Definition: nfs41_np.c:327
#define WNET_ENUMERATOR_TYPE_REMEMBERED
Definition: wnet.c:82
#define WNNC_CON_GETCONNECTIONS
Definition: npapi.h:35
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn, const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize)
Definition: wnet.c:660
#define REG_SZ
Definition: layer.c:22
GLuint const GLchar * name
Definition: glext.h:6031