Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwnet.c
Go to the documentation of this file.
00001 /* 00002 * MPR WNet functions 00003 * 00004 * Copyright 1999 Ulrich Weigand 00005 * Copyright 2004 Juan Lang 00006 * Copyright 2007 Maarten Lankhorst 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include <stdarg.h> 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "winnls.h" 00027 #include "winioctl.h" 00028 #include "winnetwk.h" 00029 #include "npapi.h" 00030 #include "winreg.h" 00031 #include "winuser.h" 00032 #define WINE_MOUNTMGR_EXTENSIONS 00033 #include "ddk/mountmgr.h" 00034 #include "wine/debug.h" 00035 #include "wine/unicode.h" 00036 #include "mprres.h" 00037 #include "wnetpriv.h" 00038 00039 WINE_DEFAULT_DEBUG_CHANNEL(mpr); 00040 00041 /* Data structures representing network service providers. Assumes only one 00042 * thread creates them, and that they are constant for the life of the process 00043 * (and therefore doesn't synchronize access). 00044 * FIXME: only basic provider data and enumeration-related data are implemented 00045 * so far, need to implement the rest too. 00046 */ 00047 typedef struct _WNetProvider 00048 { 00049 HMODULE hLib; 00050 PWSTR name; 00051 PF_NPGetCaps getCaps; 00052 DWORD dwSpecVersion; 00053 DWORD dwNetType; 00054 DWORD dwEnumScopes; 00055 PF_NPOpenEnum openEnum; 00056 PF_NPEnumResource enumResource; 00057 PF_NPCloseEnum closeEnum; 00058 PF_NPGetResourceInformation getResourceInformation; 00059 } WNetProvider, *PWNetProvider; 00060 00061 typedef struct _WNetProviderTable 00062 { 00063 LPWSTR entireNetwork; 00064 DWORD numAllocated; 00065 DWORD numProviders; 00066 WNetProvider table[1]; 00067 } WNetProviderTable, *PWNetProviderTable; 00068 00069 #define WNET_ENUMERATOR_TYPE_NULL 0 00070 #define WNET_ENUMERATOR_TYPE_GLOBAL 1 00071 #define WNET_ENUMERATOR_TYPE_PROVIDER 2 00072 #define WNET_ENUMERATOR_TYPE_CONTEXT 3 00073 00074 /* An WNet enumerator. Note that the type doesn't correspond to the scope of 00075 * the enumeration; it represents one of the following types: 00076 * - a 'null' enumeration, one that contains no members 00077 * - a global enumeration, one that's executed across all providers 00078 * - a provider-specific enumeration, one that's only executed by a single 00079 * provider 00080 * - a context enumeration. I know this contradicts what I just said about 00081 * there being no correspondence between the scope and the type, but it's 00082 * necessary for the special case that a "Entire Network" entry needs to 00083 * be enumerated in an enumeration of the context scope. Thus an enumeration 00084 * of the context scope results in a context type enumerator, which morphs 00085 * into a global enumeration (so the enumeration continues across all 00086 * providers). 00087 */ 00088 typedef struct _WNetEnumerator 00089 { 00090 DWORD enumType; 00091 DWORD providerIndex; 00092 HANDLE handle; 00093 BOOL providerDone; 00094 DWORD dwScope; 00095 DWORD dwType; 00096 DWORD dwUsage; 00097 LPNETRESOURCEW lpNet; 00098 } WNetEnumerator, *PWNetEnumerator; 00099 00100 #define BAD_PROVIDER_INDEX (DWORD)0xffffffff 00101 00102 /* Returns an index (into the global WNetProviderTable) of the provider with 00103 * the given name, or BAD_PROVIDER_INDEX if not found. 00104 */ 00105 static DWORD _findProviderIndexW(LPCWSTR lpProvider); 00106 00107 static PWNetProviderTable providerTable; 00108 00109 /* 00110 * Global provider table functions 00111 */ 00112 00113 static void _tryLoadProvider(PCWSTR provider) 00114 { 00115 static const WCHAR servicePrefix[] = { 'S','y','s','t','e','m','\\', 00116 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00117 'S','e','r','v','i','c','e','s','\\',0 }; 00118 static const WCHAR serviceFmt[] = { '%','s','%','s','\\', 00119 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r',0 }; 00120 WCHAR serviceName[MAX_PATH]; 00121 HKEY hKey; 00122 00123 TRACE("%s\n", debugstr_w(provider)); 00124 snprintfW(serviceName, sizeof(serviceName) / sizeof(WCHAR), serviceFmt, 00125 servicePrefix, provider); 00126 serviceName[sizeof(serviceName) / sizeof(WCHAR) - 1] = '\0'; 00127 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, serviceName, 0, KEY_READ, &hKey) == 00128 ERROR_SUCCESS) 00129 { 00130 static const WCHAR szProviderPath[] = { 'P','r','o','v','i','d','e','r', 00131 'P','a','t','h',0 }; 00132 WCHAR providerPath[MAX_PATH]; 00133 DWORD type, size = sizeof(providerPath); 00134 00135 if (RegQueryValueExW(hKey, szProviderPath, NULL, &type, 00136 (LPBYTE)providerPath, &size) == ERROR_SUCCESS && type == REG_SZ) 00137 { 00138 static const WCHAR szProviderName[] = { 'N','a','m','e',0 }; 00139 PWSTR name = NULL; 00140 00141 size = 0; 00142 RegQueryValueExW(hKey, szProviderName, NULL, NULL, NULL, &size); 00143 if (size) 00144 { 00145 name = HeapAlloc(GetProcessHeap(), 0, size); 00146 if (RegQueryValueExW(hKey, szProviderName, NULL, &type, 00147 (LPBYTE)name, &size) != ERROR_SUCCESS || type != REG_SZ) 00148 { 00149 HeapFree(GetProcessHeap(), 0, name); 00150 name = NULL; 00151 } 00152 } 00153 if (name) 00154 { 00155 HMODULE hLib = LoadLibraryW(providerPath); 00156 00157 if (hLib) 00158 { 00159 PF_NPGetCaps getCaps = (PF_NPGetCaps)GetProcAddress(hLib, 00160 "NPGetCaps"); 00161 00162 TRACE("loaded lib %p\n", hLib); 00163 if (getCaps) 00164 { 00165 PWNetProvider provider = 00166 &providerTable->table[providerTable->numProviders]; 00167 00168 provider->hLib = hLib; 00169 provider->name = name; 00170 TRACE("name is %s\n", debugstr_w(name)); 00171 provider->getCaps = getCaps; 00172 provider->dwSpecVersion = getCaps(WNNC_SPEC_VERSION); 00173 provider->dwNetType = getCaps(WNNC_NET_TYPE); 00174 TRACE("net type is 0x%08x\n", provider->dwNetType); 00175 provider->dwEnumScopes = getCaps(WNNC_ENUMERATION); 00176 if (provider->dwEnumScopes) 00177 { 00178 TRACE("supports enumeration\n"); 00179 provider->openEnum = (PF_NPOpenEnum) 00180 GetProcAddress(hLib, "NPOpenEnum"); 00181 TRACE("openEnum is %p\n", provider->openEnum); 00182 provider->enumResource = (PF_NPEnumResource) 00183 GetProcAddress(hLib, "NPEnumResource"); 00184 TRACE("enumResource is %p\n", 00185 provider->enumResource); 00186 provider->closeEnum = (PF_NPCloseEnum) 00187 GetProcAddress(hLib, "NPCloseEnum"); 00188 TRACE("closeEnum is %p\n", provider->closeEnum); 00189 provider->getResourceInformation = (PF_NPGetResourceInformation) 00190 GetProcAddress(hLib, "NPGetResourceInformation"); 00191 TRACE("getResourceInformation is %p\n", 00192 provider->getResourceInformation); 00193 if (!provider->openEnum || !provider->enumResource 00194 || !provider->closeEnum) 00195 { 00196 provider->openEnum = NULL; 00197 provider->enumResource = NULL; 00198 provider->closeEnum = NULL; 00199 provider->dwEnumScopes = 0; 00200 WARN("Couldn't load enumeration functions\n"); 00201 } 00202 } 00203 providerTable->numProviders++; 00204 } 00205 else 00206 { 00207 WARN("Provider %s didn't export NPGetCaps\n", 00208 debugstr_w(provider)); 00209 HeapFree(GetProcessHeap(), 0, name); 00210 FreeLibrary(hLib); 00211 } 00212 } 00213 else 00214 { 00215 WARN("Couldn't load library %s for provider %s\n", 00216 debugstr_w(providerPath), debugstr_w(provider)); 00217 HeapFree(GetProcessHeap(), 0, name); 00218 } 00219 } 00220 else 00221 { 00222 WARN("Couldn't get provider name for provider %s\n", 00223 debugstr_w(provider)); 00224 } 00225 } 00226 else 00227 WARN("Couldn't open value %s\n", debugstr_w(szProviderPath)); 00228 RegCloseKey(hKey); 00229 } 00230 else 00231 WARN("Couldn't open service key for provider %s\n", 00232 debugstr_w(provider)); 00233 } 00234 00235 void wnetInit(HINSTANCE hInstDll) 00236 { 00237 static const WCHAR providerOrderKey[] = { 'S','y','s','t','e','m','\\', 00238 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', 00239 'C','o','n','t','r','o','l','\\', 00240 'N','e','t','w','o','r','k','P','r','o','v','i','d','e','r','\\', 00241 'O','r','d','e','r',0 }; 00242 static const WCHAR providerOrder[] = { 'P','r','o','v','i','d','e','r', 00243 'O','r','d','e','r',0 }; 00244 HKEY hKey; 00245 00246 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, providerOrderKey, 0, KEY_READ, &hKey) 00247 == ERROR_SUCCESS) 00248 { 00249 DWORD size = 0; 00250 00251 RegQueryValueExW(hKey, providerOrder, NULL, NULL, NULL, &size); 00252 if (size) 00253 { 00254 PWSTR providers = HeapAlloc(GetProcessHeap(), 0, size); 00255 00256 if (providers) 00257 { 00258 DWORD type; 00259 00260 if (RegQueryValueExW(hKey, providerOrder, NULL, &type, 00261 (LPBYTE)providers, &size) == ERROR_SUCCESS && type == REG_SZ) 00262 { 00263 PWSTR ptr; 00264 DWORD numToAllocate; 00265 00266 TRACE("provider order is %s\n", debugstr_w(providers)); 00267 /* first count commas as a heuristic for how many to 00268 * allocate space for */ 00269 for (ptr = providers, numToAllocate = 1; ptr; ) 00270 { 00271 ptr = strchrW(ptr, ','); 00272 if (ptr) { 00273 numToAllocate++; 00274 ptr++; 00275 } 00276 } 00277 providerTable = 00278 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 00279 sizeof(WNetProviderTable) 00280 + (numToAllocate - 1) * sizeof(WNetProvider)); 00281 if (providerTable) 00282 { 00283 PWSTR ptrPrev; 00284 int entireNetworkLen; 00285 LPCWSTR stringresource; 00286 00287 entireNetworkLen = LoadStringW(hInstDll, 00288 IDS_ENTIRENETWORK, (LPWSTR)&stringresource, 0); 00289 providerTable->entireNetwork = HeapAlloc( 00290 GetProcessHeap(), 0, (entireNetworkLen + 1) * 00291 sizeof(WCHAR)); 00292 if (providerTable->entireNetwork) 00293 { 00294 memcpy(providerTable->entireNetwork, stringresource, entireNetworkLen*sizeof(WCHAR)); 00295 providerTable->entireNetwork[entireNetworkLen] = 0; 00296 } 00297 providerTable->numAllocated = numToAllocate; 00298 for (ptr = providers; ptr; ) 00299 { 00300 ptrPrev = ptr; 00301 ptr = strchrW(ptr, ','); 00302 if (ptr) 00303 *ptr++ = '\0'; 00304 _tryLoadProvider(ptrPrev); 00305 } 00306 } 00307 } 00308 HeapFree(GetProcessHeap(), 0, providers); 00309 } 00310 } 00311 RegCloseKey(hKey); 00312 } 00313 } 00314 00315 void wnetFree(void) 00316 { 00317 if (providerTable) 00318 { 00319 DWORD i; 00320 00321 for (i = 0; i < providerTable->numProviders; i++) 00322 { 00323 HeapFree(GetProcessHeap(), 0, providerTable->table[i].name); 00324 FreeModule(providerTable->table[i].hLib); 00325 } 00326 HeapFree(GetProcessHeap(), 0, providerTable->entireNetwork); 00327 HeapFree(GetProcessHeap(), 0, providerTable); 00328 providerTable = NULL; 00329 } 00330 } 00331 00332 static DWORD _findProviderIndexW(LPCWSTR lpProvider) 00333 { 00334 DWORD ret = BAD_PROVIDER_INDEX; 00335 00336 if (providerTable && providerTable->numProviders) 00337 { 00338 DWORD i; 00339 00340 for (i = 0; i < providerTable->numProviders && 00341 ret == BAD_PROVIDER_INDEX; i++) 00342 if (!strcmpW(lpProvider, providerTable->table[i].name)) 00343 ret = i; 00344 } 00345 return ret; 00346 } 00347 00348 /* 00349 * Browsing Functions 00350 */ 00351 00352 static LPNETRESOURCEW _copyNetResourceForEnumW(LPNETRESOURCEW lpNet) 00353 { 00354 LPNETRESOURCEW ret; 00355 00356 if (lpNet) 00357 { 00358 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(NETRESOURCEW)); 00359 if (ret) 00360 { 00361 size_t len; 00362 00363 *ret = *lpNet; 00364 ret->lpLocalName = ret->lpComment = ret->lpProvider = NULL; 00365 if (lpNet->lpRemoteName) 00366 { 00367 len = strlenW(lpNet->lpRemoteName) + 1; 00368 ret->lpRemoteName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00369 if (ret->lpRemoteName) 00370 strcpyW(ret->lpRemoteName, lpNet->lpRemoteName); 00371 } 00372 } 00373 } 00374 else 00375 ret = NULL; 00376 return ret; 00377 } 00378 00379 static void _freeEnumNetResource(LPNETRESOURCEW lpNet) 00380 { 00381 if (lpNet) 00382 { 00383 HeapFree(GetProcessHeap(), 0, lpNet->lpRemoteName); 00384 HeapFree(GetProcessHeap(), 0, lpNet); 00385 } 00386 } 00387 00388 static PWNetEnumerator _createNullEnumerator(void) 00389 { 00390 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(), 00391 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator)); 00392 00393 if (ret) 00394 ret->enumType = WNET_ENUMERATOR_TYPE_NULL; 00395 return ret; 00396 } 00397 00398 static PWNetEnumerator _createGlobalEnumeratorW(DWORD dwScope, DWORD dwType, 00399 DWORD dwUsage, LPNETRESOURCEW lpNet) 00400 { 00401 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(), 00402 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator)); 00403 00404 if (ret) 00405 { 00406 ret->enumType = WNET_ENUMERATOR_TYPE_GLOBAL; 00407 ret->dwScope = dwScope; 00408 ret->dwType = dwType; 00409 ret->dwUsage = dwUsage; 00410 ret->lpNet = _copyNetResourceForEnumW(lpNet); 00411 } 00412 return ret; 00413 } 00414 00415 static PWNetEnumerator _createProviderEnumerator(DWORD dwScope, DWORD dwType, 00416 DWORD dwUsage, DWORD index, HANDLE handle) 00417 { 00418 PWNetEnumerator ret; 00419 00420 if (!providerTable || index >= providerTable->numProviders) 00421 ret = NULL; 00422 else 00423 { 00424 ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WNetEnumerator)); 00425 if (ret) 00426 { 00427 ret->enumType = WNET_ENUMERATOR_TYPE_PROVIDER; 00428 ret->providerIndex = index; 00429 ret->dwScope = dwScope; 00430 ret->dwType = dwType; 00431 ret->dwUsage = dwUsage; 00432 ret->handle = handle; 00433 } 00434 } 00435 return ret; 00436 } 00437 00438 static PWNetEnumerator _createContextEnumerator(DWORD dwScope, DWORD dwType, 00439 DWORD dwUsage) 00440 { 00441 PWNetEnumerator ret = HeapAlloc(GetProcessHeap(), 00442 HEAP_ZERO_MEMORY, sizeof(WNetEnumerator)); 00443 00444 if (ret) 00445 { 00446 ret->enumType = WNET_ENUMERATOR_TYPE_CONTEXT; 00447 ret->dwScope = dwScope; 00448 ret->dwType = dwType; 00449 ret->dwUsage = dwUsage; 00450 } 00451 return ret; 00452 } 00453 00454 /* Thunks the array of wide-string LPNETRESOURCEs lpNetArrayIn into buffer 00455 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries 00456 * to start. On return, *lpcCount reflects the number thunked into lpBuffer. 00457 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA 00458 * if not all members of the array could be thunked, and something else on 00459 * failure. 00460 */ 00461 static DWORD _thunkNetResourceArrayWToA(const NETRESOURCEW *lpNetArrayIn, 00462 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize) 00463 { 00464 DWORD i, numToThunk, totalBytes, ret; 00465 LPSTR strNext; 00466 00467 if (!lpNetArrayIn) 00468 return WN_BAD_POINTER; 00469 if (!lpcCount) 00470 return WN_BAD_POINTER; 00471 if (*lpcCount == -1) 00472 return WN_BAD_VALUE; 00473 if (!lpBuffer) 00474 return WN_BAD_POINTER; 00475 if (!lpBufferSize) 00476 return WN_BAD_POINTER; 00477 00478 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++) 00479 { 00480 const NETRESOURCEW *lpNet = lpNetArrayIn + i; 00481 00482 totalBytes += sizeof(NETRESOURCEA); 00483 if (lpNet->lpLocalName) 00484 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpLocalName, 00485 -1, NULL, 0, NULL, NULL); 00486 if (lpNet->lpRemoteName) 00487 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpRemoteName, 00488 -1, NULL, 0, NULL, NULL); 00489 if (lpNet->lpComment) 00490 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpComment, 00491 -1, NULL, 0, NULL, NULL); 00492 if (lpNet->lpProvider) 00493 totalBytes += WideCharToMultiByte(CP_ACP, 0, lpNet->lpProvider, 00494 -1, NULL, 0, NULL, NULL); 00495 if (totalBytes < *lpBufferSize) 00496 numToThunk = i + 1; 00497 } 00498 strNext = (LPSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEA)); 00499 for (i = 0; i < numToThunk; i++) 00500 { 00501 LPNETRESOURCEA lpNetOut = (LPNETRESOURCEA)lpBuffer + i; 00502 const NETRESOURCEW *lpNetIn = lpNetArrayIn + i; 00503 00504 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEA)); 00505 /* lie about string lengths, we already verified how many 00506 * we have space for above 00507 */ 00508 if (lpNetIn->lpLocalName) 00509 { 00510 lpNetOut->lpLocalName = strNext; 00511 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpLocalName, -1, 00512 lpNetOut->lpLocalName, *lpBufferSize, NULL, NULL); 00513 } 00514 if (lpNetIn->lpRemoteName) 00515 { 00516 lpNetOut->lpRemoteName = strNext; 00517 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpRemoteName, -1, 00518 lpNetOut->lpRemoteName, *lpBufferSize, NULL, NULL); 00519 } 00520 if (lpNetIn->lpComment) 00521 { 00522 lpNetOut->lpComment = strNext; 00523 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpComment, -1, 00524 lpNetOut->lpComment, *lpBufferSize, NULL, NULL); 00525 } 00526 if (lpNetIn->lpProvider) 00527 { 00528 lpNetOut->lpProvider = strNext; 00529 strNext += WideCharToMultiByte(CP_ACP, 0, lpNetIn->lpProvider, -1, 00530 lpNetOut->lpProvider, *lpBufferSize, NULL, NULL); 00531 } 00532 } 00533 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS; 00534 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk, 00535 *lpcCount, ret); 00536 return ret; 00537 } 00538 00539 /* Thunks the array of multibyte-string LPNETRESOURCEs lpNetArrayIn into buffer 00540 * lpBuffer, with size *lpBufferSize. lpNetArrayIn contains *lpcCount entries 00541 * to start. On return, *lpcCount reflects the number thunked into lpBuffer. 00542 * Returns WN_SUCCESS on success (all of lpNetArrayIn thunked), WN_MORE_DATA 00543 * if not all members of the array could be thunked, and something else on 00544 * failure. 00545 */ 00546 static DWORD _thunkNetResourceArrayAToW(const NETRESOURCEA *lpNetArrayIn, 00547 const DWORD *lpcCount, LPVOID lpBuffer, const DWORD *lpBufferSize) 00548 { 00549 DWORD i, numToThunk, totalBytes, ret; 00550 LPWSTR strNext; 00551 00552 if (!lpNetArrayIn) 00553 return WN_BAD_POINTER; 00554 if (!lpcCount) 00555 return WN_BAD_POINTER; 00556 if (*lpcCount == -1) 00557 return WN_BAD_VALUE; 00558 if (!lpBuffer) 00559 return WN_BAD_POINTER; 00560 if (!lpBufferSize) 00561 return WN_BAD_POINTER; 00562 00563 for (i = 0, numToThunk = 0, totalBytes = 0; i < *lpcCount; i++) 00564 { 00565 const NETRESOURCEA *lpNet = lpNetArrayIn + i; 00566 00567 totalBytes += sizeof(NETRESOURCEW); 00568 if (lpNet->lpLocalName) 00569 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpLocalName, 00570 -1, NULL, 0) * sizeof(WCHAR); 00571 if (lpNet->lpRemoteName) 00572 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpRemoteName, 00573 -1, NULL, 0) * sizeof(WCHAR); 00574 if (lpNet->lpComment) 00575 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpComment, 00576 -1, NULL, 0) * sizeof(WCHAR); 00577 if (lpNet->lpProvider) 00578 totalBytes += MultiByteToWideChar(CP_ACP, 0, lpNet->lpProvider, 00579 -1, NULL, 0) * sizeof(WCHAR); 00580 if (totalBytes < *lpBufferSize) 00581 numToThunk = i + 1; 00582 } 00583 strNext = (LPWSTR)((LPBYTE)lpBuffer + numToThunk * sizeof(NETRESOURCEW)); 00584 for (i = 0; i < numToThunk; i++) 00585 { 00586 LPNETRESOURCEW lpNetOut = (LPNETRESOURCEW)lpBuffer + i; 00587 const NETRESOURCEA *lpNetIn = lpNetArrayIn + i; 00588 00589 memcpy(lpNetOut, lpNetIn, sizeof(NETRESOURCEW)); 00590 /* lie about string lengths, we already verified how many 00591 * we have space for above 00592 */ 00593 if (lpNetIn->lpLocalName) 00594 { 00595 lpNetOut->lpLocalName = strNext; 00596 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpLocalName, 00597 -1, lpNetOut->lpLocalName, *lpBufferSize); 00598 } 00599 if (lpNetIn->lpRemoteName) 00600 { 00601 lpNetOut->lpRemoteName = strNext; 00602 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpRemoteName, 00603 -1, lpNetOut->lpRemoteName, *lpBufferSize); 00604 } 00605 if (lpNetIn->lpComment) 00606 { 00607 lpNetOut->lpComment = strNext; 00608 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpComment, 00609 -1, lpNetOut->lpComment, *lpBufferSize); 00610 } 00611 if (lpNetIn->lpProvider) 00612 { 00613 lpNetOut->lpProvider = strNext; 00614 strNext += MultiByteToWideChar(CP_ACP, 0, lpNetIn->lpProvider, 00615 -1, lpNetOut->lpProvider, *lpBufferSize); 00616 } 00617 } 00618 ret = numToThunk < *lpcCount ? WN_MORE_DATA : WN_SUCCESS; 00619 TRACE("numToThunk is %d, *lpcCount is %d, returning %d\n", numToThunk, 00620 *lpcCount, ret); 00621 return ret; 00622 } 00623 00624 /********************************************************************* 00625 * WNetOpenEnumA [MPR.@] 00626 * 00627 * See comments for WNetOpenEnumW. 00628 */ 00629 DWORD WINAPI WNetOpenEnumA( DWORD dwScope, DWORD dwType, DWORD dwUsage, 00630 LPNETRESOURCEA lpNet, LPHANDLE lphEnum ) 00631 { 00632 DWORD ret; 00633 00634 TRACE( "(%08X, %08X, %08X, %p, %p)\n", 00635 dwScope, dwType, dwUsage, lpNet, lphEnum ); 00636 00637 if (!lphEnum) 00638 ret = WN_BAD_POINTER; 00639 else if (!providerTable || providerTable->numProviders == 0) 00640 { 00641 lphEnum = NULL; 00642 ret = WN_NO_NETWORK; 00643 } 00644 else 00645 { 00646 if (lpNet) 00647 { 00648 LPNETRESOURCEW lpNetWide = NULL; 00649 BYTE buf[1024]; 00650 DWORD size = sizeof(buf), count = 1; 00651 BOOL allocated = FALSE; 00652 00653 ret = _thunkNetResourceArrayAToW(lpNet, &count, buf, &size); 00654 if (ret == WN_MORE_DATA) 00655 { 00656 lpNetWide = HeapAlloc(GetProcessHeap(), 0, 00657 size); 00658 if (lpNetWide) 00659 { 00660 ret = _thunkNetResourceArrayAToW(lpNet, &count, lpNetWide, 00661 &size); 00662 allocated = TRUE; 00663 } 00664 else 00665 ret = WN_OUT_OF_MEMORY; 00666 } 00667 else if (ret == WN_SUCCESS) 00668 lpNetWide = (LPNETRESOURCEW)buf; 00669 if (ret == WN_SUCCESS) 00670 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, lpNetWide, 00671 lphEnum); 00672 if (allocated) 00673 HeapFree(GetProcessHeap(), 0, lpNetWide); 00674 } 00675 else 00676 ret = WNetOpenEnumW(dwScope, dwType, dwUsage, NULL, lphEnum); 00677 } 00678 if (ret) 00679 SetLastError(ret); 00680 TRACE("Returning %d\n", ret); 00681 return ret; 00682 } 00683 00684 /********************************************************************* 00685 * WNetOpenEnumW [MPR.@] 00686 * 00687 * Network enumeration has way too many parameters, so I'm not positive I got 00688 * them right. What I've got so far: 00689 * 00690 * - If the scope is RESOURCE_GLOBALNET, and no LPNETRESOURCE is passed, 00691 * all the network providers should be enumerated. 00692 * 00693 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and 00694 * and neither the LPNETRESOURCE's lpRemoteName nor the LPNETRESOURCE's 00695 * lpProvider is set, all the network providers should be enumerated. 00696 * (This means the enumeration is a list of network providers, not that the 00697 * enumeration is passed on to the providers.) 00698 * 00699 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and the 00700 * resource matches the "Entire Network" resource (no remote name, no 00701 * provider, comment is the "Entire Network" string), a RESOURCE_GLOBALNET 00702 * enumeration is done on every network provider. 00703 * 00704 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and 00705 * the LPNETRESOURCE's lpProvider is set, enumeration will be passed through 00706 * only to the given network provider. 00707 * 00708 * - If the scope is RESOURCE_GLOBALNET, and LPNETRESOURCE is passed, and 00709 * no lpProvider is set, enumeration will be tried on every network provider, 00710 * in the order in which they're loaded. 00711 * 00712 * - The LPNETRESOURCE should be disregarded for scopes besides 00713 * RESOURCE_GLOBALNET. MSDN states that lpNet must be NULL if dwScope is not 00714 * RESOURCE_GLOBALNET, but Windows doesn't return an error if it isn't NULL. 00715 * 00716 * - If the scope is RESOURCE_CONTEXT, MS includes an "Entire Network" net 00717 * resource in the enumerated list, as well as any machines in your 00718 * workgroup. The machines in your workgroup come from doing a 00719 * RESOURCE_CONTEXT enumeration of every Network Provider. 00720 */ 00721 DWORD WINAPI WNetOpenEnumW( DWORD dwScope, DWORD dwType, DWORD dwUsage, 00722 LPNETRESOURCEW lpNet, LPHANDLE lphEnum ) 00723 { 00724 DWORD ret; 00725 00726 TRACE( "(%08X, %08X, %08X, %p, %p)\n", 00727 dwScope, dwType, dwUsage, lpNet, lphEnum ); 00728 00729 if (!lphEnum) 00730 ret = WN_BAD_POINTER; 00731 else if (!providerTable || providerTable->numProviders == 0) 00732 { 00733 lphEnum = NULL; 00734 ret = WN_NO_NETWORK; 00735 } 00736 else 00737 { 00738 switch (dwScope) 00739 { 00740 case RESOURCE_GLOBALNET: 00741 if (lpNet) 00742 { 00743 if (lpNet->lpProvider) 00744 { 00745 DWORD index = _findProviderIndexW(lpNet->lpProvider); 00746 00747 if (index != BAD_PROVIDER_INDEX) 00748 { 00749 if (providerTable->table[index].openEnum && 00750 providerTable->table[index].dwEnumScopes & WNNC_ENUM_GLOBAL) 00751 { 00752 HANDLE handle; 00753 00754 ret = providerTable->table[index].openEnum( 00755 dwScope, dwType, dwUsage, lpNet, &handle); 00756 if (ret == WN_SUCCESS) 00757 { 00758 *lphEnum = _createProviderEnumerator( 00759 dwScope, dwType, dwUsage, index, handle); 00760 ret = *lphEnum ? WN_SUCCESS : 00761 WN_OUT_OF_MEMORY; 00762 } 00763 } 00764 else 00765 ret = WN_NOT_SUPPORTED; 00766 } 00767 else 00768 ret = WN_BAD_PROVIDER; 00769 } 00770 else if (lpNet->lpRemoteName) 00771 { 00772 *lphEnum = _createGlobalEnumeratorW(dwScope, 00773 dwType, dwUsage, lpNet); 00774 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY; 00775 } 00776 else 00777 { 00778 if (lpNet->lpComment && !strcmpW(lpNet->lpComment, 00779 providerTable->entireNetwork)) 00780 { 00781 /* comment matches the "Entire Network", enumerate 00782 * global scope of every provider 00783 */ 00784 *lphEnum = _createGlobalEnumeratorW(dwScope, 00785 dwType, dwUsage, lpNet); 00786 } 00787 else 00788 { 00789 /* this is the same as not having passed lpNet */ 00790 *lphEnum = _createGlobalEnumeratorW(dwScope, 00791 dwType, dwUsage, NULL); 00792 } 00793 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY; 00794 } 00795 } 00796 else 00797 { 00798 *lphEnum = _createGlobalEnumeratorW(dwScope, dwType, 00799 dwUsage, lpNet); 00800 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY; 00801 } 00802 break; 00803 case RESOURCE_CONTEXT: 00804 *lphEnum = _createContextEnumerator(dwScope, dwType, dwUsage); 00805 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY; 00806 break; 00807 case RESOURCE_REMEMBERED: 00808 case RESOURCE_CONNECTED: 00809 *lphEnum = _createNullEnumerator(); 00810 ret = *lphEnum ? WN_SUCCESS : WN_OUT_OF_MEMORY; 00811 break; 00812 default: 00813 WARN("unknown scope 0x%08x\n", dwScope); 00814 ret = WN_BAD_VALUE; 00815 } 00816 } 00817 if (ret) 00818 SetLastError(ret); 00819 TRACE("Returning %d\n", ret); 00820 return ret; 00821 } 00822 00823 /********************************************************************* 00824 * WNetEnumResourceA [MPR.@] 00825 */ 00826 DWORD WINAPI WNetEnumResourceA( HANDLE hEnum, LPDWORD lpcCount, 00827 LPVOID lpBuffer, LPDWORD lpBufferSize ) 00828 { 00829 DWORD ret; 00830 00831 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize ); 00832 00833 if (!hEnum) 00834 ret = WN_BAD_POINTER; 00835 else if (!lpcCount) 00836 ret = WN_BAD_POINTER; 00837 else if (!lpBuffer) 00838 ret = WN_BAD_POINTER; 00839 else if (!lpBufferSize) 00840 ret = WN_BAD_POINTER; 00841 else if (*lpBufferSize < sizeof(NETRESOURCEA)) 00842 { 00843 *lpBufferSize = sizeof(NETRESOURCEA); 00844 ret = WN_MORE_DATA; 00845 } 00846 else 00847 { 00848 DWORD localCount = *lpcCount, localSize = *lpBufferSize; 00849 LPVOID localBuffer = HeapAlloc(GetProcessHeap(), 0, localSize); 00850 00851 if (localBuffer) 00852 { 00853 ret = WNetEnumResourceW(hEnum, &localCount, localBuffer, 00854 &localSize); 00855 if (ret == WN_SUCCESS || (ret == WN_MORE_DATA && localCount != -1)) 00856 { 00857 /* FIXME: this isn't necessarily going to work in the case of 00858 * WN_MORE_DATA, because our enumerator may have moved on to 00859 * the next provider. MSDN states that a large (16KB) buffer 00860 * size is the appropriate usage of this function, so 00861 * hopefully it won't be an issue. 00862 */ 00863 ret = _thunkNetResourceArrayWToA(localBuffer, &localCount, 00864 lpBuffer, lpBufferSize); 00865 *lpcCount = localCount; 00866 } 00867 HeapFree(GetProcessHeap(), 0, localBuffer); 00868 } 00869 else 00870 ret = WN_OUT_OF_MEMORY; 00871 } 00872 if (ret) 00873 SetLastError(ret); 00874 TRACE("Returning %d\n", ret); 00875 return ret; 00876 } 00877 00878 static DWORD _countProviderBytesW(PWNetProvider provider) 00879 { 00880 DWORD ret; 00881 00882 if (provider) 00883 { 00884 ret = sizeof(NETRESOURCEW); 00885 ret += 2 * (strlenW(provider->name) + 1) * sizeof(WCHAR); 00886 } 00887 else 00888 ret = 0; 00889 return ret; 00890 } 00891 00892 static DWORD _enumerateProvidersW(PWNetEnumerator enumerator, LPDWORD lpcCount, 00893 LPVOID lpBuffer, const DWORD *lpBufferSize) 00894 { 00895 DWORD ret; 00896 00897 if (!enumerator) 00898 return WN_BAD_POINTER; 00899 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL) 00900 return WN_BAD_VALUE; 00901 if (!lpcCount) 00902 return WN_BAD_POINTER; 00903 if (!lpBuffer) 00904 return WN_BAD_POINTER; 00905 if (!lpBufferSize) 00906 return WN_BAD_POINTER; 00907 if (*lpBufferSize < sizeof(NETRESOURCEA)) 00908 return WN_MORE_DATA; 00909 00910 if (!providerTable || enumerator->providerIndex >= 00911 providerTable->numProviders) 00912 ret = WN_NO_MORE_ENTRIES; 00913 else 00914 { 00915 DWORD bytes = 0, count = 0, countLimit, i; 00916 LPNETRESOURCEW resource; 00917 LPWSTR strNext; 00918 00919 countLimit = *lpcCount == -1 ? 00920 providerTable->numProviders - enumerator->providerIndex : *lpcCount; 00921 while (count < countLimit && bytes < *lpBufferSize) 00922 { 00923 DWORD bytesNext = _countProviderBytesW( 00924 &providerTable->table[count + enumerator->providerIndex]); 00925 00926 if (bytes + bytesNext < *lpBufferSize) 00927 { 00928 bytes += bytesNext; 00929 count++; 00930 } 00931 } 00932 strNext = (LPWSTR)((LPBYTE)lpBuffer + count * sizeof(NETRESOURCEW)); 00933 for (i = 0, resource = lpBuffer; i < count; i++, resource++) 00934 { 00935 resource->dwScope = RESOURCE_GLOBALNET; 00936 resource->dwType = RESOURCETYPE_ANY; 00937 resource->dwDisplayType = RESOURCEDISPLAYTYPE_NETWORK; 00938 resource->dwUsage = RESOURCEUSAGE_CONTAINER | 00939 RESOURCEUSAGE_RESERVED; 00940 resource->lpLocalName = NULL; 00941 resource->lpRemoteName = strNext; 00942 strcpyW(resource->lpRemoteName, 00943 providerTable->table[i + enumerator->providerIndex].name); 00944 strNext += strlenW(resource->lpRemoteName) + 1; 00945 resource->lpComment = NULL; 00946 resource->lpProvider = strNext; 00947 strcpyW(resource->lpProvider, 00948 providerTable->table[i + enumerator->providerIndex].name); 00949 strNext += strlenW(resource->lpProvider) + 1; 00950 } 00951 enumerator->providerIndex += count; 00952 *lpcCount = count; 00953 ret = count > 0 ? WN_SUCCESS : WN_MORE_DATA; 00954 } 00955 TRACE("Returning %d\n", ret); 00956 return ret; 00957 } 00958 00959 /* Advances the enumerator (assumed to be a global enumerator) to the next 00960 * provider that supports the enumeration scope passed to WNetOpenEnum. Does 00961 * not open a handle with the next provider. 00962 * If the existing handle is NULL, may leave the enumerator unchanged, since 00963 * the current provider may support the desired scope. 00964 * If the existing handle is not NULL, closes it before moving on. 00965 * Returns WN_SUCCESS on success, WN_NO_MORE_ENTRIES if there is no available 00966 * provider, and another error on failure. 00967 */ 00968 static DWORD _globalEnumeratorAdvance(PWNetEnumerator enumerator) 00969 { 00970 if (!enumerator) 00971 return WN_BAD_POINTER; 00972 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL) 00973 return WN_BAD_VALUE; 00974 if (!providerTable || enumerator->providerIndex >= 00975 providerTable->numProviders) 00976 return WN_NO_MORE_ENTRIES; 00977 00978 if (enumerator->providerDone) 00979 { 00980 DWORD dwEnum = 0; 00981 enumerator->providerDone = FALSE; 00982 if (enumerator->handle) 00983 { 00984 providerTable->table[enumerator->providerIndex].closeEnum( 00985 enumerator->handle); 00986 enumerator->handle = NULL; 00987 enumerator->providerIndex++; 00988 } 00989 if (enumerator->dwScope == RESOURCE_CONNECTED) 00990 dwEnum = WNNC_ENUM_LOCAL; 00991 else if (enumerator->dwScope == RESOURCE_GLOBALNET) 00992 dwEnum = WNNC_ENUM_GLOBAL; 00993 else if (enumerator->dwScope == RESOURCE_CONTEXT) 00994 dwEnum = WNNC_ENUM_CONTEXT; 00995 for (; enumerator->providerIndex < providerTable->numProviders && 00996 !(providerTable->table[enumerator->providerIndex].dwEnumScopes 00997 & dwEnum); enumerator->providerIndex++) 00998 ; 00999 } 01000 return enumerator->providerIndex < providerTable->numProviders ? 01001 WN_SUCCESS : WN_NO_MORE_ENTRIES; 01002 } 01003 01004 /* "Passes through" call to the next provider that supports the enumeration 01005 * type. 01006 * FIXME: if one call to a provider's enumerator succeeds while there's still 01007 * space in lpBuffer, I don't call to the next provider. The caller may not 01008 * expect that it should call EnumResourceW again with a return value of 01009 * WN_SUCCESS (depending what *lpcCount was to begin with). That means strings 01010 * may have to be moved around a bit, ick. 01011 */ 01012 static DWORD _enumerateGlobalPassthroughW(PWNetEnumerator enumerator, 01013 LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize) 01014 { 01015 DWORD ret; 01016 01017 if (!enumerator) 01018 return WN_BAD_POINTER; 01019 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL) 01020 return WN_BAD_VALUE; 01021 if (!lpcCount) 01022 return WN_BAD_POINTER; 01023 if (!lpBuffer) 01024 return WN_BAD_POINTER; 01025 if (!lpBufferSize) 01026 return WN_BAD_POINTER; 01027 if (*lpBufferSize < sizeof(NETRESOURCEW)) 01028 return WN_MORE_DATA; 01029 01030 ret = _globalEnumeratorAdvance(enumerator); 01031 if (ret == WN_SUCCESS) 01032 { 01033 ret = providerTable->table[enumerator->providerIndex]. 01034 openEnum(enumerator->dwScope, enumerator->dwType, 01035 enumerator->dwUsage, enumerator->lpNet, 01036 &enumerator->handle); 01037 if (ret == WN_SUCCESS) 01038 { 01039 ret = providerTable->table[enumerator->providerIndex]. 01040 enumResource(enumerator->handle, lpcCount, lpBuffer, 01041 lpBufferSize); 01042 if (ret != WN_MORE_DATA) 01043 enumerator->providerDone = TRUE; 01044 } 01045 } 01046 TRACE("Returning %d\n", ret); 01047 return ret; 01048 } 01049 01050 static DWORD _enumerateGlobalW(PWNetEnumerator enumerator, LPDWORD lpcCount, 01051 LPVOID lpBuffer, LPDWORD lpBufferSize) 01052 { 01053 DWORD ret; 01054 01055 if (!enumerator) 01056 return WN_BAD_POINTER; 01057 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_GLOBAL) 01058 return WN_BAD_VALUE; 01059 if (!lpcCount) 01060 return WN_BAD_POINTER; 01061 if (!lpBuffer) 01062 return WN_BAD_POINTER; 01063 if (!lpBufferSize) 01064 return WN_BAD_POINTER; 01065 if (*lpBufferSize < sizeof(NETRESOURCEW)) 01066 return WN_MORE_DATA; 01067 if (!providerTable) 01068 return WN_NO_NETWORK; 01069 01070 switch (enumerator->dwScope) 01071 { 01072 case RESOURCE_GLOBALNET: 01073 if (enumerator->lpNet) 01074 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, 01075 lpBuffer, lpBufferSize); 01076 else 01077 ret = _enumerateProvidersW(enumerator, lpcCount, lpBuffer, 01078 lpBufferSize); 01079 break; 01080 case RESOURCE_CONTEXT: 01081 ret = _enumerateGlobalPassthroughW(enumerator, lpcCount, lpBuffer, 01082 lpBufferSize); 01083 break; 01084 default: 01085 WARN("unexpected scope 0x%08x\n", enumerator->dwScope); 01086 ret = WN_NO_MORE_ENTRIES; 01087 } 01088 TRACE("Returning %d\n", ret); 01089 return ret; 01090 } 01091 01092 static DWORD _enumerateProviderW(PWNetEnumerator enumerator, LPDWORD lpcCount, 01093 LPVOID lpBuffer, LPDWORD lpBufferSize) 01094 { 01095 if (!enumerator) 01096 return WN_BAD_POINTER; 01097 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_PROVIDER) 01098 return WN_BAD_VALUE; 01099 if (!enumerator->handle) 01100 return WN_BAD_VALUE; 01101 if (!lpcCount) 01102 return WN_BAD_POINTER; 01103 if (!lpBuffer) 01104 return WN_BAD_POINTER; 01105 if (!lpBufferSize) 01106 return WN_BAD_POINTER; 01107 if (!providerTable) 01108 return WN_NO_NETWORK; 01109 if (enumerator->providerIndex >= providerTable->numProviders) 01110 return WN_NO_MORE_ENTRIES; 01111 if (!providerTable->table[enumerator->providerIndex].enumResource) 01112 return WN_BAD_VALUE; 01113 return providerTable->table[enumerator->providerIndex].enumResource( 01114 enumerator->handle, lpcCount, lpBuffer, lpBufferSize); 01115 } 01116 01117 static DWORD _enumerateContextW(PWNetEnumerator enumerator, LPDWORD lpcCount, 01118 LPVOID lpBuffer, LPDWORD lpBufferSize) 01119 { 01120 DWORD ret; 01121 size_t cchEntireNetworkLen, bytesNeeded; 01122 01123 if (!enumerator) 01124 return WN_BAD_POINTER; 01125 if (enumerator->enumType != WNET_ENUMERATOR_TYPE_CONTEXT) 01126 return WN_BAD_VALUE; 01127 if (!lpcCount) 01128 return WN_BAD_POINTER; 01129 if (!lpBuffer) 01130 return WN_BAD_POINTER; 01131 if (!lpBufferSize) 01132 return WN_BAD_POINTER; 01133 if (!providerTable) 01134 return WN_NO_NETWORK; 01135 01136 cchEntireNetworkLen = strlenW(providerTable->entireNetwork) + 1; 01137 bytesNeeded = sizeof(NETRESOURCEW) + cchEntireNetworkLen * sizeof(WCHAR); 01138 if (*lpBufferSize < bytesNeeded) 01139 { 01140 *lpBufferSize = bytesNeeded; 01141 ret = WN_MORE_DATA; 01142 } 01143 else 01144 { 01145 LPNETRESOURCEW lpNet = lpBuffer; 01146 01147 lpNet->dwScope = RESOURCE_GLOBALNET; 01148 lpNet->dwType = enumerator->dwType; 01149 lpNet->dwDisplayType = RESOURCEDISPLAYTYPE_ROOT; 01150 lpNet->dwUsage = RESOURCEUSAGE_CONTAINER; 01151 lpNet->lpLocalName = NULL; 01152 lpNet->lpRemoteName = NULL; 01153 lpNet->lpProvider = NULL; 01154 /* odd, but correct: put comment at end of buffer, so it won't get 01155 * overwritten by subsequent calls to a provider's enumResource 01156 */ 01157 lpNet->lpComment = (LPWSTR)((LPBYTE)lpBuffer + *lpBufferSize - 01158 (cchEntireNetworkLen * sizeof(WCHAR))); 01159 strcpyW(lpNet->lpComment, providerTable->entireNetwork); 01160 ret = WN_SUCCESS; 01161 } 01162 if (ret == WN_SUCCESS) 01163 { 01164 DWORD bufferSize = *lpBufferSize - bytesNeeded; 01165 01166 /* "Entire Network" entry enumerated--morph this into a global 01167 * enumerator. enumerator->lpNet continues to be NULL, since it has 01168 * no meaning when the scope isn't RESOURCE_GLOBALNET. 01169 */ 01170 enumerator->enumType = WNET_ENUMERATOR_TYPE_GLOBAL; 01171 ret = _enumerateGlobalW(enumerator, lpcCount, 01172 (LPBYTE)lpBuffer + bytesNeeded, &bufferSize); 01173 if (ret == WN_SUCCESS) 01174 { 01175 /* reflect the fact that we already enumerated "Entire Network" */ 01176 lpcCount++; 01177 *lpBufferSize = bufferSize + bytesNeeded; 01178 } 01179 else 01180 { 01181 /* the provider enumeration failed, but we already succeeded in 01182 * enumerating "Entire Network"--leave type as global to allow a 01183 * retry, but indicate success with a count of one. 01184 */ 01185 ret = WN_SUCCESS; 01186 *lpcCount = 1; 01187 *lpBufferSize = bytesNeeded; 01188 } 01189 } 01190 TRACE("Returning %d\n", ret); 01191 return ret; 01192 } 01193 01194 /********************************************************************* 01195 * WNetEnumResourceW [MPR.@] 01196 */ 01197 DWORD WINAPI WNetEnumResourceW( HANDLE hEnum, LPDWORD lpcCount, 01198 LPVOID lpBuffer, LPDWORD lpBufferSize ) 01199 { 01200 DWORD ret; 01201 01202 TRACE( "(%p, %p, %p, %p)\n", hEnum, lpcCount, lpBuffer, lpBufferSize ); 01203 01204 if (!hEnum) 01205 ret = WN_BAD_POINTER; 01206 else if (!lpcCount) 01207 ret = WN_BAD_POINTER; 01208 else if (!lpBuffer) 01209 ret = WN_BAD_POINTER; 01210 else if (!lpBufferSize) 01211 ret = WN_BAD_POINTER; 01212 else if (*lpBufferSize < sizeof(NETRESOURCEW)) 01213 { 01214 *lpBufferSize = sizeof(NETRESOURCEW); 01215 ret = WN_MORE_DATA; 01216 } 01217 else 01218 { 01219 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum; 01220 01221 switch (enumerator->enumType) 01222 { 01223 case WNET_ENUMERATOR_TYPE_NULL: 01224 ret = WN_NO_MORE_ENTRIES; 01225 break; 01226 case WNET_ENUMERATOR_TYPE_GLOBAL: 01227 ret = _enumerateGlobalW(enumerator, lpcCount, lpBuffer, 01228 lpBufferSize); 01229 break; 01230 case WNET_ENUMERATOR_TYPE_PROVIDER: 01231 ret = _enumerateProviderW(enumerator, lpcCount, lpBuffer, 01232 lpBufferSize); 01233 break; 01234 case WNET_ENUMERATOR_TYPE_CONTEXT: 01235 ret = _enumerateContextW(enumerator, lpcCount, lpBuffer, 01236 lpBufferSize); 01237 break; 01238 default: 01239 WARN("bogus enumerator type!\n"); 01240 ret = WN_NO_NETWORK; 01241 } 01242 } 01243 if (ret) 01244 SetLastError(ret); 01245 TRACE("Returning %d\n", ret); 01246 return ret; 01247 } 01248 01249 /********************************************************************* 01250 * WNetCloseEnum [MPR.@] 01251 */ 01252 DWORD WINAPI WNetCloseEnum( HANDLE hEnum ) 01253 { 01254 DWORD ret; 01255 01256 TRACE( "(%p)\n", hEnum ); 01257 01258 if (hEnum) 01259 { 01260 PWNetEnumerator enumerator = (PWNetEnumerator)hEnum; 01261 01262 switch (enumerator->enumType) 01263 { 01264 case WNET_ENUMERATOR_TYPE_NULL: 01265 ret = WN_SUCCESS; 01266 break; 01267 case WNET_ENUMERATOR_TYPE_GLOBAL: 01268 if (enumerator->lpNet) 01269 _freeEnumNetResource(enumerator->lpNet); 01270 if (enumerator->handle) 01271 providerTable->table[enumerator->providerIndex]. 01272 closeEnum(enumerator->handle); 01273 ret = WN_SUCCESS; 01274 break; 01275 case WNET_ENUMERATOR_TYPE_PROVIDER: 01276 if (enumerator->handle) 01277 providerTable->table[enumerator->providerIndex]. 01278 closeEnum(enumerator->handle); 01279 ret = WN_SUCCESS; 01280 break; 01281 default: 01282 WARN("bogus enumerator type!\n"); 01283 ret = WN_BAD_HANDLE; 01284 } 01285 HeapFree(GetProcessHeap(), 0, hEnum); 01286 } 01287 else 01288 ret = WN_BAD_HANDLE; 01289 if (ret) 01290 SetLastError(ret); 01291 TRACE("Returning %d\n", ret); 01292 return ret; 01293 } 01294 01295 /********************************************************************* 01296 * WNetGetResourceInformationA [MPR.@] 01297 * 01298 * See WNetGetResourceInformationW 01299 */ 01300 DWORD WINAPI WNetGetResourceInformationA( LPNETRESOURCEA lpNetResource, 01301 LPVOID lpBuffer, LPDWORD cbBuffer, 01302 LPSTR *lplpSystem ) 01303 { 01304 DWORD ret; 01305 01306 TRACE( "(%p, %p, %p, %p)\n", 01307 lpNetResource, lpBuffer, cbBuffer, lplpSystem ); 01308 01309 if (!providerTable || providerTable->numProviders == 0) 01310 ret = WN_NO_NETWORK; 01311 else if (lpNetResource) 01312 { 01313 LPNETRESOURCEW lpNetResourceW = NULL; 01314 DWORD size = 1024, count = 1; 01315 DWORD len; 01316 01317 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size); 01318 ret = _thunkNetResourceArrayAToW(lpNetResource, &count, lpNetResourceW, &size); 01319 if (ret == WN_MORE_DATA) 01320 { 01321 HeapFree(GetProcessHeap(), 0, lpNetResourceW); 01322 lpNetResourceW = HeapAlloc(GetProcessHeap(), 0, size); 01323 if (lpNetResourceW) 01324 ret = _thunkNetResourceArrayAToW(lpNetResource, 01325 &count, lpNetResourceW, &size); 01326 else 01327 ret = WN_OUT_OF_MEMORY; 01328 } 01329 if (ret == WN_SUCCESS) 01330 { 01331 LPWSTR lpSystemW = NULL; 01332 LPVOID lpBufferW; 01333 size = 1024; 01334 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size); 01335 if (lpBufferW) 01336 { 01337 ret = WNetGetResourceInformationW(lpNetResourceW, 01338 lpBufferW, &size, &lpSystemW); 01339 if (ret == WN_MORE_DATA) 01340 { 01341 HeapFree(GetProcessHeap(), 0, lpBufferW); 01342 lpBufferW = HeapAlloc(GetProcessHeap(), 0, size); 01343 if (lpBufferW) 01344 ret = WNetGetResourceInformationW(lpNetResourceW, 01345 lpBufferW, &size, &lpSystemW); 01346 else 01347 ret = WN_OUT_OF_MEMORY; 01348 } 01349 if (ret == WN_SUCCESS) 01350 { 01351 ret = _thunkNetResourceArrayWToA(lpBufferW, 01352 &count, lpBuffer, cbBuffer); 01353 HeapFree(GetProcessHeap(), 0, lpNetResourceW); 01354 lpNetResourceW = lpBufferW; 01355 size = sizeof(NETRESOURCEA); 01356 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpRemoteName, 01357 -1, NULL, 0, NULL, NULL); 01358 size += WideCharToMultiByte(CP_ACP, 0, lpNetResourceW->lpProvider, 01359 -1, NULL, 0, NULL, NULL); 01360 01361 len = WideCharToMultiByte(CP_ACP, 0, lpSystemW, 01362 -1, NULL, 0, NULL, NULL); 01363 if ((len) && ( size + len < *cbBuffer)) 01364 { 01365 *lplpSystem = (char*)lpBuffer + *cbBuffer - len; 01366 WideCharToMultiByte(CP_ACP, 0, lpSystemW, -1, 01367 *lplpSystem, len, NULL, NULL); 01368 ret = WN_SUCCESS; 01369 } 01370 else 01371 ret = WN_MORE_DATA; 01372 } 01373 else 01374 ret = WN_OUT_OF_MEMORY; 01375 HeapFree(GetProcessHeap(), 0, lpBufferW); 01376 } 01377 else 01378 ret = WN_OUT_OF_MEMORY; 01379 HeapFree(GetProcessHeap(), 0, lpSystemW); 01380 } 01381 HeapFree(GetProcessHeap(), 0, lpNetResourceW); 01382 } 01383 else 01384 ret = WN_NO_NETWORK; 01385 01386 if (ret) 01387 SetLastError(ret); 01388 TRACE("Returning %d\n", ret); 01389 return ret; 01390 } 01391 01392 /********************************************************************* 01393 * WNetGetResourceInformationW [MPR.@] 01394 * 01395 * WNetGetResourceInformationW function identifies the network provider 01396 * that owns the resource and gets information about the type of the resource. 01397 * 01398 * PARAMS: 01399 * lpNetResource [ I] the pointer to NETRESOURCEW structure, that 01400 * defines a network resource. 01401 * lpBuffer [ O] the pointer to buffer, containing result. It 01402 * contains NETRESOURCEW structure and strings to 01403 * which the members of the NETRESOURCEW structure 01404 * point. 01405 * cbBuffer [I/O] the pointer to DWORD number - size of buffer 01406 * in bytes. 01407 * lplpSystem [ O] the pointer to string in the output buffer, 01408 * containing the part of the resource name without 01409 * names of the server and share. 01410 * 01411 * RETURNS: 01412 * NO_ERROR if the function succeeds. System error code if the function fails. 01413 */ 01414 01415 DWORD WINAPI WNetGetResourceInformationW( LPNETRESOURCEW lpNetResource, 01416 LPVOID lpBuffer, LPDWORD cbBuffer, 01417 LPWSTR *lplpSystem ) 01418 { 01419 DWORD ret = WN_NO_NETWORK; 01420 DWORD index; 01421 01422 TRACE( "(%p, %p, %p, %p)\n", 01423 lpNetResource, lpBuffer, cbBuffer, lplpSystem); 01424 01425 if (!(lpBuffer)) 01426 ret = WN_OUT_OF_MEMORY; 01427 else if (providerTable != NULL) 01428 { 01429 /* FIXME: For function value of a variable is indifferent, it does 01430 * search of all providers in a network. 01431 */ 01432 for (index = 0; index < providerTable->numProviders; index++) 01433 { 01434 if(providerTable->table[index].getCaps(WNNC_DIALOG) & 01435 WNNC_DLG_GETRESOURCEINFORMATION) 01436 { 01437 if (providerTable->table[index].getResourceInformation) 01438 ret = providerTable->table[index].getResourceInformation( 01439 lpNetResource, lpBuffer, cbBuffer, lplpSystem); 01440 else 01441 ret = WN_NO_NETWORK; 01442 if (ret == WN_SUCCESS) 01443 break; 01444 } 01445 } 01446 } 01447 if (ret) 01448 SetLastError(ret); 01449 return ret; 01450 } 01451 01452 /********************************************************************* 01453 * WNetGetResourceParentA [MPR.@] 01454 */ 01455 DWORD WINAPI WNetGetResourceParentA( LPNETRESOURCEA lpNetResource, 01456 LPVOID lpBuffer, LPDWORD lpBufferSize ) 01457 { 01458 FIXME( "(%p, %p, %p): stub\n", 01459 lpNetResource, lpBuffer, lpBufferSize ); 01460 01461 SetLastError(WN_NO_NETWORK); 01462 return WN_NO_NETWORK; 01463 } 01464 01465 /********************************************************************* 01466 * WNetGetResourceParentW [MPR.@] 01467 */ 01468 DWORD WINAPI WNetGetResourceParentW( LPNETRESOURCEW lpNetResource, 01469 LPVOID lpBuffer, LPDWORD lpBufferSize ) 01470 { 01471 FIXME( "(%p, %p, %p): stub\n", 01472 lpNetResource, lpBuffer, lpBufferSize ); 01473 01474 SetLastError(WN_NO_NETWORK); 01475 return WN_NO_NETWORK; 01476 } 01477 01478 01479 01480 /* 01481 * Connection Functions 01482 */ 01483 01484 /********************************************************************* 01485 * WNetAddConnectionA [MPR.@] 01486 */ 01487 DWORD WINAPI WNetAddConnectionA( LPCSTR lpRemoteName, LPCSTR lpPassword, 01488 LPCSTR lpLocalName ) 01489 { 01490 FIXME( "(%s, %p, %s): stub\n", 01491 debugstr_a(lpRemoteName), lpPassword, debugstr_a(lpLocalName) ); 01492 01493 SetLastError(WN_NO_NETWORK); 01494 return WN_NO_NETWORK; 01495 } 01496 01497 /********************************************************************* 01498 * WNetAddConnectionW [MPR.@] 01499 */ 01500 DWORD WINAPI WNetAddConnectionW( LPCWSTR lpRemoteName, LPCWSTR lpPassword, 01501 LPCWSTR lpLocalName ) 01502 { 01503 FIXME( "(%s, %p, %s): stub\n", 01504 debugstr_w(lpRemoteName), lpPassword, debugstr_w(lpLocalName) ); 01505 01506 SetLastError(WN_NO_NETWORK); 01507 return WN_NO_NETWORK; 01508 } 01509 01510 /********************************************************************* 01511 * WNetAddConnection2A [MPR.@] 01512 */ 01513 DWORD WINAPI WNetAddConnection2A( LPNETRESOURCEA lpNetResource, 01514 LPCSTR lpPassword, LPCSTR lpUserID, 01515 DWORD dwFlags ) 01516 { 01517 FIXME( "(%p, %p, %s, 0x%08X): stub\n", 01518 lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags ); 01519 01520 SetLastError(WN_NO_NETWORK); 01521 return WN_NO_NETWORK; 01522 } 01523 01524 /********************************************************************* 01525 * WNetAddConnection2W [MPR.@] 01526 */ 01527 DWORD WINAPI WNetAddConnection2W( LPNETRESOURCEW lpNetResource, 01528 LPCWSTR lpPassword, LPCWSTR lpUserID, 01529 DWORD dwFlags ) 01530 { 01531 FIXME( "(%p, %p, %s, 0x%08X): stub\n", 01532 lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags ); 01533 01534 SetLastError(WN_NO_NETWORK); 01535 return WN_NO_NETWORK; 01536 } 01537 01538 /********************************************************************* 01539 * WNetAddConnection3A [MPR.@] 01540 */ 01541 DWORD WINAPI WNetAddConnection3A( HWND hwndOwner, LPNETRESOURCEA lpNetResource, 01542 LPCSTR lpPassword, LPCSTR lpUserID, 01543 DWORD dwFlags ) 01544 { 01545 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n", 01546 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags ); 01547 01548 SetLastError(WN_NO_NETWORK); 01549 return WN_NO_NETWORK; 01550 } 01551 01552 /********************************************************************* 01553 * WNetAddConnection3W [MPR.@] 01554 */ 01555 DWORD WINAPI WNetAddConnection3W( HWND hwndOwner, LPNETRESOURCEW lpNetResource, 01556 LPCWSTR lpPassword, LPCWSTR lpUserID, 01557 DWORD dwFlags ) 01558 { 01559 FIXME( "(%p, %p, %p, %s, 0x%08X), stub\n", 01560 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags ); 01561 01562 SetLastError(WN_NO_NETWORK); 01563 return WN_NO_NETWORK; 01564 } 01565 01566 /***************************************************************** 01567 * WNetUseConnectionA [MPR.@] 01568 */ 01569 DWORD WINAPI WNetUseConnectionA( HWND hwndOwner, LPNETRESOURCEA lpNetResource, 01570 LPCSTR lpPassword, LPCSTR lpUserID, DWORD dwFlags, 01571 LPSTR lpAccessName, LPDWORD lpBufferSize, 01572 LPDWORD lpResult ) 01573 { 01574 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", 01575 hwndOwner, lpNetResource, lpPassword, debugstr_a(lpUserID), dwFlags, 01576 debugstr_a(lpAccessName), lpBufferSize, lpResult ); 01577 01578 SetLastError(WN_NO_NETWORK); 01579 return WN_NO_NETWORK; 01580 } 01581 01582 /***************************************************************** 01583 * WNetUseConnectionW [MPR.@] 01584 */ 01585 DWORD WINAPI WNetUseConnectionW( HWND hwndOwner, LPNETRESOURCEW lpNetResource, 01586 LPCWSTR lpPassword, LPCWSTR lpUserID, DWORD dwFlags, 01587 LPWSTR lpAccessName, LPDWORD lpBufferSize, 01588 LPDWORD lpResult ) 01589 { 01590 FIXME( "(%p, %p, %p, %s, 0x%08X, %s, %p, %p), stub\n", 01591 hwndOwner, lpNetResource, lpPassword, debugstr_w(lpUserID), dwFlags, 01592 debugstr_w(lpAccessName), lpBufferSize, lpResult ); 01593 01594 SetLastError(WN_NO_NETWORK); 01595 return WN_NO_NETWORK; 01596 } 01597 01598 /********************************************************************* 01599 * WNetCancelConnectionA [MPR.@] 01600 */ 01601 DWORD WINAPI WNetCancelConnectionA( LPCSTR lpName, BOOL fForce ) 01602 { 01603 FIXME( "(%s, %d), stub\n", debugstr_a(lpName), fForce ); 01604 01605 return WN_SUCCESS; 01606 } 01607 01608 /********************************************************************* 01609 * WNetCancelConnectionW [MPR.@] 01610 */ 01611 DWORD WINAPI WNetCancelConnectionW( LPCWSTR lpName, BOOL fForce ) 01612 { 01613 FIXME( "(%s, %d), stub\n", debugstr_w(lpName), fForce ); 01614 01615 return WN_SUCCESS; 01616 } 01617 01618 /********************************************************************* 01619 * WNetCancelConnection2A [MPR.@] 01620 */ 01621 DWORD WINAPI WNetCancelConnection2A( LPCSTR lpName, DWORD dwFlags, BOOL fForce ) 01622 { 01623 FIXME( "(%s, %08X, %d), stub\n", debugstr_a(lpName), dwFlags, fForce ); 01624 01625 return WN_SUCCESS; 01626 } 01627 01628 /********************************************************************* 01629 * WNetCancelConnection2W [MPR.@] 01630 */ 01631 DWORD WINAPI WNetCancelConnection2W( LPCWSTR lpName, DWORD dwFlags, BOOL fForce ) 01632 { 01633 FIXME( "(%s, %08X, %d), stub\n", debugstr_w(lpName), dwFlags, fForce ); 01634 01635 return WN_SUCCESS; 01636 } 01637 01638 /***************************************************************** 01639 * WNetRestoreConnectionA [MPR.@] 01640 */ 01641 DWORD WINAPI WNetRestoreConnectionA( HWND hwndOwner, LPCSTR lpszDevice ) 01642 { 01643 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_a(lpszDevice) ); 01644 01645 SetLastError(WN_NO_NETWORK); 01646 return WN_NO_NETWORK; 01647 } 01648 01649 /***************************************************************** 01650 * WNetRestoreConnectionW [MPR.@] 01651 */ 01652 DWORD WINAPI WNetRestoreConnectionW( HWND hwndOwner, LPCWSTR lpszDevice ) 01653 { 01654 FIXME( "(%p, %s), stub\n", hwndOwner, debugstr_w(lpszDevice) ); 01655 01656 SetLastError(WN_NO_NETWORK); 01657 return WN_NO_NETWORK; 01658 } 01659 01660 /************************************************************************** 01661 * WNetGetConnectionA [MPR.@] 01662 * 01663 * RETURNS 01664 * - WN_BAD_LOCALNAME lpLocalName makes no sense 01665 * - WN_NOT_CONNECTED drive is a local drive 01666 * - WN_MORE_DATA buffer isn't big enough 01667 * - WN_SUCCESS success (net path in buffer) 01668 * 01669 * FIXME: need to test return values under different errors 01670 */ 01671 DWORD WINAPI WNetGetConnectionA( LPCSTR lpLocalName, 01672 LPSTR lpRemoteName, LPDWORD lpBufferSize ) 01673 { 01674 DWORD ret; 01675 01676 if (!lpLocalName) 01677 ret = WN_BAD_POINTER; 01678 else if (!lpBufferSize) 01679 ret = WN_BAD_POINTER; 01680 else if (!lpRemoteName && *lpBufferSize) 01681 ret = WN_BAD_POINTER; 01682 else 01683 { 01684 int len = MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, NULL, 0); 01685 01686 if (len) 01687 { 01688 PWSTR wideLocalName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 01689 01690 if (wideLocalName) 01691 { 01692 WCHAR wideRemoteStatic[MAX_PATH]; 01693 DWORD wideRemoteSize = sizeof(wideRemoteStatic) / sizeof(WCHAR); 01694 01695 MultiByteToWideChar(CP_ACP, 0, lpLocalName, -1, wideLocalName, len); 01696 01697 /* try once without memory allocation */ 01698 ret = WNetGetConnectionW(wideLocalName, wideRemoteStatic, 01699 &wideRemoteSize); 01700 if (ret == WN_SUCCESS) 01701 { 01702 int len = WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, 01703 -1, NULL, 0, NULL, NULL); 01704 01705 if (len <= *lpBufferSize) 01706 { 01707 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, -1, 01708 lpRemoteName, *lpBufferSize, NULL, NULL); 01709 ret = WN_SUCCESS; 01710 } 01711 else 01712 { 01713 *lpBufferSize = len; 01714 ret = WN_MORE_DATA; 01715 } 01716 } 01717 else if (ret == WN_MORE_DATA) 01718 { 01719 PWSTR wideRemote = HeapAlloc(GetProcessHeap(), 0, 01720 wideRemoteSize * sizeof(WCHAR)); 01721 01722 if (wideRemote) 01723 { 01724 ret = WNetGetConnectionW(wideLocalName, wideRemote, 01725 &wideRemoteSize); 01726 if (ret == WN_SUCCESS) 01727 { 01728 if (len <= *lpBufferSize) 01729 { 01730 WideCharToMultiByte(CP_ACP, 0, wideRemoteStatic, 01731 -1, lpRemoteName, *lpBufferSize, NULL, NULL); 01732 ret = WN_SUCCESS; 01733 } 01734 else 01735 { 01736 *lpBufferSize = len; 01737 ret = WN_MORE_DATA; 01738 } 01739 } 01740 HeapFree(GetProcessHeap(), 0, wideRemote); 01741 } 01742 else 01743 ret = WN_OUT_OF_MEMORY; 01744 } 01745 HeapFree(GetProcessHeap(), 0, wideLocalName); 01746 } 01747 else 01748 ret = WN_OUT_OF_MEMORY; 01749 } 01750 else 01751 ret = WN_BAD_LOCALNAME; 01752 } 01753 if (ret) 01754 SetLastError(ret); 01755 TRACE("Returning %d\n", ret); 01756 return ret; 01757 } 01758 01759 /* find the network connection for a given drive; helper for WNetGetConnection */ 01760 static DWORD get_drive_connection( WCHAR letter, LPWSTR remote, LPDWORD size ) 01761 { 01762 char buffer[1024]; 01763 struct mountmgr_unix_drive *data = (struct mountmgr_unix_drive *)buffer; 01764 HANDLE mgr; 01765 DWORD ret = WN_NOT_CONNECTED; 01766 01767 if ((mgr = CreateFileW( MOUNTMGR_DOS_DEVICE_NAME, GENERIC_READ|GENERIC_WRITE, 01768 FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 01769 0, 0 )) == INVALID_HANDLE_VALUE) 01770 { 01771 ERR( "failed to open mount manager err %u\n", GetLastError() ); 01772 return ret; 01773 } 01774 memset( data, 0, sizeof(*data) ); 01775 data->letter = letter; 01776 if (DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE, data, sizeof(*data), 01777 data, sizeof(buffer), NULL, NULL )) 01778 { 01779 char *p, *mount_point = buffer + data->mount_point_offset; 01780 DWORD len; 01781 01782 if (data->mount_point_offset && !strncmp( mount_point, "unc/", 4 )) 01783 { 01784 mount_point += 2; 01785 mount_point[0] = '\\'; 01786 for (p = mount_point; *p; p++) if (*p == '/') *p = '\\'; 01787 01788 len = MultiByteToWideChar( CP_UNIXCP, 0, mount_point, -1, NULL, 0 ); 01789 if (len > *size) 01790 { 01791 *size = len; 01792 ret = WN_MORE_DATA; 01793 } 01794 else 01795 { 01796 *size = MultiByteToWideChar( CP_UNIXCP, 0, mount_point, -1, remote, *size); 01797 ret = WN_SUCCESS; 01798 } 01799 } 01800 } 01801 CloseHandle( mgr ); 01802 return ret; 01803 } 01804 01805 /************************************************************************** 01806 * WNetGetConnectionW [MPR.@] 01807 * 01808 * FIXME: need to test return values under different errors 01809 */ 01810 DWORD WINAPI WNetGetConnectionW( LPCWSTR lpLocalName, 01811 LPWSTR lpRemoteName, LPDWORD lpBufferSize ) 01812 { 01813 DWORD ret; 01814 01815 TRACE("(%s, %p, %p)\n", debugstr_w(lpLocalName), lpRemoteName, 01816 lpBufferSize); 01817 01818 if (!lpLocalName) 01819 ret = WN_BAD_POINTER; 01820 else if (!lpBufferSize) 01821 ret = WN_BAD_POINTER; 01822 else if (!lpRemoteName && *lpBufferSize) 01823 ret = WN_BAD_POINTER; 01824 else if (!lpLocalName[0]) 01825 ret = WN_BAD_LOCALNAME; 01826 else 01827 { 01828 if (lpLocalName[1] == ':') 01829 { 01830 switch(GetDriveTypeW(lpLocalName)) 01831 { 01832 case DRIVE_REMOTE: 01833 ret = get_drive_connection( lpLocalName[0], lpRemoteName, lpBufferSize ); 01834 break; 01835 case DRIVE_REMOVABLE: 01836 case DRIVE_FIXED: 01837 case DRIVE_CDROM: 01838 TRACE("file is local\n"); 01839 ret = WN_NOT_CONNECTED; 01840 break; 01841 default: 01842 ret = WN_BAD_LOCALNAME; 01843 } 01844 } 01845 else 01846 ret = WN_BAD_LOCALNAME; 01847 } 01848 if (ret) 01849 SetLastError(ret); 01850 TRACE("Returning %d\n", ret); 01851 return ret; 01852 } 01853 01854 /************************************************************************** 01855 * WNetSetConnectionA [MPR.@] 01856 */ 01857 DWORD WINAPI WNetSetConnectionA( LPCSTR lpName, DWORD dwProperty, 01858 LPVOID pvValue ) 01859 { 01860 FIXME( "(%s, %08X, %p): stub\n", debugstr_a(lpName), dwProperty, pvValue ); 01861 01862 SetLastError(WN_NO_NETWORK); 01863 return WN_NO_NETWORK; 01864 } 01865 01866 /************************************************************************** 01867 * WNetSetConnectionW [MPR.@] 01868 */ 01869 DWORD WINAPI WNetSetConnectionW( LPCWSTR lpName, DWORD dwProperty, 01870 LPVOID pvValue ) 01871 { 01872 FIXME( "(%s, %08X, %p): stub\n", debugstr_w(lpName), dwProperty, pvValue ); 01873 01874 SetLastError(WN_NO_NETWORK); 01875 return WN_NO_NETWORK; 01876 } 01877 01878 /***************************************************************** 01879 * WNetGetUniversalNameA [MPR.@] 01880 */ 01881 DWORD WINAPI WNetGetUniversalNameA ( LPCSTR lpLocalPath, DWORD dwInfoLevel, 01882 LPVOID lpBuffer, LPDWORD lpBufferSize ) 01883 { 01884 DWORD err, size; 01885 01886 FIXME( "(%s, 0x%08X, %p, %p): stub\n", 01887 debugstr_a(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize); 01888 01889 switch (dwInfoLevel) 01890 { 01891 case UNIVERSAL_NAME_INFO_LEVEL: 01892 { 01893 LPUNIVERSAL_NAME_INFOA info = lpBuffer; 01894 01895 size = sizeof(*info) + lstrlenA(lpLocalPath) + 1; 01896 if (*lpBufferSize < size) 01897 { 01898 err = WN_MORE_DATA; 01899 break; 01900 } 01901 info->lpUniversalName = (char *)info + sizeof(*info); 01902 lstrcpyA(info->lpUniversalName, lpLocalPath); 01903 *lpBufferSize = size; 01904 err = WN_NO_ERROR; 01905 break; 01906 } 01907 case REMOTE_NAME_INFO_LEVEL: 01908 err = WN_NO_NETWORK; 01909 break; 01910 01911 default: 01912 err = WN_BAD_VALUE; 01913 break; 01914 } 01915 01916 SetLastError(err); 01917 return err; 01918 } 01919 01920 /***************************************************************** 01921 * WNetGetUniversalNameW [MPR.@] 01922 */ 01923 DWORD WINAPI WNetGetUniversalNameW ( LPCWSTR lpLocalPath, DWORD dwInfoLevel, 01924 LPVOID lpBuffer, LPDWORD lpBufferSize ) 01925 { 01926 DWORD err, size; 01927 01928 FIXME( "(%s, 0x%08X, %p, %p): stub\n", 01929 debugstr_w(lpLocalPath), dwInfoLevel, lpBuffer, lpBufferSize); 01930 01931 switch (dwInfoLevel) 01932 { 01933 case UNIVERSAL_NAME_INFO_LEVEL: 01934 { 01935 LPUNIVERSAL_NAME_INFOW info = lpBuffer; 01936 01937 size = sizeof(*info) + (lstrlenW(lpLocalPath) + 1) * sizeof(WCHAR); 01938 if (*lpBufferSize < size) 01939 { 01940 err = WN_MORE_DATA; 01941 break; 01942 } 01943 info->lpUniversalName = (LPWSTR)((char *)info + sizeof(*info)); 01944 lstrcpyW(info->lpUniversalName, lpLocalPath); 01945 *lpBufferSize = size; 01946 err = WN_NO_ERROR; 01947 break; 01948 } 01949 case REMOTE_NAME_INFO_LEVEL: 01950 err = WN_NO_NETWORK; 01951 break; 01952 01953 default: 01954 err = WN_BAD_VALUE; 01955 break; 01956 } 01957 01958 if (err != WN_NO_ERROR) SetLastError(err); 01959 return err; 01960 } 01961 01962 01963 01964 /* 01965 * Other Functions 01966 */ 01967 01968 /************************************************************************** 01969 * WNetGetUserA [MPR.@] 01970 * 01971 * FIXME: we should not return ourselves, but the owner of the drive lpName 01972 */ 01973 DWORD WINAPI WNetGetUserA( LPCSTR lpName, LPSTR lpUserID, LPDWORD lpBufferSize ) 01974 { 01975 if (GetUserNameA( lpUserID, lpBufferSize )) return WN_SUCCESS; 01976 return GetLastError(); 01977 } 01978 01979 /***************************************************************** 01980 * WNetGetUserW [MPR.@] 01981 * 01982 * FIXME: we should not return ourselves, but the owner of the drive lpName 01983 */ 01984 DWORD WINAPI WNetGetUserW( LPCWSTR lpName, LPWSTR lpUserID, LPDWORD lpBufferSize ) 01985 { 01986 if (GetUserNameW( lpUserID, lpBufferSize )) return WN_SUCCESS; 01987 return GetLastError(); 01988 } 01989 01990 /********************************************************************* 01991 * WNetConnectionDialog [MPR.@] 01992 */ 01993 DWORD WINAPI WNetConnectionDialog( HWND hwnd, DWORD dwType ) 01994 { 01995 FIXME( "(%p, %08X): stub\n", hwnd, dwType ); 01996 01997 SetLastError(WN_NO_NETWORK); 01998 return WN_NO_NETWORK; 01999 } 02000 02001 /********************************************************************* 02002 * WNetConnectionDialog1A [MPR.@] 02003 */ 02004 DWORD WINAPI WNetConnectionDialog1A( LPCONNECTDLGSTRUCTA lpConnDlgStruct ) 02005 { 02006 FIXME( "(%p): stub\n", lpConnDlgStruct ); 02007 02008 SetLastError(WN_NO_NETWORK); 02009 return WN_NO_NETWORK; 02010 } 02011 02012 /********************************************************************* 02013 * WNetConnectionDialog1W [MPR.@] 02014 */ 02015 DWORD WINAPI WNetConnectionDialog1W( LPCONNECTDLGSTRUCTW lpConnDlgStruct ) 02016 { 02017 FIXME( "(%p): stub\n", lpConnDlgStruct ); 02018 02019 SetLastError(WN_NO_NETWORK); 02020 return WN_NO_NETWORK; 02021 } 02022 02023 /********************************************************************* 02024 * WNetDisconnectDialog [MPR.@] 02025 */ 02026 DWORD WINAPI WNetDisconnectDialog( HWND hwnd, DWORD dwType ) 02027 { 02028 FIXME( "(%p, %08X): stub\n", hwnd, dwType ); 02029 02030 SetLastError(WN_NO_NETWORK); 02031 return WN_NO_NETWORK; 02032 } 02033 02034 /********************************************************************* 02035 * WNetDisconnectDialog1A [MPR.@] 02036 */ 02037 DWORD WINAPI WNetDisconnectDialog1A( LPDISCDLGSTRUCTA lpConnDlgStruct ) 02038 { 02039 FIXME( "(%p): stub\n", lpConnDlgStruct ); 02040 02041 SetLastError(WN_NO_NETWORK); 02042 return WN_NO_NETWORK; 02043 } 02044 02045 /********************************************************************* 02046 * WNetDisconnectDialog1W [MPR.@] 02047 */ 02048 DWORD WINAPI WNetDisconnectDialog1W( LPDISCDLGSTRUCTW lpConnDlgStruct ) 02049 { 02050 FIXME( "(%p): stub\n", lpConnDlgStruct ); 02051 02052 SetLastError(WN_NO_NETWORK); 02053 return WN_NO_NETWORK; 02054 } 02055 02056 /********************************************************************* 02057 * WNetGetLastErrorA [MPR.@] 02058 */ 02059 DWORD WINAPI WNetGetLastErrorA( LPDWORD lpError, 02060 LPSTR lpErrorBuf, DWORD nErrorBufSize, 02061 LPSTR lpNameBuf, DWORD nNameBufSize ) 02062 { 02063 FIXME( "(%p, %p, %d, %p, %d): stub\n", 02064 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize ); 02065 02066 SetLastError(WN_NO_NETWORK); 02067 return WN_NO_NETWORK; 02068 } 02069 02070 /********************************************************************* 02071 * WNetGetLastErrorW [MPR.@] 02072 */ 02073 DWORD WINAPI WNetGetLastErrorW( LPDWORD lpError, 02074 LPWSTR lpErrorBuf, DWORD nErrorBufSize, 02075 LPWSTR lpNameBuf, DWORD nNameBufSize ) 02076 { 02077 FIXME( "(%p, %p, %d, %p, %d): stub\n", 02078 lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize ); 02079 02080 SetLastError(WN_NO_NETWORK); 02081 return WN_NO_NETWORK; 02082 } 02083 02084 /********************************************************************* 02085 * WNetGetNetworkInformationA [MPR.@] 02086 */ 02087 DWORD WINAPI WNetGetNetworkInformationA( LPCSTR lpProvider, 02088 LPNETINFOSTRUCT lpNetInfoStruct ) 02089 { 02090 DWORD ret; 02091 02092 TRACE( "(%s, %p)\n", debugstr_a(lpProvider), lpNetInfoStruct ); 02093 02094 if (!lpProvider) 02095 ret = WN_BAD_POINTER; 02096 else 02097 { 02098 int len; 02099 02100 len = MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, NULL, 0); 02101 if (len) 02102 { 02103 LPWSTR wideProvider = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 02104 02105 if (wideProvider) 02106 { 02107 MultiByteToWideChar(CP_ACP, 0, lpProvider, -1, wideProvider, 02108 len); 02109 ret = WNetGetNetworkInformationW(wideProvider, lpNetInfoStruct); 02110 HeapFree(GetProcessHeap(), 0, wideProvider); 02111 } 02112 else 02113 ret = WN_OUT_OF_MEMORY; 02114 } 02115 else 02116 ret = GetLastError(); 02117 } 02118 if (ret) 02119 SetLastError(ret); 02120 TRACE("Returning %d\n", ret); 02121 return ret; 02122 } 02123 02124 /********************************************************************* 02125 * WNetGetNetworkInformationW [MPR.@] 02126 */ 02127 DWORD WINAPI WNetGetNetworkInformationW( LPCWSTR lpProvider, 02128 LPNETINFOSTRUCT lpNetInfoStruct ) 02129 { 02130 DWORD ret; 02131 02132 TRACE( "(%s, %p)\n", debugstr_w(lpProvider), lpNetInfoStruct ); 02133 02134 if (!lpProvider) 02135 ret = WN_BAD_POINTER; 02136 else if (!lpNetInfoStruct) 02137 ret = WN_BAD_POINTER; 02138 else if (lpNetInfoStruct->cbStructure < sizeof(NETINFOSTRUCT)) 02139 ret = WN_BAD_VALUE; 02140 else 02141 { 02142 if (providerTable && providerTable->numProviders) 02143 { 02144 DWORD providerIndex = _findProviderIndexW(lpProvider); 02145 02146 if (providerIndex != BAD_PROVIDER_INDEX) 02147 { 02148 lpNetInfoStruct->cbStructure = sizeof(NETINFOSTRUCT); 02149 lpNetInfoStruct->dwProviderVersion = 02150 providerTable->table[providerIndex].dwSpecVersion; 02151 lpNetInfoStruct->dwStatus = NO_ERROR; 02152 lpNetInfoStruct->dwCharacteristics = 0; 02153 lpNetInfoStruct->dwHandle = 0; 02154 lpNetInfoStruct->wNetType = 02155 HIWORD(providerTable->table[providerIndex].dwNetType); 02156 lpNetInfoStruct->dwPrinters = -1; 02157 lpNetInfoStruct->dwDrives = -1; 02158 ret = WN_SUCCESS; 02159 } 02160 else 02161 ret = WN_BAD_PROVIDER; 02162 } 02163 else 02164 ret = WN_NO_NETWORK; 02165 } 02166 if (ret) 02167 SetLastError(ret); 02168 TRACE("Returning %d\n", ret); 02169 return ret; 02170 } 02171 02172 /***************************************************************** 02173 * WNetGetProviderNameA [MPR.@] 02174 */ 02175 DWORD WINAPI WNetGetProviderNameA( DWORD dwNetType, 02176 LPSTR lpProvider, LPDWORD lpBufferSize ) 02177 { 02178 DWORD ret; 02179 02180 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_a(lpProvider), 02181 lpBufferSize); 02182 02183 if (!lpProvider) 02184 ret = WN_BAD_POINTER; 02185 else if (!lpBufferSize) 02186 ret = WN_BAD_POINTER; 02187 else 02188 { 02189 if (providerTable) 02190 { 02191 DWORD i; 02192 02193 ret = WN_NO_NETWORK; 02194 for (i = 0; i < providerTable->numProviders && 02195 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType); 02196 i++) 02197 ; 02198 if (i < providerTable->numProviders) 02199 { 02200 DWORD sizeNeeded = WideCharToMultiByte(CP_ACP, 0, 02201 providerTable->table[i].name, -1, NULL, 0, NULL, NULL); 02202 02203 if (*lpBufferSize < sizeNeeded) 02204 { 02205 *lpBufferSize = sizeNeeded; 02206 ret = WN_MORE_DATA; 02207 } 02208 else 02209 { 02210 WideCharToMultiByte(CP_ACP, 0, providerTable->table[i].name, 02211 -1, lpProvider, *lpBufferSize, NULL, NULL); 02212 ret = WN_SUCCESS; 02213 /* FIXME: is *lpBufferSize set to the number of characters 02214 * copied? */ 02215 } 02216 } 02217 } 02218 else 02219 ret = WN_NO_NETWORK; 02220 } 02221 if (ret) 02222 SetLastError(ret); 02223 TRACE("Returning %d\n", ret); 02224 return ret; 02225 } 02226 02227 /***************************************************************** 02228 * WNetGetProviderNameW [MPR.@] 02229 */ 02230 DWORD WINAPI WNetGetProviderNameW( DWORD dwNetType, 02231 LPWSTR lpProvider, LPDWORD lpBufferSize ) 02232 { 02233 DWORD ret; 02234 02235 TRACE("(0x%08x, %s, %p)\n", dwNetType, debugstr_w(lpProvider), 02236 lpBufferSize); 02237 02238 if (!lpProvider) 02239 ret = WN_BAD_POINTER; 02240 else if (!lpBufferSize) 02241 ret = WN_BAD_POINTER; 02242 else 02243 { 02244 if (providerTable) 02245 { 02246 DWORD i; 02247 02248 ret = WN_NO_NETWORK; 02249 for (i = 0; i < providerTable->numProviders && 02250 HIWORD(providerTable->table[i].dwNetType) != HIWORD(dwNetType); 02251 i++) 02252 ; 02253 if (i < providerTable->numProviders) 02254 { 02255 DWORD sizeNeeded = strlenW(providerTable->table[i].name) + 1; 02256 02257 if (*lpBufferSize < sizeNeeded) 02258 { 02259 *lpBufferSize = sizeNeeded; 02260 ret = WN_MORE_DATA; 02261 } 02262 else 02263 { 02264 strcpyW(lpProvider, providerTable->table[i].name); 02265 ret = WN_SUCCESS; 02266 /* FIXME: is *lpBufferSize set to the number of characters 02267 * copied? */ 02268 } 02269 } 02270 } 02271 else 02272 ret = WN_NO_NETWORK; 02273 } 02274 if (ret) 02275 SetLastError(ret); 02276 TRACE("Returning %d\n", ret); 02277 return ret; 02278 } Generated on Sat May 26 2012 04:23:17 for ReactOS by
1.7.6.1
|