title: AddJob + SetPrinter: is it possible to set dmCopies and get effect?
body: <p>What I need is to re-print spooled file (not job*) again, setting a new amount of copies.</p>
  
  <p>So far following attempts were tried:</p>
  
  <ul>
  <li>OpenPrinter, AddJob, SetJob (with JOB_INFO_2->pDevMode)</li>
  <li>OpenPrinter, SetPrinter, DocumentProperties, AddJob, SetJob</li>
  <li>OpenPrinter, StartDocPrinter, StartPagePrinter, WritePrinter</li>
  </ul>
  
  <p>Numerous ClosePrinter combinations and a number of workarounds for SetPrinter..DocumentProperties part - no success.</p>
  
  <p>Changing printers (HP to Brother), restarting spooler and PC - no effect.</p>
  
  <p>It can be seen in the print jobs list, that a number of copies is set. However, what I get out of printer is one copy.</p>
  
  <p>Also, <code>pDevMode-&gt;dmFields</code> is set with <code>|= DM_COPIES</code> in all relevant cases.</p>
  
  <p>So now, is there any effective route to set a number of copies, possibly other params (collate) and print a raw PCL/PS document without going GDI or printing the job numerous times?</p>
  
  <pre><code>#include "006_pclblacky_t.h"
  #define PNAME L"HP"
  
  t_006pclblacky::t_006pclblacky()
  {
          settings.color.set = false;
          settings.copies.set = false;
          settings.ori.set = false;
          settings.paper.set = false;
  }
  
  
  t_006pclblacky::~t_006pclblacky()
  {
  }
  
  int t_006pclblacky::Run()
  {
          int rc = 0;
  
          rc = subtest_001();
          if (rc != 0) return rc;
  
          return 0;
  
  }
  
  void t_006pclblacky::defaults() {
  }
  
  void t_006pclblacky::GetJobInfo(int JobId)
  {
          HANDLE ph;
          DOC_INFO_1 di1;
          DWORD dwRead, dwWritten;
          DWORD x,y,z;
          int rc;
          PRINTER_DEFAULTSW Defaults = { NULL, NULL, PRINTER_ALL_ACCESS};
          OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
  
  
          try {
                  rc = GetJob(ph, JobId, 1, NULL, 0, &amp;x);
                  if (rc != 122 &amp;&amp; x &lt; 1) {
                          assert(122 == 0);
                  }
          } catch (...) {
                  assert(1 == 0);
          }
  
          JOB_INFO_1 *jg1 = (JOB_INFO_1*)malloc(x);
          try {
                  GetJob(ph, JobId, 1, (LPBYTE)jg1, x, &amp;y);
          } catch (...) {
                  assert(1 == 0);
          }
  
          jg1-&gt;TotalPages = 2;
  
  
          rc = SetJob(ph, JobId, 1, (LPBYTE)jg1, JOB_CONTROL_PAUSE);
          assert (rc &gt; 0);
          rc = GetLastError();
  
          try {
                  if (GetJob(ph, JobId, 2, NULL, 0, &amp;x) != 122 &amp;&amp; x &lt; 1) {
                          assert(122 == 0);
                  }
          } catch (...) {
                  assert(1 == 0);
          }
          //jg1-&gt;PagesPrinted = 1;
  
          JOB_INFO_2 *jg2 = (JOB_INFO_2*)malloc(x);
          try {
                  GetJob(ph, JobId, 2, (LPBYTE)jg2, x, &amp;y);
          } catch (...) {
                  assert(1 == 0);
          }
  }
  
  
  void t_006pclblacky::SendFileToPrinter(LPCWSTR fileName, LPWSTR docName)
  {
  
          HANDLE ph;
          DOC_INFO_1 di1;
          DWORD dwRead, dwWritten;
  
  
          std::ifstream file(fileName, ios::in | ios::binary | ios::ate);
          std::ifstream::pos_type fileSize;
          char* fileContents;
          int rc;
          PRINTER_DEFAULTSW Defaults = { NULL, NULL, PRINTER_ALL_ACCESS};
          LPDEVMODE devmOld = NULL;
          OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
  
          di1.pDatatype = L"RAW"; // IsV4Driver("Printer Name") ? "XPS_PASS" : "RAW";
          di1.pDocName = docName;
          di1.pOutputFile = NULL;
  
          fileSize = file.tellg();
          if (fileSize &lt; 1) {
                  return;
          }
  
          fileContents = new char[fileSize];
          file.seekg(0, ios::beg);
          if (!file.read(fileContents, fileSize))
          {
          assert(0 == 1);
          }
  
          dwRead = fileSize;
  
          if (!settings.ori.set &amp;&amp; !settings.color.set &amp;&amp; !settings.copies.set &amp;&amp; !settings.paper.set) {
                  StartDocPrinter(ph, 1, (LPBYTE)&amp;di1);
  
                  StartPagePrinter(ph);
  
                  if (file.is_open())
                  {
                          WritePrinter(ph, fileContents, dwRead, &amp;dwWritten);
                          file.close();
                  }
                  else {
                          assert(0 == 1);
                  }
  
                  EndPagePrinter(ph);
  
                  EndDocPrinter(ph);
          } else {
                  devmOld = GetPrinterParams(ph);
                  ClosePrinter(ph);
                  Defaults.pDevMode = devmOld;
                  OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
                  //ClosePrinter(ph);
                  //OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
                  SetPrinterParams(ph);
                  //ClosePrinter(ph);
                  //OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
  
                  int tsz = sizeof(ADDJOB_INFO_1)+MAX_PATH+1;
                  ADDJOB_INFO_1 *aji = (ADDJOB_INFO_1*)malloc(tsz);
                  DWORD d = 0;
                  rc = AddJob(ph, 1, (LPBYTE)aji, tsz, &amp;d);
                  if (rc == 0) {
                          rc = GetLastError();
                  }
                  assert (aji-&gt;JobId != 0);
  
                  DWORD x,y,z;
  
                  try {
                          rc = GetJob(ph, aji-&gt;JobId, 1, NULL, 0, &amp;x);
                          if (rc != 122 &amp;&amp; x &lt; 1) {
                                  assert(122 == 0);
                          }
                  } catch (...) {
                          assert(1 == 0);
                  }
  
                  JOB_INFO_1 *jg1 = (JOB_INFO_1*)malloc(x);
                  try {
                          GetJob(ph, aji-&gt;JobId, 1, (LPBYTE)jg1, x, &amp;y);
                  } catch (...) {
                          assert(1 == 0);
                  }
  
                  /*JOB_INFO_1 *ji1 = (JOB_INFO_1*)malloc(sizeof(JOB_INFO_1));
                  ji1-&gt;pDatatype = L"RAW";
                  ji1-&gt;pPrinterName = jg1-&gt;pPrinterName;
                  ji1-&gt;TotalPages = 2; // test
                  ji1-&gt;pDocument = jg1-&gt;pDocument;
                  ji1-&gt;pMachineName = jg1-&gt;pMachineName;
                  ji1-&gt;pUserName = jg1-&gt;pUserName;*/
                  jg1-&gt;TotalPages = 1;
                  jg1-&gt;pDocument = docName;
  
  
                  rc = SetJob(ph, aji-&gt;JobId, 1, (LPBYTE)jg1, JOB_CONTROL_PAUSE);
                  assert (rc &gt; 0);
                  rc = GetLastError();
  
                  try {
                          if (GetJob(ph, aji-&gt;JobId, 2, NULL, 0, &amp;x) != 122 &amp;&amp; x &lt; 1) {
                                  assert(122 == 0);
                          }
                  } catch (...) {
                          assert(1 == 0);
                  }
                  jg1-&gt;PagesPrinted = 2;
                  jg1-&gt;TotalPages = 2;
  
                  JOB_INFO_2 *jg2 = (JOB_INFO_2*)malloc(x);
                  try {
                          GetJob(ph, aji-&gt;JobId, 2, (LPBYTE)jg2, x, &amp;y);
                  } catch (...) {
                          assert(1 == 0);
                  }
                  /*JOB_INFO_2 *ji2 = (JOB_INFO_2*)malloc(sizeof(JOB_INFO_2));
                  ji2-&gt;pDevMode = (PDEVMODE)malloc(sizeof(DEVMODE));
                  ji2-&gt;pDevMode-&gt;dmPaperSize = settings.paper.val;
                  ji2-&gt;pDatatype = L"RAW";
                  ji2-&gt;pPrinterName = jg2-&gt;pPrinterName;
                  ji2-&gt;TotalPages = 2;
                  */
  
                  DWORD dmf = jg2-&gt;pDevMode-&gt;dmFields;
                  dmf = DM_COLLATE;
  
  
                  if (settings.copies.set) {
                          if (! jg2-&gt;pDevMode-&gt;dmFields &amp; DM_COPIES) {
                                  jg2-&gt;pDevMode-&gt;dmFields |= DM_COPIES;
                          }
                          jg2-&gt;pDevMode-&gt;dmCopies = settings.copies.val;
                  }
                  if (settings.color.set) {
                          jg2-&gt;pDevMode-&gt;dmColor = settings.color.val;
                          jg2-&gt;pDevMode-&gt;dmFields |= DM_COLOR;
                  }
                  if (settings.ori.set) {
                          jg2-&gt;pDevMode-&gt;dmOrientation = settings.ori.val;
                          jg2-&gt;pDevMode-&gt;dmFields |= DM_ORIENTATION;
                  }
                  if (settings.paper.set) {
                          jg2-&gt;pDevMode-&gt;dmPaperSize = settings.paper.val;
                          jg2-&gt;pDevMode-&gt;dmFields |= DM_PAPERSIZE;
                  }
                  jg2-&gt;TotalPages = 2;
                  jg2-&gt;PagesPrinted = 2;
                  // Çàïèñàòü ôàéë çàäàíèÿ
                  std::ofstream file2(aji-&gt;Path, ios::out | ios::binary | ios::ate);
                  file2.write(fileContents, fileSize);
                  file2.flush();
                  file2.close();
  
                  rc = SetJob(ph, aji-&gt;JobId, 2, (LPBYTE)jg2, JOB_CONTROL_RESTART);
                  assert(rc &gt; 0);
                  rc = GetLastError();
                  GetJob(ph, aji-&gt;JobId, 2, (LPBYTE)jg2, x, &amp;y);
  
                  ScheduleJob(ph, aji-&gt;JobId);
          }
  
          if (devmOld != NULL) {
                  ClosePrinter(ph);
                  OpenPrinter(PNAME, &amp;ph, &amp;Defaults);
                  RestorePrinterParams(ph, devmOld);
          }
  
          ClosePrinter(ph);
  }
  
  int t_006pclblacky::subtest_001()
  {
          defaults();
          SetCopies(2);
          SetOrientation(2);
          SendFileToPrinter(L"test.pcl", L"test.pcl");
  }
  
          return rc;
  }
  
  t_006pclblacky* t_006pclblacky::SetOrientation(int i)
  {
          this-&gt;settings.ori.set = true;
          this-&gt;settings.ori.val = i;
          return this;
  }
  t_006pclblacky* t_006pclblacky::SetColor(int i)
  {
          this-&gt;settings.color.set = true;
          this-&gt;settings.color.val = i;
          return this;
  }
  t_006pclblacky* t_006pclblacky::SetCopies(int i)
  {
          this-&gt;settings.copies.set = true;
          this-&gt;settings.copies.val = i;
          return this;
  }
  
  t_006pclblacky* t_006pclblacky::SetPaperSize(int i)
  {
          this-&gt;settings.paper.set = true;
          this-&gt;settings.paper.val = i;
          return this;
  }
  
  void t_006pclblacky::SetPrinterParams(HANDLE ph)
  { // http://www.rsdn.ru/forum/dotnet/4070489.flat
          // http://www.codeproject.com/Articles/132365/Configuring-Printer-Settings-Programmatically
  
          DWORD dwNeeded, dwNeeded2;
          int rc = GetPrinter(ph, 2, 0, 0, &amp;dwNeeded);
          if (rc != 0 || (rc == 0 &amp;&amp; dwNeeded &gt; 0 &amp;&amp; dwNeeded &lt; 10240 /* TODO magic? */)) {
                  PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR,dwNeeded);
                  GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &amp;dwNeeded);
           // check that the driver supports the changes
  
                  int x = DocumentProperties(NULL, ph, PNAME, NULL, pi2-&gt;pDevMode, DM_OUT_BUFFER);
          //        LPDEVMODE y = (LPDEVMODE)malloc(x);
  //
          //        rc = DocumentProperties(NULL, ph, PNAME, NULL, y, DM_OUT_BUFFER);
  
                  AffectDevMode(pi2-&gt;pDevMode);
                  //pi2-&gt;pDevMode = y;
                  pi2-&gt;pSecurityDescriptor = 0;
  
                  ::DocumentProperties (NULL, ph, PNAME, NULL, pi2-&gt;pDevMode, DM_IN_BUFFER);
                  rc = SetPrinter(ph, 2, (LPBYTE)pi2, 0);
          }
  
  
          rc = GetPrinter(ph, 2, 0, 0, &amp;dwNeeded2);
          if (rc != 0 || (rc == 0 &amp;&amp; dwNeeded2 &gt; 0 &amp;&amp; dwNeeded2 &lt; 10240 /* TODO magic? */)) {
                  PRINTER_INFO_2 *pi3 = (PRINTER_INFO_2 *)::GlobalAlloc(GPTR,dwNeeded2);
                  GetPrinter(ph, 2, (LPBYTE)pi3, dwNeeded, &amp;dwNeeded);
                  assert(pi3-&gt;pDevMode-&gt;dmCopies &gt; 1);
          }
  
  }
  
  void t_006pclblacky::RestorePrinterParams(HANDLE ph, LPDEVMODE old)
  {
          DWORD dwNeeded;
          GetPrinter(ph, 2, 0, 0, &amp;dwNeeded);
          PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR,dwNeeded);
          GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &amp;dwNeeded);
  
          if (settings.copies.set) {
  
                  pi2-&gt;pDevMode-&gt;dmCopies = old-&gt;dmCopies;
          }
          if (settings.color.set) {
                  pi2-&gt;pDevMode-&gt;dmColor = old-&gt;dmColor;
          }
          if (settings.ori.set) {
                  pi2-&gt;pDevMode-&gt;dmOrientation = old-&gt;dmOrientation;
          }
          if (settings.paper.set) {
                  pi2-&gt;pDevMode-&gt;dmPaperSize = old-&gt;dmPaperSize;
          }
          //ClosePrinter(ph);
  }
  
  void t_006pclblacky::AffectDevMode(LPDEVMODE dm)
  {
  /* if(dm-&gt;dmFields &amp; DM_PAPERSIZE )
  {
                  // define the page size as A3
  dm-&gt;dmPaperSize = DMPAPER_A3;
                  // define, which field was changed
  dm-&gt;dmFields |= DM_PAPERSIZE;
          }*/
  
          if (settings.copies.set) {
                  if (! dm-&gt;dmFields &amp; DM_COPIES) {
                          dm-&gt;dmFields |= DM_COPIES;
                  }
                  dm-&gt;dmCopies = settings.copies.val;
          }
          if (settings.color.set) {
                  dm-&gt;dmColor = settings.color.val;
                  dm-&gt;dmFields |= DM_COLOR;
          }
          if (settings.ori.set) {
                  dm-&gt;dmOrientation = settings.ori.val;
                  dm-&gt;dmFields |= DM_ORIENTATION;
          }
          if (settings.paper.set) {
                  dm-&gt;dmPaperSize = settings.paper.val;
                  dm-&gt;dmFields |= DM_PAPERSIZE;
          }
  
  
  }
  
  LPDEVMODE t_006pclblacky::GetPrinterParams(HANDLE ph)
  {
          LPDEVMODE out;
          DWORD dwNeeded;
          GetPrinter(ph, 2, 0, 0, &amp;dwNeeded);
          PRINTER_INFO_2 *pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR,dwNeeded);
          GetPrinter(ph, 2, (LPBYTE)pi2, dwNeeded, &amp;dwNeeded);
  
          DWORD lNeeded = pi2-&gt;pDevMode-&gt;dmSize + pi2-&gt;pDevMode-&gt;dmDriverExtra;
          out = (LPDEVMODEW) malloc(lNeeded);
          memcpy(out, pi2-&gt;pDevMode, lNeeded);
  
  //        ClosePrinter(ph);
  
          return out;
  } 
  </code></pre>