util.c
上传用户:looem2003
上传日期:2014-07-20
资源大小:13733k
文件大小:26k
源码类别:

打印编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. All Rights Reserved
  4. Module Name:
  5.     util.c
  6. --*/
  7. #include "precomp.h"
  8. #pragma hdrstop
  9. #pragma prefast (suppress : __WARNING_INCORRECT_ANNOTATION_STRING, "The Pointer is part of an Array. This is the only way to annotate it")
  10. #pragma prefast (suppress : __WARNING_INCORRECT_ANNOTATION, "The Pointer is part of an Array. This is the only way to annotate it")
  11. extern PMONITORINIT g_pMonitorInit;
  12. extern WCHAR g_szPortsList[];
  13. extern WCHAR g_szPortsKey[];
  14. //
  15. // These globals are needed so that AddPort can call
  16. // SPOOLSS!EnumPorts to see whether the port to be added
  17. // already exists.
  18. typedef BOOL
  19. (WINAPI *FnEnumPortsW)(
  20.     LPWSTR   pName,
  21.     DWORD    Level,
  22.     LPBYTE   pPort,
  23.     DWORD    cbBuf,
  24.     LPDWORD  pcbNeeded,
  25.     LPDWORD  pcReturned
  26.     );
  27. HMODULE hSpoolssDll = NULL;
  28. FnEnumPortsW pfnSpoolssEnumPorts = NULL;
  29. VOID
  30. LcmRemoveColon(
  31.     __inout LPWSTR  pName
  32.     )
  33. {
  34.     DWORD   Length;
  35.     Length = wcslen(pName);
  36.     if (pName[Length-1] == L':')
  37.         pName[Length-1] = 0;
  38. }
  39. BOOL
  40. IsCOMPort(
  41.     __in    LPWSTR pPort
  42. )
  43. {
  44.     //
  45.     // Must begin with szLcmCOM
  46.     //
  47.     if ( _wcsnicmp( pPort, szLcmCOM, 3 ) )
  48.     {
  49.         return FALSE;
  50.     }
  51.     //
  52.     // wcslen guarenteed >= 3
  53.     //
  54.     return pPort[ wcslen( pPort ) - 1 ] == L':';
  55. }
  56. BOOL
  57. IsLPTPort(
  58.     __in    LPWSTR pPort
  59. )
  60. {
  61.     //
  62.     // Must begin with szLcmLPT
  63.     //
  64.     if ( _wcsnicmp( pPort, szLcmLPT, 3 ) )
  65.     {
  66.         return FALSE;
  67.     }
  68.     //
  69.     // wcslen guarenteed >= 3
  70.     //
  71.     return pPort[ wcslen( pPort ) - 1 ] == L':';
  72. }
  73. BOOL
  74. GetIniCommValues(
  75.     __in LPWSTR          pName,
  76.          LPDCB          pdcb,
  77.          LPCOMMTIMEOUTS pcto
  78. )
  79. {
  80.     BOOL    bRet = TRUE;
  81.     LPWSTR  pszEntry = NULL;
  82.     if (bRet)
  83.     {
  84.         bRet = GetIniCommValuesFromRegistry (pName, &pszEntry);
  85.     }
  86.     if (bRet)
  87.     {
  88.         bRet =  BuildCommDCB (pszEntry, pdcb);
  89.     }
  90.     if (bRet)
  91.     {
  92.         GetTransmissionRetryTimeoutFromRegistry (&pcto-> WriteTotalTimeoutConstant);
  93.         pcto->WriteTotalTimeoutConstant*=1000;
  94.     }
  95.     FreeSplMem(pszEntry);
  96.     return bRet;
  97. }
  98. HMODULE
  99. LoadSystemLibrary (
  100.     __in    LPCWSTR szDllName
  101.     )
  102. {
  103.     HMODULE hModule = NULL;
  104.     WCHAR szFullDllName [MAX_PATH] = L"";
  105.     if (GetSystemDirectory (szFullDllName, COUNTOF (szFullDllName)) &&
  106.         StringCchCat (szFullDllName, COUNTOF (szFullDllName), L"\") == S_OK &&
  107.         StringCchCat (szFullDllName, COUNTOF (szFullDllName), szDllName) == S_OK)
  108.     {
  109.         hModule = LoadLibrary (szFullDllName);
  110.     }
  111.     return hModule;
  112. }
  113. /* PortExists
  114.  *
  115.  * Calls EnumPorts to check whether the port name already exists.
  116.  * This asks every monitor, rather than just this one.
  117.  * The function will return TRUE if the specified port is in the list.
  118.  * If an error occurs, the return is FALSE and the variable pointed
  119.  * to by pError contains the return from GetLastError().
  120.  * The caller must therefore always check that *pError == NO_ERROR.
  121.  */
  122. BOOL
  123. PortExists(
  124.     __in_opt LPWSTR pName,
  125.     __in     LPWSTR pPortName,
  126.     __out    PDWORD pError
  127. )
  128. {
  129.     DWORD cbNeeded;
  130.     DWORD cReturned;
  131.     DWORD cbPorts;
  132.     LPPORT_INFO_1 pPorts;
  133.     DWORD i;
  134.     BOOL  Found = TRUE;
  135.     *pError = NO_ERROR;
  136.     if (!hSpoolssDll) {
  137.         hSpoolssDll = LoadSystemLibrary (L"SPOOLSS.DLL");
  138.         if (hSpoolssDll) {
  139.             pfnSpoolssEnumPorts = (FnEnumPortsW)GetProcAddress(hSpoolssDll,
  140.                                                  "EnumPortsW");
  141.             if (!pfnSpoolssEnumPorts) {
  142.                 *pError = GetLastError();
  143.                 FreeLibrary(hSpoolssDll);
  144.                 hSpoolssDll = NULL;
  145.             }
  146.         } else {
  147.             *pError = GetLastError();
  148.         }
  149.     }
  150.     if (!pfnSpoolssEnumPorts)
  151.         return FALSE;
  152.     if (!(*pfnSpoolssEnumPorts)(pName, 1, NULL, 0, &cbNeeded, &cReturned))
  153.     {
  154.         if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  155.         {
  156.             cbPorts = cbNeeded;
  157.             pPorts = (LPPORT_INFO_1)AllocSplMem(cbPorts);
  158.             if (pPorts)
  159.             {
  160.                 if ((*pfnSpoolssEnumPorts)(pName, 1, (LPBYTE)pPorts, cbPorts,
  161.                                            &cbNeeded, &cReturned))
  162.                 {
  163.                     Found = FALSE;
  164.                     for (i = 0; i < cReturned; i++)
  165.                     {
  166.                         if (!lstrcmpi(pPorts[i].pName, pPortName))
  167.                             Found = TRUE;
  168.                     }
  169.                 }
  170.             }
  171.             FreeSplMem(pPorts);
  172.         }
  173.     }
  174.     else
  175.         Found = FALSE;
  176.     return Found;
  177. }
  178. VOID
  179. LcmSplInSem(
  180.    VOID
  181. )
  182. {
  183.     if (LcmSpoolerSection.OwningThread != (HANDLE) UIntToPtr(GetCurrentThreadId())) {
  184.         DBG_MSG(DBG_ERROR, ("Not in spooler semaphoren"));
  185.     }
  186. }
  187. VOID
  188. LcmSplOutSem(
  189.    VOID
  190. )
  191. {
  192.     if (LcmSpoolerSection.OwningThread == (HANDLE) UIntToPtr(GetCurrentThreadId())) {
  193.         DBG_MSG(DBG_ERROR, ("Inside spooler semaphore !!n"));
  194.     }
  195. }
  196. VOID
  197. LcmEnterSplSem(
  198.    VOID
  199. )
  200. {
  201.     EnterCriticalSection(&LcmSpoolerSection);
  202. }
  203. VOID
  204. LcmLeaveSplSem(
  205.    VOID
  206. )
  207. {
  208. #if DBG
  209.     LcmSplInSem();
  210. #endif
  211.     LeaveCriticalSection(&LcmSpoolerSection);
  212. }
  213. PINIENTRY
  214. LcmFindName(
  215.    __in PINIENTRY pIniKey,
  216.    __in LPWSTR pName
  217. )
  218. {
  219.     if (pName) {
  220.         while (pIniKey) {
  221.             if (!lstrcmpi(pIniKey->pName, pName)) {
  222.                 return pIniKey;
  223.             }
  224.             pIniKey=pIniKey->pNext;
  225.         }
  226.     }
  227.     return FALSE;
  228. }
  229. PINIENTRY
  230. LcmFindIniKey(
  231.    __in PINIENTRY pIniEntry,
  232.    __in LPWSTR pName
  233. )
  234. {
  235.    if (!pName)
  236.       return NULL;
  237.    LcmSplInSem();
  238.    while (pIniEntry && lstrcmpi(pName, pIniEntry->pName))
  239.       pIniEntry = pIniEntry->pNext;
  240.    return pIniEntry;
  241. }
  242. LPBYTE
  243. LcmPackStrings(
  244.    __in     LPWSTR *pSource,
  245.    __out    LPBYTE pDest,
  246.    __inout  DWORD *DestOffsets,
  247.    __inout  LPBYTE pEnd
  248. )
  249. {
  250.    while (*DestOffsets != -1) {
  251.       if (*pSource) {
  252.           size_t cbString = wcslen(*pSource)*sizeof(WCHAR) + sizeof(WCHAR);
  253.          pEnd-= cbString;
  254.          (VOID) StringCbCopy ((LPWSTR) pEnd, cbString, *pSource);
  255.          *(LPWSTR UNALIGNED *)(pDest+*DestOffsets)= (LPWSTR) pEnd;
  256.       } else
  257.          *(LPWSTR UNALIGNED *)(pDest+*DestOffsets)=0;
  258.       pSource++;
  259.       DestOffsets++;
  260.    }
  261.    return pEnd;
  262. }
  263. /* LcmMessage
  264.  *
  265.  * Displays a LcmMessage by loading the strings whose IDs are passed into
  266.  * the function, and substituting the supplied variable argument list
  267.  * using the varargs macros.
  268.  *
  269.  */
  270. int
  271. LcmMessage(
  272.     HWND hwnd,
  273.     DWORD Type,
  274.     int CaptionID,
  275.     int TextID,
  276.     ...
  277.     )
  278. {
  279.     WCHAR   MsgText[256];
  280.     WCHAR   MsgFormat[256];
  281.     WCHAR   MsgCaption[40];
  282.     va_list vargs;
  283.     if( ( LoadString( LcmhInst, TextID, MsgFormat,
  284.                       sizeof MsgFormat / sizeof *MsgFormat ) > 0 )
  285.      && ( LoadString( LcmhInst, CaptionID, MsgCaption,
  286.                       sizeof MsgCaption / sizeof *MsgCaption ) > 0 ) )
  287.     {
  288.         va_start( vargs, TextID );
  289.         (VOID) StringCchVPrintf (MsgText, COUNTOF (MsgText), MsgFormat, vargs );
  290.         va_end( vargs );
  291.         return MessageBox(hwnd, MsgText, MsgCaption, Type);
  292.     }
  293.     else
  294.         return 0;
  295. }
  296. /*
  297.  *
  298.  */
  299. LPTSTR
  300. LcmGetErrorString(
  301.     DWORD   Error
  302. )
  303. {
  304.     TCHAR   Buffer[1024];
  305.     LPTSTR  pErrorString = NULL;
  306.     if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  307.                        NULL, Error, 0, Buffer,
  308.                        COUNTOF(Buffer), NULL )
  309.       == 0 )
  310.         LoadString( LcmhInst, IDS_UNKNOWN_ERROR,
  311.                     Buffer, COUNTOF(Buffer) );
  312.     pErrorString = AllocSplStr(Buffer);
  313.     return pErrorString;
  314. }
  315. DWORD
  316. ReportError(
  317.     HWND  hwndParent,
  318.     DWORD idTitle,
  319.     DWORD idDefaultError
  320.     )
  321. {
  322.     DWORD  ErrorID;
  323.     DWORD  MsgType;
  324.     LPTSTR pErrorString;
  325.     ErrorID = GetLastError( );
  326.     if( ErrorID == ERROR_ACCESS_DENIED )
  327.         MsgType = MSG_INFORMATION;
  328.     else
  329.         MsgType = MSG_ERROR;
  330.     pErrorString = LcmGetErrorString( ErrorID );
  331.     LcmMessage( hwndParent, MsgType, idTitle,
  332.              idDefaultError, pErrorString );
  333.     FreeSplStr( pErrorString );
  334.     return ErrorID;
  335. }
  336. DWORD
  337. WINAPIV
  338. StrNCatBuffW(
  339.     __out_ecount(cchBuffer) PWSTR       pszBuffer,
  340.     UINT        cchBuffer,
  341.     ...
  342.     )
  343. /*++
  344. Description:
  345.     This routine concatenates a set of null terminated strings
  346.     into the provided buffer.  The last argument must be a NULL
  347.     to signify the end of the argument list.  This only called
  348.         from LocalMon by functions that use WCHARS.
  349. Arguments:
  350.     pszBuffer  - pointer buffer where to place the concatenated
  351.                  string.
  352.     cchBuffer  - character count of the provided buffer including
  353.                  the null terminator.
  354.     ...        - variable number of string to concatenate.
  355. Returns:
  356.     ERROR_SUCCESS if new concatenated string is returned,
  357.     or ERROR_XXX if an error occurred.
  358. Notes:
  359.     The caller must pass valid strings as arguments to this routine,
  360.     if an integer or other parameter is passed the routine will either
  361.     crash or fail abnormally.  Since this is an internal routine
  362.     we are not in try except block for performance reasons.
  363. --*/
  364. {
  365.     DWORD   dwRetval    = ERROR_INVALID_PARAMETER;
  366.     PCWSTR  pszTemp     = NULL;
  367.     PWSTR   pszDest     = NULL;
  368.     va_list pArgs;
  369.     //
  370.     // Validate the pointer where to return the buffer.
  371.     //
  372.     if (pszBuffer && cchBuffer)
  373.     {
  374.         //
  375.         // Assume success.
  376.         //
  377.         dwRetval = ERROR_SUCCESS;
  378.         //
  379.         // Get pointer to argument frame.
  380.         //
  381.         va_start(pArgs, cchBuffer);
  382.         //
  383.         // Get temp destination pointer.
  384.         //
  385.         pszDest = pszBuffer;
  386.         //
  387.         // Insure we have space for the null terminator.
  388.         //
  389.         cchBuffer--;
  390.         //
  391.         // Collect all the arguments.
  392.         //
  393.         for ( ; ; )
  394.         {
  395.             //
  396.             // Get pointer to the next argument.
  397.             //
  398.             pszTemp = va_arg(pArgs, PCWSTR);
  399.             if (!pszTemp)
  400.             {
  401.                 break;
  402.             }
  403.             //
  404.             // Copy the data into the destination buffer.
  405.             //
  406.             for ( ; cchBuffer; cchBuffer-- )
  407.             {
  408.                 if (!(*pszDest = *pszTemp))
  409.                 {
  410.                     break;
  411.                 }
  412.                 pszDest++, pszTemp++;
  413.             }
  414.             //
  415.             // If were unable to write all the strings to the buffer,
  416.             // set the error code and nuke the incomplete copied strings.
  417.             //
  418.             if (!cchBuffer && pszTemp && *pszTemp)
  419.             {
  420.                 dwRetval = ERROR_BUFFER_OVERFLOW;
  421.                 *pszBuffer = L'';
  422.                 break;
  423.             }
  424.         }
  425.         //
  426.         // Terminate the buffer always.
  427.         //
  428.         *pszDest = L'';
  429.         va_end(pArgs);
  430.     }
  431.     //
  432.     // Set the last error in case the caller forgets to.
  433.     //
  434.     if (dwRetval != ERROR_SUCCESS)
  435.     {
  436.         SetLastError(dwRetval);
  437.     }
  438.     return dwRetval;
  439. }
  440. /* PortIsValid
  441.  *
  442.  * Validate the port by attempting to create/open it.
  443.  */
  444. BOOL
  445. PortIsValid(
  446.     __in    LPWSTR pPortName
  447. )
  448. {
  449.     HANDLE hFile;
  450.     BOOL   Valid = FALSE;
  451.     LPWSTR pAdjustedName = NULL;
  452.     //
  453.     // For COM and LPT ports, no verification
  454.     //
  455.     if ( IS_COM_PORT( pPortName ) ||
  456.         IS_LPT_PORT( pPortName ) ||
  457.         IS_FILE_PORT( pPortName ) ||
  458.         IS_POPFAX_PORT( pPortName ) )
  459.     {
  460.         return TRUE;
  461.     }
  462.     pAdjustedName = AdjustFileName( pPortName);
  463.     if (pAdjustedName)
  464.     {
  465.         hFile = CreateFile(pAdjustedName,
  466.                            GENERIC_WRITE,
  467.                            FILE_SHARE_READ,
  468.                            NULL,
  469.                            OPEN_EXISTING,
  470.                            FILE_ATTRIBUTE_NORMAL,
  471.                            NULL);
  472.         if (hFile == INVALID_HANDLE_VALUE) {
  473.             hFile = CreateFile(pAdjustedName,
  474.                                GENERIC_WRITE,
  475.                                FILE_SHARE_READ,
  476.                                NULL,
  477.                                OPEN_ALWAYS,
  478.                                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
  479.                                NULL);
  480.         }
  481.         if (hFile != INVALID_HANDLE_VALUE) {
  482.             CloseHandle(hFile);
  483.             Valid = TRUE;
  484.         } else {
  485.             Valid = FALSE;
  486.         }
  487.         FreeSplMem(pAdjustedName);
  488.     }
  489.     else
  490.     {
  491.         SetLastError(ERROR_FILE_NOT_FOUND);
  492.     }
  493.     return Valid;
  494. }
  495. BOOL
  496. GetIniCommValuesFromRegistry (
  497.     __in        LPCWSTR     pszPortName,
  498.     __deref_out LPWSTR*     ppszCommValues
  499.     )
  500. /*++
  501. Description:
  502.     This function returns the communication parameters from the Registry
  503.     of the specified port in the format: "921600,8,n,1.5,x"
  504. Arguments:
  505.     pszPortName     - [in]  the name of the specific port
  506.     ppszCommValues  - [out] address of the pointer that will point to the string
  507.                             Note, if the function succeeds the caller is responsible for memory deletion by calling FreeSplMem.
  508. Returns:
  509.     Win32 error code
  510.     Note, if not ERROR_SUCCESS the output parameter stays unchanged.
  511. --*/
  512. {
  513.     LPWSTR pszCommValues = NULL;
  514.     DWORD  dwStatus       = ERROR_SUCCESS;
  515.     DWORD  cbData         = 64,
  516.            dwBlockSize;
  517.     HKEY   hPorts = NULL;
  518.     //
  519.     // open the registry key
  520.     //
  521.     dwStatus = g_pMonitorInit->pMonitorReg->fpCreateKey(g_pMonitorInit->hckRegistryRoot, 
  522.                                                         g_szPortsKey, 
  523.                                                         REG_OPTION_NON_VOLATILE,
  524.                                                         KEY_QUERY_VALUE,
  525.                                                         NULL,
  526.                                                         &hPorts, 
  527.                                                         NULL,
  528.                                                         g_pMonitorInit->hSpooler);
  529.     //
  530.     // allocate the initial memory based on COM ports: "921600,8,n,1.5,x" with some extra space
  531.     //
  532.     if (dwStatus == ERROR_SUCCESS)
  533.     {
  534.         dwStatus = (pszCommValues = (PWSTR)AllocSplMem (cbData + sizeof(WCHAR))) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  535.     }
  536.     
  537.     //
  538.     // get the string size
  539.     //
  540.     if (dwStatus == ERROR_SUCCESS)
  541.     {
  542.         DWORD dwType = 0;
  543.         dwBlockSize = cbData;
  544.         pszCommValues[cbData / sizeof(WCHAR)] = UNICODE_NULL;
  545.         dwStatus = g_pMonitorInit->pMonitorReg->fpQueryValue(hPorts, 
  546.                                                              pszPortName, 
  547.                                                              &dwType, 
  548.                                                              (BYTE*)pszCommValues, 
  549.                                                              &cbData,
  550.                                                              g_pMonitorInit->hSpooler);
  551.         //
  552.         // check the result
  553.         //
  554.         if (dwStatus == ERROR_MORE_DATA)
  555.         {
  556.             dwStatus = ERROR_SUCCESS;
  557.             //
  558.             // release the buffer
  559.             //
  560.             FreeSplMem (pszCommValues);
  561.             //
  562.             // allocate precise amount of memory
  563.             //
  564.             if (dwStatus == ERROR_SUCCESS)
  565.             {
  566.                 dwStatus = (pszCommValues = (PWSTR)AllocSplMem (cbData + sizeof(WCHAR))) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  567.             }
  568.             //
  569.             // get data again
  570.             //
  571.             if (dwStatus == ERROR_SUCCESS)
  572.             {
  573.                 dwBlockSize = cbData;
  574.                 pszCommValues[cbData / sizeof(WCHAR)] = UNICODE_NULL;
  575.                 dwStatus = g_pMonitorInit->pMonitorReg->fpQueryValue(hPorts, 
  576.                                                                      pszPortName, 
  577.                                                                      &dwType, 
  578.                                                                      (BYTE*)pszCommValues, 
  579.                                                                      &cbData,
  580.                                                                      g_pMonitorInit->hSpooler);
  581.                 if (dwStatus == ERROR_SUCCESS && dwType != REG_SZ)
  582.                 {
  583.                     //
  584.                     // unexpected data type
  585.                     //
  586.                     dwStatus = ERROR_INVALID_DATA;
  587.                 }
  588.             }
  589.         }
  590.         else if (dwStatus == ERROR_SUCCESS && dwType != REG_SZ)
  591.         {
  592.             //
  593.             // unexpected data type
  594.             //
  595.             dwStatus = ERROR_INVALID_DATA;
  596.         }
  597.     }
  598.     //
  599.     // update output parameter
  600.     //
  601.     if (dwStatus == ERROR_SUCCESS)
  602.     {
  603.         // Add a NULL terminator because RegQueryValueEx does not guarantee it
  604.         DWORD dwNullIndex = (dwBlockSize/2)-1;
  605.         pszCommValues[dwNullIndex] = 0x00;
  606.         *ppszCommValues = pszCommValues;
  607.         pszCommValues   = NULL;
  608.     }
  609.     //
  610.     // cleanup
  611.     //
  612.     if (pszCommValues)
  613.     {
  614.         FreeSplMem (pszCommValues);
  615.     }
  616.     if (hPorts)
  617.     {
  618.         RegCloseKey (hPorts);
  619.     }
  620.     return dwStatus == ERROR_SUCCESS;
  621. }
  622. VOID
  623. GetTransmissionRetryTimeoutFromRegistry (
  624.     __out DWORD*      pdwTimeout
  625.     )
  626. /*++
  627. Description:
  628.     This function returns the timeout value stored in Registry at
  629.     HKLMSoftwareMicrosoftWindows NTCurrentVersionWindows:TransmissionRetryTimeout
  630. Arguments:
  631.     pdwTimeout  - [out] pointer to DWORD that will receive the timeout value
  632. Returns:
  633.     Win32 error code;
  634.     Note, if not ERROR_SUCCESS the output parameter stays unchanged.
  635. --*/
  636. {
  637.     extern WCHAR gszWindows [];
  638.     DWORD  dwStatus     = ERROR_SUCCESS;
  639.     LPWSTR pszTimeout   = NULL;
  640.     DWORD  dwTimeout    = 0;
  641.     DWORD  cbData       = 10,
  642.            dwBlockSize;
  643.     HKEY   hWindows     = NULL;
  644.     //
  645.     // open the registry key
  646.     //
  647.     if (dwStatus == ERROR_SUCCESS)
  648.     {
  649.         dwStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE, gszWindows, 0, KEY_QUERY_VALUE, &hWindows);
  650.     }
  651.     //
  652.     // allocate the initial memory for timeout string
  653.     // this is a timeout period in seconds with initial value of 90
  654.     // it shouldn't be larger then four digits (four WCHARs)
  655.     //
  656.     if (dwStatus == ERROR_SUCCESS)
  657.     {
  658.         dwStatus = (pszTimeout = (PWSTR)AllocSplMem (cbData + sizeof(WCHAR))) ? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  659.     }
  660.     //
  661.     // get data
  662.     //
  663.     if (dwStatus == ERROR_SUCCESS)
  664.     {
  665.         DWORD dwType = 0;
  666.         dwBlockSize = cbData;
  667.         pszTimeout[cbData / sizeof(WCHAR)] = UNICODE_NULL;
  668.         dwStatus = RegQueryValueEx (hWindows, szINIKey_TransmissionRetryTimeout, 0, &dwType, (BYTE*)pszTimeout, &cbData);
  669.         //
  670.         // check the result
  671.         //
  672.         if (dwStatus == ERROR_MORE_DATA)
  673.         {
  674.             dwStatus = ERROR_SUCCESS;
  675.             //
  676.             // release the buffer
  677.             //
  678.             FreeSplMem (pszTimeout);
  679.             //
  680.             // allocate precise amount of memory
  681.             //
  682.             if (dwStatus == ERROR_SUCCESS)
  683.             {
  684.                 dwStatus = (pszTimeout = (PWSTR)AllocSplMem (cbData + sizeof(WCHAR)))? ERROR_SUCCESS : ERROR_OUTOFMEMORY;
  685.             }
  686.             //
  687.             // get data again
  688.             //
  689.             if (dwStatus == ERROR_SUCCESS)
  690.             {
  691.                 dwBlockSize = cbData;
  692.                 pszTimeout[cbData / sizeof(WCHAR)] = UNICODE_NULL;
  693.                 dwStatus = RegQueryValueEx (hWindows, szINIKey_TransmissionRetryTimeout, 0, &dwType, (BYTE*)pszTimeout, &cbData);
  694.                 if (dwStatus == ERROR_SUCCESS && dwType != REG_SZ)
  695.                 {
  696.                     //
  697.                     // unexpected data type
  698.                     //
  699.                     dwStatus = ERROR_INVALID_DATA;
  700.                 }
  701.             }
  702.         }
  703.         else if (dwStatus == ERROR_SUCCESS && dwType != REG_SZ)
  704.         {
  705.             //
  706.             // unexpected data type
  707.             //
  708.             dwStatus = ERROR_INVALID_DATA;
  709.         }
  710.     }
  711.     //
  712.     // retrieve timeout value from string
  713.     //
  714.     if (dwStatus == ERROR_SUCCESS)
  715.     {
  716.         // Add a NULL terminator because RegQueryValueEx does not guarantee it
  717.         DWORD dwNullIndex = (dwBlockSize/2)-1;
  718.         pszTimeout[dwNullIndex] = 0x00;
  719.         dwStatus = (swscanf (pszTimeout, L"%lu", &dwTimeout) == 1)? ERROR_SUCCESS : ERROR_INVALID_DATA;
  720.     }
  721.     //
  722.     // update output parameter
  723.     //
  724.     *pdwTimeout = (dwStatus == ERROR_SUCCESS)? dwTimeout : 45;
  725.     //
  726.     // cleanup
  727.     //
  728.     if (pszTimeout)
  729.     {
  730.         FreeSplMem (pszTimeout);
  731.     }
  732.     if (hWindows)
  733.     {
  734.         RegCloseKey (hWindows);
  735.     }
  736. }
  737. DWORD
  738. SetTransmissionRetryTimeoutInRegistry (
  739.     __in LPCWSTR       pszTimeout
  740.     )
  741. /*++
  742. Description:
  743.     This function returns sets the timeout value in the Registry at
  744.     HKLMSoftwareMicrosoftWindows NTCurrentVersionWindows:TransmissionRetryTimeout
  745. Arguments:
  746.     pdwTimeout  - [in] new timeout value
  747. Returns:
  748.     Win32 error code
  749. --*/
  750. {
  751.     extern WCHAR gszWindows [];
  752.     DWORD  dwStatus  = ERROR_SUCCESS;
  753.     //
  754.     // open the registry key
  755.     //
  756.     HKEY hWindows = NULL;
  757.     if (dwStatus == ERROR_SUCCESS)
  758.     {
  759.         dwStatus = RegOpenKeyEx (HKEY_LOCAL_MACHINE, gszWindows, 0, KEY_SET_VALUE, &hWindows);
  760.     }
  761.     //
  762.     // get data
  763.     //
  764.     if (dwStatus == ERROR_SUCCESS)
  765.     {
  766.         DWORD cbData = (wcslen (pszTimeout) + 1) * sizeof pszTimeout [0];
  767.         dwStatus = RegSetValueEx (hWindows, szINIKey_TransmissionRetryTimeout, 0, REG_SZ, (BYTE*)pszTimeout, cbData);
  768.     }
  769.     //
  770.     // cleanup
  771.     //
  772.     if (hWindows)
  773.     {
  774.         RegCloseKey (hWindows);
  775.     }
  776.     return dwStatus;
  777. }
  778. BOOL
  779. AddPortInRegistry (
  780.     __in LPCWSTR pszPortName
  781.     )
  782. /*++
  783. Description:
  784.     This function adds the port name in the Registry as
  785.     Note, no communcation parameters will be added.
  786. Arguments:
  787.     pszPortName     - [in] port name
  788. Returns:
  789.     Win32 error code
  790. --*/
  791. {
  792.     DWORD        dwStatus = ERROR_SUCCESS;
  793.     HANDLE       hToken = NULL;
  794.     HKEY         hPorts = NULL;
  795.     if (pszPortName == NULL)
  796.     {
  797.         dwStatus = ERROR_INVALID_DATA;
  798.         goto done;
  799.     }
  800.     // Note:  Port monitor writers need to think about what resources are being used and
  801.     //        what level of security should be required in the creation of a port.
  802.     {
  803.         hToken = RevertToPrinterSelf();
  804.     }
  805.     
  806.     //
  807.     // open the key
  808.     //
  809.     dwStatus = g_pMonitorInit->pMonitorReg->fpCreateKey(g_pMonitorInit->hckRegistryRoot, 
  810.                                                         g_szPortsKey, 
  811.                                                         REG_OPTION_NON_VOLATILE,
  812.                                                         KEY_SET_VALUE,
  813.                                                         NULL,
  814.                                                         &hPorts, 
  815.                                                         NULL,
  816.                                                         g_pMonitorInit->hSpooler);
  817.     //
  818.     // add the new value
  819.     //
  820.     if (dwStatus == ERROR_SUCCESS)
  821.     {
  822.         WCHAR szEmpty [] = L"";
  823.         dwStatus = g_pMonitorInit->pMonitorReg->fpSetValue(hPorts, 
  824.                                                            pszPortName, 
  825.                                                            REG_SZ, 
  826.                                                            (BYTE*) szEmpty, 
  827.                                                            sizeof szEmpty,
  828.                                                            g_pMonitorInit->hSpooler);
  829.     }
  830. done:
  831.     //
  832.     // cleanup
  833.     //
  834.     if (hPorts)
  835.     {
  836.         RegCloseKey (hPorts);
  837.     }
  838.     if (hToken)
  839.         ImpersonatePrinterClient(hToken);
  840.     return dwStatus == ERROR_SUCCESS;
  841. }
  842. VOID
  843. DeletePortFromRegistry (
  844.     __in LPCWSTR         pszPortName
  845.     )
  846. /*++
  847. Description:
  848.     This function deletes the port from the Registry. Basicaly, it deletes the Registry value
  849. Arguments:
  850.     pszPortName     - [in] port name
  851. Returns:
  852.     Win32 error code
  853. --*/
  854. {
  855.     DWORD  dwStatus = ERROR_SUCCESS;
  856.     HANDLE hToken = NULL;
  857.     HKEY   hPorts = NULL;
  858.     if (pszPortName == NULL)
  859.     {
  860.         dwStatus = ERROR_INVALID_DATA;
  861.         goto done;
  862.     }
  863.     // Note:  Port monitor writers need to think about what resources are being used and
  864.     //        what level of security should be required in the deletion of a port.
  865.     {
  866.         hToken = RevertToPrinterSelf();
  867.     }
  868.     //
  869.     // open the key
  870.     //
  871.     dwStatus = g_pMonitorInit->pMonitorReg->fpCreateKey(g_pMonitorInit->hckRegistryRoot, 
  872.                                                         g_szPortsKey, 
  873.                                                         REG_OPTION_NON_VOLATILE,
  874.                                                         KEY_SET_VALUE,
  875.                                                         NULL,
  876.                                                         &hPorts, 
  877.                                                         NULL,
  878.                                                         g_pMonitorInit->hSpooler);
  879.     //
  880.     // remove the new value
  881.     //
  882.     if (dwStatus == ERROR_SUCCESS)
  883.     {
  884.         dwStatus = g_pMonitorInit->pMonitorReg->fpDeleteValue(hPorts, 
  885.                                                               pszPortName,
  886.                                                               g_pMonitorInit->hSpooler);
  887.     }
  888.     
  889. done:
  890.     //
  891.     // cleanup
  892.     //
  893.     if (hPorts)
  894.     {
  895.         RegCloseKey (hPorts);
  896.     }
  897.     if (hToken)
  898.         ImpersonatePrinterClient(hToken);
  899. }
  900. LPWSTR
  901. AdjustFileName(
  902.     __in LPWSTR pFileName
  903.     )
  904. {
  905.     LPWSTR pNewName    = NULL;
  906.     pNewName = AllocSplStr( pFileName);
  907.     return pNewName;
  908. }