1 /* 2 * PROJECT: ReactOS Spooler Router 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Miscellaneous tool functions 5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 6 */ 7 8 #include "precomp.h" 9 10 11 /** 12 * @name PackStrings 13 * 14 * Takes an array of Unicode strings and fills an output buffer with these strings at the end and pointers to each string at specific offsets. 15 * Useful helper for functions that copy an information structure including strings into a given buffer (like PRINTER_INFO_1). 16 * 17 * @param pSource 18 * The array of Unicode strings to copy. Needs to have at least as many elements as the DestOffsets array. 19 * 20 * @param pDest 21 * Pointer to the beginning of the output buffer. 22 * The caller is responsible for verifying that this buffer is large enough to hold all strings and pointers. 23 * 24 * @param DestOffsets 25 * Array of byte offsets in the output buffer. For each element of DestOffsets, the function will copy the address of the corresponding copied 26 * string of pSource to this location in the output buffer. If a string in pSource is NULL, the function will set the pointer address to NULL 27 * in the output buffer. 28 * Use macros like FIELD_OFFSET to calculate the offsets for this array. 29 * The last element of the array must have the value MAXDWORD to let the function detect the end of the array. 30 * 31 * @param pEnd 32 * Pointer to the end of the output buffer. That means the first element outside of the buffer given in pDest. 33 * 34 * @return 35 * Returns a pointer to the beginning of the strings in pDest. 36 * The strings are copied in reverse order, so this pointer will point to the last copied string of pSource. 37 */ 38 PBYTE WINAPI 39 PackStrings(PWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd) 40 { 41 DWORD cbString; 42 ULONG_PTR StringAddress; 43 44 // Loop until we reach an element with offset set to MAXDWORD. 45 while (*DestOffsets != MAXDWORD) 46 { 47 StringAddress = 0; 48 49 if (*pSource) 50 { 51 // Determine the length of the source string. 52 cbString = (wcslen(*pSource) + 1) * sizeof(WCHAR); 53 54 // Copy it before the last string. 55 pEnd -= cbString; 56 StringAddress = (ULONG_PTR)pEnd; 57 CopyMemory(pEnd, *pSource, cbString); 58 } 59 60 // Copy the address of the copied string to the location given by the offset. 61 CopyMemory(&pDest[*DestOffsets], &StringAddress, sizeof(ULONG_PTR)); 62 63 // Advance to the next source string and destination offset. 64 pSource++; 65 DestOffsets++; 66 } 67 68 // pEnd is now at the last string we copied. Return this value as a pointer to the beginning of all strings in the output buffer. 69 return pEnd; 70 } 71