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.

553 lines
16 KiB

  1. /*++
  2. Copyright (c) 1990 - 1996 Microsoft Corporation
  3. Module Name:
  4. Files.c
  5. Abstract:
  6. This module provides routines required to copy files associated with a
  7. printer on printer connection
  8. Author:
  9. Muhunthan Sivapragasam (MuhuntS) 05-Dec-96
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. #include "clusspl.h"
  14. HMODULE
  15. SplLoadLibraryTheCopyFileModule(
  16. HANDLE hPrinter,
  17. LPWSTR pszModule
  18. )
  19. {
  20. UINT uErrorMode;
  21. DWORD dwLen;
  22. WCHAR szPath[MAX_PATH];
  23. PSPOOL pSpool = (PSPOOL)hPrinter;
  24. HMODULE hModule;
  25. PINIDRIVER pIniDriver;
  26. uErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  27. //
  28. // This should be fine because we will be using the process path. Unforunately
  29. // the registry has been set up not to use a full path, so we can't change this
  30. // and be sure of not breaking backward compatability.
  31. //
  32. hModule = LoadLibrary(pszModule);
  33. //
  34. // If the module could not be found in $Path look for it in the
  35. // printer driver directory
  36. //
  37. if ( !hModule &&
  38. GetLastError() == ERROR_MOD_NOT_FOUND &&
  39. (dwLen = GetIniDriverAndDirForThisMachine(pSpool->pIniPrinter,
  40. szPath,
  41. &pIniDriver)) ) {
  42. if (!BoolFromHResult(StringCchCopy(szPath+dwLen, COUNTOF(szPath) - dwLen, pszModule))) {
  43. goto Cleanup;
  44. }
  45. hModule = LoadLibraryEx(szPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  46. }
  47. Cleanup:
  48. (VOID)SetErrorMode(uErrorMode);
  49. return hModule;
  50. }
  51. BOOL
  52. GenerateDirectoryNamesForCopyFilesKey(
  53. PSPOOL pSpool,
  54. HKEY hKey,
  55. LPWSTR *ppszSourceDir,
  56. LPWSTR *ppszTargetDir,
  57. DWORD cbMax
  58. )
  59. {
  60. BOOL bRet = FALSE, bInCS = FALSE;
  61. DWORD dwType, dwSize, dwSourceDirSize, dwTargetDirSize;
  62. LPWSTR pszDir, ppszFiles, pszModule = NULL, pszPrinterName = NULL;
  63. HMODULE hModule = NULL;
  64. DWORD (*pfn)(LPWSTR pszPrinterName,
  65. LPCWSTR pszDirectory,
  66. LPBYTE pSplClientInfo,
  67. DWORD dwLevel,
  68. LPWSTR pszSourceDir,
  69. LPDWORD pcchSourceDirSize,
  70. LPWSTR pszTargetDir,
  71. LPDWORD pcchTargetDirSize,
  72. DWORD dwFlags
  73. );
  74. SPLCLIENT_INFO_1 SplClientInfo1;
  75. //
  76. // First find the keys we need from the registry
  77. // "Directory", "Files" values are mandatory. "Module" is optional
  78. //
  79. pszDir = (LPWSTR) AllocSplMem(cbMax);
  80. ppszFiles = (LPWSTR) AllocSplMem(cbMax);
  81. pszModule = (LPWSTR) AllocSplMem(cbMax);
  82. if ( !pszDir || !ppszFiles || !pszModule )
  83. goto Cleanup;
  84. if ( (dwSize = cbMax) &&
  85. ERROR_SUCCESS == SplRegQueryValue(hKey,
  86. L"Directory",
  87. &dwType,
  88. (LPBYTE)pszDir,
  89. &dwSize,
  90. pSpool->pIniSpooler) &&
  91. dwType == REG_SZ &&
  92. (dwSize = cbMax) &&
  93. ERROR_SUCCESS == SplRegQueryValue(hKey,
  94. L"Files",
  95. &dwType,
  96. (LPBYTE)ppszFiles,
  97. &dwSize,
  98. pSpool->pIniSpooler) &&
  99. dwType == REG_MULTI_SZ ) {
  100. dwSize = cbMax;
  101. if ( ERROR_SUCCESS == SplRegQueryValue(hKey,
  102. L"Module",
  103. &dwType,
  104. (LPBYTE)pszModule,
  105. &dwSize,
  106. pSpool->pIniSpooler) &&
  107. dwType != REG_SZ ) {
  108. SetLastError(ERROR_INVALID_PARAMETER);
  109. goto Cleanup;
  110. }
  111. }
  112. //
  113. // If a module is given we need to call into to "correct" the path
  114. // We will first try LoadLibrary on the module, if we can't find the module
  115. // we will look in the driver directory for it
  116. //
  117. if ( pszModule && *pszModule ) {
  118. if ( !(hModule = SplLoadLibraryTheCopyFileModule(pSpool, pszModule)) ||
  119. !((FARPROC)pfn = GetProcAddress(hModule, "GenerateCopyFilePaths")) )
  120. goto Cleanup;
  121. }
  122. dwTargetDirSize = MAX_PATH;
  123. dwSourceDirSize = INTERNET_MAX_HOST_NAME_LENGTH + MAX_PATH;
  124. *ppszSourceDir = (LPWSTR) AllocSplMem(dwSourceDirSize * sizeof(WCHAR));
  125. *ppszTargetDir = (LPWSTR) AllocSplMem(dwTargetDirSize * sizeof(WCHAR));
  126. if ( !*ppszSourceDir || !*ppszTargetDir )
  127. goto Cleanup;
  128. EnterSplSem();
  129. bInCS = TRUE;
  130. pszPrinterName = AllocSplStr(pSpool->pIniPrinter->pName);
  131. //
  132. // For source dir we will give full path the way the client will understand
  133. // (ie. have correct prefix -- server nam, dns name etc).
  134. // For target dir we will give a relative path off print$
  135. //
  136. if ( !pszPrinterName || wcslen(pszDir) >= dwTargetDirSize ||
  137. wcslen(pSpool->pFullMachineName) +
  138. wcslen(pSpool->pIniSpooler->pszDriversShare) +
  139. wcslen(pszDir) + 2 >= dwSourceDirSize ) {
  140. SetLastError(ERROR_INVALID_PARAMETER);
  141. goto Cleanup;
  142. }
  143. StringCchPrintf(*ppszSourceDir, dwSourceDirSize,
  144. L"%ws\\%ws\\%ws",
  145. pSpool->pFullMachineName,
  146. pSpool->pIniSpooler->pszDriversShare,
  147. pszDir);
  148. CopyMemory((LPBYTE)&SplClientInfo1, (LPBYTE)&pSpool->SplClientInfo1, sizeof(SPLCLIENT_INFO_1));
  149. SplClientInfo1.pUserName = NULL;
  150. SplClientInfo1.pMachineName = NULL;
  151. LeaveSplSem();
  152. bInCS = FALSE;
  153. StringCchCopy(*ppszTargetDir, dwTargetDirSize, pszDir);
  154. if ( hModule ) {
  155. //
  156. // On free builds we do not want spooler to crash
  157. //
  158. #if DBG
  159. #else
  160. try {
  161. #endif
  162. if ( ERROR_SUCCESS != pfn(pszPrinterName,
  163. pszDir,
  164. (LPBYTE)&SplClientInfo1,
  165. 1,
  166. *ppszSourceDir,
  167. &dwSourceDirSize,
  168. *ppszTargetDir,
  169. &dwTargetDirSize,
  170. COPYFILE_FLAG_SERVER_SPOOLER) )
  171. #if DBG
  172. goto Cleanup;
  173. #else
  174. leave;
  175. #endif
  176. bRet = TRUE;
  177. #if DBG
  178. #else
  179. } except(1) {
  180. }
  181. #endif
  182. } else {
  183. bRet = TRUE;
  184. }
  185. Cleanup:
  186. if ( bInCS )
  187. LeaveSplSem();
  188. SplOutSem();
  189. FreeSplStr(pszDir);
  190. FreeSplStr(ppszFiles);
  191. FreeSplStr(pszModule);
  192. FreeSplStr(pszPrinterName);
  193. if ( hModule )
  194. FreeLibrary(hModule);
  195. if ( !bRet ) {
  196. FreeSplStr(*ppszSourceDir);
  197. FreeSplStr(*ppszTargetDir);
  198. *ppszSourceDir = *ppszTargetDir = NULL;
  199. }
  200. return bRet;
  201. }
  202. LPWSTR
  203. BuildFilesCopiedAsAString(
  204. PINTERNAL_DRV_FILE pInternalDriverFile,
  205. DWORD dwCount
  206. )
  207. /*++
  208. For files copied we log an event. This routine allocates memory and
  209. generates the file list as a comma separated string
  210. --*/
  211. {
  212. DWORD dwIndex;
  213. SIZE_T Size;
  214. LPWSTR pszRet, psz2;
  215. LPCWSTR psz;
  216. //
  217. // Must have some files.
  218. //
  219. SPLASSERT( dwCount );
  220. for ( dwIndex = 0, Size = 0 ; dwIndex < dwCount ; ++dwIndex ) {
  221. //
  222. // Find the file name part
  223. //
  224. psz = FindFileName(pInternalDriverFile[dwIndex]. pFileName);
  225. if( psz ){
  226. //
  227. // Two characters for ", " separator. This also includes the
  228. // terminating NULL sice we count this for all files, but only
  229. // append ", " to the internal ones.
  230. //
  231. Size += wcslen(psz) + 2;
  232. }
  233. }
  234. pszRet = AllocSplMem((DWORD)(Size * sizeof(WCHAR)));
  235. if ( !pszRet )
  236. return NULL;
  237. for ( dwIndex = 0, psz2 = pszRet ; dwIndex < dwCount ; ++dwIndex ) {
  238. //
  239. // Find the file name part
  240. //
  241. psz = FindFileName(pInternalDriverFile[dwIndex].pFileName );
  242. if( psz ){
  243. StringCchCopyEx(psz2, Size, psz, &psz2, &Size, 0);
  244. if ( dwIndex < dwCount - 1) {
  245. StringCchCopyEx(psz2, Size, L", ", &psz2, &Size, 0);
  246. }
  247. }
  248. }
  249. return pszRet;
  250. }
  251. BOOL
  252. SplCopyNumberOfFiles(
  253. LPWSTR pszPrinterName,
  254. LPWSTR *ppszSourceFileNames,
  255. DWORD dwCount,
  256. LPWSTR pszTargetDir,
  257. LPBOOL pbFilesAddedOrUpdated
  258. )
  259. {
  260. BOOL bRet=FALSE, bFilesMoved;
  261. LPWSTR pszFiles;
  262. DWORD dwIndex;
  263. LPWSTR pszNewDir = NULL;
  264. LPWSTR pszOldDir = NULL;
  265. BOOL bFilesUpdated;
  266. INTERNAL_DRV_FILE *pInternalDriverFiles = NULL;
  267. BOOL bWaitForReboot = FALSE;
  268. *pbFilesAddedOrUpdated = FALSE;
  269. pInternalDriverFiles = (INTERNAL_DRV_FILE *) AllocSplMem(dwCount*sizeof(INTERNAL_DRV_FILE));
  270. if ( !pInternalDriverFiles )
  271. return FALSE;
  272. for ( dwIndex = 0 ; dwIndex < dwCount ; ++dwIndex ) {
  273. pInternalDriverFiles[dwIndex].pFileName = ppszSourceFileNames[dwIndex];
  274. //
  275. // This is "fine" because this ultimately comes from the server registry,
  276. // so it is no worse than anything else in point and print. Which is a
  277. // known filed issue.
  278. //
  279. pInternalDriverFiles[dwIndex].hFileHandle = CreateFile(ppszSourceFileNames[dwIndex],
  280. GENERIC_READ,
  281. FILE_SHARE_READ,
  282. NULL,
  283. OPEN_EXISTING,
  284. FILE_FLAG_SEQUENTIAL_SCAN,
  285. NULL);
  286. if ( pInternalDriverFiles[dwIndex].hFileHandle == INVALID_HANDLE_VALUE )
  287. goto Cleanup;
  288. }
  289. if ( !DirectoryExists(pszTargetDir) &&
  290. !CreateDirectoryWithoutImpersonatingUser(pszTargetDir) )
  291. goto Cleanup;
  292. // Create the New Directory
  293. if (!BoolFromStatus(StrCatAlloc(&pszNewDir, pszTargetDir, L"\\New", NULL))) {
  294. goto Cleanup;
  295. }
  296. if (!DirectoryExists(pszNewDir) &&
  297. !CreateDirectoryWithoutImpersonatingUser(pszNewDir)) {
  298. // Failed to create New directory
  299. goto Cleanup;
  300. }
  301. // Create the Old Directory
  302. if (!BoolFromStatus(StrCatAlloc(&pszOldDir, pszTargetDir, L"\\Old", NULL))) {
  303. goto Cleanup;
  304. }
  305. if (!DirectoryExists(pszOldDir) &&
  306. !CreateDirectoryWithoutImpersonatingUser(pszOldDir)) {
  307. // Failed to create Old directory
  308. goto Cleanup;
  309. }
  310. EnterSplSem();
  311. bFilesUpdated = FALSE;
  312. for (dwIndex = 0 ; dwIndex < dwCount ; ++dwIndex) {
  313. if (!(bRet = UpdateFile(NULL,
  314. pInternalDriverFiles[dwIndex].hFileHandle,
  315. pInternalDriverFiles[dwIndex].pFileName,
  316. 0,
  317. pszTargetDir,
  318. APD_COPY_NEW_FILES,
  319. TRUE,
  320. &bFilesUpdated,
  321. &bFilesMoved,
  322. TRUE,
  323. FALSE))) {
  324. //
  325. // Files could not be copied correctly
  326. //
  327. break;
  328. }
  329. if (bFilesUpdated) {
  330. *pbFilesAddedOrUpdated = TRUE;
  331. }
  332. }
  333. if (bRet && *pbFilesAddedOrUpdated) {
  334. bRet = MoveNewDriverRelatedFiles( pszNewDir,
  335. pszTargetDir,
  336. pszOldDir,
  337. pInternalDriverFiles,
  338. dwCount,
  339. NULL,
  340. NULL);
  341. //
  342. // Don't delete "New" directory if the files couldn't be moved in "Color" directory
  343. //
  344. bWaitForReboot = !bRet;
  345. }
  346. LeaveSplSem();
  347. Cleanup:
  348. if ( pszNewDir ) {
  349. DeleteDirectoryRecursively(pszNewDir, bWaitForReboot);
  350. FreeSplMem(pszNewDir);
  351. }
  352. if ( pszOldDir ) {
  353. DeleteDirectoryRecursively(pszOldDir, FALSE);
  354. FreeSplMem(pszOldDir);
  355. }
  356. if ( *pbFilesAddedOrUpdated &&
  357. (pszFiles = BuildFilesCopiedAsAString(pInternalDriverFiles, dwCount)) ) {
  358. SplLogEvent(pLocalIniSpooler,
  359. LOG_WARNING,
  360. MSG_FILES_COPIED,
  361. FALSE,
  362. pszFiles,
  363. pszPrinterName,
  364. NULL);
  365. FreeSplMem(pszFiles);
  366. }
  367. if ( pInternalDriverFiles ) {
  368. while ( dwIndex-- )
  369. CloseHandle(pInternalDriverFiles[dwIndex].hFileHandle);
  370. FreeSplMem(pInternalDriverFiles);
  371. }
  372. return bRet;
  373. }
  374. BOOL
  375. SplCopyFileEvent(
  376. HANDLE hPrinter,
  377. LPWSTR pszKey,
  378. DWORD dwCopyFileEvent
  379. )
  380. {
  381. BOOL bRet = FALSE;
  382. DWORD dwNeeded, dwType, dwLastError;
  383. LPWSTR pszModule = NULL;
  384. PSPOOL pSpool = (PSPOOL)hPrinter;
  385. HMODULE hModule = NULL;
  386. BOOL (*pfnSpoolerCopyFileEvent)(
  387. LPWSTR pszPrinterName,
  388. LPWSTR pszKey,
  389. DWORD dwCopyFileEvent
  390. );
  391. SPLASSERT(pSpool->pIniSpooler->signature == ISP_SIGNATURE);
  392. dwLastError = SplGetPrinterDataEx(hPrinter,
  393. pszKey,
  394. L"Module",
  395. &dwType,
  396. NULL,
  397. 0,
  398. &dwNeeded);
  399. //
  400. // If there is no module name there is no callback needed
  401. //
  402. if ( dwLastError == ERROR_FILE_NOT_FOUND )
  403. return TRUE;
  404. if ( dwLastError != ERROR_SUCCESS ||
  405. !(pszModule = (LPWSTR) AllocSplMem(dwNeeded)) ||
  406. SplGetPrinterDataEx(hPrinter,
  407. pszKey,
  408. L"Module",
  409. &dwType,
  410. (LPBYTE)pszModule,
  411. dwNeeded,
  412. &dwNeeded) ||
  413. dwType != REG_SZ ) {
  414. goto Cleanup;
  415. }
  416. if ( !(hModule = SplLoadLibraryTheCopyFileModule(hPrinter,
  417. pszModule)) ||
  418. !((FARPROC)pfnSpoolerCopyFileEvent = GetProcAddress(hModule,
  419. "SpoolerCopyFileEvent")) )
  420. goto Cleanup;
  421. #if DBG
  422. #else
  423. try {
  424. #endif
  425. bRet = pfnSpoolerCopyFileEvent(pSpool->pName,
  426. pszKey,
  427. dwCopyFileEvent);
  428. #if DBG
  429. #else
  430. } except(1) {
  431. }
  432. #endif
  433. Cleanup:
  434. FreeSplStr(pszModule);
  435. if ( hModule )
  436. FreeLibrary(hModule);
  437. return bRet;
  438. }