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.
 
 
 
 
 
 

583 lines
15 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
All rights reserved.
Module Name:
Network.c
Abstract:
Routines to migrate Win95 network printers to NT via using RunOnce entries
Author:
Muhunthan Sivapragasam (MuhuntS) 18-Aug-1997
Revision History:
--*/
#include "precomp.h"
BOOL bDoNetPrnUpgrade = FALSE;
LPSTR pszNetPrnEntry = NULL;
CHAR szSpool[] = "\\spool\\";
CHAR szMigDll[] = "migrate.dll";
CHAR szRunOnceCount[] = "RunOnceCount";
CHAR szRunOnceCountPath[] = "System\\CurrentControlSet\\control\\Print";
CHAR szRunOnceRegistryPath[] = "Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce";
//
// This is stored in the registry so when network printer upgrade using
// RunOnce key is tries enough times without success we can delete files
//
#define MIN_NETWORK_PRN_RETRIES 5
DWORD dwRunOnceCount = 0;
LPSTR
GetRunOnceValueToSet(
)
/*++
--*/
{
CHAR szPath[MAX_PATH];
DWORD dwLen, dwSize;
LPSTR pszRet = NULL;
dwSize = sizeof(szPath)/sizeof(szPath[0]);
if ( !(dwLen = GetFileNameInSpoolDir(szPath, dwSize, szMigDll)) )
goto Done;
//
// Now build up the RunOnce key which will be set for each user
//
dwSize = strlen("rundll32.exe") + dwLen +
+ strlen("ProcessWin9xNetworkPrinters") + 4;
if ( pszRet = AllocMem(dwSize * sizeof(CHAR)) )
StringCchPrintfA(pszRet, dwSize,
"rundll32.exe %s,ProcessWin9xNetworkPrinters",
szPath);
Done:
return pszRet;
}
VOID
SetupNetworkPrinterUpgrade(
IN LPCSTR pszWorkingDir
)
/*++
Routine Description:
This is called during InitializeSystemNT to setup the upgrade of network
printers
Arguments:
pszWorkingDir : Gives the working directory assigned for printing
Return Value:
None
If everything was setup right bDoNetPrnUpgrade is TRUE, and pszNetPrnEntry
is the value to set in per user registry for RunOnce
--*/
{
CHAR szSource[MAX_PATH], szTarget[MAX_PATH];
DWORD dwSize, dwLen;
//
// First check if the source paths is ok
//
dwLen = strlen(szNetprnFile);
dwSize = sizeof(szTarget)/sizeof(szTarget[0]);
if ( strlen(pszWorkingDir) + dwLen + 2 > dwSize )
return;
//
// Need to make a copy of migrate.dll and netwkprn.txt to
// the %windir%\system32\spool directory
//
StringCchPrintfA(szSource, SIZECHARS(szSource), "%s\\%s", pszWorkingDir, szNetprnFile);
if ( !GetFileNameInSpoolDir(szTarget, dwSize, szNetprnFile) ||
!CopyFileA(szSource, szTarget, FALSE) )
return;
if (!MakeACopyOfMigrateDll( pszWorkingDir ))
{
return;
}
bDoNetPrnUpgrade = (pszNetPrnEntry = GetRunOnceValueToSet()) != NULL;
}
VOID
WriteRunOnceCount(
)
/*++
Routine Description:
This routine is called to write the number of times we need to try the
network printer upgrade
Arguments:
None
Return Value:
None
--*/
{
HKEY hKey;
DWORD dwSize;
if ( dwRunOnceCount == 0 )
return;
//
// We will try number of user + MIN_NETWORK_PRN_RETRIES till we succeed
//
dwRunOnceCount += MIN_NETWORK_PRN_RETRIES;
if ( ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE,
szRunOnceCountPath,
0,
KEY_WRITE,
&hKey) )
return;
dwSize = sizeof(dwRunOnceCount);
RegSetValueExA(hKey,
szRunOnceCount,
0,
REG_DWORD,
(LPBYTE)&dwRunOnceCount,
dwSize);
RegCloseKey(hKey);
}
BOOL
ProcessNetPrnUpgradeForUser(
HKEY hKeyUser
)
/*++
Routine Description:
This is called during MigrateUserNT to handle network printer upgrade
for the user
Arguments:
hKeyUser : Handle to the user registry key
Return Value:
Return TRUE on success, and FALSE else
--*/
{
HKEY hKey = NULL;
DWORD dwLastError;
dwLastError = RegCreateKeyExA(hKeyUser,
szRunOnceRegistryPath,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL);
if ( dwLastError == ERROR_SUCCESS ) {
dwLastError = RegSetValueExA(hKey,
"Printing Migration",
0,
REG_SZ,
pszNetPrnEntry,
( strlen(pszNetPrnEntry) + 1 )
* sizeof(CHAR));
#ifdef VERBOSE
if ( dwLastError == ERROR_SUCCESS )
DebugMsg("Wrote %s to %s", pszNetPrnEntry, szRunOnceRegistryPath);
#endif
}
if ( hKey )
RegCloseKey(hKey);
if ( dwLastError ) {
SetLastError(dwLastError);
return FALSE;
}
return TRUE;
}
VOID
DecrementRunOnceCount(
IN DWORD dwDiff,
IN BOOL bResetRunOnceForUser
)
/*++
Routine Description:
Called after once network printer upgrade is called when user logged in,
so we can decrement the retry count
When ref count reaches 0 we then we can delete the files
Arguments:
dwDiff : Value by which ref count should be decremented
bResetRunOnceForUser : We need to set RunOnce key again for the user
Return Value:
None
--*/
{
HKEY hKey;
DWORD dwSize, dwCount, dwType;
CHAR szPath[MAX_PATH];
if ( ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE,
szRunOnceCountPath,
0,
KEY_ALL_ACCESS,
&hKey) )
return;
dwSize = sizeof(dwCount);
if ( ERROR_SUCCESS == RegQueryValueExA(hKey, szRunOnceCount, 0, &dwType,
(LPBYTE)&dwCount, &dwSize) ) {
dwCount -= dwDiff;
if ( dwCount ) {
RegSetValueExA(hKey,
szRunOnceCount,
0,
REG_DWORD,
(LPBYTE)&dwCount,
dwSize);
if ( bResetRunOnceForUser &&
(pszNetPrnEntry = GetRunOnceValueToSet()) ) {
ProcessNetPrnUpgradeForUser(HKEY_CURRENT_USER);
FreeMem(pszNetPrnEntry);
pszNetPrnEntry = NULL;
#ifdef VERBOSE
DebugMsg("Processing network/shared printers failed. Will try next time user logs in.");
#endif
}
} else {
dwSize = sizeof(szPath)/sizeof(szPath[0]);
RegDeleteValueA(hKey, szRunOnceCount);
if ( GetFileNameInSpoolDir(szPath, dwSize, szMigDll) )
DeleteFileA(szPath);
if ( GetFileNameInSpoolDir(szPath, dwSize, szNetprnFile) )
DeleteFileA(szPath);
DebugMsg("Giving up on setting network/shared printers");
}
}
RegCloseKey(hKey);
}
BOOL
AddNetworkPrinter(
IN LPPRINTER_INFO_2A pPrinterInfo2
)
/*++
Routine Description:
This is called to add a windows 9x network printer. We will first try to
make a conenction and if that fails we will add a masq. printer
Arguments:
pPrinterInfo2 : Pointer to printer info 2 of the printer
Return Value:
TRUE on success, FALSE else
--*/
{
BOOL bRet = FALSE;
LPSTR pszName, psz;
HANDLE hPrinter = NULL;
pszName = pPrinterInfo2->pPortName;
if ( !OpenPrinterA(pszName, &hPrinter, NULL) ) {
if ( psz = ErrorMsg() ) {
DebugMsg("OpenPrinter failed for %s. %s", pszName, psz);
FreeMem(psz);
psz = NULL;
}
goto Done;
}
//
// Try to make a printer connection. If that fails with some error
// other than unknown driver create a masq printer
//
if ( AddPrinterConnectionA(pszName) ) {
if ( pPrinterInfo2->Attributes & PRINTER_ATTRIBUTE_DEFAULT )
SetDefaultPrinterA(pszName);
bRet = TRUE;
goto Done;
}
if ( GetLastError() == ERROR_UNKNOWN_PRINTER_DRIVER ) {
if ( psz = ErrorMsg() ) {
DebugMsg("AddPrinterConnection failed for %s. %s", pszName, psz);
FreeMem(psz);
psz = NULL;
}
goto Done;
}
ClosePrinter(hPrinter);
//
// Masc. printers should have port name, printer name both saying
// \\server\share. Otherwise printui gets confused and does not refresh
// server status correctly (this is since printui has to poll for masc.
// printers)
//
// So we need to fixup PrinterInfo2 temporarily
//
psz = pPrinterInfo2->pPrinterName;
pPrinterInfo2->pPrinterName = pPrinterInfo2->pPortName;
if ( hPrinter = AddPrinterA(NULL, 2, (LPBYTE)pPrinterInfo2) ) {
if ( pPrinterInfo2->Attributes & PRINTER_ATTRIBUTE_DEFAULT )
SetDefaultPrinterA(pPrinterInfo2->pPrinterName);
pPrinterInfo2->pPrinterName = psz;
bRet = TRUE;
goto Done;
}
pPrinterInfo2->pPrinterName = psz;
if ( psz = ErrorMsg() ) {
DebugMsg("AddPrinterA failed for %s. %s", pszName, psz);
FreeMem(psz);
psz = NULL;
}
Done:
if ( hPrinter )
ClosePrinter(hPrinter);
return bRet;
}
BOOL
SharePrinter(
IN LPSTR pszPrinterName
)
/*++
Routine Description:
This is called to share a printer when the user logs in for the first time
to NT. Printers can not be shared during GUI setup because we are not on
the network yet.
Arguments:
pszPrinterName : Printer name
Return Value:
TRUE on success, FALSE else
--*/
{
BOOL bRet = FALSE;
DWORD dwNeeded;
HANDLE hPrinter = NULL;
LPBYTE pBuf = NULL;
LPSTR psz;
PRINTER_DEFAULTS PrinterDflts = { NULL, NULL, PRINTER_ALL_ACCESS };
if ( !OpenPrinterA(pszPrinterName, &hPrinter, &PrinterDflts) ) {
if ( psz = ErrorMsg() ) {
DebugMsg("OpenPrinterA failed for %s. %s", pszPrinterName, psz);
FreeMem(psz);
psz = NULL;
}
goto Cleanup;
}
GetPrinterA(hPrinter, 2, NULL, 0, &dwNeeded);
if ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
!(pBuf = AllocMem(dwNeeded)) ||
!GetPrinterA(hPrinter, 2, pBuf, dwNeeded, &dwNeeded) ) {
if ( psz = ErrorMsg() ) {
DebugMsg("GetPrinterA failed for %s. %s", pszPrinterName, psz);
FreeMem(psz);
psz = NULL;
}
goto Cleanup;
}
((LPPRINTER_INFO_2A)pBuf)->Attributes |= PRINTER_ATTRIBUTE_SHARED;
bRet = SetPrinterA(hPrinter, 2, pBuf, 0);
if ( !bRet && (psz = ErrorMsg()) ) {
DebugMsg("OpenPrinterA failed for %s. %s", pszPrinterName, psz);
FreeMem(psz);
psz = NULL;
}
Cleanup:
if ( hPrinter )
ClosePrinter(hPrinter);
FreeMem(pBuf);
return bRet;
}
VOID
ProcessWin9xNetworkPrinters(
)
/*++
Routine Description:
This is called the first time the user logs in to create network printer
connections/masq printers.
Reads the Win9x printing configuration we stored in the text file
so that printing components can be upgraded
Arguments:
ppPrinterNode : Gives the list of netowrk printers on Win9x
Return Value:
TRUE on succesfully reading the config information, FALSE else
--*/
{
BOOL bFail = FALSE, bSuccess = TRUE;
HANDLE hFile = INVALID_HANDLE_VALUE;
CHAR c, szFile[MAX_PATH], szLine[2*MAX_PATH];
DWORD dwSize, dwLen;
PRINTER_INFO_2A PrinterInfo2;
#ifdef VERBOSE
DebugMsg("ProcessWin9xNetworkPrinters called");
#endif
//
// If file is not found quit
//
dwSize = sizeof(szFile)/sizeof(szFile[0]);
if ( !GetFileNameInSpoolDir(szFile, dwSize, szNetprnFile) ) {
DebugMsg("ProcessWin9xNetworkPrinters: GetFileNameInSpoolDir failed\n");
goto Cleanup;
}
hFile = CreateFileA(szFile,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if ( hFile == INVALID_HANDLE_VALUE ) {
DebugMsg("ProcessWin9xNetworkPrinters: CreateFile failed with %d for %s",
GetLastError(), szLine);
goto Cleanup;
}
//
// Read the printer info
//
if ( My_fgets(szLine, dwSize, hFile) == NULL ||
strncmp(szLine, "[Printers]", strlen("[Printers]")) )
goto Cleanup;
do {
c = (CHAR) My_fgetc(hFile);
if ( c == EOF || c == '\n' )
break; // Normal exit
if ( c != 'S' || !My_ungetc(hFile) )
goto Cleanup;
ZeroMemory(&PrinterInfo2, sizeof(PrinterInfo2));
ReadPrinterInfo2(hFile, &PrinterInfo2, &bFail);
if ( bFail )
goto Cleanup;
//
// If this was a network printer on Win9x it needs to be added as a
// connection or as a masc printer
//
if ( PrinterInfo2.Attributes & PRINTER_ATTRIBUTE_NETWORK ) {
if ( !AddNetworkPrinter(&PrinterInfo2) && bSuccess )
bSuccess = FALSE;
} else if ( PrinterInfo2.Attributes & PRINTER_ATTRIBUTE_SHARED ) {
if ( !SharePrinter(PrinterInfo2.pPrinterName) && bSuccess )
bSuccess = FALSE;
}
} while ( !bFail );
Cleanup:
if ( hFile != INVALID_HANDLE_VALUE )
CloseHandle(hFile);
if ( bSuccess && !bFail )
DecrementRunOnceCount(MIN_NETWORK_PRN_RETRIES, FALSE);
else
DecrementRunOnceCount(1, TRUE);
}