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.

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