/******************************************************************** StrAnsiAlloc - allocates or reuses dynamic ANSI string memory NOTE: caller is responsible for freeing ppsz even if function fails ********************************************************************/ extern "C" HRESULT DAPI StrAnsiAlloc( __inout LPSTR* ppsz, __in DWORD_PTR cch ) { Assert(ppsz && cch); HRESULT hr = S_OK; LPSTR psz = NULL; if (cch >= MAXDWORD / sizeof(WCHAR)) { ExitOnFailure1(hr = E_OUTOFMEMORY, "Not enough memory to allocate string of size: %d", cch); } if (*ppsz) psz = static_cast<LPSTR>(MemReAlloc(*ppsz, sizeof(CHAR) * cch, FALSE)); else psz = static_cast<LPSTR>(MemAlloc(sizeof(CHAR) * cch, TRUE)); ExitOnNull1(psz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %d", cch); *ppsz = psz; LExit: return hr; }
static HRESULT CreateSidFromDomainRidPair( PSID pDomainSid, DWORD dwRid, PSID* ppSid ) { HRESULT hr = S_OK; PSID pSid = NULL; // get domain SID sub authority count UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid); // allocate SID buffer DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1); if (*ppSid) { SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid); if (-1 == ccb) ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer"); if (ccb < dwLengthRequired) { pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired); ExitOnNull1(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired); *ppSid = pSid; } } else { *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired); ExitOnNull1(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired); } ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1); // copy sub autorities DWORD i = 0; for (; i < ucSubAuthorityCount; i++) *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i); *::GetSidSubAuthority(*ppSid, i) = dwRid; hr = S_OK; LExit: return hr; }
/******************************************************************** StrAllocStringAnsi - allocates or reuses dynamic string memory and copies in an existing ANSI string NOTE: caller is responsible for freeing ppwz even if function fails NOTE: cchSource must equal the length of wzSource (not including the NULL terminator) NOTE: if cchSource == 0, length of wzSource is used instead ********************************************************************/ extern "C" HRESULT DAPI StrAllocStringAnsi( __inout LPWSTR* ppwz, __in LPCSTR szSource, __in DWORD_PTR cchSource, __in UINT uiCodepage ) { Assert(ppwz && szSource); HRESULT hr = S_OK; LPWSTR pwz = NULL; DWORD_PTR cch = 0; DWORD_PTR cchDest = cchSource; // at least enough if (*ppwz) { cch = MemSize(*ppwz); // get the count in bytes so we can check if it failed (returns -1) if (-1 == cch) { ExitOnFailure(hr = E_INVALIDARG, "failed to get size of destination string"); } cch /= sizeof(WCHAR); //convert the count in bytes to count in characters } if (0 == cchSource) { cchDest = ::MultiByteToWideChar(uiCodepage, 0, szSource, -1, NULL, 0); if (0 == cchDest) { ExitWithLastError1(hr, "failed to get required size for conversion to unicode: %s", szSource); } --cchDest; //subtract one because MultiByteToWideChar includes space for the NULL terminator that we track below } else if (L'\0' == szSource[cchSource]) // if the source already had a null terminator, don't count that in the character count because we track it below { cchDest = cchSource - 1; } if (cch < cchDest + 1) { cch = cchDest + 1; if (cch >= MAXDWORD / sizeof(WCHAR)) { ExitOnFailure1(hr = E_OUTOFMEMORY, "Not enough memory to allocate string of size: %d", cch); } if (*ppwz) { pwz = static_cast<LPWSTR>(MemReAlloc(*ppwz, sizeof(WCHAR) * cch, TRUE)); } else { pwz = static_cast<LPWSTR>(MemAlloc(sizeof(WCHAR) * cch, TRUE)); } ExitOnNull1(pwz, hr, E_OUTOFMEMORY, "failed to allocate string, len: %d", cch); *ppwz = pwz; } if (0 == ::MultiByteToWideChar(uiCodepage, 0, szSource, 0 == cchSource ? -1 : (int)cchSource, *ppwz, (int)cch)) { ExitWithLastError1(hr, "failed to convert to unicode: %s", szSource); } (*ppwz)[cchDest] = L'\0'; LExit: return hr; }
/******************************************************************** CabOperation - helper function that enumerates or extracts files from cabinet NOTE: wzCabinet must be full path to cabinet file wzExtractFile can be a single file id or "*" to extract all files wzExttractDir must be normalized (end in a "\") if pfnBeginFile is NULL pfnEndFile must be NULL and vice versa pfnNotify is callback function to get notified for each file in the cabinet. If it's NULL, files will be extracted. ********************************************************************/ static HRESULT DAPI CabOperation( __in LPCWSTR wzCabinet, __in LPCWSTR wzExtractFile, __in_opt LPCWSTR wzExtractDir, __in_opt CAB_CALLBACK_PROGRESS pfnProgress, __in_opt LPVOID pvContext, __in_opt STDCALL_PFNFDINOTIFY pfnNotify, __in DWORD64 dw64EmbeddedOffset ) { HRESULT hr = S_OK; BOOL fResult; LPWSTR sczCabinet = NULL; LPWSTR pwz = NULL; CHAR szCabDirectory[MAX_PATH * 4]; // Make sure these are big enough for UTF-8 strings CHAR szCabFile[MAX_PATH * 4]; CAB_CALLBACK_STRUCT ccs; PFNFDINOTIFY pfnFdiNotify; // // ensure the cabinet.dll is loaded // if (!vhfdi) { hr = LoadCabinetDll(); ExitOnFailure(hr, "failed to load CABINET.DLL"); } hr = StrAllocString(&sczCabinet, wzCabinet, 0); ExitOnFailure1(hr, "Failed to make copy of cabinet name:%ls", wzCabinet); // // split the cabinet full path into directory and filename and convert to multi-byte (ick!) // pwz = FileFromPath(sczCabinet); ExitOnNull1(pwz, hr, E_INVALIDARG, "failed to process cabinet path: %ls", wzCabinet); if (!::WideCharToMultiByte(CP_UTF8, 0, pwz, -1, szCabFile, countof(szCabFile), NULL, NULL)) { ExitWithLastError1(hr, "failed to convert cabinet filename to ASCII: %ls", pwz); } *pwz = '\0'; // If a full path was not provided, use the relative current directory. if (wzCabinet == pwz) { hr = ::StringCchCopyA(szCabDirectory, countof(szCabDirectory), ".\\"); ExitOnFailure(hr, "Failed to copy relative current directory as cabinet directory."); } else { if (!::WideCharToMultiByte(CP_UTF8, 0, sczCabinet, -1, szCabDirectory, countof(szCabDirectory), NULL, NULL)) { ExitWithLastError1(hr, "failed to convert cabinet directory to ASCII: %ls", sczCabinet); } } // // iterate through files in cabinet extracting them to the callback function // ccs.fStopExtracting = FALSE; ccs.pwzExtract = wzExtractFile; ccs.pwzExtractDir = wzExtractDir; ccs.pfnProgress = pfnProgress; ccs.pvContext = pvContext; vdw64EmbeddedOffset = dw64EmbeddedOffset; // if pfnNotify is given, use it, otherwise use default callback if (NULL == pfnNotify) { pfnFdiNotify = CabExtractCallback; } else { v_pfnNetFx11Notify = pfnNotify; pfnFdiNotify = FDINotify; } fResult = vpfnFDICopy(vhfdi, szCabFile, szCabDirectory, 0, pfnFdiNotify, NULL, static_cast<void*>(&ccs)); if (!fResult && !ccs.fStopExtracting) // if something went wrong and it wasn't us just stopping the extraction, then return a failure { ExitWithLastError1(hr, "failed to extract cabinet file: %ls", sczCabinet); } LExit: ReleaseStr(sczCabinet); v_pfnNetFx11Notify = NULL; return hr; }