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.

449 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. port.c
  5. Abstract:
  6. This module contains the code for port handling
  7. Author:
  8. Yi-Hsin Sung (yihsins) 15-May-1993
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windef.h>
  15. #include <winbase.h>
  16. #include <winreg.h>
  17. #include <wingdi.h>
  18. #include <winspool.h>
  19. #include <splutil.h>
  20. #include <nwspl.h>
  21. //------------------------------------------------------------------
  22. //
  23. // Local Functions
  24. //
  25. //------------------------------------------------------------------
  26. HMODULE hSpoolssDll = NULL;
  27. FARPROC pfnSpoolssEnumPorts = NULL;
  28. HANDLE
  29. RevertToPrinterSelf(
  30. VOID
  31. );
  32. BOOL
  33. ImpersonatePrinterClient(
  34. HANDLE hToken
  35. );
  36. BOOL
  37. IsLocalMachine(
  38. LPWSTR pszName
  39. )
  40. {
  41. if ( !pszName || !*pszName )
  42. return TRUE;
  43. if ( *pszName == L'\\' && *(pszName+1) == L'\\')
  44. if ( !lstrcmpi( pszName, szMachineName) )
  45. return TRUE;
  46. return FALSE;
  47. }
  48. BOOL
  49. PortExists(
  50. LPWSTR pPortName,
  51. LPDWORD pError
  52. )
  53. /* PortExists
  54. *
  55. * Calls EnumPorts to check whether the port name already exists.
  56. * This asks every monitor, rather than just this one.
  57. * The function will return TRUE if the specified port is in the list.
  58. * If an error occurs, the return is FALSE and the variable pointed
  59. * to by pError contains the return from GetLastError().
  60. * The caller must therefore always check that *pError == NO_ERROR.
  61. */
  62. {
  63. DWORD cbNeeded;
  64. DWORD cReturned;
  65. DWORD cbPorts;
  66. LPPORT_INFO_1W pPorts;
  67. DWORD i;
  68. BOOL Found = FALSE;
  69. *pError = NO_ERROR;
  70. if ( !hSpoolssDll )
  71. {
  72. if ( hSpoolssDll = LoadLibrary( L"SPOOLSS.DLL" ))
  73. {
  74. pfnSpoolssEnumPorts = GetProcAddress(hSpoolssDll, "EnumPortsW");
  75. if ( !pfnSpoolssEnumPorts )
  76. {
  77. *pError = GetLastError();
  78. FreeLibrary( hSpoolssDll );
  79. hSpoolssDll = NULL;
  80. }
  81. }
  82. else
  83. {
  84. *pError = GetLastError();
  85. }
  86. }
  87. if ( !pfnSpoolssEnumPorts )
  88. return FALSE;
  89. if ( !(*pfnSpoolssEnumPorts)( NULL, 1, NULL, 0, &cbNeeded, &cReturned) )
  90. {
  91. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  92. {
  93. cbPorts = cbNeeded;
  94. EnterCriticalSection( &NwSplSem );
  95. pPorts = AllocNwSplMem( LMEM_ZEROINIT, cbPorts );
  96. if ( pPorts )
  97. {
  98. if ( (*pfnSpoolssEnumPorts)( NULL, 1, (LPBYTE)pPorts, cbPorts,
  99. &cbNeeded, &cReturned))
  100. {
  101. for ( i = 0; i < cReturned; i++)
  102. {
  103. if ( !lstrcmpi( pPorts[i].pName, pPortName) )
  104. Found = TRUE;
  105. }
  106. }
  107. else
  108. {
  109. *pError = GetLastError();
  110. }
  111. FreeNwSplMem( pPorts, cbPorts );
  112. }
  113. else
  114. {
  115. *pError = ERROR_NOT_ENOUGH_MEMORY;
  116. }
  117. LeaveCriticalSection( &NwSplSem );
  118. }
  119. else
  120. {
  121. *pError = GetLastError();
  122. }
  123. }
  124. return Found;
  125. }
  126. BOOL
  127. PortKnown(
  128. LPWSTR pPortName
  129. )
  130. {
  131. PNWPORT pNwPort;
  132. EnterCriticalSection( &NwSplSem );
  133. pNwPort = pNwFirstPort;
  134. while ( pNwPort )
  135. {
  136. if ( !lstrcmpi( pNwPort->pName, pPortName ) )
  137. {
  138. LeaveCriticalSection( &NwSplSem );
  139. return TRUE;
  140. }
  141. pNwPort = pNwPort->pNext;
  142. }
  143. LeaveCriticalSection( &NwSplSem );
  144. return FALSE;
  145. }
  146. PNWPORT
  147. CreatePortEntry(
  148. LPWSTR pPortName
  149. )
  150. {
  151. PNWPORT pNwPort, pPort;
  152. DWORD cb = sizeof(NWPORT) + (wcslen(pPortName) + 1) * sizeof(WCHAR);
  153. if ( pNwPort = AllocNwSplMem( LMEM_ZEROINIT, cb))
  154. {
  155. pNwPort->pName = wcscpy((LPWSTR)(pNwPort+1), pPortName);
  156. pNwPort->cb = cb;
  157. pNwPort->pNext = NULL;
  158. EnterCriticalSection( &NwSplSem );
  159. if ( pPort = pNwFirstPort )
  160. {
  161. while ( pPort->pNext )
  162. pPort = pPort->pNext;
  163. pPort->pNext = pNwPort;
  164. }
  165. else
  166. {
  167. pNwFirstPort = pNwPort;
  168. }
  169. LeaveCriticalSection( &NwSplSem );
  170. }
  171. return pNwPort;
  172. }
  173. BOOL
  174. DeletePortEntry(
  175. LPWSTR pPortName
  176. )
  177. /*
  178. Return TRUE when the port name is found and deleted. FALSE otherwise.
  179. */
  180. {
  181. BOOL fRetVal;
  182. PNWPORT pPort, pPrevPort;
  183. EnterCriticalSection( &NwSplSem );
  184. pPort = pNwFirstPort;
  185. while ( pPort && lstrcmpi(pPort->pName, pPortName))
  186. {
  187. pPrevPort = pPort;
  188. pPort = pPort->pNext;
  189. }
  190. if (pPort)
  191. {
  192. if (pPort == pNwFirstPort)
  193. {
  194. pNwFirstPort = pPort->pNext;
  195. }
  196. else
  197. {
  198. pPrevPort->pNext = pPort->pNext;
  199. }
  200. FreeNwSplMem( pPort, pPort->cb );
  201. fRetVal = TRUE;
  202. }
  203. else
  204. {
  205. fRetVal = FALSE;
  206. }
  207. LeaveCriticalSection( &NwSplSem );
  208. return fRetVal;
  209. }
  210. VOID
  211. DeleteAllPortEntries(
  212. VOID
  213. )
  214. {
  215. PNWPORT pPort, pNextPort;
  216. for ( pPort = pNwFirstPort; pPort; pPort = pNextPort )
  217. {
  218. pNextPort = pPort->pNext;
  219. FreeNwSplMem( pPort, pPort->cb );
  220. }
  221. }
  222. DWORD
  223. CreateRegistryEntry(
  224. LPWSTR pPortName
  225. )
  226. {
  227. DWORD err;
  228. HANDLE hToken;
  229. HKEY hkeyPath;
  230. HKEY hkeyPortNames;
  231. hToken = RevertToPrinterSelf();
  232. err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, pszRegistryPath, 0,
  233. NULL, 0, KEY_WRITE, NULL, &hkeyPath, NULL );
  234. if ( !err )
  235. {
  236. err = RegCreateKeyEx( hkeyPath, pszRegistryPortNames, 0,
  237. NULL, 0, KEY_WRITE, NULL, &hkeyPortNames, NULL );
  238. if ( !err )
  239. {
  240. err = RegSetValueEx( hkeyPortNames,
  241. pPortName,
  242. 0,
  243. REG_SZ,
  244. (LPBYTE) L"",
  245. 0 );
  246. RegCloseKey( hkeyPortNames );
  247. }
  248. else
  249. {
  250. KdPrint(("RegCreateKeyEx (%ws) failed: Error = %d\n",
  251. pszRegistryPortNames, err ) );
  252. }
  253. RegCloseKey( hkeyPath );
  254. }
  255. else
  256. {
  257. KdPrint(("RegCreateKeyEx (%ws) failed: Error = %d\n",
  258. pszRegistryPath, err ) );
  259. }
  260. if ( hToken )
  261. (void)ImpersonatePrinterClient(hToken);
  262. return err;
  263. }
  264. DWORD
  265. DeleteRegistryEntry(
  266. LPWSTR pPortName
  267. )
  268. {
  269. DWORD err;
  270. HANDLE hToken;
  271. HKEY hkeyPath;
  272. HKEY hkeyPortNames;
  273. hToken = RevertToPrinterSelf();
  274. err = RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszRegistryPath, 0,
  275. KEY_WRITE, &hkeyPath );
  276. if ( !err )
  277. {
  278. err = RegOpenKeyEx( hkeyPath, pszRegistryPortNames, 0,
  279. KEY_WRITE, &hkeyPortNames );
  280. if ( !err )
  281. {
  282. err = RegDeleteValue( hkeyPortNames, pPortName );
  283. RegCloseKey( hkeyPortNames );
  284. }
  285. else
  286. {
  287. KdPrint(("RegOpenKeyEx (%ws) failed: Error = %d\n",
  288. pszRegistryPortNames, err ) );
  289. }
  290. RegCloseKey( hkeyPath );
  291. }
  292. else
  293. {
  294. KdPrint(("RegOpenKeyEx (%ws) failed: Error = %d\n",
  295. pszRegistryPath, err ) );
  296. }
  297. if ( hToken )
  298. (void)ImpersonatePrinterClient(hToken);
  299. return err;
  300. }
  301. HANDLE
  302. RevertToPrinterSelf(
  303. VOID
  304. )
  305. {
  306. HANDLE NewToken = NULL;
  307. HANDLE OldToken;
  308. NTSTATUS ntstatus;
  309. ntstatus = NtOpenThreadToken(
  310. NtCurrentThread(),
  311. TOKEN_IMPERSONATE,
  312. TRUE,
  313. &OldToken
  314. );
  315. if ( !NT_SUCCESS(ntstatus) ) {
  316. SetLastError(ntstatus);
  317. return FALSE;
  318. }
  319. ntstatus = NtSetInformationThread(
  320. NtCurrentThread(),
  321. ThreadImpersonationToken,
  322. (PVOID)&NewToken,
  323. (ULONG)sizeof(HANDLE)
  324. );
  325. if ( !NT_SUCCESS(ntstatus) ) {
  326. SetLastError(ntstatus);
  327. return FALSE;
  328. }
  329. return OldToken;
  330. }
  331. BOOL
  332. ImpersonatePrinterClient(
  333. HANDLE hToken
  334. )
  335. {
  336. NTSTATUS ntstatus = NtSetInformationThread(
  337. NtCurrentThread(),
  338. ThreadImpersonationToken,
  339. (PVOID) &hToken,
  340. (ULONG) sizeof(HANDLE));
  341. if ( !NT_SUCCESS(ntstatus) ) {
  342. SetLastError( ntstatus );
  343. return FALSE;
  344. }
  345. (VOID) NtClose(hToken);
  346. return TRUE;
  347. }