rdpwsx!RDPPNUTL_RemoveAllTSPrinters函数分析

0: kd> p

04:47:22.343 898061FC.E1757188 TShrSRV: ICASRV callback table saved

rdpwsx!WsxInitialize+0x65:

001b:70fbe182 e86c1a0000 call rdpwsx!RDPPNUTL_RemoveAllTSPrinters (70fbfbf3)

0: kd> p

04:47:22.359 898061FC.E1757188 RDPPNUTL: RDPPNUTL_RemoveAllTSPrinters entry

04:47:22.359 898061FC.E1757188 RDPPNUTL: Loading registry settings.

04:47:22.359 898061FC.E1757188 RDPPNUTL: Failed to read spooler timeout value.: 00000002.

04:47:22.359 898061FC.E1757188 RDPPNUTL: Enter WaitForSpoolerToStart.

04:47:23.359 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

AudioSrv: pid=972

WIARPC:Exception 0x6ba calling WIA RPC server

04:47:25.359 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:26.359 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:27.359 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:28.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:29.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:30.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:30.937 896CEADC.E174F1E8 TERMSRV: -|--------------------------------------------|-

04:47:30.953 896CEADC.E174F1E8 TERMSRV: Client SPN: NT AUTHORITY\SYSTEM

04:47:30.968 896CEADC.E174F1E8 TERMSRV: Authentication level: RPC_C_AUTHN_LEVEL_PKT_PRIVACY

04:47:30.968 896CEADC.E174F1E8 TERMSRV: Authentication service: RPC_C_AUTHN_WINNT

04:47:30.968 896CEADC.E174F1E8 TERMSRV: -|--------------------------------------------|-

04:47:30.968 8976078C.E1738DE8 TERMSRV: -|--------------------------------------------|-

04:47:30.968 8976078C.E1738DE8 TERMSRV: Client SPN: NT AUTHORITY\SYSTEM

04:47:30.968 8976078C.E1738DE8 TERMSRV: Authentication level: RPC_C_AUTHN_LEVEL_PKT_PRIVACY

04:47:30.968 8976078C.E1738DE8 TERMSRV: Authentication service: RPC_C_AUTHN_WINNT

04:47:30.968 8976078C.E1738DE8 TERMSRV: -|--------------------------------------------|-

04:47:31.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

WARNING: This break is not a step/trace completion.

The last command has been cleared to prevent

accidental continuation of this unrelated event.

Check the event, location and thread before resuming.

Break instruction exception - code 80000003 (first chance)

*******************************************************************************

* *

* You are seeing this message because you pressed either *

* CTRL+C (if you run console kernel debugger) or, *

* CTRL+BREAK (if you run GUI kernel debugger), *

* on your debugger machine's keyboard. *

* *

* THIS IS NOT A BUG OR A SYSTEM CRASH *

* *

* If you did not intend to break into the debugger, press the "g" key, then *

* press the "Enter" key now. This message might immediately reappear. If it *

* does, press "g" and "Enter" again. *

* *

*******************************************************************************

nt!RtlpBreakWithStatusInstruction:

80ae0d1c cc int 3

0: kd> g

04:47:32.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:33.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:34.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:35.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:36.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

456.1144> AUTOENRL: RegisterAutoEnrollmentProcessing exiting with error: (0x80004004)

00000:Ageint(1):Couldn't turn CSC ON!!!!!!!!!

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

04:47:37.203 896CEADC.E174F1E8 TERMSRV: -|--------------------------------------------|-

04:47:37.218 896CEADC.E174F1E8 TERMSRV: Client SPN: NT AUTHORITY\SYSTEM

04:47:37.218 896CEADC.E174F1E8 TERMSRV: Authentication level: RPC_C_AUTHN_LEVEL_PKT_PRIVACY

04:47:37.218 896CEADC.E174F1E8 TERMSRV: Authentication service: RPC_C_AUTHN_WINNT

04:47:37.218 896CEADC.E174F1E8 TERMSRV: -|--------------------------------------------|-

04:47:37.218 896CEADC.E174F1E8 TERMSRV: WinStationQueryInformation LogonId=0, Class=6

04:47:37.218 896CEADC.E174F1E8 TERMSRV: RpcCheckClientAccess, AccessCheckAndAuditAlarm(0) returned no error

04:47:37.218 896CEADC.E174F1E8 TERMSRV: WinStationQueryInformation LogonId=0, Class=6, Status=0x0

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

04:47:37.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:38.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:39.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:40.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:41.375 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

00000:Ageint(1):Couldn't turn CSC ON!!!!!!!!!

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

MSV1_0.dll CRITICAL SpAcceptCredentials: Collision from NlpFindActiveLogon for 0:0x3e4

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

04:47:42.390 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:42.390 898061FC.E1757188 RDPPNUTL: Exit WaitForSpoolerToStart.

WINMM(p456:t460): ClientUpdatePnpInfo: warning: called in winlogon before logged on

WINMM(p456:t472): ClientUpdatePnpInfo: warning: called in winlogon before logged on

SENS RegQueryValueEx(SENS_DEBUG_LEVEL) failed with 0x2

05B0

TftpdServiceMain: Parameters...

Debug flags : 0x000F000F

Hash table size : 256 buckets

Buffer low water-mark : 5 buffers

Buffer high water-mark : 256 buffers

Max retries : 10 attempts

Root directory : \tftpdroot\

Valid client mask : *.*.*.*

Valid read file mask : *

Valid master mask : *.*.*.*

Valid write file mask : *

SENS -3565781 Started successfully.

05B0 TftpdIoInitializeSocketContext(socket = master): TID = <0.0.0.0:69>.

0604 TftpdIoReadNotification(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 00000000, socket = master).

0604 TftpdIoAllocateBuffer(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 004548A8).

0604 TftpdIoPostReceiveBuffer(buffer = 00000000, socket = master).

0604 TftpdIoAllocateBuffer(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 00454B20).

0604 TftpdIoPostReceiveBuffer(buffer = 00000000, socket = master).

0604 TftpdIoAllocateBuffer(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 00454D98).

0604 TftpdIoPostReceiveBuffer(buffer = 00000000, socket = master).

0604 TftpdIoAllocateBuffer(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 00455010).

0604 TftpdIoPostReceiveBuffer(buffer = 00000000, socket = master).

0604 TftpdIoAllocateBuffer(socket = master).

0604 TftpdIoPostReceiveBuffer(buffer = 00455288).

05B0 TftpdServiceMain(): Service running.

TftpdServiceMain(): Service running.Debug flags: 0x000F000F

04:47:42.687 898061FC.E1757188 RDPPNUTL: First EnumPrinters succeeded.

04:47:42.687 898061FC.E1757188 RDPPNUTL: DeleteTSPrinters entry

04:47:42.687 898061FC.E1757188 RDPPNUTL: DeleteTSPrinters exit

04:47:42.687 898061FC.E1757188 TShrSRV: RDPPNUTL_RemoveAllTSPrinters exit

04:47:42.687 898061FC.E1757188 TShrSRV: TSrvMainThread created

D:\srv03rtm\termsrv>grep "RDPPNUTL_RemoveAllTSPrinters entry" -nr D:\srv03rtm\termsrv

D:\srv03rtm\termsrv/rdpwsx/rdpex/rdppnutl.c:113: TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: RDPPNUTL_RemoveAllTSPrinters entry\n"));

04:47:22.359 898061FC.E1757188 RDPPNUTL: Loading registry settings.

void

LoadRDPPNUTLRegistrySettings()

{

HKEY regKey;

DWORD dwResult;

DWORD type;

DWORD sz;

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Loading registry settings.\n"));

//

// Open the registry key.

//

dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, DEVICERDR_REG_NAME,

0, KEY_READ, &regKey);

