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.

444 lines
9.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. MODULE NAME
  4. autodial.c
  5. ABSTRACT
  6. This module contains support for RAS AutoDial system service.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 22-Apr-1996
  9. REVISION HISTORY
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <stdlib.h>
  17. #include <windows.h>
  18. #include <acd.h>
  19. #include <debug.h>
  20. #include <winsock2.h>
  21. #include <dnsapi.h>
  22. #define NEW_TRANSPORT_INTERVAL 0
  23. BOOLEAN
  24. AcsHlpSendCommand(
  25. IN PACD_NOTIFICATION pRequest
  26. )
  27. /*++
  28. DESCRIPTION
  29. Take an automatic connection driver command block
  30. and send it to the driver.
  31. ARGUMENTS
  32. pRequest: a pointer to the command block
  33. RETURN VALUE
  34. TRUE if successful; FALSE otherwise.
  35. --*/
  36. {
  37. NTSTATUS status;
  38. HANDLE hAcd;
  39. HANDLE hNotif = NULL;
  40. UNICODE_STRING nameString;
  41. OBJECT_ATTRIBUTES objectAttributes;
  42. IO_STATUS_BLOCK ioStatusBlock;
  43. //
  44. // Initialize the name of the automatic
  45. // connection device.
  46. //
  47. RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
  48. //
  49. // Initialize the object attributes.
  50. //
  51. InitializeObjectAttributes(
  52. &objectAttributes,
  53. &nameString,
  54. OBJ_CASE_INSENSITIVE,
  55. (HANDLE)NULL,
  56. (PSECURITY_DESCRIPTOR)NULL);
  57. //
  58. // Open the automatic connection device.
  59. //
  60. status = NtCreateFile(
  61. &hAcd,
  62. FILE_READ_DATA|FILE_WRITE_DATA,
  63. &objectAttributes,
  64. &ioStatusBlock,
  65. NULL,
  66. FILE_ATTRIBUTE_NORMAL,
  67. FILE_SHARE_READ|FILE_SHARE_WRITE,
  68. FILE_OPEN_IF,
  69. 0,
  70. NULL,
  71. 0);
  72. if (status != STATUS_SUCCESS)
  73. return FALSE;
  74. //
  75. // Create an event to wait on.
  76. //
  77. hNotif = CreateEvent(NULL, FALSE, FALSE, NULL);
  78. if (hNotif == NULL) {
  79. CloseHandle(hAcd);
  80. return FALSE;
  81. }
  82. status = NtDeviceIoControlFile(
  83. hAcd,
  84. hNotif,
  85. NULL,
  86. NULL,
  87. &ioStatusBlock,
  88. IOCTL_ACD_CONNECT_ADDRESS,
  89. pRequest,
  90. sizeof (ACD_NOTIFICATION),
  91. NULL,
  92. 0);
  93. if (status == STATUS_PENDING) {
  94. status = WaitForSingleObject(hNotif, INFINITE);
  95. //
  96. // If WaitForSingleObject() returns successfully,
  97. // return the status from the status block,
  98. // otherwise return the wait status.
  99. //
  100. if (status == WAIT_OBJECT_0)
  101. status = ioStatusBlock.Status;
  102. }
  103. //
  104. // Free resources.
  105. //
  106. CloseHandle(hNotif);
  107. CloseHandle(hAcd);
  108. return (status == STATUS_SUCCESS);
  109. } // AcsHlpSendCommand
  110. BOOLEAN
  111. AcsHlpAttemptConnection(
  112. IN PACD_ADDR pAddr
  113. )
  114. /*++
  115. DESCRIPTION
  116. Construct an automatic connection driver command block
  117. to attempt to create an autodial connection for
  118. the specified address.
  119. ARGUMENTS
  120. pAddr: a pointer to the address
  121. RETURN VALUE
  122. TRUE if successful; FALSE otherwise.
  123. --*/
  124. {
  125. ACD_NOTIFICATION request;
  126. //
  127. // Initialize the request with
  128. // the address.
  129. //
  130. RtlCopyMemory(&request.addr, pAddr, sizeof (ACD_ADDR));
  131. request.ulFlags = 0;
  132. RtlZeroMemory(&request.adapter, sizeof (ACD_ADAPTER));
  133. //
  134. // Give this request to the automatic
  135. // connection driver.
  136. //
  137. return AcsHlpSendCommand(&request);
  138. } // AcsHlpAttemptConnection
  139. BOOLEAN
  140. AcsHlpNoteNewConnection(
  141. IN PACD_ADDR pAddr,
  142. IN PACD_ADAPTER pAdapter
  143. )
  144. /*++
  145. DESCRIPTION
  146. Construct an automatic connection driver command block
  147. to notify the automatic connection service of a new connection.
  148. ARGUMENTS
  149. pAddr: a pointer to the address
  150. pAdapter: a pointer to the adapter over which the new
  151. connection was made
  152. RETURN VALUE
  153. TRUE if successful; FALSE otherwise.
  154. --*/
  155. {
  156. ULONG cbAddress;
  157. ACD_NOTIFICATION request;
  158. //
  159. // Initialize the request with
  160. // the address.
  161. //
  162. RtlCopyMemory(&request.addr, pAddr, sizeof (ACD_ADDR));
  163. request.ulFlags = ACD_NOTIFICATION_SUCCESS;
  164. RtlCopyMemory(&request.adapter, pAdapter, sizeof (ACD_ADAPTER));
  165. //
  166. // Give this request to the automatic
  167. // connection driver.
  168. //
  169. return AcsHlpSendCommand(&request);
  170. } // AcsHlpNoteNewConnection
  171. CHAR *
  172. pszDupWtoA(
  173. IN LPCWSTR psz
  174. )
  175. {
  176. CHAR* pszNew = NULL;
  177. if (NULL != psz)
  178. {
  179. DWORD cb;
  180. cb = WideCharToMultiByte(CP_ACP,
  181. 0,
  182. psz,
  183. -1,
  184. NULL,
  185. 0,
  186. NULL,
  187. NULL);
  188. pszNew = (CHAR*) LocalAlloc(LPTR, cb);
  189. if (NULL == pszNew)
  190. {
  191. goto done;
  192. }
  193. cb = WideCharToMultiByte(CP_ACP,
  194. 0,
  195. psz,
  196. -1,
  197. pszNew,
  198. cb,
  199. NULL,
  200. NULL);
  201. if (!cb)
  202. {
  203. LocalFree(pszNew);
  204. pszNew = NULL;
  205. goto done;
  206. }
  207. }
  208. done:
  209. return pszNew;
  210. }
  211. BOOL
  212. fIsDnsName(LPCWSTR pszName)
  213. {
  214. HINSTANCE hInst = NULL;
  215. BOOL fRet = FALSE;
  216. FARPROC pfnDnsValidateName = NULL;
  217. if( (NULL == (hInst = LoadLibrary(TEXT("dnsapi.dll"))))
  218. || (NULL == (pfnDnsValidateName = GetProcAddress(
  219. hInst,
  220. "DnsValidateName_W")
  221. )))
  222. {
  223. DWORD retcode = GetLastError();
  224. goto done;
  225. }
  226. fRet = (ERROR_SUCCESS == pfnDnsValidateName(pszName, DnsNameDomain));
  227. done:
  228. if(NULL != hInst)
  229. {
  230. FreeLibrary(hInst);
  231. }
  232. return fRet;
  233. }
  234. ULONG
  235. ulGetAutodialSleepInterval()
  236. {
  237. DWORD dwSleepInterval = NEW_TRANSPORT_INTERVAL;
  238. HKEY hkey = NULL;
  239. DWORD dwType;
  240. DWORD dwSize = sizeof(DWORD);
  241. TCHAR *pszAutodialParam =
  242. TEXT("SYSTEM\\CurrentControlSet\\Services\\RasAuto\\Parameters");
  243. if (ERROR_SUCCESS != RegOpenKeyEx(
  244. HKEY_LOCAL_MACHINE,
  245. pszAutodialParam,
  246. 0, KEY_READ,
  247. &hkey))
  248. {
  249. goto done;
  250. }
  251. if(ERROR_SUCCESS != RegQueryValueEx(
  252. hkey,
  253. TEXT("NewTransportWaitInterval"),
  254. NULL,
  255. &dwType,
  256. (LPBYTE) &dwSleepInterval,
  257. &dwSize))
  258. {
  259. goto done;
  260. }
  261. done:
  262. if(NULL != hkey)
  263. {
  264. RegCloseKey(hkey);
  265. }
  266. return (ULONG) dwSleepInterval;
  267. }
  268. DWORD
  269. DwGetAcdAddr(ACD_ADDR *paddr, LPCWSTR pszName)
  270. {
  271. CHAR *pszNameA = NULL;
  272. CHAR *pszNameAt = NULL;
  273. DWORD retcode = ERROR_SUCCESS;
  274. ULONG ulIpAddr = 0;
  275. if( (NULL == pszName)
  276. || (NULL == paddr))
  277. {
  278. retcode = E_INVALIDARG;
  279. goto done;
  280. }
  281. pszNameA = pszDupWtoA(pszName);
  282. if(NULL == pszNameA)
  283. {
  284. retcode = E_FAIL;
  285. goto done;
  286. }
  287. if(INADDR_NONE != (ulIpAddr = inet_addr(pszNameA)))
  288. {
  289. paddr->fType = ACD_ADDR_IP;
  290. paddr->ulIpaddr = ulIpAddr;
  291. goto done;
  292. }
  293. if(fIsDnsName(pszName))
  294. {
  295. paddr->fType = ACD_ADDR_INET;
  296. RtlCopyMemory((PBYTE) paddr->szInet,
  297. (PBYTE) pszNameA,
  298. strlen(pszNameA) + 1);
  299. goto done;
  300. }
  301. pszNameAt = pszNameA;
  302. //
  303. // Skip '\\' if required
  304. //
  305. if( (TEXT('\0') != pszName[0])
  306. && (TEXT('\\') == pszName[0])
  307. && (TEXT('\\') == pszName[1]))
  308. {
  309. pszNameA += 2;
  310. }
  311. //
  312. // Default to a netbios name if its neither an ip address
  313. // or a dns name
  314. //
  315. paddr->fType = ACD_ADDR_NB;
  316. RtlCopyMemory((PBYTE) paddr->cNetbios,
  317. (PBYTE) pszNameA,
  318. strlen(pszNameA) + 1);
  319. done:
  320. if(NULL != pszNameAt)
  321. {
  322. LocalFree(pszNameAt);
  323. }
  324. return retcode;
  325. }
  326. BOOL
  327. AcsHlpNbConnection(LPCWSTR pszName)
  328. {
  329. ACD_ADDR addr = {0};
  330. BOOL fRet;
  331. if(!(fRet = (ERROR_SUCCESS == DwGetAcdAddr(&addr, pszName))))
  332. {
  333. goto done;
  334. }
  335. fRet = AcsHlpAttemptConnection(&addr);
  336. //
  337. // Temporary solution for beta2. We may need to wait till redir gets
  338. // a new transport notification. Currently There is no way to
  339. // guarantee that redir is bound to some transport before returning
  340. // from this api.
  341. //
  342. if(fRet)
  343. {
  344. ULONG ulSleepInterval = ulGetAutodialSleepInterval();
  345. if(ulSleepInterval > 0)
  346. {
  347. Sleep(ulSleepInterval);
  348. }
  349. }
  350. done:
  351. return fRet;
  352. }