void testDestEnd(){ wchar_t dest[11]; wchar_t * destEnd; diag("Test calculation of destEnd."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), &destEnd, NULL, 0, L"Data")), "Test calculation of destEnd " "while printing short string."); is_wstring(L"Data", dest, "Result of printing short string."); ok(destEnd == &dest[4], "Value of destEnd after printing short string."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), &destEnd, NULL, 0, L"")), "Test calculation of destEnd " "while printing empty string."); is_wstring(L"", dest, "Result of printing empty string."); ok(destEnd == &dest[0], "Value of destEnd after printing empty string."); ok(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), &destEnd, NULL, 0, L"longer %ls", L"string") == STRSAFE_E_INSUFFICIENT_BUFFER, "Test calculation of destEnd " "while printing a too long string."); is_wstring(L"longer str", dest, "Result of printing a too long string."); ok(destEnd == &dest[10], "Value of destEnd after printing a too long string."); }
void testRemaining(){ wchar_t dest[11]; size_t remaining; diag("Test calculation of remaining space."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, &remaining, 0, L"STR")), "Test calculation of remaining space " "while printing short string."); is_wstring(L"STR", dest, "Result of printing short string."); is_int(8 * sizeof(wchar_t), remaining, "Number of remaining characters after printing short string."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, &remaining, 0, L"")), "Test calculation of remaining space " "while printing empty string."); is_wstring(L"", dest, "Result of printing empty string."); is_int(11 * sizeof(wchar_t), remaining, "Number of remaining characters after printing empty string."); ok(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, &remaining, 0, L"too long string") == STRSAFE_E_INSUFFICIENT_BUFFER, "Test calculation of remaining space " "while printing a too long string."); is_wstring(L"too long s", dest, "Result of printing a too long string."); is_int(1 * sizeof(wchar_t), remaining, "Number of remaining characters after printing " "a too long string."); }
static VOID pLoadImageFromNode(SHIMGVW_FILENODE *node, HWND hwnd) { WCHAR szTitleBuf[800]; WCHAR szResStr[512]; WCHAR *c; if (node) { c = wcsrchr(node->FileName, '\\'); if (c) { c++; } LoadStringW(hInstance, IDS_APPTITLE, szResStr, 512); StringCbPrintfExW(szTitleBuf, 800, NULL, NULL, 0, L"%ls%ls%ls", szResStr, L" - ", c); SetWindowTextW(hwnd, szTitleBuf); if (image) { GdipDisposeImage(image); } pLoadImage(node->FileName); InvalidateRect(hDispWnd, NULL, TRUE); UpdateWindow(hDispWnd); } }
int main(void){ wchar_t dest[11]; plan(31); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, 0, L"test")), "Print short string without any extended functionality."); is_wstring(L"test", dest, "Result of printing short string."); testDestEnd(); testRemaining(); testFlags(); return 0; }
static void pSaveImageAs(HWND hwnd) { OPENFILENAMEW sfn; ImageCodecInfo *codecInfo; WCHAR szSaveFileName[MAX_PATH]; WCHAR *szFilterMask; GUID rawFormat; UINT num; UINT size; UINT sizeRemain; UINT j; WCHAR *c; GdipGetImageEncodersSize(&num, &size); codecInfo = malloc(size); if (!codecInfo) { DPRINT1("malloc() failed in pSaveImageAs()\n"); return; } GdipGetImageEncoders(num, size, codecInfo); GdipGetImageRawFormat(image, &rawFormat); sizeRemain = 0; for (j = 0; j < num; ++j) { // Every pair needs space for the Description, twice the Extensions, 1 char for the space, 2 for the braces and 2 for the NULL terminators. sizeRemain = sizeRemain + (((wcslen(codecInfo[j].FormatDescription) + (wcslen(codecInfo[j].FilenameExtension) * 2) + 5) * sizeof(WCHAR))); } /* Add two more chars for the last terminator */ sizeRemain = sizeRemain + (sizeof(WCHAR) * 2); szFilterMask = malloc(sizeRemain); if (!szFilterMask) { DPRINT1("cannot allocate memory for filter mask in pSaveImageAs()"); free(codecInfo); return; } ZeroMemory(szSaveFileName, sizeof(szSaveFileName)); ZeroMemory(szFilterMask, sizeRemain); ZeroMemory(&sfn, sizeof(sfn)); sfn.lStructSize = sizeof(sfn); sfn.hwndOwner = hwnd; sfn.hInstance = hInstance; sfn.lpstrFile = szSaveFileName; sfn.lpstrFilter = szFilterMask; sfn.nMaxFile = MAX_PATH; sfn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY; c = szFilterMask; for (j = 0; j < num; ++j) { StringCbPrintfExW(c, sizeRemain, &c, &sizeRemain, 0, L"%ls (%ls)", codecInfo[j].FormatDescription, codecInfo[j].FilenameExtension); /* Skip the NULL character */ c++; sizeRemain -= sizeof(*c); StringCbPrintfExW(c, sizeRemain, &c, &sizeRemain, 0, L"%ls", codecInfo[j].FilenameExtension); /* Skip the NULL character */ c++; sizeRemain -= sizeof(*c); if (IsEqualGUID(&rawFormat, &codecInfo[j].FormatID) == TRUE) { sfn.nFilterIndex = j + 1; } } if (GetSaveFileNameW(&sfn)) { if (GdipSaveImageToFile(image, szSaveFileName, &codecInfo[sfn.nFilterIndex - 1].Clsid, NULL) != Ok) { DPRINT1("GdipSaveImageToFile() failed\n"); } } free(szFilterMask); free(codecInfo); }
static SHIMGVW_FILENODE* pBuildFileList(LPWSTR szFirstFile) { HANDLE hFindHandle; WCHAR *extension; WCHAR szSearchPath[MAX_PATH]; WCHAR szSearchMask[MAX_PATH]; WCHAR szFileTypes[MAX_PATH]; WIN32_FIND_DATAW findData; SHIMGVW_FILENODE *currentNode; SHIMGVW_FILENODE *root; SHIMGVW_FILENODE *conductor; ImageCodecInfo *codecInfo; UINT num; UINT size; UINT j; wcscpy(szSearchPath, szFirstFile); PathRemoveFileSpecW(szSearchPath); GdipGetImageDecodersSize(&num, &size); codecInfo = malloc(size); if (!codecInfo) { DPRINT1("malloc() failed in pLoadFileList()\n"); return NULL; } GdipGetImageDecoders(num, size, codecInfo); root = malloc(sizeof(SHIMGVW_FILENODE)); if (!root) { DPRINT1("malloc() failed in pLoadFileList()\n"); free(codecInfo); return NULL; } conductor = root; for (j = 0; j < num; ++j) { StringCbPrintfExW(szFileTypes, MAX_PATH, NULL, NULL, 0, L"%ls", codecInfo[j].FilenameExtension); extension = wcstok(szFileTypes, L";"); while (extension != NULL) { StringCbPrintfExW(szSearchMask, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", extension); hFindHandle = FindFirstFileW(szSearchMask, &findData); if (hFindHandle != INVALID_HANDLE_VALUE) { do { StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", findData.cFileName); // compare the name of the requested file with the one currently found. // if the name matches, the current node is returned by the function. if (wcscmp(szFirstFile, conductor->FileName) == 0) { currentNode = conductor; } conductor->Next = malloc(sizeof(SHIMGVW_FILENODE)); // if malloc fails, make circular what we have and return it if (!conductor->Next) { DPRINT1("malloc() failed in pLoadFileList()\n"); conductor->Next = root; root->Prev = conductor; FindClose(hFindHandle); free(codecInfo); return conductor; } conductor->Next->Prev = conductor; conductor = conductor->Next; } while (FindNextFileW(hFindHandle, &findData) != 0); FindClose(hFindHandle); } extension = wcstok(NULL, L";"); } } // we now have a node too much in the list. In case the requested file was not found, // we use this node to store the name of it, otherwise we free it. if (currentNode == NULL) { StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls", szFirstFile); currentNode = conductor; } else { conductor = conductor->Prev; free(conductor->Next); } // link the last node with the first one to make the list circular conductor->Next = root; root->Prev = conductor; conductor = currentNode; free(codecInfo); return conductor; }
void testFlags(){ wchar_t dest[11]; wchar_t * wanted; diag("Test the STRSAFE_IGNORE_NULLS flag."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, STRSAFE_IGNORE_NULLS, NULL)), "Test printing a NULL string."); is_wstring(L"", dest, "Result of printing a NULL string."); diag("Test the STRSAFE_FILL_BEHIND_NULL flag."); ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, STRSAFE_FILL_BEHIND_NULL | '@', L"testing")), "Test filling with '@' behind null termination."); is_wstring(L"testing", dest, "Result of printing and filling behind null termination."); wanted = malloc(3 * sizeof(wchar_t)); if(wanted == NULL){ bail("Memory allocation failed."); } memset(wanted, '@', 3 * sizeof(wchar_t)); ok(memcmp(&dest[8], wanted, 3 * sizeof(wchar_t)) == 0, "Correct data filled after null termination."); free(wanted); diag("Test the STRSAFE_FILL_ON_FAILURE flag."); ok(FAILED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, STRSAFE_FILL_ON_FAILURE | '@', L"too much data")), "Test filling with '@' on failure."); wanted = malloc(11 * sizeof(wchar_t)); if(wanted == NULL){ bail("Memory allocation failed."); } memset(wanted, '@', 10 * sizeof(wchar_t)); wanted[10] = L'\0'; ok(memcmp(dest, wanted, 11 * sizeof(wchar_t)) == 0, "Result of filling with '@' on failure."); free(wanted); diag("Test the STRSAFE_NULL_ON_FAILURE flag."); ok(FAILED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, STRSAFE_NULL_ON_FAILURE, L"Also too much")), "Test nulling string on failure."); is_wstring(L"", dest, "Result when nulling string on failure."); diag("Test the STRSAFE_NO_TRUNCATION flag."); ok(FAILED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t), NULL, NULL, STRSAFE_NO_TRUNCATION, L"Won't fit in dest")), "Test printing with truncating disabled."); is_wstring(L"", dest, "Result after printing with truncating disabled."); }
int vswprintfex( wchar_t *buffer, int buffersize, const wchar_t *format, va_list argList ) { int ptr=0; const wchar_t* in=format; LPWSTR end; int nNextArg=0,index,length; while (*in!='\0') { if (*in=='%') { in++; // Finding first non number for(index=0;in[index]>=L'0' && in[index]<=L'9';index++); // Now index points to nonnumberic character if (in[index]==L':') { // ok number was argument place if (index==0) return 0; nNextArg=_wtoi(in); // finding next '%' in+=index+1; for (length=0;in[length]!=L'\0' && in[length]!=L'%';length++); wchar_t* pTemp=new wchar_t[length+2]; pTemp[0]=L'%'; MemCopyW(pTemp+1,in,length); pTemp[length+1]=L'\0'; HRESULT hRes=StringCbPrintfExW(buffer+ptr,(buffersize-ptr)*sizeof(wchar_t),&end, NULL,STRSAFE_IGNORE_NULLS,pTemp,va_getarg(argList,nNextArg)); if (FAILED(hRes)) return 0; ptr=int(end-buffer); delete[] pTemp; if (in[length]==L'\0') break; in+=length; } else { nNextArg++; for (;in[index]!=L'\0' && in[index]!=L'%';index++); wchar_t* pTemp=new wchar_t[index+2]; pTemp[0]='%'; MemCopyW(pTemp+1,in,index); pTemp[index+1]=L'\0'; HRESULT hRes=StringCbPrintfExW(buffer+ptr,(buffersize-ptr)*sizeof(wchar_t),&end, NULL,STRSAFE_IGNORE_NULLS,pTemp,va_getarg(argList,nNextArg)); if (FAILED(hRes)) return 0; ptr=int(end-buffer); delete[] pTemp; if (in[index]==L'\0') break; in+=index; } } else buffer[ptr++]=*(in++); } buffer[ptr]='\0'; return ptr; }
VOID __fastcall HashSaveWorkerMain( PHASHSAVECONTEXT phsctx ) { // Note that ALL message communication to and from the main window MUST // be asynchronous, or else there may be a deadlock. // Prep: expand directories, max path, etc. (prefix was set by earlier call) PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, TRUE); if (! HashCalcPrepare(phsctx)) return; HashCalcSetSaveFormat(phsctx); PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, FALSE); // Extract the slist into a vector for parallel_for_each std::vector<PHASHSAVEITEM> vecpItems; vecpItems.resize(phsctx->cTotal + 1); SLBuildIndex(phsctx->hList, (PVOID*)vecpItems.data()); assert(vecpItems.back() == nullptr); vecpItems.pop_back(); assert(vecpItems.back() != nullptr); #ifdef USE_PPL const bool bMultithreaded = vecpItems.size() > 1 && IsSSD(vecpItems[0]->szPath); concurrency::concurrent_vector<void*> vecBuffers; // a vector of all allocated read buffers (one per thread) DWORD dwBufferTlsIndex = TlsAlloc(); // TLS index of the current thread's read buffer if (dwBufferTlsIndex == TLS_OUT_OF_INDEXES) return; #else constexpr bool bMultithreaded = false; #endif PBYTE pbTheBuffer; // file read buffer, used iff not multithreaded if (! bMultithreaded) { pbTheBuffer = (PBYTE)VirtualAlloc(NULL, READ_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE); if (pbTheBuffer == NULL) return; } // Initialize the progress bar update synchronization vars CRITICAL_SECTION updateCritSec; volatile ULONGLONG cbCurrentMaxSize = 0; if (bMultithreaded) InitializeCriticalSection(&updateCritSec); #ifdef _TIMED DWORD dwStarted; dwStarted = GetTickCount(); #endif class CanceledException {}; // concurrency::parallel_for_each(vecpItems.cbegin(), vecpItems.cend(), ... auto per_file_worker = [&](PHASHSAVEITEM pItem) { WHCTXEX whctx; // Indicate which hash type we are after, see WHEX... values in WinHash.h whctx.dwFlags = 1 << (phsctx->ofn.nFilterIndex - 1); PBYTE pbBuffer; #ifdef USE_PPL if (bMultithreaded) { // Allocate or retrieve the already-allocated read buffer for the current thread pbBuffer = (PBYTE)TlsGetValue(dwBufferTlsIndex); if (pbBuffer == NULL) { pbBuffer = (PBYTE)VirtualAlloc(NULL, READ_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE); if (pbBuffer == NULL) throw CanceledException(); // Cache the read buffer for the current thread vecBuffers.push_back(pbBuffer); TlsSetValue(dwBufferTlsIndex, pbBuffer); } } #endif #pragma warning(push) #pragma warning(disable: 4700 4703) // potentially uninitialized local pointer variable 'pbBuffer' used // Get the hash WorkerThreadHashFile( (PCOMMONCONTEXT)phsctx, pItem->szPath, &whctx, &pItem->results, bMultithreaded ? pbBuffer : pbTheBuffer, NULL, 0, bMultithreaded ? &updateCritSec : NULL, &cbCurrentMaxSize #ifdef _TIMED , &pItem->dwElapsed #endif ); if (phsctx->status == PAUSED) WaitForSingleObject(phsctx->hUnpauseEvent, INFINITE); if (phsctx->status == CANCEL_REQUESTED) throw CanceledException(); // Write the data HashCalcWriteResult(phsctx, pItem); // Update the UI InterlockedIncrement(&phsctx->cSentMsgs); PostMessage(phsctx->hWnd, HM_WORKERTHREAD_UPDATE, (WPARAM)phsctx, (LPARAM)pItem); }; #pragma warning(pop) try { #ifdef USE_PPL if (bMultithreaded) concurrency::parallel_for_each(vecpItems.cbegin(), vecpItems.cend(), per_file_worker); else #endif std::for_each(vecpItems.cbegin(), vecpItems.cend(), per_file_worker); } catch (CanceledException) {} // ignore cancellation requests #ifdef _TIMED if (phsctx->cTotal > 1 && phsctx->status != CANCEL_REQUESTED) { union { CHAR szA[MAX_STRINGMSG]; WCHAR szW[MAX_STRINGMSG]; } buffer; size_t cbBufferLeft; if (phsctx->opt.dwSaveEncoding == 1) // UTF-16 { StringCbPrintfExW(buffer.szW, sizeof(buffer), NULL, &cbBufferLeft, 0, L"; Total elapsed: %d ms\r\n", GetTickCount() - dwStarted); } else // UTF-8 or ANSI { StringCbPrintfExA(buffer.szA, sizeof(buffer), NULL, &cbBufferLeft, 0, "; Total elapsed: %d ms\r\n", GetTickCount() - dwStarted); } DWORD dwUnused; WriteFile(phsctx->hFileOut, buffer.szA, (DWORD) (sizeof(buffer) - cbBufferLeft), &dwUnused, NULL); } #endif #ifdef USE_PPL if (bMultithreaded) { for (void* pBuffer : vecBuffers) VirtualFree(pBuffer, 0, MEM_RELEASE); DeleteCriticalSection(&updateCritSec); } else #endif VirtualFree(pbTheBuffer, 0, MEM_RELEASE); }