Skip to content

Instantly share code, notes, and snippets.

@meitinger
Last active November 26, 2018 00:05
Show Gist options
  • Save meitinger/fd5d3228c52f2ddc7bb87244afea035f to your computer and use it in GitHub Desktop.
Save meitinger/fd5d3228c52f2ddc7bb87244afea035f to your computer and use it in GitHub Desktop.
Utility that waits for a (redirected) printer to become ready, sets it as default and launches a program.
/* Copyright (C) 2017-2018 Manuel Meitinger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define STRICT
#include <Windows.h>
#pragma comment(linker, "/ENTRY:Run")
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "Winspool.lib")
#define MessageTitle L"..."
#define DefaultPrinterPrefix L"..."
#define NumberOfRetries 100
#define ProgramToRun L"..."
#define DO(what, op) \
if (!(op)) \
{ \
exitCode = GetLastError(); \
MessageBoxW(NULL, L"Cannot " what L".", MessageTitle, MB_OK | MB_ICONERROR); \
goto Cleanup; \
}
void Run(void)
{
UINT exitCode = ERROR_SUCCESS;
DWORD size = 0x1000;
LPPRINTER_INFO_4W printers = NULL;
BOOL found;
INT retry;
DWORD count;
BOOL success;
LPPRINTER_INFO_4W newPrinters;
LPWSTR printer;
INT offset;
LPWSTR cmdLine;
BOOL escaped;
LPWSTR newCmdLine = NULL;
STARTUPINFOW startup;
PROCESS_INFORMATION process = {NULL, NULL};
DO(L"allocate buffer", printers = HeapAlloc(GetProcessHeap(), 0, size));
found = FALSE;
retry = 0;
while (!found && retry < NumberOfRetries)
{
DO(L"query printers", (success = EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, (LPBYTE)printers, size, &size, &count)) || GetLastError() == ERROR_INSUFFICIENT_BUFFER);
if (!success)
{
DO(L"reallocate buffer", newPrinters = HeapReAlloc(GetProcessHeap(), 0, printers, size));
printers = newPrinters;
continue;
}
while (count-- > 0)
{
printer = printers[count].pPrinterName;
offset = 0;
while (DefaultPrinterPrefix[offset] && printer[offset] == DefaultPrinterPrefix[offset])
{
offset++;
}
if (!DefaultPrinterPrefix[offset])
{
SetDefaultPrinterW(printer);
found = TRUE;
break;
}
}
Sleep(1000);
retry++;
}
if (!found)
{
MessageBoxW(NULL, L"Printer not found: " DefaultPrinterPrefix, MessageTitle, MB_OK | MB_ICONWARNING);
}
cmdLine = GetCommandLineW();
escaped = FALSE;
offset = 0;
while (cmdLine[offset])
{
if (cmdLine[offset] == L'"')
{
escaped = !escaped;
}
else if (!escaped && cmdLine[offset] <= L' ')
{
break;
}
offset++;
}
DO(L"allocate cmd line", newCmdLine = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(ProgramToRun) + lstrlenW(cmdLine + offset) + 1) * sizeof(WCHAR)));
DO(L"set application", lstrcpyW(newCmdLine, ProgramToRun));
DO(L"set arguments", lstrcatW(newCmdLine, cmdLine + offset));
SecureZeroMemory(&startup, sizeof(startup));
startup.cb = sizeof(startup);
DO(L"launch program", CreateProcessW(NULL, newCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &process));
DO(L"wait for program", WaitForSingleObject(process.hProcess, INFINITE) == WAIT_OBJECT_0);
Cleanup:
if (process.hThread)
{
CloseHandle(process.hThread);
}
if (process.hProcess)
{
CloseHandle(process.hProcess);
}
if (newCmdLine)
{
HeapFree(GetProcessHeap(), 0, newCmdLine);
}
if (printers)
{
HeapFree(GetProcessHeap(), 0, printers);
}
ExitProcess(exitCode);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment