LPTSTR GetErrorString( DWORD Error ) { TCHAR Buffer[1024]; LPTSTR pErrorString = NULL; DWORD dwFlags; HANDLE hModule; if ((Error >= NERR_BASE) && (Error <= MAX_NERR)){ hModule = LoadLibrary(TEXT("NETMSG.DLL")); dwFlags = FORMAT_MESSAGE_FROM_HMODULE; } else { hModule = NULL; dwFlags = FORMAT_MESSAGE_FROM_SYSTEM; } if( FormatMessage( dwFlags, hModule, Error, 0, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), NULL ) == 0 ) LoadString( hInst, IDS_UNKNOWN_ERROR, Buffer, sizeof(Buffer)/sizeof(Buffer[0])); pErrorString = AllocSplStr(Buffer); if (hModule) { FreeLibrary(hModule); } return pErrorString; }
LPTSTR Make8dot3Name( LPTSTR pSourceName ) { LPTSTR p, pName; TCHAR NameBuffer[MAX_PRINTER_NAME_LEN+MAX_SHARE_NAME_LEN+1]; LPTSTR p8dot3Name = NULL; pName = pSourceName; /* Skip initial blanks: */ while( *pName && ( *pName == SPACE ) ) pName++; /* Skip over all backslashes: */ if( p = _tcsrchr( pName, BACKSLASH ) ) { /* If there's another character after the backslash, * make that the first character of the name: */ if( *(p+1) ) { pName = p+1; } /* Try to find another string before the backslash: */ else { /* Back through any backslashes at the end of the name: */ while( ( *p == BACKSLASH ) && ( p > pName ) ) p--; /* Back up to any preceding backslash or the beginning * of the name: */ while( ( *p != BACKSLASH ) && ( p > pName ) ) p--; if( *p == BACKSLASH ) p++; pName = p; } } /* Copy the complete name: */ _tcscpy( NameBuffer, pName ); StripBlanks( NameBuffer ); NameBuffer[8] = NULLC; FreeSplStr( pSourceName ); return AllocSplStr( NameBuffer ); }
BOOL ReallocSplStr( LPTSTR *plpStr, LPTSTR lpStr ) { FreeSplStr(*plpStr); *plpStr=AllocSplStr(lpStr); return TRUE; }
BOOL ReallocSplStr( LPWSTR *ppStr, LPWSTR pStr ) { LPWSTR pOldStr = *ppStr; *ppStr = AllocSplStr(pStr); FreeSplStr(pOldStr); if ( *ppStr == NULL && pStr != NULL ) { return FALSE; } return TRUE; }
BOOL StartDocPort( HANDLE hPort, LPWSTR pPrinterName, DWORD JobId, DWORD Level, LPBYTE pDocInfo ) { PINIPORT pIniPort = (PINIPORT)hPort; LPWSTR pFileName; pIniPort->hFile = INVALID_HANDLE_VALUE; EnterSplSem(); if (pIniPort->pPrinterName = AllocSplStr(pPrinterName)) { if (OpenPrinter(pPrinterName, &pIniPort->hPrinter, NULL)) { pIniPort->JobId = JobId; pFileName = pIniPort->pName; pIniPort->hFile = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } else FreeSplStr(pIniPort->pPrinterName); } LeaveSplSem(); if (pIniPort->hFile == INVALID_HANDLE_VALUE) { // DbgPrint("localmon!StartDocPort FAILED %x\n", GetLastError()); return FALSE; } else { return TRUE; } }
/*++ Routine Name: PortNameCommandOK Routine Description: Handles the case when the user clicks ok on the port name dialog Arguments: hDlg - handle to dialog Return Value: TRUE success, FALSE an error occurred. --*/ BOOL PortNameCommandOK( HWND hwnd ) { PPORTDIALOG pPort; WCHAR string [MAX_LOCAL_PORTNAME + 1] = L""; WCHAR trimmedString [MAX_LOCAL_PORTNAME + 1] = L""; WCHAR szWideSpace[] = L" "; BOOL rc; DWORD cbNeeded; DWORD dwStatus = NO_ERROR; DWORD indexString = 0; DWORD indexTrimmedString = 0; SHORT end; size_t cbSize = 0; if ((pPort = (PPORTDIALOG) GetWindowLongPtr( hwnd, GWLP_USERDATA )) == NULL) { dwStatus = ERROR_INVALID_DATA; ErrorMessage (hwnd, dwStatus); SetLastError (dwStatus); return FALSE; } GetDlgItemText( hwnd, IDD_PN_EF_PORTNAME, string, COUNTOF(string)); string [COUNTOF (string) - 1] = L'\0'; // // Trim the string for Spaces (Front & Back) // // First Cut off any spaces at the front // while ((indexString < COUNTOF(string)) && (string[indexString] == szWideSpace[0])) { indexString++; } while ((indexString < COUNTOF(string)-1) && (string[indexString])) { trimmedString[indexTrimmedString++] = string[indexString++]; } trimmedString[indexTrimmedString] = 0x00; // // Next Cut off any spaces at the end // end = (SHORT) wcslen(trimmedString)-1; while ((end >= 0) && (trimmedString[end] == szWideSpace[0])) { trimmedString[end--] = 0x00; } cbSize = (wcslen(string) + 1) * sizeof(*string); if (cbSize <= DWORD_MAX) { rc = XcvData( pPort->hXcv, L"PortIsValid", (PBYTE) trimmedString, (DWORD)cbSize, (PBYTE) NULL, 0, &cbNeeded, &dwStatus); } else { rc = FALSE; } if (!rc) { return FALSE; } else if (dwStatus != ERROR_SUCCESS) { SetLastError(dwStatus); if ( (dwStatus == ERROR_INVALID_NAME) || (*trimmedString == 0x00) ) Message( hwnd, MSG_ERROR, IDS_LOCALMONITOR, IDS_INVALIDPORTNAME_S, string ); else ErrorMessage(hwnd, dwStatus); return FALSE; } else { pPort->pszPortName = AllocSplStr( trimmedString ); pPort->dwRet = dwStatus; EndDialog( hwnd, ERROR_SUCCESS ); return TRUE; } }
PINIPORT CreatePortEntry( __in LPTSTR pszPortName ) /*++ Routine Description: Creates a IniPort entry for a port. Needs to be called inside monitor critical section. Arguments: pszPortName : Name of the port Return Value: On success pointer to the IniPort stucture. On failure NULL --*/ { PINIPORT pIniPort = NULL; HANDLE DoneWriting = NULL; HANDLE DoneReading = NULL; HANDLE WakeUp = NULL; LPWSTR pszString = NULL; SplInSem(); DoneWriting = CreateEvent(NULL, FALSE, TRUE, NULL); if (!DoneWriting) { goto Fail; } WakeUp = CreateEvent(NULL, FALSE, FALSE, NULL); if (!WakeUp) { goto Fail; } // // manual-reset event, initially signal state // DoneReading = CreateEvent(NULL, TRUE, TRUE, NULL); if (!DoneReading) { goto Fail; } pIniPort = (PINIPORT) AllocSplMem(sizeof(*pIniPort)); if (!pIniPort) { goto Fail; } pszString = AllocSplStr(pszPortName); if (!pszString) { goto Fail; } pIniPort->pNext = NULL; pIniPort->signature = PJ_SIGNATURE; pIniPort->DoneWriting = DoneWriting; pIniPort->DoneReading = DoneReading; pIniPort->WakeUp = WakeUp; pIniPort->hUstatusThread= NULL; pIniPort->pszPortName = pszString; pIniPort->pNext = pIniFirstPort; pIniFirstPort = pIniPort; return pIniPort; Fail: if (DoneWriting) { CloseHandle (DoneWriting); } if (DoneReading) { CloseHandle (DoneReading); } if (WakeUp) { CloseHandle (WakeUp); } FreeSplMem (pszString); FreeSplMem (pIniPort); return NULL; }
DWORD WINAPI CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle) { const WCHAR wszDoubleBackslash[] = L"\\"; const DWORD cchDoubleBackslash = _countof(wszDoubleBackslash) - 1; DWORD cchMachineName; DWORD cchUserName; DWORD dwErrorCode; PLOCAL_JOB pJob; RPC_BINDING_HANDLE hServerBinding = NULL; RPC_WSTR pwszBinding = NULL; RPC_WSTR pwszMachineName = NULL; // Create a new job. pJob = DllAllocSplMem(sizeof(LOCAL_JOB)); if (!pJob) { dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); goto Cleanup; } // Reserve an ID for this job. if (!_GetNextJobID(&pJob->dwJobID)) { dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; goto Cleanup; } // Copy over defaults to the LOCAL_JOB structure. pJob->pPrinter = pPrinterHandle->pPrinter; pJob->pPrintProcessor = pPrinterHandle->pPrinter->pPrintProcessor; pJob->dwPriority = DEF_PRIORITY; pJob->dwStatus = JOB_STATUS_SPOOLING; pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype); pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName); pJob->pDevMode = DuplicateDevMode(pPrinterHandle->pDevMode); GetSystemTime(&pJob->stSubmitted); // Get the user name for the Job. cchUserName = UNLEN + 1; pJob->pwszUserName = DllAllocSplMem(cchUserName * sizeof(WCHAR)); if (!GetUserNameW(pJob->pwszUserName, &cchUserName)) { dwErrorCode = GetLastError(); ERR("GetUserNameW failed with error %lu!\n", dwErrorCode); goto Cleanup; } // FIXME: For now, pwszNotifyName equals pwszUserName. pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName); // Get the name of the machine that submitted the Job over RPC. dwErrorCode = RpcBindingServerFromClient(NULL, &hServerBinding); if (dwErrorCode != RPC_S_OK) { ERR("RpcBindingServerFromClient failed with status %lu!\n", dwErrorCode); goto Cleanup; } dwErrorCode = RpcBindingToStringBindingW(hServerBinding, &pwszBinding); if (dwErrorCode != RPC_S_OK) { ERR("RpcBindingToStringBindingW failed with status %lu!\n", dwErrorCode); goto Cleanup; } dwErrorCode = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL); if (dwErrorCode != RPC_S_OK) { ERR("RpcStringBindingParseW failed with status %lu!\n", dwErrorCode); goto Cleanup; } cchMachineName = wcslen(pwszMachineName); pJob->pwszMachineName = DllAllocSplMem((cchMachineName + cchDoubleBackslash + 1) * sizeof(WCHAR)); CopyMemory(pJob->pwszMachineName, wszDoubleBackslash, cchDoubleBackslash * sizeof(WCHAR)); CopyMemory(&pJob->pwszMachineName[cchDoubleBackslash], pwszMachineName, (cchMachineName + 1) * sizeof(WCHAR)); // Add the job to the Global Job List. if (!InsertElementSkiplist(&GlobalJobList, pJob)) { dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID); goto Cleanup; } // Add the job at the end of the Printer's Job List. // As all new jobs are created with default priority, we can be sure that it would always be inserted at the end. if (!InsertTailElementSkiplist(&pJob->pPrinter->JobList, pJob)) { dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID); goto Cleanup; } // We were successful! pPrinterHandle->bStartedDoc = TRUE; pPrinterHandle->pJob = pJob; dwErrorCode = ERROR_SUCCESS; // Don't let the cleanup routine free this. pJob = NULL; Cleanup: if (pJob) DllFreeSplMem(pJob); if (pwszMachineName) RpcStringFreeW(&pwszMachineName); if (pwszBinding) RpcStringFreeW(&pwszBinding); if (hServerBinding) RpcBindingFree(&hServerBinding); return dwErrorCode; }
PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath) { DWORD cbFileSize; DWORD cbRead; HANDLE hFile = INVALID_HANDLE_VALUE; PLOCAL_JOB pJob; PLOCAL_JOB pReturnValue = NULL; PLOCAL_PRINTER pPrinter; PLOCAL_PRINT_PROCESSOR pPrintProcessor; PSHD_HEADER pShadowFile = NULL; PWSTR pwszPrinterName; PWSTR pwszPrintProcessor; // Try to open the file. hFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { ERR("CreateFileW failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); goto Cleanup; } // Get its file size (small enough for a single DWORD) and allocate memory for all of it. cbFileSize = GetFileSize(hFile, NULL); pShadowFile = DllAllocSplMem(cbFileSize); if (!pShadowFile) { ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); goto Cleanup; } // Read the entire file. if (!ReadFile(hFile, pShadowFile, cbFileSize, &cbRead, NULL)) { ERR("ReadFile failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); goto Cleanup; } // Check signature and header size. if (pShadowFile->dwSignature != SHD_WIN2003_SIGNATURE || pShadowFile->cbHeader != sizeof(SHD_HEADER)) { ERR("Signature or Header Size mismatch for file \"%S\"!\n", pwszFilePath); goto Cleanup; } // Retrieve the associated printer from the list. pwszPrinterName = (PWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrinterName); pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL); if (!pPrinter) { ERR("Shadow file \"%S\" references a non-existing printer \"%S\"!\n", pwszFilePath, pwszPrinterName); goto Cleanup; } // Retrieve the associated Print Processor from the list. pwszPrintProcessor = (PWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrintProcessor); pPrintProcessor = FindPrintProcessor(pwszPrintProcessor); if (!pPrintProcessor) { ERR("Shadow file \"%S\" references a non-existing Print Processor \"%S\"!\n", pwszFilePath, pwszPrintProcessor); goto Cleanup; } // Create a new job structure and copy over the relevant fields. pJob = DllAllocSplMem(sizeof(LOCAL_JOB)); if (!pJob) { ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); goto Cleanup; } pJob->dwJobID = pShadowFile->dwJobID; pJob->dwPriority = pShadowFile->dwPriority; pJob->dwStartTime = pShadowFile->dwStartTime; pJob->dwTotalPages = pShadowFile->dwTotalPages; pJob->dwUntilTime = pShadowFile->dwUntilTime; pJob->pPrinter = pPrinter; pJob->pPrintProcessor = pPrintProcessor; pJob->pDevMode = DuplicateDevMode((PDEVMODEW)((ULONG_PTR)pShadowFile + pShadowFile->offDevMode)); pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype)); pJob->pwszMachineName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offMachineName)); CopyMemory(&pJob->stSubmitted, &pShadowFile->stSubmitted, sizeof(SYSTEMTIME)); // Copy the optional values. if (pShadowFile->offDocumentName) pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName)); if (pShadowFile->offNotifyName) pJob->pwszNotifyName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offNotifyName)); if (pShadowFile->offPrintProcessorParameters) pJob->pwszPrintProcessorParameters = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrintProcessorParameters)); if (pShadowFile->offUserName) pJob->pwszUserName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offUserName)); // Jobs read from shadow files were always added using AddJob. pJob->bAddedJob = TRUE; pReturnValue = pJob; Cleanup: if (pShadowFile) DllFreeSplMem(pShadowFile); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); return pReturnValue; }
/*++ ******************************************************************* O p e n P r i n t P r o c e s s o r Routine Description: Arguments: pPrinterName => name of printer we are opening for pPrintProcessorOpenData => information used for opening the print processor Return Value: PPRINTPROCESSORDATA => processor data of opened processor if successful NULL if failed - caller uses GetLastError for reason NOTE: OpenPrinter will be called iff this returns a valid handle (and we're not journal) ******************************************************************* --*/ HANDLE OpenPrintProcessor( _In_ LPWSTR pPrinterName, _In_ PPRINTPROCESSOROPENDATA pPrintProcessorOpenData ) { PPRINTPROCESSORDATA pData; LPWSTR *pMyDatatypes = Datatypes; DWORD uDatatype = 0; HANDLE hPrinter = 0; HDC hDC = 0; PDEVMODEW pDevmode = NULL; DWORD dwNewDevmodeSize = 0; /** If the caller passed a NULL for the open data, fail the call. pPrintProcessorOpenData->pDevMode can be NULL **/ if (!pPrintProcessorOpenData || !pPrintProcessorOpenData->pDatatype || !*pPrintProcessorOpenData->pDatatype) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } /** Search for the data type index we are opening for **/ while (*pMyDatatypes) { if (!_wcsicmp(*pMyDatatypes,pPrintProcessorOpenData->pDatatype)) { break; } pMyDatatypes++; uDatatype++; } /** Allocate a buffer for the print processor data to return **/ pData = (PPRINTPROCESSORDATA)AllocSplMem(sizeof(PRINTPROCESSORDATA)); if (!pData) { ODS(("Alloc failed in OpenPrintProcessor, while printing on %ws\n", pPrinterName)); return NULL; } ZeroMemory ( pData, sizeof (PRINTPROCESSORDATA) ); /** Open the processor accordingly **/ switch (uDatatype) { case PRINTPROCESSOR_TYPE_RAW: if (!OpenPrinter(pPrinterName, &hPrinter, NULL)) goto Fail; break; case PRINTPROCESSOR_TYPE_EMF_50_1: case PRINTPROCESSOR_TYPE_EMF_50_2: case PRINTPROCESSOR_TYPE_EMF_50_3: if(pPrintProcessorOpenData->pDevMode) { if ( ! SUCCEEDED ( DWordAdd(pPrintProcessorOpenData->pDevMode->dmSize, pPrintProcessorOpenData->pDevMode->dmDriverExtra, &dwNewDevmodeSize) ) || (NULL == (pDevmode=(PDEVMODE)AllocSplMem( dwNewDevmodeSize ) ) ) ) { goto Fail; } memcpy(pDevmode, pPrintProcessorOpenData->pDevMode, pPrintProcessorOpenData->pDevMode->dmSize+ pPrintProcessorOpenData->pDevMode->dmDriverExtra); } break; case PRINTPROCESSOR_TYPE_TEXT: if ((hDC = CreateDC( L"", pPrinterName, L"", pPrintProcessorOpenData->pDevMode)) == NULL) goto Fail; break; default: SetLastError(ERROR_INVALID_DATATYPE); goto Fail; } /** Fill in the print processors information **/ pData->cb = sizeof(PRINTPROCESSORDATA); pData->signature = PRINTPROCESSORDATA_SIGNATURE; pData->JobId = pPrintProcessorOpenData->JobId; pData->hPrinter = hPrinter; pData->semPaused = CreateEvent(NULL, TRUE, TRUE,NULL); pData->uDatatype = uDatatype; pData->hDC = hDC; pData->Copies = 1; pData->TabSize = BASE_TAB_SIZE; /** Allocate and fill in the processors strings **/ pData->pPrinterName = AllocSplStr(pPrinterName); pData->pDatatype = AllocSplStr(pPrintProcessorOpenData->pDatatype); pData->pDocument = AllocSplStr(pPrintProcessorOpenData->pDocumentName); pData->pOutputFile = AllocSplStr(pPrintProcessorOpenData->pOutputFile); pData->pParameters = AllocSplStr(pPrintProcessorOpenData->pParameters); pData->pDevmode = pDevmode; pData->pPrinterNameFromOpenData = AllocSplStr(pPrintProcessorOpenData->pPrinterName); // // Check for validity of pData. In the AllocSplStr above, if RHS is non-null, then LHS // should be non-null. // if ( NULL == pData->semPaused || ( NULL != pPrinterName && NULL == pData->pPrinterName ) || ( NULL != pPrintProcessorOpenData->pDatatype && NULL == pData->pDatatype ) || ( NULL != pPrintProcessorOpenData->pDocumentName && NULL == pData->pDocument ) || ( NULL != pPrintProcessorOpenData->pOutputFile && NULL == pData->pOutputFile ) || ( NULL != pPrintProcessorOpenData->pParameters && NULL == pData->pParameters ) || ( NULL != pPrintProcessorOpenData->pPrinterName && NULL == pData->pPrinterNameFromOpenData) ) { goto Fail; } /** Parse the parameters string **/ if (pData->pParameters) { ULONG value; USHORT length = sizeof(ULONG); /** Look to see if there is a COPIES=n key/value in the Parameters field of this job. This tells us the number of times to play the data. **/ if (pData->pParameters) { GetKeyValue(pData->pParameters, pCopiesKey, VALUE_ULONG, &length, &value); if (length == sizeof(ULONG)) { pData->Copies = value; } } /** If this is a text job, see if the tab size is in there **/ if (uDatatype == PRINTPROCESSOR_TYPE_TEXT) { length = sizeof(ULONG); GetKeyValue(pData->pParameters, pTabsKey, VALUE_ULONG, &length, &value); if ((length == sizeof(ULONG)) && value) { pData->TabSize = value; } } } /* If we have a parameter string */ /** If we are doing copies, we need to check to see if this is a direct or spooled job. If it is direct, then we can't do copies because we can't rewind the data stream. **/ if (pData->Copies > 1) { ULONG Error; PPRINTER_INFO_2 pPrinterInfo2; /** If we don't already have the printer open, open it **/ if (uDatatype != PRINTPROCESSOR_TYPE_RAW ) { OpenPrinter(pPrinterName, &hPrinter, NULL); } if (hPrinter && hPrinter != INVALID_HANDLE_VALUE) { /** Get the printer info - this returns an allocated buffer **/ pPrinterInfo2 = (PPRINTER_INFO_2)GetPrinterInfo(hPrinter, 2, &Error); /** If we couldn't get the info, be safe and don't do copies **/ if (!pPrinterInfo2) { ODS(("GetPrinter failed - falling back to 1 copy\n")); pData->Copies = 1; } else { if (pPrinterInfo2->Attributes & PRINTER_ATTRIBUTE_DIRECT) { pData->Copies = 1; } FreeSplMem((PUCHAR)pPrinterInfo2); } /** If we just opened the printer, close it **/ if (uDatatype != PRINTPROCESSOR_TYPE_RAW ) { ClosePrinter(hPrinter); } } else { pData->Copies = 1; } } return (HANDLE)pData; Fail: BReleasePPData(&pData); return FALSE; }
HANDLE CreatePrinterHandle( LPWSTR pPrinterName, PINIPRINTER pIniPrinter, PINIPORT pIniPort, PINIPORT pIniNetPort, PINIJOB pIniJob, DWORD TypeofHandle, HANDLE hPort, PPRINTER_DEFAULTS pDefaults, PINISPOOLER pIniSpooler, DWORD AccessRequested, LPBYTE pSplClientInfo, DWORD dwLevel, HANDLE hReadFile ) { PSPOOL pSpool = NULL; BOOL bStatus = FALSE; HANDLE hReturnHandle = NULL; LPDEVMODE pDevMode = NULL; PSPLCLIENT_INFO_1 pSplClientInfo1 = (PSPLCLIENT_INFO_1)pSplClientInfo; SPLASSERT( pIniSpooler->signature == ISP_SIGNATURE ); if ( dwLevel && ( dwLevel != 1 || !pSplClientInfo) ) { DBGMSG(DBG_ERROR, ("CreatePrintHandle: Invalid client info %x - %d\n", pSplClientInfo, dwLevel)); pSplClientInfo = NULL; } try { pSpool = (PSPOOL)AllocSplMem( SPOOL_SIZE ); if ( pSpool == NULL ) { DBGMSG( DBG_WARNING, ("CreatePrinterHandle failed to allocate SPOOL %d\n", GetLastError() )); leave; } pSpool->signature = SJ_SIGNATURE; pSpool->pIniPrinter = pIniPrinter; pSpool->hReadFile = hReadFile; // // We get other useful info like build #, client architecture // we do not need this info now -- so we do not put it in PSPOOL // if ( (TypeofHandle & PRINTER_HANDLE_REMOTE) ) { if ( !pSplClientInfo ) { TypeofHandle |= PRINTER_HANDLE_3XCLIENT; } else if ( dwLevel == 1 ) { SPLASSERT(pSplClientInfo1->pUserName && pSplClientInfo1->pMachineName); pSpool->pUserName = AllocSplStr(pSplClientInfo1->pUserName); pSpool->pMachineName = AllocSplStr(pSplClientInfo1->pMachineName); if ( !pSpool->pUserName || !pSpool->pMachineName ) { DBGMSG(DBG_WARNING, ("CreatePrinterHandle: could not allocate memory for user name or machine name\n")); } } } if ( TypeofHandle & PRINTER_HANDLE_SERVER ) { bStatus = ValidateObjectAccess( SPOOLER_OBJECT_SERVER, AccessRequested, pSpool, pIniSpooler ); } else { bStatus = ValidateObjectAccess( SPOOLER_OBJECT_PRINTER, AccessRequested, pSpool, pIniSpooler ); } if ( !bStatus ) { SetLastError(ERROR_ACCESS_DENIED); leave; } MapGenericToSpecificAccess(SPOOLER_OBJECT_PRINTER, pSpool->GrantedAccess, &pSpool->GrantedAccess); pSpool->pIniPort = pIniPort; pSpool->pIniNetPort = pIniNetPort; pSpool->pIniJob = pIniJob; pSpool->TypeofHandle = TypeofHandle; pSpool->hPort = hPort; pSpool->Status = 0; pSpool->pDevMode = NULL; pSpool->pName = AllocSplStr( pPrinterName ); if ( pSpool->pName == NULL ) { leave; } pSpool->pIniSpooler = pIniSpooler; if ( pIniPrinter ) { if ( pDefaults ) { // // Allocate DevMode // if ( pDefaults->pDevMode ) { pDevMode = pDefaults->pDevMode; } else { pDevMode = pIniPrinter->pDevMode; } if ( pDevMode != NULL ) { pSpool->pDevMode = AllocSplMem( pDevMode->dmSize + pDevMode->dmDriverExtra ); if ( pSpool->pDevMode == NULL ) { DBGMSG(DBG_WARNING, ("CreatePrinterHandle failed allocation for devmode %d\n", GetLastError() )); leave; } memcpy( pSpool->pDevMode, pDevMode, pDevMode->dmSize + pDevMode->dmDriverExtra ); } } // // Allocate Datype and Print Processor // if ( pDefaults && pDefaults->pDatatype ) { pSpool->pDatatype = AllocSplStr( pDefaults->pDatatype ); pSpool->pIniPrintProc = FindDatatype( pIniPrinter->pIniPrintProc, pSpool->pDatatype ); } else { pSpool->pDatatype = AllocSplStr( pIniPrinter->pDatatype ); pSpool->pIniPrintProc = pIniPrinter->pIniPrintProc; } if ( pSpool->pIniPrintProc == NULL ) { DBGMSG( DBG_WARNING,("CreatePrinterHandle failed to PrintProcessor for datatype %ws %d\n", pSpool->pDatatype, GetLastError() )); leave; } SPLASSERT( pSpool->pIniPrintProc->signature == IPP_SIGNATURE ); pSpool->pIniPrintProc->cRef++; if ( pSpool->pDatatype == NULL ) { DBGMSG( DBG_WARNING,("CreatePrinterHandle failed to allocate DataType %x\n", GetLastError() )); leave; } } // Add us to the linked list of handles for this printer. // This will be scanned when a change occurs on the printer, // and will be updated with a flag indicating what type of // change it was. // There is a flag for each handle, because we cannot guarantee // that all threads will have time to reference a flag in the // INIPRINTER before it is updated. if ( TypeofHandle & PRINTER_HANDLE_PRINTER ) { pSpool->pNext = pSpool->pIniPrinter->pSpool; pSpool->pIniPrinter->pSpool = pSpool; } else if ( TypeofHandle & PRINTER_HANDLE_SERVER ) { // // For server handles, hang them off the global IniSpooler: // pSpool->pNext = pIniSpooler->pSpool; pIniSpooler->pSpool = pSpool; INCSPOOLERREF( pIniSpooler ); } // Note Only PRINTER_HANDLE_PRINTER are attatched to the // pIniPrinter, since those are the handle which will require // change notifications. if ( pSpool->pIniPrinter != NULL ) { INCPRINTERREF( pSpool->pIniPrinter ); } hReturnHandle = (HANDLE)pSpool; } finally { if ( hReturnHandle == NULL ) { // Failure CleanUP if ( pSpool != NULL ) { FreeSplStr(pSpool->pUserName); FreeSplStr(pSpool->pMachineName); FreeSplStr( pSpool->pName ) ; FreeSplStr( pSpool->pDatatype ); if ( pSpool->pIniPrintProc != NULL ) pSpool->pIniPrintProc->cRef--; if ( pSpool->pDevMode ) FreeSplMem( pSpool->pDevMode ); FreeSplMem( pSpool ); pSpool = NULL; } } } return hReturnHandle; }