[PATCH] winspool: implement EnumFormsA/W for form level 1, add a few builtin forms
Marcel Partap
mpartap at gmx.net
Sun Dec 9 12:48:46 CST 2007
---
dlls/winspool.drv/info.c | 269 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 263 insertions(+), 6 deletions(-)
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index 236d77d..27fd31d 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -139,6 +139,25 @@ typedef struct {
LPCWSTR versionsubdir;
} printenv_t;
+/* ############ FORMS ############ */
+typedef struct {
+ SIZEL size;
+ RECTL area;
+ DWORD formorder;
+ DWORD flags;
+} form_regentry_t;
+
+struct builtin_form {
+ WCHAR formname[CCHFORMNAME];
+ form_regentry_t formdata;
+};
+
+static const struct builtin_form builtin_forms[] = {
+ {{'L','e','t','t','e','r',0}, {{216000,279000}, {0,0,216000,279000}, 0, FORM_BUILTIN}},
+ {{'A','3',0}, {{297000,420000}, {0,0,297000,420000}, 0, FORM_BUILTIN}},
+ {{'A','4',0}, {{210000,297000}, {0,0,210000,297000}, 0, FORM_BUILTIN}},
+ {{'A','5',0}, {{148000,210000}, {0,0,148000,210000}, 0, FORM_BUILTIN}} };
+
/* ############################### */
static struct list monitor_handles = LIST_INIT( monitor_handles );
@@ -163,6 +182,12 @@ static const WCHAR DriversW[] = { 'S','y','s','t','e','m','\\',
'E','n','v','i','r','o','n','m','e','n','t','s','\\',
'%','s','\\','D','r','i','v','e','r','s','%','s',0 };
+static const WCHAR FormsW[] = { 'S','y','s','t','e','m','\\',
+ 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
+ 'c','o','n','t','r','o','l','\\',
+ 'P','r','i','n','t','\\',
+ 'F','o','r','m','s',0 };
+
static const WCHAR MonitorsW[] = { 'S','y','s','t','e','m','\\',
'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'C','o','n','t','r','o','l','\\',
@@ -6991,25 +7016,257 @@ BOOL WINAPI DeletePrintProvidorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPrin
}
/******************************************************************************
+ * calculate needed size then write form to provided buffer if big enough (INTERNAL)
+ */
+static void write_form_to_buffer(LPWSTR formname, const form_regentry_t *databuffer, DWORD formnumber, LPBYTE *pBuffer, LPBYTE *strptr, DWORD cbBuf, DWORD *needed, BOOL unicode)
+{
+ DWORD forminfosize = sizeof(FORM_INFO_1W);
+ DWORD formnamesize;
+ PFORM_INFO_1W pFI;
+
+ if (unicode) formnamesize = (strlenW(formname)+1)*sizeof(WCHAR);
+ else formnamesize = WideCharToMultiByte(CP_ACP, 0, formname, -1, NULL, 0, NULL, NULL);
+ *needed += formnamesize + forminfosize;
+
+ /* don't write beyond buffer size */
+ if (*pBuffer && cbBuf >= *needed)
+ {
+ pFI = (PFORM_INFO_1W)*pBuffer;
+ if (unicode)
+ {
+ TRACE("%p: writing FORM_INFO_1W #%d\n", *pBuffer, formnumber);
+ lstrcpyW((LPWSTR)*strptr, formname);
+ }
+ else
+ {
+ TRACE("%p: writing FORM_INFO_1A #%d\n", *pBuffer, formnumber);
+ WideCharToMultiByte(CP_ACP, 0, formname, -1, (LPSTR)*strptr, formnamesize, NULL, NULL);
+ }
+
+ /* FORM_INFO_1A/W identical except type of string pName points to */
+ pFI->pName = (LPWSTR)*strptr;
+ pFI->Size = databuffer->size;
+ pFI->ImageableArea = databuffer->area;
+ /* there are two incarnations of form registry entries (with and without DWORD formorder) */
+ /* Wine uses only the former one but handle the other one by offsetting flags by one DWORD */
+ pFI->Flags = (sizeof(form_regentry_t) == sizeof(form_regentry_t)) ? databuffer->flags : databuffer->formorder;
+ }
+ *pBuffer += forminfosize;
+ *strptr += formnamesize;
+}
+
+/*****************************************************************************
+ * enumerate the local forms (INTERNAL)
+ *
+ * returns the needed size (in bytes) for pForm
+ * and *lpreturned is set to number of entries returned in pForm
+ *
+ *NOTES:
+ * fixme: level 2 support missing
+ */
+static DWORD get_local_forms(DWORD level, LPBYTE pForm, DWORD cbBuf, LPDWORD lpreturned, BOOL unicode)
+{
+ HKEY hformskey = NULL;
+ INT i;
+ DWORD index = 0;
+ DWORD needed = 0;
+ WCHAR formname[CCHFORMNAME+1];
+ DWORD formnamelen = sizeof(formname);
+ DWORD forminfosize;
+ DWORD buffersize = sizeof(form_regentry_t);
+ LPBYTE strptr;
+ DWORD regtype;
+ DWORD numentries;
+ form_regentry_t databuffer;
+
+ /* sizeof(FORM_INFO_1A) equals sizeof(FORM_INFO_1W) */
+ forminfosize = sizeof(FORM_INFO_1W);
+
+ /* set string pointer to after calculated size of form structures */
+ numentries = *lpreturned;
+ strptr = pForm + numentries * forminfosize;
+
+ /* create the "Forms"-key if non-existent and receive a handle to it */
+ if (RegCreateKeyW(HKEY_LOCAL_MACHINE, FormsW, &hformskey) == ERROR_SUCCESS)
+ {
+ /* handle built-in forms */
+ numentries = sizeof(builtin_forms)/sizeof(builtin_forms[0]);
+ for (i = 0; i < numentries; i++) {
+ write_form_to_buffer(builtin_forms[i].formname, &builtin_forms[i].formdata, i, &pForm, &strptr, cbBuf, &needed, unicode);
+ }
+ /* scan and spit out all form entries */
+ while (RegEnumValueW(hformskey, index, formname, &formnamelen, NULL,
+ ®type, (LPBYTE)&databuffer, &buffersize) == ERROR_SUCCESS)
+ {
+ if (formname[0])
+ {
+ numentries++;
+ write_form_to_buffer(formname, &databuffer, numentries, &pForm, &strptr, cbBuf, &needed, unicode);
+ }
+ index++;
+ formnamelen = sizeof(formname);
+ buffersize = sizeof(form_regentry_t);
+ }
+ RegCloseKey(hformskey);
+ }
+ *lpreturned = numentries;
+ TRACE("returned %d byte for %d entries\n", needed, numentries);
+ return needed;
+}
+
+/******************************************************************************
* EnumFormsA (WINSPOOL.@)
+ * same as EnumFormsW except unicode = FALSE
*/
BOOL WINAPI EnumFormsA( HANDLE hPrinter, DWORD Level, LPBYTE pForm,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned )
{
- FIXME("%p %x %p %x %p %p\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD needed = 0;
+ DWORD numentries = 0;
+ BOOL res = FALSE;
+ opened_printer_t *printer = NULL;
+
+ TRACE("(hPrinter = %p, Level = %d, pForm = %p, cbBuf = %u, pcbNeeded = %p, pcReturned = %p) called\n",
+ hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
+
+ /* fixme: if valid ignore hPrinter: return all forms for every printer */
+ if (!(printer = get_opened_printer(hPrinter)))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ goto efA_cleanup;
+ }
+
+ /* valid levels are 1 and 2*/
+ if (Level != 2 && Level != 1)
+ {
+ SetLastError(ERROR_INVALID_LEVEL);
+ goto efA_cleanup;
+ }
+
+ if (Level == 2)
+ {
+ FIXME("level 2 not yet supported\n");
+ SetLastError(ERROR_INVALID_LEVEL);
+ goto efA_cleanup;
+ }
+
+ /* Scan all Forms */
+ numentries = 0;
+ needed = get_local_forms(Level, NULL, 0, &numentries, FALSE);
+
+ /* we calculated the needed buffersize. now do the error-checks */
+ if (cbBuf < needed)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto efA_cleanup;
+ }
+ if (!pForm)
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ goto efA_cleanup;
+ }
+ if (!pcbNeeded || !pcReturned)
+ {
+ SetLastError(RPC_X_NULL_REF_POINTER);
+ goto efA_cleanup;
+ }
+
+ /* fill the Buffer with the forminfos*/
+ if ((needed = get_local_forms(Level, pForm, cbBuf, &numentries, FALSE)) == 0) res = FALSE;
+ else res = TRUE;
+
+efA_cleanup:
+ if (pcbNeeded) *pcbNeeded = needed;
+ if (pcReturned) *pcReturned = numentries;
+
+ TRACE("returning %d with LastError = %u (%d byte for %d entries)\n",
+ res, GetLastError(), needed, numentries);
+ return (res);
}
/******************************************************************************
* EnumFormsW (WINSPOOL.@)
+ * enumerates available paper forms for specified printer
+ *
+ * PARAMS
+ * hPrinter (I) handle to printer
+ * Level (I) type of returned form information data structure
+ * pForm (O) pointer to user supplied buffer
+ * cbBuf (I) size of buffer
+ * pcbNeeded (O) required/ used buffer space
+ * pcReturned (O) number of returned forms
+ *
+ * RETURNS
+ * Success: TRUE (non-zero value)
+ * Failure: FALSE (0)
+ *
+ * NOTES
+ * FORM_INFO_2* (not yet implemented)
*/
BOOL WINAPI EnumFormsW( HANDLE hPrinter, DWORD Level, LPBYTE pForm,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned )
{
- FIXME("%p %x %p %x %p %p\n", hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+ DWORD needed = 0;
+ DWORD numentries = 0;
+ BOOL res = FALSE;
+ opened_printer_t *printer = NULL;
+
+ TRACE("(hPrinter = %p, Level = %d, pForm = %p, cbBuf = %u, pcbNeeded = %p, pcReturned = %p) called\n",
+ hPrinter, Level, pForm, cbBuf, pcbNeeded, pcReturned);
+
+ /* fixme: if valid ignore hPrinter: return all forms for every printer */
+ if (!(printer = get_opened_printer(hPrinter)))
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ goto efW_cleanup;
+ }
+
+ /* valid levels are 1 and 2*/
+ if (Level != 2 && Level != 1)
+ {
+ SetLastError(ERROR_INVALID_LEVEL);
+ goto efW_cleanup;
+ }
+
+ if (Level == 2)
+ {
+ FIXME("level 2 not yet supported\n");
+ SetLastError(ERROR_INVALID_LEVEL);
+ goto efW_cleanup;
+ }
+
+ /* Scan all Forms */
+ numentries = 0;
+ needed = get_local_forms(Level, NULL, 0, &numentries, TRUE);
+
+ /* we calculated the needed buffersize. now do the error-checks */
+ if (cbBuf < needed)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto efW_cleanup;
+ }
+ if (!pForm)
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ goto efW_cleanup;
+ }
+ if (!pcbNeeded || !pcReturned)
+ {
+ SetLastError(RPC_X_NULL_REF_POINTER);
+ goto efW_cleanup;
+ }
+
+ /* fill the Buffer with the forminfos*/
+ if ((needed = get_local_forms(Level, pForm, cbBuf, &numentries, TRUE)) == 0) res = FALSE;
+ else res = TRUE;
+
+efW_cleanup:
+ if (pcbNeeded) *pcbNeeded = needed;
+ if (pcReturned) *pcReturned = numentries;
+
+ TRACE("returning %d with LastError = %u (%d byte for %d entries)\n",
+ res, GetLastError(), needed, numentries);
+ return (res);
}
/*****************************************************************************
--
1.5.3.7
--------------040609060005070505070702--
More information about the wine-patches
mailing list