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.

935 lines
24 KiB

  1. /*++
  2. Copyright (c) 1990 - 1995 Microsoft Corporation
  3. Module Name:
  4. net.c
  5. Abstract:
  6. This module provides all the network stuuf for localspl
  7. Author:
  8. Dave Snipp (DaveSn) 15-Mar-1991
  9. Notes:
  10. We just need to get the winspool printer name associated with a given
  11. queue name. The SHARE_INFO_2 structure has a shi2_path field that would
  12. be nice to use, but NetShareGetInfo level 2 is privileged. So, by
  13. DaveSn's arm twisting and agreement with windows/spooler/localspl/net.c,
  14. we're going to use the shi1_remark field for this. This allows us to
  15. do NetShareGetInfo level 1, which is not privileged.
  16. This has been fixed by allowing OpenPrinter to succeed on share names.
  17. If there is no comment, we put the printer name in as the remark
  18. (for graceful upgrades from pre-PPC).
  19. Revision History:
  20. 02-Sep-1992 JohnRo
  21. RAID 3556: DosPrintQGetInfo(from downlevel) level 3, rc=124. (4&5 too.)
  22. Jun 93 mattfe pIniSpooler
  23. --*/
  24. #define UNICODE 1
  25. #define NOMINMAX
  26. #include <precomp.h>
  27. #pragma hdrstop
  28. #include "clusspl.h"
  29. #ifdef DBG_SHARE
  30. #include <messages.h>
  31. #endif
  32. NET_API_STATUS (*pfnNetShareAdd)();
  33. NET_API_STATUS (*pfnNetShareSetInfo)();
  34. NET_API_STATUS (*pfnNetShareDel)();
  35. NET_API_STATUS (*pfnNetServerEnum)();
  36. NET_API_STATUS (*pfnNetWkstaUserGetInfo)();
  37. NET_API_STATUS (*pfnNetApiBufferFree)();
  38. NET_API_STATUS (*pfnNetAlertRaiseEx)();
  39. NET_API_STATUS (*pfnNetShareGetInfo)(LPWSTR, LPWSTR, DWORD, LPBYTE *);
  40. extern SHARE_INFO_2 PrintShareInfo;
  41. extern SHARE_INFO_2 PrtProcsShareInfo;
  42. BOOL
  43. InitializeNet(
  44. VOID
  45. )
  46. {
  47. HANDLE hNetApi;
  48. UINT uOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  49. hNetApi = LoadLibrary(TEXT("netapi32.dll"));
  50. SetErrorMode(uOldErrorMode);
  51. if ( !hNetApi )
  52. return FALSE;
  53. pfnNetShareAdd = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareAdd");
  54. pfnNetShareSetInfo = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareSetInfo");
  55. pfnNetShareDel = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetShareDel");
  56. pfnNetServerEnum = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetServerEnum");
  57. pfnNetWkstaUserGetInfo = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetWkstaUserGetInfo");
  58. pfnNetApiBufferFree = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetApiBufferFree");
  59. pfnNetAlertRaiseEx = (NET_API_STATUS (*)()) GetProcAddress(hNetApi,"NetAlertRaiseEx");
  60. pfnNetShareGetInfo = (NET_API_STATUS (*)(LPWSTR, LPWSTR, DWORD, LPBYTE *))GetProcAddress(hNetApi, "NetShareGetInfo");
  61. if ( pfnNetShareAdd == NULL ||
  62. pfnNetShareSetInfo == NULL ||
  63. pfnNetShareDel == NULL ||
  64. pfnNetServerEnum == NULL ||
  65. pfnNetWkstaUserGetInfo == NULL ||
  66. pfnNetApiBufferFree == NULL ||
  67. pfnNetAlertRaiseEx == NULL ||
  68. pfnNetShareGetInfo == NULL) {
  69. return FALSE;
  70. }
  71. return TRUE;
  72. }
  73. BOOL
  74. SetPrinterShareInfo(
  75. PINIPRINTER pIniPrinter
  76. )
  77. /*++
  78. Routine Description:
  79. Sets the share information about a printer.
  80. Note: This does not update the share path. We need to
  81. delete and re-create the share in order to change the path.
  82. Arguments:
  83. pIniPrinter - Printer that needs to be updated.
  84. Return Value:
  85. TRUE - Success
  86. FALSE - Failed
  87. --*/
  88. {
  89. SHARE_INFO_502 ShareInfo;
  90. HANDLE hToken;
  91. PSECURITY_DESCRIPTOR pShareSecurityDescriptor = NULL;
  92. DWORD ParmError, rc;
  93. SplInSem();
  94. pShareSecurityDescriptor = MapPrinterSDToShareSD(pIniPrinter->pSecurityDescriptor);
  95. if ( !pShareSecurityDescriptor ) {
  96. rc = ERROR_INVALID_SECURITY_DESCR;
  97. goto Cleanup;
  98. }
  99. ZeroMemory((LPVOID)&ShareInfo, sizeof(ShareInfo));
  100. ShareInfo.shi502_netname = pIniPrinter->pShareName;
  101. ShareInfo.shi502_type = STYPE_PRINTQ;
  102. ShareInfo.shi502_permissions = 0;
  103. ShareInfo.shi502_max_uses = SHI_USES_UNLIMITED;
  104. ShareInfo.shi502_current_uses = SHI_USES_UNLIMITED;
  105. ShareInfo.shi502_passwd = NULL;
  106. ShareInfo.shi502_security_descriptor = pShareSecurityDescriptor;
  107. if ( pIniPrinter->pComment && pIniPrinter->pComment[0] ) {
  108. ShareInfo.shi502_remark = pIniPrinter->pComment;
  109. } else {
  110. ShareInfo.shi502_remark = pIniPrinter->pName;
  111. }
  112. INCPRINTERREF(pIniPrinter);
  113. LeaveSplSem();
  114. SplOutSem(); // We *MUST* be out of our semaphore as the NetShareSet may
  115. // come back and call spooler
  116. hToken = RevertToPrinterSelf();
  117. rc = (*pfnNetShareSetInfo)(NULL,
  118. ShareInfo.shi502_netname,
  119. 502,
  120. &ShareInfo,
  121. &ParmError);
  122. if ( rc ) {
  123. if (rc == NERR_NetNameNotFound)
  124. {
  125. //
  126. // This can happen deny all access to a shared printer, then
  127. // restart the computer. The server service tries to validate
  128. // it's share on startup, but since it has no access, it fails
  129. // and deletes it (it also wants a handle to the printer). When
  130. // you grant everyone access, we try to change the ACL on the
  131. // SMB share, but since it was deleted, we fail. Recreate
  132. // the share here.
  133. //
  134. EnterSplSem();
  135. if (!ShareThisPrinter(pIniPrinter,
  136. pIniPrinter->pShareName,
  137. TRUE)) {
  138. rc = GetLastError();
  139. } else {
  140. rc = ERROR_SUCCESS;
  141. }
  142. LeaveSplSem();
  143. }
  144. if (rc) {
  145. DBGMSG(DBG_WARNING,
  146. ("NetShareSetInfo/ShareThisPrinter failed: Error %d, Parm %d\n",
  147. rc, ParmError));
  148. SetLastError(rc);
  149. }
  150. }
  151. ImpersonatePrinterClient(hToken);
  152. EnterSplSem();
  153. DECPRINTERREF(pIniPrinter);
  154. Cleanup:
  155. SplInSem();
  156. return rc == ERROR_SUCCESS;
  157. }
  158. BOOL
  159. ShareThisPrinter(
  160. PINIPRINTER pIniPrinter,
  161. LPWSTR pShareName,
  162. BOOL bShare
  163. )
  164. /*++
  165. Routine Description:
  166. Shares or UnShares a Printer.
  167. Note: this really should be two functions, and the return value
  168. is very confusing.
  169. Note: no validation of sharename is done. This must be done by
  170. callee, usually in ValidatePrinterInfo.
  171. Arguments:
  172. Return Value:
  173. Returns whether the printer is shared after this call.
  174. TRUE - Shared
  175. FALSE - Not Shared
  176. --*/
  177. {
  178. SHARE_INFO_502 ShareInfo = {0};
  179. DWORD rc;
  180. DWORD ParmError;
  181. PSECURITY_DESCRIPTOR pShareSecurityDescriptor = NULL;
  182. PINISPOOLER pIniSpooler = pIniPrinter->pIniSpooler;
  183. PSHARE_INFO_2 pShareInfo = (PSHARE_INFO_2)pIniSpooler->pDriversShareInfo;
  184. LPTSTR pszPrinterNameWithToken = NULL;
  185. HANDLE hToken;
  186. BOOL bReturn = FALSE;
  187. BOOL bSame = FALSE;
  188. LPWSTR pShareNameCopy = NULL;
  189. SPLASSERT( pIniPrinter->pName );
  190. SplInSem();
  191. pShareNameCopy = AllocSplStr(pShareName);
  192. if (!pShareNameCopy) {
  193. goto Done;
  194. }
  195. if ( bShare ) {
  196. if (!pfnNetShareAdd) {
  197. SetLastError( ERROR_PROC_NOT_FOUND );
  198. goto Done;
  199. }
  200. //
  201. // Share name validation has been moved into ValidatePrinterInfo.
  202. //
  203. if ((pShareSecurityDescriptor =
  204. MapPrinterSDToShareSD(pIniPrinter->pSecurityDescriptor)) == NULL) {
  205. SetLastError(ERROR_INVALID_SECURITY_DESCR);
  206. goto Done;
  207. }
  208. ShareInfo.shi502_netname = pShareNameCopy; // hplaser
  209. //
  210. // If there is a comment, use it; otherwise set the remark
  211. // to be the printer name.
  212. //
  213. // Note: if the printer name changes and we don't have a comment,
  214. // we will reshare the printer to update the remark.
  215. //
  216. if( pIniPrinter->pComment && pIniPrinter->pComment[0] ){
  217. ShareInfo.shi502_remark = pIniPrinter->pComment;
  218. } else {
  219. ShareInfo.shi502_remark = pIniPrinter->pName;
  220. }
  221. //
  222. // Use the fully qualifed name, and make sure it exists in
  223. // localspl by using LocalsplOnlyToken.
  224. //
  225. pszPrinterNameWithToken = pszGetPrinterName(
  226. pIniPrinter,
  227. pIniSpooler != pLocalIniSpooler,
  228. pszLocalsplOnlyToken );
  229. if( !pszPrinterNameWithToken ){
  230. goto Done;
  231. }
  232. ShareInfo.shi502_path = pszPrinterNameWithToken;
  233. ShareInfo.shi502_type = STYPE_PRINTQ;
  234. ShareInfo.shi502_permissions = 0;
  235. ShareInfo.shi502_max_uses = SHI_USES_UNLIMITED;
  236. ShareInfo.shi502_current_uses = SHI_USES_UNLIMITED;
  237. ShareInfo.shi502_passwd = NULL;
  238. ShareInfo.shi502_security_descriptor = pShareSecurityDescriptor;
  239. INCPRINTERREF(pIniPrinter);
  240. LeaveSplSem();
  241. //
  242. // We *MUST* be out of our semaphore as the NetShareAdd is
  243. // going to come round and call OpenPrinter.
  244. //
  245. SplOutSem();
  246. // Go add the Print Share
  247. hToken = RevertToPrinterSelf();
  248. // Add a share for the spool\drivers directory:
  249. if( rc = AddPrintShare( pIniSpooler )){
  250. EnterSplSem();
  251. DECPRINTERREF(pIniPrinter);
  252. ImpersonatePrinterClient(hToken);
  253. SetLastError(rc);
  254. goto Done;
  255. }
  256. #if DBG
  257. {
  258. WCHAR UserName[256];
  259. DWORD cbUserName=256;
  260. if (MODULE_DEBUG & DBG_SECURITY)
  261. GetUserName(UserName, &cbUserName);
  262. DBGMSG( DBG_SECURITY, ( "Calling NetShareAdd in context %ws\n", UserName ) );
  263. }
  264. #endif
  265. // Add the printer share:
  266. rc = (*pfnNetShareAdd)(NULL, 502, (LPBYTE)&ShareInfo, &ParmError);
  267. // Now take care of Web sharing. i.e. make sure wwwroot\sharename is created if the
  268. // printer is either local or masqurading. We cannot allow sharing of RPC connections.
  269. if( fW3SvcInstalled && (pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL))
  270. WebShare( pShareNameCopy );
  271. //
  272. // If the return code is that the share already exists, then check to
  273. // see whether this share is to the same device, if it is we just
  274. // update the info on the share and return success.
  275. //
  276. if (rc == NERR_DuplicateShare) {
  277. if (ERROR_SUCCESS == CheckShareSame(pIniPrinter, &ShareInfo, &bSame) && bSame) {
  278. rc = ERROR_SUCCESS;
  279. }
  280. }
  281. ImpersonatePrinterClient(hToken);
  282. EnterSplSem();
  283. DECPRINTERREF(pIniPrinter);
  284. if (ERROR_SUCCESS != rc) {
  285. DBGMSG( DBG_WARNING,
  286. ( "NetShareAdd failed %lx, Parameter %d\n",
  287. rc, ParmError ));
  288. if ((rc == ERROR_INVALID_PARAMETER) &&
  289. (ParmError == SHARE_NETNAME_PARMNUM)) {
  290. rc = ERROR_INVALID_SHARENAME;
  291. }
  292. SetLastError(rc);
  293. goto Done;
  294. }
  295. SPLASSERT( pIniPrinter != NULL);
  296. SPLASSERT( pIniPrinter->signature == IP_SIGNATURE);
  297. SPLASSERT( pIniPrinter->pIniSpooler != NULL);
  298. SPLASSERT( pIniPrinter->pIniSpooler->signature == ISP_SIGNATURE );
  299. CreateServerThread();
  300. //
  301. // The Printer is shared.
  302. //
  303. bReturn = TRUE;
  304. } else {
  305. if ( !pfnNetShareDel ) {
  306. bReturn = TRUE;
  307. goto Done;
  308. }
  309. INCPRINTERREF( pIniPrinter );
  310. LeaveSplSem();
  311. SplOutSem();
  312. hToken = RevertToPrinterSelf();
  313. rc = (*pfnNetShareDel)(NULL, pShareName, 0);
  314. // Now take care of Web unsharing. i.e. make sure wwwroot\sharename is deleted.
  315. if( fW3SvcInstalled && (pIniSpooler->SpoolerFlags & SPL_TYPE_LOCAL) && !(pIniSpooler->SpoolerFlags & SPL_TYPE_CLUSTER))
  316. WebUnShare( pShareName );
  317. ImpersonatePrinterClient(hToken);
  318. EnterSplSem();
  319. DECPRINTERREF(pIniPrinter);
  320. // The share may have been deleted manually, so don't worry
  321. // if we get NERR_NetNameNotFound:
  322. if ( rc && ( rc != NERR_NetNameNotFound )){
  323. DBGMSG(DBG_WARNING, ("NetShareDel failed %lx\n", rc));
  324. SetLastError( rc );
  325. bReturn = TRUE;
  326. }
  327. }
  328. Done:
  329. if( pShareSecurityDescriptor ){
  330. LocalFree(pShareSecurityDescriptor);
  331. }
  332. FreeSplStr(pszPrinterNameWithToken);
  333. FreeSplStr(pShareNameCopy);
  334. return bReturn;
  335. }
  336. /*--
  337. FillAlertStructWithJobStrings
  338. Allocates memory which has to be freed by caller.
  339. --*/
  340. HRESULT
  341. FillAlertStructWithJobStrings(
  342. PINIJOB pIniJob,
  343. PRINT_OTHER_INFO **pAlertInfo,
  344. PDWORD size
  345. )
  346. {
  347. HRESULT RetVal = E_FAIL;
  348. DWORD cbSizetoAlloc = 0;
  349. PBYTE pBuffer = NULL;
  350. LPWSTR psz = NULL;
  351. if (pIniJob && pAlertInfo && !(*pAlertInfo) && size)
  352. {
  353. //
  354. // Do this in the splSem so that no one can jo a SetJob While we're not looking
  355. //
  356. EnterSplSem();
  357. //
  358. // We don't know how big these strings are going to be in future, so size
  359. // them dynamically and alloc the structure to always be big enough.
  360. //
  361. cbSizetoAlloc = sizeof(PRINT_OTHER_INFO);
  362. //
  363. // We don't have to check some of these for existence, we know they exist.
  364. //
  365. cbSizetoAlloc += wcslen(pIniJob->pNotify) + 1 +
  366. wcslen(pIniJob->pIniPrinter->pName) + 1 +
  367. wcslen(pIniJob->pIniPrinter->pIniSpooler->pMachineName) + 1;
  368. if ( pIniJob->pDocument )
  369. {
  370. cbSizetoAlloc += wcslen(pIniJob->pDocument) + 1;
  371. }
  372. else
  373. {
  374. cbSizetoAlloc += 2;
  375. }
  376. if (pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopupToComputer &&
  377. pIniJob->pMachineName)
  378. {
  379. cbSizetoAlloc += wcslen(pIniJob->pMachineName) + 1;
  380. }
  381. else
  382. {
  383. cbSizetoAlloc += wcslen(pIniJob->pNotify) + 1;
  384. }
  385. if ( pIniJob->pStatus )
  386. {
  387. cbSizetoAlloc += wcslen(pIniJob->pStatus) + 1;
  388. }
  389. else
  390. {
  391. cbSizetoAlloc += 2;
  392. }
  393. //
  394. // Scale the buffer by the number of bytes per character.
  395. //
  396. cbSizetoAlloc = cbSizetoAlloc * sizeof(TCHAR);
  397. //
  398. // Alloc the memory
  399. //
  400. pBuffer = AllocSplMem(cbSizetoAlloc);
  401. if ( pBuffer )
  402. {
  403. psz = (LPWSTR)ALERT_VAR_DATA((PRINT_OTHER_INFO *)pBuffer);
  404. //
  405. // Do the copying
  406. //
  407. //
  408. // Computer Name
  409. //
  410. if(pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopupToComputer &&
  411. pIniJob->pMachineName ){
  412. wcscpy( psz, pIniJob->pMachineName );
  413. } else {
  414. wcscpy( psz, pIniJob->pNotify );
  415. }
  416. psz+=wcslen(psz)+1;
  417. // UserName
  418. wcscpy(psz, pIniJob->pNotify);
  419. psz+=wcslen(psz)+1;
  420. // Document Name
  421. if (pIniJob->pDocument)
  422. wcscpy(psz, pIniJob->pDocument);
  423. else
  424. wcscpy(psz, L"");
  425. psz += wcslen(psz) + 1;
  426. // Printer Name
  427. wcscpy(psz, pIniJob->pIniPrinter->pName);
  428. psz += wcslen(psz)+1;
  429. // Server Name
  430. wcscpy(psz, pIniJob->pIniPrinter->pIniSpooler->pMachineName);
  431. psz += wcslen(psz)+1;
  432. // Status_string
  433. // We should pass in other status strings for the other status errors, too.
  434. if (pIniJob->pStatus && (pIniJob->Status & (JOB_ERROR | JOB_OFFLINE | JOB_PAPEROUT)))
  435. wcscpy(psz, pIniJob->pStatus);
  436. else
  437. wcscpy(psz, L"");
  438. psz += wcslen(psz) + 1;
  439. //
  440. // Pass back the size and struct
  441. //
  442. *size = (DWORD)((PBYTE)psz - pBuffer);
  443. *pAlertInfo = (PRINT_OTHER_INFO *)pBuffer;
  444. RetVal = NOERROR;
  445. }
  446. else
  447. {
  448. RetVal = E_OUTOFMEMORY;
  449. }
  450. //
  451. // Leave the Spooler Semaphore
  452. //
  453. LeaveSplSem();
  454. }
  455. else
  456. {
  457. RetVal = E_INVALIDARG;
  458. }
  459. return RetVal;
  460. }
  461. VOID
  462. SendJobAlert(
  463. PINIJOB pIniJob
  464. )
  465. {
  466. PRINT_OTHER_INFO *pinfo = NULL;
  467. DWORD RetVal = ERROR_SUCCESS;
  468. DWORD Status;
  469. FILETIME FileTime;
  470. DWORD AlertSize = 0;
  471. #ifdef _HYDRA_
  472. // Allow Hydra Sessions to be notified since they are remote
  473. if( (USER_SHARED_DATA->SuiteMask & (1 << TerminalServer)) ) {
  474. if ( !pIniJob->pNotify ||
  475. !pIniJob->pNotify[0] ||
  476. !pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopups ) {
  477. return;
  478. }
  479. }
  480. else {
  481. if ( !pIniJob->pNotify ||
  482. !pIniJob->pNotify[0] ||
  483. !(pIniJob->Status & JOB_REMOTE) ||
  484. !pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopups ) {
  485. return;
  486. }
  487. }
  488. #else
  489. if ( !pIniJob->pNotify ||
  490. !pIniJob->pNotify[0] ||
  491. !(pIniJob->Status & JOB_REMOTE) ||
  492. !pIniJob->pIniPrinter->pIniSpooler->bEnableNetPopups ) {
  493. return;
  494. }
  495. #endif
  496. if ( FAILED(RetVal = FillAlertStructWithJobStrings(pIniJob, &pinfo, &AlertSize)))
  497. {
  498. if ( pinfo )
  499. FreeSplMem(pinfo);
  500. return;
  501. }
  502. pinfo->alrtpr_jobid = pIniJob->JobId;
  503. if (pIniJob->Status & (JOB_PRINTING | JOB_DESPOOLING | JOB_PRINTED | JOB_COMPLETE))
  504. Status = PRJOB_QS_PRINTING;
  505. else if (pIniJob->Status & JOB_PAUSED)
  506. Status = PRJOB_QS_PAUSED;
  507. else if (pIniJob->Status & JOB_SPOOLING)
  508. Status = PRJOB_QS_SPOOLING;
  509. else
  510. Status = PRJOB_QS_QUEUED;
  511. if (pIniJob->Status & (JOB_ERROR | JOB_OFFLINE | JOB_PAPEROUT)) {
  512. Status |= PRJOB_ERROR;
  513. if (pIniJob->Status & JOB_OFFLINE)
  514. Status |= PRJOB_DESTOFFLINE;
  515. if (pIniJob->Status & JOB_PAPEROUT)
  516. Status |= PRJOB_DESTNOPAPER;
  517. }
  518. if (pIniJob->Status & JOB_PRINTED)
  519. Status |= PRJOB_COMPLETE;
  520. else if (pIniJob->Status & JOB_PENDING_DELETION)
  521. Status |= PRJOB_DELETED;
  522. pinfo->alrtpr_status = Status;
  523. SystemTimeToFileTime( &pIniJob->Submitted, &FileTime );
  524. // FileTimeToDosDateTime(&FileTime, &DosDate, &DosTime);
  525. // pinfo->alrtpr_submitted = DosDate << 16 | DosTime;
  526. RtlTimeToSecondsSince1970((PLARGE_INTEGER) &FileTime,
  527. &pinfo->alrtpr_submitted);
  528. pinfo->alrtpr_size = pIniJob->Size;
  529. (*pfnNetAlertRaiseEx)(ALERT_PRINT_EVENT,
  530. (PBYTE) pinfo,
  531. AlertSize,
  532. L"SPOOLER");
  533. if ( pinfo )
  534. FreeSplMem(pinfo);
  535. }
  536. DWORD
  537. AddPrintShare(
  538. PINISPOOLER pIniSpooler
  539. )
  540. /*++
  541. Routine Description:
  542. Adds the print$ share based on pIniSpooler.
  543. Arguments:
  544. pIniSpooler - Share path is based on this information. pDriversShareInfo
  545. must be initialized before calling this routine.
  546. Return Value:
  547. TRUE - Success.
  548. FALSE - Failed. LastError set.
  549. --*/
  550. {
  551. DWORD rc;
  552. DWORD ParmError;
  553. SHARE_INFO_1501 ShareInfo1501 = {0};
  554. PSHARE_INFO_2 pShareInfo = (PSHARE_INFO_2)pIniSpooler->pDriversShareInfo;
  555. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  556. //
  557. // Assert that the path is identical to the local one since there's
  558. // only one print$ share. It should always be.
  559. //
  560. SPLASSERT( !lstrcmpi( pShareInfo->shi2_path,
  561. ((PSHARE_INFO_2)pLocalIniSpooler->pDriversShareInfo)->shi2_path ));
  562. rc = (*pfnNetShareAdd)( NULL,
  563. 2,
  564. (LPBYTE)pShareInfo,
  565. &ParmError );
  566. //
  567. // If it already exists, assume it is set up correctly.
  568. //
  569. if( rc == NERR_DuplicateShare ){
  570. return ERROR_SUCCESS;
  571. }
  572. //
  573. // If we didn't create the share, fail.
  574. //
  575. if( rc != ERROR_SUCCESS ){
  576. DBGMSG( DBG_WARN,
  577. ( "AddPrintShare: Error %d, Parm %d\n", rc, ParmError));
  578. return rc;
  579. }
  580. //
  581. // Set security on the newly created share.
  582. //
  583. // Bug 54844
  584. // If this fails, we've created the share but haven't put security
  585. // on it. Then since it exists, we'll never try and set it again.
  586. //
  587. pSecurityDescriptor = CreateDriversShareSecurityDescriptor();
  588. if( !pSecurityDescriptor ){
  589. return GetLastError();
  590. }
  591. ShareInfo1501.shi1501_security_descriptor = pSecurityDescriptor;
  592. rc = (*pfnNetShareSetInfo)( NULL,
  593. pShareInfo->shi2_netname,
  594. 1501,
  595. &ShareInfo1501,
  596. &ParmError );
  597. if( rc != ERROR_SUCCESS ){
  598. DBGMSG( DBG_WARN,
  599. ( "NetShareSetInfo failed: Error %d, Parm %d\n",
  600. rc, ParmError));
  601. }
  602. LocalFree(pSecurityDescriptor);
  603. return rc;
  604. }
  605. /*++
  606. Routine Name:
  607. CheckShareSame
  608. Routine Description:
  609. This checks to see whether the given share name is the same on both the
  610. local and remote machines.
  611. Arguments:
  612. pIniPrinter - The iniprinter for which we are adding the share.
  613. pShareInfo502 - The share info that we are attempting to add the share
  614. with.
  615. pbSame - The return parameter is TRUE if the shares were the same
  616. If the rc is not ERROR_SUCCESS, then the info could not
  617. be set.
  618. Return Value:
  619. An error code.
  620. --*/
  621. DWORD
  622. CheckShareSame(
  623. IN PINIPRINTER pIniPrinter,
  624. IN SHARE_INFO_502 *pShareInfo502,
  625. OUT BOOL *pbSame
  626. )
  627. {
  628. DWORD rc = ERROR_SUCCESS;
  629. SHARE_INFO_2 *pShareInfoCompare = NULL;
  630. BOOL bPathEquivalent = FALSE;
  631. BOOL bSame = FALSE;
  632. DWORD ParmError;
  633. SplOutSem();
  634. //
  635. // Get the share info for the share, we should already have determined
  636. // that this share exists.
  637. //
  638. rc = pfnNetShareGetInfo(NULL, pShareInfo502->shi502_netname, 2, (LPBYTE *)&pShareInfoCompare);
  639. if (ERROR_SUCCESS == rc)
  640. {
  641. if (STYPE_PRINTQ == pShareInfoCompare->shi2_type)
  642. {
  643. //
  644. // Check to see whether the paths are the same, in the upgrade case, the
  645. // LocalSplOnly will be taken off, so, compare this too.
  646. //
  647. bSame = !_wcsicmp(pShareInfoCompare->shi2_path, pShareInfo502->shi502_path);
  648. //
  649. // If they are not the same, compare it to the name of the printer.
  650. //
  651. if (!bSame)
  652. {
  653. EnterSplSem();
  654. bSame = bPathEquivalent = !_wcsicmp(pIniPrinter->pName, pShareInfoCompare->shi2_path);
  655. LeaveSplSem();
  656. }
  657. }
  658. }
  659. *pbSame = bSame;
  660. if (ERROR_SUCCESS == rc && bSame)
  661. {
  662. //
  663. // If the paths are identical, we can just set the share info, otherwise
  664. // we have to delete and recreate the share.
  665. //
  666. if (!bPathEquivalent)
  667. {
  668. //
  669. // OK, they are the same, set the share info instead.
  670. //
  671. rc = (*pfnNetShareSetInfo)(NULL, pShareInfo502->shi502_netname, 502, pShareInfo502, &ParmError);
  672. }
  673. else
  674. {
  675. rc = (*pfnNetShareDel)(NULL, pShareInfo502->shi502_netname, 0);
  676. if (ERROR_SUCCESS == rc)
  677. {
  678. rc = (*pfnNetShareAdd)(NULL, 502, (LPBYTE)pShareInfo502, &ParmError);
  679. }
  680. }
  681. }
  682. if (pShareInfoCompare)
  683. {
  684. pfnNetApiBufferFree(pShareInfoCompare);
  685. }
  686. return rc;
  687. }