|
|
//
// Unicwrap.cpp
//
// Simple thunking layer for NT/9X.
//
//
#include "stdafx.h"
#define _NO_UNICWRAP_WRAPPERS_
#include "theapp.h"
#include "cstrinout.h"
///////////////////////////////////////////////////////////////////////////
//
// WNET
//
DWORD WNetOpenEnumWrapW(DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum) { ASSERT(sizeof(NETRESOURCEA)==sizeof(NETRESOURCEW));
if (g_fRunningOnNT) { return WNetOpenEnumW(dwScope, dwType, dwUsage, lpNetResource, lphEnum); } else { if (!lpNetResource) { return WNetOpenEnumA(dwScope, dwType, dwUsage, NULL, lphEnum); } else { CStrIn cstrLocalName(lpNetResource->lpLocalName); CStrIn cstrRemoteName(lpNetResource->lpRemoteName); CStrIn cstrComment(lpNetResource->lpComment); CStrIn cstrProvider(lpNetResource->lpProvider); NETRESOURCEA nrA; CopyMemory(&nrA, lpNetResource, sizeof(nrA));
nrA.lpLocalName = cstrLocalName; nrA.lpRemoteName = cstrRemoteName; nrA.lpComment = cstrComment; nrA.lpProvider = cstrProvider;
return WNetOpenEnumA(dwScope, dwType, dwUsage, &nrA, lphEnum); } } }
DWORD WNetEnumResourceWrapW(HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize) { ASSERT((!*lpBufferSize && !lpBuffer) || (*lpBufferSize && lpBuffer));
if (g_fRunningOnNT) { return WNetEnumResourceW(hEnum, lpcCount, lpBuffer, lpBufferSize); } else { DWORD dwRet; LPVOID lpBufferA = NULL; DWORD dwBufferSizeA = (*lpBufferSize) / 2;
if (dwBufferSizeA) { lpBufferA = malloc(dwBufferSizeA); if (!lpBufferA) return ERROR_OUTOFMEMORY; }
dwRet = WNetEnumResourceA(hEnum, lpcCount, lpBufferA, &dwBufferSizeA);
if ((0 == dwRet) || (ERROR_MORE_DATA == dwRet)) { if (lpBufferA) { LPNETRESOURCEW pnrW = (LPNETRESOURCEW)lpBuffer; LPNETRESOURCEA pnrA = (LPNETRESOURCEA)lpBufferA; LPWSTR pwszStrings = (LPWSTR)&pnrW[*lpcCount]; DWORD cchStrings = (*lpBufferSize - (DWORD)((LPBYTE)pwszStrings - (LPBYTE)pnrW)) / sizeof(WCHAR); DWORD i;
// if cchStrings goes to 0 before all strings are copied, pwszStrings points
// one past the buffer length. this case shouldn't happen, but if it does
// we don't want to fault - reduce cchStrings by one so we point to valid memory.
//
cchStrings --; for (i=0 ; i<*lpcCount ; i++) { ASSERT(sizeof(NETRESOURCEW) == sizeof(NETRESOURCEA)); CopyMemory(pnrW, pnrA, sizeof(NETRESOURCEA));
if (pnrA->lpLocalName) { DWORD cch = SHAnsiToUnicode(pnrA->lpLocalName, pwszStrings, cchStrings); pnrW->lpLocalName = pwszStrings; pwszStrings += cch; cchStrings -= cch; } if (pnrA->lpRemoteName) { DWORD cch = SHAnsiToUnicode(pnrA->lpRemoteName, pwszStrings, cchStrings); pnrW->lpRemoteName = pwszStrings; pwszStrings += cch; cchStrings -= cch; } if (pnrA->lpComment) { DWORD cch = SHAnsiToUnicode(pnrA->lpComment, pwszStrings, cchStrings); pnrW->lpComment = pwszStrings; pwszStrings += cch; cchStrings -= cch; } if (pnrA->lpProvider) { DWORD cch = SHAnsiToUnicode(pnrA->lpProvider, pwszStrings, cchStrings); pnrW->lpProvider = pwszStrings; pwszStrings += cch; cchStrings -= cch; }
pnrW++; pnrA++; } // (and null out that memory for the overflow case)
*pwszStrings = TEXTW('\0'); }
*lpBufferSize = dwBufferSizeA * 2 + 1; }
if (lpBufferA) { free(lpBufferA); }
return dwRet; }
return WN_NOT_SUPPORTED; }
DWORD WNetGetUserWrapW(LPCWSTR lpName, LPWSTR lpUserName, LPDWORD lpnLength) { if (g_fRunningOnNT) { return WNetGetUserW(lpName, lpUserName, lpnLength); } else { CStrIn cstrName(lpName); CStrOut cstrUserName(lpUserName, *lpnLength);
// *lpnLength is character count, so no adjustment needed on ERROR_MORE_DATA
return WNetGetUserA(cstrName, cstrUserName, lpnLength); } }
///////////////////////////////////////////////////////////////////////////
//
// RAS
//
// ras structure thunkers
class CRasDialParamsIn { public: CRasDialParamsIn(LPRASDIALPARAMSW pRDP);
void Convert();
operator LPRASDIALPARAMSA() { return _pRDPW ? &_rdp : NULL; };
private:
RASDIALPARAMSA _rdp; LPRASDIALPARAMSW _pRDPW; };
CRasDialParamsIn::CRasDialParamsIn(LPRASDIALPARAMSW pRDP) { _pRDPW = pRDP; _rdp.dwSize = sizeof(_rdp); }
void CRasDialParamsIn::Convert() { if (_pRDPW) { _rdp.dwSize = sizeof(_rdp); SHUnicodeToAnsi(_pRDPW->szEntryName, _rdp.szEntryName, ARRAYSIZE(_rdp.szEntryName)); SHUnicodeToAnsi(_pRDPW->szPhoneNumber, _rdp.szPhoneNumber, ARRAYSIZE(_rdp.szPhoneNumber)); SHUnicodeToAnsi(_pRDPW->szCallbackNumber, _rdp.szCallbackNumber, ARRAYSIZE(_rdp.szCallbackNumber)); SHUnicodeToAnsi(_pRDPW->szUserName, _rdp.szUserName, ARRAYSIZE(_rdp.szUserName)); SHUnicodeToAnsi(_pRDPW->szPassword, _rdp.szPassword, ARRAYSIZE(_rdp.szPassword)); SHUnicodeToAnsi(_pRDPW->szDomain, _rdp.szDomain, ARRAYSIZE(_rdp.szDomain)); } }
class CRasDialParamsOut { public: CRasDialParamsOut(LPRASDIALPARAMSW pRDP) { _pRDPW = pRDP; _rdp.dwSize = sizeof(_rdp); };
void Convert(); void NullOutBuffer();
operator LPRASDIALPARAMSA() { return _pRDPW ? &_rdp : NULL; };
private:
RASDIALPARAMSA _rdp; LPRASDIALPARAMSW _pRDPW; };
void CRasDialParamsOut::Convert() { if (_pRDPW) { ASSERT(_pRDPW->dwSize == sizeof(*_pRDPW)); SHAnsiToUnicode(_rdp.szEntryName, _pRDPW->szEntryName, ARRAYSIZE(_pRDPW->szEntryName)); SHAnsiToUnicode(_rdp.szPhoneNumber, _pRDPW->szPhoneNumber, ARRAYSIZE(_pRDPW->szPhoneNumber)); SHAnsiToUnicode(_rdp.szCallbackNumber, _pRDPW->szCallbackNumber, ARRAYSIZE(_pRDPW->szCallbackNumber)); SHAnsiToUnicode(_rdp.szUserName, _pRDPW->szUserName, ARRAYSIZE(_pRDPW->szUserName)); SHAnsiToUnicode(_rdp.szPassword, _pRDPW->szPassword, ARRAYSIZE(_pRDPW->szPassword)); SHAnsiToUnicode(_rdp.szDomain, _pRDPW->szDomain, ARRAYSIZE(_pRDPW->szDomain)); } }
void CRasDialParamsOut::NullOutBuffer() { if (_pRDPW) { _pRDPW->szEntryName[0] = '\0'; _pRDPW->szPhoneNumber[0] = '\0'; _pRDPW->szCallbackNumber[0] = '\0'; _pRDPW->szUserName[0] = '\0'; _pRDPW->szPassword[0] = '\0'; _pRDPW->szDomain[0] = '\0'; } }
//
// ras function wrappers
//
// Use old size so we work downlevel
#define OLD_RASENTRYNAMEA_SIZE ((DWORD)(&((RASENTRYNAMEA*)NULL)->dwFlags))
DWORD RasEnumEntriesWrapW(LPCWSTR reserved, LPCWSTR pszPhoneBookPath, LPRASENTRYNAMEW pRasEntryNameW, LPDWORD pcb, LPDWORD pcEntries) { ASSERT(NULL==reserved && NULL==pszPhoneBookPath); // we don't thunk these, so make sure we don't call with them
ASSERT(!pRasEntryNameW || *pcb>0); // we're either requesting the size or we have a buffer
if (g_fRunningOnNT) { return RasEnumEntriesW(reserved, pszPhoneBookPath, pRasEntryNameW, pcb, pcEntries); } else { DWORD dwRet = 0; // assume success
DWORD cbA = *pcb / 2; // inverse of below
LPRASENTRYNAMEA pRasEntryNameA = NULL;
// if we're requesting info, allocate an ansi buffer
if (pRasEntryNameW) { pRasEntryNameA = (LPRASENTRYNAMEA)malloc(cbA);
if (pRasEntryNameA) { pRasEntryNameA->dwSize = OLD_RASENTRYNAMEA_SIZE; } else { dwRet = ERROR_NOT_ENOUGH_MEMORY; } } if (0==dwRet) { dwRet = RasEnumEntriesA(NULL, NULL, pRasEntryNameA, &cbA, pcEntries);
// we successfully got info, thunk it back
if (0 == dwRet && pRasEntryNameA) { UINT i;
RASENTRYNAMEA* pRasEntryNameA2 = pRasEntryNameA;
for (i=0 ; i<*pcEntries ; i++) { pRasEntryNameW[i].dwSize = sizeof(pRasEntryNameW[i]); SHAnsiToUnicode(pRasEntryNameA2->szEntryName, pRasEntryNameW[i].szEntryName, ARRAYSIZE(pRasEntryNameW[i].szEntryName)); pRasEntryNameA2 = (RASENTRYNAMEA*)((BYTE*)pRasEntryNameA2 + OLD_RASENTRYNAMEA_SIZE); } }
// allow room for thunking
*pcb = *pcEntries * sizeof(RASENTRYNAMEW); }
if (pRasEntryNameA) free(pRasEntryNameA);
return dwRet; } }
DWORD RasSetEntryDialParamsWrapW(LPCWSTR pszPhonebook, LPRASDIALPARAMSW lpRasDialParamsW, BOOL fRemovePassword) { ASSERT(NULL==pszPhonebook); // we don't thunk this
if (g_fRunningOnNT) { return RasSetEntryDialParamsW(pszPhonebook, lpRasDialParamsW, fRemovePassword); } else { CRasDialParamsIn rdp(lpRasDialParamsW);
rdp.Convert();
return RasSetEntryDialParamsA(NULL, rdp, fRemovePassword); } }
DWORD RasGetEntryDialParamsWrapW(LPCWSTR pszPhonebook, LPRASDIALPARAMSW lpRasDialParamsW, LPBOOL pfRemovePassword) { ASSERT(NULL==pszPhonebook); // we don't thunk this
if (g_fRunningOnNT) { return RasGetEntryDialParamsW(pszPhonebook, lpRasDialParamsW, pfRemovePassword); } else { DWORD dwRet; CRasDialParamsOut rdp(lpRasDialParamsW);
dwRet = RasGetEntryDialParamsA(NULL, rdp, pfRemovePassword);
if (ERROR_SUCCESS == dwRet) { rdp.Convert(); } else { rdp.NullOutBuffer(); }
return dwRet; } }
DWORD RnaGetDefaultAutodialConnectionWrap(LPWSTR szBuffer, DWORD cchBuffer, LPDWORD lpdwOptions) { ASSERT(0 < cchBuffer); ASSERT(cchBuffer <= MAX_PATH); // largest string we thunk
if (!g_fRunningOnNT) { DWORD dwRet;
CStrOut cstroutBuffer(szBuffer, cchBuffer);
dwRet = RnaGetDefaultAutodialConnection(cstroutBuffer, cstroutBuffer.BufSize(), lpdwOptions);
cstroutBuffer.ConvertIncludingNul();
return(dwRet); }
// NT doesn't have an implementation of this function
*lpdwOptions = 0; szBuffer[0] = TEXT('\0');
return 0; }
DWORD RnaSetDefaultAutodialConnectionWrap(LPWSTR szEntry, DWORD dwOptions) { ASSERT(lstrlen(szEntry) < MAX_PATH); // should be valid since we assert this on the Get...
if (!g_fRunningOnNT) { CStrIn cstrinEntry(szEntry); return RnaSetDefaultAutodialConnection(cstrinEntry, dwOptions); }
// NT doesn't have an implementation of this function
return 0; }
//
// PropertySheet wrappers.
//
INT_PTR WINAPI PropertySheetWrapW(LPCPROPSHEETHEADERW ppshW) { INT_PTR iRet;
if (g_fRunningOnNT) { iRet = PropertySheetW(ppshW); } else { //
// Warning! Warning! Warning!
//
// This code assumes that none of the strings in this struct are being
// used. If a string gets used then the structure will have to be
// converted. It also assumes that PROPSHEETHEADERW and
// PROPSHEETHEADERA are the same except for string types.
//
COMPILETIME_ASSERT(sizeof(PROPSHEETHEADERW) == sizeof(PROPSHEETHEADERA));
ASSERT(NULL == ppshW->pszIcon || !(ppshW->dwFlags & PSH_USEICONID) || IS_INTRESOURCE(ppshW->pszIcon)); ASSERT(NULL == ppshW->pszCaption || IS_INTRESOURCE(ppshW->pszCaption)); ASSERT(NULL == ppshW->pStartPage || !(ppshW->dwFlags & PSH_USEPSTARTPAGE) || IS_INTRESOURCE(ppshW->pStartPage)); ASSERT(NULL == ppshW->pszIcon || !(ppshW->dwFlags & PSH_USEICONID) || IS_INTRESOURCE(ppshW->pszIcon)); ASSERT(NULL == ppshW->pszbmWatermark || !(ppshW->dwFlags & PSH_USEHBMWATERMARK) || IS_INTRESOURCE(ppshW->pszbmWatermark)); ASSERT(NULL == ppshW->pszbmHeader || !(ppshW->dwFlags & PSH_USEHBMHEADER) || IS_INTRESOURCE(ppshW->pszbmHeader));
iRet = PropertySheetA((LPCPROPSHEETHEADERA)ppshW); }
return iRet; }
HPROPSHEETPAGE WINAPI CreatePropertySheetPageWrapW(LPCPROPSHEETPAGEW ppspW) { HPROPSHEETPAGE hpspRet;
if (g_fRunningOnNT) { hpspRet = CreatePropertySheetPageW(ppspW); } else { //
// Warning! Warning! Warning!
//
// This code assumes that none of the strings in this struct are being
// used. If a string gets used then the structure will have to be
// converted. It also assumes that PROPSHEETPAGEW and
// PROPSHEETPAGEA are the same except for string types.
//
COMPILETIME_ASSERT(sizeof(PROPSHEETPAGEW) == sizeof(PROPSHEETPAGEA));
ASSERT(NULL == ppspW->pszTemplate || (ppspW->dwFlags & PSP_DLGINDIRECT) || IS_INTRESOURCE(ppspW->pszTemplate)); ASSERT(NULL == ppspW->pszIcon || !(ppspW->dwFlags & PSP_USEICONID) || IS_INTRESOURCE(ppspW->pszIcon)); ASSERT(NULL == ppspW->pszTitle || !(ppspW->dwFlags & PSP_USETITLE) || IS_INTRESOURCE(ppspW->pszTitle)); ASSERT(NULL == ppspW->pszHeaderTitle || !(ppspW->dwFlags & PSP_USEHEADERTITLE) || IS_INTRESOURCE(ppspW->pszHeaderTitle)); ASSERT(NULL == ppspW->pszHeaderSubTitle || !(ppspW->dwFlags & PSP_USEHEADERSUBTITLE) || IS_INTRESOURCE(ppspW->pszHeaderSubTitle));
hpspRet = CreatePropertySheetPageA((LPCPROPSHEETPAGEA)ppspW); }
return hpspRet; }
//
// Miscelaneous APIs that aren't wrapped in shlwapi. Move to shlwapi?
//
UINT WINAPI GlobalGetAtomNameWrapW(ATOM nAtom, LPWSTR lpBuffer, int nSize) { UINT uRet;
if (g_fRunningOnNT) { uRet = GlobalGetAtomNameW(nAtom, lpBuffer, nSize); } else { CStrOut csoBuffer(lpBuffer, nSize);
uRet = GlobalGetAtomNameA(nAtom, csoBuffer, csoBuffer.BufSize()); }
return uRet; }
BOOL WINAPI GetComputerNameWrapW(LPWSTR lpBuffer, LPDWORD pnSize) { BOOL fRet;
if (g_fRunningOnNT) { fRet = GetComputerNameW(lpBuffer, pnSize); } else { CStrOut csoBuffer(lpBuffer, *pnSize); DWORD cch = csoBuffer.BufSize();
fRet = GetComputerNameA(csoBuffer, &cch);
if (fRet && pnSize) { *pnSize = csoBuffer.ConvertExcludingNul(); } }
return fRet; }
BOOL WINAPI SetComputerNameWrapW(LPCWSTR lpComputerName) { BOOL fRet;
if (g_fRunningOnNT) { fRet = SetComputerNameW(lpComputerName); } else { CStrIn csiComputerName(lpComputerName);
fRet = SetComputerNameA(csiComputerName); }
return fRet; }
UINT WINAPI GetDriveTypeWrapW(LPCWSTR lpRootPathName) { UINT uRet;
if (g_fRunningOnNT) { uRet = GetDriveTypeW(lpRootPathName); } else { CStrIn csiRootPathName(lpRootPathName);
uRet = GetDriveTypeA(csiRootPathName); }
return uRet; }
//
// Printer wrappers.
//
class CPrinterEnumIn { public: CPrinterEnumIn(DWORD dwLevel, BYTE* pPrinterEnum, DWORD cbPrinterEnum, DWORD* ppsbNeeded, DWORD* pcPrinters); ~CPrinterEnumIn();
operator BYTE*() {return _pPrinterEnumA;} operator DWORD() {return _cbPrinterEnumA;}
private: void Convert(void); void ConvertStruct(const PRINTER_INFO_5A* ppi5A, PRINTER_INFO_5W* ppi5W, LPWSTR* ppszCurrent, UINT* pcchCurrent); void ConvertStructString(LPCSTR pszA, LPWSTR* ppszDst, LPWSTR* ppszW, UINT* pcchW);
private: BYTE* _pPrinterEnum; DWORD _cbPrinterEnum; DWORD* _pcbNeeded; DWORD* _pcPrinters;
BYTE* _pPrinterEnumA; DWORD _cbPrinterEnumA; };
CPrinterEnumIn::CPrinterEnumIn(DWORD dwLevel, BYTE* pPrinterEnum, DWORD cbPrinterEnum, DWORD* pcbNeeded, DWORD* pcPrinters) { ASSERT(5 == dwLevel); // only level supported.
_pPrinterEnum = pPrinterEnum; _cbPrinterEnum = cbPrinterEnum; _pcbNeeded = pcbNeeded; _pcPrinters = pcPrinters;
if (_cbPrinterEnum) { _pPrinterEnumA = (BYTE*)LocalAlloc(LPTR, _cbPrinterEnum);
_cbPrinterEnumA = _pPrinterEnumA ? _cbPrinterEnum : 0; } else { _pPrinterEnumA = NULL; _cbPrinterEnumA = 0; } }
CPrinterEnumIn::~CPrinterEnumIn() { Convert();
if (_pPrinterEnumA) LocalFree(_pPrinterEnumA); }
void CPrinterEnumIn::Convert() { if (!_pPrinterEnumA) { *_pcbNeeded *= 2; } else { UINT cchCurrent = _cbPrinterEnum > (sizeof(PRINTER_INFO_5) * *_pcPrinters) ? (_cbPrinterEnum - (sizeof(PRINTER_INFO_5) * *_pcPrinters)) / sizeof(WCHAR) : 0;
LPWSTR pszCurrent = cchCurrent ? (LPWSTR)&(((PRINTER_INFO_5*)_pPrinterEnum)[*_pcPrinters]) : NULL;
for (UINT i = 0; i < *_pcPrinters; i++) { ConvertStruct(&((const PRINTER_INFO_5A*)_pPrinterEnumA)[i], &((PRINTER_INFO_5W*)_pPrinterEnum)[i], &pszCurrent, &cchCurrent); } }
return; }
void CPrinterEnumIn::ConvertStruct(const PRINTER_INFO_5A* ppi5A, PRINTER_INFO_5W* ppi5W, LPWSTR* ppszCurrent, UINT* pcchCurrent) { if (ppi5A->pPrinterName && *pcchCurrent) { ConvertStructString(ppi5A->pPrinterName, &ppi5W->pPrinterName, ppszCurrent, pcchCurrent); }
if (ppi5A->pPortName && *pcchCurrent) { ConvertStructString(ppi5A->pPortName, &ppi5W->pPortName, ppszCurrent, pcchCurrent); }
ppi5W->Attributes = ppi5A->Attributes; ppi5W->DeviceNotSelectedTimeout = ppi5A->DeviceNotSelectedTimeout; ppi5W->TransmissionRetryTimeout = ppi5A->TransmissionRetryTimeout;
return; }
void CPrinterEnumIn::ConvertStructString(LPCSTR pszA, LPWSTR* ppszDst, LPWSTR* ppszW, UINT* pcchW) { UINT cch = MultiByteToWideChar(CP_ACP, 0, pszA, -1, *ppszW, *pcchW);
if (cch) { *ppszDst = *ppszW; *pcchW -= cch; *ppszW += cch; } else { *ppszDst = NULL; *pcchW = 0; *ppszW = NULL; }
return; }
BOOL EnumPrintersWrapW(DWORD dwFlags, LPWSTR pszName, DWORD dwLevel, BYTE* pPrinterEnum, DWORD cbPrinterEnum, DWORD* pcbNeeded, DWORD* pcPrinters) { BOOL fRet;
if (g_fRunningOnNT) { fRet = EnumPrintersW(dwFlags, pszName, dwLevel, pPrinterEnum, cbPrinterEnum, pcbNeeded, pcPrinters); } else { CStrIn strName(pszName); CPrinterEnumIn cpeiPrinterEnum(dwLevel, pPrinterEnum, cbPrinterEnum, pcbNeeded, pcPrinters);
fRet = EnumPrintersA(dwFlags, strName, dwLevel, cpeiPrinterEnum, cpeiPrinterEnum, pcbNeeded, pcPrinters); }
return fRet; }
|