SUPPORT.CPP
/////////////////////////////////////////////////////////////////////////////// 
// 
//  File Name  
//      SUPPORT.CPP 
// 
//  Description 
//      Support functions for remote admin program. 
// 
//  Author 
//      Irving De la Cruz 
//       
//  Revision: 1.7 
// 
// Written for Microsoft Windows Developer Support 
// Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved. 
// 
#include "_WINDS.H" 
 
/////////////////////////////////////////////////////////////////////////////// 
//    ReleaseSyncObj() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
// 
void WINAPI ReleaseSyncObj() 
{ 
    DeleteCriticalSection (&g_csIOInfo); 
    DeleteCriticalSection (&g_csPipeID); 
    DeleteCriticalSection (&g_csNotifLinks); 
    DeleteCriticalSection (&g_csServiceState); 
    CloseHandle (g_IOInfo.hResumeEvent); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    LoadSettingsFromRegistry() 
// 
//    Parameters 
//      None 
// 
//    Purpose 
//      This function is used to load the application setting structure values 
//      from the registry under a subkey for our application. The entire data 
//      structure is read from a single sub entry as an array of binary data, 
//      unreadable to humans. 
//       
//    Return Value 
//      None 
//       
void WINAPI LoadSettingsFromRegistry() 
{ 
    HKEY hAppKey; 
    // Try to open the key in the registry, open it with READ rights, 
    // and read the data into our strcture 
    if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, 
                                       WINDS_SERVICE_REGISTRY_KEY, 
                                       0, 
                                       KEY_READ, 
                                       &hAppKey)) 
    { 
        ULONG cbSize = MAX_PATH*sizeof(TCHAR); 
        DWORD dwError = RegQueryValueEx (hAppKey, 
                                         DATA_FILE_SUB_KEY, 
                                         NULL, 
                                         NULL, 
                                         (LPBYTE)g_szDataFile, 
                                         &cbSize); 
        RegCloseKey (hAppKey); 
        // If we failed to get the data from the registry we can't return 
        // yet, we will proceed to initialize the options with default 
        // values 
        if (ERROR_SUCCESS == dwError) 
        { 
            return; 
        } 
    } 
    // If we couldn't read the file name, then initialize to default values 
    lstrcpy (g_szDataFile, TEXT(".\\WINDS.DAT")); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    SaveSettingsToRegistry() 