if (dwResult == ERROR_SUCCESS) {

#define DEVICERDR_REG_NAME REG_CONTROL_TSERVER L"\\AddIns\\Terminal Server Redirector"

#define DEVICERDR_REG_NAME_A REG_CONTROL_TSERVER_A "\\AddIns\\Terminal Server Redirector"

/*

* Device Redirection Values

*/

#define DEVICERDR_SESSIONID L"TSSessionID"

#define DEVICERDR_SESSIONID_A "TSSessionID"

#define DEVICERDR_WAITFORSPOOLTIMEOUT L"WaitForSpoolerTimeOut"

#define DEVICERDR_WAITFORSPOOLTIMEOUT_A "WaitForSpoolerTimeOut"

if (dwResult == ERROR_SUCCESS) {

//

// Read the "wait for spooler" timeout value.

//

sz = sizeof(SpoolerServiceTimeout);

dwResult = RegQueryValueEx(

regKey,

DEVICERDR_WAITFORSPOOLTIMEOUT,

NULL,

&type,

(PBYTE)&SpoolerServiceTimeout,

&sz

);

if (dwResult != ERROR_SUCCESS){

TRACE((DEBUG_TSHRSRV_WARN,

"RDPPNUTL: Failed to read spooler timeout value.: %08X.\n",

dwResult));

}

else {

TRACE((DEBUG_TSHRSRV_WARN,

"RDPPNUTL: Spooler timeout value is %ld.\n",

SpoolerServiceTimeout));

}

04:47:22.359 898061FC.E1757188 RDPPNUTL: Failed to read spooler timeout value.: 00000002.

DWORD

RDPPNUTL_RemoveAllTSPrinters()

{

//

// Load registry settings for this module.

//

LoadRDPPNUTLRegistrySettings();

//

// Wait until the spooler has finished initializing.

//

status = WaitForSpoolerToStart();

if (status != ERROR_SUCCESS) {

TRACE((

DEBUG_TSHRSRV_DEBUG,

"RDPPNUTL: RDPPNUTL_RemoveAllTSPrinters exiting because spooler failed to start.\n"

));

return status;

}

WaitForSpoolerToStart rdppnutl.c (termsrv\rdpwsx\rdpex) 133

DWORD

WaitForSpoolerToStart()

/*++

Routine Description:

Waits until the spooler finishes initializing or until a timeout period

elapses.

Arguments:

Return Value:

Returns ERROR_SUCCESS if the spooler successfully initialized. Otherwise,

an error code is returned.

--*/

{

SC_HANDLE scManager = NULL;

SC_HANDLE hService = NULL;

DWORD result = ERROR_SUCCESS;

SERVICE_STATUS serviceStatus;

DWORD i;

QUERY_SERVICE_CONFIG *pServiceConfig = NULL;

DWORD bufSize;

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Enter WaitForSpoolerToStart.\n"));

//

// Open the service control manager.

//

scManager = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);

if (scManager == NULL) {

result = GetLastError();

TRACE((DEBUG_TSHRSRV_ERROR,"RDPPNUTL: OpenSCManager failed with %08X.\n",

result));

goto CleanUpAndExit;

}

//

// Open the spooler service.

//

hService = OpenService(scManager, SPOOLER, SERVICE_ALL_ACCESS);

if (hService == NULL) {

result = GetLastError();

TRACE((DEBUG_TSHRSRV_ERROR,

"RDPPNUTL: OpenService on spooler failed with %08X.\n",

result));

goto CleanUpAndExit;

}

//

// If the spooler is currently running, that is all we need to know.

//

if (!QueryServiceStatus(hService, &serviceStatus)) {

result = GetLastError();

TRACE((DEBUG_TSHRSRV_ERROR,

"RDPPNUTL: QueryServiceStatus on spooler failed with %08X.\n",

result));

goto CleanUpAndExit;

}

else if (serviceStatus.dwCurrentState == SERVICE_RUNNING) {

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Spooler is running.\n"));

result = ERROR_SUCCESS;

goto CleanUpAndExit;

}

//

// Size the spooler service query configuration buffer. This API should

// fail with ERROR_INSUFFICIENT_BUFFER, so we can get the size of the

// buffer before we call the function with real parameters.

//

if (!QueryServiceConfig(hService, NULL, 0, &bufSize) &&

(GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {

pServiceConfig = (QUERY_SERVICE_CONFIG *)TSHeapAlloc(

HEAP_ZERO_MEMORY,

bufSize,

TS_HTAG_TSS_SPOOLERINFO

);

if (pServiceConfig == NULL) {

TRACE((DEBUG_TSHRSRV_ERROR,"RDPPNUTL: ALLOCMEM failed. Error: %08X.\n", GetLastError()));

result = ERROR_OUTOFMEMORY;

goto CleanUpAndExit;

}

}

else {

TRACE((DEBUG_TSHRSRV_ERROR,"RDPPNUTL: QueryServiceConfig unexpected return.\n"));

result = E_UNEXPECTED;

goto CleanUpAndExit;

}

//

// Get the spooler's configuration information.

//

if (!QueryServiceConfig(hService, pServiceConfig, bufSize, &bufSize)) {

TRACE((DEBUG_TSHRSRV_ERROR,"RDPPNUTL: QueryServiceConfig failed: %08X.\n",

GetLastError()));

result = GetLastError();

goto CleanUpAndExit;

}

//

// If the spooler is not automatically configured to start on demand or

// automatically on system start then that is all we need to know.

//

if (pServiceConfig->dwStartType != SERVICE_AUTO_START) {

TRACE((DEBUG_TSHRSRV_WARN,"RDPPNUTL: Spooler not configured to start.\n"));

result = E_FAIL;

goto CleanUpAndExit;

}

//

// Poll the service status until we timeout or until the spooler

// starts.

//

for (i=0; (i<SpoolerServiceTimeout) &&
(serviceStatus.dwCurrentState != SERVICE_RUNNING); i++) {

//
// Sleep for a sec.
//
Sleep(1000);

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Spooler is still initializing.\n"));

//

// Try again.

//

if (!QueryServiceStatus(hService, &serviceStatus)) {

result = GetLastError();

TRACE((DEBUG_TSHRSRV_ERROR,

"RDPPNUTL: QueryServiceStatus on spooler failed with %08X.\n",

result));

goto CleanUpAndExit;

}

}

//

// Sucess if the spooler is now running.

//

if (serviceStatus.dwCurrentState == SERVICE_RUNNING) {

result = ERROR_SUCCESS;

}

else {

TRACE((DEBUG_TSHRSRV_WARN,

"RDPPNUTL: Spooler is not running after a timeout or error.\n")

);

result = E_FAIL;

}

CleanUpAndExit:

if (pServiceConfig != NULL) {

TSHeapFree(pServiceConfig);

}

if (scManager != NULL) {

CloseServiceHandle(scManager);

}

if (hService != NULL) {

CloseServiceHandle(hService);

}

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Exit WaitForSpoolerToStart.\n"));

return result;

}

解析:45秒

0: kd> x rdpwsx!SpoolerServiceTimeout

70fcf5c0 rdpwsx!SpoolerServiceTimeout = 0x2d

//////////////////////////////////////////////////////////////

//

// Globals to this Module

//

// Number of seconds to wait for the spooler to finish initializing.

DWORD SpoolerServiceTimeout = 45;

//

// Poll the service status until we timeout or until the spooler

// starts.

//

for (i=0; (i<SpoolerServiceTimeout) &&

(serviceStatus.dwCurrentState != SERVICE_RUNNING); i++) {

//

// Sleep for a sec.

//

Sleep(1000);

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Spooler is still initializing.\n"));

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: Exit WaitForSpoolerToStart.\n"));

return result;

}

04:47:42.390 898061FC.E1757188 RDPPNUTL: Spooler is still initializing.

04:47:42.390 898061FC.E1757188 RDPPNUTL: Exit WaitForSpoolerToStart.

注:可以打开调试看看PRINTSPOOLER服务什么时候启动成功

0: kd> x nt!kd_*Spooler*

80b18a64 nt!Kd_PRINTSPOOLER_Mask = 0

注:

else {

TRACE((DEBUG_TSHRSRV_DEBUG,"RDPPNUTL: First EnumPrinters succeeded.\n"));

status = ERROR_SUCCESS;

pPrinterInfo = (PRINTER_INFO_5 *)stackBuf;

}

//

// Delete all the TS printers. We allow ERROR_INSUFFICIENT_BUFFER here because

// a second invokation of EnumPrinters may have missed a few last-minute

// printer additions.

//

if ((status == ERROR_SUCCESS) || (status == ERROR_INSUFFICIENT_BUFFER)) {

DeleteTSPrinters(pPrinterInfo, cReturnedStructs);

status = ERROR_SUCCESS;

}

//

// Release the printer info buffer.

//

if (buf != NULL) {

TSHeapFree(buf);

}

TRACE((DEBUG_TSHRSRV_DEBUG,"TShrSRV: RDPPNUTL_RemoveAllTSPrinters exit\n"));

return status;

}

04:47:42.687 898061FC.E1757188 RDPPNUTL: First EnumPrinters succeeded.

04:47:42.687 898061FC.E1757188 RDPPNUTL: DeleteTSPrinters entry

04:47:42.687 898061FC.E1757188 RDPPNUTL: DeleteTSPrinters exit

04:47:42.687 898061FC.E1757188 TShrSRV: RDPPNUTL_RemoveAllTSPrinters exit

void

DeleteTSPrinters(

IN PRINTER_INFO_5 *pPrinterInfo,

IN DWORD count

)

/*++

Routine Description:

Actually performs the printer deletion.

Arguments:

pPrinterInfo - All printer queues on the system.

count - Number of printers in pPrinterInfo

Return Value:

NA

--*/

{

DWORD i;

DWORD regValueDataType;

DWORD sessionID;

HANDLE hPrinter = NULL;

DWORD bufSize;

PRINTER_DEFAULTS defaults = {NULL, NULL, PRINTER_ALL_ACCESS};

DBGMSG(DBG_TRACE, ("RDPPNUTL: DeleteTSPrinters entry\n"));

for (i=0; i<count; i++) {

if (pPrinterInfoi.pPrinterName) {

DBGMSG(DBG_TRACE, ("RDPPNUTL: Checking %ws for TS printer status.\n",

pPrinterInfoi.pPrinterName));

//

// Is this a TS printer?

//

if (pPrinterInfoi.pPortName &&

(pPrinterInfoi.pPortName0 == 'T') &&

(pPrinterInfoi.pPortName1 == 'S') &&

ISNUM(pPrinterInfoi.pPortName2)) {

DBGMSG(DBG_ERROR, ("RDPPNUTL: %ws is a TS printer.\n",

pPrinterInfoi.pPrinterName));

}

else {

continue;

}

//

// Purge and delete the printer.

//

if (OpenPrinter(pPrinterInfoi.pPrinterName, &hPrinter, &defaults)) {

if (!SetPrinter(hPrinter, 0, NULL, PRINTER_CONTROL_PURGE) ||

!DeletePrinter(hPrinter)) {

DBGMSG(DBG_ERROR, ("RDPPNUTL: Error deleting printer %ws.\n",

pPrinterInfoi.pPrinterName));

}

else {

DBGMSG(DBG_ERROR, ("RDPPNUTL: Successfully deleted %ws.\n",

pPrinterInfoi.pPrinterName));

}

ClosePrinter(hPrinter);

}

else {

DBGMSG(DBG_ERROR,

("RDPPNUTL: OpenPrinter failed for %ws. Error: %08X.\n",

pPrinterInfoi.pPrinterName,

GetLastError())

);

}

}

else {

DBGMSG(DBG_ERROR, ("RDPPNUTL: Printer %ld is NULL\n", i));

}

}

DBGMSG(DBG_TRACE, ("RDPPNUTL: DeleteTSPrinters exit\n"));

}