Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1153 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. dllmain.c
  5. Abstract:
  6. Main module for sporder.dll... the 32-Bit Windows functions that are
  7. used to change the order or WinSock2 transport service providers and
  8. name space providers.
  9. Revision History:
  10. --*/
  11. #include <windows.h>
  12. #include <ws2spi.h>
  13. #include <string.h>
  14. #include "sporder.h"
  15. #define MAX_ENTRIES 1000 // hack, make dynamic
  16. void
  17. _cdecl
  18. MyDbgPrint(
  19. PSTR Format,
  20. ...
  21. )
  22. {
  23. va_list arglist;
  24. char OutputBuffer[1024];
  25. va_start (arglist, Format);
  26. wvsprintf (OutputBuffer, Format, arglist);
  27. va_end (arglist);
  28. OutputDebugString (OutputBuffer);
  29. }
  30. #if DBG
  31. #define DBGOUT(args) MyDbgPrint args
  32. #else
  33. #define DBGOUT(args)
  34. #endif
  35. typedef struct {
  36. GUID ProviderId;
  37. char DisplayString[MAX_PATH];
  38. DWORD Enabled;
  39. char LibraryPath[MAX_PATH];
  40. DWORD StoresServiceClassInfo;
  41. DWORD SupportedNameSpace;
  42. DWORD Version;
  43. } NSP_ITEM;
  44. NSP_ITEM garNspCat[MAX_ENTRIES];
  45. //
  46. // hack, structure copied from winsock2\dll\winsock2\dcatitem.cpp.
  47. // code should eventually be common.
  48. //
  49. typedef struct {
  50. char LibraryPath[MAX_PATH];
  51. // The unexpanded path where the provider DLL is found.
  52. WSAPROTOCOL_INFOW ProtoInfo;
  53. // The protocol information. Note that if the WSAPROTOCOL_INFOW structure
  54. // is ever changed to a non-flat structure (i.e., containing pointers)
  55. // then this type definition will have to be changed, since this
  56. // structure must be strictly flat.
  57. } PACKED_CAT_ITEM;
  58. PACKED_CAT_ITEM garPackCat[MAX_ENTRIES];
  59. DWORD garcbData[MAX_ENTRIES];
  60. //
  61. // When we first enumerate and read the child registry keys, store all of
  62. // those names for later use.
  63. //
  64. TCHAR pszKeyNames[MAX_ENTRIES][MAX_PATH];
  65. //
  66. // The name of the registry keys that we are interested in.
  67. //
  68. TCHAR pszBaseKey[]= TEXT("SYSTEM\\CurrentControlSet\\Services\\WinSock2\\Parameters");
  69. TCHAR pszProtocolCatalog[]= TEXT("Protocol_Catalog9");
  70. TCHAR pszNameSpaceCatalog[]= TEXT("NameSpace_Catalog5");
  71. TCHAR pszCurrentProtocolCatalog[]= TEXT("Current_Protocol_Catalog");
  72. TCHAR pszCurrentNameSpaceCatalog[]=TEXT("Current_NameSpace_Catalog");
  73. TCHAR pszCatalogEntries[]= TEXT("Catalog_Entries");
  74. TCHAR pszDisplayString[]= TEXT("DisplayString");
  75. TCHAR pszEnabled[]= TEXT("Enabled");
  76. TCHAR pszLibraryPath[]= TEXT("LibraryPath");
  77. TCHAR pszProviderId[]= TEXT("ProviderId");
  78. TCHAR pszStoresServiceClassInfo[]= TEXT("StoresServiceClassInfo");
  79. TCHAR pszSupportedNameSpace[]= TEXT("SupportedNameSpace");
  80. TCHAR pszVersion[]= TEXT("Version");
  81. #define WS2_SZ_KEYNAME TEXT("PackedCatalogItem")
  82. BOOL
  83. WINAPI
  84. DllMain (
  85. HANDLE hDLL,
  86. DWORD dwReason,
  87. LPVOID lpReserved)
  88. /*++
  89. Obligatory main() routine for DLL.
  90. --*/
  91. {
  92. return TRUE;
  93. }
  94. int
  95. WSPAPI
  96. WSCWriteProviderOrder (
  97. IN LPDWORD lpwdCatalogEntryId,
  98. IN DWORD dwNumberOfEntries)
  99. /*++
  100. Routine Description:
  101. Reorder existing WinSock2 service providers. The order of the service
  102. providers determines their priority in being selected for use. The
  103. sporder.exe tool will show you the installed provider and their ordering,
  104. Alternately, WSAEnumProtocols(), in conjunction with this function,
  105. will allow you to write your own tool.
  106. Arguments:
  107. lpwdCatalogEntryId [in]
  108. An array of CatalogEntryId elements as found in the WSAPROTOCOL_INFO
  109. structure. The order of the CatalogEntryId elements is the new
  110. priority ordering for the service providers.
  111. dwNumberOfEntries [in]
  112. The number of elements in the lpwdCatalogEntryId array.
  113. Return Value:
  114. ERROR_SUCCESS - the service providers have been reordered.
  115. WSAEINVAL - input parameters were bad, no action was taken.
  116. WSATRY_AGAIN - the routine is being called by another thread or process.
  117. any registry error code
  118. Comments:
  119. Here are scenarios in which the WSCWriteProviderOrder function may fail:
  120. The dwNumberOfEntries is not equal to the number of registered service
  121. providers.
  122. The lpwdCatalogEntryId contains an invalid catalog ID.
  123. The lpwdCatalogEntryId does not contain all valid catalog IDs exactly
  124. 1 time.
  125. The routine is not able to access the registry for some reason
  126. (e.g. inadequate user persmissions)
  127. Another process (or thread) is currently calling the routine.
  128. --*/
  129. {
  130. int iIndex;
  131. int iNumRegCatEntries;
  132. int iWPOReturn;
  133. DWORD i,j;
  134. LONG r;
  135. HKEY hKey;
  136. HKEY hSubKey;
  137. DWORD dwBytes;
  138. DWORD dwType;
  139. TCHAR pszBuffer[MAX_PATH];
  140. TCHAR pszFinalKey[MAX_PATH];
  141. DWORD dwMapping[MAX_ENTRIES];
  142. DWORD dwDummy[MAX_ENTRIES];
  143. DWORD dwWait;
  144. HANDLE hMutex;
  145. static char pszMutextName[] = TEXT("sporder.dll");
  146. HMODULE hWS2_32;
  147. //
  148. // If WS2_32 is loaded (it is if it was used to load catalog
  149. // in the first place), then try to use it to reoder entries.
  150. // Otherwise, use old hackish way of writing to the registry directly.
  151. //
  152. hWS2_32 = GetModuleHandle (TEXT ("WS2_32.DLL"));
  153. if (hWS2_32!=NULL) {
  154. LPWSCWRITEPROVIDERORDER lpWSCWriteProviderOrder;
  155. lpWSCWriteProviderOrder =
  156. (LPWSCWRITEPROVIDERORDER)GetProcAddress (
  157. hWS2_32,
  158. "WSCWriteProviderOrder");
  159. if (lpWSCWriteProviderOrder!=NULL) {
  160. //MyDbgPrint ("SPORDER: calling ws2_32!WSCWriteProviderOrder...\n");
  161. iWPOReturn = lpWSCWriteProviderOrder (
  162. lpwdCatalogEntryId,
  163. dwNumberOfEntries
  164. );
  165. return iWPOReturn;
  166. }
  167. }
  168. //
  169. // Set function return code equal to success
  170. // (assume the best and wait to be proven otherwise)
  171. //
  172. iWPOReturn = ERROR_SUCCESS;
  173. //
  174. // Make sure that we can handle a request of this size.
  175. // Hack, this code needs to be replaced by dynamic memory allocation.
  176. //
  177. if (dwNumberOfEntries > MAX_ENTRIES) {
  178. return WSA_NOT_ENOUGH_MEMORY;
  179. }
  180. //
  181. // Protect the code that modifies the registry with a mutex.
  182. //
  183. hMutex = CreateMutexA (NULL, FALSE, pszMutextName);
  184. if (hMutex==NULL) {
  185. return WSASYSCALLFAILURE;
  186. }
  187. dwWait = WaitForSingleObject (hMutex, 0);
  188. if (dwWait == WAIT_TIMEOUT)
  189. {
  190. DBGOUT((TEXT("WaitForSingleObject, WAIT_TIMEOUT\n")));
  191. iWPOReturn = WSATRY_AGAIN;
  192. goto closeMutex;
  193. }
  194. //
  195. // read catentry format & return error if mismatch
  196. //
  197. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  198. pszBaseKey,
  199. 0,
  200. KEY_QUERY_VALUE,
  201. &hKey);
  202. if (r != ERROR_SUCCESS)
  203. {
  204. DBGOUT((TEXT("RegOpenKeyEx, pszBaseKey, failed \n")));
  205. iWPOReturn = r;
  206. goto releaseMutex;
  207. }
  208. //
  209. // Read the current registry storage format being used by WinSock2.
  210. // Compare with expected value, and return failure if wrong format.
  211. //
  212. dwBytes = sizeof (pszBuffer);
  213. r = RegQueryValueEx (hKey,
  214. pszCurrentProtocolCatalog,
  215. NULL,
  216. &dwType,
  217. (LPVOID) pszBuffer,
  218. &dwBytes);
  219. RegCloseKey (hKey);
  220. if (r != ERROR_SUCCESS)
  221. {
  222. DBGOUT((TEXT("RegQueryValueEx, pszCurrentProtocolCatalog, failed \n")));
  223. iWPOReturn = r;
  224. goto releaseMutex;
  225. }
  226. if (lstrcmp (pszProtocolCatalog, pszBuffer) != 0)
  227. {
  228. DBGOUT((TEXT("Wrong reg. format \n")));
  229. iWPOReturn = WSAEINVAL;
  230. goto releaseMutex;
  231. }
  232. //
  233. // Build the final registry key that has the actual catalogs in it
  234. // pszBaseKey + \ + pszCurrentProtocolCatalog + \ + pszCatalogEntries
  235. // and open it for enumeration
  236. //
  237. lstrcpy (pszFinalKey, pszBaseKey);
  238. lstrcat (pszFinalKey, TEXT("\\"));
  239. lstrcat (pszFinalKey, pszProtocolCatalog);
  240. lstrcat (pszFinalKey, TEXT("\\"));
  241. lstrcat (pszFinalKey, pszCatalogEntries);
  242. DBGOUT((pszFinalKey));
  243. DBGOUT((TEXT("\n")));
  244. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  245. pszFinalKey,
  246. 0,
  247. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  248. &hKey);
  249. if (r != ERROR_SUCCESS)
  250. {
  251. DBGOUT((TEXT("RegOpenKeyEx failed \n")));
  252. iWPOReturn = r;
  253. goto releaseMutex;
  254. }
  255. //
  256. // The initial open succeeded, now enumerate registry keys
  257. // until we don't get any more back
  258. //
  259. for (iIndex = 0; ;iIndex++)
  260. {
  261. TCHAR pszSubKey[MAX_PATH];
  262. TCHAR szFinalPlusSubKey[MAX_PATH];
  263. FILETIME ftDummy;
  264. DWORD dwSize;
  265. if (iIndex>=MAX_ENTRIES) {
  266. DBGOUT((TEXT("iIndex>=MAX_ENTRIES\n")));
  267. iWPOReturn = WSAEINVAL;
  268. goto releaseMutex;
  269. }
  270. dwSize = MAX_PATH;
  271. pszSubKey[0]=0;
  272. r=RegEnumKeyEx (hKey,
  273. iIndex,
  274. pszSubKey,
  275. &dwSize,
  276. NULL,
  277. NULL,
  278. NULL,
  279. &ftDummy);
  280. //
  281. // Once we have all of the keys, we'll get return code: no_more_items.
  282. // close the handle, and exit for loop.
  283. //
  284. if (r == ERROR_NO_MORE_ITEMS)
  285. {
  286. iNumRegCatEntries = iIndex;
  287. RegCloseKey(hKey);
  288. break; // exit for loop
  289. }
  290. //
  291. // Check for other, unexpected error conditions
  292. //
  293. if (r != ERROR_SUCCESS)
  294. {
  295. DBGOUT((TEXT("Unexpected Error \n")));
  296. iWPOReturn = r;
  297. goto releaseMutex;
  298. }
  299. //
  300. // Build up the complete name of the subkey, store it away in
  301. // pszKeyNames for future use, and then open the key.
  302. //
  303. lstrcpy (szFinalPlusSubKey, pszFinalKey);
  304. lstrcat (szFinalPlusSubKey, TEXT("\\"));
  305. lstrcat (szFinalPlusSubKey, pszSubKey);
  306. lstrcpy (&pszKeyNames[iIndex][0],szFinalPlusSubKey);
  307. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  308. szFinalPlusSubKey,
  309. 0,
  310. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  311. &hSubKey);
  312. if (r != ERROR_SUCCESS)
  313. {
  314. DBGOUT((TEXT("RegOpenKeyEx, Badly formated subkey \n")));
  315. iWPOReturn = r;
  316. goto releaseMutex;
  317. }
  318. //
  319. // Finally, read the binary catalog entry data into our global array.
  320. //
  321. dwBytes = sizeof (PACKED_CAT_ITEM);
  322. dwType = REG_BINARY;
  323. r = RegQueryValueEx (hSubKey,
  324. WS2_SZ_KEYNAME,
  325. NULL,
  326. &dwType,
  327. (LPVOID) &garPackCat[iIndex],
  328. &dwBytes);
  329. garcbData[iIndex]=dwBytes;
  330. if (r != ERROR_SUCCESS)
  331. {
  332. DBGOUT((TEXT("RegQueryValueEx failed \n")));
  333. iWPOReturn = r;
  334. goto releaseMutex;
  335. }
  336. RegCloseKey(hSubKey);
  337. } // end for
  338. //
  339. // compare dwNumberOfEntries w/ actual number & fail if wrong
  340. //
  341. if (iNumRegCatEntries != (int) dwNumberOfEntries)
  342. {
  343. DBGOUT((TEXT("iNumRegCatEntries != dwNumberOfEntries \n")));
  344. iWPOReturn = WSAEINVAL;
  345. goto releaseMutex;
  346. }
  347. //
  348. // verify that array passed in has same entries as actual list,
  349. // and construct index mapping at the same time. index mapping says
  350. // that entry dwMapping[i] should be written to key number i.
  351. //
  352. // for array validation:
  353. // step through actual list of catalog entries,
  354. // set dummy to -1 if match
  355. // check that dummy array is all -1 and fail if not true.
  356. //
  357. ZeroMemory (dwDummy, dwNumberOfEntries * sizeof (DWORD));
  358. ZeroMemory (dwMapping, dwNumberOfEntries * sizeof (DWORD));
  359. for (i = 0; i < dwNumberOfEntries ;i++)
  360. {
  361. for (j = 0; j< dwNumberOfEntries ;j++)
  362. {
  363. if (garPackCat[i].ProtoInfo.dwCatalogEntryId ==
  364. lpwdCatalogEntryId[j])
  365. {
  366. dwDummy[j] = (DWORD)-1;
  367. dwMapping[j] = i;
  368. }
  369. }
  370. }
  371. for (j = 0; j< dwNumberOfEntries ;j++)
  372. {
  373. if (dwDummy[j] != (DWORD)-1)
  374. {
  375. iWPOReturn = WSAEINVAL;
  376. goto releaseMutex;
  377. }
  378. }
  379. //
  380. // Finally, all parameter validation is complete,
  381. // and we've read all of the catalog entries.
  382. //
  383. // step through array passed in
  384. // and if not equal, lookup pre-read entry, and write as registry key
  385. //
  386. for (i = 0; i < dwNumberOfEntries ;i++)
  387. {
  388. if (dwMapping[i] != i)
  389. {
  390. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  391. &pszKeyNames[i][0],
  392. 0,
  393. KEY_SET_VALUE,
  394. &hKey);
  395. if (r != ERROR_SUCCESS)
  396. {
  397. DBGOUT((TEXT("RegOpenKeyEx, KEY_SET_VALUE failed \n")));
  398. iWPOReturn = r;
  399. goto releaseMutex;
  400. }
  401. r = RegSetValueEx (hKey,
  402. WS2_SZ_KEYNAME,
  403. 0,
  404. REG_BINARY,
  405. (LPVOID) &garPackCat[dwMapping[i]],
  406. garcbData[i]);
  407. if (r != ERROR_SUCCESS)
  408. {
  409. DBGOUT((TEXT("RegSetValueEx failed \n")));
  410. iWPOReturn = r;
  411. goto releaseMutex;
  412. }
  413. RegCloseKey(hKey);
  414. DBGOUT((TEXT("wrote entry %d in location %d \n"), dwMapping[i], i));
  415. }
  416. }
  417. //
  418. // Release Mutex, close handle, and return.
  419. // Notice that this function MUST return only from here at the
  420. // end so that we are certain to release the mutex.
  421. //
  422. releaseMutex:
  423. ReleaseMutex (hMutex);
  424. closeMutex:
  425. CloseHandle (hMutex);
  426. return iWPOReturn;
  427. }
  428. LONG
  429. ReadNamspaceRegistry(
  430. HKEY hKey,
  431. NSP_ITEM *pItem
  432. )
  433. {
  434. LONG r;
  435. HKEY hSubKey;
  436. DWORD dwBytes;
  437. DWORD dwType;
  438. dwBytes = sizeof(pItem->DisplayString);
  439. r = RegQueryValueEx(hKey,
  440. pszDisplayString,
  441. NULL,
  442. &dwType,
  443. (LPVOID) &pItem->DisplayString,
  444. &dwBytes);
  445. if (r != ERROR_SUCCESS) {
  446. DBGOUT((TEXT("RegQueryValueEx, pszDisplayString, failed \n")));
  447. return r;
  448. }
  449. dwBytes = sizeof(pItem->Enabled);
  450. r = RegQueryValueEx(hKey,
  451. pszEnabled,
  452. NULL,
  453. &dwType,
  454. (LPVOID) &pItem->Enabled,
  455. &dwBytes);
  456. if (r != ERROR_SUCCESS) {
  457. DBGOUT((TEXT("RegQueryValueEx, pszEnabled, failed \n")));
  458. return r;
  459. }
  460. dwBytes = sizeof(pItem->LibraryPath);
  461. r = RegQueryValueEx(hKey,
  462. pszLibraryPath,
  463. NULL,
  464. &dwType,
  465. (LPVOID) &pItem->LibraryPath,
  466. &dwBytes);
  467. if (r != ERROR_SUCCESS) {
  468. DBGOUT((TEXT("RegQueryValueEx, pszLibraryPath, failed \n")));
  469. return r;
  470. }
  471. dwBytes = sizeof(pItem->ProviderId);
  472. r = RegQueryValueEx(hKey,
  473. pszProviderId,
  474. NULL,
  475. &dwType,
  476. (LPVOID) &pItem->ProviderId,
  477. &dwBytes);
  478. if (r != ERROR_SUCCESS) {
  479. DBGOUT((TEXT("RegQueryValueEx, pszProviderId, failed \n")));
  480. return r;
  481. }
  482. dwBytes = sizeof(pItem->StoresServiceClassInfo);
  483. r = RegQueryValueEx(hKey,
  484. pszStoresServiceClassInfo,
  485. NULL,
  486. &dwType,
  487. (LPVOID) &pItem->StoresServiceClassInfo,
  488. &dwBytes);
  489. if (r != ERROR_SUCCESS) {
  490. DBGOUT((TEXT("RegQueryValueEx, pszStoresServiceClassInfo, failed \n")));
  491. return r;
  492. }
  493. dwBytes = sizeof(pItem->SupportedNameSpace);
  494. r = RegQueryValueEx(hKey,
  495. pszSupportedNameSpace,
  496. NULL,
  497. &dwType,
  498. (LPVOID) &pItem->SupportedNameSpace,
  499. &dwBytes);
  500. if (r != ERROR_SUCCESS) {
  501. DBGOUT((TEXT("RegQueryValueEx, pszSupportedNameSpace, failed \n")));
  502. return r;
  503. }
  504. dwBytes = sizeof(pItem->Version);
  505. r = RegQueryValueEx(hKey,
  506. pszVersion,
  507. NULL,
  508. &dwType,
  509. (LPVOID) &pItem->Version,
  510. &dwBytes);
  511. if (r != ERROR_SUCCESS) {
  512. DBGOUT((TEXT("RegQueryValueEx, pszVersion, failed \n")));
  513. return r;
  514. }
  515. return ERROR_SUCCESS;
  516. }
  517. #define GUIDEQUAL(Guid1, Guid2) \
  518. ( (Guid1)->Data1 == (Guid2)->Data1 && \
  519. (Guid1)->Data2 == (Guid2)->Data2 && \
  520. (Guid1)->Data3 == (Guid2)->Data3 && \
  521. (Guid1)->Data4[0] == (Guid2)->Data4[0] && \
  522. (Guid1)->Data4[1] == (Guid2)->Data4[1] && \
  523. (Guid1)->Data4[2] == (Guid2)->Data4[2] && \
  524. (Guid1)->Data4[3] == (Guid2)->Data4[3] && \
  525. (Guid1)->Data4[4] == (Guid2)->Data4[4] && \
  526. (Guid1)->Data4[5] == (Guid2)->Data4[5] && \
  527. (Guid1)->Data4[6] == (Guid2)->Data4[6] && \
  528. (Guid1)->Data4[7] == (Guid2)->Data4[7] )
  529. LONG
  530. WriteNameSpaceRegistry(
  531. HKEY hKey,
  532. NSP_ITEM *pItem
  533. )
  534. {
  535. LONG r;
  536. HKEY hSubKey;
  537. r = RegSetValueEx (hKey,
  538. pszDisplayString,
  539. 0,
  540. REG_SZ,
  541. (LPVOID) &pItem->DisplayString,
  542. lstrlen(pItem->DisplayString) + 1);
  543. if (r != ERROR_SUCCESS) {
  544. DBGOUT((TEXT("RegSetValueEx failed \n")));
  545. return r;
  546. }
  547. r = RegSetValueEx (hKey,
  548. pszEnabled,
  549. 0,
  550. REG_DWORD,
  551. (LPVOID) &pItem->Enabled,
  552. sizeof(DWORD));
  553. if (r != ERROR_SUCCESS) {
  554. DBGOUT((TEXT("RegSetValueEx failed \n")));
  555. return r;
  556. }
  557. r = RegSetValueEx (hKey,
  558. pszLibraryPath,
  559. 0,
  560. REG_SZ,
  561. (LPVOID) &pItem->LibraryPath,
  562. lstrlen(pItem->LibraryPath) + 1);
  563. if (r != ERROR_SUCCESS) {
  564. DBGOUT((TEXT("RegSetValueEx failed \n")));
  565. return r;
  566. }
  567. r = RegSetValueEx (hKey,
  568. pszProviderId,
  569. 0,
  570. REG_BINARY,
  571. (LPVOID) &pItem->ProviderId,
  572. sizeof(pItem->ProviderId));
  573. if (r != ERROR_SUCCESS) {
  574. DBGOUT((TEXT("RegSetValueEx failed \n")));
  575. return r;
  576. }
  577. r = RegSetValueEx (hKey,
  578. pszStoresServiceClassInfo,
  579. 0,
  580. REG_DWORD,
  581. (LPVOID) &pItem->StoresServiceClassInfo,
  582. sizeof(DWORD));
  583. if (r != ERROR_SUCCESS) {
  584. DBGOUT((TEXT("RegSetValueEx failed \n")));
  585. return r;
  586. }
  587. r = RegSetValueEx (hKey,
  588. pszSupportedNameSpace,
  589. 0,
  590. REG_DWORD,
  591. (LPVOID) &pItem->SupportedNameSpace,
  592. sizeof(DWORD));
  593. if (r != ERROR_SUCCESS) {
  594. DBGOUT((TEXT("RegSetValueEx failed \n")));
  595. return r;
  596. }
  597. r = RegSetValueEx (hKey,
  598. pszVersion,
  599. 0,
  600. REG_DWORD,
  601. (LPVOID) &pItem->Version,
  602. sizeof(DWORD));
  603. if (r != ERROR_SUCCESS) {
  604. DBGOUT((TEXT("RegSetValueEx failed \n")));
  605. return r;
  606. }
  607. return r;
  608. }
  609. int
  610. WSPAPI
  611. WSCWriteNameSpaceOrder (
  612. IN LPGUID lpProviderId,
  613. IN DWORD dwNumberOfEntries)
  614. /*++
  615. --*/
  616. {
  617. int iIndex;
  618. int iNumRegCatEntries;
  619. int iWPOReturn;
  620. DWORD i,j;
  621. LONG r;
  622. HKEY hKey;
  623. HKEY hSubKey;
  624. DWORD dwBytes;
  625. DWORD dwType;
  626. TCHAR pszBuffer[MAX_PATH];
  627. TCHAR pszFinalKey[MAX_PATH];
  628. DWORD dwMapping[MAX_ENTRIES];
  629. DWORD dwDummy[MAX_ENTRIES];
  630. DWORD dwWait;
  631. HANDLE hMutex;
  632. static char pszMutextName[] = TEXT("sporder.dll");
  633. HMODULE hWS2_32;
  634. //
  635. // If WS2_32 is loaded (it is if it was used to load catalog
  636. // in the first place), then try to use it to reoder entries.
  637. // Otherwise, use old hackish way of writing to the registry directly.
  638. //
  639. hWS2_32 = GetModuleHandle (TEXT ("WS2_32.DLL"));
  640. if (hWS2_32!=NULL) {
  641. LPWSCWRITENAMESPACEORDER lpWSCWriteNameSpaceOrder;
  642. lpWSCWriteNameSpaceOrder =
  643. (LPWSCWRITENAMESPACEORDER)GetProcAddress (
  644. hWS2_32,
  645. "WSCWriteNameSpaceOrder");
  646. if (lpWSCWriteNameSpaceOrder!=NULL) {
  647. //MyDbgPrint ("SPORDER: calling ws2_32!WSCWriteNameSpaceOrder...\n");
  648. iWPOReturn = lpWSCWriteNameSpaceOrder (
  649. lpProviderId,
  650. dwNumberOfEntries
  651. );
  652. return iWPOReturn;
  653. }
  654. }
  655. //
  656. // Set function return code equal to success
  657. // (assume the best and wait to be proven otherwise)
  658. //
  659. iWPOReturn = ERROR_SUCCESS;
  660. //
  661. // Make sure that we can handle a request of this size.
  662. // Hack, this code needs to be replaced by dynamic memory allocation.
  663. //
  664. if ( dwNumberOfEntries > MAX_ENTRIES)
  665. return WSA_NOT_ENOUGH_MEMORY;
  666. //
  667. // Protect the code that modifies the registry with a mutex.
  668. //
  669. hMutex = CreateMutexA (NULL, FALSE, pszMutextName);
  670. if (hMutex==NULL) {
  671. return WSASYSCALLFAILURE;
  672. }
  673. dwWait = WaitForSingleObject (hMutex, 0);
  674. if (dwWait == WAIT_TIMEOUT)
  675. {
  676. DBGOUT((TEXT("WaitForSingleObject, WAIT_TIMEOUT\n")));
  677. iWPOReturn = ERROR_BUSY;
  678. goto closeMutex;
  679. }
  680. //
  681. // read catentry format & return error if mismatch
  682. //
  683. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  684. pszBaseKey,
  685. 0,
  686. KEY_QUERY_VALUE,
  687. &hKey);
  688. if (r != ERROR_SUCCESS)
  689. {
  690. DBGOUT((TEXT("RegOpenKeyEx, pszBaseKey, failed \n")));
  691. iWPOReturn = r;
  692. goto releaseMutex;
  693. }
  694. //
  695. // Read the current registry storage format being used by WinSock2.
  696. // Compare with expected value, and return failure if wrong format.
  697. //
  698. dwBytes = sizeof (pszBuffer);
  699. r = RegQueryValueEx (hKey,
  700. pszCurrentNameSpaceCatalog,
  701. NULL,
  702. &dwType,
  703. (LPVOID) pszBuffer,
  704. &dwBytes);
  705. RegCloseKey (hKey);
  706. if (r != ERROR_SUCCESS)
  707. {
  708. DBGOUT((TEXT("RegQueryValueEx, pszCurrentNameSpaceCatalog, failed \n")));
  709. iWPOReturn = r;
  710. goto releaseMutex;
  711. }
  712. if (lstrcmp (pszNameSpaceCatalog, pszBuffer) != 0)
  713. {
  714. DBGOUT((TEXT("Wrong reg. format \n")));
  715. iWPOReturn = WSAEINVAL;
  716. goto releaseMutex;
  717. }
  718. //
  719. // Build the final registry key that has the actual catalogs in it
  720. // pszBaseKey + \ + pszCurrentNameSpaceCatalog + \ + pszCatalogEntries
  721. // and open it for enumeration
  722. //
  723. lstrcpy (pszFinalKey, pszBaseKey);
  724. lstrcat (pszFinalKey, TEXT("\\"));
  725. lstrcat (pszFinalKey, pszNameSpaceCatalog);
  726. lstrcat (pszFinalKey, TEXT("\\"));
  727. lstrcat (pszFinalKey, pszCatalogEntries);
  728. DBGOUT((pszFinalKey));
  729. DBGOUT((TEXT("\n")));
  730. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  731. pszFinalKey,
  732. 0,
  733. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  734. &hKey);
  735. if (r != ERROR_SUCCESS)
  736. {
  737. DBGOUT((TEXT("RegOpenKeyEx failed \n")));
  738. iWPOReturn = r;
  739. goto releaseMutex;
  740. }
  741. //
  742. // The initial open succeeded, now enumerate registry keys
  743. // until we don't get any more back
  744. //
  745. for (iIndex = 0; ;iIndex++)
  746. {
  747. TCHAR pszSubKey[MAX_PATH];
  748. TCHAR szFinalPlusSubKey[MAX_PATH];
  749. FILETIME ftDummy;
  750. DWORD dwSize;
  751. if (iIndex>=MAX_ENTRIES) {
  752. DBGOUT((TEXT("iIndex>=MAX_ENTRIES\n")));
  753. iWPOReturn = WSAEINVAL;
  754. goto releaseMutex;
  755. }
  756. dwSize = MAX_PATH;
  757. pszSubKey[0]=0;
  758. r=RegEnumKeyEx (hKey,
  759. iIndex,
  760. pszSubKey,
  761. &dwSize,
  762. NULL,
  763. NULL,
  764. NULL,
  765. &ftDummy);
  766. //
  767. // Once we have all of the keys, we'll get return code: no_more_items.
  768. // close the handle, and exit for loop.
  769. //
  770. if (r == ERROR_NO_MORE_ITEMS)
  771. {
  772. iNumRegCatEntries = iIndex;
  773. RegCloseKey(hKey);
  774. break; // exit for loop
  775. }
  776. //
  777. // Check for other, unexpected error conditions
  778. //
  779. if (r != ERROR_SUCCESS)
  780. {
  781. DBGOUT((TEXT("Unexpected Error \n")));
  782. iWPOReturn = r;
  783. goto releaseMutex;
  784. }
  785. //
  786. // Build up the complete name of the subkey, store it away in
  787. // pszKeyNames for future use, and then open the key.
  788. //
  789. lstrcpy (szFinalPlusSubKey, pszFinalKey);
  790. lstrcat (szFinalPlusSubKey, TEXT("\\"));
  791. lstrcat (szFinalPlusSubKey, pszSubKey);
  792. lstrcpy (&pszKeyNames[iIndex][0],szFinalPlusSubKey);
  793. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  794. szFinalPlusSubKey,
  795. 0,
  796. KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
  797. &hSubKey);
  798. if (r != ERROR_SUCCESS)
  799. {
  800. DBGOUT((TEXT("RegOpenKeyEx, Badly formated subkey \n")));
  801. iWPOReturn = r;
  802. goto releaseMutex;
  803. }
  804. //
  805. // Finally, read the binary catalog entry data into our global array.
  806. //
  807. dwBytes = sizeof (PACKED_CAT_ITEM);
  808. dwType = REG_BINARY;
  809. r = ReadNamspaceRegistry (hSubKey,
  810. &garNspCat[iIndex]);
  811. if (r != ERROR_SUCCESS)
  812. {
  813. DBGOUT((TEXT("ReadNamspaceRegistry failed \n")));
  814. iWPOReturn = r;
  815. goto releaseMutex;
  816. }
  817. RegCloseKey(hSubKey);
  818. } // end for
  819. //
  820. // compare dwNumberOfEntries w/ actual number & fail if wrong
  821. //
  822. if (iNumRegCatEntries != (int) dwNumberOfEntries)
  823. {
  824. DBGOUT((TEXT("iNumRegCatEntries != dwNumberOfEntries \n")));
  825. iWPOReturn = WSAEINVAL;
  826. goto releaseMutex;
  827. }
  828. //
  829. // verify that array passed in has same entries as actual list,
  830. // and construct index mapping at the same time. index mapping says
  831. // that entry dwMapping[i] should be written to key number i.
  832. //
  833. // for array validation:
  834. // step through actual list of catalog entries,
  835. // set dummy to -1 if match
  836. // check that dummy array is all -1 and fail if not true.
  837. //
  838. ZeroMemory (dwDummy, dwNumberOfEntries * sizeof (DWORD));
  839. ZeroMemory (dwMapping, dwNumberOfEntries * sizeof (DWORD));
  840. for (i = 0; i < dwNumberOfEntries ;i++)
  841. {
  842. for (j = 0; j< dwNumberOfEntries ;j++)
  843. {
  844. if (GUIDEQUAL(&garNspCat[i].ProviderId, &lpProviderId[j]))
  845. {
  846. dwDummy[j] = (DWORD)-1;
  847. dwMapping[j] = i;
  848. }
  849. }
  850. }
  851. for (j = 0; j< dwNumberOfEntries ;j++)
  852. {
  853. if (dwDummy[j] != (DWORD)-1)
  854. {
  855. iWPOReturn = WSAEINVAL;
  856. goto releaseMutex;
  857. }
  858. }
  859. //
  860. // Finally, all parameter validation is complete,
  861. // and we've read all of the catalog entries.
  862. //
  863. // step through array passed in
  864. // and if not equal, lookup pre-read entry, and write as registry key
  865. //
  866. for (i = 0; i < dwNumberOfEntries ;i++)
  867. {
  868. if (dwMapping[i] != i)
  869. {
  870. r = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  871. &pszKeyNames[i][0],
  872. 0,
  873. KEY_SET_VALUE,
  874. &hKey);
  875. if (r != ERROR_SUCCESS)
  876. {
  877. DBGOUT((TEXT("RegOpenKeyEx, KEY_SET_VALUE failed \n")));
  878. iWPOReturn = r;
  879. goto releaseMutex;
  880. }
  881. r = WriteNameSpaceRegistry(hKey, &garNspCat[dwMapping[i]]);
  882. if (r != ERROR_SUCCESS)
  883. {
  884. DBGOUT((TEXT("RegSetValueEx failed \n")));
  885. iWPOReturn = r;
  886. goto releaseMutex;
  887. }
  888. RegCloseKey(hKey);
  889. DBGOUT((TEXT("wrote entry %d in location %d \n"), dwMapping[i], i));
  890. }
  891. }
  892. //
  893. // Release Mutex, close handle, and return.
  894. // Notice that this function MUST return only from here at the
  895. // end so that we are certain to release the mutex.
  896. //
  897. releaseMutex:
  898. ReleaseMutex (hMutex);
  899. closeMutex:
  900. CloseHandle (hMutex);
  901. return iWPOReturn;
  902. }
  903. #if DBG
  904. void
  905. _cdecl
  906. DbgPrint(
  907. PTCH Format,
  908. ...
  909. )
  910. /*++
  911. Write debug output messages if compiled with DEBUG
  912. --*/
  913. {
  914. TCHAR buffer[MAX_PATH];
  915. va_list marker;
  916. va_start (marker,Format);
  917. wvsprintf (buffer,Format, marker);
  918. OutputDebugString (TEXT("SPORDER: "));
  919. OutputDebugString (buffer);
  920. return;
  921. }
  922. #endif