// 
//    Parameters 
//      None 
// 
//    Purpose 
//      This function is used to save the settings structure values to the 
//      registry under a subkey for our application. The key where we write 
//      the values is created if it doesn't exist. The entire structure data 
//      is written to a single sub entry as an array of binary data, 
//      unreadable to humans. 
//       
//    Return Value 
//      None 
//       
void WINAPI SaveSettingsToRegistry() 
{ 
    HKEY hAppKey; 
    DWORD dwDisposition = MAX_PATH*sizeof(TCHAR); 
    // Try to open the key in the registry, open it with READ/WRITE rights 
    if (ERROR_SUCCESS != RegCreateKeyEx (HKEY_LOCAL_MACHINE, 
                                         WINDS_SERVICE_REGISTRY_KEY, 
                                         0, 
                                         NULL, 
                                         REG_OPTION_NON_VOLATILE, 
                                         KEY_WRITE, 
                                         NULL, 
                                         &hAppKey, 
                                         &dwDisposition)) 
    { 
        // If we fail to access the registry, we need to get out, we don't 
        // have a key opened where to write 
        TraceResult ("SaveSettingsToRegistry: Failed to open app key", HRESULT_FROM_WIN32(GetLastError())); 
    } 
    else 
    { 
        // With the opened key handle, create a sub entry where we save our 
        // structure values. For this sample we just write the entire 
        // structure as a big blob of data, which we read the save way. 
        if (ERROR_SUCCESS != RegSetValueEx (hAppKey, 
                                            DATA_FILE_SUB_KEY, 
                                            0, 
                                            REG_SZ, 
                                            (LPBYTE)g_szDataFile, 
                                            (lstrlen (g_szDataFile)+1)*sizeof(TCHAR))) 
        { 
            TraceResult ("SaveSettingsToRegistry: Failed to save registry values", HRESULT_FROM_WIN32(GetLastError())); 
        } 
        // Close the handle we have open and return the appropiate flag 
        RegCloseKey (hAppKey); 
    } 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    GetLocalTempFileName() 
// 
//    Parameters 
//      pszFileName     Pointer to a buffer allocated by the caller where the 
//                      function returns a fully qualified patha and file for 
//                      a uniquely named temporary file name. 
// 
//    Purpose 
//      This function creates a temporary file name. The file name will be 
//      returned in the pszFileName buffer which must have been allocated by 
//      the caller. The file will have a fully qualified path to its location. 
//      The location of the file is on the TEMP directory as set in the system. 
// 
//    Return Value 
//      0 if the function is successful at creating a temporary 
//      unique file name. A system error code otherwise. 
// 
HRESULT WINAPI GetLocalTempFileName(LPTSTR pszFileName) 
{ 
    HRESULT hResult = S_OK; 
    TCHAR szTmpPath[_MAX_PATH]; 
 
    // Ask the system for the TEMP directory 
    if (!GetTempPath (_MAX_PATH, szTmpPath)) 
    { 
        hResult = HRESULT_FROM_WIN32(GetLastError()); 
        TraceResult ("GetLocalTempFileName: Failed to get temp path", hResult); 
        return hResult; 
    } 
 
    if (!GetTempFileName (szTmpPath,        // Call the Win32 API 
                          TEXT("WDS"),      // Our fixed prefix for temp files 
                          0,                // Use a pseudo-unique number 
                          pszFileName))     // Destination buffer 
    { 
        hResult = HRESULT_FROM_WIN32(GetLastError()); 
        TraceResult ("GetLocalTempFileName: Failed to get temp file name", hResult); 
    } 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    FileCopy() 
// 
//    Parameters                         
//      hDest           handle to destination file/stream 
//      hSrc            handle to source file/stream 
//      dwMsgLen        number of bytes to copy 
// 
//    Purpose 
//      Copies bytes from one open file or stream object to another file 
//      stream object. 
//       
//    Return Value 
//      NO_ERROR on success, ERROR_READ/WRITE_FAULT otherwise 
//       
long WINAPI FileCopy(HANDLE hDest, HANDLE hSrc, DWORD dwMsgLen) 
{ 
    BYTE  buf[IO_BUFFERSIZE];  
    DWORD nRead, nRemaining = dwMsgLen; 
    BOOL  bRes; 
    for (DWORD nWritten=0; nRemaining>0; nRemaining -= nWritten) 
    { 
        bRes = ReadFile (hSrc, buf, min(nRemaining, (DWORD)IO_BUFFERSIZE), &nRead, NULL); 
        if (!nRead || !bRes) 
        { 
            return HRESULT_FROM_WIN32(ERROR_READ_FAULT); 
        } 
        bRes = WriteFile(hDest, buf, nRead, &nWritten, NULL); 
        if (!nWritten || !bRes) 
        { 
            return HRESULT_FROM_WIN32(ERROR_WRITE_FAULT); 
        } 
    } 
    return NO_ERROR; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    WaitForClientConnection() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
// 
long WINAPI WaitForClientConnection (HANDLE hPipe, DWORD dwTimeOut) 
{ 
    dwTimeOut *= 1000; // The timeout value comes is seconds so we must convert them to milliseconds. 
 
    long lResult = 0; 
    BOOL bResult; 
    OVERLAPPED ovWait = { 0 }; 
    ovWait.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); 
    if (NULL == ovWait.hEvent) 
    { 
        lResult = HRESULT_FROM_WIN32(GetLastError()); 
        TraceResult ("WaitForClientConnection: Failed to create wait event", lResult); 
    } 
    else 
    { 
        bResult = ConnectNamedPipe (hPipe, &ovWait); 
        if (FALSE == bResult) 
        { 
            lResult = HRESULT_FROM_WIN32(GetLastError()); 
            if (HRESULT_FROM_WIN32(lResult) == HRESULT_FROM_WIN32(ERROR_IO_PENDING) || 
                HRESULT_FROM_WIN32(lResult) == HRESULT_FROM_WIN32(ERROR_PIPE_CONNECTED)) 
            { 
                lResult = S_OK; 
            } 
        } 
        if (!lResult) 
        { 
            lResult = WaitForSingleObject (ovWait.hEvent, dwTimeOut); 
            if (WAIT_OBJECT_0 == lResult) 
            { 
                lResult = 0; // No error; 
            } 
            else 
            { 
                TraceMessage ("WaitForClientConnection: Client did not connect. Timeout"); 
                lResult = HRESULT_FROM_WIN32(ERROR_PIPE_NOT_CONNECTED); 
            } 
        } 
        else 
        { 
            lResult = HRESULT_FROM_WIN32(GetLastError()); 
            TraceResult ("WaitForClientConnection: Failed to wait for connection", lResult); 
        } 
        CloseHandle (ovWait.hEvent); 
    } 
    return lResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    AnsiToUnicode() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      None. 
// 
HRESULT WINAPI AnsiToUnicode (LPSTR   szStr, 
                              LPWSTR  wcStr, 
                              ULONG   cchUnicode) 
{ 
    HRESULT hResult = S_OK; 
    // Do we have a string to duplicate? 
    if (!szStr || !wcStr) 
    { 
        TraceMessage ("AnsiToUnicode: NULL string pointers"); 
        return E_INVALIDARG; 
    } 
    int iChars = MultiByteToWideChar (CP_ACP, 
                                      MB_PRECOMPOSED, 
                                      szStr, 
                                      -1, 
                                      wcStr, 
                                      cchUnicode); 
    if (0 == iChars) 
    { 
        hResult = HRESULT_FROM_WIN32(GetLastError()); 
        TraceResult ("AnsiToUnicode: Failed tp convert to UNICODE", hResult); 
    } 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    UnicodeToAnsi() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      None. 
// 
HRESULT WINAPI UnicodeToAnsi (LPWSTR  wcStr, 
                              LPSTR   szStr, 
                              ULONG   cchAnsi) 
{ 
    HRESULT hResult = S_OK; 
    // Do we have a string to duplicate? 
    if (!szStr || !wcStr) 
    { 
        TraceMessage ("UnicodeToAnsi: NULL string pointers"); 
        return E_INVALIDARG; 
    } 
    int iChars = WideCharToMultiByte (CP_ACP, 
                                      0, 
                                      wcStr, 
                                      -1, 
                                      szStr, 
                                      cchAnsi, 
                                      NULL, 
                                      NULL); 
    if (0 == iChars) 
    { 
        hResult = HRESULT_FROM_WIN32(GetLastError()); 
        TraceResult ("UnicodeToAnsi: Failed tp convert to UNICODE", hResult); 
    } 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    GetNextPipeID() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
// 
DWORD WINAPI GetNextPipeID() 
{ 
    DWORD dwPipeID; 
    EnterCriticalSection (&g_csPipeID); 
    if (g_dwNextPipeID > MAX_PIPE_NUMBER) 
    { 
        g_dwNextPipeID = MIN_PIPE_NUMBER; 
    } 
    dwPipeID = g_dwNextPipeID; 
    g_dwNextPipeID++; 
    LeaveCriticalSection (&g_csPipeID); 
    return dwPipeID; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::CObjectList() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      None. 
// 
CObjectList::CObjectList() 
{ 
    TraceMessage ("CObjectList: Constructor called"); 
    m_hHeap = GetProcessHeap(); 
    m_pHead = NULL; 
    InitializeCriticalSection (&m_csObj); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::~CObjectList() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      None. 
// 
CObjectList::~CObjectList() 
{ 
    TraceMessage ("CObjectList: Destructor called"); 
    // Free the entire list 
    POBJLIST_NODE pNode = m_pHead; 
    while (m_pHead) 
    { 
        pNode = m_pHead->pNext; 
        HeapFree (m_hHeap, 0, m_pHead); 
        m_pHead = pNode; 
    } 
    DeleteCriticalSection (&m_csObj); 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::Insert() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CObjectList::Insert (DWORD             dwObjID, 
                                  LPTSTR            pObjName, 
                                  WINDS_AB_OBJTYPE  ObjType) 
{ 
    // Allocate a new node 
    POBJLIST_NODE pNode, pNewNode = (POBJLIST_NODE)HeapAlloc (m_hHeap, 
                                                              HEAP_ZERO_MEMORY, 
                                                              sizeof(OBJLIST_NODE)); 
    if (NULL == pNewNode) 
    { 
        TraceResult ("CObjectList::Insert: Failed to allocate new node", E_OUTOFMEMORY); 
        return E_OUTOFMEMORY; 
    } 
    // Copy the data of the node 
    // pNewNode->pNext = NULL; <- implied in the allocation 
    pNewNode->dwObjID = dwObjID; 
    pNewNode->ObjType = ObjType; 
    lstrcpy (pNewNode->szObjAlias, pObjName); 
     
    EnterCriticalSection (&m_csObj); 
    // Insert the node at the end of the list 
    if (m_pHead) 
    { 
        pNode = m_pHead; 
        while (m_pHead) 
        { 
            if (NULL == pNode->pNext) 
            { 
                pNode->pNext = pNewNode; 
                break; // Out of the WHILE() loop 
            } 
            pNode = pNode->pNext; 
        } 
    } 
    else 
    { 
        m_pHead = pNewNode; 
    } 
    LeaveCriticalSection (&m_csObj); 
    return S_OK; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::Delete() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CObjectList::Delete (DWORD dwObjID) 
{ 
    HRESULT hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 
    EnterCriticalSection (&m_csObj); 
    POBJLIST_NODE pNext, pPrev = NULL, pNode = m_pHead; 
    while (pNode) 
    { 
        if (pNode->dwObjID == dwObjID) 
        { 
            // If the node is the head of the list, make the head point to the next node 
            if (m_pHead == pNode) 
            { 
                m_pHead = m_pHead->pNext; 
            } 
            // Save the next pointer so that we may delete the current node 
            pNext = pNode->pNext; 
            HeapFree (m_hHeap, 0, pNode); 
            if (pPrev) 
            { 
                pPrev->pNext = pNext; 
            } 
            hResult = S_OK; 
            break; // Out of the WHILE() loop 
        } 
        else 
        { 
            pPrev = pNode; 
            pNode = pNode->pNext; 
        } 
    } 
    LeaveCriticalSection (&m_csObj); 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::FindObjFromID() 
// 
//    Parameters 
//       
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CObjectList::FindObjFromID (DWORD              dwObjID, 
                                         LPTSTR             pObjName, 
                                         WINDS_AB_OBJTYPE * pObjType) 
{ 
    HRESULT hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 
    EnterCriticalSection (&m_csObj); 
    POBJLIST_NODE pNode = m_pHead; 
    while (pNode) 
    { 
        if (pNode->dwObjID == dwObjID) 
        { 
            *pObjType = pNode->ObjType; 
            lstrcpy (pObjName, pNode->szObjAlias); 
            hResult = S_OK;  
            break; // Out of the WHILE() loop 
        } 
        pNode = pNode->pNext; 
    } 
    LeaveCriticalSection (&m_csObj); 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::FindObjFromName() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CObjectList::FindObjFromName (WINDS_AB_OBJTYPE     ObjType, 
                                           LPTSTR               pObjName, 
                                           DWORD *              pdwObjID) 
{ 
    HRESULT hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 
    EnterCriticalSection (&m_csObj); 
    POBJLIST_NODE pNode = m_pHead; 
    while (pNode) 
    { 
        if (pNode->ObjType == ObjType && 0 == lstrcmpi (pNode->szObjAlias, pObjName)) 
        { 
            *pdwObjID = pNode->dwObjID; 
            hResult = S_OK; 
            break; // Out of the WHILE() loop 
        } 
        pNode = pNode->pNext; 
    } 
    LeaveCriticalSection (&m_csObj); 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::FindObjAndTypeFromName() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
STDMETHODIMP CObjectList::FindObjAndTypeFromName (LPTSTR               pObjName, 
                                                  WINDS_AB_OBJTYPE *   pObjType, 
                                                  DWORD *              pdwObjID) 
{ 
    HRESULT hResult = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 
    EnterCriticalSection (&m_csObj); 
    POBJLIST_NODE pNode = m_pHead; 
    while (pNode) 
    { 
        if (0 == lstrcmpi (pNode->szObjAlias, pObjName)) 
        { 
            *pObjType = pNode->ObjType; 
            *pdwObjID = pNode->dwObjID; 
            hResult = S_OK; 
            break; // Out of the WHILE() loop 
        } 
        pNode = pNode->pNext; 
    } 
    LeaveCriticalSection (&m_csObj); 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CObjectList::IsAliasNameAvailable() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
//      An HRESULT 
// 
BOOL WINAPI CObjectList::IsAliasNameAvailable (LPTSTR pObjName) 
{ 
    BOOL bResult = TRUE; 
    EnterCriticalSection (&m_csObj); 
    POBJLIST_NODE pNode = m_pHead; 
    while (pNode) 
    { 
        if (0 == lstrcmpi (pNode->szObjAlias, pObjName)) 
        { 
            bResult = FALSE; 
            break; // Out of the WHILE() loop 
        } 
        pNode = pNode->pNext; 
    } 
    LeaveCriticalSection (&m_csObj); 
    return bResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CreateDLsDirectory() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
// 
HRESULT WINAPI CreateDLsDirectory (LPSTORAGE pStorage) 
{ 
    LPSTORAGE pPFStg; 
    HRESULT hResult = pStorage->CreateStorage (DISTRIBUTION_LISTS, CREATE_FLAGS, 0, 0, &pPFStg); 
    if (!hResult) 
    { 
        pPFStg->Release(); 
    } 
    return hResult; 
} 
 
/////////////////////////////////////////////////////////////////////////////// 
//    CreatePublicFoldersDirectory() 
// 
//    Parameters 
// 
//    Purpose 
// 
//    Return Value 
// 
HRESULT WINAPI CreatePublicFoldersDirectory (LPSTORAGE pStorage) 
{ 
    LPSTORAGE pPFStg; 
    HRESULT hResult = pStorage->CreateStorage (PUBLIC_FOLDERS_ROOT, CREATE_FLAGS, 0, 0, &pPFStg); 
    if (!hResult) 
    { 
        pPFStg->Release(); 
    } 
    return hResult; 
} 
 
// End of file for SUPPORT.CPP