368 lines
10 KiB
C
368 lines
10 KiB
C
/*++
|
|
|
|
|
|
Copyright (c) 1994 - 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Files.c
|
|
|
|
Abstract:
|
|
|
|
This module contains routines for copying files specified under the
|
|
CopyFiles key of a print queue
|
|
|
|
Author:
|
|
|
|
Muhunthan Sivapragasam (Muhunthan Sivapragasam) Nov-27-96
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
|
|
WCHAR *szSpoolDirectory = L"\\spool";
|
|
|
|
extern SPLCLIENT_INFO_1 gSplClientInfo1;
|
|
|
|
#define PRINTER_ENUM_KEY_SIZE 400
|
|
|
|
|
|
BOOL
|
|
ProcessACopyFileKey(
|
|
PWSPOOL pSpool,
|
|
LPWSTR pszKey,
|
|
LPWSTR pszModule,
|
|
LPWSTR pszDir,
|
|
LPWSTR ppszFiles,
|
|
LPWSTR pszSourceDir,
|
|
LPWSTR pszTargetDir,
|
|
PSPLCLIENT_INFO_1 pSplClientInfo1
|
|
)
|
|
{
|
|
BOOL bRet = FALSE, bFilesUpdated;
|
|
DWORD dwLen, dwCount, dwTemp, dwSourceDirSize, dwTargetDirSize;
|
|
LPWSTR *ppszFileNames = NULL, pszBuf = NULL, p1, p2;
|
|
HINSTANCE hModule = NULL;
|
|
DWORD (*pfn)(LPWSTR pszPrinterName,
|
|
LPCWSTR pszDirectory,
|
|
LPBYTE pSplClientInfo,
|
|
DWORD dwLevel,
|
|
LPWSTR pszSourceDir,
|
|
LPDWORD pcchSourceDirSize,
|
|
LPWSTR pszTargetDir,
|
|
LPDWORD pcchTargetDirSize,
|
|
DWORD dwFlags
|
|
);
|
|
|
|
//
|
|
// If a module is given we need to call into to "correct" the path
|
|
// We will first try LoadLibrary on the module, if we can't find the module
|
|
// we will look in the driver directory for it
|
|
//
|
|
if ( pszModule && *pszModule ) {
|
|
|
|
if ( !(hModule = SplLoadLibraryTheCopyFileModule(pSpool, pszModule)) ||
|
|
!((FARPROC)pfn = GetProcAddress(hModule, "GenerateCopyFilePaths")) )
|
|
goto Cleanup;
|
|
|
|
dwSourceDirSize = dwTargetDirSize = MAX_PATH;
|
|
|
|
#if DBG
|
|
#else
|
|
try {
|
|
#endif
|
|
|
|
//
|
|
// On free builds we do not want spooler to crash
|
|
//
|
|
if ( ERROR_SUCCESS != pfn(pSpool->pName,
|
|
pszDir,
|
|
(LPVOID)pSplClientInfo1,
|
|
1,
|
|
pszSourceDir,
|
|
&dwSourceDirSize,
|
|
pszTargetDir,
|
|
&dwTargetDirSize,
|
|
COPYFILE_FLAG_CLIENT_SPOOLER) )
|
|
#if DBG
|
|
goto Cleanup;
|
|
#else
|
|
leave;
|
|
#endif
|
|
|
|
bRet = TRUE;
|
|
#if DBG
|
|
#else
|
|
} except(1) {
|
|
}
|
|
#endif
|
|
|
|
if ( !bRet )
|
|
goto Cleanup;
|
|
|
|
} else {
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
dwSourceDirSize = wcslen(pszSourceDir);
|
|
dwTargetDirSize = wcslen(pszTargetDir);
|
|
|
|
pszSourceDir[dwSourceDirSize] = L'\\';
|
|
|
|
pszSourceDir[++dwSourceDirSize] = L'\0';
|
|
pszTargetDir[dwTargetDirSize] = L'\0';
|
|
|
|
|
|
//
|
|
// First find out number of files and size of one long buffer to put
|
|
// all filenames. We need to build fully qualified filenames in the source
|
|
// directory
|
|
//
|
|
for ( dwCount = dwLen = 0, p1 = ppszFiles ; *p1 ; p1 += dwTemp, ++dwCount ) {
|
|
|
|
dwTemp = wcslen(p1) + 1;
|
|
dwLen += dwTemp + dwSourceDirSize;
|
|
}
|
|
|
|
pszBuf = (LPWSTR) AllocSplMem(dwLen * sizeof(WCHAR));
|
|
ppszFileNames = (LPWSTR *) AllocSplMem(dwCount * sizeof(LPWSTR));
|
|
|
|
if ( !pszBuf || !ppszFileNames )
|
|
goto Cleanup;
|
|
|
|
for ( p1 = ppszFiles, p2 = pszBuf, dwCount = dwTemp = 0 ;
|
|
*p1 ; p1 += wcslen(p1) + 1, ++dwCount ) {
|
|
|
|
wcscpy(p2, pszSourceDir);
|
|
wcscpy(p2 + dwSourceDirSize, p1);
|
|
|
|
ppszFileNames[dwCount] = p2;
|
|
|
|
dwTemp += dwSourceDirSize + wcslen(p1) + 1;
|
|
p2 = pszBuf + dwTemp;
|
|
}
|
|
|
|
SPLASSERT(dwTemp == dwLen);
|
|
|
|
bRet = SplCopyNumberOfFiles(pSpool->pName,
|
|
ppszFileNames,
|
|
dwCount,
|
|
pszTargetDir,
|
|
&bFilesUpdated);
|
|
|
|
if ( bFilesUpdated )
|
|
(VOID) SplCopyFileEvent(pSpool->hSplPrinter,
|
|
pszKey,
|
|
COPYFILE_EVENT_FILES_CHANGED);
|
|
Cleanup:
|
|
if ( hModule )
|
|
FreeLibrary(hModule);
|
|
|
|
FreeSplMem(pszBuf);
|
|
FreeSplMem(ppszFileNames);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CopyFilesUnderAKey(
|
|
PWSPOOL pSpool,
|
|
LPWSTR pszSubKey,
|
|
PSPLCLIENT_INFO_1 pSplClientInfo1
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
DWORD dwSize, dwLen, dwType, dwNeeded;
|
|
WCHAR szSourceDir[MAX_PATH], szTargetDir[MAX_PATH];
|
|
LPWSTR pszDir, ppszFiles, pszModule;
|
|
|
|
pszDir = ppszFiles = pszModule = NULL;
|
|
|
|
dwSize = sizeof(szSourceDir);
|
|
|
|
if ( SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"Directory",
|
|
&dwType,
|
|
(LPBYTE)szSourceDir,
|
|
dwSize,
|
|
&dwNeeded) ||
|
|
dwType != REG_SZ ||
|
|
!(pszDir = AllocSplStr(szSourceDir)) ||
|
|
SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"SourceDir",
|
|
&dwType,
|
|
(LPBYTE)szSourceDir,
|
|
dwSize,
|
|
&dwNeeded) ||
|
|
dwType != REG_SZ ||
|
|
dwNeeded + sizeof(WCHAR) > dwSize ||
|
|
SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"Files",
|
|
&dwType,
|
|
(LPBYTE)szTargetDir, // Can't pass NULL
|
|
0,
|
|
&dwNeeded) != ERROR_MORE_DATA ||
|
|
!(ppszFiles = (LPWSTR) AllocSplMem(dwNeeded)) ||
|
|
SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"Files",
|
|
&dwType,
|
|
(LPBYTE)ppszFiles,
|
|
dwNeeded,
|
|
&dwNeeded) ||
|
|
dwType != REG_MULTI_SZ ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Module name is optional
|
|
//
|
|
dwLen = SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"Module",
|
|
&dwType,
|
|
(LPBYTE)szTargetDir,
|
|
dwSize,
|
|
&dwNeeded);
|
|
|
|
if ( dwLen == ERROR_SUCCESS ) {
|
|
|
|
if ( dwType != REG_SZ ||
|
|
!(pszModule = AllocSplStr(szTargetDir)) ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
} else if ( dwLen != ERROR_FILE_NOT_FOUND ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwLen = dwSize;
|
|
//
|
|
// Target directory we got from the server is relative to print$.
|
|
// We need to convert it to a fully qualified path now
|
|
//
|
|
if ( !SplGetDriverDir(pSpool->hIniSpooler, szTargetDir, &dwLen) )
|
|
goto Cleanup;
|
|
|
|
szTargetDir[dwLen-1] = L'\\';
|
|
|
|
dwSize -= dwLen * sizeof(WCHAR);
|
|
if ( SplGetPrinterDataEx(pSpool->hSplPrinter,
|
|
pszSubKey,
|
|
L"TargetDir",
|
|
&dwType,
|
|
(LPBYTE)(szTargetDir + dwLen),
|
|
dwSize,
|
|
&dwNeeded) ||
|
|
dwType != REG_SZ ) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
bRet = ProcessACopyFileKey(pSpool,
|
|
pszSubKey,
|
|
pszModule,
|
|
pszDir,
|
|
ppszFiles,
|
|
szSourceDir,
|
|
szTargetDir,
|
|
pSplClientInfo1);
|
|
|
|
Cleanup:
|
|
FreeSplStr(pszDir);
|
|
FreeSplStr(ppszFiles);
|
|
FreeSplStr(pszModule);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
BOOL
|
|
RefreshPrinterCopyFiles(
|
|
PWSPOOL pSpool
|
|
)
|
|
{
|
|
DWORD dwNeeded, dwSize = 0, dwLastError;
|
|
LPWSTR pszBuf = NULL, pszSubKey;
|
|
WCHAR szUserName[MAX_PATH+1], szKey[MAX_PATH];
|
|
SPLCLIENT_INFO_1 SplClientInfo;
|
|
|
|
if ( pSpool->Type != SJ_WIN32HANDLE )
|
|
return TRUE;
|
|
|
|
SYNCRPCHANDLE(pSpool);
|
|
|
|
SPLASSERT(pSpool->Status & WSPOOL_STATUS_USE_CACHE);
|
|
|
|
//
|
|
// If it is a 3x server it is not going to support the rpc calls we need
|
|
// so there is nothing to copy
|
|
//
|
|
if ( pSpool->bNt3xServer )
|
|
return TRUE;
|
|
|
|
Retry:
|
|
|
|
dwLastError = SplEnumPrinterKey(pSpool->hSplPrinter,
|
|
L"CopyFiles",
|
|
pszBuf,
|
|
dwSize,
|
|
&dwNeeded);
|
|
|
|
//
|
|
// If first time size was not enough we will try once more with dwNeeded
|
|
//
|
|
if ( dwLastError == ERROR_MORE_DATA &&
|
|
dwSize == 0 &&
|
|
dwNeeded != 0 ) {
|
|
|
|
dwSize = dwNeeded;
|
|
pszBuf = AllocSplMem(dwSize);
|
|
|
|
if ( !pszBuf )
|
|
goto Cleanup;
|
|
|
|
goto Retry;
|
|
}
|
|
|
|
//
|
|
// If the call failed, or there was no sub key we are done
|
|
//
|
|
if ( dwLastError != ERROR_SUCCESS )
|
|
goto Cleanup;
|
|
|
|
CopyMemory((LPBYTE)&SplClientInfo,
|
|
(LPBYTE)&gSplClientInfo1,
|
|
sizeof(SplClientInfo));
|
|
|
|
SplClientInfo.pMachineName = SplClientInfo.pUserName = NULL;
|
|
|
|
for ( pszSubKey = pszBuf ; *pszSubKey ; pszSubKey += wcslen(pszSubKey) + 1 ) {
|
|
|
|
if ( sizeof(szKey)/sizeof(szKey[0])
|
|
> wcslen(L"CopyFiles") + wcslen(pszSubKey) ) {
|
|
|
|
wsprintf(szKey, L"%ws\\%ws", L"CopyFiles", pszSubKey);
|
|
CopyFilesUnderAKey(pSpool, szKey, &SplClientInfo);
|
|
} else {
|
|
|
|
SPLASSERT(sizeof(szKey)/sizeof(szKey[0]) >
|
|
wcslen(L"CopyFiles") + wcslen(pszSubKey));
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
FreeSplMem(pszBuf);
|
|
|
|
return dwLastError == ERROR_SUCCESS;
|
|
}
|