4 * Copyright 1999 Ulrich Weigand
5 * Copyright 2004 Juan Lang
6 * Copyright 2007 Maarten Lankhorst
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #define WINE_MOUNTMGR_EXTENSIONS
33 #include "ddk/mountmgr.h"
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mpr
);
41 /* Data structures representing network service providers. Assumes only one
42 * thread creates them, and that they are constant for the life of the process
43 * (and therefore doesn't synchronize access).
44 * FIXME: only basic provider data and enumeration-related data are implemented
45 * so far, need to implement the rest too.
47 typedef struct _WNetProvider
55 PF_NPOpenEnum openEnum
;
56 PF_NPEnumResource enumResource
;
57 PF_NPCloseEnum closeEnum
;
58 PF_NPGetResourceInformation getResourceInformation
;
59 PF_NPAddConnection addConnection
;
60 PF_NPAddConnection3 addConnection3
;
61 } WNetProvider
, *PWNetProvider
;
63 typedef struct _WNetProviderTable
68 WNetProvider table
[1];
69 } WNetProviderTable
, *PWNetProviderTable
;
71 #define WNET_ENUMERATOR_TYPE_NULL 0
72 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
73 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
74 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
76 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
77 * the enumeration; it represents one of the following types:
78 * - a 'null' enumeration, one that contains no members
79 * - a global enumeration, one that's executed across all providers
80 * - a provider-specific enumeration, one that's only executed by a single
82 * - a context enumeration. I know this contradicts what I just said about
83 * there being no correspondence between the scope and the type, but it's
84 * necessary for the special case that a "Entire Network" entry needs to
85 * be enumerated in an enumeration of the context scope. Thus an enumeration
86 * of the context scope results in a context type enumerator, which morphs
87 * into a global enumeration (so the enumeration continues across all
90 typedef struct _WNetEnumerator
100 } WNetEnumerator
, *PWNetEnumerator
;
102 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
104 /* Returns an index (into the global WNetProviderTable) of the provider with
105 * the given name, or BAD_PROVIDER_INDEX if not found.
107 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
);
109 static PWNetProviderTable providerTable
;
112 * Global provider table functions
115 static void _tryLoadProvider(PCWSTR provider
)
117 static const WCHAR servicePrefix
[] = { 'S','y','s','t','e','m','\\',
118 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
119 'S','e','r','v','i','c','e','s','\\',0 };
120 static const WCHAR serviceFmt
[] = { '%','s','%','s','\\',
121 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
122 WCHAR serviceName
[MAX_PATH
];
125 TRACE("%s\n", debugstr_w(provider
));
126 snprintfW(serviceName
, sizeof(serviceName
) / sizeof(WCHAR
), serviceFmt
,
127 servicePrefix
, provider
);
128 serviceName
[sizeof(serviceName
) / sizeof(WCHAR
) - 1] = '\0';
129 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, serviceName
, 0, KEY_READ
, &hKey
) ==
132 static const WCHAR szProviderPath
[] = { 'P','r','o','v','i','d','e','r',
134 WCHAR providerPath
[MAX_PATH
];
135 DWORD type
, size
= sizeof(providerPath
);
137 if (RegQueryValueExW(hKey
, szProviderPath
, NULL
, &type
,
138 (LPBYTE
)providerPath
, &size
) == ERROR_SUCCESS
&& (type
== REG_SZ
|| type
== REG_EXPAND_SZ
))
140 static const WCHAR szProviderName
[] = { 'N','a','m','e',0 };
143 if (type
== REG_EXPAND_SZ
)
145 WCHAR path
[MAX_PATH
];
146 if (ExpandEnvironmentStringsW(providerPath
, path
, MAX_PATH
)) lstrcpyW( providerPath
, path
);
150 RegQueryValueExW(hKey
, szProviderName
, NULL
, NULL
, NULL
, &size
);
153 name
= HeapAlloc(GetProcessHeap(), 0, size
);
154 if (RegQueryValueExW(hKey
, szProviderName
, NULL
, &type
,
155 (LPBYTE
)name
, &size
) != ERROR_SUCCESS
|| type
!= REG_SZ
)
157 HeapFree(GetProcessHeap(), 0, name
);
163 HMODULE hLib
= LoadLibraryW(providerPath
);
167 #define MPR_GETPROC(proc) ((PF_##proc)GetProcAddress(hLib, #proc))
169 PF_NPGetCaps getCaps
= MPR_GETPROC(NPGetCaps
);
171 TRACE("loaded lib %p\n", hLib
);
174 PWNetProvider provider
=
175 &providerTable
->table
[providerTable
->numProviders
];
177 provider
->hLib
= hLib
;
178 provider
->name
= name
;
179 TRACE("name is %s\n", debugstr_w(name
));
180 provider
->getCaps
= getCaps
;
181 provider
->dwSpecVersion
= getCaps(WNNC_SPEC_VERSION
);
182 provider
->dwNetType
= getCaps(WNNC_NET_TYPE
);
183 TRACE("net type is 0x%08x\n", provider
->dwNetType
);
184 provider
->dwEnumScopes
= getCaps(WNNC_ENUMERATION
);
185 if (provider
->dwEnumScopes
)
187 TRACE("supports enumeration\n");
188 provider
->openEnum
= MPR_GETPROC(NPOpenEnum
);
189 TRACE("NPOpenEnum %p\n", provider
->openEnum
);
190 provider
->enumResource
= MPR_GETPROC(NPEnumResource
);
191 TRACE("NPEnumResource %p\n", provider
->enumResource
);
192 provider
->closeEnum
= MPR_GETPROC(NPCloseEnum
);
193 TRACE("NPCloseEnum %p\n", provider
->closeEnum
);
194 provider
->getResourceInformation
= MPR_GETPROC(NPGetResourceInformation
);
195 TRACE("NPGetResourceInformation %p\n", provider
->getResourceInformation
);
196 if (!provider
->openEnum
||
197 !provider
->enumResource
||
198 !provider
->closeEnum
)
200 provider
->openEnum
= NULL
;
201 provider
->enumResource
= NULL
;
202 provider
->closeEnum
= NULL
;
203 provider
->dwEnumScopes
= 0;
204 WARN("Couldn't load enumeration functions\n");
207 provider
->addConnection
= MPR_GETPROC(NPAddConnection
);
208 provider
->addConnection3
= MPR_GETPROC(NPAddConnection3
);
209 TRACE("NPAddConnection %p\n", provider
->addConnection
);
210 TRACE("NPAddConnection3 %p\n", provider
->addConnection3
);
211 providerTable
->numProviders
++;
215 WARN("Provider %s didn't export NPGetCaps\n",
216 debugstr_w(provider
));
217 HeapFree(GetProcessHeap(), 0, name
);
225 WARN("Couldn't load library %s for provider %s\n",
226 debugstr_w(providerPath
), debugstr_w(provider
));
227 HeapFree(GetProcessHeap(), 0, name
);
232 WARN("Couldn't get provider name for provider %s\n",
233 debugstr_w(provider
));
237 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath
));
241 WARN("Couldn't open service key for provider %s\n",
242 debugstr_w(provider
));
245 void wnetInit(HINSTANCE hInstDll
)
247 static const WCHAR providerOrderKey
[] = { 'S','y','s','t','e','m','\\',
248 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
249 'C','o','n','t','r','o','l','\\',
250 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
251 'O','r','d','e','r',0 };
252 static const WCHAR providerOrder
[] = { 'P','r','o','v','i','d','e','r',
253 'O','r','d','e','r',0 };
256 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, providerOrderKey
, 0, KEY_READ
, &hKey
)
261 RegQueryValueExW(hKey
, providerOrder
, NULL
, NULL
, NULL
, &size
);
264 PWSTR providers
= HeapAlloc(GetProcessHeap(), 0, size
);
270 if (RegQueryValueExW(hKey
, providerOrder
, NULL
, &type
,
271 (LPBYTE
)providers
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
276 TRACE("provider order is %s\n", debugstr_w(providers
));
277 /* first count commas as a heuristic for how many to
278 * allocate space for */
279 for (ptr
= providers
, numToAllocate
= 1; ptr
; )
281 ptr
= strchrW(ptr
, ',');
288 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
289 sizeof(WNetProviderTable
)
290 + (numToAllocate
- 1) * sizeof(WNetProvider
));
294 int entireNetworkLen
;
295 LPCWSTR stringresource
;
297 entireNetworkLen
= LoadStringW(hInstDll
,
298 IDS_ENTIRENETWORK
, (LPWSTR
)&stringresource
, 0);
299 providerTable
->entireNetwork
= HeapAlloc(
300 GetProcessHeap(), 0, (entireNetworkLen
+ 1) *
302 if (providerTable
->entireNetwork
)
304 memcpy(providerTable
->entireNetwork
, stringresource
, entireNetworkLen
*sizeof(WCHAR
));
305 providerTable
->entireNetwork
[entireNetworkLen
] = 0;
307 providerTable
->numAllocated
= numToAllocate
;
308 for (ptr
= providers
; ptr
; )
311 ptr
= strchrW(ptr
, ',');
314 _tryLoadProvider(ptrPrev
);
318 HeapFree(GetProcessHeap(), 0, providers
);
331 for (i
= 0; i
< providerTable
->numProviders
; i
++)
333 HeapFree(GetProcessHeap(), 0, providerTable
->table
[i
].name
);
334 FreeModule(providerTable
->table
[i
].hLib
);
336 HeapFree(GetProcessHeap(), 0, providerTable
->entireNetwork
);
337 HeapFree(GetProcessHeap(), 0, providerTable
);
338 providerTable
= NULL
;
342 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
)
344 DWORD ret
= BAD_PROVIDER_INDEX
;
346 if (providerTable
&& providerTable
->numProviders
)
350 for (i
= 0; i
< providerTable
->numProviders
&&
351 ret
== BAD_PROVIDER_INDEX
; i
++)
352 if (!strcmpW(lpProvider
, providerTable
->table
[i
].name
))
362 static LPNETRESOURCEW
_copyNetResourceForEnumW(LPNETRESOURCEW lpNet
)
368 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW
));
374 ret
->lpLocalName
= ret
->lpComment
= ret
->lpProvider
= NULL
;
375 if (lpNet
->lpRemoteName
)
377 len
= strlenW(lpNet
->lpRemoteName
) + 1;
378 ret
->lpRemoteName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
379 if (ret
->lpRemoteName
)
380 strcpyW(ret
->lpRemoteName
, lpNet
->lpRemoteName
);
389 static void _freeEnumNetResource(LPNETRESOURCEW lpNet
)
393 HeapFree(GetProcessHeap(), 0, lpNet
->lpRemoteName
);
394 HeapFree(GetProcessHeap(), 0, lpNet
);
398 static PWNetEnumerator
_createNullEnumerator(void)
400 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
401 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
404 ret
->enumType
= WNET_ENUMERATOR_TYPE_NULL
;
408 static PWNetEnumerator
_createGlobalEnumeratorW(DWORD dwScope
, DWORD dwType
,
409 DWORD dwUsage
, LPNETRESOURCEW lpNet
)
411 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
412 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
416 ret
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
417 ret
->dwScope
= dwScope
;
418 ret
->dwType
= dwType
;
419 ret
->dwUsage
= dwUsage
;
420 ret
->lpNet
= _copyNetResourceForEnumW(lpNet
);
425 static PWNetEnumerator
_createProviderEnumerator(DWORD dwScope
, DWORD dwType
,
426 DWORD dwUsage
, DWORD index
, HANDLE handle
)
430 if (!providerTable
|| index
>= providerTable
->numProviders
)
434 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
437 ret
->enumType
= WNET_ENUMERATOR_TYPE_PROVIDER
;
438 ret
->providerIndex
= index
;
439 ret
->dwScope
= dwScope
;
440 ret
->dwType
= dwType
;
441 ret
->dwUsage
= dwUsage
;
442 ret
->handle
= handle
;
448 static PWNetEnumerator
_createContextEnumerator(DWORD dwScope
, DWORD dwType
,
451 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
452 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
456 ret
->enumType
= WNET_ENUMERATOR_TYPE_CONTEXT
;
457 ret
->dwScope
= dwScope
;
458 ret
->dwType
= dwType
;
459 ret
->dwUsage
= dwUsage
;
464 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
465 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
466 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
467 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
468 * if not all members of the array could be thunked, and something else on
471 static DWORD
_thunkNetResourceArrayWToA(const NETRESOURCEW
*lpNetArrayIn
,
472 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
474 DWORD i
, numToThunk
, totalBytes
, ret
;
478 return WN_BAD_POINTER
;
480 return WN_BAD_POINTER
;
484 return WN_BAD_POINTER
;
486 return WN_BAD_POINTER
;
488 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
490 const NETRESOURCEW
*lpNet
= lpNetArrayIn
+ i
;
492 totalBytes
+= sizeof(NETRESOURCEA
);
493 if (lpNet
->lpLocalName
)
494 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpLocalName
,
495 -1, NULL
, 0, NULL
, NULL
);
496 if (lpNet
->lpRemoteName
)
497 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpRemoteName
,
498 -1, NULL
, 0, NULL
, NULL
);
499 if (lpNet
->lpComment
)
500 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpComment
,
501 -1, NULL
, 0, NULL
, NULL
);
502 if (lpNet
->lpProvider
)
503 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpProvider
,
504 -1, NULL
, 0, NULL
, NULL
);
505 if (totalBytes
< *lpBufferSize
)
508 strNext
= (LPSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEA
));
509 for (i
= 0; i
< numToThunk
; i
++)
511 LPNETRESOURCEA lpNetOut
= (LPNETRESOURCEA
)lpBuffer
+ i
;
512 const NETRESOURCEW
*lpNetIn
= lpNetArrayIn
+ i
;
514 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEA
));
515 /* lie about string lengths, we already verified how many
516 * we have space for above
518 if (lpNetIn
->lpLocalName
)
520 lpNetOut
->lpLocalName
= strNext
;
521 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpLocalName
, -1,
522 lpNetOut
->lpLocalName
, *lpBufferSize
, NULL
, NULL
);
524 if (lpNetIn
->lpRemoteName
)
526 lpNetOut
->lpRemoteName
= strNext
;
527 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpRemoteName
, -1,
528 lpNetOut
->lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
530 if (lpNetIn
->lpComment
)
532 lpNetOut
->lpComment
= strNext
;
533 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpComment
, -1,
534 lpNetOut
->lpComment
, *lpBufferSize
, NULL
, NULL
);
536 if (lpNetIn
->lpProvider
)
538 lpNetOut
->lpProvider
= strNext
;
539 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpProvider
, -1,
540 lpNetOut
->lpProvider
, *lpBufferSize
, NULL
, NULL
);
543 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
544 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
549 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
550 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
551 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
552 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
553 * if not all members of the array could be thunked, and something else on
556 static DWORD
_thunkNetResourceArrayAToW(const NETRESOURCEA
*lpNetArrayIn
,
557 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
559 DWORD i
, numToThunk
, totalBytes
, ret
;
563 return WN_BAD_POINTER
;
565 return WN_BAD_POINTER
;
569 return WN_BAD_POINTER
;
571 return WN_BAD_POINTER
;
573 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
575 const NETRESOURCEA
*lpNet
= lpNetArrayIn
+ i
;
577 totalBytes
+= sizeof(NETRESOURCEW
);
578 if (lpNet
->lpLocalName
)
579 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpLocalName
,
580 -1, NULL
, 0) * sizeof(WCHAR
);
581 if (lpNet
->lpRemoteName
)
582 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpRemoteName
,
583 -1, NULL
, 0) * sizeof(WCHAR
);
584 if (lpNet
->lpComment
)
585 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpComment
,
586 -1, NULL
, 0) * sizeof(WCHAR
);
587 if (lpNet
->lpProvider
)
588 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpProvider
,
589 -1, NULL
, 0) * sizeof(WCHAR
);
590 if (totalBytes
< *lpBufferSize
)
593 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEW
));
594 for (i
= 0; i
< numToThunk
; i
++)
596 LPNETRESOURCEW lpNetOut
= (LPNETRESOURCEW
)lpBuffer
+ i
;
597 const NETRESOURCEA
*lpNetIn
= lpNetArrayIn
+ i
;
599 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEW
));
600 /* lie about string lengths, we already verified how many
601 * we have space for above
603 if (lpNetIn
->lpLocalName
)
605 lpNetOut
->lpLocalName
= strNext
;
606 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpLocalName
,
607 -1, lpNetOut
->lpLocalName
, *lpBufferSize
);
609 if (lpNetIn
->lpRemoteName
)
611 lpNetOut
->lpRemoteName
= strNext
;
612 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpRemoteName
,
613 -1, lpNetOut
->lpRemoteName
, *lpBufferSize
);
615 if (lpNetIn
->lpComment
)
617 lpNetOut
->lpComment
= strNext
;
618 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpComment
,
619 -1, lpNetOut
->lpComment
, *lpBufferSize
);
621 if (lpNetIn
->lpProvider
)
623 lpNetOut
->lpProvider
= strNext
;
624 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpProvider
,
625 -1, lpNetOut
->lpProvider
, *lpBufferSize
);
628 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
629 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
634 /*********************************************************************
635 * WNetOpenEnumA [MPR.@]
637 * See comments for WNetOpenEnumW.
639 DWORD WINAPI
WNetOpenEnumA( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
640 LPNETRESOURCEA lpNet
, LPHANDLE lphEnum
)
644 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
645 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
648 ret
= WN_BAD_POINTER
;
649 else if (!providerTable
|| providerTable
->numProviders
== 0)
658 LPNETRESOURCEW lpNetWide
= NULL
;
660 DWORD size
= sizeof(buf
), count
= 1;
661 BOOL allocated
= FALSE
;
663 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, buf
, &size
);
664 if (ret
== WN_MORE_DATA
)
666 lpNetWide
= HeapAlloc(GetProcessHeap(), 0,
670 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, lpNetWide
,
675 ret
= WN_OUT_OF_MEMORY
;
677 else if (ret
== WN_SUCCESS
)
678 lpNetWide
= (LPNETRESOURCEW
)buf
;
679 if (ret
== WN_SUCCESS
)
680 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, lpNetWide
,
683 HeapFree(GetProcessHeap(), 0, lpNetWide
);
686 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, NULL
, lphEnum
);
690 TRACE("Returning %d\n", ret
);
694 /*********************************************************************
695 * WNetOpenEnumW [MPR.@]
697 * Network enumeration has way too many parameters, so I'm not positive I got
698 * them right. What I've got so far:
700 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
701 * all the network providers should be enumerated.
703 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
704 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
705 * lpProvider is set, all the network providers should be enumerated.
706 * (This means the enumeration is a list of network providers, not that the
707 * enumeration is passed on to the providers.)
709 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
710 * resource matches the "Entire Network" resource (no remote name, no
711 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
712 * enumeration is done on every network provider.
714 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
715 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
716 * only to the given network provider.
718 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
719 * no lpProvider is set, enumeration will be tried on every network provider,
720 * in the order in which they're loaded.
722 * - The LPNETRESOURCE should be disregarded for scopes besides
723 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
724 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
726 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
727 * resource in the enumerated list, as well as any machines in your
728 * workgroup. The machines in your workgroup come from doing a
729 * RESOURCE_CONTEXT enumeration of every Network Provider.
731 DWORD WINAPI
WNetOpenEnumW( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
732 LPNETRESOURCEW lpNet
, LPHANDLE lphEnum
)
736 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
737 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
740 ret
= WN_BAD_POINTER
;
741 else if (!providerTable
|| providerTable
->numProviders
== 0)
750 case RESOURCE_GLOBALNET
:
753 if (lpNet
->lpProvider
)
755 DWORD index
= _findProviderIndexW(lpNet
->lpProvider
);
757 if (index
!= BAD_PROVIDER_INDEX
)
759 if (providerTable
->table
[index
].openEnum
&&
760 providerTable
->table
[index
].dwEnumScopes
& WNNC_ENUM_GLOBAL
)
763 PWSTR RemoteName
= lpNet
->lpRemoteName
;
765 if ((lpNet
->dwUsage
& RESOURCEUSAGE_CONTAINER
) &&
766 RemoteName
&& !strcmpW(RemoteName
, lpNet
->lpProvider
))
767 lpNet
->lpRemoteName
= NULL
;
769 ret
= providerTable
->table
[index
].openEnum(
770 dwScope
, dwType
, dwUsage
, lpNet
, &handle
);
771 if (ret
== WN_SUCCESS
)
773 *lphEnum
= _createProviderEnumerator(
774 dwScope
, dwType
, dwUsage
, index
, handle
);
775 ret
= *lphEnum
? WN_SUCCESS
:
779 lpNet
->lpRemoteName
= RemoteName
;
782 ret
= WN_NOT_SUPPORTED
;
785 ret
= WN_BAD_PROVIDER
;
787 else if (lpNet
->lpRemoteName
)
789 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
790 dwType
, dwUsage
, lpNet
);
791 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
795 if (lpNet
->lpComment
&& !strcmpW(lpNet
->lpComment
,
796 providerTable
->entireNetwork
))
798 /* comment matches the "Entire Network", enumerate
799 * global scope of every provider
801 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
802 dwType
, dwUsage
, lpNet
);
806 /* this is the same as not having passed lpNet */
807 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
808 dwType
, dwUsage
, NULL
);
810 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
815 *lphEnum
= _createGlobalEnumeratorW(dwScope
, dwType
,
817 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
820 case RESOURCE_CONTEXT
:
821 *lphEnum
= _createContextEnumerator(dwScope
, dwType
, dwUsage
);
822 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
824 case RESOURCE_REMEMBERED
:
825 case RESOURCE_CONNECTED
:
826 *lphEnum
= _createNullEnumerator();
827 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
830 WARN("unknown scope 0x%08x\n", dwScope
);
836 TRACE("Returning %d\n", ret
);
840 /*********************************************************************
841 * WNetEnumResourceA [MPR.@]
843 DWORD WINAPI
WNetEnumResourceA( HANDLE hEnum
, LPDWORD lpcCount
,
844 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
848 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
851 ret
= WN_BAD_POINTER
;
853 ret
= WN_BAD_POINTER
;
855 ret
= WN_BAD_POINTER
;
856 else if (!lpBufferSize
)
857 ret
= WN_BAD_POINTER
;
858 else if (*lpBufferSize
< sizeof(NETRESOURCEA
))
860 *lpBufferSize
= sizeof(NETRESOURCEA
);
865 DWORD localCount
= *lpcCount
, localSize
= *lpBufferSize
;
866 LPVOID localBuffer
= HeapAlloc(GetProcessHeap(), 0, localSize
);
870 ret
= WNetEnumResourceW(hEnum
, &localCount
, localBuffer
,
872 if (ret
== WN_SUCCESS
|| (ret
== WN_MORE_DATA
&& localCount
!= -1))
874 /* FIXME: this isn't necessarily going to work in the case of
875 * WN_MORE_DATA, because our enumerator may have moved on to
876 * the next provider. MSDN states that a large (16KB) buffer
877 * size is the appropriate usage of this function, so
878 * hopefully it won't be an issue.
880 ret
= _thunkNetResourceArrayWToA(localBuffer
, &localCount
,
881 lpBuffer
, lpBufferSize
);
882 *lpcCount
= localCount
;
884 HeapFree(GetProcessHeap(), 0, localBuffer
);
887 ret
= WN_OUT_OF_MEMORY
;
891 TRACE("Returning %d\n", ret
);
895 static DWORD
_countProviderBytesW(PWNetProvider provider
)
901 ret
= sizeof(NETRESOURCEW
);
902 ret
+= 2 * (strlenW(provider
->name
) + 1) * sizeof(WCHAR
);
909 static DWORD
_enumerateProvidersW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
910 LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
915 return WN_BAD_POINTER
;
916 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
919 return WN_BAD_POINTER
;
921 return WN_BAD_POINTER
;
923 return WN_BAD_POINTER
;
924 if (*lpBufferSize
< sizeof(NETRESOURCEA
))
927 if (!providerTable
|| enumerator
->providerIndex
>=
928 providerTable
->numProviders
)
929 ret
= WN_NO_MORE_ENTRIES
;
932 DWORD bytes
= 0, count
= 0, countLimit
, i
;
933 LPNETRESOURCEW resource
;
936 countLimit
= *lpcCount
== -1 ?
937 providerTable
->numProviders
- enumerator
->providerIndex
: *lpcCount
;
938 while (count
< countLimit
&& bytes
< *lpBufferSize
)
940 DWORD bytesNext
= _countProviderBytesW(
941 &providerTable
->table
[count
+ enumerator
->providerIndex
]);
943 if (bytes
+ bytesNext
< *lpBufferSize
)
949 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ count
* sizeof(NETRESOURCEW
));
950 for (i
= 0, resource
= lpBuffer
; i
< count
; i
++, resource
++)
952 resource
->dwScope
= RESOURCE_GLOBALNET
;
953 resource
->dwType
= RESOURCETYPE_ANY
;
954 resource
->dwDisplayType
= RESOURCEDISPLAYTYPE_NETWORK
;
955 resource
->dwUsage
= RESOURCEUSAGE_CONTAINER
|
956 RESOURCEUSAGE_RESERVED
;
957 resource
->lpLocalName
= NULL
;
958 resource
->lpRemoteName
= strNext
;
959 strcpyW(resource
->lpRemoteName
,
960 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
961 strNext
+= strlenW(resource
->lpRemoteName
) + 1;
962 resource
->lpComment
= NULL
;
963 resource
->lpProvider
= strNext
;
964 strcpyW(resource
->lpProvider
,
965 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
966 strNext
+= strlenW(resource
->lpProvider
) + 1;
968 enumerator
->providerIndex
+= count
;
970 ret
= count
> 0 ? WN_SUCCESS
: WN_MORE_DATA
;
972 TRACE("Returning %d\n", ret
);
976 /* Advances the enumerator (assumed to be a global enumerator) to the next
977 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
978 * not open a handle with the next provider.
979 * If the existing handle is NULL, may leave the enumerator unchanged, since
980 * the current provider may support the desired scope.
981 * If the existing handle is not NULL, closes it before moving on.
982 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
983 * provider, and another error on failure.
985 static DWORD
_globalEnumeratorAdvance(PWNetEnumerator enumerator
)
988 return WN_BAD_POINTER
;
989 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
991 if (!providerTable
|| enumerator
->providerIndex
>=
992 providerTable
->numProviders
)
993 return WN_NO_MORE_ENTRIES
;
995 if (enumerator
->providerDone
)
998 enumerator
->providerDone
= FALSE
;
999 if (enumerator
->handle
)
1001 providerTable
->table
[enumerator
->providerIndex
].closeEnum(
1002 enumerator
->handle
);
1003 enumerator
->handle
= NULL
;
1004 enumerator
->providerIndex
++;
1006 if (enumerator
->dwScope
== RESOURCE_CONNECTED
)
1007 dwEnum
= WNNC_ENUM_LOCAL
;
1008 else if (enumerator
->dwScope
== RESOURCE_GLOBALNET
)
1009 dwEnum
= WNNC_ENUM_GLOBAL
;
1010 else if (enumerator
->dwScope
== RESOURCE_CONTEXT
)
1011 dwEnum
= WNNC_ENUM_CONTEXT
;
1012 for (; enumerator
->providerIndex
< providerTable
->numProviders
&&
1013 !(providerTable
->table
[enumerator
->providerIndex
].dwEnumScopes
1014 & dwEnum
); enumerator
->providerIndex
++)
1017 return enumerator
->providerIndex
< providerTable
->numProviders
?
1018 WN_SUCCESS
: WN_NO_MORE_ENTRIES
;
1021 /* "Passes through" call to the next provider that supports the enumeration
1023 * FIXME: if one call to a provider's enumerator succeeds while there's still
1024 * space in lpBuffer, I don't call to the next provider. The caller may not
1025 * expect that it should call EnumResourceW again with a return value of
1026 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1027 * may have to be moved around a bit, ick.
1029 static DWORD
_enumerateGlobalPassthroughW(PWNetEnumerator enumerator
,
1030 LPDWORD lpcCount
, LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1035 return WN_BAD_POINTER
;
1036 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1037 return WN_BAD_VALUE
;
1039 return WN_BAD_POINTER
;
1041 return WN_BAD_POINTER
;
1043 return WN_BAD_POINTER
;
1044 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1045 return WN_MORE_DATA
;
1047 ret
= _globalEnumeratorAdvance(enumerator
);
1048 if (ret
== WN_SUCCESS
)
1050 ret
= providerTable
->table
[enumerator
->providerIndex
].
1051 openEnum(enumerator
->dwScope
, enumerator
->dwType
,
1052 enumerator
->dwUsage
, enumerator
->lpNet
,
1053 &enumerator
->handle
);
1054 if (ret
== WN_SUCCESS
)
1056 ret
= providerTable
->table
[enumerator
->providerIndex
].
1057 enumResource(enumerator
->handle
, lpcCount
, lpBuffer
,
1059 if (ret
!= WN_MORE_DATA
)
1060 enumerator
->providerDone
= TRUE
;
1063 TRACE("Returning %d\n", ret
);
1067 static DWORD
_enumerateGlobalW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1068 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1073 return WN_BAD_POINTER
;
1074 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1075 return WN_BAD_VALUE
;
1077 return WN_BAD_POINTER
;
1079 return WN_BAD_POINTER
;
1081 return WN_BAD_POINTER
;
1082 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1083 return WN_MORE_DATA
;
1085 return WN_NO_NETWORK
;
1087 switch (enumerator
->dwScope
)
1089 case RESOURCE_GLOBALNET
:
1090 if (enumerator
->lpNet
)
1091 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
,
1092 lpBuffer
, lpBufferSize
);
1094 ret
= _enumerateProvidersW(enumerator
, lpcCount
, lpBuffer
,
1097 case RESOURCE_CONTEXT
:
1098 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
, lpBuffer
,
1102 WARN("unexpected scope 0x%08x\n", enumerator
->dwScope
);
1103 ret
= WN_NO_MORE_ENTRIES
;
1105 TRACE("Returning %d\n", ret
);
1109 static DWORD
_enumerateProviderW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1110 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1113 return WN_BAD_POINTER
;
1114 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_PROVIDER
)
1115 return WN_BAD_VALUE
;
1116 if (!enumerator
->handle
)
1117 return WN_BAD_VALUE
;
1119 return WN_BAD_POINTER
;
1121 return WN_BAD_POINTER
;
1123 return WN_BAD_POINTER
;
1125 return WN_NO_NETWORK
;
1126 if (enumerator
->providerIndex
>= providerTable
->numProviders
)
1127 return WN_NO_MORE_ENTRIES
;
1128 if (!providerTable
->table
[enumerator
->providerIndex
].enumResource
)
1129 return WN_BAD_VALUE
;
1130 return providerTable
->table
[enumerator
->providerIndex
].enumResource(
1131 enumerator
->handle
, lpcCount
, lpBuffer
, lpBufferSize
);
1134 static DWORD
_enumerateContextW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1135 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1138 size_t cchEntireNetworkLen
, bytesNeeded
;
1141 return WN_BAD_POINTER
;
1142 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_CONTEXT
)
1143 return WN_BAD_VALUE
;
1145 return WN_BAD_POINTER
;
1147 return WN_BAD_POINTER
;
1149 return WN_BAD_POINTER
;
1151 return WN_NO_NETWORK
;
1153 cchEntireNetworkLen
= strlenW(providerTable
->entireNetwork
) + 1;
1154 bytesNeeded
= sizeof(NETRESOURCEW
) + cchEntireNetworkLen
* sizeof(WCHAR
);
1155 if (*lpBufferSize
< bytesNeeded
)
1157 *lpBufferSize
= bytesNeeded
;
1162 LPNETRESOURCEW lpNet
= lpBuffer
;
1164 lpNet
->dwScope
= RESOURCE_GLOBALNET
;
1165 lpNet
->dwType
= enumerator
->dwType
;
1166 lpNet
->dwDisplayType
= RESOURCEDISPLAYTYPE_ROOT
;
1167 lpNet
->dwUsage
= RESOURCEUSAGE_CONTAINER
;
1168 lpNet
->lpLocalName
= NULL
;
1169 lpNet
->lpRemoteName
= NULL
;
1170 lpNet
->lpProvider
= NULL
;
1171 /* odd, but correct: put comment at end of buffer, so it won't get
1172 * overwritten by subsequent calls to a provider's enumResource
1174 lpNet
->lpComment
= (LPWSTR
)((LPBYTE
)lpBuffer
+ *lpBufferSize
-
1175 (cchEntireNetworkLen
* sizeof(WCHAR
)));
1176 strcpyW(lpNet
->lpComment
, providerTable
->entireNetwork
);
1179 if (ret
== WN_SUCCESS
)
1181 DWORD bufferSize
= *lpBufferSize
- bytesNeeded
;
1183 /* "Entire Network" entry enumerated--morph this into a global
1184 * enumerator. enumerator->lpNet continues to be NULL, since it has
1185 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1187 enumerator
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
1188 ret
= _enumerateGlobalW(enumerator
, lpcCount
,
1189 (LPBYTE
)lpBuffer
+ bytesNeeded
, &bufferSize
);
1190 if (ret
== WN_SUCCESS
)
1192 /* reflect the fact that we already enumerated "Entire Network" */
1194 *lpBufferSize
= bufferSize
+ bytesNeeded
;
1198 /* the provider enumeration failed, but we already succeeded in
1199 * enumerating "Entire Network"--leave type as global to allow a
1200 * retry, but indicate success with a count of one.
1204 *lpBufferSize
= bytesNeeded
;
1207 TRACE("Returning %d\n", ret
);
1211 /*********************************************************************
1212 * WNetEnumResourceW [MPR.@]
1214 DWORD WINAPI
WNetEnumResourceW( HANDLE hEnum
, LPDWORD lpcCount
,
1215 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1219 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
1222 ret
= WN_BAD_POINTER
;
1224 ret
= WN_BAD_POINTER
;
1226 ret
= WN_BAD_POINTER
;
1227 else if (!lpBufferSize
)
1228 ret
= WN_BAD_POINTER
;
1229 else if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1231 *lpBufferSize
= sizeof(NETRESOURCEW
);
1236 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1238 switch (enumerator
->enumType
)
1240 case WNET_ENUMERATOR_TYPE_NULL
:
1241 ret
= WN_NO_MORE_ENTRIES
;
1243 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1244 ret
= _enumerateGlobalW(enumerator
, lpcCount
, lpBuffer
,
1247 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1248 ret
= _enumerateProviderW(enumerator
, lpcCount
, lpBuffer
,
1251 case WNET_ENUMERATOR_TYPE_CONTEXT
:
1252 ret
= _enumerateContextW(enumerator
, lpcCount
, lpBuffer
,
1256 WARN("bogus enumerator type!\n");
1257 ret
= WN_NO_NETWORK
;
1262 TRACE("Returning %d\n", ret
);
1266 /*********************************************************************
1267 * WNetCloseEnum [MPR.@]
1269 DWORD WINAPI
WNetCloseEnum( HANDLE hEnum
)
1273 TRACE( "(%p)\n", hEnum
);
1277 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1279 switch (enumerator
->enumType
)
1281 case WNET_ENUMERATOR_TYPE_NULL
:
1284 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1285 if (enumerator
->lpNet
)
1286 _freeEnumNetResource(enumerator
->lpNet
);
1287 if (enumerator
->handle
)
1288 providerTable
->table
[enumerator
->providerIndex
].
1289 closeEnum(enumerator
->handle
);
1292 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1293 if (enumerator
->handle
)
1294 providerTable
->table
[enumerator
->providerIndex
].
1295 closeEnum(enumerator
->handle
);
1299 WARN("bogus enumerator type!\n");
1300 ret
= WN_BAD_HANDLE
;
1302 HeapFree(GetProcessHeap(), 0, hEnum
);
1305 ret
= WN_BAD_HANDLE
;
1308 TRACE("Returning %d\n", ret
);
1312 /*********************************************************************
1313 * WNetGetResourceInformationA [MPR.@]
1315 * See WNetGetResourceInformationW
1317 DWORD WINAPI
WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource
,
1318 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1323 TRACE( "(%p, %p, %p, %p)\n",
1324 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1326 if (!providerTable
|| providerTable
->numProviders
== 0)
1327 ret
= WN_NO_NETWORK
;
1328 else if (lpNetResource
)
1330 LPNETRESOURCEW lpNetResourceW
= NULL
;
1331 DWORD size
= 1024, count
= 1;
1334 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1335 ret
= _thunkNetResourceArrayAToW(lpNetResource
, &count
, lpNetResourceW
, &size
);
1336 if (ret
== WN_MORE_DATA
)
1338 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1339 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1341 ret
= _thunkNetResourceArrayAToW(lpNetResource
,
1342 &count
, lpNetResourceW
, &size
);
1344 ret
= WN_OUT_OF_MEMORY
;
1346 if (ret
== WN_SUCCESS
)
1348 LPWSTR lpSystemW
= NULL
;
1351 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1354 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1355 lpBufferW
, &size
, &lpSystemW
);
1356 if (ret
== WN_MORE_DATA
)
1358 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1359 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1361 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1362 lpBufferW
, &size
, &lpSystemW
);
1364 ret
= WN_OUT_OF_MEMORY
;
1366 if (ret
== WN_SUCCESS
)
1368 ret
= _thunkNetResourceArrayWToA(lpBufferW
,
1369 &count
, lpBuffer
, cbBuffer
);
1370 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1371 lpNetResourceW
= lpBufferW
;
1372 size
= sizeof(NETRESOURCEA
);
1373 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpRemoteName
,
1374 -1, NULL
, 0, NULL
, NULL
);
1375 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpProvider
,
1376 -1, NULL
, 0, NULL
, NULL
);
1378 len
= WideCharToMultiByte(CP_ACP
, 0, lpSystemW
,
1379 -1, NULL
, 0, NULL
, NULL
);
1380 if ((len
) && ( size
+ len
< *cbBuffer
))
1382 *lplpSystem
= (char*)lpBuffer
+ *cbBuffer
- len
;
1383 WideCharToMultiByte(CP_ACP
, 0, lpSystemW
, -1,
1384 *lplpSystem
, len
, NULL
, NULL
);
1391 ret
= WN_OUT_OF_MEMORY
;
1392 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1395 ret
= WN_OUT_OF_MEMORY
;
1396 HeapFree(GetProcessHeap(), 0, lpSystemW
);
1398 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1401 ret
= WN_NO_NETWORK
;
1405 TRACE("Returning %d\n", ret
);
1409 /*********************************************************************
1410 * WNetGetResourceInformationW [MPR.@]
1412 * WNetGetResourceInformationW function identifies the network provider
1413 * that owns the resource and gets information about the type of the resource.
1416 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1417 * defines a network resource.
1418 * lpBuffer [ O] the pointer to buffer, containing result. It
1419 * contains NETRESOURCEW structure and strings to
1420 * which the members of the NETRESOURCEW structure
1422 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1424 * lplpSystem [ O] the pointer to string in the output buffer,
1425 * containing the part of the resource name without
1426 * names of the server and share.
1429 * NO_ERROR if the function succeeds. System error code if the function fails.
1432 DWORD WINAPI
WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource
,
1433 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1434 LPWSTR
*lplpSystem
)
1436 DWORD ret
= WN_NO_NETWORK
;
1439 TRACE( "(%p, %p, %p, %p)\n",
1440 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1443 ret
= WN_OUT_OF_MEMORY
;
1444 else if (providerTable
!= NULL
)
1446 /* FIXME: For function value of a variable is indifferent, it does
1447 * search of all providers in a network.
1449 for (index
= 0; index
< providerTable
->numProviders
; index
++)
1451 if(providerTable
->table
[index
].getCaps(WNNC_DIALOG
) &
1452 WNNC_DLG_GETRESOURCEINFORMATION
)
1454 if (providerTable
->table
[index
].getResourceInformation
)
1455 ret
= providerTable
->table
[index
].getResourceInformation(
1456 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1458 ret
= WN_NO_NETWORK
;
1459 if (ret
== WN_SUCCESS
)
1469 /*********************************************************************
1470 * WNetGetResourceParentA [MPR.@]
1472 DWORD WINAPI
WNetGetResourceParentA( LPNETRESOURCEA lpNetResource
,
1473 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1475 FIXME( "(%p, %p, %p): stub\n",
1476 lpNetResource
, lpBuffer
, lpBufferSize
);
1478 SetLastError(WN_NO_NETWORK
);
1479 return WN_NO_NETWORK
;
1482 /*********************************************************************
1483 * WNetGetResourceParentW [MPR.@]
1485 DWORD WINAPI
WNetGetResourceParentW( LPNETRESOURCEW lpNetResource
,
1486 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1488 FIXME( "(%p, %p, %p): stub\n",
1489 lpNetResource
, lpBuffer
, lpBufferSize
);
1491 SetLastError(WN_NO_NETWORK
);
1492 return WN_NO_NETWORK
;
1498 * Connection Functions
1501 /*********************************************************************
1502 * WNetAddConnectionA [MPR.@]
1504 DWORD WINAPI
WNetAddConnectionA( LPCSTR lpRemoteName
, LPCSTR lpPassword
,
1505 LPCSTR lpLocalName
)
1507 NETRESOURCEA resourcesA
;
1509 memset(&resourcesA
, 0, sizeof(resourcesA
));
1510 resourcesA
.lpRemoteName
= (LPSTR
)lpRemoteName
;
1511 resourcesA
.lpLocalName
= (LPSTR
)lpLocalName
;
1512 return WNetUseConnectionA(NULL
, &resourcesA
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1515 /*********************************************************************
1516 * WNetAddConnectionW [MPR.@]
1518 DWORD WINAPI
WNetAddConnectionW( LPCWSTR lpRemoteName
, LPCWSTR lpPassword
,
1519 LPCWSTR lpLocalName
)
1521 NETRESOURCEW resourcesW
;
1523 memset(&resourcesW
, 0, sizeof(resourcesW
));
1524 resourcesW
.lpRemoteName
= (LPWSTR
)lpRemoteName
;
1525 resourcesW
.lpLocalName
= (LPWSTR
)lpLocalName
;
1526 return WNetUseConnectionW(NULL
, &resourcesW
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1529 /*********************************************************************
1530 * WNetAddConnection2A [MPR.@]
1532 DWORD WINAPI
WNetAddConnection2A( LPNETRESOURCEA lpNetResource
,
1533 LPCSTR lpPassword
, LPCSTR lpUserID
,
1536 return WNetUseConnectionA(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1540 /*********************************************************************
1541 * WNetAddConnection2W [MPR.@]
1543 DWORD WINAPI
WNetAddConnection2W( LPNETRESOURCEW lpNetResource
,
1544 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1547 return WNetUseConnectionW(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1551 /*********************************************************************
1552 * WNetAddConnection3A [MPR.@]
1554 DWORD WINAPI
WNetAddConnection3A( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1555 LPCSTR lpPassword
, LPCSTR lpUserID
,
1558 return WNetUseConnectionA(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1559 dwFlags
, NULL
, 0, NULL
);
1562 /*********************************************************************
1563 * WNetAddConnection3W [MPR.@]
1565 DWORD WINAPI
WNetAddConnection3W( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1566 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1569 return WNetUseConnectionW(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1570 dwFlags
, NULL
, 0, NULL
);
1573 struct use_connection_context
1576 NETRESOURCEW
*resource
;
1577 NETRESOURCEA
*resourceA
; /* only set for WNetUseConnectionA */
1584 DWORD (*pre_set_accessname
)(struct use_connection_context
*);
1585 void (*set_accessname
)(struct use_connection_context
*);
1588 static DWORD
use_connection_pre_set_accessnameW(struct use_connection_context
*ctxt
)
1590 if (ctxt
->accessname
&& ctxt
->buffer_size
&& *ctxt
->buffer_size
)
1594 if (ctxt
->resource
->lpLocalName
)
1595 len
= strlenW(ctxt
->resource
->lpLocalName
);
1597 len
= strlenW(ctxt
->resource
->lpRemoteName
);
1599 if (++len
> *ctxt
->buffer_size
)
1601 *ctxt
->buffer_size
= len
;
1602 return ERROR_MORE_DATA
;
1606 ctxt
->accessname
= NULL
;
1608 return ERROR_SUCCESS
;
1611 static void use_connection_set_accessnameW(struct use_connection_context
*ctxt
)
1613 WCHAR
*accessname
= ctxt
->accessname
;
1614 if (ctxt
->resource
->lpLocalName
)
1615 strcpyW(accessname
, ctxt
->resource
->lpLocalName
);
1617 strcpyW(accessname
, ctxt
->resource
->lpRemoteName
);
1620 static DWORD
wnet_use_connection( struct use_connection_context
*ctxt
)
1622 WNetProvider
*provider
;
1623 DWORD index
, ret
, caps
;
1625 if (!providerTable
|| providerTable
->numProviders
== 0)
1626 return WN_NO_NETWORK
;
1628 if (!ctxt
->resource
)
1629 return ERROR_INVALID_PARAMETER
;
1631 if (!ctxt
->resource
->lpProvider
)
1633 FIXME("Networking provider selection is not implemented.\n");
1634 return WN_NO_NETWORK
;
1637 if (!ctxt
->resource
->lpLocalName
&& (ctxt
->flags
& CONNECT_REDIRECT
))
1639 FIXME("Locale device selection is not implemented.\n");
1640 return WN_NO_NETWORK
;
1643 if (ctxt
->flags
& CONNECT_INTERACTIVE
)
1644 return ERROR_BAD_NET_NAME
;
1646 index
= _findProviderIndexW(ctxt
->resource
->lpProvider
);
1647 if (index
== BAD_PROVIDER_INDEX
)
1648 return ERROR_BAD_PROVIDER
;
1650 provider
= &providerTable
->table
[index
];
1651 caps
= provider
->getCaps(WNNC_CONNECTION
);
1652 if (!(caps
& (WNNC_CON_ADDCONNECTION
| WNNC_CON_ADDCONNECTION3
)))
1653 return ERROR_BAD_PROVIDER
;
1655 if ((ret
= ctxt
->pre_set_accessname(ctxt
)))
1658 ret
= WN_ACCESS_DENIED
;
1659 if ((caps
& WNNC_CON_ADDCONNECTION3
) && provider
->addConnection3
)
1660 ret
= provider
->addConnection3(ctxt
->hwndOwner
, ctxt
->resource
, ctxt
->password
, ctxt
->userid
, ctxt
->flags
);
1661 else if ((caps
& WNNC_CON_ADDCONNECTION
) && provider
->addConnection
)
1662 ret
= provider
->addConnection(ctxt
->resource
, ctxt
->password
, ctxt
->userid
);
1664 if (ret
== WN_SUCCESS
&& ctxt
->accessname
)
1665 ctxt
->set_accessname(ctxt
);
1670 /*****************************************************************
1671 * WNetUseConnectionW [MPR.@]
1673 DWORD WINAPI
WNetUseConnectionW( HWND hwndOwner
, NETRESOURCEW
*resource
, LPCWSTR password
,
1674 LPCWSTR userid
, DWORD flags
, LPWSTR accessname
, DWORD
*buffer_size
, DWORD
*result
)
1676 struct use_connection_context ctxt
;
1678 TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n",
1679 hwndOwner
, resource
, password
, debugstr_w(userid
), flags
,
1680 accessname
, buffer_size
, result
);
1682 ctxt
.hwndOwner
= hwndOwner
;
1683 ctxt
.resource
= resource
;
1684 ctxt
.resourceA
= NULL
;
1685 ctxt
.password
= (WCHAR
*)password
;
1686 ctxt
.userid
= (WCHAR
*)userid
;
1688 ctxt
.accessname
= accessname
;
1689 ctxt
.buffer_size
= buffer_size
;
1690 ctxt
.result
= result
;
1691 ctxt
.pre_set_accessname
= use_connection_pre_set_accessnameW
;
1692 ctxt
.set_accessname
= use_connection_set_accessnameW
;
1694 return wnet_use_connection(&ctxt
);
1697 static DWORD
use_connection_pre_set_accessnameA(struct use_connection_context
*ctxt
)
1699 if (ctxt
->accessname
&& ctxt
->buffer_size
&& *ctxt
->buffer_size
)
1703 if (ctxt
->resourceA
->lpLocalName
)
1704 len
= strlen(ctxt
->resourceA
->lpLocalName
);
1706 len
= strlen(ctxt
->resourceA
->lpRemoteName
);
1708 if (++len
> *ctxt
->buffer_size
)
1710 *ctxt
->buffer_size
= len
;
1711 return ERROR_MORE_DATA
;
1715 ctxt
->accessname
= NULL
;
1717 return ERROR_SUCCESS
;
1720 static void use_connection_set_accessnameA(struct use_connection_context
*ctxt
)
1722 char *accessname
= ctxt
->accessname
;
1723 if (ctxt
->resourceA
->lpLocalName
)
1724 strcpy(accessname
, ctxt
->resourceA
->lpLocalName
);
1726 strcpy(accessname
, ctxt
->resourceA
->lpRemoteName
);
1729 static LPWSTR
strdupAtoW( LPCSTR str
)
1734 if (!str
) return NULL
;
1735 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
1736 ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
1737 if (ret
) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
1741 static void netresource_a_to_w( NETRESOURCEA
*resourceA
, NETRESOURCEW
*resourceW
)
1743 resourceW
->dwScope
= resourceA
->dwScope
;
1744 resourceW
->dwType
= resourceA
->dwType
;
1745 resourceW
->dwDisplayType
= resourceA
->dwDisplayType
;
1746 resourceW
->dwUsage
= resourceA
->dwUsage
;
1747 resourceW
->lpLocalName
= strdupAtoW(resourceA
->lpLocalName
);
1748 resourceW
->lpRemoteName
= strdupAtoW(resourceA
->lpRemoteName
);
1749 resourceW
->lpComment
= strdupAtoW(resourceA
->lpComment
);
1750 resourceW
->lpProvider
= strdupAtoW(resourceA
->lpProvider
);
1753 static void free_netresourceW( NETRESOURCEW
*resource
)
1755 HeapFree(GetProcessHeap(), 0, resource
->lpLocalName
);
1756 HeapFree(GetProcessHeap(), 0, resource
->lpRemoteName
);
1757 HeapFree(GetProcessHeap(), 0, resource
->lpComment
);
1758 HeapFree(GetProcessHeap(), 0, resource
->lpProvider
);
1761 /*****************************************************************
1762 * WNetUseConnectionA [MPR.@]
1764 DWORD WINAPI
WNetUseConnectionA( HWND hwndOwner
, NETRESOURCEA
*resource
,
1765 LPCSTR password
, LPCSTR userid
, DWORD flags
, LPSTR accessname
,
1766 DWORD
*buffer_size
, DWORD
*result
)
1768 struct use_connection_context ctxt
;
1769 NETRESOURCEW resourceW
;
1772 TRACE( "(%p, %p, %p, %s, 0x%08X, %p, %p, %p)\n", hwndOwner
, resource
, password
, debugstr_a(userid
), flags
,
1773 accessname
, buffer_size
, result
);
1775 netresource_a_to_w(resource
, &resourceW
);
1777 ctxt
.hwndOwner
= hwndOwner
;
1778 ctxt
.resource
= &resourceW
;
1779 ctxt
.resourceA
= resource
;
1780 ctxt
.password
= strdupAtoW(password
);
1781 ctxt
.userid
= strdupAtoW(userid
);
1783 ctxt
.accessname
= accessname
;
1784 ctxt
.buffer_size
= buffer_size
;
1785 ctxt
.result
= result
;
1786 ctxt
.pre_set_accessname
= use_connection_pre_set_accessnameA
;
1787 ctxt
.set_accessname
= use_connection_set_accessnameA
;
1789 ret
= wnet_use_connection(&ctxt
);
1791 free_netresourceW(&resourceW
);
1792 HeapFree(GetProcessHeap(), 0, ctxt
.password
);
1793 HeapFree(GetProcessHeap(), 0, ctxt
.userid
);
1798 /*********************************************************************
1799 * WNetCancelConnectionA [MPR.@]
1801 DWORD WINAPI
WNetCancelConnectionA( LPCSTR lpName
, BOOL fForce
)
1803 FIXME( "(%s, %d), stub\n", debugstr_a(lpName
), fForce
);
1808 /*********************************************************************
1809 * WNetCancelConnectionW [MPR.@]
1811 DWORD WINAPI
WNetCancelConnectionW( LPCWSTR lpName
, BOOL fForce
)
1813 FIXME( "(%s, %d), stub\n", debugstr_w(lpName
), fForce
);
1818 /*********************************************************************
1819 * WNetCancelConnection2A [MPR.@]
1821 DWORD WINAPI
WNetCancelConnection2A( LPCSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1823 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName
), dwFlags
, fForce
);
1828 /*********************************************************************
1829 * WNetCancelConnection2W [MPR.@]
1831 DWORD WINAPI
WNetCancelConnection2W( LPCWSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1833 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName
), dwFlags
, fForce
);
1838 /*****************************************************************
1839 * WNetRestoreConnectionA [MPR.@]
1841 DWORD WINAPI
WNetRestoreConnectionA( HWND hwndOwner
, LPCSTR lpszDevice
)
1843 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_a(lpszDevice
) );
1845 SetLastError(WN_NO_NETWORK
);
1846 return WN_NO_NETWORK
;
1849 /*****************************************************************
1850 * WNetRestoreConnectionW [MPR.@]
1852 DWORD WINAPI
WNetRestoreConnectionW( HWND hwndOwner
, LPCWSTR lpszDevice
)
1854 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_w(lpszDevice
) );
1856 SetLastError(WN_NO_NETWORK
);
1857 return WN_NO_NETWORK
;
1860 /**************************************************************************
1861 * WNetGetConnectionA [MPR.@]
1864 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1865 * - WN_NOT_CONNECTED drive is a local drive
1866 * - WN_MORE_DATA buffer isn't big enough
1867 * - WN_SUCCESS success (net path in buffer)
1869 * FIXME: need to test return values under different errors
1871 DWORD WINAPI
WNetGetConnectionA( LPCSTR lpLocalName
,
1872 LPSTR lpRemoteName
, LPDWORD lpBufferSize
)
1877 ret
= WN_BAD_POINTER
;
1878 else if (!lpBufferSize
)
1879 ret
= WN_BAD_POINTER
;
1880 else if (!lpRemoteName
&& *lpBufferSize
)
1881 ret
= WN_BAD_POINTER
;
1884 int len
= MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, NULL
, 0);
1888 PWSTR wideLocalName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1892 WCHAR wideRemoteStatic
[MAX_PATH
];
1893 DWORD wideRemoteSize
= sizeof(wideRemoteStatic
) / sizeof(WCHAR
);
1895 MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, wideLocalName
, len
);
1897 /* try once without memory allocation */
1898 ret
= WNetGetConnectionW(wideLocalName
, wideRemoteStatic
,
1900 if (ret
== WN_SUCCESS
)
1902 int len
= WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1903 -1, NULL
, 0, NULL
, NULL
);
1905 if (len
<= *lpBufferSize
)
1907 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
, -1,
1908 lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1913 *lpBufferSize
= len
;
1917 else if (ret
== WN_MORE_DATA
)
1919 PWSTR wideRemote
= HeapAlloc(GetProcessHeap(), 0,
1920 wideRemoteSize
* sizeof(WCHAR
));
1924 ret
= WNetGetConnectionW(wideLocalName
, wideRemote
,
1926 if (ret
== WN_SUCCESS
)
1928 if (len
<= *lpBufferSize
)
1930 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1931 -1, lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1936 *lpBufferSize
= len
;
1940 HeapFree(GetProcessHeap(), 0, wideRemote
);
1943 ret
= WN_OUT_OF_MEMORY
;
1945 HeapFree(GetProcessHeap(), 0, wideLocalName
);
1948 ret
= WN_OUT_OF_MEMORY
;
1951 ret
= WN_BAD_LOCALNAME
;
1955 TRACE("Returning %d\n", ret
);
1959 /* find the network connection for a given drive; helper for WNetGetConnection */
1960 static DWORD
get_drive_connection( WCHAR letter
, LPWSTR remote
, LPDWORD size
)
1963 struct mountmgr_unix_drive
*data
= (struct mountmgr_unix_drive
*)buffer
;
1965 DWORD ret
= WN_NOT_CONNECTED
;
1966 DWORD bytes_returned
;
1968 if ((mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
,
1969 FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
,
1970 0, 0 )) == INVALID_HANDLE_VALUE
)
1972 ERR( "failed to open mount manager err %u\n", GetLastError() );
1975 memset( data
, 0, sizeof(*data
) );
1976 data
->letter
= letter
;
1977 if (DeviceIoControl( mgr
, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
, data
, sizeof(*data
),
1978 data
, sizeof(buffer
), &bytes_returned
, NULL
))
1980 char *p
, *mount_point
= buffer
+ data
->mount_point_offset
;
1983 if (data
->mount_point_offset
&& !strncmp( mount_point
, "unc/", 4 ))
1986 mount_point
[0] = '\\';
1987 for (p
= mount_point
; *p
; p
++) if (*p
== '/') *p
= '\\';
1989 len
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, NULL
, 0 );
1997 *size
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, remote
, *size
);
2006 /**************************************************************************
2007 * WNetGetConnectionW [MPR.@]
2009 * FIXME: need to test return values under different errors
2011 DWORD WINAPI
WNetGetConnectionW( LPCWSTR lpLocalName
,
2012 LPWSTR lpRemoteName
, LPDWORD lpBufferSize
)
2016 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName
), lpRemoteName
,
2020 ret
= WN_BAD_POINTER
;
2021 else if (!lpBufferSize
)
2022 ret
= WN_BAD_POINTER
;
2023 else if (!lpRemoteName
&& *lpBufferSize
)
2024 ret
= WN_BAD_POINTER
;
2025 else if (!lpLocalName
[0])
2026 ret
= WN_BAD_LOCALNAME
;
2029 if (lpLocalName
[1] == ':')
2031 switch(GetDriveTypeW(lpLocalName
))
2034 ret
= get_drive_connection( lpLocalName
[0], lpRemoteName
, lpBufferSize
);
2036 case DRIVE_REMOVABLE
:
2039 TRACE("file is local\n");
2040 ret
= WN_NOT_CONNECTED
;
2043 ret
= WN_BAD_LOCALNAME
;
2047 ret
= WN_BAD_LOCALNAME
;
2051 TRACE("Returning %d\n", ret
);
2055 /**************************************************************************
2056 * WNetSetConnectionA [MPR.@]
2058 DWORD WINAPI
WNetSetConnectionA( LPCSTR lpName
, DWORD dwProperty
,
2061 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName
), dwProperty
, pvValue
);
2063 SetLastError(WN_NO_NETWORK
);
2064 return WN_NO_NETWORK
;
2067 /**************************************************************************
2068 * WNetSetConnectionW [MPR.@]
2070 DWORD WINAPI
WNetSetConnectionW( LPCWSTR lpName
, DWORD dwProperty
,
2073 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName
), dwProperty
, pvValue
);
2075 SetLastError(WN_NO_NETWORK
);
2076 return WN_NO_NETWORK
;
2079 /*****************************************************************
2080 * WNetGetUniversalNameA [MPR.@]
2082 DWORD WINAPI
WNetGetUniversalNameA ( LPCSTR lpLocalPath
, DWORD dwInfoLevel
,
2083 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
2087 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2088 debugstr_a(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
2090 switch (dwInfoLevel
)
2092 case UNIVERSAL_NAME_INFO_LEVEL
:
2094 LPUNIVERSAL_NAME_INFOA info
= lpBuffer
;
2096 if (GetDriveTypeA(lpLocalPath
) != DRIVE_REMOTE
)
2098 err
= ERROR_NOT_CONNECTED
;
2102 size
= sizeof(*info
) + lstrlenA(lpLocalPath
) + 1;
2103 if (*lpBufferSize
< size
)
2108 info
->lpUniversalName
= (char *)info
+ sizeof(*info
);
2109 lstrcpyA(info
->lpUniversalName
, lpLocalPath
);
2113 case REMOTE_NAME_INFO_LEVEL
:
2114 err
= WN_NO_NETWORK
;
2126 /*****************************************************************
2127 * WNetGetUniversalNameW [MPR.@]
2129 DWORD WINAPI
WNetGetUniversalNameW ( LPCWSTR lpLocalPath
, DWORD dwInfoLevel
,
2130 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
2134 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2135 debugstr_w(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
2137 switch (dwInfoLevel
)
2139 case UNIVERSAL_NAME_INFO_LEVEL
:
2141 LPUNIVERSAL_NAME_INFOW info
= lpBuffer
;
2143 if (GetDriveTypeW(lpLocalPath
) != DRIVE_REMOTE
)
2145 err
= ERROR_NOT_CONNECTED
;
2149 size
= sizeof(*info
) + (lstrlenW(lpLocalPath
) + 1) * sizeof(WCHAR
);
2150 if (*lpBufferSize
< size
)
2155 info
->lpUniversalName
= (LPWSTR
)((char *)info
+ sizeof(*info
));
2156 lstrcpyW(info
->lpUniversalName
, lpLocalPath
);
2160 case REMOTE_NAME_INFO_LEVEL
:
2161 err
= WN_NO_NETWORK
;
2169 if (err
!= WN_NO_ERROR
) SetLastError(err
);
2179 /**************************************************************************
2180 * WNetGetUserA [MPR.@]
2182 * FIXME: we should not return ourselves, but the owner of the drive lpName
2184 DWORD WINAPI
WNetGetUserA( LPCSTR lpName
, LPSTR lpUserID
, LPDWORD lpBufferSize
)
2186 if (GetUserNameA( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
2187 return GetLastError();
2190 /*****************************************************************
2191 * WNetGetUserW [MPR.@]
2193 * FIXME: we should not return ourselves, but the owner of the drive lpName
2195 DWORD WINAPI
WNetGetUserW( LPCWSTR lpName
, LPWSTR lpUserID
, LPDWORD lpBufferSize
)
2197 if (GetUserNameW( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
2198 return GetLastError();
2201 /*********************************************************************
2202 * WNetConnectionDialog [MPR.@]
2204 DWORD WINAPI
WNetConnectionDialog( HWND hwnd
, DWORD dwType
)
2206 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2208 SetLastError(WN_NO_NETWORK
);
2209 return WN_NO_NETWORK
;
2212 /*********************************************************************
2213 * WNetConnectionDialog1A [MPR.@]
2215 DWORD WINAPI
WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct
)
2217 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2219 SetLastError(WN_NO_NETWORK
);
2220 return WN_NO_NETWORK
;
2223 /*********************************************************************
2224 * WNetConnectionDialog1W [MPR.@]
2226 DWORD WINAPI
WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct
)
2228 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2230 SetLastError(WN_NO_NETWORK
);
2231 return WN_NO_NETWORK
;
2234 /*********************************************************************
2235 * WNetDisconnectDialog [MPR.@]
2237 DWORD WINAPI
WNetDisconnectDialog( HWND hwnd
, DWORD dwType
)
2239 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2241 SetLastError(WN_NO_NETWORK
);
2242 return WN_NO_NETWORK
;
2245 /*********************************************************************
2246 * WNetDisconnectDialog1A [MPR.@]
2248 DWORD WINAPI
WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct
)
2250 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2252 SetLastError(WN_NO_NETWORK
);
2253 return WN_NO_NETWORK
;
2256 /*********************************************************************
2257 * WNetDisconnectDialog1W [MPR.@]
2259 DWORD WINAPI
WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct
)
2261 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2263 SetLastError(WN_NO_NETWORK
);
2264 return WN_NO_NETWORK
;
2267 /*********************************************************************
2268 * WNetGetLastErrorA [MPR.@]
2270 DWORD WINAPI
WNetGetLastErrorA( LPDWORD lpError
,
2271 LPSTR lpErrorBuf
, DWORD nErrorBufSize
,
2272 LPSTR lpNameBuf
, DWORD nNameBufSize
)
2274 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2275 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2277 SetLastError(WN_NO_NETWORK
);
2278 return WN_NO_NETWORK
;
2281 /*********************************************************************
2282 * WNetGetLastErrorW [MPR.@]
2284 DWORD WINAPI
WNetGetLastErrorW( LPDWORD lpError
,
2285 LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
2286 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
2288 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2289 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2291 SetLastError(WN_NO_NETWORK
);
2292 return WN_NO_NETWORK
;
2295 /*********************************************************************
2296 * WNetGetNetworkInformationA [MPR.@]
2298 DWORD WINAPI
WNetGetNetworkInformationA( LPCSTR lpProvider
,
2299 LPNETINFOSTRUCT lpNetInfoStruct
)
2303 TRACE( "(%s, %p)\n", debugstr_a(lpProvider
), lpNetInfoStruct
);
2306 ret
= WN_BAD_POINTER
;
2311 len
= MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, NULL
, 0);
2314 LPWSTR wideProvider
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2318 MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, wideProvider
,
2320 ret
= WNetGetNetworkInformationW(wideProvider
, lpNetInfoStruct
);
2321 HeapFree(GetProcessHeap(), 0, wideProvider
);
2324 ret
= WN_OUT_OF_MEMORY
;
2327 ret
= GetLastError();
2331 TRACE("Returning %d\n", ret
);
2335 /*********************************************************************
2336 * WNetGetNetworkInformationW [MPR.@]
2338 DWORD WINAPI
WNetGetNetworkInformationW( LPCWSTR lpProvider
,
2339 LPNETINFOSTRUCT lpNetInfoStruct
)
2343 TRACE( "(%s, %p)\n", debugstr_w(lpProvider
), lpNetInfoStruct
);
2346 ret
= WN_BAD_POINTER
;
2347 else if (!lpNetInfoStruct
)
2348 ret
= WN_BAD_POINTER
;
2349 else if (lpNetInfoStruct
->cbStructure
< sizeof(NETINFOSTRUCT
))
2353 if (providerTable
&& providerTable
->numProviders
)
2355 DWORD providerIndex
= _findProviderIndexW(lpProvider
);
2357 if (providerIndex
!= BAD_PROVIDER_INDEX
)
2359 lpNetInfoStruct
->cbStructure
= sizeof(NETINFOSTRUCT
);
2360 lpNetInfoStruct
->dwProviderVersion
=
2361 providerTable
->table
[providerIndex
].dwSpecVersion
;
2362 lpNetInfoStruct
->dwStatus
= NO_ERROR
;
2363 lpNetInfoStruct
->dwCharacteristics
= 0;
2364 lpNetInfoStruct
->dwHandle
= 0;
2365 lpNetInfoStruct
->wNetType
=
2366 HIWORD(providerTable
->table
[providerIndex
].dwNetType
);
2367 lpNetInfoStruct
->dwPrinters
= -1;
2368 lpNetInfoStruct
->dwDrives
= -1;
2372 ret
= WN_BAD_PROVIDER
;
2375 ret
= WN_NO_NETWORK
;
2379 TRACE("Returning %d\n", ret
);
2383 /*****************************************************************
2384 * WNetGetProviderNameA [MPR.@]
2386 DWORD WINAPI
WNetGetProviderNameA( DWORD dwNetType
,
2387 LPSTR lpProvider
, LPDWORD lpBufferSize
)
2391 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_a(lpProvider
),
2395 ret
= WN_BAD_POINTER
;
2396 else if (!lpBufferSize
)
2397 ret
= WN_BAD_POINTER
;
2404 ret
= WN_NO_NETWORK
;
2405 for (i
= 0; i
< providerTable
->numProviders
&&
2406 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2409 if (i
< providerTable
->numProviders
)
2411 DWORD sizeNeeded
= WideCharToMultiByte(CP_ACP
, 0,
2412 providerTable
->table
[i
].name
, -1, NULL
, 0, NULL
, NULL
);
2414 if (*lpBufferSize
< sizeNeeded
)
2416 *lpBufferSize
= sizeNeeded
;
2421 WideCharToMultiByte(CP_ACP
, 0, providerTable
->table
[i
].name
,
2422 -1, lpProvider
, *lpBufferSize
, NULL
, NULL
);
2424 /* FIXME: is *lpBufferSize set to the number of characters
2430 ret
= WN_NO_NETWORK
;
2434 TRACE("Returning %d\n", ret
);
2438 /*****************************************************************
2439 * WNetGetProviderNameW [MPR.@]
2441 DWORD WINAPI
WNetGetProviderNameW( DWORD dwNetType
,
2442 LPWSTR lpProvider
, LPDWORD lpBufferSize
)
2446 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_w(lpProvider
),
2450 ret
= WN_BAD_POINTER
;
2451 else if (!lpBufferSize
)
2452 ret
= WN_BAD_POINTER
;
2459 ret
= WN_NO_NETWORK
;
2460 for (i
= 0; i
< providerTable
->numProviders
&&
2461 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2464 if (i
< providerTable
->numProviders
)
2466 DWORD sizeNeeded
= strlenW(providerTable
->table
[i
].name
) + 1;
2468 if (*lpBufferSize
< sizeNeeded
)
2470 *lpBufferSize
= sizeNeeded
;
2475 strcpyW(lpProvider
, providerTable
->table
[i
].name
);
2477 /* FIXME: is *lpBufferSize set to the number of characters
2483 ret
= WN_NO_NETWORK
;
2487 TRACE("Returning %d\n", ret
);