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
27 #define WINE_MOUNTMGR_EXTENSIONS
28 #include <ddk/mountmgr.h>
29 #include <wine/unicode.h>
31 /* Data structures representing network service providers. Assumes only one
32 * thread creates them, and that they are constant for the life of the process
33 * (and therefore doesn't synchronize access).
34 * FIXME: only basic provider data and enumeration-related data are implemented
35 * so far, need to implement the rest too.
37 typedef struct _WNetProvider
45 PF_NPOpenEnum openEnum
;
46 PF_NPEnumResource enumResource
;
47 PF_NPCloseEnum closeEnum
;
48 PF_NPGetResourceInformation getResourceInformation
;
49 PF_NPAddConnection addConnection
;
50 PF_NPAddConnection3 addConnection3
;
51 } WNetProvider
, *PWNetProvider
;
53 typedef struct _WNetProviderTable
58 WNetProvider table
[1];
59 } WNetProviderTable
, *PWNetProviderTable
;
61 #define WNET_ENUMERATOR_TYPE_NULL 0
62 #define WNET_ENUMERATOR_TYPE_GLOBAL 1
63 #define WNET_ENUMERATOR_TYPE_PROVIDER 2
64 #define WNET_ENUMERATOR_TYPE_CONTEXT 3
66 /* An WNet enumerator. Note that the type doesn't correspond to the scope of
67 * the enumeration; it represents one of the following types:
68 * - a 'null' enumeration, one that contains no members
69 * - a global enumeration, one that's executed across all providers
70 * - a provider-specific enumeration, one that's only executed by a single
72 * - a context enumeration. I know this contradicts what I just said about
73 * there being no correspondence between the scope and the type, but it's
74 * necessary for the special case that a "Entire Network" entry needs to
75 * be enumerated in an enumeration of the context scope. Thus an enumeration
76 * of the context scope results in a context type enumerator, which morphs
77 * into a global enumeration (so the enumeration continues across all
80 typedef struct _WNetEnumerator
90 } WNetEnumerator
, *PWNetEnumerator
;
92 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff
94 /* Returns an index (into the global WNetProviderTable) of the provider with
95 * the given name, or BAD_PROVIDER_INDEX if not found.
97 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
);
99 static PWNetProviderTable providerTable
;
102 * Global provider table functions
105 static void _tryLoadProvider(PCWSTR provider
)
107 static const WCHAR servicePrefix
[] = { 'S','y','s','t','e','m','\\',
108 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
109 'S','e','r','v','i','c','e','s','\\',0 };
110 static const WCHAR serviceFmt
[] = { '%','s','%','s','\\',
111 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 };
112 WCHAR serviceName
[MAX_PATH
];
115 TRACE("%s\n", debugstr_w(provider
));
116 snprintfW(serviceName
, sizeof(serviceName
) / sizeof(WCHAR
), serviceFmt
,
117 servicePrefix
, provider
);
118 serviceName
[sizeof(serviceName
) / sizeof(WCHAR
) - 1] = '\0';
119 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, serviceName
, 0, KEY_READ
, &hKey
) ==
122 static const WCHAR szProviderPath
[] = { 'P','r','o','v','i','d','e','r',
124 WCHAR providerPath
[MAX_PATH
];
125 DWORD type
, size
= sizeof(providerPath
);
127 if (RegQueryValueExW(hKey
, szProviderPath
, NULL
, &type
,
128 (LPBYTE
)providerPath
, &size
) == ERROR_SUCCESS
&& (type
== REG_SZ
|| type
== REG_EXPAND_SZ
))
130 static const WCHAR szProviderName
[] = { 'N','a','m','e',0 };
133 if (type
== REG_EXPAND_SZ
)
135 WCHAR path
[MAX_PATH
];
136 if (ExpandEnvironmentStringsW(providerPath
, path
, MAX_PATH
)) lstrcpyW( providerPath
, path
);
140 RegQueryValueExW(hKey
, szProviderName
, NULL
, NULL
, NULL
, &size
);
143 name
= HeapAlloc(GetProcessHeap(), 0, size
);
144 if (RegQueryValueExW(hKey
, szProviderName
, NULL
, &type
,
145 (LPBYTE
)name
, &size
) != ERROR_SUCCESS
|| type
!= REG_SZ
)
147 HeapFree(GetProcessHeap(), 0, name
);
153 HMODULE hLib
= LoadLibraryW(providerPath
);
157 #define MPR_GETPROC(proc) ((PF_##proc)GetProcAddress(hLib, #proc))
159 PF_NPGetCaps getCaps
= MPR_GETPROC(NPGetCaps
);
161 TRACE("loaded lib %p\n", hLib
);
164 PWNetProvider provider
=
165 &providerTable
->table
[providerTable
->numProviders
];
167 provider
->hLib
= hLib
;
168 provider
->name
= name
;
169 TRACE("name is %s\n", debugstr_w(name
));
170 provider
->getCaps
= getCaps
;
171 provider
->dwSpecVersion
= getCaps(WNNC_SPEC_VERSION
);
172 provider
->dwNetType
= getCaps(WNNC_NET_TYPE
);
173 TRACE("net type is 0x%08x\n", provider
->dwNetType
);
174 provider
->dwEnumScopes
= getCaps(WNNC_ENUMERATION
);
175 if (provider
->dwEnumScopes
)
177 TRACE("supports enumeration\n");
178 provider
->openEnum
= MPR_GETPROC(NPOpenEnum
);
179 TRACE("NPOpenEnum %p\n", provider
->openEnum
);
180 provider
->enumResource
= MPR_GETPROC(NPEnumResource
);
181 TRACE("NPEnumResource %p\n", provider
->enumResource
);
182 provider
->closeEnum
= MPR_GETPROC(NPCloseEnum
);
183 TRACE("NPCloseEnum %p\n", provider
->closeEnum
);
184 provider
->getResourceInformation
= MPR_GETPROC(NPGetResourceInformation
);
185 TRACE("NPGetResourceInformation %p\n", provider
->getResourceInformation
);
186 if (!provider
->openEnum
||
187 !provider
->enumResource
||
188 !provider
->closeEnum
)
190 provider
->openEnum
= NULL
;
191 provider
->enumResource
= NULL
;
192 provider
->closeEnum
= NULL
;
193 provider
->dwEnumScopes
= 0;
194 WARN("Couldn't load enumeration functions\n");
197 provider
->addConnection
= MPR_GETPROC(NPAddConnection
);
198 provider
->addConnection3
= MPR_GETPROC(NPAddConnection3
);
199 TRACE("NPAddConnection %p\n", provider
->addConnection
);
200 TRACE("NPAddConnection3 %p\n", provider
->addConnection3
);
201 providerTable
->numProviders
++;
205 WARN("Provider %s didn't export NPGetCaps\n",
206 debugstr_w(provider
));
207 HeapFree(GetProcessHeap(), 0, name
);
215 WARN("Couldn't load library %s for provider %s\n",
216 debugstr_w(providerPath
), debugstr_w(provider
));
217 HeapFree(GetProcessHeap(), 0, name
);
222 WARN("Couldn't get provider name for provider %s\n",
223 debugstr_w(provider
));
227 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath
));
231 WARN("Couldn't open service key for provider %s\n",
232 debugstr_w(provider
));
235 void wnetInit(HINSTANCE hInstDll
)
237 static const WCHAR providerOrderKey
[] = { 'S','y','s','t','e','m','\\',
238 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
239 'C','o','n','t','r','o','l','\\',
240 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\',
241 'O','r','d','e','r',0 };
242 static const WCHAR providerOrder
[] = { 'P','r','o','v','i','d','e','r',
243 'O','r','d','e','r',0 };
246 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, providerOrderKey
, 0, KEY_READ
, &hKey
)
251 RegQueryValueExW(hKey
, providerOrder
, NULL
, NULL
, NULL
, &size
);
254 PWSTR providers
= HeapAlloc(GetProcessHeap(), 0, size
);
260 if (RegQueryValueExW(hKey
, providerOrder
, NULL
, &type
,
261 (LPBYTE
)providers
, &size
) == ERROR_SUCCESS
&& type
== REG_SZ
)
266 TRACE("provider order is %s\n", debugstr_w(providers
));
267 /* first count commas as a heuristic for how many to
268 * allocate space for */
269 for (ptr
= providers
, numToAllocate
= 1; ptr
; )
271 ptr
= strchrW(ptr
, ',');
278 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
279 sizeof(WNetProviderTable
)
280 + (numToAllocate
- 1) * sizeof(WNetProvider
));
284 int entireNetworkLen
;
285 LPCWSTR stringresource
;
287 entireNetworkLen
= LoadStringW(hInstDll
,
288 IDS_ENTIRENETWORK
, (LPWSTR
)&stringresource
, 0);
289 providerTable
->entireNetwork
= HeapAlloc(
290 GetProcessHeap(), 0, (entireNetworkLen
+ 1) *
292 if (providerTable
->entireNetwork
)
294 memcpy(providerTable
->entireNetwork
, stringresource
, entireNetworkLen
*sizeof(WCHAR
));
295 providerTable
->entireNetwork
[entireNetworkLen
] = 0;
297 providerTable
->numAllocated
= numToAllocate
;
298 for (ptr
= providers
; ptr
; )
301 ptr
= strchrW(ptr
, ',');
304 _tryLoadProvider(ptrPrev
);
308 HeapFree(GetProcessHeap(), 0, providers
);
321 for (i
= 0; i
< providerTable
->numProviders
; i
++)
323 HeapFree(GetProcessHeap(), 0, providerTable
->table
[i
].name
);
324 FreeModule(providerTable
->table
[i
].hLib
);
326 HeapFree(GetProcessHeap(), 0, providerTable
->entireNetwork
);
327 HeapFree(GetProcessHeap(), 0, providerTable
);
328 providerTable
= NULL
;
332 static DWORD
_findProviderIndexW(LPCWSTR lpProvider
)
334 DWORD ret
= BAD_PROVIDER_INDEX
;
336 if (providerTable
&& providerTable
->numProviders
)
340 for (i
= 0; i
< providerTable
->numProviders
&&
341 ret
== BAD_PROVIDER_INDEX
; i
++)
342 if (!strcmpW(lpProvider
, providerTable
->table
[i
].name
))
352 static LPNETRESOURCEW
_copyNetResourceForEnumW(LPNETRESOURCEW lpNet
)
358 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW
));
364 ret
->lpLocalName
= ret
->lpComment
= ret
->lpProvider
= NULL
;
365 if (lpNet
->lpRemoteName
)
367 len
= strlenW(lpNet
->lpRemoteName
) + 1;
368 ret
->lpRemoteName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
369 if (ret
->lpRemoteName
)
370 strcpyW(ret
->lpRemoteName
, lpNet
->lpRemoteName
);
379 static void _freeEnumNetResource(LPNETRESOURCEW lpNet
)
383 HeapFree(GetProcessHeap(), 0, lpNet
->lpRemoteName
);
384 HeapFree(GetProcessHeap(), 0, lpNet
);
388 static PWNetEnumerator
_createNullEnumerator(void)
390 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
391 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
394 ret
->enumType
= WNET_ENUMERATOR_TYPE_NULL
;
398 static PWNetEnumerator
_createGlobalEnumeratorW(DWORD dwScope
, DWORD dwType
,
399 DWORD dwUsage
, LPNETRESOURCEW lpNet
)
401 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
402 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
406 ret
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
407 ret
->dwScope
= dwScope
;
408 ret
->dwType
= dwType
;
409 ret
->dwUsage
= dwUsage
;
410 ret
->lpNet
= _copyNetResourceForEnumW(lpNet
);
415 static PWNetEnumerator
_createProviderEnumerator(DWORD dwScope
, DWORD dwType
,
416 DWORD dwUsage
, DWORD index
, HANDLE handle
)
420 if (!providerTable
|| index
>= providerTable
->numProviders
)
424 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
427 ret
->enumType
= WNET_ENUMERATOR_TYPE_PROVIDER
;
428 ret
->providerIndex
= index
;
429 ret
->dwScope
= dwScope
;
430 ret
->dwType
= dwType
;
431 ret
->dwUsage
= dwUsage
;
432 ret
->handle
= handle
;
438 static PWNetEnumerator
_createContextEnumerator(DWORD dwScope
, DWORD dwType
,
441 PWNetEnumerator ret
= HeapAlloc(GetProcessHeap(),
442 HEAP_ZERO_MEMORY
, sizeof(WNetEnumerator
));
446 ret
->enumType
= WNET_ENUMERATOR_TYPE_CONTEXT
;
447 ret
->dwScope
= dwScope
;
448 ret
->dwType
= dwType
;
449 ret
->dwUsage
= dwUsage
;
454 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer
455 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
456 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
457 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
458 * if not all members of the array could be thunked, and something else on
461 static DWORD
_thunkNetResourceArrayWToA(const NETRESOURCEW
*lpNetArrayIn
,
462 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
464 DWORD i
, numToThunk
, totalBytes
, ret
;
468 return WN_BAD_POINTER
;
470 return WN_BAD_POINTER
;
474 return WN_BAD_POINTER
;
476 return WN_BAD_POINTER
;
478 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
480 const NETRESOURCEW
*lpNet
= lpNetArrayIn
+ i
;
482 totalBytes
+= sizeof(NETRESOURCEA
);
483 if (lpNet
->lpLocalName
)
484 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpLocalName
,
485 -1, NULL
, 0, NULL
, NULL
);
486 if (lpNet
->lpRemoteName
)
487 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpRemoteName
,
488 -1, NULL
, 0, NULL
, NULL
);
489 if (lpNet
->lpComment
)
490 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpComment
,
491 -1, NULL
, 0, NULL
, NULL
);
492 if (lpNet
->lpProvider
)
493 totalBytes
+= WideCharToMultiByte(CP_ACP
, 0, lpNet
->lpProvider
,
494 -1, NULL
, 0, NULL
, NULL
);
495 if (totalBytes
< *lpBufferSize
)
498 strNext
= (LPSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEA
));
499 for (i
= 0; i
< numToThunk
; i
++)
501 LPNETRESOURCEA lpNetOut
= (LPNETRESOURCEA
)lpBuffer
+ i
;
502 const NETRESOURCEW
*lpNetIn
= lpNetArrayIn
+ i
;
504 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEA
));
505 /* lie about string lengths, we already verified how many
506 * we have space for above
508 if (lpNetIn
->lpLocalName
)
510 lpNetOut
->lpLocalName
= strNext
;
511 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpLocalName
, -1,
512 lpNetOut
->lpLocalName
, *lpBufferSize
, NULL
, NULL
);
514 if (lpNetIn
->lpRemoteName
)
516 lpNetOut
->lpRemoteName
= strNext
;
517 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpRemoteName
, -1,
518 lpNetOut
->lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
520 if (lpNetIn
->lpComment
)
522 lpNetOut
->lpComment
= strNext
;
523 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpComment
, -1,
524 lpNetOut
->lpComment
, *lpBufferSize
, NULL
, NULL
);
526 if (lpNetIn
->lpProvider
)
528 lpNetOut
->lpProvider
= strNext
;
529 strNext
+= WideCharToMultiByte(CP_ACP
, 0, lpNetIn
->lpProvider
, -1,
530 lpNetOut
->lpProvider
, *lpBufferSize
, NULL
, NULL
);
533 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
534 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
539 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer
540 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries
541 * to start. On return, *lpcCount reflects the number thunked into lpBuffer.
542 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA
543 * if not all members of the array could be thunked, and something else on
546 static DWORD
_thunkNetResourceArrayAToW(const NETRESOURCEA
*lpNetArrayIn
,
547 const DWORD
*lpcCount
, LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
549 DWORD i
, numToThunk
, totalBytes
, ret
;
553 return WN_BAD_POINTER
;
555 return WN_BAD_POINTER
;
559 return WN_BAD_POINTER
;
561 return WN_BAD_POINTER
;
563 for (i
= 0, numToThunk
= 0, totalBytes
= 0; i
< *lpcCount
; i
++)
565 const NETRESOURCEA
*lpNet
= lpNetArrayIn
+ i
;
567 totalBytes
+= sizeof(NETRESOURCEW
);
568 if (lpNet
->lpLocalName
)
569 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpLocalName
,
570 -1, NULL
, 0) * sizeof(WCHAR
);
571 if (lpNet
->lpRemoteName
)
572 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpRemoteName
,
573 -1, NULL
, 0) * sizeof(WCHAR
);
574 if (lpNet
->lpComment
)
575 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpComment
,
576 -1, NULL
, 0) * sizeof(WCHAR
);
577 if (lpNet
->lpProvider
)
578 totalBytes
+= MultiByteToWideChar(CP_ACP
, 0, lpNet
->lpProvider
,
579 -1, NULL
, 0) * sizeof(WCHAR
);
580 if (totalBytes
< *lpBufferSize
)
583 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ numToThunk
* sizeof(NETRESOURCEW
));
584 for (i
= 0; i
< numToThunk
; i
++)
586 LPNETRESOURCEW lpNetOut
= (LPNETRESOURCEW
)lpBuffer
+ i
;
587 const NETRESOURCEA
*lpNetIn
= lpNetArrayIn
+ i
;
589 memcpy(lpNetOut
, lpNetIn
, sizeof(NETRESOURCEW
));
590 /* lie about string lengths, we already verified how many
591 * we have space for above
593 if (lpNetIn
->lpLocalName
)
595 lpNetOut
->lpLocalName
= strNext
;
596 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpLocalName
,
597 -1, lpNetOut
->lpLocalName
, *lpBufferSize
);
599 if (lpNetIn
->lpRemoteName
)
601 lpNetOut
->lpRemoteName
= strNext
;
602 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpRemoteName
,
603 -1, lpNetOut
->lpRemoteName
, *lpBufferSize
);
605 if (lpNetIn
->lpComment
)
607 lpNetOut
->lpComment
= strNext
;
608 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpComment
,
609 -1, lpNetOut
->lpComment
, *lpBufferSize
);
611 if (lpNetIn
->lpProvider
)
613 lpNetOut
->lpProvider
= strNext
;
614 strNext
+= MultiByteToWideChar(CP_ACP
, 0, lpNetIn
->lpProvider
,
615 -1, lpNetOut
->lpProvider
, *lpBufferSize
);
618 ret
= numToThunk
< *lpcCount
? WN_MORE_DATA
: WN_SUCCESS
;
619 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk
,
624 /*********************************************************************
625 * WNetOpenEnumA [MPR.@]
627 * See comments for WNetOpenEnumW.
629 DWORD WINAPI
WNetOpenEnumA( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
630 LPNETRESOURCEA lpNet
, LPHANDLE lphEnum
)
634 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
635 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
638 ret
= WN_BAD_POINTER
;
639 else if (!providerTable
|| providerTable
->numProviders
== 0)
648 LPNETRESOURCEW lpNetWide
= NULL
;
650 DWORD size
= sizeof(buf
), count
= 1;
651 BOOL allocated
= FALSE
;
653 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, buf
, &size
);
654 if (ret
== WN_MORE_DATA
)
656 lpNetWide
= HeapAlloc(GetProcessHeap(), 0,
660 ret
= _thunkNetResourceArrayAToW(lpNet
, &count
, lpNetWide
,
665 ret
= WN_OUT_OF_MEMORY
;
667 else if (ret
== WN_SUCCESS
)
668 lpNetWide
= (LPNETRESOURCEW
)buf
;
669 if (ret
== WN_SUCCESS
)
670 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, lpNetWide
,
673 HeapFree(GetProcessHeap(), 0, lpNetWide
);
676 ret
= WNetOpenEnumW(dwScope
, dwType
, dwUsage
, NULL
, lphEnum
);
680 TRACE("Returning %d\n", ret
);
684 /*********************************************************************
685 * WNetOpenEnumW [MPR.@]
687 * Network enumeration has way too many parameters, so I'm not positive I got
688 * them right. What I've got so far:
690 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed,
691 * all the network providers should be enumerated.
693 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
694 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's
695 * lpProvider is set, all the network providers should be enumerated.
696 * (This means the enumeration is a list of network providers, not that the
697 * enumeration is passed on to the providers.)
699 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the
700 * resource matches the "Entire Network" resource (no remote name, no
701 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET
702 * enumeration is done on every network provider.
704 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
705 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through
706 * only to the given network provider.
708 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and
709 * no lpProvider is set, enumeration will be tried on every network provider,
710 * in the order in which they're loaded.
712 * - The LPNETRESOURCE should be disregarded for scopes besides
713 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not
714 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL.
716 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net
717 * resource in the enumerated list, as well as any machines in your
718 * workgroup. The machines in your workgroup come from doing a
719 * RESOURCE_CONTEXT enumeration of every Network Provider.
721 DWORD WINAPI
WNetOpenEnumW( DWORD dwScope
, DWORD dwType
, DWORD dwUsage
,
722 LPNETRESOURCEW lpNet
, LPHANDLE lphEnum
)
726 TRACE( "(%08X, %08X, %08X, %p, %p)\n",
727 dwScope
, dwType
, dwUsage
, lpNet
, lphEnum
);
730 ret
= WN_BAD_POINTER
;
731 else if (!providerTable
|| providerTable
->numProviders
== 0)
740 case RESOURCE_GLOBALNET
:
743 if (lpNet
->lpProvider
)
745 DWORD index
= _findProviderIndexW(lpNet
->lpProvider
);
747 if (index
!= BAD_PROVIDER_INDEX
)
749 if (providerTable
->table
[index
].openEnum
&&
750 providerTable
->table
[index
].dwEnumScopes
& WNNC_ENUM_GLOBAL
)
754 ret
= providerTable
->table
[index
].openEnum(
755 dwScope
, dwType
, dwUsage
, lpNet
, &handle
);
756 if (ret
== WN_SUCCESS
)
758 *lphEnum
= _createProviderEnumerator(
759 dwScope
, dwType
, dwUsage
, index
, handle
);
760 ret
= *lphEnum
? WN_SUCCESS
:
765 ret
= WN_NOT_SUPPORTED
;
768 ret
= WN_BAD_PROVIDER
;
770 else if (lpNet
->lpRemoteName
)
772 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
773 dwType
, dwUsage
, lpNet
);
774 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
778 if (lpNet
->lpComment
&& !strcmpW(lpNet
->lpComment
,
779 providerTable
->entireNetwork
))
781 /* comment matches the "Entire Network", enumerate
782 * global scope of every provider
784 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
785 dwType
, dwUsage
, lpNet
);
789 /* this is the same as not having passed lpNet */
790 *lphEnum
= _createGlobalEnumeratorW(dwScope
,
791 dwType
, dwUsage
, NULL
);
793 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
798 *lphEnum
= _createGlobalEnumeratorW(dwScope
, dwType
,
800 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
803 case RESOURCE_CONTEXT
:
804 *lphEnum
= _createContextEnumerator(dwScope
, dwType
, dwUsage
);
805 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
807 case RESOURCE_REMEMBERED
:
808 case RESOURCE_CONNECTED
:
809 *lphEnum
= _createNullEnumerator();
810 ret
= *lphEnum
? WN_SUCCESS
: WN_OUT_OF_MEMORY
;
813 WARN("unknown scope 0x%08x\n", dwScope
);
819 TRACE("Returning %d\n", ret
);
823 /*********************************************************************
824 * WNetEnumResourceA [MPR.@]
826 DWORD WINAPI
WNetEnumResourceA( HANDLE hEnum
, LPDWORD lpcCount
,
827 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
831 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
834 ret
= WN_BAD_POINTER
;
836 ret
= WN_BAD_POINTER
;
838 ret
= WN_BAD_POINTER
;
839 else if (!lpBufferSize
)
840 ret
= WN_BAD_POINTER
;
841 else if (*lpBufferSize
< sizeof(NETRESOURCEA
))
843 *lpBufferSize
= sizeof(NETRESOURCEA
);
848 DWORD localCount
= *lpcCount
, localSize
= *lpBufferSize
;
849 LPVOID localBuffer
= HeapAlloc(GetProcessHeap(), 0, localSize
);
853 ret
= WNetEnumResourceW(hEnum
, &localCount
, localBuffer
,
855 if (ret
== WN_SUCCESS
|| (ret
== WN_MORE_DATA
&& localCount
!= -1))
857 /* FIXME: this isn't necessarily going to work in the case of
858 * WN_MORE_DATA, because our enumerator may have moved on to
859 * the next provider. MSDN states that a large (16KB) buffer
860 * size is the appropriate usage of this function, so
861 * hopefully it won't be an issue.
863 ret
= _thunkNetResourceArrayWToA(localBuffer
, &localCount
,
864 lpBuffer
, lpBufferSize
);
865 *lpcCount
= localCount
;
867 HeapFree(GetProcessHeap(), 0, localBuffer
);
870 ret
= WN_OUT_OF_MEMORY
;
874 TRACE("Returning %d\n", ret
);
878 static DWORD
_countProviderBytesW(PWNetProvider provider
)
884 ret
= sizeof(NETRESOURCEW
);
885 ret
+= 2 * (strlenW(provider
->name
) + 1) * sizeof(WCHAR
);
892 static DWORD
_enumerateProvidersW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
893 LPVOID lpBuffer
, const DWORD
*lpBufferSize
)
898 return WN_BAD_POINTER
;
899 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
902 return WN_BAD_POINTER
;
904 return WN_BAD_POINTER
;
906 return WN_BAD_POINTER
;
907 if (*lpBufferSize
< sizeof(NETRESOURCEA
))
910 if (!providerTable
|| enumerator
->providerIndex
>=
911 providerTable
->numProviders
)
912 ret
= WN_NO_MORE_ENTRIES
;
915 DWORD bytes
= 0, count
= 0, countLimit
, i
;
916 LPNETRESOURCEW resource
;
919 countLimit
= *lpcCount
== -1 ?
920 providerTable
->numProviders
- enumerator
->providerIndex
: *lpcCount
;
921 while (count
< countLimit
&& bytes
< *lpBufferSize
)
923 DWORD bytesNext
= _countProviderBytesW(
924 &providerTable
->table
[count
+ enumerator
->providerIndex
]);
926 if (bytes
+ bytesNext
< *lpBufferSize
)
932 strNext
= (LPWSTR
)((LPBYTE
)lpBuffer
+ count
* sizeof(NETRESOURCEW
));
933 for (i
= 0, resource
= lpBuffer
; i
< count
; i
++, resource
++)
935 resource
->dwScope
= RESOURCE_GLOBALNET
;
936 resource
->dwType
= RESOURCETYPE_ANY
;
937 resource
->dwDisplayType
= RESOURCEDISPLAYTYPE_NETWORK
;
938 resource
->dwUsage
= RESOURCEUSAGE_CONTAINER
|
939 RESOURCEUSAGE_RESERVED
;
940 resource
->lpLocalName
= NULL
;
941 resource
->lpRemoteName
= strNext
;
942 strcpyW(resource
->lpRemoteName
,
943 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
944 strNext
+= strlenW(resource
->lpRemoteName
) + 1;
945 resource
->lpComment
= NULL
;
946 resource
->lpProvider
= strNext
;
947 strcpyW(resource
->lpProvider
,
948 providerTable
->table
[i
+ enumerator
->providerIndex
].name
);
949 strNext
+= strlenW(resource
->lpProvider
) + 1;
951 enumerator
->providerIndex
+= count
;
953 ret
= count
> 0 ? WN_SUCCESS
: WN_MORE_DATA
;
955 TRACE("Returning %d\n", ret
);
959 /* Advances the enumerator (assumed to be a global enumerator) to the next
960 * provider that supports the enumeration scope passed to WNetOpenEnum. Does
961 * not open a handle with the next provider.
962 * If the existing handle is NULL, may leave the enumerator unchanged, since
963 * the current provider may support the desired scope.
964 * If the existing handle is not NULL, closes it before moving on.
965 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available
966 * provider, and another error on failure.
968 static DWORD
_globalEnumeratorAdvance(PWNetEnumerator enumerator
)
971 return WN_BAD_POINTER
;
972 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
974 if (!providerTable
|| enumerator
->providerIndex
>=
975 providerTable
->numProviders
)
976 return WN_NO_MORE_ENTRIES
;
978 if (enumerator
->providerDone
)
981 enumerator
->providerDone
= FALSE
;
982 if (enumerator
->handle
)
984 providerTable
->table
[enumerator
->providerIndex
].closeEnum(
986 enumerator
->handle
= NULL
;
987 enumerator
->providerIndex
++;
989 if (enumerator
->dwScope
== RESOURCE_CONNECTED
)
990 dwEnum
= WNNC_ENUM_LOCAL
;
991 else if (enumerator
->dwScope
== RESOURCE_GLOBALNET
)
992 dwEnum
= WNNC_ENUM_GLOBAL
;
993 else if (enumerator
->dwScope
== RESOURCE_CONTEXT
)
994 dwEnum
= WNNC_ENUM_CONTEXT
;
995 for (; enumerator
->providerIndex
< providerTable
->numProviders
&&
996 !(providerTable
->table
[enumerator
->providerIndex
].dwEnumScopes
997 & dwEnum
); enumerator
->providerIndex
++)
1000 return enumerator
->providerIndex
< providerTable
->numProviders
?
1001 WN_SUCCESS
: WN_NO_MORE_ENTRIES
;
1004 /* "Passes through" call to the next provider that supports the enumeration
1006 * FIXME: if one call to a provider's enumerator succeeds while there's still
1007 * space in lpBuffer, I don't call to the next provider. The caller may not
1008 * expect that it should call EnumResourceW again with a return value of
1009 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings
1010 * may have to be moved around a bit, ick.
1012 static DWORD
_enumerateGlobalPassthroughW(PWNetEnumerator enumerator
,
1013 LPDWORD lpcCount
, LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1018 return WN_BAD_POINTER
;
1019 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1020 return WN_BAD_VALUE
;
1022 return WN_BAD_POINTER
;
1024 return WN_BAD_POINTER
;
1026 return WN_BAD_POINTER
;
1027 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1028 return WN_MORE_DATA
;
1030 ret
= _globalEnumeratorAdvance(enumerator
);
1031 if (ret
== WN_SUCCESS
)
1033 ret
= providerTable
->table
[enumerator
->providerIndex
].
1034 openEnum(enumerator
->dwScope
, enumerator
->dwType
,
1035 enumerator
->dwUsage
, enumerator
->lpNet
,
1036 &enumerator
->handle
);
1037 if (ret
== WN_SUCCESS
)
1039 ret
= providerTable
->table
[enumerator
->providerIndex
].
1040 enumResource(enumerator
->handle
, lpcCount
, lpBuffer
,
1042 if (ret
!= WN_MORE_DATA
)
1043 enumerator
->providerDone
= TRUE
;
1046 TRACE("Returning %d\n", ret
);
1050 static DWORD
_enumerateGlobalW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1051 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1056 return WN_BAD_POINTER
;
1057 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_GLOBAL
)
1058 return WN_BAD_VALUE
;
1060 return WN_BAD_POINTER
;
1062 return WN_BAD_POINTER
;
1064 return WN_BAD_POINTER
;
1065 if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1066 return WN_MORE_DATA
;
1068 return WN_NO_NETWORK
;
1070 switch (enumerator
->dwScope
)
1072 case RESOURCE_GLOBALNET
:
1073 if (enumerator
->lpNet
)
1074 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
,
1075 lpBuffer
, lpBufferSize
);
1077 ret
= _enumerateProvidersW(enumerator
, lpcCount
, lpBuffer
,
1080 case RESOURCE_CONTEXT
:
1081 ret
= _enumerateGlobalPassthroughW(enumerator
, lpcCount
, lpBuffer
,
1085 WARN("unexpected scope 0x%08x\n", enumerator
->dwScope
);
1086 ret
= WN_NO_MORE_ENTRIES
;
1088 TRACE("Returning %d\n", ret
);
1092 static DWORD
_enumerateProviderW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1093 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1096 return WN_BAD_POINTER
;
1097 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_PROVIDER
)
1098 return WN_BAD_VALUE
;
1099 if (!enumerator
->handle
)
1100 return WN_BAD_VALUE
;
1102 return WN_BAD_POINTER
;
1104 return WN_BAD_POINTER
;
1106 return WN_BAD_POINTER
;
1108 return WN_NO_NETWORK
;
1109 if (enumerator
->providerIndex
>= providerTable
->numProviders
)
1110 return WN_NO_MORE_ENTRIES
;
1111 if (!providerTable
->table
[enumerator
->providerIndex
].enumResource
)
1112 return WN_BAD_VALUE
;
1113 return providerTable
->table
[enumerator
->providerIndex
].enumResource(
1114 enumerator
->handle
, lpcCount
, lpBuffer
, lpBufferSize
);
1117 static DWORD
_enumerateContextW(PWNetEnumerator enumerator
, LPDWORD lpcCount
,
1118 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1121 size_t cchEntireNetworkLen
, bytesNeeded
;
1124 return WN_BAD_POINTER
;
1125 if (enumerator
->enumType
!= WNET_ENUMERATOR_TYPE_CONTEXT
)
1126 return WN_BAD_VALUE
;
1128 return WN_BAD_POINTER
;
1130 return WN_BAD_POINTER
;
1132 return WN_BAD_POINTER
;
1134 return WN_NO_NETWORK
;
1136 cchEntireNetworkLen
= strlenW(providerTable
->entireNetwork
) + 1;
1137 bytesNeeded
= sizeof(NETRESOURCEW
) + cchEntireNetworkLen
* sizeof(WCHAR
);
1138 if (*lpBufferSize
< bytesNeeded
)
1140 *lpBufferSize
= bytesNeeded
;
1145 LPNETRESOURCEW lpNet
= lpBuffer
;
1147 lpNet
->dwScope
= RESOURCE_GLOBALNET
;
1148 lpNet
->dwType
= enumerator
->dwType
;
1149 lpNet
->dwDisplayType
= RESOURCEDISPLAYTYPE_ROOT
;
1150 lpNet
->dwUsage
= RESOURCEUSAGE_CONTAINER
;
1151 lpNet
->lpLocalName
= NULL
;
1152 lpNet
->lpRemoteName
= NULL
;
1153 lpNet
->lpProvider
= NULL
;
1154 /* odd, but correct: put comment at end of buffer, so it won't get
1155 * overwritten by subsequent calls to a provider's enumResource
1157 lpNet
->lpComment
= (LPWSTR
)((LPBYTE
)lpBuffer
+ *lpBufferSize
-
1158 (cchEntireNetworkLen
* sizeof(WCHAR
)));
1159 strcpyW(lpNet
->lpComment
, providerTable
->entireNetwork
);
1162 if (ret
== WN_SUCCESS
)
1164 DWORD bufferSize
= *lpBufferSize
- bytesNeeded
;
1166 /* "Entire Network" entry enumerated--morph this into a global
1167 * enumerator. enumerator->lpNet continues to be NULL, since it has
1168 * no meaning when the scope isn't RESOURCE_GLOBALNET.
1170 enumerator
->enumType
= WNET_ENUMERATOR_TYPE_GLOBAL
;
1171 ret
= _enumerateGlobalW(enumerator
, lpcCount
,
1172 (LPBYTE
)lpBuffer
+ bytesNeeded
, &bufferSize
);
1173 if (ret
== WN_SUCCESS
)
1175 /* reflect the fact that we already enumerated "Entire Network" */
1177 *lpBufferSize
= bufferSize
+ bytesNeeded
;
1181 /* the provider enumeration failed, but we already succeeded in
1182 * enumerating "Entire Network"--leave type as global to allow a
1183 * retry, but indicate success with a count of one.
1187 *lpBufferSize
= bytesNeeded
;
1190 TRACE("Returning %d\n", ret
);
1194 /*********************************************************************
1195 * WNetEnumResourceW [MPR.@]
1197 DWORD WINAPI
WNetEnumResourceW( HANDLE hEnum
, LPDWORD lpcCount
,
1198 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1202 TRACE( "(%p, %p, %p, %p)\n", hEnum
, lpcCount
, lpBuffer
, lpBufferSize
);
1205 ret
= WN_BAD_POINTER
;
1207 ret
= WN_BAD_POINTER
;
1209 ret
= WN_BAD_POINTER
;
1210 else if (!lpBufferSize
)
1211 ret
= WN_BAD_POINTER
;
1212 else if (*lpBufferSize
< sizeof(NETRESOURCEW
))
1214 *lpBufferSize
= sizeof(NETRESOURCEW
);
1219 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1221 switch (enumerator
->enumType
)
1223 case WNET_ENUMERATOR_TYPE_NULL
:
1224 ret
= WN_NO_MORE_ENTRIES
;
1226 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1227 ret
= _enumerateGlobalW(enumerator
, lpcCount
, lpBuffer
,
1230 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1231 ret
= _enumerateProviderW(enumerator
, lpcCount
, lpBuffer
,
1234 case WNET_ENUMERATOR_TYPE_CONTEXT
:
1235 ret
= _enumerateContextW(enumerator
, lpcCount
, lpBuffer
,
1239 WARN("bogus enumerator type!\n");
1240 ret
= WN_NO_NETWORK
;
1245 TRACE("Returning %d\n", ret
);
1249 /*********************************************************************
1250 * WNetCloseEnum [MPR.@]
1252 DWORD WINAPI
WNetCloseEnum( HANDLE hEnum
)
1256 TRACE( "(%p)\n", hEnum
);
1260 PWNetEnumerator enumerator
= (PWNetEnumerator
)hEnum
;
1262 switch (enumerator
->enumType
)
1264 case WNET_ENUMERATOR_TYPE_NULL
:
1267 case WNET_ENUMERATOR_TYPE_GLOBAL
:
1268 if (enumerator
->lpNet
)
1269 _freeEnumNetResource(enumerator
->lpNet
);
1270 if (enumerator
->handle
)
1271 providerTable
->table
[enumerator
->providerIndex
].
1272 closeEnum(enumerator
->handle
);
1275 case WNET_ENUMERATOR_TYPE_PROVIDER
:
1276 if (enumerator
->handle
)
1277 providerTable
->table
[enumerator
->providerIndex
].
1278 closeEnum(enumerator
->handle
);
1282 WARN("bogus enumerator type!\n");
1283 ret
= WN_BAD_HANDLE
;
1285 HeapFree(GetProcessHeap(), 0, hEnum
);
1288 ret
= WN_BAD_HANDLE
;
1291 TRACE("Returning %d\n", ret
);
1295 /*********************************************************************
1296 * WNetGetResourceInformationA [MPR.@]
1298 * See WNetGetResourceInformationW
1300 DWORD WINAPI
WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource
,
1301 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1306 TRACE( "(%p, %p, %p, %p)\n",
1307 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1309 if (!providerTable
|| providerTable
->numProviders
== 0)
1310 ret
= WN_NO_NETWORK
;
1311 else if (lpNetResource
)
1313 LPNETRESOURCEW lpNetResourceW
= NULL
;
1314 DWORD size
= 1024, count
= 1;
1317 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1318 ret
= _thunkNetResourceArrayAToW(lpNetResource
, &count
, lpNetResourceW
, &size
);
1319 if (ret
== WN_MORE_DATA
)
1321 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1322 lpNetResourceW
= HeapAlloc(GetProcessHeap(), 0, size
);
1324 ret
= _thunkNetResourceArrayAToW(lpNetResource
,
1325 &count
, lpNetResourceW
, &size
);
1327 ret
= WN_OUT_OF_MEMORY
;
1329 if (ret
== WN_SUCCESS
)
1331 LPWSTR lpSystemW
= NULL
;
1334 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1337 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1338 lpBufferW
, &size
, &lpSystemW
);
1339 if (ret
== WN_MORE_DATA
)
1341 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1342 lpBufferW
= HeapAlloc(GetProcessHeap(), 0, size
);
1344 ret
= WNetGetResourceInformationW(lpNetResourceW
,
1345 lpBufferW
, &size
, &lpSystemW
);
1347 ret
= WN_OUT_OF_MEMORY
;
1349 if (ret
== WN_SUCCESS
)
1351 ret
= _thunkNetResourceArrayWToA(lpBufferW
,
1352 &count
, lpBuffer
, cbBuffer
);
1353 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1354 lpNetResourceW
= lpBufferW
;
1355 size
= sizeof(NETRESOURCEA
);
1356 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpRemoteName
,
1357 -1, NULL
, 0, NULL
, NULL
);
1358 size
+= WideCharToMultiByte(CP_ACP
, 0, lpNetResourceW
->lpProvider
,
1359 -1, NULL
, 0, NULL
, NULL
);
1361 len
= WideCharToMultiByte(CP_ACP
, 0, lpSystemW
,
1362 -1, NULL
, 0, NULL
, NULL
);
1363 if ((len
) && ( size
+ len
< *cbBuffer
))
1365 *lplpSystem
= (char*)lpBuffer
+ *cbBuffer
- len
;
1366 WideCharToMultiByte(CP_ACP
, 0, lpSystemW
, -1,
1367 *lplpSystem
, len
, NULL
, NULL
);
1374 ret
= WN_OUT_OF_MEMORY
;
1375 HeapFree(GetProcessHeap(), 0, lpBufferW
);
1378 ret
= WN_OUT_OF_MEMORY
;
1379 HeapFree(GetProcessHeap(), 0, lpSystemW
);
1381 HeapFree(GetProcessHeap(), 0, lpNetResourceW
);
1384 ret
= WN_NO_NETWORK
;
1388 TRACE("Returning %d\n", ret
);
1392 /*********************************************************************
1393 * WNetGetResourceInformationW [MPR.@]
1395 * WNetGetResourceInformationW function identifies the network provider
1396 * that owns the resource and gets information about the type of the resource.
1399 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that
1400 * defines a network resource.
1401 * lpBuffer [ O] the pointer to buffer, containing result. It
1402 * contains NETRESOURCEW structure and strings to
1403 * which the members of the NETRESOURCEW structure
1405 * cbBuffer [I/O] the pointer to DWORD number - size of buffer
1407 * lplpSystem [ O] the pointer to string in the output buffer,
1408 * containing the part of the resource name without
1409 * names of the server and share.
1412 * NO_ERROR if the function succeeds. System error code if the function fails.
1415 DWORD WINAPI
WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource
,
1416 LPVOID lpBuffer
, LPDWORD cbBuffer
,
1417 LPWSTR
*lplpSystem
)
1419 DWORD ret
= WN_NO_NETWORK
;
1422 TRACE( "(%p, %p, %p, %p)\n",
1423 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1426 ret
= WN_OUT_OF_MEMORY
;
1427 else if (providerTable
!= NULL
)
1429 /* FIXME: For function value of a variable is indifferent, it does
1430 * search of all providers in a network.
1432 for (index
= 0; index
< providerTable
->numProviders
; index
++)
1434 if(providerTable
->table
[index
].getCaps(WNNC_DIALOG
) &
1435 WNNC_DLG_GETRESOURCEINFORMATION
)
1437 if (providerTable
->table
[index
].getResourceInformation
)
1438 ret
= providerTable
->table
[index
].getResourceInformation(
1439 lpNetResource
, lpBuffer
, cbBuffer
, lplpSystem
);
1441 ret
= WN_NO_NETWORK
;
1442 if (ret
== WN_SUCCESS
)
1452 /*********************************************************************
1453 * WNetGetResourceParentA [MPR.@]
1455 DWORD WINAPI
WNetGetResourceParentA( LPNETRESOURCEA lpNetResource
,
1456 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1458 FIXME( "(%p, %p, %p): stub\n",
1459 lpNetResource
, lpBuffer
, lpBufferSize
);
1461 SetLastError(WN_NO_NETWORK
);
1462 return WN_NO_NETWORK
;
1465 /*********************************************************************
1466 * WNetGetResourceParentW [MPR.@]
1468 DWORD WINAPI
WNetGetResourceParentW( LPNETRESOURCEW lpNetResource
,
1469 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
1471 FIXME( "(%p, %p, %p): stub\n",
1472 lpNetResource
, lpBuffer
, lpBufferSize
);
1474 SetLastError(WN_NO_NETWORK
);
1475 return WN_NO_NETWORK
;
1481 * Connection Functions
1484 /*********************************************************************
1485 * WNetAddConnectionA [MPR.@]
1487 DWORD WINAPI
WNetAddConnectionA( LPCSTR lpRemoteName
, LPCSTR lpPassword
,
1488 LPCSTR lpLocalName
)
1490 NETRESOURCEA resourcesA
;
1492 memset(&resourcesA
, 0, sizeof(resourcesA
));
1493 resourcesA
.lpRemoteName
= (LPSTR
)lpRemoteName
;
1494 resourcesA
.lpLocalName
= (LPSTR
)lpLocalName
;
1495 return WNetUseConnectionA(NULL
, &resourcesA
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1498 /*********************************************************************
1499 * WNetAddConnectionW [MPR.@]
1501 DWORD WINAPI
WNetAddConnectionW( LPCWSTR lpRemoteName
, LPCWSTR lpPassword
,
1502 LPCWSTR lpLocalName
)
1504 NETRESOURCEW resourcesW
;
1506 memset(&resourcesW
, 0, sizeof(resourcesW
));
1507 resourcesW
.lpRemoteName
= (LPWSTR
)lpRemoteName
;
1508 resourcesW
.lpLocalName
= (LPWSTR
)lpLocalName
;
1509 return WNetUseConnectionW(NULL
, &resourcesW
, lpPassword
, NULL
, 0, NULL
, 0, NULL
);
1512 /*********************************************************************
1513 * WNetAddConnection2A [MPR.@]
1515 DWORD WINAPI
WNetAddConnection2A( LPNETRESOURCEA lpNetResource
,
1516 LPCSTR lpPassword
, LPCSTR lpUserID
,
1519 return WNetUseConnectionA(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1523 /*********************************************************************
1524 * WNetAddConnection2W [MPR.@]
1526 DWORD WINAPI
WNetAddConnection2W( LPNETRESOURCEW lpNetResource
,
1527 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1530 return WNetUseConnectionW(NULL
, lpNetResource
, lpPassword
, lpUserID
, dwFlags
,
1534 /*********************************************************************
1535 * WNetAddConnection3A [MPR.@]
1537 DWORD WINAPI
WNetAddConnection3A( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1538 LPCSTR lpPassword
, LPCSTR lpUserID
,
1541 return WNetUseConnectionA(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1542 dwFlags
, NULL
, 0, NULL
);
1545 /*********************************************************************
1546 * WNetAddConnection3W [MPR.@]
1548 DWORD WINAPI
WNetAddConnection3W( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1549 LPCWSTR lpPassword
, LPCWSTR lpUserID
,
1552 return WNetUseConnectionW(hwndOwner
, lpNetResource
, lpPassword
, lpUserID
,
1553 dwFlags
, NULL
, 0, NULL
);
1556 /* Convert an ANSI string to wide */
1557 static LPWSTR
strdupAtoW( LPCSTR str
)
1562 if (!str
) return NULL
;
1563 len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
1564 ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
1565 if (ret
) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
1569 /* Convert ANSI NETRESOURCE struct to wide structure */
1570 static VOID
convert_netresourcea_to_w( LPNETRESOURCEA lpNetResourceA
,
1571 LPNETRESOURCEW lpNetResourceW
)
1573 lpNetResourceW
->dwScope
= lpNetResourceA
->dwScope
;
1574 lpNetResourceW
->dwType
= lpNetResourceA
->dwType
;
1575 lpNetResourceW
->dwDisplayType
= lpNetResourceA
->dwDisplayType
;
1576 lpNetResourceW
->dwUsage
= lpNetResourceA
->dwUsage
;
1577 lpNetResourceW
->lpLocalName
= strdupAtoW(lpNetResourceA
->lpLocalName
);
1578 lpNetResourceW
->lpRemoteName
= strdupAtoW(lpNetResourceA
->lpRemoteName
);
1579 lpNetResourceW
->lpComment
= strdupAtoW(lpNetResourceA
->lpComment
);
1580 lpNetResourceW
->lpProvider
= strdupAtoW(lpNetResourceA
->lpProvider
);
1583 /*****************************************************************
1584 * WNetUseConnectionA [MPR.@]
1586 DWORD WINAPI
WNetUseConnectionA( HWND hwndOwner
, LPNETRESOURCEA lpNetResource
,
1587 LPCSTR lpPassword
, LPCSTR lpUserID
, DWORD dwFlags
,
1588 LPSTR lpAccessName
, LPDWORD lpBufferSize
,
1591 NETRESOURCEW resourcesW
, *pRes
= NULL
;
1592 PWSTR passW
, userIDW
, accessNameW
= NULL
;
1593 DWORD ret
= WN_MORE_DATA
;
1594 DWORD bufferSize
= 1;
1599 convert_netresourcea_to_w(lpNetResource
, &resourcesW
);
1603 passW
= strdupAtoW(lpPassword
);
1604 userIDW
= strdupAtoW(lpUserID
);
1606 if (lpAccessName
&& lpBufferSize
&& *lpBufferSize
)
1610 ret
= WNetUseConnectionW(hwndOwner
, pRes
, passW
, userIDW
, dwFlags
,
1611 &probe
, &bufferSize
, lpResult
);
1612 if (ret
== WN_MORE_DATA
)
1613 accessNameW
= HeapAlloc(GetProcessHeap(), 0, bufferSize
* sizeof(WCHAR
));
1616 if (ret
== WN_MORE_DATA
)
1618 ret
= WNetUseConnectionW(hwndOwner
, pRes
, passW
, userIDW
, dwFlags
,
1619 accessNameW
, &bufferSize
, lpResult
);
1620 if (ret
== WN_SUCCESS
)
1622 if (lpAccessName
&& lpBufferSize
&& *lpBufferSize
&& accessNameW
)
1624 len
= WideCharToMultiByte(CP_ACP
, 0, accessNameW
, -1, NULL
, 0, NULL
, NULL
);
1627 if (len
<= *lpBufferSize
)
1628 WideCharToMultiByte(CP_ACP
, 0, accessNameW
, -1, lpAccessName
, len
, NULL
, NULL
);
1631 WNetCancelConnectionW(accessNameW
, TRUE
);
1632 *lpBufferSize
= len
;
1642 HeapFree(GetProcessHeap(), 0, resourcesW
.lpLocalName
);
1643 HeapFree(GetProcessHeap(), 0, resourcesW
.lpRemoteName
);
1644 HeapFree(GetProcessHeap(), 0, resourcesW
.lpComment
);
1645 HeapFree(GetProcessHeap(), 0, resourcesW
.lpProvider
);
1647 HeapFree(GetProcessHeap(), 0, passW
);
1648 HeapFree(GetProcessHeap(), 0, userIDW
);
1649 HeapFree(GetProcessHeap(), 0, accessNameW
);
1654 /*****************************************************************
1655 * WNetUseConnectionW [MPR.@]
1657 DWORD WINAPI
WNetUseConnectionW( HWND hwndOwner
, LPNETRESOURCEW lpNetResource
,
1658 LPCWSTR lpPassword
, LPCWSTR lpUserID
, DWORD dwFlags
,
1659 LPWSTR lpAccessName
, LPDWORD lpBufferSize
,
1667 PF_NPAddConnection3 addConn3
;
1668 PF_NPAddConnection addConn
;
1670 if (!providerTable
|| providerTable
->numProviders
== 0) {
1671 SetLastError(WN_NO_NETWORK
);
1672 return WN_NO_NETWORK
;
1675 if (!lpNetResource
) {
1676 SetLastError(ERROR_INVALID_PARAMETER
);
1677 return ERROR_INVALID_PARAMETER
;
1680 if (!lpNetResource
->lpProvider
|| !*lpNetResource
->lpProvider
) {
1681 SetLastError(ERROR_BAD_PROVIDER
);
1682 return ERROR_BAD_PROVIDER
;
1685 if (!lpNetResource
->lpLocalName
|| !*lpNetResource
->lpLocalName
) {
1686 SetLastError(ERROR_BAD_DEVICE
);
1687 return ERROR_BAD_DEVICE
;
1690 if ((!(lpNetResource
->lpLocalName
[0] >= 'a' && lpNetResource
->lpLocalName
[0] <= 'z') &&
1691 !(lpNetResource
->lpLocalName
[0] >= 'A' && lpNetResource
->lpLocalName
[0] <= 'Z')) ||
1692 lpNetResource
->lpLocalName
[1] != ':' || lpNetResource
->lpLocalName
[2]) {
1693 SetLastError(ERROR_BAD_DEVICE
);
1694 return ERROR_BAD_DEVICE
;
1697 id
= (lpNetResource
->lpLocalName
[0] >= 'a') ? lpNetResource
->lpLocalName
[0] - 'a' : lpNetResource
->lpLocalName
[0] - 'A';
1698 drives
= GetLogicalDrives();
1699 if (drives
& (1 << id
)) {
1700 SetLastError(ERROR_ALREADY_ASSIGNED
);
1701 return ERROR_ALREADY_ASSIGNED
;
1704 provider
= _findProviderIndexW(lpNetResource
->lpProvider
);
1705 if (provider
== BAD_PROVIDER_INDEX
) {
1706 SetLastError(ERROR_BAD_PROVIDER
);
1707 return ERROR_BAD_PROVIDER
;
1710 cap
= providerTable
->table
[provider
].getCaps(WNNC_CONNECTION
);
1711 if (!(cap
& WNNC_CON_ADDCONNECTION
) && !(cap
& WNNC_CON_ADDCONNECTION3
)) {
1712 SetLastError(ERROR_BAD_PROVIDER
);
1713 return ERROR_BAD_PROVIDER
;
1716 ret
= WN_ACCESS_DENIED
;
1717 if (cap
& WNNC_CON_ADDCONNECTION3
) {
1718 addConn3
= (PF_NPAddConnection3
)GetProcAddress(providerTable
->table
[provider
].hLib
, "NPAddConnection3");
1720 ret
= addConn3(hwndOwner
, lpNetResource
, (LPWSTR
)lpPassword
, (LPWSTR
)lpUserID
, dwFlags
);
1723 else if (cap
& WNNC_CON_ADDCONNECTION
) {
1724 addConn
= (PF_NPAddConnection
)GetProcAddress(providerTable
->table
[provider
].hLib
, "NPAddConnection");
1726 ret
= addConn(lpNetResource
, (LPWSTR
)lpPassword
, (LPWSTR
)lpUserID
);
1733 /*********************************************************************
1734 * WNetCancelConnectionA [MPR.@]
1736 DWORD WINAPI
WNetCancelConnectionA( LPCSTR lpName
, BOOL fForce
)
1738 FIXME( "(%s, %d), stub\n", debugstr_a(lpName
), fForce
);
1743 /*********************************************************************
1744 * WNetCancelConnectionW [MPR.@]
1746 DWORD WINAPI
WNetCancelConnectionW( LPCWSTR lpName
, BOOL fForce
)
1748 FIXME( "(%s, %d), stub\n", debugstr_w(lpName
), fForce
);
1753 /*********************************************************************
1754 * WNetCancelConnection2A [MPR.@]
1756 DWORD WINAPI
WNetCancelConnection2A( LPCSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1758 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName
), dwFlags
, fForce
);
1763 /*********************************************************************
1764 * WNetCancelConnection2W [MPR.@]
1766 DWORD WINAPI
WNetCancelConnection2W( LPCWSTR lpName
, DWORD dwFlags
, BOOL fForce
)
1768 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName
), dwFlags
, fForce
);
1773 /*****************************************************************
1774 * WNetRestoreConnectionA [MPR.@]
1776 DWORD WINAPI
WNetRestoreConnectionA( HWND hwndOwner
, LPCSTR lpszDevice
)
1778 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_a(lpszDevice
) );
1780 SetLastError(WN_NO_NETWORK
);
1781 return WN_NO_NETWORK
;
1784 /*****************************************************************
1785 * WNetRestoreConnectionW [MPR.@]
1787 DWORD WINAPI
WNetRestoreConnectionW( HWND hwndOwner
, LPCWSTR lpszDevice
)
1789 FIXME( "(%p, %s), stub\n", hwndOwner
, debugstr_w(lpszDevice
) );
1791 SetLastError(WN_NO_NETWORK
);
1792 return WN_NO_NETWORK
;
1795 /**************************************************************************
1796 * WNetGetConnectionA [MPR.@]
1799 * - WN_BAD_LOCALNAME lpLocalName makes no sense
1800 * - WN_NOT_CONNECTED drive is a local drive
1801 * - WN_MORE_DATA buffer isn't big enough
1802 * - WN_SUCCESS success (net path in buffer)
1804 * FIXME: need to test return values under different errors
1806 DWORD WINAPI
WNetGetConnectionA( LPCSTR lpLocalName
,
1807 LPSTR lpRemoteName
, LPDWORD lpBufferSize
)
1812 ret
= WN_BAD_POINTER
;
1813 else if (!lpBufferSize
)
1814 ret
= WN_BAD_POINTER
;
1815 else if (!lpRemoteName
&& *lpBufferSize
)
1816 ret
= WN_BAD_POINTER
;
1819 int len
= MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, NULL
, 0);
1823 PWSTR wideLocalName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1827 WCHAR wideRemoteStatic
[MAX_PATH
];
1828 DWORD wideRemoteSize
= sizeof(wideRemoteStatic
) / sizeof(WCHAR
);
1830 MultiByteToWideChar(CP_ACP
, 0, lpLocalName
, -1, wideLocalName
, len
);
1832 /* try once without memory allocation */
1833 ret
= WNetGetConnectionW(wideLocalName
, wideRemoteStatic
,
1835 if (ret
== WN_SUCCESS
)
1837 int len
= WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1838 -1, NULL
, 0, NULL
, NULL
);
1840 if (len
<= *lpBufferSize
)
1842 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
, -1,
1843 lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1848 *lpBufferSize
= len
;
1852 else if (ret
== WN_MORE_DATA
)
1854 PWSTR wideRemote
= HeapAlloc(GetProcessHeap(), 0,
1855 wideRemoteSize
* sizeof(WCHAR
));
1859 ret
= WNetGetConnectionW(wideLocalName
, wideRemote
,
1861 if (ret
== WN_SUCCESS
)
1863 if (len
<= *lpBufferSize
)
1865 WideCharToMultiByte(CP_ACP
, 0, wideRemoteStatic
,
1866 -1, lpRemoteName
, *lpBufferSize
, NULL
, NULL
);
1871 *lpBufferSize
= len
;
1875 HeapFree(GetProcessHeap(), 0, wideRemote
);
1878 ret
= WN_OUT_OF_MEMORY
;
1880 HeapFree(GetProcessHeap(), 0, wideLocalName
);
1883 ret
= WN_OUT_OF_MEMORY
;
1886 ret
= WN_BAD_LOCALNAME
;
1890 TRACE("Returning %d\n", ret
);
1894 /* find the network connection for a given drive; helper for WNetGetConnection */
1895 static DWORD
get_drive_connection( WCHAR letter
, LPWSTR remote
, LPDWORD size
)
1898 struct mountmgr_unix_drive
*data
= (struct mountmgr_unix_drive
*)buffer
;
1900 DWORD ret
= WN_NOT_CONNECTED
;
1901 DWORD bytes_returned
;
1903 if ((mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
,
1904 FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
,
1905 0, 0 )) == INVALID_HANDLE_VALUE
)
1907 ERR( "failed to open mount manager err %u\n", GetLastError() );
1910 memset( data
, 0, sizeof(*data
) );
1911 data
->letter
= letter
;
1912 if (DeviceIoControl( mgr
, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE
, data
, sizeof(*data
),
1913 data
, sizeof(buffer
), &bytes_returned
, NULL
))
1915 char *p
, *mount_point
= buffer
+ data
->mount_point_offset
;
1918 if (data
->mount_point_offset
&& !strncmp( mount_point
, "unc/", 4 ))
1921 mount_point
[0] = '\\';
1922 for (p
= mount_point
; *p
; p
++) if (*p
== '/') *p
= '\\';
1924 len
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, NULL
, 0 );
1932 *size
= MultiByteToWideChar( CP_UNIXCP
, 0, mount_point
, -1, remote
, *size
);
1941 /**************************************************************************
1942 * WNetGetConnectionW [MPR.@]
1944 * FIXME: need to test return values under different errors
1946 DWORD WINAPI
WNetGetConnectionW( LPCWSTR lpLocalName
,
1947 LPWSTR lpRemoteName
, LPDWORD lpBufferSize
)
1951 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName
), lpRemoteName
,
1955 ret
= WN_BAD_POINTER
;
1956 else if (!lpBufferSize
)
1957 ret
= WN_BAD_POINTER
;
1958 else if (!lpRemoteName
&& *lpBufferSize
)
1959 ret
= WN_BAD_POINTER
;
1960 else if (!lpLocalName
[0])
1961 ret
= WN_BAD_LOCALNAME
;
1964 if (lpLocalName
[1] == ':')
1966 switch(GetDriveTypeW(lpLocalName
))
1969 ret
= get_drive_connection( lpLocalName
[0], lpRemoteName
, lpBufferSize
);
1971 case DRIVE_REMOVABLE
:
1974 TRACE("file is local\n");
1975 ret
= WN_NOT_CONNECTED
;
1978 ret
= WN_BAD_LOCALNAME
;
1982 ret
= WN_BAD_LOCALNAME
;
1986 TRACE("Returning %d\n", ret
);
1990 /**************************************************************************
1991 * WNetSetConnectionA [MPR.@]
1993 DWORD WINAPI
WNetSetConnectionA( LPCSTR lpName
, DWORD dwProperty
,
1996 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName
), dwProperty
, pvValue
);
1998 SetLastError(WN_NO_NETWORK
);
1999 return WN_NO_NETWORK
;
2002 /**************************************************************************
2003 * WNetSetConnectionW [MPR.@]
2005 DWORD WINAPI
WNetSetConnectionW( LPCWSTR lpName
, DWORD dwProperty
,
2008 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName
), dwProperty
, pvValue
);
2010 SetLastError(WN_NO_NETWORK
);
2011 return WN_NO_NETWORK
;
2014 /*****************************************************************
2015 * WNetGetUniversalNameA [MPR.@]
2017 DWORD WINAPI
WNetGetUniversalNameA ( LPCSTR lpLocalPath
, DWORD dwInfoLevel
,
2018 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
2022 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2023 debugstr_a(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
2025 switch (dwInfoLevel
)
2027 case UNIVERSAL_NAME_INFO_LEVEL
:
2029 LPUNIVERSAL_NAME_INFOA info
= lpBuffer
;
2031 if (GetDriveTypeA(lpLocalPath
) != DRIVE_REMOTE
)
2033 err
= ERROR_NOT_CONNECTED
;
2037 size
= sizeof(*info
) + lstrlenA(lpLocalPath
) + 1;
2038 if (*lpBufferSize
< size
)
2043 info
->lpUniversalName
= (char *)info
+ sizeof(*info
);
2044 lstrcpyA(info
->lpUniversalName
, lpLocalPath
);
2048 case REMOTE_NAME_INFO_LEVEL
:
2049 err
= WN_NO_NETWORK
;
2061 /*****************************************************************
2062 * WNetGetUniversalNameW [MPR.@]
2064 DWORD WINAPI
WNetGetUniversalNameW ( LPCWSTR lpLocalPath
, DWORD dwInfoLevel
,
2065 LPVOID lpBuffer
, LPDWORD lpBufferSize
)
2069 FIXME( "(%s, 0x%08X, %p, %p): stub\n",
2070 debugstr_w(lpLocalPath
), dwInfoLevel
, lpBuffer
, lpBufferSize
);
2072 switch (dwInfoLevel
)
2074 case UNIVERSAL_NAME_INFO_LEVEL
:
2076 LPUNIVERSAL_NAME_INFOW info
= lpBuffer
;
2078 if (GetDriveTypeW(lpLocalPath
) != DRIVE_REMOTE
)
2080 err
= ERROR_NOT_CONNECTED
;
2084 size
= sizeof(*info
) + (lstrlenW(lpLocalPath
) + 1) * sizeof(WCHAR
);
2085 if (*lpBufferSize
< size
)
2090 info
->lpUniversalName
= (LPWSTR
)((char *)info
+ sizeof(*info
));
2091 lstrcpyW(info
->lpUniversalName
, lpLocalPath
);
2095 case REMOTE_NAME_INFO_LEVEL
:
2096 err
= WN_NOT_CONNECTED
;
2104 if (err
!= WN_NO_ERROR
) SetLastError(err
);
2114 /**************************************************************************
2115 * WNetGetUserA [MPR.@]
2117 * FIXME: we should not return ourselves, but the owner of the drive lpName
2119 DWORD WINAPI
WNetGetUserA( LPCSTR lpName
, LPSTR lpUserID
, LPDWORD lpBufferSize
)
2121 if (GetUserNameA( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
2122 return GetLastError();
2125 /*****************************************************************
2126 * WNetGetUserW [MPR.@]
2128 * FIXME: we should not return ourselves, but the owner of the drive lpName
2130 DWORD WINAPI
WNetGetUserW( LPCWSTR lpName
, LPWSTR lpUserID
, LPDWORD lpBufferSize
)
2132 if (GetUserNameW( lpUserID
, lpBufferSize
)) return WN_SUCCESS
;
2133 return GetLastError();
2136 /*********************************************************************
2137 * WNetConnectionDialog [MPR.@]
2139 DWORD WINAPI
WNetConnectionDialog( HWND hwnd
, DWORD dwType
)
2141 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2143 SetLastError(WN_NO_NETWORK
);
2144 return WN_NO_NETWORK
;
2147 /*********************************************************************
2148 * WNetConnectionDialog1A [MPR.@]
2150 DWORD WINAPI
WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct
)
2152 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2154 SetLastError(WN_NO_NETWORK
);
2155 return WN_NO_NETWORK
;
2158 /*********************************************************************
2159 * WNetConnectionDialog1W [MPR.@]
2161 DWORD WINAPI
WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct
)
2163 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2165 SetLastError(WN_NO_NETWORK
);
2166 return WN_NO_NETWORK
;
2169 /*********************************************************************
2170 * WNetDisconnectDialog [MPR.@]
2172 DWORD WINAPI
WNetDisconnectDialog( HWND hwnd
, DWORD dwType
)
2174 FIXME( "(%p, %08X): stub\n", hwnd
, dwType
);
2176 SetLastError(WN_NO_NETWORK
);
2177 return WN_NO_NETWORK
;
2180 /*********************************************************************
2181 * WNetDisconnectDialog1A [MPR.@]
2183 DWORD WINAPI
WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct
)
2185 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2187 SetLastError(WN_NO_NETWORK
);
2188 return WN_NO_NETWORK
;
2191 /*********************************************************************
2192 * WNetDisconnectDialog1W [MPR.@]
2194 DWORD WINAPI
WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct
)
2196 FIXME( "(%p): stub\n", lpConnDlgStruct
);
2198 SetLastError(WN_NO_NETWORK
);
2199 return WN_NO_NETWORK
;
2202 /*********************************************************************
2203 * WNetGetLastErrorA [MPR.@]
2205 DWORD WINAPI
WNetGetLastErrorA( LPDWORD lpError
,
2206 LPSTR lpErrorBuf
, DWORD nErrorBufSize
,
2207 LPSTR lpNameBuf
, DWORD nNameBufSize
)
2209 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2210 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2212 SetLastError(WN_NO_NETWORK
);
2213 return WN_NO_NETWORK
;
2216 /*********************************************************************
2217 * WNetGetLastErrorW [MPR.@]
2219 DWORD WINAPI
WNetGetLastErrorW( LPDWORD lpError
,
2220 LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
2221 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
2223 FIXME( "(%p, %p, %d, %p, %d): stub\n",
2224 lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
2226 SetLastError(WN_NO_NETWORK
);
2227 return WN_NO_NETWORK
;
2230 /*********************************************************************
2231 * WNetGetNetworkInformationA [MPR.@]
2233 DWORD WINAPI
WNetGetNetworkInformationA( LPCSTR lpProvider
,
2234 LPNETINFOSTRUCT lpNetInfoStruct
)
2238 TRACE( "(%s, %p)\n", debugstr_a(lpProvider
), lpNetInfoStruct
);
2241 ret
= WN_BAD_POINTER
;
2246 len
= MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, NULL
, 0);
2249 LPWSTR wideProvider
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2253 MultiByteToWideChar(CP_ACP
, 0, lpProvider
, -1, wideProvider
,
2255 ret
= WNetGetNetworkInformationW(wideProvider
, lpNetInfoStruct
);
2256 HeapFree(GetProcessHeap(), 0, wideProvider
);
2259 ret
= WN_OUT_OF_MEMORY
;
2262 ret
= GetLastError();
2266 TRACE("Returning %d\n", ret
);
2270 /*********************************************************************
2271 * WNetGetNetworkInformationW [MPR.@]
2273 DWORD WINAPI
WNetGetNetworkInformationW( LPCWSTR lpProvider
,
2274 LPNETINFOSTRUCT lpNetInfoStruct
)
2278 TRACE( "(%s, %p)\n", debugstr_w(lpProvider
), lpNetInfoStruct
);
2281 ret
= WN_BAD_POINTER
;
2282 else if (!lpNetInfoStruct
)
2283 ret
= WN_BAD_POINTER
;
2284 else if (lpNetInfoStruct
->cbStructure
< sizeof(NETINFOSTRUCT
))
2288 if (providerTable
&& providerTable
->numProviders
)
2290 DWORD providerIndex
= _findProviderIndexW(lpProvider
);
2292 if (providerIndex
!= BAD_PROVIDER_INDEX
)
2294 lpNetInfoStruct
->cbStructure
= sizeof(NETINFOSTRUCT
);
2295 lpNetInfoStruct
->dwProviderVersion
=
2296 providerTable
->table
[providerIndex
].dwSpecVersion
;
2297 lpNetInfoStruct
->dwStatus
= NO_ERROR
;
2298 lpNetInfoStruct
->dwCharacteristics
= 0;
2299 lpNetInfoStruct
->dwHandle
= 0;
2300 lpNetInfoStruct
->wNetType
=
2301 HIWORD(providerTable
->table
[providerIndex
].dwNetType
);
2302 lpNetInfoStruct
->dwPrinters
= -1;
2303 lpNetInfoStruct
->dwDrives
= -1;
2307 ret
= WN_BAD_PROVIDER
;
2310 ret
= WN_NO_NETWORK
;
2314 TRACE("Returning %d\n", ret
);
2318 /*****************************************************************
2319 * WNetGetProviderNameA [MPR.@]
2321 DWORD WINAPI
WNetGetProviderNameA( DWORD dwNetType
,
2322 LPSTR lpProvider
, LPDWORD lpBufferSize
)
2326 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_a(lpProvider
),
2330 ret
= WN_BAD_POINTER
;
2331 else if (!lpBufferSize
)
2332 ret
= WN_BAD_POINTER
;
2339 ret
= WN_NO_NETWORK
;
2340 for (i
= 0; i
< providerTable
->numProviders
&&
2341 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2344 if (i
< providerTable
->numProviders
)
2346 DWORD sizeNeeded
= WideCharToMultiByte(CP_ACP
, 0,
2347 providerTable
->table
[i
].name
, -1, NULL
, 0, NULL
, NULL
);
2349 if (*lpBufferSize
< sizeNeeded
)
2351 *lpBufferSize
= sizeNeeded
;
2356 WideCharToMultiByte(CP_ACP
, 0, providerTable
->table
[i
].name
,
2357 -1, lpProvider
, *lpBufferSize
, NULL
, NULL
);
2359 /* FIXME: is *lpBufferSize set to the number of characters
2365 ret
= WN_NO_NETWORK
;
2369 TRACE("Returning %d\n", ret
);
2373 /*****************************************************************
2374 * WNetGetProviderNameW [MPR.@]
2376 DWORD WINAPI
WNetGetProviderNameW( DWORD dwNetType
,
2377 LPWSTR lpProvider
, LPDWORD lpBufferSize
)
2381 TRACE("(0x%08x, %s, %p)\n", dwNetType
, debugstr_w(lpProvider
),
2385 ret
= WN_BAD_POINTER
;
2386 else if (!lpBufferSize
)
2387 ret
= WN_BAD_POINTER
;
2394 ret
= WN_NO_NETWORK
;
2395 for (i
= 0; i
< providerTable
->numProviders
&&
2396 HIWORD(providerTable
->table
[i
].dwNetType
) != HIWORD(dwNetType
);
2399 if (i
< providerTable
->numProviders
)
2401 DWORD sizeNeeded
= strlenW(providerTable
->table
[i
].name
) + 1;
2403 if (*lpBufferSize
< sizeNeeded
)
2405 *lpBufferSize
= sizeNeeded
;
2410 strcpyW(lpProvider
, providerTable
->table
[i
].name
);
2412 /* FIXME: is *lpBufferSize set to the number of characters
2418 ret
= WN_NO_NETWORK
;
2422 TRACE("Returning %d\n", ret
);