C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

■86385 / 4階層)  印刷の設定方法
□投稿者/ 魔界の仮面弁士 (1549回)-(2018/01/25(Thu) 11:26:37)
No86315 (夜叉丸 さん) に返信
> PrintGrid を使用して PrintGrid("一覧表", PrintGridFlags.FitToPage) としています。
PrintGrid って、下記のことですよね。
http://c1.grapecity.com/help/web/winforms/winforms_flexgrid/C1.Win.C1FlexGrid.4~C1.Win.C1FlexGrid.C1FlexGridBase~PrintGrid%28String%2cPrintGridFlags%29.html

FlexGrid / ComponentOne Studio に関する技術的な相談なら、
GrapeCity のサポートに問い合わせた方が良いのでは…?
https://www.grapecity.co.jp/developer/support/technical



No86381 (夜叉丸 さん) に返信
> SHDファイルが作成されました。
> バイナリファイルですよね。

TSXBIN や Stirling といった、構造体の表示に対応した
バイナリエディターを利用すると、解析が楽になるかも知れません。
(といっても、構造体表示のためには定義ファイルを自作する必要があるのですが)


> 中身がわかりませんでした。
http://www.undocprint.org/formats/winspool/shd
https://www.codeproject.com/Articles/9720/The-Windows-NT-print-spool-shadow-file-format


まずは .SHD ファイルの先頭 4 バイトを判断。DWORD dwSignature の部分です。
これが、Jitta さんが述べられた 「シグネチャ(シグニチャ)」に当たります。
>> 最近のだと、シグニチャに SHD_SIGNATURE_WIN2012 があるはずなので、シグニチャの部分は違っているかも。


提示の資料によれば、その値は

68,49,00,00 (0x00004968) なら Windows 2003 フォーマット
67,49,00,00 (0x00004967) なら Windows 2000/XP フォーマット
66,49,00,00 (0x00004966) なら Windows NT フォーマット
4B,49,00,00 (0x0000494B) なら Windows 98 フォーマット

だそうです。ここに無いシグネチャの場合は……私も分かりません。(^^;;

参考までに、手元の環境で実験したところ、
 Server 2012 … 68,49,00,00(0x00004968)
 Windows 7  … 23,51,00,00(0x00005123)
 Win10(1709) … 23,51,00,00(0x00005123)
になっていました。

これにより構造体の種類が分かるので、対応するものを探します。
たとえば 67,49,00,00 あるいは 68,49,00,00 なら、
SHADOW_FILE_HEADER_WIN2000 を参照することになります。


次に問題となるのが、32bit/64bit の判定。

メンバー名の先頭が off で始まるエントリーは、先の資料では DWORD と書かれていますが、
これは C# でいうところの IntPtr 型メンバーであり、実際には構造体のオフセットを示しています。

>> ぱっと見ただけでは32ビットと64ビットの区別が付きません。64ビットの場合、offset の DWORD が QWORD になっているので注意。

たとえば、SHADOW_FILE_HEADER_WIN2000 フォーマットであった場合で言えば、
まずは 32bit フォーマットと仮定して、構造体先頭 20 バイトを読み捨てて、
 DWORD offUserName;   // オフセット[0x0014〜0x0017]
 DWORD offNotifyName;  // オフセット[0x0018〜0x001B]
 DWORD offDocumentName; // オフセット[0x001C〜0x001F]
の位置にある、4 バイトデータ 3 つを読み取っていきます。

この時、offUserName と offDocumentName が ゼロを指していて、
offNotifyName だけに値が入っている場合、このデータは
32bit フォーマットではなく、64bit の可能性が高いので、
 QWORD offUserName;   // オフセット[0x0014〜0x001B]
 QWORD offNotifyName;  // オフセット[0x001C〜0x0023]
 QWORD offDocumentName; // オフセット[0x0024〜0x002B]
に読みかえます。

32bit/64bit どちらの場合でも、これらの値は、
構造体サイズよりも小さな値を指し示すはずです。
(構造体から溢れる値が示されているようなら、解析失敗ということで)


これらのここで示された値は、「構造体の先頭からの相対位置」なので、
そこにあるバイナリを文字列として読み取ります。恐らくは
32bit なら Shift_JIS 相当、64bit なら UTF-16 相当でしょう。

その文字列を目視確認してみて、ユーザー名・通知名・文書名に相当する
内容が書き込まれているようなら、ここまでの解析は成功しているはず。


ここまでで、32bit/64bit のいずれになるのかを判定できたら、
>> この中で、offDevMode の値が、印刷時の設定を記録しているアドレスです。この値まで、ファイルを読み飛ばします。
に進み、DEVMODE 構造体を取り出します。

DEVMODE 構造体の先頭部、すなわち offDevMode が指し示すオフセットアドレスには、
 TCHAR dmDeviceName[CCHDEVICENAME];
があるので視認しやすいかと思います。
ここにあるのはプリンタ名を示した 32 文字の固定長文字列であり、
先ほどと同様、32bit なら Shift_JIS 相当、64bit なら UTF-16 相当です。



>> DEVMODE 構造体が入っているので、読み取り、dmColor を確認します。
>> この値自体は DMCOLOR_COLOR か、DMCOLOR_MONOCHROME のどちらかのはずです。

64 bit 版の .SHD の場合は、「offDevMode の値 + 0x5C」の場所からの 2 バイトを読み取ります。
∵ 64bit 版 DEVMODE では 92 バイト目が「short dmColor」

32bit 版の .SHD の場合は、「offDevMode の値 + 0x3C」の場所からの 2 バイトを読み取ります。
∵ 32bit 版 DEVMODE では 60 バイト目が「short dmColor」


ちなみに
 DMCOLOR_MONOCHROME = 0x0001
 DMCOLOR_COLOR = 0x0002
です。
編集キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←Re[3]: 印刷の設定方法 /夜叉丸 →Re[5]: 印刷の設定方法 /Jitta
 
上記関連ツリー

印刷の設定方法 / 夜叉丸 (18/01/17(Wed) 13:51) #86315
Re[1]: 印刷の設定方法 / Jitta (18/01/19(Fri) 14:25) #86332
  └ Re[2]: 印刷の設定方法 / Jitta (18/01/20(Sat) 09:48) #86338
    └ Re[3]: 印刷の設定方法 / 夜叉丸 (18/01/24(Wed) 12:23) #86381
      ├ Re[4]: 印刷の設定方法 / Jitta (18/01/24(Wed) 21:53) #86382
      └ 印刷の設定方法 / 魔界の仮面弁士 (18/01/25(Thu) 11:26) #86385 ←Now
        └ Re[5]: 印刷の設定方法 / Jitta (18/01/29(Mon) 08:37) #86434
          └ Re[6]: 印刷の設定方法 / 夜叉丸 (18/01/31(Wed) 14:32) #86463
            └ Re[7]: 印刷の設定方法 / PANG2 (18/01/31(Wed) 15:37) #86465
              └ Re[8]: 印刷の設定方法 / 夜叉丸 (18/02/08(Thu) 15:14) #86525 解決済み

上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信