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.

367 lines
10 KiB

  1. /*++
  2. Copyright (c) 1994 - 1996 Microsoft Corporation
  3. Module Name:
  4. Files.c
  5. Abstract:
  6. This module contains routines for copying files specified under the
  7. CopyFiles key of a print queue
  8. Author:
  9. Muhunthan Sivapragasam (Muhunthan Sivapragasam) Nov-27-96
  10. Revision History:
  11. --*/
  12. #include <precomp.h>
  13. WCHAR *szSpoolDirectory = L"\\spool";
  14. extern SPLCLIENT_INFO_1 gSplClientInfo1;
  15. #define PRINTER_ENUM_KEY_SIZE 400
  16. BOOL
  17. ProcessACopyFileKey(
  18. PWSPOOL pSpool,
  19. LPWSTR pszKey,
  20. LPWSTR pszModule,
  21. LPWSTR pszDir,
  22. LPWSTR ppszFiles,
  23. LPWSTR pszSourceDir,
  24. LPWSTR pszTargetDir,
  25. PSPLCLIENT_INFO_1 pSplClientInfo1
  26. )
  27. {
  28. BOOL bRet = FALSE, bFilesUpdated;
  29. DWORD dwLen, dwCount, dwTemp, dwSourceDirSize, dwTargetDirSize;
  30. LPWSTR *ppszFileNames = NULL, pszBuf = NULL, p1, p2;
  31. HINSTANCE hModule = NULL;
  32. DWORD (*pfn)(LPWSTR pszPrinterName,
  33. LPCWSTR pszDirectory,
  34. LPBYTE pSplClientInfo,
  35. DWORD dwLevel,
  36. LPWSTR pszSourceDir,
  37. LPDWORD pcchSourceDirSize,
  38. LPWSTR pszTargetDir,
  39. LPDWORD pcchTargetDirSize,
  40. DWORD dwFlags
  41. );
  42. //
  43. // If a module is given we need to call into to "correct" the path
  44. // We will first try LoadLibrary on the module, if we can't find the module
  45. // we will look in the driver directory for it
  46. //
  47. if ( pszModule && *pszModule ) {
  48. if ( !(hModule = SplLoadLibraryTheCopyFileModule(pSpool, pszModule)) ||
  49. !((FARPROC)pfn = GetProcAddress(hModule, "GenerateCopyFilePaths")) )
  50. goto Cleanup;
  51. dwSourceDirSize = dwTargetDirSize = MAX_PATH;
  52. #if DBG
  53. #else
  54. try {
  55. #endif
  56. //
  57. // On free builds we do not want spooler to crash
  58. //
  59. if ( ERROR_SUCCESS != pfn(pSpool->pName,
  60. pszDir,
  61. (LPVOID)pSplClientInfo1,
  62. 1,
  63. pszSourceDir,
  64. &dwSourceDirSize,
  65. pszTargetDir,
  66. &dwTargetDirSize,
  67. COPYFILE_FLAG_CLIENT_SPOOLER) )
  68. #if DBG
  69. goto Cleanup;
  70. #else
  71. leave;
  72. #endif
  73. bRet = TRUE;
  74. #if DBG
  75. #else
  76. } except(1) {
  77. }
  78. #endif
  79. if ( !bRet )
  80. goto Cleanup;
  81. } else {
  82. bRet = TRUE;
  83. }
  84. dwSourceDirSize = wcslen(pszSourceDir);
  85. dwTargetDirSize = wcslen(pszTargetDir);
  86. pszSourceDir[dwSourceDirSize] = L'\\';
  87. pszSourceDir[++dwSourceDirSize] = L'\0';
  88. pszTargetDir[dwTargetDirSize] = L'\0';
  89. //
  90. // First find out number of files and size of one long buffer to put
  91. // all filenames. We need to build fully qualified filenames in the source
  92. // directory
  93. //
  94. for ( dwCount = dwLen = 0, p1 = ppszFiles ; *p1 ; p1 += dwTemp, ++dwCount ) {
  95. dwTemp = wcslen(p1) + 1;
  96. dwLen += dwTemp + dwSourceDirSize;
  97. }
  98. pszBuf = (LPWSTR) AllocSplMem(dwLen * sizeof(WCHAR));
  99. ppszFileNames = (LPWSTR *) AllocSplMem(dwCount * sizeof(LPWSTR));
  100. if ( !pszBuf || !ppszFileNames )
  101. goto Cleanup;
  102. for ( p1 = ppszFiles, p2 = pszBuf, dwCount = dwTemp = 0 ;
  103. *p1 ; p1 += wcslen(p1) + 1, ++dwCount ) {
  104. wcscpy(p2, pszSourceDir);
  105. wcscpy(p2 + dwSourceDirSize, p1);
  106. ppszFileNames[dwCount] = p2;
  107. dwTemp += dwSourceDirSize + wcslen(p1) + 1;
  108. p2 = pszBuf + dwTemp;
  109. }
  110. SPLASSERT(dwTemp == dwLen);
  111. bRet = SplCopyNumberOfFiles(pSpool->pName,
  112. ppszFileNames,
  113. dwCount,
  114. pszTargetDir,
  115. &bFilesUpdated);
  116. if ( bFilesUpdated )
  117. (VOID) SplCopyFileEvent(pSpool->hSplPrinter,
  118. pszKey,
  119. COPYFILE_EVENT_FILES_CHANGED);
  120. Cleanup:
  121. if ( hModule )
  122. FreeLibrary(hModule);
  123. FreeSplMem(pszBuf);
  124. FreeSplMem(ppszFileNames);
  125. return bRet;
  126. }
  127. BOOL
  128. CopyFilesUnderAKey(
  129. PWSPOOL pSpool,
  130. LPWSTR pszSubKey,
  131. PSPLCLIENT_INFO_1 pSplClientInfo1
  132. )
  133. {
  134. BOOL bRet = FALSE;
  135. DWORD dwSize, dwLen, dwType, dwNeeded;
  136. WCHAR szSourceDir[MAX_PATH], szTargetDir[MAX_PATH];
  137. LPWSTR pszDir, ppszFiles, pszModule;
  138. pszDir = ppszFiles = pszModule = NULL;
  139. dwSize = sizeof(szSourceDir);
  140. if ( SplGetPrinterDataEx(pSpool->hSplPrinter,
  141. pszSubKey,
  142. L"Directory",
  143. &dwType,
  144. (LPBYTE)szSourceDir,
  145. dwSize,
  146. &dwNeeded) ||
  147. dwType != REG_SZ ||
  148. !(pszDir = AllocSplStr(szSourceDir)) ||
  149. SplGetPrinterDataEx(pSpool->hSplPrinter,
  150. pszSubKey,
  151. L"SourceDir",
  152. &dwType,
  153. (LPBYTE)szSourceDir,
  154. dwSize,
  155. &dwNeeded) ||
  156. dwType != REG_SZ ||
  157. dwNeeded + sizeof(WCHAR) > dwSize ||
  158. SplGetPrinterDataEx(pSpool->hSplPrinter,
  159. pszSubKey,
  160. L"Files",
  161. &dwType,
  162. (LPBYTE)szTargetDir, // Can't pass NULL
  163. 0,
  164. &dwNeeded) != ERROR_MORE_DATA ||
  165. !(ppszFiles = (LPWSTR) AllocSplMem(dwNeeded)) ||
  166. SplGetPrinterDataEx(pSpool->hSplPrinter,
  167. pszSubKey,
  168. L"Files",
  169. &dwType,
  170. (LPBYTE)ppszFiles,
  171. dwNeeded,
  172. &dwNeeded) ||
  173. dwType != REG_MULTI_SZ ) {
  174. goto Cleanup;
  175. }
  176. //
  177. // Module name is optional
  178. //
  179. dwLen = SplGetPrinterDataEx(pSpool->hSplPrinter,
  180. pszSubKey,
  181. L"Module",
  182. &dwType,
  183. (LPBYTE)szTargetDir,
  184. dwSize,
  185. &dwNeeded);
  186. if ( dwLen == ERROR_SUCCESS ) {
  187. if ( dwType != REG_SZ ||
  188. !(pszModule = AllocSplStr(szTargetDir)) ) {
  189. goto Cleanup;
  190. }
  191. } else if ( dwLen != ERROR_FILE_NOT_FOUND ) {
  192. goto Cleanup;
  193. }
  194. dwLen = dwSize;
  195. //
  196. // Target directory we got from the server is relative to print$.
  197. // We need to convert it to a fully qualified path now
  198. //
  199. if ( !SplGetDriverDir(pSpool->hIniSpooler, szTargetDir, &dwLen) )
  200. goto Cleanup;
  201. szTargetDir[dwLen-1] = L'\\';
  202. dwSize -= dwLen * sizeof(WCHAR);
  203. if ( SplGetPrinterDataEx(pSpool->hSplPrinter,
  204. pszSubKey,
  205. L"TargetDir",
  206. &dwType,
  207. (LPBYTE)(szTargetDir + dwLen),
  208. dwSize,
  209. &dwNeeded) ||
  210. dwType != REG_SZ ) {
  211. goto Cleanup;
  212. }
  213. bRet = ProcessACopyFileKey(pSpool,
  214. pszSubKey,
  215. pszModule,
  216. pszDir,
  217. ppszFiles,
  218. szSourceDir,
  219. szTargetDir,
  220. pSplClientInfo1);
  221. Cleanup:
  222. FreeSplStr(pszDir);
  223. FreeSplStr(ppszFiles);
  224. FreeSplStr(pszModule);
  225. return bRet;
  226. }
  227. BOOL
  228. RefreshPrinterCopyFiles(
  229. PWSPOOL pSpool
  230. )
  231. {
  232. DWORD dwNeeded, dwSize = 0, dwLastError;
  233. LPWSTR pszBuf = NULL, pszSubKey;
  234. WCHAR szUserName[MAX_PATH+1], szKey[MAX_PATH];
  235. SPLCLIENT_INFO_1 SplClientInfo;
  236. if ( pSpool->Type != SJ_WIN32HANDLE )
  237. return TRUE;
  238. SYNCRPCHANDLE(pSpool);
  239. SPLASSERT(pSpool->Status & WSPOOL_STATUS_USE_CACHE);
  240. //
  241. // If it is a 3x server it is not going to support the rpc calls we need
  242. // so there is nothing to copy
  243. //
  244. if ( pSpool->bNt3xServer )
  245. return TRUE;
  246. Retry:
  247. dwLastError = SplEnumPrinterKey(pSpool->hSplPrinter,
  248. L"CopyFiles",
  249. pszBuf,
  250. dwSize,
  251. &dwNeeded);
  252. //
  253. // If first time size was not enough we will try once more with dwNeeded
  254. //
  255. if ( dwLastError == ERROR_MORE_DATA &&
  256. dwSize == 0 &&
  257. dwNeeded != 0 ) {
  258. dwSize = dwNeeded;
  259. pszBuf = AllocSplMem(dwSize);
  260. if ( !pszBuf )
  261. goto Cleanup;
  262. goto Retry;
  263. }
  264. //
  265. // If the call failed, or there was no sub key we are done
  266. //
  267. if ( dwLastError != ERROR_SUCCESS )
  268. goto Cleanup;
  269. CopyMemory((LPBYTE)&SplClientInfo,
  270. (LPBYTE)&gSplClientInfo1,
  271. sizeof(SplClientInfo));
  272. SplClientInfo.pMachineName = SplClientInfo.pUserName = NULL;
  273. for ( pszSubKey = pszBuf ; *pszSubKey ; pszSubKey += wcslen(pszSubKey) + 1 ) {
  274. if ( sizeof(szKey)/sizeof(szKey[0])
  275. > wcslen(L"CopyFiles") + wcslen(pszSubKey) ) {
  276. wsprintf(szKey, L"%ws\\%ws", L"CopyFiles", pszSubKey);
  277. CopyFilesUnderAKey(pSpool, szKey, &SplClientInfo);
  278. } else {
  279. SPLASSERT(sizeof(szKey)/sizeof(szKey[0]) >
  280. wcslen(L"CopyFiles") + wcslen(pszSubKey));
  281. }
  282. }
  283. Cleanup:
  284. FreeSplMem(pszBuf);
  285. return dwLastError == ERROR_SUCCESS;
  286. }