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.

1637 lines
39 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. This module provides all the utility functions for the Routing Layer and
  7. the local Print Providor
  8. Author:
  9. Dave Snipp (DaveSn) 15-Mar-1991
  10. Revision History:
  11. --*/
  12. #define NOMINMAX
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <winsock2.h>
  18. #include <ws2tcpip.h>
  19. #include <dsrole.h>
  20. #include <commctrl.h>
  21. #include <winddiui.h>
  22. #include <winspool.h>
  23. #include <w32types.h>
  24. #include <local.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <splcom.h>
  28. #include <splapip.h>
  29. #include <offsets.h>
  30. MODULE_DEBUG_INIT( DBG_ERROR, DBG_ERROR );
  31. // used to break infinite loop in ConvertDevMode
  32. LPCWSTR pszCnvrtdmToken = L",DEVMODE";
  33. LPCWSTR pszDrvConvert = L",DrvConvert";
  34. DWORD
  35. Win32IsOlderThan(
  36. DWORD i,
  37. DWORD j
  38. );
  39. VOID
  40. SplInSem(
  41. VOID
  42. )
  43. {
  44. if (SpoolerSection.OwningThread != (HANDLE) ULongToPtr(GetCurrentThreadId())) {
  45. DBGMSG(DBG_ERROR, ("Not in spooler semaphore\n"));
  46. }
  47. }
  48. VOID
  49. SplOutSem(
  50. VOID
  51. )
  52. {
  53. if (SpoolerSection.OwningThread == (HANDLE) ULongToPtr(GetCurrentThreadId())) {
  54. DBGMSG(DBG_ERROR, ("Inside spooler semaphore !!\n"));
  55. }
  56. }
  57. #if DBG
  58. DWORD dwLeave = 0;
  59. DWORD dwEnter = 0;
  60. #endif
  61. VOID
  62. EnterSplSem(
  63. VOID
  64. )
  65. {
  66. #if DBG
  67. LPDWORD pRetAddr;
  68. #endif
  69. EnterCriticalSection(&SpoolerSection);
  70. #if i386
  71. #if DBG
  72. pRetAddr = (LPDWORD)&pRetAddr;
  73. pRetAddr++;
  74. pRetAddr++;
  75. dwEnter = *pRetAddr;
  76. #endif
  77. #endif
  78. }
  79. VOID
  80. LeaveSplSem(
  81. VOID
  82. )
  83. {
  84. #if i386
  85. #if DBG
  86. LPDWORD pRetAddr;
  87. pRetAddr = (LPDWORD)&pRetAddr;
  88. pRetAddr++;
  89. pRetAddr++;
  90. dwLeave = *pRetAddr;
  91. #endif
  92. #endif
  93. SplInSem();
  94. LeaveCriticalSection(&SpoolerSection);
  95. }
  96. PWINIPORT
  97. FindPort(
  98. LPWSTR pName,
  99. PWINIPORT pFirstPort
  100. )
  101. {
  102. PWINIPORT pIniPort;
  103. pIniPort = pFirstPort;
  104. if (pName) {
  105. while (pIniPort) {
  106. if (!lstrcmpi( pIniPort->pName, pName )) {
  107. return pIniPort;
  108. }
  109. pIniPort=pIniPort->pNext;
  110. }
  111. }
  112. return FALSE;
  113. }
  114. BOOL
  115. MyName(
  116. LPWSTR pName
  117. )
  118. {
  119. if (!pName || !*pName)
  120. return TRUE;
  121. if (*pName == L'\\' && *(pName+1) == L'\\')
  122. if (!lstrcmpi(pName, szMachineName))
  123. return TRUE;
  124. return FALSE;
  125. }
  126. /*++
  127. Routine Description
  128. Determines whether or not a machine name contains the local machine name.
  129. Localspl enum calls fail if pName != local machine name (\\Machine).
  130. Remote enum provider is then called. The remote enum provider must check
  131. if the UNC name refers to the local machine, and fail if it does to avoid
  132. endless recursion.
  133. Arguments:
  134. LPWSTR pName - UNC name.
  135. Return Value:
  136. TRUE: pName == \\szMachineName\...
  137. - or -
  138. pName == \\szMachineName
  139. FALSE: anything else
  140. Author: swilson
  141. --*/
  142. BOOL
  143. CheckMyName(
  144. PWSTR pNameStart
  145. )
  146. {
  147. PWCHAR pMachine;
  148. LPWSTR pName;
  149. DWORD i;
  150. SplInSem();
  151. if (VALIDATE_NAME(pNameStart)) {
  152. for (i = 0 , pName = pNameStart + 2 ; i < gcOtherNames ; ++i , pName = pNameStart + 2) {
  153. for(pMachine = gppszOtherNames[i] ;
  154. *pName && towupper(*pName) == towupper(*pMachine) ;
  155. ++pName, ++pMachine)
  156. ;
  157. if(!*pMachine && (!*pName || *pName == L'\\'))
  158. return TRUE;
  159. }
  160. }
  161. return FALSE;
  162. }
  163. BOOL
  164. RefreshMachineNamesCache(
  165. )
  166. {
  167. PWSTR *ppszOtherNames;
  168. DWORD cOtherNames;
  169. SplInSem();
  170. //
  171. // Get other machine names first. Only if it succeeds do we replace the cache.
  172. //
  173. if (!BuildOtherNamesFromMachineName(&ppszOtherNames, &cOtherNames))
  174. return FALSE;
  175. FreeOtherNames(&gppszOtherNames, &gcOtherNames);
  176. gppszOtherNames = ppszOtherNames;
  177. gcOtherNames = cOtherNames;
  178. return TRUE;
  179. }
  180. BOOL
  181. MachineNameHasDot(
  182. PWSTR pName
  183. )
  184. {
  185. PWSTR psz;
  186. if (!VALIDATE_NAME(pName))
  187. return FALSE;
  188. //
  189. // pName may be \\Server or \\Server\Printer and we only care about the Server
  190. //
  191. for (psz = pName + 2 ; *psz && *psz != L'\\' ; ++psz)
  192. {
  193. if (*psz == L'.')
  194. return TRUE;
  195. }
  196. return FALSE;
  197. }
  198. BOOL
  199. MyUNCName(
  200. PWSTR pName
  201. )
  202. {
  203. BOOL bRet;
  204. EnterSplSem();
  205. if (!(bRet = CheckMyName(pName)) && MachineNameHasDot(pName) && RefreshMachineNamesCache())
  206. {
  207. bRet = CheckMyName(pName);
  208. }
  209. LeaveSplSem();
  210. return bRet;
  211. }
  212. #define MAX_CACHE_ENTRIES 20
  213. LMCACHE LMCacheTable[MAX_CACHE_ENTRIES];
  214. DWORD
  215. FindEntryinLMCache(
  216. LPWSTR pServerName,
  217. LPWSTR pShareName
  218. )
  219. {
  220. DWORD i;
  221. DBGMSG(DBG_TRACE, ("FindEntryinLMCache with %ws and %ws\n", pServerName, pShareName));
  222. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  223. if (LMCacheTable[i].bAvailable) {
  224. if (!_wcsicmp(LMCacheTable[i].szServerName, pServerName)
  225. && !_wcsicmp(LMCacheTable[i].szShareName, pShareName)) {
  226. //
  227. // update the time stamp so that it is current and not old
  228. //
  229. GetSystemTime(&LMCacheTable[i].st);
  230. //
  231. //
  232. //
  233. DBGMSG(DBG_TRACE, ("FindEntryinLMCache returning with %d\n", i));
  234. return(i);
  235. }
  236. }
  237. }
  238. DBGMSG(DBG_TRACE, ("FindEntryinLMCache returning with -1\n"));
  239. return((DWORD)-1);
  240. }
  241. DWORD
  242. AddEntrytoLMCache(
  243. LPWSTR pServerName,
  244. LPWSTR pShareName
  245. )
  246. {
  247. DWORD LRUEntry = (DWORD)-1;
  248. DWORD i;
  249. DBGMSG(DBG_TRACE, ("AddEntrytoLMCache with %ws and %ws\n", pServerName, pShareName));
  250. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  251. if (!LMCacheTable[i].bAvailable) {
  252. LMCacheTable[i].bAvailable = TRUE;
  253. wcscpy(LMCacheTable[i].szServerName, pServerName);
  254. wcscpy(LMCacheTable[i]. szShareName, pShareName);
  255. //
  256. // update the time stamp so that we know when this entry was made
  257. //
  258. GetSystemTime(&LMCacheTable[i].st);
  259. DBGMSG(DBG_TRACE, ("AddEntrytoLMCache returning with %d\n", i));
  260. return(i);
  261. } else {
  262. if ((LRUEntry == (DWORD)-1) ||
  263. (i == IsOlderThan(i, LRUEntry))){
  264. LRUEntry = i;
  265. }
  266. }
  267. }
  268. //
  269. // We have no available entries, replace with the
  270. // LRU Entry
  271. LMCacheTable[LRUEntry].bAvailable = TRUE;
  272. wcscpy(LMCacheTable[LRUEntry].szServerName, pServerName);
  273. wcscpy(LMCacheTable[LRUEntry].szShareName, pShareName);
  274. DBGMSG(DBG_TRACE, ("AddEntrytoLMCache returning with %d\n", LRUEntry));
  275. return(LRUEntry);
  276. }
  277. VOID
  278. DeleteEntryfromLMCache(
  279. LPWSTR pServerName,
  280. LPWSTR pShareName
  281. )
  282. {
  283. DWORD i;
  284. DBGMSG(DBG_TRACE, ("DeleteEntryFromLMCache with %ws and %ws\n", pServerName, pShareName));
  285. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  286. if (LMCacheTable[i].bAvailable) {
  287. if (!_wcsicmp(LMCacheTable[i].szServerName, pServerName)
  288. && !_wcsicmp(LMCacheTable[i].szShareName, pShareName)) {
  289. //
  290. // reset the available flag on this node
  291. //
  292. LMCacheTable[i].bAvailable = FALSE;
  293. DBGMSG(DBG_TRACE, ("DeleteEntryFromLMCache returning after deleting the %d th entry\n", i));
  294. return;
  295. }
  296. }
  297. }
  298. DBGMSG(DBG_TRACE, ("DeleteEntryFromLMCache returning after not finding an entry to delete\n"));
  299. }
  300. DWORD
  301. IsOlderThan(
  302. DWORD i,
  303. DWORD j
  304. )
  305. {
  306. SYSTEMTIME *pi, *pj;
  307. DWORD iMs, jMs;
  308. DBGMSG(DBG_TRACE, ("IsOlderThan entering with i %d j %d\n", i, j));
  309. pi = &(LMCacheTable[i].st);
  310. pj = &(LMCacheTable[j].st);
  311. DBGMSG(DBG_TRACE, ("Index i %d - %d:%d:%d:%d:%d:%d:%d\n",
  312. i, pi->wYear, pi->wMonth, pi->wDay, pi->wHour, pi->wMinute, pi->wSecond, pi->wMilliseconds));
  313. DBGMSG(DBG_TRACE,("Index j %d - %d:%d:%d:%d:%d:%d:%d\n",
  314. j, pj->wYear, pj->wMonth, pj->wDay, pj->wHour, pj->wMinute, pj->wSecond, pj->wMilliseconds));
  315. if (pi->wYear < pj->wYear) {
  316. DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
  317. return(i);
  318. } else if (pi->wYear > pj->wYear) {
  319. DBGMSG(DBG_TRACE, ("IsOlderThan than returns %d\n", j));
  320. return(j);
  321. } else if (pi->wMonth < pj->wMonth) {
  322. DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
  323. return(i);
  324. } else if (pi->wMonth > pj->wMonth) {
  325. DBGMSG(DBG_TRACE, ("IsOlderThan than returns %d\n", j));
  326. return(j);
  327. } else if (pi->wDay < pj->wDay) {
  328. DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
  329. return(i);
  330. } else if (pi->wDay > pj->wDay) {
  331. DBGMSG(DBG_TRACE, ("IsOlderThan than returns %d\n", j));
  332. return(j);
  333. } else {
  334. iMs = ((((pi->wHour * 60) + pi->wMinute)*60) + pi->wSecond)* 1000 + pi->wMilliseconds;
  335. jMs = ((((pj->wHour * 60) + pj->wMinute)*60) + pj->wSecond)* 1000 + pj->wMilliseconds;
  336. if (iMs <= jMs) {
  337. DBGMSG(DBG_TRACE, ("IsOlderThan returns %d\n", i));
  338. return(i);
  339. } else {
  340. DBGMSG(DBG_TRACE, ("IsOlderThan than returns %d\n", j));
  341. return(j);
  342. }
  343. }
  344. }
  345. WIN32LMCACHE Win32LMCacheTable[MAX_CACHE_ENTRIES];
  346. DWORD
  347. FindEntryinWin32LMCache(
  348. LPWSTR pServerName
  349. )
  350. {
  351. DWORD i;
  352. DBGMSG(DBG_TRACE, ("FindEntryinWin32LMCache with %ws\n", pServerName));
  353. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  354. if (Win32LMCacheTable[i].bAvailable) {
  355. if (!_wcsicmp(Win32LMCacheTable[i].szServerName, pServerName)) {
  356. //
  357. // update the time stamp so that it is current and not old
  358. //
  359. GetSystemTime(&Win32LMCacheTable[i].st);
  360. //
  361. //
  362. //
  363. DBGMSG(DBG_TRACE, ("FindEntryinWin32LMCache returning with %d\n", i));
  364. return(i);
  365. }
  366. }
  367. }
  368. DBGMSG(DBG_TRACE, ("FindEntryinWin32LMCache returning with -1\n"));
  369. return((DWORD)-1);
  370. }
  371. DWORD
  372. AddEntrytoWin32LMCache(
  373. LPWSTR pServerName
  374. )
  375. {
  376. DWORD LRUEntry = (DWORD)-1;
  377. DWORD i;
  378. DBGMSG(DBG_TRACE, ("AddEntrytoWin32LMCache with %ws\n", pServerName));
  379. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  380. if (!Win32LMCacheTable[i].bAvailable) {
  381. Win32LMCacheTable[i].bAvailable = TRUE;
  382. wcscpy(Win32LMCacheTable[i].szServerName, pServerName);
  383. //
  384. // update the time stamp so that we know when this entry was made
  385. //
  386. GetSystemTime(&Win32LMCacheTable[i].st);
  387. DBGMSG(DBG_TRACE, ("AddEntrytoWin32LMCache returning with %d\n", i));
  388. return(i);
  389. } else {
  390. if ((LRUEntry == -1) ||
  391. (i == Win32IsOlderThan(i, LRUEntry))){
  392. LRUEntry = i;
  393. }
  394. }
  395. }
  396. //
  397. // We have no available entries, replace with the
  398. // LRU Entry
  399. Win32LMCacheTable[LRUEntry].bAvailable = TRUE;
  400. wcscpy(Win32LMCacheTable[LRUEntry].szServerName, pServerName);
  401. DBGMSG(DBG_TRACE, ("AddEntrytoWin32LMCache returning with %d\n", LRUEntry));
  402. return(LRUEntry);
  403. }
  404. VOID
  405. DeleteEntryfromWin32LMCache(
  406. LPWSTR pServerName
  407. )
  408. {
  409. DWORD i;
  410. DBGMSG(DBG_TRACE, ("DeleteEntryFromWin32LMCache with %ws\n", pServerName));
  411. for (i = 0; i < MAX_CACHE_ENTRIES; i++ ) {
  412. if (Win32LMCacheTable[i].bAvailable) {
  413. if (!_wcsicmp(Win32LMCacheTable[i].szServerName, pServerName)) {
  414. //
  415. // reset the available flag on this node
  416. //
  417. Win32LMCacheTable[i].bAvailable = FALSE;
  418. DBGMSG(DBG_TRACE, ("DeleteEntryFromWin32LMCache returning after deleting the %d th entry\n", i));
  419. return;
  420. }
  421. }
  422. }
  423. DBGMSG(DBG_TRACE, ("DeleteEntryFromWin32LMCache returning after not finding an entry to delete\n"));
  424. }
  425. DWORD
  426. Win32IsOlderThan(
  427. DWORD i,
  428. DWORD j
  429. )
  430. {
  431. SYSTEMTIME *pi, *pj;
  432. DWORD iMs, jMs;
  433. DBGMSG(DBG_TRACE, ("Win32IsOlderThan entering with i %d j %d\n", i, j));
  434. pi = &(Win32LMCacheTable[i].st);
  435. pj = &(Win32LMCacheTable[j].st);
  436. DBGMSG(DBG_TRACE, ("Index i %d - %d:%d:%d:%d:%d:%d:%d\n",
  437. i, pi->wYear, pi->wMonth, pi->wDay, pi->wHour, pi->wMinute, pi->wSecond, pi->wMilliseconds));
  438. DBGMSG(DBG_TRACE,("Index j %d - %d:%d:%d:%d:%d:%d:%d\n",
  439. j, pj->wYear, pj->wMonth, pj->wDay, pj->wHour, pj->wMinute, pj->wSecond, pj->wMilliseconds));
  440. if (pi->wYear < pj->wYear) {
  441. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", i));
  442. return(i);
  443. } else if (pi->wYear > pj->wYear) {
  444. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", j));
  445. return(j);
  446. } else if (pi->wMonth < pj->wMonth) {
  447. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", i));
  448. return(i);
  449. } else if (pi->wMonth > pj->wMonth) {
  450. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", j));
  451. return(j);
  452. } else if (pi->wDay < pj->wDay) {
  453. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", i));
  454. return(i);
  455. } else if (pi->wDay > pj->wDay) {
  456. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", j));
  457. return(j);
  458. } else {
  459. iMs = ((((pi->wHour * 60) + pi->wMinute)*60) + pi->wSecond)* 1000 + pi->wMilliseconds;
  460. jMs = ((((pj->wHour * 60) + pj->wMinute)*60) + pj->wSecond)* 1000 + pj->wMilliseconds;
  461. if (iMs <= jMs) {
  462. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", i));
  463. return(i);
  464. } else {
  465. DBGMSG(DBG_TRACE, ("Win32IsOlderThan returns %d\n", j));
  466. return(j);
  467. }
  468. }
  469. }
  470. BOOL
  471. GetSid(
  472. PHANDLE phToken
  473. )
  474. {
  475. if (!OpenThreadToken( GetCurrentThread(),
  476. TOKEN_IMPERSONATE,
  477. TRUE,
  478. phToken)) {
  479. DBGMSG(DBG_WARNING, ("OpenThreadToken failed: %d\n", GetLastError()));
  480. return FALSE;
  481. } else {
  482. return TRUE;
  483. }
  484. }
  485. BOOL
  486. SetCurrentSid(
  487. HANDLE hToken
  488. )
  489. {
  490. #if DBG
  491. WCHAR UserName[256];
  492. DWORD cbUserName=256;
  493. if( MODULE_DEBUG & DBG_TRACE )
  494. GetUserName(UserName, &cbUserName);
  495. DBGMSG(DBG_TRACE, ("SetCurrentSid BEFORE: user name is %ws\n", UserName));
  496. #endif
  497. NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken,
  498. &hToken, sizeof(hToken));
  499. #if DBG
  500. cbUserName = 256;
  501. if( MODULE_DEBUG & DBG_TRACE )
  502. GetUserName(UserName, &cbUserName);
  503. DBGMSG(DBG_TRACE, ("SetCurrentSid AFTER: user name is %ws\n", UserName));
  504. #endif
  505. return TRUE;
  506. }
  507. BOOL
  508. ValidateW32SpoolHandle(
  509. PWSPOOL pSpool
  510. )
  511. {
  512. SplOutSem();
  513. try {
  514. if (!pSpool || (pSpool->signature != WSJ_SIGNATURE)) {
  515. DBGMSG( DBG_TRACE, ("ValidateW32SpoolHandle error invalid handle %x\n", pSpool));
  516. SetLastError(ERROR_INVALID_HANDLE);
  517. return(FALSE);
  518. }
  519. return(TRUE);
  520. } except (1) {
  521. DBGMSG( DBG_TRACE, ("ValidateW32SpoolHandle error invalid handle %x\n", pSpool));
  522. return(FALSE);
  523. }
  524. }
  525. BOOL
  526. ValidRawDatatype(
  527. LPCWSTR pszDatatype
  528. )
  529. {
  530. if( !pszDatatype || _wcsnicmp( pszDatatype, pszRaw, 3 )){
  531. return FALSE;
  532. }
  533. return TRUE;
  534. }
  535. HANDLE
  536. LoadDriverFiletoConvertDevmodeFromPSpool(
  537. HANDLE hSplPrinter
  538. )
  539. /*++
  540. Finds out full path to the driver file and creates a DEVMODECHG_INFO
  541. (which does a LoadLibrary)
  542. Arguments:
  543. h : A cache handle
  544. Return Value:
  545. On succes a valid pointer, else NULL
  546. --*/
  547. {
  548. LPBYTE pDriver = NULL;
  549. LPWSTR pConfigFile;
  550. HANDLE hDevModeChgInfo = NULL;
  551. DWORD dwNeeded;
  552. DWORD dwServerMajorVersion = 0, dwServerMinorVersion = 0;
  553. if ( hSplPrinter == INVALID_HANDLE_VALUE ) {
  554. SPLASSERT(hSplPrinter != INVALID_HANDLE_VALUE);
  555. return NULL;
  556. }
  557. SplGetPrinterDriverEx(hSplPrinter,
  558. szEnvironment,
  559. 2,
  560. NULL,
  561. 0,
  562. &dwNeeded,
  563. cThisMajorVersion,
  564. cThisMinorVersion,
  565. &dwServerMajorVersion,
  566. &dwServerMinorVersion);
  567. if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  568. goto Cleanup;
  569. pDriver = AllocSplMem(dwNeeded);
  570. if ( !pDriver ||
  571. !SplGetPrinterDriverEx(hSplPrinter,
  572. szEnvironment,
  573. 2,
  574. (LPBYTE)pDriver,
  575. dwNeeded,
  576. &dwNeeded,
  577. cThisMajorVersion,
  578. cThisMinorVersion,
  579. &dwServerMajorVersion,
  580. &dwServerMinorVersion) )
  581. goto Cleanup;
  582. pConfigFile = ((LPDRIVER_INFO_2)pDriver)->pConfigFile;
  583. hDevModeChgInfo = LoadDriverFiletoConvertDevmode(pConfigFile);
  584. Cleanup:
  585. if ( pDriver )
  586. FreeSplMem(pDriver);
  587. return hDevModeChgInfo;
  588. }
  589. BOOL
  590. DoDevModeConversionAndBuildNewPrinterInfo2(
  591. IN LPPRINTER_INFO_2 pInPrinter2,
  592. IN DWORD dwInSize,
  593. IN OUT LPBYTE pOutBuf,
  594. IN DWORD dwOutSize,
  595. IN OUT LPDWORD pcbNeeded,
  596. IN PWSPOOL pSpool
  597. )
  598. /*++
  599. Calls driver to do a devmode conversion and builds a new printer info 2.
  600. Devmode is put at the end and then strings are packed from there.
  601. Arguments:
  602. pInPrinter2 - Printer Info2 structure with devmode info
  603. dwInSize - Number of characters needed to pack info in pInPrinter
  604. (not necessarily the size of the input buffer)
  605. dwOutSize - buffer size
  606. pOutBuf - Buffer to do the operation
  607. pcbNeeded - Amount of memory copied (in characters)
  608. pSpool - Points to w32 handle
  609. Return Value:
  610. TRUE on success, FALSE on error
  611. --*/
  612. {
  613. BOOL bReturn = FALSE;
  614. LPDEVMODE pNewDevMode = NULL, pCacheDevMode, pInDevMode;
  615. DWORD dwDevModeSize, dwSecuritySize, dwNeeded = 0;
  616. HANDLE hDevModeChgInfo = NULL;
  617. LPWSTR SourceStrings[sizeof(PRINTER_INFO_2)/sizeof(LPWSTR)];
  618. LPWSTR *pSourceStrings=SourceStrings;
  619. LPDWORD pOffsets;
  620. LPBYTE pEnd;
  621. PWCACHEINIPRINTEREXTRA pExtraData;
  622. LPWSTR pPrinterName = NULL;
  623. VALIDATEW32HANDLE(pSpool);
  624. pInDevMode = pInPrinter2->pDevMode;
  625. if ( !pInDevMode || pSpool->hSplPrinter == INVALID_HANDLE_VALUE ) {
  626. goto AfterDevModeConversion;
  627. }
  628. if ( !SplGetPrinterExtra(pSpool->hSplPrinter,
  629. &(PBYTE)pExtraData) ) {
  630. DBGMSG(DBG_ERROR,
  631. ("DoDevModeConversionAndBuildNewPrinterInfo2: SplGetPrinterExtra error %d\n",
  632. GetLastError()));
  633. goto AfterDevModeConversion;
  634. }
  635. //
  636. // Only time we do not have to convert devmode is if the server is running
  637. // same version NT and also we have a devmode which matches the server
  638. // devmode in dmSize, dmDriverExtra, dmSpecVersion, and dmDriverVersion
  639. //
  640. pCacheDevMode = pExtraData->pPI2 ? pExtraData->pPI2->pDevMode : NULL;
  641. if ( (pExtraData->dwServerVersion == gdwThisGetVersion ||
  642. (pSpool->Status & WSPOOL_STATUS_CNVRTDEVMODE)) &&
  643. pCacheDevMode &&
  644. pInDevMode->dmSize == pCacheDevMode->dmSize &&
  645. pInDevMode->dmDriverExtra == pCacheDevMode->dmDriverExtra &&
  646. pInDevMode->dmSpecVersion == pCacheDevMode->dmSpecVersion &&
  647. pInDevMode->dmDriverVersion == pCacheDevMode->dmDriverVersion ) {
  648. dwDevModeSize = pInDevMode->dmSize + pInDevMode->dmDriverExtra;
  649. dwNeeded = dwInSize;
  650. if ( dwOutSize < dwNeeded ) {
  651. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  652. goto Cleanup;
  653. }
  654. //
  655. // Put DevMode at the end
  656. //
  657. pNewDevMode = (LPDEVMODE)(pOutBuf + dwOutSize - dwDevModeSize);
  658. CopyMemory((LPBYTE)pNewDevMode,
  659. (LPBYTE)pInDevMode,
  660. dwDevModeSize);
  661. goto AfterDevModeConversion;
  662. }
  663. hDevModeChgInfo = LoadDriverFiletoConvertDevmodeFromPSpool(pSpool->hSplPrinter);
  664. if ( !hDevModeChgInfo )
  665. goto AfterDevModeConversion;
  666. dwDevModeSize = 0;
  667. SPLASSERT( pSpool->pName != NULL );
  668. //
  669. // Append ,DEVMODE to end of pSpool->pName
  670. //
  671. pPrinterName = AllocSplMem((lstrlen(pSpool->pName) + lstrlen(pszCnvrtdmToken) + 1) * sizeof pPrinterName[0]);
  672. if ( !pPrinterName )
  673. goto Cleanup;
  674. wcscpy(pPrinterName,pSpool->pName);
  675. wcscat(pPrinterName,pszCnvrtdmToken);
  676. //
  677. // Findout size of default devmode
  678. //
  679. if ( ERROR_INSUFFICIENT_BUFFER != CallDrvDevModeConversion(hDevModeChgInfo,
  680. pPrinterName,
  681. NULL,
  682. (LPBYTE *)&pNewDevMode,
  683. &dwDevModeSize,
  684. CDM_DRIVER_DEFAULT,
  685. FALSE) )
  686. goto AfterDevModeConversion;
  687. //
  688. // Findout size needed to have current version devmode
  689. //
  690. dwNeeded = dwInSize + dwDevModeSize - pInDevMode->dmSize
  691. - pInDevMode->dmDriverExtra;
  692. if ( dwOutSize < dwNeeded ) {
  693. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  694. goto Cleanup;
  695. }
  696. //
  697. // Put DevMode at the end
  698. //
  699. pNewDevMode = (LPDEVMODE)(pOutBuf + dwOutSize - dwDevModeSize);
  700. //
  701. // Get default devmode and then convert remote devmode to that format
  702. //
  703. if ( ERROR_SUCCESS != CallDrvDevModeConversion(hDevModeChgInfo,
  704. pPrinterName,
  705. NULL,
  706. (LPBYTE *)&pNewDevMode,
  707. &dwDevModeSize,
  708. CDM_DRIVER_DEFAULT,
  709. FALSE) ||
  710. ERROR_SUCCESS != CallDrvDevModeConversion(hDevModeChgInfo,
  711. pPrinterName,
  712. (LPBYTE)pInDevMode,
  713. (LPBYTE *)&pNewDevMode,
  714. &dwDevModeSize,
  715. CDM_CONVERT,
  716. FALSE) ) {
  717. pNewDevMode = NULL;
  718. goto AfterDevModeConversion;
  719. }
  720. AfterDevModeConversion:
  721. //
  722. // At this point if pNewDevMode != NULL dev mode conversion has been done
  723. // by the driver. If not either we did not get a devmode or conversion failed
  724. // In either case set devmode to NULL
  725. //
  726. if ( !pNewDevMode ) {
  727. dwNeeded = dwInSize;
  728. if ( dwOutSize < dwNeeded ) {
  729. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  730. goto Cleanup;
  731. }
  732. }
  733. bReturn = TRUE;
  734. CopyMemory(pOutBuf, (LPBYTE)pInPrinter2, sizeof(PRINTER_INFO_2));
  735. ((LPPRINTER_INFO_2)pOutBuf)->pDevMode = pNewDevMode;
  736. pEnd = (pNewDevMode ? (LPBYTE) pNewDevMode
  737. : (LPBYTE) (pOutBuf + dwOutSize));
  738. if ( pInPrinter2->pSecurityDescriptor ) {
  739. dwSecuritySize = GetSecurityDescriptorLength(
  740. pInPrinter2->pSecurityDescriptor);
  741. pEnd -= dwSecuritySize;
  742. CopyMemory(pEnd, pInPrinter2->pSecurityDescriptor, dwSecuritySize);
  743. ((LPPRINTER_INFO_2)pOutBuf)->pSecurityDescriptor =
  744. (PSECURITY_DESCRIPTOR) pEnd;
  745. } else {
  746. ((LPPRINTER_INFO_2)pOutBuf)->pSecurityDescriptor = NULL;
  747. }
  748. pOffsets = PrinterInfo2Strings;
  749. *pSourceStrings++ = pInPrinter2->pServerName;
  750. *pSourceStrings++ = pInPrinter2->pPrinterName;
  751. *pSourceStrings++ = pInPrinter2->pShareName;
  752. *pSourceStrings++ = pInPrinter2->pPortName;
  753. *pSourceStrings++ = pInPrinter2->pDriverName;
  754. *pSourceStrings++ = pInPrinter2->pComment;
  755. *pSourceStrings++ = pInPrinter2->pLocation;
  756. *pSourceStrings++ = pInPrinter2->pSepFile;
  757. *pSourceStrings++ = pInPrinter2->pPrintProcessor;
  758. *pSourceStrings++ = pInPrinter2->pDatatype;
  759. *pSourceStrings++ = pInPrinter2->pParameters;
  760. pEnd = PackStrings(SourceStrings, (LPBYTE)pOutBuf, pOffsets, pEnd);
  761. SPLASSERT(pEnd > pOutBuf && pEnd < pOutBuf + dwOutSize);
  762. bReturn = TRUE;
  763. Cleanup:
  764. *pcbNeeded = dwNeeded;
  765. if ( hDevModeChgInfo )
  766. UnloadDriverFile(hDevModeChgInfo);
  767. if (pPrinterName)
  768. FreeSplMem(pPrinterName);
  769. return bReturn;
  770. }
  771. PWSTR
  772. StripString(
  773. PWSTR pszString,
  774. PCWSTR pszStrip,
  775. PCWSTR pszTerminator
  776. )
  777. {
  778. //
  779. // Strips the first occurence of pszStrip from pszString if
  780. // the next character after pszStrip is one of the characters
  781. // in pszTerminator. NULL is an implicit terminator, so if you
  782. // want to strip pszStrip only at the end of pszString, just pass
  783. // in an empty string for pszTerminator.
  784. //
  785. // Returns: Pointer to pszString if pszStrip was found
  786. // NULL is pszStrip was not found
  787. //
  788. PWSTR psz;
  789. DWORD dwStripLength;
  790. if (!pszStrip || !pszString || !pszTerminator)
  791. return NULL;
  792. dwStripLength = wcslen(pszStrip);
  793. for(psz = pszString ; psz ;) {
  794. // find pszStrip in pszString
  795. if ((psz = wcsstr(psz, pszStrip))) {
  796. // check for the terminator & strip pszStrip
  797. if (!*(psz + dwStripLength) || wcschr(pszTerminator, *(psz + dwStripLength))) {
  798. wcscpy(psz, psz + dwStripLength);
  799. return pszString;
  800. } else {
  801. ++psz;
  802. }
  803. }
  804. }
  805. return NULL;
  806. }
  807. BOOL
  808. AddDriverFromLocalCab(
  809. LPTSTR pszDriverName,
  810. LPHANDLE pIniSpooler
  811. )
  812. {
  813. DRIVER_INFO_7 DriverInfo7;
  814. if( GetPolicy() & SERVER_INSTALL_ONLY ) {
  815. return FALSE;
  816. }
  817. DriverInfo7.cbSize = sizeof( DriverInfo7 );
  818. DriverInfo7.cVersion = 0;
  819. DriverInfo7.pszDriverName = pszDriverName;
  820. DriverInfo7.pszInfName = NULL;
  821. DriverInfo7.pszInstallSourceRoot = NULL;
  822. return ( SplAddPrinterDriverEx( NULL,
  823. 7,
  824. (LPBYTE)&DriverInfo7,
  825. APD_COPY_NEW_FILES,
  826. pIniSpooler,
  827. DO_NOT_USE_SCRATCH_DIR,
  828. FALSE ) );
  829. }
  830. /*++
  831. Routine Name:
  832. IsAdminAccess
  833. Description:
  834. This returns whether the given printer defaults are asking for admin access,
  835. we consider the request to be admin access if the printer defaults are
  836. non-NULL and have PRINTER_ACCESS_ADMINISTER or WRITE_DAC specified.
  837. Arguments:
  838. pDefaults - The printer defaults, may be NULL.
  839. Return Value:
  840. None.
  841. --*/
  842. BOOL
  843. IsAdminAccess(
  844. IN PRINTER_DEFAULTS *pDefaults
  845. )
  846. {
  847. return pDefaults && (pDefaults->DesiredAccess & (PRINTER_ACCESS_ADMINISTER | WRITE_DAC));
  848. }
  849. /*++
  850. Routine Name:
  851. AreWeOnADomain
  852. Description:
  853. This returns whether this machine is a domain joined machine or not.
  854. Arguments:
  855. pbDomain - If TRUE, we are on a domain.
  856. Return Value:
  857. An HRESULT.
  858. --*/
  859. HRESULT
  860. AreWeOnADomain(
  861. OUT BOOL *pbDomain
  862. )
  863. {
  864. HRESULT hr = pbDomain ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  865. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pRoleInfo = NULL;
  866. BOOL bOnDomain = FALSE;
  867. if (SUCCEEDED(hr))
  868. {
  869. hr = HResultFromWin32(DsRoleGetPrimaryDomainInformation(NULL,
  870. DsRolePrimaryDomainInfoBasic,
  871. (BYTE **)(&pRoleInfo)));
  872. }
  873. if (SUCCEEDED(hr))
  874. {
  875. bOnDomain = pRoleInfo->MachineRole == DsRole_RoleMemberWorkstation ||
  876. pRoleInfo->MachineRole == DsRole_RoleMemberServer ||
  877. pRoleInfo->MachineRole == DsRole_RoleBackupDomainController ||
  878. pRoleInfo->MachineRole == DsRole_RolePrimaryDomainController;
  879. }
  880. if (pRoleInfo)
  881. {
  882. DsRoleFreeMemory((VOID *)pRoleInfo);
  883. }
  884. if (pbDomain)
  885. {
  886. *pbDomain = bOnDomain;
  887. }
  888. return hr;
  889. }
  890. /*++
  891. Routine Name:
  892. GetServerNameFromQueue
  893. Description:
  894. This returns the server name from the given queue name.
  895. Arguments:
  896. pszQueue - The queue name,
  897. ppszServerName - The server name.
  898. Return Value:
  899. An HRESULT.
  900. --*/
  901. HRESULT
  902. GetServerNameFromPrinterName(
  903. IN PCWSTR pszQueue,
  904. OUT PWSTR *ppszServerName
  905. )
  906. {
  907. HRESULT hr = pszQueue && ppszServerName ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  908. PWSTR pszServer = NULL;
  909. if (SUCCEEDED(hr))
  910. {
  911. hr = *pszQueue++ == L'\\' && *pszQueue++ == L'\\' ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PRINTER_NAME);
  912. }
  913. if (SUCCEEDED(hr))
  914. {
  915. pszServer = AllocSplStr(pszQueue);
  916. hr = pszServer ? S_OK : HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  917. }
  918. if (SUCCEEDED(hr))
  919. {
  920. PWSTR pszSlash = wcschr(&pszServer[2], L'\\');
  921. //
  922. // If there was no second slash, then what we have is the server name.
  923. //
  924. if (pszSlash)
  925. {
  926. *pszSlash = L'\0';
  927. }
  928. }
  929. if (SUCCEEDED(hr))
  930. {
  931. *ppszServerName = pszServer;
  932. pszServer = NULL;
  933. }
  934. FreeSplMem(pszServer);
  935. return hr;
  936. }
  937. /*++
  938. Routine Name:
  939. GetDNSNameFromServerName
  940. Description:
  941. This returns a fully qualified DNS name from the server name. It is
  942. basically copied from localspl because this is dead-end code. In CSR,
  943. we will fix this properly.
  944. Arguments:
  945. pszServerName - The server name whose fully qualified name we are obtaining.
  946. ppszFullyQualified -
  947. Return Value:
  948. An HRESULT.
  949. --*/
  950. HRESULT
  951. GetDNSNameFromServerName(
  952. IN PCWSTR pszServerName,
  953. OUT PWSTR *ppszFullyQualified
  954. )
  955. {
  956. PSTR pszAnsiMachineName = NULL;
  957. struct hostent *pHostEnt;
  958. WORD wVersion;
  959. WSADATA WSAData;
  960. HRESULT hr = pszServerName && *pszServerName && ppszFullyQualified ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  961. PWSTR pszDummy = NULL;
  962. GetFullyQualifiedDomainName(pszServerName, &pszDummy);
  963. if (SUCCEEDED(hr))
  964. {
  965. wVersion = MAKEWORD(1, 1);
  966. hr = HResultFromWin32(WSAStartup(wVersion, &WSAData));
  967. }
  968. if (SUCCEEDED(hr))
  969. {
  970. hr = UnicodeToAnsiString(pszServerName, &pszAnsiMachineName);
  971. if (SUCCEEDED(hr))
  972. {
  973. pHostEnt = gethostbyname(pszAnsiMachineName);
  974. hr = pHostEnt ? S_OK : HResultFromWin32(WSAGetLastError());
  975. }
  976. if (SUCCEEDED(hr))
  977. {
  978. *ppszFullyQualified = AnsiToUnicodeStringWithAlloc(pHostEnt->h_name);
  979. hr = *ppszFullyQualified ? S_OK : HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  980. }
  981. WSACleanup();
  982. }
  983. FreeSplMem(pszAnsiMachineName);
  984. return hr;
  985. }
  986. /*++
  987. Routine Name:
  988. UnicodeToAnsiString
  989. Routine Description:
  990. This allocates an ANSI string and converts it using the thread's codepage.
  991. Arguments:
  992. pszUnicode - The incoming, non-NULL, NULL terminated unicode string.
  993. ppszAnsi - The returned ANSI string.
  994. Return Value:
  995. An HRESULT
  996. --*/
  997. HRESULT
  998. UnicodeToAnsiString(
  999. IN PCWSTR pszUnicode,
  1000. OUT PSTR *ppszAnsi
  1001. )
  1002. {
  1003. HRESULT hRetval = E_FAIL;
  1004. PSTR pszAnsi = NULL;
  1005. INT AnsiStringLength = 0;
  1006. hRetval = pszUnicode && ppszAnsi ? S_OK : E_INVALIDARG;
  1007. if (ppszAnsi)
  1008. {
  1009. *ppszAnsi = NULL;
  1010. }
  1011. if (SUCCEEDED(hRetval))
  1012. {
  1013. AnsiStringLength = WideCharToMultiByte(CP_THREAD_ACP, 0, pszUnicode, -1, NULL, 0, NULL, NULL);
  1014. hRetval = AnsiStringLength != 0 ? S_OK : GetLastErrorAsHResult();
  1015. }
  1016. if (SUCCEEDED(hRetval))
  1017. {
  1018. pszAnsi = AllocSplMem(AnsiStringLength);
  1019. hRetval = pszAnsi ? S_OK : E_OUTOFMEMORY;
  1020. }
  1021. if (SUCCEEDED(hRetval))
  1022. {
  1023. hRetval = WideCharToMultiByte(CP_THREAD_ACP, 0, pszUnicode, -1, pszAnsi, AnsiStringLength, NULL, NULL) != 0 ? S_OK : GetLastErrorAsHResult();
  1024. }
  1025. if (SUCCEEDED(hRetval))
  1026. {
  1027. *ppszAnsi = pszAnsi;
  1028. pszAnsi = NULL;
  1029. }
  1030. FreeSplMem(pszAnsi);
  1031. return hRetval;
  1032. }
  1033. /*++
  1034. Routine Name:
  1035. AnsiToUnicodeStringWithAlloc
  1036. Description:
  1037. Convert ANSI string to UNICODE. Routine allocates memory from the heap
  1038. which should be freed by the caller.
  1039. Arguments:
  1040. pAnsi - Points to the ANSI string
  1041. Return Value:
  1042. Pointer to UNICODE string
  1043. --*/
  1044. LPWSTR
  1045. AnsiToUnicodeStringWithAlloc(
  1046. LPSTR pAnsi
  1047. )
  1048. {
  1049. LPWSTR pUnicode;
  1050. DWORD rc;
  1051. rc = MultiByteToWideChar(CP_ACP,
  1052. MB_PRECOMPOSED,
  1053. pAnsi,
  1054. -1,
  1055. NULL,
  1056. 0);
  1057. rc *= sizeof(WCHAR);
  1058. if ( !rc || !(pUnicode = (LPWSTR) AllocSplMem(rc)) )
  1059. return NULL;
  1060. rc = MultiByteToWideChar(CP_ACP,
  1061. MB_PRECOMPOSED,
  1062. pAnsi,
  1063. -1,
  1064. pUnicode,
  1065. rc);
  1066. if ( rc )
  1067. return pUnicode;
  1068. else {
  1069. FreeSplMem(pUnicode);
  1070. return NULL;
  1071. }
  1072. }
  1073. /*++
  1074. Routine Name:
  1075. CheckSamePhysicalAddress
  1076. Description:
  1077. This checks to see whether two servers share a same network address. What it
  1078. does is check to see whether the first physical network address of the first
  1079. print server can be found in the list of addresses supported by the second
  1080. print server.
  1081. Arguments:
  1082. pszServer1 - The first server in the list.
  1083. pszServer2 - The second server in the list.
  1084. pbSameAddress - If TRUE, the first physical address of server1 can be found
  1085. in server2.
  1086. Return Value:
  1087. An HRESULT.
  1088. --*/
  1089. HRESULT
  1090. CheckSamePhysicalAddress(
  1091. IN PCWSTR pszServer1,
  1092. IN PCWSTR pszServer2,
  1093. OUT BOOL *pbSameAddress
  1094. )
  1095. {
  1096. BOOL bSameAddress = FALSE;
  1097. PSTR pszAnsiServer1 = NULL;
  1098. PSTR pszAnsiServer2 = NULL;
  1099. ADDRINFO *pAddrInfo1 = NULL;
  1100. ADDRINFO *pAddrInfo2 = NULL;
  1101. WSADATA WSAData;
  1102. WORD wVersion;
  1103. HRESULT hr = pszServer1 && pszServer2 && pbSameAddress ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1104. if (SUCCEEDED(hr))
  1105. {
  1106. wVersion = MAKEWORD(1, 1);
  1107. hr = HResultFromWin32(WSAStartup(wVersion, &WSAData));
  1108. }
  1109. if (SUCCEEDED(hr))
  1110. {
  1111. ADDRINFO *pAddrInfoScan = NULL;
  1112. hr = UnicodeToAnsiString(pszServer1, &pszAnsiServer1);
  1113. if (SUCCEEDED(hr))
  1114. {
  1115. hr = UnicodeToAnsiString(pszServer2, &pszAnsiServer2);
  1116. }
  1117. if (SUCCEEDED(hr))
  1118. {
  1119. hr = getaddrinfo(pszAnsiServer1, NULL, NULL, &pAddrInfo1) == 0 ? S_OK : HResultFromWin32(WSAGetLastError());
  1120. }
  1121. if (SUCCEEDED(hr))
  1122. {
  1123. hr = getaddrinfo(pszAnsiServer2, NULL, NULL, &pAddrInfo2) == 0 ? S_OK : HResultFromWin32(WSAGetLastError());
  1124. }
  1125. //
  1126. // OK, now for the hokey bit, we check to see whether we can exactly
  1127. // match the first element in pAddrInfo1 anywhere in pAddrInfo2.
  1128. //
  1129. for(pAddrInfoScan = pAddrInfo2; pAddrInfo2 && !bSameAddress; pAddrInfo2 = pAddrInfo2->ai_next)
  1130. {
  1131. //
  1132. // If the lengths of the addresses are the same, then compare the
  1133. // actual addresses.
  1134. //
  1135. if (pAddrInfoScan->ai_addrlen == pAddrInfo1->ai_addrlen &&
  1136. !memcmp(pAddrInfoScan->ai_addr, pAddrInfo1->ai_addr, pAddrInfoScan->ai_addrlen))
  1137. {
  1138. bSameAddress = TRUE;
  1139. }
  1140. }
  1141. freeaddrinfo(pAddrInfo1);
  1142. freeaddrinfo(pAddrInfo2);
  1143. WSACleanup();
  1144. }
  1145. if (pbSameAddress)
  1146. {
  1147. *pbSameAddress = bSameAddress;
  1148. }
  1149. FreeSplMem(pszAnsiServer1);
  1150. FreeSplMem(pszAnsiServer2);
  1151. return hr;
  1152. }
  1153. /*++
  1154. Routine Name:
  1155. CheckUserPrintAdmin
  1156. Description:
  1157. This checks to see whether the given user is a print admin.
  1158. Arguments:
  1159. pbUserAdmin - If TRUE, the user is a print admin.
  1160. Return Value:
  1161. An HRESULT.
  1162. --*/
  1163. HRESULT
  1164. CheckUserPrintAdmin(
  1165. OUT BOOL *pbUserAdmin
  1166. )
  1167. {
  1168. //
  1169. // Check to see whether the caller has access to the local print
  1170. // server, if we do have access, then we allow point and print.
  1171. //
  1172. HANDLE hServer = NULL;
  1173. PRINTER_DEFAULTS Defaults = {NULL, NULL, SERVER_ACCESS_ADMINISTER };
  1174. HRESULT hr = pbUserAdmin ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1175. //
  1176. // This actually calls into the router and not into winspool.drv.
  1177. //
  1178. if (SUCCEEDED(hr))
  1179. {
  1180. }
  1181. hr = OpenPrinterW(NULL, &hServer, &Defaults) ? S_OK : GetLastErrorAsHResultAndFail();
  1182. if (SUCCEEDED(hr))
  1183. {
  1184. *pbUserAdmin = TRUE;
  1185. }
  1186. else if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
  1187. {
  1188. *pbUserAdmin = FALSE;
  1189. hr = S_OK;
  1190. }
  1191. if (hServer)
  1192. {
  1193. ClosePrinter(hServer);
  1194. }
  1195. return hr;
  1196. }
  1197. /*++
  1198. Routine Name:
  1199. GetFullyQualifiedDomainName
  1200. Description:
  1201. This returns a truly fully qualified name, being the name that the endpoint
  1202. expects to use, or
  1203. Arguments:
  1204. pszServerName - The server name whose fully qualified name we are obtaining.
  1205. ppszFullyQualified - The returned fully qualified name.
  1206. Return Value:
  1207. An HRESULT.
  1208. --*/
  1209. HRESULT
  1210. GetFullyQualifiedDomainName(
  1211. IN PCWSTR pszServerName,
  1212. OUT PWSTR *ppszFullyQualified
  1213. )
  1214. {
  1215. WORD wVersion;
  1216. WSADATA WSAData;
  1217. PSTR pszAnsiMachineName = NULL;
  1218. HRESULT hr = pszServerName && *pszServerName && ppszFullyQualified ? S_OK : HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1219. if (SUCCEEDED(hr))
  1220. {
  1221. wVersion = MAKEWORD(1, 1);
  1222. hr = HResultFromWin32(WSAStartup(wVersion, &WSAData));
  1223. }
  1224. if (SUCCEEDED(hr))
  1225. {
  1226. ADDRINFO *pAddrInfo = NULL;
  1227. CHAR HostName[NI_MAXHOST];
  1228. hr = UnicodeToAnsiString(pszServerName, &pszAnsiMachineName);
  1229. if (SUCCEEDED(hr))
  1230. {
  1231. hr = getaddrinfo(pszAnsiMachineName, NULL, NULL, &pAddrInfo) == 0 ? S_OK : HResultFromWin32(WSAGetLastError());
  1232. }
  1233. //
  1234. // Now the we have a socket addr, do a reverse name lookup on the name.
  1235. //
  1236. if (SUCCEEDED(hr))
  1237. {
  1238. hr = HResultFromWin32(getnameinfo(pAddrInfo->ai_addr, pAddrInfo->ai_addrlen, HostName, sizeof(HostName), NULL, 0, NI_NAMEREQD));
  1239. }
  1240. if (SUCCEEDED(hr))
  1241. {
  1242. *ppszFullyQualified = AnsiToUnicodeStringWithAlloc(HostName);
  1243. hr = *ppszFullyQualified ? S_OK : HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
  1244. }
  1245. if (pAddrInfo)
  1246. {
  1247. freeaddrinfo(pAddrInfo);
  1248. }
  1249. WSACleanup();
  1250. }
  1251. FreeSplMem(pszAnsiMachineName);
  1252. return hr;
  1253. }