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