windows-nt/Source/XPSP1/NT/printscan/fax/test/faxvrfy/util.c
2020-09-26 16:20:57 +08:00

625 lines
19 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
util.c
Abstract:
This module:
1) Finds the device name of a port
2) Initializes NTLog
3) Starts the log file
4) Closes the log file
5) Gets the current time
6) Writes a string to the log and text files
7) Checks if an edit control string is composed of only ASCII characters
8) Encodes a TSID
9) Decodes a TSID
Author:
Steven Kehrli (steveke) 11/15/1997
--*/
#ifndef _UTIL_C
#define _UTIL_C
VOID
fnFindDeviceName(
PFAX_PORT_INFO pFaxPortsConfig,
DWORD dwNumPorts,
DWORD dwDeviceId,
LPWSTR *pszDeviceName
)
/*++
Routine Description:
Finds the device name of a port
Arguments:
pFaxPortsConfig - pointer to the fax ports configuration
dwNumFaxPorts - number of ports
dwDeviceId - port id
pszDeviceName - device name
Return Value:
None
--*/
{
// dwIndex is a counter to enumerate each port
DWORD dwIndex;
// Set szDeviceName to NULL
*pszDeviceName = NULL;
for (dwIndex = 0; dwIndex < dwNumPorts; dwIndex++) {
// Search, by priority, each port for the appropriate port
if (pFaxPortsConfig[dwIndex].DeviceId == dwDeviceId) {
if (pFaxPortsConfig[dwIndex].DeviceName) {
*pszDeviceName = (LPWSTR) pFaxPortsConfig[dwIndex].DeviceName;
}
return;
}
}
}
BOOL
fnInitializeNTLog(
)
/*++
Routine Description:
Initializes NTLog
Return Value:
TRUE on success
--*/
{
// hInstance is the handle to the NTLog dll
HINSTANCE hInstance;
// Get the handle to the NTLog dll
hInstance = LoadLibrary((LPCWSTR) NTLOG_DLL);
if (!hInstance) {
DebugMacro(L"LoadLibrary(%s) failed, ec = 0x%08x\n", NTLOG_DLL, GetLastError());
return FALSE;
}
// Map all needed functions
g_NTLogApi.hInstance = hInstance;
// tlCreateLog
g_NTLogApi.ptlCreateLog = (PTLCREATELOG) GetProcAddress(hInstance, "tlCreateLog_W");
if (!g_NTLogApi.ptlCreateLog) {
DebugMacro(L"GetProcAddress(tlCreateLog) failed, ec = 0x%08x\n", GetLastError());
FreeLibrary(hInstance);
return FALSE;
}
// tlDestroyLog
g_NTLogApi.ptlDestroyLog = (PTLDESTROYLOG) GetProcAddress(hInstance, "tlDestroyLog");
if (!g_NTLogApi.ptlDestroyLog) {
DebugMacro(L"GetProcAddress(tlDestroyLog) failed, ec = 0x%08x\n", GetLastError());
FreeLibrary(hInstance);
return FALSE;
}
// tlAddParticipant
g_NTLogApi.ptlAddParticipant = (PTLADDPARTICIPANT) GetProcAddress(hInstance, "tlAddParticipant");
if (!g_NTLogApi.ptlAddParticipant) {
DebugMacro(L"GetProcAddress(tlAddParticipant) failed, ec = 0x%08x\n", GetLastError());
FreeLibrary(hInstance);
return FALSE;
}
// tlRemoveParticipant
g_NTLogApi.ptlRemoveParticipant = (PTLREMOVEPARTICIPANT) GetProcAddress(hInstance, "tlRemoveParticipant");
if (!g_NTLogApi.ptlRemoveParticipant) {
DebugMacro(L"GetProcAddress(tlRemoveParticipant) failed, ec = 0x%08x\n", GetLastError());
FreeLibrary(hInstance);
return FALSE;
}
// tlLog
g_NTLogApi.ptlLog = (PTLLOG) GetProcAddress(hInstance, "tlLog_W");
if (!g_NTLogApi.ptlLog) {
DebugMacro(L"GetProcAddress(tlLog) failed, ec = 0x%08x\n", GetLastError());
FreeLibrary(hInstance);
return FALSE;
}
return TRUE;
}
VOID
fnStartLogFile(
)
/*++
Routine Description:
Starts the log file
Return Value:
None
--*/
{
// cUnicodeBOM is the Unicode BOM
WCHAR cUnicodeBOM = 0xFEFF;
DWORD cb;
INT iInt;
// Create the new text log file
g_hTxtFile = CreateFile(FAXVRFY_TXT, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(g_hTxtFile, &cUnicodeBOM, sizeof(WCHAR), &cb, NULL);
// Create the new NTLog log file
if (g_bNTLogAvailable) {
g_hLogFile = (HANDLE) g_NTLogApi.ptlCreateLog(FAXVRFY_LOG, TLS_INFO | TLS_SEV2 | TLS_WARN | TLS_PASS | TLS_TEST | TLS_VARIATION | TLS_REFRESH);
g_NTLogApi.ptlAddParticipant(g_hLogFile, 0, 0);
}
}
VOID
fnCloseLogFile(
)
/*++
Routine Description:
Closes the log file
Return Value:
None
--*/
{
CloseHandle(g_hTxtFile);
if (g_bNTLogAvailable) {
g_NTLogApi.ptlRemoveParticipant(g_hLogFile);
g_NTLogApi.ptlDestroyLog(g_hLogFile);
FreeLibrary(g_NTLogApi.hInstance);
}
}
VOID
fnGetCurrentTime(
LPWSTR *szCurrentTime
)
/*++
Routine Description:
Gets the current time
Arguments:
szFaxTime - string representation of the current time
Return Value:
None
--*/
{
// CurrentTime is the current time
SYSTEMTIME CurrentTime;
// lcid is the default locale
LCID lcid;
// szDate is the date
LPWSTR szDate;
// szTime is the time
LPWSTR szTime;
DWORD cb;
// Set szCurrentTime to NULL
*szCurrentTime = NULL;
// Get the current time
GetLocalTime(&CurrentTime);
// Get the default locale
lcid = GetUserDefaultLCID();
// Determine the memory required by the date
cb = GetDateFormat(lcid, DATE_SHORTDATE, &CurrentTime, NULL, NULL, 0);
// Allocate the memory for the date
szDate = MemAllocMacro(cb * sizeof(WCHAR));
// Get the date
GetDateFormat(lcid, DATE_SHORTDATE, &CurrentTime, NULL, szDate, cb);
// Determine the memory required by the time
cb = GetTimeFormat(lcid, TIME_FORCE24HOURFORMAT, &CurrentTime, NULL, NULL, 0);
// Allocate the memory for the time
szTime = MemAllocMacro(cb * sizeof(WCHAR));
// Get the time
GetTimeFormat(lcid, 0, &CurrentTime, NULL, szTime, cb);
// Allocate the memory for the time of the fax
*szCurrentTime = MemAllocMacro((lstrlen(szDate) + lstrlen(szTime) + 4) * sizeof(WCHAR));
// Copy the date
lstrcpy(*szCurrentTime, szDate);
// Append a space
lstrcat(*szCurrentTime, L" ");
// Append the time
lstrcat(*szCurrentTime, szTime);
lstrcat(*szCurrentTime, L"\r\n");
}
VOID
fnWriteLogFile(
BOOL bTime,
LPWSTR szFormatString,
...
)
/*++
Routine Description:
Writes a string to the log and text files
Arguments:
bTime - indicates current time should be logged
szFormatString - pointer to the string
Return Value:
None
--*/
{
va_list varg_ptr;
// szOutputString is the output string
WCHAR szOutputString[1024];
// szCurrentTime is the current time
LPWSTR szCurrentTime;
DWORD cb;
if (bTime) {
// Get the current time
fnGetCurrentTime(&szCurrentTime);
WriteFile(g_hTxtFile, szCurrentTime, lstrlen(szCurrentTime) * sizeof(WCHAR), &cb, NULL);
// Free the current time
MemFreeMacro(szCurrentTime);
}
va_start(varg_ptr, szFormatString);
_vsnwprintf(szOutputString, sizeof(szOutputString), szFormatString, varg_ptr);
WriteFile(g_hTxtFile, szOutputString, lstrlen(szOutputString) * sizeof(WCHAR), &cb, NULL);
}
BOOL
fnIsStringASCII(
LPWSTR szString
)
/*++
Routine Description:
Checks if a string is composed of only ASCII characters
Arguments:
szString - string
Return Value:
TRUE on success
--*/
{
// szSearchString is the string used to search for non-ASCII characters
LPWSTR szSearchString;
BOOL bRslt;
szSearchString = szString;
bRslt = TRUE;
while ((*szSearchString) && (bRslt)) {
if ((*szSearchString < (WCHAR) 0x0020) || (*szSearchString >= (WCHAR) MAXCHAR)) {
// Found a non-ASCII character
bRslt = FALSE;
}
szSearchString = CharNext(szSearchString);
}
return bRslt;
}
BOOL
fnIsEditControlASCII(
HWND hWnd,
UINT uResource,
DWORD dwResourceLen
)
/*++
Routine Description:
Checks if an edit control string is composed of only ASCII characters
Arguments:
hWnd - handle to the window
uResource - edit control resource id
dwResourceLen - length of the edit control
Return Value:
TRUE on success
--*/
{
// szResourceString is the edit control string
LPWSTR szResourceString;
BOOL bRslt;
bRslt = TRUE;
// Allocate the memory for the edit control string
szResourceString = MemAllocMacro(dwResourceLen * sizeof(WCHAR));
// Get the edit control string
GetDlgItemText(hWnd, uResource, szResourceString, dwResourceLen);
bRslt = fnIsStringASCII(szResourceString);
MemFreeMacro(szResourceString);
return bRslt;
}
VOID
fnEncodeTsid(
LPWSTR szTsid,
LPWSTR szControlChars,
LPWSTR szEncodedTsid
)
/*++
Routine Description:
Encodes a TSID
Arguments:
szTsid - original TSID
szControlChars - control characters to prepend TSID
szEncodedTsid - encoded TSID
Encoding a TSID is difficult. Each ASCII value of the TSID must fall in the range 32 (0x0020) and 126 (0x009E), a range of 95.
The TSID is encoded as follows:
1) Prepend TSID with the control characters. The control characters are used to verify FaxVrfy sent the fax.
2) Create a random number based on wMilliseconds:
1) wMilliseconds MOD 48 (0x0030): This gives a range of 0 - 48, half the ASCII value range of TSID
2) Add 24 (0x0018): This moves the range to 24 - 72, guaranteeing the ASCII values of the TSID will be changed.
3) Create a shift number based on the random number:
1) wRandomNumber MOD (TSID length / 2): This gives a range of 0 - (TSID length / 2), half the TSID length
2) Add (TSID length / 4): This moves the range to (TSID length / 4) - 3 * (TSID length / 4), guaranteeing the ASCII values of the TSID will be shifted.
4) Create an intermediate string where each ASCII value of the intermediate string is
1) Subtract 32 (0x0020) from each ASCII value of the TSID: This gives a range of 0 - 94.
2) Add the random number
3) MOD 95 (0x005F): This ensures each ASCII value of the intermediate string is in the range 0 - 94.
4) Add 32 (0x0020): This moves the range back to 32 - 126.
5) Create an array of pointers to each ASCII value of the encoded TSID
6) Determine the appropriate offset in the encoded TSID
1) Add the shift number to the current offset
2) MOD (TSID length - wIndex): This ensures the offset is in the range 0 - (number of remaining offsets).
7) Place the next ASCII value of the intermediate string into the appropriate offset in the encoded TSID
8) Compact the remaining offsets of the encoded TSID
9) Repeat steps 6 - 8 until all offsets have been used
10) Create the final encoded string
1) Add 32 (0x0020) to the random number: This ensure the random number is in the range 56 - 104.
2) Set the first character of the encoded string to the ASCII value of the random number.
3) Concatenate the encoded string with the encoded TSID
Return Value:
None
--*/
{
// szControlString is the TSID prepended by the control characters
WCHAR szControlString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szEncodeChar is the encoding character
WCHAR szEncodeChar[ENCODE_CHAR_LEN + 1] = {'\0'};
// szIntermediateString is the intermediate encoded string
WCHAR szIntermediateString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szFinalString is the final encoded string
WCHAR szFinalString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szShiftChars is an array of pointers to each ASCII value of the encoded TSID
LPWSTR szShiftChars[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// SystemTime is the current system time where wMilliseconds is used to generate wRandomNumber and wShiftNumber
SYSTEMTIME SystemTime;
// wRandomNumber is a number to increment each ASCII value of the TSID
WORD wRandomNumber;
// wShiftNumber is a number to shift the order of each ASCII value of the TSID
WORD wShiftNumber;
// wIndex is a counter to enumerate each ASCII value of the TSID
WORD wIndex;
// wOffset is a counter to identify the appropriate offset of the encoded TSID when shifting each ASCII value of the TSID
WORD wOffset;
// wCompact is a counter to compact the remaining offsets of the encoded TSID
WORD wCompact;
// Set szControlString
lstrcpy(szControlString, szControlChars);
lstrcat(szControlString, szTsid);
// Get the current system time
GetSystemTime(&SystemTime);
// Create the random number: (wMilliseconds MOD 48) + 24
wRandomNumber = (SystemTime.wMilliseconds % (WORD) 0x0030) + (WORD) 0x0018;
// Create the shift number: (wRandomNumber MOD (lstrlen(szControlString) / 2)) + (lstrlen(szControlString) / 4)
wShiftNumber = ((wRandomNumber) % ((WORD) lstrlen(szControlString) / 2)) + ((WORD) lstrlen(szControlString) / 4);
// Set szEncodeChar
szEncodeChar[0] = (WCHAR) wRandomNumber + (WCHAR) 0x0020;
for (wIndex = 0; wIndex < (WORD) lstrlen(szControlString); wIndex++) {
// Create the intermediate string: ((ASCII value of the TSID - 32 + wRandomNumber) MOD 95) + 32
szIntermediateString[wIndex] = ((szControlString[wIndex] - (WCHAR) 0x0020 + (WCHAR) wRandomNumber) % (WCHAR) 0x005F) + (WCHAR) 0x0020;
}
for (wIndex = 0; wIndex < (WORD) lstrlen(szIntermediateString); wIndex++) {
// Create the list of remaining offsets of the encoded TSID
szShiftChars[wIndex] = (LPWSTR) ((UINT_PTR) szFinalString + (sizeof(WCHAR) * wIndex));
}
for (wIndex = 0, wOffset = 0; wIndex < (WORD) lstrlen(szIntermediateString); wIndex++) {
// Determine the appropriate offset of the encoded TSID
wOffset = (wOffset + wShiftNumber) % (lstrlen(szIntermediateString) - wIndex);
// Set the appropriate offset of the encoded TSID
*((LPWSTR) szShiftChars[wOffset]) = szIntermediateString[wIndex];
// Compact the remaining offsets of the encoded TSID
for (wCompact = wOffset; wCompact < (lstrlen(szIntermediateString) - wIndex); wCompact++) {
szShiftChars[wCompact] = szShiftChars[wCompact + 1];
}
}
// Set szEncodedTsid
lstrcpy(szEncodedTsid, szEncodeChar);
lstrcat(szEncodedTsid, szFinalString);
}
BOOL
fnDecodeTsid(
LPWSTR szTsid,
LPWSTR szControlChars,
LPWSTR szDecodedTsid
)
/*++
Routine Description:
Decodes a TSID
Arguments:
szTsid - encoded TSID
szControlChars - control characters to prepend TSID
szDecodedTsid - decoded TSID
The TSID is decoded as follows:
1) Isolate the encoded TSID from the random number.
2) Get the random number:
1) The first character in the TSID is the ASCII value of the random number
2) Subtract 32 (0x0020) from the ASCII value to get the random number.
3) Get the shift number based on the random number:
1) wRandomNumber MOD (TSID length / 2): This gives a range of 0 - (TSID length / 2), half the TSID length
2) Add (TSID length / 4): This moves the range to (TSID length / 4) - 3 * (TSID length / 4), guaranteeing the ASCII values of the TSID will be shifted.
4) Create an array of pointers to each ASCII value of the intermediate string
5) Determine the appropriate offset in the intermediate string
1) Add the shift number to the current offset
2) MOD (TSID length - wIndex): This ensures the offset is in the range 0 - (number of remaining offsets).
6) Place the next ASCII value of the encoded TSID into the appropriate offset in the intermediate string
7) Compact the remaining offsets of the intermediate string
8) Repeat steps 6 - 8 until all offsets have been used
9) Create the final string where each ASCII value of the final string is
1) Subtract 32 (0x0020) from each ASCII value of the intermediate string: This gives a range of 0 - 94.
2) Add 95 (0x005F): This ensures each ASCII value will not underflow when subtracting the random number.
3) Subtract the random number
3) MOD 95 (0x005F): This ensures each ASCII value of the intermediate string is in the range 0 - 94.
4) Add 32 (0x0020): This moves the range back to 32 - 126.
10) Create the final decoded string
11) Isolate and compare the control characters
Return Value:
TRUE if control characters match
--*/
{
// szControlString is the TSID prepended by the control characters
WCHAR szControlString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szEncodeChar is the encoding character
WCHAR szEncodeChar[ENCODE_CHAR_LEN + 1] = {'\0'};
// szIntermediateString is the intermediate encoded string
WCHAR szIntermediateString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szFinalString is the final encoded string
WCHAR szFinalString[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// szShiftChars is an array of pointers to each ASCII value of the encoded TSID
LPWSTR szShiftChars[CONTROL_CHAR_LEN + PHONE_NUM_LEN + 1] = {'\0'};
// wRandomNumber is a number to decrement each ASCII value of the encoded TSID
WORD wRandomNumber;
// wShiftNumber is a number to shift the order of each ASCII value of the encoded TSID
WORD wShiftNumber;
// wIndex is a counter to enumerate each ASCII value of the TSID
WORD wIndex;
// wOffset is a counter to identify the appropriate offset of the decoded TSID when shifting each ASCII value of the encoded TSID
WORD wOffset;
// wCompact is a counter to compact the remaining offsets of the decoded TSID
WORD wCompact;
// Get szControlString
lstrcpy(szControlString, (LPWSTR) ((UINT_PTR) szTsid + sizeof(WCHAR)));
// Get szEncodeChar
szEncodeChar[0] = *szTsid;
// Get the random number
wRandomNumber = (WORD) ((WCHAR) szEncodeChar[0] - (WCHAR) 0x0020);
// Create the shift number: (wRandomNumber MOD (lstrlen(szControlString) / 2)) + (lstrlen(szControlString) / 4)
wShiftNumber = ((wRandomNumber) % ((WORD) lstrlen(szControlString) / 2)) + ((WORD) lstrlen(szControlString) / 4);
for (wIndex = 0; wIndex < (WORD) lstrlen(szControlString); wIndex++) {
// Create the list of remaining offsets of the decoded TSID
szShiftChars[wIndex] = (LPWSTR) ((UINT_PTR) szControlString + (sizeof(WCHAR) * wIndex));
}
for (wIndex = 0, wOffset = 0; wIndex < (WORD) lstrlen(szControlString); wIndex++) {
// Determine the appropriate offset of the decoded TSID
wOffset = (wOffset + wShiftNumber) % (lstrlen(szControlString) - wIndex);
// Set the appropriate offset of the decoded TSID
szIntermediateString[wIndex] = *((LPWSTR) szShiftChars[wOffset]);
// Compact the remaining offsets of the decoded TSID
for (wCompact = wOffset; wCompact < (lstrlen(szControlString) - wIndex); wCompact++) {
szShiftChars[wCompact] = szShiftChars[wCompact + 1];
}
}
for (wIndex = 0; wIndex < (WORD) lstrlen(szIntermediateString); wIndex++) {
// Create the final string: ((ASCII value of the TSID - 32 + 95 - wRandomNumber) MOD 95) + 32
szFinalString[wIndex] = ((szIntermediateString[wIndex] - (WCHAR) 0x0020 + (WCHAR) 0x005F - (WCHAR) wRandomNumber) % (WCHAR) 0x005F) + (WCHAR) 0x0020;
}
// Set szDecodedTsid
lstrcpy(szDecodedTsid, (LPWSTR) ((UINT_PTR) szFinalString + lstrlen(szControlChars) * sizeof(WCHAR)));
// Isolate the control characters
lstrcpy((LPWSTR) ((UINT_PTR) szFinalString + lstrlen(szControlChars) * sizeof(WCHAR)), L"\0");
// Compare the control characters
return lstrcmp(szControlChars, szFinalString) ? FALSE : TRUE;
}
#endif