Source code of Windows XP (NT5)
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.

567 lines
13 KiB

  1. #include "npstub.h"
  2. #include <netspi.h>
  3. #include <npord.h>
  4. #include <nphook.h>
  5. #include <npstubx.h> /* message defs, class name */
  6. #define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))
  7. HINSTANCE hInstance = NULL;
  8. HWND hwndMonitor = NULL;
  9. CRITICAL_SECTION critsec;
  10. ATOM aClass = NULL;
  11. #define ENTERCRITICAL EnterCriticalSection(&::critsec);
  12. #define LEAVECRITICAL LeaveCriticalSection(&::critsec);
  13. UINT cCallsInProgress = 0;
  14. BOOL fShouldUnload = FALSE;
  15. /* This chunk of code invokes the entrypoint hooking feature of MPR. We hook
  16. * things and immediately unhook ourselves. We don't really want to hook
  17. * any functionality, this is just a way to kick MPR so he'll redetermine
  18. * the capabilities (via NPGetCaps) of all the net providers, including
  19. * ours.
  20. */
  21. F_NPSHookMPR HookHookMPR;
  22. F_UnHookMPR HookUnHookMPR;
  23. F_LoadLibrary HookLoadLibrary;
  24. F_FreeLibrary HookFreeLibrary;
  25. F_GetProcAddress HookGetProcAddress;
  26. F_LoadLibrary16 HookWMLoadWinnet16;
  27. F_FreeLibrary16 HookWMFreeWinnet16;
  28. F_GetProcAddressByName16 HookWMGetProcAddressByName;
  29. F_GetProcAddressByOrdinal16 HookWMGetProcAddressByOrdinal;
  30. MPRCALLS MPRCalls = { HookHookMPR,
  31. HookUnHookMPR,
  32. HookLoadLibrary,
  33. HookFreeLibrary,
  34. HookGetProcAddress,
  35. HookWMLoadWinnet16,
  36. HookWMFreeWinnet16,
  37. HookWMGetProcAddressByName,
  38. HookWMGetProcAddressByOrdinal };
  39. DWORD NPSERVICE HookHookMPR ( PMPRCALLS pMPRCalls )
  40. {
  41. return ((PF_NPSHookMPR)(MPRCalls.pfNPSHookMPR))(pMPRCalls);
  42. }
  43. DWORD NPSERVICE HookUnHookMPR ( PF_NPSHookMPR pfReqNPSHookMPR,
  44. PMPRCALLS pReqMPRCalls )
  45. {
  46. if (pfReqNPSHookMPR == HookHookMPR) {
  47. // The unhook request has reached the hooker that issued
  48. // the NPSUnHookMe call (us).
  49. // In other words we are now sucessfully unhooked
  50. // and may do our unhooking cleanup.
  51. // In particular, we can release our tables that
  52. // manage LoadLibrary/GetProcAddress.
  53. // Note that this code may be executing on a different
  54. // thread to the NPSUnHookMe call which may have returned
  55. // a while ago.
  56. return WN_SUCCESS;
  57. }
  58. else {
  59. // Another hooker has requested to unhook by calling
  60. // NPSUnHookMe which causes us to be called here.
  61. // Pass the request on to the MPR service NPSUnHookMPR to
  62. // process the request, giving it our MPRCALLS
  63. // data structure so that it can figure out if
  64. // we are the right hooker to update and otherwise
  65. // MPR will pass the request on to the next hooker.
  66. return NPSUnHookMPR ( pfReqNPSHookMPR,
  67. pReqMPRCalls,
  68. (PMPRCALLS)&MPRCalls );
  69. }
  70. }
  71. HINSTANCE HookLoadLibrary(
  72. LPCTSTR lpszLibFile
  73. )
  74. {
  75. return MPRCalls.pfLoadLibrary(lpszLibFile);
  76. }
  77. BOOL HookFreeLibrary(
  78. HMODULE hLibModule
  79. )
  80. {
  81. return MPRCalls.pfFreeLibrary(hLibModule);
  82. }
  83. FARPROC HookGetProcAddress(
  84. HMODULE hModule,
  85. LPCSTR lpszProc
  86. )
  87. {
  88. return MPRCalls.pfGetProcAddress(hModule, lpszProc);
  89. }
  90. HANDLE16 HookWMLoadWinnet16(
  91. LPCTSTR lpszLibFile
  92. )
  93. {
  94. return MPRCalls.pfLoadLibrary16(lpszLibFile);
  95. }
  96. VOID HookWMFreeWinnet16(
  97. HANDLE16 hLibModule
  98. )
  99. {
  100. MPRCalls.pfFreeLibrary16(hLibModule);
  101. }
  102. DWORD WINAPI HookWMGetProcAddressByName(
  103. LPCSTR lpszProc,
  104. HANDLE16 hModule
  105. )
  106. {
  107. return MPRCalls.pfGetProcAddressByName16(lpszProc, hModule);
  108. }
  109. DWORD WINAPI HookWMGetProcAddressByOrdinal(
  110. WORD wOrdinal,
  111. HANDLE16 hModule
  112. )
  113. {
  114. return MPRCalls.pfGetProcAddressByOrdinal16(wOrdinal, hModule);
  115. }
  116. void KickMPR(void)
  117. {
  118. if (NPSHookMPR((PMPRCALLS)&MPRCalls) == WN_SUCCESS) {
  119. NPSUnHookMe(HookHookMPR, (PMPRCALLS)&MPRCalls);
  120. }
  121. }
  122. /***** End MPR hooking code *****/
  123. /***** Begin code to delay-load the real net provider DLL *****/
  124. HMODULE hmodRealNP = NULL;
  125. PF_NPGetCaps pfnNPGetCaps = NULL;
  126. PF_NPGetUniversalName pfnNPGetUniversalName = NULL;
  127. PF_NPGetUser pfnNPGetUser = NULL;
  128. PF_NPValidLocalDevice pfnNPValidLocalDevice = NULL;
  129. PF_NPAddConnection pfnNPAddConnection = NULL;
  130. PF_NPCancelConnection pfnNPCancelConnection = NULL;
  131. PF_NPGetConnection pfnNPGetConnection = NULL;
  132. PF_NPGetConnectionPerformance pfnNPGetConnectionPerformance = NULL;
  133. PF_NPFormatNetworkName pfnNPFormatNetworkName = NULL;
  134. PF_NPOpenEnum pfnNPOpenEnum = NULL;
  135. PF_NPEnumResource pfnNPEnumResource = NULL;
  136. PF_NPCloseEnum pfnNPCloseEnum = NULL;
  137. PF_NPGetResourceParent pfnNPGetResourceParent = NULL;
  138. PF_NPGetResourceInformation pfnNPGetResourceInformation = NULL;
  139. PF_NPLogon pfnNPLogon = NULL;
  140. PF_NPLogoff pfnNPLogoff = NULL;
  141. PF_NPGetHomeDirectory pfnNPGetHomeDirectory = NULL;
  142. PF_NPGetPolicyPath pfnNPGetPolicyPath = NULL;
  143. struct {
  144. UINT nOrd;
  145. FARPROC *ppfn;
  146. } aProcs[] = {
  147. { ORD_GETCAPS, (FARPROC *)&pfnNPGetCaps },
  148. { ORD_GETUNIVERSALNAME, (FARPROC *)&pfnNPGetUniversalName },
  149. { ORD_GETUSER, (FARPROC *)&pfnNPGetUser },
  150. { ORD_VALIDDEVICE, (FARPROC *)&pfnNPValidLocalDevice },
  151. { ORD_ADDCONNECTION, (FARPROC *)&pfnNPAddConnection },
  152. { ORD_CANCELCONNECTION, (FARPROC *)&pfnNPCancelConnection },
  153. { ORD_GETCONNECTIONS, (FARPROC *)&pfnNPGetConnection },
  154. { ORD_GETCONNPERFORMANCE, (FARPROC *)&pfnNPGetConnectionPerformance },
  155. { ORD_FORMATNETWORKNAME, (FARPROC *)&pfnNPFormatNetworkName },
  156. { ORD_OPENENUM, (FARPROC *)&pfnNPOpenEnum },
  157. { ORD_ENUMRESOURCE, (FARPROC *)&pfnNPEnumResource },
  158. { ORD_CLOSEENUM, (FARPROC *)&pfnNPCloseEnum },
  159. { ORD_GETRESOURCEPARENT, (FARPROC *)&pfnNPGetResourceParent },
  160. { ORD_GETRESOURCEINFORMATION, (FARPROC *)&pfnNPGetResourceInformation },
  161. { ORD_LOGON, (FARPROC *)&pfnNPLogon },
  162. { ORD_LOGOFF, (FARPROC *)&pfnNPLogoff },
  163. { ORD_GETHOMEDIRECTORY, (FARPROC *)&pfnNPGetHomeDirectory },
  164. { ORD_GETPOLICYPATH, (FARPROC *)&pfnNPGetPolicyPath },
  165. };
  166. void LoadRealNP(void)
  167. {
  168. ENTERCRITICAL
  169. if (::hmodRealNP == NULL) {
  170. char szDLLName[MAX_PATH];
  171. szDLLName[0] = '\0';
  172. HKEY hkeySection;
  173. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\NPSTUB\\NetworkProvider",
  174. 0, KEY_QUERY_VALUE, &hkeySection) == ERROR_SUCCESS) {
  175. DWORD dwType;
  176. DWORD cbData = sizeof(szDLLName);
  177. RegQueryValueEx(hkeySection, "RealDLL", NULL, &dwType, (LPBYTE)szDLLName, &cbData);
  178. RegCloseKey(hkeySection);
  179. }
  180. if (szDLLName[0] == '\0')
  181. lstrcpy(szDLLName, "mslocusr.dll");
  182. ::hmodRealNP = LoadLibrary(szDLLName);
  183. if (::hmodRealNP != NULL) {
  184. for (UINT i=0; i<ARRAYSIZE(::aProcs); i++) {
  185. *(aProcs[i].ppfn) = GetProcAddress(::hmodRealNP, (LPCSTR)aProcs[i].nOrd);
  186. }
  187. }
  188. }
  189. LEAVECRITICAL
  190. }
  191. void UnloadRealNP(void)
  192. {
  193. ENTERCRITICAL
  194. {
  195. if (cCallsInProgress > 0) {
  196. fShouldUnload = TRUE;
  197. }
  198. else {
  199. for (UINT i=0; i<ARRAYSIZE(::aProcs); i++) {
  200. *(aProcs[i].ppfn) = NULL;
  201. }
  202. FreeLibrary(hmodRealNP);
  203. hmodRealNP = NULL;
  204. fShouldUnload = FALSE;
  205. KickMPR();
  206. }
  207. }
  208. LEAVECRITICAL
  209. }
  210. LRESULT MonitorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  211. {
  212. switch (msg) {
  213. case WM_NPSTUB_LOADDLL:
  214. LoadRealNP();
  215. KickMPR();
  216. break;
  217. case WM_NPSTUB_UNLOADDLL:
  218. UnloadRealNP();
  219. break;
  220. }
  221. return DefWindowProc(hwnd, msg, wParam, lParam);
  222. }
  223. void _ProcessAttach()
  224. {
  225. //
  226. // All the per-instance initialization code should come here.
  227. //
  228. ::DisableThreadLibraryCalls(::hInstance);
  229. InitializeCriticalSection(&::critsec);
  230. WNDCLASS wc;
  231. wc.style = 0;
  232. wc.lpfnWndProc = MonitorWndProc;
  233. wc.cbClsExtra = 0;
  234. wc.cbWndExtra = 0;
  235. wc.hInstance = ::hInstance;
  236. wc.hIcon = NULL;
  237. wc.hCursor = NULL;
  238. wc.hbrBackground = NULL;
  239. wc.lpszMenuName = NULL;
  240. wc.lpszClassName = szNPSTUBClassName;
  241. ::aClass = RegisterClass(&wc);
  242. if (::aClass != NULL) {
  243. ::hwndMonitor = CreateWindow(szNPSTUBClassName, "",
  244. WS_POPUP | WS_DISABLED,
  245. 0, 0, 0, 0,
  246. NULL, NULL,
  247. ::hInstance, NULL);
  248. }
  249. LoadRealNP();
  250. }
  251. void _ProcessDetach()
  252. {
  253. if (::hwndMonitor != NULL)
  254. DestroyWindow(::hwndMonitor);
  255. if (::aClass != NULL)
  256. UnregisterClass((LPSTR)(WORD)::aClass, ::hInstance);
  257. DeleteCriticalSection(&::critsec);
  258. }
  259. extern "C" STDAPI_(BOOL) DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID reserved)
  260. {
  261. if (fdwReason == DLL_PROCESS_ATTACH)
  262. {
  263. ::hInstance = hInstDll;
  264. _ProcessAttach();
  265. }
  266. else if (fdwReason == DLL_PROCESS_DETACH)
  267. {
  268. _ProcessDetach();
  269. }
  270. return TRUE;
  271. }
  272. void EnterSPI(void)
  273. {
  274. ENTERCRITICAL
  275. {
  276. ::cCallsInProgress++;
  277. }
  278. LEAVECRITICAL
  279. }
  280. void LeaveSPI(void)
  281. {
  282. ENTERCRITICAL
  283. {
  284. ::cCallsInProgress--;
  285. if (::fShouldUnload && !::cCallsInProgress)
  286. PostMessage(::hwndMonitor, WM_NPSTUB_UNLOADDLL, 0, 0);
  287. }
  288. LEAVECRITICAL
  289. }
  290. #define CALLNP(name,err,params) \
  291. { \
  292. if (pfn##name == NULL) \
  293. return err; \
  294. DWORD dwRet = err; \
  295. EnterSPI(); \
  296. if (pfn##name != NULL) \
  297. dwRet = (*pfn##name)params; \
  298. LeaveSPI(); \
  299. return dwRet; \
  300. } //last line doesn't need a backslash
  301. SPIENTRY NPGetCaps(
  302. DWORD nIndex
  303. )
  304. {
  305. CALLNP(NPGetCaps,0,(nIndex));
  306. }
  307. SPIENTRY NPGetUniversalName(
  308. LPTSTR lpLocalPath,
  309. DWORD dwInfoLevel,
  310. LPVOID lpBuffer,
  311. LPDWORD lpBufferSize
  312. )
  313. {
  314. CALLNP(NPGetUniversalName,WN_NOT_SUPPORTED,
  315. (lpLocalPath,dwInfoLevel,lpBuffer,lpBufferSize));
  316. }
  317. SPIENTRY NPGetUser(
  318. LPTSTR lpName,
  319. LPTSTR lpAuthenticationID,
  320. LPDWORD lpBufferSize
  321. )
  322. {
  323. CALLNP(NPGetUser,WN_NOT_SUPPORTED,
  324. (lpName,lpAuthenticationID,lpBufferSize));
  325. }
  326. SPIENTRY NPValidLocalDevice(
  327. DWORD dwType,
  328. DWORD dwNumber
  329. )
  330. {
  331. CALLNP(NPValidLocalDevice,WN_NOT_SUPPORTED,(dwType,dwNumber));
  332. }
  333. SPIENTRY NPAddConnection(
  334. HWND hwndOwner,
  335. LPNETRESOURCE lpNetResource,
  336. LPTSTR lpPassword,
  337. LPTSTR lpUserID,
  338. DWORD dwFlags,
  339. LPTSTR lpAccessName,
  340. LPDWORD lpBufferSize,
  341. LPDWORD lpResult
  342. )
  343. {
  344. CALLNP(NPAddConnection,WN_NOT_SUPPORTED,
  345. (hwndOwner,lpNetResource,lpPassword,lpUserID,dwFlags,lpAccessName,lpBufferSize,lpResult));
  346. }
  347. SPIENTRY NPCancelConnection(
  348. LPTSTR lpName,
  349. BOOL fForce,
  350. DWORD dwFlags
  351. )
  352. {
  353. CALLNP(NPCancelConnection,WN_NOT_SUPPORTED,
  354. (lpName,fForce,dwFlags));
  355. }
  356. SPIENTRY NPGetConnection(
  357. LPTSTR lpLocalName,
  358. LPTSTR lpRemoteName,
  359. LPDWORD lpBufferSize
  360. )
  361. {
  362. CALLNP(NPGetConnection,WN_NOT_SUPPORTED,
  363. (lpLocalName,lpRemoteName,lpBufferSize));
  364. }
  365. SPIENTRY NPGetConnectionPerformance(
  366. LPTSTR lpRemoteName,
  367. LPNETCONNECTINFOSTRUCT lpNetConnectInfoStruct
  368. )
  369. {
  370. CALLNP(NPGetConnectionPerformance,WN_NOT_SUPPORTED,
  371. (lpRemoteName,lpNetConnectInfoStruct));
  372. }
  373. SPIENTRY NPFormatNetworkName(
  374. LPTSTR lpRemoteName,
  375. LPTSTR lpFormattedName,
  376. LPDWORD lpnLength,
  377. DWORD dwFlags,
  378. DWORD dwAveCharPerLine
  379. )
  380. {
  381. CALLNP(NPFormatNetworkName,WN_NOT_SUPPORTED,
  382. (lpRemoteName,lpFormattedName,lpnLength,dwFlags,dwAveCharPerLine));
  383. }
  384. SPIENTRY NPOpenEnum(
  385. DWORD dwScope,
  386. DWORD dwType,
  387. DWORD dwUsage,
  388. LPNETRESOURCE lpNetResource,
  389. LPHANDLE lphEnum
  390. )
  391. {
  392. CALLNP(NPOpenEnum,WN_NOT_SUPPORTED,
  393. (dwScope,dwType,dwUsage,lpNetResource,lphEnum));
  394. }
  395. SPIENTRY NPEnumResource(
  396. HANDLE hEnum,
  397. LPDWORD lpcCount,
  398. LPVOID lpBuffer,
  399. DWORD cbBuffer,
  400. LPDWORD lpcbFree
  401. )
  402. {
  403. CALLNP(NPEnumResource,WN_NOT_SUPPORTED,
  404. (hEnum,lpcCount,lpBuffer,cbBuffer,lpcbFree));
  405. }
  406. SPIENTRY NPCloseEnum(
  407. HANDLE hEnum
  408. )
  409. {
  410. CALLNP(NPCloseEnum,WN_NOT_SUPPORTED,
  411. (hEnum));
  412. }
  413. SPIENTRY NPGetResourceParent(
  414. LPNETRESOURCE lpNetResource,
  415. LPVOID lpBuffer,
  416. LPDWORD cbBuffer
  417. )
  418. {
  419. CALLNP(NPGetResourceParent,WN_NOT_SUPPORTED,
  420. (lpNetResource,lpBuffer,cbBuffer));
  421. }
  422. SPIENTRY NPGetResourceInformation(
  423. LPNETRESOURCE lpNetResource,
  424. LPVOID lpBuffer,
  425. LPDWORD cbBuffer,
  426. LPSTR *lplpSystem
  427. )
  428. {
  429. CALLNP(NPGetResourceInformation,WN_NOT_SUPPORTED,
  430. (lpNetResource,lpBuffer,cbBuffer,lplpSystem));
  431. }
  432. SPIENTRY NPLogon(
  433. HWND hwndOwner,
  434. LPLOGONINFO lpAuthentInfo,
  435. LPLOGONINFO lpPreviousAuthentInfo,
  436. LPTSTR lpLogonScript,
  437. DWORD dwBufferSize,
  438. DWORD dwFlags
  439. )
  440. {
  441. CALLNP(NPLogon,WN_NOT_SUPPORTED,
  442. (hwndOwner,lpAuthentInfo,lpPreviousAuthentInfo,lpLogonScript,dwBufferSize,dwFlags));
  443. }
  444. SPIENTRY NPLogoff(
  445. HWND hwndOwner,
  446. LPLOGONINFO lpAuthentInfo,
  447. DWORD dwReason
  448. )
  449. {
  450. CALLNP(NPLogoff,WN_NOT_SUPPORTED,
  451. (hwndOwner,lpAuthentInfo,dwReason));
  452. }
  453. SPIENTRY NPGetHomeDirectory(
  454. LPTSTR lpDirectory,
  455. LPDWORD lpBufferSize
  456. )
  457. {
  458. CALLNP(NPGetHomeDirectory,WN_NOT_SUPPORTED,
  459. (lpDirectory,lpBufferSize));
  460. }
  461. SPIENTRY NPGetPolicyPath(
  462. LPTSTR lpPath,
  463. LPDWORD lpBufferSize,
  464. DWORD dwFlags
  465. )
  466. {
  467. CALLNP(NPGetPolicyPath,WN_NOT_SUPPORTED,
  468. (lpPath,lpBufferSize,dwFlags));
  469. }